From 7e068801fbf82413ac0a5e63e586c268bd457434 Mon Sep 17 00:00:00 2001 From: tzafrir Date: Mon, 4 Feb 2008 23:00:48 +0000 Subject: Move kernel stuff to under kernel/ (merged branch /zaptel/team/tzafrir/move ) Closes issue #7117. git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@3793 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- Kbuild | 50 - Makefile | 66 +- adt_lec.c | 68 - adt_lec.h | 43 - arith.h | 364 - biquad.h | 73 - configure | 4 +- configure.ac | 2 +- datamods/Makefile | 32 - datamods/hdlc_cisco.c | 335 - datamods/hdlc_fr.c | 1273 -- datamods/hdlc_generic.c | 355 - datamods/hdlc_ppp.c | 114 - datamods/hdlc_raw.c | 89 - datamods/hdlc_raw_eth.c | 107 - datamods/syncppp.c | 1485 -- digits.h | 43 - ecdis.h | 118 - fasthdlc.h | 462 - fir.h | 130 - fxotune.c | 4 +- fxotune.h | 2 - fxstest.c | 2 +- hdlcgen.c | 2 +- hdlcstress.c | 4 +- hdlctest.c | 4 +- hdlcverify.c | 2 +- hpec/hpec.h | 47 - hpec/hpec_user.h | 40 - hpec/hpec_zaptel.h | 146 - jpah.h | 104 - kb1ec.h | 597 - kb1ec_const.h | 72 - kernel/GNUmakefile | 160 + kernel/Kbuild | 64 + kernel/Makefile | 6 + kernel/adt_lec.c | 68 + kernel/adt_lec.h | 43 + kernel/arith.h | 364 + kernel/biquad.h | 73 + kernel/datamods/Makefile | 32 + kernel/datamods/hdlc_cisco.c | 335 + kernel/datamods/hdlc_fr.c | 1273 ++ kernel/datamods/hdlc_generic.c | 355 + kernel/datamods/hdlc_ppp.c | 114 + kernel/datamods/hdlc_raw.c | 89 + kernel/datamods/hdlc_raw_eth.c | 107 + kernel/datamods/syncppp.c | 1485 ++ kernel/digits.h | 43 + kernel/ecdis.h | 118 + kernel/fasthdlc.h | 462 + kernel/fir.h | 130 + kernel/hpec/hpec.h | 47 + kernel/hpec/hpec_user.h | 40 + kernel/hpec/hpec_zaptel.h | 146 + kernel/jpah.h | 104 + kernel/kb1ec.h | 597 + kernel/kb1ec_const.h | 72 + kernel/makefw.c | 88 + kernel/mg2ec.h | 725 + kernel/mg2ec_const.h | 88 + kernel/pciradio.c | 1934 +++ kernel/pciradio.rbt | 10531 +++++++++++++ kernel/proslic.h | 190 + kernel/sec-2.h | 451 + kernel/sec.h | 310 + kernel/tor2-hw.h | 187 + kernel/tor2.c | 1520 ++ kernel/torisa.c | 1172 ++ kernel/tormenta2.rbt | 17482 +++++++++++++++++++++ kernel/wcfxo.c | 1103 ++ kernel/wct1xxp.c | 1438 ++ kernel/wct4xxp/Kbuild | 27 + kernel/wct4xxp/Makefile | 36 + kernel/wct4xxp/base.c | 3877 +++++ kernel/wct4xxp/vpm450m.c | 577 + kernel/wct4xxp/vpm450m.h | 44 + kernel/wct4xxp/wct4xxp-diag.c | 414 + kernel/wct4xxp/wct4xxp.h | 111 + kernel/wctc4xxp/Kbuild | 20 + kernel/wctc4xxp/Makefile | 16 + kernel/wctc4xxp/base.c | 2027 +++ kernel/wctc4xxp/codec_test.c | 332 + kernel/wctdm.c | 2602 +++ kernel/wctdm.h | 69 + kernel/wctdm24xxp/GpakApi.c | 1636 ++ kernel/wctdm24xxp/GpakApi.h | 637 + kernel/wctdm24xxp/GpakCust.c | 476 + kernel/wctdm24xxp/GpakCust.h | 181 + kernel/wctdm24xxp/GpakHpi.h | 80 + kernel/wctdm24xxp/Kbuild | 25 + kernel/wctdm24xxp/Makefile | 27 + kernel/wctdm24xxp/base.c | 4484 ++++++ kernel/wctdm24xxp/gpakErrs.h | 156 + kernel/wctdm24xxp/gpakenum.h | 192 + kernel/wctdm24xxp/wctdm24xxp.h | 280 + kernel/wcte11xp.c | 1644 ++ kernel/wcte12xp/GpakApi.c | 1613 ++ kernel/wcte12xp/GpakApi.h | 637 + kernel/wcte12xp/GpakErrs.h | 156 + kernel/wcte12xp/GpakHpi.h | 80 + kernel/wcte12xp/Kbuild | 25 + kernel/wcte12xp/Makefile | 25 + kernel/wcte12xp/base.c | 2139 +++ kernel/wcte12xp/gpakenum.h | 191 + kernel/wcte12xp/vpmadt032.c | 1385 ++ kernel/wcte12xp/vpmadt032.h | 148 + kernel/wcte12xp/wcte12xp.h | 179 + kernel/wcusb.c | 1490 ++ kernel/wcusb.h | 142 + kernel/xpp/.version | 1 + kernel/xpp/Changelog_xpp | 232 + kernel/xpp/Kbuild | 58 + kernel/xpp/Makefile | 7 + kernel/xpp/README.Astribank | 1131 ++ kernel/xpp/calibrate_slics | 308 + kernel/xpp/card_bri.c | 1731 ++ kernel/xpp/card_bri.h | 31 + kernel/xpp/card_fxo.c | 1218 ++ kernel/xpp/card_fxo.h | 45 + kernel/xpp/card_fxs.c | 1620 ++ kernel/xpp/card_fxs.h | 45 + kernel/xpp/card_global.c | 342 + kernel/xpp/card_global.h | 94 + kernel/xpp/card_pri.c | 1673 ++ kernel/xpp/card_pri.h | 32 + kernel/xpp/firmwares/FPGA_1141.hex | 658 + kernel/xpp/firmwares/FPGA_1151.hex | 664 + kernel/xpp/firmwares/FPGA_FXS.hex | 648 + kernel/xpp/firmwares/LICENSE.firmware | 37 + kernel/xpp/firmwares/README | 19 + kernel/xpp/firmwares/USB_FW.hex | 223 + kernel/xpp/init_card_3_29 | 189 + kernel/xpp/init_card_4_29 | 165 + kernel/xpp/init_card_6_29 | 434 + kernel/xpp/init_card_7_29 | 434 + kernel/xpp/init_card_9_29 | 358 + kernel/xpp/param_doc | 40 + kernel/xpp/parport_debug.c | 113 + kernel/xpp/parport_debug.h | 31 + kernel/xpp/utils/Makefile | 136 + kernel/xpp/utils/astribank_hook | 53 + kernel/xpp/utils/example_default_zaptel | 31 + kernel/xpp/utils/fpga_load.8 | 86 + kernel/xpp/utils/fpga_load.c | 1003 ++ kernel/xpp/utils/genzaptelconf | 1195 ++ kernel/xpp/utils/genzaptelconf.8 | 326 + kernel/xpp/utils/hexfile.c | 567 + kernel/xpp/utils/hexfile.h | 123 + kernel/xpp/utils/lszaptel | 108 + kernel/xpp/utils/print_modes.c | 44 + kernel/xpp/utils/test_parse.c | 35 + kernel/xpp/utils/xpp.rules | 13 + kernel/xpp/utils/xpp_blink | 130 + kernel/xpp/utils/xpp_fxloader | 245 + kernel/xpp/utils/xpp_fxloader.usermap | 10 + kernel/xpp/utils/xpp_modprobe | 10 + kernel/xpp/utils/xpp_sync | 226 + kernel/xpp/utils/zapconf | 576 + kernel/xpp/utils/zaptel-helper | 401 + kernel/xpp/utils/zaptel_drivers | 9 + kernel/xpp/utils/zaptel_hardware | 164 + kernel/xpp/utils/zconf/Zaptel.pm | 68 + kernel/xpp/utils/zconf/Zaptel/Chans.pm | 187 + kernel/xpp/utils/zconf/Zaptel/Config/Defaults.pm | 54 + kernel/xpp/utils/zconf/Zaptel/Hardware.pm | 60 + kernel/xpp/utils/zconf/Zaptel/Hardware/PCI.pm | 204 + kernel/xpp/utils/zconf/Zaptel/Hardware/USB.pm | 116 + kernel/xpp/utils/zconf/Zaptel/Span.pm | 160 + kernel/xpp/utils/zconf/Zaptel/Utils.pm | 52 + kernel/xpp/utils/zconf/Zaptel/Xpp.pm | 183 + kernel/xpp/utils/zconf/Zaptel/Xpp/Line.pm | 59 + kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm | 117 + kernel/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm | 123 + kernel/xpp/utils/zt_registration | 125 + kernel/xpp/xbus-core.c | 1798 +++ kernel/xpp/xbus-core.h | 278 + kernel/xpp/xbus-pcm.c | 1168 ++ kernel/xpp/xbus-pcm.h | 106 + kernel/xpp/xbus-sysfs.c | 273 + kernel/xpp/xdefs.h | 131 + kernel/xpp/xframe_queue.c | 258 + kernel/xpp/xframe_queue.h | 34 + kernel/xpp/xpd.h | 223 + kernel/xpp/xpp_log.h | 52 + kernel/xpp/xpp_usb.c | 1085 ++ kernel/xpp/xpp_zap.c | 1049 ++ kernel/xpp/xpp_zap.h | 49 + kernel/xpp/xproto.c | 446 + kernel/xpp/xproto.h | 306 + kernel/xpp/zap_debug.c | 91 + kernel/xpp/zap_debug.h | 190 + kernel/zaptel-base.c | 7443 +++++++++ kernel/zaptel.h | 2009 +++ kernel/zconfig.h | 197 + kernel/ztd-eth.c | 451 + kernel/ztd-loc.c | 282 + kernel/ztdummy.c | 429 + kernel/ztdummy.h | 152 + kernel/ztdynamic.c | 870 + kernel/zttranscode.c | 491 + makefw.c | 88 - mg2ec.h | 725 - mg2ec_const.h | 88 - patgen.c | 2 +- patlooptest.c | 2 +- pattest.c | 2 +- pciradio.c | 1934 --- pciradio.rbt | 10531 ------------- proslic.h | 190 - sec-2.h | 451 - sec.h | 310 - timertest.c | 2 +- tonezone.h | 2 +- tor2-hw.h | 187 - tor2.c | 1520 -- torisa.c | 1172 -- torisatool.c | 2 +- tormenta2.rbt | 17482 --------------------- wcfxo.c | 1103 -- wct1xxp.c | 1438 -- wct4xxp/Kbuild | 25 - wct4xxp/Makefile | 34 - wct4xxp/base.c | 3877 ----- wct4xxp/vpm450m.c | 577 - wct4xxp/vpm450m.h | 44 - wct4xxp/wct4xxp-diag.c | 414 - wct4xxp/wct4xxp.h | 111 - wctc4xxp/Kbuild | 18 - wctc4xxp/Makefile | 16 - wctc4xxp/base.c | 2027 --- wctc4xxp/codec_test.c | 332 - wctdm.c | 2602 --- wctdm.h | 69 - wctdm24xxp/GpakApi.c | 1636 -- wctdm24xxp/GpakApi.h | 637 - wctdm24xxp/GpakCust.c | 476 - wctdm24xxp/GpakCust.h | 181 - wctdm24xxp/GpakHpi.h | 80 - wctdm24xxp/Kbuild | 23 - wctdm24xxp/Makefile | 27 - wctdm24xxp/base.c | 4485 ------ wctdm24xxp/gpakErrs.h | 156 - wctdm24xxp/gpakenum.h | 192 - wctdm24xxp/wctdm24xxp.h | 280 - wcte11xp.c | 1644 -- wcte12xp/GpakApi.c | 1613 -- wcte12xp/GpakApi.h | 637 - wcte12xp/GpakErrs.h | 156 - wcte12xp/GpakHpi.h | 80 - wcte12xp/Kbuild | 23 - wcte12xp/Makefile | 25 - wcte12xp/base.c | 2139 --- wcte12xp/gpakenum.h | 191 - wcte12xp/vpmadt032.c | 1385 -- wcte12xp/vpmadt032.h | 148 - wcte12xp/wcte12xp.h | 179 - wcusb.c | 1490 -- wcusb.h | 142 - xpp/.version | 1 - xpp/Changelog_xpp | 232 - xpp/Kbuild | 58 - xpp/Makefile | 7 - xpp/README.Astribank | 1131 -- xpp/calibrate_slics | 308 - xpp/card_bri.c | 1731 -- xpp/card_bri.h | 31 - xpp/card_fxo.c | 1218 -- xpp/card_fxo.h | 45 - xpp/card_fxs.c | 1620 -- xpp/card_fxs.h | 45 - xpp/card_global.c | 342 - xpp/card_global.h | 94 - xpp/card_pri.c | 1673 -- xpp/card_pri.h | 32 - xpp/firmwares/FPGA_1141.hex | 658 - xpp/firmwares/FPGA_1151.hex | 664 - xpp/firmwares/FPGA_FXS.hex | 648 - xpp/firmwares/LICENSE.firmware | 37 - xpp/firmwares/README | 19 - xpp/firmwares/USB_FW.hex | 223 - xpp/init_card_3_29 | 189 - xpp/init_card_4_29 | 165 - xpp/init_card_6_29 | 434 - xpp/init_card_7_29 | 434 - xpp/init_card_9_29 | 358 - xpp/param_doc | 40 - xpp/parport_debug.c | 113 - xpp/parport_debug.h | 31 - xpp/utils/Makefile | 136 - xpp/utils/astribank_hook | 53 - xpp/utils/example_default_zaptel | 31 - xpp/utils/fpga_load.8 | 86 - xpp/utils/fpga_load.c | 1003 -- xpp/utils/genzaptelconf | 1195 -- xpp/utils/genzaptelconf.8 | 326 - xpp/utils/hexfile.c | 567 - xpp/utils/hexfile.h | 123 - xpp/utils/lszaptel | 108 - xpp/utils/print_modes.c | 44 - xpp/utils/test_parse.c | 35 - xpp/utils/xpp.rules | 13 - xpp/utils/xpp_blink | 130 - xpp/utils/xpp_fxloader | 245 - xpp/utils/xpp_fxloader.usermap | 10 - xpp/utils/xpp_modprobe | 10 - xpp/utils/xpp_sync | 226 - xpp/utils/zapconf | 576 - xpp/utils/zaptel-helper | 401 - xpp/utils/zaptel_drivers | 9 - xpp/utils/zaptel_hardware | 164 - xpp/utils/zconf/Zaptel.pm | 68 - xpp/utils/zconf/Zaptel/Chans.pm | 187 - xpp/utils/zconf/Zaptel/Config/Defaults.pm | 56 - xpp/utils/zconf/Zaptel/Hardware.pm | 60 - xpp/utils/zconf/Zaptel/Hardware/PCI.pm | 204 - xpp/utils/zconf/Zaptel/Hardware/USB.pm | 116 - xpp/utils/zconf/Zaptel/Span.pm | 160 - xpp/utils/zconf/Zaptel/Utils.pm | 52 - xpp/utils/zconf/Zaptel/Xpp.pm | 183 - xpp/utils/zconf/Zaptel/Xpp/Line.pm | 59 - xpp/utils/zconf/Zaptel/Xpp/Xbus.pm | 117 - xpp/utils/zconf/Zaptel/Xpp/Xpd.pm | 123 - xpp/utils/zt_registration | 125 - xpp/xbus-core.c | 1798 --- xpp/xbus-core.h | 278 - xpp/xbus-pcm.c | 1168 -- xpp/xbus-pcm.h | 106 - xpp/xbus-sysfs.c | 273 - xpp/xdefs.h | 131 - xpp/xframe_queue.c | 258 - xpp/xframe_queue.h | 34 - xpp/xpd.h | 223 - xpp/xpp_log.h | 52 - xpp/xpp_usb.c | 1085 -- xpp/xpp_zap.c | 1049 -- xpp/xpp_zap.h | 49 - xpp/xproto.c | 446 - xpp/xproto.h | 306 - xpp/zap_debug.c | 91 - xpp/zap_debug.h | 190 - zaptel-base.c | 7451 --------- zaptel.h | 2009 --- zconfig.h | 197 - ztcfg-dude.c | 2 +- ztcfg.c | 2 +- ztd-eth.c | 451 - ztd-loc.c | 282 - ztdiag.c | 2 +- ztdummy.c | 429 - ztdummy.h | 152 - ztdynamic.c | 870 - ztmonitor.c | 2 +- ztscan.c | 2 +- zttool.c | 2 +- zttranscode.c | 491 - 356 files changed, 111220 insertions(+), 111051 deletions(-) delete mode 100644 Kbuild delete mode 100644 adt_lec.c delete mode 100644 adt_lec.h delete mode 100644 arith.h delete mode 100644 biquad.h delete mode 100644 datamods/Makefile delete mode 100644 datamods/hdlc_cisco.c delete mode 100644 datamods/hdlc_fr.c delete mode 100644 datamods/hdlc_generic.c delete mode 100644 datamods/hdlc_ppp.c delete mode 100644 datamods/hdlc_raw.c delete mode 100644 datamods/hdlc_raw_eth.c delete mode 100644 datamods/syncppp.c delete mode 100644 digits.h delete mode 100644 ecdis.h delete mode 100644 fasthdlc.h delete mode 100644 fir.h delete mode 100644 hpec/hpec.h delete mode 100644 hpec/hpec_user.h delete mode 100644 hpec/hpec_zaptel.h delete mode 100644 jpah.h delete mode 100644 kb1ec.h delete mode 100644 kb1ec_const.h create mode 100644 kernel/GNUmakefile create mode 100644 kernel/Kbuild create mode 100644 kernel/Makefile create mode 100644 kernel/adt_lec.c create mode 100644 kernel/adt_lec.h create mode 100644 kernel/arith.h create mode 100644 kernel/biquad.h create mode 100644 kernel/datamods/Makefile create mode 100644 kernel/datamods/hdlc_cisco.c create mode 100644 kernel/datamods/hdlc_fr.c create mode 100644 kernel/datamods/hdlc_generic.c create mode 100644 kernel/datamods/hdlc_ppp.c create mode 100644 kernel/datamods/hdlc_raw.c create mode 100644 kernel/datamods/hdlc_raw_eth.c create mode 100644 kernel/datamods/syncppp.c create mode 100644 kernel/digits.h create mode 100644 kernel/ecdis.h create mode 100644 kernel/fasthdlc.h create mode 100644 kernel/fir.h create mode 100644 kernel/hpec/hpec.h create mode 100644 kernel/hpec/hpec_user.h create mode 100644 kernel/hpec/hpec_zaptel.h create mode 100644 kernel/jpah.h create mode 100644 kernel/kb1ec.h create mode 100644 kernel/kb1ec_const.h create mode 100644 kernel/makefw.c create mode 100644 kernel/mg2ec.h create mode 100644 kernel/mg2ec_const.h create mode 100644 kernel/pciradio.c create mode 100644 kernel/pciradio.rbt create mode 100644 kernel/proslic.h create mode 100644 kernel/sec-2.h create mode 100644 kernel/sec.h create mode 100644 kernel/tor2-hw.h create mode 100644 kernel/tor2.c create mode 100644 kernel/torisa.c create mode 100644 kernel/tormenta2.rbt create mode 100644 kernel/wcfxo.c create mode 100644 kernel/wct1xxp.c create mode 100644 kernel/wct4xxp/Kbuild create mode 100644 kernel/wct4xxp/Makefile create mode 100644 kernel/wct4xxp/base.c create mode 100644 kernel/wct4xxp/vpm450m.c create mode 100644 kernel/wct4xxp/vpm450m.h create mode 100644 kernel/wct4xxp/wct4xxp-diag.c create mode 100644 kernel/wct4xxp/wct4xxp.h create mode 100644 kernel/wctc4xxp/Kbuild create mode 100644 kernel/wctc4xxp/Makefile create mode 100644 kernel/wctc4xxp/base.c create mode 100644 kernel/wctc4xxp/codec_test.c create mode 100644 kernel/wctdm.c create mode 100644 kernel/wctdm.h create mode 100644 kernel/wctdm24xxp/GpakApi.c create mode 100644 kernel/wctdm24xxp/GpakApi.h create mode 100644 kernel/wctdm24xxp/GpakCust.c create mode 100644 kernel/wctdm24xxp/GpakCust.h create mode 100644 kernel/wctdm24xxp/GpakHpi.h create mode 100644 kernel/wctdm24xxp/Kbuild create mode 100644 kernel/wctdm24xxp/Makefile create mode 100644 kernel/wctdm24xxp/base.c create mode 100644 kernel/wctdm24xxp/gpakErrs.h create mode 100644 kernel/wctdm24xxp/gpakenum.h create mode 100644 kernel/wctdm24xxp/wctdm24xxp.h create mode 100644 kernel/wcte11xp.c create mode 100644 kernel/wcte12xp/GpakApi.c create mode 100644 kernel/wcte12xp/GpakApi.h create mode 100644 kernel/wcte12xp/GpakErrs.h create mode 100644 kernel/wcte12xp/GpakHpi.h create mode 100644 kernel/wcte12xp/Kbuild create mode 100644 kernel/wcte12xp/Makefile create mode 100644 kernel/wcte12xp/base.c create mode 100644 kernel/wcte12xp/gpakenum.h create mode 100644 kernel/wcte12xp/vpmadt032.c create mode 100644 kernel/wcte12xp/vpmadt032.h create mode 100644 kernel/wcte12xp/wcte12xp.h create mode 100644 kernel/wcusb.c create mode 100644 kernel/wcusb.h create mode 100644 kernel/xpp/.version create mode 100644 kernel/xpp/Changelog_xpp create mode 100644 kernel/xpp/Kbuild create mode 100644 kernel/xpp/Makefile create mode 100644 kernel/xpp/README.Astribank create mode 100755 kernel/xpp/calibrate_slics create mode 100644 kernel/xpp/card_bri.c create mode 100644 kernel/xpp/card_bri.h create mode 100644 kernel/xpp/card_fxo.c create mode 100644 kernel/xpp/card_fxo.h create mode 100644 kernel/xpp/card_fxs.c create mode 100644 kernel/xpp/card_fxs.h create mode 100644 kernel/xpp/card_global.c create mode 100644 kernel/xpp/card_global.h create mode 100644 kernel/xpp/card_pri.c create mode 100644 kernel/xpp/card_pri.h create mode 100644 kernel/xpp/firmwares/FPGA_1141.hex create mode 100644 kernel/xpp/firmwares/FPGA_1151.hex create mode 100644 kernel/xpp/firmwares/FPGA_FXS.hex create mode 100644 kernel/xpp/firmwares/LICENSE.firmware create mode 100644 kernel/xpp/firmwares/README create mode 100644 kernel/xpp/firmwares/USB_FW.hex create mode 100755 kernel/xpp/init_card_3_29 create mode 100755 kernel/xpp/init_card_4_29 create mode 100755 kernel/xpp/init_card_6_29 create mode 100755 kernel/xpp/init_card_7_29 create mode 100755 kernel/xpp/init_card_9_29 create mode 100755 kernel/xpp/param_doc create mode 100644 kernel/xpp/parport_debug.c create mode 100644 kernel/xpp/parport_debug.h create mode 100644 kernel/xpp/utils/Makefile create mode 100755 kernel/xpp/utils/astribank_hook create mode 100644 kernel/xpp/utils/example_default_zaptel create mode 100644 kernel/xpp/utils/fpga_load.8 create mode 100644 kernel/xpp/utils/fpga_load.c create mode 100755 kernel/xpp/utils/genzaptelconf create mode 100644 kernel/xpp/utils/genzaptelconf.8 create mode 100644 kernel/xpp/utils/hexfile.c create mode 100644 kernel/xpp/utils/hexfile.h create mode 100755 kernel/xpp/utils/lszaptel create mode 100644 kernel/xpp/utils/print_modes.c create mode 100644 kernel/xpp/utils/test_parse.c create mode 100644 kernel/xpp/utils/xpp.rules create mode 100755 kernel/xpp/utils/xpp_blink create mode 100644 kernel/xpp/utils/xpp_fxloader create mode 100644 kernel/xpp/utils/xpp_fxloader.usermap create mode 100644 kernel/xpp/utils/xpp_modprobe create mode 100755 kernel/xpp/utils/xpp_sync create mode 100755 kernel/xpp/utils/zapconf create mode 100644 kernel/xpp/utils/zaptel-helper create mode 100755 kernel/xpp/utils/zaptel_drivers create mode 100755 kernel/xpp/utils/zaptel_hardware create mode 100644 kernel/xpp/utils/zconf/Zaptel.pm create mode 100644 kernel/xpp/utils/zconf/Zaptel/Chans.pm create mode 100644 kernel/xpp/utils/zconf/Zaptel/Config/Defaults.pm create mode 100644 kernel/xpp/utils/zconf/Zaptel/Hardware.pm create mode 100644 kernel/xpp/utils/zconf/Zaptel/Hardware/PCI.pm create mode 100644 kernel/xpp/utils/zconf/Zaptel/Hardware/USB.pm create mode 100644 kernel/xpp/utils/zconf/Zaptel/Span.pm create mode 100644 kernel/xpp/utils/zconf/Zaptel/Utils.pm create mode 100644 kernel/xpp/utils/zconf/Zaptel/Xpp.pm create mode 100644 kernel/xpp/utils/zconf/Zaptel/Xpp/Line.pm create mode 100644 kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm create mode 100644 kernel/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm create mode 100755 kernel/xpp/utils/zt_registration create mode 100644 kernel/xpp/xbus-core.c create mode 100644 kernel/xpp/xbus-core.h create mode 100644 kernel/xpp/xbus-pcm.c create mode 100644 kernel/xpp/xbus-pcm.h create mode 100644 kernel/xpp/xbus-sysfs.c create mode 100644 kernel/xpp/xdefs.h create mode 100644 kernel/xpp/xframe_queue.c create mode 100644 kernel/xpp/xframe_queue.h create mode 100644 kernel/xpp/xpd.h create mode 100644 kernel/xpp/xpp_log.h create mode 100644 kernel/xpp/xpp_usb.c create mode 100644 kernel/xpp/xpp_zap.c create mode 100644 kernel/xpp/xpp_zap.h create mode 100644 kernel/xpp/xproto.c create mode 100644 kernel/xpp/xproto.h create mode 100644 kernel/xpp/zap_debug.c create mode 100644 kernel/xpp/zap_debug.h create mode 100644 kernel/zaptel-base.c create mode 100644 kernel/zaptel.h create mode 100644 kernel/zconfig.h create mode 100644 kernel/ztd-eth.c create mode 100644 kernel/ztd-loc.c create mode 100644 kernel/ztdummy.c create mode 100644 kernel/ztdummy.h create mode 100644 kernel/ztdynamic.c create mode 100644 kernel/zttranscode.c delete mode 100644 makefw.c delete mode 100644 mg2ec.h delete mode 100644 mg2ec_const.h delete mode 100644 pciradio.c delete mode 100644 pciradio.rbt delete mode 100644 proslic.h delete mode 100644 sec-2.h delete mode 100644 sec.h delete mode 100644 tor2-hw.h delete mode 100644 tor2.c delete mode 100644 torisa.c delete mode 100644 tormenta2.rbt delete mode 100644 wcfxo.c delete mode 100644 wct1xxp.c delete mode 100644 wct4xxp/Kbuild delete mode 100644 wct4xxp/Makefile delete mode 100644 wct4xxp/base.c delete mode 100644 wct4xxp/vpm450m.c delete mode 100644 wct4xxp/vpm450m.h delete mode 100644 wct4xxp/wct4xxp-diag.c delete mode 100644 wct4xxp/wct4xxp.h delete mode 100644 wctc4xxp/Kbuild delete mode 100644 wctc4xxp/Makefile delete mode 100644 wctc4xxp/base.c delete mode 100644 wctc4xxp/codec_test.c delete mode 100644 wctdm.c delete mode 100644 wctdm.h delete mode 100644 wctdm24xxp/GpakApi.c delete mode 100644 wctdm24xxp/GpakApi.h delete mode 100644 wctdm24xxp/GpakCust.c delete mode 100644 wctdm24xxp/GpakCust.h delete mode 100644 wctdm24xxp/GpakHpi.h delete mode 100644 wctdm24xxp/Kbuild delete mode 100644 wctdm24xxp/Makefile delete mode 100644 wctdm24xxp/base.c delete mode 100644 wctdm24xxp/gpakErrs.h delete mode 100644 wctdm24xxp/gpakenum.h delete mode 100644 wctdm24xxp/wctdm24xxp.h delete mode 100644 wcte11xp.c delete mode 100644 wcte12xp/GpakApi.c delete mode 100644 wcte12xp/GpakApi.h delete mode 100644 wcte12xp/GpakErrs.h delete mode 100644 wcte12xp/GpakHpi.h delete mode 100644 wcte12xp/Kbuild delete mode 100644 wcte12xp/Makefile delete mode 100644 wcte12xp/base.c delete mode 100644 wcte12xp/gpakenum.h delete mode 100644 wcte12xp/vpmadt032.c delete mode 100644 wcte12xp/vpmadt032.h delete mode 100644 wcte12xp/wcte12xp.h delete mode 100644 wcusb.c delete mode 100644 wcusb.h delete mode 100644 xpp/.version delete mode 100644 xpp/Changelog_xpp delete mode 100644 xpp/Kbuild delete mode 100644 xpp/Makefile delete mode 100644 xpp/README.Astribank delete mode 100755 xpp/calibrate_slics delete mode 100644 xpp/card_bri.c delete mode 100644 xpp/card_bri.h delete mode 100644 xpp/card_fxo.c delete mode 100644 xpp/card_fxo.h delete mode 100644 xpp/card_fxs.c delete mode 100644 xpp/card_fxs.h delete mode 100644 xpp/card_global.c delete mode 100644 xpp/card_global.h delete mode 100644 xpp/card_pri.c delete mode 100644 xpp/card_pri.h delete mode 100644 xpp/firmwares/FPGA_1141.hex delete mode 100644 xpp/firmwares/FPGA_1151.hex delete mode 100644 xpp/firmwares/FPGA_FXS.hex delete mode 100644 xpp/firmwares/LICENSE.firmware delete mode 100644 xpp/firmwares/README delete mode 100644 xpp/firmwares/USB_FW.hex delete mode 100755 xpp/init_card_3_29 delete mode 100755 xpp/init_card_4_29 delete mode 100755 xpp/init_card_6_29 delete mode 100755 xpp/init_card_7_29 delete mode 100755 xpp/init_card_9_29 delete mode 100755 xpp/param_doc delete mode 100644 xpp/parport_debug.c delete mode 100644 xpp/parport_debug.h delete mode 100644 xpp/utils/Makefile delete mode 100755 xpp/utils/astribank_hook delete mode 100644 xpp/utils/example_default_zaptel delete mode 100644 xpp/utils/fpga_load.8 delete mode 100644 xpp/utils/fpga_load.c delete mode 100755 xpp/utils/genzaptelconf delete mode 100644 xpp/utils/genzaptelconf.8 delete mode 100644 xpp/utils/hexfile.c delete mode 100644 xpp/utils/hexfile.h delete mode 100755 xpp/utils/lszaptel delete mode 100644 xpp/utils/print_modes.c delete mode 100644 xpp/utils/test_parse.c delete mode 100644 xpp/utils/xpp.rules delete mode 100755 xpp/utils/xpp_blink delete mode 100644 xpp/utils/xpp_fxloader delete mode 100644 xpp/utils/xpp_fxloader.usermap delete mode 100644 xpp/utils/xpp_modprobe delete mode 100755 xpp/utils/xpp_sync delete mode 100755 xpp/utils/zapconf delete mode 100644 xpp/utils/zaptel-helper delete mode 100755 xpp/utils/zaptel_drivers delete mode 100755 xpp/utils/zaptel_hardware delete mode 100644 xpp/utils/zconf/Zaptel.pm delete mode 100644 xpp/utils/zconf/Zaptel/Chans.pm delete mode 100644 xpp/utils/zconf/Zaptel/Config/Defaults.pm delete mode 100644 xpp/utils/zconf/Zaptel/Hardware.pm delete mode 100644 xpp/utils/zconf/Zaptel/Hardware/PCI.pm delete mode 100644 xpp/utils/zconf/Zaptel/Hardware/USB.pm delete mode 100644 xpp/utils/zconf/Zaptel/Span.pm delete mode 100644 xpp/utils/zconf/Zaptel/Utils.pm delete mode 100644 xpp/utils/zconf/Zaptel/Xpp.pm delete mode 100644 xpp/utils/zconf/Zaptel/Xpp/Line.pm delete mode 100644 xpp/utils/zconf/Zaptel/Xpp/Xbus.pm delete mode 100644 xpp/utils/zconf/Zaptel/Xpp/Xpd.pm delete mode 100755 xpp/utils/zt_registration delete mode 100644 xpp/xbus-core.c delete mode 100644 xpp/xbus-core.h delete mode 100644 xpp/xbus-pcm.c delete mode 100644 xpp/xbus-pcm.h delete mode 100644 xpp/xbus-sysfs.c delete mode 100644 xpp/xdefs.h delete mode 100644 xpp/xframe_queue.c delete mode 100644 xpp/xframe_queue.h delete mode 100644 xpp/xpd.h delete mode 100644 xpp/xpp_log.h delete mode 100644 xpp/xpp_usb.c delete mode 100644 xpp/xpp_zap.c delete mode 100644 xpp/xpp_zap.h delete mode 100644 xpp/xproto.c delete mode 100644 xpp/xproto.h delete mode 100644 xpp/zap_debug.c delete mode 100644 xpp/zap_debug.h delete mode 100644 zaptel-base.c delete mode 100644 zaptel.h delete mode 100644 zconfig.h delete mode 100644 ztd-eth.c delete mode 100644 ztd-loc.c delete mode 100644 ztdummy.c delete mode 100644 ztdummy.h delete mode 100644 ztdynamic.c delete mode 100644 zttranscode.c diff --git a/Kbuild b/Kbuild deleted file mode 100644 index fdd8d39..0000000 --- a/Kbuild +++ /dev/null @@ -1,50 +0,0 @@ -ifdef ECHO_CAN_NAME - ECHO_CAN_CFLAGS := -DECHO_CAN_FROMENV -DECHO_CAN_$(ECHO_CAN_NAME) -endif - -obj-m := $(KBUILD_OBJ_M) - -EXTRA_CFLAGS := -I$(src) -DSTANDALONE_ZAPATA -EXTRA_CFLAGS += $(ECHO_CAN_CFLAGS) - -# fix typo present in CentOS and RHEL 2.6.9 kernels -BAD_KERNELS_VERS := 22 34 34.0.1 34.0.2 -BAD_KERNELS := $(foreach ver,$(BAD_KERNELS_VERS),2.6.9-$(ver).EL 2.6.9-$(ver).ELsmp) -ifneq (,$(filter $(KVERS),$(BAD_KERNELS))) -EXTRA_CFLAGS+=-Drw_lock_t=rwlock_t -endif - -zaptel-objs := zaptel-base.o - -ifeq ($(HPEC_PRESENT),yes) -ifeq ($(ARCH),i386) -zaptel-objs += hpec/hpec_x86_32.o -endif - -ifeq ($(ARCH),x86_64) -zaptel-objs += hpec/hpec_x86_64.o -endif - -EXTRA_CFLAGS += -DECHO_CAN_HPEC -I$(src)/hpec -endif - - -# set CONFIG_ZAPTEL_MMX for a number of CPU types. -# Right now this part is not enabled, unless you build with -# ZAPTEL_MMX_AUTO=something . -ZAPMMX_WHITELIST_i386 = M586MMX M686 MPENTIUMII MPENTIUMIII MPENTIUMM \ - MPENTIUM4 MVIAC3_2 - -ZAPMMX_WHITELIST_x86_64 = - -# A list of configuration variables to test: CONFIG_M686 , etc. -ZAPMMX_CONFIG_VARS := $(ZAPMMX_WHITELIST_$(ARCH):%=CONFIG_%) - -# expand them: -ZAPMMX_CONFIG_VALS := $(strip $(foreach var,$(ZAPMMX_CONFIG_VARS),$(var)) ) -ifneq (,$(ZAPTEL_MMX_AUTO)) - ifneq (,$(ZAPMMX_CONFIG_VALS)) - # TODO: make that - CFLAGS_zaptel-base.o += -DCONFIG_ZAPTEL_MMX - endif -endif diff --git a/Makefile b/Makefile index 0f01537..f7fb84a 100644 --- a/Makefile +++ b/Makefile @@ -105,10 +105,10 @@ ifeq ($(findstring xpp,$(MENUSELECT_MODULES)),) BUILD_XPP:=yes endif -SUBDIRS_UTILS_ALL:= xpp/utils ppp +SUBDIRS_UTILS_ALL:= kernel/xpp/utils ppp SUBDIRS_UTILS := ifeq ($(BUILD_XPP),yes) - SUBDIRS_UTILS += xpp/utils + SUBDIRS_UTILS += kernel/xpp/utils endif #SUBDIRS_UTILS += ppp @@ -122,6 +122,8 @@ BUILD_MODULES:=$(BUILD_TOPDIR_MODULES) $(BUILD_SUBDIR_MODULES) MOD_DESTDIR:=zaptel +KERN_DIR:=kernel + #NOTE NOTE NOTE # # all variables set before the include of Makefile.kernel26 are needed by the 2.6 kernel module build process @@ -137,15 +139,15 @@ else KBUILD_OBJ_M=$(BUILD_TOPDIR_MODULES:%=%.o) $(BUILD_SUBDIR_MODULES:%=%/) ifeq ($(BUILDVER),linux24) - INSTALL_MODULES:=$(BUILD_TOPDIR_MODULES:%=%.o) + INSTALL_MODULES:=$(BUILD_TOPDIR_MODULES:%=$(KERN_DIR)/%.o) INSTALL_MODULES+=$(foreach mod,$(BUILD_SUBDIR_MODULES),$(mod)/$(mod).o) - ALL_MODULES:=$(TOPDIR_MODULES:%=%.o) - ALL_MODULES+=$(SUBDIR_MODULES:%=%/%.o) + ALL_MODULES:=$(TOPDIR_MODULES:%=$(KERN_DIR)/%.o) + ALL_MODULES+=$(SUBDIR_MODULES:%=$(KERN_DIR)/%/%.o) else - INSTALL_MODULES:=$(BUILD_TOPDIR_MODULES:%=%.ko) - INSTALL_MODULES+=$(foreach mod,$(filter-out xpp,$(BUILD_SUBDIR_MODULES)),$(mod)/$(mod).ko) + INSTALL_MODULES:=$(BUILD_TOPDIR_MODULES:%=$(KERN_DIR)/%.ko) + INSTALL_MODULES+=$(foreach mod,$(filter-out xpp,$(BUILD_SUBDIR_MODULES)),$(KERN_DIR)/$(mod)/$(mod).ko) ifneq ($(filter xpp,$(BUILD_SUBDIR_MODULES)),) - INSTALL_MODULES+=$(patsubst %,xpp/%.ko,xpp_usb xpd_fxo xpd_fxs xpp) + INSTALL_MODULES+=$(patsubst %,$(KERN_DIR)/xpp/%.ko,xpp_usb xpd_fxo xpd_fxs xpp) endif ALL_MODULES:=$(TOPDIR_MODULES:%=%.ko) @@ -186,8 +188,13 @@ MODULE_ALIASES=wcfxs wctdm8xxp wct2xxp KFLAGS+=-DSTANDALONE_ZAPATA CFLAGS+=-DSTANDALONE_ZAPATA -KMAKE = $(MAKE) -C $(KSRC) SUBDIRS=$(PWD) \ +ifeq ($(BUILDVER),linux24) +KMAKE = $(MAKE) -C kernel HOTPLUG_FIRMWARE=$(HOTPLUG_FIRMWARE) \ + BUILD_TOPDIR_MODULES="$(BUILD_TOPDIR_MODULES)" BUILD_SUBDIR_MODULES="$(BUILD_SUBDIR_MODULES)" +else +KMAKE = $(MAKE) -C $(KSRC) SUBDIRS=$(PWD)/kernel \ HOTPLUG_FIRMWARE=$(HOTPLUG_FIRMWARE) KBUILD_OBJ_M="$(KBUILD_OBJ_M)" +endif KMAKE_INST = $(KMAKE) \ INSTALL_MOD_PATH=$(DESTDIR) INSTALL_MOD_DIR=misc modules_install @@ -291,13 +298,13 @@ programs: libs utils utils: $(BINS) utils-subdirs -modules: prereq +modules: @if [ -z "$(KSRC)" -o ! -d "$(KSRC)" ]; then echo "You do not appear to have the sources for the $(KVERS) kernel installed."; exit 1 ; fi -ifeq ($(BUILDVER),linux26) +#ifeq ($(BUILDVER),linux26) $(KMAKE) modules -else -modules: $(INSTALL_MODULES) -endif +#else +#modules: $(INSTALL_MODULES) +#endif ifeq ($(HPEC_PRESENT),yes) ifeq ($(ARCH),i386) @@ -327,26 +334,17 @@ zonedata.lo: zonedata.c tonezone.lo: tonezone.c $(CC) -c $(CFLAGS) -o $@ $^ -tor2fw.h: tormenta2.rbt makefw - ./makefw $< tor2fw > $@ - -radfw.h: pciradio.rbt makefw - ./makefw $< radfw > $@ - -makefw: makefw.c - $(HOSTCC) -o $@ $^ - prereq: config.status tor2fw.h radfw.h version.h -zttool.o: zaptel.h +zttool.o: kernel/zaptel.h zttool.o: CFLAGS+=$(NEWT_INCLUDE) zttool: LDLIBS+=$(NEWT_LIB) -ztscan.o: zaptel.h +ztscan.o: kernel/zaptel.h -ztprovision.o: zaptel.h +ztprovision.o: kernel/zaptel.h -ztmonitor.o: zaptel.h +ztmonitor.o: kernel/zaptel.h ztspeed: CFLAGS= @@ -359,7 +357,7 @@ $(LTZ_A): $(LTZ_A_OBJS) $(LTZ_SO): $(LTZ_SO_OBJS) $(CC) $(CFLAGS) -shared -Wl,-soname,$(LTZ_SO).$(LTZ_SO_MAJOR_VER).$(LTZ_SO_MINOR_VER) -o $@ $^ $(LDFLAGS) $(LDLIBS) -lm -ztcfg.o: ztcfg.h zaptel.h +ztcfg.o: ztcfg.h kernel/zaptel.h ztcfg: ztcfg.o $(LTZ_A) ztcfg: LDLIBS+=-lm @@ -516,7 +514,7 @@ install-utils-subdirs: done install-include: - $(INSTALL) -D -m 644 zaptel.h $(DESTDIR)$(INC_DIR)/zaptel.h + $(INSTALL) -D -m 644 kernel/zaptel.h $(DESTDIR)$(INC_DIR)/zaptel.h devices: ifndef DYNFS @@ -603,7 +601,7 @@ endif @echo "optimal value for the variable MODULES ." @echo "" @echo "I think that the zaptel hardware you have on your system is:" - @xpp/utils/zaptel_hardware || true + @kernel/xpp/utils/zaptel_hardware || true update: @@ -622,17 +620,11 @@ update: clean: -@$(MAKE) -C menuselect clean - rm -f torisatool makefw tor2fw.h radfw.h + rm -f torisatool rm -f $(BINS) rm -f *.o ztcfg tzdriver sethdlc sethdlc-new rm -f $(LTZ_SO) $(LTZ_A) *.lo -ifeq ($(BUILDVER),linux26) - ifneq (,$(KSRC)) $(KMAKE) clean - endif -else - $(MAKE) -C wct4xxp clean -endif @for dir in $(SUBDIRS_UTILS_ALL); do \ $(MAKE) -C $$dir clean; \ done diff --git a/adt_lec.c b/adt_lec.c deleted file mode 100644 index d191e2b..0000000 --- a/adt_lec.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * ADT Line Echo Canceller Parameter Parsing - * - * Copyright (C) 2008 Digium, Inc. - * - * Kevin P. Fleming - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _ADT_LEC_C -#define _ADT_LEC_C - -#include - -static inline void adt_lec_init_defaults(struct adt_lec_params *params, __u32 tap_length) -{ - memset(params, 0, sizeof(*params)); - params->tap_length = tap_length; -} - -static int adt_lec_parse_params(struct adt_lec_params *params, struct zt_echocanparams *ecp, struct zt_echocanparam *p) -{ - unsigned int x; - char *c; - - for (x = 0; x < ecp->param_count; x++) { - for (c = p[x].name; *c; c++) - *c = tolower(*c); - if (!strcmp(p[x].name, "nlp_type")) { - switch (p[x].value) { - case ADT_LEC_NLP_OFF: - case ADT_LEC_NLP_MUTE: - case ADT_LEC_RANDOM_NOISE: - case ADT_LEC_HOTH_NOISE: - case ADT_LEC_SUPPRESS: - params->nlp_type = p[x].value; - break; - default: - return -EINVAL; - } - } else if (!strcmp(p[x].name, "nlp_thresh")) { - params->nlp_threshold = p[x].value; - } else if (!strcmp(p[x].name, "nlp_suppress")) { - params->nlp_max_suppress = p[x].value; - } else { - return -EINVAL; - } - } - - return 0; -} - -#endif /* _ADT_LEC_C */ diff --git a/adt_lec.h b/adt_lec.h deleted file mode 100644 index c91020d..0000000 --- a/adt_lec.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * ADT Line Echo Canceller Parameter Parsing - * - * Copyright (C) 2008 Digium, Inc. - * - * Kevin P. Fleming - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _ADT_LEC_H -#define _ADT_LEC_H - -enum adt_lec_nlp_type { - ADT_LEC_NLP_OFF = 0, - ADT_LEC_NLP_MUTE, - ADT_LEC_RANDOM_NOISE, - ADT_LEC_HOTH_NOISE, - ADT_LEC_SUPPRESS, -}; - -struct adt_lec_params { - __u32 tap_length; - enum adt_lec_nlp_type nlp_type; - __u32 nlp_threshold; - __u32 nlp_max_suppress; -}; - -#endif /* _ADT_LEC_H */ diff --git a/arith.h b/arith.h deleted file mode 100644 index 3059db5..0000000 --- a/arith.h +++ /dev/null @@ -1,364 +0,0 @@ -#ifndef _ZAPTEL_ARITH_H -#define _ZAPTEL_ARITH_H -/* - * Handy add/subtract functions to operate on chunks of shorts. - * Feel free to add customizations for additional architectures - * - */ - -#ifdef CONFIG_ZAPTEL_MMX -#ifdef ZT_CHUNKSIZE -static inline void __ACSS(volatile short *dst, const short *src) -{ - __asm__ __volatile__ ( - "movq 0(%0), %%mm0;\n" - "movq 0(%1), %%mm1;\n" - "movq 8(%0), %%mm2;\n" - "movq 8(%1), %%mm3;\n" - "paddsw %%mm1, %%mm0;\n" - "paddsw %%mm3, %%mm2;\n" - "movq %%mm0, 0(%0);\n" - "movq %%mm2, 8(%0);\n" - : "=r" (dst) - : "r" (src), "0" (dst) - : "memory" -#ifdef CLOBBERMMX - , "%mm0", "%mm1", "%mm2", "%mm3" -#endif - ); - -} -static inline void __SCSS(volatile short *dst, const short *src) -{ - __asm__ __volatile__ ( - "movq 0(%0), %%mm0;\n" - "movq 0(%1), %%mm1;\n" - "movq 8(%0), %%mm2;\n" - "movq 8(%1), %%mm3;\n" - "psubsw %%mm1, %%mm0;\n" - "psubsw %%mm3, %%mm2;\n" - "movq %%mm0, 0(%0);\n" - "movq %%mm2, 8(%0);\n" - : "=r" (dst) - : "r" (src), "0" (dst) - : "memory" -#ifdef CLOBBERMMX - , "%mm0", "%mm1", "%mm2", "%mm3" -#endif - ); - -} - -#if (ZT_CHUNKSIZE == 8) -#define ACSS(a,b) __ACSS(a,b) -#define SCSS(a,b) __SCSS(a,b) -#elif (ZT_CHUNKSIZE > 8) -static inline void ACSS(volatile short *dst, const short *src) -{ - int x; - for (x=0;x>= 4; - - /* Clear our accumulator, mm4 */ - - /* - - For every set of eight... - - Load 16 coefficients into four registers... - Shift each word right 16 to make them shorts... - Pack the resulting shorts into two registers... - With the coefficients now in mm0 and mm2, load the - history into mm1 and mm3... - Multiply/add mm1 into mm0, and mm3 into mm2... - Add mm2 into mm0 (without saturation, alas). Now we have two half-results. - Accumulate in mm4 (again, without saturation, alas) - */ - __asm__ ( - "pxor %%mm4, %%mm4;\n" - "mov %1, %%edi;\n" - "mov %2, %%esi;\n" - "mov %3, %%ecx;\n" - "1:" - "movq 0(%%edi), %%mm0;\n" - "movq 8(%%edi), %%mm1;\n" - "movq 16(%%edi), %%mm2;\n" - "movq 24(%%edi), %%mm3;\n" - /* can't use 4/5 since 4 is the accumulator for us */ - "movq 32(%%edi), %%mm6;\n" - "movq 40(%%edi), %%mm7;\n" - "psrad $16, %%mm0;\n" - "psrad $16, %%mm1;\n" - "psrad $16, %%mm2;\n" - "psrad $16, %%mm3;\n" - "psrad $16, %%mm6;\n" - "psrad $16, %%mm7;\n" - "packssdw %%mm1, %%mm0;\n" - "packssdw %%mm3, %%mm2;\n" - "packssdw %%mm7, %%mm6;\n" - "movq 0(%%esi), %%mm1;\n" - "movq 8(%%esi), %%mm3;\n" - "movq 16(%%esi), %%mm7;\n" - "pmaddwd %%mm1, %%mm0;\n" - "pmaddwd %%mm3, %%mm2;\n" - "pmaddwd %%mm7, %%mm6;\n" - "paddd %%mm6, %%mm4;\n" - "paddd %%mm2, %%mm4;\n" - "paddd %%mm0, %%mm4;\n" - /* Come back and do for the last few bytes */ - "movq 48(%%edi), %%mm6;\n" - "movq 56(%%edi), %%mm7;\n" - "psrad $16, %%mm6;\n" - "psrad $16, %%mm7;\n" - "packssdw %%mm7, %%mm6;\n" - "movq 24(%%esi), %%mm7;\n" - "pmaddwd %%mm7, %%mm6;\n" - "paddd %%mm6, %%mm4;\n" - "add $64, %%edi;\n" - "add $32, %%esi;\n" - "dec %%ecx;\n" - "jnz 1b;\n" - "movq %%mm4, %%mm0;\n" - "psrlq $32, %%mm0;\n" - "paddd %%mm0, %%mm4;\n" - "movd %%mm4, %0;\n" - : "=r" (sum) - : "r" (coeffs), "r" (hist), "r" (len) - : "%ecx", "%edi", "%esi" - ); - - return sum; -} - -static inline void UPDATE(volatile int *taps, const short *history, const int nsuppr, const int ntaps) -{ - int i; - int correction; - for (i=0;i>= 4; - /* First, load up taps, */ - __asm__ ( - "pxor %%mm4, %%mm4;\n" - "mov %0, %%edi;\n" - "mov %1, %%esi;\n" - "mov %3, %%ecx;\n" - "1:" - "jnz 1b;\n" - "movq %%mm4, %%mm0;\n" - "psrlq $32, %%mm0;\n" - "paddd %%mm0, %%mm4;\n" - "movd %%mm4, %0;\n" - : "=r" (taps), "=r" (taps_short) - : "r" (history), "r" (nsuppr), "r" (ntaps), "0" (taps) - : "%ecx", "%edi", "%esi" - ); -#endif -#if 1 - for (i=0;i> 16; - } -#endif -} - -static inline int CONVOLVE2(const short *coeffs, const short *hist, int len) -{ - int sum; - /* Divide length by 16 */ - len >>= 4; - - /* Clear our accumulator, mm4 */ - - /* - - For every set of eight... - Load in eight coefficients and eight historic samples, multliply add and - accumulate the result - */ - __asm__ ( - "pxor %%mm4, %%mm4;\n" - "mov %1, %%edi;\n" - "mov %2, %%esi;\n" - "mov %3, %%ecx;\n" - "1:" - "movq 0(%%edi), %%mm0;\n" - "movq 8(%%edi), %%mm2;\n" - "movq 0(%%esi), %%mm1;\n" - "movq 8(%%esi), %%mm3;\n" - "pmaddwd %%mm1, %%mm0;\n" - "pmaddwd %%mm3, %%mm2;\n" - "paddd %%mm2, %%mm4;\n" - "paddd %%mm0, %%mm4;\n" - "movq 16(%%edi), %%mm0;\n" - "movq 24(%%edi), %%mm2;\n" - "movq 16(%%esi), %%mm1;\n" - "movq 24(%%esi), %%mm3;\n" - "pmaddwd %%mm1, %%mm0;\n" - "pmaddwd %%mm3, %%mm2;\n" - "paddd %%mm2, %%mm4;\n" - "paddd %%mm0, %%mm4;\n" - "add $32, %%edi;\n" - "add $32, %%esi;\n" - "dec %%ecx;\n" - "jnz 1b;\n" - "movq %%mm4, %%mm0;\n" - "psrlq $32, %%mm0;\n" - "paddd %%mm0, %%mm4;\n" - "movd %%mm4, %0;\n" - : "=r" (sum) - : "r" (coeffs), "r" (hist), "r" (len) - : "%ecx", "%edi", "%esi" - ); - - return sum; -} -static inline short MAX16(const short *y, int len, int *pos) -{ - int k; - short max = 0; - int bestpos = 0; - for (k=0;k 32767) - sum = 32767; - else if (sum < -32768) - sum = -32768; - dst[x] = sum; - } -#endif -} - -static inline void SCSS(short *dst, short *src) -{ - int x; - - /* Subtract src from dst with saturation, storing in dst */ -#ifdef BFIN - for (x = 0; x < ZT_CHUNKSIZE; x++) - dst[x] = __builtin_bfin_sub_fr1x16(dst[x], src[x]); -#else - int sum; - - for (x = 0; x < ZT_CHUNKSIZE; x++) { - sum = dst[x] - src[x]; - if (sum > 32767) - sum = 32767; - else if (sum < -32768) - sum = -32768; - dst[x] = sum; - } -#endif -} - -#endif /* ZT_CHUNKSIZE */ - -static inline int CONVOLVE(const int *coeffs, const short *hist, int len) -{ - int x; - int sum = 0; - for (x=0;x> 16) * hist[x]; - return sum; -} - -static inline int CONVOLVE2(const short *coeffs, const short *hist, int len) -{ - int x; - int sum = 0; - for (x=0;x> 16; - } -} - -static inline short MAX16(const short *y, int len, int *pos) -{ - int k; - short max = 0; - int bestpos = 0; - for (k=0;k - * - * Copyright (C) 2001 Steve Underwood - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -typedef struct -{ - int32_t gain; - int32_t a1; - int32_t a2; - int32_t b1; - int32_t b2; - - int32_t z1; - int32_t z2; -} biquad2_state_t; - -static inline void biquad2_init (biquad2_state_t *bq, - int32_t gain, - int32_t a1, - int32_t a2, - int32_t b1, - int32_t b2) -{ - bq->gain = gain; - bq->a1 = a1; - bq->a2 = a2; - bq->b1 = b1; - bq->b2 = b2; - - bq->z1 = 0; - bq->z2 = 0; -} -/*- End of function --------------------------------------------------------*/ - -static inline int16_t biquad2 (biquad2_state_t *bq, int16_t sample) -{ - int32_t y; - int32_t z0; - - z0 = sample*bq->gain + bq->z1*bq->a1 + bq->z2*bq->a2; - y = z0 + bq->z1*bq->b1 + bq->z2*bq->b2; - - bq->z2 = bq->z1; - bq->z1 = z0 >> 15; - y >>= 15; - return y; -} -/*- End of function --------------------------------------------------------*/ -/*- End of file ------------------------------------------------------------*/ diff --git a/configure b/configure index 5848d77..c28a322 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac Revision: 3195 . +# From configure.ac Revision: 3198 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61. # @@ -580,7 +580,7 @@ PACKAGE_STRING= PACKAGE_BUGREPORT= ac_unique_file="zaptel" -ac_unique_file="zaptel-base.c" +ac_unique_file="kernel/zaptel-base.c" # Factoring default headers for most tests. ac_includes_default="\ #include diff --git a/configure.ac b/configure.ac index 5ef2cbd..bda6cd0 100644 --- a/configure.ac +++ b/configure.ac @@ -9,7 +9,7 @@ m4_define([ZAP_VERSION], AC_INIT(zaptel, ZAP_VERSION, www.asterisk.org) # check existence of the package -AC_CONFIG_SRCDIR([zaptel-base.c]) +AC_CONFIG_SRCDIR([kernel/zaptel-base.c]) AC_COPYRIGHT("Zaptel") AC_REVISION($Revision$) diff --git a/datamods/Makefile b/datamods/Makefile deleted file mode 100644 index 310073e..0000000 --- a/datamods/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -.EXPORT_ALL_VARIABLES: -MODULES= \ - hdlc_cisco hdlc_generic hdlc_raw syncppp \ - hdlc_fr hdlc_ppp hdlc_raw_eth - - -PWD=$(shell pwd) - -MODULESO:=$(MODULES:%=%.o) -MODULESKO:=$(MODULES:%=%.ko) -KMAKE = $(MAKE) -C $(KSRC) SUBDIRS=$(PWD) -KMAKE_INST = $(KMAKE) \ - INSTALL_MOD_PATH=$(INSTALL_PREFIX) INSTALL_MOD_DIR=misc modules_install - -obj-m := $(MODULESO) -#obj-m:=hdlc_raw.o hdlc_cisco.o -#obj-m := hdlc_cisco.o hdlc_cisco.mod.o hdlc_fr.o hdlc_generic.o hdlc_ppp.o hdlc_raw.o hdlc_raw_eth.o hdlc_raw.mod.o hdlc_x25.o - -all: - @echo "You don't want to do make here. Do it from up above" - -clean: - $(KMAKE) clean - -install: $(MODULESKO) - $(KMAKE_INST) - -datamods: - @echo "To build: $(obj-m)" - @echo $(KSRC) - @if [ -z "$(KSRC)" -o ! -d "$(KSRC)" ]; then echo "You do not appear to have the sources for the $(KVERS) kernel installed."; exit 1 ; fi - $(KMAKE) modules diff --git a/datamods/hdlc_cisco.c b/datamods/hdlc_cisco.c deleted file mode 100644 index 1fd0466..0000000 --- a/datamods/hdlc_cisco.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Generic HDLC support routines for Linux - * Cisco HDLC support - * - * Copyright (C) 2000 - 2003 Krzysztof Halasa - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#undef DEBUG_HARD_HEADER - -#define CISCO_MULTICAST 0x8F /* Cisco multicast address */ -#define CISCO_UNICAST 0x0F /* Cisco unicast address */ -#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ -#define CISCO_SYS_INFO 0x2000 /* Cisco interface/system info */ -#define CISCO_ADDR_REQ 0 /* Cisco address request */ -#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ -#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ - - -static int cisco_hard_header(struct sk_buff *skb, struct net_device *dev, - u16 type, void *daddr, void *saddr, - unsigned int len) -{ - hdlc_header *data; -#ifdef DEBUG_HARD_HEADER - printk(KERN_DEBUG "%s: cisco_hard_header called\n", dev->name); -#endif - - skb_push(skb, sizeof(hdlc_header)); - data = (hdlc_header*)skb->data; - if (type == CISCO_KEEPALIVE) - data->address = CISCO_MULTICAST; - else - data->address = CISCO_UNICAST; - data->control = 0; - data->protocol = htons(type); - - return sizeof(hdlc_header); -} - - - -static void cisco_keepalive_send(struct net_device *dev, u32 type, - u32 par1, u32 par2) -{ - struct sk_buff *skb; - cisco_packet *data; - - skb = dev_alloc_skb(sizeof(hdlc_header) + sizeof(cisco_packet)); - if (!skb) { - printk(KERN_WARNING - "%s: Memory squeeze on cisco_keepalive_send()\n", - dev->name); - return; - } - skb_reserve(skb, 4); - cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0); - data = (cisco_packet*)(skb->data + 4); - - data->type = htonl(type); - data->par1 = htonl(par1); - data->par2 = htonl(par2); - data->rel = 0xFFFF; - /* we will need do_div here if 1000 % HZ != 0 */ - data->time = htonl((jiffies - INITIAL_JIFFIES) * (1000 / HZ)); - - skb_put(skb, sizeof(cisco_packet)); - skb->priority = TC_PRIO_CONTROL; - skb->dev = dev; - skb->nh.raw = skb->data; - - dev_queue_xmit(skb); -} - - - -static __be16 cisco_type_trans(struct sk_buff *skb, struct net_device *dev) -{ - hdlc_header *data = (hdlc_header*)skb->data; - - if (skb->len < sizeof(hdlc_header)) - return __constant_htons(ETH_P_HDLC); - - if (data->address != CISCO_MULTICAST && - data->address != CISCO_UNICAST) - return __constant_htons(ETH_P_HDLC); - - switch(data->protocol) { - case __constant_htons(ETH_P_IP): - case __constant_htons(ETH_P_IPX): - case __constant_htons(ETH_P_IPV6): - skb_pull(skb, sizeof(hdlc_header)); - return data->protocol; - default: - return __constant_htons(ETH_P_HDLC); - } -} - - -static int cisco_rx(struct sk_buff *skb) -{ - struct net_device *dev = skb->dev; - hdlc_device *hdlc = dev_to_hdlc(dev); - hdlc_header *data = (hdlc_header*)skb->data; - cisco_packet *cisco_data; - struct in_device *in_dev; - u32 addr, mask; - - if (skb->len < sizeof(hdlc_header)) - goto rx_error; - - if (data->address != CISCO_MULTICAST && - data->address != CISCO_UNICAST) - goto rx_error; - - switch(ntohs(data->protocol)) { - case CISCO_SYS_INFO: - /* Packet is not needed, drop it. */ - dev_kfree_skb_any(skb); - return NET_RX_SUCCESS; - - case CISCO_KEEPALIVE: - if (skb->len != sizeof(hdlc_header) + CISCO_PACKET_LEN && - skb->len != sizeof(hdlc_header) + CISCO_BIG_PACKET_LEN) { - printk(KERN_INFO "%s: Invalid length of Cisco " - "control packet (%d bytes)\n", - dev->name, skb->len); - goto rx_error; - } - - cisco_data = (cisco_packet*)(skb->data + sizeof(hdlc_header)); - - switch(ntohl (cisco_data->type)) { - case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */ - in_dev = dev->ip_ptr; - addr = 0; - mask = ~0; /* is the mask correct? */ - - if (in_dev != NULL) { - struct in_ifaddr **ifap = &in_dev->ifa_list; - - while (*ifap != NULL) { - if (strcmp(dev->name, - (*ifap)->ifa_label) == 0) { - addr = (*ifap)->ifa_local; - mask = (*ifap)->ifa_mask; - break; - } - ifap = &(*ifap)->ifa_next; - } - - cisco_keepalive_send(dev, CISCO_ADDR_REPLY, - addr, mask); - } - dev_kfree_skb_any(skb); - return NET_RX_SUCCESS; - - case CISCO_ADDR_REPLY: - printk(KERN_INFO "%s: Unexpected Cisco IP address " - "reply\n", dev->name); - goto rx_error; - - case CISCO_KEEPALIVE_REQ: - hdlc->state.cisco.rxseq = ntohl(cisco_data->par1); - if (hdlc->state.cisco.request_sent && - ntohl(cisco_data->par2)==hdlc->state.cisco.txseq) { - hdlc->state.cisco.last_poll = jiffies; - if (!hdlc->state.cisco.up) { - u32 sec, min, hrs, days; - sec = ntohl(cisco_data->time) / 1000; - min = sec / 60; sec -= min * 60; - hrs = min / 60; min -= hrs * 60; - days = hrs / 24; hrs -= days * 24; - printk(KERN_INFO "%s: Link up (peer " - "uptime %ud%uh%um%us)\n", - dev->name, days, hrs, - min, sec); -#if 0 - netif_carrier_on(dev); -#endif - hdlc->state.cisco.up = 1; - } - } - - dev_kfree_skb_any(skb); - return NET_RX_SUCCESS; - } /* switch(keepalive type) */ - } /* switch(protocol) */ - - printk(KERN_INFO "%s: Unsupported protocol %x\n", dev->name, - data->protocol); - dev_kfree_skb_any(skb); - return NET_RX_DROP; - - rx_error: - hdlc->stats.rx_errors++; /* Mark error */ - dev_kfree_skb_any(skb); - return NET_RX_DROP; -} - - - -static void cisco_timer(unsigned long arg) -{ - struct net_device *dev = (struct net_device *)arg; - hdlc_device *hdlc = dev_to_hdlc(dev); - - if (hdlc->state.cisco.up && - time_after(jiffies, hdlc->state.cisco.last_poll + - hdlc->state.cisco.settings.timeout * HZ)) { - hdlc->state.cisco.up = 0; - printk(KERN_INFO "%s: Link down\n", dev->name); -#if 0 - netif_carrier_off(dev); -#endif - } - - cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, - ++hdlc->state.cisco.txseq, - hdlc->state.cisco.rxseq); - hdlc->state.cisco.request_sent = 1; - hdlc->state.cisco.timer.expires = jiffies + - hdlc->state.cisco.settings.interval * HZ; - hdlc->state.cisco.timer.function = cisco_timer; - hdlc->state.cisco.timer.data = arg; - add_timer(&hdlc->state.cisco.timer); -} - - - -static void cisco_start(struct net_device *dev) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); - hdlc->state.cisco.up = 0; - hdlc->state.cisco.request_sent = 0; - hdlc->state.cisco.txseq = hdlc->state.cisco.rxseq = 0; - - init_timer(&hdlc->state.cisco.timer); - hdlc->state.cisco.timer.expires = jiffies + HZ; /*First poll after 1s*/ - hdlc->state.cisco.timer.function = cisco_timer; - hdlc->state.cisco.timer.data = (unsigned long)dev; - add_timer(&hdlc->state.cisco.timer); -} - - - -static void cisco_stop(struct net_device *dev) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); - del_timer_sync(&hdlc->state.cisco.timer); -#if 0 - if (netif_carrier_ok(dev)) - netif_carrier_off(dev); -#endif - hdlc->state.cisco.up = 0; - hdlc->state.cisco.request_sent = 0; -} - - - -int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr) -{ - cisco_proto __user *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco; - const size_t size = sizeof(cisco_proto); - cisco_proto new_settings; - hdlc_device *hdlc = dev_to_hdlc(dev); - int result; - - switch (ifr->ifr_settings.type) { - case IF_GET_PROTO: - ifr->ifr_settings.type = IF_PROTO_CISCO; - if (ifr->ifr_settings.size < size) { - ifr->ifr_settings.size = size; /* data size wanted */ - return -ENOBUFS; - } - if (copy_to_user(cisco_s, &hdlc->state.cisco.settings, size)) - return -EFAULT; - return 0; - - case IF_PROTO_CISCO: - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - - if(dev->flags & IFF_UP) - return -EBUSY; - - if (copy_from_user(&new_settings, cisco_s, size)) - return -EFAULT; - - if (new_settings.interval < 1 || - new_settings.timeout < 2) - return -EINVAL; - - result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); - - if (result) - return result; - - hdlc_proto_detach(hdlc); - memcpy(&hdlc->state.cisco.settings, &new_settings, size); - memset(&hdlc->proto, 0, sizeof(hdlc->proto)); - - hdlc->proto.start = cisco_start; - hdlc->proto.stop = cisco_stop; - hdlc->proto.netif_rx = cisco_rx; - hdlc->proto.type_trans = cisco_type_trans; - hdlc->proto.id = IF_PROTO_CISCO; - dev->hard_start_xmit = hdlc->xmit; - dev->hard_header = cisco_hard_header; - dev->hard_header_cache = NULL; - dev->type = ARPHRD_CISCO; - dev->flags = IFF_POINTOPOINT | IFF_NOARP; - dev->addr_len = 0; - return 0; - } - - return -EINVAL; -} diff --git a/datamods/hdlc_fr.c b/datamods/hdlc_fr.c deleted file mode 100644 index 523afe1..0000000 --- a/datamods/hdlc_fr.c +++ /dev/null @@ -1,1273 +0,0 @@ -/* - * Generic HDLC support routines for Linux - * Frame Relay support - * - * Copyright (C) 1999 - 2005 Krzysztof Halasa - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - - Theory of PVC state - - DCE mode: - - (exist,new) -> 0,0 when "PVC create" or if "link unreliable" - 0,x -> 1,1 if "link reliable" when sending FULL STATUS - 1,1 -> 1,0 if received FULL STATUS ACK - - (active) -> 0 when "ifconfig PVC down" or "link unreliable" or "PVC create" - -> 1 when "PVC up" and (exist,new) = 1,0 - - DTE mode: - (exist,new,active) = FULL STATUS if "link reliable" - = 0, 0, 0 if "link unreliable" - No LMI: - active = open and "link reliable" - exist = new = not used - - CCITT LMI: ITU-T Q.933 Annex A - ANSI LMI: ANSI T1.617 Annex D - CISCO LMI: the original, aka "Gang of Four" LMI - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#undef DEBUG_PKT -#undef DEBUG_ECN -#undef DEBUG_LINK - -#define FR_UI 0x03 -#define FR_PAD 0x00 - -#define NLPID_IP 0xCC -#define NLPID_IPV6 0x8E -#define NLPID_SNAP 0x80 -#define NLPID_PAD 0x00 -#define NLPID_CCITT_ANSI_LMI 0x08 -#define NLPID_CISCO_LMI 0x09 - - -#define LMI_CCITT_ANSI_DLCI 0 /* LMI DLCI */ -#define LMI_CISCO_DLCI 1023 - -#define LMI_CALLREF 0x00 /* Call Reference */ -#define LMI_ANSI_LOCKSHIFT 0x95 /* ANSI locking shift */ -#define LMI_ANSI_CISCO_REPTYPE 0x01 /* report type */ -#define LMI_CCITT_REPTYPE 0x51 -#define LMI_ANSI_CISCO_ALIVE 0x03 /* keep alive */ -#define LMI_CCITT_ALIVE 0x53 -#define LMI_ANSI_CISCO_PVCSTAT 0x07 /* PVC status */ -#define LMI_CCITT_PVCSTAT 0x57 - -#define LMI_FULLREP 0x00 /* full report */ -#define LMI_INTEGRITY 0x01 /* link integrity report */ -#define LMI_SINGLE 0x02 /* single PVC report */ - -#define LMI_STATUS_ENQUIRY 0x75 -#define LMI_STATUS 0x7D /* reply */ - -#define LMI_REPT_LEN 1 /* report type element length */ -#define LMI_INTEG_LEN 2 /* link integrity element length */ - -#define LMI_CCITT_CISCO_LENGTH 13 /* LMI frame lengths */ -#define LMI_ANSI_LENGTH 14 - - -typedef struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned ea1: 1; - unsigned cr: 1; - unsigned dlcih: 6; - - unsigned ea2: 1; - unsigned de: 1; - unsigned becn: 1; - unsigned fecn: 1; - unsigned dlcil: 4; -#else - unsigned dlcih: 6; - unsigned cr: 1; - unsigned ea1: 1; - - unsigned dlcil: 4; - unsigned fecn: 1; - unsigned becn: 1; - unsigned de: 1; - unsigned ea2: 1; -#endif -}__attribute__ ((packed)) fr_hdr; - - -static inline u16 q922_to_dlci(u8 *hdr) -{ - return ((hdr[0] & 0xFC) << 2) | ((hdr[1] & 0xF0) >> 4); -} - - - -static inline void dlci_to_q922(u8 *hdr, u16 dlci) -{ - hdr[0] = (dlci >> 2) & 0xFC; - hdr[1] = ((dlci << 4) & 0xF0) | 0x01; -} - - - -static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci) -{ - pvc_device *pvc = hdlc->state.fr.first_pvc; - - while (pvc) { - if (pvc->dlci == dlci) - return pvc; - if (pvc->dlci > dlci) - return NULL; /* the listed is sorted */ - pvc = pvc->next; - } - - return NULL; -} - - -static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); - pvc_device *pvc, **pvc_p = &hdlc->state.fr.first_pvc; - - while (*pvc_p) { - if ((*pvc_p)->dlci == dlci) - return *pvc_p; - if ((*pvc_p)->dlci > dlci) - break; /* the list is sorted */ - pvc_p = &(*pvc_p)->next; - } - - pvc = kmalloc(sizeof(pvc_device), GFP_ATOMIC); - if (!pvc) - return NULL; - - memset(pvc, 0, sizeof(pvc_device)); - pvc->dlci = dlci; - pvc->master = dev; - pvc->next = *pvc_p; /* Put it in the chain */ - *pvc_p = pvc; - return pvc; -} - - -static inline int pvc_is_used(pvc_device *pvc) -{ - return pvc->main != NULL || pvc->ether != NULL; -} - - -static inline void pvc_carrier(int on, pvc_device *pvc) -{ - if (on) { - if (pvc->main) - if (!netif_carrier_ok(pvc->main)) - netif_carrier_on(pvc->main); - if (pvc->ether) - if (!netif_carrier_ok(pvc->ether)) - netif_carrier_on(pvc->ether); - } else { - if (pvc->main) - if (netif_carrier_ok(pvc->main)) - netif_carrier_off(pvc->main); - if (pvc->ether) - if (netif_carrier_ok(pvc->ether)) - netif_carrier_off(pvc->ether); - } -} - - -static inline void delete_unused_pvcs(hdlc_device *hdlc) -{ - pvc_device **pvc_p = &hdlc->state.fr.first_pvc; - - while (*pvc_p) { - if (!pvc_is_used(*pvc_p)) { - pvc_device *pvc = *pvc_p; - *pvc_p = pvc->next; - kfree(pvc); - continue; - } - pvc_p = &(*pvc_p)->next; - } -} - - -static inline struct net_device** get_dev_p(pvc_device *pvc, int type) -{ - if (type == ARPHRD_ETHER) - return &pvc->ether; - else - return &pvc->main; -} - - -static int fr_hard_header(struct sk_buff **skb_p, u16 dlci) -{ - u16 head_len; - struct sk_buff *skb = *skb_p; - - switch (skb->protocol) { - case __constant_ntohs(NLPID_CCITT_ANSI_LMI): - head_len = 4; - skb_push(skb, head_len); - skb->data[3] = NLPID_CCITT_ANSI_LMI; - break; - - case __constant_ntohs(NLPID_CISCO_LMI): - head_len = 4; - skb_push(skb, head_len); - skb->data[3] = NLPID_CISCO_LMI; - break; - - case __constant_ntohs(ETH_P_IP): - head_len = 4; - skb_push(skb, head_len); - skb->data[3] = NLPID_IP; - break; - - case __constant_ntohs(ETH_P_IPV6): - head_len = 4; - skb_push(skb, head_len); - skb->data[3] = NLPID_IPV6; - break; - - case __constant_ntohs(ETH_P_802_3): - head_len = 10; - if (skb_headroom(skb) < head_len) { - struct sk_buff *skb2 = skb_realloc_headroom(skb, - head_len); - if (!skb2) - return -ENOBUFS; - dev_kfree_skb(skb); - skb = *skb_p = skb2; - } - skb_push(skb, head_len); - skb->data[3] = FR_PAD; - skb->data[4] = NLPID_SNAP; - skb->data[5] = FR_PAD; - skb->data[6] = 0x80; - skb->data[7] = 0xC2; - skb->data[8] = 0x00; - skb->data[9] = 0x07; /* bridged Ethernet frame w/out FCS */ - break; - - default: - head_len = 10; - skb_push(skb, head_len); - skb->data[3] = FR_PAD; - skb->data[4] = NLPID_SNAP; - skb->data[5] = FR_PAD; - skb->data[6] = FR_PAD; - skb->data[7] = FR_PAD; - *(u16*)(skb->data + 8) = skb->protocol; - } - - dlci_to_q922(skb->data, dlci); - skb->data[2] = FR_UI; - return 0; -} - - - -static int pvc_open(struct net_device *dev) -{ - pvc_device *pvc = dev_to_pvc(dev); - - if ((pvc->master->flags & IFF_UP) == 0) - return -EIO; /* Master must be UP in order to activate PVC */ - - if (pvc->open_count++ == 0) { - hdlc_device *hdlc = dev_to_hdlc(pvc->master); - if (hdlc->state.fr.settings.lmi == LMI_NONE) - pvc->state.active = hdlc->carrier; - - pvc_carrier(pvc->state.active, pvc); - hdlc->state.fr.dce_changed = 1; - } - return 0; -} - - - -static int pvc_close(struct net_device *dev) -{ - pvc_device *pvc = dev_to_pvc(dev); - - if (--pvc->open_count == 0) { - hdlc_device *hdlc = dev_to_hdlc(pvc->master); - if (hdlc->state.fr.settings.lmi == LMI_NONE) - pvc->state.active = 0; - - if (hdlc->state.fr.settings.dce) { - hdlc->state.fr.dce_changed = 1; - pvc->state.active = 0; - } - } - return 0; -} - - - -static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - pvc_device *pvc = dev_to_pvc(dev); - fr_proto_pvc_info info; - - if (ifr->ifr_settings.type == IF_GET_PROTO) { - if (dev->type == ARPHRD_ETHER) - ifr->ifr_settings.type = IF_PROTO_FR_ETH_PVC; - else - ifr->ifr_settings.type = IF_PROTO_FR_PVC; - - if (ifr->ifr_settings.size < sizeof(info)) { - /* data size wanted */ - ifr->ifr_settings.size = sizeof(info); - return -ENOBUFS; - } - - info.dlci = pvc->dlci; - memcpy(info.master, pvc->master->name, IFNAMSIZ); - if (copy_to_user(ifr->ifr_settings.ifs_ifsu.fr_pvc_info, - &info, sizeof(info))) - return -EFAULT; - return 0; - } - - return -EINVAL; -} - - -static inline struct net_device_stats *pvc_get_stats(struct net_device *dev) -{ - return netdev_priv(dev); -} - - - -static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) -{ - pvc_device *pvc = dev_to_pvc(dev); - struct net_device_stats *stats = pvc_get_stats(dev); - - if (pvc->state.active) { - if (dev->type == ARPHRD_ETHER) { - int pad = ETH_ZLEN - skb->len; - if (pad > 0) { /* Pad the frame with zeros */ - int len = skb->len; - if (skb_tailroom(skb) < pad) - if (pskb_expand_head(skb, 0, pad, - GFP_ATOMIC)) { - stats->tx_dropped++; - dev_kfree_skb(skb); - return 0; - } - skb_put(skb, pad); - memset(skb->data + len, 0, pad); - } - skb->protocol = __constant_htons(ETH_P_802_3); - } - if (!fr_hard_header(&skb, pvc->dlci)) { - stats->tx_bytes += skb->len; - stats->tx_packets++; - if (pvc->state.fecn) /* TX Congestion counter */ - stats->tx_compressed++; - skb->dev = pvc->master; - dev_queue_xmit(skb); - return 0; - } - } - - stats->tx_dropped++; - dev_kfree_skb(skb); - return 0; -} - - - -static int pvc_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - - - -static inline void fr_log_dlci_active(pvc_device *pvc) -{ - printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n", - pvc->master->name, - pvc->dlci, - pvc->main ? pvc->main->name : "", - pvc->main && pvc->ether ? " " : "", - pvc->ether ? pvc->ether->name : "", - pvc->state.new ? " new" : "", - !pvc->state.exist ? "deleted" : - pvc->state.active ? "active" : "inactive"); -} - - - -static inline u8 fr_lmi_nextseq(u8 x) -{ - x++; - return x ? x : 1; -} - - - -static void fr_lmi_send(struct net_device *dev, int fullrep) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); - struct sk_buff *skb; - pvc_device *pvc = hdlc->state.fr.first_pvc; - int lmi = hdlc->state.fr.settings.lmi; - int dce = hdlc->state.fr.settings.dce; - int len = lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH; - int stat_len = (lmi == LMI_CISCO) ? 6 : 3; - u8 *data; - int i = 0; - - if (dce && fullrep) { - len += hdlc->state.fr.dce_pvc_count * (2 + stat_len); - if (len > HDLC_MAX_MRU) { - printk(KERN_WARNING "%s: Too many PVCs while sending " - "LMI full report\n", dev->name); - return; - } - } - - skb = dev_alloc_skb(len); - if (!skb) { - printk(KERN_WARNING "%s: Memory squeeze on fr_lmi_send()\n", - dev->name); - return; - } - memset(skb->data, 0, len); - skb_reserve(skb, 4); - if (lmi == LMI_CISCO) { - skb->protocol = __constant_htons(NLPID_CISCO_LMI); - fr_hard_header(&skb, LMI_CISCO_DLCI); - } else { - skb->protocol = __constant_htons(NLPID_CCITT_ANSI_LMI); - fr_hard_header(&skb, LMI_CCITT_ANSI_DLCI); - } - data = skb->tail; - data[i++] = LMI_CALLREF; - data[i++] = dce ? LMI_STATUS : LMI_STATUS_ENQUIRY; - if (lmi == LMI_ANSI) - data[i++] = LMI_ANSI_LOCKSHIFT; - data[i++] = lmi == LMI_CCITT ? LMI_CCITT_REPTYPE : - LMI_ANSI_CISCO_REPTYPE; - data[i++] = LMI_REPT_LEN; - data[i++] = fullrep ? LMI_FULLREP : LMI_INTEGRITY; - data[i++] = lmi == LMI_CCITT ? LMI_CCITT_ALIVE : LMI_ANSI_CISCO_ALIVE; - data[i++] = LMI_INTEG_LEN; - data[i++] = hdlc->state.fr.txseq =fr_lmi_nextseq(hdlc->state.fr.txseq); - data[i++] = hdlc->state.fr.rxseq; - - if (dce && fullrep) { - while (pvc) { - data[i++] = lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT : - LMI_ANSI_CISCO_PVCSTAT; - data[i++] = stat_len; - - /* LMI start/restart */ - if (hdlc->state.fr.reliable && !pvc->state.exist) { - pvc->state.exist = pvc->state.new = 1; - fr_log_dlci_active(pvc); - } - - /* ifconfig PVC up */ - if (pvc->open_count && !pvc->state.active && - pvc->state.exist && !pvc->state.new) { - pvc_carrier(1, pvc); - pvc->state.active = 1; - fr_log_dlci_active(pvc); - } - - if (lmi == LMI_CISCO) { - data[i] = pvc->dlci >> 8; - data[i + 1] = pvc->dlci & 0xFF; - } else { - data[i] = (pvc->dlci >> 4) & 0x3F; - data[i + 1] = ((pvc->dlci << 3) & 0x78) | 0x80; - data[i + 2] = 0x80; - } - - if (pvc->state.new) - data[i + 2] |= 0x08; - else if (pvc->state.active) - data[i + 2] |= 0x02; - - i += stat_len; - pvc = pvc->next; - } - } - - skb_put(skb, i); - skb->priority = TC_PRIO_CONTROL; - skb->dev = dev; - skb->nh.raw = skb->data; - - dev_queue_xmit(skb); -} - - - -static void fr_set_link_state(int reliable, struct net_device *dev) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); - pvc_device *pvc = hdlc->state.fr.first_pvc; - - hdlc->state.fr.reliable = reliable; - if (reliable) { -#if 0 - if (!netif_carrier_ok(dev)) - netif_carrier_on(dev); -#endif - - hdlc->state.fr.n391cnt = 0; /* Request full status */ - hdlc->state.fr.dce_changed = 1; - - if (hdlc->state.fr.settings.lmi == LMI_NONE) { - while (pvc) { /* Activate all PVCs */ - pvc_carrier(1, pvc); - pvc->state.exist = pvc->state.active = 1; - pvc->state.new = 0; - pvc = pvc->next; - } - } - } else { -#if 0 - if (netif_carrier_ok(dev)) - netif_carrier_off(dev); -#endif - - while (pvc) { /* Deactivate all PVCs */ - pvc_carrier(0, pvc); - pvc->state.exist = pvc->state.active = 0; - pvc->state.new = 0; - if (!hdlc->state.fr.settings.dce) - pvc->state.bandwidth = 0; - pvc = pvc->next; - } - } -} - - - -static void fr_timer(unsigned long arg) -{ - struct net_device *dev = (struct net_device *)arg; - hdlc_device *hdlc = dev_to_hdlc(dev); - int i, cnt = 0, reliable; - u32 list; - - if (hdlc->state.fr.settings.dce) { - reliable = hdlc->state.fr.request && - time_before(jiffies, hdlc->state.fr.last_poll + - hdlc->state.fr.settings.t392 * HZ); - hdlc->state.fr.request = 0; - } else { - hdlc->state.fr.last_errors <<= 1; /* Shift the list */ - if (hdlc->state.fr.request) { - if (hdlc->state.fr.reliable) - printk(KERN_INFO "%s: No LMI status reply " - "received\n", dev->name); - hdlc->state.fr.last_errors |= 1; - } - - list = hdlc->state.fr.last_errors; - for (i = 0; i < hdlc->state.fr.settings.n393; i++, list >>= 1) - cnt += (list & 1); /* errors count */ - - reliable = (cnt < hdlc->state.fr.settings.n392); - } - - if (hdlc->state.fr.reliable != reliable) { - printk(KERN_INFO "%s: Link %sreliable\n", dev->name, - reliable ? "" : "un"); - fr_set_link_state(reliable, dev); - } - - if (hdlc->state.fr.settings.dce) - hdlc->state.fr.timer.expires = jiffies + - hdlc->state.fr.settings.t392 * HZ; - else { - if (hdlc->state.fr.n391cnt) - hdlc->state.fr.n391cnt--; - - fr_lmi_send(dev, hdlc->state.fr.n391cnt == 0); - - hdlc->state.fr.last_poll = jiffies; - hdlc->state.fr.request = 1; - hdlc->state.fr.timer.expires = jiffies + - hdlc->state.fr.settings.t391 * HZ; - } - - hdlc->state.fr.timer.function = fr_timer; - hdlc->state.fr.timer.data = arg; - add_timer(&hdlc->state.fr.timer); -} - - - -static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); - pvc_device *pvc; - u8 rxseq, txseq; - int lmi = hdlc->state.fr.settings.lmi; - int dce = hdlc->state.fr.settings.dce; - int stat_len = (lmi == LMI_CISCO) ? 6 : 3, reptype, error, no_ram, i; - - if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH : - LMI_CCITT_CISCO_LENGTH)) { - printk(KERN_INFO "%s: Short LMI frame\n", dev->name); - return 1; - } - - if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI : - NLPID_CCITT_ANSI_LMI)) { - printk(KERN_INFO "%s: Received non-LMI frame with LMI" - " DLCI\n", dev->name); - return 1; - } - - if (skb->data[4] != LMI_CALLREF) { - printk(KERN_INFO "%s: Invalid LMI Call reference (0x%02X)\n", - dev->name, skb->data[4]); - return 1; - } - - if (skb->data[5] != (dce ? LMI_STATUS_ENQUIRY : LMI_STATUS)) { - printk(KERN_INFO "%s: Invalid LMI Message type (0x%02X)\n", - dev->name, skb->data[5]); - return 1; - } - - if (lmi == LMI_ANSI) { - if (skb->data[6] != LMI_ANSI_LOCKSHIFT) { - printk(KERN_INFO "%s: Not ANSI locking shift in LMI" - " message (0x%02X)\n", dev->name, skb->data[6]); - return 1; - } - i = 7; - } else - i = 6; - - if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_REPTYPE : - LMI_ANSI_CISCO_REPTYPE)) { - printk(KERN_INFO "%s: Not an LMI Report type IE (0x%02X)\n", - dev->name, skb->data[i]); - return 1; - } - - if (skb->data[++i] != LMI_REPT_LEN) { - printk(KERN_INFO "%s: Invalid LMI Report type IE length" - " (%u)\n", dev->name, skb->data[i]); - return 1; - } - - reptype = skb->data[++i]; - if (reptype != LMI_INTEGRITY && reptype != LMI_FULLREP) { - printk(KERN_INFO "%s: Unsupported LMI Report type (0x%02X)\n", - dev->name, reptype); - return 1; - } - - if (skb->data[++i] != (lmi == LMI_CCITT ? LMI_CCITT_ALIVE : - LMI_ANSI_CISCO_ALIVE)) { - printk(KERN_INFO "%s: Not an LMI Link integrity verification" - " IE (0x%02X)\n", dev->name, skb->data[i]); - return 1; - } - - if (skb->data[++i] != LMI_INTEG_LEN) { - printk(KERN_INFO "%s: Invalid LMI Link integrity verification" - " IE length (%u)\n", dev->name, skb->data[i]); - return 1; - } - i++; - - hdlc->state.fr.rxseq = skb->data[i++]; /* TX sequence from peer */ - rxseq = skb->data[i++]; /* Should confirm our sequence */ - - txseq = hdlc->state.fr.txseq; - - if (dce) - hdlc->state.fr.last_poll = jiffies; - - error = 0; - if (!hdlc->state.fr.reliable) - error = 1; - - if (rxseq == 0 || rxseq != txseq) { - hdlc->state.fr.n391cnt = 0; /* Ask for full report next time */ - error = 1; - } - - if (dce) { - if (hdlc->state.fr.fullrep_sent && !error) { -/* Stop sending full report - the last one has been confirmed by DTE */ - hdlc->state.fr.fullrep_sent = 0; - pvc = hdlc->state.fr.first_pvc; - while (pvc) { - if (pvc->state.new) { - pvc->state.new = 0; - -/* Tell DTE that new PVC is now active */ - hdlc->state.fr.dce_changed = 1; - } - pvc = pvc->next; - } - } - - if (hdlc->state.fr.dce_changed) { - reptype = LMI_FULLREP; - hdlc->state.fr.fullrep_sent = 1; - hdlc->state.fr.dce_changed = 0; - } - - hdlc->state.fr.request = 1; /* got request */ - fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0); - return 0; - } - - /* DTE */ - - hdlc->state.fr.request = 0; /* got response, no request pending */ - - if (error) - return 0; - - if (reptype != LMI_FULLREP) - return 0; - - pvc = hdlc->state.fr.first_pvc; - - while (pvc) { - pvc->state.deleted = 1; - pvc = pvc->next; - } - - no_ram = 0; - while (skb->len >= i + 2 + stat_len) { - u16 dlci; - u32 bw; - unsigned int active, new; - - if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT : - LMI_ANSI_CISCO_PVCSTAT)) { - printk(KERN_INFO "%s: Not an LMI PVC status IE" - " (0x%02X)\n", dev->name, skb->data[i]); - return 1; - } - - if (skb->data[++i] != stat_len) { - printk(KERN_INFO "%s: Invalid LMI PVC status IE length" - " (%u)\n", dev->name, skb->data[i]); - return 1; - } - i++; - - new = !! (skb->data[i + 2] & 0x08); - active = !! (skb->data[i + 2] & 0x02); - if (lmi == LMI_CISCO) { - dlci = (skb->data[i] << 8) | skb->data[i + 1]; - bw = (skb->data[i + 3] << 16) | - (skb->data[i + 4] << 8) | - (skb->data[i + 5]); - } else { - dlci = ((skb->data[i] & 0x3F) << 4) | - ((skb->data[i + 1] & 0x78) >> 3); - bw = 0; - } - - pvc = add_pvc(dev, dlci); - - if (!pvc && !no_ram) { - printk(KERN_WARNING - "%s: Memory squeeze on fr_lmi_recv()\n", - dev->name); - no_ram = 1; - } - - if (pvc) { - pvc->state.exist = 1; - pvc->state.deleted = 0; - if (active != pvc->state.active || - new != pvc->state.new || - bw != pvc->state.bandwidth || - !pvc->state.exist) { - pvc->state.new = new; - pvc->state.active = active; - pvc->state.bandwidth = bw; - pvc_carrier(active, pvc); - fr_log_dlci_active(pvc); - } - } - - i += stat_len; - } - - pvc = hdlc->state.fr.first_pvc; - - while (pvc) { - if (pvc->state.deleted && pvc->state.exist) { - pvc_carrier(0, pvc); - pvc->state.active = pvc->state.new = 0; - pvc->state.exist = 0; - pvc->state.bandwidth = 0; - fr_log_dlci_active(pvc); - } - pvc = pvc->next; - } - - /* Next full report after N391 polls */ - hdlc->state.fr.n391cnt = hdlc->state.fr.settings.n391; - - return 0; -} - - - -static int fr_rx(struct sk_buff *skb) -{ - struct net_device *ndev = skb->dev; - hdlc_device *hdlc = dev_to_hdlc(ndev); - fr_hdr *fh = (fr_hdr*)skb->data; - u8 *data = skb->data; - u16 dlci; - pvc_device *pvc; - struct net_device *dev = NULL; - - if (skb->len <= 4 || fh->ea1 || data[2] != FR_UI) - goto rx_error; - - dlci = q922_to_dlci(skb->data); - - if ((dlci == LMI_CCITT_ANSI_DLCI && - (hdlc->state.fr.settings.lmi == LMI_ANSI || - hdlc->state.fr.settings.lmi == LMI_CCITT)) || - (dlci == LMI_CISCO_DLCI && - hdlc->state.fr.settings.lmi == LMI_CISCO)) { - if (fr_lmi_recv(ndev, skb)) - goto rx_error; - dev_kfree_skb_any(skb); - return NET_RX_SUCCESS; - } - - pvc = find_pvc(hdlc, dlci); - if (!pvc) { -#ifdef DEBUG_PKT - printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n", - ndev->name, dlci); -#endif - dev_kfree_skb_any(skb); - return NET_RX_DROP; - } - - if (pvc->state.fecn != fh->fecn) { -#ifdef DEBUG_ECN - printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", ndev->name, - dlci, fh->fecn ? "N" : "FF"); -#endif - pvc->state.fecn ^= 1; - } - - if (pvc->state.becn != fh->becn) { -#ifdef DEBUG_ECN - printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", ndev->name, - dlci, fh->becn ? "N" : "FF"); -#endif - pvc->state.becn ^= 1; - } - - - if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { - hdlc->stats.rx_dropped++; - return NET_RX_DROP; - } - - if (data[3] == NLPID_IP) { - skb_pull(skb, 4); /* Remove 4-byte header (hdr, UI, NLPID) */ - dev = pvc->main; - skb->protocol = htons(ETH_P_IP); - - } else if (data[3] == NLPID_IPV6) { - skb_pull(skb, 4); /* Remove 4-byte header (hdr, UI, NLPID) */ - dev = pvc->main; - skb->protocol = htons(ETH_P_IPV6); - - } else if (skb->len > 10 && data[3] == FR_PAD && - data[4] == NLPID_SNAP && data[5] == FR_PAD) { - u16 oui = ntohs(*(u16*)(data + 6)); - u16 pid = ntohs(*(u16*)(data + 8)); - skb_pull(skb, 10); - - switch ((((u32)oui) << 16) | pid) { - case ETH_P_ARP: /* routed frame with SNAP */ - case ETH_P_IPX: - case ETH_P_IP: /* a long variant */ - case ETH_P_IPV6: - dev = pvc->main; - skb->protocol = htons(pid); - break; - - case 0x80C20007: /* bridged Ethernet frame */ - if ((dev = pvc->ether) != NULL) - skb->protocol = eth_type_trans(skb, dev); - break; - - default: - printk(KERN_INFO "%s: Unsupported protocol, OUI=%x " - "PID=%x\n", ndev->name, oui, pid); - dev_kfree_skb_any(skb); - return NET_RX_DROP; - } - } else { - printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x " - "length = %i\n", ndev->name, data[3], skb->len); - dev_kfree_skb_any(skb); - return NET_RX_DROP; - } - - if (dev) { - struct net_device_stats *stats = pvc_get_stats(dev); - stats->rx_packets++; /* PVC traffic */ - stats->rx_bytes += skb->len; - if (pvc->state.becn) - stats->rx_compressed++; - skb->dev = dev; - netif_rx(skb); - return NET_RX_SUCCESS; - } else { - dev_kfree_skb_any(skb); - return NET_RX_DROP; - } - - rx_error: - hdlc->stats.rx_errors++; /* Mark error */ - dev_kfree_skb_any(skb); - return NET_RX_DROP; -} - - - -static void fr_start(struct net_device *dev) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); -#ifdef DEBUG_LINK - printk(KERN_DEBUG "fr_start\n"); -#endif - if (hdlc->state.fr.settings.lmi != LMI_NONE) { - hdlc->state.fr.reliable = 0; - hdlc->state.fr.dce_changed = 1; - hdlc->state.fr.request = 0; - hdlc->state.fr.fullrep_sent = 0; - hdlc->state.fr.last_errors = 0xFFFFFFFF; - hdlc->state.fr.n391cnt = 0; - hdlc->state.fr.txseq = hdlc->state.fr.rxseq = 0; - - init_timer(&hdlc->state.fr.timer); - /* First poll after 1 s */ - hdlc->state.fr.timer.expires = jiffies + HZ; - hdlc->state.fr.timer.function = fr_timer; - hdlc->state.fr.timer.data = (unsigned long)dev; - add_timer(&hdlc->state.fr.timer); - } else - fr_set_link_state(1, dev); -} - - - -static void fr_stop(struct net_device *dev) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); -#ifdef DEBUG_LINK - printk(KERN_DEBUG "fr_stop\n"); -#endif - if (hdlc->state.fr.settings.lmi != LMI_NONE) - del_timer_sync(&hdlc->state.fr.timer); - fr_set_link_state(0, dev); -} - - - -static void fr_close(struct net_device *dev) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); - pvc_device *pvc = hdlc->state.fr.first_pvc; - - while (pvc) { /* Shutdown all PVCs for this FRAD */ - if (pvc->main) - dev_close(pvc->main); - if (pvc->ether) - dev_close(pvc->ether); - pvc = pvc->next; - } -} - -static void dlci_setup(struct net_device *dev) -{ - dev->type = ARPHRD_DLCI; - dev->flags = IFF_POINTOPOINT; - dev->hard_header_len = 10; - dev->addr_len = 2; -} - -static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type) -{ - hdlc_device *hdlc = dev_to_hdlc(master); - pvc_device *pvc = NULL; - struct net_device *dev; - int result, used; - char * prefix = "pvc%d"; - - if (type == ARPHRD_ETHER) - prefix = "pvceth%d"; - - if ((pvc = add_pvc(master, dlci)) == NULL) { - printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n", - master->name); - return -ENOBUFS; - } - - if (*get_dev_p(pvc, type)) - return -EEXIST; - - used = pvc_is_used(pvc); - - if (type == ARPHRD_ETHER) - dev = alloc_netdev(sizeof(struct net_device_stats), - "pvceth%d", ether_setup); - else - dev = alloc_netdev(sizeof(struct net_device_stats), - "pvc%d", dlci_setup); - - if (!dev) { - printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n", - master->name); - delete_unused_pvcs(hdlc); - return -ENOBUFS; - } - - if (type == ARPHRD_ETHER) { - memcpy(dev->dev_addr, "\x00\x01", 2); - get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2); - } else { - *(u16*)dev->dev_addr = htons(dlci); - dlci_to_q922(dev->broadcast, dlci); - } - dev->hard_start_xmit = pvc_xmit; - dev->get_stats = pvc_get_stats; - dev->open = pvc_open; - dev->stop = pvc_close; - dev->do_ioctl = pvc_ioctl; - dev->change_mtu = pvc_change_mtu; - dev->mtu = HDLC_MAX_MTU; - dev->tx_queue_len = 0; - dev->priv = pvc; - - result = dev_alloc_name(dev, dev->name); - if (result < 0) { - free_netdev(dev); - delete_unused_pvcs(hdlc); - return result; - } - - if (register_netdevice(dev) != 0) { - free_netdev(dev); - delete_unused_pvcs(hdlc); - return -EIO; - } - - dev->destructor = free_netdev; - *get_dev_p(pvc, type) = dev; - if (!used) { - hdlc->state.fr.dce_changed = 1; - hdlc->state.fr.dce_pvc_count++; - } - return 0; -} - - - -static int fr_del_pvc(hdlc_device *hdlc, unsigned int dlci, int type) -{ - pvc_device *pvc; - struct net_device *dev; - - if ((pvc = find_pvc(hdlc, dlci)) == NULL) - return -ENOENT; - - if ((dev = *get_dev_p(pvc, type)) == NULL) - return -ENOENT; - - if (dev->flags & IFF_UP) - return -EBUSY; /* PVC in use */ - - unregister_netdevice(dev); /* the destructor will free_netdev(dev) */ - *get_dev_p(pvc, type) = NULL; - - if (!pvc_is_used(pvc)) { - hdlc->state.fr.dce_pvc_count--; - hdlc->state.fr.dce_changed = 1; - } - delete_unused_pvcs(hdlc); - return 0; -} - - - -static void fr_destroy(hdlc_device *hdlc) -{ - pvc_device *pvc; - - pvc = hdlc->state.fr.first_pvc; - hdlc->state.fr.first_pvc = NULL; /* All PVCs destroyed */ - hdlc->state.fr.dce_pvc_count = 0; - hdlc->state.fr.dce_changed = 1; - - while (pvc) { - pvc_device *next = pvc->next; - /* destructors will free_netdev() main and ether */ - if (pvc->main) - unregister_netdevice(pvc->main); - - if (pvc->ether) - unregister_netdevice(pvc->ether); - - kfree(pvc); - pvc = next; - } -} - - - -int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr) -{ - fr_proto __user *fr_s = ifr->ifr_settings.ifs_ifsu.fr; - const size_t size = sizeof(fr_proto); - fr_proto new_settings; - hdlc_device *hdlc = dev_to_hdlc(dev); - fr_proto_pvc pvc; - int result; - - switch (ifr->ifr_settings.type) { - case IF_GET_PROTO: - ifr->ifr_settings.type = IF_PROTO_FR; - if (ifr->ifr_settings.size < size) { - ifr->ifr_settings.size = size; /* data size wanted */ - return -ENOBUFS; - } - if (copy_to_user(fr_s, &hdlc->state.fr.settings, size)) - return -EFAULT; - return 0; - - case IF_PROTO_FR: - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - - if(dev->flags & IFF_UP) - return -EBUSY; - - if (copy_from_user(&new_settings, fr_s, size)) - return -EFAULT; - - if (new_settings.lmi == LMI_DEFAULT) - new_settings.lmi = LMI_ANSI; - - if ((new_settings.lmi != LMI_NONE && - new_settings.lmi != LMI_ANSI && - new_settings.lmi != LMI_CCITT && - new_settings.lmi != LMI_CISCO) || - new_settings.t391 < 1 || - new_settings.t392 < 2 || - new_settings.n391 < 1 || - new_settings.n392 < 1 || - new_settings.n393 < new_settings.n392 || - new_settings.n393 > 32 || - (new_settings.dce != 0 && - new_settings.dce != 1)) - return -EINVAL; - - result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); - if (result) - return result; - - if (hdlc->proto.id != IF_PROTO_FR) { - hdlc_proto_detach(hdlc); - hdlc->state.fr.first_pvc = NULL; - hdlc->state.fr.dce_pvc_count = 0; - } - memcpy(&hdlc->state.fr.settings, &new_settings, size); - memset(&hdlc->proto, 0, sizeof(hdlc->proto)); - - hdlc->proto.close = fr_close; - hdlc->proto.start = fr_start; - hdlc->proto.stop = fr_stop; - hdlc->proto.detach = fr_destroy; - hdlc->proto.netif_rx = fr_rx; - hdlc->proto.id = IF_PROTO_FR; - dev->hard_start_xmit = hdlc->xmit; - dev->hard_header = NULL; - dev->type = ARPHRD_FRAD; - dev->flags = IFF_POINTOPOINT | IFF_NOARP; - dev->addr_len = 0; - return 0; - - case IF_PROTO_FR_ADD_PVC: - case IF_PROTO_FR_DEL_PVC: - case IF_PROTO_FR_ADD_ETH_PVC: - case IF_PROTO_FR_DEL_ETH_PVC: - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (copy_from_user(&pvc, ifr->ifr_settings.ifs_ifsu.fr_pvc, - sizeof(fr_proto_pvc))) - return -EFAULT; - - if (pvc.dlci <= 0 || pvc.dlci >= 1024) - return -EINVAL; /* Only 10 bits, DLCI 0 reserved */ - - if (ifr->ifr_settings.type == IF_PROTO_FR_ADD_ETH_PVC || - ifr->ifr_settings.type == IF_PROTO_FR_DEL_ETH_PVC) - result = ARPHRD_ETHER; /* bridged Ethernet device */ - else - result = ARPHRD_DLCI; - - if (ifr->ifr_settings.type == IF_PROTO_FR_ADD_PVC || - ifr->ifr_settings.type == IF_PROTO_FR_ADD_ETH_PVC) - return fr_add_pvc(dev, pvc.dlci, result); - else - return fr_del_pvc(hdlc, pvc.dlci, result); - } - - return -EINVAL; -} diff --git a/datamods/hdlc_generic.c b/datamods/hdlc_generic.c deleted file mode 100644 index 46cef8f..0000000 --- a/datamods/hdlc_generic.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Generic HDLC support routines for Linux - * - * Copyright (C) 1999 - 2005 Krzysztof Halasa - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * Currently supported: - * * raw IP-in-HDLC - * * Cisco HDLC - * * Frame Relay with ANSI or CCITT LMI (both user and network side) - * * PPP - * * X.25 - * - * Use sethdlc utility to set line parameters, protocol and PVCs - * - * How does it work: - * - proto.open(), close(), start(), stop() calls are serialized. - * The order is: open, [ start, stop ... ] close ... - * - proto.start() and stop() are called with spin_lock_irq held. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -static const char* version = "HDLC support module revision 1.18"; - -#undef DEBUG_LINK - - -static int hdlc_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - - - -static struct net_device_stats *hdlc_get_stats(struct net_device *dev) -{ - return hdlc_stats(dev); -} - - - -static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *p, struct net_device *orig_dev) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); - if (hdlc->proto.netif_rx) - return hdlc->proto.netif_rx(skb); - - hdlc->stats.rx_dropped++; /* Shouldn't happen */ - dev_kfree_skb(skb); - return NET_RX_DROP; -} - - - -static void __hdlc_set_carrier_on(struct net_device *dev) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); - if (hdlc->proto.start) - return hdlc->proto.start(dev); -#if 0 -#ifdef DEBUG_LINK - if (netif_carrier_ok(dev)) - printk(KERN_ERR "hdlc_set_carrier_on(): already on\n"); -#endif - netif_carrier_on(dev); -#endif -} - - - -static void __hdlc_set_carrier_off(struct net_device *dev) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); - if (hdlc->proto.stop) - return hdlc->proto.stop(dev); - -#if 0 -#ifdef DEBUG_LINK - if (!netif_carrier_ok(dev)) - printk(KERN_ERR "hdlc_set_carrier_off(): already off\n"); -#endif - netif_carrier_off(dev); -#endif -} - - - -void hdlc_set_carrier(int on, struct net_device *dev) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); - unsigned long flags; - on = on ? 1 : 0; - -#ifdef DEBUG_LINK - printk(KERN_DEBUG "hdlc_set_carrier %i\n", on); -#endif - - spin_lock_irqsave(&hdlc->state_lock, flags); - - if (hdlc->carrier == on) - goto carrier_exit; /* no change in DCD line level */ - -#ifdef DEBUG_LINK - printk(KERN_INFO "%s: carrier %s\n", dev->name, on ? "ON" : "off"); -#endif - hdlc->carrier = on; - - if (!hdlc->open) - goto carrier_exit; - - if (hdlc->carrier) { - printk(KERN_INFO "%s: Carrier detected\n", dev->name); - __hdlc_set_carrier_on(dev); - } else { - printk(KERN_INFO "%s: Carrier lost\n", dev->name); - __hdlc_set_carrier_off(dev); - } - -carrier_exit: - spin_unlock_irqrestore(&hdlc->state_lock, flags); -} - - - -/* Must be called by hardware driver when HDLC device is being opened */ -int hdlc_open(struct net_device *dev) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); -#ifdef DEBUG_LINK - printk(KERN_DEBUG "hdlc_open() carrier %i open %i\n", - hdlc->carrier, hdlc->open); -#endif - - if (hdlc->proto.id == -1) - return -ENOSYS; /* no protocol attached */ - - if (hdlc->proto.open) { - int result = hdlc->proto.open(dev); - if (result) - return result; - } - - spin_lock_irq(&hdlc->state_lock); - - if (hdlc->carrier) { - printk(KERN_INFO "%s: Carrier detected\n", dev->name); - __hdlc_set_carrier_on(dev); - } else - printk(KERN_INFO "%s: No carrier\n", dev->name); - - hdlc->open = 1; - - spin_unlock_irq(&hdlc->state_lock); - return 0; -} - - - -/* Must be called by hardware driver when HDLC device is being closed */ -void hdlc_close(struct net_device *dev) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); -#ifdef DEBUG_LINK - printk(KERN_DEBUG "hdlc_close() carrier %i open %i\n", - hdlc->carrier, hdlc->open); -#endif - - spin_lock_irq(&hdlc->state_lock); - - hdlc->open = 0; - if (hdlc->carrier) - __hdlc_set_carrier_off(dev); - - spin_unlock_irq(&hdlc->state_lock); - - if (hdlc->proto.close) - hdlc->proto.close(dev); -} - - - -#ifndef CONFIG_HDLC_RAW -#define hdlc_raw_ioctl(dev, ifr) -ENOSYS -#endif - -#ifndef CONFIG_HDLC_RAW_ETH -#define hdlc_raw_eth_ioctl(dev, ifr) -ENOSYS -#endif - -#ifndef CONFIG_HDLC_PPP -#define hdlc_ppp_ioctl(dev, ifr) -ENOSYS -#endif - -#ifndef CONFIG_HDLC_CISCO -#define hdlc_cisco_ioctl(dev, ifr) -ENOSYS -#endif - -#ifndef CONFIG_HDLC_FR -#define hdlc_fr_ioctl(dev, ifr) -ENOSYS -#endif - -#ifndef CONFIG_HDLC_X25 -#define hdlc_x25_ioctl(dev, ifr) -ENOSYS -#endif - - -int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); - unsigned int proto; - - if (cmd != SIOCWANDEV) - return -EINVAL; - - switch(ifr->ifr_settings.type) { - case IF_PROTO_HDLC: - case IF_PROTO_HDLC_ETH: - case IF_PROTO_PPP: - case IF_PROTO_CISCO: - case IF_PROTO_FR: - case IF_PROTO_X25: - proto = ifr->ifr_settings.type; - break; - - default: - proto = hdlc->proto.id; - } - - switch(proto) { - case IF_PROTO_HDLC: return hdlc_raw_ioctl(dev, ifr); - case IF_PROTO_HDLC_ETH: return hdlc_raw_eth_ioctl(dev, ifr); - case IF_PROTO_PPP: return hdlc_ppp_ioctl(dev, ifr); - case IF_PROTO_CISCO: return hdlc_cisco_ioctl(dev, ifr); - case IF_PROTO_FR: return hdlc_fr_ioctl(dev, ifr); - case IF_PROTO_X25: return hdlc_x25_ioctl(dev, ifr); - default: return -EINVAL; - } -} - -static void hdlc_setup(struct net_device *dev) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); - - dev->get_stats = hdlc_get_stats; - dev->change_mtu = hdlc_change_mtu; - dev->mtu = HDLC_MAX_MTU; - - dev->type = ARPHRD_RAWHDLC; - dev->hard_header_len = 16; - - dev->flags = IFF_POINTOPOINT | IFF_NOARP; - - hdlc->proto.id = -1; - hdlc->proto.detach = NULL; - hdlc->carrier = 1; - hdlc->open = 0; - spin_lock_init(&hdlc->state_lock); -} - -struct net_device *alloc_hdlcdev(void *priv) -{ - struct net_device *dev; - dev = alloc_netdev(sizeof(hdlc_device), "hdlc%d", hdlc_setup); - if (dev) - dev_to_hdlc(dev)->priv = priv; - return dev; -} - -int register_hdlc_device(struct net_device *dev) -{ - int result = dev_alloc_name(dev, "hdlc%d"); - if (result < 0) - return result; - - result = register_netdev(dev); - if (result != 0) - return -EIO; - -#if 0 - if (netif_carrier_ok(dev)) - netif_carrier_off(dev); /* no carrier until DCD goes up */ -#endif - - return 0; -} - - - -void unregister_hdlc_device(struct net_device *dev) -{ - rtnl_lock(); - hdlc_proto_detach(dev_to_hdlc(dev)); - unregister_netdevice(dev); - rtnl_unlock(); -} - - - -MODULE_AUTHOR("Krzysztof Halasa "); -MODULE_DESCRIPTION("HDLC support module"); -MODULE_LICENSE("GPL v2"); - -EXPORT_SYMBOL(hdlc_open); -EXPORT_SYMBOL(hdlc_close); -EXPORT_SYMBOL(hdlc_set_carrier); -EXPORT_SYMBOL(hdlc_ioctl); -EXPORT_SYMBOL(alloc_hdlcdev); -EXPORT_SYMBOL(register_hdlc_device); -EXPORT_SYMBOL(unregister_hdlc_device); - -static struct packet_type hdlc_packet_type = { - .type = __constant_htons(ETH_P_HDLC), - .func = hdlc_rcv, -}; - - -static int __init hdlc_module_init(void) -{ - printk(KERN_INFO "%s\n", version); - dev_add_pack(&hdlc_packet_type); - return 0; -} - - - -static void __exit hdlc_module_exit(void) -{ - dev_remove_pack(&hdlc_packet_type); -} - - -module_init(hdlc_module_init); -module_exit(hdlc_module_exit); diff --git a/datamods/hdlc_ppp.c b/datamods/hdlc_ppp.c deleted file mode 100644 index b81263e..0000000 --- a/datamods/hdlc_ppp.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Generic HDLC support routines for Linux - * Point-to-point protocol support - * - * Copyright (C) 1999 - 2003 Krzysztof Halasa - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -static int ppp_open(struct net_device *dev) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); - void *old_ioctl; - int result; - - dev->priv = &hdlc->state.ppp.syncppp_ptr; - hdlc->state.ppp.syncppp_ptr = &hdlc->state.ppp.pppdev; - hdlc->state.ppp.pppdev.dev = dev; - - old_ioctl = dev->do_ioctl; - hdlc->state.ppp.old_change_mtu = dev->change_mtu; - sppp_attach(&hdlc->state.ppp.pppdev); - /* sppp_attach nukes them. We don't need syncppp's ioctl */ - dev->do_ioctl = old_ioctl; - hdlc->state.ppp.pppdev.sppp.pp_flags &= ~PP_CISCO; - dev->type = ARPHRD_PPP; - result = sppp_open(dev); - if (result) { - sppp_detach(dev); - return result; - } - - return 0; -} - - - -static void ppp_close(struct net_device *dev) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); - - sppp_close(dev); - sppp_detach(dev); - dev->rebuild_header = NULL; - dev->change_mtu = hdlc->state.ppp.old_change_mtu; - dev->mtu = HDLC_MAX_MTU; - dev->hard_header_len = 16; -} - - - -static __be16 ppp_type_trans(struct sk_buff *skb, struct net_device *dev) -{ - return __constant_htons(ETH_P_WAN_PPP); -} - - - -int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr) -{ - hdlc_device *hdlc = dev_to_hdlc(dev); - int result; - - switch (ifr->ifr_settings.type) { - case IF_GET_PROTO: - ifr->ifr_settings.type = IF_PROTO_PPP; - return 0; /* return protocol only, no settable parameters */ - - case IF_PROTO_PPP: - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - - if(dev->flags & IFF_UP) - return -EBUSY; - - /* no settable parameters */ - - result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); - if (result) - return result; - - hdlc_proto_detach(hdlc); - memset(&hdlc->proto, 0, sizeof(hdlc->proto)); - - hdlc->proto.open = ppp_open; - hdlc->proto.close = ppp_close; - hdlc->proto.type_trans = ppp_type_trans; - hdlc->proto.id = IF_PROTO_PPP; - dev->hard_start_xmit = hdlc->xmit; - dev->hard_header = NULL; - dev->type = ARPHRD_PPP; - dev->addr_len = 0; - return 0; - } - - return -EINVAL; -} diff --git a/datamods/hdlc_raw.c b/datamods/hdlc_raw.c deleted file mode 100644 index 9456d31..0000000 --- a/datamods/hdlc_raw.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Generic HDLC support routines for Linux - * HDLC support - * - * Copyright (C) 1999 - 2003 Krzysztof Halasa - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev) -{ - return __constant_htons(ETH_P_IP); -} - - - -int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr) -{ - raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; - const size_t size = sizeof(raw_hdlc_proto); - raw_hdlc_proto new_settings; - hdlc_device *hdlc = dev_to_hdlc(dev); - int result; - - switch (ifr->ifr_settings.type) { - case IF_GET_PROTO: - ifr->ifr_settings.type = IF_PROTO_HDLC; - if (ifr->ifr_settings.size < size) { - ifr->ifr_settings.size = size; /* data size wanted */ - return -ENOBUFS; - } - if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size)) - return -EFAULT; - return 0; - - case IF_PROTO_HDLC: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (dev->flags & IFF_UP) - return -EBUSY; - - if (copy_from_user(&new_settings, raw_s, size)) - return -EFAULT; - - if (new_settings.encoding == ENCODING_DEFAULT) - new_settings.encoding = ENCODING_NRZ; - - if (new_settings.parity == PARITY_DEFAULT) - new_settings.parity = PARITY_CRC16_PR1_CCITT; - - result = hdlc->attach(dev, new_settings.encoding, - new_settings.parity); - if (result) - return result; - - hdlc_proto_detach(hdlc); - memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size); - memset(&hdlc->proto, 0, sizeof(hdlc->proto)); - - hdlc->proto.type_trans = raw_type_trans; - hdlc->proto.id = IF_PROTO_HDLC; - dev->hard_start_xmit = hdlc->xmit; - dev->hard_header = NULL; - dev->type = ARPHRD_RAWHDLC; - dev->flags = IFF_POINTOPOINT | IFF_NOARP; - dev->addr_len = 0; - return 0; - } - - return -EINVAL; -} diff --git a/datamods/hdlc_raw_eth.c b/datamods/hdlc_raw_eth.c deleted file mode 100644 index b1285cc..0000000 --- a/datamods/hdlc_raw_eth.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Generic HDLC support routines for Linux - * HDLC Ethernet emulation support - * - * Copyright (C) 2002-2003 Krzysztof Halasa - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -static int eth_tx(struct sk_buff *skb, struct net_device *dev) -{ - int pad = ETH_ZLEN - skb->len; - if (pad > 0) { /* Pad the frame with zeros */ - int len = skb->len; - if (skb_tailroom(skb) < pad) - if (pskb_expand_head(skb, 0, pad, GFP_ATOMIC)) { - hdlc_stats(dev)->tx_dropped++; - dev_kfree_skb(skb); - return 0; - } - skb_put(skb, pad); - memset(skb->data + len, 0, pad); - } - return dev_to_hdlc(dev)->xmit(skb, dev); -} - - -int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) -{ - raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; - const size_t size = sizeof(raw_hdlc_proto); - raw_hdlc_proto new_settings; - hdlc_device *hdlc = dev_to_hdlc(dev); - int result; - void *old_ch_mtu; - int old_qlen; - - switch (ifr->ifr_settings.type) { - case IF_GET_PROTO: - ifr->ifr_settings.type = IF_PROTO_HDLC_ETH; - if (ifr->ifr_settings.size < size) { - ifr->ifr_settings.size = size; /* data size wanted */ - return -ENOBUFS; - } - if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size)) - return -EFAULT; - return 0; - - case IF_PROTO_HDLC_ETH: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (dev->flags & IFF_UP) - return -EBUSY; - - if (copy_from_user(&new_settings, raw_s, size)) - return -EFAULT; - - if (new_settings.encoding == ENCODING_DEFAULT) - new_settings.encoding = ENCODING_NRZ; - - if (new_settings.parity == PARITY_DEFAULT) - new_settings.parity = PARITY_CRC16_PR1_CCITT; - - result = hdlc->attach(dev, new_settings.encoding, - new_settings.parity); - if (result) - return result; - - hdlc_proto_detach(hdlc); - memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size); - memset(&hdlc->proto, 0, sizeof(hdlc->proto)); - - hdlc->proto.type_trans = eth_type_trans; - hdlc->proto.id = IF_PROTO_HDLC_ETH; - dev->hard_start_xmit = eth_tx; - old_ch_mtu = dev->change_mtu; - old_qlen = dev->tx_queue_len; - ether_setup(dev); - dev->change_mtu = old_ch_mtu; - dev->tx_queue_len = old_qlen; - memcpy(dev->dev_addr, "\x00\x01", 2); - get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2); - return 0; - } - - return -EINVAL; -} diff --git a/datamods/syncppp.c b/datamods/syncppp.c deleted file mode 100644 index 5ca283a..0000000 --- a/datamods/syncppp.c +++ /dev/null @@ -1,1485 +0,0 @@ -/* - * NET3: A (fairly minimal) implementation of synchronous PPP for Linux - * as well as a CISCO HDLC implementation. See the copyright - * message below for the original source. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the license, or (at your option) any later version. - * - * Note however. This code is also used in a different form by FreeBSD. - * Therefore when making any non OS specific change please consider - * contributing it back to the original author under the terms - * below in addition. - * -- Alan - * - * Port for Linux-2.1 by Jan "Yenya" Kasprzak - */ - -/* - * Synchronous PPP/Cisco link level subroutines. - * Keepalive protocol implemented in both Cisco and PPP modes. - * - * Copyright (C) 1994 Cronyx Ltd. - * Author: Serge Vakulenko, - * - * This software is distributed with NO WARRANTIES, not even the implied - * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Authors grant any other persons or organisations permission to use - * or modify this software as long as this message is kept with the software, - * all derivative works or modified versions. - * - * Version 1.9, Wed Oct 4 18:58:15 MSK 1995 - * - * $Id$ - */ -#undef DEBUG - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#define MAXALIVECNT 6 /* max. alive packets */ - -#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ -#define PPP_UI 0x03 /* Unnumbered Information */ -#define PPP_IP 0x0021 /* Internet Protocol */ -#define PPP_ISO 0x0023 /* ISO OSI Protocol */ -#define PPP_XNS 0x0025 /* Xerox NS Protocol */ -#define PPP_IPX 0x002b /* Novell IPX Protocol */ -#define PPP_LCP 0xc021 /* Link Control Protocol */ -#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ - -#define LCP_CONF_REQ 1 /* PPP LCP configure request */ -#define LCP_CONF_ACK 2 /* PPP LCP configure acknowledge */ -#define LCP_CONF_NAK 3 /* PPP LCP configure negative ack */ -#define LCP_CONF_REJ 4 /* PPP LCP configure reject */ -#define LCP_TERM_REQ 5 /* PPP LCP terminate request */ -#define LCP_TERM_ACK 6 /* PPP LCP terminate acknowledge */ -#define LCP_CODE_REJ 7 /* PPP LCP code reject */ -#define LCP_PROTO_REJ 8 /* PPP LCP protocol reject */ -#define LCP_ECHO_REQ 9 /* PPP LCP echo request */ -#define LCP_ECHO_REPLY 10 /* PPP LCP echo reply */ -#define LCP_DISC_REQ 11 /* PPP LCP discard request */ - -#define LCP_OPT_MRU 1 /* maximum receive unit */ -#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ -#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ -#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ -#define LCP_OPT_MAGIC 5 /* magic number */ -#define LCP_OPT_RESERVED 6 /* reserved */ -#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ -#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ - -#define IPCP_CONF_REQ LCP_CONF_REQ /* PPP IPCP configure request */ -#define IPCP_CONF_ACK LCP_CONF_ACK /* PPP IPCP configure acknowledge */ -#define IPCP_CONF_NAK LCP_CONF_NAK /* PPP IPCP configure negative ack */ -#define IPCP_CONF_REJ LCP_CONF_REJ /* PPP IPCP configure reject */ -#define IPCP_TERM_REQ LCP_TERM_REQ /* PPP IPCP terminate request */ -#define IPCP_TERM_ACK LCP_TERM_ACK /* PPP IPCP terminate acknowledge */ -#define IPCP_CODE_REJ LCP_CODE_REJ /* PPP IPCP code reject */ - -#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ -#define CISCO_UNICAST 0x0f /* Cisco unicast address */ -#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ -#define CISCO_ADDR_REQ 0 /* Cisco address request */ -#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ -#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ - -struct ppp_header { - u8 address; - u8 control; - u16 protocol; -}; -#define PPP_HEADER_LEN sizeof (struct ppp_header) - -struct lcp_header { - u8 type; - u8 ident; - u16 len; -}; -#define LCP_HEADER_LEN sizeof (struct lcp_header) - -struct cisco_packet { - u32 type; - u32 par1; - u32 par2; - u16 rel; - u16 time0; - u16 time1; -}; -#define CISCO_PACKET_LEN 18 -#define CISCO_BIG_PACKET_LEN 20 - -static struct sppp *spppq; -static struct timer_list sppp_keepalive_timer; -static DEFINE_SPINLOCK(spppq_lock); - -/* global xmit queue for sending packets while spinlock is held */ -static struct sk_buff_head tx_queue; - -static void sppp_keepalive (unsigned long dummy); -static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type, - u8 ident, u16 len, void *data); -static void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2); -static void sppp_lcp_input (struct sppp *sp, struct sk_buff *m); -static void sppp_cisco_input (struct sppp *sp, struct sk_buff *m); -static void sppp_ipcp_input (struct sppp *sp, struct sk_buff *m); -static void sppp_lcp_open (struct sppp *sp); -static void sppp_ipcp_open (struct sppp *sp); -static int sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h, - int len, u32 *magic); -static void sppp_cp_timeout (unsigned long arg); -static char *sppp_lcp_type_name (u8 type); -static char *sppp_ipcp_type_name (u8 type); -static void sppp_print_bytes (u8 *p, u16 len); - -static int debug; - -/* Flush global outgoing packet queue to dev_queue_xmit(). - * - * dev_queue_xmit() must be called with interrupts enabled - * which means it can't be called with spinlocks held. - * If a packet needs to be sent while a spinlock is held, - * then put the packet into tx_queue, and call sppp_flush_xmit() - * after spinlock is released. - */ -static void sppp_flush_xmit(void) -{ - struct sk_buff *skb; - while ((skb = skb_dequeue(&tx_queue)) != NULL) - dev_queue_xmit(skb); -} - -/* - * Interface down stub - */ - -static void if_down(struct net_device *dev) -{ - struct sppp *sp = (struct sppp *)sppp_of(dev); - - sp->pp_link_state=SPPP_LINK_DOWN; -} - -/* - * Timeout routine activations. - */ - -static void sppp_set_timeout(struct sppp *p,int s) -{ - if (! (p->pp_flags & PP_TIMO)) - { - init_timer(&p->pp_timer); - p->pp_timer.function=sppp_cp_timeout; - p->pp_timer.expires=jiffies+s*HZ; - p->pp_timer.data=(unsigned long)p; - p->pp_flags |= PP_TIMO; - add_timer(&p->pp_timer); - } -} - -static void sppp_clear_timeout(struct sppp *p) -{ - if (p->pp_flags & PP_TIMO) - { - del_timer(&p->pp_timer); - p->pp_flags &= ~PP_TIMO; - } -} - -/** - * sppp_input - receive and process a WAN PPP frame - * @skb: The buffer to process - * @dev: The device it arrived on - * - * This can be called directly by cards that do not have - * timing constraints but is normally called from the network layer - * after interrupt servicing to process frames queued via netif_rx(). - * - * We process the options in the card. If the frame is destined for - * the protocol stacks then it requeues the frame for the upper level - * protocol. If it is a control from it is processed and discarded - * here. - */ - -static void sppp_input (struct net_device *dev, struct sk_buff *skb) -{ - struct ppp_header *h; - struct sppp *sp = (struct sppp *)sppp_of(dev); - unsigned long flags; - - skb->dev=dev; - skb->mac.raw=skb->data; - - if (dev->flags & IFF_RUNNING) - { - /* Count received bytes, add FCS and one flag */ - sp->ibytes+= skb->len + 3; - sp->ipkts++; - } - - if (!pskb_may_pull(skb, PPP_HEADER_LEN)) { - /* Too small packet, drop it. */ - if (sp->pp_flags & PP_DEBUG) - printk (KERN_DEBUG "%s: input packet is too small, %d bytes\n", - dev->name, skb->len); - kfree_skb(skb); - return; - } - - /* Get PPP header. */ - h = (struct ppp_header *)skb->data; - skb_pull(skb,sizeof(struct ppp_header)); - - spin_lock_irqsave(&sp->lock, flags); - - switch (h->address) { - default: /* Invalid PPP packet. */ - goto invalid; - case PPP_ALLSTATIONS: - if (h->control != PPP_UI) - goto invalid; - if (sp->pp_flags & PP_CISCO) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: PPP packet in Cisco mode <0x%x 0x%x 0x%x>\n", - dev->name, - h->address, h->control, ntohs (h->protocol)); - goto drop; - } - switch (ntohs (h->protocol)) { - default: - if (sp->lcp.state == LCP_STATE_OPENED) - sppp_cp_send (sp, PPP_LCP, LCP_PROTO_REJ, - ++sp->pp_seq, skb->len + 2, - &h->protocol); - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: invalid input protocol <0x%x 0x%x 0x%x>\n", - dev->name, - h->address, h->control, ntohs (h->protocol)); - goto drop; - case PPP_LCP: - sppp_lcp_input (sp, skb); - goto drop; - case PPP_IPCP: - if (sp->lcp.state == LCP_STATE_OPENED) - sppp_ipcp_input (sp, skb); - else - printk(KERN_DEBUG "IPCP when still waiting LCP finish.\n"); - goto drop; - case PPP_IP: - if (sp->ipcp.state == IPCP_STATE_OPENED) { - if(sp->pp_flags&PP_DEBUG) - printk(KERN_DEBUG "Yow an IP frame.\n"); - skb->protocol=htons(ETH_P_IP); - netif_rx(skb); - dev->last_rx = jiffies; - goto done; - } - break; -#ifdef IPX - case PPP_IPX: - /* IPX IPXCP not implemented yet */ - if (sp->lcp.state == LCP_STATE_OPENED) { - skb->protocol=htons(ETH_P_IPX); - netif_rx(skb); - dev->last_rx = jiffies; - goto done; - } - break; -#endif - } - break; - case CISCO_MULTICAST: - case CISCO_UNICAST: - /* Don't check the control field here (RFC 1547). */ - if (! (sp->pp_flags & PP_CISCO)) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: Cisco packet in PPP mode <0x%x 0x%x 0x%x>\n", - dev->name, - h->address, h->control, ntohs (h->protocol)); - goto drop; - } - switch (ntohs (h->protocol)) { - default: - goto invalid; - case CISCO_KEEPALIVE: - sppp_cisco_input (sp, skb); - goto drop; -#ifdef CONFIG_INET - case ETH_P_IP: - skb->protocol=htons(ETH_P_IP); - netif_rx(skb); - dev->last_rx = jiffies; - goto done; -#endif -#ifdef CONFIG_IPX - case ETH_P_IPX: - skb->protocol=htons(ETH_P_IPX); - netif_rx(skb); - dev->last_rx = jiffies; - goto done; -#endif - } - break; - } - goto drop; - -invalid: - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: invalid input packet <0x%x 0x%x 0x%x>\n", - dev->name, h->address, h->control, ntohs (h->protocol)); -drop: - kfree_skb(skb); -done: - spin_unlock_irqrestore(&sp->lock, flags); - sppp_flush_xmit(); - return; -} - -/* - * Handle transmit packets. - */ - -static int sppp_hard_header(struct sk_buff *skb, struct net_device *dev, __u16 type, - void *daddr, void *saddr, unsigned int len) -{ - struct sppp *sp = (struct sppp *)sppp_of(dev); - struct ppp_header *h; - skb_push(skb,sizeof(struct ppp_header)); - h=(struct ppp_header *)skb->data; - if(sp->pp_flags&PP_CISCO) - { - h->address = CISCO_UNICAST; - h->control = 0; - } - else - { - h->address = PPP_ALLSTATIONS; - h->control = PPP_UI; - } - if(sp->pp_flags & PP_CISCO) - { - h->protocol = htons(type); - } - else switch(type) - { - case ETH_P_IP: - h->protocol = htons(PPP_IP); - break; - case ETH_P_IPX: - h->protocol = htons(PPP_IPX); - break; - } - return sizeof(struct ppp_header); -} - -static int sppp_rebuild_header(struct sk_buff *skb) -{ - return 0; -} - -/* - * Send keepalive packets, every 10 seconds. - */ - -static void sppp_keepalive (unsigned long dummy) -{ - struct sppp *sp; - unsigned long flags; - - spin_lock_irqsave(&spppq_lock, flags); - - for (sp=spppq; sp; sp=sp->pp_next) - { - struct net_device *dev = sp->pp_if; - - /* Keepalive mode disabled or channel down? */ - if (! (sp->pp_flags & PP_KEEPALIVE) || - ! (dev->flags & IFF_UP)) - continue; - - spin_lock(&sp->lock); - - /* No keepalive in PPP mode if LCP not opened yet. */ - if (! (sp->pp_flags & PP_CISCO) && - sp->lcp.state != LCP_STATE_OPENED) { - spin_unlock(&sp->lock); - continue; - } - - if (sp->pp_alivecnt == MAXALIVECNT) { - /* No keepalive packets got. Stop the interface. */ - printk (KERN_WARNING "%s: protocol down\n", dev->name); - if_down (dev); - if (! (sp->pp_flags & PP_CISCO)) { - /* Shut down the PPP link. */ - sp->lcp.magic = jiffies; - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - sppp_clear_timeout (sp); - /* Initiate negotiation. */ - sppp_lcp_open (sp); - } - } - if (sp->pp_alivecnt <= MAXALIVECNT) - ++sp->pp_alivecnt; - if (sp->pp_flags & PP_CISCO) - sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq, - sp->pp_rseq); - else if (sp->lcp.state == LCP_STATE_OPENED) { - long nmagic = htonl (sp->lcp.magic); - sp->lcp.echoid = ++sp->pp_seq; - sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REQ, - sp->lcp.echoid, 4, &nmagic); - } - - spin_unlock(&sp->lock); - } - spin_unlock_irqrestore(&spppq_lock, flags); - sppp_flush_xmit(); - sppp_keepalive_timer.expires=jiffies+10*HZ; - add_timer(&sppp_keepalive_timer); -} - -/* - * Handle incoming PPP Link Control Protocol packets. - */ - -static void sppp_lcp_input (struct sppp *sp, struct sk_buff *skb) -{ - struct lcp_header *h; - struct net_device *dev = sp->pp_if; - int len = skb->len; - u8 *p, opt[6]; - u32 rmagic; - - if (!pskb_may_pull(skb, sizeof(struct lcp_header))) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: invalid lcp packet length: %d bytes\n", - dev->name, len); - return; - } - h = (struct lcp_header *)skb->data; - skb_pull(skb,sizeof(struct lcp_header *)); - - if (sp->pp_flags & PP_DEBUG) - { - char state = '?'; - switch (sp->lcp.state) { - case LCP_STATE_CLOSED: state = 'C'; break; - case LCP_STATE_ACK_RCVD: state = 'R'; break; - case LCP_STATE_ACK_SENT: state = 'S'; break; - case LCP_STATE_OPENED: state = 'O'; break; - } - printk (KERN_WARNING "%s: lcp input(%c): %d bytes <%s id=%xh len=%xh", - dev->name, state, len, - sppp_lcp_type_name (h->type), h->ident, ntohs (h->len)); - if (len > 4) - sppp_print_bytes ((u8*) (h+1), len-4); - printk (">\n"); - } - if (len > ntohs (h->len)) - len = ntohs (h->len); - switch (h->type) { - default: - /* Unknown packet type -- send Code-Reject packet. */ - sppp_cp_send (sp, PPP_LCP, LCP_CODE_REJ, ++sp->pp_seq, - skb->len, h); - break; - case LCP_CONF_REQ: - if (len < 4) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_DEBUG"%s: invalid lcp configure request packet length: %d bytes\n", - dev->name, len); - break; - } - if (len>4 && !sppp_lcp_conf_parse_options (sp, h, len, &rmagic)) - goto badreq; - if (rmagic == sp->lcp.magic) { - /* Local and remote magics equal -- loopback? */ - if (sp->pp_loopcnt >= MAXALIVECNT*5) { - printk (KERN_WARNING "%s: loopback\n", - dev->name); - sp->pp_loopcnt = 0; - if (dev->flags & IFF_UP) { - if_down (dev); - } - } else if (sp->pp_flags & PP_DEBUG) - printk (KERN_DEBUG "%s: conf req: magic glitch\n", - dev->name); - ++sp->pp_loopcnt; - - /* MUST send Conf-Nack packet. */ - rmagic = ~sp->lcp.magic; - opt[0] = LCP_OPT_MAGIC; - opt[1] = sizeof (opt); - opt[2] = rmagic >> 24; - opt[3] = rmagic >> 16; - opt[4] = rmagic >> 8; - opt[5] = rmagic; - sppp_cp_send (sp, PPP_LCP, LCP_CONF_NAK, - h->ident, sizeof (opt), &opt); -badreq: - switch (sp->lcp.state) { - case LCP_STATE_OPENED: - /* Initiate renegotiation. */ - sppp_lcp_open (sp); - /* fall through... */ - case LCP_STATE_ACK_SENT: - /* Go to closed state. */ - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - } - break; - } - /* Send Configure-Ack packet. */ - sp->pp_loopcnt = 0; - if (sp->lcp.state != LCP_STATE_OPENED) { - sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK, - h->ident, len-4, h+1); - } - /* Change the state. */ - switch (sp->lcp.state) { - case LCP_STATE_CLOSED: - sp->lcp.state = LCP_STATE_ACK_SENT; - break; - case LCP_STATE_ACK_RCVD: - sp->lcp.state = LCP_STATE_OPENED; - sppp_ipcp_open (sp); - break; - case LCP_STATE_OPENED: - /* Remote magic changed -- close session. */ - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - /* Initiate renegotiation. */ - sppp_lcp_open (sp); - /* Send ACK after our REQ in attempt to break loop */ - sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK, - h->ident, len-4, h+1); - sp->lcp.state = LCP_STATE_ACK_SENT; - break; - } - break; - case LCP_CONF_ACK: - if (h->ident != sp->lcp.confid) - break; - sppp_clear_timeout (sp); - if ((sp->pp_link_state != SPPP_LINK_UP) && - (dev->flags & IFF_UP)) { - /* Coming out of loopback mode. */ - sp->pp_link_state=SPPP_LINK_UP; - printk (KERN_INFO "%s: protocol up\n", dev->name); - } - switch (sp->lcp.state) { - case LCP_STATE_CLOSED: - sp->lcp.state = LCP_STATE_ACK_RCVD; - sppp_set_timeout (sp, 5); - break; - case LCP_STATE_ACK_SENT: - sp->lcp.state = LCP_STATE_OPENED; - sppp_ipcp_open (sp); - break; - } - break; - case LCP_CONF_NAK: - if (h->ident != sp->lcp.confid) - break; - p = (u8*) (h+1); - if (len>=10 && p[0] == LCP_OPT_MAGIC && p[1] >= 4) { - rmagic = (u32)p[2] << 24 | - (u32)p[3] << 16 | p[4] << 8 | p[5]; - if (rmagic == ~sp->lcp.magic) { - int newmagic; - if (sp->pp_flags & PP_DEBUG) - printk (KERN_DEBUG "%s: conf nak: magic glitch\n", - dev->name); - get_random_bytes(&newmagic, sizeof(newmagic)); - sp->lcp.magic += newmagic; - } else - sp->lcp.magic = rmagic; - } - if (sp->lcp.state != LCP_STATE_ACK_SENT) { - /* Go to closed state. */ - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - } - /* The link will be renegotiated after timeout, - * to avoid endless req-nack loop. */ - sppp_clear_timeout (sp); - sppp_set_timeout (sp, 2); - break; - case LCP_CONF_REJ: - if (h->ident != sp->lcp.confid) - break; - sppp_clear_timeout (sp); - /* Initiate renegotiation. */ - sppp_lcp_open (sp); - if (sp->lcp.state != LCP_STATE_ACK_SENT) { - /* Go to closed state. */ - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - } - break; - case LCP_TERM_REQ: - sppp_clear_timeout (sp); - /* Send Terminate-Ack packet. */ - sppp_cp_send (sp, PPP_LCP, LCP_TERM_ACK, h->ident, 0, NULL); - /* Go to closed state. */ - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - /* Initiate renegotiation. */ - sppp_lcp_open (sp); - break; - case LCP_TERM_ACK: - case LCP_CODE_REJ: - case LCP_PROTO_REJ: - /* Ignore for now. */ - break; - case LCP_DISC_REQ: - /* Discard the packet. */ - break; - case LCP_ECHO_REQ: - if (sp->lcp.state != LCP_STATE_OPENED) - break; - if (len < 8) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: invalid lcp echo request packet length: %d bytes\n", - dev->name, len); - break; - } - if (ntohl (*(long*)(h+1)) == sp->lcp.magic) { - /* Line loopback mode detected. */ - printk (KERN_WARNING "%s: loopback\n", dev->name); - if_down (dev); - - /* Shut down the PPP link. */ - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - sppp_clear_timeout (sp); - /* Initiate negotiation. */ - sppp_lcp_open (sp); - break; - } - *(long*)(h+1) = htonl (sp->lcp.magic); - sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REPLY, h->ident, len-4, h+1); - break; - case LCP_ECHO_REPLY: - if (h->ident != sp->lcp.echoid) - break; - if (len < 8) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: invalid lcp echo reply packet length: %d bytes\n", - dev->name, len); - break; - } - if (ntohl (*(long*)(h+1)) != sp->lcp.magic) - sp->pp_alivecnt = 0; - break; - } -} - -/* - * Handle incoming Cisco keepalive protocol packets. - */ - -static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) -{ - struct cisco_packet *h; - struct net_device *dev = sp->pp_if; - - if (!pskb_may_pull(skb, sizeof(struct cisco_packet)) - || (skb->len != CISCO_PACKET_LEN - && skb->len != CISCO_BIG_PACKET_LEN)) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: invalid cisco packet length: %d bytes\n", - dev->name, skb->len); - return; - } - h = (struct cisco_packet *)skb->data; - skb_pull(skb, sizeof(struct cisco_packet*)); - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: cisco input: %d bytes <%xh %xh %xh %xh %xh-%xh>\n", - dev->name, skb->len, - ntohl (h->type), h->par1, h->par2, h->rel, - h->time0, h->time1); - switch (ntohl (h->type)) { - default: - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: unknown cisco packet type: 0x%x\n", - dev->name, ntohl (h->type)); - break; - case CISCO_ADDR_REPLY: - /* Reply on address request, ignore */ - break; - case CISCO_KEEPALIVE_REQ: - sp->pp_alivecnt = 0; - sp->pp_rseq = ntohl (h->par1); - if (sp->pp_seq == sp->pp_rseq) { - /* Local and remote sequence numbers are equal. - * Probably, the line is in loopback mode. */ - int newseq; - if (sp->pp_loopcnt >= MAXALIVECNT) { - printk (KERN_WARNING "%s: loopback\n", - dev->name); - sp->pp_loopcnt = 0; - if (dev->flags & IFF_UP) { - if_down (dev); - } - } - ++sp->pp_loopcnt; - - /* Generate new local sequence number */ - get_random_bytes(&newseq, sizeof(newseq)); - sp->pp_seq ^= newseq; - break; - } - sp->pp_loopcnt = 0; - if (sp->pp_link_state==SPPP_LINK_DOWN && - (dev->flags & IFF_UP)) { - sp->pp_link_state=SPPP_LINK_UP; - printk (KERN_INFO "%s: protocol up\n", dev->name); - } - break; - case CISCO_ADDR_REQ: - /* Stolen from net/ipv4/devinet.c -- SIOCGIFADDR ioctl */ - { - struct in_device *in_dev; - struct in_ifaddr *ifa; - u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */ -#ifdef CONFIG_INET - rcu_read_lock(); - if ((in_dev = __in_dev_get_rcu(dev)) != NULL) - { - for (ifa=in_dev->ifa_list; ifa != NULL; - ifa=ifa->ifa_next) { - if (strcmp(dev->name, ifa->ifa_label) == 0) - { - addr = ifa->ifa_local; - mask = ifa->ifa_mask; - break; - } - } - } - rcu_read_unlock(); -#endif - /* I hope both addr and mask are in the net order */ - sppp_cisco_send (sp, CISCO_ADDR_REPLY, addr, mask); - break; - } - } -} - - -/* - * Send PPP LCP packet. - */ - -static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type, - u8 ident, u16 len, void *data) -{ - struct ppp_header *h; - struct lcp_header *lh; - struct sk_buff *skb; - struct net_device *dev = sp->pp_if; - - skb=alloc_skb(dev->hard_header_len+PPP_HEADER_LEN+LCP_HEADER_LEN+len, - GFP_ATOMIC); - if (skb==NULL) - return; - - skb_reserve(skb,dev->hard_header_len); - - h = (struct ppp_header *)skb_put(skb, sizeof(struct ppp_header)); - h->address = PPP_ALLSTATIONS; /* broadcast address */ - h->control = PPP_UI; /* Unnumbered Info */ - h->protocol = htons (proto); /* Link Control Protocol */ - - lh = (struct lcp_header *)skb_put(skb, sizeof(struct lcp_header)); - lh->type = type; - lh->ident = ident; - lh->len = htons (LCP_HEADER_LEN + len); - - if (len) - memcpy(skb_put(skb,len),data, len); - - if (sp->pp_flags & PP_DEBUG) { - printk (KERN_WARNING "%s: %s output <%s id=%xh len=%xh", - dev->name, - proto==PPP_LCP ? "lcp" : "ipcp", - proto==PPP_LCP ? sppp_lcp_type_name (lh->type) : - sppp_ipcp_type_name (lh->type), lh->ident, - ntohs (lh->len)); - if (len) - sppp_print_bytes ((u8*) (lh+1), len); - printk (">\n"); - } - sp->obytes += skb->len; - /* Control is high priority so it doesn't get queued behind data */ - skb->priority=TC_PRIO_CONTROL; - skb->dev = dev; - skb_queue_tail(&tx_queue, skb); -} - -/* - * Send Cisco keepalive packet. - */ - -static void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2) -{ - struct ppp_header *h; - struct cisco_packet *ch; - struct sk_buff *skb; - struct net_device *dev = sp->pp_if; - u32 t = jiffies * 1000/HZ; - - skb=alloc_skb(dev->hard_header_len+PPP_HEADER_LEN+CISCO_PACKET_LEN, - GFP_ATOMIC); - - if(skb==NULL) - return; - - skb_reserve(skb, dev->hard_header_len); - h = (struct ppp_header *)skb_put (skb, sizeof(struct ppp_header)); - h->address = CISCO_MULTICAST; - h->control = 0; - h->protocol = htons (CISCO_KEEPALIVE); - - ch = (struct cisco_packet*)skb_put(skb, CISCO_PACKET_LEN); - ch->type = htonl (type); - ch->par1 = htonl (par1); - ch->par2 = htonl (par2); - ch->rel = -1; - ch->time0 = htons ((u16) (t >> 16)); - ch->time1 = htons ((u16) t); - - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: cisco output: <%xh %xh %xh %xh %xh-%xh>\n", - dev->name, ntohl (ch->type), ch->par1, - ch->par2, ch->rel, ch->time0, ch->time1); - sp->obytes += skb->len; - skb->priority=TC_PRIO_CONTROL; - skb->dev = dev; - skb_queue_tail(&tx_queue, skb); -} - -/** - * sppp_close - close down a synchronous PPP or Cisco HDLC link - * @dev: The network device to drop the link of - * - * This drops the logical interface to the channel. It is not - * done politely as we assume we will also be dropping DTR. Any - * timeouts are killed. - */ - -int sppp_close (struct net_device *dev) -{ - struct sppp *sp = (struct sppp *)sppp_of(dev); - unsigned long flags; - - spin_lock_irqsave(&sp->lock, flags); - sp->pp_link_state = SPPP_LINK_DOWN; - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - sppp_clear_timeout (sp); - spin_unlock_irqrestore(&sp->lock, flags); - - return 0; -} - -EXPORT_SYMBOL(sppp_close); - -/** - * sppp_open - open a synchronous PPP or Cisco HDLC link - * @dev: Network device to activate - * - * Close down any existing synchronous session and commence - * from scratch. In the PPP case this means negotiating LCP/IPCP - * and friends, while for Cisco HDLC we simply need to start sending - * keepalives - */ - -int sppp_open (struct net_device *dev) -{ - struct sppp *sp = (struct sppp *)sppp_of(dev); - unsigned long flags; - - sppp_close(dev); - - spin_lock_irqsave(&sp->lock, flags); - if (!(sp->pp_flags & PP_CISCO)) { - sppp_lcp_open (sp); - } - sp->pp_link_state = SPPP_LINK_DOWN; - spin_unlock_irqrestore(&sp->lock, flags); - sppp_flush_xmit(); - - return 0; -} - -EXPORT_SYMBOL(sppp_open); - -/** - * sppp_reopen - notify of physical link loss - * @dev: Device that lost the link - * - * This function informs the synchronous protocol code that - * the underlying link died (for example a carrier drop on X.21) - * - * We increment the magic numbers to ensure that if the other end - * failed to notice we will correctly start a new session. It happens - * do to the nature of telco circuits is that you can lose carrier on - * one endonly. - * - * Having done this we go back to negotiating. This function may - * be called from an interrupt context. - */ - -int sppp_reopen (struct net_device *dev) -{ - struct sppp *sp = (struct sppp *)sppp_of(dev); - unsigned long flags; - - sppp_close(dev); - - spin_lock_irqsave(&sp->lock, flags); - if (!(sp->pp_flags & PP_CISCO)) - { - sp->lcp.magic = jiffies; - ++sp->pp_seq; - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - /* Give it a moment for the line to settle then go */ - sppp_set_timeout (sp, 1); - } - sp->pp_link_state=SPPP_LINK_DOWN; - spin_unlock_irqrestore(&sp->lock, flags); - - return 0; -} - -EXPORT_SYMBOL(sppp_reopen); - -/** - * sppp_change_mtu - Change the link MTU - * @dev: Device to change MTU on - * @new_mtu: New MTU - * - * Change the MTU on the link. This can only be called with - * the link down. It returns an error if the link is up or - * the mtu is out of range. - */ - -static int sppp_change_mtu(struct net_device *dev, int new_mtu) -{ - if(new_mtu<128||new_mtu>PPP_MTU||(dev->flags&IFF_UP)) - return -EINVAL; - dev->mtu=new_mtu; - return 0; -} - -/** - * sppp_do_ioctl - Ioctl handler for ppp/hdlc - * @dev: Device subject to ioctl - * @ifr: Interface request block from the user - * @cmd: Command that is being issued - * - * This function handles the ioctls that may be issued by the user - * to control the settings of a PPP/HDLC link. It does both busy - * and security checks. This function is intended to be wrapped by - * callers who wish to add additional ioctl calls of their own. - */ - -int sppp_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct sppp *sp = (struct sppp *)sppp_of(dev); - - if(dev->flags&IFF_UP) - return -EBUSY; - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - - switch(cmd) - { - case SPPPIOCCISCO: - sp->pp_flags|=PP_CISCO; - dev->type = ARPHRD_HDLC; - break; - case SPPPIOCPPP: - sp->pp_flags&=~PP_CISCO; - dev->type = ARPHRD_PPP; - break; - case SPPPIOCDEBUG: - sp->pp_flags&=~PP_DEBUG; - if(ifr->ifr_flags) - sp->pp_flags|=PP_DEBUG; - break; - case SPPPIOCGFLAGS: - if(copy_to_user(ifr->ifr_data, &sp->pp_flags, sizeof(sp->pp_flags))) - return -EFAULT; - break; - case SPPPIOCSFLAGS: - if(copy_from_user(&sp->pp_flags, ifr->ifr_data, sizeof(sp->pp_flags))) - return -EFAULT; - break; - default: - return -EINVAL; - } - return 0; -} - -EXPORT_SYMBOL(sppp_do_ioctl); - -/** - * sppp_attach - attach synchronous PPP/HDLC to a device - * @pd: PPP device to initialise - * - * This initialises the PPP/HDLC support on an interface. At the - * time of calling the dev element must point to the network device - * that this interface is attached to. The interface should not yet - * be registered. - */ - -void sppp_attach(struct ppp_device *pd) -{ - struct net_device *dev = pd->dev; - struct sppp *sp = &pd->sppp; - unsigned long flags; - - /* Make sure embedding is safe for sppp_of */ - BUG_ON(sppp_of(dev) != sp); - - spin_lock_irqsave(&spppq_lock, flags); - /* Initialize keepalive handler. */ - if (! spppq) - { - init_timer(&sppp_keepalive_timer); - sppp_keepalive_timer.expires=jiffies+10*HZ; - sppp_keepalive_timer.function=sppp_keepalive; - add_timer(&sppp_keepalive_timer); - } - /* Insert new entry into the keepalive list. */ - sp->pp_next = spppq; - spppq = sp; - spin_unlock_irqrestore(&spppq_lock, flags); - - sp->pp_loopcnt = 0; - sp->pp_alivecnt = 0; - sp->pp_seq = 0; - sp->pp_rseq = 0; - sp->pp_flags = PP_KEEPALIVE|PP_CISCO|debug;/*PP_DEBUG;*/ - sp->lcp.magic = 0; - sp->lcp.state = LCP_STATE_CLOSED; - sp->ipcp.state = IPCP_STATE_CLOSED; - sp->pp_if = dev; - spin_lock_init(&sp->lock); - - /* - * Device specific setup. All but interrupt handler and - * hard_start_xmit. - */ - - dev->hard_header = sppp_hard_header; - dev->rebuild_header = sppp_rebuild_header; - dev->tx_queue_len = 10; - dev->type = ARPHRD_HDLC; - dev->addr_len = 0; - dev->hard_header_len = sizeof(struct ppp_header); - dev->mtu = PPP_MTU; - /* - * These 4 are callers but MUST also call sppp_ functions - */ - dev->do_ioctl = sppp_do_ioctl; -#if 0 - dev->get_stats = NULL; /* Let the driver override these */ - dev->open = sppp_open; - dev->stop = sppp_close; -#endif - dev->change_mtu = sppp_change_mtu; - dev->hard_header_cache = NULL; - dev->header_cache_update = NULL; - dev->flags = IFF_MULTICAST|IFF_POINTOPOINT|IFF_NOARP; -} - -EXPORT_SYMBOL(sppp_attach); - -/** - * sppp_detach - release PPP resources from a device - * @dev: Network device to release - * - * Stop and free up any PPP/HDLC resources used by this - * interface. This must be called before the device is - * freed. - */ - -void sppp_detach (struct net_device *dev) -{ - struct sppp **q, *p, *sp = (struct sppp *)sppp_of(dev); - unsigned long flags; - - spin_lock_irqsave(&spppq_lock, flags); - /* Remove the entry from the keepalive list. */ - for (q = &spppq; (p = *q); q = &p->pp_next) - if (p == sp) { - *q = p->pp_next; - break; - } - - /* Stop keepalive handler. */ - if (! spppq) - del_timer(&sppp_keepalive_timer); - sppp_clear_timeout (sp); - spin_unlock_irqrestore(&spppq_lock, flags); -} - -EXPORT_SYMBOL(sppp_detach); - -/* - * Analyze the LCP Configure-Request options list - * for the presence of unknown options. - * If the request contains unknown options, build and - * send Configure-reject packet, containing only unknown options. - */ -static int -sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h, - int len, u32 *magic) -{ - u8 *buf, *r, *p; - int rlen; - - len -= 4; - buf = r = kmalloc (len, GFP_ATOMIC); - if (! buf) - return (0); - - p = (void*) (h+1); - for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { - switch (*p) { - case LCP_OPT_MAGIC: - /* Magic number -- extract. */ - if (len >= 6 && p[1] == 6) { - *magic = (u32)p[2] << 24 | - (u32)p[3] << 16 | p[4] << 8 | p[5]; - continue; - } - break; - case LCP_OPT_ASYNC_MAP: - /* Async control character map -- check to be zero. */ - if (len >= 6 && p[1] == 6 && ! p[2] && ! p[3] && - ! p[4] && ! p[5]) - continue; - break; - case LCP_OPT_MRU: - /* Maximum receive unit -- always OK. */ - continue; - default: - /* Others not supported. */ - break; - } - /* Add the option to rejected list. */ - memcpy(r, p, p[1]); - r += p[1]; - rlen += p[1]; - } - if (rlen) - sppp_cp_send (sp, PPP_LCP, LCP_CONF_REJ, h->ident, rlen, buf); - kfree(buf); - return (rlen == 0); -} - -static void sppp_ipcp_input (struct sppp *sp, struct sk_buff *skb) -{ - struct lcp_header *h; - struct net_device *dev = sp->pp_if; - int len = skb->len; - - if (!pskb_may_pull(skb, sizeof(struct lcp_header))) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: invalid ipcp packet length: %d bytes\n", - dev->name, len); - return; - } - h = (struct lcp_header *)skb->data; - skb_pull(skb,sizeof(struct lcp_header)); - if (sp->pp_flags & PP_DEBUG) { - printk (KERN_WARNING "%s: ipcp input: %d bytes <%s id=%xh len=%xh", - dev->name, len, - sppp_ipcp_type_name (h->type), h->ident, ntohs (h->len)); - if (len > 4) - sppp_print_bytes ((u8*) (h+1), len-4); - printk (">\n"); - } - if (len > ntohs (h->len)) - len = ntohs (h->len); - switch (h->type) { - default: - /* Unknown packet type -- send Code-Reject packet. */ - sppp_cp_send (sp, PPP_IPCP, IPCP_CODE_REJ, ++sp->pp_seq, len, h); - break; - case IPCP_CONF_REQ: - if (len < 4) { - if (sp->pp_flags & PP_DEBUG) - printk (KERN_WARNING "%s: invalid ipcp configure request packet length: %d bytes\n", - dev->name, len); - return; - } - if (len > 4) { - sppp_cp_send (sp, PPP_IPCP, LCP_CONF_REJ, h->ident, - len-4, h+1); - - switch (sp->ipcp.state) { - case IPCP_STATE_OPENED: - /* Initiate renegotiation. */ - sppp_ipcp_open (sp); - /* fall through... */ - case IPCP_STATE_ACK_SENT: - /* Go to closed state. */ - sp->ipcp.state = IPCP_STATE_CLOSED; - } - } else { - /* Send Configure-Ack packet. */ - sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_ACK, h->ident, - 0, NULL); - /* Change the state. */ - if (sp->ipcp.state == IPCP_STATE_ACK_RCVD) - sp->ipcp.state = IPCP_STATE_OPENED; - else - sp->ipcp.state = IPCP_STATE_ACK_SENT; - } - break; - case IPCP_CONF_ACK: - if (h->ident != sp->ipcp.confid) - break; - sppp_clear_timeout (sp); - switch (sp->ipcp.state) { - case IPCP_STATE_CLOSED: - sp->ipcp.state = IPCP_STATE_ACK_RCVD; - sppp_set_timeout (sp, 5); - break; - case IPCP_STATE_ACK_SENT: - sp->ipcp.state = IPCP_STATE_OPENED; - break; - } - break; - case IPCP_CONF_NAK: - case IPCP_CONF_REJ: - if (h->ident != sp->ipcp.confid) - break; - sppp_clear_timeout (sp); - /* Initiate renegotiation. */ - sppp_ipcp_open (sp); - if (sp->ipcp.state != IPCP_STATE_ACK_SENT) - /* Go to closed state. */ - sp->ipcp.state = IPCP_STATE_CLOSED; - break; - case IPCP_TERM_REQ: - /* Send Terminate-Ack packet. */ - sppp_cp_send (sp, PPP_IPCP, IPCP_TERM_ACK, h->ident, 0, NULL); - /* Go to closed state. */ - sp->ipcp.state = IPCP_STATE_CLOSED; - /* Initiate renegotiation. */ - sppp_ipcp_open (sp); - break; - case IPCP_TERM_ACK: - /* Ignore for now. */ - case IPCP_CODE_REJ: - /* Ignore for now. */ - break; - } -} - -static void sppp_lcp_open (struct sppp *sp) -{ - char opt[6]; - - if (! sp->lcp.magic) - sp->lcp.magic = jiffies; - opt[0] = LCP_OPT_MAGIC; - opt[1] = sizeof (opt); - opt[2] = sp->lcp.magic >> 24; - opt[3] = sp->lcp.magic >> 16; - opt[4] = sp->lcp.magic >> 8; - opt[5] = sp->lcp.magic; - sp->lcp.confid = ++sp->pp_seq; - sppp_cp_send (sp, PPP_LCP, LCP_CONF_REQ, sp->lcp.confid, - sizeof (opt), &opt); - sppp_set_timeout (sp, 2); -} - -static void sppp_ipcp_open (struct sppp *sp) -{ - sp->ipcp.confid = ++sp->pp_seq; - sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_REQ, sp->ipcp.confid, 0, NULL); - sppp_set_timeout (sp, 2); -} - -/* - * Process PPP control protocol timeouts. - */ - -static void sppp_cp_timeout (unsigned long arg) -{ - struct sppp *sp = (struct sppp*) arg; - unsigned long flags; - - spin_lock_irqsave(&sp->lock, flags); - - sp->pp_flags &= ~PP_TIMO; - if (! (sp->pp_if->flags & IFF_UP) || (sp->pp_flags & PP_CISCO)) { - spin_unlock_irqrestore(&sp->lock, flags); - return; - } - switch (sp->lcp.state) { - case LCP_STATE_CLOSED: - /* No ACK for Configure-Request, retry. */ - sppp_lcp_open (sp); - break; - case LCP_STATE_ACK_RCVD: - /* ACK got, but no Configure-Request for peer, retry. */ - sppp_lcp_open (sp); - sp->lcp.state = LCP_STATE_CLOSED; - break; - case LCP_STATE_ACK_SENT: - /* ACK sent but no ACK for Configure-Request, retry. */ - sppp_lcp_open (sp); - break; - case LCP_STATE_OPENED: - /* LCP is already OK, try IPCP. */ - switch (sp->ipcp.state) { - case IPCP_STATE_CLOSED: - /* No ACK for Configure-Request, retry. */ - sppp_ipcp_open (sp); - break; - case IPCP_STATE_ACK_RCVD: - /* ACK got, but no Configure-Request for peer, retry. */ - sppp_ipcp_open (sp); - sp->ipcp.state = IPCP_STATE_CLOSED; - break; - case IPCP_STATE_ACK_SENT: - /* ACK sent but no ACK for Configure-Request, retry. */ - sppp_ipcp_open (sp); - break; - case IPCP_STATE_OPENED: - /* IPCP is OK. */ - break; - } - break; - } - spin_unlock_irqrestore(&sp->lock, flags); - sppp_flush_xmit(); -} - -static char *sppp_lcp_type_name (u8 type) -{ - static char buf [8]; - switch (type) { - case LCP_CONF_REQ: return ("conf-req"); - case LCP_CONF_ACK: return ("conf-ack"); - case LCP_CONF_NAK: return ("conf-nack"); - case LCP_CONF_REJ: return ("conf-rej"); - case LCP_TERM_REQ: return ("term-req"); - case LCP_TERM_ACK: return ("term-ack"); - case LCP_CODE_REJ: return ("code-rej"); - case LCP_PROTO_REJ: return ("proto-rej"); - case LCP_ECHO_REQ: return ("echo-req"); - case LCP_ECHO_REPLY: return ("echo-reply"); - case LCP_DISC_REQ: return ("discard-req"); - } - sprintf (buf, "%xh", type); - return (buf); -} - -static char *sppp_ipcp_type_name (u8 type) -{ - static char buf [8]; - switch (type) { - case IPCP_CONF_REQ: return ("conf-req"); - case IPCP_CONF_ACK: return ("conf-ack"); - case IPCP_CONF_NAK: return ("conf-nack"); - case IPCP_CONF_REJ: return ("conf-rej"); - case IPCP_TERM_REQ: return ("term-req"); - case IPCP_TERM_ACK: return ("term-ack"); - case IPCP_CODE_REJ: return ("code-rej"); - } - sprintf (buf, "%xh", type); - return (buf); -} - -static void sppp_print_bytes (u_char *p, u16 len) -{ - printk (" %x", *p++); - while (--len > 0) - printk ("-%x", *p++); -} - -/** - * sppp_rcv - receive and process a WAN PPP frame - * @skb: The buffer to process - * @dev: The device it arrived on - * @p: Unused - * @orig_dev: Unused - * - * Protocol glue. This drives the deferred processing mode the poorer - * cards use. This can be called directly by cards that do not have - * timing constraints but is normally called from the network layer - * after interrupt servicing to process frames queued via netif_rx. - */ - -static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev) -{ - if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) - return NET_RX_DROP; - sppp_input(dev,skb); - return 0; -} - -static struct packet_type sppp_packet_type = { - .type = __constant_htons(ETH_P_WAN_PPP), - .func = sppp_rcv, -}; - -static char banner[] __initdata = - KERN_INFO "Cronyx Ltd, Synchronous PPP and CISCO HDLC (c) 1994\n" - KERN_INFO "Linux port (c) 1998 Building Number Three Ltd & " - "Jan \"Yenya\" Kasprzak.\n"; - -static int __init sync_ppp_init(void) -{ - if(debug) - debug=PP_DEBUG; - printk(banner); - skb_queue_head_init(&tx_queue); - dev_add_pack(&sppp_packet_type); - return 0; -} - - -static void __exit sync_ppp_cleanup(void) -{ - dev_remove_pack(&sppp_packet_type); -} - -module_init(sync_ppp_init); -module_exit(sync_ppp_cleanup); -module_param(debug, int, 0); -MODULE_LICENSE("GPL"); - diff --git a/digits.h b/digits.h deleted file mode 100644 index eba09dd..0000000 --- a/digits.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Zapata Telephony - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Use DTMF/MFv1 tables - */ - -#ifndef _DIGITS_H -#define _DIGITS_H - -#define DEFAULT_DTMF_LENGTH 100 * ZT_CHUNKSIZE -#define DEFAULT_MFV1_LENGTH 60 * ZT_CHUNKSIZE -#define PAUSE_LENGTH 500 * ZT_CHUNKSIZE - -/* At the end of silence, the tone stops */ -static struct zt_tone dtmf_silence = { - .tonesamples = DEFAULT_DTMF_LENGTH, -}; - -/* At the end of silence, the tone stops */ -static struct zt_tone mfv1_silence = { - .tonesamples = DEFAULT_MFV1_LENGTH, -}; - -/* A pause in the dialing */ -static struct zt_tone tone_pause = { - .tonesamples = PAUSE_LENGTH, -}; - -#endif diff --git a/ecdis.h b/ecdis.h deleted file mode 100644 index 4d3801b..0000000 --- a/ecdis.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * SpanDSP - a series of DSP components for telephony - * - * ec_disable_detector.h - A detector which should eventually meet the - * G.164/G.165 requirements for detecting the - * 2100Hz echo cancellor disable tone. - * - * Written by Steve Underwood - * - * Copyright (C) 2001 Steve Underwood - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "biquad.h" - -typedef struct -{ - biquad2_state_t notch; - int notch_level; - int channel_level; - int tone_present; - int tone_cycle_duration; - int good_cycles; - int hit; -} echo_can_disable_detector_state_t; - - -#define FALSE 0 -#define TRUE (!FALSE) - -static inline void echo_can_disable_detector_init (echo_can_disable_detector_state_t *det) -{ - /* Elliptic notch */ - /* This is actually centred at 2095Hz, but gets the balance we want, due - to the asymmetric walls of the notch */ - biquad2_init (&det->notch, - (int32_t) (-0.7600000*32768.0), - (int32_t) (-0.1183852*32768.0), - (int32_t) (-0.5104039*32768.0), - (int32_t) ( 0.1567596*32768.0), - (int32_t) ( 1.0000000*32768.0)); - - det->channel_level = 0; - det->notch_level = 0; - det->tone_present = FALSE; - det->tone_cycle_duration = 0; - det->good_cycles = 0; - det->hit = 0; -} -/*- End of function --------------------------------------------------------*/ - -static inline int echo_can_disable_detector_update (echo_can_disable_detector_state_t *det, - int16_t amp) -{ - int16_t notched; - - notched = biquad2 (&det->notch, amp); - /* Estimate the overall energy in the channel, and the energy in - the notch (i.e. overall channel energy - tone energy => noise). - Use abs instead of multiply for speed (is it really faster?). - Damp the overall energy a little more for a stable result. - Damp the notch energy a little less, so we don't damp out the - blip every time the phase reverses */ - det->channel_level += ((abs(amp) - det->channel_level) >> 5); - det->notch_level += ((abs(notched) - det->notch_level) >> 4); - if (det->channel_level > 280) - { - /* There is adequate energy in the channel. Is it mostly at 2100Hz? */ - if (det->notch_level*6 < det->channel_level) - { - /* The notch says yes, so we have the tone. */ - if (!det->tone_present) - { - /* Do we get a kick every 450+-25ms? */ - if (det->tone_cycle_duration >= 425*8 - && - det->tone_cycle_duration <= 475*8) - { - det->good_cycles++; - if (det->good_cycles > 2) - det->hit = TRUE; - } - det->tone_cycle_duration = 0; - } - det->tone_present = TRUE; - } - else - { - det->tone_present = FALSE; - } - det->tone_cycle_duration++; - } - else - { - det->tone_present = FALSE; - det->tone_cycle_duration = 0; - det->good_cycles = 0; - } - return det->hit; -} -/*- End of function --------------------------------------------------------*/ -/*- End of file ------------------------------------------------------------*/ diff --git a/fasthdlc.h b/fasthdlc.h deleted file mode 100644 index adb5597..0000000 --- a/fasthdlc.h +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Mark's Mythical Table-based raw HDLC implementation - * - * This is designed to be a very fast, but memory efficient - * implementation of standard HDLC protocol. - * - * This table based HDLC technology is PATENT PENDING, but will always be - * remain freely distributable under the terms of the GPL version 2.0. - * - * For non-GPL licensing, please contact Mark Spencer at - * the below e-mail address. - * - * Copyright (C) 2001, Linux Support Services, Inc. - * - * Written by Mark Spencer - * - * Distributed under the terms of the GNU General Public License - * Version 2.0. - * - */ - -#ifndef _FASTHDLC_H -#define _FASTHDLC_H - -struct fasthdlc_state { - int state; /* What state we are in */ - unsigned int data; /* Our current data queue */ - int bits; /* Number of bits in our data queue */ - int ones; /* Number of ones */ -}; - -#ifdef FAST_HDLC_NEED_TABLES -#define RETURN_COMPLETE_FLAG (0x1000) -#define RETURN_DISCARD_FLAG (0x2000) -#define RETURN_EMPTY_FLAG (0x4000) - -/* Unlike most HDLC implementations, we define only two states, - when we are in a valid frame, and when we are searching for - a frame header */ - -#define FRAME_SEARCH 0 -#define PROCESS_FRAME 1 - -/* - - HDLC Search State table -- Look for a frame header. The return value - of this table is as follows: - - |---8---|---7---|---6---|---5---|---4---|---3---|---2---|---1---| - | Z E R O E S | Next | Bits Consumed | - |-------|-------|-------|-------|-------|-------|-------|-------| - - The indexes for this table are the state (0 or 1) and the next 8 - bits of the stream. - - Note that this table is only used for state 0 and 1. - - The user should discard the top "bits consumed" bits of data before - the next call. "Next state" represents the actual next state for - decoding. - -*/ -static unsigned char hdlc_search[256]; - -/* - HDLC Data Table - - The indexes to this table are the number of one's we've seen so far (0-5) and - the next 10 bits of input (which is enough to guarantee us that we - will retrieve at least one byte of data (or frame or whatever). - - The format for the return value is: - - Bits 15: Status (1=Valid Data, 0=Control Frame (see bits 7-0 for type)) - Bits 14-12: Number of ones in a row, so far - Bits 11-8: The number of bits consumed (0-10) - Bits 7-0: The return data (if appropriate) - - The next state is simply bit #15 - -*/ - -#define CONTROL_COMPLETE 1 -#define CONTROL_ABORT 2 - -#define STATUS_MASK (1 << 15) -#define STATUS_VALID (1 << 15) -#define STATUS_CONTROL (0 << 15) -#define STATE_MASK (1 << 15) -#define ONES_MASK (7 << 12) -#define DATA_MASK (0xff) - -static unsigned short hdlc_frame[6][1024]; - -static unsigned int minbits[2] = { 8, 10 }; - -/* - Last, but not least, we have the encoder table. It takes - as its indices the number of ones so far and a byte of data - and returns an int composed of the following fields: - - Bots 31-22: Actual Data - Bits 21-16: Unused - Bits 15-8: Number of ones - Bits 3-0: Number of bits of output (13-4) to use - - Of course we could optimize by reducing to two tables, but I don't - really think it's worth the trouble at this point. - */ - -static unsigned int hdlc_encode[6][256]; - -static inline char hdlc_search_precalc(unsigned char c) -{ - int x, p=0; - /* Look for a flag. If this isn't a flag, - line us up for the next possible shot at - a flag */ - - /* If it's a flag, we go to state 1, and have - consumed 8 bits */ - if (c == 0x7e) - return 0x10 | 8; - - /* If it's an abort, we stay in the same state - and have consumed 8 bits */ - if (c == 0x7f) - return 0x00 | 8; - - /* If it's all 1's, we state in the same state and - have consumed 8 bits */ - if (c == 0xff) - return 0x00 | 8; - - /* If we get here, we must have at least one zero in us - but we're not the flag. So, start at the end (LSB) and - work our way to the top (MSB) looking for a zero. The - position of that 0 is most optimistic start of a real - frame header */ - x=1; - p=7; - while(p && (c & x)) { - x <<= 1; - p--; - } - return p; -} - -#ifdef DEBUG_PRECALC -static inline void hdlc_search_print(char c, char r) -{ - int x=0x80; - while(x) { - printf("%s", c & x ? "1" : "0"); - x >>= 1; - } - printf(" => State %d, Consume %d\n", (r & 0x10) >> 4, r & 0xf); -} -#endif - -#define HFP(status, ones, bits, data) \ - ((status) | ((ones) << 12) | ((bits) << 8) | (data)) - -static inline unsigned int hdlc_frame_precalc(unsigned char x, unsigned short c) -{ - /* Assume we have seen 'x' one's so far, and have read the - bottom 10 bytes of c (MSB first). Now, we HAVE to have - a byte of data or a frame or something. We are assumed - to be at the beginning of a byte of data or something */ - unsigned char ones = x; - unsigned char data=0; - int bits=0; - int consumed=0; - while(bits < 8) { - data >>=1; - consumed++; - if (ones == 5) { - /* We've seen five ones */ - if (c & 0x0200) { - /* Another one -- Some sort of signal frame */ - if ((!(c & 0x0100)) && (bits == 6)) { - /* This is a frame terminator (10) */ - return HFP(0, - 0, 8, CONTROL_COMPLETE); - } else { - /* Yuck! It's something else... - Abort this entire frame, and - start looking for a good frame */ - return HFP(0, - 0, consumed+1, CONTROL_ABORT); - } - } else { - /* It's an inserted zero, just skip it */ - ones = 0; - data <<= 1; - } - } else { - /* Add it to our bit list, LSB to - MSB */ - if (c & 0x0200) { - data |= 0x80; - ones++; - } else - ones=0; - bits++; - } - c <<= 1; - } - /* Consume the extra 0 now rather than later. */ - if (ones == 5) { - ones = 0; - consumed++; - } - return HFP(STATUS_VALID, ones, consumed, data); -} - -#ifdef DEBUG_PRECALC - -static inline void hdlc_frame_print(unsigned char x, unsigned short c, unsigned int res) -{ - int z=0x0200; - char *status[] = { - "Control", - "Valid", - }; - printf("%d one's then ", x); - while(z) { - printf("%s", c & z ? "1" : "0"); - z >>= 1; - } - printf(" => Status %s, ", res & STATUS_MASK ? "1" : "0"); - printf("Consumed: %d, ", (res & 0x0f00) >> 8); - printf("Status: %s, ", status[(res & STATUS_MASK) >> 15]); - printf("Ones: %d, ", (res & ONES_MASK) >> 12); - printf("Data: %02x\n", res & 0xff); - -} - -#endif - -static inline unsigned int hdlc_encode_precalc(int x, unsigned char y) -{ - int bits=0; - int ones=x; - unsigned short data=0; - int z; - for (z=0;z<8;z++) { - /* Zero-stuff if needed */ - if (ones == 5) { - /* Stuff a zero */ - data <<= 1; - ones=0; - bits++; - } - if (y & 0x01) { - /* There's a one */ - data <<= 1; - data |= 0x1; - ones++; - bits++; - } else { - data <<= 1; - ones = 0; - bits++; - } - y >>= 1; - } - /* Special case -- Stuff the zero at the end if appropriate */ - if (ones == 5) { - /* Stuff a zero */ - data <<= 1; - ones=0; - bits++; - } - data <<= (10-bits); - return (data << 22) | (ones << 8) | (bits); -} - -#ifdef DEBUG_PRECALC -static inline void hdlc_encode_print(int x, unsigned char y, unsigned int val) -{ - unsigned int z; - unsigned short c; - printf("%d ones, %02x (", x, y); - z = 0x80; - while(z) { - printf("%s", y & z ? "1" : "0"); - z >>= 1; - } - printf(") encoded as "); - z = 1 << 31; - for (x=0;x<(val & 0xf);x++) { - printf("%s", val & z ? "1" : "0"); - z >>= 1; - } - printf(" with %d ones now, %d bits in len\n", (val & 0xf00) >> 8, val & 0xf); - - -} -#endif - -static inline void fasthdlc_precalc(void) -{ - int x; - int y; - /* First the easy part -- the searching */ - for (x=0;x<256;x++) { - hdlc_search[x] = hdlc_search_precalc(x); -#ifdef DEBUG_PRECALC - hdlc_search_print(x, hdlc_search[x]); -#endif - } - /* Now the hard part -- the frame tables */ - for (x=0;x<6;x++) { - /* Given the # of preceeding ones, process the next - byte of input (up to 10 actual bits) */ - for (y=0;y<1024;y++) { - hdlc_frame[x][y] = hdlc_frame_precalc(x, y); -#ifdef DEBUG_PRECALC - hdlc_frame_print(x, y, hdlc_frame[x][y]); -#endif - } - } - /* Now another not-so-hard part, the encoding table */ - for (x=0;x<6;x++) { - for (y=0;y<256;y++) { - hdlc_encode[x][y] = hdlc_encode_precalc(x,y); -#ifdef DEBUG_PRECALC - hdlc_encode_print(x,y,hdlc_encode[x][y]); -#endif - } - } -} - - -static inline void fasthdlc_init(struct fasthdlc_state *h) -{ - /* Initializes all states appropriately */ - h->state = 0; - h->bits = 0; - h->data = 0; - h->ones = 0; - -} - -static inline int fasthdlc_tx_load_nocheck(struct fasthdlc_state *h, unsigned char c) -{ - unsigned int res; - res = hdlc_encode[h->ones][c]; - h->ones = (res & 0xf00) >> 8; - h->data |= (res & 0xffc00000) >> h->bits; - h->bits += (res & 0xf); - return 0; -} - -static inline int fasthdlc_tx_load(struct fasthdlc_state *h, unsigned char c) -{ - /* Gotta have at least 10 bits left */ - if (h->bits > 22) - return -1; - return fasthdlc_tx_load_nocheck(h, c); -} - -static inline int fasthdlc_tx_frame_nocheck(struct fasthdlc_state *h) -{ - h->ones = 0; - h->data |= ( 0x7e000000 >> h->bits); - h->bits += 8; - return 0; -} - -static inline int fasthdlc_tx_frame(struct fasthdlc_state *h) -{ - if (h->bits > 24) - return -1; - return fasthdlc_tx_frame_nocheck(h); -} - -static inline int fasthdlc_tx_run_nocheck(struct fasthdlc_state *h) -{ - unsigned char b; - b = h->data >> 24; - h->bits -= 8; - h->data <<= 8; - return b; -} - -static inline int fasthdlc_tx_run(struct fasthdlc_state *h) -{ - if (h->bits < 8) - return -1; - return fasthdlc_tx_run_nocheck(h); -} - -static inline int fasthdlc_rx_load_nocheck(struct fasthdlc_state *h, unsigned char b) -{ - /* Put the new byte in the data stream */ - h->data |= b << (24-h->bits); - h->bits += 8; - return 0; -} - -static inline int fasthdlc_rx_load(struct fasthdlc_state *h, unsigned char b) -{ - /* Make sure we have enough space */ - if (h->bits > 24) - return -1; - return fasthdlc_rx_load_nocheck(h, b); -} - -/* - Returns a data character if available, logical OR'd with - zero or more of RETURN_COMPLETE_FLAG, RETURN_DISCARD_FLAG, - and RETURN_EMPTY_FLAG, signifying a complete frame, a - discarded frame, or there is nothing to return. - */ - -static inline int fasthdlc_rx_run(struct fasthdlc_state *h) -{ - unsigned short next; - int retval=RETURN_EMPTY_FLAG; - while ((h->bits >= minbits[h->state]) && (retval == RETURN_EMPTY_FLAG)) { - /* Run until we can no longer be assured that we will - have enough bits to continue */ - switch(h->state) { - case FRAME_SEARCH: - /* Look for an HDLC frame, keying from - the top byte. */ - next = hdlc_search[h->data >> 24]; - h->bits -= next & 0x0f; - h->data <<= next & 0x0f; - h->state = next >> 4; - h->ones = 0; - break; - case PROCESS_FRAME: - /* Process as much as the next ten bits */ - next = hdlc_frame[h->ones][h->data >> 22]; - h->bits -= ((next & 0x0f00) >> 8); - h->data <<= ((next & 0x0f00) >> 8); - h->state = (next & STATE_MASK) >> 15; - h->ones = (next & ONES_MASK) >> 12; - switch(next & STATUS_MASK) { - case STATUS_CONTROL: - if (next & CONTROL_COMPLETE) { - /* A complete, valid frame received */ - retval = (RETURN_COMPLETE_FLAG); - /* Stay in this state */ - h->state = 1; - } else { - /* An abort (either out of sync of explicit) */ - retval = (RETURN_DISCARD_FLAG); - } - break; - case STATUS_VALID: - retval = (next & DATA_MASK); - } - } - } - return retval; -} -#endif /* FAST_HDLC_NEED_TABLES */ -#endif diff --git a/fir.h b/fir.h deleted file mode 100644 index 1722285..0000000 --- a/fir.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * SpanDSP - a series of DSP components for telephony - * - * fir.h - General telephony FIR routines - * - * Written by Steve Underwood - * - * Copyright (C) 2002 Steve Underwood - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#if !defined(_FIR_H_) -#define _FIR_H_ - -typedef struct -{ - int taps; - int curr_pos; - int16_t *coeffs; - int16_t *history; -} fir16_state_t; - -typedef struct -{ - int taps; - int curr_pos; - int32_t *coeffs; - int16_t *history; -} fir32_state_t; - -static inline void fir16_create (fir16_state_t *fir, - int16_t *coeffs, - int taps) -{ - fir->taps = taps; - fir->curr_pos = taps - 1; - fir->coeffs = coeffs; - fir->history = MALLOC (taps*sizeof (int16_t)); - if (fir->history) - memset (fir->history, '\0', taps*sizeof (int16_t)); -} -/*- End of function --------------------------------------------------------*/ - -static inline void fir16_free (fir16_state_t *fir) -{ - FREE (fir->history); -} -/*- End of function --------------------------------------------------------*/ - -static inline int16_t fir16 (fir16_state_t *fir, int16_t sample) -{ - int i; - int offset1; - int offset2; - int32_t y; - - fir->history[fir->curr_pos] = sample; - offset2 = fir->curr_pos + 1; - offset1 = fir->taps - offset2; - y = 0; - for (i = fir->taps - 1; i >= offset1; i--) - y += fir->coeffs[i]*fir->history[i - offset1]; - for ( ; i >= 0; i--) - y += fir->coeffs[i]*fir->history[i + offset2]; - if (fir->curr_pos <= 0) - fir->curr_pos = fir->taps; - fir->curr_pos--; - return y >> 15; -} -/*- End of function --------------------------------------------------------*/ - -static inline void fir32_create (fir32_state_t *fir, - int32_t *coeffs, - int taps) -{ - fir->taps = taps; - fir->curr_pos = taps - 1; - fir->coeffs = coeffs; - fir->history = MALLOC (taps*sizeof (int16_t)); - if (fir->history) - memset (fir->history, '\0', taps*sizeof (int16_t)); -} -/*- End of function --------------------------------------------------------*/ - -static inline void fir32_free (fir32_state_t *fir) -{ - FREE (fir->history); -} -/*- End of function --------------------------------------------------------*/ - -static inline int16_t fir32 (fir32_state_t *fir, int16_t sample) -{ - int i; - int offset1; - int offset2; - int32_t y; - - fir->history[fir->curr_pos] = sample; - offset2 = fir->curr_pos + 1; - offset1 = fir->taps - offset2; - y = 0; - for (i = fir->taps - 1; i >= offset1; i--) - y += fir->coeffs[i]*fir->history[i - offset1]; - for ( ; i >= 0; i--) - y += fir->coeffs[i]*fir->history[i + offset2]; - if (fir->curr_pos <= 0) - fir->curr_pos = fir->taps; - fir->curr_pos--; - return y >> 15; -} -/*- End of function --------------------------------------------------------*/ - -#endif -/*- End of file ------------------------------------------------------------*/ diff --git a/fxotune.c b/fxotune.c index ea4467e..bf8b6af 100644 --- a/fxotune.c +++ b/fxotune.c @@ -24,11 +24,11 @@ #include #ifdef STANDALONE_ZAPATA -#include "zaptel.h" +#include "kernel/zaptel.h" #else #include #endif -#include "wctdm.h" +#include "kernel/wctdm.h" #include "fxotune.h" #define TEST_DURATION 2000 diff --git a/fxotune.h b/fxotune.h index 1fc2ef9..093f03e 100644 --- a/fxotune.h +++ b/fxotune.h @@ -13,8 +13,6 @@ * (C) 2005 Digium, Inc. */ -#include "wctdm.h" - struct wctdm_echo_coefs echo_trys [] = { /* 600 ohm echo settings */ diff --git a/fxstest.c b/fxstest.c index 922a1a9..4fe7c32 100644 --- a/fxstest.c +++ b/fxstest.c @@ -5,7 +5,7 @@ #include #include #include -#include "zaptel.h" +#include "kernel/zaptel.h" #include "tonezone.h" #include "wctdm.h" diff --git a/hdlcgen.c b/hdlcgen.c index 15dc45c..417004b 100644 --- a/hdlcgen.c +++ b/hdlcgen.c @@ -1,5 +1,5 @@ #define FAST_HDLC_NEED_TABLES -#include "fasthdlc.h" +#include "kernel/fasthdlc.h" #include #include #include diff --git a/hdlcstress.c b/hdlcstress.c index b27e7dc..6aa82ed 100644 --- a/hdlcstress.c +++ b/hdlcstress.c @@ -2,7 +2,7 @@ #include #include #include -#include "zaptel.h" +#include "kernel/zaptel.h" #include #include #include @@ -11,7 +11,7 @@ #include #include "bittest.h" #define FAST_HDLC_NEED_TABLES -#include "fasthdlc.h" +#include "kernel/fasthdlc.h" /* #define BLOCK_SIZE 2048 */ #define BLOCK_SIZE 2041 diff --git a/hdlctest.c b/hdlctest.c index abebbe6..a95c9ef 100644 --- a/hdlctest.c +++ b/hdlctest.c @@ -2,7 +2,7 @@ #include #include #include -#include "zaptel.h" +#include "kernel/zaptel.h" #include #include #include @@ -11,7 +11,7 @@ #include #include "bittest.h" #define FAST_HDLC_NEED_TABLES -#include "fasthdlc.h" +#include "kernel/fasthdlc.h" #define BLOCK_SIZE 2039 diff --git a/hdlcverify.c b/hdlcverify.c index 1937876..8212b2a 100644 --- a/hdlcverify.c +++ b/hdlcverify.c @@ -1,5 +1,5 @@ #define FAST_HDLC_NEED_TABLES -#include "fasthdlc.h" +#include "kernel/fasthdlc.h" #include #include #include diff --git a/hpec/hpec.h b/hpec/hpec.h deleted file mode 100644 index 7e90f12..0000000 --- a/hpec/hpec.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Zapata Telephony Interface to Digium High-Performance Echo Canceller - * - * Copyright (C) 2006 Digium, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#if !defined(_HPEC_H) -#define _HPEC_H - -struct echo_can_state; - -void __attribute__((regparm(0))) hpec_init(int __attribute__((regparm(0))) __attribute__((format (printf, 1, 2))) (*logger)(const char *format, ...), - unsigned int debug, - unsigned int chunk_size, - void * (*memalloc)(size_t len), - void (*memfree)(void *ptr)); - -void __attribute__((regparm(0))) hpec_shutdown(void); - -int __attribute__((regparm(0))) hpec_license_challenge(struct hpec_challenge *challenge); - -int __attribute__((regparm(0))) hpec_license_check(struct hpec_license *license); - -struct echo_can_state __attribute__((regparm(0))) *hpec_channel_alloc(unsigned int len); - -void __attribute__((regparm(0))) hpec_channel_free(struct echo_can_state *channel); - -void __attribute__((regparm(0))) hpec_channel_update(struct echo_can_state *channel, short *iref, short *isig); - -#endif /* !defined(_HPEC_H) */ - diff --git a/hpec/hpec_user.h b/hpec/hpec_user.h deleted file mode 100644 index bf006eb..0000000 --- a/hpec/hpec_user.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Zapata Telephony Interface to Digium High-Performance Echo Canceller - * - * Copyright (C) 2006 Digium, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#if !defined(_HPEC_USER_H) -#define _HPEC_USER_H - -struct hpec_challenge { - __u8 challenge[16]; -}; - -struct hpec_license { - __u32 numchannels; - __u8 userinfo[256]; - __u8 response[16]; -}; - -#define ZT_EC_LICENSE_CHALLENGE _IOR(ZT_CODE, 60, struct hpec_challenge) -#define ZT_EC_LICENSE_RESPONSE _IOW(ZT_CODE, 61, struct hpec_license) - -#endif /* !defined(_HPEC_USER_H) */ - diff --git a/hpec/hpec_zaptel.h b/hpec/hpec_zaptel.h deleted file mode 100644 index 2fb5a14..0000000 --- a/hpec/hpec_zaptel.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Zapata Telephony Interface to Digium High-Performance Echo Canceller - * - * Copyright (C) 2006 Digium, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#if !defined(_HPEC_ZAPTEL_H) -#define _HPEC_ZAPTEL_H - -#define ZT_EC_ARRAY_UPDATE - -#include "hpec_user.h" -#include "hpec.h" - -static int __attribute__((regparm(0))) __attribute__((format (printf, 1, 2))) logger(const char *format, ...) -{ - int res; - va_list args; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9) - va_start(args, format); - res = vprintk(format, args); - va_end(args); -#else - char buf[256]; - - va_start(args, format); - res = vsnprintf(buf, sizeof(buf), format, args); - va_end(args); - printk(buf); -#endif - - return res; -} - -static void *memalloc(size_t len) -{ - return kmalloc(len, GFP_KERNEL); -} - -static void memfree(void *ptr) -{ - kfree(ptr); -} - -static void echo_can_init(void) -{ - printk("Zaptel Echo Canceller: Digium High-Performance Echo Canceller\n"); - hpec_init(logger, debug, ZT_CHUNKSIZE, memalloc, memfree); -} - -static void echo_can_identify(char *buf, size_t len) -{ - strncpy(buf, "HPEC", len); -} - -static void echo_can_shutdown(void) -{ - hpec_shutdown(); -} - -static inline void echo_can_free(struct echo_can_state *ec) -{ - hpec_channel_free(ec); -} - -static inline void echo_can_array_update(struct echo_can_state *ec, short *iref, short *isig) -{ - hpec_channel_update(ec, iref, isig); -} - -DECLARE_MUTEX(alloc_lock); - -static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p, - struct echo_can_state **ec) -{ - if (ecp->param_count > 0) { - printk(KERN_WARNING "HPEC does not support parameters; failing request\n"); - return -EINVAL; - } - - if (down_interruptible(&alloc_lock)) - return -ENOTTY; - - *ec = hpec_channel_alloc(ecp->tap_length); - - up(&alloc_lock); - - return *ec ? 0 : -ENOTTY; -} - -static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) -{ - return 1; -} - -DECLARE_MUTEX(license_lock); - -static int hpec_license_ioctl(unsigned int cmd, unsigned long data) -{ - struct hpec_challenge challenge; - struct hpec_license license; - int result = 0; - - switch (cmd) { - case ZT_EC_LICENSE_CHALLENGE: - if (down_interruptible(&license_lock)) - return -EINTR; - memset(&challenge, 0, sizeof(challenge)); - if (hpec_license_challenge(&challenge)) - result = -ENODEV; - if (!result && copy_to_user((unsigned char *) data, &challenge, sizeof(challenge))) - result = -EFAULT; - up(&license_lock); - return result; - case ZT_EC_LICENSE_RESPONSE: - if (down_interruptible(&license_lock)) - return -EINTR; - if (copy_from_user(&license, (unsigned char *) data, sizeof(license))) - result = -EFAULT; - if (!result && hpec_license_check(&license)) - result = -EACCES; - up(&license_lock); - return result; - default: - return -ENOSYS; - } -} - -#endif /* !defined(_HPEC_ZAPTEL_H) */ diff --git a/jpah.h b/jpah.h deleted file mode 100644 index f72c5fa..0000000 --- a/jpah.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * ECHO_CAN_JP1 - * - * by Jason Parker - * - * Based upon mg2ec.h - sort of. - * This "echo can" will completely hose your audio. - * Don't use it unless you're absolutely sure you know what you're doing. - * - * Copyright (C) 2007, Digium, Inc. - * - * This program is free software and may be used and - * distributed according to the terms of the GNU - * General Public License, incorporated herein by - * reference. - * - */ - -#ifndef _JP_ECHO_H -#define _JP_ECHO_H - -#ifdef __KERNEL__ -#include -#include -#define MALLOC(a) kmalloc((a), GFP_KERNEL) -#define FREE(a) kfree(a) -#else -#include -#include -#include -#include -#define MALLOC(a) malloc(a) -#define FREE(a) free(a) -#endif - -/* Echo canceller definition */ -struct echo_can_state { - /* an arbitrary ID for this echo can - this really should be settable from the calling channel... */ - int id; - - /* absolute time - aka. sample number index - essentially the number of samples since this can was init'ed */ - int i_d; -}; - -static void echo_can_init(void) -{ - printk("Zaptel Audio Hoser: JP1\n"); -} - -static void echo_can_identify(char *buf, size_t len) -{ - strncpy(buf, "JP1", len); -} - -static void echo_can_shutdown(void) -{ -} - -static inline void init_cc(struct echo_can_state *ec) -{ - void *ptr = ec; - unsigned long tmp; - /* Double-word align past end of state */ - ptr += sizeof(struct echo_can_state); - tmp = (unsigned long)ptr; - tmp += 3; - tmp &= ~3L; - ptr = (void *)tmp; -} - -static inline void echo_can_free(struct echo_can_state *ec) -{ - FREE(ec); -} - -static inline short echo_can_update(struct echo_can_state *ec, short iref, short isig) -{ - static int blah = 0; - - if (blah < 2) { - blah++; - return 0; - } else { - blah = (blah + 1) % 3; - return isig; - } -} - -static inline struct echo_can_state *echo_can_create(int len, int adaption_mode) -{ - struct echo_can_state *ec; - ec = (struct echo_can_state *)MALLOC(sizeof(struct echo_can_state) + 4); /* align */ - if (ec) { - memset(ec, 0, sizeof(struct echo_can_state) + 4); /* align */ - init_cc(ec); - } - return ec; -} - -static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) -{ - return 0; -} -#endif diff --git a/kb1ec.h b/kb1ec.h deleted file mode 100644 index 33236b7..0000000 --- a/kb1ec.h +++ /dev/null @@ -1,597 +0,0 @@ -/* - * ECHO_CAN_KB1 - * - * by Kris Boutilier - * - * Based upon mech2.h - * - * Copyright (C) 2002, Digium, Inc. - * - * This program is free software and may be used and - * distributed according to the terms of the GNU - * General Public License, incorporated herein by - * reference. - * - * Additional background on the techniques used in this code can be found in: - * - * Messerschmitt, David; Hedberg, David; Cole, Christopher; Haoui, Amine; - * Winship, Peter; "Digital Voice Echo Canceller with a TMS32020," - * in Digital Signal Processing Applications with the TMS320 Family, - * pp. 415-437, Texas Instruments, Inc., 1986. - * - * A pdf of which is available by searching on the document title at http://www.ti.com/ - * - */ - -#ifndef _MARK2_ECHO_H -#define _MARK2_ECHO_H - -#include -#include -#include - -#define MALLOC(a) kmalloc((a), GFP_KERNEL) -#define FREE(a) kfree(a) - -/* Uncomment to provide summary statistics for overall echo can performance every 4000 samples */ -/* #define MEC2_STATS 4000 */ - -/* Uncomment to generate per-sample statistics - this will severely degrade system performance and audio quality */ -/* #define MEC2_STATS_DETAILED */ - -/* Get optimized routines for math */ -#include "arith.h" - -/* Bring in definitions for the various constants and thresholds */ -#include "kb1ec_const.h" - -#ifndef NULL -#define NULL 0 -#endif -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE (!FALSE) -#endif - -/* Generic circular buffer definition */ -typedef struct { - /* Pointer to the relative 'start' of the buffer */ - int idx_d; - /* The absolute size of the buffer */ - int size_d; - /* The actual sample - twice as large as we need, however we do store values at idx_d and idx_d+size_d */ - short *buf_d; -} echo_can_cb_s; - -/* Echo canceller definition */ -struct echo_can_state { - /* an arbitrary ID for this echo can - this really should be settable from the calling channel... */ - int id; - - /* absolute time - aka. sample number index - essentially the number of samples since this can was init'ed */ - int i_d; - - /* Pre-computed constants */ - /* ---------------------- */ - /* Number of filter coefficents */ - int N_d; - /* Rate of adaptation of filter */ - int beta2_i; - - /* Accumulators for power computations */ - /* ----------------------------------- */ - /* reference signal power estimate - aka. Average absolute value of y(k) */ - int Ly_i; - /* ... */ - int Lu_i; - - /* Accumulators for signal detectors */ - /* --------------------------------- */ - /* Power estimate of the recent past of the near-end hybrid signal - aka. Short-time average of: 2 x |s(i)| */ - int s_tilde_i; - /* Power estimate of the recent past of the far-end receive signal - aka. Short-time average of: |y(i)| */ - int y_tilde_i; - - /* Near end speech detection counter - stores Hangover counter time remaining, in samples */ - int HCNTR_d; - - /* Circular buffers and coefficients */ - /* --------------------------------- */ - /* ... */ - int *a_i; - /* ... */ - short *a_s; - /* Reference samples of far-end receive signal */ - echo_can_cb_s y_s; - /* Reference samples of near-end signal */ - echo_can_cb_s s_s; - /* Reference samples of near-end signal minus echo estimate */ - echo_can_cb_s u_s; - /* Reference samples of far-end receive signal used to calculate short-time average */ - echo_can_cb_s y_tilde_s; - - /* Peak far-end receive signal */ - /* --------------------------- */ - /* Highest y_tilde value in the sample buffer */ - short max_y_tilde; - /* Index of the sample containing the max_y_tilde value */ - int max_y_tilde_pos; - -#ifdef MEC2_STATS - /* Storage for performance statistics */ - int cntr_nearend_speech_frames; - int cntr_residualcorrected_frames; - int cntr_residualcorrected_framesskipped; - int cntr_coeff_updates; - int cntr_coeff_missedupdates; - - int avg_Lu_i_toolow; - int avg_Lu_i_ok; -#endif - unsigned int aggressive:1; -}; - -static void echo_can_init(void) -{ - printk("Zaptel Echo Canceller: KB1\n"); -} - -static void echo_can_identify(char *buf, size_t len) -{ - strncpy(buf, "KB1", len); -} - -static void echo_can_shutdown(void) -{ -} - -static inline void init_cb_s(echo_can_cb_s *cb, int len, void *where) -{ - cb->buf_d = (short *)where; - cb->idx_d = 0; - cb->size_d = len; -} - -static inline void add_cc_s(echo_can_cb_s *cb, short newval) -{ - /* Can't use modulus because N+M isn't a power of two (generally) */ - cb->idx_d--; - if (cb->idx_d < (int)0) - /* Whoops - the pointer to the 'start' wrapped around so reset it to the top of the buffer */ - cb->idx_d += cb->size_d; - - /* Load two copies into memory */ - cb->buf_d[cb->idx_d] = newval; - cb->buf_d[cb->idx_d + cb->size_d] = newval; -} - -static inline short get_cc_s(echo_can_cb_s *cb, int pos) -{ - /* Load two copies into memory */ - return cb->buf_d[cb->idx_d + pos]; -} - -static inline void init_cc(struct echo_can_state *ec, int N, int maxy, int maxu) -{ - - void *ptr = ec; - unsigned long tmp; - /* Double-word align past end of state */ - ptr += sizeof(struct echo_can_state); - tmp = (unsigned long)ptr; - tmp += 3; - tmp &= ~3L; - ptr = (void *)tmp; - - /* Reset parameters */ - ec->N_d = N; - ec->beta2_i = DEFAULT_BETA1_I; - - /* Allocate coefficient memory */ - ec->a_i = ptr; - ptr += (sizeof(int) * ec->N_d); - ec->a_s = ptr; - ptr += (sizeof(short) * ec->N_d); - - /* Reset Y circular buffer (short version) */ - init_cb_s(&ec->y_s, maxy, ptr); - ptr += (sizeof(short) * (maxy) * 2); - - /* Reset Sigma circular buffer (short version for FIR filter) */ - init_cb_s(&ec->s_s, (1 << DEFAULT_ALPHA_ST_I), ptr); - ptr += (sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) * 2); - - init_cb_s(&ec->u_s, maxu, ptr); - ptr += (sizeof(short) * maxu * 2); - - /* Allocate a buffer for the reference signal power computation */ - init_cb_s(&ec->y_tilde_s, ec->N_d, ptr); - - /* Reset the absolute time index */ - ec->i_d = (int)0; - - /* Reset the power computations (for y and u) */ - ec->Ly_i = DEFAULT_CUTOFF_I; - ec->Lu_i = DEFAULT_CUTOFF_I; - -#ifdef MEC2_STATS - /* set the identity */ - ec->id = (int)&ptr; - - /* Reset performance stats */ - ec->cntr_nearend_speech_frames = (int)0; - ec->cntr_residualcorrected_frames = (int)0; - ec->cntr_residualcorrected_framesskipped = (int)0; - ec->cntr_coeff_updates = (int)0; - ec->cntr_coeff_missedupdates = (int)0; - - ec->avg_Lu_i_toolow = (int)0; - ec->avg_Lu_i_ok = (int)0; -#endif - - /* Reset the near-end speech detector */ - ec->s_tilde_i = (int)0; - ec->y_tilde_i = (int)0; - ec->HCNTR_d = (int)0; - -} - -static inline void echo_can_free(struct echo_can_state *ec) -{ - FREE(ec); -} - -static inline short echo_can_update(struct echo_can_state *ec, short iref, short isig) -{ - - /* Declare local variables that are used more than once */ - /* ... */ - int k; - /* ... */ - int rs; - /* ... */ - short u; - /* ... */ - int Py_i; - /* ... */ - int two_beta_i; - - /* flow A on pg. 428 */ - /* eq. (16): high-pass filter the input to generate the next value; - * push the current value into the circular buffer - * - * sdc_im1_d = sdc_d; - * sdc_d = sig; - * s_i_d = sdc_d; - * s_d = s_i_d; - * s_i_d = (float)(1.0 - gamma_d) * s_i_d - * + (float)(0.5 * (1.0 - gamma_d)) * (sdc_d - sdc_im1_d); - */ - - /* Update the Far-end receive signal circular buffers and accumulators */ - /* ------------------------------------------------------------------- */ - /* Delete the oldest sample from the power estimate accumulator */ - ec->y_tilde_i -= abs(get_cc_s(&ec->y_s, (1 << DEFAULT_ALPHA_YT_I) - 1 )) >> DEFAULT_ALPHA_YT_I; - /* Add the new sample to the power estimate accumulator */ - ec->y_tilde_i += abs(iref) >> DEFAULT_ALPHA_ST_I; - /* Push a copy of the new sample into its circular buffer */ - add_cc_s(&ec->y_s, iref); - - - /* eq. (2): compute r in fixed-point */ - rs = CONVOLVE2(ec->a_s, - ec->y_s.buf_d + ec->y_s.idx_d, - ec->N_d); - rs >>= 15; - - /* eq. (3): compute the output value (see figure 3) and the error - * note: the error is the same as the output signal when near-end - * speech is not present - */ - u = isig - rs; - - /* Push a copy of the output value sample into its circular buffer */ - add_cc_s(&ec->u_s, u); - - - /* Update the Near-end hybrid signal circular buffers and accumulators */ - /* ------------------------------------------------------------------- */ - /* Delete the oldest sample from the power estimate accumulator */ - ec->s_tilde_i -= abs(get_cc_s(&ec->s_s, (1 << DEFAULT_ALPHA_ST_I) - 1 )); - /* Add the new sample to the power estimate accumulator */ - ec->s_tilde_i += abs(isig); - /* Push a copy of the new sample into it's circular buffer */ - add_cc_s(&ec->s_s, isig); - - - /* Push a copy of the current short-time average of the far-end receive signal into it's circular buffer */ - add_cc_s(&ec->y_tilde_s, ec->y_tilde_i); - - /* flow B on pg. 428 */ - - /* If the hangover timer isn't running then compute the new convergence factor, otherwise set Py_i to 32768 */ - if (!ec->HCNTR_d) { - Py_i = (ec->Ly_i >> DEFAULT_SIGMA_LY_I) * (ec->Ly_i >> DEFAULT_SIGMA_LY_I); - Py_i >>= 15; - } else { - Py_i = (1 << 15); - } - -#if 0 - /* Vary rate of adaptation depending on position in the file - * Do not do this for the first (DEFAULT_UPDATE_TIME) secs after speech - * has begun of the file to allow the echo cancellor to estimate the - * channel accurately - * Still needs conversion! - */ - - if (ec->start_speech_d != 0 ){ - if ( ec->i_d > (DEFAULT_T0 + ec->start_speech_d)*(SAMPLE_FREQ) ){ - ec->beta2_d = max_cc_float(MIN_BETA, DEFAULT_BETA1 * exp((-1/DEFAULT_TAU)*((ec->i_d/(float)SAMPLE_FREQ) - DEFAULT_T0 - ec->start_speech_d))); - } - } else { - ec->beta2_d = DEFAULT_BETA1; - } -#endif - - /* Fixed point, inverted */ - ec->beta2_i = DEFAULT_BETA1_I; - - /* Fixed point version, inverted */ - two_beta_i = (ec->beta2_i * Py_i) >> 15; - if (!two_beta_i) - two_beta_i++; - - /* Update the Suppressed signal power estimate accumulator */ - /* ------------------------------------------------------- */ - /* Delete the oldest sample from the power estimate accumulator */ - ec->Lu_i -= abs(get_cc_s(&ec->u_s, (1 << DEFAULT_SIGMA_LU_I) - 1 )) ; - /* Add the new sample to the power estimate accumulator */ - ec->Lu_i += abs(u); - - /* Update the Far-end reference signal power estimate accumulator */ - /* -------------------------------------------------------------- */ - /* eq. (10): update power estimate of the reference */ - /* Delete the oldest sample from the power estimate accumulator */ - ec->Ly_i -= abs(get_cc_s(&ec->y_s, (1 << DEFAULT_SIGMA_LY_I) - 1)) ; - /* Add the new sample to the power estimate accumulator */ - ec->Ly_i += abs(iref); - - if (ec->Ly_i < DEFAULT_CUTOFF_I) - ec->Ly_i = DEFAULT_CUTOFF_I; - - - /* Update the Peak far-end receive signal detected */ - /* ----------------------------------------------- */ - if (ec->y_tilde_i > ec->max_y_tilde) { - /* New highest y_tilde with full life */ - ec->max_y_tilde = ec->y_tilde_i; - ec->max_y_tilde_pos = ec->N_d - 1; - } else if (--ec->max_y_tilde_pos < 0) { - /* Time to find new max y tilde... */ - ec->max_y_tilde = MAX16(ec->y_tilde_s.buf_d + ec->y_tilde_s.idx_d, ec->N_d, &ec->max_y_tilde_pos); - } - - /* Determine if near end speech was detected in this sample */ - /* -------------------------------------------------------- */ - if (((ec->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)) > ec->max_y_tilde) - && (ec->max_y_tilde > 0)) { - /* Then start the Hangover counter */ - ec->HCNTR_d = DEFAULT_HANGT; -#ifdef MEC2_STATS_DETAILED - printk(KERN_INFO "Reset near end speech timer with: s_tilde_i %d, stmnt %d, max_y_tilde %d\n", ec->s_tilde_i, (ec->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)), ec->max_y_tilde); -#endif -#ifdef MEC2_STATS - ++ec->cntr_nearend_speech_frames; -#endif - } else if (ec->HCNTR_d > (int)0) { - /* otherwise, if it's still non-zero, decrement the Hangover counter by one sample */ -#ifdef MEC2_STATS - ++ec->cntr_nearend_speech_frames; -#endif - ec->HCNTR_d--; - } - - /* Update coefficients if no near-end speech in this sample (ie. HCNTR_d = 0) - * and we have enough signal to bother trying to update. - * -------------------------------------------------------------------------- - */ - if (!ec->HCNTR_d && /* no near-end speech present */ - !(ec->i_d % DEFAULT_M)) { /* we only update on every DEFAULM_M'th sample from the stream */ - if (ec->Lu_i > MIN_UPDATE_THRESH_I) { /* there is sufficient energy above the noise floor to contain meaningful data */ - /* so loop over all the filter coefficients */ -#ifdef MEC2_STATS_DETAILED - printk( KERN_INFO "updating coefficients with: ec->Lu_i %9d\n", ec->Lu_i); -#endif -#ifdef MEC2_STATS - ec->avg_Lu_i_ok = ec->avg_Lu_i_ok + ec->Lu_i; - ++ec->cntr_coeff_updates; -#endif - for (k=0; k < ec->N_d; k++) { - /* eq. (7): compute an expectation over M_d samples */ - int grad2; - grad2 = CONVOLVE2(ec->u_s.buf_d + ec->u_s.idx_d, - ec->y_s.buf_d + ec->y_s.idx_d + k, - DEFAULT_M); - /* eq. (7): update the coefficient */ - ec->a_i[k] += grad2 / two_beta_i; - ec->a_s[k] = ec->a_i[k] >> 16; - } - } else { -#ifdef MEC2_STATS_DETAILED - printk( KERN_INFO "insufficient signal to update coefficients ec->Lu_i %5d < %5d\n", ec->Lu_i, MIN_UPDATE_THRESH_I); -#endif -#ifdef MEC2_STATS - ec->avg_Lu_i_toolow = ec->avg_Lu_i_toolow + ec->Lu_i; - ++ec->cntr_coeff_missedupdates; -#endif - } - } - - /* paragraph below eq. (15): if no near-end speech in the sample and - * the reference signal power estimate > cutoff threshold - * then perform residual error suppression - */ -#ifdef MEC2_STATS_DETAILED - if (ec->HCNTR_d == 0) - printk( KERN_INFO "possibily correcting frame with ec->Ly_i %9d ec->Lu_i %9d and expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1))); -#endif - -#ifndef NO_ECHO_SUPPRESSOR - if (ec->aggressive) { - if ((ec->HCNTR_d < AGGRESSIVE_HCNTR) && (ec->Ly_i > (ec->Lu_i << 1))) { - for (k=0; k < 2; k++) { - u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I)) + 1); - } -#ifdef MEC2_STATS_DETAILED - printk( KERN_INFO "aggresively correcting frame with ec->Ly_i %9d ec->Lu_i %9d expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1))); -#endif -#ifdef MEC2_STATS - ++ec->cntr_residualcorrected_frames; -#endif - } - } else { - if (ec->HCNTR_d == 0) { - if ((ec->Ly_i/(ec->Lu_i + 1)) > DEFAULT_SUPPR_I) { - for (k=0; k < 1; k++) { - u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I + 2)) + 1); - } -#ifdef MEC2_STATS_DETAILED - printk( KERN_INFO "correcting frame with ec->Ly_i %9d ec->Lu_i %9d expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1))); -#endif -#ifdef MEC2_STATS - ++ec->cntr_residualcorrected_frames; -#endif - } -#ifdef MEC2_STATS - else { - ++ec->cntr_residualcorrected_framesskipped; - } -#endif - } - } -#endif - -#if 0 - /* This will generate a non-linear supression factor, once converted */ - if ((ec->HCNTR_d == 0) && - ((ec->Lu_d/ec->Ly_d) < DEFAULT_SUPPR) && - (ec->Lu_d/ec->Ly_d > EC_MIN_DB_VALUE)) { - suppr_factor = (10 / (float)(SUPPR_FLOOR - SUPPR_CEIL)) * log(ec->Lu_d/ec->Ly_d) - - SUPPR_CEIL / (float)(SUPPR_FLOOR - SUPPR_CEIL); - u_suppr = pow(10.0, (suppr_factor) * RES_SUPR_FACTOR / 10.0) * u_suppr; - } -#endif - -#ifdef MEC2_STATS - /* Periodically dump performance stats */ - if ((ec->i_d % MEC2_STATS) == 0) { - /* make sure to avoid div0's! */ - if (ec->cntr_coeff_missedupdates > 0) - ec->avg_Lu_i_toolow = (int)(ec->avg_Lu_i_toolow / ec->cntr_coeff_missedupdates); - else - ec->avg_Lu_i_toolow = -1; - - if (ec->cntr_coeff_updates > 0) - ec->avg_Lu_i_ok = (ec->avg_Lu_i_ok / ec->cntr_coeff_updates); - else - ec->avg_Lu_i_ok = -1; - - printk( KERN_INFO "%d: Near end speech: %5d Residuals corrected/skipped: %5d/%5d Coefficients updated ok/low sig: %3d/%3d Lu_i avg ok/low sig %6d/%5d\n", - ec->id, - ec->cntr_nearend_speech_frames, - ec->cntr_residualcorrected_frames, ec->cntr_residualcorrected_framesskipped, - ec->cntr_coeff_updates, ec->cntr_coeff_missedupdates, - ec->avg_Lu_i_ok, ec->avg_Lu_i_toolow); - - ec->cntr_nearend_speech_frames = 0; - ec->cntr_residualcorrected_frames = 0; - ec->cntr_residualcorrected_framesskipped = 0; - ec->cntr_coeff_updates = 0; - ec->cntr_coeff_missedupdates = 0; - ec->avg_Lu_i_ok = 0; - ec->avg_Lu_i_toolow = 0; - } -#endif - - /* Increment the sample index and return the corrected sample */ - ec->i_d++; - return u; -} - -static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p, - struct echo_can_state **ec) -{ - int maxy; - int maxu; - size_t size; - unsigned int x; - char *c; - - maxy = ecp->tap_length + DEFAULT_M; - maxu = DEFAULT_M; - if (maxy < (1 << DEFAULT_ALPHA_YT_I)) - maxy = (1 << DEFAULT_ALPHA_YT_I); - if (maxy < (1 << DEFAULT_SIGMA_LY_I)) - maxy = (1 << DEFAULT_SIGMA_LY_I); - if (maxu < (1 << DEFAULT_SIGMA_LU_I)) - maxu = (1 << DEFAULT_SIGMA_LU_I); - - size = sizeof(*ec) + - 4 + /* align */ - sizeof(int) * ecp->tap_length + /* a_i */ - sizeof(short) * ecp->tap_length + /* a_s */ - 2 * sizeof(short) * (maxy) + /* y_s */ - 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */ - 2 * sizeof(short) * (maxu) + /* u_s */ - 2 * sizeof(short) * ecp->tap_length; /* y_tilde_s */ - - if (!(*ec = MALLOC(size))) - return -ENOMEM; - - memset(*ec, 0, size); - -#ifdef AGGRESSIVE_SUPPRESSOR - (*ec)->aggressive = 1; -#endif - - for (x = 0; x < ecp->param_count; x++) { - for (c = p[x].name; *c; c++) - *c = tolower(*c); - if (!strcmp(p[x].name, "aggressive")) { - (*ec)->aggressive = p[x].value ? 1 : 0; - } else { - printk(KERN_WARNING "Unknown parameter supplied to KB1 echo canceler: '%s'\n", p[x].name); - kfree(*ec); - - return -EINVAL; - } - } - - init_cc(*ec, ecp->tap_length, maxy, maxu); - - return 0; -} - -static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) -{ - /* Set the hangover counter to the length of the can to - * avoid adjustments occuring immediately after initial forced training - */ - ec->HCNTR_d = ec->N_d << 1; - - if (pos >= ec->N_d) - return 1; - - ec->a_i[pos] = val << 17; - ec->a_s[pos] = val << 1; - - if (++pos >= ec->N_d) - return 1; - - return 0; -} - -#endif diff --git a/kb1ec_const.h b/kb1ec_const.h deleted file mode 100644 index 0849b14..0000000 --- a/kb1ec_const.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - Important constants for tuning kb1 echo can - */ -#ifndef _MEC2_CONST_H -#define _MEC2_CONST_H - - -/* Convergence (aka. adaptation) speed -- higher means slower */ -#define DEFAULT_BETA1_I 2048 - -/* Constants for various power computations */ -#define DEFAULT_SIGMA_LY_I 7 -#define DEFAULT_SIGMA_LU_I 7 -#define DEFAULT_ALPHA_ST_I 5 /* near-end speech detection sensitivity factor */ -#define DEFAULT_ALPHA_YT_I 5 - -#define DEFAULT_CUTOFF_I 128 - -/* Define the near-end speech hangover counter: if near-end speech - * is declared, hcntr is set equal to hangt (see pg. 432) - */ -#define DEFAULT_HANGT 600 /* in samples, so 600 samples = 75ms */ - -/* define the residual error suppression threshold */ -#define DEFAULT_SUPPR_I 16 /* 16 = -24db */ - -/* This is the minimum reference signal power estimate level - * that will result in filter adaptation. - * If this is too low then background noise will cause the filter - * coefficients to constantly be updated. - */ -#define MIN_UPDATE_THRESH_I 4096 - -/* The number of samples used to update coefficients using the - * the block update method (M). It should be related back to the - * length of the echo can. - * ie. it only updates coefficients when (sample number MOD default_m) = 0 - * - * Getting this wrong may cause an oops. Consider yourself warned! - */ -#define DEFAULT_M 16 /* every 16th sample */ - -/* If AGGRESSIVE supression is enabled, then we start cancelling residual - * echos again even while there is potentially the very end of a near-side - * signal present. - * This defines how many samples of DEFAULT_HANGT can remain before we - * kick back in - */ -#define AGGRESSIVE_HCNTR 160 /* in samples, so 160 samples = 20ms */ - - -/***************************************************************/ -/* The following knobs are not implemented in the current code */ - -/* we need a dynamic level of suppression varying with the ratio of the - power of the echo to the power of the reference signal this is - done so that we have a smoother background. - we have a higher suppression when the power ratio is closer to - suppr_ceil and reduces logarithmically as we approach suppr_floor. - */ -#define SUPPR_FLOOR -64 -#define SUPPR_CEIL -24 - -/* in a second departure, we calculate the residual error suppression - * as a percentage of the reference signal energy level. The threshold - * is defined in terms of dB below the reference signal. - */ -#define RES_SUPR_FACTOR -20 - - -#endif /* _MEC2_CONST_H */ - diff --git a/kernel/GNUmakefile b/kernel/GNUmakefile new file mode 100644 index 0000000..3ec8aa6 --- /dev/null +++ b/kernel/GNUmakefile @@ -0,0 +1,160 @@ +# +# Zaptel kernel 2.4 makefile +# +# Copyright (C) 2008 Digium, Inc. +# + +CFLAGS+=-DSTANDALONE_ZAPATA + +ifeq ($(MAKELEVEL),0) +PWD:=$(shell pwd) +endif + +KINCLUDES:=$(KSRC)/include + +BUILDVER:=linux24 + +HOTPLUG_FIRMWARE:=no + +ifeq ($(HOTPLUG_FIRMWARE),yes) + CFLAGS+=-DHOTPLUG_FIRMWARE +endif + +ifeq ($(ARCH),i386) +ifneq ($(wildcard $(PWD)/hpec/hpec_x86_32.o_shipped),) +HPEC_PRESENT=yes +endif +endif + +ifeq ($(ARCH),x86_64) +ifneq ($(wildcard $(PWD)/hpec/hpec_x86_64.o_shipped),) +HPEC_PRESENT=yes +endif +endif + +BUILD_MODULES:=$(BUILD_TOPDIR_MODULES) $(BUILD_SUBDIR_MODULES) +ALL_MODULES := $(BUILD_TOPDIR_MODULES:%=%.o) \ + $(join $(BUILD_SUBDIR_MODULES:%=%/), $(BUILD_SUBDIR_MODULES:%=%.o)) + +OPTFLAG=-O2 +CFLAGS+=-I. $(OPTFLAGS) -g -fPIC -Wall -DBUILDING_TONEZONE #-DTONEZONE_DRIVER +ifneq (,$(findstring ppc,$(UNAME_M))) +CFLAGS_PPC:=-fsigned-char +endif +ifneq (,$(findstring x86_64,$(UNAME_M))) +CFLAGS_x86_64:=-m64 +endif +CFLAGS+=$(CFLAGS_PPC) $(CFLAGS_x86_64) +KFLAGS=-I$(KINCLUDES) -O6 +KFLAGS+=-DMODULE -D__KERNEL__ -DEXPORT_SYMTAB -I$(KSRC)/drivers/net \ + -Wall -I. -Wstrict-prototypes -fomit-frame-pointer -I$(KSRC)/drivers/net/wan -I$(KINCLUDES)/net +ifneq (,$(wildcard $(KINCLUDES)/linux/modversions.h)) + KFLAGS+=-DMODVERSIONS -include $(KINCLUDES)/linux/modversions.h +endif +ifneq (,$(findstring ppc,$(UNAME_M))) +KFLAGS_PPC:=-msoft-float -fsigned-char +endif +KFLAGS+=$(KFLAGS_PPC) + ifneq (,$(findstring x86_64,$(UNAME_M))) + KFLAGS+=-mcmodel=kernel + endif + +# +# Features are now configured in zconfig.h +# + +MODULE_ALIASES=wcfxs wctdm8xxp wct2xxp + +KFLAGS+=-DSTANDALONE_ZAPATA + +MOD_DIR:=$(DESTDIR)/lib/modules/$(KVERS)/misc + +all: modules + +ifeq ($(HPEC_PRESENT),yes) +ifeq ($(ARCH),i386) +ZAPTEL_HPEC:=hpec/hpec_x86_32.o_shipped +endif + +ifeq ($(ARCH),x86_64) +ZAPTEL_HPEC:=hpec/hpec_x86_64.o_shipped +endif + +KFLAGS+=-DECHO_CAN_HPEC -I$(PWD)/hpec +zaptel-base.o: hpec/hpec_zaptel.h hpec/hpec_user.h +endif + +prereq: tor2fw.h radfw.h version.h + +tor2fw.h: tormenta2.rbt makefw + ./makefw $< tor2fw > $@ + +radfw.h: pciradio.rbt makefw + ./makefw $< radfw > $@ + +makefw: makefw.c + $(HOSTCC) -o $@ $^ + + +modules: $(ALL_MODULES) + +wct4xxp/wct4xxp.o: + $(MAKE) -C wct4xxp KFLAGS="$(KFLAGS) -I.." CFLAGS="$(CFLAGS) -I.." + +tor2.o: tor2-hw.h tor2fw.h + +zaptel-base.o: digits.h arith.h sec.h sec-2.h kb1ec.h mg2ec.h zconfig.h + +wcusb.o: wcusb.h + +wctdm.o: wctdm.h + +wctdm24xxp/wctdm24xxp.o: + $(MAKE) -C wctdm24xxp KFLAGS="$(KFLAGS) -I.." CFLAGS="$(CFLAGS) -I.." + +wcte12xp/wcte12xp.o: + $(MAKE) -C wcte12xp KFLAGS="$(KFLAGS) -I.." CFLAGS="$(CFLAGS) -I.." + +pciradio.o: radfw.h + +ztdummy.o: ztdummy.h + +zaptel.o: zaptel-base.o $(ZAPTEL_HPEC) + $(LD) -r -o $@ $< $(ZAPTEL_HPEC) + +$(filter-out zaptel.o,$(BUILD_TOPDIR_MODULES:%=%.o)) zaptel-base.o: %.o: %.c zaptel.h + $(CC) $(KFLAGS) -o $@ -c $< + +install: all devices install-modules install-programs install-firmware + @echo "###################################################" + @echo "###" + @echo "### Zaptel installed successfully." + @echo "### If you have not done so before, install init scripts with:" + @echo "###" + @echo "### make config" + @echo "###" + @echo "###################################################" + +BASENAMES=$(sort $(shell for x in $(ALL_MODULES); do basename $x; done)) +uninstall-modules: + +BASENAMES=$(sort $(shell for mod in $(ALL_MODULES); do basename $$mod; done)) + +install-modules: $(INSTALL_MODULES) uninstall-modules + $(INSTALL) -d $(DESTDIR)$(MOD_DIR) + $(INSTALL) -m 644 $(INSTALL_MODULES) $(DESTDIR)$(MOD_DIR) + [ `id -u` = 0 ] && /sbin/depmod -a $(KVERS) || : + +clean: + rm -f makefw tor2fw.h radfw.h + rm -f *.o + $(MAKE) -C wct4xxp clean + rm -rf .tmp_versions + rm -f core + +distclean: dist-clean + +dist-clean: clean + +.PHONY: menuselect distclean dist-clean clean all _all install modules config install-modules uninstall-modules + diff --git a/kernel/Kbuild b/kernel/Kbuild new file mode 100644 index 0000000..7454c90 --- /dev/null +++ b/kernel/Kbuild @@ -0,0 +1,64 @@ +ifdef ECHO_CAN_NAME + ECHO_CAN_CFLAGS := -DECHO_CAN_FROMENV -DECHO_CAN_$(ECHO_CAN_NAME) +endif + +obj-m := $(KBUILD_OBJ_M) + +EXTRA_CFLAGS := -I$(src) -DSTANDALONE_ZAPATA +EXTRA_CFLAGS += $(ECHO_CAN_CFLAGS) + +# fix typo present in CentOS and RHEL 2.6.9 kernels +BAD_KERNELS_VERS := 22 34 34.0.1 34.0.2 +BAD_KERNELS := $(foreach ver,$(BAD_KERNELS_VERS),2.6.9-$(ver).EL 2.6.9-$(ver).ELsmp) +ifneq (,$(filter $(KVERS),$(BAD_KERNELS))) +EXTRA_CFLAGS+=-Drw_lock_t=rwlock_t +endif + +zaptel-objs := zaptel-base.o + +ifeq ($(HPEC_PRESENT),yes) +ifeq ($(ARCH),i386) +zaptel-objs += hpec/hpec_x86_32.o +endif + +ifeq ($(ARCH),x86_64) +zaptel-objs += hpec/hpec_x86_64.o +endif + +EXTRA_CFLAGS += -DECHO_CAN_HPEC -I$(src)/hpec +endif + +$(obj)/pciradio.o: $(obj)/radfw.h +$(obj)/tor2.o: $(obj)/tor2fw.h + +hostprogs-y := $(obj)/makefw + +$(obj)/tor2fw.h: $(src)/tormenta2.rbt $(obj)/makefw + $(obj)/makefw $< tor2fw > $@ + +$(obj)/radfw.h: $(src)/pciradio.rbt $(obj)/makefw + $(obj)/makefw $< radfw > $@ + +$(obj)/makefw: $(src)/makefw.c + $(HOSTCC) -o $@ $^ + + +# set CONFIG_ZAPTEL_MMX for a number of CPU types. +# Right now this part is not enabled, unless you build with +# ZAPTEL_MMX_AUTO=something . +ZAPMMX_WHITELIST_i386 = M586MMX M686 MPENTIUMII MPENTIUMIII MPENTIUMM \ + MPENTIUM4 MVIAC3_2 + +ZAPMMX_WHITELIST_x86_64 = + +# A list of configuration variables to test: CONFIG_M686 , etc. +ZAPMMX_CONFIG_VARS := $(ZAPMMX_WHITELIST_$(ARCH):%=CONFIG_%) + +# expand them: +ZAPMMX_CONFIG_VALS := $(strip $(foreach var,$(ZAPMMX_CONFIG_VARS),$(var)) ) +ifneq (,$(ZAPTEL_MMX_AUTO)) + ifneq (,$(ZAPMMX_CONFIG_VALS)) + # TODO: make that + CFLAGS_zaptel-base.o += -DCONFIG_ZAPTEL_MMX + endif +endif diff --git a/kernel/Makefile b/kernel/Makefile new file mode 100644 index 0000000..56453cb --- /dev/null +++ b/kernel/Makefile @@ -0,0 +1,6 @@ +ifneq ($(KBUILD_EXTMOD),) +# We only get here on kernels 2.6.0-2.6.9 . +# For newer kernels, Kbuild will be included directly by the kernel +# build system. +include $(src)/Kbuild +endif diff --git a/kernel/adt_lec.c b/kernel/adt_lec.c new file mode 100644 index 0000000..d191e2b --- /dev/null +++ b/kernel/adt_lec.c @@ -0,0 +1,68 @@ +/* + * ADT Line Echo Canceller Parameter Parsing + * + * Copyright (C) 2008 Digium, Inc. + * + * Kevin P. Fleming + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _ADT_LEC_C +#define _ADT_LEC_C + +#include + +static inline void adt_lec_init_defaults(struct adt_lec_params *params, __u32 tap_length) +{ + memset(params, 0, sizeof(*params)); + params->tap_length = tap_length; +} + +static int adt_lec_parse_params(struct adt_lec_params *params, struct zt_echocanparams *ecp, struct zt_echocanparam *p) +{ + unsigned int x; + char *c; + + for (x = 0; x < ecp->param_count; x++) { + for (c = p[x].name; *c; c++) + *c = tolower(*c); + if (!strcmp(p[x].name, "nlp_type")) { + switch (p[x].value) { + case ADT_LEC_NLP_OFF: + case ADT_LEC_NLP_MUTE: + case ADT_LEC_RANDOM_NOISE: + case ADT_LEC_HOTH_NOISE: + case ADT_LEC_SUPPRESS: + params->nlp_type = p[x].value; + break; + default: + return -EINVAL; + } + } else if (!strcmp(p[x].name, "nlp_thresh")) { + params->nlp_threshold = p[x].value; + } else if (!strcmp(p[x].name, "nlp_suppress")) { + params->nlp_max_suppress = p[x].value; + } else { + return -EINVAL; + } + } + + return 0; +} + +#endif /* _ADT_LEC_C */ diff --git a/kernel/adt_lec.h b/kernel/adt_lec.h new file mode 100644 index 0000000..c91020d --- /dev/null +++ b/kernel/adt_lec.h @@ -0,0 +1,43 @@ +/* + * ADT Line Echo Canceller Parameter Parsing + * + * Copyright (C) 2008 Digium, Inc. + * + * Kevin P. Fleming + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _ADT_LEC_H +#define _ADT_LEC_H + +enum adt_lec_nlp_type { + ADT_LEC_NLP_OFF = 0, + ADT_LEC_NLP_MUTE, + ADT_LEC_RANDOM_NOISE, + ADT_LEC_HOTH_NOISE, + ADT_LEC_SUPPRESS, +}; + +struct adt_lec_params { + __u32 tap_length; + enum adt_lec_nlp_type nlp_type; + __u32 nlp_threshold; + __u32 nlp_max_suppress; +}; + +#endif /* _ADT_LEC_H */ diff --git a/kernel/arith.h b/kernel/arith.h new file mode 100644 index 0000000..3059db5 --- /dev/null +++ b/kernel/arith.h @@ -0,0 +1,364 @@ +#ifndef _ZAPTEL_ARITH_H +#define _ZAPTEL_ARITH_H +/* + * Handy add/subtract functions to operate on chunks of shorts. + * Feel free to add customizations for additional architectures + * + */ + +#ifdef CONFIG_ZAPTEL_MMX +#ifdef ZT_CHUNKSIZE +static inline void __ACSS(volatile short *dst, const short *src) +{ + __asm__ __volatile__ ( + "movq 0(%0), %%mm0;\n" + "movq 0(%1), %%mm1;\n" + "movq 8(%0), %%mm2;\n" + "movq 8(%1), %%mm3;\n" + "paddsw %%mm1, %%mm0;\n" + "paddsw %%mm3, %%mm2;\n" + "movq %%mm0, 0(%0);\n" + "movq %%mm2, 8(%0);\n" + : "=r" (dst) + : "r" (src), "0" (dst) + : "memory" +#ifdef CLOBBERMMX + , "%mm0", "%mm1", "%mm2", "%mm3" +#endif + ); + +} +static inline void __SCSS(volatile short *dst, const short *src) +{ + __asm__ __volatile__ ( + "movq 0(%0), %%mm0;\n" + "movq 0(%1), %%mm1;\n" + "movq 8(%0), %%mm2;\n" + "movq 8(%1), %%mm3;\n" + "psubsw %%mm1, %%mm0;\n" + "psubsw %%mm3, %%mm2;\n" + "movq %%mm0, 0(%0);\n" + "movq %%mm2, 8(%0);\n" + : "=r" (dst) + : "r" (src), "0" (dst) + : "memory" +#ifdef CLOBBERMMX + , "%mm0", "%mm1", "%mm2", "%mm3" +#endif + ); + +} + +#if (ZT_CHUNKSIZE == 8) +#define ACSS(a,b) __ACSS(a,b) +#define SCSS(a,b) __SCSS(a,b) +#elif (ZT_CHUNKSIZE > 8) +static inline void ACSS(volatile short *dst, const short *src) +{ + int x; + for (x=0;x>= 4; + + /* Clear our accumulator, mm4 */ + + /* + + For every set of eight... + + Load 16 coefficients into four registers... + Shift each word right 16 to make them shorts... + Pack the resulting shorts into two registers... + With the coefficients now in mm0 and mm2, load the + history into mm1 and mm3... + Multiply/add mm1 into mm0, and mm3 into mm2... + Add mm2 into mm0 (without saturation, alas). Now we have two half-results. + Accumulate in mm4 (again, without saturation, alas) + */ + __asm__ ( + "pxor %%mm4, %%mm4;\n" + "mov %1, %%edi;\n" + "mov %2, %%esi;\n" + "mov %3, %%ecx;\n" + "1:" + "movq 0(%%edi), %%mm0;\n" + "movq 8(%%edi), %%mm1;\n" + "movq 16(%%edi), %%mm2;\n" + "movq 24(%%edi), %%mm3;\n" + /* can't use 4/5 since 4 is the accumulator for us */ + "movq 32(%%edi), %%mm6;\n" + "movq 40(%%edi), %%mm7;\n" + "psrad $16, %%mm0;\n" + "psrad $16, %%mm1;\n" + "psrad $16, %%mm2;\n" + "psrad $16, %%mm3;\n" + "psrad $16, %%mm6;\n" + "psrad $16, %%mm7;\n" + "packssdw %%mm1, %%mm0;\n" + "packssdw %%mm3, %%mm2;\n" + "packssdw %%mm7, %%mm6;\n" + "movq 0(%%esi), %%mm1;\n" + "movq 8(%%esi), %%mm3;\n" + "movq 16(%%esi), %%mm7;\n" + "pmaddwd %%mm1, %%mm0;\n" + "pmaddwd %%mm3, %%mm2;\n" + "pmaddwd %%mm7, %%mm6;\n" + "paddd %%mm6, %%mm4;\n" + "paddd %%mm2, %%mm4;\n" + "paddd %%mm0, %%mm4;\n" + /* Come back and do for the last few bytes */ + "movq 48(%%edi), %%mm6;\n" + "movq 56(%%edi), %%mm7;\n" + "psrad $16, %%mm6;\n" + "psrad $16, %%mm7;\n" + "packssdw %%mm7, %%mm6;\n" + "movq 24(%%esi), %%mm7;\n" + "pmaddwd %%mm7, %%mm6;\n" + "paddd %%mm6, %%mm4;\n" + "add $64, %%edi;\n" + "add $32, %%esi;\n" + "dec %%ecx;\n" + "jnz 1b;\n" + "movq %%mm4, %%mm0;\n" + "psrlq $32, %%mm0;\n" + "paddd %%mm0, %%mm4;\n" + "movd %%mm4, %0;\n" + : "=r" (sum) + : "r" (coeffs), "r" (hist), "r" (len) + : "%ecx", "%edi", "%esi" + ); + + return sum; +} + +static inline void UPDATE(volatile int *taps, const short *history, const int nsuppr, const int ntaps) +{ + int i; + int correction; + for (i=0;i>= 4; + /* First, load up taps, */ + __asm__ ( + "pxor %%mm4, %%mm4;\n" + "mov %0, %%edi;\n" + "mov %1, %%esi;\n" + "mov %3, %%ecx;\n" + "1:" + "jnz 1b;\n" + "movq %%mm4, %%mm0;\n" + "psrlq $32, %%mm0;\n" + "paddd %%mm0, %%mm4;\n" + "movd %%mm4, %0;\n" + : "=r" (taps), "=r" (taps_short) + : "r" (history), "r" (nsuppr), "r" (ntaps), "0" (taps) + : "%ecx", "%edi", "%esi" + ); +#endif +#if 1 + for (i=0;i> 16; + } +#endif +} + +static inline int CONVOLVE2(const short *coeffs, const short *hist, int len) +{ + int sum; + /* Divide length by 16 */ + len >>= 4; + + /* Clear our accumulator, mm4 */ + + /* + + For every set of eight... + Load in eight coefficients and eight historic samples, multliply add and + accumulate the result + */ + __asm__ ( + "pxor %%mm4, %%mm4;\n" + "mov %1, %%edi;\n" + "mov %2, %%esi;\n" + "mov %3, %%ecx;\n" + "1:" + "movq 0(%%edi), %%mm0;\n" + "movq 8(%%edi), %%mm2;\n" + "movq 0(%%esi), %%mm1;\n" + "movq 8(%%esi), %%mm3;\n" + "pmaddwd %%mm1, %%mm0;\n" + "pmaddwd %%mm3, %%mm2;\n" + "paddd %%mm2, %%mm4;\n" + "paddd %%mm0, %%mm4;\n" + "movq 16(%%edi), %%mm0;\n" + "movq 24(%%edi), %%mm2;\n" + "movq 16(%%esi), %%mm1;\n" + "movq 24(%%esi), %%mm3;\n" + "pmaddwd %%mm1, %%mm0;\n" + "pmaddwd %%mm3, %%mm2;\n" + "paddd %%mm2, %%mm4;\n" + "paddd %%mm0, %%mm4;\n" + "add $32, %%edi;\n" + "add $32, %%esi;\n" + "dec %%ecx;\n" + "jnz 1b;\n" + "movq %%mm4, %%mm0;\n" + "psrlq $32, %%mm0;\n" + "paddd %%mm0, %%mm4;\n" + "movd %%mm4, %0;\n" + : "=r" (sum) + : "r" (coeffs), "r" (hist), "r" (len) + : "%ecx", "%edi", "%esi" + ); + + return sum; +} +static inline short MAX16(const short *y, int len, int *pos) +{ + int k; + short max = 0; + int bestpos = 0; + for (k=0;k 32767) + sum = 32767; + else if (sum < -32768) + sum = -32768; + dst[x] = sum; + } +#endif +} + +static inline void SCSS(short *dst, short *src) +{ + int x; + + /* Subtract src from dst with saturation, storing in dst */ +#ifdef BFIN + for (x = 0; x < ZT_CHUNKSIZE; x++) + dst[x] = __builtin_bfin_sub_fr1x16(dst[x], src[x]); +#else + int sum; + + for (x = 0; x < ZT_CHUNKSIZE; x++) { + sum = dst[x] - src[x]; + if (sum > 32767) + sum = 32767; + else if (sum < -32768) + sum = -32768; + dst[x] = sum; + } +#endif +} + +#endif /* ZT_CHUNKSIZE */ + +static inline int CONVOLVE(const int *coeffs, const short *hist, int len) +{ + int x; + int sum = 0; + for (x=0;x> 16) * hist[x]; + return sum; +} + +static inline int CONVOLVE2(const short *coeffs, const short *hist, int len) +{ + int x; + int sum = 0; + for (x=0;x> 16; + } +} + +static inline short MAX16(const short *y, int len, int *pos) +{ + int k; + short max = 0; + int bestpos = 0; + for (k=0;k + * + * Copyright (C) 2001 Steve Underwood + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +typedef struct +{ + int32_t gain; + int32_t a1; + int32_t a2; + int32_t b1; + int32_t b2; + + int32_t z1; + int32_t z2; +} biquad2_state_t; + +static inline void biquad2_init (biquad2_state_t *bq, + int32_t gain, + int32_t a1, + int32_t a2, + int32_t b1, + int32_t b2) +{ + bq->gain = gain; + bq->a1 = a1; + bq->a2 = a2; + bq->b1 = b1; + bq->b2 = b2; + + bq->z1 = 0; + bq->z2 = 0; +} +/*- End of function --------------------------------------------------------*/ + +static inline int16_t biquad2 (biquad2_state_t *bq, int16_t sample) +{ + int32_t y; + int32_t z0; + + z0 = sample*bq->gain + bq->z1*bq->a1 + bq->z2*bq->a2; + y = z0 + bq->z1*bq->b1 + bq->z2*bq->b2; + + bq->z2 = bq->z1; + bq->z1 = z0 >> 15; + y >>= 15; + return y; +} +/*- End of function --------------------------------------------------------*/ +/*- End of file ------------------------------------------------------------*/ diff --git a/kernel/datamods/Makefile b/kernel/datamods/Makefile new file mode 100644 index 0000000..310073e --- /dev/null +++ b/kernel/datamods/Makefile @@ -0,0 +1,32 @@ +.EXPORT_ALL_VARIABLES: +MODULES= \ + hdlc_cisco hdlc_generic hdlc_raw syncppp \ + hdlc_fr hdlc_ppp hdlc_raw_eth + + +PWD=$(shell pwd) + +MODULESO:=$(MODULES:%=%.o) +MODULESKO:=$(MODULES:%=%.ko) +KMAKE = $(MAKE) -C $(KSRC) SUBDIRS=$(PWD) +KMAKE_INST = $(KMAKE) \ + INSTALL_MOD_PATH=$(INSTALL_PREFIX) INSTALL_MOD_DIR=misc modules_install + +obj-m := $(MODULESO) +#obj-m:=hdlc_raw.o hdlc_cisco.o +#obj-m := hdlc_cisco.o hdlc_cisco.mod.o hdlc_fr.o hdlc_generic.o hdlc_ppp.o hdlc_raw.o hdlc_raw_eth.o hdlc_raw.mod.o hdlc_x25.o + +all: + @echo "You don't want to do make here. Do it from up above" + +clean: + $(KMAKE) clean + +install: $(MODULESKO) + $(KMAKE_INST) + +datamods: + @echo "To build: $(obj-m)" + @echo $(KSRC) + @if [ -z "$(KSRC)" -o ! -d "$(KSRC)" ]; then echo "You do not appear to have the sources for the $(KVERS) kernel installed."; exit 1 ; fi + $(KMAKE) modules diff --git a/kernel/datamods/hdlc_cisco.c b/kernel/datamods/hdlc_cisco.c new file mode 100644 index 0000000..1fd0466 --- /dev/null +++ b/kernel/datamods/hdlc_cisco.c @@ -0,0 +1,335 @@ +/* + * Generic HDLC support routines for Linux + * Cisco HDLC support + * + * Copyright (C) 2000 - 2003 Krzysztof Halasa + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG_HARD_HEADER + +#define CISCO_MULTICAST 0x8F /* Cisco multicast address */ +#define CISCO_UNICAST 0x0F /* Cisco unicast address */ +#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ +#define CISCO_SYS_INFO 0x2000 /* Cisco interface/system info */ +#define CISCO_ADDR_REQ 0 /* Cisco address request */ +#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ +#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ + + +static int cisco_hard_header(struct sk_buff *skb, struct net_device *dev, + u16 type, void *daddr, void *saddr, + unsigned int len) +{ + hdlc_header *data; +#ifdef DEBUG_HARD_HEADER + printk(KERN_DEBUG "%s: cisco_hard_header called\n", dev->name); +#endif + + skb_push(skb, sizeof(hdlc_header)); + data = (hdlc_header*)skb->data; + if (type == CISCO_KEEPALIVE) + data->address = CISCO_MULTICAST; + else + data->address = CISCO_UNICAST; + data->control = 0; + data->protocol = htons(type); + + return sizeof(hdlc_header); +} + + + +static void cisco_keepalive_send(struct net_device *dev, u32 type, + u32 par1, u32 par2) +{ + struct sk_buff *skb; + cisco_packet *data; + + skb = dev_alloc_skb(sizeof(hdlc_header) + sizeof(cisco_packet)); + if (!skb) { + printk(KERN_WARNING + "%s: Memory squeeze on cisco_keepalive_send()\n", + dev->name); + return; + } + skb_reserve(skb, 4); + cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0); + data = (cisco_packet*)(skb->data + 4); + + data->type = htonl(type); + data->par1 = htonl(par1); + data->par2 = htonl(par2); + data->rel = 0xFFFF; + /* we will need do_div here if 1000 % HZ != 0 */ + data->time = htonl((jiffies - INITIAL_JIFFIES) * (1000 / HZ)); + + skb_put(skb, sizeof(cisco_packet)); + skb->priority = TC_PRIO_CONTROL; + skb->dev = dev; + skb->nh.raw = skb->data; + + dev_queue_xmit(skb); +} + + + +static __be16 cisco_type_trans(struct sk_buff *skb, struct net_device *dev) +{ + hdlc_header *data = (hdlc_header*)skb->data; + + if (skb->len < sizeof(hdlc_header)) + return __constant_htons(ETH_P_HDLC); + + if (data->address != CISCO_MULTICAST && + data->address != CISCO_UNICAST) + return __constant_htons(ETH_P_HDLC); + + switch(data->protocol) { + case __constant_htons(ETH_P_IP): + case __constant_htons(ETH_P_IPX): + case __constant_htons(ETH_P_IPV6): + skb_pull(skb, sizeof(hdlc_header)); + return data->protocol; + default: + return __constant_htons(ETH_P_HDLC); + } +} + + +static int cisco_rx(struct sk_buff *skb) +{ + struct net_device *dev = skb->dev; + hdlc_device *hdlc = dev_to_hdlc(dev); + hdlc_header *data = (hdlc_header*)skb->data; + cisco_packet *cisco_data; + struct in_device *in_dev; + u32 addr, mask; + + if (skb->len < sizeof(hdlc_header)) + goto rx_error; + + if (data->address != CISCO_MULTICAST && + data->address != CISCO_UNICAST) + goto rx_error; + + switch(ntohs(data->protocol)) { + case CISCO_SYS_INFO: + /* Packet is not needed, drop it. */ + dev_kfree_skb_any(skb); + return NET_RX_SUCCESS; + + case CISCO_KEEPALIVE: + if (skb->len != sizeof(hdlc_header) + CISCO_PACKET_LEN && + skb->len != sizeof(hdlc_header) + CISCO_BIG_PACKET_LEN) { + printk(KERN_INFO "%s: Invalid length of Cisco " + "control packet (%d bytes)\n", + dev->name, skb->len); + goto rx_error; + } + + cisco_data = (cisco_packet*)(skb->data + sizeof(hdlc_header)); + + switch(ntohl (cisco_data->type)) { + case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */ + in_dev = dev->ip_ptr; + addr = 0; + mask = ~0; /* is the mask correct? */ + + if (in_dev != NULL) { + struct in_ifaddr **ifap = &in_dev->ifa_list; + + while (*ifap != NULL) { + if (strcmp(dev->name, + (*ifap)->ifa_label) == 0) { + addr = (*ifap)->ifa_local; + mask = (*ifap)->ifa_mask; + break; + } + ifap = &(*ifap)->ifa_next; + } + + cisco_keepalive_send(dev, CISCO_ADDR_REPLY, + addr, mask); + } + dev_kfree_skb_any(skb); + return NET_RX_SUCCESS; + + case CISCO_ADDR_REPLY: + printk(KERN_INFO "%s: Unexpected Cisco IP address " + "reply\n", dev->name); + goto rx_error; + + case CISCO_KEEPALIVE_REQ: + hdlc->state.cisco.rxseq = ntohl(cisco_data->par1); + if (hdlc->state.cisco.request_sent && + ntohl(cisco_data->par2)==hdlc->state.cisco.txseq) { + hdlc->state.cisco.last_poll = jiffies; + if (!hdlc->state.cisco.up) { + u32 sec, min, hrs, days; + sec = ntohl(cisco_data->time) / 1000; + min = sec / 60; sec -= min * 60; + hrs = min / 60; min -= hrs * 60; + days = hrs / 24; hrs -= days * 24; + printk(KERN_INFO "%s: Link up (peer " + "uptime %ud%uh%um%us)\n", + dev->name, days, hrs, + min, sec); +#if 0 + netif_carrier_on(dev); +#endif + hdlc->state.cisco.up = 1; + } + } + + dev_kfree_skb_any(skb); + return NET_RX_SUCCESS; + } /* switch(keepalive type) */ + } /* switch(protocol) */ + + printk(KERN_INFO "%s: Unsupported protocol %x\n", dev->name, + data->protocol); + dev_kfree_skb_any(skb); + return NET_RX_DROP; + + rx_error: + hdlc->stats.rx_errors++; /* Mark error */ + dev_kfree_skb_any(skb); + return NET_RX_DROP; +} + + + +static void cisco_timer(unsigned long arg) +{ + struct net_device *dev = (struct net_device *)arg; + hdlc_device *hdlc = dev_to_hdlc(dev); + + if (hdlc->state.cisco.up && + time_after(jiffies, hdlc->state.cisco.last_poll + + hdlc->state.cisco.settings.timeout * HZ)) { + hdlc->state.cisco.up = 0; + printk(KERN_INFO "%s: Link down\n", dev->name); +#if 0 + netif_carrier_off(dev); +#endif + } + + cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, + ++hdlc->state.cisco.txseq, + hdlc->state.cisco.rxseq); + hdlc->state.cisco.request_sent = 1; + hdlc->state.cisco.timer.expires = jiffies + + hdlc->state.cisco.settings.interval * HZ; + hdlc->state.cisco.timer.function = cisco_timer; + hdlc->state.cisco.timer.data = arg; + add_timer(&hdlc->state.cisco.timer); +} + + + +static void cisco_start(struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + hdlc->state.cisco.up = 0; + hdlc->state.cisco.request_sent = 0; + hdlc->state.cisco.txseq = hdlc->state.cisco.rxseq = 0; + + init_timer(&hdlc->state.cisco.timer); + hdlc->state.cisco.timer.expires = jiffies + HZ; /*First poll after 1s*/ + hdlc->state.cisco.timer.function = cisco_timer; + hdlc->state.cisco.timer.data = (unsigned long)dev; + add_timer(&hdlc->state.cisco.timer); +} + + + +static void cisco_stop(struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + del_timer_sync(&hdlc->state.cisco.timer); +#if 0 + if (netif_carrier_ok(dev)) + netif_carrier_off(dev); +#endif + hdlc->state.cisco.up = 0; + hdlc->state.cisco.request_sent = 0; +} + + + +int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr) +{ + cisco_proto __user *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco; + const size_t size = sizeof(cisco_proto); + cisco_proto new_settings; + hdlc_device *hdlc = dev_to_hdlc(dev); + int result; + + switch (ifr->ifr_settings.type) { + case IF_GET_PROTO: + ifr->ifr_settings.type = IF_PROTO_CISCO; + if (ifr->ifr_settings.size < size) { + ifr->ifr_settings.size = size; /* data size wanted */ + return -ENOBUFS; + } + if (copy_to_user(cisco_s, &hdlc->state.cisco.settings, size)) + return -EFAULT; + return 0; + + case IF_PROTO_CISCO: + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + + if(dev->flags & IFF_UP) + return -EBUSY; + + if (copy_from_user(&new_settings, cisco_s, size)) + return -EFAULT; + + if (new_settings.interval < 1 || + new_settings.timeout < 2) + return -EINVAL; + + result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); + + if (result) + return result; + + hdlc_proto_detach(hdlc); + memcpy(&hdlc->state.cisco.settings, &new_settings, size); + memset(&hdlc->proto, 0, sizeof(hdlc->proto)); + + hdlc->proto.start = cisco_start; + hdlc->proto.stop = cisco_stop; + hdlc->proto.netif_rx = cisco_rx; + hdlc->proto.type_trans = cisco_type_trans; + hdlc->proto.id = IF_PROTO_CISCO; + dev->hard_start_xmit = hdlc->xmit; + dev->hard_header = cisco_hard_header; + dev->hard_header_cache = NULL; + dev->type = ARPHRD_CISCO; + dev->flags = IFF_POINTOPOINT | IFF_NOARP; + dev->addr_len = 0; + return 0; + } + + return -EINVAL; +} diff --git a/kernel/datamods/hdlc_fr.c b/kernel/datamods/hdlc_fr.c new file mode 100644 index 0000000..523afe1 --- /dev/null +++ b/kernel/datamods/hdlc_fr.c @@ -0,0 +1,1273 @@ +/* + * Generic HDLC support routines for Linux + * Frame Relay support + * + * Copyright (C) 1999 - 2005 Krzysztof Halasa + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + + Theory of PVC state + + DCE mode: + + (exist,new) -> 0,0 when "PVC create" or if "link unreliable" + 0,x -> 1,1 if "link reliable" when sending FULL STATUS + 1,1 -> 1,0 if received FULL STATUS ACK + + (active) -> 0 when "ifconfig PVC down" or "link unreliable" or "PVC create" + -> 1 when "PVC up" and (exist,new) = 1,0 + + DTE mode: + (exist,new,active) = FULL STATUS if "link reliable" + = 0, 0, 0 if "link unreliable" + No LMI: + active = open and "link reliable" + exist = new = not used + + CCITT LMI: ITU-T Q.933 Annex A + ANSI LMI: ANSI T1.617 Annex D + CISCO LMI: the original, aka "Gang of Four" LMI + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG_PKT +#undef DEBUG_ECN +#undef DEBUG_LINK + +#define FR_UI 0x03 +#define FR_PAD 0x00 + +#define NLPID_IP 0xCC +#define NLPID_IPV6 0x8E +#define NLPID_SNAP 0x80 +#define NLPID_PAD 0x00 +#define NLPID_CCITT_ANSI_LMI 0x08 +#define NLPID_CISCO_LMI 0x09 + + +#define LMI_CCITT_ANSI_DLCI 0 /* LMI DLCI */ +#define LMI_CISCO_DLCI 1023 + +#define LMI_CALLREF 0x00 /* Call Reference */ +#define LMI_ANSI_LOCKSHIFT 0x95 /* ANSI locking shift */ +#define LMI_ANSI_CISCO_REPTYPE 0x01 /* report type */ +#define LMI_CCITT_REPTYPE 0x51 +#define LMI_ANSI_CISCO_ALIVE 0x03 /* keep alive */ +#define LMI_CCITT_ALIVE 0x53 +#define LMI_ANSI_CISCO_PVCSTAT 0x07 /* PVC status */ +#define LMI_CCITT_PVCSTAT 0x57 + +#define LMI_FULLREP 0x00 /* full report */ +#define LMI_INTEGRITY 0x01 /* link integrity report */ +#define LMI_SINGLE 0x02 /* single PVC report */ + +#define LMI_STATUS_ENQUIRY 0x75 +#define LMI_STATUS 0x7D /* reply */ + +#define LMI_REPT_LEN 1 /* report type element length */ +#define LMI_INTEG_LEN 2 /* link integrity element length */ + +#define LMI_CCITT_CISCO_LENGTH 13 /* LMI frame lengths */ +#define LMI_ANSI_LENGTH 14 + + +typedef struct { +#if defined(__LITTLE_ENDIAN_BITFIELD) + unsigned ea1: 1; + unsigned cr: 1; + unsigned dlcih: 6; + + unsigned ea2: 1; + unsigned de: 1; + unsigned becn: 1; + unsigned fecn: 1; + unsigned dlcil: 4; +#else + unsigned dlcih: 6; + unsigned cr: 1; + unsigned ea1: 1; + + unsigned dlcil: 4; + unsigned fecn: 1; + unsigned becn: 1; + unsigned de: 1; + unsigned ea2: 1; +#endif +}__attribute__ ((packed)) fr_hdr; + + +static inline u16 q922_to_dlci(u8 *hdr) +{ + return ((hdr[0] & 0xFC) << 2) | ((hdr[1] & 0xF0) >> 4); +} + + + +static inline void dlci_to_q922(u8 *hdr, u16 dlci) +{ + hdr[0] = (dlci >> 2) & 0xFC; + hdr[1] = ((dlci << 4) & 0xF0) | 0x01; +} + + + +static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci) +{ + pvc_device *pvc = hdlc->state.fr.first_pvc; + + while (pvc) { + if (pvc->dlci == dlci) + return pvc; + if (pvc->dlci > dlci) + return NULL; /* the listed is sorted */ + pvc = pvc->next; + } + + return NULL; +} + + +static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + pvc_device *pvc, **pvc_p = &hdlc->state.fr.first_pvc; + + while (*pvc_p) { + if ((*pvc_p)->dlci == dlci) + return *pvc_p; + if ((*pvc_p)->dlci > dlci) + break; /* the list is sorted */ + pvc_p = &(*pvc_p)->next; + } + + pvc = kmalloc(sizeof(pvc_device), GFP_ATOMIC); + if (!pvc) + return NULL; + + memset(pvc, 0, sizeof(pvc_device)); + pvc->dlci = dlci; + pvc->master = dev; + pvc->next = *pvc_p; /* Put it in the chain */ + *pvc_p = pvc; + return pvc; +} + + +static inline int pvc_is_used(pvc_device *pvc) +{ + return pvc->main != NULL || pvc->ether != NULL; +} + + +static inline void pvc_carrier(int on, pvc_device *pvc) +{ + if (on) { + if (pvc->main) + if (!netif_carrier_ok(pvc->main)) + netif_carrier_on(pvc->main); + if (pvc->ether) + if (!netif_carrier_ok(pvc->ether)) + netif_carrier_on(pvc->ether); + } else { + if (pvc->main) + if (netif_carrier_ok(pvc->main)) + netif_carrier_off(pvc->main); + if (pvc->ether) + if (netif_carrier_ok(pvc->ether)) + netif_carrier_off(pvc->ether); + } +} + + +static inline void delete_unused_pvcs(hdlc_device *hdlc) +{ + pvc_device **pvc_p = &hdlc->state.fr.first_pvc; + + while (*pvc_p) { + if (!pvc_is_used(*pvc_p)) { + pvc_device *pvc = *pvc_p; + *pvc_p = pvc->next; + kfree(pvc); + continue; + } + pvc_p = &(*pvc_p)->next; + } +} + + +static inline struct net_device** get_dev_p(pvc_device *pvc, int type) +{ + if (type == ARPHRD_ETHER) + return &pvc->ether; + else + return &pvc->main; +} + + +static int fr_hard_header(struct sk_buff **skb_p, u16 dlci) +{ + u16 head_len; + struct sk_buff *skb = *skb_p; + + switch (skb->protocol) { + case __constant_ntohs(NLPID_CCITT_ANSI_LMI): + head_len = 4; + skb_push(skb, head_len); + skb->data[3] = NLPID_CCITT_ANSI_LMI; + break; + + case __constant_ntohs(NLPID_CISCO_LMI): + head_len = 4; + skb_push(skb, head_len); + skb->data[3] = NLPID_CISCO_LMI; + break; + + case __constant_ntohs(ETH_P_IP): + head_len = 4; + skb_push(skb, head_len); + skb->data[3] = NLPID_IP; + break; + + case __constant_ntohs(ETH_P_IPV6): + head_len = 4; + skb_push(skb, head_len); + skb->data[3] = NLPID_IPV6; + break; + + case __constant_ntohs(ETH_P_802_3): + head_len = 10; + if (skb_headroom(skb) < head_len) { + struct sk_buff *skb2 = skb_realloc_headroom(skb, + head_len); + if (!skb2) + return -ENOBUFS; + dev_kfree_skb(skb); + skb = *skb_p = skb2; + } + skb_push(skb, head_len); + skb->data[3] = FR_PAD; + skb->data[4] = NLPID_SNAP; + skb->data[5] = FR_PAD; + skb->data[6] = 0x80; + skb->data[7] = 0xC2; + skb->data[8] = 0x00; + skb->data[9] = 0x07; /* bridged Ethernet frame w/out FCS */ + break; + + default: + head_len = 10; + skb_push(skb, head_len); + skb->data[3] = FR_PAD; + skb->data[4] = NLPID_SNAP; + skb->data[5] = FR_PAD; + skb->data[6] = FR_PAD; + skb->data[7] = FR_PAD; + *(u16*)(skb->data + 8) = skb->protocol; + } + + dlci_to_q922(skb->data, dlci); + skb->data[2] = FR_UI; + return 0; +} + + + +static int pvc_open(struct net_device *dev) +{ + pvc_device *pvc = dev_to_pvc(dev); + + if ((pvc->master->flags & IFF_UP) == 0) + return -EIO; /* Master must be UP in order to activate PVC */ + + if (pvc->open_count++ == 0) { + hdlc_device *hdlc = dev_to_hdlc(pvc->master); + if (hdlc->state.fr.settings.lmi == LMI_NONE) + pvc->state.active = hdlc->carrier; + + pvc_carrier(pvc->state.active, pvc); + hdlc->state.fr.dce_changed = 1; + } + return 0; +} + + + +static int pvc_close(struct net_device *dev) +{ + pvc_device *pvc = dev_to_pvc(dev); + + if (--pvc->open_count == 0) { + hdlc_device *hdlc = dev_to_hdlc(pvc->master); + if (hdlc->state.fr.settings.lmi == LMI_NONE) + pvc->state.active = 0; + + if (hdlc->state.fr.settings.dce) { + hdlc->state.fr.dce_changed = 1; + pvc->state.active = 0; + } + } + return 0; +} + + + +static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + pvc_device *pvc = dev_to_pvc(dev); + fr_proto_pvc_info info; + + if (ifr->ifr_settings.type == IF_GET_PROTO) { + if (dev->type == ARPHRD_ETHER) + ifr->ifr_settings.type = IF_PROTO_FR_ETH_PVC; + else + ifr->ifr_settings.type = IF_PROTO_FR_PVC; + + if (ifr->ifr_settings.size < sizeof(info)) { + /* data size wanted */ + ifr->ifr_settings.size = sizeof(info); + return -ENOBUFS; + } + + info.dlci = pvc->dlci; + memcpy(info.master, pvc->master->name, IFNAMSIZ); + if (copy_to_user(ifr->ifr_settings.ifs_ifsu.fr_pvc_info, + &info, sizeof(info))) + return -EFAULT; + return 0; + } + + return -EINVAL; +} + + +static inline struct net_device_stats *pvc_get_stats(struct net_device *dev) +{ + return netdev_priv(dev); +} + + + +static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) +{ + pvc_device *pvc = dev_to_pvc(dev); + struct net_device_stats *stats = pvc_get_stats(dev); + + if (pvc->state.active) { + if (dev->type == ARPHRD_ETHER) { + int pad = ETH_ZLEN - skb->len; + if (pad > 0) { /* Pad the frame with zeros */ + int len = skb->len; + if (skb_tailroom(skb) < pad) + if (pskb_expand_head(skb, 0, pad, + GFP_ATOMIC)) { + stats->tx_dropped++; + dev_kfree_skb(skb); + return 0; + } + skb_put(skb, pad); + memset(skb->data + len, 0, pad); + } + skb->protocol = __constant_htons(ETH_P_802_3); + } + if (!fr_hard_header(&skb, pvc->dlci)) { + stats->tx_bytes += skb->len; + stats->tx_packets++; + if (pvc->state.fecn) /* TX Congestion counter */ + stats->tx_compressed++; + skb->dev = pvc->master; + dev_queue_xmit(skb); + return 0; + } + } + + stats->tx_dropped++; + dev_kfree_skb(skb); + return 0; +} + + + +static int pvc_change_mtu(struct net_device *dev, int new_mtu) +{ + if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU)) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + + + +static inline void fr_log_dlci_active(pvc_device *pvc) +{ + printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n", + pvc->master->name, + pvc->dlci, + pvc->main ? pvc->main->name : "", + pvc->main && pvc->ether ? " " : "", + pvc->ether ? pvc->ether->name : "", + pvc->state.new ? " new" : "", + !pvc->state.exist ? "deleted" : + pvc->state.active ? "active" : "inactive"); +} + + + +static inline u8 fr_lmi_nextseq(u8 x) +{ + x++; + return x ? x : 1; +} + + + +static void fr_lmi_send(struct net_device *dev, int fullrep) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + struct sk_buff *skb; + pvc_device *pvc = hdlc->state.fr.first_pvc; + int lmi = hdlc->state.fr.settings.lmi; + int dce = hdlc->state.fr.settings.dce; + int len = lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH; + int stat_len = (lmi == LMI_CISCO) ? 6 : 3; + u8 *data; + int i = 0; + + if (dce && fullrep) { + len += hdlc->state.fr.dce_pvc_count * (2 + stat_len); + if (len > HDLC_MAX_MRU) { + printk(KERN_WARNING "%s: Too many PVCs while sending " + "LMI full report\n", dev->name); + return; + } + } + + skb = dev_alloc_skb(len); + if (!skb) { + printk(KERN_WARNING "%s: Memory squeeze on fr_lmi_send()\n", + dev->name); + return; + } + memset(skb->data, 0, len); + skb_reserve(skb, 4); + if (lmi == LMI_CISCO) { + skb->protocol = __constant_htons(NLPID_CISCO_LMI); + fr_hard_header(&skb, LMI_CISCO_DLCI); + } else { + skb->protocol = __constant_htons(NLPID_CCITT_ANSI_LMI); + fr_hard_header(&skb, LMI_CCITT_ANSI_DLCI); + } + data = skb->tail; + data[i++] = LMI_CALLREF; + data[i++] = dce ? LMI_STATUS : LMI_STATUS_ENQUIRY; + if (lmi == LMI_ANSI) + data[i++] = LMI_ANSI_LOCKSHIFT; + data[i++] = lmi == LMI_CCITT ? LMI_CCITT_REPTYPE : + LMI_ANSI_CISCO_REPTYPE; + data[i++] = LMI_REPT_LEN; + data[i++] = fullrep ? LMI_FULLREP : LMI_INTEGRITY; + data[i++] = lmi == LMI_CCITT ? LMI_CCITT_ALIVE : LMI_ANSI_CISCO_ALIVE; + data[i++] = LMI_INTEG_LEN; + data[i++] = hdlc->state.fr.txseq =fr_lmi_nextseq(hdlc->state.fr.txseq); + data[i++] = hdlc->state.fr.rxseq; + + if (dce && fullrep) { + while (pvc) { + data[i++] = lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT : + LMI_ANSI_CISCO_PVCSTAT; + data[i++] = stat_len; + + /* LMI start/restart */ + if (hdlc->state.fr.reliable && !pvc->state.exist) { + pvc->state.exist = pvc->state.new = 1; + fr_log_dlci_active(pvc); + } + + /* ifconfig PVC up */ + if (pvc->open_count && !pvc->state.active && + pvc->state.exist && !pvc->state.new) { + pvc_carrier(1, pvc); + pvc->state.active = 1; + fr_log_dlci_active(pvc); + } + + if (lmi == LMI_CISCO) { + data[i] = pvc->dlci >> 8; + data[i + 1] = pvc->dlci & 0xFF; + } else { + data[i] = (pvc->dlci >> 4) & 0x3F; + data[i + 1] = ((pvc->dlci << 3) & 0x78) | 0x80; + data[i + 2] = 0x80; + } + + if (pvc->state.new) + data[i + 2] |= 0x08; + else if (pvc->state.active) + data[i + 2] |= 0x02; + + i += stat_len; + pvc = pvc->next; + } + } + + skb_put(skb, i); + skb->priority = TC_PRIO_CONTROL; + skb->dev = dev; + skb->nh.raw = skb->data; + + dev_queue_xmit(skb); +} + + + +static void fr_set_link_state(int reliable, struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + pvc_device *pvc = hdlc->state.fr.first_pvc; + + hdlc->state.fr.reliable = reliable; + if (reliable) { +#if 0 + if (!netif_carrier_ok(dev)) + netif_carrier_on(dev); +#endif + + hdlc->state.fr.n391cnt = 0; /* Request full status */ + hdlc->state.fr.dce_changed = 1; + + if (hdlc->state.fr.settings.lmi == LMI_NONE) { + while (pvc) { /* Activate all PVCs */ + pvc_carrier(1, pvc); + pvc->state.exist = pvc->state.active = 1; + pvc->state.new = 0; + pvc = pvc->next; + } + } + } else { +#if 0 + if (netif_carrier_ok(dev)) + netif_carrier_off(dev); +#endif + + while (pvc) { /* Deactivate all PVCs */ + pvc_carrier(0, pvc); + pvc->state.exist = pvc->state.active = 0; + pvc->state.new = 0; + if (!hdlc->state.fr.settings.dce) + pvc->state.bandwidth = 0; + pvc = pvc->next; + } + } +} + + + +static void fr_timer(unsigned long arg) +{ + struct net_device *dev = (struct net_device *)arg; + hdlc_device *hdlc = dev_to_hdlc(dev); + int i, cnt = 0, reliable; + u32 list; + + if (hdlc->state.fr.settings.dce) { + reliable = hdlc->state.fr.request && + time_before(jiffies, hdlc->state.fr.last_poll + + hdlc->state.fr.settings.t392 * HZ); + hdlc->state.fr.request = 0; + } else { + hdlc->state.fr.last_errors <<= 1; /* Shift the list */ + if (hdlc->state.fr.request) { + if (hdlc->state.fr.reliable) + printk(KERN_INFO "%s: No LMI status reply " + "received\n", dev->name); + hdlc->state.fr.last_errors |= 1; + } + + list = hdlc->state.fr.last_errors; + for (i = 0; i < hdlc->state.fr.settings.n393; i++, list >>= 1) + cnt += (list & 1); /* errors count */ + + reliable = (cnt < hdlc->state.fr.settings.n392); + } + + if (hdlc->state.fr.reliable != reliable) { + printk(KERN_INFO "%s: Link %sreliable\n", dev->name, + reliable ? "" : "un"); + fr_set_link_state(reliable, dev); + } + + if (hdlc->state.fr.settings.dce) + hdlc->state.fr.timer.expires = jiffies + + hdlc->state.fr.settings.t392 * HZ; + else { + if (hdlc->state.fr.n391cnt) + hdlc->state.fr.n391cnt--; + + fr_lmi_send(dev, hdlc->state.fr.n391cnt == 0); + + hdlc->state.fr.last_poll = jiffies; + hdlc->state.fr.request = 1; + hdlc->state.fr.timer.expires = jiffies + + hdlc->state.fr.settings.t391 * HZ; + } + + hdlc->state.fr.timer.function = fr_timer; + hdlc->state.fr.timer.data = arg; + add_timer(&hdlc->state.fr.timer); +} + + + +static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + pvc_device *pvc; + u8 rxseq, txseq; + int lmi = hdlc->state.fr.settings.lmi; + int dce = hdlc->state.fr.settings.dce; + int stat_len = (lmi == LMI_CISCO) ? 6 : 3, reptype, error, no_ram, i; + + if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH : + LMI_CCITT_CISCO_LENGTH)) { + printk(KERN_INFO "%s: Short LMI frame\n", dev->name); + return 1; + } + + if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI : + NLPID_CCITT_ANSI_LMI)) { + printk(KERN_INFO "%s: Received non-LMI frame with LMI" + " DLCI\n", dev->name); + return 1; + } + + if (skb->data[4] != LMI_CALLREF) { + printk(KERN_INFO "%s: Invalid LMI Call reference (0x%02X)\n", + dev->name, skb->data[4]); + return 1; + } + + if (skb->data[5] != (dce ? LMI_STATUS_ENQUIRY : LMI_STATUS)) { + printk(KERN_INFO "%s: Invalid LMI Message type (0x%02X)\n", + dev->name, skb->data[5]); + return 1; + } + + if (lmi == LMI_ANSI) { + if (skb->data[6] != LMI_ANSI_LOCKSHIFT) { + printk(KERN_INFO "%s: Not ANSI locking shift in LMI" + " message (0x%02X)\n", dev->name, skb->data[6]); + return 1; + } + i = 7; + } else + i = 6; + + if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_REPTYPE : + LMI_ANSI_CISCO_REPTYPE)) { + printk(KERN_INFO "%s: Not an LMI Report type IE (0x%02X)\n", + dev->name, skb->data[i]); + return 1; + } + + if (skb->data[++i] != LMI_REPT_LEN) { + printk(KERN_INFO "%s: Invalid LMI Report type IE length" + " (%u)\n", dev->name, skb->data[i]); + return 1; + } + + reptype = skb->data[++i]; + if (reptype != LMI_INTEGRITY && reptype != LMI_FULLREP) { + printk(KERN_INFO "%s: Unsupported LMI Report type (0x%02X)\n", + dev->name, reptype); + return 1; + } + + if (skb->data[++i] != (lmi == LMI_CCITT ? LMI_CCITT_ALIVE : + LMI_ANSI_CISCO_ALIVE)) { + printk(KERN_INFO "%s: Not an LMI Link integrity verification" + " IE (0x%02X)\n", dev->name, skb->data[i]); + return 1; + } + + if (skb->data[++i] != LMI_INTEG_LEN) { + printk(KERN_INFO "%s: Invalid LMI Link integrity verification" + " IE length (%u)\n", dev->name, skb->data[i]); + return 1; + } + i++; + + hdlc->state.fr.rxseq = skb->data[i++]; /* TX sequence from peer */ + rxseq = skb->data[i++]; /* Should confirm our sequence */ + + txseq = hdlc->state.fr.txseq; + + if (dce) + hdlc->state.fr.last_poll = jiffies; + + error = 0; + if (!hdlc->state.fr.reliable) + error = 1; + + if (rxseq == 0 || rxseq != txseq) { + hdlc->state.fr.n391cnt = 0; /* Ask for full report next time */ + error = 1; + } + + if (dce) { + if (hdlc->state.fr.fullrep_sent && !error) { +/* Stop sending full report - the last one has been confirmed by DTE */ + hdlc->state.fr.fullrep_sent = 0; + pvc = hdlc->state.fr.first_pvc; + while (pvc) { + if (pvc->state.new) { + pvc->state.new = 0; + +/* Tell DTE that new PVC is now active */ + hdlc->state.fr.dce_changed = 1; + } + pvc = pvc->next; + } + } + + if (hdlc->state.fr.dce_changed) { + reptype = LMI_FULLREP; + hdlc->state.fr.fullrep_sent = 1; + hdlc->state.fr.dce_changed = 0; + } + + hdlc->state.fr.request = 1; /* got request */ + fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0); + return 0; + } + + /* DTE */ + + hdlc->state.fr.request = 0; /* got response, no request pending */ + + if (error) + return 0; + + if (reptype != LMI_FULLREP) + return 0; + + pvc = hdlc->state.fr.first_pvc; + + while (pvc) { + pvc->state.deleted = 1; + pvc = pvc->next; + } + + no_ram = 0; + while (skb->len >= i + 2 + stat_len) { + u16 dlci; + u32 bw; + unsigned int active, new; + + if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT : + LMI_ANSI_CISCO_PVCSTAT)) { + printk(KERN_INFO "%s: Not an LMI PVC status IE" + " (0x%02X)\n", dev->name, skb->data[i]); + return 1; + } + + if (skb->data[++i] != stat_len) { + printk(KERN_INFO "%s: Invalid LMI PVC status IE length" + " (%u)\n", dev->name, skb->data[i]); + return 1; + } + i++; + + new = !! (skb->data[i + 2] & 0x08); + active = !! (skb->data[i + 2] & 0x02); + if (lmi == LMI_CISCO) { + dlci = (skb->data[i] << 8) | skb->data[i + 1]; + bw = (skb->data[i + 3] << 16) | + (skb->data[i + 4] << 8) | + (skb->data[i + 5]); + } else { + dlci = ((skb->data[i] & 0x3F) << 4) | + ((skb->data[i + 1] & 0x78) >> 3); + bw = 0; + } + + pvc = add_pvc(dev, dlci); + + if (!pvc && !no_ram) { + printk(KERN_WARNING + "%s: Memory squeeze on fr_lmi_recv()\n", + dev->name); + no_ram = 1; + } + + if (pvc) { + pvc->state.exist = 1; + pvc->state.deleted = 0; + if (active != pvc->state.active || + new != pvc->state.new || + bw != pvc->state.bandwidth || + !pvc->state.exist) { + pvc->state.new = new; + pvc->state.active = active; + pvc->state.bandwidth = bw; + pvc_carrier(active, pvc); + fr_log_dlci_active(pvc); + } + } + + i += stat_len; + } + + pvc = hdlc->state.fr.first_pvc; + + while (pvc) { + if (pvc->state.deleted && pvc->state.exist) { + pvc_carrier(0, pvc); + pvc->state.active = pvc->state.new = 0; + pvc->state.exist = 0; + pvc->state.bandwidth = 0; + fr_log_dlci_active(pvc); + } + pvc = pvc->next; + } + + /* Next full report after N391 polls */ + hdlc->state.fr.n391cnt = hdlc->state.fr.settings.n391; + + return 0; +} + + + +static int fr_rx(struct sk_buff *skb) +{ + struct net_device *ndev = skb->dev; + hdlc_device *hdlc = dev_to_hdlc(ndev); + fr_hdr *fh = (fr_hdr*)skb->data; + u8 *data = skb->data; + u16 dlci; + pvc_device *pvc; + struct net_device *dev = NULL; + + if (skb->len <= 4 || fh->ea1 || data[2] != FR_UI) + goto rx_error; + + dlci = q922_to_dlci(skb->data); + + if ((dlci == LMI_CCITT_ANSI_DLCI && + (hdlc->state.fr.settings.lmi == LMI_ANSI || + hdlc->state.fr.settings.lmi == LMI_CCITT)) || + (dlci == LMI_CISCO_DLCI && + hdlc->state.fr.settings.lmi == LMI_CISCO)) { + if (fr_lmi_recv(ndev, skb)) + goto rx_error; + dev_kfree_skb_any(skb); + return NET_RX_SUCCESS; + } + + pvc = find_pvc(hdlc, dlci); + if (!pvc) { +#ifdef DEBUG_PKT + printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n", + ndev->name, dlci); +#endif + dev_kfree_skb_any(skb); + return NET_RX_DROP; + } + + if (pvc->state.fecn != fh->fecn) { +#ifdef DEBUG_ECN + printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", ndev->name, + dlci, fh->fecn ? "N" : "FF"); +#endif + pvc->state.fecn ^= 1; + } + + if (pvc->state.becn != fh->becn) { +#ifdef DEBUG_ECN + printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", ndev->name, + dlci, fh->becn ? "N" : "FF"); +#endif + pvc->state.becn ^= 1; + } + + + if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { + hdlc->stats.rx_dropped++; + return NET_RX_DROP; + } + + if (data[3] == NLPID_IP) { + skb_pull(skb, 4); /* Remove 4-byte header (hdr, UI, NLPID) */ + dev = pvc->main; + skb->protocol = htons(ETH_P_IP); + + } else if (data[3] == NLPID_IPV6) { + skb_pull(skb, 4); /* Remove 4-byte header (hdr, UI, NLPID) */ + dev = pvc->main; + skb->protocol = htons(ETH_P_IPV6); + + } else if (skb->len > 10 && data[3] == FR_PAD && + data[4] == NLPID_SNAP && data[5] == FR_PAD) { + u16 oui = ntohs(*(u16*)(data + 6)); + u16 pid = ntohs(*(u16*)(data + 8)); + skb_pull(skb, 10); + + switch ((((u32)oui) << 16) | pid) { + case ETH_P_ARP: /* routed frame with SNAP */ + case ETH_P_IPX: + case ETH_P_IP: /* a long variant */ + case ETH_P_IPV6: + dev = pvc->main; + skb->protocol = htons(pid); + break; + + case 0x80C20007: /* bridged Ethernet frame */ + if ((dev = pvc->ether) != NULL) + skb->protocol = eth_type_trans(skb, dev); + break; + + default: + printk(KERN_INFO "%s: Unsupported protocol, OUI=%x " + "PID=%x\n", ndev->name, oui, pid); + dev_kfree_skb_any(skb); + return NET_RX_DROP; + } + } else { + printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x " + "length = %i\n", ndev->name, data[3], skb->len); + dev_kfree_skb_any(skb); + return NET_RX_DROP; + } + + if (dev) { + struct net_device_stats *stats = pvc_get_stats(dev); + stats->rx_packets++; /* PVC traffic */ + stats->rx_bytes += skb->len; + if (pvc->state.becn) + stats->rx_compressed++; + skb->dev = dev; + netif_rx(skb); + return NET_RX_SUCCESS; + } else { + dev_kfree_skb_any(skb); + return NET_RX_DROP; + } + + rx_error: + hdlc->stats.rx_errors++; /* Mark error */ + dev_kfree_skb_any(skb); + return NET_RX_DROP; +} + + + +static void fr_start(struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); +#ifdef DEBUG_LINK + printk(KERN_DEBUG "fr_start\n"); +#endif + if (hdlc->state.fr.settings.lmi != LMI_NONE) { + hdlc->state.fr.reliable = 0; + hdlc->state.fr.dce_changed = 1; + hdlc->state.fr.request = 0; + hdlc->state.fr.fullrep_sent = 0; + hdlc->state.fr.last_errors = 0xFFFFFFFF; + hdlc->state.fr.n391cnt = 0; + hdlc->state.fr.txseq = hdlc->state.fr.rxseq = 0; + + init_timer(&hdlc->state.fr.timer); + /* First poll after 1 s */ + hdlc->state.fr.timer.expires = jiffies + HZ; + hdlc->state.fr.timer.function = fr_timer; + hdlc->state.fr.timer.data = (unsigned long)dev; + add_timer(&hdlc->state.fr.timer); + } else + fr_set_link_state(1, dev); +} + + + +static void fr_stop(struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); +#ifdef DEBUG_LINK + printk(KERN_DEBUG "fr_stop\n"); +#endif + if (hdlc->state.fr.settings.lmi != LMI_NONE) + del_timer_sync(&hdlc->state.fr.timer); + fr_set_link_state(0, dev); +} + + + +static void fr_close(struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + pvc_device *pvc = hdlc->state.fr.first_pvc; + + while (pvc) { /* Shutdown all PVCs for this FRAD */ + if (pvc->main) + dev_close(pvc->main); + if (pvc->ether) + dev_close(pvc->ether); + pvc = pvc->next; + } +} + +static void dlci_setup(struct net_device *dev) +{ + dev->type = ARPHRD_DLCI; + dev->flags = IFF_POINTOPOINT; + dev->hard_header_len = 10; + dev->addr_len = 2; +} + +static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type) +{ + hdlc_device *hdlc = dev_to_hdlc(master); + pvc_device *pvc = NULL; + struct net_device *dev; + int result, used; + char * prefix = "pvc%d"; + + if (type == ARPHRD_ETHER) + prefix = "pvceth%d"; + + if ((pvc = add_pvc(master, dlci)) == NULL) { + printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n", + master->name); + return -ENOBUFS; + } + + if (*get_dev_p(pvc, type)) + return -EEXIST; + + used = pvc_is_used(pvc); + + if (type == ARPHRD_ETHER) + dev = alloc_netdev(sizeof(struct net_device_stats), + "pvceth%d", ether_setup); + else + dev = alloc_netdev(sizeof(struct net_device_stats), + "pvc%d", dlci_setup); + + if (!dev) { + printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n", + master->name); + delete_unused_pvcs(hdlc); + return -ENOBUFS; + } + + if (type == ARPHRD_ETHER) { + memcpy(dev->dev_addr, "\x00\x01", 2); + get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2); + } else { + *(u16*)dev->dev_addr = htons(dlci); + dlci_to_q922(dev->broadcast, dlci); + } + dev->hard_start_xmit = pvc_xmit; + dev->get_stats = pvc_get_stats; + dev->open = pvc_open; + dev->stop = pvc_close; + dev->do_ioctl = pvc_ioctl; + dev->change_mtu = pvc_change_mtu; + dev->mtu = HDLC_MAX_MTU; + dev->tx_queue_len = 0; + dev->priv = pvc; + + result = dev_alloc_name(dev, dev->name); + if (result < 0) { + free_netdev(dev); + delete_unused_pvcs(hdlc); + return result; + } + + if (register_netdevice(dev) != 0) { + free_netdev(dev); + delete_unused_pvcs(hdlc); + return -EIO; + } + + dev->destructor = free_netdev; + *get_dev_p(pvc, type) = dev; + if (!used) { + hdlc->state.fr.dce_changed = 1; + hdlc->state.fr.dce_pvc_count++; + } + return 0; +} + + + +static int fr_del_pvc(hdlc_device *hdlc, unsigned int dlci, int type) +{ + pvc_device *pvc; + struct net_device *dev; + + if ((pvc = find_pvc(hdlc, dlci)) == NULL) + return -ENOENT; + + if ((dev = *get_dev_p(pvc, type)) == NULL) + return -ENOENT; + + if (dev->flags & IFF_UP) + return -EBUSY; /* PVC in use */ + + unregister_netdevice(dev); /* the destructor will free_netdev(dev) */ + *get_dev_p(pvc, type) = NULL; + + if (!pvc_is_used(pvc)) { + hdlc->state.fr.dce_pvc_count--; + hdlc->state.fr.dce_changed = 1; + } + delete_unused_pvcs(hdlc); + return 0; +} + + + +static void fr_destroy(hdlc_device *hdlc) +{ + pvc_device *pvc; + + pvc = hdlc->state.fr.first_pvc; + hdlc->state.fr.first_pvc = NULL; /* All PVCs destroyed */ + hdlc->state.fr.dce_pvc_count = 0; + hdlc->state.fr.dce_changed = 1; + + while (pvc) { + pvc_device *next = pvc->next; + /* destructors will free_netdev() main and ether */ + if (pvc->main) + unregister_netdevice(pvc->main); + + if (pvc->ether) + unregister_netdevice(pvc->ether); + + kfree(pvc); + pvc = next; + } +} + + + +int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr) +{ + fr_proto __user *fr_s = ifr->ifr_settings.ifs_ifsu.fr; + const size_t size = sizeof(fr_proto); + fr_proto new_settings; + hdlc_device *hdlc = dev_to_hdlc(dev); + fr_proto_pvc pvc; + int result; + + switch (ifr->ifr_settings.type) { + case IF_GET_PROTO: + ifr->ifr_settings.type = IF_PROTO_FR; + if (ifr->ifr_settings.size < size) { + ifr->ifr_settings.size = size; /* data size wanted */ + return -ENOBUFS; + } + if (copy_to_user(fr_s, &hdlc->state.fr.settings, size)) + return -EFAULT; + return 0; + + case IF_PROTO_FR: + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + + if(dev->flags & IFF_UP) + return -EBUSY; + + if (copy_from_user(&new_settings, fr_s, size)) + return -EFAULT; + + if (new_settings.lmi == LMI_DEFAULT) + new_settings.lmi = LMI_ANSI; + + if ((new_settings.lmi != LMI_NONE && + new_settings.lmi != LMI_ANSI && + new_settings.lmi != LMI_CCITT && + new_settings.lmi != LMI_CISCO) || + new_settings.t391 < 1 || + new_settings.t392 < 2 || + new_settings.n391 < 1 || + new_settings.n392 < 1 || + new_settings.n393 < new_settings.n392 || + new_settings.n393 > 32 || + (new_settings.dce != 0 && + new_settings.dce != 1)) + return -EINVAL; + + result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); + if (result) + return result; + + if (hdlc->proto.id != IF_PROTO_FR) { + hdlc_proto_detach(hdlc); + hdlc->state.fr.first_pvc = NULL; + hdlc->state.fr.dce_pvc_count = 0; + } + memcpy(&hdlc->state.fr.settings, &new_settings, size); + memset(&hdlc->proto, 0, sizeof(hdlc->proto)); + + hdlc->proto.close = fr_close; + hdlc->proto.start = fr_start; + hdlc->proto.stop = fr_stop; + hdlc->proto.detach = fr_destroy; + hdlc->proto.netif_rx = fr_rx; + hdlc->proto.id = IF_PROTO_FR; + dev->hard_start_xmit = hdlc->xmit; + dev->hard_header = NULL; + dev->type = ARPHRD_FRAD; + dev->flags = IFF_POINTOPOINT | IFF_NOARP; + dev->addr_len = 0; + return 0; + + case IF_PROTO_FR_ADD_PVC: + case IF_PROTO_FR_DEL_PVC: + case IF_PROTO_FR_ADD_ETH_PVC: + case IF_PROTO_FR_DEL_ETH_PVC: + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (copy_from_user(&pvc, ifr->ifr_settings.ifs_ifsu.fr_pvc, + sizeof(fr_proto_pvc))) + return -EFAULT; + + if (pvc.dlci <= 0 || pvc.dlci >= 1024) + return -EINVAL; /* Only 10 bits, DLCI 0 reserved */ + + if (ifr->ifr_settings.type == IF_PROTO_FR_ADD_ETH_PVC || + ifr->ifr_settings.type == IF_PROTO_FR_DEL_ETH_PVC) + result = ARPHRD_ETHER; /* bridged Ethernet device */ + else + result = ARPHRD_DLCI; + + if (ifr->ifr_settings.type == IF_PROTO_FR_ADD_PVC || + ifr->ifr_settings.type == IF_PROTO_FR_ADD_ETH_PVC) + return fr_add_pvc(dev, pvc.dlci, result); + else + return fr_del_pvc(hdlc, pvc.dlci, result); + } + + return -EINVAL; +} diff --git a/kernel/datamods/hdlc_generic.c b/kernel/datamods/hdlc_generic.c new file mode 100644 index 0000000..46cef8f --- /dev/null +++ b/kernel/datamods/hdlc_generic.c @@ -0,0 +1,355 @@ +/* + * Generic HDLC support routines for Linux + * + * Copyright (C) 1999 - 2005 Krzysztof Halasa + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * Currently supported: + * * raw IP-in-HDLC + * * Cisco HDLC + * * Frame Relay with ANSI or CCITT LMI (both user and network side) + * * PPP + * * X.25 + * + * Use sethdlc utility to set line parameters, protocol and PVCs + * + * How does it work: + * - proto.open(), close(), start(), stop() calls are serialized. + * The order is: open, [ start, stop ... ] close ... + * - proto.start() and stop() are called with spin_lock_irq held. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static const char* version = "HDLC support module revision 1.18"; + +#undef DEBUG_LINK + + +static int hdlc_change_mtu(struct net_device *dev, int new_mtu) +{ + if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU)) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + + + +static struct net_device_stats *hdlc_get_stats(struct net_device *dev) +{ + return hdlc_stats(dev); +} + + + +static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *p, struct net_device *orig_dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + if (hdlc->proto.netif_rx) + return hdlc->proto.netif_rx(skb); + + hdlc->stats.rx_dropped++; /* Shouldn't happen */ + dev_kfree_skb(skb); + return NET_RX_DROP; +} + + + +static void __hdlc_set_carrier_on(struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + if (hdlc->proto.start) + return hdlc->proto.start(dev); +#if 0 +#ifdef DEBUG_LINK + if (netif_carrier_ok(dev)) + printk(KERN_ERR "hdlc_set_carrier_on(): already on\n"); +#endif + netif_carrier_on(dev); +#endif +} + + + +static void __hdlc_set_carrier_off(struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + if (hdlc->proto.stop) + return hdlc->proto.stop(dev); + +#if 0 +#ifdef DEBUG_LINK + if (!netif_carrier_ok(dev)) + printk(KERN_ERR "hdlc_set_carrier_off(): already off\n"); +#endif + netif_carrier_off(dev); +#endif +} + + + +void hdlc_set_carrier(int on, struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + unsigned long flags; + on = on ? 1 : 0; + +#ifdef DEBUG_LINK + printk(KERN_DEBUG "hdlc_set_carrier %i\n", on); +#endif + + spin_lock_irqsave(&hdlc->state_lock, flags); + + if (hdlc->carrier == on) + goto carrier_exit; /* no change in DCD line level */ + +#ifdef DEBUG_LINK + printk(KERN_INFO "%s: carrier %s\n", dev->name, on ? "ON" : "off"); +#endif + hdlc->carrier = on; + + if (!hdlc->open) + goto carrier_exit; + + if (hdlc->carrier) { + printk(KERN_INFO "%s: Carrier detected\n", dev->name); + __hdlc_set_carrier_on(dev); + } else { + printk(KERN_INFO "%s: Carrier lost\n", dev->name); + __hdlc_set_carrier_off(dev); + } + +carrier_exit: + spin_unlock_irqrestore(&hdlc->state_lock, flags); +} + + + +/* Must be called by hardware driver when HDLC device is being opened */ +int hdlc_open(struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); +#ifdef DEBUG_LINK + printk(KERN_DEBUG "hdlc_open() carrier %i open %i\n", + hdlc->carrier, hdlc->open); +#endif + + if (hdlc->proto.id == -1) + return -ENOSYS; /* no protocol attached */ + + if (hdlc->proto.open) { + int result = hdlc->proto.open(dev); + if (result) + return result; + } + + spin_lock_irq(&hdlc->state_lock); + + if (hdlc->carrier) { + printk(KERN_INFO "%s: Carrier detected\n", dev->name); + __hdlc_set_carrier_on(dev); + } else + printk(KERN_INFO "%s: No carrier\n", dev->name); + + hdlc->open = 1; + + spin_unlock_irq(&hdlc->state_lock); + return 0; +} + + + +/* Must be called by hardware driver when HDLC device is being closed */ +void hdlc_close(struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); +#ifdef DEBUG_LINK + printk(KERN_DEBUG "hdlc_close() carrier %i open %i\n", + hdlc->carrier, hdlc->open); +#endif + + spin_lock_irq(&hdlc->state_lock); + + hdlc->open = 0; + if (hdlc->carrier) + __hdlc_set_carrier_off(dev); + + spin_unlock_irq(&hdlc->state_lock); + + if (hdlc->proto.close) + hdlc->proto.close(dev); +} + + + +#ifndef CONFIG_HDLC_RAW +#define hdlc_raw_ioctl(dev, ifr) -ENOSYS +#endif + +#ifndef CONFIG_HDLC_RAW_ETH +#define hdlc_raw_eth_ioctl(dev, ifr) -ENOSYS +#endif + +#ifndef CONFIG_HDLC_PPP +#define hdlc_ppp_ioctl(dev, ifr) -ENOSYS +#endif + +#ifndef CONFIG_HDLC_CISCO +#define hdlc_cisco_ioctl(dev, ifr) -ENOSYS +#endif + +#ifndef CONFIG_HDLC_FR +#define hdlc_fr_ioctl(dev, ifr) -ENOSYS +#endif + +#ifndef CONFIG_HDLC_X25 +#define hdlc_x25_ioctl(dev, ifr) -ENOSYS +#endif + + +int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + unsigned int proto; + + if (cmd != SIOCWANDEV) + return -EINVAL; + + switch(ifr->ifr_settings.type) { + case IF_PROTO_HDLC: + case IF_PROTO_HDLC_ETH: + case IF_PROTO_PPP: + case IF_PROTO_CISCO: + case IF_PROTO_FR: + case IF_PROTO_X25: + proto = ifr->ifr_settings.type; + break; + + default: + proto = hdlc->proto.id; + } + + switch(proto) { + case IF_PROTO_HDLC: return hdlc_raw_ioctl(dev, ifr); + case IF_PROTO_HDLC_ETH: return hdlc_raw_eth_ioctl(dev, ifr); + case IF_PROTO_PPP: return hdlc_ppp_ioctl(dev, ifr); + case IF_PROTO_CISCO: return hdlc_cisco_ioctl(dev, ifr); + case IF_PROTO_FR: return hdlc_fr_ioctl(dev, ifr); + case IF_PROTO_X25: return hdlc_x25_ioctl(dev, ifr); + default: return -EINVAL; + } +} + +static void hdlc_setup(struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + + dev->get_stats = hdlc_get_stats; + dev->change_mtu = hdlc_change_mtu; + dev->mtu = HDLC_MAX_MTU; + + dev->type = ARPHRD_RAWHDLC; + dev->hard_header_len = 16; + + dev->flags = IFF_POINTOPOINT | IFF_NOARP; + + hdlc->proto.id = -1; + hdlc->proto.detach = NULL; + hdlc->carrier = 1; + hdlc->open = 0; + spin_lock_init(&hdlc->state_lock); +} + +struct net_device *alloc_hdlcdev(void *priv) +{ + struct net_device *dev; + dev = alloc_netdev(sizeof(hdlc_device), "hdlc%d", hdlc_setup); + if (dev) + dev_to_hdlc(dev)->priv = priv; + return dev; +} + +int register_hdlc_device(struct net_device *dev) +{ + int result = dev_alloc_name(dev, "hdlc%d"); + if (result < 0) + return result; + + result = register_netdev(dev); + if (result != 0) + return -EIO; + +#if 0 + if (netif_carrier_ok(dev)) + netif_carrier_off(dev); /* no carrier until DCD goes up */ +#endif + + return 0; +} + + + +void unregister_hdlc_device(struct net_device *dev) +{ + rtnl_lock(); + hdlc_proto_detach(dev_to_hdlc(dev)); + unregister_netdevice(dev); + rtnl_unlock(); +} + + + +MODULE_AUTHOR("Krzysztof Halasa "); +MODULE_DESCRIPTION("HDLC support module"); +MODULE_LICENSE("GPL v2"); + +EXPORT_SYMBOL(hdlc_open); +EXPORT_SYMBOL(hdlc_close); +EXPORT_SYMBOL(hdlc_set_carrier); +EXPORT_SYMBOL(hdlc_ioctl); +EXPORT_SYMBOL(alloc_hdlcdev); +EXPORT_SYMBOL(register_hdlc_device); +EXPORT_SYMBOL(unregister_hdlc_device); + +static struct packet_type hdlc_packet_type = { + .type = __constant_htons(ETH_P_HDLC), + .func = hdlc_rcv, +}; + + +static int __init hdlc_module_init(void) +{ + printk(KERN_INFO "%s\n", version); + dev_add_pack(&hdlc_packet_type); + return 0; +} + + + +static void __exit hdlc_module_exit(void) +{ + dev_remove_pack(&hdlc_packet_type); +} + + +module_init(hdlc_module_init); +module_exit(hdlc_module_exit); diff --git a/kernel/datamods/hdlc_ppp.c b/kernel/datamods/hdlc_ppp.c new file mode 100644 index 0000000..b81263e --- /dev/null +++ b/kernel/datamods/hdlc_ppp.c @@ -0,0 +1,114 @@ +/* + * Generic HDLC support routines for Linux + * Point-to-point protocol support + * + * Copyright (C) 1999 - 2003 Krzysztof Halasa + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static int ppp_open(struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + void *old_ioctl; + int result; + + dev->priv = &hdlc->state.ppp.syncppp_ptr; + hdlc->state.ppp.syncppp_ptr = &hdlc->state.ppp.pppdev; + hdlc->state.ppp.pppdev.dev = dev; + + old_ioctl = dev->do_ioctl; + hdlc->state.ppp.old_change_mtu = dev->change_mtu; + sppp_attach(&hdlc->state.ppp.pppdev); + /* sppp_attach nukes them. We don't need syncppp's ioctl */ + dev->do_ioctl = old_ioctl; + hdlc->state.ppp.pppdev.sppp.pp_flags &= ~PP_CISCO; + dev->type = ARPHRD_PPP; + result = sppp_open(dev); + if (result) { + sppp_detach(dev); + return result; + } + + return 0; +} + + + +static void ppp_close(struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + + sppp_close(dev); + sppp_detach(dev); + dev->rebuild_header = NULL; + dev->change_mtu = hdlc->state.ppp.old_change_mtu; + dev->mtu = HDLC_MAX_MTU; + dev->hard_header_len = 16; +} + + + +static __be16 ppp_type_trans(struct sk_buff *skb, struct net_device *dev) +{ + return __constant_htons(ETH_P_WAN_PPP); +} + + + +int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + int result; + + switch (ifr->ifr_settings.type) { + case IF_GET_PROTO: + ifr->ifr_settings.type = IF_PROTO_PPP; + return 0; /* return protocol only, no settable parameters */ + + case IF_PROTO_PPP: + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + + if(dev->flags & IFF_UP) + return -EBUSY; + + /* no settable parameters */ + + result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); + if (result) + return result; + + hdlc_proto_detach(hdlc); + memset(&hdlc->proto, 0, sizeof(hdlc->proto)); + + hdlc->proto.open = ppp_open; + hdlc->proto.close = ppp_close; + hdlc->proto.type_trans = ppp_type_trans; + hdlc->proto.id = IF_PROTO_PPP; + dev->hard_start_xmit = hdlc->xmit; + dev->hard_header = NULL; + dev->type = ARPHRD_PPP; + dev->addr_len = 0; + return 0; + } + + return -EINVAL; +} diff --git a/kernel/datamods/hdlc_raw.c b/kernel/datamods/hdlc_raw.c new file mode 100644 index 0000000..9456d31 --- /dev/null +++ b/kernel/datamods/hdlc_raw.c @@ -0,0 +1,89 @@ +/* + * Generic HDLC support routines for Linux + * HDLC support + * + * Copyright (C) 1999 - 2003 Krzysztof Halasa + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev) +{ + return __constant_htons(ETH_P_IP); +} + + + +int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr) +{ + raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; + const size_t size = sizeof(raw_hdlc_proto); + raw_hdlc_proto new_settings; + hdlc_device *hdlc = dev_to_hdlc(dev); + int result; + + switch (ifr->ifr_settings.type) { + case IF_GET_PROTO: + ifr->ifr_settings.type = IF_PROTO_HDLC; + if (ifr->ifr_settings.size < size) { + ifr->ifr_settings.size = size; /* data size wanted */ + return -ENOBUFS; + } + if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size)) + return -EFAULT; + return 0; + + case IF_PROTO_HDLC: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (dev->flags & IFF_UP) + return -EBUSY; + + if (copy_from_user(&new_settings, raw_s, size)) + return -EFAULT; + + if (new_settings.encoding == ENCODING_DEFAULT) + new_settings.encoding = ENCODING_NRZ; + + if (new_settings.parity == PARITY_DEFAULT) + new_settings.parity = PARITY_CRC16_PR1_CCITT; + + result = hdlc->attach(dev, new_settings.encoding, + new_settings.parity); + if (result) + return result; + + hdlc_proto_detach(hdlc); + memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size); + memset(&hdlc->proto, 0, sizeof(hdlc->proto)); + + hdlc->proto.type_trans = raw_type_trans; + hdlc->proto.id = IF_PROTO_HDLC; + dev->hard_start_xmit = hdlc->xmit; + dev->hard_header = NULL; + dev->type = ARPHRD_RAWHDLC; + dev->flags = IFF_POINTOPOINT | IFF_NOARP; + dev->addr_len = 0; + return 0; + } + + return -EINVAL; +} diff --git a/kernel/datamods/hdlc_raw_eth.c b/kernel/datamods/hdlc_raw_eth.c new file mode 100644 index 0000000..b1285cc --- /dev/null +++ b/kernel/datamods/hdlc_raw_eth.c @@ -0,0 +1,107 @@ +/* + * Generic HDLC support routines for Linux + * HDLC Ethernet emulation support + * + * Copyright (C) 2002-2003 Krzysztof Halasa + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static int eth_tx(struct sk_buff *skb, struct net_device *dev) +{ + int pad = ETH_ZLEN - skb->len; + if (pad > 0) { /* Pad the frame with zeros */ + int len = skb->len; + if (skb_tailroom(skb) < pad) + if (pskb_expand_head(skb, 0, pad, GFP_ATOMIC)) { + hdlc_stats(dev)->tx_dropped++; + dev_kfree_skb(skb); + return 0; + } + skb_put(skb, pad); + memset(skb->data + len, 0, pad); + } + return dev_to_hdlc(dev)->xmit(skb, dev); +} + + +int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) +{ + raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; + const size_t size = sizeof(raw_hdlc_proto); + raw_hdlc_proto new_settings; + hdlc_device *hdlc = dev_to_hdlc(dev); + int result; + void *old_ch_mtu; + int old_qlen; + + switch (ifr->ifr_settings.type) { + case IF_GET_PROTO: + ifr->ifr_settings.type = IF_PROTO_HDLC_ETH; + if (ifr->ifr_settings.size < size) { + ifr->ifr_settings.size = size; /* data size wanted */ + return -ENOBUFS; + } + if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size)) + return -EFAULT; + return 0; + + case IF_PROTO_HDLC_ETH: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (dev->flags & IFF_UP) + return -EBUSY; + + if (copy_from_user(&new_settings, raw_s, size)) + return -EFAULT; + + if (new_settings.encoding == ENCODING_DEFAULT) + new_settings.encoding = ENCODING_NRZ; + + if (new_settings.parity == PARITY_DEFAULT) + new_settings.parity = PARITY_CRC16_PR1_CCITT; + + result = hdlc->attach(dev, new_settings.encoding, + new_settings.parity); + if (result) + return result; + + hdlc_proto_detach(hdlc); + memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size); + memset(&hdlc->proto, 0, sizeof(hdlc->proto)); + + hdlc->proto.type_trans = eth_type_trans; + hdlc->proto.id = IF_PROTO_HDLC_ETH; + dev->hard_start_xmit = eth_tx; + old_ch_mtu = dev->change_mtu; + old_qlen = dev->tx_queue_len; + ether_setup(dev); + dev->change_mtu = old_ch_mtu; + dev->tx_queue_len = old_qlen; + memcpy(dev->dev_addr, "\x00\x01", 2); + get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2); + return 0; + } + + return -EINVAL; +} diff --git a/kernel/datamods/syncppp.c b/kernel/datamods/syncppp.c new file mode 100644 index 0000000..5ca283a --- /dev/null +++ b/kernel/datamods/syncppp.c @@ -0,0 +1,1485 @@ +/* + * NET3: A (fairly minimal) implementation of synchronous PPP for Linux + * as well as a CISCO HDLC implementation. See the copyright + * message below for the original source. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the license, or (at your option) any later version. + * + * Note however. This code is also used in a different form by FreeBSD. + * Therefore when making any non OS specific change please consider + * contributing it back to the original author under the terms + * below in addition. + * -- Alan + * + * Port for Linux-2.1 by Jan "Yenya" Kasprzak + */ + +/* + * Synchronous PPP/Cisco link level subroutines. + * Keepalive protocol implemented in both Cisco and PPP modes. + * + * Copyright (C) 1994 Cronyx Ltd. + * Author: Serge Vakulenko, + * + * This software is distributed with NO WARRANTIES, not even the implied + * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Authors grant any other persons or organisations permission to use + * or modify this software as long as this message is kept with the software, + * all derivative works or modified versions. + * + * Version 1.9, Wed Oct 4 18:58:15 MSK 1995 + * + * $Id$ + */ +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#define MAXALIVECNT 6 /* max. alive packets */ + +#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ +#define PPP_UI 0x03 /* Unnumbered Information */ +#define PPP_IP 0x0021 /* Internet Protocol */ +#define PPP_ISO 0x0023 /* ISO OSI Protocol */ +#define PPP_XNS 0x0025 /* Xerox NS Protocol */ +#define PPP_IPX 0x002b /* Novell IPX Protocol */ +#define PPP_LCP 0xc021 /* Link Control Protocol */ +#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */ + +#define LCP_CONF_REQ 1 /* PPP LCP configure request */ +#define LCP_CONF_ACK 2 /* PPP LCP configure acknowledge */ +#define LCP_CONF_NAK 3 /* PPP LCP configure negative ack */ +#define LCP_CONF_REJ 4 /* PPP LCP configure reject */ +#define LCP_TERM_REQ 5 /* PPP LCP terminate request */ +#define LCP_TERM_ACK 6 /* PPP LCP terminate acknowledge */ +#define LCP_CODE_REJ 7 /* PPP LCP code reject */ +#define LCP_PROTO_REJ 8 /* PPP LCP protocol reject */ +#define LCP_ECHO_REQ 9 /* PPP LCP echo request */ +#define LCP_ECHO_REPLY 10 /* PPP LCP echo reply */ +#define LCP_DISC_REQ 11 /* PPP LCP discard request */ + +#define LCP_OPT_MRU 1 /* maximum receive unit */ +#define LCP_OPT_ASYNC_MAP 2 /* async control character map */ +#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */ +#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */ +#define LCP_OPT_MAGIC 5 /* magic number */ +#define LCP_OPT_RESERVED 6 /* reserved */ +#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */ +#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */ + +#define IPCP_CONF_REQ LCP_CONF_REQ /* PPP IPCP configure request */ +#define IPCP_CONF_ACK LCP_CONF_ACK /* PPP IPCP configure acknowledge */ +#define IPCP_CONF_NAK LCP_CONF_NAK /* PPP IPCP configure negative ack */ +#define IPCP_CONF_REJ LCP_CONF_REJ /* PPP IPCP configure reject */ +#define IPCP_TERM_REQ LCP_TERM_REQ /* PPP IPCP terminate request */ +#define IPCP_TERM_ACK LCP_TERM_ACK /* PPP IPCP terminate acknowledge */ +#define IPCP_CODE_REJ LCP_CODE_REJ /* PPP IPCP code reject */ + +#define CISCO_MULTICAST 0x8f /* Cisco multicast address */ +#define CISCO_UNICAST 0x0f /* Cisco unicast address */ +#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ +#define CISCO_ADDR_REQ 0 /* Cisco address request */ +#define CISCO_ADDR_REPLY 1 /* Cisco address reply */ +#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */ + +struct ppp_header { + u8 address; + u8 control; + u16 protocol; +}; +#define PPP_HEADER_LEN sizeof (struct ppp_header) + +struct lcp_header { + u8 type; + u8 ident; + u16 len; +}; +#define LCP_HEADER_LEN sizeof (struct lcp_header) + +struct cisco_packet { + u32 type; + u32 par1; + u32 par2; + u16 rel; + u16 time0; + u16 time1; +}; +#define CISCO_PACKET_LEN 18 +#define CISCO_BIG_PACKET_LEN 20 + +static struct sppp *spppq; +static struct timer_list sppp_keepalive_timer; +static DEFINE_SPINLOCK(spppq_lock); + +/* global xmit queue for sending packets while spinlock is held */ +static struct sk_buff_head tx_queue; + +static void sppp_keepalive (unsigned long dummy); +static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type, + u8 ident, u16 len, void *data); +static void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2); +static void sppp_lcp_input (struct sppp *sp, struct sk_buff *m); +static void sppp_cisco_input (struct sppp *sp, struct sk_buff *m); +static void sppp_ipcp_input (struct sppp *sp, struct sk_buff *m); +static void sppp_lcp_open (struct sppp *sp); +static void sppp_ipcp_open (struct sppp *sp); +static int sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h, + int len, u32 *magic); +static void sppp_cp_timeout (unsigned long arg); +static char *sppp_lcp_type_name (u8 type); +static char *sppp_ipcp_type_name (u8 type); +static void sppp_print_bytes (u8 *p, u16 len); + +static int debug; + +/* Flush global outgoing packet queue to dev_queue_xmit(). + * + * dev_queue_xmit() must be called with interrupts enabled + * which means it can't be called with spinlocks held. + * If a packet needs to be sent while a spinlock is held, + * then put the packet into tx_queue, and call sppp_flush_xmit() + * after spinlock is released. + */ +static void sppp_flush_xmit(void) +{ + struct sk_buff *skb; + while ((skb = skb_dequeue(&tx_queue)) != NULL) + dev_queue_xmit(skb); +} + +/* + * Interface down stub + */ + +static void if_down(struct net_device *dev) +{ + struct sppp *sp = (struct sppp *)sppp_of(dev); + + sp->pp_link_state=SPPP_LINK_DOWN; +} + +/* + * Timeout routine activations. + */ + +static void sppp_set_timeout(struct sppp *p,int s) +{ + if (! (p->pp_flags & PP_TIMO)) + { + init_timer(&p->pp_timer); + p->pp_timer.function=sppp_cp_timeout; + p->pp_timer.expires=jiffies+s*HZ; + p->pp_timer.data=(unsigned long)p; + p->pp_flags |= PP_TIMO; + add_timer(&p->pp_timer); + } +} + +static void sppp_clear_timeout(struct sppp *p) +{ + if (p->pp_flags & PP_TIMO) + { + del_timer(&p->pp_timer); + p->pp_flags &= ~PP_TIMO; + } +} + +/** + * sppp_input - receive and process a WAN PPP frame + * @skb: The buffer to process + * @dev: The device it arrived on + * + * This can be called directly by cards that do not have + * timing constraints but is normally called from the network layer + * after interrupt servicing to process frames queued via netif_rx(). + * + * We process the options in the card. If the frame is destined for + * the protocol stacks then it requeues the frame for the upper level + * protocol. If it is a control from it is processed and discarded + * here. + */ + +static void sppp_input (struct net_device *dev, struct sk_buff *skb) +{ + struct ppp_header *h; + struct sppp *sp = (struct sppp *)sppp_of(dev); + unsigned long flags; + + skb->dev=dev; + skb->mac.raw=skb->data; + + if (dev->flags & IFF_RUNNING) + { + /* Count received bytes, add FCS and one flag */ + sp->ibytes+= skb->len + 3; + sp->ipkts++; + } + + if (!pskb_may_pull(skb, PPP_HEADER_LEN)) { + /* Too small packet, drop it. */ + if (sp->pp_flags & PP_DEBUG) + printk (KERN_DEBUG "%s: input packet is too small, %d bytes\n", + dev->name, skb->len); + kfree_skb(skb); + return; + } + + /* Get PPP header. */ + h = (struct ppp_header *)skb->data; + skb_pull(skb,sizeof(struct ppp_header)); + + spin_lock_irqsave(&sp->lock, flags); + + switch (h->address) { + default: /* Invalid PPP packet. */ + goto invalid; + case PPP_ALLSTATIONS: + if (h->control != PPP_UI) + goto invalid; + if (sp->pp_flags & PP_CISCO) { + if (sp->pp_flags & PP_DEBUG) + printk (KERN_WARNING "%s: PPP packet in Cisco mode <0x%x 0x%x 0x%x>\n", + dev->name, + h->address, h->control, ntohs (h->protocol)); + goto drop; + } + switch (ntohs (h->protocol)) { + default: + if (sp->lcp.state == LCP_STATE_OPENED) + sppp_cp_send (sp, PPP_LCP, LCP_PROTO_REJ, + ++sp->pp_seq, skb->len + 2, + &h->protocol); + if (sp->pp_flags & PP_DEBUG) + printk (KERN_WARNING "%s: invalid input protocol <0x%x 0x%x 0x%x>\n", + dev->name, + h->address, h->control, ntohs (h->protocol)); + goto drop; + case PPP_LCP: + sppp_lcp_input (sp, skb); + goto drop; + case PPP_IPCP: + if (sp->lcp.state == LCP_STATE_OPENED) + sppp_ipcp_input (sp, skb); + else + printk(KERN_DEBUG "IPCP when still waiting LCP finish.\n"); + goto drop; + case PPP_IP: + if (sp->ipcp.state == IPCP_STATE_OPENED) { + if(sp->pp_flags&PP_DEBUG) + printk(KERN_DEBUG "Yow an IP frame.\n"); + skb->protocol=htons(ETH_P_IP); + netif_rx(skb); + dev->last_rx = jiffies; + goto done; + } + break; +#ifdef IPX + case PPP_IPX: + /* IPX IPXCP not implemented yet */ + if (sp->lcp.state == LCP_STATE_OPENED) { + skb->protocol=htons(ETH_P_IPX); + netif_rx(skb); + dev->last_rx = jiffies; + goto done; + } + break; +#endif + } + break; + case CISCO_MULTICAST: + case CISCO_UNICAST: + /* Don't check the control field here (RFC 1547). */ + if (! (sp->pp_flags & PP_CISCO)) { + if (sp->pp_flags & PP_DEBUG) + printk (KERN_WARNING "%s: Cisco packet in PPP mode <0x%x 0x%x 0x%x>\n", + dev->name, + h->address, h->control, ntohs (h->protocol)); + goto drop; + } + switch (ntohs (h->protocol)) { + default: + goto invalid; + case CISCO_KEEPALIVE: + sppp_cisco_input (sp, skb); + goto drop; +#ifdef CONFIG_INET + case ETH_P_IP: + skb->protocol=htons(ETH_P_IP); + netif_rx(skb); + dev->last_rx = jiffies; + goto done; +#endif +#ifdef CONFIG_IPX + case ETH_P_IPX: + skb->protocol=htons(ETH_P_IPX); + netif_rx(skb); + dev->last_rx = jiffies; + goto done; +#endif + } + break; + } + goto drop; + +invalid: + if (sp->pp_flags & PP_DEBUG) + printk (KERN_WARNING "%s: invalid input packet <0x%x 0x%x 0x%x>\n", + dev->name, h->address, h->control, ntohs (h->protocol)); +drop: + kfree_skb(skb); +done: + spin_unlock_irqrestore(&sp->lock, flags); + sppp_flush_xmit(); + return; +} + +/* + * Handle transmit packets. + */ + +static int sppp_hard_header(struct sk_buff *skb, struct net_device *dev, __u16 type, + void *daddr, void *saddr, unsigned int len) +{ + struct sppp *sp = (struct sppp *)sppp_of(dev); + struct ppp_header *h; + skb_push(skb,sizeof(struct ppp_header)); + h=(struct ppp_header *)skb->data; + if(sp->pp_flags&PP_CISCO) + { + h->address = CISCO_UNICAST; + h->control = 0; + } + else + { + h->address = PPP_ALLSTATIONS; + h->control = PPP_UI; + } + if(sp->pp_flags & PP_CISCO) + { + h->protocol = htons(type); + } + else switch(type) + { + case ETH_P_IP: + h->protocol = htons(PPP_IP); + break; + case ETH_P_IPX: + h->protocol = htons(PPP_IPX); + break; + } + return sizeof(struct ppp_header); +} + +static int sppp_rebuild_header(struct sk_buff *skb) +{ + return 0; +} + +/* + * Send keepalive packets, every 10 seconds. + */ + +static void sppp_keepalive (unsigned long dummy) +{ + struct sppp *sp; + unsigned long flags; + + spin_lock_irqsave(&spppq_lock, flags); + + for (sp=spppq; sp; sp=sp->pp_next) + { + struct net_device *dev = sp->pp_if; + + /* Keepalive mode disabled or channel down? */ + if (! (sp->pp_flags & PP_KEEPALIVE) || + ! (dev->flags & IFF_UP)) + continue; + + spin_lock(&sp->lock); + + /* No keepalive in PPP mode if LCP not opened yet. */ + if (! (sp->pp_flags & PP_CISCO) && + sp->lcp.state != LCP_STATE_OPENED) { + spin_unlock(&sp->lock); + continue; + } + + if (sp->pp_alivecnt == MAXALIVECNT) { + /* No keepalive packets got. Stop the interface. */ + printk (KERN_WARNING "%s: protocol down\n", dev->name); + if_down (dev); + if (! (sp->pp_flags & PP_CISCO)) { + /* Shut down the PPP link. */ + sp->lcp.magic = jiffies; + sp->lcp.state = LCP_STATE_CLOSED; + sp->ipcp.state = IPCP_STATE_CLOSED; + sppp_clear_timeout (sp); + /* Initiate negotiation. */ + sppp_lcp_open (sp); + } + } + if (sp->pp_alivecnt <= MAXALIVECNT) + ++sp->pp_alivecnt; + if (sp->pp_flags & PP_CISCO) + sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq, + sp->pp_rseq); + else if (sp->lcp.state == LCP_STATE_OPENED) { + long nmagic = htonl (sp->lcp.magic); + sp->lcp.echoid = ++sp->pp_seq; + sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REQ, + sp->lcp.echoid, 4, &nmagic); + } + + spin_unlock(&sp->lock); + } + spin_unlock_irqrestore(&spppq_lock, flags); + sppp_flush_xmit(); + sppp_keepalive_timer.expires=jiffies+10*HZ; + add_timer(&sppp_keepalive_timer); +} + +/* + * Handle incoming PPP Link Control Protocol packets. + */ + +static void sppp_lcp_input (struct sppp *sp, struct sk_buff *skb) +{ + struct lcp_header *h; + struct net_device *dev = sp->pp_if; + int len = skb->len; + u8 *p, opt[6]; + u32 rmagic; + + if (!pskb_may_pull(skb, sizeof(struct lcp_header))) { + if (sp->pp_flags & PP_DEBUG) + printk (KERN_WARNING "%s: invalid lcp packet length: %d bytes\n", + dev->name, len); + return; + } + h = (struct lcp_header *)skb->data; + skb_pull(skb,sizeof(struct lcp_header *)); + + if (sp->pp_flags & PP_DEBUG) + { + char state = '?'; + switch (sp->lcp.state) { + case LCP_STATE_CLOSED: state = 'C'; break; + case LCP_STATE_ACK_RCVD: state = 'R'; break; + case LCP_STATE_ACK_SENT: state = 'S'; break; + case LCP_STATE_OPENED: state = 'O'; break; + } + printk (KERN_WARNING "%s: lcp input(%c): %d bytes <%s id=%xh len=%xh", + dev->name, state, len, + sppp_lcp_type_name (h->type), h->ident, ntohs (h->len)); + if (len > 4) + sppp_print_bytes ((u8*) (h+1), len-4); + printk (">\n"); + } + if (len > ntohs (h->len)) + len = ntohs (h->len); + switch (h->type) { + default: + /* Unknown packet type -- send Code-Reject packet. */ + sppp_cp_send (sp, PPP_LCP, LCP_CODE_REJ, ++sp->pp_seq, + skb->len, h); + break; + case LCP_CONF_REQ: + if (len < 4) { + if (sp->pp_flags & PP_DEBUG) + printk (KERN_DEBUG"%s: invalid lcp configure request packet length: %d bytes\n", + dev->name, len); + break; + } + if (len>4 && !sppp_lcp_conf_parse_options (sp, h, len, &rmagic)) + goto badreq; + if (rmagic == sp->lcp.magic) { + /* Local and remote magics equal -- loopback? */ + if (sp->pp_loopcnt >= MAXALIVECNT*5) { + printk (KERN_WARNING "%s: loopback\n", + dev->name); + sp->pp_loopcnt = 0; + if (dev->flags & IFF_UP) { + if_down (dev); + } + } else if (sp->pp_flags & PP_DEBUG) + printk (KERN_DEBUG "%s: conf req: magic glitch\n", + dev->name); + ++sp->pp_loopcnt; + + /* MUST send Conf-Nack packet. */ + rmagic = ~sp->lcp.magic; + opt[0] = LCP_OPT_MAGIC; + opt[1] = sizeof (opt); + opt[2] = rmagic >> 24; + opt[3] = rmagic >> 16; + opt[4] = rmagic >> 8; + opt[5] = rmagic; + sppp_cp_send (sp, PPP_LCP, LCP_CONF_NAK, + h->ident, sizeof (opt), &opt); +badreq: + switch (sp->lcp.state) { + case LCP_STATE_OPENED: + /* Initiate renegotiation. */ + sppp_lcp_open (sp); + /* fall through... */ + case LCP_STATE_ACK_SENT: + /* Go to closed state. */ + sp->lcp.state = LCP_STATE_CLOSED; + sp->ipcp.state = IPCP_STATE_CLOSED; + } + break; + } + /* Send Configure-Ack packet. */ + sp->pp_loopcnt = 0; + if (sp->lcp.state != LCP_STATE_OPENED) { + sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK, + h->ident, len-4, h+1); + } + /* Change the state. */ + switch (sp->lcp.state) { + case LCP_STATE_CLOSED: + sp->lcp.state = LCP_STATE_ACK_SENT; + break; + case LCP_STATE_ACK_RCVD: + sp->lcp.state = LCP_STATE_OPENED; + sppp_ipcp_open (sp); + break; + case LCP_STATE_OPENED: + /* Remote magic changed -- close session. */ + sp->lcp.state = LCP_STATE_CLOSED; + sp->ipcp.state = IPCP_STATE_CLOSED; + /* Initiate renegotiation. */ + sppp_lcp_open (sp); + /* Send ACK after our REQ in attempt to break loop */ + sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK, + h->ident, len-4, h+1); + sp->lcp.state = LCP_STATE_ACK_SENT; + break; + } + break; + case LCP_CONF_ACK: + if (h->ident != sp->lcp.confid) + break; + sppp_clear_timeout (sp); + if ((sp->pp_link_state != SPPP_LINK_UP) && + (dev->flags & IFF_UP)) { + /* Coming out of loopback mode. */ + sp->pp_link_state=SPPP_LINK_UP; + printk (KERN_INFO "%s: protocol up\n", dev->name); + } + switch (sp->lcp.state) { + case LCP_STATE_CLOSED: + sp->lcp.state = LCP_STATE_ACK_RCVD; + sppp_set_timeout (sp, 5); + break; + case LCP_STATE_ACK_SENT: + sp->lcp.state = LCP_STATE_OPENED; + sppp_ipcp_open (sp); + break; + } + break; + case LCP_CONF_NAK: + if (h->ident != sp->lcp.confid) + break; + p = (u8*) (h+1); + if (len>=10 && p[0] == LCP_OPT_MAGIC && p[1] >= 4) { + rmagic = (u32)p[2] << 24 | + (u32)p[3] << 16 | p[4] << 8 | p[5]; + if (rmagic == ~sp->lcp.magic) { + int newmagic; + if (sp->pp_flags & PP_DEBUG) + printk (KERN_DEBUG "%s: conf nak: magic glitch\n", + dev->name); + get_random_bytes(&newmagic, sizeof(newmagic)); + sp->lcp.magic += newmagic; + } else + sp->lcp.magic = rmagic; + } + if (sp->lcp.state != LCP_STATE_ACK_SENT) { + /* Go to closed state. */ + sp->lcp.state = LCP_STATE_CLOSED; + sp->ipcp.state = IPCP_STATE_CLOSED; + } + /* The link will be renegotiated after timeout, + * to avoid endless req-nack loop. */ + sppp_clear_timeout (sp); + sppp_set_timeout (sp, 2); + break; + case LCP_CONF_REJ: + if (h->ident != sp->lcp.confid) + break; + sppp_clear_timeout (sp); + /* Initiate renegotiation. */ + sppp_lcp_open (sp); + if (sp->lcp.state != LCP_STATE_ACK_SENT) { + /* Go to closed state. */ + sp->lcp.state = LCP_STATE_CLOSED; + sp->ipcp.state = IPCP_STATE_CLOSED; + } + break; + case LCP_TERM_REQ: + sppp_clear_timeout (sp); + /* Send Terminate-Ack packet. */ + sppp_cp_send (sp, PPP_LCP, LCP_TERM_ACK, h->ident, 0, NULL); + /* Go to closed state. */ + sp->lcp.state = LCP_STATE_CLOSED; + sp->ipcp.state = IPCP_STATE_CLOSED; + /* Initiate renegotiation. */ + sppp_lcp_open (sp); + break; + case LCP_TERM_ACK: + case LCP_CODE_REJ: + case LCP_PROTO_REJ: + /* Ignore for now. */ + break; + case LCP_DISC_REQ: + /* Discard the packet. */ + break; + case LCP_ECHO_REQ: + if (sp->lcp.state != LCP_STATE_OPENED) + break; + if (len < 8) { + if (sp->pp_flags & PP_DEBUG) + printk (KERN_WARNING "%s: invalid lcp echo request packet length: %d bytes\n", + dev->name, len); + break; + } + if (ntohl (*(long*)(h+1)) == sp->lcp.magic) { + /* Line loopback mode detected. */ + printk (KERN_WARNING "%s: loopback\n", dev->name); + if_down (dev); + + /* Shut down the PPP link. */ + sp->lcp.state = LCP_STATE_CLOSED; + sp->ipcp.state = IPCP_STATE_CLOSED; + sppp_clear_timeout (sp); + /* Initiate negotiation. */ + sppp_lcp_open (sp); + break; + } + *(long*)(h+1) = htonl (sp->lcp.magic); + sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REPLY, h->ident, len-4, h+1); + break; + case LCP_ECHO_REPLY: + if (h->ident != sp->lcp.echoid) + break; + if (len < 8) { + if (sp->pp_flags & PP_DEBUG) + printk (KERN_WARNING "%s: invalid lcp echo reply packet length: %d bytes\n", + dev->name, len); + break; + } + if (ntohl (*(long*)(h+1)) != sp->lcp.magic) + sp->pp_alivecnt = 0; + break; + } +} + +/* + * Handle incoming Cisco keepalive protocol packets. + */ + +static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) +{ + struct cisco_packet *h; + struct net_device *dev = sp->pp_if; + + if (!pskb_may_pull(skb, sizeof(struct cisco_packet)) + || (skb->len != CISCO_PACKET_LEN + && skb->len != CISCO_BIG_PACKET_LEN)) { + if (sp->pp_flags & PP_DEBUG) + printk (KERN_WARNING "%s: invalid cisco packet length: %d bytes\n", + dev->name, skb->len); + return; + } + h = (struct cisco_packet *)skb->data; + skb_pull(skb, sizeof(struct cisco_packet*)); + if (sp->pp_flags & PP_DEBUG) + printk (KERN_WARNING "%s: cisco input: %d bytes <%xh %xh %xh %xh %xh-%xh>\n", + dev->name, skb->len, + ntohl (h->type), h->par1, h->par2, h->rel, + h->time0, h->time1); + switch (ntohl (h->type)) { + default: + if (sp->pp_flags & PP_DEBUG) + printk (KERN_WARNING "%s: unknown cisco packet type: 0x%x\n", + dev->name, ntohl (h->type)); + break; + case CISCO_ADDR_REPLY: + /* Reply on address request, ignore */ + break; + case CISCO_KEEPALIVE_REQ: + sp->pp_alivecnt = 0; + sp->pp_rseq = ntohl (h->par1); + if (sp->pp_seq == sp->pp_rseq) { + /* Local and remote sequence numbers are equal. + * Probably, the line is in loopback mode. */ + int newseq; + if (sp->pp_loopcnt >= MAXALIVECNT) { + printk (KERN_WARNING "%s: loopback\n", + dev->name); + sp->pp_loopcnt = 0; + if (dev->flags & IFF_UP) { + if_down (dev); + } + } + ++sp->pp_loopcnt; + + /* Generate new local sequence number */ + get_random_bytes(&newseq, sizeof(newseq)); + sp->pp_seq ^= newseq; + break; + } + sp->pp_loopcnt = 0; + if (sp->pp_link_state==SPPP_LINK_DOWN && + (dev->flags & IFF_UP)) { + sp->pp_link_state=SPPP_LINK_UP; + printk (KERN_INFO "%s: protocol up\n", dev->name); + } + break; + case CISCO_ADDR_REQ: + /* Stolen from net/ipv4/devinet.c -- SIOCGIFADDR ioctl */ + { + struct in_device *in_dev; + struct in_ifaddr *ifa; + u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */ +#ifdef CONFIG_INET + rcu_read_lock(); + if ((in_dev = __in_dev_get_rcu(dev)) != NULL) + { + for (ifa=in_dev->ifa_list; ifa != NULL; + ifa=ifa->ifa_next) { + if (strcmp(dev->name, ifa->ifa_label) == 0) + { + addr = ifa->ifa_local; + mask = ifa->ifa_mask; + break; + } + } + } + rcu_read_unlock(); +#endif + /* I hope both addr and mask are in the net order */ + sppp_cisco_send (sp, CISCO_ADDR_REPLY, addr, mask); + break; + } + } +} + + +/* + * Send PPP LCP packet. + */ + +static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type, + u8 ident, u16 len, void *data) +{ + struct ppp_header *h; + struct lcp_header *lh; + struct sk_buff *skb; + struct net_device *dev = sp->pp_if; + + skb=alloc_skb(dev->hard_header_len+PPP_HEADER_LEN+LCP_HEADER_LEN+len, + GFP_ATOMIC); + if (skb==NULL) + return; + + skb_reserve(skb,dev->hard_header_len); + + h = (struct ppp_header *)skb_put(skb, sizeof(struct ppp_header)); + h->address = PPP_ALLSTATIONS; /* broadcast address */ + h->control = PPP_UI; /* Unnumbered Info */ + h->protocol = htons (proto); /* Link Control Protocol */ + + lh = (struct lcp_header *)skb_put(skb, sizeof(struct lcp_header)); + lh->type = type; + lh->ident = ident; + lh->len = htons (LCP_HEADER_LEN + len); + + if (len) + memcpy(skb_put(skb,len),data, len); + + if (sp->pp_flags & PP_DEBUG) { + printk (KERN_WARNING "%s: %s output <%s id=%xh len=%xh", + dev->name, + proto==PPP_LCP ? "lcp" : "ipcp", + proto==PPP_LCP ? sppp_lcp_type_name (lh->type) : + sppp_ipcp_type_name (lh->type), lh->ident, + ntohs (lh->len)); + if (len) + sppp_print_bytes ((u8*) (lh+1), len); + printk (">\n"); + } + sp->obytes += skb->len; + /* Control is high priority so it doesn't get queued behind data */ + skb->priority=TC_PRIO_CONTROL; + skb->dev = dev; + skb_queue_tail(&tx_queue, skb); +} + +/* + * Send Cisco keepalive packet. + */ + +static void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2) +{ + struct ppp_header *h; + struct cisco_packet *ch; + struct sk_buff *skb; + struct net_device *dev = sp->pp_if; + u32 t = jiffies * 1000/HZ; + + skb=alloc_skb(dev->hard_header_len+PPP_HEADER_LEN+CISCO_PACKET_LEN, + GFP_ATOMIC); + + if(skb==NULL) + return; + + skb_reserve(skb, dev->hard_header_len); + h = (struct ppp_header *)skb_put (skb, sizeof(struct ppp_header)); + h->address = CISCO_MULTICAST; + h->control = 0; + h->protocol = htons (CISCO_KEEPALIVE); + + ch = (struct cisco_packet*)skb_put(skb, CISCO_PACKET_LEN); + ch->type = htonl (type); + ch->par1 = htonl (par1); + ch->par2 = htonl (par2); + ch->rel = -1; + ch->time0 = htons ((u16) (t >> 16)); + ch->time1 = htons ((u16) t); + + if (sp->pp_flags & PP_DEBUG) + printk (KERN_WARNING "%s: cisco output: <%xh %xh %xh %xh %xh-%xh>\n", + dev->name, ntohl (ch->type), ch->par1, + ch->par2, ch->rel, ch->time0, ch->time1); + sp->obytes += skb->len; + skb->priority=TC_PRIO_CONTROL; + skb->dev = dev; + skb_queue_tail(&tx_queue, skb); +} + +/** + * sppp_close - close down a synchronous PPP or Cisco HDLC link + * @dev: The network device to drop the link of + * + * This drops the logical interface to the channel. It is not + * done politely as we assume we will also be dropping DTR. Any + * timeouts are killed. + */ + +int sppp_close (struct net_device *dev) +{ + struct sppp *sp = (struct sppp *)sppp_of(dev); + unsigned long flags; + + spin_lock_irqsave(&sp->lock, flags); + sp->pp_link_state = SPPP_LINK_DOWN; + sp->lcp.state = LCP_STATE_CLOSED; + sp->ipcp.state = IPCP_STATE_CLOSED; + sppp_clear_timeout (sp); + spin_unlock_irqrestore(&sp->lock, flags); + + return 0; +} + +EXPORT_SYMBOL(sppp_close); + +/** + * sppp_open - open a synchronous PPP or Cisco HDLC link + * @dev: Network device to activate + * + * Close down any existing synchronous session and commence + * from scratch. In the PPP case this means negotiating LCP/IPCP + * and friends, while for Cisco HDLC we simply need to start sending + * keepalives + */ + +int sppp_open (struct net_device *dev) +{ + struct sppp *sp = (struct sppp *)sppp_of(dev); + unsigned long flags; + + sppp_close(dev); + + spin_lock_irqsave(&sp->lock, flags); + if (!(sp->pp_flags & PP_CISCO)) { + sppp_lcp_open (sp); + } + sp->pp_link_state = SPPP_LINK_DOWN; + spin_unlock_irqrestore(&sp->lock, flags); + sppp_flush_xmit(); + + return 0; +} + +EXPORT_SYMBOL(sppp_open); + +/** + * sppp_reopen - notify of physical link loss + * @dev: Device that lost the link + * + * This function informs the synchronous protocol code that + * the underlying link died (for example a carrier drop on X.21) + * + * We increment the magic numbers to ensure that if the other end + * failed to notice we will correctly start a new session. It happens + * do to the nature of telco circuits is that you can lose carrier on + * one endonly. + * + * Having done this we go back to negotiating. This function may + * be called from an interrupt context. + */ + +int sppp_reopen (struct net_device *dev) +{ + struct sppp *sp = (struct sppp *)sppp_of(dev); + unsigned long flags; + + sppp_close(dev); + + spin_lock_irqsave(&sp->lock, flags); + if (!(sp->pp_flags & PP_CISCO)) + { + sp->lcp.magic = jiffies; + ++sp->pp_seq; + sp->lcp.state = LCP_STATE_CLOSED; + sp->ipcp.state = IPCP_STATE_CLOSED; + /* Give it a moment for the line to settle then go */ + sppp_set_timeout (sp, 1); + } + sp->pp_link_state=SPPP_LINK_DOWN; + spin_unlock_irqrestore(&sp->lock, flags); + + return 0; +} + +EXPORT_SYMBOL(sppp_reopen); + +/** + * sppp_change_mtu - Change the link MTU + * @dev: Device to change MTU on + * @new_mtu: New MTU + * + * Change the MTU on the link. This can only be called with + * the link down. It returns an error if the link is up or + * the mtu is out of range. + */ + +static int sppp_change_mtu(struct net_device *dev, int new_mtu) +{ + if(new_mtu<128||new_mtu>PPP_MTU||(dev->flags&IFF_UP)) + return -EINVAL; + dev->mtu=new_mtu; + return 0; +} + +/** + * sppp_do_ioctl - Ioctl handler for ppp/hdlc + * @dev: Device subject to ioctl + * @ifr: Interface request block from the user + * @cmd: Command that is being issued + * + * This function handles the ioctls that may be issued by the user + * to control the settings of a PPP/HDLC link. It does both busy + * and security checks. This function is intended to be wrapped by + * callers who wish to add additional ioctl calls of their own. + */ + +int sppp_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + struct sppp *sp = (struct sppp *)sppp_of(dev); + + if(dev->flags&IFF_UP) + return -EBUSY; + + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + + switch(cmd) + { + case SPPPIOCCISCO: + sp->pp_flags|=PP_CISCO; + dev->type = ARPHRD_HDLC; + break; + case SPPPIOCPPP: + sp->pp_flags&=~PP_CISCO; + dev->type = ARPHRD_PPP; + break; + case SPPPIOCDEBUG: + sp->pp_flags&=~PP_DEBUG; + if(ifr->ifr_flags) + sp->pp_flags|=PP_DEBUG; + break; + case SPPPIOCGFLAGS: + if(copy_to_user(ifr->ifr_data, &sp->pp_flags, sizeof(sp->pp_flags))) + return -EFAULT; + break; + case SPPPIOCSFLAGS: + if(copy_from_user(&sp->pp_flags, ifr->ifr_data, sizeof(sp->pp_flags))) + return -EFAULT; + break; + default: + return -EINVAL; + } + return 0; +} + +EXPORT_SYMBOL(sppp_do_ioctl); + +/** + * sppp_attach - attach synchronous PPP/HDLC to a device + * @pd: PPP device to initialise + * + * This initialises the PPP/HDLC support on an interface. At the + * time of calling the dev element must point to the network device + * that this interface is attached to. The interface should not yet + * be registered. + */ + +void sppp_attach(struct ppp_device *pd) +{ + struct net_device *dev = pd->dev; + struct sppp *sp = &pd->sppp; + unsigned long flags; + + /* Make sure embedding is safe for sppp_of */ + BUG_ON(sppp_of(dev) != sp); + + spin_lock_irqsave(&spppq_lock, flags); + /* Initialize keepalive handler. */ + if (! spppq) + { + init_timer(&sppp_keepalive_timer); + sppp_keepalive_timer.expires=jiffies+10*HZ; + sppp_keepalive_timer.function=sppp_keepalive; + add_timer(&sppp_keepalive_timer); + } + /* Insert new entry into the keepalive list. */ + sp->pp_next = spppq; + spppq = sp; + spin_unlock_irqrestore(&spppq_lock, flags); + + sp->pp_loopcnt = 0; + sp->pp_alivecnt = 0; + sp->pp_seq = 0; + sp->pp_rseq = 0; + sp->pp_flags = PP_KEEPALIVE|PP_CISCO|debug;/*PP_DEBUG;*/ + sp->lcp.magic = 0; + sp->lcp.state = LCP_STATE_CLOSED; + sp->ipcp.state = IPCP_STATE_CLOSED; + sp->pp_if = dev; + spin_lock_init(&sp->lock); + + /* + * Device specific setup. All but interrupt handler and + * hard_start_xmit. + */ + + dev->hard_header = sppp_hard_header; + dev->rebuild_header = sppp_rebuild_header; + dev->tx_queue_len = 10; + dev->type = ARPHRD_HDLC; + dev->addr_len = 0; + dev->hard_header_len = sizeof(struct ppp_header); + dev->mtu = PPP_MTU; + /* + * These 4 are callers but MUST also call sppp_ functions + */ + dev->do_ioctl = sppp_do_ioctl; +#if 0 + dev->get_stats = NULL; /* Let the driver override these */ + dev->open = sppp_open; + dev->stop = sppp_close; +#endif + dev->change_mtu = sppp_change_mtu; + dev->hard_header_cache = NULL; + dev->header_cache_update = NULL; + dev->flags = IFF_MULTICAST|IFF_POINTOPOINT|IFF_NOARP; +} + +EXPORT_SYMBOL(sppp_attach); + +/** + * sppp_detach - release PPP resources from a device + * @dev: Network device to release + * + * Stop and free up any PPP/HDLC resources used by this + * interface. This must be called before the device is + * freed. + */ + +void sppp_detach (struct net_device *dev) +{ + struct sppp **q, *p, *sp = (struct sppp *)sppp_of(dev); + unsigned long flags; + + spin_lock_irqsave(&spppq_lock, flags); + /* Remove the entry from the keepalive list. */ + for (q = &spppq; (p = *q); q = &p->pp_next) + if (p == sp) { + *q = p->pp_next; + break; + } + + /* Stop keepalive handler. */ + if (! spppq) + del_timer(&sppp_keepalive_timer); + sppp_clear_timeout (sp); + spin_unlock_irqrestore(&spppq_lock, flags); +} + +EXPORT_SYMBOL(sppp_detach); + +/* + * Analyze the LCP Configure-Request options list + * for the presence of unknown options. + * If the request contains unknown options, build and + * send Configure-reject packet, containing only unknown options. + */ +static int +sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h, + int len, u32 *magic) +{ + u8 *buf, *r, *p; + int rlen; + + len -= 4; + buf = r = kmalloc (len, GFP_ATOMIC); + if (! buf) + return (0); + + p = (void*) (h+1); + for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) { + switch (*p) { + case LCP_OPT_MAGIC: + /* Magic number -- extract. */ + if (len >= 6 && p[1] == 6) { + *magic = (u32)p[2] << 24 | + (u32)p[3] << 16 | p[4] << 8 | p[5]; + continue; + } + break; + case LCP_OPT_ASYNC_MAP: + /* Async control character map -- check to be zero. */ + if (len >= 6 && p[1] == 6 && ! p[2] && ! p[3] && + ! p[4] && ! p[5]) + continue; + break; + case LCP_OPT_MRU: + /* Maximum receive unit -- always OK. */ + continue; + default: + /* Others not supported. */ + break; + } + /* Add the option to rejected list. */ + memcpy(r, p, p[1]); + r += p[1]; + rlen += p[1]; + } + if (rlen) + sppp_cp_send (sp, PPP_LCP, LCP_CONF_REJ, h->ident, rlen, buf); + kfree(buf); + return (rlen == 0); +} + +static void sppp_ipcp_input (struct sppp *sp, struct sk_buff *skb) +{ + struct lcp_header *h; + struct net_device *dev = sp->pp_if; + int len = skb->len; + + if (!pskb_may_pull(skb, sizeof(struct lcp_header))) { + if (sp->pp_flags & PP_DEBUG) + printk (KERN_WARNING "%s: invalid ipcp packet length: %d bytes\n", + dev->name, len); + return; + } + h = (struct lcp_header *)skb->data; + skb_pull(skb,sizeof(struct lcp_header)); + if (sp->pp_flags & PP_DEBUG) { + printk (KERN_WARNING "%s: ipcp input: %d bytes <%s id=%xh len=%xh", + dev->name, len, + sppp_ipcp_type_name (h->type), h->ident, ntohs (h->len)); + if (len > 4) + sppp_print_bytes ((u8*) (h+1), len-4); + printk (">\n"); + } + if (len > ntohs (h->len)) + len = ntohs (h->len); + switch (h->type) { + default: + /* Unknown packet type -- send Code-Reject packet. */ + sppp_cp_send (sp, PPP_IPCP, IPCP_CODE_REJ, ++sp->pp_seq, len, h); + break; + case IPCP_CONF_REQ: + if (len < 4) { + if (sp->pp_flags & PP_DEBUG) + printk (KERN_WARNING "%s: invalid ipcp configure request packet length: %d bytes\n", + dev->name, len); + return; + } + if (len > 4) { + sppp_cp_send (sp, PPP_IPCP, LCP_CONF_REJ, h->ident, + len-4, h+1); + + switch (sp->ipcp.state) { + case IPCP_STATE_OPENED: + /* Initiate renegotiation. */ + sppp_ipcp_open (sp); + /* fall through... */ + case IPCP_STATE_ACK_SENT: + /* Go to closed state. */ + sp->ipcp.state = IPCP_STATE_CLOSED; + } + } else { + /* Send Configure-Ack packet. */ + sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_ACK, h->ident, + 0, NULL); + /* Change the state. */ + if (sp->ipcp.state == IPCP_STATE_ACK_RCVD) + sp->ipcp.state = IPCP_STATE_OPENED; + else + sp->ipcp.state = IPCP_STATE_ACK_SENT; + } + break; + case IPCP_CONF_ACK: + if (h->ident != sp->ipcp.confid) + break; + sppp_clear_timeout (sp); + switch (sp->ipcp.state) { + case IPCP_STATE_CLOSED: + sp->ipcp.state = IPCP_STATE_ACK_RCVD; + sppp_set_timeout (sp, 5); + break; + case IPCP_STATE_ACK_SENT: + sp->ipcp.state = IPCP_STATE_OPENED; + break; + } + break; + case IPCP_CONF_NAK: + case IPCP_CONF_REJ: + if (h->ident != sp->ipcp.confid) + break; + sppp_clear_timeout (sp); + /* Initiate renegotiation. */ + sppp_ipcp_open (sp); + if (sp->ipcp.state != IPCP_STATE_ACK_SENT) + /* Go to closed state. */ + sp->ipcp.state = IPCP_STATE_CLOSED; + break; + case IPCP_TERM_REQ: + /* Send Terminate-Ack packet. */ + sppp_cp_send (sp, PPP_IPCP, IPCP_TERM_ACK, h->ident, 0, NULL); + /* Go to closed state. */ + sp->ipcp.state = IPCP_STATE_CLOSED; + /* Initiate renegotiation. */ + sppp_ipcp_open (sp); + break; + case IPCP_TERM_ACK: + /* Ignore for now. */ + case IPCP_CODE_REJ: + /* Ignore for now. */ + break; + } +} + +static void sppp_lcp_open (struct sppp *sp) +{ + char opt[6]; + + if (! sp->lcp.magic) + sp->lcp.magic = jiffies; + opt[0] = LCP_OPT_MAGIC; + opt[1] = sizeof (opt); + opt[2] = sp->lcp.magic >> 24; + opt[3] = sp->lcp.magic >> 16; + opt[4] = sp->lcp.magic >> 8; + opt[5] = sp->lcp.magic; + sp->lcp.confid = ++sp->pp_seq; + sppp_cp_send (sp, PPP_LCP, LCP_CONF_REQ, sp->lcp.confid, + sizeof (opt), &opt); + sppp_set_timeout (sp, 2); +} + +static void sppp_ipcp_open (struct sppp *sp) +{ + sp->ipcp.confid = ++sp->pp_seq; + sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_REQ, sp->ipcp.confid, 0, NULL); + sppp_set_timeout (sp, 2); +} + +/* + * Process PPP control protocol timeouts. + */ + +static void sppp_cp_timeout (unsigned long arg) +{ + struct sppp *sp = (struct sppp*) arg; + unsigned long flags; + + spin_lock_irqsave(&sp->lock, flags); + + sp->pp_flags &= ~PP_TIMO; + if (! (sp->pp_if->flags & IFF_UP) || (sp->pp_flags & PP_CISCO)) { + spin_unlock_irqrestore(&sp->lock, flags); + return; + } + switch (sp->lcp.state) { + case LCP_STATE_CLOSED: + /* No ACK for Configure-Request, retry. */ + sppp_lcp_open (sp); + break; + case LCP_STATE_ACK_RCVD: + /* ACK got, but no Configure-Request for peer, retry. */ + sppp_lcp_open (sp); + sp->lcp.state = LCP_STATE_CLOSED; + break; + case LCP_STATE_ACK_SENT: + /* ACK sent but no ACK for Configure-Request, retry. */ + sppp_lcp_open (sp); + break; + case LCP_STATE_OPENED: + /* LCP is already OK, try IPCP. */ + switch (sp->ipcp.state) { + case IPCP_STATE_CLOSED: + /* No ACK for Configure-Request, retry. */ + sppp_ipcp_open (sp); + break; + case IPCP_STATE_ACK_RCVD: + /* ACK got, but no Configure-Request for peer, retry. */ + sppp_ipcp_open (sp); + sp->ipcp.state = IPCP_STATE_CLOSED; + break; + case IPCP_STATE_ACK_SENT: + /* ACK sent but no ACK for Configure-Request, retry. */ + sppp_ipcp_open (sp); + break; + case IPCP_STATE_OPENED: + /* IPCP is OK. */ + break; + } + break; + } + spin_unlock_irqrestore(&sp->lock, flags); + sppp_flush_xmit(); +} + +static char *sppp_lcp_type_name (u8 type) +{ + static char buf [8]; + switch (type) { + case LCP_CONF_REQ: return ("conf-req"); + case LCP_CONF_ACK: return ("conf-ack"); + case LCP_CONF_NAK: return ("conf-nack"); + case LCP_CONF_REJ: return ("conf-rej"); + case LCP_TERM_REQ: return ("term-req"); + case LCP_TERM_ACK: return ("term-ack"); + case LCP_CODE_REJ: return ("code-rej"); + case LCP_PROTO_REJ: return ("proto-rej"); + case LCP_ECHO_REQ: return ("echo-req"); + case LCP_ECHO_REPLY: return ("echo-reply"); + case LCP_DISC_REQ: return ("discard-req"); + } + sprintf (buf, "%xh", type); + return (buf); +} + +static char *sppp_ipcp_type_name (u8 type) +{ + static char buf [8]; + switch (type) { + case IPCP_CONF_REQ: return ("conf-req"); + case IPCP_CONF_ACK: return ("conf-ack"); + case IPCP_CONF_NAK: return ("conf-nack"); + case IPCP_CONF_REJ: return ("conf-rej"); + case IPCP_TERM_REQ: return ("term-req"); + case IPCP_TERM_ACK: return ("term-ack"); + case IPCP_CODE_REJ: return ("code-rej"); + } + sprintf (buf, "%xh", type); + return (buf); +} + +static void sppp_print_bytes (u_char *p, u16 len) +{ + printk (" %x", *p++); + while (--len > 0) + printk ("-%x", *p++); +} + +/** + * sppp_rcv - receive and process a WAN PPP frame + * @skb: The buffer to process + * @dev: The device it arrived on + * @p: Unused + * @orig_dev: Unused + * + * Protocol glue. This drives the deferred processing mode the poorer + * cards use. This can be called directly by cards that do not have + * timing constraints but is normally called from the network layer + * after interrupt servicing to process frames queued via netif_rx. + */ + +static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev) +{ + if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) + return NET_RX_DROP; + sppp_input(dev,skb); + return 0; +} + +static struct packet_type sppp_packet_type = { + .type = __constant_htons(ETH_P_WAN_PPP), + .func = sppp_rcv, +}; + +static char banner[] __initdata = + KERN_INFO "Cronyx Ltd, Synchronous PPP and CISCO HDLC (c) 1994\n" + KERN_INFO "Linux port (c) 1998 Building Number Three Ltd & " + "Jan \"Yenya\" Kasprzak.\n"; + +static int __init sync_ppp_init(void) +{ + if(debug) + debug=PP_DEBUG; + printk(banner); + skb_queue_head_init(&tx_queue); + dev_add_pack(&sppp_packet_type); + return 0; +} + + +static void __exit sync_ppp_cleanup(void) +{ + dev_remove_pack(&sppp_packet_type); +} + +module_init(sync_ppp_init); +module_exit(sync_ppp_cleanup); +module_param(debug, int, 0); +MODULE_LICENSE("GPL"); + diff --git a/kernel/digits.h b/kernel/digits.h new file mode 100644 index 0000000..eba09dd --- /dev/null +++ b/kernel/digits.h @@ -0,0 +1,43 @@ +/* + * Zapata Telephony + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Use DTMF/MFv1 tables + */ + +#ifndef _DIGITS_H +#define _DIGITS_H + +#define DEFAULT_DTMF_LENGTH 100 * ZT_CHUNKSIZE +#define DEFAULT_MFV1_LENGTH 60 * ZT_CHUNKSIZE +#define PAUSE_LENGTH 500 * ZT_CHUNKSIZE + +/* At the end of silence, the tone stops */ +static struct zt_tone dtmf_silence = { + .tonesamples = DEFAULT_DTMF_LENGTH, +}; + +/* At the end of silence, the tone stops */ +static struct zt_tone mfv1_silence = { + .tonesamples = DEFAULT_MFV1_LENGTH, +}; + +/* A pause in the dialing */ +static struct zt_tone tone_pause = { + .tonesamples = PAUSE_LENGTH, +}; + +#endif diff --git a/kernel/ecdis.h b/kernel/ecdis.h new file mode 100644 index 0000000..4d3801b --- /dev/null +++ b/kernel/ecdis.h @@ -0,0 +1,118 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * ec_disable_detector.h - A detector which should eventually meet the + * G.164/G.165 requirements for detecting the + * 2100Hz echo cancellor disable tone. + * + * Written by Steve Underwood + * + * Copyright (C) 2001 Steve Underwood + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "biquad.h" + +typedef struct +{ + biquad2_state_t notch; + int notch_level; + int channel_level; + int tone_present; + int tone_cycle_duration; + int good_cycles; + int hit; +} echo_can_disable_detector_state_t; + + +#define FALSE 0 +#define TRUE (!FALSE) + +static inline void echo_can_disable_detector_init (echo_can_disable_detector_state_t *det) +{ + /* Elliptic notch */ + /* This is actually centred at 2095Hz, but gets the balance we want, due + to the asymmetric walls of the notch */ + biquad2_init (&det->notch, + (int32_t) (-0.7600000*32768.0), + (int32_t) (-0.1183852*32768.0), + (int32_t) (-0.5104039*32768.0), + (int32_t) ( 0.1567596*32768.0), + (int32_t) ( 1.0000000*32768.0)); + + det->channel_level = 0; + det->notch_level = 0; + det->tone_present = FALSE; + det->tone_cycle_duration = 0; + det->good_cycles = 0; + det->hit = 0; +} +/*- End of function --------------------------------------------------------*/ + +static inline int echo_can_disable_detector_update (echo_can_disable_detector_state_t *det, + int16_t amp) +{ + int16_t notched; + + notched = biquad2 (&det->notch, amp); + /* Estimate the overall energy in the channel, and the energy in + the notch (i.e. overall channel energy - tone energy => noise). + Use abs instead of multiply for speed (is it really faster?). + Damp the overall energy a little more for a stable result. + Damp the notch energy a little less, so we don't damp out the + blip every time the phase reverses */ + det->channel_level += ((abs(amp) - det->channel_level) >> 5); + det->notch_level += ((abs(notched) - det->notch_level) >> 4); + if (det->channel_level > 280) + { + /* There is adequate energy in the channel. Is it mostly at 2100Hz? */ + if (det->notch_level*6 < det->channel_level) + { + /* The notch says yes, so we have the tone. */ + if (!det->tone_present) + { + /* Do we get a kick every 450+-25ms? */ + if (det->tone_cycle_duration >= 425*8 + && + det->tone_cycle_duration <= 475*8) + { + det->good_cycles++; + if (det->good_cycles > 2) + det->hit = TRUE; + } + det->tone_cycle_duration = 0; + } + det->tone_present = TRUE; + } + else + { + det->tone_present = FALSE; + } + det->tone_cycle_duration++; + } + else + { + det->tone_present = FALSE; + det->tone_cycle_duration = 0; + det->good_cycles = 0; + } + return det->hit; +} +/*- End of function --------------------------------------------------------*/ +/*- End of file ------------------------------------------------------------*/ diff --git a/kernel/fasthdlc.h b/kernel/fasthdlc.h new file mode 100644 index 0000000..adb5597 --- /dev/null +++ b/kernel/fasthdlc.h @@ -0,0 +1,462 @@ +/* + * Mark's Mythical Table-based raw HDLC implementation + * + * This is designed to be a very fast, but memory efficient + * implementation of standard HDLC protocol. + * + * This table based HDLC technology is PATENT PENDING, but will always be + * remain freely distributable under the terms of the GPL version 2.0. + * + * For non-GPL licensing, please contact Mark Spencer at + * the below e-mail address. + * + * Copyright (C) 2001, Linux Support Services, Inc. + * + * Written by Mark Spencer + * + * Distributed under the terms of the GNU General Public License + * Version 2.0. + * + */ + +#ifndef _FASTHDLC_H +#define _FASTHDLC_H + +struct fasthdlc_state { + int state; /* What state we are in */ + unsigned int data; /* Our current data queue */ + int bits; /* Number of bits in our data queue */ + int ones; /* Number of ones */ +}; + +#ifdef FAST_HDLC_NEED_TABLES +#define RETURN_COMPLETE_FLAG (0x1000) +#define RETURN_DISCARD_FLAG (0x2000) +#define RETURN_EMPTY_FLAG (0x4000) + +/* Unlike most HDLC implementations, we define only two states, + when we are in a valid frame, and when we are searching for + a frame header */ + +#define FRAME_SEARCH 0 +#define PROCESS_FRAME 1 + +/* + + HDLC Search State table -- Look for a frame header. The return value + of this table is as follows: + + |---8---|---7---|---6---|---5---|---4---|---3---|---2---|---1---| + | Z E R O E S | Next | Bits Consumed | + |-------|-------|-------|-------|-------|-------|-------|-------| + + The indexes for this table are the state (0 or 1) and the next 8 + bits of the stream. + + Note that this table is only used for state 0 and 1. + + The user should discard the top "bits consumed" bits of data before + the next call. "Next state" represents the actual next state for + decoding. + +*/ +static unsigned char hdlc_search[256]; + +/* + HDLC Data Table + + The indexes to this table are the number of one's we've seen so far (0-5) and + the next 10 bits of input (which is enough to guarantee us that we + will retrieve at least one byte of data (or frame or whatever). + + The format for the return value is: + + Bits 15: Status (1=Valid Data, 0=Control Frame (see bits 7-0 for type)) + Bits 14-12: Number of ones in a row, so far + Bits 11-8: The number of bits consumed (0-10) + Bits 7-0: The return data (if appropriate) + + The next state is simply bit #15 + +*/ + +#define CONTROL_COMPLETE 1 +#define CONTROL_ABORT 2 + +#define STATUS_MASK (1 << 15) +#define STATUS_VALID (1 << 15) +#define STATUS_CONTROL (0 << 15) +#define STATE_MASK (1 << 15) +#define ONES_MASK (7 << 12) +#define DATA_MASK (0xff) + +static unsigned short hdlc_frame[6][1024]; + +static unsigned int minbits[2] = { 8, 10 }; + +/* + Last, but not least, we have the encoder table. It takes + as its indices the number of ones so far and a byte of data + and returns an int composed of the following fields: + + Bots 31-22: Actual Data + Bits 21-16: Unused + Bits 15-8: Number of ones + Bits 3-0: Number of bits of output (13-4) to use + + Of course we could optimize by reducing to two tables, but I don't + really think it's worth the trouble at this point. + */ + +static unsigned int hdlc_encode[6][256]; + +static inline char hdlc_search_precalc(unsigned char c) +{ + int x, p=0; + /* Look for a flag. If this isn't a flag, + line us up for the next possible shot at + a flag */ + + /* If it's a flag, we go to state 1, and have + consumed 8 bits */ + if (c == 0x7e) + return 0x10 | 8; + + /* If it's an abort, we stay in the same state + and have consumed 8 bits */ + if (c == 0x7f) + return 0x00 | 8; + + /* If it's all 1's, we state in the same state and + have consumed 8 bits */ + if (c == 0xff) + return 0x00 | 8; + + /* If we get here, we must have at least one zero in us + but we're not the flag. So, start at the end (LSB) and + work our way to the top (MSB) looking for a zero. The + position of that 0 is most optimistic start of a real + frame header */ + x=1; + p=7; + while(p && (c & x)) { + x <<= 1; + p--; + } + return p; +} + +#ifdef DEBUG_PRECALC +static inline void hdlc_search_print(char c, char r) +{ + int x=0x80; + while(x) { + printf("%s", c & x ? "1" : "0"); + x >>= 1; + } + printf(" => State %d, Consume %d\n", (r & 0x10) >> 4, r & 0xf); +} +#endif + +#define HFP(status, ones, bits, data) \ + ((status) | ((ones) << 12) | ((bits) << 8) | (data)) + +static inline unsigned int hdlc_frame_precalc(unsigned char x, unsigned short c) +{ + /* Assume we have seen 'x' one's so far, and have read the + bottom 10 bytes of c (MSB first). Now, we HAVE to have + a byte of data or a frame or something. We are assumed + to be at the beginning of a byte of data or something */ + unsigned char ones = x; + unsigned char data=0; + int bits=0; + int consumed=0; + while(bits < 8) { + data >>=1; + consumed++; + if (ones == 5) { + /* We've seen five ones */ + if (c & 0x0200) { + /* Another one -- Some sort of signal frame */ + if ((!(c & 0x0100)) && (bits == 6)) { + /* This is a frame terminator (10) */ + return HFP(0, + 0, 8, CONTROL_COMPLETE); + } else { + /* Yuck! It's something else... + Abort this entire frame, and + start looking for a good frame */ + return HFP(0, + 0, consumed+1, CONTROL_ABORT); + } + } else { + /* It's an inserted zero, just skip it */ + ones = 0; + data <<= 1; + } + } else { + /* Add it to our bit list, LSB to + MSB */ + if (c & 0x0200) { + data |= 0x80; + ones++; + } else + ones=0; + bits++; + } + c <<= 1; + } + /* Consume the extra 0 now rather than later. */ + if (ones == 5) { + ones = 0; + consumed++; + } + return HFP(STATUS_VALID, ones, consumed, data); +} + +#ifdef DEBUG_PRECALC + +static inline void hdlc_frame_print(unsigned char x, unsigned short c, unsigned int res) +{ + int z=0x0200; + char *status[] = { + "Control", + "Valid", + }; + printf("%d one's then ", x); + while(z) { + printf("%s", c & z ? "1" : "0"); + z >>= 1; + } + printf(" => Status %s, ", res & STATUS_MASK ? "1" : "0"); + printf("Consumed: %d, ", (res & 0x0f00) >> 8); + printf("Status: %s, ", status[(res & STATUS_MASK) >> 15]); + printf("Ones: %d, ", (res & ONES_MASK) >> 12); + printf("Data: %02x\n", res & 0xff); + +} + +#endif + +static inline unsigned int hdlc_encode_precalc(int x, unsigned char y) +{ + int bits=0; + int ones=x; + unsigned short data=0; + int z; + for (z=0;z<8;z++) { + /* Zero-stuff if needed */ + if (ones == 5) { + /* Stuff a zero */ + data <<= 1; + ones=0; + bits++; + } + if (y & 0x01) { + /* There's a one */ + data <<= 1; + data |= 0x1; + ones++; + bits++; + } else { + data <<= 1; + ones = 0; + bits++; + } + y >>= 1; + } + /* Special case -- Stuff the zero at the end if appropriate */ + if (ones == 5) { + /* Stuff a zero */ + data <<= 1; + ones=0; + bits++; + } + data <<= (10-bits); + return (data << 22) | (ones << 8) | (bits); +} + +#ifdef DEBUG_PRECALC +static inline void hdlc_encode_print(int x, unsigned char y, unsigned int val) +{ + unsigned int z; + unsigned short c; + printf("%d ones, %02x (", x, y); + z = 0x80; + while(z) { + printf("%s", y & z ? "1" : "0"); + z >>= 1; + } + printf(") encoded as "); + z = 1 << 31; + for (x=0;x<(val & 0xf);x++) { + printf("%s", val & z ? "1" : "0"); + z >>= 1; + } + printf(" with %d ones now, %d bits in len\n", (val & 0xf00) >> 8, val & 0xf); + + +} +#endif + +static inline void fasthdlc_precalc(void) +{ + int x; + int y; + /* First the easy part -- the searching */ + for (x=0;x<256;x++) { + hdlc_search[x] = hdlc_search_precalc(x); +#ifdef DEBUG_PRECALC + hdlc_search_print(x, hdlc_search[x]); +#endif + } + /* Now the hard part -- the frame tables */ + for (x=0;x<6;x++) { + /* Given the # of preceeding ones, process the next + byte of input (up to 10 actual bits) */ + for (y=0;y<1024;y++) { + hdlc_frame[x][y] = hdlc_frame_precalc(x, y); +#ifdef DEBUG_PRECALC + hdlc_frame_print(x, y, hdlc_frame[x][y]); +#endif + } + } + /* Now another not-so-hard part, the encoding table */ + for (x=0;x<6;x++) { + for (y=0;y<256;y++) { + hdlc_encode[x][y] = hdlc_encode_precalc(x,y); +#ifdef DEBUG_PRECALC + hdlc_encode_print(x,y,hdlc_encode[x][y]); +#endif + } + } +} + + +static inline void fasthdlc_init(struct fasthdlc_state *h) +{ + /* Initializes all states appropriately */ + h->state = 0; + h->bits = 0; + h->data = 0; + h->ones = 0; + +} + +static inline int fasthdlc_tx_load_nocheck(struct fasthdlc_state *h, unsigned char c) +{ + unsigned int res; + res = hdlc_encode[h->ones][c]; + h->ones = (res & 0xf00) >> 8; + h->data |= (res & 0xffc00000) >> h->bits; + h->bits += (res & 0xf); + return 0; +} + +static inline int fasthdlc_tx_load(struct fasthdlc_state *h, unsigned char c) +{ + /* Gotta have at least 10 bits left */ + if (h->bits > 22) + return -1; + return fasthdlc_tx_load_nocheck(h, c); +} + +static inline int fasthdlc_tx_frame_nocheck(struct fasthdlc_state *h) +{ + h->ones = 0; + h->data |= ( 0x7e000000 >> h->bits); + h->bits += 8; + return 0; +} + +static inline int fasthdlc_tx_frame(struct fasthdlc_state *h) +{ + if (h->bits > 24) + return -1; + return fasthdlc_tx_frame_nocheck(h); +} + +static inline int fasthdlc_tx_run_nocheck(struct fasthdlc_state *h) +{ + unsigned char b; + b = h->data >> 24; + h->bits -= 8; + h->data <<= 8; + return b; +} + +static inline int fasthdlc_tx_run(struct fasthdlc_state *h) +{ + if (h->bits < 8) + return -1; + return fasthdlc_tx_run_nocheck(h); +} + +static inline int fasthdlc_rx_load_nocheck(struct fasthdlc_state *h, unsigned char b) +{ + /* Put the new byte in the data stream */ + h->data |= b << (24-h->bits); + h->bits += 8; + return 0; +} + +static inline int fasthdlc_rx_load(struct fasthdlc_state *h, unsigned char b) +{ + /* Make sure we have enough space */ + if (h->bits > 24) + return -1; + return fasthdlc_rx_load_nocheck(h, b); +} + +/* + Returns a data character if available, logical OR'd with + zero or more of RETURN_COMPLETE_FLAG, RETURN_DISCARD_FLAG, + and RETURN_EMPTY_FLAG, signifying a complete frame, a + discarded frame, or there is nothing to return. + */ + +static inline int fasthdlc_rx_run(struct fasthdlc_state *h) +{ + unsigned short next; + int retval=RETURN_EMPTY_FLAG; + while ((h->bits >= minbits[h->state]) && (retval == RETURN_EMPTY_FLAG)) { + /* Run until we can no longer be assured that we will + have enough bits to continue */ + switch(h->state) { + case FRAME_SEARCH: + /* Look for an HDLC frame, keying from + the top byte. */ + next = hdlc_search[h->data >> 24]; + h->bits -= next & 0x0f; + h->data <<= next & 0x0f; + h->state = next >> 4; + h->ones = 0; + break; + case PROCESS_FRAME: + /* Process as much as the next ten bits */ + next = hdlc_frame[h->ones][h->data >> 22]; + h->bits -= ((next & 0x0f00) >> 8); + h->data <<= ((next & 0x0f00) >> 8); + h->state = (next & STATE_MASK) >> 15; + h->ones = (next & ONES_MASK) >> 12; + switch(next & STATUS_MASK) { + case STATUS_CONTROL: + if (next & CONTROL_COMPLETE) { + /* A complete, valid frame received */ + retval = (RETURN_COMPLETE_FLAG); + /* Stay in this state */ + h->state = 1; + } else { + /* An abort (either out of sync of explicit) */ + retval = (RETURN_DISCARD_FLAG); + } + break; + case STATUS_VALID: + retval = (next & DATA_MASK); + } + } + } + return retval; +} +#endif /* FAST_HDLC_NEED_TABLES */ +#endif diff --git a/kernel/fir.h b/kernel/fir.h new file mode 100644 index 0000000..1722285 --- /dev/null +++ b/kernel/fir.h @@ -0,0 +1,130 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * fir.h - General telephony FIR routines + * + * Written by Steve Underwood + * + * Copyright (C) 2002 Steve Underwood + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#if !defined(_FIR_H_) +#define _FIR_H_ + +typedef struct +{ + int taps; + int curr_pos; + int16_t *coeffs; + int16_t *history; +} fir16_state_t; + +typedef struct +{ + int taps; + int curr_pos; + int32_t *coeffs; + int16_t *history; +} fir32_state_t; + +static inline void fir16_create (fir16_state_t *fir, + int16_t *coeffs, + int taps) +{ + fir->taps = taps; + fir->curr_pos = taps - 1; + fir->coeffs = coeffs; + fir->history = MALLOC (taps*sizeof (int16_t)); + if (fir->history) + memset (fir->history, '\0', taps*sizeof (int16_t)); +} +/*- End of function --------------------------------------------------------*/ + +static inline void fir16_free (fir16_state_t *fir) +{ + FREE (fir->history); +} +/*- End of function --------------------------------------------------------*/ + +static inline int16_t fir16 (fir16_state_t *fir, int16_t sample) +{ + int i; + int offset1; + int offset2; + int32_t y; + + fir->history[fir->curr_pos] = sample; + offset2 = fir->curr_pos + 1; + offset1 = fir->taps - offset2; + y = 0; + for (i = fir->taps - 1; i >= offset1; i--) + y += fir->coeffs[i]*fir->history[i - offset1]; + for ( ; i >= 0; i--) + y += fir->coeffs[i]*fir->history[i + offset2]; + if (fir->curr_pos <= 0) + fir->curr_pos = fir->taps; + fir->curr_pos--; + return y >> 15; +} +/*- End of function --------------------------------------------------------*/ + +static inline void fir32_create (fir32_state_t *fir, + int32_t *coeffs, + int taps) +{ + fir->taps = taps; + fir->curr_pos = taps - 1; + fir->coeffs = coeffs; + fir->history = MALLOC (taps*sizeof (int16_t)); + if (fir->history) + memset (fir->history, '\0', taps*sizeof (int16_t)); +} +/*- End of function --------------------------------------------------------*/ + +static inline void fir32_free (fir32_state_t *fir) +{ + FREE (fir->history); +} +/*- End of function --------------------------------------------------------*/ + +static inline int16_t fir32 (fir32_state_t *fir, int16_t sample) +{ + int i; + int offset1; + int offset2; + int32_t y; + + fir->history[fir->curr_pos] = sample; + offset2 = fir->curr_pos + 1; + offset1 = fir->taps - offset2; + y = 0; + for (i = fir->taps - 1; i >= offset1; i--) + y += fir->coeffs[i]*fir->history[i - offset1]; + for ( ; i >= 0; i--) + y += fir->coeffs[i]*fir->history[i + offset2]; + if (fir->curr_pos <= 0) + fir->curr_pos = fir->taps; + fir->curr_pos--; + return y >> 15; +} +/*- End of function --------------------------------------------------------*/ + +#endif +/*- End of file ------------------------------------------------------------*/ diff --git a/kernel/hpec/hpec.h b/kernel/hpec/hpec.h new file mode 100644 index 0000000..7e90f12 --- /dev/null +++ b/kernel/hpec/hpec.h @@ -0,0 +1,47 @@ +/* + * Zapata Telephony Interface to Digium High-Performance Echo Canceller + * + * Copyright (C) 2006 Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(_HPEC_H) +#define _HPEC_H + +struct echo_can_state; + +void __attribute__((regparm(0))) hpec_init(int __attribute__((regparm(0))) __attribute__((format (printf, 1, 2))) (*logger)(const char *format, ...), + unsigned int debug, + unsigned int chunk_size, + void * (*memalloc)(size_t len), + void (*memfree)(void *ptr)); + +void __attribute__((regparm(0))) hpec_shutdown(void); + +int __attribute__((regparm(0))) hpec_license_challenge(struct hpec_challenge *challenge); + +int __attribute__((regparm(0))) hpec_license_check(struct hpec_license *license); + +struct echo_can_state __attribute__((regparm(0))) *hpec_channel_alloc(unsigned int len); + +void __attribute__((regparm(0))) hpec_channel_free(struct echo_can_state *channel); + +void __attribute__((regparm(0))) hpec_channel_update(struct echo_can_state *channel, short *iref, short *isig); + +#endif /* !defined(_HPEC_H) */ + diff --git a/kernel/hpec/hpec_user.h b/kernel/hpec/hpec_user.h new file mode 100644 index 0000000..bf006eb --- /dev/null +++ b/kernel/hpec/hpec_user.h @@ -0,0 +1,40 @@ +/* + * Zapata Telephony Interface to Digium High-Performance Echo Canceller + * + * Copyright (C) 2006 Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(_HPEC_USER_H) +#define _HPEC_USER_H + +struct hpec_challenge { + __u8 challenge[16]; +}; + +struct hpec_license { + __u32 numchannels; + __u8 userinfo[256]; + __u8 response[16]; +}; + +#define ZT_EC_LICENSE_CHALLENGE _IOR(ZT_CODE, 60, struct hpec_challenge) +#define ZT_EC_LICENSE_RESPONSE _IOW(ZT_CODE, 61, struct hpec_license) + +#endif /* !defined(_HPEC_USER_H) */ + diff --git a/kernel/hpec/hpec_zaptel.h b/kernel/hpec/hpec_zaptel.h new file mode 100644 index 0000000..2fb5a14 --- /dev/null +++ b/kernel/hpec/hpec_zaptel.h @@ -0,0 +1,146 @@ +/* + * Zapata Telephony Interface to Digium High-Performance Echo Canceller + * + * Copyright (C) 2006 Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(_HPEC_ZAPTEL_H) +#define _HPEC_ZAPTEL_H + +#define ZT_EC_ARRAY_UPDATE + +#include "hpec_user.h" +#include "hpec.h" + +static int __attribute__((regparm(0))) __attribute__((format (printf, 1, 2))) logger(const char *format, ...) +{ + int res; + va_list args; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9) + va_start(args, format); + res = vprintk(format, args); + va_end(args); +#else + char buf[256]; + + va_start(args, format); + res = vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + printk(buf); +#endif + + return res; +} + +static void *memalloc(size_t len) +{ + return kmalloc(len, GFP_KERNEL); +} + +static void memfree(void *ptr) +{ + kfree(ptr); +} + +static void echo_can_init(void) +{ + printk("Zaptel Echo Canceller: Digium High-Performance Echo Canceller\n"); + hpec_init(logger, debug, ZT_CHUNKSIZE, memalloc, memfree); +} + +static void echo_can_identify(char *buf, size_t len) +{ + strncpy(buf, "HPEC", len); +} + +static void echo_can_shutdown(void) +{ + hpec_shutdown(); +} + +static inline void echo_can_free(struct echo_can_state *ec) +{ + hpec_channel_free(ec); +} + +static inline void echo_can_array_update(struct echo_can_state *ec, short *iref, short *isig) +{ + hpec_channel_update(ec, iref, isig); +} + +DECLARE_MUTEX(alloc_lock); + +static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p, + struct echo_can_state **ec) +{ + if (ecp->param_count > 0) { + printk(KERN_WARNING "HPEC does not support parameters; failing request\n"); + return -EINVAL; + } + + if (down_interruptible(&alloc_lock)) + return -ENOTTY; + + *ec = hpec_channel_alloc(ecp->tap_length); + + up(&alloc_lock); + + return *ec ? 0 : -ENOTTY; +} + +static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) +{ + return 1; +} + +DECLARE_MUTEX(license_lock); + +static int hpec_license_ioctl(unsigned int cmd, unsigned long data) +{ + struct hpec_challenge challenge; + struct hpec_license license; + int result = 0; + + switch (cmd) { + case ZT_EC_LICENSE_CHALLENGE: + if (down_interruptible(&license_lock)) + return -EINTR; + memset(&challenge, 0, sizeof(challenge)); + if (hpec_license_challenge(&challenge)) + result = -ENODEV; + if (!result && copy_to_user((unsigned char *) data, &challenge, sizeof(challenge))) + result = -EFAULT; + up(&license_lock); + return result; + case ZT_EC_LICENSE_RESPONSE: + if (down_interruptible(&license_lock)) + return -EINTR; + if (copy_from_user(&license, (unsigned char *) data, sizeof(license))) + result = -EFAULT; + if (!result && hpec_license_check(&license)) + result = -EACCES; + up(&license_lock); + return result; + default: + return -ENOSYS; + } +} + +#endif /* !defined(_HPEC_ZAPTEL_H) */ diff --git a/kernel/jpah.h b/kernel/jpah.h new file mode 100644 index 0000000..f72c5fa --- /dev/null +++ b/kernel/jpah.h @@ -0,0 +1,104 @@ +/* + * ECHO_CAN_JP1 + * + * by Jason Parker + * + * Based upon mg2ec.h - sort of. + * This "echo can" will completely hose your audio. + * Don't use it unless you're absolutely sure you know what you're doing. + * + * Copyright (C) 2007, Digium, Inc. + * + * This program is free software and may be used and + * distributed according to the terms of the GNU + * General Public License, incorporated herein by + * reference. + * + */ + +#ifndef _JP_ECHO_H +#define _JP_ECHO_H + +#ifdef __KERNEL__ +#include +#include +#define MALLOC(a) kmalloc((a), GFP_KERNEL) +#define FREE(a) kfree(a) +#else +#include +#include +#include +#include +#define MALLOC(a) malloc(a) +#define FREE(a) free(a) +#endif + +/* Echo canceller definition */ +struct echo_can_state { + /* an arbitrary ID for this echo can - this really should be settable from the calling channel... */ + int id; + + /* absolute time - aka. sample number index - essentially the number of samples since this can was init'ed */ + int i_d; +}; + +static void echo_can_init(void) +{ + printk("Zaptel Audio Hoser: JP1\n"); +} + +static void echo_can_identify(char *buf, size_t len) +{ + strncpy(buf, "JP1", len); +} + +static void echo_can_shutdown(void) +{ +} + +static inline void init_cc(struct echo_can_state *ec) +{ + void *ptr = ec; + unsigned long tmp; + /* Double-word align past end of state */ + ptr += sizeof(struct echo_can_state); + tmp = (unsigned long)ptr; + tmp += 3; + tmp &= ~3L; + ptr = (void *)tmp; +} + +static inline void echo_can_free(struct echo_can_state *ec) +{ + FREE(ec); +} + +static inline short echo_can_update(struct echo_can_state *ec, short iref, short isig) +{ + static int blah = 0; + + if (blah < 2) { + blah++; + return 0; + } else { + blah = (blah + 1) % 3; + return isig; + } +} + +static inline struct echo_can_state *echo_can_create(int len, int adaption_mode) +{ + struct echo_can_state *ec; + ec = (struct echo_can_state *)MALLOC(sizeof(struct echo_can_state) + 4); /* align */ + if (ec) { + memset(ec, 0, sizeof(struct echo_can_state) + 4); /* align */ + init_cc(ec); + } + return ec; +} + +static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) +{ + return 0; +} +#endif diff --git a/kernel/kb1ec.h b/kernel/kb1ec.h new file mode 100644 index 0000000..33236b7 --- /dev/null +++ b/kernel/kb1ec.h @@ -0,0 +1,597 @@ +/* + * ECHO_CAN_KB1 + * + * by Kris Boutilier + * + * Based upon mech2.h + * + * Copyright (C) 2002, Digium, Inc. + * + * This program is free software and may be used and + * distributed according to the terms of the GNU + * General Public License, incorporated herein by + * reference. + * + * Additional background on the techniques used in this code can be found in: + * + * Messerschmitt, David; Hedberg, David; Cole, Christopher; Haoui, Amine; + * Winship, Peter; "Digital Voice Echo Canceller with a TMS32020," + * in Digital Signal Processing Applications with the TMS320 Family, + * pp. 415-437, Texas Instruments, Inc., 1986. + * + * A pdf of which is available by searching on the document title at http://www.ti.com/ + * + */ + +#ifndef _MARK2_ECHO_H +#define _MARK2_ECHO_H + +#include +#include +#include + +#define MALLOC(a) kmalloc((a), GFP_KERNEL) +#define FREE(a) kfree(a) + +/* Uncomment to provide summary statistics for overall echo can performance every 4000 samples */ +/* #define MEC2_STATS 4000 */ + +/* Uncomment to generate per-sample statistics - this will severely degrade system performance and audio quality */ +/* #define MEC2_STATS_DETAILED */ + +/* Get optimized routines for math */ +#include "arith.h" + +/* Bring in definitions for the various constants and thresholds */ +#include "kb1ec_const.h" + +#ifndef NULL +#define NULL 0 +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +/* Generic circular buffer definition */ +typedef struct { + /* Pointer to the relative 'start' of the buffer */ + int idx_d; + /* The absolute size of the buffer */ + int size_d; + /* The actual sample - twice as large as we need, however we do store values at idx_d and idx_d+size_d */ + short *buf_d; +} echo_can_cb_s; + +/* Echo canceller definition */ +struct echo_can_state { + /* an arbitrary ID for this echo can - this really should be settable from the calling channel... */ + int id; + + /* absolute time - aka. sample number index - essentially the number of samples since this can was init'ed */ + int i_d; + + /* Pre-computed constants */ + /* ---------------------- */ + /* Number of filter coefficents */ + int N_d; + /* Rate of adaptation of filter */ + int beta2_i; + + /* Accumulators for power computations */ + /* ----------------------------------- */ + /* reference signal power estimate - aka. Average absolute value of y(k) */ + int Ly_i; + /* ... */ + int Lu_i; + + /* Accumulators for signal detectors */ + /* --------------------------------- */ + /* Power estimate of the recent past of the near-end hybrid signal - aka. Short-time average of: 2 x |s(i)| */ + int s_tilde_i; + /* Power estimate of the recent past of the far-end receive signal - aka. Short-time average of: |y(i)| */ + int y_tilde_i; + + /* Near end speech detection counter - stores Hangover counter time remaining, in samples */ + int HCNTR_d; + + /* Circular buffers and coefficients */ + /* --------------------------------- */ + /* ... */ + int *a_i; + /* ... */ + short *a_s; + /* Reference samples of far-end receive signal */ + echo_can_cb_s y_s; + /* Reference samples of near-end signal */ + echo_can_cb_s s_s; + /* Reference samples of near-end signal minus echo estimate */ + echo_can_cb_s u_s; + /* Reference samples of far-end receive signal used to calculate short-time average */ + echo_can_cb_s y_tilde_s; + + /* Peak far-end receive signal */ + /* --------------------------- */ + /* Highest y_tilde value in the sample buffer */ + short max_y_tilde; + /* Index of the sample containing the max_y_tilde value */ + int max_y_tilde_pos; + +#ifdef MEC2_STATS + /* Storage for performance statistics */ + int cntr_nearend_speech_frames; + int cntr_residualcorrected_frames; + int cntr_residualcorrected_framesskipped; + int cntr_coeff_updates; + int cntr_coeff_missedupdates; + + int avg_Lu_i_toolow; + int avg_Lu_i_ok; +#endif + unsigned int aggressive:1; +}; + +static void echo_can_init(void) +{ + printk("Zaptel Echo Canceller: KB1\n"); +} + +static void echo_can_identify(char *buf, size_t len) +{ + strncpy(buf, "KB1", len); +} + +static void echo_can_shutdown(void) +{ +} + +static inline void init_cb_s(echo_can_cb_s *cb, int len, void *where) +{ + cb->buf_d = (short *)where; + cb->idx_d = 0; + cb->size_d = len; +} + +static inline void add_cc_s(echo_can_cb_s *cb, short newval) +{ + /* Can't use modulus because N+M isn't a power of two (generally) */ + cb->idx_d--; + if (cb->idx_d < (int)0) + /* Whoops - the pointer to the 'start' wrapped around so reset it to the top of the buffer */ + cb->idx_d += cb->size_d; + + /* Load two copies into memory */ + cb->buf_d[cb->idx_d] = newval; + cb->buf_d[cb->idx_d + cb->size_d] = newval; +} + +static inline short get_cc_s(echo_can_cb_s *cb, int pos) +{ + /* Load two copies into memory */ + return cb->buf_d[cb->idx_d + pos]; +} + +static inline void init_cc(struct echo_can_state *ec, int N, int maxy, int maxu) +{ + + void *ptr = ec; + unsigned long tmp; + /* Double-word align past end of state */ + ptr += sizeof(struct echo_can_state); + tmp = (unsigned long)ptr; + tmp += 3; + tmp &= ~3L; + ptr = (void *)tmp; + + /* Reset parameters */ + ec->N_d = N; + ec->beta2_i = DEFAULT_BETA1_I; + + /* Allocate coefficient memory */ + ec->a_i = ptr; + ptr += (sizeof(int) * ec->N_d); + ec->a_s = ptr; + ptr += (sizeof(short) * ec->N_d); + + /* Reset Y circular buffer (short version) */ + init_cb_s(&ec->y_s, maxy, ptr); + ptr += (sizeof(short) * (maxy) * 2); + + /* Reset Sigma circular buffer (short version for FIR filter) */ + init_cb_s(&ec->s_s, (1 << DEFAULT_ALPHA_ST_I), ptr); + ptr += (sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) * 2); + + init_cb_s(&ec->u_s, maxu, ptr); + ptr += (sizeof(short) * maxu * 2); + + /* Allocate a buffer for the reference signal power computation */ + init_cb_s(&ec->y_tilde_s, ec->N_d, ptr); + + /* Reset the absolute time index */ + ec->i_d = (int)0; + + /* Reset the power computations (for y and u) */ + ec->Ly_i = DEFAULT_CUTOFF_I; + ec->Lu_i = DEFAULT_CUTOFF_I; + +#ifdef MEC2_STATS + /* set the identity */ + ec->id = (int)&ptr; + + /* Reset performance stats */ + ec->cntr_nearend_speech_frames = (int)0; + ec->cntr_residualcorrected_frames = (int)0; + ec->cntr_residualcorrected_framesskipped = (int)0; + ec->cntr_coeff_updates = (int)0; + ec->cntr_coeff_missedupdates = (int)0; + + ec->avg_Lu_i_toolow = (int)0; + ec->avg_Lu_i_ok = (int)0; +#endif + + /* Reset the near-end speech detector */ + ec->s_tilde_i = (int)0; + ec->y_tilde_i = (int)0; + ec->HCNTR_d = (int)0; + +} + +static inline void echo_can_free(struct echo_can_state *ec) +{ + FREE(ec); +} + +static inline short echo_can_update(struct echo_can_state *ec, short iref, short isig) +{ + + /* Declare local variables that are used more than once */ + /* ... */ + int k; + /* ... */ + int rs; + /* ... */ + short u; + /* ... */ + int Py_i; + /* ... */ + int two_beta_i; + + /* flow A on pg. 428 */ + /* eq. (16): high-pass filter the input to generate the next value; + * push the current value into the circular buffer + * + * sdc_im1_d = sdc_d; + * sdc_d = sig; + * s_i_d = sdc_d; + * s_d = s_i_d; + * s_i_d = (float)(1.0 - gamma_d) * s_i_d + * + (float)(0.5 * (1.0 - gamma_d)) * (sdc_d - sdc_im1_d); + */ + + /* Update the Far-end receive signal circular buffers and accumulators */ + /* ------------------------------------------------------------------- */ + /* Delete the oldest sample from the power estimate accumulator */ + ec->y_tilde_i -= abs(get_cc_s(&ec->y_s, (1 << DEFAULT_ALPHA_YT_I) - 1 )) >> DEFAULT_ALPHA_YT_I; + /* Add the new sample to the power estimate accumulator */ + ec->y_tilde_i += abs(iref) >> DEFAULT_ALPHA_ST_I; + /* Push a copy of the new sample into its circular buffer */ + add_cc_s(&ec->y_s, iref); + + + /* eq. (2): compute r in fixed-point */ + rs = CONVOLVE2(ec->a_s, + ec->y_s.buf_d + ec->y_s.idx_d, + ec->N_d); + rs >>= 15; + + /* eq. (3): compute the output value (see figure 3) and the error + * note: the error is the same as the output signal when near-end + * speech is not present + */ + u = isig - rs; + + /* Push a copy of the output value sample into its circular buffer */ + add_cc_s(&ec->u_s, u); + + + /* Update the Near-end hybrid signal circular buffers and accumulators */ + /* ------------------------------------------------------------------- */ + /* Delete the oldest sample from the power estimate accumulator */ + ec->s_tilde_i -= abs(get_cc_s(&ec->s_s, (1 << DEFAULT_ALPHA_ST_I) - 1 )); + /* Add the new sample to the power estimate accumulator */ + ec->s_tilde_i += abs(isig); + /* Push a copy of the new sample into it's circular buffer */ + add_cc_s(&ec->s_s, isig); + + + /* Push a copy of the current short-time average of the far-end receive signal into it's circular buffer */ + add_cc_s(&ec->y_tilde_s, ec->y_tilde_i); + + /* flow B on pg. 428 */ + + /* If the hangover timer isn't running then compute the new convergence factor, otherwise set Py_i to 32768 */ + if (!ec->HCNTR_d) { + Py_i = (ec->Ly_i >> DEFAULT_SIGMA_LY_I) * (ec->Ly_i >> DEFAULT_SIGMA_LY_I); + Py_i >>= 15; + } else { + Py_i = (1 << 15); + } + +#if 0 + /* Vary rate of adaptation depending on position in the file + * Do not do this for the first (DEFAULT_UPDATE_TIME) secs after speech + * has begun of the file to allow the echo cancellor to estimate the + * channel accurately + * Still needs conversion! + */ + + if (ec->start_speech_d != 0 ){ + if ( ec->i_d > (DEFAULT_T0 + ec->start_speech_d)*(SAMPLE_FREQ) ){ + ec->beta2_d = max_cc_float(MIN_BETA, DEFAULT_BETA1 * exp((-1/DEFAULT_TAU)*((ec->i_d/(float)SAMPLE_FREQ) - DEFAULT_T0 - ec->start_speech_d))); + } + } else { + ec->beta2_d = DEFAULT_BETA1; + } +#endif + + /* Fixed point, inverted */ + ec->beta2_i = DEFAULT_BETA1_I; + + /* Fixed point version, inverted */ + two_beta_i = (ec->beta2_i * Py_i) >> 15; + if (!two_beta_i) + two_beta_i++; + + /* Update the Suppressed signal power estimate accumulator */ + /* ------------------------------------------------------- */ + /* Delete the oldest sample from the power estimate accumulator */ + ec->Lu_i -= abs(get_cc_s(&ec->u_s, (1 << DEFAULT_SIGMA_LU_I) - 1 )) ; + /* Add the new sample to the power estimate accumulator */ + ec->Lu_i += abs(u); + + /* Update the Far-end reference signal power estimate accumulator */ + /* -------------------------------------------------------------- */ + /* eq. (10): update power estimate of the reference */ + /* Delete the oldest sample from the power estimate accumulator */ + ec->Ly_i -= abs(get_cc_s(&ec->y_s, (1 << DEFAULT_SIGMA_LY_I) - 1)) ; + /* Add the new sample to the power estimate accumulator */ + ec->Ly_i += abs(iref); + + if (ec->Ly_i < DEFAULT_CUTOFF_I) + ec->Ly_i = DEFAULT_CUTOFF_I; + + + /* Update the Peak far-end receive signal detected */ + /* ----------------------------------------------- */ + if (ec->y_tilde_i > ec->max_y_tilde) { + /* New highest y_tilde with full life */ + ec->max_y_tilde = ec->y_tilde_i; + ec->max_y_tilde_pos = ec->N_d - 1; + } else if (--ec->max_y_tilde_pos < 0) { + /* Time to find new max y tilde... */ + ec->max_y_tilde = MAX16(ec->y_tilde_s.buf_d + ec->y_tilde_s.idx_d, ec->N_d, &ec->max_y_tilde_pos); + } + + /* Determine if near end speech was detected in this sample */ + /* -------------------------------------------------------- */ + if (((ec->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)) > ec->max_y_tilde) + && (ec->max_y_tilde > 0)) { + /* Then start the Hangover counter */ + ec->HCNTR_d = DEFAULT_HANGT; +#ifdef MEC2_STATS_DETAILED + printk(KERN_INFO "Reset near end speech timer with: s_tilde_i %d, stmnt %d, max_y_tilde %d\n", ec->s_tilde_i, (ec->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)), ec->max_y_tilde); +#endif +#ifdef MEC2_STATS + ++ec->cntr_nearend_speech_frames; +#endif + } else if (ec->HCNTR_d > (int)0) { + /* otherwise, if it's still non-zero, decrement the Hangover counter by one sample */ +#ifdef MEC2_STATS + ++ec->cntr_nearend_speech_frames; +#endif + ec->HCNTR_d--; + } + + /* Update coefficients if no near-end speech in this sample (ie. HCNTR_d = 0) + * and we have enough signal to bother trying to update. + * -------------------------------------------------------------------------- + */ + if (!ec->HCNTR_d && /* no near-end speech present */ + !(ec->i_d % DEFAULT_M)) { /* we only update on every DEFAULM_M'th sample from the stream */ + if (ec->Lu_i > MIN_UPDATE_THRESH_I) { /* there is sufficient energy above the noise floor to contain meaningful data */ + /* so loop over all the filter coefficients */ +#ifdef MEC2_STATS_DETAILED + printk( KERN_INFO "updating coefficients with: ec->Lu_i %9d\n", ec->Lu_i); +#endif +#ifdef MEC2_STATS + ec->avg_Lu_i_ok = ec->avg_Lu_i_ok + ec->Lu_i; + ++ec->cntr_coeff_updates; +#endif + for (k=0; k < ec->N_d; k++) { + /* eq. (7): compute an expectation over M_d samples */ + int grad2; + grad2 = CONVOLVE2(ec->u_s.buf_d + ec->u_s.idx_d, + ec->y_s.buf_d + ec->y_s.idx_d + k, + DEFAULT_M); + /* eq. (7): update the coefficient */ + ec->a_i[k] += grad2 / two_beta_i; + ec->a_s[k] = ec->a_i[k] >> 16; + } + } else { +#ifdef MEC2_STATS_DETAILED + printk( KERN_INFO "insufficient signal to update coefficients ec->Lu_i %5d < %5d\n", ec->Lu_i, MIN_UPDATE_THRESH_I); +#endif +#ifdef MEC2_STATS + ec->avg_Lu_i_toolow = ec->avg_Lu_i_toolow + ec->Lu_i; + ++ec->cntr_coeff_missedupdates; +#endif + } + } + + /* paragraph below eq. (15): if no near-end speech in the sample and + * the reference signal power estimate > cutoff threshold + * then perform residual error suppression + */ +#ifdef MEC2_STATS_DETAILED + if (ec->HCNTR_d == 0) + printk( KERN_INFO "possibily correcting frame with ec->Ly_i %9d ec->Lu_i %9d and expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1))); +#endif + +#ifndef NO_ECHO_SUPPRESSOR + if (ec->aggressive) { + if ((ec->HCNTR_d < AGGRESSIVE_HCNTR) && (ec->Ly_i > (ec->Lu_i << 1))) { + for (k=0; k < 2; k++) { + u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I)) + 1); + } +#ifdef MEC2_STATS_DETAILED + printk( KERN_INFO "aggresively correcting frame with ec->Ly_i %9d ec->Lu_i %9d expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1))); +#endif +#ifdef MEC2_STATS + ++ec->cntr_residualcorrected_frames; +#endif + } + } else { + if (ec->HCNTR_d == 0) { + if ((ec->Ly_i/(ec->Lu_i + 1)) > DEFAULT_SUPPR_I) { + for (k=0; k < 1; k++) { + u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I + 2)) + 1); + } +#ifdef MEC2_STATS_DETAILED + printk( KERN_INFO "correcting frame with ec->Ly_i %9d ec->Lu_i %9d expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1))); +#endif +#ifdef MEC2_STATS + ++ec->cntr_residualcorrected_frames; +#endif + } +#ifdef MEC2_STATS + else { + ++ec->cntr_residualcorrected_framesskipped; + } +#endif + } + } +#endif + +#if 0 + /* This will generate a non-linear supression factor, once converted */ + if ((ec->HCNTR_d == 0) && + ((ec->Lu_d/ec->Ly_d) < DEFAULT_SUPPR) && + (ec->Lu_d/ec->Ly_d > EC_MIN_DB_VALUE)) { + suppr_factor = (10 / (float)(SUPPR_FLOOR - SUPPR_CEIL)) * log(ec->Lu_d/ec->Ly_d) + - SUPPR_CEIL / (float)(SUPPR_FLOOR - SUPPR_CEIL); + u_suppr = pow(10.0, (suppr_factor) * RES_SUPR_FACTOR / 10.0) * u_suppr; + } +#endif + +#ifdef MEC2_STATS + /* Periodically dump performance stats */ + if ((ec->i_d % MEC2_STATS) == 0) { + /* make sure to avoid div0's! */ + if (ec->cntr_coeff_missedupdates > 0) + ec->avg_Lu_i_toolow = (int)(ec->avg_Lu_i_toolow / ec->cntr_coeff_missedupdates); + else + ec->avg_Lu_i_toolow = -1; + + if (ec->cntr_coeff_updates > 0) + ec->avg_Lu_i_ok = (ec->avg_Lu_i_ok / ec->cntr_coeff_updates); + else + ec->avg_Lu_i_ok = -1; + + printk( KERN_INFO "%d: Near end speech: %5d Residuals corrected/skipped: %5d/%5d Coefficients updated ok/low sig: %3d/%3d Lu_i avg ok/low sig %6d/%5d\n", + ec->id, + ec->cntr_nearend_speech_frames, + ec->cntr_residualcorrected_frames, ec->cntr_residualcorrected_framesskipped, + ec->cntr_coeff_updates, ec->cntr_coeff_missedupdates, + ec->avg_Lu_i_ok, ec->avg_Lu_i_toolow); + + ec->cntr_nearend_speech_frames = 0; + ec->cntr_residualcorrected_frames = 0; + ec->cntr_residualcorrected_framesskipped = 0; + ec->cntr_coeff_updates = 0; + ec->cntr_coeff_missedupdates = 0; + ec->avg_Lu_i_ok = 0; + ec->avg_Lu_i_toolow = 0; + } +#endif + + /* Increment the sample index and return the corrected sample */ + ec->i_d++; + return u; +} + +static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p, + struct echo_can_state **ec) +{ + int maxy; + int maxu; + size_t size; + unsigned int x; + char *c; + + maxy = ecp->tap_length + DEFAULT_M; + maxu = DEFAULT_M; + if (maxy < (1 << DEFAULT_ALPHA_YT_I)) + maxy = (1 << DEFAULT_ALPHA_YT_I); + if (maxy < (1 << DEFAULT_SIGMA_LY_I)) + maxy = (1 << DEFAULT_SIGMA_LY_I); + if (maxu < (1 << DEFAULT_SIGMA_LU_I)) + maxu = (1 << DEFAULT_SIGMA_LU_I); + + size = sizeof(*ec) + + 4 + /* align */ + sizeof(int) * ecp->tap_length + /* a_i */ + sizeof(short) * ecp->tap_length + /* a_s */ + 2 * sizeof(short) * (maxy) + /* y_s */ + 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */ + 2 * sizeof(short) * (maxu) + /* u_s */ + 2 * sizeof(short) * ecp->tap_length; /* y_tilde_s */ + + if (!(*ec = MALLOC(size))) + return -ENOMEM; + + memset(*ec, 0, size); + +#ifdef AGGRESSIVE_SUPPRESSOR + (*ec)->aggressive = 1; +#endif + + for (x = 0; x < ecp->param_count; x++) { + for (c = p[x].name; *c; c++) + *c = tolower(*c); + if (!strcmp(p[x].name, "aggressive")) { + (*ec)->aggressive = p[x].value ? 1 : 0; + } else { + printk(KERN_WARNING "Unknown parameter supplied to KB1 echo canceler: '%s'\n", p[x].name); + kfree(*ec); + + return -EINVAL; + } + } + + init_cc(*ec, ecp->tap_length, maxy, maxu); + + return 0; +} + +static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) +{ + /* Set the hangover counter to the length of the can to + * avoid adjustments occuring immediately after initial forced training + */ + ec->HCNTR_d = ec->N_d << 1; + + if (pos >= ec->N_d) + return 1; + + ec->a_i[pos] = val << 17; + ec->a_s[pos] = val << 1; + + if (++pos >= ec->N_d) + return 1; + + return 0; +} + +#endif diff --git a/kernel/kb1ec_const.h b/kernel/kb1ec_const.h new file mode 100644 index 0000000..0849b14 --- /dev/null +++ b/kernel/kb1ec_const.h @@ -0,0 +1,72 @@ +/* + Important constants for tuning kb1 echo can + */ +#ifndef _MEC2_CONST_H +#define _MEC2_CONST_H + + +/* Convergence (aka. adaptation) speed -- higher means slower */ +#define DEFAULT_BETA1_I 2048 + +/* Constants for various power computations */ +#define DEFAULT_SIGMA_LY_I 7 +#define DEFAULT_SIGMA_LU_I 7 +#define DEFAULT_ALPHA_ST_I 5 /* near-end speech detection sensitivity factor */ +#define DEFAULT_ALPHA_YT_I 5 + +#define DEFAULT_CUTOFF_I 128 + +/* Define the near-end speech hangover counter: if near-end speech + * is declared, hcntr is set equal to hangt (see pg. 432) + */ +#define DEFAULT_HANGT 600 /* in samples, so 600 samples = 75ms */ + +/* define the residual error suppression threshold */ +#define DEFAULT_SUPPR_I 16 /* 16 = -24db */ + +/* This is the minimum reference signal power estimate level + * that will result in filter adaptation. + * If this is too low then background noise will cause the filter + * coefficients to constantly be updated. + */ +#define MIN_UPDATE_THRESH_I 4096 + +/* The number of samples used to update coefficients using the + * the block update method (M). It should be related back to the + * length of the echo can. + * ie. it only updates coefficients when (sample number MOD default_m) = 0 + * + * Getting this wrong may cause an oops. Consider yourself warned! + */ +#define DEFAULT_M 16 /* every 16th sample */ + +/* If AGGRESSIVE supression is enabled, then we start cancelling residual + * echos again even while there is potentially the very end of a near-side + * signal present. + * This defines how many samples of DEFAULT_HANGT can remain before we + * kick back in + */ +#define AGGRESSIVE_HCNTR 160 /* in samples, so 160 samples = 20ms */ + + +/***************************************************************/ +/* The following knobs are not implemented in the current code */ + +/* we need a dynamic level of suppression varying with the ratio of the + power of the echo to the power of the reference signal this is + done so that we have a smoother background. + we have a higher suppression when the power ratio is closer to + suppr_ceil and reduces logarithmically as we approach suppr_floor. + */ +#define SUPPR_FLOOR -64 +#define SUPPR_CEIL -24 + +/* in a second departure, we calculate the residual error suppression + * as a percentage of the reference signal energy level. The threshold + * is defined in terms of dB below the reference signal. + */ +#define RES_SUPR_FACTOR -20 + + +#endif /* _MEC2_CONST_H */ + diff --git a/kernel/makefw.c b/kernel/makefw.c new file mode 100644 index 0000000..6a5b0d9 --- /dev/null +++ b/kernel/makefw.c @@ -0,0 +1,88 @@ +/* Xilinx firmware convertor program. + * + * + * Written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001 Linux Support Services, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under thet erms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Primary Author: Mark Spencer + * + */ + +#include +#include +#include + +#define SWATH 12 + +int main(int argc, char *argv[]) +{ +FILE *fp; +int i,j,nbytes; +unsigned char c; +char buf[300]; + + if (argc < 3) + { + puts("Usage... makefw filename.rbt array_name"); + exit(1); + } + + fp = fopen(argv[1],"r"); + if (!fp) + { + perror("bit file open"); + exit(1); + } + nbytes = 0; + printf("static unsigned char %s[] = {\n",argv[2]); + i = 0; + while(fgets(buf,sizeof(buf) - 1,fp)) + { + if (!buf[0]) continue; + if (buf[strlen(buf) - 1] < ' ') buf[strlen(buf) - 1] = 0; + if (!buf[0]) continue; + if (buf[strlen(buf) - 1] < ' ') buf[strlen(buf) - 1] = 0; + if (!buf[0]) continue; + if (strlen(buf) < 32) continue; + if ((buf[0] != '0') && (buf[0] != '1')) continue; + c = 0; + for(j = 0; buf[j]; j++) + { + if (buf[j] > '0') c |= 1 << (j & 7); + if ((j & 7) == 7) + { + nbytes++; + if (i) printf(","); + printf("0x%02x",c); + if (i++ == SWATH) { + printf(",\n"); + i = 0; + } + c = 0; + } + } + } + printf("\n};\n\n"); + fprintf(stderr,"Loaded %d bytes from file\n",nbytes); + fclose(fp); + exit(0); +} + diff --git a/kernel/mg2ec.h b/kernel/mg2ec.h new file mode 100644 index 0000000..2dc3597 --- /dev/null +++ b/kernel/mg2ec.h @@ -0,0 +1,725 @@ +/* + * ECHO_CAN_MG2 + * + * by Michael Gernoth + * + * Based upon kb1ec.h and mec2.h + * + * Copyright (C) 2002, Digium, Inc. + * + * This program is free software and may be used and + * distributed according to the terms of the GNU + * General Public License, incorporated herein by + * reference. + * + * Additional background on the techniques used in this code can be found in: + * + * Messerschmitt, David; Hedberg, David; Cole, Christopher; Haoui, Amine; + * Winship, Peter; "Digital Voice Echo Canceller with a TMS32020," + * in Digital Signal Processing Applications with the TMS320 Family, + * pp. 415-437, Texas Instruments, Inc., 1986. + * + * A pdf of which is available by searching on the document title at http://www.ti.com/ + * + */ + +#ifndef _MG2_ECHO_H +#define _MG2_ECHO_H + +#include +#include +#include + +#define MALLOC(a) kmalloc((a), GFP_KERNEL) +#define FREE(a) kfree(a) + +#define ABS(a) abs(a!=-32768?a:-32767) + +#define RESTORE_COEFFS {\ + int x;\ + memcpy(ec->a_i, ec->c_i, ec->N_d*sizeof(int));\ + for (x=0;xN_d;x++) {\ + ec->a_s[x] = ec->a_i[x] >> 16;\ + }\ + ec->backup = BACKUP;\ + } + +/* Uncomment to provide summary statistics for overall echo can performance every 4000 samples */ +/* #define MEC2_STATS 4000 */ + +/* Uncomment to generate per-sample statistics - this will severely degrade system performance and audio quality */ +/* #define MEC2_STATS_DETAILED */ + +/* Uncomment to generate per-call DC bias offset messages */ +/* #define MEC2_DCBIAS_MESSAGE */ + +/* Get optimized routines for math */ +#include "arith.h" + +/* Bring in definitions for the various constants and thresholds */ +#include "mg2ec_const.h" + +#define DC_NORMALIZE + +#ifndef NULL +#define NULL 0 +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +/* Generic circular buffer definition */ +typedef struct { + /* Pointer to the relative 'start' of the buffer */ + int idx_d; + /* The absolute size of the buffer */ + int size_d; + /* The actual sample - twice as large as we need, however we do store values at idx_d and idx_d+size_d */ + short *buf_d; +} echo_can_cb_s; + +/* Echo canceller definition */ +struct echo_can_state { + /* an arbitrary ID for this echo can - this really should be settable from the calling channel... */ + int id; + + /* absolute time - aka. sample number index - essentially the number of samples since this can was init'ed */ + int i_d; + + /* Pre-computed constants */ + /* ---------------------- */ + /* Number of filter coefficents */ + int N_d; + /* Rate of adaptation of filter */ + int beta2_i; + + /* Accumulators for power computations */ + /* ----------------------------------- */ + /* reference signal power estimate - aka. Average absolute value of y(k) */ + int Ly_i; + /* ... */ + int Lu_i; + + /* Accumulators for signal detectors */ + /* --------------------------------- */ + /* Power estimate of the recent past of the near-end hybrid signal - aka. Short-time average of: 2 x |s(i)| */ + int s_tilde_i; + /* Power estimate of the recent past of the far-end receive signal - aka. Short-time average of: |y(i)| */ + int y_tilde_i; + + /* Near end speech detection counter - stores Hangover counter time remaining, in samples */ + int HCNTR_d; + + /* Circular buffers and coefficients */ + /* --------------------------------- */ + /* ... */ + int *a_i; + /* ... */ + short *a_s; + /* Backups */ + int *b_i; + int *c_i; + /* Reference samples of far-end receive signal */ + echo_can_cb_s y_s; + /* Reference samples of near-end signal */ + echo_can_cb_s s_s; + /* Reference samples of near-end signal minus echo estimate */ + echo_can_cb_s u_s; + /* Reference samples of far-end receive signal used to calculate short-time average */ + echo_can_cb_s y_tilde_s; + + /* Peak far-end receive signal */ + /* --------------------------- */ + /* Highest y_tilde value in the sample buffer */ + short max_y_tilde; + /* Index of the sample containing the max_y_tilde value */ + int max_y_tilde_pos; + +#ifdef MEC2_STATS + /* Storage for performance statistics */ + int cntr_nearend_speech_frames; + int cntr_residualcorrected_frames; + int cntr_residualcorrected_framesskipped; + int cntr_coeff_updates; + int cntr_coeff_missedupdates; + + int avg_Lu_i_toolow; + int avg_Lu_i_ok; +#endif + unsigned int aggressive:1; + short lastsig; + int lastcount; + int backup; +#ifdef DC_NORMALIZE + int dc_estimate; +#endif + +}; + +static void echo_can_init(void) +{ + printk("Zaptel Echo Canceller: MG2\n"); +} + +static void echo_can_identify(char *buf, size_t len) +{ + strncpy(buf, "MG2", len); +} + +static void echo_can_shutdown(void) +{ +} + +static inline void init_cb_s(echo_can_cb_s *cb, int len, void *where) +{ + cb->buf_d = (short *)where; + cb->idx_d = 0; + cb->size_d = len; +} + +static inline void add_cc_s(echo_can_cb_s *cb, short newval) +{ + /* Can't use modulus because N+M isn't a power of two (generally) */ + cb->idx_d--; + if (cb->idx_d < (int)0) + /* Whoops - the pointer to the 'start' wrapped around so reset it to the top of the buffer */ + cb->idx_d += cb->size_d; + + /* Load two copies into memory */ + cb->buf_d[cb->idx_d] = newval; + cb->buf_d[cb->idx_d + cb->size_d] = newval; +} + +static inline short get_cc_s(echo_can_cb_s *cb, int pos) +{ + /* Load two copies into memory */ + return cb->buf_d[cb->idx_d + pos]; +} + +static inline void init_cc(struct echo_can_state *ec, int N, int maxy, int maxu) +{ + + void *ptr = ec; + unsigned long tmp; + /* Double-word align past end of state */ + ptr += sizeof(struct echo_can_state); + tmp = (unsigned long)ptr; + tmp += 3; + tmp &= ~3L; + ptr = (void *)tmp; + + /* Reset parameters */ + ec->N_d = N; + ec->beta2_i = DEFAULT_BETA1_I; + + /* Allocate coefficient memory */ + ec->a_i = ptr; + ptr += (sizeof(int) * ec->N_d); + ec->a_s = ptr; + ptr += (sizeof(short) * ec->N_d); + + /* Allocate backup memory */ + ec->b_i = ptr; + ptr += (sizeof(int) * ec->N_d); + ec->c_i = ptr; + ptr += (sizeof(int) * ec->N_d); + + /* Reset Y circular buffer (short version) */ + init_cb_s(&ec->y_s, maxy, ptr); + ptr += (sizeof(short) * (maxy) * 2); + + /* Reset Sigma circular buffer (short version for FIR filter) */ + init_cb_s(&ec->s_s, (1 << DEFAULT_ALPHA_ST_I), ptr); + ptr += (sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) * 2); + + init_cb_s(&ec->u_s, maxu, ptr); + ptr += (sizeof(short) * maxu * 2); + + /* Allocate a buffer for the reference signal power computation */ + init_cb_s(&ec->y_tilde_s, ec->N_d, ptr); + + /* Reset the absolute time index */ + ec->i_d = (int)0; + + /* Reset the power computations (for y and u) */ + ec->Ly_i = DEFAULT_CUTOFF_I; + ec->Lu_i = DEFAULT_CUTOFF_I; + +#ifdef MEC2_STATS + /* set the identity */ + ec->id = (int)&ptr; + + /* Reset performance stats */ + ec->cntr_nearend_speech_frames = (int)0; + ec->cntr_residualcorrected_frames = (int)0; + ec->cntr_residualcorrected_framesskipped = (int)0; + ec->cntr_coeff_updates = (int)0; + ec->cntr_coeff_missedupdates = (int)0; + + ec->avg_Lu_i_toolow = (int)0; + ec->avg_Lu_i_ok = (int)0; +#endif + + /* Reset the near-end speech detector */ + ec->s_tilde_i = (int)0; + ec->y_tilde_i = (int)0; + ec->HCNTR_d = (int)0; + +} + +static inline void echo_can_free(struct echo_can_state *ec) +{ +#if defined(DC_NORMALIZE) && defined(MEC2_DCBIAS_MESSAGE) + printk("EC: DC bias calculated: %d V\n", ec->dc_estimate >> 15); +#endif + FREE(ec); +} + +#ifdef DC_NORMALIZE +short inline dc_removal(int *dc_estimate, short samp) +{ + *dc_estimate += ((((int)samp << 15) - *dc_estimate) >> 9); + return samp - (*dc_estimate >> 15); +} +#endif + +static inline short echo_can_update(struct echo_can_state *ec, short iref, short isig) +{ + + /* Declare local variables that are used more than once */ + /* ... */ + int k; + /* ... */ + int rs; + /* ... */ + short u; + /* ... */ + int Py_i; + /* ... */ + int two_beta_i; + +#ifdef DC_NORMALIZE + isig = dc_removal(&ec->dc_estimate, isig); +#endif + + /* flow A on pg. 428 */ + /* eq. (16): high-pass filter the input to generate the next value; + * push the current value into the circular buffer + * + * sdc_im1_d = sdc_d; + * sdc_d = sig; + * s_i_d = sdc_d; + * s_d = s_i_d; + * s_i_d = (float)(1.0 - gamma_d) * s_i_d + * + (float)(0.5 * (1.0 - gamma_d)) * (sdc_d - sdc_im1_d); + */ + + /* Update the Far-end receive signal circular buffers and accumulators */ + /* ------------------------------------------------------------------- */ + /* Delete the oldest sample from the power estimate accumulator */ + ec->y_tilde_i -= abs(get_cc_s(&ec->y_s, (1 << DEFAULT_ALPHA_YT_I) - 1 )) >> DEFAULT_ALPHA_YT_I; + /* Add the new sample to the power estimate accumulator */ + ec->y_tilde_i += abs(iref) >> DEFAULT_ALPHA_ST_I; + /* Push a copy of the new sample into its circular buffer */ + add_cc_s(&ec->y_s, iref); + + + /* eq. (2): compute r in fixed-point */ + rs = CONVOLVE2(ec->a_s, + ec->y_s.buf_d + ec->y_s.idx_d, + ec->N_d); + rs >>= 15; + + if (ec->lastsig == isig) { + ec->lastcount++; + } else { + ec->lastcount = 0; + ec->lastsig = isig; + } + + if (isig == 0) { + u = 0; + } else if (ec->lastcount > 255) { + /* We have seen the same input-signal more than 255 times, + * we should pass it through uncancelled, as we are likely on hold */ + u = isig; + } else { + if (rs < -32768) { + rs = -32768; + ec->HCNTR_d = DEFAULT_HANGT; + RESTORE_COEFFS; + } else if (rs > 32767) { + rs = 32767; + ec->HCNTR_d = DEFAULT_HANGT; + RESTORE_COEFFS; + } + + if (ABS(ABS(rs)-ABS(isig)) > MAX_SIGN_ERROR) + { + rs = 0; + RESTORE_COEFFS; + } + + /* eq. (3): compute the output value (see figure 3) and the error + * note: the error is the same as the output signal when near-end + * speech is not present + */ + u = isig - rs; + + if (u / isig < 0) + u = isig - (rs >> 1); + } + + /* Push a copy of the output value sample into its circular buffer */ + add_cc_s(&ec->u_s, u); + + if (!ec->backup) { + /* Backup coefficients periodically */ + ec->backup = BACKUP; + memcpy(ec->c_i,ec->b_i,ec->N_d*sizeof(int)); + memcpy(ec->b_i,ec->a_i,ec->N_d*sizeof(int)); + } else + ec->backup--; + + + /* Update the Near-end hybrid signal circular buffers and accumulators */ + /* ------------------------------------------------------------------- */ + /* Delete the oldest sample from the power estimate accumulator */ + ec->s_tilde_i -= abs(get_cc_s(&ec->s_s, (1 << DEFAULT_ALPHA_ST_I) - 1 )); + /* Add the new sample to the power estimate accumulator */ + ec->s_tilde_i += abs(isig); + /* Push a copy of the new sample into it's circular buffer */ + add_cc_s(&ec->s_s, isig); + + + /* Push a copy of the current short-time average of the far-end receive signal into it's circular buffer */ + add_cc_s(&ec->y_tilde_s, ec->y_tilde_i); + + /* flow B on pg. 428 */ + + /* If the hangover timer isn't running then compute the new convergence factor, otherwise set Py_i to 32768 */ + if (!ec->HCNTR_d) { + Py_i = (ec->Ly_i >> DEFAULT_SIGMA_LY_I) * (ec->Ly_i >> DEFAULT_SIGMA_LY_I); + Py_i >>= 15; + } else { + Py_i = (1 << 15); + } + +#if 0 + /* Vary rate of adaptation depending on position in the file + * Do not do this for the first (DEFAULT_UPDATE_TIME) secs after speech + * has begun of the file to allow the echo cancellor to estimate the + * channel accurately + * Still needs conversion! + */ + + if (ec->start_speech_d != 0 ){ + if ( ec->i_d > (DEFAULT_T0 + ec->start_speech_d)*(SAMPLE_FREQ) ){ + ec->beta2_d = max_cc_float(MIN_BETA, DEFAULT_BETA1 * exp((-1/DEFAULT_TAU)*((ec->i_d/(float)SAMPLE_FREQ) - DEFAULT_T0 - ec->start_speech_d))); + } + } else { + ec->beta2_d = DEFAULT_BETA1; + } +#endif + + /* Fixed point, inverted */ + ec->beta2_i = DEFAULT_BETA1_I; + + /* Fixed point version, inverted */ + two_beta_i = (ec->beta2_i * Py_i) >> 15; + if (!two_beta_i) + two_beta_i++; + + /* Update the Suppressed signal power estimate accumulator */ + /* ------------------------------------------------------- */ + /* Delete the oldest sample from the power estimate accumulator */ + ec->Lu_i -= abs(get_cc_s(&ec->u_s, (1 << DEFAULT_SIGMA_LU_I) - 1 )) ; + /* Add the new sample to the power estimate accumulator */ + ec->Lu_i += abs(u); + + /* Update the Far-end reference signal power estimate accumulator */ + /* -------------------------------------------------------------- */ + /* eq. (10): update power estimate of the reference */ + /* Delete the oldest sample from the power estimate accumulator */ + ec->Ly_i -= abs(get_cc_s(&ec->y_s, (1 << DEFAULT_SIGMA_LY_I) - 1)) ; + /* Add the new sample to the power estimate accumulator */ + ec->Ly_i += abs(iref); + + if (ec->Ly_i < DEFAULT_CUTOFF_I) + ec->Ly_i = DEFAULT_CUTOFF_I; + + + /* Update the Peak far-end receive signal detected */ + /* ----------------------------------------------- */ + if (ec->y_tilde_i > ec->max_y_tilde) { + /* New highest y_tilde with full life */ + ec->max_y_tilde = ec->y_tilde_i; + ec->max_y_tilde_pos = ec->N_d - 1; + } else if (--ec->max_y_tilde_pos < 0) { + /* Time to find new max y tilde... */ + ec->max_y_tilde = MAX16(ec->y_tilde_s.buf_d + ec->y_tilde_s.idx_d, ec->N_d, &ec->max_y_tilde_pos); + } + + /* Determine if near end speech was detected in this sample */ + /* -------------------------------------------------------- */ + if (((ec->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)) > ec->max_y_tilde) + && (ec->max_y_tilde > 0)) { + /* Then start the Hangover counter */ + ec->HCNTR_d = DEFAULT_HANGT; + RESTORE_COEFFS; +#ifdef MEC2_STATS_DETAILED + printk(KERN_INFO "Reset near end speech timer with: s_tilde_i %d, stmnt %d, max_y_tilde %d\n", ec->s_tilde_i, (ec->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)), ec->max_y_tilde); +#endif +#ifdef MEC2_STATS + ++ec->cntr_nearend_speech_frames; +#endif + } else if (ec->HCNTR_d > (int)0) { + /* otherwise, if it's still non-zero, decrement the Hangover counter by one sample */ +#ifdef MEC2_STATS + ++ec->cntr_nearend_speech_frames; +#endif + ec->HCNTR_d--; + } + + /* Update coefficients if no near-end speech in this sample (ie. HCNTR_d = 0) + * and we have enough signal to bother trying to update. + * -------------------------------------------------------------------------- + */ + if (!ec->HCNTR_d && /* no near-end speech present */ + !(ec->i_d % DEFAULT_M)) { /* we only update on every DEFAULM_M'th sample from the stream */ + if (ec->Lu_i > MIN_UPDATE_THRESH_I) { /* there is sufficient energy above the noise floor to contain meaningful data */ + /* so loop over all the filter coefficients */ +#ifdef USED_COEFFS + int max_coeffs[USED_COEFFS]; + int *pos; + + if (ec->N_d > USED_COEFFS) + memset(max_coeffs, 0, USED_COEFFS*sizeof(int)); +#endif +#ifdef MEC2_STATS_DETAILED + printk(KERN_INFO "updating coefficients with: ec->Lu_i %9d\n", ec->Lu_i); +#endif +#ifdef MEC2_STATS + ec->avg_Lu_i_ok = ec->avg_Lu_i_ok + ec->Lu_i; + ++ec->cntr_coeff_updates; +#endif + for (k=0; k < ec->N_d; k++) { + /* eq. (7): compute an expectation over M_d samples */ + int grad2; + grad2 = CONVOLVE2(ec->u_s.buf_d + ec->u_s.idx_d, + ec->y_s.buf_d + ec->y_s.idx_d + k, + DEFAULT_M); + /* eq. (7): update the coefficient */ + ec->a_i[k] += grad2 / two_beta_i; + ec->a_s[k] = ec->a_i[k] >> 16; + +#ifdef USED_COEFFS + if (ec->N_d > USED_COEFFS) { + if (abs(ec->a_i[k]) > max_coeffs[USED_COEFFS-1]) { + /* More or less insertion-sort... */ + pos = max_coeffs; + while (*pos > abs(ec->a_i[k])) + pos++; + + if (*pos > max_coeffs[USED_COEFFS-1]) + memmove(pos+1, pos, (USED_COEFFS-(pos-max_coeffs)-1)*sizeof(int)); + + *pos = abs(ec->a_i[k]); + } + } +#endif + } + +#ifdef USED_COEFFS + /* Filter out irrelevant coefficients */ + if (ec->N_d > USED_COEFFS) + for (k=0; k < ec->N_d; k++) + if (abs(ec->a_i[k]) < max_coeffs[USED_COEFFS-1]) + ec->a_i[k] = ec->a_s[k] = 0; +#endif + } else { +#ifdef MEC2_STATS_DETAILED + printk(KERN_INFO "insufficient signal to update coefficients ec->Lu_i %5d < %5d\n", ec->Lu_i, MIN_UPDATE_THRESH_I); +#endif +#ifdef MEC2_STATS + ec->avg_Lu_i_toolow = ec->avg_Lu_i_toolow + ec->Lu_i; + ++ec->cntr_coeff_missedupdates; +#endif + } + } + + /* paragraph below eq. (15): if no near-end speech in the sample and + * the reference signal power estimate > cutoff threshold + * then perform residual error suppression + */ +#ifdef MEC2_STATS_DETAILED + if (ec->HCNTR_d == 0) + printk(KERN_INFO "possibily correcting frame with ec->Ly_i %9d ec->Lu_i %9d and expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1))); +#endif + +#ifndef NO_ECHO_SUPPRESSOR + if (ec->aggressive) { + if ((ec->HCNTR_d < AGGRESSIVE_HCNTR) && (ec->Ly_i > (ec->Lu_i << 1))) { + for (k=0; k < 2; k++) { + u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I)) + 1); + } +#ifdef MEC2_STATS_DETAILED + printk(KERN_INFO "aggresively correcting frame with ec->Ly_i %9d ec->Lu_i %9d expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1))); +#endif +#ifdef MEC2_STATS + ++ec->cntr_residualcorrected_frames; +#endif + } + } else { + if (ec->HCNTR_d == 0) { + if ((ec->Ly_i/(ec->Lu_i + 1)) > DEFAULT_SUPPR_I) { + for (k=0; k < 1; k++) { + u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I + 2)) + 1); + } +#ifdef MEC2_STATS_DETAILED + printk(KERN_INFO "correcting frame with ec->Ly_i %9d ec->Lu_i %9d expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1))); +#endif +#ifdef MEC2_STATS + ++ec->cntr_residualcorrected_frames; +#endif + } +#ifdef MEC2_STATS + else { + ++ec->cntr_residualcorrected_framesskipped; + } +#endif + } + } +#endif + +#if 0 + /* This will generate a non-linear supression factor, once converted */ + if ((ec->HCNTR_d == 0) && + ((ec->Lu_d/ec->Ly_d) < DEFAULT_SUPPR) && + (ec->Lu_d/ec->Ly_d > EC_MIN_DB_VALUE)) { + suppr_factor = (10 / (float)(SUPPR_FLOOR - SUPPR_CEIL)) * log(ec->Lu_d/ec->Ly_d) + - SUPPR_CEIL / (float)(SUPPR_FLOOR - SUPPR_CEIL); + u_suppr = pow(10.0, (suppr_factor) * RES_SUPR_FACTOR / 10.0) * u_suppr; + } +#endif + +#ifdef MEC2_STATS + /* Periodically dump performance stats */ + if ((ec->i_d % MEC2_STATS) == 0) { + /* make sure to avoid div0's! */ + if (ec->cntr_coeff_missedupdates > 0) + ec->avg_Lu_i_toolow = (int)(ec->avg_Lu_i_toolow / ec->cntr_coeff_missedupdates); + else + ec->avg_Lu_i_toolow = -1; + + if (ec->cntr_coeff_updates > 0) + ec->avg_Lu_i_ok = (ec->avg_Lu_i_ok / ec->cntr_coeff_updates); + else + ec->avg_Lu_i_ok = -1; + + printk(KERN_INFO "%d: Near end speech: %5d Residuals corrected/skipped: %5d/%5d Coefficients updated ok/low sig: %3d/%3d Lu_i avg ok/low sig %6d/%5d\n", + ec->id, + ec->cntr_nearend_speech_frames, + ec->cntr_residualcorrected_frames, ec->cntr_residualcorrected_framesskipped, + ec->cntr_coeff_updates, ec->cntr_coeff_missedupdates, + ec->avg_Lu_i_ok, ec->avg_Lu_i_toolow); + + ec->cntr_nearend_speech_frames = 0; + ec->cntr_residualcorrected_frames = 0; + ec->cntr_residualcorrected_framesskipped = 0; + ec->cntr_coeff_updates = 0; + ec->cntr_coeff_missedupdates = 0; + ec->avg_Lu_i_ok = 0; + ec->avg_Lu_i_toolow = 0; + } +#endif + + /* Increment the sample index and return the corrected sample */ + ec->i_d++; + return u; +} + +static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p, + struct echo_can_state **ec) +{ + int maxy; + int maxu; + size_t size; + unsigned int x; + char *c; + + maxy = ecp->tap_length + DEFAULT_M; + maxu = DEFAULT_M; + if (maxy < (1 << DEFAULT_ALPHA_YT_I)) + maxy = (1 << DEFAULT_ALPHA_YT_I); + if (maxy < (1 << DEFAULT_SIGMA_LY_I)) + maxy = (1 << DEFAULT_SIGMA_LY_I); + if (maxu < (1 << DEFAULT_SIGMA_LU_I)) + maxu = (1 << DEFAULT_SIGMA_LU_I); + size = sizeof(**ec) + + 4 + /* align */ + sizeof(int) * ecp->tap_length + /* a_i */ + sizeof(short) * ecp->tap_length + /* a_s */ + sizeof(int) * ecp->tap_length + /* b_i */ + sizeof(int) * ecp->tap_length + /* c_i */ + 2 * sizeof(short) * (maxy) + /* y_s */ + 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */ + 2 * sizeof(short) * (maxu) + /* u_s */ + 2 * sizeof(short) * ecp->tap_length; /* y_tilde_s */ + + if (!(*ec = MALLOC(size))) + return -ENOMEM; + + memset(*ec, 0, size); + +#ifdef AGGRESSIVE_SUPPRESSOR + (*ec)->aggressive = 1; +#endif + + for (x = 0; x < ecp->param_count; x++) { + for (c = p[x].name; *c; c++) + *c = tolower(*c); + if (!strcmp(p[x].name, "aggressive")) { + (*ec)->aggressive = p[x].value ? 1 : 0; + } else { + printk(KERN_WARNING "Unknown parameter supplied to MG2 echo canceler: '%s'\n", p[x].name); + kfree(*ec); + + return -EINVAL; + } + } + + init_cc(*ec, ecp->tap_length, maxy, maxu); + + return 0; +} + +static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) +{ + /* Set the hangover counter to the length of the can to + * avoid adjustments occuring immediately after initial forced training + */ + ec->HCNTR_d = ec->N_d << 1; + + if (pos >= ec->N_d) { + memcpy(ec->b_i,ec->a_i,ec->N_d*sizeof(int)); + memcpy(ec->c_i,ec->a_i,ec->N_d*sizeof(int)); + return 1; + } + + ec->a_i[pos] = val << 17; + ec->a_s[pos] = val << 1; + + if (++pos >= ec->N_d) { + memcpy(ec->b_i,ec->a_i,ec->N_d*sizeof(int)); + memcpy(ec->c_i,ec->a_i,ec->N_d*sizeof(int)); + return 1; + } + + return 0; +} + +#endif diff --git a/kernel/mg2ec_const.h b/kernel/mg2ec_const.h new file mode 100644 index 0000000..08fd897 --- /dev/null +++ b/kernel/mg2ec_const.h @@ -0,0 +1,88 @@ +/* + Important constants for tuning mg2 echo can + */ +#ifndef _MG2_CONST_H +#define _MG2_CONST_H + + +/* Convergence (aka. adaptation) speed -- higher means slower */ +#define DEFAULT_BETA1_I 2048 + +/* Constants for various power computations */ +#define DEFAULT_SIGMA_LY_I 7 +#define DEFAULT_SIGMA_LU_I 7 +#define DEFAULT_ALPHA_ST_I 5 /* near-end speech detection sensitivity factor */ +#define DEFAULT_ALPHA_YT_I 5 + +#define DEFAULT_CUTOFF_I 128 + +/* Define the near-end speech hangover counter: if near-end speech + * is declared, hcntr is set equal to hangt (see pg. 432) + */ +#define DEFAULT_HANGT 600 /* in samples, so 600 samples = 75ms */ + +/* define the residual error suppression threshold */ +#define DEFAULT_SUPPR_I 16 /* 16 = -24db */ + +/* This is the minimum reference signal power estimate level + * that will result in filter adaptation. + * If this is too low then background noise will cause the filter + * coefficients to constantly be updated. + */ +#define MIN_UPDATE_THRESH_I 2048 + +/* The number of samples used to update coefficients using the + * the block update method (M). It should be related back to the + * length of the echo can. + * ie. it only updates coefficients when (sample number MOD default_m) = 0 + * + * Getting this wrong may cause an oops. Consider yourself warned! + */ +#define DEFAULT_M 16 /* every 16th sample */ + +/* If AGGRESSIVE supression is enabled, then we start cancelling residual + * echos again even while there is potentially the very end of a near-side + * signal present. + * This defines how many samples of DEFAULT_HANGT can remain before we + * kick back in + */ +#define AGGRESSIVE_HCNTR 160 /* in samples, so 160 samples = 20ms */ + +/* Treat sample as error if it has a different sign as the + * input signal and is this number larger in ABS() as + * the input-signal */ +#define MAX_SIGN_ERROR 3000 + +/* Number of coefficients really used for calculating the + * simulated echo. The value specifies how many of the + * biggest coefficients are used for calculating rs. + * This helps on long echo-tails by artificially limiting + * the number of coefficients for the calculation and + * preventing overflows. + * Comment this to deactivate the code */ +#define USED_COEFFS 64 + +/* Backup coefficients every this number of samples */ +#define BACKUP 256 + +/***************************************************************/ +/* The following knobs are not implemented in the current code */ + +/* we need a dynamic level of suppression varying with the ratio of the + power of the echo to the power of the reference signal this is + done so that we have a smoother background. + we have a higher suppression when the power ratio is closer to + suppr_ceil and reduces logarithmically as we approach suppr_floor. + */ +#define SUPPR_FLOOR -64 +#define SUPPR_CEIL -24 + +/* in a second departure, we calculate the residual error suppression + * as a percentage of the reference signal energy level. The threshold + * is defined in terms of dB below the reference signal. + */ +#define RES_SUPR_FACTOR -20 + + +#endif /* _MG2_CONST_H */ + diff --git a/kernel/pciradio.c b/kernel/pciradio.c new file mode 100644 index 0000000..55270c1 --- /dev/null +++ b/kernel/pciradio.c @@ -0,0 +1,1934 @@ +/* + * PCI RADIO Card Zapata Telephony PCI Quad Radio Interface driver + * + * Written by Jim Dixon + * Based on previous work by Mark Spencer + * Based on previous works, designs, and archetectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001-2007 Jim Dixon / Zapata Telephony. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + The PCI Radio Interface card interfaces up to 4 two-way radios (either + a base/mobile radio or repeater system) to Zaptel channels. The driver + may work either independent of an application, or with it, through + the driver;s ioctl() interface. This file gives you access to specify + load-time parameters for Radio channels, so that the driver may run + by itself, and just act like a generic Zaptel radio interface. +*/ + +/* Latency tests: + +Without driver: 308496 +With driver: 303826 (1.5 %) + +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef STANDALONE_ZAPATA +#include "zaptel.h" +#else +#include +#endif + +#ifdef LINUX26 +#include +#endif + +#define RAD_MAX_IFACES 128 + +#define NUM_CODES 15 + +#define SERIAL_BUFLEN 128 + +#define SRX_TIMEOUT 300 + +#define RAD_CNTL 0x00 +#define RAD_OPER 0x01 +#define RAD_AUXC 0x02 +#define RAD_AUXD 0x03 + #define XPGM 4 + #define XCS 2 + +#define RAD_MASK0 0x04 +#define RAD_MASK1 0x05 +#define RAD_INTSTAT 0x06 +#define RAD_AUXR 0x07 + #define XINIT 8 + #define XDONE 0x10 + +#define RAD_DMAWS 0x08 +#define RAD_DMAWI 0x0c +#define RAD_DMAWE 0x10 +#define RAD_DMARS 0x18 +#define RAD_DMARI 0x1c +#define RAD_DMARE 0x20 + +#define RAD_AUXFUNC 0x2b +#define RAD_SERCTL 0x2d +#define RAD_FSCDELAY 0x2f + +#define RAD_REGBASE 0xc0 + +#define RAD_CTCSSMASK 0xf +#define RAD_CTCSSOTHER 0xf +#define RAD_CTCSSVALID 0x10 + +#define NUM_CHANS 4 + +#define RAD_GOTRX_DEBOUNCE_TIME 75 +#define RAD_CTCSS_ACQUIRE_TIME 10 +#define RAD_CTCSS_TALKOFF_TIME 1000 + +#define ZT_RADPAR_CTCSSACQUIRETIME 18 /* DEBUG only, this belongs in zaptel.h */ +#define ZT_RADPAR_CTCSSTALKOFFTIME 19 /* DEBUG only, this belongs in zaptel.h */ + +/* +* MX828 Commands +*/ + +#define MX828_GEN_RESET 0x01 /* W */ +#define MX828_SAUDIO_CTRL 0x80 /* W */ +#define MX828_SAUDIO_STATUS 0x81 /* R */ +#define MX828_SAUDIO_SETUP 0x82 /* W */ +#define MX828_TX_TONE 0x83 /* W16 */ +#define MX828_RX_TONE 0x84 /* W16 */ +#define MX828_DCS3 0x85 /* W */ +#define MX828_DCS2 0x86 /* W */ +#define MX828_DCS1 0x87 /* W */ +#define MX828_GEN_CTRL 0x88 /* W */ +#define MX828_GPT 0x8B /* W */ +#define MX828_IRQ_MASK 0x8E /* W */ +#define MX828_SELCALL 0x8D /* W16 */ +#define MX828_AUD_CTRL 0x8A /* W16 */ +#define MX828_IRQ_FLAG 0x8F /* R */ + + +struct encdec +{ + unsigned char state; /* 0 = idle */ + int chan; + unsigned char req[NUM_CHANS]; + unsigned char dcsrx[NUM_CHANS]; + unsigned char ctrx[NUM_CHANS]; + unsigned char dcstx[NUM_CHANS]; + unsigned char cttx[NUM_CHANS]; + unsigned char saudio_ctrl[NUM_CHANS]; + unsigned char saudio_setup[NUM_CHANS]; + unsigned char txcode[NUM_CHANS]; + unsigned long lastcmd; + int myindex[NUM_CHANS]; + unsigned long waittime; + unsigned char retstate; +} ; + + +struct pciradio { + struct pci_dev *dev; + struct zt_span span; + unsigned char ios; + int usecount; + unsigned int intcount; + int dead; + int pos; + int freeregion; + int nchans; + spinlock_t lock; + int remote_locked; + unsigned char rxbuf[SERIAL_BUFLEN]; + unsigned short rxindex; + unsigned long srxtimer; + unsigned char txbuf[SERIAL_BUFLEN]; + unsigned short txindex; + unsigned short txlen; + unsigned char pasave; + unsigned char pfsave; + volatile unsigned long ioaddr; + dma_addr_t readdma; + dma_addr_t writedma; + volatile unsigned int *writechunk; /* Double-word aligned write memory */ + volatile unsigned int *readchunk; /* Double-word aligned read memory */ + unsigned char saudio_status[NUM_CHANS]; + char gotcor[NUM_CHANS]; + char gotct[NUM_CHANS]; + char newctcssstate[NUM_CHANS]; + char ctcssstate[NUM_CHANS]; + char gotrx[NUM_CHANS]; + char gotrx1[NUM_CHANS]; + char gottx[NUM_CHANS]; + char lasttx[NUM_CHANS]; + int gotrxtimer[NUM_CHANS]; + int ctcsstimer[NUM_CHANS]; + int debouncetime[NUM_CHANS]; + int ctcssacquiretime[NUM_CHANS]; + int ctcsstalkofftime[NUM_CHANS]; + int bursttime[NUM_CHANS]; + int bursttimer[NUM_CHANS]; + unsigned char remmode[NUM_CHANS]; + unsigned short present_code[NUM_CHANS]; + unsigned short last_code[NUM_CHANS]; + unsigned short rxcode[NUM_CHANS][NUM_CODES + 1]; + unsigned short rxclass[NUM_CHANS][NUM_CODES + 1]; + unsigned short txcode[NUM_CHANS][NUM_CODES + 1];; + unsigned char radmode[NUM_CHANS]; +#define RADMODE_INVERTCOR 1 +#define RADMODE_IGNORECOR 2 +#define RADMODE_EXTTONE 4 +#define RADMODE_EXTINVERT 8 +#define RADMODE_IGNORECT 16 +#define RADMODE_NOENCODE 32 + unsigned char corthresh[NUM_CHANS]; + struct zt_chan chans[NUM_CHANS]; + unsigned char mx828_addr; + struct encdec encdec; + unsigned long lastremcmd; +}; + + +static struct pciradio *ifaces[RAD_MAX_IFACES]; + +static void pciradio_release(struct pciradio *rad); + +static int debug = 0; + +struct tonedef { + int code; + unsigned char b1; + unsigned char b2; +} ; + +#include "radfw.h" + +static struct tonedef cttable_tx [] = { +{0,0,0}, +{670,0xE,0xB1}, +{693,0xE,0x34}, +{719,0xD,0xB1}, +{744,0xD,0x3B}, +{770,0xC,0xC9}, +{797,0xC,0x5A}, +{825,0xB,0xEF}, +{854,0xB,0x87}, +{885,0xB,0x1F}, +{915,0xA,0xC2}, +{948,0xA,0x62}, +{974,0xA,0x1B}, +{1000,0x9,0xD8}, +{1035,0x9,0x83}, +{1072,0x9,0x2F}, +{1109,0x8,0xE0}, +{1148,0x8,0x93}, +{1188,0x8,0x49}, +{1230,0x8,0x1}, +{1273,0x7,0xBC}, +{1318,0x7,0x78}, +{1365,0x7,0x36}, +{1413,0x6,0xF7}, +{1462,0x6,0xBC}, +{1514,0x6,0x80}, +{1567,0x6,0x48}, +{1598,0x6,0x29}, +{1622,0x6,0x12}, +{1679,0x5,0xDD}, +{1738,0x5,0xAA}, +{1799,0x5,0x79}, +{1835,0x5,0x5D}, +{1862,0x5,0x49}, +{1899,0x5,0x2F}, +{1928,0x5,0x1B}, +{1966,0x5,0x2}, +{1995,0x4,0xEF}, +{2035,0x4,0xD6}, +{2065,0x4,0xC4}, +{2107,0x4,0xAC}, +{2181,0x4,0x83}, +{2257,0x4,0x5D}, +{2291,0x4,0x4C}, +{2336,0x4,0x37}, +{2418,0x4,0x12}, +{2503,0x3,0xEF}, +{2541,0x3,0xE0}, +{0,0,0} +} ; + +static struct tonedef cttable_rx [] = { +{0,0,0}, +{670,0x3,0xD8}, +{693,0x4,0x9}, +{719,0x4,0x1B}, +{744,0x4,0x4E}, +{770,0x4,0x83}, +{797,0x4,0x94}, +{825,0x4,0xCB}, +{854,0x5,0x2}, +{885,0x5,0x14}, +{915,0x5,0x4C}, +{948,0x5,0x87}, +{974,0x5,0x94}, +{1000,0x5,0xCB}, +{1035,0x6,0x7}, +{1072,0x6,0x45}, +{1109,0x6,0x82}, +{1148,0x6,0xC0}, +{1188,0x6,0xD1}, +{1230,0x7,0x10}, +{1273,0x7,0x50}, +{1318,0x7,0xC0}, +{1365,0x8,0x2}, +{1413,0x8,0x44}, +{1462,0x8,0x86}, +{1514,0x8,0xC9}, +{1567,0x9,0xC}, +{1598,0x9,0x48}, +{1622,0x9,0x82}, +{1679,0x9,0xC6}, +{1738,0xA,0xB}, +{1799,0xA,0x84}, +{1835,0xA,0xC2}, +{1862,0xA,0xC9}, +{1899,0xB,0x8}, +{1928,0xB,0x44}, +{1966,0xB,0x83}, +{1995,0xB,0x8A}, +{2035,0xB,0xC9}, +{2065,0xC,0x6}, +{2107,0xC,0x46}, +{2181,0xC,0xC3}, +{2257,0xD,0x41}, +{2291,0xD,0x48}, +{2336,0xD,0x89}, +{2418,0xE,0x8}, +{2503,0xE,0x88}, +{2541,0xE,0xC7}, +{0,0,0} +}; + +static struct { + int code; + char b3; + char b2; + char b1; +} dcstable[] = { +{0,0,0,0}, +{23,0x76,0x38,0x13}, +{25,0x6B,0x78,0x15}, +{26,0x65,0xD8,0x16}, +{31,0x51,0xF8,0x19}, +{32,0x5F,0x58,0x1A}, +{43,0x5B,0x68,0x23}, +{47,0x0F,0xD8,0x27}, +{51,0x7C,0xA8,0x29}, +{54,0x6F,0x48,0x2C}, +{65,0x5D,0x18,0x35}, +{71,0x67,0x98,0x39}, +{72,0x69,0x38,0x3A}, +{73,0x2E,0x68,0x3B}, +{74,0x74,0x78,0x3C}, +{114,0x35,0xE8,0x4C}, +{115,0x72,0xB8,0x4D}, +{116,0x7C,0x18,0x4E}, +{125,0x07,0xB8,0x55}, +{131,0x3D,0x38,0x59}, +{132,0x33,0x98,0x5A}, +{134,0x2E,0xD8,0x5C}, +{143,0x37,0xA8,0x63}, +{152,0x1E,0xC8,0x6A}, +{155,0x44,0xD8,0x6D}, +{156,0x4A,0x78,0x6E}, +{162,0x6B,0xC8,0x72}, +{165,0x31,0xD8,0x75}, +{172,0x05,0xF8,0x7A}, +{174,0x18,0xB8,0x7C}, +{205,0x6E,0x98,0x85}, +{223,0x68,0xE8,0x93}, +{226,0x7B,0x08,0x96}, +{243,0x45,0xB8,0xA3}, +{244,0x1F,0xA8,0xA4}, +{245,0x58,0xF8,0xA5}, +{251,0x62,0x78,0xA9}, +{261,0x17,0x78,0xB1}, +{263,0x5E,0x88,0xB3}, +{265,0x43,0xC8,0xB5}, +{271,0x79,0x48,0xB9}, +{306,0x0C,0xF8,0xC6}, +{311,0x38,0xD8,0xC9}, +{315,0x6C,0x68,0xCD}, +{331,0x23,0xE8,0xD9}, +{343,0x29,0x78,0xE3}, +{346,0x3A,0x98,0xE6}, +{351,0x0E,0xB8,0xE9}, +{364,0x68,0x58,0xF4}, +{365,0x2F,0x08,0xF5}, +{371,0x15,0x88,0xF9}, +{411,0x77,0x69,0x09}, +{412,0x79,0xC9,0x0A}, +{413,0x3E,0x99,0x0B}, +{423,0x4B,0x99,0x13}, +{431,0x6C,0x59,0x19}, +{432,0x62,0xF9,0x1A}, +{445,0x7B,0x89,0x25}, +{464,0x27,0xE9,0x34}, +{465,0x60,0xB9,0x35}, +{466,0x6E,0x19,0x36}, +{503,0x3C,0x69,0x43}, +{506,0x2F,0x89,0x46}, +{516,0x41,0xB9,0x4E}, +{532,0x0E,0x39,0x5A}, +{546,0x19,0xE9,0x66}, +{565,0x0C,0x79,0x75}, +{606,0x5D,0x99,0x86}, +{612,0x67,0x19,0x8A}, +{624,0x0F,0x59,0x94}, +{627,0x01,0xF9,0x97}, +{631,0x72,0x89,0x99}, +{632,0x7C,0x29,0x9A}, +{654,0x4C,0x39,0xAC}, +{662,0x24,0x79,0xB2}, +{664,0x39,0x39,0xB4}, +{703,0x22,0xB9,0xC3}, +{712,0x0B,0xD9,0xCA}, +{723,0x39,0x89,0xD3}, +{731,0x1E,0x49,0xD9}, +{732,0x10,0xE9,0xDA}, +{734,0x0D,0xA9,0xDC}, +{743,0x14,0xD9,0xE3}, +{754,0x20,0xF9,0xEC}, +{0,0,0,0} +}; + +static int gettxtone(int code) +{ +int i; + + if (!code) return(0); + for(i = 0; cttable_tx[i].code || (!i); i++) + { + if (cttable_tx[i].code == code) + { + return (i); + } + } + return(-1); +} + +static int getrxtone(int code) +{ +int i; + + if (!code) return(0); + for(i = 0; cttable_rx[i].code || (!i); i++) + { + if (cttable_rx[i].code == code) + { + return (i); + } + } + return(-1); +} + + +static int getdcstone(int code) +{ +int i; + + if (!code) return(0); + for(i = 0; dcstable[i].code || (!i); i++) + { + if (dcstable[i].code == code) + { + return (i); + } + } + return(-1); +} + + +void __pciradio_setcreg(struct pciradio *rad, unsigned char reg, unsigned char val) +{ + outb(val, rad->ioaddr + RAD_REGBASE + ((reg & 0xf) << 2)); +} + +unsigned char __pciradio_getcreg(struct pciradio *rad, unsigned char reg) +{ + return inb(rad->ioaddr + RAD_REGBASE + ((reg & 0xf) << 2)); +} + + +void rbi_out(struct pciradio *rad, int n, unsigned char *rbicmd) +{ +unsigned long flags; +int x; +DECLARE_WAIT_QUEUE_HEAD(mywait); + + + for(;;) + { + spin_lock_irqsave(&rad->lock,flags); + x = rad->remote_locked || (__pciradio_getcreg(rad,0xc) & 2); + if (!x) rad->remote_locked = 1; + spin_unlock_irqrestore(&rad->lock,flags); + if (x) interruptible_sleep_on_timeout(&mywait,2); + else break; + } + spin_lock_irqsave(&rad->lock,flags); + /* enable and address RBI serializer */ + __pciradio_setcreg(rad,0xf,rad->pfsave | (n << 4) | 0x40); + /* output commands */ + for(x = 0; x < 5; x++) __pciradio_setcreg(rad,0xc,rbicmd[x]); + /* output it */ + __pciradio_setcreg(rad,0xb,1); + rad->remote_locked = 0; + spin_unlock_irqrestore(&rad->lock,flags); + return; +} + + +/* +* Output a command to the MX828 over the serial bus +*/ + + +void mx828_command(struct pciradio *rad,int channel, unsigned char command, unsigned char *byte1, unsigned char *byte2) +{ + + if(channel > 3) + return; + + rad->mx828_addr = channel; + __pciradio_setcreg(rad,0,channel); + if (byte1) __pciradio_setcreg(rad,1,*byte1); + if (byte2) __pciradio_setcreg(rad,2,*byte2); + __pciradio_setcreg(rad,3,command); + +} + +void mx828_command_wait(struct pciradio *rad,int channel, unsigned char command, unsigned char *byte1, unsigned char *byte2) +{ +DECLARE_WAIT_QUEUE_HEAD(mywait); +unsigned long flags; + + + spin_lock_irqsave(&rad->lock,flags); + while(rad->encdec.state) + { + spin_unlock_irqrestore(&rad->lock,flags); + interruptible_sleep_on_timeout(&mywait,2); + spin_lock_irqsave(&rad->lock,flags); + } + rad->encdec.lastcmd = jiffies + 1000; + spin_unlock_irqrestore(&rad->lock,flags); + while(__pciradio_getcreg(rad,0xc) & 1); + rad->encdec.lastcmd = jiffies + 1000; + spin_lock_irqsave(&rad->lock,flags); + rad->encdec.lastcmd = jiffies + 1000; + mx828_command(rad,channel,command,byte1,byte2); + spin_unlock_irqrestore(&rad->lock,flags); + rad->encdec.lastcmd = jiffies + 1000; + while(__pciradio_getcreg(rad,0xc) & 1); + rad->encdec.lastcmd = jiffies; +} + +static void _do_encdec(struct pciradio *rad) +{ +int i,n; +unsigned char byte1 = 0,byte2 = 0; + + /* return doing nothing if busy */ + if ((rad->encdec.lastcmd + 2) > jiffies) return; + if (__pciradio_getcreg(rad,0xc) & 1) return; + n = 0; + byte2 = 0; + switch(rad->encdec.state) + { + case 0: + for(i = 0; i < rad->nchans; i++) + { + n = (unsigned)(i - rad->intcount) % rad->nchans; + if (rad->encdec.req[n]) break; + } + if (i >= rad->nchans) return; + rad->encdec.req[n] = 0; + rad->encdec.dcsrx[n] = 0; + rad->encdec.ctrx[n] = 0; + rad->encdec.dcstx[n] = 0; + rad->encdec.cttx[n] = 0; + rad->encdec.myindex[n] = 0; + rad->encdec.req[n] = 0; + rad->encdec.chan = n; + + /* if something in code 0 for rx, is DCS */ + if (rad->rxcode[n][0]) rad->encdec.dcsrx[n] = 1; + else { /* otherwise, if something in other codes, is CT rx */ + for(i = 1; i <= NUM_CODES; i++) + { + if (rad->rxcode[n][1]) rad->encdec.ctrx[n] = 1; + } + } + /* get index for tx code. Will be 0 if not receiving a CT */ + rad->encdec.myindex[n] = 0; + if (rad->gotrx[n] && rad->encdec.ctrx[n] && (rad->present_code[n])) + rad->encdec.myindex[n] = rad->present_code[n]; + /* get actual tx code from array */ + rad->encdec.txcode[n] = rad->txcode[n][rad->encdec.myindex[n]]; + if (rad->encdec.txcode[n] & 0x8000) rad->encdec.dcstx[n] = 1; + else if (rad->encdec.txcode[n]) rad->encdec.cttx[n] = 1; + if (rad->radmode[n] & RADMODE_NOENCODE) + rad->encdec.dcstx[n] = rad->encdec.cttx[n] = 0; + if ((!rad->gottx[n]) || rad->bursttimer[n]) + rad->encdec.dcstx[n] = rad->encdec.cttx[n] = 0; + rad->encdec.saudio_ctrl[n] = 0; + rad->encdec.saudio_setup[n] = 0; + rad->encdec.state = 1; + break; + case 1: + if (rad->encdec.dcstx[rad->encdec.chan] && (!rad->encdec.dcsrx[rad->encdec.chan])) /* if to transmit DCS */ + { + rad->encdec.saudio_setup[rad->encdec.chan] |= 3; + rad->encdec.saudio_ctrl[rad->encdec.chan] |= 0x80; + byte1 = dcstable[rad->encdec.txcode[rad->encdec.chan] & 0x7fff].b1; + mx828_command(rad,rad->encdec.chan, MX828_DCS1, &byte1, &byte2 ); + rad->encdec.state = 2; + break; + } + rad->encdec.state = 4; + break; + case 2: + byte1 = dcstable[rad->encdec.txcode[rad->encdec.chan] & 0x7fff].b2; + mx828_command(rad,rad->encdec.chan, MX828_DCS2, &byte1, &byte2 ); + rad->encdec.state = 3; + break; + case 3: + byte1 = dcstable[rad->encdec.txcode[rad->encdec.chan] & 0x7fff].b3; + mx828_command(rad,rad->encdec.chan, MX828_DCS3, &byte1, &byte2 ); + rad->encdec.state = 4; + break; + case 4: + if (rad->encdec.cttx[rad->encdec.chan]) + { + rad->encdec.saudio_ctrl[rad->encdec.chan] |= 0x80; + byte1 = cttable_tx[rad->encdec.txcode[rad->encdec.chan]].b1; + byte2 = cttable_tx[rad->encdec.txcode[rad->encdec.chan]].b2; + mx828_command(rad,rad->encdec.chan, MX828_TX_TONE, &byte1, &byte2 ); + } + rad->encdec.state = 5; + break; + case 5: + if (rad->encdec.dcsrx[rad->encdec.chan]) + { + rad->encdec.saudio_setup[rad->encdec.chan] |= 1; + rad->encdec.saudio_ctrl[rad->encdec.chan] |= 0x41; + byte1 = dcstable[rad->rxcode[rad->encdec.chan][0]].b1; + mx828_command(rad,rad->encdec.chan, MX828_DCS1, &byte1, &byte2 ); + rad->encdec.state = 6; + break; + } + rad->encdec.state = 8; + break; + case 6: + byte1 = dcstable[rad->rxcode[rad->encdec.chan][0]].b2; + mx828_command(rad,rad->encdec.chan, MX828_DCS2, &byte1, &byte2 ); + rad->encdec.state = 7; + break; + case 7: + byte1 = dcstable[rad->rxcode[rad->encdec.chan][0]].b3; + mx828_command(rad,rad->encdec.chan, MX828_DCS3, &byte1, &byte2 ); + rad->encdec.state = 8; + break; + case 8: + if (rad->encdec.ctrx[rad->encdec.chan]) + { + rad->encdec.saudio_setup[rad->encdec.chan] |= 0x80; + rad->encdec.saudio_ctrl[rad->encdec.chan] |= 0x60; + } + byte1 = rad->encdec.saudio_setup[rad->encdec.chan]; + mx828_command(rad,rad->encdec.chan, MX828_SAUDIO_SETUP, &byte1, &byte2 ); + rad->encdec.state = 9; + break; + case 9: + byte1 = rad->encdec.saudio_ctrl[rad->encdec.chan]; + mx828_command(rad,rad->encdec.chan, MX828_SAUDIO_CTRL, &byte1, &byte2 ); + rad->encdec.state = 10; + break; + case 10: + rad->encdec.chan = 0; + rad->encdec.state = 0; + break; + } +} + +static inline void pciradio_transmitprep(struct pciradio *rad, unsigned char ints) +{ + volatile unsigned int *writechunk; + int x; + if (ints & 0x01) + /* Write is at interrupt address. Start writing from normal offset */ + writechunk = rad->writechunk; + else + writechunk = rad->writechunk + ZT_CHUNKSIZE; + + /* Calculate Transmission */ + zt_transmit(&rad->span); + + for (x=0;xchans[0].writechunk[x] << 24); + writechunk[x] |= (rad->chans[1].writechunk[x] << 16); + writechunk[x] |= (rad->chans[2].writechunk[x] << 8); + writechunk[x] |= (rad->chans[3].writechunk[x]); + } +} + +static inline void pciradio_receiveprep(struct pciradio *rad, unsigned char ints) +{ + volatile unsigned int *readchunk; + int x; + + if (ints & 0x08) + readchunk = rad->readchunk + ZT_CHUNKSIZE; + else + /* Read is at interrupt address. Valid data is available at normal offset */ + readchunk = rad->readchunk; + for (x=0;xchans[0].readchunk[x] = (readchunk[x] >> 24) & 0xff; + rad->chans[1].readchunk[x] = (readchunk[x] >> 16) & 0xff; + rad->chans[2].readchunk[x] = (readchunk[x] >> 8) & 0xff; + rad->chans[3].readchunk[x] = (readchunk[x]) & 0xff; + } + for (x=0;xnchans;x++) { + zt_ec_chunk(&rad->chans[x], rad->chans[x].readchunk, rad->chans[x].writechunk); + } + zt_receive(&rad->span); +} + +static void pciradio_stop_dma(struct pciradio *rad); +static void pciradio_reset_serial(struct pciradio *rad); +static void pciradio_restart_dma(struct pciradio *rad); + +#ifdef LEAVE_THIS_COMMENTED_OUT +#ifdef LINUX26 +static irqreturn_t pciradio_interrupt(int irq, void *dev_id, struct pt_regs *regs) +#else +static void pciradio_interrupt(int irq, void *dev_id, struct pt_regs *regs) +#endif +#endif + +ZAP_IRQ_HANDLER(pciradio_interrupt) +{ + struct pciradio *rad = dev_id; + unsigned char ints,byte1,byte2,gotcor,gotctcss,gotslowctcss,ctcss; + int i,x,gotrx; + + ints = inb(rad->ioaddr + RAD_INTSTAT); + outb(ints, rad->ioaddr + RAD_INTSTAT); + + if (!ints) +#ifdef LINUX26 + return IRQ_NONE; +#else + return; +#endif + + if (ints & 0x10) { + /* Stop DMA, wait for watchdog */ + printk("RADIO PCI Master abort\n"); + pciradio_stop_dma(rad); +#ifdef LINUX26 + return IRQ_RETVAL(1); +#else + return; +#endif + } + + if (ints & 0x20) { + printk("RADIO PCI Target abort\n"); +#ifdef LINUX26 + return IRQ_RETVAL(1); +#else + return; +#endif + } + + if (ints & 0x0f) { + + rad->intcount++; + x = rad->intcount % rad->nchans; + /* freeze */ + __pciradio_setcreg(rad,0,rad->mx828_addr | 4); + /* read SAUDIO_STATUS for the proper channel */ + byte1 = rad->saudio_status[x] = __pciradio_getcreg(rad,x); + /* thaw */ + __pciradio_setcreg(rad,0,rad->mx828_addr); + /* get COR input */ + byte2 = __pciradio_getcreg(rad,9); + /* get bit for this channel */ + gotcor = byte2 & (1 << x); + if (rad->radmode[x] & RADMODE_INVERTCOR) gotcor = !gotcor; + rad->gotcor[x] = gotcor; + if (rad->radmode[x] & RADMODE_IGNORECOR) gotcor = 1; + gotslowctcss = 0; + if ((byte1 & RAD_CTCSSVALID) && + ((byte1 & RAD_CTCSSMASK) != RAD_CTCSSOTHER)) gotslowctcss = 1; + gotctcss = 1; + ctcss = 0; + /* set ctcss to 1 if decoding ctcss */ + if (!rad->rxcode[x][0]) + { + for(i = 1; i <= NUM_CODES; i++) + { + if (rad->rxcode[x][i]) + { + ctcss = 1; + break; + } + } + } + if (ctcss) + { + if ((!(byte1 & 0x40)) || + ((!rad->gotrx[x]) && (!gotslowctcss))) gotctcss = 0; + } + rad->present_code[x] = 0; + if (rad->rxcode[x][0]) + { + if (byte1 & 0x80) gotctcss = gotslowctcss = 1; else gotctcss = 0; + } else if (gotslowctcss) rad->present_code[x] = (byte1 & RAD_CTCSSMASK) + 1; + if (rad->radmode[x] & RADMODE_EXTTONE) + { + unsigned mask = 1 << (x + 4); /* they're on the UIOB's */ + unsigned char byteuio; + + /* set UIOB as input */ + byteuio = __pciradio_getcreg(rad,0xe); + byteuio |= mask; + __pciradio_setcreg(rad,0xe,byteuio); + /* get UIO input */ + byteuio = __pciradio_getcreg(rad,8); + if (rad->radmode[x] & RADMODE_EXTINVERT) + gotctcss = gotslowctcss = ((byteuio & mask) == 0); + else + gotctcss = gotslowctcss = ((byteuio & mask) != 0); + } + rad->gotct[x] = gotslowctcss; + if ((rad->radmode[x] & RADMODE_IGNORECT) || + ((!(rad->radmode[x] & RADMODE_EXTTONE)) && (!ctcss))) + { + gotctcss = 1; + gotslowctcss = 1; + rad->present_code[x] = 0; + } + if(rad->newctcssstate[x] != gotctcss){ + rad->newctcssstate[x] = gotctcss; + if(rad->newctcssstate[x]) + rad->ctcsstimer[x]=rad->ctcssacquiretime[x]; + else + rad->ctcsstimer[x]=rad->ctcsstalkofftime[x]; + } + else{ + if(!rad->ctcsstimer[x]) + rad->ctcssstate[x] = rad->newctcssstate[x]; + else + rad->ctcsstimer[x]--; + } + gotrx = gotcor && rad->ctcssstate[x]; + if (gotrx != rad->gotrx[x]) + { + rad->gotrxtimer[x] = rad->debouncetime[x]; + } + rad->gotrx[x] = gotrx; + if (rad->present_code[x] != rad->last_code[x]) + { + rad->encdec.req[x] = 1; + rad->last_code[x] = rad->present_code[x]; + } + _do_encdec(rad); + for(x = 0; x < rad->nchans; x++) + { + unsigned char mask = 1 << x; + + if (rad->gottx[x] != rad->lasttx[x]) + { + if (rad->gottx[x]) + { + rad->bursttimer[x] = 0; + rad->pasave |= mask; + __pciradio_setcreg(rad, 0xa, rad->pasave); + } + else + { + if (!rad->bursttime[x]) + { + rad->pasave &= ~mask; + __pciradio_setcreg(rad, 0xa, rad->pasave); + } + else + { + rad->bursttimer[x] = rad->bursttime[x]; + } + } + rad->encdec.req[x] = 1; + rad->lasttx[x] = rad->gottx[x]; + } + if (rad->bursttimer[x]) + { + /* if just getting to zero */ + if (!(--rad->bursttimer[x])) + { + unsigned char mask = 1 << x; + + rad->pasave &= ~mask; + __pciradio_setcreg(rad, 0xa, rad->pasave); + } + } + + /* if timer active */ + if (rad->gotrxtimer[x]) + { + /* if just getting to zero */ + if (!(--rad->gotrxtimer[x])) + { + unsigned char mask; + + mask = 1 << (x + 4); + rad->pasave &= ~mask; + if (gotctcss) rad->pasave |= mask; + __pciradio_setcreg(rad, 0xa, rad->pasave); + + if (rad->gotrx[x] != rad->gotrx1[x]) + { + if (rad->gotrx[x]) { + if (debug) + { + if (rad->present_code[x]) + printk("Chan %d got rx (ctcss code %d)\n",x + 1, + cttable_rx[rad->rxcode[x][rad->present_code[x]]].code); + else + printk("Chan %d got rx\n",x + 1); + } + zt_hooksig(&rad->chans[x],ZT_RXSIG_OFFHOOK); + } else { + if (debug) printk("Chan %d lost rx\n",x + 1); + zt_hooksig(&rad->chans[x],ZT_RXSIG_ONHOOK); + } + rad->encdec.req[x] = 1; + } + rad->gotrx1[x] = rad->gotrx[x]; + } + } + } + /* process serial if any */ + /* send byte if there is one in buffer to send */ + if (rad->txlen && (rad->txlen != rad->txindex)) + { + /* if tx not busy */ + if (!(__pciradio_getcreg(rad,9) & 0x80)) + { + __pciradio_setcreg(rad, 4, rad->txbuf[rad->txindex++]); + } + } + rad->srxtimer++; + /* if something in rx to read */ + while(__pciradio_getcreg(rad,9) & 0x10) + { + unsigned char c = __pciradio_getcreg(rad,4); + rad->srxtimer = 0; + if (rad->rxindex < RAD_SERIAL_BUFLEN) + { + rad->rxbuf[rad->rxindex++] = c; + } + udelay(1); + } + pciradio_receiveprep(rad, ints); + pciradio_transmitprep(rad, ints); + i = 0; + for(x = 0; x < 4; x++) + { + if (rad->gottx[x]) i |= (1 << (x * 2)); + if (rad->gotrx[x]) i |= (2 << (x * 2)); + } + /* output LED's */ + __pciradio_setcreg(rad, 9, i); + } +#ifdef LINUX26 + return IRQ_RETVAL(1); +#endif + +} + +static int pciradio_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) +{ + int i,mycode; + unsigned long flags; + unsigned char byte1,byte2,mask; + union { + struct zt_radio_stat s; + struct zt_radio_param p; + } stack; + + struct pciradio *rad = chan->pvt; + DECLARE_WAIT_QUEUE_HEAD(mywait); + + switch (cmd) { + case ZT_RADIO_GETPARAM: + if (copy_from_user(&stack.p,(struct zt_radio_param *)data,sizeof(struct zt_radio_param))) return -EFAULT; + spin_lock_irqsave(&rad->lock,flags); + stack.p.data = 0; /* start with 0 value in output */ + switch(stack.p.radpar) { + case ZT_RADPAR_INVERTCOR: + if (rad->radmode[chan->chanpos - 1] & RADMODE_INVERTCOR) + stack.p.data = 1; + break; + case ZT_RADPAR_IGNORECOR: + if (rad->radmode[chan->chanpos - 1] & RADMODE_IGNORECOR) + stack.p.data = 1; + break; + case ZT_RADPAR_IGNORECT: + if (rad->radmode[chan->chanpos - 1] & RADMODE_IGNORECT) + stack.p.data = 1; + break; + case ZT_RADPAR_NOENCODE: + if (rad->radmode[chan->chanpos - 1] & RADMODE_NOENCODE) + stack.p.data = 1; + break; + case ZT_RADPAR_CORTHRESH: + stack.p.data = rad->corthresh[chan->chanpos - 1] & 7; + break; + case ZT_RADPAR_EXTRXTONE: + if (rad->radmode[chan->chanpos - 1] & RADMODE_EXTTONE) + { + stack.p.data = 1; + if (rad->radmode[chan->chanpos - 1] & RADMODE_EXTINVERT) + { + stack.p.data = 2; + } + } + break; + case ZT_RADPAR_NUMTONES: + stack.p.data = NUM_CODES; + break; + case ZT_RADPAR_RXTONE: + if ((stack.p.index < 1) || (stack.p.index > NUM_CODES)) { + spin_unlock_irqrestore(&rad->lock,flags); + return -EINVAL; + } + stack.p.data = + cttable_rx[rad->rxcode[chan->chanpos - 1][stack.p.index] & 0x7fff].code; + break; + case ZT_RADPAR_RXTONECLASS: + if ((stack.p.index < 1) || (stack.p.index > NUM_CODES)) { + spin_unlock_irqrestore(&rad->lock,flags); + return -EINVAL; + } + stack.p.data = rad->rxclass[chan->chanpos - 1][stack.p.index] & 0xffff; + break; + case ZT_RADPAR_TXTONE: + if (stack.p.index > NUM_CODES) { + spin_unlock_irqrestore(&rad->lock,flags); + return -EINVAL; + } + stack.p.data = cttable_tx[rad->txcode[chan->chanpos - 1][stack.p.index] & 0x7fff].code; + /* if a DCS tone, return as such */ + if (rad->txcode[chan->chanpos - 1][stack.p.index] & 0x8000) + stack.p.data |= 0x8000; + break; + case ZT_RADPAR_DEBOUNCETIME: + stack.p.data = rad->debouncetime[chan->chanpos - 1]; + break; + + case ZT_RADPAR_CTCSSACQUIRETIME: + stack.p.data = rad->ctcssacquiretime[chan->chanpos - 1]; + break; + + case ZT_RADPAR_CTCSSTALKOFFTIME: + stack.p.data = rad->ctcsstalkofftime[chan->chanpos - 1]; + break; + + case ZT_RADPAR_BURSTTIME: + stack.p.data = rad->bursttime[chan->chanpos - 1]; + break; + case ZT_RADPAR_UIODATA: + stack.p.data = 0; + byte1 = __pciradio_getcreg(rad,8); + if (byte1 & (1 << (chan->chanpos - 1))) stack.p.data |= 1; + if (byte1 & (1 << (chan->chanpos + 3))) stack.p.data |= 2; + break; + case ZT_RADPAR_UIOMODE: + stack.p.data = 0; + byte1 = __pciradio_getcreg(rad,0xe); + if (byte1 & (1 << (chan->chanpos - 1))) stack.p.data |= 1; + if (byte1 & (1 << (chan->chanpos + 3))) stack.p.data |= 2; + break; + case ZT_RADPAR_REMMODE: + stack.p.data = rad->remmode[chan->chanpos - 1]; + break; + default: + spin_unlock_irqrestore(&rad->lock,flags); + return -EINVAL; + } + spin_unlock_irqrestore(&rad->lock,flags); + if (copy_to_user((struct zt_radio_param *)data,&stack.p,sizeof(struct zt_radio_param))) return -EFAULT; + break; + case ZT_RADIO_SETPARAM: + if (copy_from_user(&stack.p,(struct zt_radio_param *)data,sizeof(struct zt_radio_param))) return -EFAULT; + spin_lock_irqsave(&rad->lock,flags); + switch(stack.p.radpar) { + case ZT_RADPAR_INVERTCOR: + if (stack.p.data) + rad->radmode[chan->chanpos - 1] |= RADMODE_INVERTCOR; + else + rad->radmode[chan->chanpos - 1] &= ~RADMODE_INVERTCOR; + break; + case ZT_RADPAR_IGNORECOR: + if (stack.p.data) + rad->radmode[chan->chanpos - 1] |= RADMODE_IGNORECOR; + else + rad->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECOR; + break; + case ZT_RADPAR_IGNORECT: + if (stack.p.data) + rad->radmode[chan->chanpos - 1] |= RADMODE_IGNORECT; + else + rad->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECT; + break; + case ZT_RADPAR_NOENCODE: + if (stack.p.data) + rad->radmode[chan->chanpos - 1] |= RADMODE_NOENCODE; + else + rad->radmode[chan->chanpos - 1] &= ~RADMODE_NOENCODE; + break; + case ZT_RADPAR_CORTHRESH: + if ((stack.p.data < 0) || (stack.p.data > 7)) { + spin_unlock_irqrestore(&rad->lock,flags); + return -EINVAL; + } + rad->corthresh[chan->chanpos - 1] = stack.p.data; + byte1 = 0xc0 | (rad->corthresh[chan->chanpos - 1] << 2); + spin_unlock_irqrestore(&rad->lock,flags); + mx828_command_wait(rad,chan->chanpos - 1, MX828_GEN_CTRL, &byte1, &byte2); + spin_lock_irqsave(&rad->lock,flags); + break; + case ZT_RADPAR_EXTRXTONE: + if (stack.p.data) + rad->radmode[chan->chanpos - 1] |= RADMODE_EXTTONE; + else + rad->radmode[chan->chanpos - 1] &= ~RADMODE_EXTTONE; + if (stack.p.data > 1) + rad->radmode[chan->chanpos - 1] |= RADMODE_EXTINVERT; + else + rad->radmode[chan->chanpos - 1] &= ~RADMODE_EXTINVERT; + break; + case ZT_RADPAR_INITTONE: + for(i = 0; i <= NUM_CODES; i++) + { + rad->rxcode[chan->chanpos - 1][i] = 0; + rad->rxclass[chan->chanpos - 1][i] = 0; + rad->txcode[chan->chanpos - 1][i] = 0; + } + spin_unlock_irqrestore(&rad->lock,flags); + for(i = 0; i < NUM_CODES; i++) + { + /* set to no encode/decode */ + byte1 = 0; + mx828_command_wait(rad,chan->chanpos - 1, MX828_SAUDIO_CTRL, &byte1, &byte2 ); + /* set rx tone to none */ + byte1 = i << 4; + byte2 = 0; + mx828_command_wait(rad,chan->chanpos - 1, MX828_RX_TONE, &byte1, &byte2 ); + } + spin_lock_irqsave(&rad->lock,flags); + break; + case ZT_RADPAR_RXTONE: + if (!stack.p.index) /* if RX DCS mode */ + { + if ((stack.p.data < 0) || (stack.p.data > 777)) { + spin_unlock_irqrestore(&rad->lock,flags); + return -EINVAL; + } + mycode = getdcstone(stack.p.data); + if (mycode < 0) { + spin_unlock_irqrestore(&rad->lock,flags); + return -EINVAL; + } + rad->rxcode[chan->chanpos - 1][0] = mycode; + rad->encdec.req[chan->chanpos - 1] = 1; + break; + } + if ((stack.p.index < 1) || (stack.p.index > NUM_CODES)) { + spin_unlock_irqrestore(&rad->lock,flags); + return -EINVAL; + } + mycode = getrxtone(stack.p.data); + if (mycode < 0) { + spin_unlock_irqrestore(&rad->lock,flags); + return -EINVAL; + } + rad->rxcode[chan->chanpos - 1][stack.p.index] = mycode; + byte1 = cttable_rx[mycode].b1 | ((stack.p.index - 1) << 4); + byte2 = cttable_rx[mycode].b2; + spin_unlock_irqrestore(&rad->lock,flags); + mx828_command_wait(rad,chan->chanpos - 1, MX828_RX_TONE, &byte1, &byte2 ); + spin_lock_irqsave(&rad->lock,flags); + /* zot out DCS one if there */ + rad->rxcode[chan->chanpos - 1][0] = 0; + rad->encdec.req[chan->chanpos - 1] = 1; + break; + case ZT_RADPAR_RXTONECLASS: + if ((stack.p.index < 1) || (stack.p.index > NUM_CODES)) { + spin_unlock_irqrestore(&rad->lock,flags); + return -EINVAL; + } + rad->rxclass[chan->chanpos - 1][stack.p.index] = stack.p.data & 0xffff; + break; + case ZT_RADPAR_TXTONE: + if (stack.p.index > NUM_CODES) { + spin_unlock_irqrestore(&rad->lock,flags); + return -EINVAL; + } + if (stack.p.data & 0x8000) /* if dcs */ + mycode = getdcstone(stack.p.data & 0x7fff); + else + mycode = gettxtone(stack.p.data); + if (mycode < 0) { + spin_unlock_irqrestore(&rad->lock,flags); + return -EINVAL; + } + if (stack.p.data & 0x8000) mycode |= 0x8000; + rad->txcode[chan->chanpos - 1][stack.p.index] = mycode; + rad->encdec.req[chan->chanpos - 1] = 1; + break; + case ZT_RADPAR_DEBOUNCETIME: + rad->debouncetime[chan->chanpos - 1] = stack.p.data; + break; + + case ZT_RADPAR_CTCSSACQUIRETIME: + rad->ctcssacquiretime[chan->chanpos - 1] = stack.p.data; + break; + + case ZT_RADPAR_CTCSSTALKOFFTIME: + rad->ctcsstalkofftime[chan->chanpos - 1] = stack.p.data; + break; + + case ZT_RADPAR_BURSTTIME: + rad->bursttime[chan->chanpos - 1] = stack.p.data; + break; + case ZT_RADPAR_UIODATA: + byte1 = __pciradio_getcreg(rad,8); + byte1 &= ~(1 << (chan->chanpos - 1)); + byte1 &= ~(1 << (chan->chanpos + 3)); + if (stack.p.data & 1) byte1 |= (1 << (chan->chanpos - 1)); + if (stack.p.data & 2) byte1 |= (1 << (chan->chanpos + 3)); + __pciradio_setcreg(rad,8,byte1); + break; + case ZT_RADPAR_UIOMODE: + byte1 = __pciradio_getcreg(rad,0xe); + byte1 &= ~(1 << (chan->chanpos - 1)); + byte1 &= ~(1 << (chan->chanpos + 3)); + if (stack.p.data & 1) byte1 |= (1 << (chan->chanpos - 1)); + if (stack.p.data & 2) byte1 |= (1 << (chan->chanpos + 3)); + __pciradio_setcreg(rad,0xe,byte1); + break; + case ZT_RADPAR_REMMODE: + rad->remmode[chan->chanpos - 1] = stack.p.data; + break; + case ZT_RADPAR_REMCOMMAND: + /* if no remote mode, return an error */ + if (rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_NONE) + { + spin_unlock_irqrestore(&rad->lock,flags); + return -EINVAL; + } + i = 0; + if (rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_RBI1) + { + /* set UIOA and UIOB for output */ + byte1 = __pciradio_getcreg(rad,0xe); + mask = (1 << (chan->chanpos - 1)) | + (1 << (chan->chanpos + 3)); + byte2 = byte1 & (~mask); + i = (byte2 != byte1); + __pciradio_setcreg(rad,0xe,byte2); + byte1 = __pciradio_getcreg(rad,8); + mask = 1 << (chan->chanpos - 1); + byte2 = byte1 | mask; + i = (byte2 != byte1); + __pciradio_setcreg(rad,8,byte2); + spin_unlock_irqrestore(&rad->lock,flags); + if (i || (jiffies < rad->lastremcmd + 10)) + interruptible_sleep_on_timeout(&mywait,10); + rad->lastremcmd = jiffies; + rbi_out(rad,chan->chanpos - 1,(unsigned char *)&stack.p.data); + spin_lock_irqsave(&rad->lock,flags); + break; + } + spin_unlock_irqrestore(&rad->lock,flags); + for(;;) + { + int x; + + spin_lock_irqsave(&rad->lock,flags); + x = rad->remote_locked || (__pciradio_getcreg(rad,0xc) & 2); + if (!x) rad->remote_locked = 1; + spin_unlock_irqrestore(&rad->lock,flags); + if (x) interruptible_sleep_on_timeout(&mywait,2); + else break; + } + spin_lock_irqsave(&rad->lock,flags); + /* set UIOA for input and UIOB for output */ + byte1 = __pciradio_getcreg(rad,0xe); + mask = 1 << (chan->chanpos + 3); /* B an output */ + byte2 = byte1 & (~mask); + byte2 |= 1 << (chan->chanpos - 1); /* A in input */ + __pciradio_setcreg(rad,0xe,byte2); + byte1 = __pciradio_getcreg(rad,8); + byte2 = byte1 | mask; + byte2 |= 1 << (chan->chanpos - 1); + byte2 |= 1 << (chan->chanpos + 3); + __pciradio_setcreg(rad,8,byte2); + spin_unlock_irqrestore(&rad->lock,flags); + if (byte1 != byte2) + interruptible_sleep_on_timeout(&mywait,3); + while (jiffies < rad->lastremcmd + 10) + interruptible_sleep_on_timeout(&mywait,10); + rad->lastremcmd = jiffies; + for(;;) + { + if (!(__pciradio_getcreg(rad,0xc) & 2)) break; + interruptible_sleep_on_timeout(&mywait,2); + } + spin_lock_irqsave(&rad->lock,flags); + /* enable and address async serializer */ + __pciradio_setcreg(rad,0xf,rad->pfsave | ((chan->chanpos - 1) << 4) | 0x80); + /* copy tx buffer */ + memcpy(rad->txbuf,stack.p.buf,stack.p.index); + rad->txlen = stack.p.index; + rad->txindex = 0; + rad->rxindex = 0; + rad->srxtimer = 0; + memset(stack.p.buf,0,SERIAL_BUFLEN); + stack.p.index = 0; + if (stack.p.data) for(;;) + { + rad->rxbuf[rad->rxindex] = 0; + if ((rad->rxindex < stack.p.data) && + (rad->srxtimer < SRX_TIMEOUT) && + ((rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_SERIAL) || + (!strchr((char *)rad->rxbuf,'\r')))) + { + spin_unlock_irqrestore(&rad->lock,flags); + interruptible_sleep_on_timeout(&mywait,2); + spin_lock_irqsave(&rad->lock,flags); + continue; + } + memset(stack.p.buf,0,SERIAL_BUFLEN); + if (stack.p.data && (rad->rxindex > stack.p.data)) + rad->rxindex = stack.p.data; + if (rad->rxindex) + memcpy(stack.p.buf,rad->rxbuf,rad->rxindex); + stack.p.index = rad->rxindex; + break; + } + /* wait for done only if in SERIAL_ASCII mode */ + if (rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_SERIAL_ASCII) + { + /* wait for TX to be done if not already */ + while(rad->txlen && (rad->txindex < rad->txlen)) + { + spin_unlock_irqrestore(&rad->lock,flags); + interruptible_sleep_on_timeout(&mywait,2); + spin_lock_irqsave(&rad->lock,flags); + } + /* disable and un-address async serializer */ + __pciradio_setcreg(rad,0xf,rad->pfsave); + } + rad->remote_locked = 0; + spin_unlock_irqrestore(&rad->lock,flags); + if (rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_SERIAL_ASCII) + interruptible_sleep_on_timeout(&mywait,100); + if (copy_to_user((struct zt_radio_stat *)data,&stack.p,sizeof(struct zt_radio_param))) return -EFAULT; + return 0; + default: + spin_unlock_irqrestore(&rad->lock,flags); + return -EINVAL; + } + spin_unlock_irqrestore(&rad->lock,flags); + break; + case ZT_RADIO_GETSTAT: + spin_lock_irqsave(&rad->lock,flags); + /* start with clean object */ + memset(&stack.s,0,sizeof(struct zt_radio_stat)); + /* if we have rx */ + if (rad->gotrx[chan->chanpos - 1]) + { + stack.s.radstat |= ZT_RADSTAT_RX; + if (rad->rxcode[chan->chanpos - 1][0]) + stack.s.ctcode_rx = + dcstable[rad->rxcode[chan->chanpos - 1][0]].code | 0x8000; + else { + stack.s.ctcode_rx = + cttable_rx[rad->rxcode[chan->chanpos - 1][rad->present_code[chan->chanpos - 1]]].code; + stack.s.ctclass = + rad->rxclass[chan->chanpos - 1][rad->present_code[chan->chanpos - 1]]; + } + } + /* if we have tx */ + if (rad->gottx[chan->chanpos - 1]) + { + unsigned short x,myindex; + + stack.s.radstat |= ZT_RADSTAT_TX; + stack.s.radstat |= ZT_RADSTAT_TX; + + myindex = 0; + if ((!rad->rxcode[chan->chanpos - 1][0]) + && (rad->present_code[chan->chanpos - 1])) + myindex = rad->present_code[chan->chanpos - 1]; + x = rad->txcode[chan->chanpos - 1][myindex]; + if (x & 0x8000) + stack.s.ctcode_tx = dcstable[x & 0x7fff].code | 0x8000; + else + stack.s.ctcode_tx = cttable_tx[x].code; + + } + + if (rad->radmode[chan->chanpos - 1] & RADMODE_IGNORECOR) + stack.s.radstat |= ZT_RADSTAT_IGNCOR; + if (rad->radmode[chan->chanpos - 1] & RADMODE_IGNORECT) + stack.s.radstat |= ZT_RADSTAT_IGNCT; + if (rad->radmode[chan->chanpos - 1] & RADMODE_NOENCODE) + stack.s.radstat |= ZT_RADSTAT_NOENCODE; + if (rad->gotcor[chan->chanpos - 1]) + stack.s.radstat |= ZT_RADSTAT_RXCOR; + if (rad->gotct[chan->chanpos - 1]) + stack.s.radstat |= ZT_RADSTAT_RXCT; + spin_unlock_irqrestore(&rad->lock,flags); + if (copy_to_user((struct zt_radio_stat *)data,&stack.s,sizeof(struct zt_radio_stat))) return -EFAULT; + break; + default: + return -ENOTTY; + } + return 0; + +} + +static int pciradio_open(struct zt_chan *chan) +{ + struct pciradio *rad = chan->pvt; + if (rad->dead) + return -ENODEV; + rad->usecount++; +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#endif + return 0; +} + +static int pciradio_watchdog(struct zt_span *span, int event) +{ + printk("PCI RADIO: Restarting DMA\n"); + pciradio_restart_dma(span->pvt); + return 0; +} + +static int pciradio_close(struct zt_chan *chan) +{ + struct pciradio *rad = chan->pvt; + rad->usecount--; +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#endif + /* If we're dead, release us now */ + if (!rad->usecount && rad->dead) + pciradio_release(rad); + return 0; +} + +static int pciradio_hooksig(struct zt_chan *chan, zt_txsig_t txsig) +{ + struct pciradio *rad = chan->pvt; + + switch(txsig) { + case ZT_TXSIG_START: + case ZT_TXSIG_OFFHOOK: + rad->gottx[chan->chanpos - 1] = 1; + break; + case ZT_TXSIG_ONHOOK: + rad->gottx[chan->chanpos - 1] = 0; + break; + default: + printk("pciradio: Can't set tx state to %d\n", txsig); + break; + } + if (debug) + printk("pciradio: Setting Radio hook state to %d on chan %d\n", txsig, chan->chanpos); + return 0; +} + +static int pciradio_initialize(struct pciradio *rad) +{ + int x; + + /* Zapata stuff */ + sprintf(rad->span.name, "PCIRADIO/%d", rad->pos); + sprintf(rad->span.desc, "Board %d", rad->pos + 1); + rad->span.deflaw = ZT_LAW_MULAW; + for (x=0;xnchans;x++) { + sprintf(rad->chans[x].name, "PCIRADIO/%d/%d", rad->pos, x); + rad->chans[x].sigcap = ZT_SIG_SF | ZT_SIG_EM; + rad->chans[x].chanpos = x+1; + rad->chans[x].pvt = rad; + rad->debouncetime[x] = RAD_GOTRX_DEBOUNCE_TIME; + rad->ctcssacquiretime[x] = RAD_CTCSS_ACQUIRE_TIME; + rad->ctcsstalkofftime[x] = RAD_CTCSS_TALKOFF_TIME; + } + rad->span.chans = rad->chans; + rad->span.channels = rad->nchans; + rad->span.hooksig = pciradio_hooksig; + rad->span.open = pciradio_open; + rad->span.close = pciradio_close; + rad->span.flags = ZT_FLAG_RBS; + rad->span.ioctl = pciradio_ioctl; + rad->span.watchdog = pciradio_watchdog; + init_waitqueue_head(&rad->span.maintq); + + rad->span.pvt = rad; + if (zt_register(&rad->span, 0)) { + printk("Unable to register span with zaptel\n"); + return -1; + } + return 0; +} + +static void wait_just_a_bit(int foo) +{ + long newjiffies; + newjiffies = jiffies + foo; + while(jiffies < newjiffies); +} + +static int pciradio_hardware_init(struct pciradio *rad) +{ +unsigned char byte1,byte2; +int x; +unsigned long endjif; + + /* Signal Reset */ + outb(0x01, rad->ioaddr + RAD_CNTL); + + /* Reset PCI Interface chip and registers (and serial) */ + outb(0x06, rad->ioaddr + RAD_CNTL); + /* Setup our proper outputs */ + rad->ios = 0xfe; + outb(rad->ios, rad->ioaddr + RAD_AUXD); + + /* Set all to outputs except AUX 3 & 4, which are inputs */ + outb(0x67, rad->ioaddr + RAD_AUXC); + + /* Select alternate function for AUX0 */ + outb(0x4, rad->ioaddr + RAD_AUXFUNC); + + /* Wait 1/4 of a sec */ + wait_just_a_bit(HZ/4); + + /* attempt to load the Xilinx Chip */ + /* De-assert CS+Write */ + rad->ios |= XCS; + outb(rad->ios, rad->ioaddr + RAD_AUXD); + /* Assert PGM */ + rad->ios &= ~XPGM; + outb(rad->ios, rad->ioaddr + RAD_AUXD); + /* wait for INIT and DONE to go low */ + endjif = jiffies + 10; + while (inb(rad->ioaddr + RAD_AUXR) & (XINIT | XDONE) && (jiffies <= endjif)); + if (endjif < jiffies) { + printk("Timeout waiting for INIT and DONE to go low\n"); + return -1; + } + if (debug) printk("fwload: Init and done gone to low\n"); + /* De-assert PGM */ + rad->ios |= XPGM; + outb(rad->ios, rad->ioaddr + RAD_AUXD); + /* wait for INIT to go high (clearing done */ + endjif = jiffies + 10; + while (!(inb(rad->ioaddr + RAD_AUXR) & XINIT) && (jiffies <= endjif)); + if (endjif < jiffies) { + printk("Timeout waiting for INIT to go high\n"); + return -1; + } + if (debug) printk("fwload: Init went high (clearing done)\nNow loading...\n"); + /* Assert CS+Write */ + rad->ios &= ~XCS; + outb(rad->ios, rad->ioaddr + RAD_AUXD); + for (x = 0; x < sizeof(radfw); x++) + { + /* write the byte */ + outb(radfw[x],rad->ioaddr + RAD_REGBASE); + /* if DONE signal, we're done, exit */ + if (inb(rad->ioaddr + RAD_AUXR) & XDONE) break; + /* if INIT drops, we're screwed, exit */ + if (!(inb(rad->ioaddr + RAD_AUXR) & XINIT)) break; + } + if (debug) printk("fwload: Transferred %d bytes into chip\n",x); + /* Wait for FIFO to clear */ + endjif = jiffies + 2; + while (jiffies < endjif); /* wait */ + printk("Transfered %d bytes into chip\n",x); + /* De-assert CS+Write */ + rad->ios |= XCS; + outb(rad->ios, rad->ioaddr + RAD_AUXD); + if (debug) printk("fwload: Loading done!\n"); + /* Wait for FIFO to clear */ + endjif = jiffies + 2; + while (jiffies < endjif); /* wait */ + if (!(inb(rad->ioaddr + RAD_AUXR) & XINIT)) + { + printk("Drove Init low!! CRC Error!!!\n"); + return -1; + } + if (!(inb(rad->ioaddr + RAD_AUXR) & XDONE)) + { + printk("Did not get DONE signal. Short file maybe??\n"); + return -1; + } + wait_just_a_bit(2); + /* get the thingy started */ + outb(0,rad->ioaddr + RAD_REGBASE); + outb(0,rad->ioaddr + RAD_REGBASE); + printk("Xilinx Chip successfully loaded, configured and started!!\n"); + + wait_just_a_bit(HZ/4); + + + /* Back to normal, with automatic DMA wrap around */ + outb(0x30 | 0x01, rad->ioaddr + RAD_CNTL); + + /* Configure serial port for MSB->LSB operation */ + outb(0xc1, rad->ioaddr + RAD_SERCTL); /* DEBUG set double dlck to 0 SR */ + + rad->pasave = 0; + __pciradio_setcreg(rad,0xa,rad->pasave); + + __pciradio_setcreg(rad,0xf,rad->pfsave); + __pciradio_setcreg(rad,8,0xff); + __pciradio_setcreg(rad,0xe,0xff); + __pciradio_setcreg(rad,9,0); + rad->pfsave = 0; + + /* Delay FSC by 0 so it's properly aligned */ + outb(/* 1 */ 0, rad->ioaddr + RAD_FSCDELAY); + + /* Setup DMA Addresses */ + outl(rad->writedma, rad->ioaddr + RAD_DMAWS); /* Write start */ + outl(rad->writedma + ZT_CHUNKSIZE * 4 - 4, rad->ioaddr + RAD_DMAWI); /* Middle (interrupt) */ + outl(rad->writedma + ZT_CHUNKSIZE * 8 - 4, rad->ioaddr + RAD_DMAWE); /* End */ + + outl(rad->readdma, rad->ioaddr + RAD_DMARS); /* Read start */ + outl(rad->readdma + ZT_CHUNKSIZE * 4 - 4, rad->ioaddr + RAD_DMARI); /* Middle (interrupt) */ + outl(rad->readdma + ZT_CHUNKSIZE * 8 - 4, rad->ioaddr + RAD_DMARE); /* End */ + + /* Clear interrupts */ + outb(0xff, rad->ioaddr + RAD_INTSTAT); + + /* Wait 1/4 of a second more */ + wait_just_a_bit(HZ/4); + + for(x = 0; x < rad->nchans; x++) + { + mx828_command_wait(rad,x, MX828_GEN_RESET, &byte1, &byte2 ); + byte1 = 0x3f; + byte2 = 0x3f; + mx828_command_wait(rad,x, MX828_AUD_CTRL, &byte1, &byte2 ); + byte1 = 0; + mx828_command_wait(rad,x, MX828_SAUDIO_SETUP, &byte1, &byte2 ); + byte1 = 0; + mx828_command_wait(rad,x, MX828_SAUDIO_CTRL, &byte1, &byte2 ); + byte1 = 0xc8; /* default COR thresh is 2 */ + mx828_command_wait(rad,x, MX828_GEN_CTRL, &byte1, &byte2); + rad->corthresh[x] = 2; + } + /* Wait 1/4 of a sec */ + wait_just_a_bit(HZ/4); + + return 0; +} + +static void pciradio_enable_interrupts(struct pciradio *rad) +{ + /* Enable interrupts (we care about all of them) */ + outb(0x3f, rad->ioaddr + RAD_MASK0); + /* No external interrupts */ + outb(0x00, rad->ioaddr + RAD_MASK1); +} + +static void pciradio_restart_dma(struct pciradio *rad) +{ + /* Reset Master and serial */ + outb(0x31, rad->ioaddr + RAD_CNTL); + outb(0x01, rad->ioaddr + RAD_OPER); +} + +static void pciradio_start_dma(struct pciradio *rad) +{ + /* Reset Master and serial */ + outb(0x3f, rad->ioaddr + RAD_CNTL); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + outb(0x31, rad->ioaddr + RAD_CNTL); + outb(0x01, rad->ioaddr + RAD_OPER); +} + +static void pciradio_stop_dma(struct pciradio *rad) +{ + outb(0x00, rad->ioaddr + RAD_OPER); +} + +static void pciradio_reset_serial(struct pciradio *rad) +{ + /* Reset serial */ + outb(0x3f, rad->ioaddr + RAD_CNTL); +} + +static void pciradio_disable_interrupts(struct pciradio *rad) +{ + outb(0x00, rad->ioaddr + RAD_MASK0); + outb(0x00, rad->ioaddr + RAD_MASK1); +} + +static int __devinit pciradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int res; + struct pciradio *rad; + int x; + static int initd_ifaces=0; + + if(initd_ifaces){ + memset((void *)ifaces,0,(sizeof(struct pciradio *))*RAD_MAX_IFACES); + initd_ifaces=1; + } + for (x=0;x= RAD_MAX_IFACES) { + printk("Too many interfaces\n"); + return -EIO; + } + + if (pci_enable_device(pdev)) { + res = -EIO; + } else { + rad = kmalloc(sizeof(struct pciradio), GFP_KERNEL); + if (rad) { + int i; + + ifaces[x] = rad; + memset(rad, 0, sizeof(struct pciradio)); + spin_lock_init(&rad->lock); + rad->nchans = 4; + rad->ioaddr = pci_resource_start(pdev, 0); + rad->dev = pdev; + rad->pos = x; + for(i = 0; i < rad->nchans; i++) rad->lasttx[x] = rad->gotrx1[i] = -1; + /* Keep track of whether we need to free the region */ + if (request_region(rad->ioaddr, 0xff, "pciradio")) + rad->freeregion = 1; + + /* Allocate enough memory for two zt chunks, receive and transmit. Each sample uses + 32 bits. Allocate an extra set just for control too */ + rad->writechunk = pci_alloc_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, &rad->writedma); + if (!rad->writechunk) { + printk("pciradio: Unable to allocate DMA-able memory\n"); + if (rad->freeregion) + release_region(rad->ioaddr, 0xff); + return -ENOMEM; + } + + rad->readchunk = rad->writechunk + ZT_MAX_CHUNKSIZE * 2; /* in doublewords */ + rad->readdma = rad->writedma + ZT_MAX_CHUNKSIZE * 8; /* in bytes */ + + if (pciradio_initialize(rad)) { + printk("pciradio: Unable to intialize\n"); + /* Set Reset Low */ + x=inb(rad->ioaddr + RAD_CNTL); + outb((~0x1)&x, rad->ioaddr + RAD_CNTL); + outb(x, rad->ioaddr + RAD_CNTL); + __pciradio_setcreg(rad,8,0xff); + __pciradio_setcreg(rad,0xe,0xff); + /* Free Resources */ + free_irq(pdev->irq, rad); + if (rad->freeregion) + release_region(rad->ioaddr, 0xff); + pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma); + kfree(rad); + return -EIO; + } + + /* Enable bus mastering */ + pci_set_master(pdev); + + /* Keep track of which device we are */ + pci_set_drvdata(pdev, rad); + + if (pciradio_hardware_init(rad)) { + unsigned char x; + + /* Set Reset Low */ + x=inb(rad->ioaddr + RAD_CNTL); + outb((~0x1)&x, rad->ioaddr + RAD_CNTL); + outb(x, rad->ioaddr + RAD_CNTL); + __pciradio_setcreg(rad,8,0xff); + __pciradio_setcreg(rad,0xe,0xff); + /* Free Resources */ + free_irq(pdev->irq, rad); + if (rad->freeregion) + release_region(rad->ioaddr, 0xff); + pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma); + pci_set_drvdata(pdev, NULL); + zt_unregister(&rad->span); + kfree(rad); + return -EIO; + + } + + if (request_irq(pdev->irq, pciradio_interrupt, ZAP_IRQ_SHARED, "pciradio", rad)) { + printk("pciradio: Unable to request IRQ %d\n", pdev->irq); + if (rad->freeregion) + release_region(rad->ioaddr, 0xff); + pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma); + pci_set_drvdata(pdev, NULL); + kfree(rad); + return -EIO; + } + + /* Enable interrupts */ + pciradio_enable_interrupts(rad); + /* Initialize Write/Buffers to all blank data */ + memset((void *)rad->writechunk,0,ZT_MAX_CHUNKSIZE * 2 * 2 * 4); + + /* Start DMA */ + pciradio_start_dma(rad); + printk("Found a PCI Radio Card\n"); + res = 0; + } else + res = -ENOMEM; + } + return res; +} + +static void pciradio_release(struct pciradio *rad) +{ + zt_unregister(&rad->span); + if (rad->freeregion) + release_region(rad->ioaddr, 0xff); + kfree(rad); + printk("Freed a PCI RADIO card\n"); +} + +static void __devexit pciradio_remove_one(struct pci_dev *pdev) +{ + struct pciradio *rad = pci_get_drvdata(pdev); + if (rad) { + + /* Stop any DMA */ + pciradio_stop_dma(rad); + pciradio_reset_serial(rad); + + /* In case hardware is still there */ + pciradio_disable_interrupts(rad); + + /* Immediately free resources */ + pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma); + free_irq(pdev->irq, rad); + + /* Reset PCI chip and registers */ + outb(0x3e, rad->ioaddr + RAD_CNTL); + + /* Clear Reset Line */ + outb(0x3f, rad->ioaddr + RAD_CNTL); + + __pciradio_setcreg(rad,8,0xff); + __pciradio_setcreg(rad,0xe,0xff); + + /* Release span, possibly delayed */ + if (!rad->usecount) + pciradio_release(rad); + else + rad->dead = 1; + } +} + +static struct pci_device_id pciradio_pci_tbl[] = { + { 0xe159, 0x0001, 0xe16b, PCI_ANY_ID, 0, 0, (unsigned long)"PCIRADIO" }, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, pciradio_pci_tbl); + +static struct pci_driver pciradio_driver = { + name: "pciradio", + probe: pciradio_init_one, +#ifdef LINUX26 + remove: __devexit_p(pciradio_remove_one), +#else + remove: pciradio_remove_one, +#endif + suspend: NULL, + resume: NULL, + id_table: pciradio_pci_tbl, +}; + +static int __init pciradio_init(void) +{ + int res; + + res = zap_pci_module(&pciradio_driver); + if (res) + return -ENODEV; + return 0; +} + +static void __exit pciradio_cleanup(void) +{ + pci_unregister_driver(&pciradio_driver); +} + +#ifdef LINUX26 +module_param(debug, int, 0600); +#else +MODULE_PARM(debug, "i"); +#endif + +MODULE_DESCRIPTION("Zapata Telephony PCI Radio Card Zaptel Driver"); +MODULE_AUTHOR("Jim Dixon "); + +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +module_init(pciradio_init); +module_exit(pciradio_cleanup); diff --git a/kernel/pciradio.rbt b/kernel/pciradio.rbt new file mode 100644 index 0000000..3cd2517 --- /dev/null +++ b/kernel/pciradio.rbt @@ -0,0 +1,10531 @@ +Xilinx ASCII Bitstream +Created by Bitstream E.33 +Design name: pciradio_xilinx.ncd +Architecture: spartan2 +Part: 2s30vq100 +Date: Sat Mar 12 18:19:05 2005 +Bits: 336768 +11111111111111111111111111111111 +10101010100110010101010101100110 +00110000000000001000000000000001 +00000000000000000000000000000111 +00110000000000010110000000000001 +00000000000000000000000000001000 +00110000000000010010000000000001 +00000000100000000011111100101101 +00110000000000001100000000000001 +00000000000000000000000000000000 +00110000000000001000000000000001 +00000000000000000000000000001001 +00110000000000000010000000000001 +00000000000000000000000000000000 +00110000000000001000000000000001 +00000000000000000000000000000001 +00110000000000000100000000000000 +01010000000000000010010001100011 +00000000000100100010000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000001000000000010010000000 +00000000000000000000000000000000 +00000000000100100010000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000010010000000 +00000000000000000000000000000000 +00010000000000100000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000010000000 +00000000000000000000000000000000 +00000000000000100000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000010000000 +00000000000000000000000000000000 +00000000000100100000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000010010000000 +00000000000000000000000000000000 +00010000000100100000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000001000000000010010000000 +00000000000000000000000000000000 +00010000000100100000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000010000000000 +00000000000000000000000000000000 +11101111000100100000000000001110 +00000000000000111000000000000001 +11100000000000000111100000000000 +00011110000000000000011110000000 +00000001111000000000000001111000 +00000000000111100000000000000101 +00000000000000010100000000000000 +01010000000111111100010000000000 +00000000000000000000000000000000 +11000000000001011111101000000001 +11101111001110000011011111110000 +00001100111100000101001100111100 +00000000111111011000000000110111 +11000100000011001101000000000011 +00110000010000001100111000000000 +00110011100000000000110101000000 +00000011001100000000000001110000 +00000000000000000000000000000000 +10000000000100001110101000000000 +11101111010000000010001011000000 +01011101111101000000001000111101 +00010000101110011000001000100011 +11010000100010101000000000000010 +00001000000000001000100010000000 +00100010100101000000100010101000 +00000011001000000000010000110000 +00000000000000000000000000000000 +10001000000001011100010000010001 +10100011001000000010011011001000 +00001000001101000000101000001101 +00000000101110010000000000100100 +11011000000010001001000000000010 +00001000000000001000000100000000 +00100010100000000001100100010000 +01000010011000100000000101110000 +00000000000000000000000000000000 +11000000000101011010000000000000 +10101011000000000010001011000100 +00011001101100000000001000101100 +00000000101110011000000000100010 +11000000000010101001000000000010 +00101000001000001000100000001000 +00100010101100000010100010110000 +10000010001100000000010001100000 +00000000000000000000000000000000 +00000000000101011110101110010000 +11101011000000100011010011101000 +00001100101100000000001100101100 +00000000111100110000000000110110 +11000000010011000001100000001011 +00100111000000001100101001000000 +00110010001000000000110110000100 +00000011010000000000010001110000 +00000000000000000000000000000000 +11100000000000011011101100000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111110 +11000000000011111100000100000011 +11111000100000001111101000100000 +00111110110000000010111101000000 +00001011111110000000000001100000 +00000000000000000000000000000000 +01000000000100001010010100000000 +11110011000001010011111011010001 +00001101001100100000001111101100 +00000000110010010001010000110110 +11000000000011001001000100000011 +00101101000000001110000101100000 +00111010000100000000110110101100 +00000011000100000000010000100000 +00000000000000000000000000000000 +11001000000001010010000000000100 +10111111000000000010111011000000 +00001000111101000000001011111101 +01000010100010011000010100101111 +11000001000010001001000000001010 +10101000000000001000101001000000 +00100000110101000000100010100000 +00000010101100100000000001000000 +00000000000000000000000000000000 +11100000000001010100100000000000 +10110011000000000010110011000000 +01001000001111010001001001001100 +00000000100000010100100000101110 +11000000100010000011110010000010 +00101000000000001010001001000001 +00101000100000000000100000000000 +00000010101110000000000001010000 +00000000000000000000000000000000 +00100000000000010001111000000000 +10110111100000000010111110100000 +00101000011110000000001011001110 +00000000100001011000000000101101 +11100000010010000010100100000010 +10011110000010001000010110000010 +00100001111000000000100001101000 +00000010100110000000000001000000 +00000000000000000000000000000000 +01001000000010000000110000000000 +11110011000000000011110011000000 +00001100001100000000001101001100 +11000000110000110000000000110100 +11000000000011000011000000000011 +00001000000100001110001100000000 +10111000100000000010110000010000 +00000011000100100000001000000000 +00000000000000000000000000000000 +01000000010011011011110000000000 +11111111000000000011110111000000 +01001110111101010000001111111100 +01000000111111110000000000110111 +11000010000011111111000000000011 +11111100010000001111110100010000 +00111111110000000000111011110001 +00000011010100000000011001100000 +00000000000000000000000000000000 +10101000000101011110100100000000 +11111011001000000011110011000000 +00011100101101000000101100101100 +10000001111110110010100000111110 +11000000001011001001000000001011 +00101100000000001100101000000001 +00110010100000000000000010010000 +00000011111010100000000001010000 +00000000000000000000000000000000 +01001000000110011001110100100000 +10110111010010010010110101000000 +00101100001101100000001000011100 +00100101101101110100000000101111 +11001100000010000100000000000010 +00001100000010001000001100000000 +10100001100000000000100000010000 +00000010100100100000010001100000 +00000000000000000000000000000000 +11000000000000001001111010000000 +10110111101000000010111111100000 +00001000011110100001001000011110 +01001000100101111010001000100101 +11101000000010000101100001100010 +00011110000000001000011110000000 +00100001101000000000101001111000 +00000010001100000000000000100000 +00000000000000000000000000000000 +01001000000001001100110000010000 +10110011000000000010111011110000 +00001000001100000000001000001100 +00000000101100110000000000101110 +11000000000010000001100000100010 +00001101001000001000001110010000 +00100010101001000010101000110010 +00000010100100100000010000110000 +00000000000000000000000000000000 +11101000000101011110100000000000 +11111010000000000011111110000000 +00011100101000000000011100101000 +00000000101110100000001000111110 +10000000000011001110101000000011 +00111000000000101100111000000001 +10110011100000000000111011100010 +00101011101110100000010001100000 +00000000000000000000000000000000 +01001000000000011010000000000000 +11111000000000010011111000001100 +01011110100000000000011111000000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11000000000000001111100000000000 +00111110001000000000010110000000 +00000011110100100000000000110000 +00000000000000000000000000000000 +00001000000100001010010000000000 +11110001000000000001001001000000 +00000100100100000010001100100101 +00011000110010010010000000111110 +01000000000011001001000000000010 +00100100000000000100100100000000 +00110010010100000000110000010000 +00000011000000100000010000110000 +00000000000000000000000000000000 +10000000000001000110111001000000 +10111001000000000010001001000000 +00001000100100000000001010100101 +00000010100010111100000100101110 +01000001010010000001110110001010 +00100100000001001000000101100000 +10101010011100000000100010010000 +00000010001000000000000000010000 +00000000000000000000000000000000 +00011000000001010010010000100000 +10111001000000000010101001000000 +00101000000100000000001000100101 +00000000100010010000011000101110 +01000001100010001001000000000010 +10100100000000001000100100000000 +00100010010000000010100010011000 +00000010000001100000000001000000 +00000000000000000000000000000000 +00001000000101001000010000000001 +10110001001010001010100001000000 +00001000000100101000001010000100 +10101000000000110000000000101100 +01001010000010001001001000000010 +10000100100000101000000100100000 +00101000110010000000100000010010 +00011000000000100000000100000000 +00000000000000000000000000000000 +10111000000011011110000000000000 +11111000001000000011101000000000 +00001100100001110000001100100001 +11000000010010000000000000011110 +00001000000011000000010100010011 +10100000000000001100100000000001 +00110000000101000000110010000000 +00000011001011100000001101010000 +00000000000000000000000000000000 +10011000000101011110010000000000 +11111001001010000011011101001011 +00101111100100000000001111100100 +00000000111110010000000000111110 +01001010001011111101000100000011 +01110100111000001011110100010000 +00011111010001000000111111010001 +00000011111001100000011001110000 +00000000000000000000000000000000 +00011000000101011110010000000001 +11111001001010000011111001000100 +00001110110100000000001100110100 +11100000110010110000000000111110 +01010000000011111001010000000011 +00100100000000001100100100000001 +00110011010100000000100011010000 +10000001001001100000000001110000 +00000000000000000000000000000000 +00111000000110000110000000000101 +10110000001000000010111000001000 +00001000100001001001001000100001 +00000010110010000000000000101110 +00101000000010111000000000000010 +10100000101010001000101000000000 +00110110000000000000100010000100 +00000010000011100000010000110000 +00000000000000000000000000000000 +00001000000001010100110000001000 +10110001001011000010111001001000 +00001010000100110000101000000100 +10010010100000010000000000101100 +01010001000010111001010000000010 +00000101000000001000000101000000 +00100000010100000011101000010000 +00000110000000100000000101110000 +00000000000000000000000000000000 +00011000010001011010010010000000 +10111001000000000000111001000000 +00000000100100000000001000100100 +00010000100010010000000000101110 +01000000000010111001010000000010 +10100100100000001000100100000000 +00100100010000000100101010010100 +00000010000001100000010001100000 +00000000000000000000000000000000 +10100000000101011110010100100000 +10111001000000010011110001111000 +01000010100100000011001100100100 +00000000110010010000010000111110 +01000000000011110001000000000011 +00100100000000101100000101000000 +00110010010000000000111010011000 +00001010001010000000010001110000 +00000000000000000000000000000000 +00101000000000001010011000100000 +11111001000001000011111001100100 +00001111000100001000011111000100 +00000000111110011100000000111110 +01000000000011111011000000000011 +11000100000010001111101100010010 +00111110010000000000110110010010 +00000011110010100000000001100000 +00000000000000000000000000000000 +00101000000100001010000100000000 +11111000000001010011101000010000 +00001111100000000000001111100000 +00000000111110000000000000110110 +00000000000011111000000000000011 +11100000000000001111100011000000 +10110010000000000000110010000000 +01000011110010100000010000100000 +00000000000000000000000000000000 +00101000000001000010100100001000 +10111010000000000010001010000000 +00001011111001000001001011111000 +00100000100110100101000000101110 +10000001000010111010100000000010 +11101000000000001011101000000000 +00100011101000000000100001100000 +00000010000010100000000001000000 +00000000000000000000000000000000 +00101000000001010100110100000001 +10110011000000001010000011000000 +00001011001111000000001011001100 +00000000101100110000000000100100 +11000000010010110010000001000010 +11001100000000001011001100000100 +00100000111000000010000100010001 +00000010100010100000000001010000 +00000000000000000000000000000000 +00100000000100010001110000000000 +10110111101000100010000111000000 +10001011011100001000001011011000 +00000000100101110000000000101101 +11000000000010110110010000000010 +11011100110000001011001100000000 +00100000110000100000100101010000 +00000010001010000000000001000000 +00000000000000000000000000000000 +00101000000010000001001001000000 +11110111100000010011000111100000 +00011111011110000000001111011110 +00000000111101001000100000110101 +11100000100011110111100000000011 +11011110101000001111011110010010 +00110001011000000000110100011000 +00000011101010100000001000000000 +00000000000000000000000000000000 +00001000000101011010000110010000 +11111011011010000011011011011010 +00011111101100000001001111101000 +00000001110110100110000000111110 +11000000000011111010010000000011 +11101100100000001111101101000000 +00111110000000000110111010010000 +00000011100000100000011001100000 +00000000000000000000000000000000 +01000000010011011111111000000000 +11001111100010000011011111100110 +00000100110110000000000100111110 +01000000110111111000000000111111 +11100000000011001110110000000011 +00111110000000001100111110000000 +00110011111000000000110011011000 +00000011000100000000000001110000 +00000000000000000000000000000000 +10101000000000011001110001000000 +11011111000000000010000111000000 +01001101010100010000001000111000 +00000000110101100000000001101101 +11000000000010000110010000000010 +00011100000010001010011100000000 +00111111110000000000100001010010 +00000010001010100000010001100000 +00000000000000000000000000000000 +00000000000000001011010000000000 +10000111000000000010010111000001 +00001001010100000000001000011100 +00001000100001010000000000101000 +11000000000010000111000000000010 +00011100000000001001011100000000 +00100001110000100000100001010000 +00000010000001100000000000100000 +00000000000000000000000000000000 +01100000000101001100010000000000 +10010011000000000010010011010100 +00001000100100000000101010001000 +00000000100100100000001000101100 +11000000000010000000010000000010 +00001110100000000011001100100000 +00101100101000000010100000011000 +00000010000110000000010000110000 +00000000000000000000000000000000 +10101000000101011010110100000000 +10001111000001000011011111010000 +00001001101000000000001100100100 +00000001110010110000000000111111 +11000000001011001000000100001011 +00111100100010101101101100100000 +00110010111000000010110010011010 +00000010001011100000010001100000 +00000000000000000000000000000000 +10000000000000001110110000100000 +11111011000000000011101011001000 +00101111101000000000001101100000 +00000000111110010000000000111110 +11000000000011111100010001000011 +11001100000000001110101100000000 +00111110110010000000111110010000 +00000011111000000000000000110000 +00000000000000000000000000000000 +00000001000100001111101000000000 +11111111000000000011111111000000 +00001100101000000000001100111110 +01000000110011001000000001111111 +11000000000011111100001000000011 +00101100000000101100111100000000 +00110011010000000000110001011000 +00000011101000000000010000110000 +00000000000000000000000000000000 +10000001010001000110101000011000 +10111011000001000010110011000000 +00001000101011011000001010101111 +10001000101010001000000000101110 +11000000000010010000110000000010 +00101100000000001000001100000000 +00100010000000000010100010011000 +00100011011000000100000000010000 +00000000000000000000000000000000 +10000000000001010010010010000000 +10111011000000000110111011000000 +00001000101000000000001000000100 +00000000100010110001000000101110 +11000000000010111000000000000010 +00101100000010001000101100000000 +00100000110000000000100010010010 +00000010101000000000000001000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110011000000000110011011000000 +00011010000100000000001010000000 +00000100101000000000000000101100 +11000000000010011000000000001010 +00001100000000011000001110000000 +00100000110000000000100000110000 +00000010010000100000000100000000 +00000000000000000000000000000000 +00000000000001010110010000000000 +11111111000000010011110111000000 +00101100101000000000001100100100 +00000000110010010000010000101110 +11000000000011110000000000000011 +00111100000000001100101100000000 +00110010110000000000110010010000 +00000011101000000000001101010000 +00000000000000000000000000000000 +10100000000101011101010000000000 +10111111000001000011111111000000 +01001101110100000000001111110100 +00000000111111000000000000111111 +11000000000011011100000000000011 +11111100000000001111011000000000 +00111111100000000000111101010000 +00000011101010000000011001110000 +00000000000000000000000000000000 +11000000000001011111010000000100 +10101111001100000011001111010000 +10001101110101000000001111111100 +01000000110011110001000000111111 +01100000000011111111000000000011 +00110110000000001111010010000000 +10110011001000000000111011011001 +00000011111100000000000001110000 +00000000000000000000000000000000 +10000000000100001110011000000000 +10001111000100000010001111010000 +00001000101100000000001011011100 +10000000100011110001010000101110 +01100000000010111111010011000010 +00100110000100001011100010000000 +00100000000010001000111000010000 +00000010111000000000010000110000 +00000000000000000000000000000000 +10001000000001011100010000000000 +10100011001000000010000011001101 +00011001000000100000001011001100 +11000000100000110010000100101100 +11000000000110110011001100000010 +10000100000000001011100000000000 +01100000000000100000101000000010 +00000010111000100000000101110000 +00000000000000000000000000000000 +11000000000101011010010000000011 +10100011000000000010001011000000 +00011000101000001000001011101100 +00000000100010110000000000101110 +11000100000010111011000000000010 +10100110000000001011100000000000 +01100010000001000000101010000001 +00000010111100000000010001100000 +00000000000000000000000000000000 +01000000000101011110011000000000 +11101011000001000011001011000000 +00001101100101000001001111101100 +00000000110010110000000000111110 +01100000000011111011000000001011 +10100100000000001111000001100001 +00110010001010000000111010011000 +00000011110100000000010001110000 +00000000000000000000000000000000 +11100000000000011011011001000100 +11011111000000000011111111000000 +00001111111101000100001111111100 +00000000111111110000000000111111 +01000000000011110111000000000011 +01110100000000001111110000000000 +00111111001000000000111111011000 +00000011111110000000000001100000 +00000000000000000000000000000000 +01000000000100001010011000001000 +11011011000000000011001011000000 +00001100100101000000001111001100 +00000000110010110000000000111110 +11000100000011111011000000000011 +11101100000001001111100001000100 +00110010001000000010110010000000 +00001011000100000000010000100000 +00000000000000000000000000000000 +11001000010001010000010000010000 +10001111000000000010001111000000 +10001010101100000010001011111100 +00000000100011110000000000101110 +11100001000010111111000000000010 +11101101000001001011100000000000 +00100010001100000100100010001000 +00000010001100100000000001000000 +00000000000000000000000000000000 +11100000000001010100010000000000 +10010011000000000010001011000000 +00001000001000000000001011001100 +00000000100000110000000000101100 +01101000000010110011000000000010 +11001100001000001011000100000000 +00100100110000100100100000111000 +01000010011110000000000001010000 +00000000000000000000000000000000 +00100000000000010001011000000000 +10010011100000000010000011100100 +00001010011010000010001011011110 +00001000100001111000000001101101 +11100001010010110111100000000010 +11011110000000001011110111000000 +10100101111000000000100001111000 +00000010010010000000000001000000 +00000000000000000000000000000000 +01001000000010000000110000000000 +11010011000000000011000011000000 +00001100000000000100001111001100 +00000000110000110000000000111100 +01000000000001110011000000000011 +11001100000000001111000100000000 +00110100110000000000110000100000 +10000011010100100000001000000000 +00000000000000000000000000000000 +01000000000111011001110001000000 +11101111010000100011111111010001 +10001110111000010000001111111100 +00000000111111110000100000111111 +11010000100011111111000000100011 +11111101000010001111110100000000 +00111011110000000000111111101000 +00000011100100000000011001100000 +00000000000000000000000000000000 +10101000000001011110111000000000 +11001011111000000011001011000100 +00001100101100000000001100101101 +10001000111110110110000000111110 +01010100000011111011110101000111 +00100101000000001111100100000000 +00110010110000000000111110110000 +00000011111010100000000001110000 +00000000000000000000000000000000 +01001000000100011001110000000000 +10001111011000101010001111000000 +10001000111100000000001000011101 +00100000101101110001000100101101 +11001000000010110111001010010110 +00010100100000001011010100000001 +00100001110000000000101101110000 +00000010110100100000010001100000 +00000000000000000000000000000000 +11000000010000001000111000010000 +10000111100000000010000111101001 +00001000010110000100001000011110 +10000000101101111010000000101101 +01100000000010110111100001001010 +00011110010000001011010110000101 +10100001111000010000101101101000 +00000010111100000000000000100000 +00000000000000000000000000000000 +01001000000101000100110000000000 +10000011000000000010000011000000 +00111000001100000000001000001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +00001110000000001011000100000000 +00100000110000000000101110100000 +00000010110100100000010000110000 +00000000000000000000000000000000 +11101000000101011010101010000010 +11001010000000000011001010000000 +00001100111001000000101100101000 +00000000111110100000000000111110 +10000000000011111010000000000011 +00101000000000001111001000000000 +00110010100000000100111110100000 +00000011111110100000010001100000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000100011111000000000 +00001111100000100000001111100000 +00000000111110000000000100111110 +00000000010011111000000001000011 +11100001010000001111100001000000 +00111110000000000000111111000000 +00000011110100100000000000110000 +00000000000000000000000000000000 +00001000000100001110011100000000 +11111001000000000011111001000000 +00000000100100000000101100100100 +00000000111100010000000000111010 +01000000000011111001000000000011 +11100110000000001111100110000000 +00110010010000000000111110011000 +00000011000000100000010000110000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000001010010111001000000 +00001000100100000000001000100100 +00000000101110010000000000100010 +11000000000010111001000000000010 +11101100000000001011100100011000 +00100010010100001000101110011100 +00000010001000000000000000010000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010110001000000 +00001010000100000000001000100100 +00000000101110010000000000100010 +01000000000010111001000000000010 +11100100010000001011100100000000 +10100011010000000100101111010010 +00000010000001100000000001000000 +00000000000000000000000000000000 +00001000000001000000010010100000 +10110001001010100010110001001011 +00101010000100100000101000000100 +10100000101100010010100000100000 +01100000000010110001001010000010 +11000100000000001001100100000000 +00100001011000000000101101011000 +00001010000000100000000100000000 +00000000000000000000000000000000 +10111000000011010110000010000000 +11111000001000000011111000001000 +00001110100000000010001100100000 +10000000111110000010000000111010 +00000000100011110000001000000011 +11101000000000001111100000000000 +00110010000101000000111111000101 +00000011001011100000001101010000 +00000000000000000000000000000000 +10011000000111011111010000010000 +11111001001010000011111001001010 +00001101110100111000001111100100 +10100000111110010010100010111110 +01000000000011111001001010000011 +11100100000000001111010100000000 +00111110010000000000111110010000 +00000011111001100000011001110000 +00000000000000000000000000000000 +00011000010011011111011000010000 +11111001010010000011001001000100 +00001101100100010100001100100100 +00100000110010010100100000110010 +01000000000011111001010010000011 +00100100000000001100010100000000 +00110011010000000000110011010100 +00000011110001100000000001110000 +00000000000000000000000000000000 +00111000000000001110000100000000 +10111000011000000010000000001000 +00001000100000100000101000100001 +10000000100010000110010000100010 +00000000000010111000010001000010 +00100000000000001000100000000000 +00100010000010000000110110000000 +00000010110011100000010000110000 +00000000000000000000000000000000 +00001000000001010100010100000000 +10110001000000000010000001010000 +00011011000101000000001000000100 +00100000100000010010000000100000 +01000000000010110001001000001010 +00101100000001001000000100000000 +01100000110000100000100100010000 +00000010110000100000000101110000 +00000000000000000000000000000000 +00011000000101011010010000001000 +10111001000000000010000001000000 +10000010100101100000001000100100 +00000000100010010000010010100010 +11001000010010111001000000000010 +00100100100000001000100100000000 +00100010010000000000100010010000 +00000010110001100000010001100000 +00000000000000000000000000000000 +10100000000101011110011000000000 +11111001000000000011001001000000 +00001111100100000000001100100100 +00000000110010010000000000110010 +01000000000011111001000000000011 +00000100000000101100100100000000 +00110010010000000010100110010010 +00000011111010000000010001110000 +00000000000000000000000000000000 +00101000000000011010011100000000 +11110001000000011011111001000000 +00001101000100000000001111000100 +00000010111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +10111110010000001000111110010000 +00000011110010100000000001100000 +00000000000000000000000000000000 +00101000000100001010000000001000 +11101000000000000011111000000000 +00001101100001000000001100100000 +00001100110010000000000000111110 +00000000000011110000000000000011 +00100000001000001111100010000000 +00110010001000000000110010000010 +00000011110010100000010000100000 +00000000000000000000000000000000 +00101000010001010010101000100000 +10001010000000100010111010000000 +00000000101000000000101000101000 +00000000100010100000010000101110 +10000000000010111010000000010010 +00101000000010001011011010001000 +00100011100000000110100011100100 +00000010110010100000000001000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10100011000000000010110011000000 +01000010001100000100001000001100 +00000010100010110000000000101100 +11000100000010110011000000000010 +00001100000000001011001000000000 +00100110110000000100100000110000 +00000010110010100000000001010000 +00000000000000000000000000000000 +10100000000000010000111000000000 +10000111000000000010110111000000 +00001010011100100000001000011100 +10000000100001110010010000101101 +01000000000010110111001000000010 +00011100000010001011111100000000 +10100101110000000000100001110000 +00000010111010000000000001000000 +00000000000000000000000000000000 +10101000000000000001111000000000 +11100111101100100011110111101010 +00101110001110110001001100111110 +10000000110001111000000000111101 +10100000010011111111101100000011 +00011110000000001111011010000000 +00110111111000000000110001111000 +00000011111010100000001000000000 +00000000000000000000000000000000 +00001000000101011010110000000000 +11111011011000000011111011110000 +00001100101100110000001111101101 +11010000111110110011110100111110 +01011000000011111011010000011011 +11101001001000001111101100000000 +00111010110000000000111110110000 +00000011110000100000011001100000 +00000000000000000000000000000000 +00000000000011011111111000000000 +11101111100110000011111111100010 +00101100111110000000001111111111 +00010000111111111000000000110111 +11110100000011001111100010000011 +11111010010000001111111110000000 +00111111111000000000111111111000 +00000011000000000000000001110000 +00000000000000000000000000000000 +10101000000000011001110001000000 +11100111000100000010111111000000 +00001000011100000000001011011100 +01000000101101110001000000100001 +11000100001010000111000000000010 +11011000000000001011011100010000 +00101101110000000000101101110000 +00000010001010100000010001100000 +00000000000000000000000000000000 +00000000000000000001110000000000 +10100111000000000110110111100000 +00001000011100000000001011011100 +00000000101101110000000000100011 +10000010000010010111000000000010 +11010100000000001011011100000000 +00101101110000000000101101110000 +00000010000000000000000000100000 +00000000000000000000000000000000 +00100000000101001100110000000001 +10100011000000100010110011000000 +00011000101110010000001011001100 +00000000101100110000000000100000 +11100000000110010011000000000010 +11000000000000001011001100000000 +00101100100000000000101110110100 +00000010000010000000010000110000 +00000000000000000000000000000000 +10101000000101011010110000000000 +11101111000000000011111111000000 +00001100111100000000001111111100 +00001000111111110000000000110110 +11100000000011011111000000000011 +11100100000000001111000100000000 +00101110110000000000111110110000 +00000011001010100000010001100000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11111011000000100011111011000000 +00001111101100000000001111101100 +00000000111100110000000000111110 +00010000000011101011000000000011 +11100100000000001111100101000000 +00111110110000000000111110111100 +00000011111000000000000000110000 +00000000000000000000000000000000 +00000001000100001101011100001000 +11001111000000000011110111000000 +00000100111100000010011100111100 +00000000111111110000000000110011 +10000000000011111111000000000011 +11111110000000001111110010000000 +00111011110000000000110011111000 +10000011000000000100010000110000 +00000000000000000000000000000000 +10000001010000000110111000000010 +10001011000000000010111011000000 +00001010101100000000001101101100 +00000000101110110000010000100010 +00010000000010111011000000000010 +11101010000001001011100111000000 +00111010111001010000100010010010 +00000010001000000100000000010000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10001011000000000010111011000000 +00001010101100000000001000101100 +00000000101110110000000000100010 +01100000000110111011000000000010 +11100000100000001011101100101000 +00101000110000000000100010110010 +00000010001000000000000001000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10000011000000000010110011000000 +00001010001100000100101000001100 +00000100101100110000000100100000 +00000000000010010011000000000010 +11000000000000001011001100000000 +00100000010000010000100000110000 +00000010000000100000000100000000 +00000000000000000000000000000000 +00000000000001010110110000000000 +11001111000000000011111111000000 +00001110111100000000001000111100 +00000000111101110000000000110010 +00000000100011111111000000000011 +11100100000000001111100100000000 +01111010110000010000110000100000 +00000011000000000000001101010000 +00000000000000000000000000000000 +10100000000101011111110000000000 +11111111000000000011111111000001 +01001111111100000000001111111100 +00000000111111110000000000111101 +00000000000011111111000000000011 +11110000000000001111110100000000 +00111011000000000000111111000000 +00000011111010000000011001110000 +00000000000000000000000000000000 +11000000000001011111110001000000 +11001110100000000011011111100000 +10001100111100100000001101111100 +00000000111111110010000000111111 +11000000000011001111000010000011 +00110000000000001100110110000000 +00110011000000000000111111000000 +00001011001100000000000001110000 +00000000000000000000000000000000 +10000000000100001111110100000000 +10001010100000000010001011001010 +00001000101111000000001000111110 +00000000101111110001000100101111 +11000110000011011111011001000010 +00100000000000001000100000000000 +00100010101000010000101110001100 +00000010001000000000010000110000 +00000000000000000000000000000000 +10001000000001011100110001000000 +10101001000000000010011011000000 +00101000001100010000001001001100 +00000000101100110000000000101100 +11000000000010000011000010001010 +00000100000000001000000000000000 +00100000010000000000101100100100 +00000010001000100000000101110000 +00000000000000000000000000000000 +11000000000101011010110000000000 +10101001001000000010001011000000 +00011000101100000100001000101100 +00000000101110110000000000101110 +11000000000010010011000000000010 +00101000000100001000000010000000 +00100010110000000000101110100000 +00000010001100000000010001100000 +00000000000000000000000000000000 +01000000000100011110110000000000 +11101001100000000011010011000110 +00001100001100000100001101101100 +00000000111110110000000000111110 +11000000000011001011000000000011 +00100101000000101100101011000000 +00110010110000000000111110010000 +00000011000100000000010001110000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11011101000001000011111111000001 +10001111101100000000001111101100 +00010000111110110000000000111111 +11000000000011111111000000000011 +11110000000000101111111000000000 +00111111110000000000111111010010 +00000011111110000000000001100000 +00000000000000000000000000000000 +01000000000100001000110000000000 +11101001000100000111101011000000 +00001101101100000000001101101100 +01100010110010110000000000110010 +11000000000011001011000000000011 +11001101100000101100101001000000 +10110010110000000000111101111010 +00000011000100000000010000100000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10000001010100000110001011000000 +00001000111101110100001101111110 +00000000100011110000000000100011 +11000000001010001111000000000011 +10101011100000001000101000000000 +10110010110101000000101110110100 +00000010001100100000000001000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10100010100000000010100011000000 +00001001001110000000001000001101 +00000000100000110000000000100010 +11000000000010000011000000000010 +01000001000000001000000010000000 +00100100000000000000101100000000 +00100010001110000000000001010000 +00000000000000000000000000000000 +00100000000000010001111000001001 +10000110100000000010001111100000 +01001001011110000000001001011110 +00000001100001111000000001100001 +11100100000110000111100100000010 +10000010000000001000010011100000 +00100001101000000000101100001000 +00000010000010000000000001000000 +00000000000000000000000000000000 +01001000000010000010110000000000 +11100001000000100010100011000000 +00001101001100000000001000001100 +00000000110000110000000010110010 +11000000000011000011000000000011 +11000101000000001100100001001000 +00110100010000000000111100100000 +00001011000100100000001000000000 +00000000000000000000000000000000 +01000000000111011011111000100000 +11110101000000000011110111000000 +00001110111100001000001111111100 +00000000111111110000000000111111 +11000000000011111111000011000011 +11111100000000001111110000100000 +00111111110000000000111111100000 +00000011110100000000011001100000 +00000000000000000000000000000000 +10101000000001011110111000000000 +11000011100000000011011010000000 +00101100101100000000001111101100 +10000000111110110100000000110010 +11001010000011001011101000001011 +00100100000000001100100000000000 +00110010110000000010110010010100 +10000011111010100000000001110000 +00000000000000000000000000000000 +01001000000100011011110010001000 +10000111000000001010001111000000 +00001000011100100001001011011100 +11000000101100110000100000110101 +11000000000010000111001010000010 +00010100010000101000011000000000 +00100001110000000000100001110000 +00000010110100100000010001100000 +00000000000000000000000000000000 +11000000000000001001111000001001 +10000101100000000010000111100000 +00001000011110000000001011011110 +11000000101101111001000000100001 +11100100000010010011101000000010 +00011110000000001000011010000000 +00100000111000000000101001011000 +00000010111100000000000000100000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10000001111000000010000001110000 +00011000001100000000001011001100 +00001000101100110000000000100100 +11000000001010010011000000000010 +00001100000000001000001011100000 +10100000110100000000101000110101 +00000010110100100000010000110000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11001110110000000011001110000000 +00001100101000000000001111001000 +00000000111110100000000000110010 +10000000000011011010000000000011 +00101001000000001100111011001000 +00110011101000000000111000101000 +00000011111110100000010001100000 +00000000000000000000000000000000 +01001000000000001110000000000010 +11111000000100000011101000001100 +00001111100000000000001111100001 +00000000111110000000001000111100 +00000000000011101000000000000011 +11100000100000001111100001000000 +00111110000011000000010110000000 +10010011110100100000000000110000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000100000011111001000000 +00101100000100000000001100100110 +00000000110010010000000000110010 +01000000000011001001000000000011 +11101111000000001110100100000100 +00110000010000000000110010110000 +00000011000000100000010000110000 +00000000000000000000000000000000 +10000000000001000111010000000000 +10111001010000000010111001000000 +00001000100100000000101000100101 +00000000110110010000000000101010 +01000000010010101001000000000010 +11000101000010001000000100100100 +00110110010000000110100010010000 +00000010001000000000000000010000 +00000000000000000000000000000000 +00011000000000010010010000000000 +10111001000010000010110001000000 +00001000100100001000001000100100 +01000000100000010000000000100010 +01000000010010001001000001000010 +11100101000000001010100110000000 +00100010010000000010100010010000 +00000010000001100000000001000000 +00000000000000000000000000000000 +00001000000001000000010010000000 +10110001000000000110110001000000 +01001000000100100000001000000100 +10000100100100010010100000101000 +01001010000110100001001011000010 +11000100100000001000100100000000 +00100100010010000000100000010010 +00010010000000100000000100000000 +00000000000000000000000000000000 +10111000000011010110000101000000 +11111000000000000011111000010100 +00001100100000000000001000101000 +00000000110010000111000100110000 +00001001000011001000001000010011 +11100001010000001110000001010000 +00110010000000000000110010000000 +00001011001011100000001101010000 +00000000000000000000000000000000 +10011000000111011110010100000000 +11111101000000000011111101000000 +00001111100100010000001111100100 +01000000111110010000000000111110 +01001010000011111001001010000011 +11000100010000001111111100000000 +00111111010001000000111110010001 +00000011111001100000011001110000 +00000000000000000000000000000000 +00011000000001011110010100100000 +11110101000000000011101001010000 +00001100110100101000001111110100 +00100000111110010000000000110010 +01000010000011001001000000000011 +00001101001000001100010100000000 +00110010010000100000110010010000 +10000011110001100000000001110000 +00000000000000000000000000000000 +00111000000100001110000110000000 +10111000000000000010001000000001 +00101000100001000000001110100001 +00000000101110000101000000100010 +00111010000011011000000000001010 +00100001000000101000100000100000 +00100010000100010010100011000100 +00000010110011100000010000110000 +00000000000000000000000000000000 +00001000000001011100010000000000 +10110001000000000010101001001000 +00001000000100000000001011000100 +00000000101100010010100010100000 +01000000000010000001011010100110 +00000100000001001000000100001000 +01100001011000000000100001010000 +00000010110000100000000101110000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10111011000000000010001001000010 +00001000100100000100001011100100 +00000000101110010000000000100000 +01000000000110011001000000000110 +00000101000000001000000100000101 +00100010010000000010100011010000 +00000010110001100000010001100000 +00000000000000000000000000000000 +10100000000101011110010000001000 +11110001010010000011100001110000 +00001100100100000000001111100100 +00000000111110010000000000110010 +01000000000011001001000000000011 +00100110000000001100100110000000 +00110010010100000000110010010000 +00000011111010000000010001110000 +00000000000000000000000000000000 +00101000000000011010010000000000 +11111001110010000011111001101000 +01001111100100000000001110100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11101100100000101111100111000000 +10111110010000000000111110011010 +10000011110010100000000001100000 +00000000000000000000000000000000 +00101000000100001010000000010000 +11111000010000100011001000010000 +00001101100000000000011111100000 +01010000110010000000010000111110 +00000001010011001000000000010011 +11100001000000001110100010000000 +00110000000000000000110011000000 +01000011000010100000010000100000 +00000000000000000000000000000000 +00101000000001010010100000000000 +10111110010000000010001010000001 +00001000111011000100001011111001 +00000000100010100000000000101110 +10000000001010001010000000010010 +11101000000000001000111010100000 +00111010100000010000100010100000 +00000010000010100000000001000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110011000100000010000011000000 +00001001000111011001001011001101 +00101000101010110000000001101100 +11000000000010011011000000100010 +11001101100000001010001110000000 +00100100111000000000100000100000 +00000010000010100000000001010000 +00000000000000000000000000000000 +10100000000000010001110011000000 +10111111000000000010001111001000 +01101000010100000100001011011110 +00000000101001110010000000101101 +11000100101110010111000000000010 +11010000000000001000111100000000 +00101001100100000000100001101000 +00000010001010000000000001000000 +00000000000000000000000000000000 +10101000000010000001111010000000 +11110111100000001011000111110000 +00001101010010000000001011001110 +00000010111001111110000000111111 +11101000000011010111110010100001 +11011010000000001110011110000000 +00110100111000000010110000101000 +00001011001010100000001000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111011000000100011110011000010 +00001111100000000000001111101100 +00000000110110110100001000111110 +11010000010011101011011000000011 +11101000001000001111101100000000 +00111110100000000000111110100000 +00000011110000100000011001100000 +00000000000000000000000000000000 +00000000000001011111111000000000 +11111111100000000011001111100000 +00001100110110000000001111111110 +00000100111111111100000000111111 +11110000000011101111100100011011 +00111110000000001100110010100000 +00110011011000000000110011111000 +00000011110000000000000001110000 +00000000000000000000000000000000 +10101000000100011001110001000000 +11110111001000000011010111001000 +00001000010100010000001111011100 +00000000111101110000000000111101 +11001000000010000111000000000010 +00010000001000101000011100100000 +00100001000000000000100001110000 +00000010111010100000010001100000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110111000001000010000111000000 +00001000010100000000001011011100 +01000000101101110000000000101101 +11000000010010000011000000000110 +00011100010000001000011100110100 +00100001010000000000101001111000 +10000010110000000000000000100000 +00000000000000000000000000000000 +00100000000101001100110000000000 +10100011000000000010011011010100 +00000000000100000000001010001000 +00000000101000110000000000101000 +11000000001110000011000000000010 +00001011001000001000101110000000 +00100000000000000000101000111000 +00000010110010000000010000110000 +00000000000000000000000000000000 +10101000000101011011110000000000 +10111010000000000011001111010000 +00101100001100000000001011100100 +00000000101111110000000000101111 +11000000000010001111000000000011 +00101111000000101000101101100000 +00110010111000000100111010001000 +00000011111010100000010001100000 +00000000000000000000000000000000 +10000000000000001110110000010000 +11111011000000000011111011001000 +00001111100001000001001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11100100000001001111101100100000 +00111100101000000100100110000000 +00000001111000000000000000110000 +00000000000000000000000000000000 +00000001000100001111110000000000 +11111111100000000011001111000000 +00001100111010100000101100011100 +00000000110011110000000000111101 +11000000000011001111000000000011 +11111000000000101100111100000101 +00010010110000000100110011000000 +00000011110000000100010000110000 +00000000000000000000000000000000 +10000001000001000110110000010000 +10110011000000000010001011000000 +00101000100000100000001000101111 +00000000100010110000000100101110 +11000000000010001011000000010010 +11101001001000001000101100000000 +00100010100000000110100010001001 +00000010111000000100000000010000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000100000010001011000000 +10001000101100000000001000101111 +00000000100010110000000000101110 +11000000000010001011000000000010 +11001100000000001000100010000000 +00101010010000000000100010010000 +00000010111000000000000001000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10110011000000000010000011000001 +00001000001000000000001000001100 +00000000100000110000000000101100 +11000000000010000011000000000010 +11000100000000001000000110000000 +00101000000000000000100000010000 +00000010110000100000000100000000 +00000000000000000000000000000000 +00000000000011010110110000000000 +11111001000000000011000111000000 +00001100101100000000001100101100 +00000010110011110000000000111101 +11000000000111001111000000000011 +11001100000011011100001000000100 +00111010010000000000110010010000 +00000011110000000000001101010000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11110111000000001011111111000000 +00001111111000000000001111111100 +00000100111111110000000100111111 +11000000000011111111000000000011 +11111100000000011111111100000000 +00110111000000000000111111010000 +00000011111010000000011001110000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11101101100000000011111100000100 +00001110111100000000001101110110 +00000100111111110110000000110011 +11001100100011001110000100100011 +10110000010100001100110000000000 +10110011000001000100110011010001 +01000011001100000000000001110000 +00000000000000000000000000000000 +10000000000100001100110000000000 +10001001100001000010110011001000 +00001100101111000000001000100110 +00010000101111110001000000100011 +11001100000010000010000000000111 +10100000100000001000100000000000 +00110010100010000000100010010010 +00000010001000000000010000110000 +00000000000000000000000000000000 +10001000000001011110111000000010 +10100011000000000010110011001001 +00001010001100010000001000000100 +00000000101100110010000000100000 +11000000000010010011001000100010 +10000000100000001000000000000000 +00100100000010010000100000010010 +00000010011000100000000101110000 +00000000000000000000000000000000 +11000000000101011010111000000000 +10101011000000000010111000100000 +00001001101000000000000000100100 +00000000101110110000000000000000 +11000000000010011011000000000010 +10100000000000001000100000000000 +00100010100000000000100010010000 +00000010011100000000010001100000 +00000000000000000000000000000000 +01000000000101011100110000000000 +11101001000000000011111001100000 +00001110100101000000101101101110 +00000000111110110000000010110010 +11000000000011011010000000000011 +10100011000000001100100100010000 +10110110010000000010110010100000 +00001011010100000000010001110000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11011111000010000011110111000000 +00001110111101000100001111111110 +10000000111101110000000100111111 +11000000001011101110000000000011 +11010010010001101111100110000000 +10111111110000000000111101100000 +00000011101110000000000001100000 +00000000000000000000000000000000 +01000000000100001010111000000000 +11101001000000010011111011000000 +01001110001000001000101101101100 +00000000111110110001000010110010 +11000000000011001011000000000011 +00100001000000101100000100001000 +00110000010000000000110010101010 +00000011000100000000010000100000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10001011000000010000111001000000 +00001000101000000000001000101100 +00000000101111110101000000100011 +11000000000010001011000000000010 +00100000000000001000100101100010 +00100010110000010000100010100100 +00000010001100100000000001000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10000001000000000010110011000000 +00001010000110000000001010000111 +10010000101100110000010000101000 +11000000000010000010000000100010 +00001100000000001000001000000000 +10100000000000000000100000010000 +01000010001110000000000001010000 +00000000000000000000000000000000 +00100000000000010001111000000000 +10000101100000000010110111100100 +00001000001010000100101010010110 +00100000101100111000000000101001 +11100000101010000110100000000010 +00001110000000001000011010000000 +00100000101000000010100001011000 +00000010000010000000000001000000 +00000000000000000000000000000000 +01001000000010000000110000000000 +11100011000001000011110011010000 +01001110001100101000101110001100 +10000000111100110010000000111010 +11000000010001000011000100000111 +00001101100001001100001000100000 +01110000000000000000110010010010 +00001011000100100000001000000000 +00000000000000000000000000000000 +01000000000111011011110000000000 +11111111000000000011111111000000 +10001111111000000000001100111100 +00000000111111110000000000110111 +11000000000011111111000000000011 +11111100000000001111111000000000 +10111111100000000000111111011000 +00000011110100000000011001100000 +00000000000000000000000000000000 +10101000000001011100010000000000 +11001001011000000011111010000000 +00001101000000100000001101100110 +11100000110010110010100010111010 +11100000000011001010000000000011 +11101100000000001100101100000000 +00110110010000000100110010100000 +01000011001010100000000001110000 +00000000000000000000000000000000 +01001000000100011001110000000000 +11010111001010010010111111000000 +00000101011000010000101000010100 +00000000100011110000000010100000 +11011100000010000110000000000010 +11011100000001001010011100000000 +10100001110000000100100001100000 +00000010000100100000010001100000 +00000000000000000000000000000000 +11000000000000001011101000000000 +10000101110100000010110111100000 +00001001011010000000001001111110 +10000010100001111001000000101001 +11101001100010000111100000000010 +10001110000000001010001110000000 +00100001011000000000100001101000 +00000010001100000000000000100000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10010011000000010010110010000000 +00001001001011000000001000001110 +00000000100010110000001010100000 +11000000001010000011000001100010 +11001100000000001010001100000100 +00100000110000000110100000100111 +00001010000100100000010000110000 +00000000000000000000000000000000 +11101000000101011011100000000000 +11001010000000000011111110010000 +00001101101000011000001101101010 +00000000110010100000000010111010 +10000000000011001010000000100011 +10101000000000101110101001000000 +00110010100100000000110011101100 +00001011001110100000010001100000 +00000000000000000000000000000000 +01001000000000001110001100000000 +11111000000000000011111000000010 +00001111000000000000001111100001 +01010000111110000000000000111110 +00000000000011110000000001000011 +11100000000000001011000000001000 +00111110000000100000111101000000 +00000011110100100000000000110000 +00000000000000000000000000000000 +00001000000100001110010000000010 +11101001001000000011000001000000 +00001100101100000000001100100100 +00000100111110010000000010110010 +01000000000011111001000000000011 +00100100000000001000100100000100 +00110010010000000010110010010000 +00001011000000100000010000110000 +00000000000000000000000000000000 +10000000000001000110010100100000 +10000011111000000010001001000000 +00001000100100110000001000101100 +00000000101110010000000010100010 +01000000000010111001000000000010 +00100100000000001000100100000000 +00100010010100000000100010010100 +00000010001000000000000000010000 +00000000000000000000000000000000 +00011000000001010000011000000000 +10101001000000000010001001000000 +01101000101100000100101000100100 +00000000101110010100000000100010 +01000000100010111001000000000010 +00010100000000001010110100000000 +00100001010000100100100011010000 +11000010000001100000000001000000 +00000000000000000000000000000000 +00001000000001000000010000000010 +10001001000000000010000001001000 +00001000000100100000001000000100 +00000000101100010010100010100000 +01001011000010110001001000001010 +00010100100000101010010100100000 +00100001010010000000100001010010 +00000010000000100000000100000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11101000000000000011001000000000 +00001100100000000000001100101000 +00000000111110000111000010110010 +00001000000011111000100000000011 +00100010000000001110100011010000 +00110000001101000000110001001101 +00001011001011100000001101010000 +00000000000000000000000000000000 +10011000000111011111010010100000 +11111001000000001011111101001110 +01001111100100010000001111000100 +00000000111110010000000010011110 +01001010000011111001001110000011 +11100100111000001101100100010000 +10111110010001000100111110010001 +00000011111001100000011001110000 +00000000000000000000000000000000 +00011000000000011110110100000000 +11001001000000000011111001010000 +00001110110100000000001110100100 +00000000111111010001001010110010 +01001010100010111001000000000011 +00100101000000101100110101000100 +00110010010000000000110010010010 +00001011000001100000000001110000 +00000000000000000000000000000000 +00111000000100001100001000000100 +10001000000000010010111000010100 +00001000100001000000001000100000 +00000100101110000100000010101010 +00011000000010111000010000000010 +00100001010000001000000001000001 +00100010000100000000100011000110 +10000010000011100000010000110000 +00000000000000000000000000000000 +00001000000001011100010010000000 +10000001000000010010110001001000 +00001010000101000000001010000100 +00000000101100010110000010100000 +01000011000010110001011010000010 +00000100100001001010000101100100 +00100001010110100000100101010001 +00000010000000100000000101110000 +00000000000000000000000000000000 +00011000000101011000010101000010 +10001001000000100010111001001000 +01001000100100001000001000100100 +00000100101100010000000010001010 +01000001010010111001010000001010 +00100100000000001010100100000001 +00100010010000000000100111010000 +00000010000001100000010001100000 +00000000000000000000000000000000 +10100000000101011110011000000000 +11001001000000000011111001101000 +00001110100110000000001110100110 +00000100111110010000000010010010 +01000000000001111001000000000010 +00100100000000001110100100000000 +10110010010000000000100110010000 +00000011001010000000010001110000 +00000000000000000000000000000000 +00101000000000011010111000000000 +11111001100101000011110001100000 +00001111100101000000001111100100 +10010100111110010000000000111110 +01000000000011111001000000000011 +11100100000000101101100100001000 +00111100010000000010111000010000 +00000011110010100000000001100000 +00000000000000000000000000000000 +00101000000100001010000000000010 +11001000100000000011111000000000 +10001100000001001000101110100010 +00000000111110000000000010110010 +00000000000011110000000000000011 +00000000000100001100100000000000 +10110010000000000000110011000000 +00000011000010100000010000100000 +00000000000000000000000000000000 +00101000000001010010100001000000 +10001010101000000010111010000000 +00001000111000000000001000101000 +00100000101111101100000010110110 +10000000000010111010000000001010 +00101000000000000000111001001000 +00100010100000010000100011100000 +00000010100010100000000001000000 +00000000000000000000000000000000 +00101000000001010100100100000010 +10000011100000000010110011000000 +10011000001100010000001010001100 +00000000101100010110000000101000 +11000001000010110011000000000010 +00001100000000101000101110000000 +10100000111000000010100000101000 +00000010000010100000000001010000 +00000000000000000000000000000000 +10100000000000010001100100000000 +10000111000000000010110011000000 +00111000011100000000001000011100 +00000000101101000000100010101101 +11000000000010110111000000000010 +00001100000000001000010100000000 +00100001110100000000100001100100 +00000010001010000000000001000000 +00000000000000000000000000000000 +10101000000010000001111000000010 +11000111100010000011110111100100 +00001100011010000000001110011110 +00000100111111011000000010111001 +11100100010011111111101010000111 +00011110001000001100011110000010 +00110011101000000010110011111000 +00001011001010100000001000000000 +00000000000000000000000000000000 +00001000000111011010110110110000 +11111010010000000011111011100100 +10001011001100000000001111101000 +10100000111110000000000000110110 +11000100000011111011010100100011 +11101101110000001111100100000100 +10111110100000000000111110110000 +00000011110000100000011001100000 +00000000000000000000000000000000 +00000000000001011111001000000000 +11001110100000000011111111100001 +00001111111110000000101110111010 +00000000111111111000000000111011 +11100000000011111111100000000111 +00111110010000001100111010000000 +00110011011000000100110011001000 +01000011000000000000000001110000 +00000000000000000000000000000000 +10101000000100011001000001000010 +10000110000100000010110111000000 +00001011011100101000001000010100 +01000000101101100000000000100001 +11000000010011100111000000000010 +00111100110000001000111100010000 +00100001010001000100100001000001 +10001010001010100000010001100000 +00000000000000000000000000000000 +00000000000000001001010000100010 +10000101000000000010110111100010 +00001011001100000000001011011000 +00000000101101110000000000101101 +11000000000010110011000000001010 +00011100000000001000011000000000 +00100000000000000010100000011000 +00001010000000000000000000100000 +00000000000000000000000000000000 +00100000000101001100110000000000 +10000000000001000010110011110010 +00001011001101000000001001000000 +00000100101100110000001010100100 +11000000000010100011000000000010 +00001100000000011000101100000000 +00100000001001000000100000010100 +00000010000010000000010000110000 +00000000000000000000000000000000 +10101000000101011000110000000000 +11001001000000000011111111100000 +00001111101100000000001111100100 +00000000111110000000000000111111 +11000000010011111111000000100011 +00111100000000001100101100000000 +00110010110000000000110010101101 +00000011001010100000010001100000 +00000000000000000000000000000000 +10000000000000001110110100000000 +11111001100000000011111011000001 +00001111101101000000001110101100 +00010000111110110100000000111010 +11000000000111111011000000000011 +11101100000000001111100000000000 +00111110110000000000111110100000 +00000011111000000000000000110000 +00000000000000000000000000000000 +00000001000100001111111000100000 +11011111010000000011111111000000 +00011111111100011000001101110100 +00000000111111000001000010110001 +11000000000001001111000000100011 +11011100000000001000111100000000 +00110001100000000010110001110000 +00001011000000000100010000110000 +00000000000000000000000000000000 +10000001000001000110111101100000 +10001010100000000010111011000000 +10001011001101000000001000101000 +00000100101110110100000010110110 +11000001000010101011000000000010 +11101100000100001101100011001010 +00100010100000010000101010110000 +00000010001000000100000000010000 +00000000000000000000000000000000 +10000000000001010010100000000000 +10011000000000000010111011000000 +00011011101100001000001001100010 +00001000101100100000100010100010 +11000000010010101011000001000010 +11101100000000001010100000100000 +00100010010000000000100010000000 +00000010001000000000000001000000 +00000000000000000000000000000000 +00001000000001000010100000000000 +10000000000000000010110011000000 +00001011001100000000011000000100 +00000000101100110000000001100100 +11000000000010100011000000000010 +11001100000000001011000000000000 +00000000010000000010100000000000 +00000010000000100000000100000000 +00000000000000000000000000000000 +00000000000011010100100000000000 +11011001000000000011111111000001 +00001011101100000000101101100000 +00000100111100110000000010110011 +11000000000011101111000000000011 +11111100000010001110100000000000 +10110010000000000100110010010000 +00000011000000000000001101010000 +00000000000000000000000000000000 +10100000000110011111100000000000 +11111100000000000011111111000000 +00001111110100000000101111110000 +00000000111111110000000000111111 +11000000000011011111000000000011 +11111100000000001101110000000000 +00111111000000000000111111010000 +00000011111010000000011001110000 +00000000000000000000000000000000 +11000000000001011111110001000000 +11011111000000000011001111000000 +00011110111100100000001100111100 +00000000110011110010000000110011 +00001010000011111101100000000011 +11110100000000001101111000000010 +00110011110000000000111101101000 +00000011011100000000000001110000 +00000000000000000000000000000000 +10000000000110001110110010000000 +10001011001100000011001111011010 +00001101111101000010001000111101 +11101000100011110110100000100010 +00011011000010111001000000000010 +11110110000000001000100010000100 +00110010111000000000100110110000 +00000010001100000000010000110000 +00000000000000000000000000000000 +10001000010001011000110000000100 +10010011000010000010000011010000 +00001000001100010001001010001100 +00000010100000110001000000100000 +00000000000010110001000000000110 +11001100000000001011000000000000 +00101000111000000000101100010000 +00000010001100100000000101110000 +00000000000000000000000000000000 +11000000000001011100110000000000 +10000011000000000010001011000000 +00001001101100000000001010001100 +00000000100010110000000000100010 +00100000000010111010100000000010 +11100110000000001010100010000001 +00101010100000000000100100011000 +00000010001100000000010001100000 +00000000000000000000000000000000 +01000000000101011110110000000000 +11011011000000011011001011000000 +00001100101100000000101110101100 +00000001110010110000000010010010 +00110000000010111001100000010111 +11100110100000001111101010000000 +00101010110000001000111110111000 +00001011010100000000010001110000 +00000000000000000000000000000000 +11100000000000011010110000000000 +11111011000000000011101011000000 +00001111111100000000001101111100 +00000100111111110000000000111110 +11000000000011111101000000000011 +11110100000000001101101100000000 +00110011110000100000111111110000 +00000011111110000000000001100000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11101011000000010011010011000000 +01001100001100000001001111101100 +00010000110010110000000000110110 +01000000000011011011000010000011 +10001100000000001101100011000000 +00110010110000001000110010010010 +00000011000101010000010000100000 +00000000000000000000000000000000 +11001000000001010011110000001000 +10001111000000000010001111000000 +01001010111101000000001011111100 +00000011101011110000000010100010 +11000000000010001011110011000010 +10101100000000000000000100000000 +00010110111100000010110010010100 +00000010001100100000000001000000 +00000000000000000000000000000000 +11000000000001000100110000000000 +10100011000000000010010011000000 +01001001001110011000000011001100 +00000000100010110000000001101100 +00000000000110010011100000000010 +01001100000000010001001000000001 +01100000111101000000100100000100 +00010010001110000000000001010000 +00000000000000000000000000000000 +00100000000100000101111000000000 +10000111100000000010000111100000 +01001010011110000000001011011110 +01000000101000111001000001101001 +01100100010110000111100000000010 +11010110000000101000010010010000 +00100100111000000000100001011000 +00010110001011000000000001000000 +00000000000000000000000000000000 +01001000000010000100110000000000 +11100011000000000011010011000000 +00001101001100100000001011101100 +00000000100000110000000000111100 +11010000000011011011000000000011 +11001000000000001101001001000000 +00110000110001000000110100010000 +00001011000100100000001000000000 +00000000000000000000000000000000 +01000000000101011011110000000000 +11111111000000000011111111010100 +00001111111100000000001111111101 +00100010111111110000000000110111 +11000000010011111110000000000010 +10010100000000001111110000000100 +00111011110001000000111111010001 +00000011110100000000011001100000 +00000000000000000000000000000000 +00001000000001011110110001000000 +11111011000000000011111011010100 +00001110101111001000001100101101 +00000000110010110111001000111010 +00000000000011101011100000000011 +00101100000000001101101000000000 +10110010110010100000111100111000 +00100011001010100000000001110000 +00000000000000000000000000000000 +01001000000110010001110010000100 +10110111001000000010110111000000 +00000011011101000100001010001100 +10000000110101110011000000100001 +11000000000010001111000000010010 +00011100010000001010011000000000 +00100001110000001000101101110000 +00000010001100100000010001100000 +00000000000000000000000000000000 +00100000000000000001111000000000 +10110111100100000010110111101000 +00001010001110100000001000011110 +00000000100000111000000000101001 +01100000000110100111100000000010 +00001110000000001000001010000000 +01100001111000000000101111011000 +00000010001000000000000000100000 +00000000000000000000000000000000 +01101000000001001100110000000000 +10111011000000000010111011000000 +00001011001100000000001010001100 +00000000100100110000000000101000 +11000000000010000011001100001010 +00001110000000001010001110100000 +00100000110000101000101100010101 +10000010000100100000010000110000 +00000000000000000000000000000000 +11101000000101011110100000000000 +11111010000000000011111010000000 +00001110101000000000101100101000 +00000000110010100000000000111011 +10001000000011101110000000000011 +00111011100000001100111010100000 +00110010100100001000111111101100 +00001011001110100000010001100000 +00000000000000000000000000000000 +01001000000000011010000000000000 +11111000000000000011111000000000 +01001111100000000000001111100000 +00000000111100000000000000010110 +00100000100011111000000000000011 +11100000001000001110100000000001 +00111110000000000100111110000000 +00000011110100100000000000110000 +00000000000000000000000000000000 +00001000000100001000010000000010 +11001001000000000001001001000000 +01000110100110000000001111100100 +00000000110010010000000000110100 +01000000000011001001000000000011 +11000100000000001000000100000000 +00100010110000001000111110010000 +00000011110000100000010000110000 +00000000000000000000000000000000 +10000000000001000110010000000100 +10001001000000000010001001000000 +00101000100110010000001011100100 +00000010100010010000000010100010 +01000000000010101001010000000010 +11100100000000001000100100000000 +00100010010000000000101110010100 +00000010111000000000000000010000 +00000000000000000000000000000000 +00111000000001010010010000000000 +10001001000000001010101001000000 +00001000100100000000001011000100 +00000000100010010000000000100110 +01000000000010001001000010000010 +11100100000000001010100100000000 +00101010010000000000101110010100 +00000010110001100000000001000000 +00000000000000000000000000000000 +00101000000101000000010010000000 +10000001001010000010100001001001 +00001000000100100000001011000100 +10110000100000010010100000100000 +01001000010010100001000000000010 +11000100100000011010000110100000 +00101000010010010000101100010000 +00000010110000100000000100000000 +00000000000000000000000000000000 +10111000000011000110000000000000 +11001000011100100011101000010100 +00001100100001010000001111100000 +10000000110010000010000000110100 +00000000100011001000010100000011 +11100000000000101110100000000000 +10111010000000000000111110000101 +00000011111011100000001101010000 +00000000000000000000000000000000 +10011000000001011010010011110000 +01111001000000000011011001000100 +00001101100100010000001111100100 +10110000111110010010100000111111 +01001110000011111101000000000011 +11110100010000001101110100010001 +00110110010001001000111111010000 +00000011111001100000011001110000 +00000000000000000000000000000000 +00011000000001011110010100001000 +11111001010000000011111001000000 +00001100110101000000001100100100 +00100000110010011000000000110010 +01001000000011111101010000000011 +00010100000000101100000100000000 +00110010010000101000111100010000 +00100011110001100000000101100000 +00000000000000000000000000000000 +00111000000110001110000100001000 +10111000010000000010111000011110 +00001000100001000000001010000011 +10001000110110001111100000100010 +10011001000010110000001000010011 +01100001000000001000100001000000 +00100011100100000000101110000000 +00000010110011100000010000110000 +00000000000000000000000000000000 +01001000010001011000010110000100 +10110001011001000010110001000000 +00101000000101100000001000000100 +00100000100000010000000000100000 +01010010100010110001000000000110 +00000101000000001000010111000010 +10100001010000000000101100011010 +10000010110100100000000100110000 +00000000000000000000000000000000 +00011000000001001010010000001000 +10111001000000000000110001000000 +00000000100100000000001010100100 +00000000100100010000000000100010 +01000000000010110001011000000110 +01100110001000101000110100000000 +00100111010000000000101110010010 +00000010110001100000010001100000 +00000000000000000000000000000000 +10100000000101011110010000000000 +11111001000000010011111001000000 +01000000100100000001001100100100 +00000000110010010000000010110010 +01010000000011111001010000100011 +00100100000000001100100100000010 +00110010010000000000111110011000 +00000011111010000000010001110000 +00000000000000000000000000000000 +01001000000000010010010000000100 +11111001000000000011111001000000 +00001111100100000010001111000100 +00001000111110010000000100111110 +01100100000011111001000000000011 +11000100000000001111000101000100 +00111010010000010000111110110000 +10000011110110100000000001100000 +00000000000000000000000000000000 +00001000000100001010000000000000 +11101000000001000011001000000000 +00001101000000010000001111100000 +00010000110010000000000000110110 +00010000001011001000000000000011 +00100000000000001100100000000000 +00110011000100000100111110000000 +01000011000010100000010000100000 +00000000000000000000000000000000 +00101000000001010010100000000001 +10001010000000000010001010000000 +00001001111000000000001011101000 +00000010100010100000010010100010 +10000000000011011110000000000010 +10101000000000101000101000000000 +00100010100000000100101110100000 +00000010000010100000000001000000 +00000000000000000000000000000000 +00101000000001010100110000000100 +10100011000000100010100011000000 +00001001001110001000001011001100 +00000000100000110000000010100100 +11000000000010000011000000000010 +01000100000000011000001100000000 +10100000100000000000101100110000 +00000010000010100000000001010000 +00000000000000000000000000000000 +10000000000100010001111000000000 +10000111101000000010100111001000 +00011001011000000000001011011100 +10000000100000110001000000100001 +11100100000010000101000000010010 +11010100000000001000010100000000 +00100001100000010000101111111000 +00100010001010000000000001000000 +00000000000000000000000000000000 +10001000000010001011111001000000 +10101111110000000011100111110001 +00001101011110000000001111011111 +00100000110001111010100000110111 +11101000000010000110100000000011 +01010110000000001100011010000000 +00110001101000000000111101111000 +00000011001010100000001000000000 +00000000000000000000000000000000 +00001000000101011010110000000000 +10111011001000001011011011011000 +00001111101000000000001111101100 +00000100111110110000000000111110 +11010000010011111101000000000011 +10100100000000001111100000000000 +00111110100000000000111110110110 +00001011110000100000011001100000 +00000000000000000000000000000000 +00000000000001001111111000100000 +11111111110000000011001111110000 +00001100110110000000001100111110 +00000010110011111000000010110011 +11110000000011111111100100000011 +11110110000000001110111110000000 +00110101101000000000110011111100 +00000011000000000000000001110000 +00000000000000000000000000000000 +10101000000110001001110000000000 +10110111000000000010000111000100 +00001000010001000000001101111100 +00000000100001110010000000100001 +11000000000010110101001100010010 +11010100010000001000010100000000 +00100001100001000000100001110000 +00000010001010100000010001100000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110111000000000010000111000000 +00001000011100000000001000011100 +00000000100001110000000001100001 +11000000000010110110000000100010 +11010101000000001010011000000000 +00100001101000000000100001110100 +00000010000000000000000000100000 +00000000000000000000000000000000 +00100000000001001100110000001001 +10110011000000000010000011000000 +00001000100000000000001001101100 +00000000100010110000000010100000 +11110100000010110001010100000010 +11000100010000001000000010000000 +10100000100100100000100000110000 +00000010000010000000010000110000 +00000000000000000000000000000000 +10101000000101010011110000000000 +10111111000000001110001111000000 +00101000101100000000001100111100 +00000000110011110000000000110011 +11110000000010111001010000000011 +11100000000000001110101101001000 +00110010010100000000110010110000 +00000011001010100000010001100000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11111011000000000011111011000000 +00001111101000000110001111101100 +00000000111110110000000000111110 +11000000000011111001000000000011 +11000000000000001111100100000000 +00111110010000000000111110110100 +00000011111000000000000000110000 +00000000000000000000000000000000 +00100001000100001111110000000000 +11111111000000000001111111000000 +00001111111100000000001100111100 +00000000110011110000000000110011 +11000010000011111100000010000011 +00100000000000001100101000001000 +00111111010000001000111111110000 +00000010000000000100010000110000 +00000000000000000000000000000000 +10100001000001000110110000000000 +10111011000000000010111011000001 +00001011101000000000001010101100 +00000010100010110000000010100010 +11000000000010110001100000000010 +00100001100000001000100000000000 +00101110011000000000101100110000 +00001010001000000000000000010000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000000000010111011000000 +00001011100100000000001000101100 +00000000100010110000000000100010 +11000000000010111001000100100010 +00100000000010001000101100000010 +00101110010001000000101110110100 +00000010101000000000000001000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10110011000000000010110011000000 +01001001000100000000001010001100 +00000000100000110000000000100000 +11000000000010111001000000000010 +00000000000000001000000100000000 +00101100011000000000101110110000 +00000010100000100000000100000000 +00000000000000000000000000000000 +00000000000011010111110000000000 +11110111000000000011110111000000 +00001111001100000000001100111100 +00000000110001110000000000110011 +11000000000011111000000000001011 +00100000000000001100101000000000 +00111110010000000000111110110000 +00000011100000000000001101010000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11111111000000000011111111000000 +00001111110100000010001111111100 +00000000111111110000001000111111 +11000000000011111101000000000011 +11110000000000101111110000000000 +00111111010000000000111101100000 +00000011011010000000011001110000 +00000000000000000000000000000000 +11000000000001011111100000000000 +11001101100000000011111111001000 +00001111111100110000001000110110 +00000000110011110001000000110011 +00001100001010001101100000000011 +11111100000000001100111110000000 +00110111010000000000110011000000 +00110011111100000000000001110000 +00000000000000000000000000000000 +10000000000100001010010000000100 +10001001100000010010111111001110 +00001011111101100000101000100110 +00000100100000110010000000100010 +00001100100010001011100000000010 +11111101100010001000100110000001 +00100010011000000000110110001000 +00000010111000000000010000110000 +00000000000000000000000000000000 +10001000000001001100000000000001 +10000011000001000010110011000000 +00001011001100110000001010101100 +00000000100000110010000000100000 +10001000000010000001000000000010 +11001100011000001010001100000000 +00101110110000000011100000100000 +00000010111000100000000101110000 +00000000000000000000000000000000 +11000000000101011000010000100011 +10001011001000000010111011000000 +00011011101100000000001010100110 +00000000100010110000000001101010 +00000000000010001011000000010010 +11101100000000001010101111000110 +00101010110000000000100110100000 +10000010111100000000010001100000 +00000000000000000000000000000000 +00000000000101011110000101000000 +11001001000000010011111011000000 +00001111101100000100001110000100 +00000000110010110000000001110010 +01001000000011001001100000000011 +11101100000000000110100110000000 +00111100010100100000110010000100 +00000011110000000000010001110000 +00000000000000000000000000000000 +11100000000000011011011000000000 +11111101000011000011111011000000 +00001111111100000000001101110100 +00010000111101110000000011110111 +00000100010011111111100100000011 +11111100000001101101110100000001 +00110111010001000000111110000100 +00100011111110000000000001100000 +00000000000000000000000000000000 +01000000000100001010000100000000 +11101011000000100011111011000000 +00101100001100010000001110101100 +00000000111110110000000000110000 +11000100000011111001000000000011 +11101100000000101110101101001000 +00111110110000100010110010110100 +00001011000100000000010000100000 +00000000000000000000000000000000 +11001000000001010010010111010000 +10001011000000000010111111000000 +00001000111101010000001000100100 +10000000101111110000010000100010 +00100000000010111011100000000010 +11111110000000001000001101100000 +00001110110110000000100010111000 +01000000001100100000000001000000 +00000000000000000000000000000000 +11100000000001010100011100000010 +10100001110000000010110011000000 +00011001001110000000001010000100 +00000100101100110000000000000100 +00011000010010110001100000000010 +11101100010000000010000100000000 +00001100000100010000100100010000 +00000010001110000000000001010000 +00000000000000000000000000000000 +01100000000000010000111000000000 +10010101100010110010110111100000 +11001001011110000000011000011110 +00000000101101111000001000100101 +11100000000010110101100010000010 +11011110000000001010010110000010 +00101100001000010100100101011010 +10010010000110000000000001000000 +00000000000000000000000000000000 +01001000000010000000110010001001 +11100001000001000011110011001000 +10011101101100100000001110001100 +00000000111100110000000010110100 +10001000100011110001000000000011 +11101100000000001110001100110000 +00111100110000000000110100000000 +00001001000100100000001000000000 +00000000000000000000000000000000 +01000000000111011011110100000001 +11101101000000000011111111000000 +00011110111101000001001111111101 +00000000111111110001000000111011 +11000000000011111101000100000011 +11111101001000001101111100010000 +00111111110000000000111011000010 +01000011110100000000011001100000 +00000000000000000000000000000000 +10101000000001011110110000000000 +11001011000000000011111011001001 +00001111101100010000001111100100 +10000000111110110001000000111110 +01000000010011111011001100000011 +11101100100000101100100000000000 +00111100010000000010110010110000 +00010011001010100000000001110000 +00000000000000000000000000000000 +01001000000100010000110000000000 +10000111001100000010110111010010 +00001011011100000101001011011100 +00010000101101110000001000101101 +11000000000010110111000010000010 +11011100000000001000010000000010 +00101101010000000000100001110000 +00000010000100100000010001100000 +00000000000000000000000000000000 +11000000010000000001111000000100 +10000111100101000010110111101000 +00001011011110100000001011011110 +01000001101101111000000000101101 +11100000000010110111101000000010 +11001110100000001011011010001000 +00101101011000000000100000111000 +00000010001100000000000000100000 +00000000000000000000000000000000 +01001000000101001100111000000000 +10000011000000000010110011000000 +00001011001100000000001011001100 +00011000101100110000001000101100 +11000000000010110011000100000010 +11101100000000001011001010000010 +00101100111000010000100000111111 +00000010000100100000010000110000 +00000000000000000000000000000000 +11101000000101011010100000100010 +11001010101000000011111010000000 +10001111101000000100001111101000 +00000000111110100000011001101111 +10010001000011111010100000000011 +11101000000010001111111000000100 +00111111101000000000110011100100 +00001011001110100000010001100000 +00000000000000000000000000000000 +01001000000000001110000000000010 +11111000000000000011111000000000 +00000011100001000000001111100000 +00000000111110000000000001111110 +00000010010011111000000000000011 +11100000000000000000100000100000 +00111100000001000000111100000000 +00000011110100100000000000110000 +00000000000000000000000000000000 +00001000000100001110110001000010 +11001001000000000001001001000000 +10000011000100000010001100100100 +00000000111110010000001001111100 +01000001100011001001100100000011 +11100100000000001100100110000010 +00111110010001100000110010011000 +00000011000000100000010000110000 +00000000000000000000000000000000 +10000000000001000110010100000000 +00000011000000000010001001000000 +00001011100100000000001000101101 +00000100101110010000000000101110 +01000000000010001011100000000010 +11100110000010001000100111000000 +00101110010110000000101010011000 +01000011001000000000000000010000 +00000000000000000000000000000000 +00011000000001010000010100000000 +10001001010000100010101001000000 +01011011100100000000001000100101 +00000000101110010000000000101110 +01000000000010001001000000000010 +11100100010000101000100100101000 +00101110010000000010100010010001 +00000010000001100000000001000000 +00000000000000000000000000000000 +00001000000001000000010010100010 +10001001000000000010100001001010 +00001011000100101000001000000100 +00000000101100010010001100101100 +01001000100010000001000000000010 +11000100101000011000000100000000 +00101100010010000000101000010010 +00000010000000100000000100000000 +00000000000000000000000000000000 +10111000000011000110000010010000 +11001000000001000011101000001000 +10001111101001110000001100100000 +00000000111110000000000100101110 +00010100001011001010000000000011 +11100001110000001100100000000100 +00111110000000000000110010000000 +00001011001011100000001101010000 +00000000000000000000000000000000 +10011000000111011010010010100010 +11111001000000011011011001001010 +00001111100100000000101111100100 +00000000111110010011100000111111 +01000100100011111001000000000011 +11100100000000001111110100000000 +00111111010001010010111111010001 +00000011101001100000011001110000 +00000000000000000000000000000000 +10011000000001011010011000000000 +11001001000000000011111001000100 +00001111110100100000001111100100 +00010000111110010110000000111111 +01001011000011000001000000000011 +11110101000000101100110100000100 +00111111010010000100110011010000 +00000011001001100000000001110000 +00000000000000000000000000000000 +00111000000100001110001010000010 +10001000000000000010110000010100 +00001011100000100000001011100000 +00000000101110000101000000101100 +00011001000010001000000000000010 +11100001000010001000100000000010 +00101110000100000100110110000100 +00001010000011100000010000110000 +00000000000000000000000000000000 +00001000000001001100010100100001 +10000001000001000010110001001000 +00011011000101001000001011000100 +00010001101100010010000000101100 +01000010000010000001000000000010 +11000101100001001000000100000100 +00101100011001000010100000010100 +01000010100000100000000101110000 +00000000000000000000000000000000 +00011000000101011000110010010000 +10001001000000000010111001000001 +00011011100100000000001011100100 +10000000101110010000000000101110 +01000001000010001001000000000010 +11100100000000001000100100000110 +00101110010000000000100110010100 +01000010100001100000010001100000 +00000000000000000000000000000000 +10100000000101011110010000000000 +11001001000100000011111001000000 +01001011100100000100001111100100 +00001000111110010000000000111110 +01000000001011001001000000000011 +11100100000000001100100100010000 +00111110011100000000110000010000 +00000011101010000000010001110000 +00000000000000000000000000000000 +00101000000000011010110000111000 +11111001100000000011111001000000 +00001111100100001000001111100100 +00000000111110010000000000111110 +01000100000011111001000000000011 +11100100000010001111100110000010 +00111110011001000100111110010010 +00000011010010100000000001100000 +00000000000000000000000000000000 +00101000000100001010000000000100 +11001000000000010011111000000000 +10001101100000000000001110100000 +00000000111110000000000011110010 +00000000000011001000000010000011 +00100000000000001101100010000000 +00111110000010000010110010000000 +00000011000010100000010000100000 +00000000000000000000000000000000 +00101000000001010010101000001010 +10001010000000100010111010000000 +00101000111000000000001000101011 +00000000101110100000000100000011 +10000000000010001010010000100010 +00101000000100001000111000000000 +00101101100100001000101011100000 +00000011100010100000000001000000 +00000000000000000000000000000000 +00101000000001010100111000000000 +10010011000100000010110011000000 +00011000001110000000001010001100 +10000000101100110000000000100010 +11100000000010000011010000000010 +00100100000000001001001100000000 +00101100010000000100100000011000 +00000000010010100000000001010000 +00000000000000000000000000000000 +10100000000000010001110000110000 +10010111000000000010110111101000 +00011000010110001000001000010101 +00000100101101111010001000100001 +11010000000010001111100000000010 +00010100000000011000011100000000 +00101101010000001000101001110100 +00010110101010000000000001000000 +00000000000000000000000000000000 +10101000000010000000101001000000 +11010111100010010011110111101000 +00001100111110000000001110011010 +00000000111111111100001000100001 +11100000001011000111100000001011 +00111110000000001101011110000000 +00111100011000000010110000111000 +00001011011010100000001000000000 +00000000000000000000000000000000 +00001000000011011010100010000000 +11101010001000000011111011000100 +00001110100000000000001111100000 +10000000111110110110100000111110 +11000000000011111001011000010011 +11100100000000001111101100000000 +00111110010000000000111110110000 +00000011110000100000011001100000 +00000000000000000000000000000000 +01000000000001011111011001011000 +11101111100100000011111111110000 +00101100111010000000001111111111 +00000000111111111000000000110011 +01100000010011111111110000000011 +11110110000000001100111110000000 +00110001011001000010110011111000 +01000011000100000000000001110000 +00000000000000000000000000000000 +10101000000100011001010011000000 +10000101000000000010110111000000 +00001000010000000000001011010100 +00000000101101110000000000101001 +11000000000010110111000000000010 +11110100100000101101011100000000 +00111101010011000000100001110010 +00100010001010100000010001100000 +00000000000000000000000000000000 +00010000010000001001110000010000 +10000111000000000110110011000000 +00001000011100000000001011011100 +00000000101101110000000000100001 +01000010000010110110000000000010 +11011100000010001000111100000000 +00100001010000000100100001110000 +00000110100000000000000000100000 +00000000000000000000000000000000 +01100000000101001100000100001001 +10000000000000000010111011000001 +00001000000000000000001011000100 +00000001101100110000000000101000 +11100000000010110000000000010000 +11000100000000001000001100000010 +00101000010000000000100000110000 +01100110100110000000010000110000 +00000000000000000000000000000000 +10111000000101011010100100000010 +11001000000000100011111111000000 +10001100101100000000001111101110 +00000000111111110000000000110010 +11110100000011111000100000000001 +11100100000000001000101100000000 +00100010111000000000110000110000 +00000011101011100000010001100000 +00000000000000000000000000000000 +10000000000000001100101100000000 +11111011000000000011111011000000 +00001111101100000000001111101101 +01000000111110110000000000111110 +00010000000011111010000100010011 +11000100000000001111101100010000 +00111110011000000000111110110000 +00000001011000000000000000110000 +00000000000000000000000000000000 +10000000000100001111110000100000 +11011100100000000011111111000000 +00001100111100100000000110111010 +00010000111100110000010000110011 +11000000000011111101000000000011 +11111100000000001100111100000000 +00111111010000000000110011111010 +00000011001000000000010000110000 +00000000000000000000000000000000 +10000101000001000110110000000000 +10001010110000000010111011000000 +00001000101000000010101000101001 +10000000101110110000000000100010 +00101000000010111001100001000010 +11100100000000001000100110000010 +00101100011000000010100010110000 +00000010001001000100000000010000 +00000000000000000000000000000000 +10000000000001010010010000010010 +10001000011000000010111011000000 +00001000000000000000011000100000 +01000000101110110000000000100010 +01001001000010111000000100000010 +11100100000000001000101110000000 +00101110101000100100100010110000 +00000010001000000000000001000000 +00000000000000000000000000000000 +00001000010001000000010000000000 +10000001000000100010110011000000 +00101000000000000000001010000000 +00000000101100110000010100100000 +00000000000010110010100000000010 +11000100000000001000001110000000 +00101110010000000000100000110000 +00001010000000100000000100000000 +00000000000000000000000000000000 +10000000000011010100110000000000 +11001000000000000011111111000000 +00001100100100000000001100100000 +00000100111111110000001000110010 +01000000000011111000000000000011 +11101100000000101100101100000000 +00111110010000000100110010110000 +01000011001000000000001101010000 +00000000000000000000000000000000 +10100000000111011111000000000000 +11111100000000000011111111000000 +00001101110000000010001101110000 +00000000111111110000000010111111 +00000000000011111100000000000011 +11110100000000001111010000000000 +00111111010000000000111101110000 +00000011111010000000011001110000 +00000000000000000000000000000000 +11000000000000011111011000000000 +11011111000010000011001111000110 +00001101110110010000001111110000 +00000000111111011000001100001111 +01100000100011001100001100100001 +11110110000000001100110000000010 +00110011110000000100110011110000 +00000000001100000000000001110000 +00000000000000000000000000000000 +10000000000100001110010000000000 +10001011100000010011011111011000 +00001101100100100000001011100001 +00100100101110011000000000101110 +01100000000010001000011100000010 +11100100000010001000100010000100 +00101010111000000000100010010111 +00010010001000000000010000110000 +00000000000000000000000000000000 +10001000000001011110110000000000 +10010011000000000010000011000000 +00001000000100100000001011000000 +11000000101100010000010000100100 +01000000000010000000000000000010 +11000100000000001000000000000000 +00100000101000000000100000010000 +10000010001000100000000101110000 +00000000000000000000000000000000 +11000000000101011010111000100000 +10001011000000000010010011000000 +00001001100100000000001011100110 +00010000101110111000000000101110 +10100000001010001011100000000010 +11100100100100000000100100000000 +00101010100000010010100000011000 +00100010001100000000010001100000 +00000000000000000000000000000000 +01000000000101010100011100000000 +11011011000000000001001011000000 +00001100100100000000001111100010 +00000000111110011010000000110110 +01100000000011001000110010000011 +11100111000000000100101001010000 +00110010110000000000100010010000 +00000011000100000000010001110000 +00000000000000000000000000000000 +11100000000000011011010000000000 +11111111000000000011111011000001 +00001111110101000000001111111000 +00101000111111010000000000111111 +01000001000011111101000000000011 +11110100000011001111111000000010 +00111110110100001000111111010000 +00000011111110000000000001100000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11101011000000000011111011000000 +00001101100100000000001111100101 +00000000111110110100000000111110 +11001001010011111000010001000011 +00100100001010001100001101001000 +00110010010000000000110010010000 +00000011000100000000010000100000 +00000000000000000000000000000000 +11001000000000010010110000000000 +10110111101000000010111111000000 +00101100100100000000001011101101 +00011000101110110000000001111100 +11100000000010111011110010000010 +10000100000000001000101111100000 +00100000000111000000100010010111 +00000011001100100000000001000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10100011000000010010110011000001 +00001000000100000000001011000011 +00000000101100111000010000101100 +11010100000010110000100010000010 +00000101000100001010000010000000 +00100000110000000010100000010000 +00000010011110000000000001010000 +00000000000000000000000000000000 +00100000000000010001111000000000 +10110111100001000010110111100000 +00011000011110000000011011010110 +01000000101101101100010000101001 +11100000000010110100100001000010 +10110110000010001010011110000001 +00100001111010000000100001011001 +01000010000010000000000001000000 +00000000000000000000000000000000 +01001000000010000000110000000000 +11100011000000000011110011000100 +00001100000100000100001111001001 +00100000111100110001100000101100 +11001000000011111001000000000011 +00000101000001001110001000000000 +10110000110000000000110010010000 +00000001010100100000001000000000 +00000000000000000000000000000000 +01000000000111011011110000000000 +11111111000000100011111111000000 +00001111111100000010001111110100 +00010000111111100000000100111111 +10000000000001111111000000000011 +11010100010010001101011100010000 +00111111110010010000111111010000 +00000011110100000000011001100000 +00000000000000000000000000000000 +10101000000001011110110000000000 +11111011000000000011111011000110 +01000011100100000000001111100100 +00000000111010110000000000111110 +11100001000011001011000000010011 +00100110000000000000001100000000 +00100010110000000000110010010000 +00010011001010100000000001110000 +00000000000000000000000000000000 +01001000000100011001110000000000 +10110111000000000010110111001000 +00001011011100000010000011111100 +00000000100001110000000100111101 +11000000000010000101000001000011 +01010000000000001000011100000001 +00101000110000000000100011010000 +00010010000100100000010001100000 +00000000000000000000000000000000 +11000000010000001001111000010100 +10110111100001000010110111100000 +00011011010110000100001011011111 +00010000101001111100010000101111 +11110000000010010011100000000010 +00011111000000101000011110000100 +00100001111000001010100001011000 +00001010001100000000000000100000 +00000000000000000000000000000000 +01001000000101001100100000000100 +10110011000000000010110011000000 +00011011001100000000001011001110 +00100000100000111000000000101100 +11001000000010011011110000000010 +01000101001000001000001110000000 +00101000010000000000100000010000 +00001010000100100000010000110000 +00000000000000000000000000000000 +11101000000101011011100000000000 +11111010000000000011111010000000 +00001111101000000000001111111001 +00000100111011101000001000111111 +10000000000011011110101100000011 +00111010000000001100111011000000 +10110011100110000010110010100000 +00000011001110100000010001100000 +00000000000000000000000000000000 +01001000000000001110000000100100 +11111000000000000011111000000000 +00001111100000000000001111100001 +00000000111110001000000001111010 +00010000011011101000010000000011 +11100000000000101111000001010000 +00111110000000100000111110000001 +00000011110100100000000000110000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11101001000000000011111001000000 +00001111100100000000011100000100 +00000000110010010000000000111110 +01110000100011111001000100000011 +00100100000001001111100110101000 +00110000011000000000111000010001 +00001011000000100000010000110000 +00000000000000000000000000000000 +10000000000001000100010000000000 +10001001000000000010111001000000 +00001011000100000000001000100100 +00010000101010011000010000101110 +01001000000010111001101000000010 +00100111000000001011100111000010 +10110110010100000000100010011000 +00001010001000000000000000010000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10101001000000000010111001000000 +00011011100100000000101000100100 +10000000100010010010000000101110 +01000000000110111001000000000010 +10100100010000001011101101000000 +00100010010001100000101010010000 +00000010000001100000000001000000 +00000000000000000000000000000000 +00001000000001000010010000000000 +10000001001000000010110001001001 +00011011100100000000001000000100 +10000000101000011000000000101100 +01000000000010110001001000001010 +00001100000000001011000100100100 +00100100010010000010100000010010 +00000010000000100000000100000000 +00000000000000000000000000000000 +10111000000011000110000101000000 +11101000000010000011111000010100 +00001111100000000000001000101001 +01000000110010000000000000111110 +00000000000011111000010100000011 +10000001010000001111100000000000 +00110010000000010000111010000101 +00000011001011100000001101010000 +00000000000000000000000000000000 +10011000000111011011010000000000 +11111001000000000011111001000100 +00001111110100101000001111110100 +01000000111111010000000000111101 +01000000000011111101000100100011 +11110100000000001111110100010000 +00111111010001000000111111010001 +00000011111001100000011001110000 +00000000000000000000000000000000 +00011000000001011110010001000000 +11111101100000000011111001010000 +00001111100101000000001111110101 +00000000010001010000000000111111 +01000000000011110101001000000011 +00110101000000001100110100000110 +00110011010000000010110011010110 +00001011010001100000000001110000 +00000000000000000000000000000000 +00111000000100001110000000000100 +10111000010100000010111000011100 +00001011100000100000000011101001 +00000100110110000000000000101110 +10000000000010111000001011000011 +01100000000000101000100001000000 +00101010000100010000100000000110 +00000010000011100000010000110000 +00000000000000000000000000000000 +00001000010001011100010010010000 +10110001000001000110110001001000 +00011011000100100000001011000101 +10000001100000010000000000101100 +01000000000010110001010000000010 +00000100100001101000000101000000 +01100000010100000100100000010011 +00100010010000100000000101110000 +00000000000000000000000000000000 +00011000000101011010010000010000 +10111001000000000010111001000000 +00011011100100000001001011100110 +00000100100110010000000000101110 +01000001000010111011001000010010 +01000101100000001000100100001000 +01101010010010000000100010011000 +00000010000001100000010001100000 +00000000000000000000000000000000 +10100000000101011110010101100000 +11111001000000000011111001000000 +00001111100100000010001111100101 +00000000110010011000000000111110 +01000000000011111001001000000011 +00100101000010001100100111000000 +00110000010010001000100010010000 +00001011011010000000010001110000 +00000000000000000000000000000000 +00101000000000011010010000000000 +11111001000000000011111001000000 +00001111100100000001001111100100 +00000000111110010010000100111110 +01110001000011111001000000000011 +11100110000000001111100100101000 +00111110010000000010111100010000 +10011011110010100000000001100000 +00000000000000000000000000000000 +00101000000100001010000100000000 +11001000000000000011001000000000 +00001111100000000000001100100001 +00000001110010000000100000110110 +00000010000011111000000010000011 +00100011000010001111100001000000 +00110010000101100000111010000000 +00001011000010100000010000100000 +00000000000000000000000000000000 +00101000000001010010100000000000 +10001010000000010010101010000000 +00001011101000000001001000111001 +00000000100011100000010000100011 +10101001000010111110010000010010 +00111000000001001011011000100001 +10100011100000000000100011100100 +00000010000010100000000001000000 +00000000000000000000000000000000 +00101000000001010100110000000010 +10000001000000000010010011000000 +00001011001100000010001000101110 +10000000100000110000000000100100 +11100000000010111011110000100010 +00001100000000011011001010000000 +00100100101000001000101000110000 +00001010000010100000000001010000 +00000000000000000000000000000000 +10100000000000010001111011000000 +10000011100000000010110111000100 +00001011011110100000001000001101 +00001000100101111000000000100001 +11000000000010110111010000000010 +00011100000000001011011000000000 +00100101010000000000100001010000 +00010010001010000000000001000000 +00000000000000000000000000000000 +10101000000010000011111000000000 +11000101100000000011010111100010 +01011111111110101000001100011110 +00000010110001101000000000110101 +11100000000011110111100000001011 +00010110000000001111000010000000 +00110100111000001000111001111000 +00000011001010100000001000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111011000000000011101011011000 +00001111101101110000101111100100 +00010100111010110000000100111110 +11000000100001111001000000000011 +11100100000110001111100000000001 +00111010010000000000111110110000 +00000011110000100000011001100000 +00000000000000000000000000000000 +00000000000001011111111000000000 +11111101100000000011111111100000 +00001000111110000010001111110110 +00000000111101111000000100111011 +10100100000000111111101100000011 +00111110000000001111111010000000 +00110011111010000000111111111000 +00000011000000000000000001110000 +00000000000000000000000000000000 +10101000000100011001110001000000 +10110111000000000010111111000001 +00001101011100100000001011111100 +01000100110001100010000100100001 +11000000000010110110000101000010 +00011100000001001111010001100100 +00110101010000000000101101000001 +10000010101010100000010001100000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110101000000000010110111000000 +00001000011100000010001011010000 +00000000101001110000001000101001 +11000000000010110101001000000010 +00010000001000001011110000001000 +01100001010110000000101101110000 +00000010000000000000000000100000 +00000000000000000000000000000000 +00100000000101001100110000010000 +10110011000000000010110011000000 +00001001001110000000000011000000 +00000000100000110101100000100000 +11011100000010110000000000000010 +00000011000000001010000010000000 +01100000010000000000101110101000 +00000010100010000000010000110000 +00000000000000000000000000000000 +10101000000101011011110000000000 +11111001000000000011111111000000 +00001100111110001000001111101110 +01000000111010011000000000111010 +11100000000011111001101000001011 +00101100000000001011001011000000 +00100010101100000000111110111000 +00001011001010100000010001100000 +00000000000000000000000000000000 +10000000000000001110110000100000 +11111001000000000011110011000000 +00001111101100000001001111100001 +01000000111110110000000100111110 +01000000000011111001010001000011 +11101001001000001111101000000000 +00111110111000000000111110000000 +00000011111000000000000000110000 +00000000000000000000000000000000 +00000001000100001111110000000000 +11111101010000000011111111000000 +00001100111100000000001101011100 +00000000110011110000000000110011 +11000000000011110010000010000010 +00111101000000001000110000001000 +00110011110000000100110010110000 +00000011000000000100010000110000 +00000000000000000000000000000000 +10000001000001000110110000000000 +10111001000000010010111011000000 +10101000101100000000001000100011 +00000100101000101100110000100010 +01100000010010111000010000000011 +01001011000000001000100011000100 +00100000111000000000100010100000 +01000010001000000100000000010000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111001000000000010111011000000 +00001000001100000000001001100111 +00000000100010001000000000100010 +10100000000010111001100000000010 +10101100001000001010101010000000 +00100010111000000000100010110000 +10000010001000000000000001000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10110001000000000010110011000000 +00001000001100000001001000000000 +00000000101010110000000010100000 +01000000000110110000000000000010 +01101000000000001010001000000001 +00100000110000000000100000010000 +00001010000000100000000100000000 +00000000000000000000000000000000 +00000000000011010110110000000000 +11111001000000000010111111000000 +10001100111100000000001101100000 +00000000110010110000000000110010 +01000000000011111000000000100011 +10101000000001001110100000000000 +10110010010000000000110010110000 +00000011000000000000001101010000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11111101000000000011111111000000 +00001111111100000000001111110000 +00000000111111110000000000111111 +01000000010011111100000000010011 +11111000000000000101010100000000 +00111111010000000000111111110000 +01000011111010000000011001110000 +00000000000000000000000000000000 +11000000000001011101111000000000 +11011111100100000011001110100000 +00011111111101101010001100111100 +00000000110011010000000000110011 +00000100000011001111000000000001 +01110100000010001101011100000000 +00110011111000000000110001111000 +00000011111100000000000001110000 +00000000000000000000000000000000 +10000000000100001110111000001000 +10000001001000001010001000100000 +00001011111101000000011000111100 +10100010100010011000001000100010 +00001000000011011011100000000010 +00010100000001001010101111010000 +00110010011000000000100010111000 +00000010111000000000000000110000 +00000000000000000000000000000000 +10001000000001011100100000000000 +10111011000000000010000011100000 +00000011001100100000001000001100 +01000000100000010000000010100000 +00000000000010000000000000100010 +01000100000010001001000100000100 +00100110110000000000100000110000 +01000010101000100000000101110000 +00000000000000000000000000000000 +11000000000101011010110001000000 +10001011100000000010001000000000 +00011011101100000000001000101100 +00000100100010010010000000100010 +11000000000010011001010001000010 +00100100000000001010100100000010 +00100010110000000010100010111000 +00000010111100000000010001100000 +00000000000000000000000000000000 +01000000000101011100110000000000 +11011011100010001011001010000100 +00001011101100000100001000101100 +00000000100010100110000000110010 +00100000000111000010100000000011 +01100110000000001101100100000000 +00110100110000000000110010111010 +00000011110100000000010001110000 +00000000000000000000000000000000 +11100000000000011011110000100000 +11111111000000000011111100000000 +00001111101100000000001111111100 +00000000111111000000000000111111 +01101000001011101110101001000011 +11110110010000001111010100000010 +10111111111001000000111111110000 +00000011111110000000000001100000 +00000000000000000000000000000000 +01000000000100001010010001000000 +11011011000000000011111011000000 +00001111101100000011001100001100 +00000001111110100100000000010001 +00000000000011101000000000000011 +10100110000010001100100100100000 +00110010110000100100111110010010 +00001011000100000000010000100000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10100011000000010010001000000000 +00001011111100000000001000111101 +11000000101101000000001000100010 +11000001010010001000000000010010 +00100101000000001000100110100000 +00100010110000000000111010111100 +10000010001100100000000001000000 +00000000000000000000000000000000 +11100000000001010100111000000000 +10010011000000001010110000011000 +00001011101100000001001010001100 +00000000101100110000001100100000 +00000001000010100011000000000010 +00100101100000001000001111000000 +00100000111100000000101100110000 +00000010001110000000000001010000 +00000000000000000000000000000000 +00100000000000010011111001001000 +10100111100000000010000101100000 +10001011011110010000001010011110 +00000001101100011000000000100001 +00100000110000000011100100000010 +00010110110000001000011110010000 +00100001111000000000101001111001 +00000010000010000000010001000000 +00000000000000000000000000000000 +01001000000010000000110101000000 +11010011000000000011110011000100 +00001111001100000000001110001100 +00000100101100110000000010110010 +11000000010011100010000000001011 +10001100100000001100000100000000 +01110000110000100000111100110000 +00000011000100100000000000000000 +00000000000000000000000000000000 +01000000000111011011110001000000 +11111111000000000011111111000110 +10001111111100000000001101111100 +00000000111111010000100010111111 +11000000000011111111010001000011 +11111100100000001111110100000000 +10111111110000000000111111110000 +00000011110100000000010001100000 +00000000000000000000000000000000 +10101000010101011100110000001000 +11011010000000010011111000001010 +00001111101111100000001101101101 +00100000111110110000000000111110 +01000000100011110011000000000010 +01101100101000001100100100000000 +00110110110000000100111100110000 +00100011001010100000000001110000 +00000000000000000000000000000000 +01001000000100010001110000000000 +10001111000000000010000101000000 +00001011011100010010001000011100 +10000000101101010010000010100001 +01000100000010110111000000000010 +00001100000000001000010100000000 +00100001110000000000101101110000 +00000010000100100000010001100000 +00000000000000000000000000000000 +11000000000000001001111000100000 +10010111100000000010110111101000 +00001011001110010100001001011110 +01000000101100111100000000100101 +11100000000010110110100000000010 +01011110000001001000010110000000 +00100001111000000000101101111100 +00001010001100000000000000100000 +00000000000000000000000000000000 +01001000000101001100110100000000 +10000011010000000010000011000000 +00001011001100000010001000101100 +00001000101100011100000000100000 +11000000000010110011010000000010 +00001110000010001000000100000100 +00100000111000000000101100101000 +10000010000100100000010000110000 +00000000000000000000000000000000 +11101000000001011001101000000000 +11011110100001000011111010000000 +00001011101000000000001101101000 +00001000111111100000010000110110 +10010000000011111010000000000111 +01101010100000101100101000100000 +00110011101000010000111111101100 +00000011001110100000010001100000 +00000000000000000000000000000000 +01001000000000001110000110000000 +11111000000100000011111000000000 +00001111100000000010001111100000 +00000000111110000010000000011110 +00000010000011110000000000000011 +11100000000000001111100000000000 +10111110000001000000111110000100 +00000011110100100000000000110000 +00000000000000000000000000000000 +00001000000000001110011000001000 +11101001000010000011011001100000 +10001111100100000000001111100100 +00000000010000011010000000110010 +11000000000011101011000010000011 +00000100000000001100000100000000 +00110010011001000000111010011010 +00000011000000100000010000110000 +00000000000000000000000000000000 +10000000010001000110010001000000 +10000001000000000010001011000001 +00001011100100000010001011100100 +00000000100010011000000000100010 +01000000000010001001000000000010 +00100100000010001000100101010000 +00100000010000000000100000011100 +00000010001000000000000000010000 +00000000000000000000000000000000 +00011000000001010010010000000010 +10101001000000000010111001001000 +00001011100100000000001011100101 +00000000101010010000000000100000 +11000000010010101001000000000010 +00100100000000001000100100001000 +10100010010000000100101010010000 +00000010000001100000000001000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10001001000000000010100001000000 +00001011000100101000001011000100 +10110110001000010010001000100000 +01001000000010000001001000001010 +00000110100000101000000100100000 +10100000010000000000100000010000 +00001010000000100000000100000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11101000000000000011111010000000 +00001111100000100000001111100001 +11000000111010000000000010110010 +00000000010011101000000000001011 +00100001010000101100100000000100 +00110010000000000100111010100000 +00000011001011100000001101010000 +00000000000000000000000000000000 +10011000000111011111010000000000 +11111101001010010011011001000000 +00001011100100101000001111100100 +00000000110111010001000000111110 +01001111000011111001000100000011 +11110100010000001111010100010000 +00111111010000000000111111010000 +00000011111001100000011001110000 +00000000000000000000000000000000 +00011000000000011111010000000000 +11110001010000011011101001000000 +00001111100101100000011111110101 +00000000110001010010000000110110 +01001010010011111101001000000011 +00110101000000101100110100101000 +10110010010000000000111111010000 +00000011000001100000000001110000 +00000000000000000000000000000000 +00111000000100001110000000000100 +10111000000000000010001000000000 +00001111100000000000001011100001 +00000000100010000101000000101010 +10011000000010111000000001000010 +00000001000000001000100001000000 +00100010000000001000101110000000 +00000010100011100000010000110000 +00000000000000000000000000000000 +00001000010001011100011000010000 +10110001001000000010100001000000 +00011011000101100000001011001101 +10000000100000010000000010100100 +01000011000010110001010000100010 +00001101100000001000000100000000 +00100000010000000000101110010000 +00000010000000100000000101110000 +00000000000000000000000000000000 +00011000000100011010011000000000 +10111001000010100010001001000010 +00001010100100000001001011000100 +00000000100010010000000010100010 +01000000000010111001000010010010 +00100100000000001000100100000000 +00100010010000000000101110010100 +00000010100001100000010001100000 +00000000000000000000000000000000 +10100000000101011110010000000000 +11111001110000000011101001000000 +00001011100100000000001011100100 +00000010100010010000000010110110 +01110000000011111001010000001011 +00100100000001001100100100000000 +10110010010000000000111100010100 +00000010001010000000010001110000 +00000000000000000000000000000000 +00101000000000011010010000000000 +01111001110000000011111001001000 +00001111100100000000001111100100 +00000000111110010000000100111110 +01001001000111111001100100000011 +11100110010100001111000100100000 +00111110111001000000111110010001 +00000011110010100000000001100000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11011000010000000010001000010000 +00001110100000000000001100100000 +00000000110100000001000000110010 +00010000001011000000011000000011 +00100000000000101110100000010000 +00110110000000000000111110000000 +10000011110010100000010000100000 +00000000000000000000000000000000 +00101000000001010011101100000000 +00001010000000000010001010100100 +00001011101000000000001000111000 +00000000111010100000000000110110 +10000000000010001110110000000011 +01111000000000001000111010000000 +00100010101010000000101111101100 +01000010110010100000000001000000 +00000000000000000000000000000000 +00101000000001010100111110010000 +10011011000000000010000011010000 +10001011001100000000011000001100 +00000001100100110000000001100000 +11000000000010000000100000000010 +00101100000000001010001010000000 +00100100001000000000101100111000 +00000010110010100000000001010000 +00000000000000000000000000000000 +10100000010000010011101000100000 +10001111001000001110000110000010 +00001011011110000000001000010000 +00000000101111110000000000100101 +11101100000010000100000010000010 +01011100000000001000011100000000 +00100001010000000000101101110000 +10000010111010000000000001000000 +00000000000000000000000000000000 +10101000000010000001111000000000 +11010111101100000010000111100010 +00001110001110000000101100011110 +00000000110101011000010100110000 +11101010000011000000100000000011 +00011110000000001110011110000000 +00110101001001000000111101111000 +00000011111010100000001000000000 +00000000000000000000000000000000 +00001000000111011000110000000000 +11111011001100000011111010001000 +00001011101101010001001111100100 +00000100111010010000000100111110 +11000000100011111000000000000011 +11101000000000001111001100000000 +00111110110010000000111110110000 +00000011110000100000011001100000 +00000000000000000000000000000000 +00000000010001011101111011000100 +11010111100000000011001101100000 +00001111111111000000001110111110 +01000000110011111001000010110011 +11100000000011111110100000000011 +11111110000000001111111010000000 +00110011001000000000111111111000 +00000011100000000000000001110000 +00000000000000000000000000000000 +10101000000000011001110001000000 +11010111001000000011010101000000 +00001110011100000000001000010001 +00000000100001110011000000100001 +11001000000011110110001000000010 +11010100000001001011011100000000 +10100001010000000000101101110000 +00000010111010100000010001100000 +00000000000000000000000000000000 +00000000010000001001110110010100 +10111111000000000010000101000010 +00001010001100000000001011011100 +00000100100100010000000111100001 +11000000000010110110000000000010 +11011100000000001011011100000000 +00101001100000000000101101110000 +00000010100000000000000000100000 +00000000000000000000000000000000 +00100000000101000100110000000001 +10010011000000000010010001100000 +00001010001100000000001001000100 +00000000100100010000000001100000 +11000000000010110010010000000010 +11000000000000001011001100000000 +00101000111000000000101100100100 +10000010110010000000010000110000 +00000000000000000000000000000000 +10101000000101011000110000000000 +11111111111000001011001011100000 +00001110111100000000001111101100 +00000000110110110000000000110011 +11000000000011111001000000000011 +11101100000000001111101100000000 +00111000001000100000111110111010 +00000011101010100000010001100000 +00000000000000000000000000000000 +10000000000000001110111100000000 +11111011000010000011111011010010 +00001110101100000000001110101000 +00000000111000110001000000111100 +11001100000011100001001000000111 +11100100000000001111100100000000 +00100110010000000000111110110000 +00000011111000000000000000110000 +00000000000000000000000000000000 +00000001000100001111110000010000 +11011111000000000011011100100100 +00000100111100000010000100101011 +00000000111111011100000000110111 +11000000000001001101100000000011 +00111000100010001110001100000000 +00110011100000001000110011110000 +00000011000000000100010000110000 +00000000000000000000000000000000 +10000001010001000110110000000000 +10000011000000010010000000110000 +00001010101100000000001000101001 +00000000101110010000000000110010 +11000000010010001001010010011010 +00100010000000001011101111000010 +00100010111000000000100000011100 +00000010001000000100000000010000 +00000000000000000000000000000000 +10000000000001010010110110010000 +10011011000000100010011011000011 +00011010001100000000001010100100 +00000000101110010000000000100110 +11000000101010101000000100000010 +00101100000001011011101111000000 +00100010000001000000100010111000 +11000010001000000000000001000000 +00000000000000000000000000000000 +00001000010001000010110000000000 +10001011000000000010001011000000 +00011010001100000000001010000000 +00000001101100010000000010100000 +11000000000010100000000000000010 +00000110000000001011001100000000 +10100010010000000000100000110000 +00000010000000100000000100000000 +00000000000000000000000000000000 +00000000000001010110010000000000 +11011111000000000011011000000000 +00011110111100000000101110100000 +00000000111110010000000000110111 +11000000000011101000000000000011 +00101000000001001110101100000000 +10110010100000000000110010110000 +00001011000000000000001101010000 +00000000000000000000000000000000 +10100000000110011111110000001010 +11111111000000000011111100000000 +00001111111100000000001101110000 +00000000111111010000000010111011 +11000000010011011100000000000011 +11110000000000001111111100000000 +00111111110000001010111111110000 +00000011111010000000011001110000 +00000000000000000000000000000000 +11000000000001011101000001000000 +11001111000110000011111111000000 +00011111110010000000001101110010 +00000000110001011000000000111101 +01100000000011111100001100000011 +00010000000000001100111100010000 +00110011111000000000110011110010 +00000011001100000000000001110000 +00000000000000000000000000000000 +10000000000100001110010110001010 +10001111000000000010111111110100 +00000011100000100000001000100010 +00000000000010111000010100101110 +01100000010010111000001000001010 +00100010000000001010111101010000 +00100010110000000000101000100100 +00010010001000000000010000110000 +00000000000000000000000000000000 +10001000000001011100000100000000 +10100011000000100010110011000000 +00011011001000001100001011000000 +00000000100000110000001000101100 +01000000000110110000000100000010 +10001000000000001000001100000010 +00100000110000000000100100101001 +00000010001000100000000101110000 +00000000000000000000000000000000 +11000000000101011000000000000000 +10101011000000000010111011000000 +00001011101001100000001010101000 +10000000100010110000100000101110 +10100000010010110011100010000010 +10101010001000001010101100000000 +00100010110000000100101110111000 +00000010001100000000010001100000 +00000000000000000000000000000000 +01000000000101011110001000000000 +11101011000000000011111011000000 +00001011100110000000001111100011 +00100000110010111101000000111110 +01100000000011111000100000000010 +10100010000000001100101100000000 +10100010110000000000110110100000 +00000011000100000000010001110000 +00000000000000000000000000000000 +11100000000000011011010010000000 +11011111000000010011111111000000 +00001111110000000000001101110010 +00000000111111111000000000111111 +01000001000011111000000000100011 +01010000000001101111111100000100 +00111111111001000100111011100000 +00000011111110000000000001100000 +00000000000000000000000000000000 +01000000000100001010000000000000 +11101011000000000011111011000000 +00001111101101000100001111100101 +10000000111110111010000000110010 +11000000000011011001010000010011 +00100001000000101100101110100000 +00111110110010000000110000110000 +00001011000100000000010000100000 +00000000000000000000000000000000 +11001000000000010010000000000000 +10001111000000000010111111000000 +01001110101000000000001011000011 +10000000101110101100000000100010 +11100010000010001011000000000010 +00101000100000101000111100000100 +00101100111100000000110110110000 +00001010001100100000000001000000 +00000000000000000000000000000000 +11100000000001010100000000000000 +00100011000000000010110011100000 +00001011100000000000000011000000 +00000000101100110100000000100000 +11100000000010010000000000100010 +00001001001000001000101101000000 +01101100010101000000100000010000 +00000010001110000000000001010000 +00000000000000000000000000000000 +00100000000000010011011000000000 +10000111100000000010110111100010 +00001010011110000000001011011010 +00000100101101111000000000100001 +11100000000010010101100000100110 +00011110010000001000011110010000 +00101101111000000000100101011101 +00000010000010000000000001000000 +00000000000000000000000000000000 +01001000000010000000000000000000 +11100011000100000011110011000000 +00001111000000000000001111000100 +10000000101100110001000000110000 +11000000010011010000000000000011 +00001000010000001100001100000000 +00111100010000001000110000010000 +00000011000100100000001000000000 +00000000000000000000000000000000 +01000000000111011011000000000000 +11111111010000000011111111000000 +00001111111100010000001111110000 +00000000111111110001011010111111 +10000000000011101111000100000011 +11111100010000101111111101000000 +00111101110000000000111111010000 +00000011110100000000011001100000 +00000000000000000000000000000000 +10101000000001011110000000000000 +11001011010100010011111011001010 +10001111100100000000001111100000 +00000000111110110000000000101110 +11000000100011101011000000000011 +00100000000000001100101111010001 +10110000010000000000110010110000 +01000011001010100000000001110000 +00000000000000000000000000000000 +01001000000100011000010000000000 +10000111000000000010110111010000 +00001011011100000000001011010000 +00000000101101110000000000101101 +11000001000010001101000000010010 +00011000000000001010111100000000 +00100001110000000000111000110000 +00001010000100100000010001100000 +00000000000000000000000000000000 +11000000000000001001001000000010 +10000111101000000010110111100000 +00001011010110000000001011010010 +00000001101101011000000000101111 +11100000000010000111100000000010 +00010010000000001001011110000000 +00100001111000000000100001111000 +00000010001100000000000000100000 +00000000000000000000000000000000 +01001000000101001110100000000000 +10000011000000000010110011000000 +00001011001100000010001011000001 +00000000101100110000000001101100 +11000000000010000011110000001010 +00001100000000001011001100000001 +00100000111000000000101000111000 +00000010000100100000010000110000 +00000000000000000000000000000000 +11101000000101011011100000000000 +10001010000000000011111010000000 +00001011111000000000001111011000 +00000000111111100001100000111111 +10010010000011001110101000000011 +00011000001000101101101000000000 +00110010101000000000110011101010 +00000011001110100000010001100000 +00000000000000000000000000000000 +01001000000000001110000001000000 +11110000000000000011110000000000 +00001111100000000000001111100001 +01000000111110000000000100111110 +00000010001011111000000010000011 +11100010000000001110100000000010 +00111110000001000000111010001000 +00000011110100100000000000110000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11001001000000000011001001010000 +00001100100100001010001111100100 +01100000110010011000001000111110 +01101000000011000001000000010011 +00100100000000101100100111000000 +00101110011000000000111010010000 +00000011000000100000010000110000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10001001000000001010001001100000 +00001010100100000000001011100101 +00100000100010010000000100101100 +01100000001010001001000000100010 +10100101000001001101100110000001 +00101110010000000010100000010000 +00000011011000000000000000010000 +00000000000000000000000000000000 +00011000000001010010010000000010 +10001001000000000010001001000000 +00001000100100000000001011100100 +00000010100010010001000000101110 +01000000000010001001000000000010 +00100100010000011000100100000000 +00101100010001010000101010010000 +00000010000001100000000001000000 +00000000000000000000000000000000 +00001000000001000000010010000000 +10000001001000000010000001001000 +01001010000100000000001011100100 +00000000100000010000000001101100 +01000000000010000001001000000010 +10000100100000001001000110100100 +00101100011000000000100010110010 +00000010010000100000000100000000 +00000000000000000000000000000000 +10111000000011010110000101000000 +11001000000000000011001000000000 +00001000100001010100001111100000 +00000000110010000000000000101110 +00000000000011001000010100000011 +00101000000000101100100001010000 +00111110000101000100111010000101 +00000011001011100000001101010000 +00000000000000000000000000000000 +10011000000111011111010001000000 +11111001001110000011111001000100 +01001111110100000111001111110100 +00010000111111010000000000001101 +01000000010011111101000100100010 +11010100010000001111100100010000 +00111111010000000000111111010001 +00000011111001100000011001110000 +00000000000000000000000000000000 +00011000000001011110010000000000 +11101001000000000011001101000010 +00001111100100000000001111110100 +00000000111110010000010000110010 +01000000000011111101001000100011 +00110100000001001100110101100000 +10100011010100000000110011010010 +00000011000001100000000001110000 +00000000000000000000000000000000 +00111000000100001110100111000000 +10001000011010000010001000010000 +00001011100000000000001011100000 +00000000101110000000000010100010 +00000000000010111010010000000011 +01100001000001001000100001000000 +00110110000000001000111110000010 +10000010100011100000010000110000 +00000000000000000000000000000000 +00001000000001011100010000100000 +10100001010000001010000001000000 +00001011000100101001011011000100 +00010000101110010000000000100000 +01000000000010100001001111000010 +00000101000000101000000100010001 +00100010010010010000100000010100 +00001010010000100000000101110000 +00000000000000000000000000000000 +00011000000101011010010000000100 +10001001000000000010001001000000 +00001011100100000010010011100100 +00000000101110110000100000100010 +01000000010110111001000000000010 +01101100000000101000101100000000 +00100110110000000000101110010000 +00000010110001100000010001100000 +00000000000000000000000000000000 +10100000000100011110011101000000 +11101001000000000011001001000000 +00001111100110000000001111100110 +00110000111100011101000000110010 +01000010000011101001100100010011 +00100100100000001100100100000000 +00110000011000000000110010010010 +00001011011010000000010001110000 +00000000000000000000000000000000 +00101000000000011010010000000000 +01110001000000000011111001000000 +00001111100110010000001111100100 +10001000111110111000000000111110 +11110001000011110001100001000011 +11000111000000001111100100000000 +00111110011010000000111110010000 +00000011100010100000000001100000 +00000000000000000000000000000000 +00101000000100001000000100000010 +11001000000000000011001000000001 +01001111100000000000001111100000 +00010000111110000100000000111110 +00010000000011111000010000000011 +00100001000000001100100000000000 +00110010000000100000110010000100 +00000011000010100000010000100000 +00000000000000000000000000000000 +00101000000001010010100000000000 +10001010000000000010001010100000 +00001011101000000000001111111010 +00100000101110100100010000101110 +10001000100010111010000000000010 +00111001000000101101111010000000 +00111011100000000000100011101001 +10000010100010100000000001000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10000011000000000010000011000000 +00001011001100000000001011001111 +10000000101100110010000001101100 +00100000000010110011100000100010 +00001100100000001000101100100000 +00100000111000000000100010110100 +00000010000010100000000001010000 +00000000000000000000000000000000 +10100000000000010001110010010101 +10000111001000000010000111010000 +00001011011100000000001010011100 +00000000101101000000010000101101 +10000000000110110111010000010010 +00010000000000001001001101000000 +00101101010000100000100001110000 +00000010001010000000000001000000 +00000000000000000000000000000000 +10101000000010000000111001000000 +11001111111100000011000111100000 +00001011011110000000001011011010 +00000000111101011001000000111101 +10100100000011111111100000001011 +00010110000000001100010110000000 +00110001111000000010110000111000 +00001011001010100000001000000000 +00000000000000000000000000000000 +00001000000111011010110110000000 +11111011000000001011111011000000 +00001111101100010000001111101100 +00000100111110000100000000111110 +10001000000011111011010000000010 +11000000000001001011100100000000 +00111000010000000000111110100000 +00000011110000100000011001100000 +00000000000000000000000000000000 +00000000000001011111111000100000 +11001111100000000011101111100000 +00001100011110010000001110111110 +01000000111011101001000000111011 +00100000010011001101110000100011 +01111010000000001100111110010000 +00110001101000000000110011111000 +00000011000000000000000001110000 +00000000000000000000000000000000 +10101000000100011001110001000000 +11010111000000000010000111000000 +00001101011100000001001000011100 +01000000100001000001110000100001 +00000001000010000101000000000010 +00010000000000101000010000110000 +00110101000010100000101011110000 +00000010101010100000010001100000 +00000000000000000000000000000000 +00000000000000001000110000000000 +10000111000000000010100101000000 +00001000111100000000011010111100 +00000001101001000000000000101101 +00000000000010000101100010000010 +00010001010000101000001100000001 +00100001010000000000100001110000 +00000010000000000000000000100000 +00000000000000000000000000000000 +00100000000101001100110100100000 +10010011000000000110000001000000 +00001001001101000000001000001110 +00000000100000001100110000100100 +00011000000010000001101000100010 +00000000010000101000100000000000 +00100100000000000000101000100100 +00000010100010000000010000110000 +00000000000000000000000000000000 +10101000000101011011110000000000 +11001111000000000011100011000000 +00001100111100011000001110101101 +00100000111010000100000000111110 +10000000000010001001100000001011 +00000001000000001100101100000000 +00110010110000000000110010110100 +00001011001010100000010001100000 +00000000000000000000000000000000 +10000000000000001100110001000010 +11111011000000000011111001000000 +00001111101100000000001111101100 +10000000111110000000000000111010 +10000100001011111001000000000011 +11100000000000001111101101000000 +00111110010000000000111110110010 +00000011111000000000000000110000 +00000000000000000000000000000000 +00000001000100001111110000000000 +11001111000000000011111011100000 +00001101111100000000001100110000 +00000000011111001000000000111111 +10000000000011001101000100000010 +00110100000000001000110000000010 +00110011011010000010111011110000 +00000011100000000100010000110000 +00000000000000000000000000000000 +10000001000001000110110000000000 +10101011000000000010111001100000 +00001000001100000000001010100110 +00000000101110000100000000101100 +10000000000010001001000000000010 +00100010000000001000100011000000 +10100010010000000100101010101101 +10000010001000000100000000010000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10001011000000000010111011001000 +00001001101100000000001000101110 +00000000101110000001010000101110 +00001000000010100011000000000010 +10100010000000001010100110000100 +00100000110000001000101000000000 +00000010101000000000000001000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10100011000000000010110001000000 +00001000101100000000001010000100 +00010000101100000000000001101100 +00000000000010100011000000001010 +10100000000000001010000000000010 +00100000010000000000100000000000 +00000010000000100000000100000000 +00000000000000000000000000000000 +00000000000011010111110000000000 +11000111000000100011111001000000 +00001101101100000000001100100100 +00000000111110000000000000111110 +00000000000011100111000000100011 +10100000000000001110100000000000 +00010010010000000000111010000000 +00000011100000000000001101010000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11111111000000000011111101000000 +00001111111100000100001111010100 +00000000111101000000000000111101 +00000000000011011111000000000001 +01010000000001100101110000000000 +00111111010000001000111111000000 +00000011111010000000011001110000 +00000000000000000000000000000000 +11000000000001011111101000000000 +11111111001000000011001101000100 +00001100111010000001001111111010 +00000000111111101000000000111111 +11000100000011111100000000000011 +00111000000000001100110000000000 +00110011000000000000110011100000 +00000011001100000000000001110000 +00000000000000000000000000000000 +10000000000100001110101000000000 +10111111110100000010001101000000 +00001000100010000000001011101010 +00000000101110101000000000001111 +11011000000010111010100001000010 +00101110000010001000101010000010 +00100010101000000000100010101000 +00000010101000000000010000110000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10110011000000000010000001001000 +00001010001100000000001011000000 +00000000101100100000000000101100 +11000100000010110001000000001010 +00000000000000001000000000000000 +00100000010000000000100000110000 +00000010001000100000000101110000 +00000000000000000000000000000000 +11000000000101011010100000010000 +10111011000000000010001001000000 +00101010100000000000011011100000 +00000000101110100000000000101110 +11000000010010111011000000010010 +00101110001000001000101100000000 +00100010110010000000100010110000 +00000010101100000000010001100000 +00000000000000000000000000000000 +01000000000100011110100000000000 +11111011000000000011001001000000 +00001110100001011000001111101001 +00000100111110110100100000111110 +11000000000011111000000000000011 +00101001000000101100100100000000 +00110010000100100100110010001001 +10000011000100000000010001110000 +00000000000000000000000000000000 +11100000000000011011110001000000 +10111111000000100011111001100100 +00001101110010000000001111111010 +01001000111111111001000000111111 +11000000000011111110000000000011 +11101000000000001111011100000000 +10111101101000000000111100000000 +00000011111110000000000001100000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11110011000000000011111111000000 +00101100100100110000001111100101 +00100000111110110100001000111110 +11000000000011100011010000100011 +10000001000000101100101100000000 +00110010010000000000110010010101 +00000011000100000000010000100000 +00000000000000000000000000000000 +11001000000001010010111001000000 +10111111000001100010111011000000 +00000000100000000000001111101110 +10000000101110110001100000101111 +11000000000010001011000000000010 +00101000000000001000101100000010 +00110110110010001000100010010000 +00010010001100100000000001000000 +00000000000000000000000000000000 +11100000000001010100001100000000 +00110011000000000010111001000000 +00001000001011000000001011000101 +00000000101100101100000000101100 +11000000010010100000000001001010 +01000000000000001000000000000000 +10100000000000000000100000101010 +00000010001110000000000001010000 +00000000000000000000000000000000 +00100000000000010001001000100001 +10110111100000000010110101100000 +00001000010110000000001010010110 +00000000101101111000010000101101 +11100000100010000011101100000010 +01010110000000001000001010000000 +00100100111000000000100001101000 +00000010000010000000000001000000 +00000000000000000000000000000000 +01001000000010000000010000000000 +11110011000000000011110001000000 +00001100001100000000001011001000 +00000000111100100000000000111110 +11000000000011100001011000000011 +11000000100000001100000000000000 +00110000010000000000110000110000 +00001011000100100000001000000000 +00000000000000000000000000000000 +01000000000111011011000000100000 +11111111010000000011111101000000 +10001111110100001001011111111000 +00001000111111110000000000111111 +11010000010011111111001000010011 +10110100000000000111111100000000 +00111111110000000000111111110000 +00000011110100000000011001100000 +00000000000000000000000000000000 +10101000000001011110100100100000 +11011011101100000011001101001000 +00001111101001100000001111100101 +10001000111110000110000000111110 +11001000000011111000000000000011 +00111010000000001110100100000000 +00110010101000000000110010010000 +00000011001010100000000001110000 +00000000000000000000000000000000 +01001000000100011001110010000000 +10110111001000001010000101000100 +00001011011100001000001011010101 +10100000101101010010101000101101 +11010000000010110011000000000010 +00001100000000001000011100000010 +00100001110000000000100001110000 +00000010000100100000010001100000 +00000000000000000000000000000000 +11000000000000001001111000000000 +10010011100000000010000101100000 +00001011011110000000001011011110 +00000000101101001001000000101101 +11100000000010110111100000001110 +00010010000000001010001110000000 +00100000111000000000100000011000 +00000010001100000000000000100000 +00000000000000000000000000000000 +01001000000101001100110101100000 +10110011000000000010000001100000 +01011011001100000000001011001100 +00000000101100010010000000101100 +11000000000010110011000000000010 +00001101000000001000001101110000 +10100000111000000010100000111001 +01001010000100100000010000110000 +00000000000000000000000000000000 +11101000000101011010101000001000 +11011010000000000011001010101000 +00001111101000100000001111101000 +10000000111110100000100000111110 +10000000000011111110100000000011 +00111000110000101110011011000000 +00110011101010000000110011100100 +00000011001110100000010001100000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011111000000000 +00001111100001000000001111100010 +00000000111110000000000000111110 +00000000010011110000000100000011 +11100000000000001111100000000000 +00111110000000000000111100000000 +10000011110100100000000000110000 +00000000000000000000000000000000 +00001000000100001110011010000000 +11111001000000000011111001000000 +00001111100100000000001011100100 +00000000111110011000000000111110 +01000000000011101001000000100011 +00100100000000001111100100000000 +00110010010000000000111110010000 +00000001000000100000010000110000 +00000000000000000000000000000000 +10000000000000000110111000000000 +10111001000000100010111001000000 +00001011101100001000011111101100 +00000000101110111000000000101110 +01000000000010001001100000000010 +00100100000000001011100101000010 +00110010010100000100101110010100 +00000010001000000000000000010000 +00000000000000000000000000000000 +00011000000001010010010000000001 +10111001000000000010111001000000 +00001011100100000100001011101100 +00000000101110010010000000101100 +01000000000010101001000100000010 +00100100000011001011100100001100 +00100010010000100000101110010000 +10000010100001100000000001000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001001010010010110001001000 +00001011000100000000001010000100 +00000000101100010000000000101100 +01001010000110000001001000000010 +00000100100000001011000100100000 +00100000010010000000101100010010 +00000010100000100000000100000000 +00000000000000000000000000000000 +10111000000011010110000000000100 +11111000001000100011111000000000 +00001111100000000000001011100000 +00000000111110000000000000111110 +00001000000011101000000000000011 +00100000000000001111100000000000 +10110010000000000000111110000000 +00001011101011100000001101010000 +00000000000000000000000000000000 +10011000000111011110010000000000 +11111001000000000011111101001110 +00001111100100000000001111100100 +00000000111110010000000000111110 +01001010010011111101000100001011 +11110100010000001111110100010000 +00111011010001000000111111010001 +00000011011001100000011001110000 +00000000000000000000000000000000 +00011000000001011110010000000000 +11111001000010000011011001000100 +00001111100100000101001111100100 +00000001111110010000001000111110 +01011000000011111001001000000011 +00100100000000001100100100000000 +10110010010010000000110010010010 +00000011110001100000000001110000 +00000000000000000000000000000000 +00111000000100001110000000000000 +10111000010000000010001000010100 +00001011100000000000001001101000 +00000000101110000000000000101110 +00001000000010111000000000000010 +00100001010000001000100001010000 +00100010000100000000100011000101 +00000010110011100000010000110000 +00000000000000000000000000000000 +00001000000001011100010000000000 +10110001000000000010010001001000 +00001011000110000000001011000100 +00001000101100010000000000101100 +01011000000010110101110000000110 +00010100000000001000010110000000 +00100001011001000000100001011000 +00000010110000100000000101110000 +00000000000000000000000000000000 +00011000000101011010010000100100 +10111001000000000010001001000000 +00001011100100000000001001100100 +01000000101110010000000000101110 +01000000010010111001000100010010 +00110100000100001000110110000000 +00100011010000010001100011010000 +00000010110001100000010001100000 +00000000000000000000000000000000 +10100000000101011110010100001000 +11110001000000000011011001000100 +00001111100100000000001111100100 +00000000101110010000000000111110 +01000000000011111001110000000011 +00100110000000001100100100000000 +00110010010100000010110010010100 +00000011111010000000010001110000 +00000000000000000000000000000000 +00101000000000011010010000000000 +11111011000010000011111001000000 +00001111100100000000001111100110 +00000000111110010000001000111110 +01000000000011110001000000001011 +11000111000000101111000100000000 +00111110010000000000111110010000 +00000011110010100000000001100000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000000000111111000000000 +00001111100000000000001111100001 +00000000111110000000000000111110 +00000000000011001000001000001011 +00100010000000101100100000000000 +00110000000000000000111111000000 +00000011000010100000010000100000 +00000000000000000000000000000000 +00101000000001010010100000010000 +10111010100010000110111010000000 +00001011101011100001000011101010 +00100000101110101000000000101110 +10000000100010101010010000010011 +00101000000000001000101000000000 +00100010100000000000101110100000 +00000010000010100000000001000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110001000000000010110011000000 +00001011001101001000001011001100 +00000000101100110100100000101100 +11000000000010000011000000000010 +01001100000100001000001110000000 +00100000110000000000101100101000 +00000010000010100000000001010000 +00000000000000000000000000000000 +10100000000000010001110000000100 +10110101000000000010110111001000 +00001011010100000000001011011100 +00001000101101110000100000101100 +11101100000010100011000000001010 +00011100000000001000011101000000 +00100001010000000000101101101100 +00000010001010000000000001000000 +00000000000000000000000000000000 +10101000000010000001011000100000 +11110101100000000010110111110100 +00001111011110001000001111011110 +01000000111101111000100000111101 +11101010000011000101100000000011 +01001110000000001100001010000000 +10110001101000000000111100111000 +00001011001010100000001000000000 +00000000000000000000000000000000 +00001000000111011010010110000000 +01111001011010000011111011000000 +00001111100101100000001111101101 +10000000111110010000000000111110 +11000000000011111001000000000011 +11101100000000001111101000000000 +00111110000000000000111110110000 +00000011110000100000011001100000 +00000000000000000000000000000000 +00000000000001011111111000000000 +11001110100000000011111111100000 +00001100111110000000001100111110 +00000000110011001000000100110011 +11100001000011001110100000000011 +00111010000000001100110110000000 +00111111111000000000111111001000 +00000011000000000000000001110000 +00000000000000000000000000000000 +10101000000100011001110001010000 +11010110000000000010110111000001 +00001000010000000000001101010100 +00000000110101110000000000110101 +11000000000011010110000100000010 +00011000011010001101010100000010 +00101101010001000000101101000000 +00000010101010100000010001100000 +00000000000000000000000000000000 +00000000000000001011010000000000 +10000110000000000010110111000000 +00001000111100000000001000111100 +00000000100111000000000000100100 +11000000000010000100000000001010 +00011000000000001000010000000000 +00101101100000000000101100011000 +00000010000000000000000000100000 +00000000000000000000000000000000 +00100000000101001100010110000100 +10010010000000000010110011000000 +00001000000011000000001001000110 +00000000100100010100010000100100 +11000000000010010000011000001010 +00001001000000001001000001000000 +00101100000100000000101100010001 +00000010100010000000010000110000 +00000000000000000000000000000000 +10101000000101011010100000000000 +11001001000000000011111111000000 +00001100101000100000001100100010 +00000000110110110000000000110111 +11000000000011001011100000000011 +00000111000000001100101110000000 +00111110111000000000111110100000 +00000011001010100000010001100000 +00000000000000000000000000000000 +10000000000000001110010000000000 +11111001000000000011110011000000 +01001111101000000000001111101100 +01000000111110110010000000111110 +11000000000011111011100000001011 +11100100000000001110101110000001 +00111110011000000000111110100000 +00010011111000000000000000110000 +00000000000000000000000000000000 +00000001000100001111100000000000 +11111101000000000011101111000000 +00001101111100001000001111110001 +00000000111111110000000000111111 +11000000000011110001000000000011 +01110100001000001100111000001000 +00111111100000100000111111110000 +00000011110000000100010000110000 +00000000000000000000000000000000 +10000001000001000110011001100100 +10111001100101000010111011000000 +00001010101100000000001011101110 +00100000101110010000000000101110 +11000000000010111001000000000010 +00100100000100001000101000000000 +00101110000000001000101110110000 +00000010111000000100000000010000 +00000000000000000000000000000000 +10000000000001010010100000000000 +10111000000000000010111011000000 +00001001100100100000001011100000 +00000001101110000000000000101110 +11000000000010111010000000000010 +01100010000000001000100100000000 +00101110110000000001101110000000 +00000010111000000000000001000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110000000000000010110011000000 +00001010000010000000001011000100 +00010000101100110000000000101100 +11000000000010110010000000000010 +00000000000000001000000100000000 +00101100010000000000101100000000 +00000010110000100000000100000000 +00000000000000000000000000000000 +00000000000011010110100000010000 +11111000000000000011100111000000 +00001101100100000000001111100000 +00000000111110000000000000111111 +11000000000011111000000000000011 +01100000000100001100100000000000 +00111110100000000000111110010000 +01000011110000000000001101010000 +00000000000000000000000000000000 +10100000000111011101010000000000 +11111100000000010011111111000001 +00001111010000000000001111010100 +00000000111101010000000000111111 +11000001000011111100000000000011 +11010000000000001011110000000000 +00111111000000000000111111010000 +00000011111010000000011001110000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11111111110010000011001111011000 +10000100110010000000001100110010 +00000000101111110000000000110011 +00001000000011101100100000000000 +01110000000000001100010010000000 +00111111001000000000111111011000 +00100011001100000000000001110000 +00000000000000000000000000000000 +10000000000000001110110000000000 +10111111010000000010001111000100 +00001010100110000000001000000000 +00001000101111110000000000100010 +10110000000010001000000000010010 +00100000000000001010100010000000 +00101100000000000000101100010010 +00000010001000000000011000110000 +00000000000000000000000000000000 +10001000000001011000110000000000 +10110011001000000010000011001000 +00001010100100000100101000000000 +00000000101100110000000000100000 +10010000100010100000000000000010 +11001000000100001000000100000010 +01101100000000000000101100100000 +10000010001000100000000101110000 +00000000000000000000000000000000 +11000000000101011110110000000000 +10111011000000000010001011000000 +00111010100110000000001000101010 +00100000101110110000000110100010 +10100010010010001000100010000010 +10101010001100001010100100000000 +00001110000000001000101110100000 +00000010001100000000000001100000 +00000000000000000000000000000000 +00000000000001011110110000000001 +11111011000000001011000011000000 +01001100000010100000001100100010 +00000001111110110000000000110000 +10000000000011101000110001000011 +11100000000000001100100000000000 +00111110001000000000101110010000 +00001011000000000000010001110000 +00000000000000000000000000000000 +11100000000100011011110000000000 +11111111000000000011111011000000 +00001101110100000000001111111000 +00000000111101110000010000111111 +10000000000011111100000000000011 +01110000000000001111110000000000 +00111111000100010000111111010000 +00000011111110000000000001100000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011000000000011111011000000 +01001100100100011000001110100001 +00000000110010110000001000111110 +10010000010011001000010010001011 +00111000010100001110100100000000 +00111010000000100000111010100010 +00001011000100000000010000100000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10111111000001000010111111001000 +10100000100111000000001000101000 +00000000101011110000000000101110 +10100000000010001000110000100011 +01101000000000001000100100000000 +00100010000010010000100010101100 +00000010001100100000000001000000 +00000000000000000000000000000000 +11000000000001000000110000000000 +10111011000000100010110011000000 +10001001001001000000001010001000 +00000000100000110000000000101100 +10001000001010001000110000001010 +00100110100000001010000010010100 +00101100110000000000101010011000 +00000010011100000000000000010000 +00000000000000000000000000000000 +00100000000000010001111000000000 +10110111100000000010110111100100 +10001001111110000001001000011010 +00000001101001111010000000101101 +11100101000010001100100000100010 +01011110000000101000010010010000 +00101101111001000000100001011000 +00000010010110000000010000010000 +00000000000000000000000000000000 +01001000010110000000110000001000 +11110011000000100010110011000100 +00001101001100000000001110001000 +00000000110000110001000000111100 +10000110000011000000001010010011 +00101100100000101110000100000000 +00111100110101000000111000100000 +10000011010100100000001000010000 +00000000000000000000000000000000 +01000000000011011011110000000000 +11111111000000010011111111010100 +00001110011100000000001111111000 +00000000111111110111100000001101 +11000100000011110111000000000011 +11111000000000001111110100000001 +00110011110001000000111111101000 +00000011100100000000010001100000 +00000000000000000000000000000000 +00001000000001011110110000000000 +11111011001000000011111011010000 +00101100001010000000001100101010 +00000000110010110100000010110000 +10011010000010011000000000000011 +01100100000100001100000010000000 +00110110110000000000110010010000 +00001011000000100000000001110000 +00000000000000000000000000000000 +01001000000000011001110000000000 +10110111010010000010110111001000 +00101000010100000000001010111100 +00000000110100110010000000100001 +11000000000010001100000000000010 +00011100000000001000010000000000 +00100011110000000000110001010000 +00000010000100100000011001100000 +00000000000000000000000000000000 +00100000000000001001111000000000 +10110111101000000010110111100100 +00011000111011000000001000011010 +00000000100001111000000000100001 +10100010000010010100100000010010 +01111110000010001000010110000000 +00100101111000000001100011101000 +00000010000010000000000000100000 +00000000000000000000000000000000 +01101000000101001100110000000100 +10110011000000000010110011000000 +00001000001101001000001010001111 +00000000100110110000000000100000 +11100000010010000011000000000010 +01001100000000001000000100000000 +00100000110000000000100010100000 +00000010000110100000000000110000 +00000000000000000000000000000000 +11101000000001001010100000000000 +11111010000000000011110010000000 +00101100111011000000001100111010 +11000000110010100000000000110000 +10000000101011010110000000001011 +01111001000000101100101000000000 +00110100100000000010110010100000 +00000011001110100000010001110000 +00000000000000000000000000000000 +01001000000100001010000000000000 +11111000000000000011111000010000 +01101111100001000000001111100000 +00010000111110000000000000111110 +00000001001011111000000000010011 +10000000100001001111100000000000 +00111110000000001000111011000000 +00000011110100100000000001100000 +00000000000000000000000000000000 +00001000000100001010010000000000 +11111001000000000011111001100000 +00001100100100000000001111100100 +00000000111110010000000100110010 +11000000000011001001100000001011 +00100100000000101100100111000000 +00111110010000000000110010010000 +00000011000000100000010000100000 +00000000000000000000000000000000 +10000000000001000010010000001000 +10111001000000000010111001010000 +00101010100111100010001011100100 +00000000101110010000000000101010 +01000001000010001001100100001010 +00100110000010001010100110000000 +00101110010110000000100010010000 +00000010101000000000000000010000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010111001001000 +00001000100100100000001011100100 +00000000101010010000000100101010 +01000000000010001001000000000010 +00100100100000001000100100000000 +00101111010000000010100011010000 +00000010000011100000000001000000 +00000000000000000000000000000000 +00001000000001001000010000000000 +10110001001000000010110001001000 +00001010000100000000001011000100 +00000000001100010010001000101000 +01101001001010001001000000001110 +00000100100000001000000100000000 +00101111010000000000100001010000 +00001010100010100000010100000000 +00000000000000000000000000000000 +10111000000111010110000101000000 +11111000010100000011110010010100 +00001100100000000100001111100001 +01000000111010000101000000110010 +00000000000011001000010101000011 +00100001010010001100100000000100 +00111110000101000000110011000101 +00000011001011100000001101010000 +00000000000000000000000000000000 +10111000000111011110010000000000 +10111001000100100011111001000100 +00001111110100000000001111110100 +00000100111110010001000000111110 +01000100000011111101000000010011 +11010100010000001111110100000000 +00111110010000000000111100010000 +00000011011001100000010001110000 +00000000000000000000000000000000 +00111000000001011110010000000000 +11111001000000000011001101000110 +00001100110100000000101100100100 +00000000110010010110000000111011 +01000010000011001101010000000001 +11110100010000001100110100000000 +00110001010100000000110011010000 +00000011001001100000000101110000 +00000000000000000000000000000000 +00011000000100001110000010000000 +10111000001000100010000000010000 +10001000100000000000001000100000 +10001000100010000100010000110110 +00010000000011111000001000001010 +00101000000000101000100000000000 +00100010000010000000111100000010 +10001010000011100000011000110000 +00000000000000000000000000000000 +01001000000000001000010000101000 +10110001010010000010000001001000 +00101000100110000000001000100100 +00100000100000010011000100100000 +01000000000010001001001000000110 +11000101100000001000100110000100 +00100000010000000100100100010000 +00001010100100100000000101100000 +00000000000000000000000000000000 +00011000010101001010010000010000 +10110001000000000010001001000000 +00001000101100000000001000100100 +00000010100000010000001000100110 +01000000000010111001000100001110 +00100100000001101000100100000000 +10100010010000000000001010010000 +00000010100001100000000000100000 +00000000000000000000000000000000 +10100000000001001010010000000000 +11111001000000001011001001000000 +00001100100110010000001100000100 +01000000110010010000000000111010 +01000000000011001001000011000011 +11100111000000001100000100000000 +00110010010000000010100110010110 +00000011101010000000010001110000 +00000000000000000000000000000000 +01101000000100001010010000000000 +11111001000000000011111001000000 +10001111100110000001001111100110 +00000000111110010000010000111110 +01001000000011111001100000001011 +11100100010000001111100100000000 +00111110010000000100111110010001 +00000011010100100000000001100000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11001000000000000011111000000001 +00001100100000000000001111100000 +00000000111010000000000000111100 +00000010000111001000000000000011 +00100011000000001100100000000001 +00111110000000001000110010000100 +00000011000000100000010000100000 +00000000000000000000000000000000 +00001000000001000010100000000000 +10001010000000000010110110000000 +00101000011010000001001011101000 +00000000101110100000000000101111 +10110000000010100110100000000010 +00111000000000001000111000000000 +00101111101000000000100011100000 +00000000000010100000000001000000 +00000000000000000000000000000000 +00001000000001010100110000000000 +10000011000000000010110010100000 +00001010001110100010001011001100 +00000000101000110000000000101100 +11010000000010000011100110000110 +00101110000000001010001100010000 +00101110110001000001101010110000 +01000010000010100000000001010000 +00000000000000000000000000000000 +00100000000100010001111011000000 +10000111001000000010110110010000 +00101010011100001000001011011100 +10000000101101110010010000101101 +10010000000010101111000000000010 +00011001000100001000011100000000 +00101111010000000000101001110000 +00000010001000000000010001000000 +00000000000000000000000000000000 +00101000000010001011111000000010 +11000111101100000011110110100000 +00101110011110000000001111011111 +00000000111001111011000000111100 +11100000010010000111100000001011 +00000110000000101110011110000000 +00111101111000000000111001111000 +00001011001000100000001000000000 +00000000000000000000000000000000 +00001000000101011010110110100000 +11111011000000000011111010000000 +00001101101100000000000111101100 +00101000111110110000000000111110 +10000000000011110011000000000001 +10101000000001001111101100000000 +00111110000000000010110110110000 +00000011110000100000010001100000 +00000000000000000000000000000000 +01100000000001001011111000000000 +11111111100010000011101110100000 +01001100011110000010001100111110 +00000001111111111001100000111001 +11100000010011000101100000000011 +00111010000000001100011110010000 +00110011011000000000111111111000 +00000011000100000000000000100000 +00000000000000000000000000000000 +10101000000100001001110000000000 +10110111000000100010000110000000 +00001000010100000000101000011100 +00000000111101110001000000111101 +00000010000010000100000000001010 +00111000010000001000011100000000 +00100001010001000000101101110000 +10000010001010100000011000100000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110011000000000010110110000000 +00001001111101000000001000011100 +00100000101101110000000000101101 +11000000001010001101000100000010 +00010001001000001000111100000000 +00100101010000000000101101110000 +00000010000001000000000000100000 +00000000000000000000000000000000 +01000000000101001000110000010000 +10110011000000000010010010000000 +00000001000100000000001000001111 +00000000101100110000000100101100 +00110000000010000000010101000010 +00101010000000001000001100000000 +00000100000000000000101100111100 +00000010000110000000000000100000 +00000000000000000000000000000000 +10101000000001011011110000000000 +10111111000000000011111000000000 +00001101001110000000001100111111 +00000000111111110000000000111000 +11110000000011001001110000000011 +00101110000000101100100100000000 +00110110110000000100111110110100 +00000011001010100000010001100000 +00000000000000000000000000000000 +10100000000100001110110000000000 +11111011000000000011100000000000 +01001110101110000000001111101100 +10000000111010110000000000111010 +10000000000011111001000001000011 +11101000000000001111100100000000 +00111010110000000000111110000100 +00000011111001000000000000110000 +00000000000000000000000000000000 +00000001000100001111110000000010 +11000111000000000011001111100000 +00001100110100000000001100111100 +00001000101111110000000000111111 +11000010000011011101000010010011 +00110100000000001100110110000000 +00110011111100000000110011110000 +10000011001010000000010000110000 +00000000000000000000000000000000 +10000001000001000110110000001000 +10001011000000000010001011000000 +00101000100110000100101000101100 +00000000101110110000000000101110 +10111000000010100011100000000010 +00101010000001001000000110000100 +00100010101000001000100010001101 +00000010001011000100000000010000 +00000000000000000000000000000000 +10000000000001010000110000000000 +10001011000000000010001000010100 +00001000101110000000001000101100 +00000000101110110000000000101110 +01100000000010011001100000000010 +00100010000000001000100100100000 +11100000010000000000100000110100 +00100010001000000000000001000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10000011000000000010000010000000 +00001000000100000000001000001100 +00000000101100110000000000101100 +00000000000010001000000000001010 +00000000000001101000000100000000 +00100000010000000000100000000000 +00000010000000100000010100000000 +00000000000000000000000000000000 +00000000000011010111110000000000 +11001111000000001011000011000000 +00001100100100000000001100111100 +00000000111111110000000000111110 +01000000000011011001000000001011 +00100000000010001100100100000001 +00110010010000000010110000110000 +00000011001000000000001101010000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11111111000000000011111111000000 +10001111110000000000001111111100 +00000000111111110000000000111111 +01000000100011111100000000000011 +11110000000100001111111100000000 +00111111000000000000111111000000 +00000011111010000000000001110000 +00000000000000000000000000000000 +11000000000101011101111000000000 +11111110100000010011111110100000 +00001111111100110010001101111100 +11000000111111011000010000110001 +01100000000011001101000000000011 +00110000000001001101110010000000 +00110011101000000000110011110000 +00000011001100000000000001110000 +00000000000000000000000000000000 +11000000000010001110111000000000 +10001010100001000010111000100000 +00001011111100100000101000111100 +01000000101110010000000100100010 +00000000000010101000100000000010 +00100110000000001011100100000010 +00100010110000001100100010000000 +00001010001100000000010000110000 +00000000000000000000000000000000 +11001000000001011100110000000000 +10100011000000000010110010000000 +00001011001100010000001011001100 +00000000101100010010100010101010 +01000000000010000001000000000010 +00000000000010001001000000000000 +10100010110000000000100000110000 +00000010001100100000000101110000 +00000000000000000000000000000000 +11000000000001011010110000000100 +10101010000000000010111000010100 +00001011001100000000001010101100 +00000000101110010000000000100010 +11100000000010101000100000000010 +00101110001000000011000110001000 +00100010110000100000100000111100 +00000000001100000000010001100000 +00000000000000000000000000000000 +10000100000100011110110000000000 +11101010000000000011111010100000 +00001011101100000010001111101100 +00000000111110110000000000110000 +01101000000011001000101000001011 +00100110000000001101100110000000 +00110010110001000000110010111000 +00000001000000000000010001110000 +00000000000000000000000000000000 +11100000000000011011110001000000 +11011110000010000011111100000001 +00001111111100000100101001111100 +00000000111111110000000000011111 +11000000000011110000000000100011 +11100100000000001111111100000010 +00111111110000000000111111000000 +00000000111110000000000001100000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11011011000000000011111011010110 +00001110101100000000001100101100 +00000000111110010000000000111110 +01010000000011001011000000000011 +00100100000000001100101101100000 +00111110110100000100110010111100 +00001011000100000000010000100000 +00000000000000000000000000000000 +11011000000001010000111000000000 +00001010000010000010111001010000 +00001011111100000000001101111100 +00000000101110010000000000101110 +11000000000010101010100000010010 +00101110000100001000101101000000 +00101100111000000000100010111000 +01100010001101100000000001000000 +00000000000000000000000000000000 +11000000000001000000110000000000 +10010010110000000010110001010000 +00001011001100000000101010001100 +00000000101110010000000000100100 +01000000000010000001000000010010 +00001110000000000010000100000000 +00101100111000000000100000110000 +00000010101110100000000001010000 +00000000000000000000000000000000 +11110000000000000011011000000001 +10000111100000000010110101100000 +00001011011110010000001001011110 +00000000101101011000010001101111 +11100000000000100111110100000010 +00011110001000001010010110000000 +00101101111000000010100011111000 +00000000101111000000000001000000 +00000000000000000000000000000000 +01001000000110000000110010100010 +11010011000000000111110010000000 +10011111101100000000001110001100 +00000000111100010000000000111100 +01000100000011000001000010000011 +00000000010000001110000100000000 +00111110110000100100110000110000 +00001011100100100000001000000000 +00000000000000000000000000000000 +11000000100111001011110000000000 +11111111000000000011111110000010 +00001111111100000000001101111101 +01000000111111010000000000111111 +11000000000011111111000001001011 +11111100000000101101110100010000 +00111111110001000000111101110000 +00000011010100000000011001100000 +00000000000000000000000000000000 +00001000000001011110110000000000 +11011010010000000011111001010000 +00001111101101110000001100101101 +11000000111110110000000000111110 +01000000010011111001100000000011 +00101100000000001111101100000000 +00111100110000000000110010110000 +00000011001010100000000001110000 +00000000000000000000000000000000 +11001000100000011001110000000000 +10000111001010100010110101001010 +00001011111100110000001000011100 +00000000111001110000000000101101 +11000000000010110101000001000010 +00011100000000001011011100000000 +00101101110000000000100001110000 +00000010001100100000010001100000 +00000000000000000000000000000000 +00100001000000001011111000000000 +10010111100100000010110111100000 +00001011011110000000101000011110 +00000000101001011000000001101101 +01100000000010110011100000000010 +01010110000000001011011110000000 +00101111111000000000100001111000 +00001010001000000000000000100000 +00000000000000000000000000000000 +01101000000101001100110000001000 +10000011000000000010110011000000 +00001011001100000000001000001100 +00000000101000010000000000101100 +11100000000010110011110100000010 +01001101001000001011001111100000 +00101100010111000000100000110000 +00000010000100100000010000110000 +00000000000000000000000000000000 +11100000100001001010101010001000 +11011010000000000011111010010000 +00001011101000000000001100101000 +00000000111010100010000000111111 +10000010000011111110110100000011 +01111001000000001111111011000010 +00111111101100000010110011100000 +00000011001110100000010001100000 +00000000000000000000000000000000 +01001000000100001010000000000000 +11111000010000010011111000010010 +01001111000000000000001111100000 +00000000111010000000000000111110 +00000010100011111000000000001011 +10100001000001001111100000010001 +00111110000000000000111110000000 +00000011110100100000000000110000 +00000000000000000000000000000000 +00001000000100001010010000001010 +11001001000000000011111001000000 +00001111100100000000001100100100 +00010000111110010000000000110010 +01000000000011111001100000000011 +11100100000000001111100100000100 +00110010010000000000110000010000 +00000011000000100000010000110000 +00000000000000000000000000000000 +10000001010001000000010000000000 +10001011000000000010111011101000 +00000011100100000100001000100100 +00000000111100010000000000100010 +01000000000010111001100000000010 +11100111100010000011100100000110 +00100000010100001000110110011000 +11000010001000000000000000010000 +00000000000000000000000000000000 +00011000000000010010010000000000 +10001011000000000010111001000100 +00001011100100000000001000100100 +00010000101110010000000000100010 +01000000000010111001001000000110 +11100100010000000001000101100000 +10100010010110000100100010010001 +00000010000001100000000001000000 +00000000000000000000000000000000 +00001000000001000010010000010000 +10000011000000010110110001000000 +01001011000100101000001000000100 +10100000101110010000000000100000 +01000000000010110001101000000010 +11000100100000001011000100000000 +00100010010000000000100100010010 +00000010000000100000000100000000 +00000000000000000000000000000000 +10111000000111010110000000000000 +11001000000000000011111000000000 +01001111100000100000101100100000 +10000001101110000000000010110010 +00010100000011111000000000000011 +11100000000000001111100001010000 +00110010000101000000110000000101 +00001011001011100000001101010000 +00000000000000000000000000000000 +11111000100111011101010000000000 +11111001000000000011111001000000 +00011111100100101001101111100100 +10100000111011010010100000111111 +01000000000011111111000100000011 +11110100010010001111110100000000 +10111111010000000000111111010001 +00000011111001100000011001110000 +00000000000000000000000000000000 +10111001000011011111010000000000 +11111001000000000011111001000000 +01001111100100101000001101100100 +11000000111110010100000000111100 +01010000000011110101001000000011 +00110100000010001111110100010000 +00111110010000000000110010010010 +00000011001001100000000001110000 +00000000000000000000000000000000 +01011001000000000110000000000100 +11101000000000000010111000000000 +00001110100000100000001010100010 +01000000101110001000000000101110 +00001000000010111000000000010010 +00100001010000001011100000000000 +00101110000010100010100011000110 +10000011000011100000010000110000 +00000000000000000000000000000000 +01001000000000000000010000001000 +10110001100000000010110001000000 +10011011000100101000001011000100 +10000000101100010000000000101100 +01001000000010110001010001000010 +00001110000000001011000100100000 +00101101011000000000100001010001 +00000010010100100000000101110000 +00000000000000000000000000000000 +00011000000101001010010010010000 +10101001000000110010111001000000 +00000010000100000000001010100100 +00000000101110010000000000101110 +01010100000010111011100000010010 +00100100010000001011101100000000 +00101101011000000010100011010010 +00000010000001100000010001100000 +00000000000000000000000000000000 +10100000100001001010011000001000 +11111001000000000011111001111001 +00000111100100000000001111100100 +00000000111110011000000000111110 +01010000000011111001110000001011 +00100110000000001111100110000000 +00111110010000000000110010010010 +00000011011010000000010001110000 +00000000000000000000000000000000 +01101010000100001010011000000000 +11111001000000100011111001100100 +00001111100100000000101111100100 +00000000111110010010000000011110 +01100000000011110001000011000011 +11100110000000001111100101000000 +00111110010000000000111100010000 +00001011110110100000000001100000 +00000000000000000000000000000000 +01101010000100001010000000000000 +11111000000000000011111000010010 +01001111100000000000101110100000 +00011000110010000000000000111110 +00000001100011001000010000000011 +00100010000000001111100000000000 +00110010000000000000110010000100 +00000011000010100000010000100000 +00000000000000000000000000000000 +10000000000001000010101000000000 +10111010100000000010111010101000 +00001011101000000000001010101000 +00010010100010100000011000101110 +10000000011010001110101001000010 +00111000000001001011101000001000 +00100010100000100000100010100000 +00000010000010100000000001000000 +00000000000000000000000000000000 +01001000000001010100011001000000 +10110011100000000010110011000000 +00001011001100000000101010001100 +00000000100000110000000000101100 +11000000000010000010010000000010 +00000100000000001011000100000000 +00100000110000000010100000111000 +00001010000010100000000001010000 +00000000000000000000000000000000 +01100001000000010001110000000000 +10110110000010000010110111000000 +00011011011100000000001010011110 +00001000000001110000010000101111 +11101000000010000101000000001010 +00010100000000001011010010000000 +00100001110000000000100001110000 +10000010001010000000000001000000 +00000000000000000000000000000000 +00101000100000000001011000000000 +11110111100000000011110111100000 +00001111111110010000101110111110 +00000000010001111000010000111101 +11110000000011000101100000000011 +00010110000000001111010110000000 +00110011101000000000110011101000 +00001011001010100000001000000000 +00000000000000000000000000000000 +01001010000101011010110000000001 +10111011011010000011111000000010 +00001111101100000010101111101100 +00000000111110110000001000111110 +11000000000011111001000000010011 +11100100000001001111000000000000 +10111110100000000000111110100110 +00000011110000100000011001100000 +00000000000000000000000000000000 +11100010010001001011111000001101 +11111111100100000010111101100100 +00001101111110001000001110111110 +00010010100011111001000001111111 +11100000000011111110100000000011 +00010110010000001100110110000000 +00110001111000000100110011111100 +00001011010100000000000001110000 +00000000000000000000000000000000 +10101001000000001001110000001000 +11100100000000000010110111010000 +00001101011100010000001000011100 +10000000100001110001000101101101 +11001000000010110101000100000010 +00010100000010001000010000100000 +00100001110000000000101001110001 +00000011111010100000010001100000 +00000000000000000000000000000000 +00010010000000001001110001000000 +10100111000000100010111101000000 +10001000011100000000001011011100 +00000100100001110001010000101101 +11000010000010110101010000000010 +00010100000010001000110100001000 +01100011100100000000100001100000 +00000010000001000000000000100000 +00000000000000000000000000000000 +01000000000101001000110001000100 +10100001010000000010110000000000 +01001001001100000000001001001100 +00000000100000110000000000101110 +11110000000010110001100001000010 +00001101000000001000000011000000 +10100000100000000000101000101101 +00000010110110100000010000110000 +00000000000000000000000000000000 +11111000000000010010011000000000 +11101001000000000011111010000000 +00001100111100000000101111111100 +00000000100011110000000000111111 +11110100000011111010010010000011 +00100110000100001100100110000000 +00110000010000000000110010010100 +00000011001011100000010001100000 +00000000000000000000000000000000 +10100100000100001110110000000000 +11101001010001000011111010010100 +00001111101100000000001110001100 +00000000111110110000000000111110 +11000000000011111001000000001011 +11100110000000001111100101000000 +00111110011000000100111110010000 +00100011111000000000000000110000 +00000000000000000000000000000000 +11000001000100001111010000001100 +11001101010010000011001111000000 +00001111101100000000101100101100 +00000000110011110000000000111111 +11000000000010101111000000000011 +11010000001000001100110100011000 +00110011000100000000110010000100 +10000011001000000000010000110000 +00000000000000000000000000000000 +10000001010000000100110000010000 +10100001010000000010101000010000 +00001110101100000000001101101100 +00001000100010110000001000101110 +11000000000010001001110000000010 +11100001001000101000100000000001 +00100010000000000000100010000000 +00000010001000000000000000010000 +00000000000000000000000000000000 +10000000010001010110110000001001 +10011011010000000010101001000000 +01001011001100000000011000101100 +00000000100010110000000000101110 +11000000000010101011100000000010 +11100100000000001000001100000000 +00100010010000000100100000010000 +00000010001000000000000001000000 +00000000000000000000000000000000 +00001010000000000010110000000000 +10101001000000000010100011000000 +00001011001100000000101001001100 +00000000000000110000000000101100 +11000000000010100001000000000010 +11000100000000001000001100000000 +10100010110000000000100000110000 +00001010000000100000000100000000 +00000000000000000000000000000000 +10000000000110000110110000000001 +11011011000000100011101001000000 +00001111111100000000001100101100 +00000000110010110000010000111110 +11000000000011101001000000000011 +11100100000000001100100100000000 +00110010000000000010110010000000 +00000011001000000000001101010000 +00000000000000000000000000000000 +10100010000111011111110000000000 +11111101000000000011110100000000 +00001110111100000000001111111100 +00000000111111110000001000111111 +11000000000011010101000000000010 +11111100000000001101010000000000 +00111111000000000000111111000000 +00000011111010000000011001110000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11000100100000000011001100001000 +00001100011000000000001100111110 +00000000111111110100000000110011 +11000000010011110100100000000010 +00111100000000001100111100111000 +00110011011000000010110011101000 +00000011001100000000000001110000 +00000000000000000000000000000000 +10000000000100001110011000000010 +10001000100000000010001010110000 +01001000100001000001001000100110 +00000000101111110111000000101011 +11000000010010111000100000000010 +00111101010000001000111101000100 +00100010110000000000100010011000 +00010010101000000000010000110000 +00000000000000000000000000000000 +10001000000001011110110000000000 +10001010000000001010000010000100 +00001000001001000000001000001100 +00000000101100110000001000100000 +11000000000010110011000000001010 +00001100000000001000001100100000 +00100000010000000010100010010000 +00001010001000100000000101110000 +00000000000000000000000000000000 +11000000000101011010010000000000 +10001010000000000010001010100000 +00001000100100000000001000101100 +00010000101110110000000000101010 +11000000000010111001110000101010 +00101100000000001000001100000000 +00100010110000000000100010011000 +00000010101100000000010001100000 +00000000000000000000000000000000 +00000000000101011100110000000000 +10001000000000000011001001100000 +00101000101000001000001100101100 +00000000111110110000000000110010 +11000000010011111000110000001011 +00101100000000001100101100000000 +00110010010000001000110000001000 +00000010000000000000010001110000 +00000000000000000000000000000000 +11100000000000011011010001000000 +11111100010010000011111111000000 +00001111111000000000001111110100 +00000100111111110000001000111111 +11000000000011111100000000000011 +11111100000000001111101100000000 +00111111111100000000111111010000 +00000011111110000000000001100000 +00000000000000000000000000000000 +01000000000100001010110010000000 +11111010000000000011001010100000 +00001101101000100000001100101100 +00000000111110110000000000110010 +11000000000011111011100001000000 +00101100001000001100101100000000 +00110010010000100000110010010000 +01000001000100000000010000100000 +00000000000000000000000000000000 +11001000000001010010010100000000 +10110010000000000010000010000000 +00001000001011100000001000101101 +01000000101111110000000000100011 +11000000000010110000100000000010 +00111110000010001000111100000000 +10100010111100000010100010010010 +00000011011100100000000001000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10110001000000000010010000000001 +00001000001001000100001000001100 +00000000101110110000000000100000 +11000000000010110000000010000010 +00101101000000001000001110000000 +00100010111000000000100000000000 +01000010001110000000000001010000 +00000000000000000000000000000000 +00100000000000010001111000000000 +00110100100000000010011100110100 +01001000110010000000001000010110 +00000000101100111000000000100001 +11100000100010110100100100000010 +00011110001000011000011111001000 +00100001111001000010100001011100 +00000010010110000000000001000000 +00000000000000000000000000000000 +01001000010010000000110000000000 +11110001010000001011010000000100 +00001100001000000100001100001100 +00010000111100110001000010100000 +11000001100011110001000000000011 +00101100000000001100001100010011 +00110010110000110000110000010000 +00000011000100100000001000000000 +00000000000000000000000000000000 +01000000000111011011110000000000 +11111100000000000011100100000101 +00101110110000000000001111111100 +00000000111111110100001100111111 +11000000000011111101000000001011 +11111100001000001011111100000000 +00111111110000000010111101010000 +00000011110100000000011001100000 +00000000000000000000000000000000 +10101000000001011110110111000000 +11111001000000000011110001000000 +00001100101000000000101100101100 +11100000111110110000000000110110 +11110010000011100000000000000000 +10101100100001101100101100101000 +00111110110000000010110010000000 +00000011111010100000000001110000 +00000000000000000000000000000000 +01001000000100011001110010100000 +10110100000000100010110111000000 +01001000011000000000001000010100 +10000000101101110110000000100111 +11010000000010000101000000000010 +00011100001000001000011101000000 +00101111110000000000101001010000 +00010010110100100000010001100000 +00000000000000000000000000000000 +11000000000000001001111010000000 +10110100100000000010111110100000 +00001000011010000000001000011110 +10000000100001111010010001101101 +11100000010010101101100000000110 +10011110100010001000011110000000 +00101101111000000000100101011000 +00000010111100000000000000100000 +00000000000000000000000000000000 +01001000000101001100110000001000 +10110000010010000010110010001000 +00000000001011001000001000001100 +00000000101100110000000001101100 +11000000000010000001000000000010 +00001100000000000000001100000000 +00101110110000000000101100010000 +00000010110100100000010000110000 +00000000000000000000000000000000 +11101000000101011010100000001100 +11111110000000100011111110010000 +00100000111011100000000100101000 +00000000110010100000000000111110 +10000000000011101110010000000011 +10101000000000000100101000000001 +00111110100000000000110111100000 +00000011111110100000010001100000 +00000000000000000000000000000000 +01001000010000001110000100000000 +11111000010001000011110000010100 +01001111000000000000001111100000 +00000000111110000000000000110110 +00000000000011111000001000000011 +11100000000001001111100000000000 +00111110000000000010111010000000 +00000011110100100000000000110000 +00000000000000000000000000000000 +00001000000100001110010001000000 +11111001000000000011111001000000 +00001100100100000000101100100100 +10000000111110010000000000111110 +01000000000011111001100000000010 +01100110100000000100100100000000 +00100010011000000000100010010000 +00000011110000100000010000110000 +00000000000000000000000000000000 +10000000000001000110110100100000 +10111001010010110010111001010000 +00001000100101000000101000101110 +00000000101110010000000000101110 +01000000010010110001010000000010 +00100110000001001000100100000000 +00100010011101000010100010010000 +00000010111000000000000000010000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010111001000001 +00001000100100001000001000100100 +00000000101110010000000000101110 +01000000000010111001000100000010 +11000100000000101010000100010000 +00101010010000000100101010010000 +00000010110001100000000001000000 +00000000000000000000000000000000 +00001000000001001000010000000000 +10110001000000000010110001001001 +00001000000100100000001000000100 +00000000001100010010010000101100 +01001000000010111001000000000010 +10000100100000001010000100100000 +00101000011000000001101000010000 +00000010110000100000000100000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11111000000000000011111010000000 +00101100100001010000101100100000 +00000000111110000101000000111110 +00010100000011111010000000010011 +11000001010000001110100001010000 +00111010000101000010111010100000 +00100011111011100000001101010000 +00000000000000000000000000000000 +10011000000011011110010000000000 +11111101000000010011111101000100 +00000111010100010000001111100100 +00000000111110010001000000111110 +01000100000011111101000000000010 +01100100010000001101100100010000 +10110111010000000000110111010000 +00000011111001100000011001110000 +00000000000000000000000000000000 +00011000000001011110010000000000 +11111001000000000011011101000000 +00001100010100100000001100100100 +00000100111110010000100000111110 +01000000000011111101000000000011 +10110100010000001100110100010000 +00110011010000000010110011110000 +00000011001001100000000001110000 +00000000000000000000000000000000 +00111000000100001110000000000000 +10111000000000010010001000010100 +00001000100001101000000010100000 +00000000101110000100000000101110 +00010100000010111000000000000010 +00100001010000001000000000000000 +00100010000010100000100010100000 +00100010000011100000010000110000 +00000000000000000000000000000000 +00001000000001011100010000000000 +10111001100000000010010001000000 +00001010000100010000001000000100 +00000000101100010010100000101100 +01001010010010110001000000000110 +10000100100000101000000101100100 +00100010010000000000100000110000 +00000010010000100000000101110000 +00000000000000000000000000000000 +00011000010101011010010000000000 +10111001100000000010001001000000 +00001001000100001000001010100100 +00000100101110010000000000001110 +01000000000010111001001000000010 +00100100000000001010000100000000 +10101010010000000100000010110001 +00000010010001100000010001100000 +00000000000000000000000000000000 +10100000000101001010010000010100 +11110001000001000011011001001000 +00001110100101000000001100100110 +01000000101110010000000000011110 +01000000000011110001111000000011 +10100100000100001100100100000000 +00100000010000000000110000011000 +00001011011010000000010001110000 +00000000000000000000000000000000 +00101000010000001010010000100000 +11111011000000100011111001001000 +10101110100100000000001111100110 +00010000111110010000000000111110 +01000000000011111001100010000011 +11100100000000001101100100000000 +00110110010000100000111110011000 +10010011100010100000000001100000 +00000000000000000000000000000000 +00101000000100001010000001000000 +11111000000010000011110000010000 +01001101100001000000101101100000 +01111000111110000000010100111110 +00000000000011001000000100000011 +00000000001000001111100000001000 +00110010000000000000110010000100 +00000011110010100000010000100000 +00000000000000000000000000000000 +00101000000001000010100100000000 +10111010010001000010111110110000 +00101000111000100000001000101011 +00000000101110100000010100101110 +10000000000010001110100000000011 +01111000001001001011111001000000 +00100011101000000000110111100000 +00000010110010100000000001000000 +00000000000000000000000000000000 +00101000000001010100110100000000 +10110011010000000010110010110011 +10101000001000000000001001001101 +00000001101100110000001000101100 +11000000000110000011000000000110 +01001111000000001011000101000000 +00100000111000000100101000110100 +00000010110010100000000001010000 +00000000000000000000000000000000 +00100000000000010001100000000100 +10110111000000000010110110000010 +00001000011000000000001000011000 +00000000101101110010000000101100 +11101000000010000110000000000010 +01011100000000000011010100000000 +10100001110000100000101101110000 +00000010111010000000000001000000 +00000000000000000000000000000000 +00101000000010000001111001000000 +11110111100100010010110010100000 +00101100011110000100001101010110 +00110000101101111010001000111101 +11101100001011000111100000000011 +01011110000000001111011110000000 +00110011111000001000111001111000 +00000011111010100000001000000000 +00000000000000000000000000000000 +00001000000011011010100000010000 +10111011010000000011111011000000 +00001110101001000000001111100000 +00000000111110110110100000011110 +11011100000011110011000000000011 +11101100000000001111100100000000 +00111110010000000000110110110000 +00000011110000100000011001100000 +00000000000000000000000000000000 +01000000000001011111111000000000 +11111111100000000011111101100001 +00001100111011010000101100111110 +00000000101111111001100000110011 +11100000000011001111100000000010 +10111010010000101100110110000000 +00110011011000000000110011111000 +00100011110100000000000001110000 +00000000000000000000000000000000 +10101000000100011001110000000000 +10110110000000010010110110010000 +10001000010000111000101000011001 +00000000101101110000000000101001 +11000000000010000110000100000010 +00111000010000001000010000000000 +00100011010000000000100001110001 +00010010111010100000010001100000 +00000000000000000000000000000000 +00000000000000001001000000100000 +10110111000100000010110001000000 +10111001011110000100001000011100 +01100000101101110000001000100100 +11000000001010000110000000000010 +10011000000010001001001100000000 +00100001010000000010100101110000 +00000010110001000000000000100000 +00000000000000000000000000000000 +01100000000101001100001000000100 +10110011011000000000110011000000 +00001001000011000000101000001000 +00000001001100110000010000101000 +11000000000000000010000000000010 +00001000000000001001000000000000 +01100010010000000010100100111101 +00000010110110000000010000110000 +00000000000000000000000000000000 +10101000000101011010011000000000 +10111011010000000011111010100000 +00100001101010000000100100101110 +00000001101111110000000001110011 +11000000000011000011110000000011 +10101000000001001101000100000000 +00100010111000000110110110110000 +00100011111011100000010001100000 +00000000000000000000000000000000 +10000000000000001110000000000000 +11111011000000000011111011100000 +10001110001000000000001111101101 +00000101111110110000000001111110 +11000000010011111011111000000011 +11101100000001001110100100000000 +00111110110101000000111010110100 +00000011111000010000000000110000 +00000000000000000000000000000000 +00000001010100001111111001000000 +11111111000000000011111110000000 +00101100111100011000001100110111 +00000000110010110000001000110111 +11000000110011001111000000100011 +01011000000000001100110110100000 +00110011110000000000100011110000 +10000011001000000000010000110000 +00000000000000000000000000000000 +10000001000001000110101000000000 +10111011000000100010110011010001 +00001000101000000010101000000101 +00000000100010110000000000100010 +11000000000010001011110010000010 +00101101010001101000100100000000 +00100010011000000000100000110100 +01001010001000000100000000010000 +00000000000000000000000000000000 +10000000000001010010010000000000 +10111011000000000010111001000000 +00001000101000000000001000100000 +00000000100000110000000000100000 +11000000000010001010100000101010 +01101001000000011000100100000000 +10100010111100000000101010111000 +00000010001000000000000001000000 +00000000000000000000000000000000 +00001000000101000000010000000000 +00110011100000000010111011000000 +00011000001000000000001000100000 +00000000100000110000000000100000 +11000000000010001000000000000010 +00001000000000011000000000000000 +00100000110000000001101010010000 +00000010000000100000000100000000 +00000000000000000000000000000000 +00000000000011010110000000000000 +11111011000000000011111001000000 +01001100111100000000101100100000 +00000010110011110000000010110111 +11000000000011001010000000000011 +01101000000000001100100100000000 +01110010110000000010111010110000 +00000011001000000000001101010000 +00000000000000000000000000000000 +10100000000101011111000000000001 +11111111000000000011111111000000 +00011111011000000000001111110000 +00001001111111110000001000111111 +11000000001011110110000000000011 +11110000000000001111110000000000 +00111111000000000010110111000000 +00000011111010000000011001110000 +00000000000000000000000000000000 +11000000000001011111110000000000 +11001101100000000011011111001001 +00001100111100100010001100110010 +01000000110001001000001010110011 +11000000000011110100100000000011 +00010010000000001111110010000000 +00111101001000000000110011110000 +00100011001100000000000001110000 +00000000000000000000000000000000 +11000000000110001111111101000000 +10001001100000000000111111100001 +00001000111100101011001000100000 +00000000100010010000001100100011 +11010000000010111001000000000010 +10100010000000001011100010000000 +00101110100000000000101010111100 +00010010101100000000010000110000 +00000000000000000000000000000000 +11001000000001011100110000000001 +10000001000000000010010011010000 +00001000001100110001001000001000 +00000011100010100010100000100000 +11000100000010111000000000010010 +10000000000000011011000000000000 +00101100110000000000100100010100 +00000010001100100000000101110000 +00000000000000000000000000000000 +11000000000001011010110000000000 +10001001110000000010111011000000 +00001000101100000000001000101100 +00000000000010110000000000100010 +11000000000010111001000000000010 +10100011000000011011101000000000 +00101100111000000000101110011000 +00000010101100000000010001100000 +00000000000000000000000000000000 +11000000000101011110110000000000 +11001000100000000011011011000000 +00001100101100000010001100100000 +00010000110010000000000000110010 +11000000100011110001110100000011 +10100010000000001111100010000001 +00111110111000000000110100010000 +00000011000100000000010001110000 +00000000000000000000000000000000 +11100000000000011000110000000010 +11111101000000000011110011000001 +00001111111100000000001111110000 +00001000111111000000000000111111 +11000000000011111111000000000011 +11110100000000001111111000010000 +00111111110000011000111011010000 +00000011111110000000000001100000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11001000010000000011111011000000 +00001100101100000000001100101000 +00000000111110000000000000110110 +11100010000011001001010000000011 +00100101001000001100100000010000 +00111110111000000000110010110000 +00000011110101010000010000100000 +00000000000000000000000000000000 +11000000000001010011111000010000 +10001001101000000000111111000000 +10001000111100000000001000101100 +00000000101100000000000000100011 +11010000000000001001011000001010 +10100101100000001000101001010000 +00101110110000000000100010111000 +10000010111100100000000001000000 +00000000000000000000000000000000 +11000000000001000100110000001000 +10000000100001000000110011000000 +00001000101100000000001001100100 +00010000101100000000000000100100 +11000000000010000001000000010010 +01000010000000001001000010000000 +00101100100000000000100000010000 +00000010111110000000000001010000 +00000000000000000000000000000000 +10111000000100000101111000000000 +10010110100000000010110111100000 +00001001001110000001101001010110 +00000000101111011000010001100000 +11100000001010000111110100000010 +11011110000000011001010010000000 +00101111101100000010100001011100 +00000010111011000001000001000000 +00000000000000000000000000000000 +01001010000010000100110000100000 +11000011000000000011110011000001 +00001100001100000000001101001000 +00000100111100100000000000110100 +11000000010011000001000000100011 +01000100000000001101001000000000 +00111100110000000000110000110000 +00000011110100100000001000000000 +00000000000000000000000000000000 +11000000000101011011110000100000 +11101111000100000011111111000000 +00001110111100011000101110111101 +01001000111111110000000000111111 +11000000000011111101000000000001 +10111100010000001010111000010000 +00111111110000000000111111110001 +00000011110100000000011001100000 +00000000000000000000000000000000 +00001000000001011110110010100000 +11011011000000000011111011010110 +00001100101101101000001100000111 +00010000110010000000000000111010 +11010010001011000001000000000011 +10100000000000001111001010001000 +00110010111000000000110000010000 +00000011001010100000000001110000 +00000000000000000000000000000000 +11001000100110011000110010000100 +10000101000000000010110111001000 +00001000001100000000101000010100 +00000010100011000000000000101001 +11011000000010000111000000000010 +00011100000000001011011000000000 +00100001110000000000101001010000 +00000010101100100000010001100000 +00000000000000000000000000000000 +00100000000000000001111010000010 +10100111100011000110110111101001 +00111000011110100000001000111010 +00000000100001001000000000101001 +11101000000010101101110000000010 +10010110000000001011111010000000 +00100011110000100010101001111000 +00000010001000000000000000100000 +00000000000000000000000000000000 +01101000000001001100110000000000 +10100011101000000110110011000000 +00001000001100000100011000001100 +00000000100000000100000001101000 +11000000000010110001000000000010 +00001100000010001011001010010000 +00100010111000000000101000110000 +00000010100100100000010000110000 +00000000000000000000000000000000 +11100000000101010110100000000000 +11101110100000100011111010000000 +00001100101000000000001100101000 +00010000110011100010000000111000 +10000000000011101110010000000011 +10111001000000001111101000000000 +10110011100100000000111010100000 +00000011001110100000010001100000 +00000000000000000000000000000000 +01001000000000011010000000010000 +10001000000000000011111000000000 +00001111100000000000001111100000 +00001000111110000000100000110110 +00000000000001001000000001001011 +11100001000000001111100001000000 +00111110000100100000101110000000 +00000011110100100000000000110000 +00000000000000000000000000000000 +00001000000100001000010000000000 +11001001000000000010110001000000 +00001000000100000010011100101100 +00010000111110010000000000110110 +01100000000011001001101010000011 +00100100001010001011101110100000 +00111110010000000010010000010000 +00000011000000100000010000110000 +00000000000000000000000000000000 +10000000000000000110011000000000 +10001001000000000010111001000000 +00001000100100000000001101100100 +00000000101110010000000000100010 +01100000000010000001010000000010 +10100100100000001001100111000000 +00111010010100000000100010010000 +00000010001000000000000000010000 +00000000000000000000000000000000 +00111010000001010010010001000110 +10001001000000000010111001000000 +00001010100100000000101000101100 +00000000101100010000000100100110 +01001000000010001011010000000010 +00100100100000001011100101000000 +00101110010000000000101010010000 +00000010000001100000000001000000 +00000000000000000000000000000000 +00101000000101000000010010100000 +10000001000000100010110001001010 +00101010000100101000001000000100 +00000000001100010000000000100000 +01101000001110000001000000000010 +10000100000000011001000100000000 +00101000110000000000101000011010 +00001010000000100000000100000000 +00000000000000000000000000000000 +10111000000011010110000010000000 +11001000000000000011111000001000 +11001110100000100000001000100000 +00000000111110000101000000110100 +00010100000011001000010100000011 +00100000000011001111100000000000 +00111110000101000000111010000000 +00000011001011100000001101010000 +00000000000000000000000000000000 +11011000100101011110010000000100 +11111101000000000011110001000000 +10000101100100101100101111100100 +10100000111111010000000000111110 +01000100000011111101000000000001 +11110100000001000111100100000000 +00111001110000000100110111010001 +00000011111001100000011001110000 +00000000000000000000000000000000 +00011000010000011110010010101000 +11001001000000000011001001000000 +00001000100100000010001100100101 +00010000111110010000011010110011 +01011000000011001101010000000011 +00110100000000001100110100000000 +00111111010100000000110011110010 +00100011000001100000000001110000 +00000000000000000000000000000000 +01111000000110001110000100000000 +10001010000000000010001000000001 +00001000100000100001001000000000 +00000000101110000010100100100010 +00000000000010001000001000000010 +00100000000000001000100000000000 +00101110000000000000110110000100 +00000010100011100000010000110000 +00000000000000000000000000000000 +01001000000000001000010000000000 +10001001000001000010000001010000 +00001000000101001000001000000100 +10000000101100010000000000100000 +01011000000010000001000000001010 +00100100000000001010000100000000 +00101100010010000000100100010001 +00000010000100100000000101110000 +00000000000000000000000000000000 +00011000000001001010010000010010 +10001001000000000010001001000000 +00001000100100000000001000100100 +10000000101100010000000001100000 +01000000000010000001000100000010 +00100101000000001010100100000000 +00101100111000000000100110010010 +00000010100001100000010001100000 +00000000000000000000000000000000 +10100000000100011100010000000000 +11000001000000000011001001000000 +00101100100100000000101100100100 +10000000111110011000000000110010 +01000000010011001001000000000011 +00000100000000001110100100000001 +00111110010100000010110100010000 +00000011001010000000010001110000 +00000000000000000000000000000000 +01001000000000011010110000000000 +11111011100100101011110011000001 +00001111100100000010001111100100 +00000000111110011010000000111110 +01000000001011111001000000000011 +11100100000000101101100111000000 +00111110010000010010111110010000 +00000011110110100000000001100000 +00000000000000000000000000000000 +01001000000100001010000010001000 +11001000010000000011111000001000 +00001100100000000000001100100000 +00000000110010000000010000111110 +00000000000011001000000000000011 +00100000110000001111100000000001 +00111110000100000010110010000001 +00000011110010100000010000100000 +00000000000000000000000000000000 +00101000010001010010100000000000 +10001010010000000010111010100000 +00001000101000000000001101101000 +00000000100010100000010000111111 +10000000000010001110011100010010 +00111000000000001011111000000000 +00101111100000000000100011100000 +00000011100010100000000001000000 +00000000000000000000000000000000 +01101000000001010100110100000010 +10000010001000000010110011110001 +00101011101100000000001001001100 +00000000000100110000000000101100 +01000000001010000011110000010010 +00000110000000000011001100010000 +00101100111000000000100000010000 +00000010110010100000000001010000 +00000000000000000000000000000000 +10000000000100010001010000000001 +10000100000000000010110111000010 +00011011001100000001001001011110 +00000000100101110010000000001000 +01000000000010000111000000000010 +00011100000000001011011100000000 +00101101110100000000100001010000 +00000010101010000000000001000000 +00000000000000000000000000000000 +10001000100010001000011000000010 +11000110100100000011110011100010 +00101111011111110010001101011110 +10000000110101111100010000101101 +10100000000011001111100000001011 +00011110000000001111011110000001 +00111111111000000010110001011000 +00000011111010100000001000000000 +00000000000000000000000000000000 +00001010000101011010010000100100 +11111000010000000011111011001000 +00001100101100100000001111101100 +10110010111010110110000000111110 +00000000000011111001011010001011 +11101100000001001011101100000000 +00111110100000000100111110010000 +00000011110000100000011001100000 +00000000000000000000000000000000 +00000010000001001011101000000000 +11001111100100000011111100100000 +00001100111110000000001100111110 +00100000111111111100000000111111 +01100001000011101111100000000011 +00111110000100001111010110010000 +00110011011000000000110011011001 +00000011000000000000000001110000 +00000000000000000000000000000000 +10101000000110001001000000000010 +10000101000100100010110100011000 +00001000011100010100101000011100 +00000000101101110001000000101101 +01000100000010000111000000000010 +00011100000100001011010100000000 +00110101110001000000100001110000 +00000010101010100000010001100000 +00000000000000000000000000000000 +00000000100000001000000000000010 +10000111010110010010110000000000 +00111000011100000000101001011100 +00000000101101110000000000101101 +10000000000010100111000000000010 +00011000011000001011010100001000 +00100011010000000000100001010000 +00000110000000000000000000100000 +00000000000000000000000000000000 +00100000000001001000000000000000 +10000001000000010010110000000000 +00011000001100000000001001001101 +10000000101100110100000000101100 +00000000000010001001110000000010 +00001011100000001011000110000000 +00100100101000000000100000110000 +00000010100010000000010000110000 +00000000000000000000000000000000 +10101000000100011010110000000000 +11001010010000000011111010000000 +00101100111100000000001101111101 +00010000111111110000000000111110 +00000000000011101001000000000011 +00001111000000001111101100000000 +00110010100000100010110010010000 +00000011001010100000010001100000 +00000000000000000000000000000000 +10000000000000001110010000000100 +11111000000000010011111010010000 +00001111001100000010001110101100 +00000000111110110010000000111101 +01000000000011111001010100000011 +11101000000000001111101100000000 +00111110010100000000111110010000 +00000011111000000000000000110000 +00000000000000000000000000000000 +00100001000100001101010000001000 +11011110000000000011110110000000 +00001100111100000000001100111100 +00000000111111110000000000111110 +10000000000011001101000010000011 +00111100000000101100111000000001 +00111111101010000000110001010000 +00000011000000000100010000110000 +00000000000000000000000000000000 +10100001010001000110010000000010 +10001000011000000010111010000000 +00001100101100000000001000101100 +00000000101110110000000000101110 +00010000000010101001100000010010 +00101011110000001000100111000000 +00100110000100000000100010001100 +10000010001000000000000000010000 +00000000000000000000000000000000 +10000000000001010010100000000000 +10001010000000000010111000000000 +00001000101100000100101000101100 +00001000101110110000000000101110 +00010000000010001011100010000010 +00101100000010001000100110001001 +00101100000000000000100010011000 +00100010001000000000000001000000 +00000000000000000000000000000000 +00001010000101000000000000000000 +10000000000000000010110000000000 +00001000001100000000111000001100 +00010000101100110000000000101100 +01000000000010100011000000000010 +00001000000001001000000100000100 +00100100010000000010100000010000 +00000010000000100000000100000000 +00000000000000000000000000000000 +00000000000011010110000000000000 +11001010000000000011111000000000 +00101100011100000000001100111100 +00000000111111110000001000111110 +10000000000011000111000000000011 +00101000000000001100100000000000 +00111110000000000000110010010000 +00001011000000000000001101010000 +00000000000000000000000000000000 +10100010000101011111000000000000 +11111100000000000011111100000000 +00001110111100000000001111111100 +00001000111111110000010000111111 +00000000000011111100000000000011 +11111000000010000111110100000000 +00111101000000000000111101000000 +00000011111010000000011001110000 +00000000000000000000000000000000 +11000000000001011101011000000000 +11111111000000000011001111001000 +00001101110010010001001100111110 +00000000111111110011000000110011 +11001010000011001111100000000011 +11111100111010001111111110000000 +00110011110000000000110011100000 +00000011001100000000000001110000 +00000000000000000000000000000000 +10000000000100001110010000000000 +10111011100001000010001111110000 +00001000100010000001001000101110 +00000000101111110011000000111011 +11111010010010001011100000000010 +11111101000100001011101110000010 +00101011111100010000101010101100 +00010010001000000000010000110000 +00000000000000000000000000000000 +10001000000001011100010000000000 +10110011000000000010000011000101 +00101001001000100100001000001100 +00000000101100110000000000100000 +11000000001010000011000000000010 +11001100100000001011101100000000 +00100000110100000000100000000100 +00000010001000100000000101110000 +00000000000000000000000000000000 +11000000000101011010010000000100 +10111011000000001010001011000000 +01001000100000000000101000101100 +00000000101110110000010000101110 +11000000010010001011000000000010 +11101100000000001011101100000000 +00101010110000000000101010000000 +10000010001100000000010001100000 +00000000000000000000000000000000 +01000000000101011110010000000000 +11111011000000000011001011000000 +01001101100100000000001100100110 +01000000111110110000000000110010 +11000000000010001011000000000011 +11101100000000001111001100000000 +00110010110000000000110010111101 +00000011000100000000010001110000 +00000000000000000000000000000000 +11100000000000011011010000000000 +11110011000010000011111111000001 +01101111110100010000001111110100 +00001000111101110000000000111011 +11000000000011111111000111000011 +11111100000100001111111110010000 +00111111110000010000111101110000 +00000011111110000000000001100000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11101011000000100011001011100000 +00001111101100000010001101100100 +01100000111110110000000000111110 +11000000000011001011000000000011 +11101100000110001111101110000000 +00111110110000000000111110010000 +10000011000100000000010000100000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10001111000001000010000111010000 +00001011100100000000001011100101 +00000000101111110000010000101111 +11000000000010001011110000010010 +11111100000000001011101100000000 +00101101110000110100101110010100 +00000010001100100000000001000000 +00000000000000000000000000000000 +11100000000001010100010000000000 +10100011100100000010000011000010 +00001011100000000000001011001101 +00000000101100110000001000101110 +11000000000010000001010000000010 +01001100000000001011000101100000 +01101100110000001000101100110101 +01000010001110000000000001010000 +00000000000000000000000000000000 +00100000000000010011011000010000 +00000111100100000010000111100000 +00001011011110000000001011011110 +01000000101101111000000000101100 +11100000001010000101100010000010 +11011110000000001011010110000000 +00101101111000000000101100111000 +00000010000010000000000001000000 +00000000000000000000000000000000 +01001000000010000000010000000000 +11100011000000000011000011000000 +00001111001000000000001111001100 +00000000111100110000000000111100 +11000000000011000001000000000011 +01001100000000001111001100010000 +00111100110000000000111100110000 +00100011000100100000001000000000 +00000000000000000000000000000000 +01000000000111011011010000000000 +11111111000010001011111111000000 +00001111111100000000001111111100 +00000000111111110000000001111111 +11000000000011101101000000100011 +11111100011000001111111100000100 +00111111110000000100111111110001 +00000011110100000000011001100000 +00000000000000000000000000000000 +10101000000001011110010000000000 +11111011000000100011001011001010 +00001011100000000000001111101111 +11000000110110110011100000111110 +11000100000011001011101000000000 +00101110100000001100100101100000 +00111110110010000000111110110000 +00000011111010100000000001110000 +00000000000000000000000000000000 +01001000000100011001010000000000 +10110111001000001010000111010000 +00001011011100000001001011011100 +10110000100001110010000000101101 +11000010000010000111011010000010 +10001100001000001000010101101000 +00101101110100100100101101110000 +00000010110100100000010001100000 +00000000000000000000000000000000 +11000000000000001001111000000000 +10110011100000000010000111100000 +00001011011010000001001011111110 +10001000100101111010000000101101 +11100000000010001111100000000010 +00011110100000001000011110000000 +00101101111010000000101101111000 +00000010111100000000000000100000 +00000000000000000000000000000000 +01001000000101001100111000000000 +10110011000000000010000011000000 +00001011001100000000001011001110 +00000000100000110000000000101100 +11000000000010000011100000000010 +10001100000000001000001100000000 +00101100110000000001101100110000 +00100110110100100000010000110000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11111010000000000011001010000001 +00001111011001000000001111101000 +00100000110110100000000000101110 +10000000000011001010101000100011 +00101000000000101100101000000000 +00111110100000000000111111100100 +00000011111110100000010001100000 +00000000000000000000000000000000 +01001000000000001110000001000100 +11111000000000010011111000000000 +01001111100000001000001111100000 +00000000111100000000000000111110 +00000000001011111000000000000011 +11100000000000001111100001000010 +00111110000000010000111110000000 +10000011110100100000000000110000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11110001100100000011001001000000 +00101100100100000000001100100100 +00000000111110010000000000110000 +01000000000011001001000000000011 +11100100000000001111100100000000 +00111100011000000000110000010000 +00000011000000100000010000110000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000000000010000001000000 +00001000100100000000001000101110 +01000100101110010000000000100010 +01000001000010001011000000000010 +11100100000000001011101101000001 +00101110010001010000100010010010 +00000010001000000000000000010000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001010000001010001001000000 +00001000101100000000001000100100 +00001000101110010000000000100010 +01000000001010001001000000000010 +11100100000000001011100101000000 +00101110010000000000100010010000 +00000010000001100000000001000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001001000000010000001001000 +10001000100100000000001000001100 +00000000101100010010000000100000 +01001000000010000001000000000010 +11000100100000001011000100000000 +00101100010010000010100000010010 +00001010000000100000000100000000 +00000000000000000000000000000000 +10111000000011010110000101000000 +11111000000000000011001010000000 +00001100100001010000001100100000 +00000000111110000101000010110000 +00010100000011001000000000000011 +11100001010000001111100000000000 +00111110000000000100110010000000 +00000011001011100000001101010000 +00000000000000000000000000000000 +10011000000111011111010000000000 +11111001000100000011111001000100 +00001111110100000000101111000100 +00000000101110010001010000111110 +01000100000011110001000001000011 +11100100010000001111100100000100 +00111110010001010100111111010001 +00000011111001100000011001110000 +00000000000000000000000000000000 +00011000000001011110010001000000 +11111001000000000011001101000000 +00001110100100000000001111100100 +00010000111110010000110000110010 +01000010000011111001000000000011 +11100100010000001111100100000010 +00101111010000000000111111010000 +00100001000001100000000001110000 +00000000000000000000000000000000 +00111000000100001110000000001000 +10111000010100000010001000010100 +01001000100000101000001011100000 +00000000101110000000000000101010 +00001010100010111000000000000010 +11000001010000001011100000000000 +00101110000000001000101110000000 +00000010000011100000010000110000 +00000000000000000000000000000000 +00001000000001011100010010000000 +10110001000000001010000001000000 +00001010000100000100001011000100 +00000000101100010000100000100000 +01000000000010110001000000000010 +11000100100000001011000100000000 +00101100010100001101101100010100 +00000010000000100000000101110000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10111001000000000010001001000001 +00001000100100010000001011100100 +00000000101110010000000000101010 +01000000000010111001000000000110 +11100100000000001011100100100010 +01101110010000000001101110010010 +00100010000001100000010001100000 +00000000000000000000000000000000 +10100000000101011110010000000000 +11111001000000000011001001000000 +10001110100110000000001011100100 +00000000111110010000000000010010 +01000000000010111001000000000011 +11100100000001001111100100000000 +00111110010000000000111110010000 +00000011001010000000010001110000 +00000000000000000000000000000000 +00101000000000011010011001000000 +11110011000000001011111001000000 +01001111100100000000001111100100 +00001000111110010000010000111110 +01000000000011111001000000000011 +11100100000000001111100110000000 +00111110010000010100111110010000 +10001011110010100000000001100000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11001000000010000011110000000000 +00001101100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000101100100000000000 +00111110000000001000110010000001 +00000011000010100000010000100000 +00000000000000000000000000000000 +00101000000001010010100000000000 +10001010000000000010111110000000 +10001000101000000000001011101010 +10000000101110100000000000101110 +10000000000010111010001100000010 +11101000000001001000101000000000 +00101110100000000000100001100100 +00000010000010100000000001000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10000011100000000010110011000100 +00001001001100000000001011001100 +00000000101110110000000001101100 +11000000010010110011100000000010 +11001100000000001000001100010000 +00101100110001000000100100011100 +00001010000010100000000001010000 +00000000000000000000000000000000 +10100000000000010001111011000000 +00000101010000010010110011000000 +00001000011100110000001011011100 +00000100101101110010001000101101 +11001000000010110110000000000010 +11011110100000001000011000000000 +00101101111000000000100100110000 +00000010001010000000000001000000 +00000000000000000000000000000000 +10101000000010000011111010000010 +11000110100010000011110111100000 +00001101011110010001001111011010 +01001000111101111011000000111101 +11111010000011110111100000000011 +11011110000000001100011110001000 +00111100111000000010110101011000 +00000011001010100000001000000000 +00000000000000000000000000000000 +00001000000111011010110110100000 +11111011011000000011111010000000 +00001111101100100000001111100101 +10000000111110110000000000111110 +11000000100011111010000010000011 +11101100010000001111101100100010 +00111110010000000000111010110000 +00000011110000100000011001100000 +00000000000000000000000000000000 +00000000000001011111111000000000 +10111100100100000011001101100101 +00001100111110000000001110110110 +00000000111111111000100000111111 +11100000000011111101100100000011 +11111111000000001100110110010000 +00111111111000000000101111011001 +00000011000000000000000001110000 +00000000000000000000000000000000 +10101000000100011001110000000000 +10110101000100001010000111001100 +00101000011100001000001000011100 +00000000101101110000010000101101 +11000000000010110111000000000010 +11011100000000001000010000000000 +00101101110010010000101101010011 +00001010001010100000010001100000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110110000001010010000101000000 +00001000111100000000001011010000 +00000000101101110000000000101101 +11000000000010110101000000100010 +11011100000000001001010100000000 +01101101110000000000101100010000 +00100010000000000000000000100000 +00000000000000000000000000000000 +00100000000101001100110000000001 +10110011000000000010000010000000 +00011000001110100000001001000100 +00000000101100110000010000101100 +11000000000010110011000000000010 +11101100000000001001000100000000 +00101100010000000000101100010000 +00000010000010000000010000110000 +00000000000000000000000000000000 +10101000000101011011110000000000 +10111011000000000010001010000000 +00001100111100000000001011101100 +00000000101111110000001000101111 +11000000000011111011000000000011 +11111100000000001101101100000000 +00111110110000000000111110010000 +00000011001010100000010001100000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11111011010000000011111011000000 +00001111101100000000001100101000 +00000000111110110000000000111110 +11000000000011111000010000000011 +11101100000010001110100001000010 +00111110110000000000111110000100 +00010011111000000000000000110000 +00000000000000000000000000000000 +00000001000100001111110000000010 +11001011001000000011001110000000 +00001111111100000000001100111000 +00000000111111110000000010110011 +11000000000011111111000000000011 +11101100000001001100111010100000 +00111111110000000000111111010000 +00000011000000000100010000110000 +00000000000000000000000000000000 +10000001000001000110110000000000 +10000011110000100010001010100000 +00001011101100000010001000100000 +00000000101110110000000001100010 +11000000000010111000011000000010 +11101100000001001000100000000001 +00101110011000000000101100010000 +00000011011000000100000000010000 +00000000000000000000000000000000 +10000000000001010000110000000000 +10011011000010000010001010100000 +01001011001100000100001000100100 +00001000101100110000001000100010 +11000000000010111000100000000010 +11101100000000001000101101000010 +00101110010001000000101110010110 +00000010001000000000000001000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10000011000000000010000011100000 +10001011001100000000011000001010 +00000000101100110000000000100000 +11000000000010110000000000000010 +11001100000011001000000000000000 +00101100010000000100101100010000 +00000010010000100000000100000000 +00000000000000000000000000000000 +00000000000011010111110000000000 +11011011000000001011001010000000 +01001111111100000100001100100000 +00000100111111110000000001100011 +11000000000011111000000000000011 +11111100000000001100101000000010 +00011110010000000100111110010000 +00001011000000000000001101010000 +00000000000000000000000000000000 +10100000000111011111110000000000 +01111111000000000011110110000001 +00001111011100000000101111110000 +00000000111111110000010000111111 +11000000000011111100000000100011 +11111100000000001111110000000000 +00111111010000010100111111010000 +00000011111010000000011001110000 +00000000000000000000000000000000 +11000000000001011101110010000000 +11111101100000000011101100100000 +00001100110110000000001111110010 +00000100110011110010010000110011 +11000000000011001100010000000011 +10110000000100001100110110000000 +00110011010010000000110011110100 +00100011001100000000000001110000 +00000000000000000000000000000000 +10000000000100001111111101001000 +10111001100000000010001001100000 +10001000100110000010001011100110 +00000000100011110101000100100011 +11010000000010001000001000000010 +10100000001101001000001100001100 +00100010010101100000101011110101 +00010010001000000000010000110000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10111011000000000000100010000000 +00001000000000000000001011100000 +00000000100000110010100000100000 +11010001000010100000000000010010 +00000100100010001000001100100000 +00100000010010000000100100110010 +00000010001000100000000101110000 +00000000000000000000000000000000 +11000000000101011010110000000000 +10111011000001000010001011000000 +00101000100110000000001011100100 +00000000100000110000010010100010 +11000000001010100000010000000010 +10100110000000101000101100000000 +00100010010000000000001110110000 +00000010001100000000010001100000 +00000000000000000000000000000000 +01000000000100011110110000000000 +11110001100100000011100000010010 +00001100100011001000001111100010 +00000000110010110000000000110010 +11000000000011101011010100000010 +10100010100100001100101110010001 +00100010010000000010110110011000 +00001011000100000000010001110000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11111101000000000011111101000000 +00001111110000000010001111111110 +10000000111111110000000000111110 +11000000000011011001100000000011 +11110000001000001111111100000000 +10111100010000001010111001011001 +00000011111110000000000001100000 +00000000000000000000000000000000 +01000000000100001010110000000100 +11001011001001000111111010010001 +10001111100100000000011111100000 +10000000111110110000000000111100 +11000000000011001011010000000011 +00100101000000001111101100001000 +00110010010000000000110010010000 +00001011000100000000010000100000 +00000000000000000000000000000000 +11001000000001010011111000000000 +10001011110000000010111011000000 +00001011100100000000011111001100 +00010000101111110000000000101111 +11000000000000001001111000000001 +00100100000100001011101101000000 +00110011010000001000100010011010 +00000010001100100000000001000000 +00000000000000000000000000000000 +11100000000001010100110000000001 +10000011000100000010110000000000 +00001011000100000010001011001001 +00000001101100110000000000101100 +11000001000010000000001000101010 +00100000000001001011101100000010 +00100000010000010000101000010000 +01000010001110000000000001010000 +00000000000000000000000000000000 +00100000000000010001111000000000 +10000111100000000010110100100000 +00001011011110000000001011011110 +00000000101101111000000000101101 +11100000001010000110100101001010 +01010010000000001011011110000000 +00100101011000000000101000011000 +00000010000010000000000001000000 +00000000000000000000000000000000 +01001000000010000000110000100000 +11000011000000000010110011000000 +00001111001000000000001011001000 +01000000111100110000000000111100 +11000110000011000001000100001011 +00000100011000001111001100100000 +10110000010010000010111000010000 +00000011000100100000001000000000 +00000000000000000000000000000000 +01000000000111011011110000100010 +11111111000000000011111111010100 +00001111111100000000001110111101 +00000000111111110000000000111111 +11000001000011111111000100000000 +10110100000000001111111100000000 +00111011010000000000110111011001 +00000011110100000000011001100000 +00000000000000000000000000000000 +10101000000001011110111010000010 +11001011000000000011110000101000 +00001100101110000000001100100001 +00000000111110110010100000111110 +11010010000011111010000001000011 +00110000000000000011101100000001 +00111110011000010000110010110010 +00000011001010100000000001110000 +00000000000000000000000000000000 +01001000000100011000110011000000 +10000111000000000010110100000000 +00001000010100000001001000011100 +00000100101101110000000000101101 +11011000000010110010000000000010 +00010100000000001011011100000001 +00101101010110000000100000110001 +00000010000100100000010001100000 +00000000000000000000000000000000 +11000000000000001001111010000000 +10000111100000000010111111100000 +00001000111110000000101000010010 +00100000101101111001000000101101 +11101000000010110111110000000010 +00011110000000001011011110000100 +00101100010000000000100001111000 +00000010001100000000000000100000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10000011000000000010110011000000 +10001000001101010000001000001100 +00010000101100110000000000101100 +11000000000010111011110000000010 +00001100100000001011001110010001 +00101100010000000000100000110001 +00000010000100100000010000110000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11001010000000000011111010000000 +00101100111010000000001100101010 +00000000111110100000000000111110 +10000000000011111110100000001011 +00111001000000001111101000000010 +00111110100000000110110010101000 +01001011001110100000010001100000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000010011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000001111000000010000011 +11100000000000001111100000000000 +00111110000000000000111110000100 +00000011110100100000000000110000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001100000000011111011000100 +00011111100100011000001111101101 +00000000111110010000000010110010 +01000000000011111001000000000011 +00000100100000001100100110010001 +00110010010000000000110010010000 +00000011000000100000010000110000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001100000000110111001110000 +00001011100100000000001011100101 +00000000101110010000000000100010 +01000000000010111001000000000011 +01100111100000001101000111100000 +00100010010000000100100010010110 +00000010001000000000000000010000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001001000000010111001000010 +00001011100100000000001011100100 +00000000101100010000001001100010 +01000000000010111001000000000010 +00100100000000001000100100000000 +10100000011000000000100000010000 +00000010000001100000000001000000 +00000000000000000000000000000000 +00001000000001000000010010100000 +10110001000000000010110001000000 +00001011000100000000001011001100 +00000000101100010010100001100000 +01001000000010110001001000000010 +01000100100100001001100100000000 +00100000011010000010100000010010 +00001010000000100000000100000000 +00000000000000000000000000000000 +10111000000011010110000010000000 +11111010000000000010111000000000 +00001011100000000000001111100000 +00000000111110000111000000110010 +00010100000011111000010100000011 +00100001010000001100100001010000 +00110010000101000000110010000101 +00000011001011100000001101010000 +00000000000000000000000000000000 +10011000000111011110010000000000 +11111101000000100011111001000000 +00001111010100000000001111100100 +00000000111110010000000000111110 +01000100000011111101000100000011 +11111100010001001111110100000001 +00111111010001000000111111010001 +00000011111001100000011001110000 +00000000000000000000000000000000 +00011000000001011110010010100000 +11111101000001000011111001000000 +00001111100100000010001111100100 +00000000110010010010000000111011 +01001000000011001001001001000011 +00101101000000001100000101000000 +00111110010100100000110010010010 +00000011000001100000000001110000 +00000000000000000000000000000000 +00111000000100001110000100000000 +10111000000000010010111000000000 +00001011100000000000001011100000 +00000000100010000110100000100010 +00011010010010001000011010000011 +00100001110000001000100000100000 +00101110000100000000110111000110 +10000010000011100000010000110000 +00000000000000000000000000000000 +00001000000001011100110000000000 +10110001000000000110110001000000 +00001011001100000000001011000100 +00010000100000010001010000101000 +01000100000010010101010000000010 +01010100100000001000010100000000 +00101111010010000000100001010001 +00000010010000100000000101110000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10111001001000010010111001110000 +00001011100110000000001011100100 +00000000100010010000010000100010 +01000000000010010011010000000010 +00011100000000000000110100000001 +00101111110000000000100101010000 +00000010010001100000010001100000 +00000000000000000000000000000000 +10100000000101011110010000000000 +11111001000000000011111001000000 +00001111100101100000001111000100 +00000000110010010000000000111010 +01000000000011011001000000000011 +01100111000000001100100110000000 +00111100010000000000110010010000 +00000011011010000000010001110000 +00000000000000000000000000000000 +00101000000000011010110000001000 +11111001000000000011111011000001 +01001111101100000000001101101100 +00000010111110010000000010111100 +01000000100011101001000000001011 +11100110010000101111100100100000 +00111110010000100000111110010000 +10000011100010100000000001100000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000100000011001000010000 +10001111100011000000001111100000 +00000000111110000000000000110010 +00000000000011001000010000000011 +00100000000000001100100000100000 +00110010000001000000111110000000 +00000011000010100000010000100000 +00000000000000000000000000000000 +00101000000001010010100000010000 +10111110110000000010001010100000 +00001011101000000010001011101000 +00000000101110100000000000100010 +10001000000010001010010001000010 +00101000000100001000101001001000 +00100010100000000100101110100000 +00000010100010100000000001000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110011110010001010010011000000 +00001011001100000000001011001100 +00000000101110110000000000100000 +11100000001010000011100010000010 +00001110000000001010001110000001 +10100000111100010000101100111100 +00000010000010100000000001010000 +00000000000000000000000000000000 +10100000000000010001110000000000 +10110111100000000010010111010000 +00001011011100000000001011011100 +00000000101100110010000000100001 +11100000000010000111010000000010 +00011101000001001010111110000000 +00100001110000010000101101111100 +00000010101010000000000001000000 +00000000000000000000000000000000 +10101000000010000001111000000000 +11110101100000000011010110100010 +00001111010110010000001111010110 +00000000111101111010000010110000 +11000000000011001111100000001011 +00111110000000101110011110000000 +00110001111000000000111111110000 +10001011001010100000001000000000 +00000000000000000000000000000000 +00001000000111011010110000100000 +01110011000000000011101010001000 +00001111100101000000001111100001 +00000000111110110101000000111110 +11000001000011111011000000010011 +11101100000000001101101100000000 +00111110110000010000111110110110 +00000011110000100000011001100000 +00000000000000000000000000000000 +00000000000001011111111000000000 +11111111100000000011111111100000 +00001111111010000000001111111111 +00000000111111111100000000110011 +11100001000011001101100000000011 +00110110010000001111111010000100 +00110011101000000000110011001000 +00000011000000000000000001110000 +00000000000000000000000000000000 +10101000000100011001010000000100 +10110111000000000010110111000100 +00001011011000000011001011011101 +00000100101101110001000000100011 +01000000000010000111000100000010 +00011100110000001011011100011001 +00100001100001000010100001100000 +00000010001010100000010001100000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110110000100000010110100010000 +00001011010001000000001011010100 +01100000101100110000000000100001 +11000100000010000001000000000010 +00010101000000001011011000000000 +00100001110000000010100001010000 +00000010000000000000000000100000 +00000000000000000000000000000000 +00100000000101001100010000010000 +10110001000001000010110000000000 +00001011000010010100001011000011 +00000000101100110000000000100010 +01000000000010000011000000000010 +00000100000000001011101010000000 +10100010110000000000100000110000 +00000010000010000000010000110000 +00000000000000000000000000000000 +10101000000101011010000000000000 +11111001000000100011111001000000 +00001111101101000000001111101010 +00000000111111110000010010110010 +11000000000011001010000001001011 +00101000000000001111100100000000 +00110010010000000000110010110000 +00000011001010100000010001100000 +00000000000000000000000000000000 +10000000000000001110100000000100 +11111000010000000011111001000000 +00001111101100000000001111101101 +00000000111110110000000000111110 +11000000000011111011010100000011 +11101101000000001111100100000000 +00111110010100000010111100110100 +00000011111000000000000000110000 +00000000000000000000000000000000 +00000001000100001101001000000000 +11001101000000110011111100110000 +00001111111100000000001111110000 +00101000111111110000000000111111 +11000000000011000110101000000011 +00111000000000001100110100010000 +00110010110000000000110010111000 +00000011000000000100010000110000 +00000000000000000000000000000000 +10000001000001000110101000010000 +10001000100000000010111000100000 +00001011101110000100001011100000 +00000000101110110000000000101110 +11000000110010001011010000001010 +00101001000000001000100100000000 +00100010111101000000101010111000 +00000010001000000100000000010000 +00000000000000000000000000000000 +10000000000001010010000001000010 +10001001110000000010111011000000 +00001011100000010001001011101000 +00001000101110110000000000101110 +11000000000010001000000000000010 +00000000000010101000101000000000 +00100010000000001000100010000110 +00000010001000000000000001000000 +00000000000000000000000000000000 +00001000000001000000001000000000 +10000001000000000010110011000000 +00001011000000000000001011001100 +00001100101100110000000000101100 +01000000000010000000000000000010 +00001100000000001000001100000000 +10100000000000000000101000000000 +00000010000000100000000100000000 +00000000000000000000000000000000 +00000000000011010110000000000000 +11001000000000000011111000000000 +00001111100000000000001111100000 +00000000111111110000000000111110 +11000000000011001000000000000011 +00100000000000001100000000000000 +00110010000000000010110010000000 +01000011000000000000001101010000 +00000000000000000000000000000000 +10100000000111011111000000000000 +11111101000000000011111100000001 +00001111110000000000001111110000 +00000000111111110000010000111111 +01000000000011111100000000000011 +11110000000000001111110000000000 +00111111000000000000111111000000 +00000011111010000000011001110000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11111111100000000111101111010000 +00001100011100100000001111111100 +00000000010011111000000000111111 +11001000010011001111001100000011 +00111110000000001111111110000000 +00110001111000000000110011011000 +01000011011100000000000001110000 +00000000000000000000000000000000 +10000000000100001110110000000000 +10111111110000000010001011010100 +00001000111111010000001011111101 +10100000101010111000010000101111 +11000100000010000111001000000010 +10100110000101001011101110000001 +01101010111000000000101010011000 +01010010001100000000010000110000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10110011000100000010100011001000 +00001000001100000100000011001101 +00000000100000010000000000101100 +11001010000010000011001100010010 +00001100000000001011101100000000 +00100100110000000000100000010000 +00000010011100100000000101110000 +00000000000000000000000000000000 +11000000000101011010110000010000 +10111011000000000010000011000000 +00001000101100000000001011101100 +00001000101010010000000000101110 +11000000000010001011000000000010 +10100100000000001011101100000000 +00101110110000100000101010010000 +00000010001100000000010001100000 +00000000000000000000000000000000 +01000000000101011110110000000000 +11111011000000000010101011000000 +01101000101100000000001111101100 +00000000110010110000000000111110 +11000000001011001011000000000011 +00101110010001001111001100000000 +00100110110100000000110010011000 +00000011010000000000010001110000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11111111000000000011111011000000 +00001111111100001000001111011100 +00010000111111111001010000111101 +11000000000011110111000000000011 +11110100000100001111111110010000 +00111011011100000000111111011001 +00000011111110000000000001100000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11110011000000000011001011000001 +01001110101100000000001100101100 +00000001110010010000100000111110 +11000000001011001011000000000011 +10101110000000001111101100001000 +00111110110000000000110010010000 +00000011110101000000010000100000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10111111011000010010001111000000 +00001000111101000000001000111100 +00000000101010010000000000101111 +11000000010010001111000000000010 +00100100000000001011101111000000 +00101100110000100000110100011000 +00000010111100100000000001000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10110011100010000010000011000001 +00101010001110010000001000001100 +00000000101000111100000000101100 +11000000000010000011000000000010 +00001100100000001011000101010000 +00101100110000000000100000011001 +00000010111110100000000001010000 +00000000000000000000000000000000 +00100000000000010001111000000000 +10110111100000000010000111100000 +00001000011110000100001000011110 +01000000101001111000100000101100 +11100000000010000111100000000000 +00011110000000001011011110000000 +00101111111000000000100101011000 +00000010111111000000000001000000 +00000000000000000000000000000000 +01001000000010000000110000000000 +11110011000000000011000011000000 +00001110001100000000101100101100 +00000000100000110000001000111100 +11000000000011000011000000000011 +00001100000000001111000100000000 +00111100110000000000110000010000 +00000011110100100000001000000000 +00000000000000000000000000000000 +01000000000111011010110000000000 +11110011000000001001111011000000 +00001111101101000000001111101100 +00000000010110110000000000111110 +11000010000011111011000010000011 +11101101001000001111101101001000 +00111110110000000000111110010001 +00000011110100000000011001100000 +00000000000000000000000000000000 +10101000000001011110110000000000 +11111011010000000011111011000000 +10001001001101010000001110101111 +01000000110010110011100000101110 +11010010000011111011010000000011 +11101101000000001011100101000000 +00111100110000000100110110010000 +00000001111010100000000001110000 +00000000000000000000000000000000 +01001000000100011001110000000000 +10110111010010000010110111001000 +00001000011100000100001000001100 +10100000101001110000000000101101 +11000000000010110111001010000010 +11011100000000001011011100000000 +00101101100000000000100001110000 +00000010111100100000010001100000 +00000000000000000000000000000000 +11000000000000001001111000000000 +10110111100000000010110011101100 +00001001011110100110001010011110 +00000000100001111000000000101101 +11101000010010110111100000100010 +11011110100000001011010110000001 +00101011111000010000100101011000 +00000010111000000000000000100000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110011000000000010111011000000 +10001000001100000000001000001100 +00000001101000110000000000101100 +11000000000010111011000000000010 +11001100000001001011001100000000 +00101100111100100101100000111000 +00000010110100100000010000110000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11111010000000000011111010000000 +00001101101000000000001110101000 +00000000100010100000000100111110 +10000000000011111010000000000011 +11101000000000001111101000000000 +00111011100000100000110110101010 +00000011111110100000010001100000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011111000000000 +00001111000000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100001000100 +00111110000000000000111110000000 +00000011110100100000000000110000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000000000011111001000000 +00001100100100000000101100100100 +00000000111110011000000000111110 +01000000000011001001000000000011 +00100100000000001100100100010000 +00111110010000000010110010011000 +00000011110000100000010000110000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001010000000010111001000000 +00011000100101000000001000100100 +00000000001110111001000000101110 +01000000010010001001000000000010 +00001100000000001101101101001000 +00101100010000000100100010010000 +00000010111000000000000000010000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010111001000000 +01101000100100000000001000100100 +00000000001110010100000000101100 +01000000000010101001000000000010 +00100100000000001000100100000000 +00101110010010000000100010010001 +00000010110001100000000001000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001001000000010110001001000 +00001000000100100000001000000100 +10000100101100010000000000101100 +01001000000010100001001000000010 +00100110000000001001000100000000 +00001110010000000000100000010000 +00000010110000100000000100000000 +00000000000000000000000000000000 +10111000000011010110000101000000 +11111010000000000011111000010100 +00001000101000000100001100100001 +01000000111110000000000000111110 +00010100001011101000010100000011 +00100000000000001100100000000000 +00111110000000000000110010000000 +00000011111011100000001101010000 +00000000000000000000000000000000 +10011000000111011110010000000000 +11111001000100000010111001000100 +00001111100100010000001111100100 +01000000111110010000000000111110 +01000100000011011001000100001011 +11100100000000001111100100000100 +00111111010000000100111111010000 +00000011111001100000011001110000 +00000000000000000000000000000000 +00011000000001011110010001000000 +11001101000000000011101001000100 +00001101110100100000001111100100 +10000100110010010000000100111110 +01001001000010111001010000000011 +11100100000100000011100100000000 +00111111010000000000110001010000 +00000011111001100000000001110000 +00000000000000000000000000000000 +00111000000100001110000000000000 +10001000010100000010001000010100 +00001000100001000000001011100000 +00010000100010000000000000101110 +00011010000010111000000001000010 +11100000000000001011100000000000 +00101110000000000000101010000000 +00000010110011100000010000110000 +00000000000000000000000000000000 +00001000000001011100010010000000 +10000001000000000010100001001000 +00001000000100010000001011000101 +10100000100000010000000000101100 +01000100000010110001010000000010 +11000100000000001011000100000000 +00101110010000000000100000010000 +00000010110100100000000101110000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10001001000000000010001001000000 +01001000100100000000001011000100 +00000110100010010000000001101110 +01000000000110111001000000000010 +11100100000000001011100100000000 +00101110010000000001101010010000 +00000010110001100000010001100000 +00000000000000000000000000000000 +10100000000101011110010000000000 +11001001000000000011101001000000 +00001100100100000000001111100100 +00000000100010011000000000111110 +01000000100011111001000000000010 +11100100000000001111100100000000 +00111110011001100000110010010000 +00000011111010000000010001110000 +00000000000000000000000000000000 +00101000000000011010010000000010 +11110001000000000010110001000000 +00101110100100001000001111100100 +00000000111110010001000000111110 +01000000000011111001000001000011 +11100100000000001111100100001000 +00111110011000000000111110010000 +00000011110110100000000001100000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000000000011111000000001 +00000000100000000001001111100000 +00000001111110000000000100111110 +00000000001011001000000000000011 +11100000000000001111100000000100 +00111110000000000000110010000000 +00000011100010100000010000100000 +00000000000000000000000000000000 +00101000000001010010100000000000 +10111110000110000010111010000000 +00001000111000000000001011101000 +00000000101110100000100000101110 +10000000000010001010000000000010 +11101000000000001011101000000000 +00101100100000000000110110101000 +10000010000010100000000001000000 +00000000000000000000000000000000 +00101000000001010110110000000000 +10110011000000000010110011000000 +00101000001101010000001011001100 +00000000101100110000000000101100 +11000000000010010011000000000010 +11001110000000001011001100000000 +00101100111000000000100100110000 +00000010100010100000000001010000 +00000000000000000000000000000000 +10100000000000010001110000000000 +10110110000000000010110011001000 +00001000011100000000001011011100 +00000000101101010000000000101101 +11100000000010010111001100000010 +11010000001000001011011100000000 +00101111110000110000100111111000 +01000010001010000000000001000000 +00000000000000000000000000000000 +10101000000010000001111100000000 +11110111100000000011110111100000 +01001100011110000000001111011110 +00000000101101101000001000111111 +11100001010011010111100100010001 +11011110001001001111011110000000 +00111101111000000000110101111000 +00000011101010100000001000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111010000000000011111011011101 +01001111101000000000001111101100 +00000100111110110110100000111110 +11010000000011101011000000000001 +11100000100000001111100001101000 +00111100010000000000111110110000 +00000011110000100000011001100000 +00000000000000000000000000000000 +00000000000001011111111000000000 +11111111100000000011101111110000 +10001100111010010000001111111111 +00100000111111111001000000110011 +11110010000011111111100001000011 +11111110000001001111111010000000 +00111111111000000000110011111000 +00000011110100000000000001110000 +00000000000000000000000000000000 +10101000000100011001110001000000 +10110101000000000010000111000100 +00001000010100000000001011011100 +00000000101101010000000000101001 +11000100000010110111000000000010 +11010000000000001011011100010000 +00101101110001010000101001110001 +00000010111010100000010001100000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110110000000000010100111000000 +00101000011000000000001011011100 +00000000101111000000000001100001 +11000000000010010111000000000010 +11011100000000001011011000000000 +00101111110000000000100001110000 +10000010110001000000000000100000 +00000000000000000000000000000000 +00100000000101001100110000000000 +10110000000000000010000011000000 +00001000000000000000000011001100 +00000001101100010000000001101000 +11000000000010110011000000000010 +11000000000000001011000000010000 +00101100010100000000101000111000 +00000010110110000000010000110000 +00000000000000000000000000000000 +10101000000101011011110000000000 +11111001000000000011101111000000 +00000100100100000000001011111100 +00000000111110110000000000110011 +11000000000011011111000000000011 +11101110001000001111100110000000 +00111100111100100001110010110000 +00000011111010100000010001100000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11111000000001000011111011000000 +00001111100100000000001111101100 +00000000111110000100000000111110 +11000000000011110011000000000011 +11101100000000001111100100000001 +00111110110010000000111110110000 +00000011111001000000000000110000 +00000000000000000000000000000000 +00000001000100001111110000000000 +11111101100000000011110011000000 +10001100010100000000101100111100 +00000000111111100000000000111111 +11000000000011111111000000000011 +00111000000000001111111111000000 +00011111110010000000110011111000 +00000011111000000000010000110000 +00000000000000000000000000000000 +10000001000001000110110000000000 +10111000100000000010111011000001 +01001000100000000000001000101100 +00000000101110100000010000101110 +11000000000010111011000000000010 +00101000011001001011100010000000 +00101110011000000000100010111001 +00000010111000010000000000010000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000100000010111011000000 +00001000101000010000001000101100 +00000000101010110100000000101010 +11000000010010111011000000000110 +00100100000000011011100000000000 +00101110010000000000100010110000 +00100010111000000000000001000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10110001000000000010110011000000 +00101000000100000000001000001100 +00000000101100000000000000101100 +11000000000010110011000000001000 +00000100000000011011000100000000 +00101110010000000000100000110000 +00000010110000100000000100000000 +00000000000000000000000000000000 +00000000000011010110110000000000 +11111010000000000011111111000000 +00001100101000000000011100111100 +00000000111010000000000000111011 +11000000000011111111000000000011 +00100000000000001111101000000001 +00111110010000000010110010110000 +00000011111000000000001101010000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11110100000000000011111111000000 +00000111110000000000001111111100 +00000000111101000000000100111111 +11000000000011111111000000000010 +11110000000000001111110000000000 +00111101010000000000111111010000 +00000011111010000000011001110000 +00000000000000000000000000000000 +11000000000001011111001000000000 +11111100100000100011001100100001 +00001100110010000000001111010110 +00010000110011011000000000110001 +01100000100011001100100000000011 +11110000000000001100110000000000 +00110011110001000000110011101000 +00010011001100000000000001110000 +00000000000000000000000000000000 +10000000000100001110111000000000 +10111011100000100010001000100000 +00001000101010000000001011100110 +00000000100010000000000000100010 +01000000000010001010100000000010 +11101010000000101000100100000000 +00101011110000001000100010101000 +00000010001000000000010000110000 +00000000000000000000000000000000 +10001000000001011100000000000001 +10110000000000000010000000100000 +00001000000000000000011011000000 +00000000100010000000000000101000 +01000000001010000010000000100010 +11000100000000001000000000000000 +00100000110000000010100000100000 +00001010001000100000000101110000 +00000000000000000000000000000000 +11000000000101011010110000000001 +10111011000000100010001000000000 +01001000101000000000001011100010 +00000000100010011000000000101010 +11000000000010001010100000000010 +11100100000000101000100000000010 +00101010110000000010100010100000 +00000010001100000000010001100000 +00000000000000000000000000000000 +00000000000100011110000100100000 +11111000000000000011001001000000 +01001100100100000000001111100010 +00000000110000011010000000111000 +01000000000011001000110000000011 +11100000100000101100100010010000 +10110010110000000000110000101001 +10000011000100000000010001110000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11111110000010100011111100010000 +00001111111000000010001011110100 +00000000111111010000001000110111 +01000000000011111100000000000011 +11101000000000001111011100000000 +00111110110000010000111111110000 +00000011111110000000000001100000 +00000000000000000000000000000000 +01000000000100001010000001000000 +11111001000000000000111011000000 +00001111100101000010001111100100 +11000000110010000000000000111110 +11001000000011001000011000000001 +11001101000001001100100100100000 +10110000110000000010110010110100 +10000011110100000000010000100000 +00000000000000000000000000000000 +11001000000001010010111000010000 +10110011010000010010110010110100 +01001011101000000000001110000100 +00000000100010010000000000001110 +11010000001010001000001000000010 +11101111001000001000101100000000 +00100011110111000010100010111100 +10000010111100100000000001000000 +00000000000000000000000000000000 +11100000000001010100001000000000 +10110000100000000010110010010001 +00001011000000000000001011000101 +00000000100000010000000000101100 +01010100000010000000010000000010 +11000001001000001000001001000000 +00100000110000000000100000001000 +00000010111110000000000001010000 +00000000000000000000000000000000 +01100000000000010001101000000001 +10110111100101000010110111100010 +00001011011110000000001010111110 +00000000100001101000001000101101 +01100100000010000110100000000010 +11011010000000001000010110011000 +00100001111001000000100001001000 +00000010110010000000000001000000 +00000000000000000000000000000000 +01001000000010000000000000000000 +11110000000010000011110010000000 +00001111000001000000001111001100 +00000000110000110000000000111100 +01000100000011000010010100000011 +11000000000000101100101000010001 +01110000110001000100110000100000 +01000011110100100000001000000000 +00000000000000000000000000000000 +01000000000111011011100000000000 +11111111000000000011111111010000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000100000010111110000000000011 +11110000000000001111110000010000 +00111111110001100000111111100100 +00000011110100000000011001100000 +00000000000000000000000000000000 +10101000000001011110010000000000 +11110000110000000011001001001000 +00001111000111100000001100101000 +00000000111110110000000000110010 +01000000010011001000000000000011 +11100100000000101100101000000000 +10110000110010000000110010010110 +00000011111010100000000001110000 +00000000000000000000000000000000 +01001000000100011001110001000000 +10110110000100000010000101000000 +00001011011100001000001000011100 +00000000101111010000000000110111 +01000000000010000110000000000010 +11011100000000001000011100000000 +00100001110011000000100001010000 +00000010110100100000010001100000 +00000000000000000000000000000000 +11000001000000001001011000000001 +10111101100000000010100111110000 +00001011110110000000001001010110 +00100000101101111000000000100001 +11100000000010000110110000000010 +11001110000000001010001110000000 +00100001111010000000100001111000 +00000010111100000000000000100000 +00000000000000000000000000000000 +01001000000101001100110100000000 +10110011000000000010000011000000 +00001011001100000000001001001100 +00100100101110111111000000100100 +11100000000010000011100000000010 +11001110010000001010001101110000 +00100000110000000000100000110000 +00000010110100100000010000110000 +00000000000000000000000000000000 +11101000000101011000100100000000 +11111010010000000011101010000000 +00001111101001000000001101111010 +00000000111111100100000000110010 +10101000001011001110100000000011 +11111001000010001110111011000000 +00110010100000000000110010100100 +00000011111110100000010001100000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000010001011111000110000 +00001111100000001000101110100001 +00000000111110000000000000111110 +00000000001011111000000000000011 +11100000001000000001000000000000 +00111110000000000010111110001000 +00000011110100100000000000110000 +00000000000000000000000000000000 +00001000000100001110110000100000 +11011011010000000011111011000000 +00001111101110000000001111100100 +01000000101110010000000000110010 +01000000000011001001000010000011 +11000110100000001100100100000011 +00110000010000001000110010111000 +00000011110000100000010000110000 +00000000000000000000000000000000 +10000000100001000110010000000000 +10001001010000000010111001011000 +00001011100110000000001011100111 +00000000101110010000001000100000 +01100000000010001001000000000010 +11100110000000101000100101000010 +00100010010000000010100010011100 +00000010111000000000000000010000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10011001000010000010111001000100 +00001011100100100000001011101100 +00000000101110010000000010100010 +01001000000010001001001001000010 +11100101000000001000100101000000 +10100010010000000000100010010010 +00000010110001100000000001000000 +00000000000000000000000000000000 +00001000000001000010010000000000 +10000001000001000010110001000000 +00001011000100000010011011000100 +00000000101100010000000000100010 +01000000000010000001000000000010 +11000100100000101000000100100000 +00100000010010000000100000011000 +00000010110000100000000100000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11011000000000000011111000000000 +00001111100000000000001111101000 +00000100111110000101000000110010 +00010100000011001010000000010011 +11100000000000001100100001010000 +10110010000101000000110010000000 +00100011111011100000001101010000 +00000000000000000000000000000000 +10011000000111011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111110100 +00000000111111010000000000111111 +01000000001011111101000000000011 +11110100010000001111111100010000 +00111110010001000010111111010000 +00000011111001100000011001110000 +00000000000000000000000000000000 +10011001000101011100010000000000 +11111101000000010011111101000000 +00001100100100000000001111110100 +00000000111110010100000000111101 +01000000000011000101000000000011 +00110100001000001100110100000000 +00110011010110100100110010010000 +00000011110001100000000001110000 +00000000000000000000000000000000 +00111001000110001110000000010000 +10111000000000100010111000000000 +10001101100000000000001011101000 +00001000101110000000001000101110 +00000000000010001000000000000010 +00100000000000001000000001100000 +10100010000100000010101010000000 +00000010110011100000010000110000 +00000000000000000000000000000000 +00001000000001011100010000001000 +10110001000000000010111001000000 +00001000000100000010011011000100 +00000000101100010010000000101100 +01001010000010000001100000011010 +00000100000000101000000101001000 +10100000010000000010100000010000 +00000010110000100000000101110000 +00000000000000000000000000000000 +00011000000001011010010000000000 +10111001010000000010111001000000 +00001001100100000000011011100100 +01000000101110010010000100101110 +01001000001010001001000000000010 +00100101000000001000100100000010 +00100010010000000000101010010010 +10000010110001100000010001100000 +00000000000000000000000000000000 +10100000000101001010010000000000 +11111001010000100011111001000001 +00001100100100000000001111100111 +00000000111110010010000000111110 +01000000010011000001010000000011 +00100110000001001100100101000000 +10110010010000000010110010010000 +00000011111010000000010001110000 +00000000000000000000000000000000 +00101010000000001010110000001100 +11111001000000000011111001001000 +00001111101100000000001011100100 +00010000111110011000000000111110 +01100000100011111001001000000011 +11100111000000001111100100001010 +00111110010000000000111110110000 +00000011110010100000000001100000 +00000000000000000000000000000000 +00101010000100001010000000000000 +11001000001000000011111000000000 +00001111100000000000001111100010 +01000000101110000000000000111110 +00000000000011001000000010000011 +00000000000000001111100001000000 +10110000000000000010110010000000 +00000011000010100000010000100000 +00000000000000000000000000000000 +10100000100001000010100000000000 +10001110000000000010110110101000 +00001011101000000000000011111000 +00000000101110100000000000101111 +10100010001010001110010010001010 +00111010010000001011111011000000 +00100011100000001000110110100000 +00000010000010100000000001000000 +00000000000000000000000000000000 +00101000000001010100111001000000 +10000011000000000010110011100010 +01001011001110010000000011001100 +00000000101100110000000000101110 +11100000000010000011010000000110 +00001000010101001011101110000000 +00100000001000000000100000110010 +00100010000010100000000001010000 +00000000000000000000000000000000 +01100001000000010001111000000000 +10000101010000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +01000000000010001111000000000010 +00011100000000001011011101000000 +00100000010100000010100111111000 +00000010001010000000000001000000 +00000000000000000000000000000000 +00101000000010000001111000000000 +11000111100000000011110111100000 +00001111011110000000001111010110 +00000000101101111010001000111101 +11100000000011000111100000000011 +00011110000000001111011110000000 +00110001001000000010110001001000 +00001011001010100000001000000000 +00000000000000000000000000000000 +01001000000111011010110000101010 +11111010000000100011111010000000 +10001111101100000000001111101100 +00000000111110110000000000111110 +01000000000011111001000000000010 +11101100000000001111101000000000 +00111110010000000000111100000000 +10000011110000100000011001100000 +00000000000000000000000000000000 +11000000000001011111011000000000 +11111111100100000011111101100100 +00001111110111010000001111111110 +01000000111111111000100000111111 +11100000000011001111100000000011 +11111110010000001100111010000000 +10110011101000001000110011111000 +00000011000000000000000001110000 +00000000000000000000000000000000 +10101000000000011001110100000000 +10110111000000000010110111000000 +10001011010101000000001011011000 +00000000001101110000000000101111 +11000000000010000111000000000010 +11011100000000001101010100000000 +00110101010000000000101001110000 +00000010101010100000010001100000 +00000000000000000000000000000000 +00011001000000001001010000000000 +10110111000000010010110111000000 +00011011010100000001001011011100 +00000001101101110000000000101101 +11000000000010100110000000000010 +11001100001010001001011000000000 +00100001100000000000100001000000 +00000010000000000000000000100000 +00000000000000000000000000000000 +01100010000101001100110001001001 +10110001111000000010110000010000 +00001011000100100000001011000100 +10000001100100111100000000101100 +11000000000010100000010000000010 +11001110000000001001000000100010 +00100100010000000000101000000000 +10000010100010000000010000110000 +00000000000000000000000000000000 +11111000000101011010100000000000 +11111001000000000011111001000000 +00001111101010100000001111100101 +00000000111111110000000000111110 +10000000001011101011000100000011 +11001110000000001101100101000000 +00110010000000000000110010000000 +00100011001010100000010001100000 +00000000000000000000000000000000 +10000000000000001110000100100000 +11111001010100000011111001010000 +00001111101001000000001111100101 +01000000111110110011000000111110 +01010100100001011010100000000011 +11101101000000001111001100010000 +00111110000100000000111110100100 +00000011111000000000000000110000 +00000000000000000000000000000000 +11000001000100001111101000000000 +11111101000000100011111101000010 +00001111110000000000001100110000 +00000000111111110000000001111111 +00000000000011001111000100000011 +11111100000000001100110110010100 +00110001000000000000110011000000 +00000011000000000100010000110000 +00000000000000000000000000000000 +10000001000001000110001000000000 +10111000110001000010011001100001 +00001011000000000000001000100110 +10000000110010110000001001111100 +01101000001010001000011000000010 +01101111100000001000101010000010 +00100010000100001000100000000000 +00000011001000000100000000010000 +00000000000000000000000000000000 +10000000000000010110000001000000 +10111000110000000010111000100010 +00001011101000100000101000100110 +00000000101110110000010000101110 +10100000000010001001000000000010 +11100110000001001000100000000000 +00100010100000100000100010000110 +00000010001000000000000001000000 +00000000000000000000000000000000 +00001000000000000000000000000000 +10110001000000000110010001000000 +00001011001000000000001000000000 +00001000101000110000001000101000 +11000000000010000000000000000010 +01001100000000001000000100000000 +10100000000000001100100000110000 +00000010000000100000000100000000 +00000000000000000000000000000000 +10000000000000000110000000000000 +11111000000000000011111000000000 +00001111100000000000001100100000 +00000000111110110000000000101110 +00000001000011001000000000000011 +11101100000001001100000000000000 +10110000100000000100110010000000 +00001011000000000000001101010000 +00000000000000000000000000000000 +10100000010110011111000000010000 +11111101000000000011011101000000 +00001111110000000000001111110100 +00001000110011110000000000111111 +01000000000011111100000000000011 +01111100000010000111110000000000 +00111111000000000000111101000000 +00000011101010000000011001110000 +00000000000000000000000000000000 +00000000110001010100000100000011 +01110000010000001001110001010000 +00000111000001000000110111000101 +00000001011100010100000011011100 +00010000001101110000010000001101 +11000101000000110111000101000000 +11011100000100000011011100000100 +00001101110000000011000100000000 +00000000000000000000000000000000 +00000000110001010100010000000101 +01110001000000010101110001000000 +01110111000100000001010111000100 +00000101011100011000000101011100 +01000000010001110001000000010101 +11000100000001010111000100000001 +01011100010000000101011100010000 +00010101110000000011000101010000 +00000000000000000000000000000000 +00000000100000000000001000000001 +00100000100000000100100001100000 +00010010000010000000010010000110 +00000001001000001000000001001000 +00100000000100100000100000000100 +10000010000000010010000110000000 +01001000001000000001001000001000 +00000100100000000010000000000000 +00000000000000000000000000000000 +00000000100000000000000000000001 +01100000000000000101100000000000 +00010110000000000000010110000000 +00000101011000010000000001011000 +00000000000100100000000000000101 +10000100000000010110000000000000 +01011000000000000001011000000000 +00000101100000000010000000000000 +00000000000000000000000000000000 +00000000110001010100100000000101 +01110010000000010101110010000000 +01010111001000000001010111001001 +00000101011100100000000101011100 +10000000010101110011000000010101 +11001010000001010111001000000001 +01011100100000000101011100100000 +00010101110000000011000101010000 +00000000000000000000000000000000 +00000000110001010100000000000000 +01100000000000000001100001000000 +00000110000000000000000110000010 +00000000011000000000000000011000 +00000000000001100000000000000001 +10000000000000000110000101000000 +00011000000000000000011000000000 +00000001100000000011000100000000 +00000000000000000000000000000000 +00000000110001010100100000000100 +00100010000000010000100000100000 +01000010001000000001000010000100 +00000100001000100000000100001000 +10000000010000100011000000010000 +10001000000001000010001110000001 +00001000100000000100001000100000 +00010000100000000011000100000000 +00000000000000000000000000000000 +00000000110001010100111100000101 +01000010100000010101000001110000 +00010100001010000001010100000010 +00000001010000101000000101010000 +10100000010101000010100000010101 +00001010000001010100001010000001 +01010000101100000101010000111100 +00010101000000000011000101010000 +00000000000000000000000000000000 +00000000100000000000111000000001 +00010011000000000101010111000000 +00010001011100000000010101001100 +00000001010100110000000000010101 +11000000000101010111000000000101 +01001100000000010101011100000000 +01000000110000000001000100110000 +00000100010000000010000000000000 +00000000000000000000000000000000 +00000000100000000000010000000000 +00010000000000000001000001000000 +01000001000000000000000100001100 +00000000010000000000000000010000 +00000000000001000001000000000001 +00000000000000000100000100000000 +00000000000000000000000100011000 +00000000010000010010000000000000 +00000000000000000000000000000000 +00000000110001010110000000000010 +00011000000000001000001000000000 +00100001100000000000100000100000 +00000010000010000000000010000010 +00000000001000001000000000001000 +00100000000000100000100000000000 +10000010000000000010000110000000 +00001000010000010011000101010000 +00000000000000000000000000000000 +00000000110001010100000000000101 +01100000000000010101100100000000 +01010110010000000001010110000000 +00000111011000000000000101011001 +00000000010101100100000000010101 +10000000000001010110010000000001 +01001000000000000101011000000000 +00010101100000000011000100000000 +00000000000000000000000000000000 +00000000110001010100000000000011 +01100000000000001101100000000000 +00010110000000000000110110001000 +00000001011000000000000011011000 +00000000001101100000000000001101 +10000000000000110110000000000000 +11011000000000000011011000000000 +00001101100000000011000100000000 +00000000000000000000000000000000 +00000000110001010100001000000100 +00110000100000010000110000100000 +01100011000010000001000011000011 +00000100001100001000000100001100 +00100000010000110000100000010000 +11000010000001000011000010000001 +00001100001000000100001100001000 +00010000110000000011000101010000 +00000000000000000000000000000000 +00000000100000000000000000000000 +00110000000000000000110010000000 +00000011000000000000000011000000 +00000000001100000000000000001100 +00000000000000110000000000000000 +11000000000000000011000000000000 +00001100000000000000001100000000 +00000000110000000010000000000000 +00000000000000000000000000000000 +00000000100000000000001000000001 +00110000100000000100110010110000 +00010011000010000000010011000010 +00000101001100001000000001001100 +00100000000100110000100000000100 +11000010000000010011000010000000 +01001100001000000001001100001000 +00000100110000000010000000000000 +00000000000000000000000000000000 +00000000110001010100001000000101 +01100000100000010101100000110000 +01010111000010000001010110000011 +00000101011000001000000101011000 +00100000010101100000100000010101 +10000010000001010110000010000001 +01011000001000000101011000001000 +00010101100000000011000101010000 +00000000000000000000000000000000 +00000000110001010100001000000000 +00100000100000000000100000100000 +00000110000010000000000010000010 +00000000001100001000000000001000 +00100000000000100000100000000000 +10000010000000000010000010000000 +00001000001000000000001000001000 +00000000100000000011000100000000 +00000000000000000000000000000000 +00000000110001010101001000000100 +01100000100000010001100100100000 +01000010000010000001000110010010 +00000100001100001000000100011000 +00100000010001100100100000010001 +10000010000001000110010010000001 +00011001001000000100011001001000 +00010001100000000011000100000000 +00000000000000000000000000000000 +00000000110001010110000000000101 +01011000000000010101011000000000 +00010001100000000001010101100000 +00000000000110000000000101010110 +00000000010101011000000000010101 +01100000000001010101100000000001 +01010110000000000100010110000000 +00010101010000000011000101010000 +00000000000000000000000000000000 +00000000100000000000011000000001 +01000001100000000101000001100000 +00010100000110000000010100000110 +00000001010000011000000001010000 +01100000000101000001100000000101 +00000110000000010100000110000000 +01010000011000000000010000011000 +00000100000000000010000000000000 +00000000000000000000000000000000 +00000000100000000001001000000001 +00000000100000000100000100100000 +01010000000010000000010000010010 +00000001000000001000000001000000 +00100000000100000100100000000100 +00000010000000010000010010000000 +01000001001000000001000001001000 +00000100000000000010000100000000 +00000000000000000000000000000000 +00000000110001010100011000000011 +01010001100000001101010001100000 +00110101000110000000110101000110 +00000011010100011000000011010100 +01100000001101010001100000001101 +01000110000000110101000110000000 +11010100011000000011010100011000 +00001001010000000011000101010000 +00000000000000000000000000000000 +00000000110001010100011000000101 +01110001100000010101110001100000 +01010111000110000001010111000110 +00000111011100011000000100011100 +01100000010101110001100000010001 +11000110000001010111000110000001 +01011100011000000101011100011000 +00010101110000000011000100000000 +00000000000000000000000000000000 +00000000010001010100011000000011 +01110001100000001101110001100000 +00010111000110000000110111000110 +00000000011100011000000011011100 +01100000001101110001100000001001 +11000110000000110111000110000000 +11011100011000000011011100011000 +00001101110000000001000100000000 +00000000000000000000000000000000 +00000000010001010100011000000101 +01110001100000010101110001100000 +01100111000110000001010111000110 +00000000001100011000000101011100 +01100000010101110001100000010101 +11000110000001010111000110000001 +01011100011000000101011100011000 +00010101110000000001000101010000 +00000000000000000000000000000000 +00000000000000000000001000000001 +00100000100000000100100000100000 +00010010000010000000010010000010 +00000001011100001000000001001000 +00100000000100100000100000000100 +10000010000000010010000010000000 +01001000001000000001001000001000 +00000100100000000000000000000000 +00000000000000000000000000000000 +00000000010000000000011000000001 +01100001100000000101100001100000 +00010010000110000000010110000110 +00000101011000011000000001011000 +01100000000101100001100000000001 +10000110000000010110000110000000 +00011000011000000000011000011000 +00000101100000000000000100000000 +00000000000000000000000000000000 +00000000010001010100000000000101 +01110000000000010101110000000000 +01010111000000000001010111000000 +00000101011100000000000100011100 +00000000010001110000000000010100 +11000000000001010111000000000001 +01001100000000000100011100000000 +00010101110000000001000101010000 +00000000000000000000000000000000 +00000000010001000100001000000000 +01100000100000000001100000100000 +00000110000010000000000110000010 +00000000011000001000000000011000 +00100000000001100000110000000000 +10000010000000000110000011000000 +00001000001000000000011000001000 +00000001100000000001000100000000 +00000000000000000000000000000000 +00000000010001010100001000000100 +00100000100000010000100000100000 +01000010000010000001000010000010 +00000100001000001000000100001000 +00100000010000100000100000010001 +10000010000001000010001010000001 +00011000001000000100001000001000 +00010000100000000001000100000000 +00000000000000000000000000000000 +00000000010001010100001000000101 +01000000100000010101000000100000 +00010100000010000001010100000010 +00000001010000001000000101010000 +00100000010101000000100000010101 +01000010000001010100000010000001 +01010100001000000101010000001000 +00010101000000000001000101010000 +00000000000000000000000000000000 +00000000000000000000001000000001 +01010000110000000101010000100000 +00010101000011000000010101000011 +00000001010100001100000001010100 +00110000000101010000110000000101 +01000011000000010101001010000000 +01010100001100000001010100001000 +00000101010000000000000000000000 +00000000000000000000000000000000 +00000000010000000000100000000000 +01000010000000000001000010000000 +01000100001000000000000100001000 +00000000010000100000000000010000 +10000000000001000000000001000001 +00001000000000000100000000000000 +00010000100000000000010000100000 +00000001000000000000000000000000 +00000000000000000000000000000000 +00000000010001010100001000000010 +00100000100000001000000000100000 +00100000000010000000100000000010 +00000000000000001000000010000000 +00100000001000000010100000001000 +00000010000000100000000010000000 +10000000001100000010000000001000 +00001000000000000001000101010000 +00000000000000000000000000000000 +00000000010001000100000000000101 +01100000000000010101100000000000 +01010110000000000001010110000000 +00000111011000000000000101011000 +00000000010101100000000000010101 +10000000000001010110000000000001 +01011000000000000101011000000000 +00010101100000000001000100000000 +00000000000000000000000000000000 +00000000110001010100000000000011 +01100000000000011101100000000001 +01010010000000000000110110000000 +00000001011100000000000011011000 +00000000001101100000000000001101 +10000000000000010110000000000000 +11011000000000000011011000000000 +00001101100000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000100000100 +00110000000000000000110000010000 +01000010000000000001000011000000 +00000100011000000000000100001100 +00000000010000110000000000000000 +11000000000000000011000000000001 +00001100000000000100001100000100 +00010000110000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00110000000000000000110101000000 +00000010000110000000000011010000 +00000000001001000000000000001100 +01000000000000110001000000000000 +11010000000000000011010110000000 +00001100000000000000001100000000 +00000000110000000000000000000000 +00000000000000000000000000000000 +00000000000000000000010100000001 +00110001010000010100110001110000 +01010010000101000000010011000101 +00000101001100010100000001001100 +01010000000100110001110000000100 +11000101000000010011000100100000 +01001100010000000001001100010100 +00000100110000000000000000000000 +00000000000000000000000000000000 +00000000000000000010001100000101 +01101000110000000101101000110000 +00010110100011000001010110100011 +00000101011010001100000101011010 +01110000010101101001110000010101 +10100011000001010110100011000001 +01011010001100000101011010001100 +00010101100000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00100000000000000000100101000000 +00000010000100000000000010010000 +00000000001001000000000000001000 +00010000000000100010000000000000 +10010000000000000010010100000000 +00001000000000000000001000000000 +00000000100000000000000000000000 +00000000000000000000000000000000 +00000000000000000000100001000100 +01100010000100000001100010000000 +00000110001000000001000110001000 +01000100011000100001000100011000 +10000000010001100000000110010001 +10001000010001000110000000010001 +00011000100001000100011000100001 +00010001100000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000001000101 +01010000000100000101010000000100 +00010101000000010001010101000000 +10000000010100000001000100010100 +00000100010101010000000001010101 +01000000010001010101000000011001 +01010100000001000101010100000001 +00010101010000000000000000000000 +00000000000000000000000000000000 +00000000000000000000100000100000 +01000010000010000101000010000010 +00000100001000001000010100001000 +00100001010000100000000001010000 +10000010000101000010000010000101 +01001000000000010100001000000000 +00010100100000100001010000100000 +10000101000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000101000000001 +00000010100000000100000010111110 +01010000001010000000010000001010 +01000001000000101000000001000000 +10100000000100000010100000000000 +00001010000000010000001010000000 +00000000101000000001000000101010 +01000100000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000110010000011 +01010011000000000101010011001110 +00110101001100000000110101001100 +01000011010100110000000011010100 +11000000001101010011000000000000 +01001100000000010101001100100000 +10000100110000000011010100110010 +00001101010000000000000000000000 +00000000000000000000000000000000 +00000000000000000000100010000101 +01110010000000010101110010010000 +01000111001000000001010111001000 +00000110011100100000000101011100 +10000000010101110010000000010101 +11001000000001100111001000001001 +00011100100000000101011100100010 +00010101110000000000000000000000 +00000000000000000000000000000000 +00000000000000000010001100001000 +01001000110001100001000000110000 +00000100000011000110000100100011 +00000000010010001100010000010000 +00110001100001000000110000100001 +00100011000100000100000011000000 +00010010001100001000010010001100 +00100001000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +01001111111111111101001111111111 +11110100111111111111110100111111 +11111111010011111111111111010011 +11111111111101001111111111111101 +00111111111111110100111111111111 +11010011111111111111010011111111 +11111101000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000010110111111011 +00001011001101101100001001011111 +11110100100100110110110000101100 +10011111010010110011011001000010 +01001101101100001111101001101100 +00101100110110010000111111111110 +01000010110011011011000010110111 +11101100000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011001111111100 +01001100110011110001001101011111 +11110100110101001111000100110010 +10111111010011001100111101000011 +01010011110001001111101011110001 +00110011001111010000111111111111 +01000011001100111100010011001111 +11110001000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011101100011110 +01001110110111111001001110010001 +10000100111001011111100100111010 +01111000010011101101111110000011 +10010111111001001000100111111001 +00111011011111100000100011000111 +10000011101100011110010011101100 +01111001000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000100000110 +01110000010001011001110001010000 +00110011000001000000110111000101 +00000001011100010100000000011100 +00010000001001110000010000001001 +11000001000000100111000001000001 +00011100000100000110011100010100 +00000001110000000000000000000000 +00000000000000000000000000000000 +00000000000000000000010000000001 +01110001000000010101110001000000 +00010011000100000001010011000000 +00000111001100000000000101011100 +01000000010101110001000000010101 +11000100000001010111000100000001 +01011100010000000101011100010000 +00000101110000000000000000000000 +00000000000000000000000000000000 +00000000000000000000001000000001 +00100000100000000100100000100000 +00010010000010000000000010000010 +00000000001000001000000001001000 +00100000000100100000100000000100 +10000010000000010010000010000000 +01001000001000000001001000001000 +00000100100000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000100 +01100000000000010001100101100000 +00000110000000000000000110010010 +00000000011001000000000100011000 +00000000000001100000000000000001 +10000000000000000110000000000000 +00011000000000000100011000010000 +01000001100000000000000000000000 +00000000000000000000000000000000 +00000000000000000000100100000000 +01110010000000000001110010000000 +00010010001000000001000111001000 +00000100011100101000000100011100 +10000000010001110010010000010001 +11001000000001000111001000000001 +00011100100000000100011100101000 +00010001110000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01100000000000000001100100000000 +01000110000000000000000110010000 +00000000011001000000000000011000 +00000000000001100000000000000001 +10000000000000000110000000000000 +00011000000000000000011000000000 +00000001100000000000000000000000 +00000000000000000000000000000000 +00000000000000000000100000000000 +00100010000000000000100100000000 +01000010001000000001000010010000 +00000100001001000000000100001000 +10000000010000100010000000010000 +10001000000001000010010000000001 +00001000100000000100001001100000 +00010000100000000000000000000000 +00000000000000000000000000000000 +00000000000000000010111100000000 +01001010110001000001001000100000 +01000100101010000001000100100011 +00000000010010001000000000010010 +10100000010001001010000000010001 +00101010000001000100100011000001 +00010010101100000000010010101100 +00010001000000000000000000000000 +00000000000000000000000000000000 +00001000110000000000110000000000 +00010010000000000000010010000000 +00000000001100000000000101001000 +00000000000100110000000000010100 +11000000000001010011000000000100 +00001100000000000101001100000000 +01000000110000000000000100110000 +00000000010000000001000000000000 +00000000000000000000000000000000 +00000000110000000000010000000000 +00010001100000000000010101100000 +00000000000000000000000100010110 +00000100000101100000000000011000 +00000000000001000001000000000001 +00000000000000000100010000000001 +00000100000000000000000101000000 +00000000010000000011000000000000 +00000000000000000000000000000000 +00001000110000000100000000000000 +00010000000000001000010000000000 +01100000000000000000100000000000 +00000010000100000000000010000000 +00000000001000000000000000001000 +00000000000000100000000000000000 +10000000000000000010000100000000 +00000000010000000011000000000000 +00000000000000000000000000000000 +00001000110000000100000000000100 +01100000000000010001100000000000 +01000010000000000000000110000000 +00000000011000000000000110011000 +00000000010001100000000000010001 +10000000000001000110000000000001 +00011000000000000100011000000000 +00111001100000000011000000000000 +00000000000000000000000000000000 +00010000000000000100000000000000 +01100000000000100001100000000000 +00100110000000000000100110000000 +00000000011000100000000000011000 +00000000001001100000000000001001 +10000000000000100110000000000000 +00011000000000000010011000000000 +00001001100000100000000000000000 +00000000000000000000000000000000 +01000000010001010100001000000000 +00110000100000000000110000100000 +00000011000010000001000011000010 +00010110001100001000000100001100 +00100000010000110000100000010000 +11000010000001000011000010000001 +10001100001000000100001100001000 +00010000110000000001000101010000 +00000000000000000000000000000000 +01000000010000000000000000000000 +00110000000000000000110010000000 +00000011000000000000000011001000 +00000000001100000000000000001100 +00000000000000110000000000000000 +11000000000000000011001000000000 +00001100000000000000001100000000 +00000000110000000001000001000000 +00000000000000000000000000000000 +01000000000000000000001000000000 +00110000100000000000110010110000 +00000011000010000000000011001011 +00000000001100001100000100001100 +00100000000000110000100000000000 +11000010000000000001001011000000 +00001100001000000000001100001000 +00000000110000000000000000000000 +00000000000000000000000000000000 +01000000010001010100000000000100 +01100000000000010001100000011000 +00000011000010000001000110000001 +00000100011100001100000100011000 +00100000010001100000100000010001 +10000010000001000110000011000001 +00011100001000000100011000001000 +00010001100000000001000101010000 +00000000000000000000000000000000 +01000000000000010100001000000000 +00100000100000000000100000100000 +01000010000010000000000010000010 +00000000011000001000000000001100 +00100000000000100000100000000000 +10000010000000000010000010000000 +00011000001000000000001000001000 +00000000100000000000000000000000 +00000000000000000000000000000000 +01010000000000000100001000000100 +01100000100000010001100000100000 +01000010000010000001000110000010 +00000100001000001000000100001100 +00100000010001100000100000010001 +10000010000001000110000010000001 +00001000001000000100011000001000 +00010001100000000000000000000000 +00000000000000000000000000000000 +01000000010001010100000000000100 +01010000000000010001010000000000 +01010001000000000001000101000000 +00000000000100000000000000000100 +00000000010001010000000000010001 +01000000000001000101000000000000 +00000100000000000100010100000000 +00010001010000100001000101010000 +00000000000000000000000000000000 +01001000010000000000011000000000 +01000001100000000001000001100000 +00000100000110000000000100000110 +11000000010000011000000000010000 +01100000000001000001100000000001 +00000110000000000100000110000000 +00010000011000000000010000011000 +00000001000000000000000000000000 +00000000000000000000000000000000 +01001000000000000000001000000001 +00000000101010000100000000101100 +00010000000010000000010000000010 +11010101000000001001000001000000 +00100000000100000000100000000100 +00000010000000010000000010000001 +01000000001000000001000000001000 +00000100000000000000000000000000 +00000000000000000000000000000000 +01000000010001010100011000100001 +01010001101000000101010001100110 +01110001000110000000110101000110 +11000011010100011001000011010100 +01100000001101010001100000001101 +01000110000000110101000110000000 +11010100011000000011010100011000 +00001101010000000001000101010000 +00000000000000000000000000000000 +00000000000000010100011000101110 +01110001100010011001110001000010 +01010011000110000001000111000100 +10100100011100010010000110011100 +01100000010001110001100000010001 +11000110000001000111000110000001 +00011100011000000100011100011000 +00010001110000000000000000000000 +00000000000000000000000000000000 +01000000000000010100011000000010 +01110001100000001001110001100000 +00110111000110000000110111000110 +00000001011100011000000000011100 +01100000001001110001100000001001 +11000110000000100111000110000001 +00011100011000000010011100011000 +00001101110000000000000000000000 +00000000000000000000000000000000 +01010000010001010100011000000101 +01110001100000010101110001100100 +00000111000110000001010010000110 +00000111001100011000010100001100 +01100000010101110001100000010101 +11000110000001010111000110000001 +00001100011000000101011100011000 +00010100110000100001000101010000 +00000000000000000000000000000000 +01000000000000000001001000000001 +00100100100000000100100100100100 +00010010000010000000010010010010 +00000001011000001000000001011100 +00100000000100100100100000000100 +10000010000000010010010010000000 +00001001001000000001001001001000 +00000101100000000000000000000000 +00000000000000000000000000000000 +01000000000000000000011000000000 +01100001100000000001100001100000 +00000010000110000000000110000110 +00000001011000011000000100011000 +01100000000001100001100000000001 +10000110000000000110000110000001 +00001000011000000000011000011000 +00000001100000000000000000000000 +00000000000000000000000000000000 +00000000010001010110000000010100 +01111000000000010001111000000010 +00000011100000000001000111100000 +00000100011110000000000100011110 +00000000010001111000000000010001 +11100000000001000111100000000001 +00011110000000000100011110000000 +00010001110000000001000101010000 +00000000000000000000000000000000 +01000000000000010101001000000000 +01100100100000000001100100101000 +01000010000010000000000110010010 +00000000011000001000000000011000 +00100000000001100100100000000001 +10000010000000000110010010000000 +00011001001000000000011001001000 +00000001100000000000000000000000 +00000000000000000000000000000000 +01000000000000010101001000000100 +00100100100000010000100100101000 +01000110000010000001000010010010 +00000100001000001000000100001000 +00100000010000100000100000010000 +10000010000001000010000010000001 +00001000001000000100001000001000 +00010000100000000000000000000000 +00000000000000000000000000000000 +01000000010001010100001000000100 +01000000100000010001000000011000 +01000101000010000001000100000010 +00000000010000001000000000010000 +00100000010001000000100000010001 +00000010000101000100000010000000 +00010000001000000100010000001000 +00010001000000000001000101010000 +00000000000000000000000000000000 +01000000000000000001001000000000 +01010100100000000001010100100000 +00000101000011000000000101010010 +00000000010100001100000000010100 +00110000000001010000110000000001 +01000011000000000101000010000000 +00010100001000000000010100001000 +00000001010000000000000000000000 +00000000000000000000000000000000 +01000000000000010000100000000000 +01100010000000000001100100000100 +00000110001000000000000100001000 +00000100010000100000000000010000 +10000000000001000010000000000001 +00001000000000000100001000000001 +00010000100000000000010000100000 +00000001000000000000000000000000 +00000000000000000000000000000000 +01000000010001010100001000100010 +00000000100010001000000000100110 +00000000000010000000100000000010 +00100010000000001000000010000000 +00100000001000000000100000001000 +00000010000000100000000010000000 +10000000001000000010000000001000 +00001000000000000001000101010000 +00000000000000000000000000000000 +01000000000000010100000010000100 +01100000000000010001100100001100 +01000110000000000000000110000000 +01000100011000000001000110011000 +00000000010001100000000000010001 +10000000000001000110000000000001 +00011000000000000100011000000000 +00010001100000000000000000000000 +00000000000000000000000000000000 +01000000000000010100000010000010 +01100000001000001001100100001100 +00000010000000000000100110000000 +10100000001000000001000000011101 +00000000011001100100000001011001 +10000000000000100110010000000000 +00001000000000000010011000000000 +00001001100000000000000000000000 +00000000000000000000000000000000 +01000000010001010110000010000100 +00111000001000010000111000000110 +00000010100000000001000011100000 +00100110001010000000100100011010 +00000000011000111000000000010000 +11100000000001000011100000000001 +10001010000000000100001110000000 +00010000110000000001000101010000 +00000000000000000000000000000000 +01010000000000000000000100000000 +00110000010000000000110001010100 +00000010000001000000000011000001 +00000000001000000100000000001000 +01010000000000110001010000000000 +11000001000000000011000101000000 +00001000000100000000001100000100 +00000000110000000000000000000000 +00000000000000000000000000000000 +01000000000000000000010000000000 +00110001000000000000110101001000 +00000010000101000000000011000100 +00100000001000010100100100001101 +01010000000000110101010000010000 +11000101000000000011010100000000 +00001000010000000000001100010000 +00000000110000100000000000000000 +00000000000000000000000000000000 +01000000010001010100001100000100 +01100000110000010001100000111000 +00000110000011000001000110000011 +00000100011000001100000100011000 +00110000000001100000110000000001 +10000011000001000110000111000001 +00011000001100000100011000001100 +00010001100000000001000101010000 +00000000000000000000000000000000 +01000000000000010100000000000000 +00100000000000000000100011000000 +01000010000000000000000010000000 +00000000001000000000000000001000 +01000000000000100001000000000000 +10000000000000000010000000000000 +00001000000000000000001000000000 +00000000100000000000000000000000 +00000000000000000000000000000000 +01000000000000010100100001000100 +01100010000100010001100011000100 +01000110001000010001000110001000 +01000100011000100001000100011000 +10000000000001100010000000000001 +10001000010001000110001000000001 +00011000100001000100011000100001 +00010001100000000000000000000000 +00000000000000000000000000000000 +01000000010001010100000001000100 +01010000000100010001010000000100 +01000101000000010001000101000000 +01000001000000000001000000010100 +00010100000001010000010000000001 +01000000010001000101000100010000 +00010100000001000100010100000001 +00010001010000000001000101010000 +00000000000000000000000000000000 +01000000010000000000100000100000 +01000010000010000001000010001010 +00000101001000001000000100001000 +10100000010000100000100000010000 +10000010000001000010000010000001 +00001000001000000100001000001000 +00010000100000100000010000100000 +00000001000000000000000000000000 +00000000000000000000000000000000 +00000000000000000100101000000001 +00000010100000000100000010100000 +00000000001010000000010000001010 +01000101000000101000100001000000 +10100000000100000010100000000100 +00001010000000010000001010000001 +01000000101000000001000000101000 +00000100000000000000000000000000 +00000000000000000000000000000000 +01000000010001010100110100000011 +01010011010010001101010011010010 +00000001001101000000110101001101 +01000011010100110100000011010100 +11010000001101010011010000001101 +01001101000000110101001101000000 +11010100110100000011010100110100 +00001101010000000001000101010000 +00000000000000000000000000000000 +01000000000000010100100010000000 +01110010000000000001110010000000 +01100111001000000001000111001000 +10000100011100100000000110011100 +10000000010001110010000000010001 +11001000000001000111001000000001 +00011100100000000100011100100000 +00010001110000000000000000000000 +00000000000000000000000000000000 +00000000000000000010001100001000 +01001000110000100001000000110000 +00000100100011000110000100100011 +00000000010010001100010000010000 +00110001100001000000110000100001 +00100011000110000100000011000000 +00010010001100001000010010001100 +00000001000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +01001111111111111101001111111111 +11110100111111111111110100111111 +11111111010011111111111111010011 +11111111111101001111111111111101 +00111111111111110100111111111111 +11010011111111111111010011111111 +11111101000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000001000000 +00000000000100000000000010000100 +00100000000000000000000000000000 +01000010000000000000000010000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000010110111111011 +00001011011111101100001111111111 +11110100101100110110110000101101 +11111111010010110011011111010010 +01001101101100001001001001101100 +00101100110110110000100100110110 +11000010110011011011000010110011 +01111101000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011001111111100 +01001100111111110001001111111111 +11110100110011001111000100110011 +11111111010011001100111111010011 +01010011110001001101001011110001 +00110011001111000100110101001111 +00010011001100111100010011001100 +11111101000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011101100011110 +01001110110001111001001000110001 +10000100111011011111100100111011 +00011000010011101101111000010011 +10010111111001001110000111111001 +00111011011111100100111001000110 +00010011101100011110010011101100 +01111001000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000001010000100 +00000000101000010000000000101000 +01000000000010100001000000000010 +10000100000000001010000011001100 +00101000010000000000101000001100 +11000010100001000000000010100001 +00000000001010000100000000001010 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000100000000100 +00000010000000010000000010000000 +01000000001000000001000000001000 +00000100000000100000000100000000 +10000000010000000010000000010000 +00001000000001000000001000000001 +00000000100000000100000000100000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000010000100 +00000000001000010000000000001000 +01000000000000100001000000000000 +10000100000000000010000100000000 +00001000010000000000001000010000 +00000000100001000000000000100001 +00000000000010000100000000000010 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000100 +00000000000000010000000000000000 +01000000000000000001000000000000 +00000100000000000000000100000000 +00000000010000000000000000010000 +00000000000001000000000000000001 +00000000000000000100000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000010000000 +00000000001000001100110000001000 +00110011000000100000000000000000 +10000000000000000010000000000000 +00001000000000000000001000000000 +00000000100000000000000000100000 +00000000000010000000000000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000000000000001000000000 +00000000100000000000000000100000 +00000000000010000000000000000010 +00000000000000001000000000000000 +00100000000000000000100000000000 +00000010000000000000000010000000 +00000000001000000000000000001000 +00000000000000100000000000000000 +00000000000000000000000000000000 +00001000000000000000100010000000 +00000010001000000000000010001000 +00000000001000100000000000001000 +10000000000000100010000000000000 +10001000000000000010001000000000 +00001000100000000000001000100000 +00000000100010000000000000100010 +00000000000000100000000000000000 +00000000000000000000000000000000 +00001000000000000000100000000000 +00000010000000001100110010000000 +00110011001000000000000000001000 +00000000000000100000000000000000 +10000000000000000010000000000000 +00001000000000000000001000000000 +00000000100000000000000000100000 +00000000000000100000000000000000 +00000000000000000000000000000000 +00001000000000000000101010000100 +00000010101000010000000010101000 +01000000001010100001000000001010 +10000100000000101010000100000000 +10101000010000000010101000010000 +00001010100001000000001010100001 +00000000101010000100000000101010 +00010000000000100000000000000000 +00000000000000000000000000000000 +00001000000000000000100000000100 +00000010000000010000000010000000 +01000000001000000001000000001000 +00000100000000100000000100000000 +10000000010000000010000000010000 +00001000000001000000001000000001 +00000000100000000100000000100000 +00010000000000100000000000000000 +00000000000000000000000000000000 +00001000000000000000000010000100 +00000000001000010000000000001000 +01000000000000100001000000000000 +10000100000000000010000100000000 +00001000010000000000001000010000 +00000000100001000000000000100001 +00000000000010000100000000000010 +00010000000000100000000000000000 +00000000000000000000000000000000 +00001000000100000000000000000111 +00110000000000011100110000000000 +01110011000000000001110011000000 +00000111001100000000000111001100 +00000000011100110000000000011100 +11000000000001110011000000000001 +11001100000000000111001100000000 +00011100110000100000010000000000 +00000000000000000000000000000000 +00001000000000000000000010000100 +00000000001000010000000000001000 +01110011000000100001000000000000 +10000111001100000010000100000000 +00001000010000000000001000011100 +11000000100001000000000000100001 +00000000000010000100000000000010 +00010000000000100000000000000000 +00000000000000000000000000000000 +00000000000000000000001000000000 +00000000100000000000000000100000 +01000000000010000000000000000010 +00000100000000001000000000000000 +00100000000000000000100000010000 +00000010000000000000000010000000 +00000000001000000000000000001000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000010000000 +00000000001000000000000000001000 +01000000000000100000000000000000 +10000100000000000010000000000000 +00001000000000000000001000010000 +00000000100000000000000000100000 +00000000000010000000000000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000100001000000000000000 +00000000000000000000000000000000 +00110011000000000000000000000000 +00000011001100000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000010000100000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00111100001111000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000011110000111100000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111111111111111111111111111 +11000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111111111111111111111111111 +11000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111111111111111111111111111 +11000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111111111111111111111111111 +11000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111111111111111111111111111 +11000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111111111111111111111111111 +11000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000001010000100 +00000000101000010000000000101000 +01000000000010100001000000000010 +10000100000000001010000100000000 +00101000010000000000101000010000 +00000010100001000000000010100001 +00000000001010000100000000001010 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000100 +00000000000000010000000000000000 +01000000000000000001000000000000 +00000100000000100000000100000000 +10000000010000000010000000010000 +00001000000001000000001000000001 +00000000100000000100000000100000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000100010000100 +00000000001000010000000010001000 +01000000001000100001000000001000 +10000100000000100010000100000000 +00001000010000000000001000010000 +00000000100001000000000000100001 +00000000000010000100000000000010 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000100 +00000000000000010000000000000000 +01000000000000000001000000000000 +00000100000000000000000100000000 +00000000010000000000000000010000 +00000000000001000000000000000001 +00000000000000000100000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000010000000 +00000000001000000000000000001000 +00000000000000100000000000000000 +10000000000000000010000000000000 +00001000000000000000001000000000 +00000000100000000000000000100000 +00000000000010000000000000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000000000000001000000000 +00000000100000000000000000100000 +00000000000010000000000000000010 +00000000000000001000000000000000 +00100000000000000000100000000000 +00000010000000000000000010000000 +00000000001000000000000000001000 +00000000000000100000000000000000 +00000000000000000000000000000000 +00000000000000000000100010000000 +00000010001000000000000010001000 +00000000001000100000000000001000 +10000000000000100010000000000000 +10001000000000000010001000000000 +00001000100000000000001000100000 +00000000100010000000000000100010 +00000000000000100000000000000000 +00000000000000000000000000000000 +00001000000000000000000000000000 +00000000000000000000000000000000 +00000000001000000000000000000000 +00000000000000000000000000000000 +10000000000000000010000000000000 +00001000000000000000001000000000 +00000000100000000000000000100000 +00000000000000100000000000000000 +00000000000000000000000000000000 +00001000000000000000101010000111 +00110010101000010000000010101000 +01110011001010100001000000001010 +10000100000000101010000100000000 +10101000010000000010101000010000 +00001010100001000000001010100001 +00000000101010000100000000101010 +00011100110000100000000000000000 +00000000000000000000000000000000 +00001000000000000000100000000100 +00000010000000010000000010000000 +01000000001000000001000000001000 +00000100000000100000000100000000 +10000000010000000010000000010000 +00001000000001000000001000000001 +00000000100000000100000000100000 +00010000000000100000000000000000 +00000000000000000000000000000000 +00000000000000000000000010000000 +00000000001000010000000000001000 +00000000000000100001000000000000 +10000100000000000010000100000000 +00001000010000000000001000010000 +00000000100001000000000000100001 +00000000000010000100000000000010 +00010000000000100000000000000000 +00000000000000000000000000000000 +00001000000100000000000000000100 +00000000000000011100110000000000 +01000000000000000001110011000000 +00000100000000000000000111001100 +00000000011100110000000000011100 +11000000000001110011000000000001 +11001100000000000111001100000000 +00011100110000100000010000000000 +00000000000000000000000000000000 +00001000000000000000000010000100 +00000000001000010000000000001000 +01000000000000100001000000000000 +10000100000000000010000100000000 +00001000010000000000001000010000 +00000000100001000000000000100001 +00000000000010000100000000000010 +00010000000000100000000000000000 +00000000000000000000000000000000 +00000000000000000000001000000000 +00000000100000000000000000100000 +00000000000010000000000000000010 +00000000000000001000000000000000 +00100000000000000000100000000000 +00000010000000000000000010000000 +00000000001000000000000000001000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000010000000 +00000000001000000000000000001000 +00000000000000100000000000000000 +10000000000000000010000000000000 +00001000000000000000001000000000 +00000000100000000000000000100000 +00000000000010000000000000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000100001000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000010000100000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00111100001111000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000011110000111100000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111111111111111111111111111 +11000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111111111111111111111111111 +11000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111111111111111111111111111 +11000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111111111111111111111111111 +11000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111111111111111111111111111 +11000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111111111111111111111111111 +11000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00110000000000000010000000000001 +00000010000000000000000000000000 +00110000000000000100001001001001 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00110000000000000010000000000001 +00000010000000100000000000000000 +00110000000000000100001001000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00110000000000000000000000000001 +00000000000000001010001010111110 +00110000000000001000000000000001 +00000000000000000000000000000011 +00110000000000000100000000001001 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00110000000000001000000000000001 +00000000000000000000000000000101 +00110000000000001010000000000001 +00000000000000000000000000000000 +00110000000000000000000000000001 +00000000000000001100000101111101 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 diff --git a/kernel/proslic.h b/kernel/proslic.h new file mode 100644 index 0000000..933bd34 --- /dev/null +++ b/kernel/proslic.h @@ -0,0 +1,190 @@ +// ProSlic Header File + +typedef struct { + unsigned char address; + unsigned char altaddr; + char *name; + unsigned short initial; +} alpha; + +typedef struct { + unsigned char chip_number; + unsigned char DTMF_digit; + unsigned char interrupt_line; + unsigned char hook_status; + unsigned long half_pulses[20]; // Contains the time stamps of incomming half pulses. + unsigned char half_pulses_detected; // Contains the number of half pulses detected. + unsigned char Pulse_digit; + unsigned long On_Hook_time; + unsigned long Off_Hook_time; +} chipStruct; + +// Defines +#define LPT 0X378 + +#define IDA_LO 28 +#define IDA_HI 29 + +#define IAA 30 +#define ID_ACCES_STATUS 31 +#define IAS_BIT 1 + +#define I_STATUS 31 + +#define SPI_MODE 0 +#define PCM_MODE 1 +#define PCM_XMIT_START_COUNT_LSB 2 +#define PCM_XMIT_START_COUNT_MSB 3 +#define PCM_RCV_START_COUNT_LSB 4 +#define PCM_RCV_START_COUNT_MSB 5 +#define DIO 6 + +#define AUDIO_LOOPBACK 8 +#define AUDIO_GAIN 9 +#define LINE_IMPEDANCE 10 +#define HYBRID 11 +#define RESERVED12 12 +#define RESERVED13 13 +#define PWR_DOWN1 14 +#define PWR_DOWN2 15 +#define RESERVED16 16 +#define RESERVED17 17 +#define INTRPT_STATUS1 18 +#define INTRPT_STATUS2 19 +#define INTRPT_STATUS3 20 +#define INTRPT_MASK1 21 +#define INTRPT_MASK2 22 +#define INTRPT_MASK3 23 +#define DTMF_DIGIT 24 +#define RESERVED25 25 +#define RESERVED26 26 +#define RESERVED27 27 +#define I_DATA_LOW 28 +#define I_DATA_HIGH 29 +#define I_ADDRESS 30 +#define I_STATUS 31 +#define OSC1 32 +#define OSC2 33 +#define RING_OSC_CTL 34 +#define PULSE_OSC 35 +#define OSC1_ON__LO 36 +#define OSC1_ON_HI 37 +#define OSC1_OFF_LO 38 +#define OSC1_OFF_HI 39 +#define OSC2_ON__LO 40 +#define OSC2_ON_HI 41 +#define OSC2_OFF_LO 42 +#define OSC2_OFF_HI 43 +#define PULSE_ON__LO 44 +#define PULSE_ON_HI 45 +#define PULSE_OFF_LO 46 +#define PULSE_OFF_HI 47 +#define RING_ON__LO 48 +#define RING_ON_HI 49 +#define RING_OFF_LO 50 +#define RING_OFF_HI 51 +#define RESERVED52 52 +#define RESERVED53 53 +#define RESERVED54 54 +#define RESERVED55 55 +#define RESERVED56 56 +#define RESERVED57 57 +#define RESERVED58 58 +#define RESERVED59 59 +#define RESERVED60 60 +#define RESERVED61 61 +#define RESERVED62 62 +#define RESERVED63 63 +#define LINE_STATE 64 +#define ACTIVATE_LINE 0x11 +#define RING_LINE 0x44 +#define BIAS_SQUELCH 65 +#define BAT_FEED 66 +#define AUTO_STATE 67 +#define LOOP_STAT 68 +#define LOOP_DEBOUCE 69 +#define RT_DEBOUCE 70 +#define LOOP_I_LIMIT 71 +#define OFF_HOOK_V 72 +#define COMMON_V 73 +#define BAT_V_HI 74 +#define BAT_V_LO 75 +#define PWR_STAT_DEV 76 +#define PWR_STAT 77 +#define LOOP_V_SENSE 78 +#define LOOP_I_SENSE 79 +#define TIP_V_SENSE 80 +#define RING_V_SENSE 81 +#define BAT_V_HI_SENSE 82 +#define BAT_V_LO_SENSE 83 +#define IQ1 84 +#define IQ2 85 +#define IQ3 86 +#define IQ4 87 +#define IQ5 88 +#define IQ6 89 +#define RESERVED90 90 +#define RESERVED91 91 +#define DCDC_PWM_OFF 92 +#define DCDC 93 +#define DCDC_PW_OFF 94 +#define RESERVED95 95 +#define CALIBR1 96 +#define CALIBRATE_LINE 0x78 +#define NORMAL_CALIBRATION_COMPLETE 0x20 +#define CALIBR2 97 +#define RING_GAIN_CAL 98 +#define TIP_GAIN_CAL 99 +#define DIFF_I_CAL 100 +#define COMMON_I_CAL 101 +#define I_LIMIT_GAIN_CAL 102 +#define ADC_OFFSET_CAL 103 +#define DAC_ADC_OFFSET 104 +#define DAC_OFFSET_CAL 105 +#define COMMON_BAL_CAL 106 +#define DC_PEAK_CAL 107 + +// Indirect Register (decimal) +#define DTMF_ROW_0_PEAK 0 +#define DTMF_ROW_1_PEAK 1 +#define DTMF_ROW2_PEAK 2 +#define DTMF_ROW3_PEAK 3 +#define DTMF_COL1_PEAK 4 +#define DTMF_FWD_TWIST 5 +#define DTMF_RVS_TWIST 6 +#define DTMF_ROW_RATIO_THRESH 7 +#define DTMF_COL_RATIO_THRESH 8 +#define DTMF_ROW_2ND_HARM 9 +#define DTMF_COL_2ND_HARM 10 +#define DTMF_PWR_MIN_THRESH 11 +#define DTMF_HOT_LIM_THRESH 12 +#define OSC1_COEF 13 +#define OSC1X 14 +#define OSC1Y 15 +#define OSC2_COEF 16 +#define OSC2X 17 +#define OSC2Y 18 +#define RING_V_OFF 19 +#define RING_OSC_COEF 20 +#define RING_X 21 +#define RING_Y 22 +#define PULSE_ENVEL 23 +#define PULSE_X 24 +#define PULSE_Y 25 +#define RECV_DIGITAL_GAIN 26 +#define XMIT_DIGITAL_GAIN 27 +#define LOOP_CLOSE_THRESH 28 +#define RING_TRIP_THRESH 29 +#define COMMON_MIN_THRESH 30 +#define COMMON_MAX_THRESH 31 +#define PWR_ALARM_Q1Q2 32 +#define PWR_ALARM_Q3Q4 33 +#define PWR_ALARM_Q5Q6 34 +#define LOOP_CLOSURE_FILTER 35 +#define RING_TRIP_FILTER 36 +#define THERM_LP_POLE_Q1Q2 37 +#define THERM_LP_POLE_Q3Q4 38 +#define THERM_LP_POLE_Q5Q6 39 +#define CM_BIAS_RINGING 40 +#define DCDC_MIN_V 41 +#define DCDC_XTRA 42 diff --git a/kernel/sec-2.h b/kernel/sec-2.h new file mode 100644 index 0000000..49342ea --- /dev/null +++ b/kernel/sec-2.h @@ -0,0 +1,451 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * echo.c - An echo cancellor, suitable for electrical and acoustic + * cancellation. This code does not currently comply with + * any relevant standards (e.g. G.164/5/7/8). One day.... + * + * Written by Steve Underwood + * + * Copyright (C) 2001 Steve Underwood + * + * Based on a bit from here, a bit from there, eye of toad, + * ear of bat, etc - plus, of course, my own 2 cents. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* TODO: + Finish the echo suppressor option, however nasty suppression may be + Add an option to reintroduce side tone at -24dB under appropriate conditions. + Improve double talk detector (iterative!) +*/ + +#ifndef _ZAPTEL_SEC_H +#define _ZAPTEL_SEC_H + +#ifdef __KERNEL__ +#include +#include +#define MALLOC(a) kmalloc((a), GFP_KERNEL) +#define FREE(a) kfree(a) +#else +#include +#include +#include +#include +#define MALLOC(a) malloc(a) +#define FREE(a) free(a) +#endif + +#include "fir.h" + +#ifndef NULL +#define NULL 0 +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +#define NONUPDATE_DWELL_TIME 600 /* 600 samples, or 75ms */ + +struct echo_can_state +{ + int tx_power; + int rx_power; + int clean_rx_power; + + int rx_power_threshold; + int nonupdate_dwell; + + fir16_state_t fir_state; + int16_t *fir_taps16; /* 16-bit version of FIR taps */ + int32_t *fir_taps32; /* 32-bit version of FIR taps */ + + int curr_pos; + + int taps; + int tap_mask; + int use_nlp; + int use_suppressor; + + int32_t supp_test1; + int32_t supp_test2; + int32_t supp1; + int32_t supp2; + + int32_t latest_correction; /* Indication of the magnitude of the latest + adaption, or a code to indicate why adaption + was skipped, for test purposes */ +}; + +static void echo_can_free(struct echo_can_state *ec); +static int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx); + +static void echo_can_init(void) +{ + printk("Zaptel Echo Canceller: STEVE2%s\n", ZAPTEL_ECHO_AGGRESSIVE); +} + +static void echo_can_identify(char *buf, size_t len) +{ + strncpy(buf, "STEVE2", len); +} + +static void echo_can_shutdown(void) +{ +} + +/* + * According to Jim... + */ +#define MIN_TX_POWER_FOR_ADAPTION 512 +#define MIN_RX_POWER_FOR_ADAPTION 64 + +/* + * According to Steve... + */ +/* #define MIN_TX_POWER_FOR_ADAPTION 4096 +#define MIN_RX_POWER_FOR_ADAPTION 64 */ + +static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p, + struct echo_can_state **ec) +{ + size_t size; + + if (ecp->param_count > 0) { + printk(KERN_WARNING "SEC-2 echo canceler does not support parameters; failing request\n"); + return -EINVAL; + } + + size = sizeof(**ec) + ecp->tap_length * sizeof(int32_t) + ecp->tap_length * 3 * sizeof(int16_t); + + if (!(*ec = MALLOC(size))) + return -ENOMEM; + + memset(*ec, 0, size); + + (*ec)->taps = ecp->tap_length; + (*ec)->curr_pos = ecp->tap_length - 1; + (*ec)->tap_mask = ecp->tap_length - 1; + (*ec)->fir_taps32 = (int32_t *) (*ec + sizeof(**ec)); + (*ec)->fir_taps16 = (int16_t *) (*ec + sizeof(**ec) + ecp->tap_length * sizeof(int32_t)); + /* Create FIR filter */ + fir16_create(&(*ec)->fir_state, (*ec)->fir_taps16, (*ec)->taps); + (*ec)->rx_power_threshold = 10000000; + (*ec)->use_suppressor = FALSE; + /* Non-linear processor - a fancy way to say "zap small signals, to avoid + accumulating noise". */ + (*ec)->use_nlp = FALSE; + + return 0; +} +/*- End of function --------------------------------------------------------*/ + +static inline void echo_can_free(struct echo_can_state *ec) +{ + fir16_free(&ec->fir_state); + FREE(ec); +} +/*- End of function --------------------------------------------------------*/ + +static inline int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx) +{ + int offset1; + int offset2; + int32_t echo_value; + int clean_rx; + int nsuppr; + int i; + int correction; + + /* Evaluate the echo - i.e. apply the FIR filter */ + /* Assume the gain of the FIR does not exceed unity. Exceeding unity + would seem like a rather poor thing for an echo cancellor to do :) + This means we can compute the result with a total disregard for + overflows. 16bits x 16bits -> 31bits, so no overflow can occur in + any multiply. While accumulating we may overflow and underflow the + 32 bit scale often. However, if the gain does not exceed unity, + everything should work itself out, and the final result will be + OK, without any saturation logic. */ + /* Overflow is very much possible here, and we do nothing about it because + of the compute costs */ + /* 16 bit coeffs for the LMS give lousy results (maths good, actual sound + bad!), but 32 bit coeffs require some shifting. On balance 32 bit seems + best */ + echo_value = fir16 (&ec->fir_state, tx); + + /* And the answer is..... */ + clean_rx = rx - echo_value; + + /* That was the easy part. Now we need to adapt! */ + if (ec->nonupdate_dwell > 0) + ec->nonupdate_dwell--; + + /* If there is very little being transmitted, any attempt to train is + futile. We would either be training on the far end's noise or signal, + the channel's own noise, or our noise. Either way, this is hardly good + training, so don't do it (avoid trouble). */ + /* If the received power is very low, either we are sending very little or + we are already well adapted. There is little point in trying to improve + the adaption under these circumstanceson, so don't do it (reduce the + compute load). */ + if (ec->tx_power > MIN_TX_POWER_FOR_ADAPTION + && + ec->rx_power > MIN_RX_POWER_FOR_ADAPTION) + { + /* This is a really crude piece of decision logic, but it does OK + for now. */ + if (ec->tx_power > 2*ec->rx_power) + { + /* There is no far-end speech detected */ + if (ec->nonupdate_dwell == 0) + { + /* ... and we are not in the dwell time from previous speech. */ + //nsuppr = saturate((clean_rx << 16)/ec->tx_power); + nsuppr = clean_rx >> 3; + + /* Update the FIR taps */ + offset2 = ec->curr_pos + 1; + offset1 = ec->taps - offset2; + ec->latest_correction = 0; + for (i = ec->taps - 1; i >= offset1; i--) + { + correction = ec->fir_state.history[i - offset1]*nsuppr; + /* Leak to avoid false training on signals with multiple + strong correlations. */ + ec->fir_taps32[i] -= (ec->fir_taps32[i] >> 12); + ec->fir_taps32[i] += correction; + ec->fir_state.coeffs[i] = ec->fir_taps32[i] >> 15; + ec->latest_correction += abs(correction); + } + for ( ; i >= 0; i--) + { + correction = ec->fir_state.history[i + offset2]*nsuppr; + /* Leak to avoid false training on signals with multiple + strong correlations. */ + ec->fir_taps32[i] -= (ec->fir_taps32[i] >> 12); + ec->fir_taps32[i] += correction; + ec->fir_state.coeffs[i] = ec->fir_taps32[i] >> 15; + ec->latest_correction += abs(correction); + } + } + else + { + ec->latest_correction = -1; + } + } + else + { + ec->nonupdate_dwell = NONUPDATE_DWELL_TIME; + ec->latest_correction = -2; + } + } + else + { + ec->nonupdate_dwell = 0; + ec->latest_correction = -3; + } + /* Calculate short term power levels using very simple single pole IIRs */ + /* TODO: Is the nasty modulus approach the fastest, or would a real + tx*tx power calculation actually be faster? */ + ec->tx_power += ((abs(tx) - ec->tx_power) >> 5); + ec->rx_power += ((abs(rx) - ec->rx_power) >> 5); + ec->clean_rx_power += ((abs(clean_rx) - ec->clean_rx_power) >> 5); + +#if defined(XYZZY) + if (ec->use_suppressor) + { + ec->supp_test1 += (ec->fir_state.history[ec->curr_pos] - ec->fir_state.history[(ec->curr_pos - 7) & ec->tap_mask]); + ec->supp_test2 += (ec->fir_state.history[(ec->curr_pos - 24) & ec->tap_mask] - ec->fir_state.history[(ec->curr_pos - 31) & ec->tap_mask]); + if (ec->supp_test1 > 42 && ec->supp_test2 > 42) + supp_change = 25; + else + supp_change = 50; + supp = supp_change + k1*ec->supp1 + k2*ec->supp2; + ec->supp2 = ec->supp1; + ec->supp1 = supp; + clean_rx *= (1 - supp); + } +#endif + + if (ec->use_nlp && ec->rx_power < 32) + clean_rx = 0; + + /* Roll around the rolling buffer */ + if (ec->curr_pos <= 0) + ec->curr_pos = ec->taps; + ec->curr_pos--; + + return clean_rx; +} + +#if 0 +static inline int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx) +{ + int offset; + int limit; + int32_t echo_value; + int clean_rx; + int nsuppr; + int i; + int correction; + + ec->tx_history[ec->curr_pos] = tx; + + /* Evaluate the echo - i.e. apply the FIR filter */ + /* Assume the gain of the FIR does not exceed unity. Exceeding unity + would seem like a rather poor thing for an echo cancellor to do :) + This means we can compute the result with a total disregard for + overflows. 16bits x 16bits -> 31bits, so no overflow can occur in + any multiply. While accumulating we may overflow and underflow the + 32 bit scale often. However, if the gain does not exceed unity, + everything should work itself out, and the final result will be + OK, without any saturation logic. */ + /* Overflow is very much possible here, and we do nothing about it because + of the compute costs */ + /* 16 bit coeffs for the LMS give lousy results (maths good, actual sound + bad!), but 32 bit coeffs require some shifting. On balance 32 bit seems + best */ + offset = ec->curr_pos; + limit = ec->taps - offset; + echo_value = 0; + for (i = 0; i < limit; i++) + echo_value += (ec->fir_taps[i] >> 16)*ec->tx_history[i + offset]; + offset = ec->taps - ec->curr_pos; + for ( ; i < ec->taps; i++) + echo_value += (ec->fir_taps[i] >> 16)*ec->tx_history[i - offset]; + echo_value >>= 16; + + /* And the answer is..... */ + clean_rx = rx - echo_value; + + /* That was the easy part. Now we need to adapt! */ + if (ec->nonupdate_dwell > 0) + ec->nonupdate_dwell--; + + /* If there is very little being transmitted, any attempt to train is + futile. We would either be training on the far end's noise or signal, + the channel's own noise, or our noise. Either way, this is hardly good + training, so don't do it (avoid trouble). */ + /* If the received power is very low, either we are sending very little or + we are already well adapted. There is little point in trying to improve + the adaption under these circumstanceson, so don't do it (reduce the + compute load). */ + if (ec->tx_power > MIN_TX_POWER_FOR_ADAPTION + && + ec->rx_power > MIN_RX_POWER_FOR_ADAPTION) + { + /* This is a really crude piece of decision logic, but it does OK + for now. */ + if (ec->tx_power > 2*ec->rx_power) + { + /* There is no far-end speech detected */ + if (ec->nonupdate_dwell == 0) + { + /* ... and we are not in the dwell time from previous speech. */ + //nsuppr = saturate((clean_rx << 16)/ec->tx_power); + nsuppr = clean_rx >> 3; + + /* Update the FIR taps */ + offset = ec->curr_pos; + limit = ec->taps - offset; + ec->latest_correction = 0; + for (i = 0; i < limit; i++) + { + correction = ec->tx_history[i + offset]*nsuppr; + ec->fir_taps[i] += correction; + //ec->latest_correction += abs(correction); + } + offset = ec->taps - ec->curr_pos; + for ( ; i < ec->taps; i++) + { + correction = ec->tx_history[i - offset]*nsuppr; + ec->fir_taps[i] += correction; + //ec->latest_correction += abs(correction); + } + } + else + { + ec->latest_correction = -3; + } + } + else + { + ec->nonupdate_dwell = NONUPDATE_DWELL_TIME; + ec->latest_correction = -2; + } + } + else + { + ec->nonupdate_dwell = 0; + ec->latest_correction = -1; + } + /* Calculate short term power levels using very simple single pole IIRs */ + /* TODO: Is the nasty modulus approach the fastest, or would a real + tx*tx power calculation actually be faster? */ + ec->tx_power += ((abs(tx) - ec->tx_power) >> 5); + ec->rx_power += ((abs(rx) - ec->rx_power) >> 5); + ec->clean_rx_power += ((abs(clean_rx) - ec->clean_rx_power) >> 5); + +#if defined(XYZZY) + if (ec->use_suppressor) + { + ec->supp_test1 += (ec->tx_history[ec->curr_pos] - ec->tx_history[(ec->curr_pos - 7) & ec->tap_mask]); + ec->supp_test2 += (ec->tx_history[(ec->curr_pos - 24) & ec->tap_mask] - ec->tx_history[(ec->curr_pos - 31) & ec->tap_mask]); + if (ec->supp_test1 > 42 && ec->supp_test2 > 42) + supp_change = 25; + else + supp_change = 50; + supp = supp_change + k1*ec->supp1 + k2*ec->supp2; + ec->supp2 = ec->supp1; + ec->supp1 = supp; + clean_rx *= (1 - supp); + } +#endif + + if (ec->use_nlp && ec->rx_power < 32) + clean_rx = 0; + + /* Roll around the rolling buffer */ + ec->curr_pos = (ec->curr_pos + 1) & ec->tap_mask; + + return clean_rx; +} +/*- End of function --------------------------------------------------------*/ +#endif + +static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) +{ + /* Reset hang counter to avoid adjustments after + initial forced training */ + ec->nonupdate_dwell = ec->taps << 1; + if (pos >= ec->taps) + return 1; + ec->fir_taps32[pos] = val << 17; + ec->fir_taps16[pos] = val << 1; + if (++pos >= ec->taps) + return 1; + return 0; +} + +/*- End of file ------------------------------------------------------------*/ +#endif diff --git a/kernel/sec.h b/kernel/sec.h new file mode 100644 index 0000000..6c4b7c0 --- /dev/null +++ b/kernel/sec.h @@ -0,0 +1,310 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * echo.c - An echo cancellor, suitable for electrical and acoustic + * cancellation. This code does not currently comply with + * any relevant standards (e.g. G.164/5/7/8). One day.... + * + * Written by Steve Underwood + * Various optimizations and improvements by Mark Spencer + * + * Copyright (C) 2001 Steve Underwood + * + * Based on a bit from here, a bit from there, eye of toad, + * ear of bat, etc - plus, of course, my own 2 cents. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* TODO: + Finish the echo suppressor option, however nasty suppression may be + Add an option to reintroduce side tone at -24dB under appropriate conditions. + Improve double talk detector (iterative!) +*/ + +#ifndef _ZAPTEL_SEC_H +#define _ZAPTEL_SEC_H + +#ifdef __KERNEL__ +#include +#include +#define MALLOC(a) kmalloc((a), GFP_KERNEL) +#define FREE(a) kfree(a) +#else +#include +#include +#include +#include +#define MALLOC(a) malloc(a) +#define FREE(a) free(a) +#endif + +#include "arith.h" + +#ifndef NULL +#define NULL 0 +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +#define USE_SHORTS + +#define NONUPDATE_DWELL_TIME 600 /* 600 samples, or 75ms */ + +struct echo_can_state +{ + int tx_power; + int rx_power; + int clean_rx_power; + + int rx_power_threshold; + int nonupdate_dwell; + + int16_t *tx_history; /* Last N tx samples */ + int32_t *fir_taps; /* Echo FIR taps */ + int16_t *fir_taps_short; /* Echo FIR taps, shorts instead of ints */ + + int curr_pos; + + int taps; + int tap_mask; + int use_nlp; + int use_suppressor; + + int32_t supp_test1; + int32_t supp_test2; + int32_t supp1; + int32_t supp2; + + int32_t latest_correction; /* Indication of the magnitude of the latest + adaption, or a code to indicate why adaption + was skipped, for test purposes */ +}; + +static void echo_can_init(void) +{ + printk("Zaptel Echo Canceller: STEVE%s\n", ZAPTEL_ECHO_AGGRESSIVE); +} + +static void echo_can_identify(char *buf, size_t len) +{ + strncpy(buf, "STEVE", len); +} + +static void echo_can_shutdown(void) +{ +} + +static void echo_can_free(struct echo_can_state *ec); +static int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx); + +/* Original parameters : +#define MIN_TX_POWER_FOR_ADAPTION 256 +#define MIN_RX_POWER_FOR_ADAPTION 128 +*/ + +#define MIN_TX_POWER_FOR_ADAPTION 256 +#define MIN_RX_POWER_FOR_ADAPTION 64 + +/* Better ones found by Jim +#define MIN_TX_POWER_FOR_ADAPTION 128 +#define MIN_RX_POWER_FOR_ADAPTION 64 +*/ + +static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p, + struct echo_can_state **ec) +{ + size_t size; + + if (ecp->param_count > 0) { + printk(KERN_WARNING "SEC echo canceler does not support parameters; failing request\n"); + return -EINVAL; + } + + size = sizeof(**ec) + ecp->tap_length * sizeof(int32_t) + ecp->tap_length * 3 * sizeof(int16_t); + + if (!(*ec = MALLOC(size))) + return -ENOMEM; + + memset(*ec, 0, size); + + (*ec)->taps = ecp->tap_length; + (*ec)->tap_mask = ecp->tap_length - 1; + (*ec)->tx_history = (int16_t *) (*ec + sizeof(**ec)); + (*ec)->fir_taps = (int32_t *) (*ec + sizeof(**ec) + + ecp->tap_length * 2 * sizeof(int16_t)); + (*ec)->fir_taps_short = (int16_t *) (*ec + sizeof(**ec) + + ecp->tap_length * sizeof(int32_t) + + ecp->tap_length * 2 * sizeof(int16_t)); + (*ec)->rx_power_threshold = 10000000; + (*ec)->use_suppressor = FALSE; + /* Non-linear processor - a fancy way to say "zap small signals, to avoid + accumulating noise". */ + (*ec)->use_nlp = TRUE; + + return 0; +} +/*- End of function --------------------------------------------------------*/ + +static inline void echo_can_free(struct echo_can_state *ec) +{ + FREE(ec); +} +/*- End of function --------------------------------------------------------*/ + +static inline int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx) +{ + int32_t echo_value; + int clean_rx; + int nsuppr; + + ec->tx_history[ec->curr_pos] = tx; + ec->tx_history[ec->curr_pos + ec->taps] = tx; + + /* Evaluate the echo - i.e. apply the FIR filter */ + /* Assume the gain of the FIR does not exceed unity. Exceeding unity + would seem like a rather poor thing for an echo cancellor to do :) + This means we can compute the result with a total disregard for + overflows. 16bits x 16bits -> 31bits, so no overflow can occur in + any multiply. While accumulating we may overflow and underflow the + 32 bit scale often. However, if the gain does not exceed unity, + everything should work itself out, and the final result will be + OK, without any saturation logic. */ + /* Overflow is very much possible here, and we do nothing about it because + of the compute costs */ + /* 16 bit coeffs for the LMS give lousy results (maths good, actual sound + bad!), but 32 bit coeffs require some shifting. On balance 32 bit seems + best */ +#ifdef USE_SHORTS + echo_value = CONVOLVE2(ec->fir_taps_short, ec->tx_history + ec->curr_pos, ec->taps); +#else + echo_value = CONVOLVE(ec->fir_taps, ec->tx_history + ec->curr_pos, ec->taps); +#endif + echo_value >>= 16; + + /* And the answer is..... */ + clean_rx = rx - echo_value; + + /* That was the easy part. Now we need to adapt! */ + if (ec->nonupdate_dwell > 0) + ec->nonupdate_dwell--; + + /* If there is very little being transmitted, any attempt to train is + futile. We would either be training on the far end's noise or signal, + the channel's own noise, or our noise. Either way, this is hardly good + training, so don't do it (avoid trouble). */ + /* If the received power is very low, either we are sending very little or + we are already well adapted. There is little point in trying to improve + the adaption under these circumstanceson, so don't do it (reduce the + compute load). */ + if (ec->tx_power > MIN_TX_POWER_FOR_ADAPTION + && + ec->rx_power > MIN_RX_POWER_FOR_ADAPTION) + { + /* This is a really crude piece of decision logic, but it does OK + for now. */ + if (ec->tx_power > ec->rx_power << 1) + { + /* There is no far-end speech detected */ + if (ec->nonupdate_dwell == 0) + { + /* ... and we are not in the dwell time from previous speech. */ + //nsuppr = saturate((clean_rx << 16)/ec->tx_power); + nsuppr = (clean_rx << 16) / ec->tx_power; + nsuppr >>= 4; + if (nsuppr > 512) + nsuppr = 512; + if (nsuppr < -512) + nsuppr = -512; + + /* Update the FIR taps */ + ec->latest_correction = 0; +#ifdef USE_SHORTS + UPDATE2(ec->fir_taps, ec->fir_taps_short, ec->tx_history + ec->curr_pos, nsuppr, ec->taps); +#else + UPDATE(ec->fir_taps, ec->fir_taps_short, ec->tx_history + ec->curr_pos, nsuppr, ec->taps); +#endif + } else + { + ec->latest_correction = -3; + } + } + else + { + ec->nonupdate_dwell = NONUPDATE_DWELL_TIME; + ec->latest_correction = -2; + } + } + else + { + ec->nonupdate_dwell = 0; + ec->latest_correction = -1; + } + /* Calculate short term power levels using very simple single pole IIRs */ + /* TODO: Is the nasty modulus approach the fastest, or would a real + tx*tx power calculation actually be faster? */ + ec->tx_power += ((abs(tx) - ec->tx_power) >> 5); + ec->rx_power += ((abs(rx) - ec->rx_power) >> 5); + ec->clean_rx_power += ((abs(clean_rx) - ec->clean_rx_power) >> 5); + +#if defined(XYZZY) + if (ec->use_suppressor) + { + ec->supp_test1 += (ec->tx_history[ec->curr_pos] - ec->tx_history[(ec->curr_pos - 7) & ec->tap_mask]); + ec->supp_test2 += (ec->tx_history[(ec->curr_pos - 24) & ec->tap_mask] - ec->tx_history[(ec->curr_pos - 31) & ec->tap_mask]); + if (ec->supp_test1 > 42 && ec->supp_test2 > 42) + supp_change = 25; + else + supp_change = 50; + supp = supp_change + k1*ec->supp1 + k2*ec->supp2; + ec->supp2 = ec->supp1; + ec->supp1 = supp; + clean_rx *= (1 - supp); + } +#endif + + if (ec->use_nlp && ec->rx_power < 32) + clean_rx = 0; + + /* Roll around the rolling buffer */ + ec->curr_pos = (ec->curr_pos - 1) & ec->tap_mask; + + return clean_rx; +} +/*- End of function --------------------------------------------------------*/ + +static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) +{ + /* Reset hang counter to avoid adjustments after + initial forced training */ + ec->nonupdate_dwell = ec->taps << 1; + if (pos >= ec->taps) + return 1; + ec->fir_taps[pos] = val << 17; + ec->fir_taps_short[pos] = val << 1; + if (++pos >= ec->taps) + return 1; + return 0; +} + +/*- End of file ------------------------------------------------------------*/ +#endif diff --git a/kernel/tor2-hw.h b/kernel/tor2-hw.h new file mode 100644 index 0000000..8da5c52 --- /dev/null +++ b/kernel/tor2-hw.h @@ -0,0 +1,187 @@ +/* + * Tormenta 2 Quad-T1 PCI Driver + * + * Written by Mark Spencer + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001, Linux Support Services, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _TOR2_HW_H +#define _TOR2_HW_H + +/* + * The Tormenta two consists of the following block architecture: + * + * [ Spartan ] --- [ DS 21Q352 ] -- Xfrms -- Span 1 + * | | | | | | | + * Local Bus +----- Span 2 + * | | | | + * [ PCI 9030 ] +----- Span 3 + * | | | | | | + * PCI BUS +----- Span 4 + * + * All communicatiosn to the framer (21Q352) are performed + * through the PCI 9030 part using memory mapped I/O. + * + * The Tormenta 2 requires a 2 2k wondows memory space + * which is mapped as follows: + * + * First (32 bit) space: + * + * 0x0000 -> 0x07FF: Memory map of Tx and Rx buffers. They are stored + * with increasing channel number, with each span in + * a byte of a 32-bit long word: + * Bits 31-24: Span 1 + * Bits 23-16: Span 2 + * Bits 16- 8: Span 3 + * Bits 7- 0: Span 4 + * + * + * Second (8 bit) space: + * + * 0x0000 -> 0x00FF: Registers for Transceiver 1 + * 0x0100 -> 0x01FF: Registers for Transceiver 2 + * 0x0200 -> 0x02FF: Registers for Transceiver 3 + * 0x0300 -> 0x03FF: Registers for Transceiver 4 + * + * 0x400 Write -> Firmware load location for Xilinx. This is the only valid + * register until the Xilinx is programmed to decode + * the remainder! + * + * 0x400 Write -> clkreg (sync source) + * 0=free run, 1=span 1, 2=span 2, 3=span 3, 4=span 4. + * + * 0x400 Read -> statreg + * bit 0 - Interrupt Enabled + * bit 1 - Interrupt Active + * bit 2 - Dallas Interrupt Active + * + * 0x401 Write -> ctlreg as follows: + * bit 0 - Interrupt Enable + * bit 1 - Drives "TEST1" signal ("Interrupt" outbit) + * bit 2 - Dallas Interrupt Enable (Allows DINT signal to drive INT) + * bit 3 - External Syncronization Enable (MASTER signal). + * bit 4 - Select E1 Divisor Mode (0 for T1, 1 for E1). + * bit 5 - Remote serial loopback (When set to 1, TSER is driven from RSER) + * bit 6 - Local serial loopback (When set to 1, Rx buffers are driven from Tx buffers) + * bit 7 - Interrupt Acknowledge (set to 1 to acknowledge interrupt) + * + * 0x402 Write -> LED register as follows: + * bit 0 - Span 1 Green + * bit 1 - Span 1 Red + * bit 2 - Span 2 Green + * bit 3 - Span 2 Red + * bit 4 - Span 3 Green + * bit 5 - Span 3 Red + * bit 6 - Span 4 Green + * bit 7 - Span 4 Red + * NOTE: turning on both red and green yields yellow. + * + * 0x403 Write -> TEST2, writing to bit 0 drives TEST2 pin. + * + * 0x404 Write -> ctlreg1 as follows: + * bit 0 - Non-REV.A Mode (Set this bit for Dallas chips later then Rev. A) + */ + +#ifdef NEED_PCI_IDS +/* + * Provide routines for identifying a tormenta card + */ + +#define PCI_VENDOR_ID_PLX 0x10b5 + +#ifdef __KERNEL__ +static struct pci_device_id tor2_pci_ids[] = +#else +#define PCI_ANY_ID -1 +static struct tor2_pci_id { + int vendor; + int device; + int subvendor; + int subdevice; + int class; + int classmask; + unsigned long driver_data; +} tor2_pci_ids[] = +#endif /* __KERNEL__ */ +{ + { PCI_VENDOR_ID_PLX, 0x9030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)"PLX 9030" }, /* PLX 9030 Development board */ + { PCI_VENDOR_ID_PLX, 0x3001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)"PLX Development Board" }, /* PLX 9030 Development board */ + { PCI_VENDOR_ID_PLX, 0xD00D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)"Tormenta 2 Quad T1/PRI or E1/PRA" }, /* Tormenta 2 */ + { PCI_VENDOR_ID_PLX, 0x4000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)"Tormenta 2 Quad T1/E1 (non-Digium clone)" }, /* Tormenta 2 clone */ + { 0, } +}; + +#ifndef __KERNEL__ +/* We provide a simple routine to match the given ID's */ +static inline int tor2_pci_match(int vendorid, int deviceid, char **variant) +{ + /* Returns 1 if this is a tormenta card or 0 if it isn't */ + int x; + for (x = 0; x< sizeof(tor2_pci_ids) / sizeof(tor2_pci_ids[0]); x++) + if (((tor2_pci_ids[x].vendor == PCI_ANY_ID) || + (tor2_pci_ids[x].vendor == vendorid)) && + ((tor2_pci_ids[x].device == PCI_ANY_ID) || + (tor2_pci_ids[x].device == deviceid))) { + *variant = (char *)tor2_pci_ids[x].driver_data; + return 1; + } + if (variant) + *variant = NULL; + return 0; +} +#endif /* __KERNEL__ */ +#endif /* NEED_PCI_IDS */ + +/* + * PLX PCI9030 PCI Configuration Registers + * + * This is not an all-inclusive list, just some interesting ones + * that we need and that are not standard. + * + */ +#define PLX_PCI_VPD_ADDR 0x4e /* Set address here */ +#define PLX_PCI_VPD_DATA 0x50 /* Read/Write data here */ + +#define PLX_LOC_WP_BOUNDARY 0x4e /* Bits 6-0 here */ +#define PLX_LOC_GPIOC 0x54 /* GPIO control register */ + +/* The 4 GPIO data bits we are interested in */ + +#define LOC_GPIOC_GPIO4 0x4000 /* GPIO4 data */ +#define LOC_GPIOC_GPIO5 0x20000 /* GPIO5 data */ +#define LOC_GPIOC_GPIO6 0x100000 /* GPIO6 data */ +#define LOC_GPIOC_GPIO7 0x800000 /* GPIO7 data */ + +/* define the initialization of the GPIOC register */ + +#define LOC_GPIOC_INIT_VALUE 0x2036000 /* GPIO 4&5 in write and + both high and GPIO 8 in write low */ + +/* The defines by what they actually do */ + +#define GPIO_WRITE LOC_GPIOC_GPIO4 +#define GPIO_PROGRAM LOC_GPIOC_GPIO5 +#define GPIO_INIT LOC_GPIOC_GPIO6 +#define GPIO_DONE LOC_GPIOC_GPIO7 + +#endif /* _TOR2_HW_H */ + diff --git a/kernel/tor2.c b/kernel/tor2.c new file mode 100644 index 0000000..ef2cf05 --- /dev/null +++ b/kernel/tor2.c @@ -0,0 +1,1520 @@ +/* + * Tormenta 2 Quad-T1 PCI Driver + * + * Written by Mark Spencer + * Based on previous works, designs, and archetectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001, Linux Support Services, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "zaptel.h" +#ifdef LINUX26 +#include +#endif +#define NEED_PCI_IDS +#include "tor2-hw.h" +#include "tor2fw.h" + +/* + * Tasklets provide better system interactive response at the cost of the + * possibility of losing a frame of data at very infrequent intervals. If + * you are more concerned with the performance of your machine, enable the + * tasklets. If you are strict about absolutely no drops, then do not enable + * tasklets. + */ + +/* #define ENABLE_TASKLETS */ + +/* this stuff needs to work for 64 bit systems, however using the macro causes + it to take twice as long */ +/* #define FIXTHISFOR64 */ /* as of now, un-comment for 32 bit only system */ + +#define SPANS_PER_CARD 4 +#define MAX_SPANS 16 + +#define FLAG_STARTED (1 << 0) + +#define TYPE_T1 1 /* is a T1 card */ +#define TYPE_E1 2 /* is an E1 card */ + +struct tor2_chan { + /* Private pointer for channel. We want to know our + channel and span */ + struct tor2 *tor; + int span; /* Index from 0 */ +}; + +struct tor2_span { + /* Private pointer for span. We want to know our + span number and pointer to the tor device */ + struct tor2 *tor; + int span; /* Index from 0 */ +}; + +struct tor2 { + /* This structure exists one per card */ + struct pci_dev *pci; /* Pointer to PCI device */ + int num; /* Which card we are */ + int syncsrc; /* active sync source */ + int syncs[SPANS_PER_CARD]; /* sync sources */ + int psyncs[SPANS_PER_CARD]; /* span-relative sync sources */ + int alarmtimer[SPANS_PER_CARD]; /* Alarm timer */ + char *type; /* Type of tormenta 2 card */ + int irq; /* IRQ used by device */ + int order; /* Order */ + int flags; /* Device flags */ + int syncpos[SPANS_PER_CARD]; /* span-relative sync sources */ + int master; /* Are we master */ + unsigned long plx_region; /* phy addr of PCI9030 registers */ + unsigned long plx_len; /* length of PLX window */ + volatile unsigned short *plx; /* Virtual representation of local space */ + unsigned long xilinx32_region; /* 32 bit Region allocated to Xilinx */ + unsigned long xilinx32_len; /* Length of 32 bit Xilinx region */ + volatile unsigned int *mem32; /* Virtual representation of 32 bit Xilinx memory area */ + unsigned long xilinx8_region; /* 8 bit Region allocated to Xilinx */ + unsigned long xilinx8_len; /* Length of 8 bit Xilinx region */ + volatile unsigned char *mem8; /* Virtual representation of 8 bit Xilinx memory area */ + struct zt_span spans[SPANS_PER_CARD]; /* Spans */ + struct tor2_span tspans[SPANS_PER_CARD]; /* Span data */ + struct zt_chan *chans[SPANS_PER_CARD]; /* Pointers to blocks of 24(30/31) contiguous zt_chans for each span */ + struct tor2_chan tchans[32 * SPANS_PER_CARD]; /* Channel user data */ + unsigned char txsigs[SPANS_PER_CARD][16]; /* Copy of tx sig registers */ + int loopupcnt[SPANS_PER_CARD]; /* loop up code counter */ + int loopdowncnt[SPANS_PER_CARD];/* loop down code counter */ + int spansstarted; /* number of spans started */ + spinlock_t lock; /* lock context */ + unsigned char leds; /* copy of LED register */ + unsigned char ec_chunk1[SPANS_PER_CARD][32][ZT_CHUNKSIZE]; /* first EC chunk buffer */ + unsigned char ec_chunk2[SPANS_PER_CARD][32][ZT_CHUNKSIZE]; /* second EC chunk buffer */ +#ifdef ENABLE_TASKLETS + int taskletrun; + int taskletsched; + int taskletpending; + int taskletexec; + int txerrors; + struct tasklet_struct tor2_tlet; +#endif + int cardtype; /* card type, T1 or E1 */ + unsigned int *datxlt; /* pointer to datxlt structure */ + unsigned int passno; /* number of interrupt passes */ +}; + +#define t1out(tor,span,reg,val) tor->mem8[((span - 1) * 0x100) + reg] = val +#define t1in(tor,span,reg) tor->mem8[((span - 1) * 0x100) + reg] + +#ifdef ENABLE_TASKLETS +static void tor2_tasklet(unsigned long data); +#endif + +#define GPIOC (PLX_LOC_GPIOC >> 1) /* word-oriented address for PLX GPIOC reg. (32 bit reg.) */ +#define LAS2BRD (0x30 >> 1) +#define LAS3BRD (0x34 >> 1) +#define INTCSR (0x4c >> 1) /* word-oriented address for PLX INTCSR reg. */ +#define PLX_INTENA 0x43 /* enable, hi-going, level trigger */ + +#define SYNCREG 0x400 +#define CTLREG 0x401 +#define LEDREG 0x402 +#define STATREG 0x400 +#define SWREG 0x401 +#define CTLREG1 0x404 + +#define INTENA (1 + ((loopback & 3) << 5)) +#define OUTBIT (2 + ((loopback & 3) << 5)) +#define E1DIV 0x10 +#define INTACK (0x80 + ((loopback & 3) << 5)) +#define INTACTIVE 2 +#define MASTER (1 << 3) + +/* un-define this if you dont want NON-REV A hardware support */ +/* #define NONREVA 1 */ + +#define SYNCSELF 0 +#define SYNC1 1 +#define SYNC2 2 +#define SYNC3 3 +#define SYNC4 4 +#define SYNCEXTERN 5 + +#define LEDRED 2 +#define LEDGREEN 1 + +#define MAX_TOR_CARDS 64 + +struct tor2 *cards[MAX_TOR_CARDS]; + +/* signalling bits */ +#define TOR_ABIT 8 +#define TOR_BBIT 4 + +static int debug; +static int japan; +static int loopback; +static int highestorder; +static int timingcable; + +static void set_clear(struct tor2 *tor); +static int tor2_startup(struct zt_span *span); +static int tor2_shutdown(struct zt_span *span); +static int tor2_rbsbits(struct zt_chan *chan, int bits); +static int tor2_maint(struct zt_span *span, int cmd); +static int tor2_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data); +ZAP_IRQ_HANDLER(tor2_intr); + +/* translations of data channels for 24 channels in a 32 bit PCM highway */ +unsigned datxlt_t1[] = { + 1 ,2 ,3 ,5 ,6 ,7 ,9 ,10,11,13,14,15,17,18,19,21,22,23,25,26,27,29,30,31 }; + +/* translations of data channels for 30/31 channels in a 32 bit PCM highway */ +unsigned datxlt_e1[] = { + 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, + 25,26,27,28,29,30,31 }; + +static int tor2_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) +{ + int i; + struct tor2_span *p = span->pvt; + + if (debug) + printk("Tor2: Configuring span %d\n", span->spanno); + + span->syncsrc = p->tor->syncsrc; + + /* remove this span number from the current sync sources, if there */ + for (i = 0; i < SPANS_PER_CARD; i++) { + if (p->tor->syncs[i] == span->spanno) { + p->tor->syncs[i] = 0; + p->tor->psyncs[i] = 0; + } + } + p->tor->syncpos[p->span] = lc->sync; + /* if a sync src, put it in the proper place */ + if (lc->sync) { + p->tor->syncs[lc->sync - 1] = span->spanno; + p->tor->psyncs[lc->sync - 1] = p->span + 1; + } + /* If we're already running, then go ahead and apply the changes */ + if (span->flags & ZT_FLAG_RUNNING) + return tor2_startup(span); + + return 0; +} + +static int tor2_chanconfig(struct zt_chan *chan, int sigtype) +{ + int alreadyrunning; + unsigned long flags; + struct tor2_chan *p = chan->pvt; + + alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING; + if (debug) { + if (alreadyrunning) + printk("Tor2: Reconfigured channel %d (%s) sigtype %d\n", chan->channo, chan->name, sigtype); + else + printk("Tor2: Configured channel %d (%s) sigtype %d\n", chan->channo, chan->name, sigtype); + } + /* nothing more to do if an E1 */ + if (p->tor->cardtype == TYPE_E1) return 0; + spin_lock_irqsave(&p->tor->lock, flags); + if (alreadyrunning) + set_clear(p->tor); + spin_unlock_irqrestore(&p->tor->lock, flags); + return 0; +} + +static int tor2_open(struct zt_chan *chan) +{ +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#endif + return 0; +} + +static int tor2_close(struct zt_chan *chan) +{ +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#endif + return 0; +} + +static void init_spans(struct tor2 *tor) +{ + int x, y, c; + for (x = 0; x < SPANS_PER_CARD; x++) { + sprintf(tor->spans[x].name, "Tor2/%d/%d", tor->num, x + 1); + snprintf(tor->spans[x].desc, sizeof(tor->spans[x].desc) - 1, + "Tormenta 2 (PCI) fQuad %s Card %d Span %d", + (tor->cardtype == TYPE_T1) ? "T1" : "E1", tor->num, x + 1); + tor->spans[x].manufacturer = "Digium"; + strncpy(tor->spans[x].devicetype, tor->type, sizeof(tor->spans[x].devicetype) - 1); + snprintf(tor->spans[x].location, sizeof(tor->spans[x].location) - 1, + "PCI Bus %02d Slot %02d", tor->pci->bus->number, PCI_SLOT(tor->pci->devfn) + 1); + tor->spans[x].spanconfig = tor2_spanconfig; + tor->spans[x].chanconfig = tor2_chanconfig; + tor->spans[x].startup = tor2_startup; + tor->spans[x].shutdown = tor2_shutdown; + tor->spans[x].rbsbits = tor2_rbsbits; + tor->spans[x].maint = tor2_maint; + tor->spans[x].open = tor2_open; + tor->spans[x].close = tor2_close; + if (tor->cardtype == TYPE_T1) { + tor->spans[x].channels = 24; + tor->spans[x].deflaw = ZT_LAW_MULAW; + tor->spans[x].linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; + tor->spans[x].spantype = "T1"; + } else { + tor->spans[x].channels = 31; + tor->spans[x].deflaw = ZT_LAW_ALAW; + tor->spans[x].linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4; + tor->spans[x].spantype = "E1"; + } + tor->spans[x].chans = tor->chans[x]; + tor->spans[x].flags = ZT_FLAG_RBS; + tor->spans[x].ioctl = tor2_ioctl; + tor->spans[x].pvt = &tor->tspans[x]; + tor->tspans[x].tor = tor; + tor->tspans[x].span = x; + init_waitqueue_head(&tor->spans[x].maintq); + for (y=0;yspans[x].channels;y++) { + struct zt_chan *mychans = tor->chans[x] + y; + sprintf(mychans->name, "Tor2/%d/%d/%d", tor->num, x + 1, y + 1); + mychans->sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS | + ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF | ZT_SIG_EM_E1; + c = (x * tor->spans[x].channels) + y; + mychans->pvt = &tor->tchans[c]; + mychans->chanpos = y + 1; + tor->tchans[c].span = x; + tor->tchans[c].tor = tor; + } + } +} + +static int __devinit tor2_launch(struct tor2 *tor) +{ + if (tor->spans[0].flags & ZT_FLAG_REGISTERED) + return 0; + printk("Tor2: Launching card: %d\n", tor->order); + if (zt_register(&tor->spans[0], 0)) { + printk(KERN_ERR "Unable to register span %s\n", tor->spans[0].name); + return -1; + } + if (zt_register(&tor->spans[1], 0)) { + printk(KERN_ERR "Unable to register span %s\n", tor->spans[1].name); + zt_unregister(&tor->spans[0]); + return -1; + } + if (zt_register(&tor->spans[2], 0)) { + printk(KERN_ERR "Unable to register span %s\n", tor->spans[2].name); + zt_unregister(&tor->spans[0]); + zt_unregister(&tor->spans[1]); + return -1; + } + if (zt_register(&tor->spans[3], 0)) { + printk(KERN_ERR "Unable to register span %s\n", tor->spans[3].name); + zt_unregister(&tor->spans[0]); + zt_unregister(&tor->spans[1]); + zt_unregister(&tor->spans[2]); + return -1; + } + tor->plx[INTCSR] = cpu_to_le16(PLX_INTENA); /* enable PLX interrupt */ +#ifdef ENABLE_TASKLETS + tasklet_init(&tor->tor2_tlet, tor2_tasklet, (unsigned long)tor); +#endif + return 0; +} + +static int __devinit tor2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int res,x,f; + struct tor2 *tor; + unsigned long endjif; + volatile unsigned long *gpdata_io,*lasdata_io; + unsigned long gpdata,lasdata; + + res = pci_enable_device(pdev); + if (res) + return res; + tor = kmalloc(sizeof(struct tor2), GFP_KERNEL); + if (!tor) + return -ENOMEM; + memset(tor,0,sizeof(struct tor2)); + spin_lock_init(&tor->lock); + for (x = 0; x < SPANS_PER_CARD; x++) { + tor->chans[x] = kmalloc(sizeof(struct zt_chan) * 31,GFP_KERNEL); + if (!tor->chans[x]) + return -ENOMEM; + memset(tor->chans[x],0,sizeof(struct zt_chan) * 31); + } + /* Load the resources */ + tor->irq = pdev->irq; + if (tor->irq < 1) { + printk(KERN_ERR "No IRQ allocated for device\n"); + goto err_out_free_tor; + } + tor->plx_region = pci_resource_start(pdev, 0); + tor->plx_len = pci_resource_len(pdev, 0); + tor->plx = ioremap(tor->plx_region, tor->plx_len); + /* We don't use the I/O space, so we dont do anything with section 1 */ + tor->xilinx32_region = pci_resource_start(pdev, 2); + tor->xilinx32_len = pci_resource_len(pdev, 2); + tor->mem32 = ioremap(tor->xilinx32_region, tor->xilinx32_len); + tor->xilinx8_region = pci_resource_start(pdev, 3); + tor->xilinx8_len = pci_resource_len(pdev, 3); + tor->mem8 = ioremap(tor->xilinx8_region, tor->xilinx8_len); + /* Record what type */ + tor->type = (char *)ent->driver_data; + /* Verify existence and accuracy of resources */ + if (!tor->plx_region || !tor->plx || + (pci_resource_flags(pdev, 0) & IORESOURCE_IO)) { + printk(KERN_ERR "Invalid PLX 9030 Base resource\n"); + goto err_out_free_tor; + } + if (!tor->xilinx32_region || !tor->mem32 || + (pci_resource_flags(pdev, 2) & IORESOURCE_IO)) { + printk(KERN_ERR "Invalid Xilinx 32 bit Base resource\n"); + goto err_out_free_tor; + } + if (!tor->xilinx8_region || !tor->mem8 || + (pci_resource_flags(pdev, 3) & IORESOURCE_IO)) { + printk(KERN_ERR "Invalid Xilinx 8 bit Base resource\n"); + goto err_out_free_tor; + } + /* Request regions */ + if (!request_mem_region(tor->plx_region, tor->plx_len, tor->type)) { + printk(KERN_ERR "Unable to reserve PLX memory %08lx window at %08lx\n", + tor->plx_len, tor->plx_region); + goto err_out_free_tor; + } + if (!request_mem_region(tor->xilinx32_region, tor->xilinx32_len, tor->type)) { + printk(KERN_ERR "Unable to reserve Xilinx 32 bit memory %08lx window at %08lx\n", + tor->xilinx32_len, tor->xilinx32_region); + goto err_out_release_plx_region; + } + if (!request_mem_region(tor->xilinx8_region, tor->xilinx8_len, tor->type)) { + printk(KERN_ERR "Unable to reserve Xilinx memory %08lx window at %08lx\n", + tor->xilinx8_len, tor->xilinx8_region); + goto err_out_release_plx_region; + } + pci_set_drvdata(pdev, tor); + printk("Detected %s at 0x%lx/0x%lx irq %d\n", tor->type, + tor->xilinx32_region, tor->xilinx8_region,tor->irq); + + for (x = 0; x < MAX_TOR_CARDS; x++) { + if (!cards[x]) break; + } + if (x >= MAX_TOR_CARDS) { + printk("No cards[] slot available!!\n"); + goto err_out_release_all; + } + tor->num = x; + cards[x] = tor; + + /* start programming mode */ + gpdata_io = (unsigned long *)&tor->plx[GPIOC]; + gpdata = le32_to_cpu(*gpdata_io); + + gpdata |= GPIO_WRITE; /* make sure WRITE is not asserted */ + *gpdata_io = cpu_to_le32(gpdata); + + gpdata &= ~GPIO_PROGRAM; /* activate the PROGRAM signal */ + *gpdata_io = cpu_to_le32(gpdata); + + /* wait for INIT and DONE to go low */ + endjif = jiffies + 10; + while (le32_to_cpu(*gpdata_io) & (GPIO_INIT | GPIO_DONE) && (jiffies <= endjif)); + + if (endjif < jiffies) { + printk("Timeout waiting for INIT and DONE to go low\n"); + goto err_out_release_all; + } + if (debug) printk("fwload: Init and done gone to low\n"); + gpdata |= GPIO_PROGRAM; + *gpdata_io = cpu_to_le32(gpdata); /* de-activate the PROGRAM signal */ + /* wait for INIT to go high (clearing done */ + endjif = jiffies + 10; + while (!(le32_to_cpu(*gpdata_io) & GPIO_INIT) && (jiffies <= endjif)); + if (endjif < jiffies) { + printk("Timeout waiting for INIT to go high\n"); + goto err_out_release_all; + } + + if (debug) printk("fwload: Init went high (clearing done)\nNow loading...\n"); + /* assert WRITE signal */ + gpdata &= ~GPIO_WRITE; + *gpdata_io = cpu_to_le32(gpdata); + for (x = 0; x < sizeof(tor2fw); x++) + { + /* write the byte */ + *tor->mem8 = tor2fw[x]; + /* if DONE signal, we're done, exit */ + if (le32_to_cpu(*gpdata_io) & GPIO_DONE) break; + /* if INIT drops, we're screwed, exit */ + if (!(le32_to_cpu(*gpdata_io) & GPIO_INIT)) break; + } + if (debug) printk("fwload: Transferred %d bytes into chip\n",x); + /* Wait for FIFO to clear */ + endjif = jiffies + 2; + while (jiffies < endjif); /* wait */ + /* de-assert write signal */ + gpdata |= GPIO_WRITE; + *gpdata_io = cpu_to_le32(gpdata); + if (debug) printk("fwload: Loading done!\n"); + + /* Wait for FIFO to clear */ + endjif = jiffies + 2; + while (jiffies < endjif); /* wait */ + if (!(le32_to_cpu(*gpdata_io) & GPIO_INIT)) + { + printk("Drove Init low!! CRC Error!!!\n"); + goto err_out_release_all; + } + if (!(le32_to_cpu(*gpdata_io) & GPIO_DONE)) + { + printk("Did not get DONE signal. Short file maybe??\n"); + goto err_out_release_all; + } + printk("Xilinx Chip successfully loaded, configured and started!!\n"); + + tor->mem8[SYNCREG] = 0; + tor->mem8[CTLREG] = 0; + tor->mem8[CTLREG1] = 0; + tor->mem8[LEDREG] = 0; + + /* set the LA2BRD register so that we enable block transfer, read + pre-fetch, and set to maximum read pre-fetch size */ + lasdata_io = (unsigned long *)&tor->plx[LAS2BRD]; + lasdata = *lasdata_io; + lasdata |= 0x39; + *lasdata_io = lasdata; + + /* set the LA3BRD register so that we enable block transfer */ + lasdata_io = (unsigned long *)&tor->plx[LAS3BRD]; + lasdata = *lasdata_io; + lasdata |= 1; + *lasdata_io = lasdata; + + /* check part revision data */ + x = t1in(tor,1,0xf) & 15; +#ifdef NONREVA + if (x > 3) + { + tor->mem8[CTLREG1] = NONREVA; + } +#endif + for (x = 0; x < 256; x++) tor->mem32[x] = 0x7f7f7f7f; + + + if (request_irq(tor->irq, tor2_intr, ZAP_IRQ_SHARED_DISABLED, "tor2", tor)) { + printk(KERN_ERR "Unable to request tormenta IRQ %d\n", tor->irq); + goto err_out_release_all; + } + + if (t1in(tor,1,0xf) & 0x80) { + printk("Tormenta 2 Quad E1/PRA Card\n"); + tor->cardtype = TYPE_E1; + tor->datxlt = datxlt_e1; + } else { + printk("Tormenta 2 Quad T1/PRI Card\n"); + tor->cardtype = TYPE_T1; + tor->datxlt = datxlt_t1; + } + init_spans(tor); + + tor->order = tor->mem8[SWREG]; + printk("Detected Card number: %d\n", tor->order); + + /* Launch cards as appropriate */ + x = 0; + for (;;) { + /* Find a card to activate */ + f = 0; + for (x=0;cards[x];x++) { + if (cards[x]->order <= highestorder) { + tor2_launch(cards[x]); + if (cards[x]->order == highestorder) + f = 1; + } + } + /* If we found at least one, increment the highest order and search again, otherwise stop */ + if (f) + highestorder++; + else + break; + } + + return 0; + +err_out_release_all: + release_mem_region(tor->xilinx32_region, tor->xilinx32_len); + release_mem_region(tor->xilinx8_region, tor->xilinx8_len); +err_out_release_plx_region: + release_mem_region(tor->plx_region, tor->plx_len); +err_out_free_tor: + if (tor->plx) iounmap((void *)tor->plx); + if (tor->mem8) iounmap((void *)tor->mem8); + if (tor->mem32) iounmap((void *)tor->mem32); + if (tor) { + for (x = 0; x < 3; x++) kfree(tor->chans[x]); + kfree(tor); + } + return -ENODEV; +} + +static struct pci_driver tor2_driver; + +static void __devexit tor2_remove(struct pci_dev *pdev) +{ + int x; + struct tor2 *tor; + tor = pci_get_drvdata(pdev); + if (!tor) + BUG(); + tor->mem8[SYNCREG] = 0; + tor->mem8[CTLREG] = 0; + tor->mem8[LEDREG] = 0; + tor->plx[INTCSR] = cpu_to_le16(0); + free_irq(tor->irq, tor); + if (tor->spans[0].flags & ZT_FLAG_REGISTERED) + zt_unregister(&tor->spans[0]); + if (tor->spans[1].flags & ZT_FLAG_REGISTERED) + zt_unregister(&tor->spans[1]); + if (tor->spans[2].flags & ZT_FLAG_REGISTERED) + zt_unregister(&tor->spans[2]); + if (tor->spans[3].flags & ZT_FLAG_REGISTERED) + zt_unregister(&tor->spans[3]); + release_mem_region(tor->plx_region, tor->plx_len); + release_mem_region(tor->xilinx32_region, tor->xilinx32_len); + release_mem_region(tor->xilinx8_region, tor->xilinx8_len); + if (tor->plx) iounmap((void *)tor->plx); + if (tor->mem8) iounmap((void *)tor->mem8); + if (tor->mem32) iounmap((void *)tor->mem32); + + cards[tor->num] = 0; + pci_set_drvdata(pdev, NULL); + for (x = 0; x < 3; x++) + if (tor->chans[x]) + kfree(tor->chans[x]); + kfree(tor); +} + +static struct pci_driver tor2_driver = { + name: "tormenta2", + probe: tor2_probe, +#ifdef LINUX26 + remove: __devexit_p(tor2_remove), +#else + remove: tor2_remove, +#endif + id_table: tor2_pci_ids, +}; + +static int __init tor2_init(void) { + int res; + res = zap_pci_module(&tor2_driver); + printk("Registered Tormenta2 PCI\n"); + return res; +} + +static void __exit tor2_cleanup(void) { + pci_unregister_driver(&tor2_driver); + printk("Unregistered Tormenta2\n"); +} + +static void set_clear(struct tor2 *tor) +{ + int i,j,s; + unsigned short val=0; + for (s = 0; s < SPANS_PER_CARD; s++) { + for (i = 0; i < 24; i++) { + j = (i/8); + if (tor->spans[s].chans[i].flags & ZT_FLAG_CLEAR) + val |= 1 << (i % 8); + + if ((i % 8)==7) { +#if 0 + printk("Putting %d in register %02x on span %d\n", + val, 0x39 + j, 1 + s); +#endif + t1out(tor,1 + s, 0x39 + j, val); + val = 0; + } + } + } + +} + + +static int tor2_rbsbits(struct zt_chan *chan, int bits) +{ + u_char m,c; + int k,n,b; + struct tor2_chan *p = chan->pvt; + unsigned long flags; +#if 0 + printk("Setting bits to %d on channel %s\n", bits, chan->name); +#endif + if (p->tor->cardtype == TYPE_E1) { /* do it E1 way */ + if (chan->chanpos == 16) return 0; + n = chan->chanpos - 1; + if (chan->chanpos > 16) n--; + k = p->span; + b = (n % 15) + 1; + c = p->tor->txsigs[k][b]; + m = (n / 15) * 4; /* nibble selector */ + c &= (15 << m); /* keep the other nibble */ + c |= (bits & 15) << (4 - m); /* put our new nibble here */ + p->tor->txsigs[k][b] = c; + /* output them to the chip */ + t1out(p->tor,k + 1,0x40 + b,c); + return 0; + } + n = chan->chanpos - 1; + k = p->span; + b = (n / 8); /* get byte number */ + m = 1 << (n & 7); /* get mask */ + c = p->tor->txsigs[k][b]; + c &= ~m; /* clear mask bit */ + /* set mask bit, if bit is to be set */ + if (bits & ZT_ABIT) c |= m; + p->tor->txsigs[k][b] = c; + spin_lock_irqsave(&p->tor->lock, flags); + t1out(p->tor,k + 1,0x70 + b,c); + b += 3; /* now points to b bit stuff */ + /* get current signalling values */ + c = p->tor->txsigs[k][b]; + c &= ~m; /* clear mask bit */ + /* set mask bit, if bit is to be set */ + if (bits & ZT_BBIT) c |= m; + /* save new signalling values */ + p->tor->txsigs[k][b] = c; + /* output them into the chip */ + t1out(p->tor,k + 1,0x70 + b,c); + b += 3; /* now points to c bit stuff */ + /* get current signalling values */ + c = p->tor->txsigs[k][b]; + c &= ~m; /* clear mask bit */ + /* set mask bit, if bit is to be set */ + if (bits & ZT_CBIT) c |= m; + /* save new signalling values */ + p->tor->txsigs[k][b] = c; + /* output them into the chip */ + t1out(p->tor,k + 1,0x70 + b,c); + b += 3; /* now points to d bit stuff */ + /* get current signalling values */ + c = p->tor->txsigs[k][b]; + c &= ~m; /* clear mask bit */ + /* set mask bit, if bit is to be set */ + if (bits & ZT_DBIT) c |= m; + /* save new signalling values */ + p->tor->txsigs[k][b] = c; + /* output them into the chip */ + t1out(p->tor,k + 1,0x70 + b,c); + spin_unlock_irqrestore(&p->tor->lock, flags); + return 0; +} + +static int tor2_shutdown(struct zt_span *span) +{ + int i; + int tspan; + int wasrunning; + unsigned long flags; + struct tor2_span *p = span->pvt; + + tspan = p->span + 1; + if (tspan < 0) { + printk("Tor2: Span '%d' isn't us?\n", span->spanno); + return -1; + } + + spin_lock_irqsave(&p->tor->lock, flags); + wasrunning = span->flags & ZT_FLAG_RUNNING; + + span->flags &= ~ZT_FLAG_RUNNING; + /* Zero out all registers */ + if (p->tor->cardtype == TYPE_E1) { + for (i = 0; i < 192; i++) + t1out(p->tor,tspan, i, 0); + } else { + for (i = 0; i < 160; i++) + t1out(p->tor,tspan, i, 0); + } + if (wasrunning) + p->tor->spansstarted--; + spin_unlock_irqrestore(&p->tor->lock, flags); + if (!(p->tor->spans[0].flags & ZT_FLAG_RUNNING) && + !(p->tor->spans[1].flags & ZT_FLAG_RUNNING) && + !(p->tor->spans[2].flags & ZT_FLAG_RUNNING) && + !(p->tor->spans[3].flags & ZT_FLAG_RUNNING)) + /* No longer in use, disable interrupts */ + p->tor->mem8[CTLREG] = 0; + if (debug) + printk("Span %d (%s) shutdown\n", span->spanno, span->name); + return 0; +} + + +static int tor2_startup(struct zt_span *span) +{ + unsigned long endjif; + int i; + int tspan; + unsigned long flags; + char *coding; + char *framing; + char *crcing; + int alreadyrunning; + struct tor2_span *p = span->pvt; + + tspan = p->span + 1; + if (tspan < 0) { + printk("Tor2: Span '%d' isn't us?\n", span->spanno); + return -1; + } + + spin_lock_irqsave(&p->tor->lock, flags); + + alreadyrunning = span->flags & ZT_FLAG_RUNNING; + + /* initialize the start value for the entire chunk of last ec buffer */ + for (i = 0; i < span->channels; i++) + { + memset(p->tor->ec_chunk1[p->span][i], + ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); + memset(p->tor->ec_chunk2[p->span][i], + ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); + } + /* Force re-evaluation of the timing source */ + if (timingcable) + p->tor->syncsrc = -1; + + if (p->tor->cardtype == TYPE_E1) { /* if this is an E1 card */ + unsigned char tcr1,ccr1,tcr2; + if (!alreadyrunning) { + p->tor->mem8[SYNCREG] = SYNCSELF; + p->tor->mem8[CTLREG] = E1DIV; + p->tor->mem8[LEDREG] = 0; + /* Force re-evaluation of sync src */ + /* Zero out all registers */ + for (i = 0; i < 192; i++) + t1out(p->tor,tspan, i, 0); + + /* Set up for Interleaved Serial Bus operation in byte mode */ + /* Set up all the spans every time, so we are sure they are + in a consistent state. If we don't, a card without all + its spans configured misbehaves in strange ways. */ + t1out(p->tor,1,0xb5,9); + t1out(p->tor,2,0xb5,8); + t1out(p->tor,3,0xb5,8); + t1out(p->tor,4,0xb5,8); + + t1out(p->tor,tspan,0x1a,4); /* CCR2: set LOTCMC */ + for (i = 0; i <= 8; i++) t1out(p->tor,tspan,i,0); + for (i = 0x10; i <= 0x4f; i++) if (i != 0x1a) t1out(p->tor,tspan,i,0); + t1out(p->tor,tspan,0x10,0x20); /* RCR1: Rsync as input */ + t1out(p->tor,tspan,0x11,6); /* RCR2: Sysclk=2.048 Mhz */ + t1out(p->tor,tspan,0x12,9); /* TCR1: TSiS mode */ + } + ccr1 = 0; + crcing = ""; + tcr1 = 9; /* base TCR1 value: TSis mode */ + tcr2 = 0; + if (span->lineconfig & ZT_CONFIG_CCS) { + ccr1 |= 8; /* CCR1: Rx Sig mode: CCS */ + coding = "CCS"; + } else { + tcr1 |= 0x20; + coding = "CAS"; + } + if (span->lineconfig & ZT_CONFIG_HDB3) { + ccr1 |= 0x44; /* CCR1: TX and RX HDB3 */ + framing = "HDB3"; + } else framing = "AMI"; + if (span->lineconfig & ZT_CONFIG_CRC4) { + ccr1 |= 0x11; /* CCR1: TX and TX CRC4 */ + tcr2 |= 0x02; /* TCR2: CRC4 bit auto */ + crcing = "/CRC4"; + } + t1out(p->tor,tspan,0x12,tcr1); + t1out(p->tor,tspan,0x13,tcr2); + t1out(p->tor,tspan,0x14,ccr1); + t1out(p->tor,tspan, 0x18, 0x20); /* 120 Ohm, normal */ + + if (!alreadyrunning) { + t1out(p->tor,tspan,0x1b,0x8a); /* CCR3: LIRST & TSCLKM */ + t1out(p->tor,tspan,0x20,0x1b); /* TAFR */ + t1out(p->tor,tspan,0x21,0x5f); /* TNAFR */ + t1out(p->tor,tspan,0x40,0xb); /* TSR1 */ + for (i = 0x41; i <= 0x4f; i++) t1out(p->tor,tspan,i,0x55); + for (i = 0x22; i <= 0x25; i++) t1out(p->tor,tspan,i,0xff); + /* Wait 100 ms */ + endjif = jiffies + 10; + spin_unlock_irqrestore(&p->tor->lock, flags); + while (jiffies < endjif); /* wait 100 ms */ + spin_lock_irqsave(&p->tor->lock, flags); + t1out(p->tor,tspan,0x1b,0x9a); /* CCR3: set also ESR */ + t1out(p->tor,tspan,0x1b,0x82); /* CCR3: TSCLKM only now */ + + span->flags |= ZT_FLAG_RUNNING; + p->tor->spansstarted++; + + /* enable interrupts */ + p->tor->mem8[CTLREG] = INTENA | E1DIV; + } + + spin_unlock_irqrestore(&p->tor->lock, flags); + + if (debug) { + if (alreadyrunning) + printk("Tor2: Reconfigured span %d (%s/%s%s) 120 Ohms\n", span->spanno, coding, framing, crcing); + else + printk("Tor2: Startup span %d (%s/%s%s) 120 Ohms\n", span->spanno, coding, framing, crcing); + } + } else { /* is a T1 card */ + + if (!alreadyrunning) { + p->tor->mem8[SYNCREG] = SYNCSELF; + p->tor->mem8[CTLREG] = 0; + p->tor->mem8[LEDREG] = 0; + /* Zero out all registers */ + for (i = 0; i < 160; i++) + t1out(p->tor,tspan, i, 0); + + /* Set up for Interleaved Serial Bus operation in byte mode */ + /* Set up all the spans every time, so we are sure they are + in a consistent state. If we don't, a card without all + its spans configured misbehaves in strange ways. */ + t1out(p->tor,1,0x94,9); + t1out(p->tor,2,0x94,8); + t1out(p->tor,3,0x94,8); + t1out(p->tor,4,0x94,8); + /* Full-on Sync required (RCR1) */ + t1out(p->tor,tspan, 0x2b, 8); + /* RSYNC is an input (RCR2) */ + t1out(p->tor,tspan, 0x2c, 8); + /* RBS enable (TCR1) */ + t1out(p->tor,tspan, 0x35, 0x10); + /* TSYNC to be output (TCR2) */ + t1out(p->tor,tspan, 0x36, 4); + /* Tx & Rx Elastic store, sysclk(s) = 2.048 mhz, loopback controls (CCR1) */ + t1out(p->tor,tspan, 0x37, 0x9c); + /* Set up received loopup and loopdown codes */ + t1out(p->tor,tspan, 0x12, 0x22); + t1out(p->tor,tspan, 0x14, 0x80); + t1out(p->tor,tspan, 0x15, 0x80); + /* Setup japanese mode if appropriate */ + t1out(p->tor,tspan,0x19,(japan ? 0x80 : 0x00)); /* no local loop */ + t1out(p->tor,tspan,0x1e,(japan ? 0x80 : 0x00)); /* no local loop */ + } + /* Enable F bits pattern */ + i = 0x20; + if (span->lineconfig & ZT_CONFIG_ESF) + i = 0x88; + if (span->lineconfig & ZT_CONFIG_B8ZS) + i |= 0x44; + t1out(p->tor,tspan, 0x38, i); + if (i & 0x80) + coding = "ESF"; + else + coding = "SF"; + if (i & 0x40) + framing = "B8ZS"; + else { + framing = "AMI"; + t1out(p->tor,tspan,0x7e,0x1c); /* F bits pattern (0x1c) into FDL register */ + } + t1out(p->tor,tspan, 0x7c, span->txlevel << 5); + + if (!alreadyrunning) { + /* LIRST to reset line interface */ + t1out(p->tor,tspan, 0x0a, 0x80); + + /* Wait 100 ms */ + endjif = jiffies + 10; + + spin_unlock_irqrestore(&p->tor->lock, flags); + + while (jiffies < endjif); /* wait 100 ms */ + + spin_lock_irqsave(&p->tor->lock, flags); + + t1out(p->tor,tspan,0x0a,0x30); /* LIRST back to normal, Resetting elastic stores */ + + span->flags |= ZT_FLAG_RUNNING; + p->tor->spansstarted++; + + /* enable interrupts */ + p->tor->mem8[CTLREG] = INTENA; + } + + set_clear(p->tor); + + spin_unlock_irqrestore(&p->tor->lock, flags); + + if (debug) { + if (alreadyrunning) + printk("Tor2: Reconfigured span %d (%s/%s) LBO: %s\n", span->spanno, coding, framing, zt_lboname(span->txlevel)); + else + printk("Tor2: Startup span %d (%s/%s) LBO: %s\n", span->spanno, coding, framing, zt_lboname(span->txlevel)); + } + } + if (p->tor->syncs[0] == span->spanno) printk("SPAN %d: Primary Sync Source\n",span->spanno); + if (p->tor->syncs[1] == span->spanno) printk("SPAN %d: Secondary Sync Source\n",span->spanno); + if (p->tor->syncs[2] == span->spanno) printk("SPAN %d: Tertiary Sync Source\n",span->spanno); + if (p->tor->syncs[3] == span->spanno) printk("SPAN %d: Quaternary Sync Source\n",span->spanno); + return 0; +} + +static int tor2_maint(struct zt_span *span, int cmd) +{ + struct tor2_span *p = span->pvt; + + int tspan = p->span + 1; + + if (p->tor->cardtype == TYPE_E1) + { + switch(cmd) { + case ZT_MAINT_NONE: + t1out(p->tor,tspan,0xa8,0); /* no loops */ + break; + case ZT_MAINT_LOCALLOOP: + t1out(p->tor,tspan,0xa8,0x40); /* local loop */ + break; + case ZT_MAINT_REMOTELOOP: + t1out(p->tor,tspan,0xa8,0x80); /* remote loop */ + break; + case ZT_MAINT_LOOPUP: + case ZT_MAINT_LOOPDOWN: + case ZT_MAINT_LOOPSTOP: + return -ENOSYS; + default: + printk("Tor2: Unknown maint command: %d\n", cmd); + break; + } + return 0; + } + switch(cmd) { + case ZT_MAINT_NONE: + t1out(p->tor,tspan,0x19,(japan ? 0x80 : 0x00)); /* no local loop */ + t1out(p->tor,tspan,0x0a,0); /* no remote loop */ + break; + case ZT_MAINT_LOCALLOOP: + t1out(p->tor,tspan,0x19,0x40 | (japan ? 0x80 : 0x00)); /* local loop */ + t1out(p->tor,tspan,0x0a,0); /* no remote loop */ + break; + case ZT_MAINT_REMOTELOOP: + t1out(p->tor,tspan,0x1e,(japan ? 0x80 : 0x00)); /* no local loop */ + t1out(p->tor,tspan,0x0a,0x40); /* remote loop */ + break; + case ZT_MAINT_LOOPUP: + t1out(p->tor,tspan,0x30,2); /* send loopup code */ + t1out(p->tor,tspan,0x12,0x22); /* send loopup code */ + t1out(p->tor,tspan,0x13,0x80); /* send loopup code */ + break; + case ZT_MAINT_LOOPDOWN: + t1out(p->tor,tspan,0x30,2); /* send loopdown code */ + t1out(p->tor,tspan,0x12,0x62); /* send loopdown code */ + t1out(p->tor,tspan,0x13,0x90); /* send loopdown code */ + break; + case ZT_MAINT_LOOPSTOP: + t1out(p->tor,tspan,0x30,0); /* stop sending loopup code */ + break; + default: + printk("Tor2: Unknown maint command: %d\n", cmd); + break; + } + return 0; +} + +static inline void tor2_run(struct tor2 *tor) +{ + int x,y; + for (x = 0; x < SPANS_PER_CARD; x++) { + if (tor->spans[x].flags & ZT_FLAG_RUNNING) { + /* since the Tormenta 2 PCI is double-buffered, you + need to delay the transmit data 2 entire chunks so + that the transmit will be in sync with the receive */ + for (y=0;yspans[x].channels;y++) { + zt_ec_chunk(&tor->spans[x].chans[y], + tor->spans[x].chans[y].readchunk, + tor->ec_chunk2[x][y]); + memcpy(tor->ec_chunk2[x][y],tor->ec_chunk1[x][y], + ZT_CHUNKSIZE); + memcpy(tor->ec_chunk1[x][y], + tor->spans[x].chans[y].writechunk, + ZT_CHUNKSIZE); + } + zt_receive(&tor->spans[x]); + } + } + for (x = 0; x < SPANS_PER_CARD; x++) { + if (tor->spans[x].flags & ZT_FLAG_RUNNING) + zt_transmit(&tor->spans[x]); + } +} + +#ifdef ENABLE_TASKLETS +static void tor2_tasklet(unsigned long data) +{ + struct tor2 *tor = (struct tor2 *)data; + tor->taskletrun++; + if (tor->taskletpending) { + tor->taskletexec++; + tor2_run(tor); + } + tor->taskletpending = 0; +} +#endif + +static int syncsrc = 0; +static int syncnum = 0 /* -1 */; +static int syncspan = 0; +#ifdef DEFINE_SPINLOCK +static DEFINE_SPINLOCK(synclock); +#else +static spinlock_t synclock = SPIN_LOCK_UNLOCKED; +#endif + +static int tor2_findsync(struct tor2 *tor) +{ + int i; + int x; + unsigned long flags; + int p; + int nonzero; + int newsyncsrc = 0; /* Zaptel span number */ + int newsyncnum = 0; /* tor2 card number */ + int newsyncspan = 0; /* span on given tor2 card */ + spin_lock_irqsave(&synclock, flags); +#if 1 + if (!tor->num) { + /* If we're the first card, go through all the motions, up to 8 levels + of sync source */ + p = 1; + while (p < 8) { + nonzero = 0; + for (x=0;cards[x];x++) { + for (i = 0; i < SPANS_PER_CARD; i++) { + if (cards[x]->syncpos[i]) { + nonzero = 1; + if ((cards[x]->syncpos[i] == p) && + !(cards[x]->spans[i].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK)) && + (cards[x]->spans[i].flags & ZT_FLAG_RUNNING)) { + /* This makes a good sync source */ + newsyncsrc = cards[x]->spans[i].spanno; + newsyncnum = x; + newsyncspan = i + 1; + /* Jump out */ + goto found; + } + } + } + } + if (nonzero) + p++; + else + break; + } +found: + if ((syncnum != newsyncnum) || (syncsrc != newsyncsrc) || (newsyncspan != syncspan)) { + syncnum = newsyncnum; + syncsrc = newsyncsrc; + syncspan = newsyncspan; + if (debug) printk("New syncnum: %d, syncsrc: %d, syncspan: %d\n", syncnum, syncsrc, syncspan); + } + } +#endif + /* update sync src info */ + if (tor->syncsrc != syncsrc) { + tor->syncsrc = syncsrc; + /* Update sync sources */ + for (i = 0; i < SPANS_PER_CARD; i++) { + tor->spans[i].syncsrc = tor->syncsrc; + } + if (syncnum == tor->num) { +#if 1 + /* actually set the sync register */ + tor->mem8[SYNCREG] = syncspan; +#endif + if (debug) printk("Card %d, using sync span %d, master\n", tor->num, syncspan); + tor->master = MASTER; + } else { +#if 1 + /* time from the timing cable */ + tor->mem8[SYNCREG] = SYNCEXTERN; +#endif + tor->master = 0; + if (debug) printk("Card %d, using Timing Bus, NOT master\n", tor->num); + } + } + spin_unlock_irqrestore(&synclock, flags); + return 0; +} + +ZAP_IRQ_HANDLER(tor2_intr) +{ + int n, i, j, k, syncsrc; + unsigned int rxword,txword; + + unsigned char c, rxc; + unsigned char abits, bbits; + struct tor2 *tor = (struct tor2 *) dev_id; + + /* make sure its a real interrupt for us */ + if (!(tor->mem8[STATREG] & INTACTIVE)) /* if not, just return */ + { +#ifdef LINUX26 + return IRQ_NONE; +#else + return; +#endif + } + + if (tor->cardtype == TYPE_E1) + /* set outbit, interrupt enable, and ack interrupt */ + tor->mem8[CTLREG] = OUTBIT | INTENA | INTACK | E1DIV | tor->master; + else + /* set outbit, interrupt enable, and ack interrupt */ + tor->mem8[CTLREG] = OUTBIT | INTENA | INTACK | tor->master; + +#if 0 + if (!tor->passno) + printk("Interrupt handler\n"); +#endif + + /* do the transmit output */ + for (n = 0; n < tor->spans[0].channels; n++) { + for (i = 0; i < ZT_CHUNKSIZE; i++) { + /* span 1 */ + txword = tor->spans[0].chans[n].writechunk[i] << 24; + /* span 2 */ + txword |= tor->spans[1].chans[n].writechunk[i] << 16; + /* span 3 */ + txword |= tor->spans[2].chans[n].writechunk[i] << 8; + /* span 4 */ + txword |= tor->spans[3].chans[n].writechunk[i]; + /* write to part */ +#ifdef FIXTHISFOR64 + tor->mem32[tor->datxlt[n] + (32 * i)] = txword; +#else + tor->mem32[tor->datxlt[n] + (32 * i)] = cpu_to_le32(txword); +#endif + } + } + + /* Do the receive input */ + for (n = 0; n < tor->spans[0].channels; n++) { + for (i = 0; i < ZT_CHUNKSIZE; i++) { + /* read from */ +#ifdef FIXTHISFOR64 + rxword = tor->mem32[tor->datxlt[n] + (32 * i)]; +#else + rxword = le32_to_cpu(tor->mem32[tor->datxlt[n] + (32 * i)]); +#endif + /* span 1 */ + tor->spans[0].chans[n].readchunk[i] = rxword >> 24; + /* span 2 */ + tor->spans[1].chans[n].readchunk[i] = (rxword & 0xff0000) >> 16; + /* span 3 */ + tor->spans[2].chans[n].readchunk[i] = (rxword & 0xff00) >> 8; + /* span 4 */ + tor->spans[3].chans[n].readchunk[i] = rxword & 0xff; + } + } + + i = tor->passno & 15; + /* if an E1 card, do rx signalling for it */ + if ((i < 3) && (tor->cardtype == TYPE_E1)) { /* if an E1 card */ + for (j = (i * 5); j < (i * 5) + 5; j++) { + for (k = 1; k <= SPANS_PER_CARD; k++) { + c = t1in(tor,k,0x31 + j); + rxc = c & 15; + if (rxc != tor->spans[k - 1].chans[j + 16].rxsig) { + /* Check for changes in received bits */ + if (!(tor->spans[k - 1].chans[j + 16].sig & ZT_SIG_CLEAR)) + zt_rbsbits(&tor->spans[k - 1].chans[j + 16], rxc); + } + rxc = c >> 4; + if (rxc != tor->spans[k - 1].chans[j].rxsig) { + /* Check for changes in received bits */ + if (!(tor->spans[k - 1].chans[j].sig & ZT_SIG_CLEAR)) + zt_rbsbits(&tor->spans[k - 1].chans[j], rxc); + } + } + } + } + + /* if a T1, do the signalling */ + if ((i < 12) && (tor->cardtype == TYPE_T1)) { + k = (i / 3); /* get span */ + n = (i % 3); /* get base */ + abits = t1in(tor,k + 1, 0x60 + n); + bbits = t1in(tor,k + 1, 0x63 + n); + for (j=0; j< 8; j++) { + /* Get channel number */ + i = (n * 8) + j; + rxc = 0; + if (abits & (1 << j)) rxc |= ZT_ABIT; + if (bbits & (1 << j)) rxc |= ZT_BBIT; + if (tor->spans[k].chans[i].rxsig != rxc) { + /* Check for changes in received bits */ + if (!(tor->spans[k].chans[i].sig & ZT_SIG_CLEAR)) { + zt_rbsbits(&tor->spans[k].chans[i], rxc); + } + } + } + } + + for (i = 0; i < SPANS_PER_CARD; i++) { /* Go thru all the spans */ + /* if alarm timer, and it's timed out */ + if (tor->alarmtimer[i]) { + if (!--tor->alarmtimer[i]) { + /* clear recover status */ + tor->spans[i].alarms &= ~ZT_ALARM_RECOVER; + if (tor->cardtype == TYPE_E1) + t1out(tor,i + 1,0x21,0x5f); /* turn off yel */ + else + t1out(tor,i + 1,0x35,0x10); /* turn off yel */ + zt_alarm_notify(&tor->spans[i]); /* let them know */ + } + } + } + + i = tor->passno & 15; + if ((i >= 10) && (i <= 13) && !(tor->passno & 0x30)) + { + j = 0; /* clear this alarm status */ + i -= 10; + if (tor->cardtype == TYPE_T1) { + c = t1in(tor,i + 1,0x31); /* get RIR2 */ + tor->spans[i].rxlevel = c >> 6; /* get rx level */ + t1out(tor,i + 1,0x20,0xff); + c = t1in(tor,i + 1,0x20); /* get the status */ + /* detect the code, only if we are not sending one */ + if ((!tor->spans[i].mainttimer) && (c & 0x80)) /* if loop-up code detected */ + { + /* set into remote loop, if not there already */ + if ((tor->loopupcnt[i]++ > 80) && + (tor->spans[i].maintstat != ZT_MAINT_REMOTELOOP)) + { + t1out(tor,i + 1,0x1e,(japan ? 0x80 : 0x00)); /* no local loop */ + t1out(tor,i + 1,0x0a,0x40); /* remote loop */ + tor->spans[i].maintstat = ZT_MAINT_REMOTELOOP; + } + } else tor->loopupcnt[i] = 0; + /* detect the code, only if we are not sending one */ + if ((!tor->spans[i].mainttimer) && (c & 0x40)) /* if loop-down code detected */ + { + /* if in remote loop, get out of it */ + if ((tor->loopdowncnt[i]++ > 80) && + (tor->spans[i].maintstat == ZT_MAINT_REMOTELOOP)) + { + t1out(tor,i + 1,0x1e,(japan ? 0x80 : 0x00)); /* no local loop */ + t1out(tor,i + 1,0x0a,0); /* no remote loop */ + tor->spans[i].maintstat = ZT_MAINT_NONE; + } + } else tor->loopdowncnt[i] = 0; + if (c & 3) /* if red alarm */ + { + j |= ZT_ALARM_RED; + } + if (c & 8) /* if blue alarm */ + { + j |= ZT_ALARM_BLUE; + } + } else { /* its an E1 card */ + t1out(tor,i + 1,6,0xff); + c = t1in(tor,i + 1,6); /* get the status */ + if (c & 9) /* if red alarm */ + { + j |= ZT_ALARM_RED; + } + if (c & 2) /* if blue alarm */ + { + j |= ZT_ALARM_BLUE; + } + } + /* only consider previous carrier alarm state */ + tor->spans[i].alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); + n = 1; /* set to 1 so will not be in yellow alarm if we dont + care about open channels */ + /* if to have yellow alarm if nothing open */ + if (tor->spans[i].lineconfig & ZT_CONFIG_NOTOPEN) + { + /* go thru all chans, and count # open */ + for (n = 0,k = 0; k < tor->spans[i].channels; k++) + { + if (((tor->chans[i] + k)->flags & ZT_FLAG_OPEN) || + ((tor->chans[i] + k)->flags & ZT_FLAG_NETDEV)) n++; + } + /* if none open, set alarm condition */ + if (!n) j |= ZT_ALARM_NOTOPEN; + } + /* if no more alarms, and we had some */ + if ((!j) && tor->spans[i].alarms) + { + tor->alarmtimer[i] = ZT_ALARMSETTLE_TIME; + } + if (tor->alarmtimer[i]) j |= ZT_ALARM_RECOVER; + /* if going into alarm state, set yellow alarm */ + if ((j) && (!tor->spans[i].alarms)) { + if (tor->cardtype == TYPE_E1) + t1out(tor,i + 1,0x21,0x7f); + else + t1out(tor,i + 1,0x35,0x11); + } + if (c & 4) /* if yellow alarm */ + j |= ZT_ALARM_YELLOW; + if (tor->spans[i].maintstat || tor->spans[i].mainttimer) j |= ZT_ALARM_LOOPBACK; + tor->spans[i].alarms = j; + c = (LEDRED | LEDGREEN) << (2 * i); + tor->leds &= ~c; /* mask out bits for this span */ + /* light LED's if span configured and running */ + if (tor->spans[i].flags & ZT_FLAG_RUNNING) { + if (j & ZT_ALARM_RED) tor->leds |= LEDRED << (2 * i); + else if (j & ZT_ALARM_YELLOW) tor->leds |= (LEDRED | LEDGREEN) << (2 * i); + else tor->leds |= LEDGREEN << (2 * i); + } + tor->mem8[LEDREG] = tor->leds; + zt_alarm_notify(&tor->spans[i]); + } + if (!(tor->passno % 1000)) /* even second boundary */ + { + /* do all spans */ + for (i = 1; i <= SPANS_PER_CARD; i++) + { + if (tor->cardtype == TYPE_E1) + { + /* add this second's BPV count to total one */ + tor->spans[i - 1].bpvcount += t1in(tor,i,1) + (t1in(tor,i,0) << 8); + if (tor->spans[i - 1].lineconfig & ZT_CONFIG_CRC4) + { + tor->spans[i - 1].crc4count += t1in(tor,i,3) + ((t1in(tor,i,2) & 3) << 8); + tor->spans[i - 1].ebitcount += t1in(tor,i,5) + ((t1in(tor,i,4) & 3) << 8); + } + tor->spans[i - 1].fascount += (t1in(tor,i,4) >> 2) + ((t1in(tor,i,2) & 0x3F) << 6); + } + else + { + /* add this second's BPV count to total one */ + tor->spans[i - 1].bpvcount += t1in(tor,i,0x24) + (t1in(tor,i,0x23) << 8); + } + } + } + if (!timingcable) { + /* re-evaluate active sync src (no cable version) */ + tor->syncsrc = 0; + syncsrc = 0; + /* if primary sync specified, see if we can use it */ + if (tor->psyncs[0]) + { + /* if no alarms, use it */ + if (!(tor->spans[tor->psyncs[0] - 1].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | + ZT_ALARM_LOOPBACK))) { + tor->syncsrc = tor->psyncs[0]; + syncsrc = tor->syncs[0]; + } + } + /* if any others specified, see if we can use them */ + for (i = 1; i < SPANS_PER_CARD; i++) { + /* if we dont have one yet, and there is one specified at this level, see if we can use it */ + if ((!tor->syncsrc) && (tor->psyncs[i])) { + /* if no alarms, use it */ + if (!(tor->spans[tor->psyncs[i] - 1].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | + ZT_ALARM_LOOPBACK))) { + tor->syncsrc = tor->psyncs[i]; + syncsrc = tor->syncs[i]; + } + } + } + /* update sync src info */ + for (i = 0; i < SPANS_PER_CARD; i++) tor->spans[i].syncsrc = syncsrc; + + /* actually set the sync register */ + tor->mem8[SYNCREG] = tor->syncsrc; + } else /* Timing cable version */ + tor2_findsync(tor); + + tor->passno++; + +#ifdef ENABLE_TASKLETS + if (!tor->taskletpending) { + tor->taskletpending = 1; + tor->taskletsched++; + tasklet_hi_schedule(&tor->tor2_tlet); + } else { + tor->txerrors++; + } +#else + tor2_run(tor); +#endif + /* We are not the timing bus master */ + if (tor->cardtype == TYPE_E1) + /* clear OUTBIT and enable interrupts */ + tor->mem8[CTLREG] = INTENA | E1DIV | tor->master; + else + /* clear OUTBIT and enable interrupts */ + tor->mem8[CTLREG] = INTENA | tor->master; +#ifdef LINUX26 + return IRQ_RETVAL(1); +#endif +} + + +static int tor2_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) +{ + switch(cmd) { + default: + return -ENOTTY; + } + return 0; +} + +MODULE_AUTHOR("Mark Spencer"); +MODULE_DESCRIPTION("Tormenta 2 PCI Quad T1 or E1 Zaptel Driver"); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +#ifdef LINUX26 +module_param(debug, int, 0600); +module_param(loopback, int, 0600); +module_param(timingcable, int, 0600); +module_param(japan, int, 0600); +#else +MODULE_PARM(debug, "i"); +MODULE_PARM(loopback, "i"); +MODULE_PARM(timingcable, "i"); +MODULE_PARM(japan, "i"); +#endif + +MODULE_DEVICE_TABLE(pci, tor2_pci_ids); + +module_init(tor2_init); +module_exit(tor2_cleanup); diff --git a/kernel/torisa.c b/kernel/torisa.c new file mode 100644 index 0000000..a8fb9d3 --- /dev/null +++ b/kernel/torisa.c @@ -0,0 +1,1172 @@ +/* + * Zapata Telephony "Tormenta" ISA card LINUX driver, version 2.2 11/29/01 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Modified from original tor.c by Mark Spencer + * original by Jim Dixon + */ + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef STANDALONE_ZAPATA +#include "zaptel.h" +#else +#include +#endif +#ifdef LINUX26 +#include +#endif + +/* Board address offsets (specified in word (not byte) offsets) */ +#define DDATA 0 /* Data I/O Register */ +#define DADDR 0x100 /* Dallas Card Address Reg., 0x200 in byte offset higher */ +#define CTLREG 0x100 /* Control/Status Reg., 0x200 in byte offset */ + +/* Control register bits */ +#define OUTBIT 8 /* Status output bit (for external measurements) */ +#define INTENA 4 /* Interrupt enable bit */ +#define MASTERVAL 0x41 /* Enable E1 master clock on Rev. B board */ +#define ENA16 0x80 /* 16 bit bus cycle enable bit */ + +#define TYPE_T1 1 /* is a T1 card */ +#define TYPE_E1 2 /* is an E1 card */ + +#define E1SYNCSTABLETHRESH 15000 /* amount of samples needed for E1 Sync stability */ + +static int syncsrc; + +static int syncs[2]; + +static int debug; + +#define MASTERCLOCK (*clockvals) /* value for master clock */ + +/* clock values */ +static u_char clockvals_t1[] = {MASTERVAL,0x12,0x22,MASTERVAL}; +static u_char clockvals_e1[] = {MASTERVAL,0x13,0x23,MASTERVAL}; + +static u_char *clockvals; + +/* translations of data channels for 24 channels in a 32 bit PCM highway */ +unsigned datxlt_t1[] = { 0, + 1 ,2 ,3 ,5 ,6 ,7 ,9 ,10,11,13,14,15,17,18,19,21,22,23,25,26,27,29,30,31 }; + +/* translations of data channels for 30/31 channels in a 32 bit PCM highway */ +unsigned datxlt_e1[] = { 0, + 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, + 25,26,27,28,29,30,31 }; + +unsigned int *datxlt; + +/* This is the order that the data (audio) channels get +scanned in. This was done in this rather poopy manner because when outputting +(and inputting) a sine wave, such as in the case of TDD, any repeated samples +(because of PCM bus contention) will result in nasty-sounding distortion. The +Mitel STPA chips (MT8920) have a contention mechanism, which results in a +situation where, if the processor accesses a timeslot that is currently +being transmitted or received, it will HOLD the bus until it is done with +the timeslot. This means that there can be cases where we are trying +to write to a timeslot, and its already outputting the same value +as the last one (since we didnt get there in time), and in a sine-wave +output, distortion will occur. In any other output, it will be utterly +un-noticeable. So, what we do is use a pattern that gives us the most +flexibility in how long our interrupt latency is (note: Even with this, +our interrupt latency must be between 4 and 28 microseconds!!!) Essentially +we receive the interrupt just after the 24th channel is read. It will +take us AT LEAST 30 microseconds to read it, but could take as much as +35 microseconds to read all the channels. In any case it's the very +first thing we do in the interrupt handler. Worst case (30 microseconds) +is that the MT8920 has only moved 7 channels. That's where the 6 comes from. +*/ + +static int chseq_t1[] = + { 6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,1,2,3,4,5 } ; + +static int chseq_e1[] = + { 6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,1,2,3,4,5 } ; + +static int *chseq; + +struct torisa_pvt { + int span; +}; + +static struct zt_span spans[2]; +static struct zt_chan chans[64]; +static struct torisa_pvt pvts[64]; +static u_char txsigs[2][16]; +static int loopupcnt[2]; +static int loopdowncnt[2]; +static int alarmtimer[2]; + +static int channels_per_span = 24; + +static int card_type = TYPE_T1; + +static int prefmaster = 0; + +static int spansstarted = 0; + +#ifdef DEFINE_RWLOCK +static DEFINE_RWLOCK(torisa); +#else +static rwlock_t torisa = RW_LOCK_UNLOCKED; +#endif + +static u_char readdata[2][64][ZT_MAX_CHUNKSIZE]; +static u_char writedata[2][64][ZT_MAX_CHUNKSIZE]; +static u_char last_ecwrite[2][32]; +static int curread; + +static unsigned long base; +volatile static unsigned short *maddr; + +static int irq; +static unsigned int irqcount = 0; +static unsigned int taskletsched = 0; +static unsigned int taskletrun = 0; +static unsigned int taskletexec = 0; + +/* set the control register */ +static void setctlreg(unsigned char val) +{ +volatile register char *cp; + + cp = (char *) &maddr[CTLREG]; + *cp = val; +} + +/* output a byte to one of the registers in one of the Dallas T-1 chips */ +static void t1out(int spanno, int loc, unsigned char val) +{ +register int n; +volatile register char *cp; + + /* get the memory offset */ + n = spanno << 9; + /* point a char * at the address location */ + cp = (char *) &maddr[DADDR + n]; + *cp = loc; /* set address in T1 chip */ + /* point a char * at the data location */ + cp = (char *) &maddr[DDATA + n]; + *cp = val; /* out the value */ +} + +/* get a byte from one of the registers in one of the Dallas T-1 chips */ +static unsigned char t1in(int spanno, int loc) +{ +register int n; +volatile register char *cp; + + /* get the memory offset */ + n = spanno << 9; + /* point a char * at the address location */ + cp = (char *) &maddr[DADDR + n]; + *cp = loc; /* set address in T1 chip */ + cp = (char *) &maddr[DDATA + n]; + /* point a char * at the data location */ + return(*cp); +} + +/* get input from the status register */ +static unsigned char getctlreg(void) +{ +register char *cp; + + cp = (char *) &maddr[CTLREG]; + return(*cp); +} + +static void set_clear(void) +{ + int i,j,s; + unsigned short val=0; + for (s=0;s<2;s++) { + for (i=0;ipvt; + unsigned long flags; +#if 0 + printk("Setting bits to %x hex on channel %s\n", bits, chan->name); +#endif + if (card_type == TYPE_E1) { /* do it E1 way */ + if (chan->chanpos > 30) return 0; /* cant do this for chan 31 */ + n = chan->chanpos - 1; + k = p->span; + b = (n % 15) + 1; + c = txsigs[k][b]; + m = (n / 15) * 4; /* nibble selector */ + c &= (15 << m); /* keep the other nibble */ + c |= (bits & 15) << (4 - m); /* put our new nibble here */ + txsigs[k][b] = c; + /* output them into the chip */ + t1out(k + 1,0x40 + b,c); + return 0; + } + n = chan->chanpos - 1; + k = p->span; + b = (n / 8); /* get byte number */ + m = 1 << (n & 7); /* get mask */ + c = txsigs[k][b]; + c &= ~m; /* clear mask bit */ + /* set mask bit, if bit is to be set */ + if (bits & ZT_ABIT) c |= m; + txsigs[k][b] = c; + write_lock_irqsave(&torisa, flags); + t1out(k + 1,0x70 + b,c); + b += 3; /* now points to b bit stuff */ + /* get current signalling values */ + c = txsigs[k][b]; + c &= ~m; /* clear mask bit */ + /* set mask bit, if bit is to be set */ + if (bits & ZT_BBIT) c |= m; + /* save new signalling values */ + txsigs[k][b] = c; + /* output them into the chip */ + t1out(k + 1,0x70 + b,c); + b += 3; /* now points to c bit stuff */ + /* get current signalling values */ + c = txsigs[k][b]; + c &= ~m; /* clear mask bit */ + /* set mask bit, if bit is to be set */ + if (bits & ZT_CBIT) c |= m; + /* save new signalling values */ + txsigs[k][b] = c; + /* output them into the chip */ + t1out(k + 1,0x70 + b,c); + b += 3; /* now points to d bit stuff */ + /* get current signalling values */ + c = txsigs[k][b]; + c &= ~m; /* clear mask bit */ + /* set mask bit, if bit is to be set */ + if (bits & ZT_DBIT) c |= m; + /* save new signalling values */ + txsigs[k][b] = c; + /* output them into the chip */ + t1out(k + 1,0x70 + b,c); + write_unlock_irqrestore(&torisa, flags); + return 0; +} + +static inline int getspan(struct zt_span *span) +{ + if (span == spans) + return 1; + if (span == spans + 1) + return 2; + return -1; +} + +static int torisa_shutdown(struct zt_span *span) +{ + int i; + int tspan; + int wasrunning; + unsigned long flags; + + tspan = getspan(span); + if (tspan < 0) { + printk("TorISA: Span '%d' isn't us?\n", span->spanno); + return -1; + } + + write_lock_irqsave(&torisa, flags); + wasrunning = span->flags & ZT_FLAG_RUNNING; + + span->flags &= ~ZT_FLAG_RUNNING; + /* Zero out all registers */ + for (i = 0; i< 0xff; i++) t1out(tspan, i, 0); + if (wasrunning) + spansstarted--; + write_unlock_irqrestore(&torisa, flags); + if (!spans[0].flags & ZT_FLAG_RUNNING && + !spans[1].flags & ZT_FLAG_RUNNING) + /* No longer in use, disable interrupts */ + setctlreg(clockvals[syncsrc]); + + if (debug) + printk("Span %d (%s) shutdown\n", span->spanno, span->name); + return 0; +} + +static int torisa_startup(struct zt_span *span) +{ + unsigned long endjif; + int i; + int tspan; + unsigned long flags; + char *coding; + char *framing; + char *crcing; + int alreadyrunning; + + tspan = getspan(span); + if (tspan < 0) { + printk("TorISA: Span '%d' isn't us?\n", span->spanno); + return -1; + } + + + write_lock_irqsave(&torisa, flags); + + alreadyrunning = span->flags & ZT_FLAG_RUNNING; + + /* initialize the start value for the last ec buffer */ + for(i = 0; i < span->channels; i++) + { + last_ecwrite[tspan - 1][i] = ZT_LIN2X(0,&span->chans[i]); + } + crcing = ""; + if (card_type == TYPE_T1) { /* if its a T1 card */ + if (!alreadyrunning) { + + setctlreg(MASTERCLOCK); + /* Zero out all registers */ + for (i = 0x20; i< 0x40; i++) + t1out(tspan, i, 0); + for (i = 0x60; i< 0x80; i++) + t1out(tspan, i, 0); + + /* Full-on Sync required (RCR1) */ + t1out(tspan, 0x2b, 8); + /* RSYNC is an input (RCR2) */ + t1out(tspan, 0x2c, 8); + /* RBS enable (TCR1) */ + t1out(tspan, 0x35, 0x10); + /* TSYNC to be output (TCR2) */ + t1out(tspan, 0x36, 4); + /* Tx & Rx Elastic store, sysclk = 2.048 mhz, loopback controls (CCR1) */ + t1out(tspan, 0x37, 0x8c); + } + /* Enable F bits pattern */ + i = 0x20; + if (span->lineconfig & ZT_CONFIG_ESF) + i = 0x88; + if (span->lineconfig & ZT_CONFIG_B8ZS) + i |= 0x44; + t1out(tspan, 0x38, i); + if (i & 0x80) + coding = "ESF"; + else + coding = "SF"; + if (i & 0x40) + framing = "B8ZS"; + else { + framing = "AMI"; + t1out(tspan,0x7e,0x1c); /* F bits pattern (0x1c) into FDL register */ + } + t1out(tspan, 0x7c, span->txlevel << 5); + + if (!alreadyrunning) { + /* LIRST to 1 in CCR3 */ + t1out(tspan, 0x30, 1); + + /* Wait 100 ms */ + endjif = jiffies + 10; + write_unlock_irqrestore(&torisa, flags); + + while(jiffies < endjif); /* wait 100 ms */ + + write_lock_irqsave(&torisa, flags); + t1out(tspan,0x30,0x40); /* set CCR3 to 0x40, resetting Elastic Store */ + + span->flags |= ZT_FLAG_RUNNING; + spansstarted++; + +#if 0 + printk("Enabling interrupts: %d\n", clockvals[syncsrc] | INTENA); +#endif + + /* output the clock info and enable interrupts */ + setctlreg(clockvals[syncsrc] | INTENA); + } + set_clear(); /* this only applies to a T1 */ + } else { /* if its an E1 card */ + u_char ccr1 = 0, tcr1 = 0; + + if (!alreadyrunning) { + t1out(tspan,0x1a,4); /* CCR2: set LOTCMC */ + for(i = 0; i <= 8; i++) t1out(tspan,i,0); + for(i = 0x10; i <= 0x4f; i++) if (i != 0x1a) t1out(tspan,i,0); + t1out(tspan,0x10,0x20); /* RCR1: Rsync as input */ + t1out(tspan,0x11,6); /* RCR2: Sysclk=2.048 Mhz */ + t1out(tspan,0x12,8); /* TCR1: TSiS mode */ + } + tcr1 = 8; /* base TCR1 value: TSis mode */ + if (span->lineconfig & ZT_CONFIG_CCS) { + ccr1 |= 8; /* CCR1: Rx Sig mode: CCS */ + coding = "CCS"; + } else { + tcr1 |= 0x20; + coding = "CAS"; + } + if (span->lineconfig & ZT_CONFIG_HDB3) { + ccr1 |= 0x44; /* CCR1: TX and RX HDB3 */ + framing = "HDB3"; + } else framing = "AMI"; + if (span->lineconfig & ZT_CONFIG_CRC4) { + ccr1 |= 0x11; /* CCR1: TX and TX CRC4 */ + crcing = "/CRC4"; + } + t1out(tspan,0x12,tcr1); + t1out(tspan,0x14,ccr1); + t1out(tspan, 0x18, 0x80); + + if (!alreadyrunning) { + t1out(tspan,0x1b,0x8a); /* CCR3: LIRST & TSCLKM */ + t1out(tspan,0x20,0x1b); /* TAFR */ + t1out(tspan,0x21,0x5f); /* TNAFR */ + t1out(tspan,0x40,0xb); /* TSR1 */ + for(i = 0x41; i <= 0x4f; i++) t1out(tspan,i,0x55); + for(i = 0x22; i <= 0x25; i++) t1out(tspan,i,0xff); + /* Wait 100 ms */ + endjif = jiffies + 10; + write_unlock_irqrestore(&torisa, flags); + while(jiffies < endjif); /* wait 100 ms */ + write_lock_irqsave(&torisa, flags); + t1out(tspan,0x1b,0x9a); /* CCR3: set also ESR */ + t1out(tspan,0x1b,0x82); /* CCR3: TSCLKM only now */ + + /* output the clock info and enable interrupts */ + setctlreg(clockvals[syncsrc] | INTENA); + } + + } + + write_unlock_irqrestore(&torisa, flags); + + if (debug) { + if (card_type == TYPE_T1) { + if (alreadyrunning) + printk("TorISA: Reconfigured span %d (%s/%s) LBO: %s\n", span->spanno, coding, framing, zt_lboname(span->txlevel)); + else + printk("TorISA: Startup span %d (%s/%s) LBO: %s\n", span->spanno, coding, framing, zt_lboname(span->txlevel)); + } else { + if (alreadyrunning) + printk("TorISA: Reconfigured span %d (%s/%s%s) 120 ohms\n", span->spanno, coding, framing, crcing); + else + printk("TorISA: Startup span %d (%s/%s%s) 120 ohms\n", span->spanno, coding, framing, crcing); + } + } + if (syncs[0] == span->spanno) printk("SPAN %d: Primary Sync Source\n",span->spanno); + if (syncs[1] == span->spanno) printk("SPAN %d: Secondary Sync Source\n",span->spanno); + return 0; +} + +static int torisa_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) +{ + if (debug) + printk("TorISA: Configuring span %d\n", span->spanno); + + span->syncsrc = syncsrc; + + /* remove this span number from the current sync sources, if there */ + if (syncs[0] == span->spanno) syncs[0] = 0; + if (syncs[1] == span->spanno) syncs[1] = 0; + /* if a sync src, put it in proper place */ + if (lc->sync) syncs[lc->sync - 1] = span->spanno; + + /* If we're already running, then go ahead and apply the changes */ + if (span->flags & ZT_FLAG_RUNNING) + return torisa_startup(span); + + return 0; +} + +static int torisa_chanconfig(struct zt_chan *chan, int sigtype) +{ + int alreadyrunning; + unsigned long flags; + alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING; + if (debug) { + if (alreadyrunning) + printk("TorISA: Reconfigured channel %d (%s) sigtype %d\n", chan->channo, chan->name, sigtype); + else + printk("TorISA: Configured channel %d (%s) sigtype %d\n", chan->channo, chan->name, sigtype); + } + write_lock_irqsave(&torisa, flags); + if (alreadyrunning && (card_type == TYPE_T1)) + set_clear(); + write_unlock_irqrestore(&torisa, flags); + return 0; +} + +static int torisa_open(struct zt_chan *chan) +{ +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#endif + return 0; +} + +static int torisa_close(struct zt_chan *chan) +{ +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#endif + return 0; +} + +static int torisa_maint(struct zt_span *span, int cmd) +{ + int tspan = getspan(span); + + switch(cmd) { + case ZT_MAINT_NONE: + t1out(tspan,0x1a,4); /* clear system */ + break; + case ZT_MAINT_LOCALLOOP: + t1out(tspan,0x1a,5); /* local loopback */ + break; + case ZT_MAINT_REMOTELOOP: + t1out(tspan,0x37,6); /* remote loopback */ + break; + case ZT_MAINT_LOOPUP: + if (card_type == TYPE_E1) return -ENOSYS; + t1out(tspan,0x30,2); /* send loopup code */ + break; + case ZT_MAINT_LOOPDOWN: + if (card_type == TYPE_E1) return -ENOSYS; + t1out(tspan,0x30,4); /* send loopdown code */ + break; + case ZT_MAINT_LOOPSTOP: + if (card_type == TYPE_T1) + t1out(tspan,0x30,0); /* stop sending loopup code */ + break; + default: + printk("torisa: Unknown maint command: %d\n", cmd); + break; + } + return 0; +} + +static int taskletpending; + +static struct tasklet_struct torisa_tlet; + +static void torisa_tasklet(unsigned long data) +{ + int x,y; + u_char mychunk[2][ZT_CHUNKSIZE]; + taskletrun++; + if (taskletpending) { + taskletexec++; + /* Perform receive data calculations. Reverse to run most + likely master last */ + if (spans[1].flags & ZT_FLAG_RUNNING) { + /* Perform echo cancellation */ + for (x=0;x> (j * 8)) & 0xff; + readdata[curread][j * channels_per_span + n - 1][passno % ZT_CHUNKSIZE] = rxc; + } + } + + i = passno & 127; + /* if an E1 card, do rx signalling for it */ + if (i < 3 && (card_type == TYPE_E1)) { /* if an E1 card */ + for(j = (i * 3); j < (i * 3) + 5; j++) + { + for(k = 1,x = j; k <= 2; k++,x += channels_per_span) { + c = t1in(k,0x31 + j); + rxc = c & 15; + if (rxc != chans[x + 15].rxsig) { + /* Check for changes in received bits */ + if (!(chans[x + 15].sig & ZT_SIG_CLEAR)) + zt_rbsbits(&chans[x + 15], rxc); + } + rxc = c >> 4; + if (rxc != chans[x].rxsig) { + /* Check for changes in received bits */ + if (!(chans[x].sig & ZT_SIG_CLEAR)) + zt_rbsbits(&chans[x], rxc); + } + } + } + } + /* if a t1 card, do rx signalling for it */ + if ((i < 6) && (card_type == TYPE_T1)) { + k = (i / 3); /* get span */ + n = (i % 3); /* get base */ + abits = t1in(k + 1, 0x60 + n); + bbits = t1in(k + 1, 0x63 + n); + cbits = t1in(k + 1, 0x66 + n); + dbits = t1in(k + 1, 0x69 + n); + for (j=0; j< 8; j++) { + /* Get channel number */ + i = (k * 24) + (n * 8) + j; + rxc = 0; + if (abits & (1 << j)) rxc |= ZT_ABIT; + if (bbits & (1 << j)) rxc |= ZT_BBIT; + if (cbits & (1 << j)) rxc |= ZT_CBIT; + if (dbits & (1 << j)) rxc |= ZT_DBIT; + if (chans[i].rxsig != rxc) { + /* Check for changes in received bits */ + if (!(chans[i].sig & ZT_SIG_CLEAR)) + zt_rbsbits(&chans[i], rxc); + } + } + } + + if (!(passno & 0x7)) { + for(i = 0; i < 2; i++) + { + /* if alarm timer, and it's timed out */ + if (alarmtimer[i]) { + if (!--alarmtimer[i]) + { + /* clear recover status */ + spans[i].alarms &= ~ZT_ALARM_RECOVER; + if (card_type == TYPE_T1) + t1out(i + 1,0x35,0x10); /* turn off yel */ + else + t1out(i + 1,0x21,0x5f); /* turn off remote alarm */ + zt_alarm_notify(&spans[i]); /* let them know */ + } + } + } + } + + i = passno & 511; + if ((i == 100) || (i == 101)) + { + j = 0; /* clear this alarm status */ + i -= 100; + if (card_type == TYPE_T1) { + c = t1in(i + 1,0x31); /* get RIR2 */ + spans[i].rxlevel = c >> 6; /* get rx level */ + t1out(i + 1,0x20,0xff); + c = t1in(i + 1,0x20); /* get the status */ + /* detect the code, only if we are not sending one */ + if ((!spans[i].mainttimer) && (c & 0x80)) /* if loop-up code detected */ + { + /* set into remote loop, if not there already */ + if ((loopupcnt[i]++ > 80) && + (spans[i].maintstat != ZT_MAINT_REMOTELOOP)) + { + t1out(i + 1,0x37,0x9c); /* remote loopback */ + spans[i].maintstat = ZT_MAINT_REMOTELOOP; + } + } else loopupcnt[i] = 0; + /* detect the code, only if we are not sending one */ + if ((!spans[i].mainttimer) && (c & 0x40)) /* if loop-down code detected */ + { + /* if in remote loop, get out of it */ + if ((loopdowncnt[i]++ > 80) && + (spans[i].maintstat == ZT_MAINT_REMOTELOOP)) + { + t1out(i + 1,0x37,0x8c); /* normal */ + spans[i].maintstat = ZT_MAINT_NONE; + } + } else loopdowncnt[i] = 0; + if (c & 3) /* if red alarm */ + { + j |= ZT_ALARM_RED; + } + if (c & 8) /* if blue alarm */ + { + j |= ZT_ALARM_BLUE; + } + } else { /* its an E1 card */ + t1out(i + 1,6,0xff); + c = t1in(i + 1,6); /* get the status */ + if (c & 9) /* if red alarm */ + { + j |= ZT_ALARM_RED; + } + if (c & 2) /* if blue alarm */ + { + j |= ZT_ALARM_BLUE; + } + } + /* only consider previous carrier alarm state */ + spans[i].alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); + n = 1; /* set to 1 so will not be in yellow alarm if we dont + care about open channels */ + /* if to have yellow alarm if nothing open */ + if (spans[i].lineconfig & ZT_CONFIG_NOTOPEN) + { + /* go thru all chans, and count # open */ + for(n = 0,k = (i * channels_per_span); k < (i * channels_per_span) + channels_per_span; k++) + { + if ((chans[k].flags & ZT_FLAG_OPEN) || + (chans[k].flags & ZT_FLAG_NETDEV)) n++; + } + /* if none open, set alarm condition */ + if (!n) j |= ZT_ALARM_NOTOPEN; + } + /* if no more alarms, and we had some */ + if ((!j) && spans[i].alarms) + { + alarmtimer[i] = ZT_ALARMSETTLE_TIME; + } + if (alarmtimer[i]) j |= ZT_ALARM_RECOVER; + /* if going into alarm state, set yellow (remote) alarm */ + if ((j) && (!spans[i].alarms)) { + if (card_type == TYPE_T1) t1out(i + 1,0x35,0x11); + else t1out(i + 1,0x21,0x7f); + } + if (c & 4) /* if yellow alarm */ + j |= ZT_ALARM_YELLOW; + if (spans[i].maintstat || spans[i].mainttimer) j |= ZT_ALARM_LOOPBACK; + spans[i].alarms = j; + zt_alarm_notify(&spans[i]); + } + if (!(passno % 8000)) /* even second boundary */ + { + /* do both spans */ + for(i = 1; i <= 2; i++) + { + if (card_type == TYPE_T1) { + /* add this second's BPV count to total one */ + spans[i - 1].bpvcount += t1in(i,0x24) + (t1in(i,0x23) << 8); + } else { + /* add this second's BPV count to total one */ + spans[i - 1].bpvcount += t1in(i,1) + (t1in(i,0) << 8); + } + } + } + /* re-evaluate active sync src */ + mysyncsrc = 0; + /* if primary sync specified, see if we can use it */ + if (syncs[0]) + { + /* if no alarms, use it */ + if (!(spans[syncs[0] - 1].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | + ZT_ALARM_LOOPBACK))) mysyncsrc = syncs[0]; + } + /* if we dont have one yet, and there is a secondary, see if we can use it */ + if ((!mysyncsrc) && (syncs[1])) + { + /* if no alarms, use it */ + if (!(spans[syncs[1] - 1].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | + ZT_ALARM_LOOPBACK))) mysyncsrc = syncs[1]; + } + /* on the E1 card, the PLL takes a bit of time to lock going + between internal and external clocking. There needs to be some + settle time before actually changing the source, otherwise it will + oscillate between in and out of sync */ + if (card_type == TYPE_E1) + { + /* if stable, add to count */ + if (lastsyncsrc == mysyncsrc) mysynccnt++; else mysynccnt = 0; + lastsyncsrc = mysyncsrc; + /* if stable sufficiently long, change it */ + if (mysynccnt >= E1SYNCSTABLETHRESH) + { + mysynccnt = 0; + syncsrc = mysyncsrc; + } + } + else syncsrc = mysyncsrc; /* otherwise on a T1 card, just use current value */ + /* update sync src info */ + spans[0].syncsrc = spans[1].syncsrc = syncsrc; + /* If this is the last pass, then prepare the next set */ + /* clear outbit, restore interrupt enable */ + setctlreg(clockvals[syncsrc] | INTENA); +#ifdef LINUX26 + return IRQ_RETVAL(1); +#endif +} + + +static int torisa_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) +{ + struct torisa_debug td; + switch(cmd) { + case TORISA_GETDEBUG: + td.txerrors = txerrors; + td.irqcount = irqcount; + td.taskletsched = taskletsched; + td.taskletrun = taskletrun; + td.taskletexec = taskletexec; + td.span1flags = spans[0].flags; + td.span2flags = spans[1].flags; + if (copy_to_user((struct torisa_debug *)data, &td, sizeof(td))) + return -EFAULT; + return 0; + default: + return -ENOTTY; + } + return 0; +} + +static int __init tor_init(void) +{ + if (!base) { + printk("Specify address with base=0xNNNNN\n"); + return -EIO; + } + if (tor_probe()) { + printk(KERN_ERR "No ISA tormenta card found at %05lx\n", base); + return -EIO; + } + if (request_irq(irq, torisa_intr, ZAP_IRQ_DISABLED, "torisa", NULL)) { + printk(KERN_ERR "Unable to request tormenta IRQ %d\n", irq); + return -EIO; + } + if (!request_mem_region(base, 4096, "Tormenta ISA")) { + printk(KERN_ERR "Unable to request 4k memory window at %lx\n", base); + free_irq(irq, NULL); + return -EIO; + } + + strcpy(spans[0].name, "TorISA/1"); + strncpy(spans[0].desc, "ISA Tormenta Span 1", sizeof(spans[0].desc) - 1); + spans[0].manufacturer = "Digium"; + strncpy(spans[0].devicetype, "Tormenta ISA", sizeof(spans[0].devicetype) - 1); + spans[0].spanconfig = torisa_spanconfig; + spans[0].chanconfig = torisa_chanconfig; + spans[0].startup = torisa_startup; + spans[0].shutdown = torisa_shutdown; + spans[0].rbsbits = torisa_rbsbits; + spans[0].maint = torisa_maint; + spans[0].open = torisa_open; + spans[0].close = torisa_close; + spans[0].channels = channels_per_span; + spans[0].chans = &chans[0]; + spans[0].flags = ZT_FLAG_RBS; + spans[0].ioctl = torisa_ioctl; + spans[0].irq = irq; + + if (card_type == TYPE_E1) { + spans[0].spantype = "T1"; + spans[0].linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; + spans[0].deflaw = ZT_LAW_ALAW; + } else { + spans[0].spantype = "E1"; + spans[0].linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4; + spans[0].deflaw = ZT_LAW_MULAW; + } + + spans[1] = spans[0]; + strcpy(spans[1].name, "TorISA/2"); + strcpy(spans[1].desc, "ISA Tormenta Span 2"); + spans[1].chans = &chans[channels_per_span]; + + init_waitqueue_head(&spans[0].maintq); + init_waitqueue_head(&spans[1].maintq); + + make_chans(); + if (zt_register(&spans[0], prefmaster)) { + printk(KERN_ERR "Unable to register span %s\n", spans[0].name); + return -EIO; + } + if (zt_register(&spans[1], 0)) { + printk(KERN_ERR "Unable to register span %s\n", spans[1].name); + zt_unregister(&spans[0]); + return -EIO; + } + tasklet_init(&torisa_tlet, torisa_tasklet, (long)0); + printk("TORISA Loaded\n"); + return 0; +} + + +#if !defined(LINUX26) +static int __init set_tor_base(char *str) +{ + base = simple_strtol(str, NULL, 0); + return 1; +} + +__setup("tor=", set_tor_base); +#endif + +static void __exit tor_exit(void) +{ + free_irq(irq, NULL); + release_mem_region(base, 4096); + if (spans[0].flags & ZT_FLAG_REGISTERED) + zt_unregister(&spans[0]); + if (spans[1].flags & ZT_FLAG_REGISTERED) + zt_unregister(&spans[1]); +} + +MODULE_AUTHOR("Mark Spencer "); +MODULE_DESCRIPTION("Tormenta ISA Zapata Telephony Driver"); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +#ifdef LINUX26 +module_param(prefmaster, int, 0600); +module_param(base, long, 0600); +module_param(irq, int, 0600); +module_param(syncsrc, int, 0600); +module_param(debug, int, 0600); +#else +MODULE_PARM(prefmaster, "i"); +MODULE_PARM(base, "i"); +MODULE_PARM(irq, "i"); +MODULE_PARM(syncsrc, "i"); +MODULE_PARM(debug, "i"); +#endif + +module_init(tor_init); +module_exit(tor_exit); diff --git a/kernel/tormenta2.rbt b/kernel/tormenta2.rbt new file mode 100644 index 0000000..9238b8a --- /dev/null +++ b/kernel/tormenta2.rbt @@ -0,0 +1,17482 @@ +Xilinx ASCII Bitstream +Created by Bitstream F.23 +Design name: tormenta2.ncd +Architecture: spartan2 +Part: 2s50pq208 +Date: Thu Oct 10 09:00:52 2002 +Bits: 559200 +11111111111111111111111111111111 +10101010100110010101010101100110 +00110000000000001000000000000001 +00000000000000000000000000000111 +00110000000000010110000000000001 +00000000000000000000000000001011 +00110000000000010010000000000001 +00000000100000000011111100101101 +00110000000000001100000000000001 +00000000000000000000000000000000 +00110000000000001000000000000001 +00000000000000000000000000001001 +00110000000000000010000000000001 +00000000000000000000000000000000 +00110000000000001000000000000001 +00000000000000000000000000000001 +00110000000000000100000000000000 +01010000000000000011111000000100 +00000000000100100011000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000100 +10000000000000000000000000000000 +00000000000000000000000000000000 +00000000000100100011000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000010000000000100 +10000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000100000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +10000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000100000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +10000000000000000000000000000000 +00000000000000000000000000000000 +00000000000100100000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000100 +10000000000000000000000000000000 +00000000000000000000000000000000 +00000000000100100000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000100 +10000000000000000000000000000000 +00000000000000000000000000000000 +00000000000100100000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000010000000000100 +00000000000000000000000000000000 +00000000000000000000000000000000 +11111111000100100000000000000000 +00000000000000011000000000000000 +01000000000000000001100000000000 +00000100000000000000000010000000 +00000000011000000000000000011000 +00000000000010100000000000000010 +10000000000000000010000000000000 +00101000000000000000001000000000 +00000000000000000000000000100000 +00000000000010000001111111000100 +00000000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111101000000000 +11111111100000000011111100000000 +10001111111110000000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111110000 +00000011011111100000000011111111 +10000000001111111110000000001111 +11111000000000111111000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001110001000000000 +10111011100000000010111000110100 +00001011101110000000001011101110 +00000000101110111000000000101110 +11100000000010111011100000000010 +11101110000000001011101110000000 +00101110111000000000101110111000 +00000010101011100000000010111011 +10000000001011101110000000001011 +10111000000000101110000000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100100000000000 +10100011000000000010110010000000 +00001011001100000010011010001100 +00000000101100110000000000101000 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010010011000000000010110011 +00000000001011001100000000001011 +00110000000001101110001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010000000000000 +10111011000000000010111011000010 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110010 +10000010111011000000000010111011 +00000000001011101100000000011011 +10110000000000101111000000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000101011110110100000000 +11111011000000000011111000010000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110111100 +00000011011011000000000011111011 +00000000001111101100000000001111 +10110000010000111100100000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011000001000000 +11111111000000000011111010100100 +00001111111100000000000111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111110111000 +00000011101111000000000011111111 +00000000001111111100000000001111 +11110000000000111111100000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011000000010011111000010000 +00101100101100000000001111101100 +00000000111110110000000000110110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111100110000 +00000011101011000000000011111011 +00000000001111101100000000001111 +10110000000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010010000000000000 +10111011000101100010111010000000 +00001000101100000000001011101100 +00000000101110110000000000100110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010001011000000000010111011 +00000000001011101100000000001011 +10111000100000101111001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100010000000000 +10110011000000000010110001000000 +00001000001100000000001001001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100000000 +00000010100011000000000010110011 +00000000001011001100000000001011 +00111110000000101111000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +01100000000000010001001000000000 +10110111100000000010110100100000 +00001000011110000100001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101001000 +00000010000111100000000010110111 +10000000001011011110000000001011 +01111000000000101101100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +01001000000010000000110001000000 +11110011000000000011110011000000 +00001100001100010010001111001100 +00000000111100110000000000111100 +11000000000011110011000000000011 +11001100000000001111001100000000 +00111100110000000000111100000000 +00000011100011000000000011110011 +00000000001111001100000000001111 +00110000000000111101101000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000111011011000000010000 +11111111000000000011111111000100 +00001111111100000000001111111100 +00001000111111110000000000110111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111000000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111101000000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +10101000000011011110010000010000 +11111011000000000011111001000000 +00001100101100000000001111101100 +00001000111110110000000001111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111100000000 +00000011001011000000000011111011 +00000000001111101100000000001111 +10110000000000111110101000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000000011001000000000000 +10110111000000000010110001000000 +00001000011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101000000 +00000010000111000000000010110111 +00000000001011011100000000001011 +01110000000000101101001000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000001000000001001111000000000 +10110111100000000010110111100000 +00011000011110000001001011011110 +00000001101101111000000100101001 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101111000000 +00000010000111100000000010110111 +10000000001011011110000000001011 +01111000000000101111000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000100101001100000000000000 +10110011000000000010110011000000 +00011000001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100000000 +00000010000011000000000010110011 +00000000001011001100000000001011 +00110000000000101101001100000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011011100000000000 +11111010000000000011111110011100 +00101100101000000000001111101000 +00000000111110100000000000111110 +10000000000011111010000000000011 +11101000000000001111101000000000 +00111110100000000000111111100000 +00000011001010000000000011111010 +00000000001111101000000000001111 +00100000000000111111101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000010000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000100000000111101001000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001100000000011110001000000 +00001101100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000110000001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000100000010111001000000 +00001000100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10011000000010100010000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010110000000000 +10111001000000000010111001000000 +00001000100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010010100000100000011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001100000000010110001001000 +00101000000100000000001011000100 +00000000100100010000000001101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000100100010010 +10000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000100000001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000001010110000000000000 +11111000000000000011111000000000 +00001100100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000010 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000110010111000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000101011111010000000000 +11111001000001000011111101000100 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111111010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110011000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +10011000000001011110010000000000 +11001001000000000011111001000000 +00001100100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011001001000000000011111001 +00000000001111100100000000001111 +01010000000000111110011000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000100001110000000000000 +10001000000000000010111000000000 +00001000100000000000001011100000 +00000000101110000000000000101110 +00000000000010111000000000000010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000010101000000000000010111000 +00000000001011100000000000001011 +10000000000000101100111000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000001011110010000000000 +10000001000000000010100001000000 +00001000000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +10000100000000001011000100000000 +00101100010000000000101110010000 +00000010000001000000000010110001 +00000000001011000100000000001011 +00010000000001101100001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10001001000000000010111001001010 +00001000100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010101001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011100010001000010 +11001001000000010011111001000000 +00101100100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111100010000 +00000011001001000000000011111001 +00000000001111100100000000001111 +10010000000000111110100000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000000011010011000000000 +11111011000000010011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11001000000000000011110000000000 +00001100100000000000001111100000 +00000000111110000000000000110110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000100000110000101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00100000000001010010100000000000 +10001010000000000010111010000000 +00001000101000000000001011101000 +00000000101110100000000000100110 +10000000000010111010000000000010 +11101000000000001011101000000000 +00101110100000000000101110100000 +00000010111010000000000010111010 +00000000001011101000000000001011 +11100000000000100000101000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000010 +10000010000001000010110011000000 +00001000001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000100100101000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000000010011110000000000 +10000111010000000010110111000000 +00001000011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01111000000000100100100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001111000000000 +11000100100000010011110011100000 +00101100011110000000001111011110 +00000000111101111000000000111101 +11100000000011110111100000000011 +11011110000000001111011110000000 +00111101111000000000111101111000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01101000000000110100101000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011000110000000000 +11111000011000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000110110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000010001111 +10000000000010111000001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11111110110000100011001111100000 +00001100111110000000001101111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011001111100000000011111111 +10000000001111111110000000001111 +11111000000000111101000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110000100000 +10110111000000000011010111000000 +00001000011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000011110111000000000010110111 +00000000001011011100000000001011 +01100010000000101110101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00010000000000001001110000000000 +10110110000000000010000111000000 +00001000011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010000111000000000010110111 +00000000001011011100000000001011 +01110000000000101100010000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01100000000101001100110000000000 +10110010000000000010010011000000 +00001000001100000000001011001100 +00000000101100110000000000100100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00000000000001101101100100000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11111000000101011010110100000000 +11111011000000000011001011000010 +00101100101100000000001101101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011001011000000000011111011 +00000000001111101100000000001111 +10010000000000111110101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000100000000001110110000000000 +11111011000000010011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111100110000 +00000011111011000000000011111011 +00000010001111101100000000001111 +10010000000000111110010000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001111110000100000 +11111101100000010011111011000010 +00001111111100000000001110111100 +00000000111111110000000000111111 +11000000000010111111000000000011 +11111100000000001111111100000000 +00111111110000000000111110110000 +00000011001111000000000011111111 +00000000001111111100000000001111 +11101000000000111110000001000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000001000001000110110000000100 +10111000110110000010111011000000 +00001001101100000000001011101100 +00000000101110110000000000101110 +11000000000010011011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010101011000000000010111011 +00000000001011101100000000001011 +10000000000000101110000101100000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111001000000000010111011000000 +00001011101100000000001001101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010001011000000000010111011 +00000000001011101100000001001011 +10010010000100101110000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10110001000000000010110011000000 +00001001001100000000001011001100 +00000000101100110000000000101100 +11000000000110010011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010100011000000000010110011 +00000000001011001100000000001011 +00000000000000101100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +10000000000011010110110000000000 +11111001000000000011111011000000 +00001111101100000000001110101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011001011000000000011111011 +00000000001111101100000000001111 +10110000000000111110000000000010 +00010000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11110100000001000011111111000000 +00001101111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11000000000000111110100000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11111111000000000011111111100000 +00001111111110000000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111110010000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11001000000000110111000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001110111000000000 +10111011110100010010111011100000 +00001011101110000000001110101110 +00000000101110111000000000101110 +11100000000010111011100000000010 +11101110000000001011100010000000 +00101110111000000000101110111000 +00000010111011100000000010111011 +10000000001011101110000000001011 +10001000000000100010000000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10100011000001000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011000000000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00000000000001100110001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010110000010000 +10111011000000000010111011000000 +00001011101100000000001010101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000011011100000001000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000011011 +10110000000000100111000000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000101011110110000000000 +11111111000000100011111011000000 +00001111101100000000001011101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000010111011 +00000000001111101100000000001011 +10011001000000110101000000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11111111000000000000111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000100001111111100100000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11000000000000111011100000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011001000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111100101000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10010000000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10111111100000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011100100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +00110000000000101111001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10110011010000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011000000000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00100010000000101111100100000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00100000000000010001111000000000 +10110111100000000010110111100000 +00001011011110000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011010010000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01001000000000101100100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +01001000000010000000110001000000 +11110011000010000011110011000000 +00001111001100000000001111001100 +00000000111100110000000000111100 +11000000000011110011000000000011 +11001100000000001111001100000000 +00111100110000000000111100110001 +00000011110011000000000011110011 +00000000001111001100000000001111 +00100000000000111101001000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000111011011110000010000 +11111111000000100011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111101000000 +00111111110000000000111111110000 +01000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111101000000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011110110000000000 +11111111100000000011001011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101000000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10111000000000110010101000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000100011001110000000000 +10110111100000000011010111000000 +00001110011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011000000000 +00101101110000000000101101110000 +00010010110111000000000010110111 +00000000001011011100000000001011 +01000000000000110101001000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000000001001111000000000 +10110011100000000010100111100000 +00011011011110000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +01101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000001100011000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110011000000000010110011000000 +00001010001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100110000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110010000000100101001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11111010000000000011101010000000 +00001111101000000000001111101000 +00000000111110100000000000111110 +10000000000011111010000000000011 +11101000000000001111101010000000 +00111110100000010001111110100000 +00000011111010000000000011111010 +00000000001111101000000000001111 +11100000000000110011101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011011000000000 +00001110100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000100000000111101001000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111101100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10011100000000101110000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001100000000010111001000000 +00001011100100000000001011100100 +00000000101010010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010101000000101100011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001101010000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11111000001000000011111000000000 +00001111100000000000001111100000 +00000000111010000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000011011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111101100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +01010000000000111110011000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000001011110010000000000 +11111101100000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +11010000000000111100011000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000100001110000000000000 +10111000010100000010111000000000 +00001110100000000000001011100000 +00000000101110000000000000101110 +00000000000010111000000000000010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000010111000000000000010111000 +00000000001011100000000000001011 +10100000000000101100111000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000001011100010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10111001000000000000111001000000 +00001010100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000011011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000011011 +10010000010000101100011000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101010110010000000000 +11111001000000000010111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100110010000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10011000000000111110100000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +00101000000000011010010000000100 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100110000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10011001000000111100101000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000000000011001000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000100000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010010100000000000 +10111110100001000010001010000000 +00001011101000000000001011101000 +00000000101110100000000000101110 +10000000000010111010000000000010 +11101000000000001011101000000000 +00101110100000000000101110100000 +00000010111010000000000010111010 +00000000001011101000000000001011 +11100000100000101100101000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110000000000001010100011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00111000000000101100001000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000000010001110000000000 +10110100110000000010100111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01100000000000101110000000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001111000001000 +11110100100000000011100111100000 +00001111011110000000001111011110 +00000000111101111000000000111101 +11100000000011110111100000000011 +11011110000000001111011110000000 +00111101111000000000111101111000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01011000000000111110101000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000010011011010110000000000 +11110000000000100011011011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10000000000000111100001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000001011111111000000000 +11111110100000000011001111100100 +00001111111110000000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111011110000000 +00110011111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111001000000110000000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110000000000 +10110110000000000010000111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101001110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000100001011 +01100000000010100010101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110110000000000010000111000000 +00011011011100000000001011011100 +00000000101001110000000000101101 +11000000000010110111000000000010 +11011100000000001011111100000000 +00100001110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +11110000100001100000000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00100000000101001100110000000000 +10110000000000000010000011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101000110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00101100000000100000100000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10101000000101011010110000000000 +11111001000000001011001011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00110010110000000000111110110000 +00000011111011000000000010111011 +00000000001111101100000000001011 +00110000000000110010101100000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11111000010000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110000000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +00000001000100001111110000000000 +11110101000000000011001111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11000100100000110000000001000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000001000001000110110000000000 +10111001000000000010001011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010011011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10001000000000101010000001000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000010000010001011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10010100000000100010000000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10110010000000000010000011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010010011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +10010000000000101000001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000011010110110000000000 +11111011000000000011001011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10000000000000110000100000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011111110000000100 +11110101000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011011111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +01000000000000111110000000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111101000000000 +11111100100000000011111111100000 +00001101111110010000001101111110 +01001000110011111000000000110111 +00000000000011111111100000000011 +11111100000000001101111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111111000000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000100001110011000000000 +10111000100000000010111011100000 +00001011101100000000001000001100 +00001000100010111000000000101110 +10110000000010111011100000000010 +11111110000000001010101110000000 +00101110111000000000101110111000 +00000010111011100000000010111011 +10000000001011101110000000001011 +10111000000000101111000000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11001000000001011100100000000000 +10110001000000000010110011000000 +00001011001100100001001001001100 +10000011100000110000000000101100 +00010000000010110011000000000010 +11001100000000001001001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101111001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000100011010010100000000 +10111011000000000010111011000000 +00001011001100000000001000001100 +00000000100010110000001000001110 +11000110000010111011000000000010 +11101100000000000010101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111000000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011110110000000000 +11111010010000000011111011000000 +01001101101100000001001101101100 +00000000110010110000000000111110 +01100000000010111011000000000011 +11101100000000001101101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111101010000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011011100000000 +11111110000000000011111111000000 +00000011111100000000001111111100 +00000000111111110000010000001110 +11100000000011111111000000000011 +11101100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111111100000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000100000100001010110100000000 +11101001010000000011111011000000 +00001101101100001000001111101100 +11000000110010110000000000111110 +00010000000011001011000000000011 +11001100000100001110101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111101010000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +11011000000001010010010000000001 +10001011000000000010111011000000 +00001001101111000000001011101111 +00000000110110110000000000101110 +11000000000011011011000000000010 +11111100000000001000101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111001000000100 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100000000010000 +10100001000000000010110011000000 +00001011001100000000001011001100 +00000000100100110000000000101100 +00000000010010000011000000000000 +11001100000000001010001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101111000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10110000100000010011001000001000 +10000100100000000110110111100001 +00001011011110000000001011011110 +00000000100101111000010000101101 +00100000000010010111100000000010 +11011110000000001010011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101110110000000100 +00010000000000000000000000000000 +00000000000000000000000000000000 +01001000000010000000000000000000 +10100001000000000011110011000000 +00001111001100001000001111001100 +00000000110100110001000000111100 +10000000000011000011000000000011 +11001100000000001110001100000000 +00111100110000000000111100110000 +00000011110011000000000011110011 +00000000001111001100000000001111 +00110001000000111101001000000010 +00010000000000000000000000000000 +00000000000000000000000000000000 +01000000000111011001000001000000 +11111110000100000011111111000000 +00001101111100000000001111111100 +00000000111111110000000000111111 +10000000000011111111000000000011 +11111100000000001101111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111101000000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011110100000010000 +11111011001010000001111011000000 +00001111101100000001101100101110 +00000000110010110000000000111110 +01000000000011001011000000000011 +11101100110000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11001000100100011001000000000000 +00110110000000000010110111000000 +00001011011100000000001000111100 +00000000101001110000000000101100 +11000000000010100111000000000010 +11011100010000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101111001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001001101000000000 +10110101110000000010110111100000 +00001011011110000000001000011110 +00000000100001111000000000101101 +01100000000010000111100000000010 +11011110100000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101100100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100001110000000 +10110010100000010110110011000000 +00001011101100000000001000001100 +00000000101000110000000000101100 +11111000000010100011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101101101000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +11100000000101011011100000100000 +11110010000000000011111010000000 +00001111101000000000001100101000 +00000000110010100000000000111111 +10110000000011001010000000000011 +11101000000000001111101000000000 +00111110100000000000111110100000 +00000011111010000000000011111010 +00000000001111101000000000001111 +10100000000000111111101100000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111100 +00000100000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111101001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000100 +11111011000000100011001001000000 +00001111100110000000001110100110 +00000000111110010000000000111110 +01000000000011001001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000000000010101001000000 +00001011100100000000001000100110 +00000000101110010000000000101110 +01000000000010001001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000100101110000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111011000000000010001001000000 +00001011100100100000001010100100 +10000000101110010000000000101110 +01000000000010001001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100111000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10111001000000000010100001000000 +00001011000100000000001000000100 +00000000101100010000000000101100 +01001000000010000001000000100010 +11000100101000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100101000000101 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11111000000000000011001000000000 +00001111001001010000001110101001 +01000000111110000000000000111110 +00000000001011001000000000000011 +11100000100000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111011111010000000000 +11111001000000000010111001000000 +00001111100100000000001111100100 +00000000111110010000000000111111 +01000100000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110011000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000001011100010000000000 +11111001000000000011111001000000 +00001111110100000000001100110100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100011000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01111000000100001110000000000000 +10111000000000100010111000000000 +00001011100000000000001101100000 +00000000101110000000000000101110 +00000000000010111000000000000010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000010111000000000000010111000 +00000000001011100000000000001011 +10000000000000101100111000000110 +00110000000000000000000000000000 +00000000000000000000000000000000 +01001000000001011100010000000000 +10110001000000000110110001000000 +00001011000100000000001000000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101101001000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10111001000110000110111001000000 +00001011100100000000001001100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011110010000000000 +11111001100000000011111001000000 +00001111100100000000001100100100 +00000000111110010000000000111110 +01101100000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110100000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +01101000000000011010010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000010000111110 +01100000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111101001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11101000010000000011111000000000 +00001111100000000000001111100000 +00000000110010000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111100001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010010100000000000 +10001010000000000010111010000000 +00001011111011000000001011111001 +00000000100010100000000000101110 +10000000000010111010000000000010 +11101000000000001011101000000000 +00101110100000000000101110100000 +00000010111010000000000010111010 +00000000001011101000000000001011 +10100000000000101100101000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10100011000000000010110011000000 +00001011101111001000001011001111 +00100000100000110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100101100000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000000010011111000000000 +10000111000000000010110111000000 +00001011011100001000001001011011 +00000000100001110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101110000000000100 +01000000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001111000000000 +11100111100000000011110111100000 +00001111011110000000001111111110 +00000010110001111000000000111101 +11100000000011110111100000000011 +11011110000000001111011110000000 +00111101111000000000111101111000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01111000011000111110001000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111011000000100011111011000000 +00001111101100000000001111100100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000001011111111000000000 +11111111100000100101111111100100 +00001111110110010000001100110110 +00000000110011111000000000111111 +11100000000011111111100000000011 +11111110000000001110111110000000 +00111111111000000000111111111000 +00000011011111100000000011111111 +10000000001111111110000000001111 +11111000000000111100000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110000000000 +10110111000000000110110111000000 +00001011110000000000001101010000 +00000000101001110000000000111101 +11000000000010110111000000000010 +11011100000000001000011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110001000000101110101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110111000000000010110111000000 +01001011010100000010001000011100 +00000000100001110000000000101101 +11000000000010110111000000000010 +11011100000000001010011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101100000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00100000000101001100110010000000 +10110011010100000010110011000000 +00001011100100000000001000100000 +00000000101000110000000000101000 +11100100000010110011000000000010 +11001100000000001000001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100100000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000101011010111110000000 +11111011010000000011111011000000 +00001111101000000010101000101100 +00000000110010110000000000101110 +11010100000011111011000000000011 +11101100000000001110101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000001000111 +10110000001100101110101100000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11111011001000000011111011000000 +00001111100000000000001111101001 +00000000111110110000000000111110 +11000000000011111011000000000011 +11001100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110000000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +00000001000100001111110000000000 +11111111000000000011111111000000 +00001111111010000000001100111000 +00000000110011110000000000111101 +11000000000011001111000000000011 +11101100000000001100111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000000011 +11110000000000111100100001000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110110000000000 +10111011000001000010111011000000 +00001011101011010000001010101011 +00100000110110110000000000101110 +11000000000010101011000000000010 +11101100000000001010101100000000 +00101110110000000000101110110000 +00000010011011000000000010111011 +00000000000011101100000000001011 +10110000000000101110100001000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000000010010110000000000 +10111011000000000110111011000000 +00001011101101000000001000100100 +01000000100010110000000000101110 +11000000000010001011000000000010 +11101100000000001000101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000000001101100000000001011 +10110000000000101110000000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10110011000000000010110011000001 +00001011000000000000001000000000 +00000000100100110000000000100100 +11000000001010000011000000000010 +11001100000000001010001100000000 +00101100110000000000101100110000 +00000010010011000000000010110011 +00000000001011001100000000001011 +00110000000000101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000011010110110000000000 +11111011000000000011111011000000 +01001111100000000000101100000100 +00000000110010110000000000111110 +11000000000011001011000000000011 +11101100000000001100101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100000000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11111111000000000010111111000000 +00001111110000000000001111110000 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000001111110100001000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11111111001000000011001111100000 +00001111111110000000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +00111110000000001111111110000000 +00111111111000000000111111110000 +00000011011111100000000011111111 +10000000001111111110000000001111 +11111000000000110011000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10100000000100001110111000000000 +10111111110100000000001011100000 +00001011101110000000001011101110 +00000000101110111000000000101110 +11100000000010111011100000000010 +10101110000000001011101110000000 +00101110111000000000101111110000 +00000010101011100000000010111011 +10000000001011101110000000001011 +10110000000000101010000000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100110000000100 +10110001000001000010000011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010111001000000000010 +00001100000000001011001100000000 +00101100110000000000101100110000 +00000010010011000000000010110011 +00000000001011001100000000001011 +00110000000000100010001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000101011010110000000000 +10111000000010000010001011000000 +00001011101100000000001011101100 +00000000101110110000000000100110 +11000000000110111001110000000010 +10101100000000001011101100000000 +00100110110000000000101110110000 +00000010101011000000000010111011 +00000000001011101100000000001011 +10110000000000101011000000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000101011110110000000000 +11111101000000001011001011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011110000000011 +00101100000000001111101100000000 +00111110110000000000111110110000 +00000011011011000000000011111011 +00000000001111101100000000001111 +10110000000000110000000000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000000011011110000000000 +11110101000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100001000 +00111111110000000000111110110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111111100000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011000000000011101011000000 +00001111101100000000001101101100 +00000000111110110000000000111110 +11000000000011111001000100000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011001011000000000011111011 +00000000001111101100000000001111 +10110000000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10111011000000000010001011000000 +00001001101100000000001001101100 +00000000101110110000000000101110 +11000000000010110001000000000010 +11101100000000001011101100001000 +00101110110000000000101111110000 +00001010001011000000000010011011 +00000000001011101100000000001011 +10110000000000101111001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10110011100100000010100011000000 +00001001001100000000001011001100 +00000000101100110000000000101100 +11000000000010110010000000000010 +11001100000000001011001111000000 +00101100110000000000101110110000 +00000010000011000000000010010011 +00000000001011001100000000001011 +10110000000000101111100000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +01100000000000010001111000000000 +10110111100000000010000111100000 +00001001011110000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110010000 +00101101111000000000101101111001 +00000010000111100000000010010111 +10000000001011011110000000001011 +01111000000000101101100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +01001000000010000000110001000000 +11110001000000000011100011000000 +00001101001100000000001111001100 +00000000111100110000000000111100 +11000000000011110011000000000011 +11001100000000001111001100000000 +00111100110000000000111100110000 +00000011000011000000000011010011 +00000000001111001100000000001111 +00110000000000111101001000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000111011011110000010100 +11110101100000000011111111000000 +00001101111100000000001101111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000100 +00111111110000000000111111110100 +00000011111111000000000011011111 +00000000001111111100000000001111 +11110000000000111101000000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011110110000000000 +11110001011000000011001011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +00101100000000001111001110000000 +00110010110000000000111110110001 +00001011001011000000000011111011 +00000000001111101100000000001111 +10110000000000111110101000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000100011001110000000000 +10110101000010010000000111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +10011100000000001011011100000000 +00110101110000000000101100110010 +00000010000111000000000010110111 +00000000001011011100000000001011 +01110000000000101101001000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000001000000001001111000000100 +10110111100000100000000111100000 +00001011011110000000001011011110 +00000000101101111000000000101101 +11100000000010111111100000000010 +00011110000000001011011110000000 +00100001111000000000101101111000 +00000010000111100000000010110111 +10000000001011011110000000001011 +01111000000000101111000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110011010100001010000011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +10001100000000001011001100000000 +00100100110000000000101100110000 +00000010000011000000000010110011 +00000000001011001100000000001011 +00110000010000101101001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11110110110000000011001010000000 +01001111101000000000001111101000 +00000000111110100000000000111110 +10000000000011111110000000000011 +00101000000000001111101000000000 +00110010100000000000111110100000 +00000011001010000000000011111010 +00000000001111101000000000001111 +10100000000000111111101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000010000 +11111000000010000011111000000000 +00001111100000000000000111100000 +00000000111110000000000000111110 +00000000000011111000100000000011 +11100000000000001111100001000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111101001000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000000000011001001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001100000000011 +00100100000000001111100100100000 +00111110010000000000111100010000 +00000011001001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000100001000110010000000000 +10111001000000000110001001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010110001100000000011 +01100100000000001011100111001000 +00101110010000000000101110010000 +00000010001001000000000010111001 +00000000001011100100000000001011 +10010000000000101110000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000001000010001001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001001000000010 +00100100000000001011100100000000 +00101110010000000000101110010000 +00000010001001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10111001001010000010100001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010111001000000000010 +01000100000000001011000100000000 +00101100010000000000101100010010 +10000010000001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11111000001000001010001000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +00100000000000001111100000000000 +00111110000000000100111110001010 +00001011001000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111011110010000000000 +11111101000000000011011001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011110101000000000011 +11100100000000001111100100000000 +00111110010000000000111110010010 +10000011111001000000000011111001 +00000000001111100100000000001111 +10010010100000111110011000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +10011000000001011110010000000000 +11111101100000001011001001000000 +00001011100100000000001111100100 +00000000111110010000000000111110 +01000000000011111101000000000011 +11100100000000001111110100000000 +00111110010000000000111110010000 +00000000101001000000000011111001 +00000000001111100100000000001111 +10010000000000111110011000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000100001110000000010000 +10111000000000000011011000000000 +00001011100000000000001011100000 +00000000101110000000000000101110 +00000000000010111000000000000010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000010101000000000000010111000 +00000000001011100000000000001011 +10000000000000101100111000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000001011100010000000000 +10110001010000001010000001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001100000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010000001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10111001001000000010011001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000001000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010101001000000000010111001 +00000000001011100100000000000011 +10010000010000101100011000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011110010000001000 +11111001001000100011001001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001010000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011001001000000000011111001 +00000000001111100100000000001111 +10010000000000111110100000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000000011010010000000000 +11110001100000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001101000000011 +11100100000000001111100100001000 +00111110010000000000111100010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000010000000011001000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000010000 +00111110000000000100111110000000 +00001011001000000001000011111000 +00000000001111100000000000001111 +10000000000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00100000000001010010100000000000 +10111010100000001010001010000000 +00001011101000000000001011101000 +00000000101110100000000000101110 +10000000000010111010101000000010 +11101000000000001011111000000000 +00101110100000000000101110100000 +00000010001010000000000010111010 +00000000001011101000000000001011 +10100000010000101100101000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110011100000000010000011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110001000000000010 +11001100000000001011001110000000 +00101100110000010000101100110000 +00000010000011000000000010110011 +00000000001011001100000000001011 +00110000000000101100101000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000000010001110000000000 +10110111010000000010000111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011010000000000 +00101101110000000000101101110000 +00000010000111000000000010110111 +00000000001011011100000000001011 +01110010000000101100100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001111000000000 +11110011100000001011000111100000 +00001111011110000000001111011110 +00000000111101111000000000111101 +11100000010011110111100000000011 +11011110000000001111010010000000 +00111101111000000000111100111000 +00000011000111100000000011110111 +10000000001111011110000000001111 +01111000000000111100101000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000000111100000000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110001000000111100001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11111111100000000011001111100000 +00001111111110000000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001011110010010000 +00111111111000000000111111111000 +10000011001111100000000011111111 +10000000001111111110000000001011 +11111001000000111101000000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110000000000 +10110101000000000010000111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011010000000000 +00101101110000000000101101110000 +00000010100111000000000010110111 +00000000001011011100000000001011 +01110000000100101110101000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +00010000000000001001110000000000 +10110011000000000010000111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011010000000010 +00101101110000000000101100110000 +00000010000111000000000010110111 +00000000001011011100000000001011 +01110000001000101100011000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01100000000101001100110000000000 +10110001001000000010000011000000 +00001011001100000000001011001100 +00000000101100110000000001101100 +11000000000010110011010010000010 +11001100000000001011000000000000 +00101100110000000000101110110000 +00000010100011000000000010110011 +00000000001011001100000000001011 +00110000000000101101100000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +11111000000101011010110000000000 +11111011000000001011001011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011010000000011 +11101100000000001111100000000000 +00111110110000000000111111110000 +00000011001011000000000011111011 +00000000001011101100000000001111 +11110000000000111110111000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000100000000001110110000000000 +11111011000000010011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111100001000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001011101100000000001111 +10110000000000111110000000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001111110000000000 +11110111000000000011001111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111100000000011 +11111100000010001111110000000000 +00111111110000000000111111110000 +00000011001111000000000011111111 +00000000001111111100000101001111 +11110000000100111110000001100100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000001000001000110110000001000 +10111011000000000000101011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011100000000010 +11101100000000001011100011100000 +00101110110000000000101110110000 +00000010101011000000000010111011 +00000010001011101100000000001011 +10110000000000101110000001000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000000000010001011000000 +00001011101100000000001011101100 +00000000101110110000000000101010 +11000000000010111011000100000010 +11101100000000001011100010000000 +00101110110000000000101110110000 +00000010001011000000000010111011 +00000000001011101100000000001011 +10110000000000101110000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10110001000000000010100011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000011011000000000000 +00101100110000000000101100110000 +00000010100011000000000010110011 +00000000001011001100000000001011 +00110000000000101100001000000101 +00000000000000000000000000000000 +00000000000000000000000000000000 +10000000000011010110110000000000 +11111011000000001011001011000000 +00001111101100000000001111101100 +00000000111110110000000000111010 +11000000000011111011000000000011 +11101100000000001111100000000000 +00111110110000000000111110110000 +00000011001011000000000011111011 +00000000001111101100000001001111 +10110000000100111110000000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011111110000010000 +11111101000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000000111110000000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000011111111100000000001111 +11110000000000111110100000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000011011111111000000000 +11101111100000000011111111100000 +01001111111110000000001100111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111011000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000000001110111000000000 +10111011100000000010111011100000 +00001011101000100000001000101110 +00000000101110111000000000101110 +11100000000010111011100000000010 +11101110000000001011101100000000 +00101110111000000000101110111000 +00000010111011100000000010111011 +10000000001011101110000000001011 +10111000000000101111000000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +11001000000001011100110000000000 +10100011000000000010110011000000 +00001011000100001000111001001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001010 +00110000000000101011001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010110000000000 +10111011000000000110111011000000 +00001011000100001000001001101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000010000101111000000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10010000000101011110110000000000 +11101011000000000011111011000000 +10001111100100010000001101101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001011101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111000100000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11111111000001000011111111000000 +00001111110000000001001110111100 +00000100111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111111100000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01010000000100001010110000000000 +11101011000000000011111011000000 +01001111100101100000101100101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000110001010100000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10111011000010000000111011000000 +10001011101101000000001000101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10111000000000100011001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000001000 +10110011111001000000110011000000 +00001011001100010000001001001100 +00000000001100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110011000000100011000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +11110000000000010001111000000100 +10110111100000000010110111100000 +00001011011010010000011001011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000010100011110000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01001010000000000000110000000000 +11110011000000000011110011000000 +10011111101100010110001101001100 +00000000111100110001000000111100 +11000000000011110011000000000011 +11001100000000001111001100000000 +00111100110000000000111100110000 +00000011110011000000000011110011 +00000000001111001100000000001111 +00110000000000110001101000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000101011011110000000000 +11111111000000000011111111000000 +00001111111000010000001110111100 +00000000111111110000010000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +01110000000001111101000000000110 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011110110000000000 +11111011000000000011111011000000 +00011111100111001000001100101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11001000100100011001110000000000 +10110111000000000010110111000000 +00001011110100000000001000011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101111001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001001111000000000 +10110111100000000010110111100000 +00001010010110000001001000011110 +00000000101001111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010100111 +10000000001011011110000000001010 +01111000000000101100100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110011000000000010110011000000 +00011011001100110000001000001100 +00010000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101101001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11100000000101011010100000000000 +11111010000000000011111010000000 +00001110101000000000101100101000 +00000000111010100000000000111110 +10000000000011111010000000000011 +11101000000000001111101000000000 +00101110100000000000111110100000 +00000011111010000000000011101010 +00000000001111101000000000001110 +10100000000000101111101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000100000000111101001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000000000011101001000000 +00001111101100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000110000001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10110001000000000010001001000000 +00001011100110010000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +00010000100000101010000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001010000000010001001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000100000011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001000000000010000001000000 +10001011001100000000001011000100 +00000000100100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101000001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000011010110000000000100 +11111000000000001011101000000000 +00001111100001010000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000110010111000000111 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100110101000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110111100000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +10011000000001011110010000000001 +11111101000000001011001001000000 +00001111110100000000001100100100 +00000000111110010000000000111110 +01000000000111111001000000000011 +11100100000000001111100100010000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +11010000000000111110111000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +01111000000100001110000000000000 +10111000000000000010001000000000 +00001011000000000000001000100000 +00000000101110000000000000101110 +00000000000011111000000000000010 +11100000000000001011100010100000 +00101110000000000000101110000000 +00000010111000000000000010111000 +00000000001011100000000000001011 +10000000000000101100011000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +01001000000001011100010000000000 +10110001000000000010010001000000 +00011011000100000000011001000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100100000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000001101101001000000001 +01100000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000000001 +10111011000000000010011001000000 +00001011001100000000001001100100 +00000000101110010000000000101110 +01000000000010101001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000010011011 +10010000000000101100011000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011110010000000000 +10111001000000100011011001000000 +01001111100111110000101101100100 +00000000111110010000000000111110 +01000000000010111001000000000011 +11100100000000001011100100000000 +00111110010000000000101110010000 +00000011111001000000000011111001 +00000000001111100100000000001011 +10010000000000111110000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01101000000000011010010000000000 +11111001000000000011101001000000 +00001111100110000000001110100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000100000111101101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000001000011111000000000 +00001111100000011000001100100000 +00000000111110000000000000111110 +00000000000011111000000001000011 +11100000000000001111100000000000 +00110010000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010010100000000000 +10110110000010010010111010000000 +00001011111010000000001000101000 +00000000101110100000000000101110 +10000000000010111010000000000010 +11101000000000001011101000000000 +00101010100000000000111010100000 +00000010111010000000000010111010 +00000000001011101000000000001011 +11101100000000101100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110000000000000010110011000000 +00001011001111000000001001001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00100000110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00111000000000101100001000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000000010001110000000000 +10110101000000000010110111000000 +00001011010000000000001001011100 +00000000101101110000001000101101 +11000000000010110111000000000010 +11011100000000001011011110000000 +00101001110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01100000100000101100100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001111000000000 +11110100100000000011110111100000 +01001111011110000000101101011110 +00000000101101111000000000111101 +11100000000011110111100000000011 +11011110000000001111111110000000 +00110001111000000000101101111000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01111000000000111100001000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111000000000000011111011000000 +10001111101000000000001110101100 +00001000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111010110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000001011111111000000000 +11111110100000000011111111100000 +00011111011110000000001110111110 +00000000111111111001000000111111 +11100100000001111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000101101100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110000000000 +11100111000100000010110111000000 +00001011010100100000001101011100 +00000000101101110000000000111101 +11000000000011110111000000000010 +11011100000000001011011100000000 +00101101110000000000111001110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01000000000000101110101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00010000000000001001110000000000 +10110110000000000010110111000000 +00001010111100000000001011011100 +00000000101101110000000100101101 +11000000000110110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001010 +01100000000000101100010000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01101000000101001100110000000000 +10100010000000000010110011000000 +00001011100000000000001000001100 +00000000101100110000000000101000 +11000000000010100011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000000011 +00000000000000101101000100000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10111000000101011010110000000000 +11111000000000000011111011000000 +00001110101100001000001011101100 +00001000111110110000000000101110 +11000000000010111011000000000011 +11101100000000001111111100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10010000000000101110001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11101001010000000011111011000000 +00001111100000001000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111010110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10000000001100111110010100000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001111110000000000 +11111100001000000011111111000000 +00001111110110000000001100111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11011000000000111110000001000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000000000110110000000000 +10111001110000000010111011000000 +00001011100001000000001111101100 +00000000101110110000000000101110 +11000000000011001011000000000010 +11101100000000001011111100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10010000000000101110000001100000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010110000001000 +10111010000000000010111011000000 +01001011101000100000011000101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110010000000101110100000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000000001 +10110001000000000010110011000000 +00001011000000000000101001001100 +00000000101100110000000000100100 +11000000000010000011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00000000000000101100101000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +10000000000011010110110000000000 +10111010000000000011111011000000 +00001111101100000000001100101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10100000000000111110000000000010 +00010000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11111101000000000011111111000000 +00001111110000000000001110111100 +00000000111111110000000000111111 +11000000000011101111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000001001111 +11000000000000111110100000100110 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000011011111111000000000 +11111111100000000011111111100000 +00001111111110000000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111110000000000110011111000 +00000011010100100000001011001111 +10000000001111111100000000001111 +11111000000000111111000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000000001110111000000000 +10111011100000000010111011100000 +00001011101110000000001110101110 +00000000101110111000000000101110 +11100001000010111011100000000010 +11101110000000001011101110000000 +00101111110000000000101000110000 +00000010001000100000000010001011 +10000000001011111110000000001011 +10111000000000101111000000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11001000000001011100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000100100110000 +00000010110010000000000010000011 +00000000001011001100000000001011 +00110000000000101111001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010110000000000 +10111011000000000010111011000000 +00001011101100000000001010101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000010 +00101110110000000000101110110000 +00000010111010000010000010001011 +00000000001011101100000000001011 +10110000000000101111000000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000100000101011110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000110110110000 +00000011111000010000000011001011 +00000000001111101100000000001111 +10110000000000111100000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111100110000000000111011110000 +01000011001101100100000011111111 +00000000001111101100000000001111 +11110000000000111111110000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000010110010110000 +00000011111010000000000011011011 +00000000001111101100000100001110 +10110000000000111101010000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11011000000000010010110000000000 +10111011000000000010111011000000 +00001110101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000010000010 +11101100000000001011101100000000 +00101111110000000000100010110000 +00000010000011000000000010001011 +00000000001011111100000000001000 +10110000000000101111001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10110011000000000010110011000000 +00001001001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011100000000010 +11001100000000001011001100000000 +00101100110000000000100010110000 +00000010100001000000000010010011 +00000000001011001100000000001010 +00110000000000101111000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +11110000100000010001111000000100 +10110111100000000010110111100000 +00001010011110000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000100001111001 +00000010001101100000000010000111 +10000000001011011100000000001000 +01111000000001101111110000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01001000000000000000110001000000 +11110011000000000011110011000000 +00001111001100000000001111001100 +00000000111100110000000000111100 +11000000000011110011000000000011 +11001100000000001111001100010000 +00111100110000000000110000110000 +00000011100001000000000011010011 +00000000001111001100010000001110 +00110000000000111101001000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000101011011110000000000 +11111111000000000011111111000000 +00001110111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000010 +11111100000000001111111100000000 +00111111110001000000111111110000 +01000011101101000000000011111111 +00000000001111111100100000001111 +11110000000000111101000000000110 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011110110000000100 +11111011000000100011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110111010100000110010110000 +00000011001010000000000011111011 +00000000001111101100110000001100 +10110000000000111100001000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11001000100100011001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110100000000101001110000 +00000010000111000000000010110111 +00000000001011001100010000001010 +01110000000000101111001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000001000000001001111000000000 +10110111100000000010110111100000 +00001011011110000000001010011110 +00000000101001111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101110000000000100001110000 +00000010000110100000000010110111 +10000000001011011110100000001000 +01111000000000101100100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000100101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001001001100000000 +00101100110000000000101000110000 +00000010000011110000000010110011 +00000000001011001100000000001010 +00110000010000101101101000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11100000000101011010100000001000 +11111010000000000011111010000000 +00001111101000000000001111101000 +00000000111110100000000000111110 +10000000000011111010000000000011 +11101000000000001111101000000000 +00111110100000000010110010100000 +00000010001110101000000010111010 +00000000001111101000000000001000 +10100000000000101111101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000010 +00111100000000000010111110000100 +00000011111000001000000011111000 +00000000001111000000000000001111 +10000000010000111101001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000000000011111001000000 +00001101100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001100000000011 +11100100000000001111100100000000 +00111110010000000000110110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000001000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001100000000010 +11100100000000001011100100000000 +00101110010000000000110110010110 +00000010111001000000000010111001 +00000000001011100100000000001000 +10010000000000101110100000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001001000000010 +11100100000000001011100100000000 +00101110010000000000100110010000 +00000010111001000000000010111001 +00000000001011100100000000001010 +10010000000000101100011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000110 +11000100000000001011000100000000 +00101100010010100010100100010000 +00000010110001000000000010110001 +00000010011011000100101000001000 +00010000000000101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000101110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111100001010000000110110000000 +00000011111000000000000111111000 +00000000001111100000100100011110 +10000000001001111110111000000111 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000001 +11100100000000001111100100000010 +00111110011010100000111100010010 +10000011111101000000000011111001 +00000000001111100100000000001110 +10010000000000111110011000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +10011000000101011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111101000000000011 +11100100000000001111100100000000 +00111110010000000000110011010000 +00000011001101000000000011111001 +00000000001111100100000000001111 +10010000000000111110111000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +01111000000010001110000000000000 +10111000000000000010111000000000 +00001011100000000000001011100000 +00000000111110000000000000101110 +00000000000010111000000000000010 +11100000000000001011100000000000 +00101110000000000000100010000000 +00000010001000000000000010111000 +00000000001011100000000000001011 +10000000000000111100111000000010 +00110000000000000000000000000000 +00000000000000000000000000000000 +01001000000001011100010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000010100000010000 +00000010010001000000000010110001 +00000000001011000100000000001011 +00010000000000101101001000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00011000000001011010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101010010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000100010010000 +00000010011001000000000010111001 +00000000001011100100000000001011 +10010000010000101000011000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10100000000001011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000101110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000110010010000 +01000011011001100100000011111001 +00000000001111100100000000001011 +10010000000000101110100000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +01101000000000011010010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011101001100000000011111001 +00000000001111100100000000001111 +10010000000000111101101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000000001010000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000110010000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00100000000001010010100000000000 +10111010000000000010111010000000 +00001011101000000000001011101000 +00000000101110100000000000101110 +10000000000010111010100000000010 +11101000000000001011101000000000 +00101110100000000000110101100000 +00000010111010000000000010111010 +00000000001011101000000000001011 +10100000000000101100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110001100000000110 +11001100000000001011001100000000 +00101110110000000000100000000000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100001100000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000100010001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000010000010 +11011100000000001011011100000000 +00101101110000000000100101001000 +00000010110111000000000010110111 +00000000001011011100000001001011 +01110000000000101100100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +10101000000000000001111000000000 +11110111100000000011110111100000 +00001111011110000000001111011110 +00000000101101111000000000111101 +11100000000011110111100000000011 +11011110000000001111011110000000 +00111111111100000000110001010000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01111000000000111100101000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000101011010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000100001111101100000000 +00111110110010100000111110010000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111001000000 +11111111100000000011111111100000 +00001111111110000000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111011001000 +00000011000111100000000011001111 +10000000001111111110000000001100 +11111001000000111101100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000001 +00101101110000000000100001000000 +00000011010111000100000011010111 +00000000001011011100000000001101 +01110000001000101110101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00010000000000001001110000001000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101001010000 +00000010001111000000000010000111 +00000000001011011100000000001000 +01110000001000001100010000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01100000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101110110000000000100010010000 +00000010010011000000000010010011 +00000000001011001100000000001001 +00110000000000101101000000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011110011000000000011 +11101100000000001111101100000000 +00111111110000000010111010100000 +00000011001011010000000011001011 +00000000001111101100000000001000 +10110000000000111110111000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10010100000000001110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000010011 +11101100000000001111101100000000 +00111110110000000000111110100000 +00000011111011001000000011111011 +00000000001111001100000100001111 +10110000000000111110100000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001111110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +00111100000000001111111100000000 +00111110110000000000110011110001 +00000011001111000000000011111111 +00000000001111101100000000001100 +11110000000000111110000001000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011100000000010 +00101100000000001011101100000000 +00101110110000000000100010110000 +01000010101011000000000010111011 +00000000001011101100000000001010 +10110000000000101110010001100000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000100000010 +00101100000000001011101100000000 +00101110110000000000100010100000 +00000010001011000000000010111011 +00000000001011101100000000001000 +10110000000100101110000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +00001100000000001011001100000000 +00101100110000000000100000100000 +00000010100011000000000010110011 +00000000001011001100000000001010 +00110000000000101100001000000100 +00000000000000000000000000000000 +00000000000000000000000000000000 +10000000000011010110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +00101100000000001111101100000000 +00111111110000000000110000110000 +00010011001011000001000011111011 +00000000001111101100000000001100 +10110000000000111110000000000010 +00010000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000010011111111000000000011 +11111100000000001111111100000010 +00111111110000000010111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111110100000100100 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000011011111111000000000 +11111111100000000011111111100000 +00001111111110000000011111111110 +01000000111111111000000000110011 +11100000000011111111110000000011 +00111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111111000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10000000000010001110111000000000 +10111011100000000010111011100000 +00001011101110000000001011101100 +10000000101110111000000000101010 +11100000000010111011000000000011 +01101110000000001011101110000000 +00101110111000000000101110111000 +00000010111011100000000010111011 +10000000001011101110000100001011 +10111000000000101111000000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10110011000000000010110011000000 +00001011001100000000011011001100 +00000000101100110000000000100000 +11000000000010110011001000000010 +00001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001010 +00110000000000101011001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011010110000000000 +10111011000000000010111011000000 +00001011101100000001001011101100 +00000000101110110000000000101010 +11000000000010111011000000000010 +01101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000010000101111100000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000101011110110000000000 +11111011000000000011111001000100 +00001111101100000000001011101100 +00000000111100110000000000110010 +11000000000011110011000000000011 +00101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000100111100100000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11111111000000000011111101100000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111111100000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011000000000011111001010000 +00001111101100000000001111101100 +01000000111110110000000000111110 +11000000000011111011001000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111101010000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10111011000000000010111011000010 +10001011101100000000001011101111 +01000000101110110110000000101110 +11000000000010111011101000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11000000000001000100110000000000 +10110011000000000010110010100000 +00001001001100000000001011001100 +00000000101100110010000000101100 +11000000000010110011010000100010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101111001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01100000000000000101111000000000 +10110111100000000010110111000000 +00001011011110000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101111110000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01001000000000000100110000000000 +11110011000000000011110010010100 +00001101001100000000001111001100 +00000000111100110000000101111100 +11000000010011110011000000000011 +11001100000000001111001100000000 +00111100110000000000111100110000 +00000011110011000000000011110011 +00000000001111001100000000001111 +00110000000000111101101000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000101011011110000000000 +11111111000000100011111110000000 +00001111111100000001001111111100 +00000000111111110000000101111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111101000000000110 +00100000000000000000000000000000 +00000000000000000000000000000000 +00001000000101011110110000000000 +11111011000000000011111010100000 +00011101101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100101000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000000011001110000000000 +10110111000000000010110111000000 +00001000011100000000001011011100 +00000001101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101111001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +00100000000100001001111000000000 +10110111100000000010111101100000 +01001000011110000101001010011110 +00010000101001111000000000101101 +11100000010010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101100000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01101000000101001100110000000000 +10110011000000000010110011000000 +00001000001100000000001011001100 +00000100101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101101001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011110100000000000 +11111010000000000011111110101100 +00001101101000000000001111101000 +00000000111110100000000000111110 +10000000000011111010000000000011 +11101000000000001111101000000000 +00111110100000000000111110100000 +00000011111010000000000011111010 +00000000001111101000000000001111 +10100000000000111111101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000011010000000000000 +11111000000000000011111000000000 +00001111100000000000001111100001 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111101001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001010010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +10000000110010010100000000111110 +01000000000011111001001000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000000000010111001100000 +00001011100100000000001011100100 +00100010100010011100000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101110100000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00111000000001010010010000000000 +10111001000000000010111001000100 +00001011100100000000001011000100 +00000000100010010000000000101110 +01000000000010111001000010000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001000000010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000100000110000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000001010110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100001 +01000000110010000000000000111110 +00000000000011111000010100000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111110011000000111 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000101011110010000000000 +11111001000000000011110111000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110011000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +10011000000101011010010000000000 +11111001000000000011111101000000 +00001111100100000000001111110100 +00000000111111010000000000111110 +01000000000011111101000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110111000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000100001110000000000000 +10111000000000000010111000000000 +01001011100000000000001110000000 +00000000111110000000000000101110 +00000000000010111000000000000010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000011101000000000000010111000 +00000000001011100000000000001011 +10000000000000101100011000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000001001000010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000010010110001000000000110 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101101001000000001 +00100000000000000000000000000000 +00000000000000000000000000000000 +00011000000000000010010000000000 +10111001000000000010111001000000 +00001011100100000000001010101100 +00000001101010010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010101001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10100000000001011110010000000000 +11111001000000000011111001110000 +00000111100100000000001111100100 +00000000101110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000101110100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000011010010000000000 +11111001000000000011111001110000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011101001000000000011111001 +00000000001111100100000000001111 +10010000000000111101001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00001000000000001010000000000000 +11111000000000000011111000010000 +00001111100000000000001111100000 +00000000110110000000000000111110 +00000000010011111000100000001011 +00100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000101010010100000000000 +10111010000000000010111010100000 +00001011101000000100001011111011 +00000000110111101000000000101110 +10000000000010111110000000000010 +00101000000000001011101000000000 +00101110100000000000101110100000 +00000010111010000000000010111010 +00000000001011101000000000001011 +10100000000000101100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001101 +00100000100000111000000000101100 +11000000000010110011000100000010 +01001100000000001010001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100001100000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10000000000100010001110000000000 +10110111000000000010110101010000 +00001011011100000000001011011011 +00000000100101110000100000101101 +11000000000010110101100000000010 +01011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101100100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +10001000000010000001111000000000 +11110111100000000011110111100000 +00001111011110000000001111011110 +00000000110001101000000000111101 +11100000000011111111100000000011 +01011110000000001110011110000000 +00111101111000000000101101111000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01111000000000111100101000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001011010110000000000 +11111011000000000011111001000000 +00001111101100000000001111100000 +00000000111110000000000000111110 +11000000000011111011000000000011 +10101100000000001101101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000011111 +10110000000000111100001000000010 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000001001011111000000000 +11111111100000000011110111100000 +00001110111110000000001111111110 +00000000110001011000000000110011 +11100000000010111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111101100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000110001001110000000000 +10110111000001000010110111000100 +00011000011100000000001110111000 +00000000101001110000000000110101 +11000000000010110100001000000010 +11011100000000001011011100000000 +00101101110000000000111001110000 +00000011110111000000000010110111 +00000000001011011100000000001111 +01110000000000101110001000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00010000000000001001110000000000 +10110111000000000010110101000000 +00001010011100000000001011011100 +00000000100001000000000000100001 +11000000000010110101000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101000011001000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01100000000001001000110000000000 +10110011000000000010110001110000 +00001000001100000000001010101000 +00000000101000000000000000100100 +11000000000010111001000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010100011000000000010110011 +00000000001011001100000000001010 +00110000000000101101000000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011010110000000000 +11111011000000000011110011000010 +00001110101100000000001111100100 +00001000110010110000000000110010 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000010111011000000000010111011 +00000000001111101100000001001011 +10110000000100111110111000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000100000000001110110000000000 +11111011000000000011111011000000 +00001111101100000000001111100101 +00000100111110100100000000111110 +11000000000011111001010000000011 +11101100000000001111101100000000 +00111110110000000000111010110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000001100111110100000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10100000000100001111110000000000 +11111111000000000011111111110010 +00001100111100000000001111111000 +01000000110011110000010000110011 +11000000000011111111100100001011 +00111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111110000001000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10100001000001000110110000000000 +10111011000000000010111011100000 +00001010101100000001001011100000 +00000000100000000110000000101010 +11000000000011111001000000000010 +00101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000011101011 +00000000001011101100000000001011 +10110000001000101110000001000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000000000010111011000000 +00001000101100000000001011100100 +00000000100010010000000000101010 +11000000000010111011000010000010 +00101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101110000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00001000000101000000110000000000 +10110011000000000010111011000000 +00001010001100000100001011000000 +00000010100000100000000000101000 +11000000000010100001000000000010 +00001100000000001011001100000000 +00101100110000000000101100110000 +00000010010011000000000010110011 +00000010001011001100000000001001 +00110000000000101100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +10000000000011010110110000000000 +10111011000000000011111011000000 +00001100101100000000001111100100 +00001000110010010000000000111010 +11000000000010111011000000000011 +00101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110000000000110 +00010000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011111110000000000 +11111111000000000001111111000000 +00001111111100000000001111110000 +00000000111111000000000000111111 +11000000000011111101000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011101111 +00000000001111111100000000001111 +11110000000000111110100000100110 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000011011111111000000000 +11111111100000000011111111100000 +00001111111110000000001101111110 +00000000111111111000000000111111 +00000000000011001100000000000011 +11110000000000001100110000000000 +00110011000000000000110011000000 +00000011111101000000000011001111 +10000000011111111110000000011111 +11111000000000111011000000000001 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000000001110111000000000 +10111011100000000010111011100000 +00001011101100000000001000101110 +00000000101110111000010000101110 +00000001000010001000100000000010 +11100000000000001100100010000000 +00100010001000000000100010001000 +00000010111001100000000010001011 +10000000001011101110000000001011 +10111000000101101111000000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +11001000000001011100110000000000 +10110011000000000010110011000000 +00001011001100000000001001001100 +00000000101100110000000000101100 +01000000000010010001000000000010 +11000000000000001001001000000001 +00100100000000000000100000000000 +00000010110001000000000010010011 +00000000001011001100000000001011 +00110000000000101111001000000001 +00110000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010110000000000 +10111011000000000010111011000000 +00001011001100000000001001101100 +00000000101110110000000000101110 +01000000000010011001000000000010 +11100000011000101000101000000000 +00100110000000000000100010000000 +10000010111001000010000010011011 +00000000001011101100000000001011 +10110000010001101111000000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10010000000101011110110000000000 +11111011000000000010111011000000 +00001111101100000000001101101100 +00000000111110110000000000111110 +10000000001011011000000100010011 +11100011000000101101100100000000 +10110110011000000010110010000101 +00010010111001010100001011011011 +00000000001011101100000000001011 +10110000000000111000100000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11111111000000000011111111000000 +00001111111100000000001110111100 +00000000111111110000000000111101 +10000000000011101000100000000011 +11100010000000001111110100000000 +00111011011001000000111110001000 +00000011110001100000000011101111 +00000000001111111100000000001111 +11110000000000111111100000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011000000000011111011000000 +00001111101100000000001110101100 +00000000111110110000000000111110 +11000000000011101001001000000011 +00000001000000101100001100000000 +00110100010000000000110010000100 +00000011001001010000000011001011 +00000000001111101100000000001111 +10110000001000111101010000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11011000000001010010110000000000 +10111011000000000010111011000000 +00001011101100000000001000101100 +00000000101110110000000000101110 +11000000000010001001011000000010 +00100000000000001101101100000100 +00100010011100100010100010000000 +00001010001001000000000010001011 +00000000001011101110010000001011 +10110000010000101111001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000001000 +10110011000000000010110011000000 +00001011001100000000001010001100 +00000000101100110000000000101100 +00000000000010100010110000001010 +00001100000000001000000010000100 +00100000101100100000100000110000 +00001010000010000000001010000011 +00000000001011001101000000001011 +00110000000001101111001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +11110000000000010001111000000000 +10110111100000000010110111100000 +00001011011110000000001000011110 +00000000101101111000000001101101 +00100000000010000110100000000010 +00011110000000101001010010001000 +00100000101001000000100001111001 +00000010000110100000000010010111 +10000000001011011110001000001011 +01111000000000101111110000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01001000000000000000110000000100 +11110011000000100011110011000000 +00001011101100000000001110001100 +00000000111100110000000000111110 +01000000000011100011000000000011 +00001100000000001100001000000000 +00110100100001000000100000110001 +00000011000010000000000011000011 +00000000001111001100000000001111 +00110000000000111101101000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000100101011011110000000000 +11111111000000000011111111000000 +00001111111100000000001110111100 +00000000111111110000000000111111 +01000000000011111111000100000011 +11111100010000001111011000010000 +10111111100001000000111111110001 +00000011111110100100000011101111 +00000000001111111100000000001111 +11110000000000111101000000000110 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +10000000000011011010000000000011 +00101110000000001100100100000000 +00110010110000000000110010111000 +00000011001010000000000011011011 +00000000001111101100000000011111 +10110000000000111100001000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11001000100100011001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101111 +10000000000010000110000000000010 +00001100000000001000010100000000 +00110001110000000000100000110000 +00000010000010000000010110000111 +00000000001011011100000000001011 +01110000000000111011001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000001000000001001111000010000 +10110111100000000010110111100000 +00001011011110000000001011011110 +00000000101101111000000000101101 +11100000000010010011100000000010 +00011110000000001000001110000000 +00100000111000000000100101111000 +00000010000110100000000010000111 +10000000001011011110000000001011 +01111000010000101100100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000100000010000011000000000010 +00001100000000001000001100000000 +00100000110000000000100000110000 +00000010000010000000000010000011 +00000000001011001100000000001011 +00110000000000101001001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11100000000101011010100000000000 +11111010000000000011111010000000 +00001111101000000000001011101000 +00000000111110100000000000111110 +10100000000011011010000000001011 +00101000000000101100101001000000 +10110010100100000010110110100000 +00001011001110000000001011001010 +00000000001011101000000000001011 +10100000000000101111101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000010000111100 +00000000000011110000010000000011 +11100000000000001111100000001000 +00111000000000100000111110000000 +00000011110100000000000011111000 +00000000001111100000000000001111 +10000000000000111001001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011001001010000000011 +00100100000000001111000100000000 +00110010010000000000110010010000 +00000011111001000000000011001001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10000010000001000110010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000010010001001111000000010 +00100100000000001011100100000000 +00100010010000000000100010010000 +00100010111001000000000010001001 +00000000001011100100000000001011 +10010000000000101110000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010011001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010001101000000000010 +00110100000000001011110100100000 +00100011010101000000100011010000 +00000010111101000000000010001001 +00000000001011100100000000001011 +10010000000000101100011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000100100010000000000101101 +01001011001010000101001010001010 +00010100101000001011010100101000 +10100001010010100000100001010010 +10000010110101001010000010000001 +00000000001011000100000000001011 +00010000000000101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00001000000011001000001000000011 +00100000100000001111100000100000 +00110010000010000010110010000010 +00000011111100001000001011001000 +00000000001111100000000100011111 +10000000000000111110111000000111 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111011110010000000000 +11111001000000000011111001000000 +00001111100100101000001111100100 +00000000111110010000000000111110 +01101010000011111001000000000011 +11100110101000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000001111110111000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +10011000000001011110010000000000 +11111001000000000011111001000000 +00001111100100000000001110100100 +00000000111110010000000000111110 +01000000000011010101000000000011 +11100100000000001100110100000000 +00110011010000000000110010010000 +00000011111001000000000011111001 +00000000001111110100000000001111 +10010000000000111110111000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01111000000100001110000000000000 +11111000000000000010111000000000 +00001011100000000000001011100000 +00000000101110000000000000101100 +00000000000011011000000000000010 +11000000000000001100100000000000 +00100010000000000000110110000000 +00000010111000000000000110111000 +00000000001011100000000000001111 +10000000000000101100011000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +01001000000001011100010000000000 +10110001000000000010110001000000 +00001011000100000000001010000100 +00000000101100010000000000101100 +01000000000010010001000000000010 +11000100000010001001000100000000 +00100000010000000000100000010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101101001000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10101001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101100 +01010000000010011001010000000010 +11100100000000001000100100100000 +00100010010000000000100110010000 +00000010111001000000000010111001 +00000000001011100100000000001010 +10010000000000101100011000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011110010000000000 +10111001000000000010111001000000 +00001111100100000000001110100100 +00000000111110010000000000111110 +01000000000011011001000000000011 +11100100000000101101100100000000 +10110010010000000000110010010000 +00000011111001000000000010111001 +00000000001111100100000000001011 +10010000000000111110100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01101000000000011010010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000011111100100000000001111 +10010000000000111101101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000000000011101000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011001000000010000011 +01100000000000001100000000000000 +00111110000000100000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001110 +10000000000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00100000000001010010100000000000 +10111010000000000010111010000000 +00001011101000000000001011101000 +00000000101110100000000000101110 +10000000000010001110010000000010 +00101000000000001000101010000000 +00101101101100000000101110100000 +00000010111110000000000010111010 +00000000001011111000011000001000 +10100000000000101100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110011000000000010100011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010000001010100000010 +00101100000000001000001110000000 +00101100111100000000101100110000 +00000010110010000000000010110011 +00000000001011001111000000001010 +00110000000000101100001000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000000010001110000000000 +10110111000000000010110111000000 +00001011011100100000001011011100 +00000000101101110000000000101101 +11000000000010000110100000000010 +00011100000000001000010100001000 +00101101000000100000101101110000 +00000010110110000000000010110111 +00000000001011011110000000001000 +01110000000000101100100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001111000000000 +11110111100000000011100111100000 +00001111011110110000001111011110 +00000000111101111000000000111101 +11101000000011000110100000000011 +01011111000000101100010110000000 +00111101001000000000111101111000 +00000011110110100000000011110111 +10000000001111011110000000001110 +01111000000100111100101000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111011000000000011111011000000 +00001111101101110000001111101100 +00000000111110110000000100111110 +11001100011011111010000000001011 +11101100100000001111100100000000 +00111110000000000000111110110000 +00000011111010000000000011111011 +00000000001111001100000000001111 +10110000000000111100001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111001000000 +11111111100000000011111111100000 +00001111111110000000001100111110 +00000000111111111000000000111011 +11110000000011000110100000100011 +00111111000001001111110110000010 +00110011001000000000111111111000 +00000011001110100100001011001111 +10000000001111111110000000001111 +11111000000000111101100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110000000000 +10110111000000000010110111000000 +00001011011100000000001101011100 +00000000101101110000000000111011 +11001000000011010110011000000010 +00111100000000001010010100000000 +00100001000100000000101101110000 +00000010000110000000000010000111 +00000000001011010000000000011011 +01110000000000111110101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00010000000000001001110000010000 +10110111000000000010110111000000 +00001011011100000000001001011100 +00000000101101110000000000101001 +11000000100010000110000000000010 +00011100000000001011010100000000 +00100001000000000000101101110000 +00000010000110010000100110000111 +00000000001011011100000000001011 +01110000000000101100010010000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01100000000101001100110000000000 +10110011000000000010110011000000 +10001011101100000000001001001100 +00000000101100110000000000101010 +11000000001010010010000000001010 +00001100000000001010000100000000 +00100000000000000000101100110000 +00000010000010100000000010000011 +00000000001011000000000000011011 +00110000000000101001100100000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010110000000000 +11111011000000000011111011000000 +00001111111100000000001001101100 +00000000111110110000000000111011 +11000000000010001010000000000011 +00111100000000101111100100000000 +10110010000000000000111110110000 +00001010001010011000000010001011 +00000000001111100000000000001011 +10110000000000101110111000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10010100000000001110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011110010010000000011 +11101100000000001111000100000000 +00111110000100000000111100110000 +00000011110010000000000011111011 +00000000001111100000000000001111 +10110000000000111110000000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001111110000000000 +11111111000000000011111111000000 +00011111111100000000001100111100 +00000000111111110000000000111111 +11000000000011001110001000000011 +00111100000000001110100100010000 +00110001000000000000110010110000 +00000011001010000000000011001111 +00000000001111110010000000001100 +11110000000000111110010001000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110110000000000 +10111011000000000010111011000000 +00001011101100000000001010101100 +00000000101110110000000000100110 +11000000000011011010110000000010 +00101100000000001101100100000000 +00100010001100000010100010110000 +00001010001010000000000010001011 +00000000001011000001000000001010 +10110000001000101110000001000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000000000010111011000000 +00001011101100000000011000101100 +00000000101110110000000000100110 +11000000000010001010000000000010 +00001100000000001010100100000000 +00100010001000000000100010110000 +00000010101010000000000010001011 +00000000001011101101100000001000 +10110000000000101110000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10110011000000000010110011000000 +00001011001100000000001010001100 +00000000101100110000000000100100 +11000000000010010010000000000010 +00001100000000001001000100000000 +10100000000000000010100000110000 +00011010100010000000000010000011 +00000000001011000000000000000010 +00110000000000101100101000000100 +00000000000000000000000000000000 +00000000000000000000000000000000 +10000000000011010110110000000000 +10111011000000000011111011000000 +00001011011100000000001100101100 +00000000111110110000000000110111 +11000000000011001010000000001011 +00111100000000101110100100000000 +00110010000000000000110010110000 +00010011101010000000001011001011 +00000000001111101100000000001100 +10110000000000111110000000100010 +00010000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000110111 +11000000000011111110000000000011 +11111100000000001111110100000010 +00111111000000000000111111110000 +00000011011110000000000011111111 +00000000001111110000000000001111 +11110000000100111110100000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11111100000000000011001111100000 +00001111111110000000001111111110 +00000000111111111000000000111111 +11100000110011111110100001000011 +00111110000000001111111110000000 +00111111111000000000110111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111111000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001110111000000000 +10111000110000000010001011100000 +00001011101110000000001011101110 +00000000101110111000000000101110 +11100000100010111001100000000010 +00101110000000001011101110000000 +00101110111000000000101110111000 +00000010111011100000000010111011 +10000000001011101110000000001011 +10111000000000101111000000000110 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10110000010000001010000011000000 +00001011001100000000001011001100 +00000000101000110000000000101100 +11000000000010111011000000000010 +00001100000010001011001100000000 +00101100110000000000100100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101111001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010110000000000 +10111000000110000010001011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011100000000010 +00101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000000011101100000000001011 +10110000000000101111000000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000101011110110000000000 +11111100110000000011001011000000 +00001111101100000000001111101100 +00000000111010110000000000111110 +11000000000011111010100000000011 +00101100000000001111101100000000 +00111110110000000000110110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111101010000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11110000100000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111111100000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111010011000001011001011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011001000000011 +10101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111101010000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010010111000000000 +10111000010000000110001011000000 +00001011101100000000001011101100 +00000000101110110000000000001110 +11000000000010110011000000000011 +01101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10110011100100000010000011000000 +00000011001100000000001011001100 +00000000101100110000000000001100 +11000000000010110010010000000010 +10001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101111100000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00100000000000010001111000000000 +10110111100000000010000111100000 +00001001011110000000001001011110 +00000001101101111000000000101101 +11100000000010110111100100000010 +01011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010010111 +10000000001011011110000000001011 +01111000000000101110110000000100 +00010000000000000000000000000000 +00000000000000000000000000000000 +01001000000010000000110000100000 +11110011000000000010000011000000 +00001111001100000000001111001100 +00000000111100110000000000111100 +11000000000011110011000000000011 +10001100010000001111001100000000 +00111100110000000000111100110000 +00000011110011000000000011110011 +00000000001111001100000000001111 +00110000000000111101101000000010 +00010000000000000000000000000000 +00000000000000000000000000000000 +01000000000111011011110000000000 +11111111000100000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011110111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111101000000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011110110000000000 +11111000000000000011001011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011110010000000000011 +00101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000100011001110000000000 +10110110000000000010000111000000 +00001011011100000000001011011100 +00010000101101110000000000101101 +11000000000010110111000000000010 +10011100000000001011011100000000 +00111101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101111001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000000001001111000000000 +10110010100000000010010111100000 +00001011011110000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +00011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101100100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110010011100000010000011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000100000010 +10001100000000001011001100000000 +00101000110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101101001000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11111110000000001011011010000001 +00001111101000000000001111101000 +00000000111110100000000000111110 +10000000000011110110100000000011 +00101000000000001111101000000000 +00101110100000000000111110100000 +00000011111010000000000011111010 +00000000001111101000000000001111 +10100000000000111111101000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000010000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111101001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000000000011001001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000001011 +00100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010100000000 +10110001110000000010001001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000100000010 +00100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000001000101110000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010100000000 +10111001001000000010001001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +00100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100111000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110011001000000010000001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110011000000000010 +00000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100101000000101 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11111000000000001011001000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +00100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111011110010000000000 +11111101000100000011111001000000 +00001111100100000000001111100100 +00000000101110010000000000111110 +01000000000011111101000000000011 +11100100000000001111100100000000 +01111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110011000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000001011110010000000000 +11111101100000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111101000001000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100011000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000100001110000000000000 +10111000000000000010111000000000 +00001011100000000000001011100000 +00000000101110000000000000101110 +00000000000010111000000000000010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000010111000000000000010111000 +00000000001011100000000000001011 +10000000000000101100111000000110 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000001011100010000000000 +10110001010000000010110001000000 +01001011000100000000011011000100 +00000001101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101101001000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001010000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011110010000000000 +11111001000000000010111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001110100000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110100000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +00101000000000011010110000100000 +11111001010000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000110011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111101001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000001000000011 +00100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111100001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010010101110000000 +10111110101000000010111010000000 +00001011101000000001001011101000 +00000000101110100000000000101110 +10000000000010111110011000000011 +01101000000000001011101000000000 +00101110100000000000101110100000 +00000010111010000000000010111010 +00000000001011101000000000001011 +10100000000000101100101000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100100100000000 +10110010000000000010110011000000 +00001011001100000000001011001100 +00000001101100110000000000101100 +11000000000010110011000000000010 +00001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100101000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000000010001000000000000 +10110100000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111100000000010 +01011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101110000000000100 +01000000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001101000001000 +11110111100000000010110111100001 +10001111011110000000001111011110 +00000000111101111000000000111101 +11100000010011110111100000100011 +00011110000000001111011110000000 +00111101111000000000111101111000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01111000000000111110001000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010000110101000 +11111010000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011110011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001101101100000000001111 +10110000000000111100001000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000001011111111000000000 +11100100100100000011101111100000 +00001111111110000000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +10111110010000001111111110010000 +00111111111001000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111100000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001010100000000 +10000100000000000010000111000100 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000001000010110111000000000010 +10011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101110101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10100101000000000110100111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010111111010010000010 +00011100000001001011011100000001 +00101101110000000000001101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101100000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00100000000101001100010000000000 +10000000100000000110000011000000 +00001011001100000000001011001100 +00000000101100110000000001101100 +11000000000010110011100000000010 +10001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000101011010100000000000 +11100010000010000011101011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011110010010000000011 +10101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110101000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110100100000000 +11111000000000000011111011000000 +00001111101100000000001111101100 +00000100111110110000000000111110 +11000000000011111011010000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001011101100000000001111 +10110000000000111110000000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +00000001000100001111111000000000 +11111111000000100011101111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111101000000000011 +00111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000001001111 +11110000000100111100100001000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000001010001000110111100000000 +10111011010000000010001011000001 +00001011101100000000001001101100 +00000000101110110000000000111010 +11000000000010111001100000000010 +10101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101110100001000100 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010000001000000 +10111000010000000010101011000000 +00011011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011100010000010 +00101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101110000000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000000000000000 +10111000000000000010100011000000 +00001011001100000000001001001100 +00000000101100110000000000101000 +11000000000010110011000000000010 +10001100000000001011001100000000 +00101100110000000000101100110000 +00000010010011000000000010110011 +00000000001011001100000000001011 +00110000000000101100001000000101 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000011010110010000000000 +11111001000000000011101011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +00101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100000000100011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000110011101010000000000 +11111101000000000011011111000000 +00001111111100000000001111111100 +00000000111111110000000000111011 +11000000000011110111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111110100100000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11111111100000000011111111100000 +00001111111110000000001111111110 +00000000111111111000000000110111 +11100000000011001111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11001000000000111111000000000101 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001110111000000000 +10111011100000000010111011100000 +00001011001100000000001011101110 +00000000101100110000000000100010 +11000000000011011011100000000010 +11101110000000001011101110000000 +00101110111000000000101110111000 +00000010111011100000000010111011 +10000000001011101110000000001011 +10101000000000101110000000000110 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10110011000000000010110011000000 +00001011001100000000001010001100 +00000000101100110000000000100100 +11000000000010000011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00010000000000101110001000000001 +00110000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000100010 +11000000000010011011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10000100010000101111000000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000101011110110000001000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000110110 +11000000000011001011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10000000000000111100000000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000000000 +10111111000000000011111111000000 +00001101111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001101111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11100000000000111111100000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011000000000011111011000000 +00001101101100000000001110101100 +00000000111110110000000000111010 +11000000000011101011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110100000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10111011000000000010111011000000 +00001011101100000000001000101100 +00000000101110110000000000100010 +11000000000010001011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10100000000000101111001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10110011000000000010110011000000 +00001011001100000000001010001100 +00000000101110110000000000101010 +11000000000010100011000000000010 +11001100000000001001001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00000000000000101111100000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00100000000000010001111000000000 +10110111100000000010110111100000 +00001011011110000000001000011110 +00000000101101111000000000100001 +11100000000010000111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101101100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +01001000000010000000110000000000 +11110011000000000011110011000000 +00001111001100000000001110001100 +00000000111100110000000000111010 +11000000000011100011000000000011 +11001100000000001111001100000000 +00111100110000000000101100110000 +00000011110011000000000011110011 +00000000001111001100000000001111 +00010000000000111101001000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000111011011110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11010000000000111101000000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011110110000000000 +11111011000000000011111011000000 +00001111101110000000001101101100 +00000000111110111000000000110010 +11000000001011001011000000000011 +11101100000000001111101100000000 +00111110110000000000111010110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10001000000000110110101000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000100011001110000000000 +10110111000000000010110111000000 +00001011111100000000001000011100 +00000000101101110000000000100011 +11000000000010000111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000010001011 +01110000000000100001001000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000000001001111000000000 +10110111100000000010110111100000 +00001011011110000000001001011110 +00000000101101111000000010100001 +11100000000010000111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +11111000000000100111000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001000001100 +00000000101100110000000000100000 +11000000000010000011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000100001001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11111010000000000011111010000000 +00001111101000000000001101101000 +00000000111110100000000000110010 +10000000000011001010000000000011 +11101000000000001111101000000000 +00111110100000000000111110100000 +00000011111010000000000011111010 +00000000001111101000000000001111 +11101000100000110111101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111101001000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011001001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000001010001001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101110000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101100 +01000000000010001001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010000001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111100000000000000111110 +00000000000011001000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111011110010000000000 +11111001000000000011111001000000 +00001111100100101000001111100100 +00000000111110011010100000111110 +01101010000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +01010000000000111110011000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000001011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000110010 +01000000000011001001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110011000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000100001110000000000000 +10111000000000000010111000000000 +00001011100000000000001011100000 +00000000101110000000000000101000 +00000000000010101000000000000010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000010111000000000000010111000 +00000000001011100000000000001011 +10100000000000101100111000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000001011100010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000100000 +01000000000010000001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101100010000000000101010 +01000000000010101001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011110010000001000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000110010 +01000000000011001001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110100000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000000011010010000000000 +10111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10011010000000111100101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000110010 +00000000000011001000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010010100000000000 +10111010000000000010111010000000 +00001001101000000000001001101000 +00000000101110100000000010100010 +10000000001010001010000000000010 +11101000000000001011101000000000 +00101110100000000000101110100000 +00000010111010000000000010111010 +00000000001011101000000000001011 +10100000000000101100101000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000100010 +11000000000010000011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100101000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000000010001110000000000 +10110111000000000010110111000000 +00001001011100100000001001011100 +00000000101101110001000000100001 +11000000000010000111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101100100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001111000000000 +11110111100000000011110111100000 +00001111011110000000001111011110 +00000000111111111010000000110001 +11100000000011000111100000000011 +11011110000000001111011110000000 +00111101111000000000111101111000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01111000000000111100101000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111011000000000011111011000000 +00000101101100011000001001101100 +00000000111110110000100000111110 +11010100000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011011011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000001011111111000000000 +11111111100000000011111111100000 +00001111111110000000001100111110 +00000000111111111000000000111011 +11110000000011011111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001101111110000000001110 +01111000000000110001000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110000000000 +10110111000000000010110111000000 +00001011011100000000001101011100 +00000000101101110000000000110101 +11000000000010100111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000100000110110101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110111000000000010110111000000 +00001011011100000000001000011100 +00000000101101110000000000101001 +11000000000010010111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010010111000000000010110111 +00000000001011011100000000001011 +11110000000000100000010010000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00100000000101001100110000000000 +10110011000000000010110011000000 +00001011101100000000001001001100 +00000000101110110000000000100100 +11000000000010100011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000010001011 +00111100000000100101101000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10101000000101011010110000000000 +11111011000000000011111011000000 +00001111111100000000001100101100 +00000000111111110000000000111011 +11000000000011011011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001101101100000000001110 +10111101000000110010101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110010000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +00000001000100001111110000000000 +11111111000000000011111111000000 +00001111111100000000001100111100 +00000000111111110000000000110011 +11000000000011001111000000000011 +11111100000000001110111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000000001 +11110000000000111110000001000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000001000001000110110000000000 +10111011000000000010111011000000 +00001011101100000000001010101100 +00000000101110110000000000101010 +11000000000010101011000000000010 +11101100000000001001101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000000011101100000001001001 +10110000001000101110000001000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000000000010111011000000 +00001011101100000000001010101100 +00000000101110110000000000100000 +11000000000010001011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000001000010111011 +00000000001001101100000000001001 +10110000000000101110000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10110011000000000010110011000000 +00001011001100000000001010001100 +00000000101100110000000000101000 +11000000000010100011000000000010 +11001100000000001001001100000000 +00101100110000000000101100110000 +00000000110011000000000010110011 +00000000001011001100000000001001 +00110000000000101100001000000100 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000011010110110000000000 +11111011000000000011111011000000 +00001111011100000000001100101100 +00000000111101110000000000110001 +11000000000011001011000000000011 +11101100000000001110101100000000 +00111110110000000000111110110000 +00000001111011000000000011111011 +00000000001111101100000000001101 +10110000000000111110000000000010 +00010000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11111111000000000011111111000000 +00001111111100000000001011111100 +00000000111111110000001000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000011000001110100000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11101111100000000011101111100000 +00001111111110000000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +00111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111111000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001110111000000000 +10111011100000000000111011100000 +00001011101110000000001011101110 +00000000101110111000000000101110 +11100000000010111011100000010010 +10101110000000001011101110000000 +00101110111000000000111010111000 +00000010111011100000000010111011 +10000000001011101110000000001011 +10111000000000101111000000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10110011000000000110100011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +00001100000010001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101111001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +10101100000000001011101100000000 +00101110110000000000100110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111000000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000101011110110000000000 +11101011000000000011101011000000 +00001111101100000000001011101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +00101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100010000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111011110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111111100000000100 +01000000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011000000000011011011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010010110000000100 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010110011110100000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000100100110000000000101100 +11000000000010110011000100000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101111000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00100000000000000001111000000000 +10110111100000000010110111100000 +00001011011110000000001011011110 +00000000101101111000000000101101 +11100001000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101110110000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01001000000010000000110000000000 +11110011000000000011110011000000 +00001111001100000000001111001100 +00000000110100110000000000111100 +11000000000011110011000000000011 +11001100010000001111001100000000 +00111100110000000000111100110000 +00000011110011000000000011110011 +00000000001111001100000000001111 +00110000000000111101001000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000111001011110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000000 +11111100000100001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001011111100000000001111 +11110000000000111101000000000110 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000101100001000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000100011001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101111001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000000001001111000000000 +10100111100000000010110111100000 +00001011011110000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101100100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101101101000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11101010000000000010111010000000 +00001011101000000000001111101000 +00000000111110100000000000111110 +10000000000011111010000000000011 +11101000000001001111101000000010 +00111110100000000000111110100000 +00000011111010000000000011111010 +00000000001111101000000000001111 +10100000000000101111101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111101001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001100000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000100000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101110000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11111000000001000111111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111010000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000111 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111011110010000000001 +11111001000000000111111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000001111110111000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000001011110010000000000 +11101001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111101000001000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001110 +10010000000000111000111000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000100001110000000000000 +10111000000000000010111000000000 +00001011100000000000001011100000 +00000000101110000000000000101110 +00000000000010111000000000000010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000010111000000000000010111000 +00000000001011100000000000001011 +10000000000000101100011000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00001000000001011100010000000000 +10100001000000000010110001000000 +00001011000100000000001010000100 +00000000101100010000000000101100 +01000000000010110001000000100010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001010 +00010000000000101001001000000001 +00100000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000010000 +10111001000001000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000001000010 +11100100000000001011100100000100 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000010000101100011000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011110010000000000 +11101001000000000011111001000000 +00001011100100000000001110100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001110 +10010000000000111010100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000000011010010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000100111111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111101101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11101000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000111111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010010100000000000 +10111010000000000010111010000000 +00001011101000000000001011101000 +00000000101110100000000000101110 +10000000000010111110110100000010 +11101000000000001011101000000000 +00101110100000000000100110100000 +00000010111010000000000011101010 +00000000001011101000000000001011 +10100000000000101100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10100011000000000010110011000000 +00001011001100000000011011001100 +00000000101100110000000000101100 +11000000000010110011110000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100101000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000000010001110000010000 +10110111000001000010110111000000 +00001011011100000000001011011100 +00000100101101110000000000101101 +11000000000010110110010000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010100111 +00000000001011011100000000001011 +01110000000000101100100000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001111000000000 +11100111100000000011110111100000 +00001111011110000000001111011110 +00000000111101111000000000111101 +11100000000010110101100000000011 +11011110000000001111011110000000 +00111101111000000000111101111000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01111000000000111100101000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000110110110000 +00000011111011000000000011101011 +00000000001111101100000000001111 +10110000000000111100001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000000011111111000000000 +11111111100000010011111111100000 +01001111111110000010001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110001000000 +11110111000100000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111010000000010 +11011100000000001110011100000000 +00111001110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101110101000000010 +00100000000000000000000000000000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101001110000000000100101 +11000000000010100111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101100000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00100000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001010001100000000 +00101000110000000000100100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101101000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000101011010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000110110 +11000000000011101000000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110101100000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11101011000000000011111011000000 +00001111101100000000001111101100 +00000100111110110000000000111110 +11000000000011111000000000000011 +11101100000010001111101100000000 +00111110110000000001111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110100000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000001000100001111110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111011110000000000111111 +11000000000011111101000000000011 +11111100000000001111111100000000 +00111111110000000001111111110000 +00100011111111000000000011111111 +00000000001111111100000001001111 +11110000000100111100000101000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000001000001000110110000000000 +11101011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111001110000000010 +11101100000000001001101100000000 +00101110110000000001101110110000 +00000010111011000000000011101011 +00000000001011101100000000001011 +10110000000000101110000001000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101010 +11000000000010111001100000000110 +11101100000000001011101100000001 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101110000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10100011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110001000000000110 +11001100000000001001001100000000 +00101100110000000000101100110000 +00000010110011000000000010100011 +00000000001011001100000000001011 +00110000000000101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000011010110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111010 +11000000000010111001000000000011 +11101100000000001111101100000000 +00111110110000000000101110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100000000100110 +00010000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111101000000000000 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000010001111111100000000001111 +11110000000000111110100000000011 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11111111100000000011111111100000 +00001111111110000000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11001000000000110011000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001110111000000000 +10111011100000000010111011100000 +00001011101110000000001011101110 +00000000101110111000000000101110 +11100000000010111011100000000010 +11101110000000001011101110000000 +00101110111000000000101110111000 +00000010111011100000000010111011 +10000000001011101110000000001011 +10001000000000100011000000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10100011000000000010110011000000 +00001011001100000000001010001100 +00000000101100110000000000101000 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010100011000000000010110011 +00000000001011001100000000001011 +10000000000000100011001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010110000000000 +10111011000000000010111011000000 +00001011101100000001001011101100 +00000000101110110000000000100110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000010100011000000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000101011110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10100100100000110000000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011011111000000000011111111 +00000000001111111100000000001111 +11000000000000111111100000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000100111110110000001000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10100000000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000001001011 +00110000000000101111011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10110011000000000010110011000000 +00001001001100000000001001001100 +00000000101100110000000000100100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010010011000000000010110011 +00000000001011001100000000001011 +00010000000000101111101000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00100000000000010001111000000000 +10110111100000000010110111100000 +00001011011110000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01011000000000101111110000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01001000000010000000110000000000 +11110011000000000011110011000000 +00001101001100000000001111001100 +00000000111100110000000000111100 +11000000000011110011000000000011 +11001100000000001111001100000000 +00111100110000000000111100110000 +00000011110011000000000011110011 +00000000001111001100000000001111 +00000000000000111101101000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000111011011110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111101000000000110 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000011011110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111010110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000000011001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01010000000000101111001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000000001001111000000000 +10110111100000000010110111100000 +00001011011110000000001011011110 +00000000101001111000000000101001 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01101000000000101100100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000001011011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101101001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11111010000000000011111010000000 +00001111101000000000001111101000 +00000000111010100000000000111110 +10000000000011111010000000000011 +11101000000000001111101000000000 +00111110100000000000111110100000 +00000011111010000000000011111010 +00000000001111101000000000001111 +11100000100000111111101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111101001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000110110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000011 +11100100000000001011100100000000 +00101110010000000000100110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101110000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010101001000000000010111001 +00000000001011100100000000011011 +10010000000000101100011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000100100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +00100000000000000000000000000000 +00000000000000000000000000000000 +10111000000001010110000000000000 +11111000000000000010111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011101000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000111 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000101011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +10100100000000001111100100000000 +00111110010000000000110110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +11010000000000111110111000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000001011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +00010000000000111110111000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000100001110000000000000 +10111000000000000010111000000000 +00001011100000000000001011100000 +00000000101110000000000000101110 +00000000000010111000000000000010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000010111000000000000010111000 +00000000001011100000000000001011 +10000000000000101100011000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000001011100010000000000 +10110001000000000010100001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101101001000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000011011 +10010000100000101100011000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010100001000111110100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000000011010010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10011010000000111101101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000100000000110000101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010010100000000000 +10111010000000000010111010000000 +00001011101000000000001011101000 +00000000101110100000000000101110 +10000000000010111010000000000010 +11101000000000001011101000000000 +00101110100000000000101110100000 +00000010111010000000000010111010 +00000000001011101000000000001011 +10100000000000100000001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000100100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000001001011 +00110000000000100100001000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000000010001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +11111000000000100100100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001111000000000 +11110111100000000011110111100000 +00001111011110000000001111011110 +00000000111101111000000000111101 +11100000000011110111100000000011 +11011110000000001111011110000000 +00111101111000000000111101111000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01111000000000110100101000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111011000000000011111011000001 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000010001111 +10110000000010111000001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000001011111111000000000 +11111111100000000011111111100000 +00001111111110000000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111101100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000100001011011100000000001011 +01110010000000101110101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101100010010000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00100000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000011011 +00111100000000101101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000101011010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10111000100000111110101000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000001001111101100000000001111 +10110000000000111110110000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +00000001000100001111110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000100000111110000001000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000001000001000110110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000001000010111011 +00000000001011101100000101001011 +10110000001000101110000101000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000000000010111011000000 +00001011101100000000001001101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101110000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000011010110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110000000100110 +00000000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000010100111110100000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11101111100000000011111111100000 +00001111111110010000001101110000 +10000000110011111000000000111011 +11100000000011111111000000000011 +00110010000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111111000000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001110111000000000 +11111011100000000011101011100000 +00001011101100000000001000101011 +00000000100010111000000000111010 +11100000000010111011110100000010 +00100000000000001011101110000000 +00101110111000000000101110111000 +00000010111011100000000010111011 +10000000001011101110000000001011 +10111000000000101110000000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10110011000000000010110011000000 +00001011001100000000101000000000 +01000100100000110000000001101100 +11000000000010110011000000000110 +00000100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101110001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010110000000000 +10111011000000000010111011000000 +00001011001100000000001000100001 +00000000100010110000000000101110 +11000000000010111011000001000010 +00100110001000001011101100000000 +00101110110000000000101110111000 +10000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111000000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000101011110110000000000 +11101011000000000011111011000000 +00001111101100000000001101100110 +01000010110010110000000000111110 +11000000000011111011000000000011 +00100010000000001111101100000000 +00111110110000000000111110111000 +00100011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11101111000000000011101111000000 +00001111111100000000000111111000 +00000000111111110000000000111011 +11000000000011111111000001001011 +11110000000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111111100000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011000000000011111011000000 +00001111101100000000001110001100 +00000000111110110000000000111110 +11000000000011111011000110000011 +11101101000000001100101100000000 +00111110110001000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111101000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10111011000000000010111011000000 +00001011101111110000001000101100 +00000000101110110000000000101110 +11000000000010110111000000000010 +11101100000000001010101100000000 +00101110111101000000101110010000 +00000010111011000000000010111011 +00000100001011101100000000001011 +10110000000000101111001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10110011000000000010110011000000 +00001011001100000000001000000000 +00001000101100110000000000101100 +11000000000010110011110000000010 +11000000000000001000001100000000 +00101100111000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101111000000000100 +00000000000000000000000000000000 +00000000000000000000000000000000 +00100000000000000001111000000000 +10110111100000000010110111100000 +00001011011110000100101000011110 +00000000101101111000000000100101 +11100000000010110111100000000010 +11010010000000001010011110000000 +00101101111000000000101101110001 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101100100000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01001000000010000000110000000000 +11110011000000000011110011000000 +00001111101100000001001110000000 +00000000111100110000000000111100 +11000000000011110011000000000011 +11100000000000001100001100000000 +00111100110000000000111100110000 +00000111110011000000000011110011 +00000000001111001100000000001111 +00110000000000111101001000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000111001011110000000000 +11111111000000000011111111000000 +00001111111100000000001111111000 +00000000111111110000000000111111 +11000000000011111111000010000011 +11110100000000011111111100000000 +00111111110000000000111111110001 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111101000000000110 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011110110000000000 +11111011000000000011111011000000 +00001111101100000000101100100100 +00000000110010110000000000111110 +11000000000011111011100000000011 +00100000000000001111101100000000 +00111100111000000000110010110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000000011001110000000000 +10110111000000000010110111000000 +00001011111100000000001000011100 +00000000110101110000000001101101 +11000000000010110111001000000010 +00011000000000001011011100000000 +00101101110000000000110101100000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101101001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000000001001111000000000 +10110111100000000010110111100000 +00001011011110000000001000000110 +00000000100001111000000000101001 +11100000000010110011101000000010 +00011010000000001011011110000000 +00101101111000000000100001111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101100100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110011000000000010110011000000 +00011011001100000000001000001110 +00000000100100110000000000101100 +11000000000010110011000001000010 +00101100000000001011001100000000 +00101100110000000000100100111101 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101101101000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11111010000000000011111010000000 +00001111101000000000001100111011 +00000000110010100000000000111110 +10000000000011111010000000000011 +00111010100000001111101000000000 +00111110100000000000110011100101 +00000011111010000000010011111010 +00000100001111101000000000001111 +10100000000000111111101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +01100000111110000000000000111110 +00000000000011111000000000001011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111101001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000000000011111001000000 +00001111100100000000001100000100 +00000000110010010000000000111110 +01000000000111111001100000000011 +11100110000000001100100100000000 +00111110010000000000111110010000 +00100011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000000000010111001000000 +00001011100110010000101000100100 +00000000101010010000000000101110 +01000000000110111001010000000010 +11100110000000001000100100000000 +00101110010100000000101110010000 +00000010111001000000000011111001 +00000000001011100100000000001011 +10010000000000101110000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010111001000000 +00001011000100001000001000100100 +00000000100010010000000000101110 +01000000010010111001000101000010 +11100100010000001000100100000000 +01101110010000100000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001000000000010110001000000 +00001011000100000000001000000100 +10000000101000010000000000101100 +01000000000010110001001000000010 +11000100000000101000000100000000 +01101100010000000000100100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000001000110000000000000 +11111000000000000011111000000000 +00001111100001010000001100100000 +00000000110010000000010000111110 +00000000000010111010000000000011 +11100001010010001100100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000111 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111001110010000000000 +11111001000000000011111001000000 +00001111100100000000001111110100 +01000000111110010000000000111110 +01000000000011111001000101000011 +11110100000000001111100100000000 +00111110010000000000111111010000 +00000011111001000000000011101001 +00000000001111100100000000001111 +10010000000000111110111000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000000011110010000000000 +11111001000000000011111001000000 +00001111110100000000001111100100 +00000000110110010000000000111110 +01000000000011111101000000001011 +01110100000000001100100100000000 +00111111010000000000110010010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100111000000101 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000100001110000000000000 +10111000000000000010111000000000 +00001110000000000000001011100000 +00000000110110000000000000101110 +00000000000010111000000000000010 +00100010100000001101100000000000 +00101110000000000000110110000000 +00000011101000000000000010111000 +00000000001011100000000000001011 +10000000000000101100011000000010 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000001011100010000000000 +10110001000000000010100001000000 +00001011000100000000011011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +00001110001000001000000100000000 +00101100010000000000100000010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101101001000000001 +01100000000000000000000000000000 +00000000000000000000000000000000 +00011000000100011010010000000000 +10111001000000000010111001000000 +00001010100100000000001011100100 +00000000100110010000000000101110 +01000000000010111001000000000010 +00100100100000001001100100000100 +00101110010000000000100110010100 +00000010101001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011110010000000000 +11111001000000000011101001000000 +00001111100100000000001111100111 +00100000111110010000000000111110 +01000000000011111001000000000011 +01100100000000001100100100000000 +00111100010000000000110010010000 +00000011111001000000010011111001 +00000000001111100100000000001111 +10010000000000111110100000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000000011010010000000000 +11111001000000000011111001000000 +00001110100100000000001111100111 +00000000111010010000000000111110 +01000000000011111001000010000011 +11100100000000001111100100000000 +00111110010000000000111110010100 +00000001111001000000000011111001 +00000000001011100100000000001111 +10010000000000111101101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000000000011111000000000 +00001111100000100000001100000000 +00000000110110000000000000111110 +00000000000111111000000100000011 +11100000000000001100100000000000 +00111110000010000000111110000100 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010010100000000000 +10111010000000000010111010000000 +00001011111011000000101000101000 +00000000111110100000000000111010 +10000000000010110110000000000010 +01101000000000101000101000000000 +00101111100110000000111110100000 +00000010111010000000000011101010 +00000000001011101000000000001011 +10100000000000101100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110011000000000010110011000000 +00001011001110000000001001001100 +00000000100000110000000000101100 +11000000000010110011110000000010 +11101100000000001000001100000000 +00101100001000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100001000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000000010001110000000000 +10110111000000000010110111000000 +00001011010110001000001001001100 +00000000101001110000000000100001 +11000000000010110111000000000110 +01011100000000001000011100000000 +00101101100000000000101001110000 +00000010110111000000000010100111 +00000000001011011100000000001011 +01110000000000101100100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001111000000000 +11110111100000000011110111100000 +00001111011110000000001101011110 +00000100100001111000000000111101 +11100000000010110110100000000011 +11110110000000001100011110000000 +00111101001000000000101101111000 +00000011110111100000000011110111 +10000000011111011110000000001111 +01111000000000111100101000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111011000000000011111011000000 +00001111101000000000001110101100 +00000000111110110000000000111010 +11000000000011111011000001000011 +11100100000000001111101100000000 +00111110100000000000111110110000 +00000011111011000000000011101011 +00000000001111101100000000001111 +10110000000000111100001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000001011111111000000000 +11111111100000000011111111100000 +00001111111110000000001100111110 +00000000111111111000000000111111 +11100000000011111110100000000011 +00111110000000001100111110000000 +00111111001000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111101100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110000000000 +10110111000000000011110111000000 +00001011110000000000011000011100 +00000000101101110000000000101101 +11000000000010110110000000000011 +01011100000000001101011100000000 +00101101000000000000111001110001 +10000011110111000000000010110111 +00000000001011011100000000001011 +01110000000000101110101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110111000000000010110111000000 +00001011010100000000001000011100 +00000000101101110000000000101101 +11000000000010110110000000000010 +00110100000000001001011100000000 +00101101010000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101100000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00100000000101001100110000000000 +10110011000000000010100011000000 +00001011100000000000001000001111 +01001000101100110000000000101100 +11000000000010110010000000000010 +01100101001000001001001100000000 +00101100000000000000101100110000 +00000010100011000000010010110011 +00000000001011001100000000001011 +00110000000000101101000100000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000101011010110000000000 +11111011000000000010111011000000 +00001111101000000000101100101100 +00001000111110110000000000111110 +11000000000011111001000000000011 +00101101000000001101101100000000 +00111110000000000000111110111000 +00000010111011000001000011111011 +00000000001111101100000000001111 +10110000000000111110101100000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11111011000000000011111011000000 +00001111101001000000001111101100 +10000100111110110000000000111110 +11000000000011111011000000000011 +11101110000000001111101100000000 +00111110000000000000111010110010 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110100000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +00000001000100001111110000000000 +11111111000000000011111111000000 +00001111111111000000001110011100 +00000000110011110000000000111111 +11000000000011111110000000000011 +00110100000000001100111100000000 +00111111000000000000111111110000 +00000011001111000000000011111111 +00000000001111111100000000001111 +11110000000000111100000101000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000001000001000110110000000000 +10111011000000000010111011000000 +00001011101000000000101000101100 +00000000100010110000000000101110 +11000000000010110011100000000011 +01110100000000001000101100000000 +00101110001000000000101100110000 +00000011111011000000000010111011 +00000000001011101100000000001011 +10110000000000101110000001000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000000000010111011000000 +00001011100101000000001000101100 +00000000100010110000000000101110 +11000000000010111010000100000010 +00100110000000001000101100000000 +00101110000001000000101110110000 +00000010001011000000000010111011 +00000000001011101100000000001011 +10110000000000101110000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10110011000000000010110011000000 +00001001000000000000001000001100 +00000010100000110000000000101100 +11000000000010110010000000000010 +01000100000000001000001100000000 +00101100000000000000101110110000 +00000010010011000000000010110011 +00000000001011001100000000001011 +00110000000000101100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000011010110110000000000 +11111011000000000010111011000000 +00001111100100000000001110101100 +00000000110010110000000000101110 +11000000000011111010000000000011 +00101100000000001100101100000000 +00111110010000000000111110110000 +00000011001011000000000011111011 +00000000001111101100000000001111 +10110000000000111100000000000110 +00010000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11111111000000000011111111000000 +00001111110000000000001111111100 +00000000111111110000000000111111 +11000000000011110110000000000011 +11011100000000001111111100000000 +00111111000000000100111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111110100000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11111111100000000011111111100000 +00001111111110000000001110111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011001111 +10000000001111111110000000001111 +11111000000000111011000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110111000000000 +10111011100000000010111011100000 +00001011101110000000001100101110 +00000000101110111000000000101110 +11100000000010111011100000000010 +11101110000000001011101110000000 +00101110111000000000101110111000 +00000010111011100000000011011011 +10000000001011101110000000001110 +10111000000000101111000000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10100011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00100100110000000000101100110000 +00000010110011000000000010000011 +00000000001011001100000000001011 +00110000000000101111001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010110000000000 +10111011000000000010111011000000 +00001011101100000000001010101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010011011 +00000000001011101100000000001010 +10110000000000101111100000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000001011110110000000000 +11111011000000000011111011000000 +00001111001100000000001111101100 +00000000111110110000000000111110 +11000000000010111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011110011000000000011001011 +00000000001111101100000000001111 +10110000000000111100100000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000100011011110000000000 +11111111000000000011111111000000 +00001111111100000000001101111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000011111111100000000001111 +11110000000000111111100000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011000000000011101011000000 +00001111101100000000001100101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011101011000100000011111011 +00000000001111101100000000001111 +10110000000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10111011000000000010111011000000 +00001011101100000000001000101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101110001100001011 +10110000000000101111000000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11000000000001000000110000000000 +10110011000000000010100011000000 +00001011001110010000001001001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +10001100000000001011001100000000 +00101100110000000000101100110000 +00000010100011110010000010110011 +00000000001011001111001000001011 +00110000000000101111000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00100000000000000001111000000000 +10110111100000000010110111100000 +00001011011100000000001001011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000011011 +01111000000000001111111000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01001000000110000000110000000000 +11110011000000000011100011000000 +00001111001100010000001101001100 +00000000111100110000000000111100 +11000000000011110011000000000011 +11001100000000001111001100000000 +00111100110000000000111100110000 +00000011100011000000000011110011 +00000000001111001100010000001111 +00110000000000111101101000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000111001011110000000000 +11111111000000000011111111000000 +00001111011100100000001110111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000100011111 +11110000000000111101000000000010 +00100000000000000000000000000000 +00000000000000000000000000000000 +00001000000101011110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111010110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100101000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000010011001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101111001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +00100000000000001001111000000000 +10110111100000000010110111100000 +00001011011110000000011011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101001111000000000101101111000 +00000010110111100000000110110111 +10000000001011011110000000001011 +01111000000000101100000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +11101000000001001100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000001011011001100000000001011 +00110000000000101101001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101001010100000000000 +11111010000000000011111010000000 +00001111101000000000001111101000 +00000000111110100000000000111110 +10000000000011111010000000000011 +11101000000000001111101000000000 +00111010100000000000111110100000 +00000011110010000000000011111010 +00000000001111101000000000001111 +10100000000000111111101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001010000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111101001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10001000000100001010010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011011001 +00000000001111100100010000001111 +10010000000000111100001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000010010000000000 +10111001000000000010111001000000 +00001011100100100000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001001000000010001001 +00000000001011100110000000001011 +10010000000000101110000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010101001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010011001 +00000000001011100100000000001011 +10010000000000101100011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010000001 +00000000001011001100000000001011 +00010000000000101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000111010110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011101000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011011000 +00000000001111100000000000001111 +10000000000000111110111000000111 +01010000000000000000000000000000 +00000000000000000000000000000000 +10111000000111011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110111100000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000101011110010000000000 +11111001000000000011111001000000 +00001111110100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111101000000000011111001 +00000000001111110100000000001111 +10010000000100111110111000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000000001010000000000000 +10111000000000000011101000000000 +00001011100000000000001011100000 +00000000101110000000000000101110 +00000000000010111000000000000010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000010111000000000000010111000 +00000000001011100000000000001011 +10000000000000101100011000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +01001000000001001000010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101000010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101101001000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00011000000101001010010000000000 +10111001000000000010101001000000 +10001011101100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000001001011100100000000001011 +10010000000000101100011000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101001110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111010010000000000111110010000 +00000011111001000000000011111001 +00000000011111100100000000001111 +10010000000000111110000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01101000000000001010010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100001000001111 +10010000000000111101101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000000000011101000000000 +00001111100000001000001110100000 +00000000111110000000000000111110 +00000000000011101000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000010000011111000 +00000000001111100000000000001111 +10000000000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000010100000000000 +10111010000000000010111010000000 +00001011111010000000001011101000 +00000000101110100000000000101110 +10000000000010111010000000000010 +11101000000000001011101000000000 +00101110100000000000101110100000 +00000010111110000000000010111010 +00000000001011111001000000000011 +10100000000000101100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001010100110000000000 +10110011000000000010100011000000 +00001011001100000000001010001100 +00000000101100110000000000101100 +11000000000010100011000000000010 +10001100000000001011001100000000 +00101000110000000000101100110000 +00000010110011100000000010110011 +00000000001011001110000000001011 +00110000000000101100001000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00100000000000010001110000000000 +10110111000000000010110111000000 +00001011011100001000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111010000000110110111 +00000000001011010101000000001011 +01110000000000101100000000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00101000000110000001111000000000 +11110111100000000011100111100000 +00001111011110000000001110011110 +00000000111101111000000000111101 +11100000000011100111100000000011 +11011110000000001111011110000000 +00111101111000000000111101111000 +00000011110111100000000011110111 +10000000001111011110000010001111 +01111000001000111100101000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111010000000000011111011 +00000000001111100000000000001111 +10110000000000111100001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +01100000000001001011111000000000 +11111111100000000011111111100000 +00001111111010010000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111110100100000011111111 +10000000001111111010000000001100 +11111000000000111101000000000001 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000000001001110000000000 +10110111000000000010110111000000 +00001011010000000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110101000000000011100111 +00000000001011011100000000001101 +01110000000000101110101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110111000000000010110111000000 +00001011011000000000011011011100 +00000000101001110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110110000000000110110111 +00000000001011010000000000001000 +01110000000000101100010000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01000000000101001000110000000000 +10110011000000000010110011000000 +00001011000000000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000110110000000000000010100011 +00000000001011000000000000011001 +00110000000000101101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011010110000000000 +11111011000000000011111011000000 +00001111100100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111001000000000011111011 +00000000001111001100000000001100 +10110000000000111110101000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10100000000100001110110000000000 +11111011000000000011111011000000 +00001111100100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000111101011 +00000010001111100100000000001111 +10110000000000111110110000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +00000001000100001111110000000000 +11111111000000000011111111000000 +00001111110000000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111101100000000011111111 +00000000001111111100000000101100 +11110000000000111110000001000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000001000001000110110000000000 +10111011000000000010111011000000 +00001011100011000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111010100000000010111011 +00000000001011100000000000001000 +10110000000000101110010001100000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010110110000000000 +10111011000000000010111011000000 +00001011101100010000001011101100 +00000000101110110000000000101110 +11000000000010101011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111000000100000010111011 +00000000001011101000000001001000 +10110000000100101110000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10110011000000000010110011000000 +00001011000100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110001000000000010110011 +00000000001011001100000000001000 +00110000000000101100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000110000110110000000000 +11111011000000000011111011000000 +00001111101000000000001111101100 +00000000111110110000000000111110 +11000000000011101011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111000000000000011111011 +00000000001111100000000000001100 +10110000000000101110100000000110 +00010000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011011110000000000 +11111111000000000011111111000000 +00001111110000000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111100000000000011111111 +00000000001111010000000000001111 +11110000000000111110000000100110 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11111111100000000011111111100000 +00001111111110000000001111111110 +00000000111111111000000000111111 +11100000000011111110100000000011 +10111100000000101100110110000000 +00110011111000000000111111111000 +00000011001111100000000011111111 +10000000001111111110000000001111 +11111000000000111111000000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001110111000000000 +10111011100000000010111011100000 +00001011101110000100001011101110 +00011000101110111000001000101110 +11100000000010111010100000000010 +00111110000000101000100100000000 +00100010111000010000101110111000 +00000011011011100000000010111011 +10000000001011101110000000001011 +10111000000000101110000000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010111010000000000010 +10000100000000001010001100000000 +00100000110000000000101100110000 +00000010000011000000000010110011 +00000000001011001100000000001011 +00110000000000101110001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111010100010010010 +00100100000000001000100100000000 +00100010110000000000101110110000 +00000010011011000000000010111011 +00000000001011101100000000001011 +10110000000000101111000000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000101011110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000100111110110000000000111110 +11000000010011111010110000000011 +10111100000000101110100100000000 +00110010110000000000111100110000 +00100011001011000000000011111011 +00000000001111101100000000001111 +10110000000000111101000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000100111 +11000000000011111110000000000011 +11101100011000101111111100000000 +10111111110000000000111111110000 +00010011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111111100000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111010010000000011 +11000100000000001100101100000000 +00111110110000000000110110110010 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111101000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10111011000000000010111011000000 +00001011101100000100001011101100 +00000000101110110000000000101110 +11000000000010110010000000000010 +11100101001000101000101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111001000000100 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10110011000000000010110011000000 +00001001001100000000001011001100 +00000000101100110000000000100100 +11000000000010110000100100000010 +11000100000000101000100100000000 +00101100110000000000100100110100 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101111100000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00100000000000010001111000000000 +10110111100000000010110111100000 +00001001011110000000001011011110 +00000100101101111000000000101101 +11100000000010110100100000000010 +11010110010000001000010110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000000011011110000000001011 +01111000000000101100100000000100 +00010000000000000000000000000000 +00000000000000000000000000000000 +01001000000010000000110000000000 +11110011000000000011110011000000 +00001101001100000000001111001100 +00000000111100110000000000111100 +11000000000011110010000000000011 +11001100000000001100001100000000 +00111100110000000000110100110000 +00000011110011000000000011110011 +00000000001111001100000000001111 +00110000000000111101101000000010 +00010000000000000000000000000000 +00000000000000000000000000000000 +01000000000111011011110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111100000100000011 +11111111000000001111110100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111101000000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111001000000000011 +11100101000000001110100100000000 +00111110110000000000111100111000 +00000011001011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000100011001110000000000 +10110111000000000010110111000000 +00001011011100000001001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11010100000000001000011100000000 +00101101110000000000101101110000 +00000011010111000000000010110111 +00000000001011011100000000001011 +01110000000000101101001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000000001001111000000000 +10110111100000000010110111100000 +00001011011110000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001010011111000000 +00101101111000000000101101111000 +00000010000111100000000010110111 +10000000001011011110000000001011 +01111000000000101100100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000111010010 +11001100000000001000001110000000 +00101100110000000000101100110000 +00000010010011000000000010110011 +00000000001011001100000000001011 +00110000000000101101001000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11111010000000000011111010000000 +00001111101000000000001111101000 +00000000111110100000000000111110 +10000000000011110110100000000011 +11101000000000001110101000000001 +00111110100000010000111110100000 +00000011001010000000000011111010 +00000000001111101000000000001111 +10100000000000111111101100000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000100 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111101001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001110001000011 +00100100000000001100100100000000 +00111110010000000000111110011001 +00000000111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001100000001010 +00000100000000001000100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101110000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +00100110001000101000100100000001 +00101110010000010000101110010000 +10000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100111000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001000000000010010001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +00000100100000001000000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100101000000101 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +00100000000000101100100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000010011111101000001000011 +11010100010000101111110100101000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001101100100000000001111 +10010000000000111110011000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000001011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111101000000000011 +10110110000000101100100100000000 +00110010010000000000111111010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100011000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000100001110000000000000 +10111000000000000010111000000000 +00001011100000000000001011100000 +00000000101110000000000000101110 +00000000000010111000000000000010 +00100000000000001000100010100000 +00110110000000010000101110000000 +00000000111000000000000010111000 +00000000001011100000000000001011 +10000000000000101100111000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000001011100010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101000010000000000101100 +01000000000010111001000000000010 +10000101000000001000100100001000 +00100000010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101101001000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001001000000010 +00100100100000001000100100000100 +00100110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011110010000000000 +11111001000000000011111001000000 +00001111100100000000001011100100 +00000000111010010000000000111110 +01000000000011111001100000000011 +10000100000000001100000110000000 +00110010010000000000111110010000 +01000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110100000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +00101000000000011010010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001100000000011 +11100110001000101111100100100000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111101001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +00100000000001001100100000000100 +00111110000000000000111110000001 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111100001000000100 +00000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010010100000000000 +10111010000000000010111010000000 +00001011101000000000001011101000 +00000000101110100000000000101110 +10000000000010110010100000000011 +01111001000001001010101000000000 +00101110100000000000101111101100 +00000010111010000000000010111010 +00000000001011101000000000001011 +10100000000000101100101000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110001000000000010 +00001000000000001000001100000000 +00101100110000000000101100101100 +10000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100101100000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000000010001110000000000 +10110111000000000010110111000000 +00001011011100000000001001011100 +00000000101101110000000000101101 +11000000000010111101010000000010 +01011001000000001010011100000000 +00101101110000000000101101100000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101110000000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001111000000000 +11110111100000000010110111100000 +00001111011110000000001111011110 +00000000111101111000000000111101 +11100000000011110101100000000011 +00011110000000001100011110000000 +00111101111000000000111101011000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01111000000000111110001000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111011000000000011111011000000 +00001111101100000100001111101100 +00000000111110110000000000111110 +11000000000011110001000000000011 +11000000000000001111101100000000 +00111110110000000000111110000000 +00000011111011000000000011111011 +00000000001101101100000000001111 +10110000000000111100001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000001011111111000000000 +11111111100000000011101111100000 +00001111111110000000001111111110 +00000000111111111000000000111111 +11100000000011111101100000000011 +10111010000000001100111110000000 +00111111111000000000111111001000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111100000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110000000000 +10110111000000000011100111000000 +00001011011100000000001111011100 +00000000101101110000000000111101 +11000000000010110101000000000010 +00011000010000001000011100000000 +00101101110000000000101101000000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101110101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010111111000000000010 +10010100000000001000011100001000 +00101101110000000000101101000000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101100000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00100000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001010001100 +00000000101100110000000000101000 +11000000000010110011100000000010 +00000000000000101000001110000000 +00101100110000000000101100000000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000101011010110000000000 +11111011000000000011111011000000 +00001111101100000000001011101100 +00000000111110110000000000101110 +11000000000011111011100010000011 +10000000000000101100111110000000 +00111110110000000000111110000000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110101000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11111011000000000011101011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111001000000100011 +01100000000000001111101100000000 +00111110110000000000111110000000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110000000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +00000001000100001111110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11100100000000001100111100000000 +00111111110000000000111111011000 +00000011111111000000000011111111 +00000000001101111100000000001111 +11110000000000111100100001000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000001000001000110110000000000 +10111011000000000010111011000000 +00001011101100000100001011101100 +00000000101110110000001000101110 +11000000000010111001100000010010 +11100010000000101000111100000000 +00101110110000000000101110001001 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101110100001000100 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000100000010 +11100010001000001000101100000000 +00101110110000000000101110000000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101110000000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10110011000000000010110011000000 +00001011001100000000001001001100 +00000000101100110000000000100100 +11000000000010010001000000000010 +11000000000000001000001100000000 +00101100110000000000101100000000 +00000010010011000000000010110011 +00000000001011001100000000001011 +00110000000000101100001000000101 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000011010110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000010011111011000000000011 +11100000000010001100101100000000 +00111110110000000000111110000000 +00000011111011000000000011111011 +00000000001101101100000000001111 +10110000000000111100000000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000001111110000000001111111 +11000000000011110111000000000011 +11110000000000001111111100000000 +00111111110000000000111111000000 +00000011111111000000000011111111 +00000000001111111100000000001101 +11110000000000111110100000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11111111100000000011111111100000 +00001111111110000000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111100 +10000000001111111110000000001111 +11111000000000111111000000000001 +01100000000000000000000000000000 +00000000000000000000000000000000 +10100000000100001110111000000000 +10111011100000000010111011100000 +00001011101110000000001011101110 +00000000101110111000000000101110 +11100000000010111011100000000010 +11101110000000001011101110000000 +00101110111000000000101110111000 +00000010111011100000000010111001 +10000000001011101110000000001011 +10111000000000101110100000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010100011000000000010110010 +00000000001011001100000000001011 +00110000000000101110001000000001 +00110000000000000000000000000000 +00000000000000000000000000000000 +11100000000101011010110000000000 +10111011000000000010111011000000 +00001011101100000100001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111100000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000100011110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111000 +10000000001111101100000000001111 +10110000000000111100000000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11111111000000000001111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111100 +10010000001111111100000000001111 +11110000000000111111100000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111001 +00000000001111101100000000001111 +10110000000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10111011000000000010111011000000 +00001011101100000000001110101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111001 +00000000001011101100000000001011 +10110000010000101111001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000000001 +10110011000000000010110011000000 +00001001001100000000001001001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010010000 +00000000001011001100000000001011 +00110000000000101111100000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00100000000000010001111000000100 +10110111100000000010110111100000 +00001011011110000000001010011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110101 +10000000001011011110000000001011 +01111000000000101101100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +01001000000010000000110000000000 +11110011000000000011110011000000 +00001111001100000000001111001100 +00000000111100110000000000111100 +11000000000011110011000000000011 +11001100000000001111001100000000 +00111100110000000000101100110000 +00000011110011000000000011110010 +00100000001111001100010000001111 +00110000000000111101001000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000011011011110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111101000000000010 +01100000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111010110000 +00000011111011000000000011111010 +00000000001111101100000000001111 +10110000000000111110001000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000100011001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110110 +00000000001011011100000000001011 +01110000000000101101001000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000000001001111000000000 +10110111100000000010110111100000 +00001011011110000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000010001101111000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +11000000001011001100000000001011 +00110000000000101101001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11111010000000000011111010000000 +00001111101000000000001111101000 +00000000111110100000000000111110 +10000000000011111010000000000011 +11101000000000001111101000000000 +00111110100000000000111110100000 +00000011111010000000000011111110 +11011000001111101000000000001111 +10100000000000111111101100000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111101001000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000100001110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101110000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000100011111101 +00000000001111100100000000001111 +10010000000000111110011000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000001011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110011000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000100001110000000000000 +10111000000000000010111000000000 +00001011100000000000001011100000 +00000000101110000000000000101110 +00000000000010111000000000000010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000010111000000000000010111000 +00000000001011100000000000001011 +10000000000000101100111000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000001011100010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00001100001011100100000000001011 +10010000000000101100011000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101001010010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +11000000001111100100000000001111 +10010000000000111110100000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000000001010010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00100000001111100100000000001111 +10010000000000111100101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000001000010100000000000 +10111010000000000010111010000000 +00001011101000000000001011101000 +00000000101110100000000000101110 +10000000000010111010000000000010 +11101000000000001011101000000000 +00101110100000000000101110100000 +00000010111010000000000010111010 +00000000001011101000000000001011 +10100000000000101100101000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100101000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00100000000000010001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000010001011 +01110000000000101100100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00101000000010000001111000000000 +11110111100000000011110111100000 +00001111011110000000001111011110 +00000000111101111000000000111101 +11100000000011110111100000000011 +11011110000000001111011110000000 +00111101111000000000111101111000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01111000000000111100101000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000001011111111000000000 +11111111100000000011111111100000 +00001111111110000000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011110111 +10000000001100111110000000001111 +11111000000100111101000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001101011100000000001011 +01110000000000101110101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010111111 +00000000001010011100000000001011 +01110000000000101100010000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01100000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00001000001011001100000000001011 +00110000000000101101100000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10101000000101011010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001110101100000000001111 +10110000000000111110101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001001101100000000000111 +10110000000000111110010000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +00000001000100001111110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001100111100000001001111 +11110000010100111110000001100100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000001000001000110110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010110011 +00000000001000101100000000001011 +10110000000000101110000101000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010110110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001000101100000001001011 +10110000010000101110000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00001000000000000000110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010111011 +00000000001000001100000000001011 +00110000000000101100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000010000110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001100101100000000001111 +10110000000000111110000000000010 +00010000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000101111111100000000001111 +11110000000000111110100000000010 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000000011111111000000000 +11111111100000000011111111100000 +00001111110110000001001101111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111111000000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110111000000000 +10111011100000000010111011100000 +00001011100110000000001000001100 +00100000101110111000000000101110 +11100000000010111011100000000010 +11101110000001001011101110000000 +00101110111000000000101110111000 +00000010111011100000000010111011 +10000000001011101110000000001011 +10111000000000101110000000000010 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10110011000000000010100011000000 +00001010001100000000001001001100 +10000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000001 +00101100110000000001101100110000 +00000010110011000000000010110011 +00000000001011001100000000001010 +00110000000000101010001000000001 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010110000000000 +10111011000000000010111011000000 +00001011101100001000001000101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111000000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +01000000000101011110110000000000 +11111011000000000011111011000000 +00001111101111000000001101101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100000000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11111111000000000011111111000000 +10001111111110100000001110111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00010011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111111100000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011000000000011111011000000 +00001111101110100010101100101100 +00100010110010110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10111011000000000010111011000000 +00001011001110000000001000101111 +00000000100010110000000000111110 +11000000000010111011000000000010 +11101100000010001011101100000000 +00101110110000000000101110110000 +00000011111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10110011000000000010110011000000 +00001011000001000000001000001101 +00000000100000110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101111000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00100000000000010001111000000000 +10110111100000000010110111100000 +00001011011010000000001000011110 +00100000100001111000000000101001 +11100000000010110111100000000010 +11011110000000011011011110000000 +00101101111000000000101101111000 +00000010100111100000000010110111 +10000000001011011110000000001011 +01111000000000101100100000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01001000000000000000110000000000 +11110011000000000011110011000000 +00001111000100000000001100001100 +00000000110000110000010001101100 +11000000000011110011000000000011 +11001100010000001111001100000000 +00111100110000000000111100110000 +00000010110011000000000011110011 +00000000001111001100000000001111 +00110000000000111101001000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000111011011110000000000 +11111111000000000011111111000000 +00001111011000000000001111111100 +01000000111111110000000000111111 +11000000000011111111000000000011 +11111100000100001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111101000000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011110110000000000 +11111011000000000011111011000000 +00001111001010000000001100001100 +00000000110010110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000100011001110000000000 +10110111000000000010110111000000 +00001011011100000000001101011100 +00000000101001110000000000111001 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101101001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000000001001111000000000 +10110111100000000010110111100000 +00001010011110000010001000011110 +00000000100001111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101100100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110011000000000010110011000000 +00001011001100100000101001001100 +00000000000000110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000100100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101101101000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11111010000000000011111010000000 +00001111111000001000001100101000 +00000010110010100000000000111110 +10000000000011111010000000000011 +11101000000000001111101000000000 +00111110100000000000111110100000 +00000011111010000000000011111010 +00000000001111101000000000001111 +10100000000000111111101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011111000000000 +10001111100001000000001111100000 +00000000111110000000000000111010 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111101001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100111 +00000000110010010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000000000010011001000000 +00001011100111001000001011100111 +00000000100010010000000000101110 +01000000000010111001000001000010 +11100100000000001011100100000000 +00101110010000000000100110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101110000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010011001000000 +00001011100110000000001011000101 +00000000100010010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001000000000010010001000000 +00001011000100000000001011000100 +00000010101000010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +00100000000000000000000000000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11111000000000000011011000000000 +00001111100000000000001111100001 +01000000110010000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000111 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111011110010000000000 +11111001000000000011011001000000 +00001111110100000000001111100100 +00000000110110010000000000111110 +01000000000011111001000000000010 +11100100000000001111100100000000 +00111110010000000000110110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110111100000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000001011110010000000000 +11101001000000000011111001000000 +00001111110100000000001111110100 +00000000110010010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100111000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000100001110000000000000 +10111000000000000010111000000000 +00001011100000000000001011100000 +00000010100010000000000000101110 +00000000000011111000000000000010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000010111000000000000010111000 +00000000001110100000000000001011 +10000000000000101100011000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000001011100010000000000 +10100001000000000010110001000000 +00001011000100000000001011000100 +00000000100100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101101001000000001 +01100000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10111001000000000010111001000000 +00001011100100100000001011000100 +00000000100110010000000000101110 +01000000000010101001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001010100100000000001011 +10010000000000101100011000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011110010000000000 +11101001000000000011111001000000 +00001111100101100000001111100100 +00000010110110010000000000111110 +01000000000010111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000000011010010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111010010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001110100100000000001111 +10010000000000111101101100000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000000000011111000000000 +00001111100001000000001111100000 +10000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000100 +00011110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010010100000000000 +10111010000000000010111010000000 +00001011111010001000001011111010 +10000000101110100000000000101110 +10000000000010111010000000000010 +11101000000000001011101000000000 +00101110100000000000101110100000 +00000010111010000000000010111010 +00000000001011101000000000001011 +10100000000000101100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110011000000000010110011000000 +00001011001101100000001011001110 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100001000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000000010001110000000000 +10110111000000000010110111000000 +00001011010100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101100100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001111000000000 +11110111100000000011110111100000 +00001111010110000000001111011110 +00000000111101111000000000111101 +11100000000011110111100000000011 +11011110000000001111011110000000 +00111101111000000000101101111000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01111000000000111100001000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111011000000000011111011000000 +00001111100100000000001111101000 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000101011111111000000000 +11111111100000000011111111100000 +00001111011110000000001100110110 +00000000110011111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111101100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110000000000 +10110111000000000010110111000000 +00001011011101000000001101011100 +00000000100001110000000000111101 +11000000000011110111000000000010 +11011100000000001011011100000000 +00111101110000000000111001110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101110101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110111000000000010110111000000 +00001010011000000000001001011000 +00000000100001110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001010 +01110000000000101100000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00100000000101001100110000000000 +10110011000000000010110011000000 +00001011001000010000101000001000 +00000000100000110000000000001000 +11000000000000100011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011010110000000000 +10111011000000000011111011000000 +00001111000100000000001001101000 +00000010110010110000000000101110 +11000000000010111011000000000011 +11101100000000001111101100000000 +00111110110000000000101110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11111011000000000011111011000000 +10001111100101100000001111101100 +00000000111110110000000000111110 +11000000000111111011000000000011 +11101100000001001111101100000000 +00111010110000000000111010110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110000000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +00000001000000001111110000000000 +11101111000000000011111111000000 +00001111110100000000001100110010 +00000000111111110000000000111111 +11000000000011111111000001000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111100000001000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000001000001000110110000000000 +10111011000000000010111011000000 +00001011100011000000001010101001 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000100001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101110000001000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000000000010111011000000 +00001011100110000000001000100101 +01000000101010110000000000101110 +11000000000010111011000000000110 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101110100000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10110011000000000010110011000000 +00001011000100000000101000001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100101000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000011010110110000000000 +11111011000000000011111011000000 +00001111100000000000001100000000 +00000000111010110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100000000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11111111000000000011111111000000 +00001111110000000000001110111000 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000001111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111110100000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000011011111111000000000 +11111111100000100011111111100000 +00001101111110000000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111111000000000001 +01100000000000000000000000000000 +00000000000000000000000000000000 +11100000000000001110111000000000 +10111011100000000010111011100000 +00001011101110000000001011101110 +00000000101110111000000000101110 +11100000000010111011100000000010 +11101110000000001011101110000000 +00101110111000000000101110111000 +00000010111011100000000010111011 +10000010001011101110000000001011 +10111000000000101111000000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +11001000000001011100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001001001100000000 +00101100110000000000101100110000 +00000010100011000000000010110011 +00000000001011001100000000001011 +00110000000000101111001000000001 +00110000000000000000000000000000 +00000000000000000000000000000000 +11100000000101011010110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111000000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000101011110110000000000 +11111011000000000011111011000000 +00001101101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000100001111 +10110000000000111100000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000010000 +11111111000000000011111111000000 +00000111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000001000111111100000000100 +01000000000000000000000000000000 +00000000000000000000000000000000 +01010100000100001010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000110110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000001000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010010011000000000010110011 +00000000001011001100000000001001 +00110000000000101111000100000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +10110000000000010001111000000000 +10110111100000000010110111100000 +00001011011110000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101111111000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01001000000000000000110000000000 +11110011000000000011110011000000 +00001111001100000000001111001100 +00000000111100110000000000111100 +11000000000011110011000000000011 +11001100000000001111001100000000 +00111100110000000000101100110000 +00000011110011000000000011110011 +00000000001111001100000000001111 +00110000000000111101001100000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000101011011110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111101000000000010 +00100000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111010110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11001000000100011001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000011110111000000000011110111 +00000000001011011100000000001111 +01110000000000111111001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001001111000000000 +10110111100000000010110111100000 +00001011011110000000001011011110 +00000000101001111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101100100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010100011000000000010100011 +00000000001011001100000000001010 +00110000000000101001101000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11111010000000000011111010000000 +00001111101000000000001111101000 +00000000111110100000000000111110 +10000000000011111010000000000011 +11101000000000001111101000000000 +00111110100000000000111110100000 +00000010111010000000000010111010 +00000000001011101000000000001011 +10100000000000101111101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111101001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10001000000100001110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000110110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000000011 +10010000000000101110000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010111001000000 +00001001100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +00100000000000000000000000000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000111 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000011111100100000000001111 +10010000000000111110111000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000011011110010000000000 +11111001000000000011111001000000 +00001111100100000000001110100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011101001000000000111111001 +00000000001111100100000000001111 +10010000000000111110111000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000000001110000000000000 +10111000000000000010111000000000 +00001011100000000000001011100000 +00000000111010000000000000101110 +00000000000010111000000000000010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000010111000000000000010111000 +00000000001011100000000000001111 +10000000000000111100011000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +01001000000001011100010000000000 +10110001000000000010110001000000 +00001011000100000000001010000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010100001000000000010110001 +00000000001011000100000000001011 +00010000000000101101001000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101010010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001010 +10010000000000101000011000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101001010010000000000 +11111001000000000011111001000000 +00001111100100000000001110100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011101001000000000010111001 +00000000001111100100000000001011 +10010000000000101110100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01101000000000001010010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111010010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111101101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000010001111100000000000001111 +10000000000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000001000010100000000000 +10111010000000000010111010000000 +00001011101000000000001011101000 +00000000101110100000000000101110 +10000000000010111010000000000011 +10101000000000001011101000000000 +00101110100000000000101110100000 +00000010111010000000000010111010 +00000000001011101000000000001011 +10100000000000101100001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100001100000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00100000000000010001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +10011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000100101100100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00101000000000000001111000000000 +11110111100000000010110111100000 +00001111011110000000001111011110 +00000000111101111000000000111101 +11100000000011110111100000000011 +11011110000000001111011110000000 +00111101111000000000111101111000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01111000000000111100101000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000101011010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +10101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000001011111111000000000 +11111111100000000011111111100000 +00001110111110000000001111111110 +00000000111011111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111101100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001111 +01110000000000101110101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110111000000000010110111000000 +00001010011100000000001011011100 +00000000101001110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101001110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101100010000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01100000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001010 +00110000000000101101001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000101011010110000000000 +11111011000000000011111011000000 +00001110101100000000001011101100 +00000000111010110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111010110000 +00000010111011000000000011111011 +00000000001111101100000000001011 +10110000000000111110101000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000010000111110110000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +00000001000100001111110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001101 +11110000000000111110000001000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000111110 +11000000000010111011000000000011 +10101100000000001011101100000000 +00101110110000000000101110110000 +00000011111011000000000010111011 +00000000001011101100000000001011 +10110000010000101110000001100000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010110110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101110000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00001000000000000000110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101000 +11000000000010110011000000000010 +10001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000010000110110000000000 +11111011000000000010111011000000 +00001111101100000000001111101100 +00000000111110110000000000101110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001101 +10110000000000111110000000000110 +00010000000000000000000000000000 +00000000000000000000000000000000 +10100000000110011111110000000000 +11111111000000000011111111000000 +00001111111100000000011111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011101111000000000011111111 +00000000001111111100000000001111 +11110000001000111110100000100010 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000000011111111000000000 +11111111100000000011111111100000 +00001101111110000000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111100000000001011111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111111000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110111000000000 +10111011100000000010111011100000 +00001011101110000000001011101110 +00000000101110111000000000101110 +11100000000010111011100000000010 +11111110000000001011101110000000 +00101110111000000000101110111000 +00000010011011100000000010111011 +10000000001011101110000000001011 +10111000000000101110000000000110 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10110011000000000010110011000001 +00001011001100000100001011001100 +00000000101100110000000000001000 +11000000000010110011000000000010 +11001100000000001001001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001010 +00110000000000101010001000000001 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11111100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111000000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +01000000000101011110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111010 +11000000000011111011000000000010 +11101100000000001111101100000000 +00111110110000011000111110110000 +00000001111011000000000011111011 +00000000001111101100000000001111 +10110000000000111101000000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011011111000000000011111111 +00000000001111111100000000001111 +11110000000000111111100000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011000000000011111011000000 +00011111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100001000001111101100000000 +00111110110000000000111110110000 +00000111111011000000000011111011 +00000000001111101100000000001111 +10110000000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10111011000000100010111011000001 +10001011101100000000001011101100 +00001000101110110000000000111110 +11000000000010111011000000000010 +11101111000000001110101100000000 +00101110110000000000101110110000 +00000011111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001101010000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101111000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00100000000000010001111000000000 +10110111100000000010110111100000 +10011011011110000010001011011110 +00000000101101111000000000101001 +11100000000010110111100000000010 +11011110000000001010011110000000 +00101101111000000000101101111000 +00000010100111100000000010110111 +10000000001011011110000000001011 +01111000000000101100100000000100 +00010000000000000000000000000000 +00000000000000000000000000000000 +01001000000000000000110000000000 +11110011000000000011110011000000 +00001011001100000000001111001100 +00000000111100110000000000101100 +11000000000011110011000000000011 +11001100000000001111001100000000 +00111100110000000000111100110000 +00000010110011000000000011110011 +00000000001111001100000000001111 +00110000000000111101001000000010 +00010000000000000000000000000000 +00000000000000000000000000000000 +01000000000111011011110000000000 +11111111000000000011111111000000 +00001111111100000010001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111110000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111101000000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011110110000000000 +11111011000000000011111011000000 +00001110101100000001001111101100 +00000000011110110000000000111110 +11000000000011111011000000000011 +11001100010000001100101100000000 +00111110110000000000101110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000100011001110000000000 +10110111000000000010110111000000 +00000011011100000000001011011100 +00000001101101110000000000111001 +11000000000010010111000000000010 +11011100100000001010011100000000 +00101101110000000000001101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101101001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000000001001111000000000 +10110111100000000010110111100000 +00001011011110000000001010011110 +00000001101001111000000000101101 +11100000000010110111100000000010 +11011110000000001000011110000000 +00101101111000000000101101111000 +00100010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101100100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000100001011001100 +00000000101100110000000000101100 +11000000000010010011000000000010 +11001100000000001010001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101101101000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11111010000000000011111010000000 +00001111101000000000001111101000 +00000000111110100000000000111110 +10000000000011111010000000000011 +11101000000000001100101000000000 +00111110100000000000111110100000 +00000011111010000000000011111010 +00000000001111101000000000001111 +10100000000000111111101000000100 +01010000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011111000000000 +00001111100000000001001111100000 +00000100111110000000000000111010 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111101001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001100100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000111010010000000000101110 +01000000000010111001000000010010 +11010101000000001000100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101110000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00011000000000010010010000000000 +10111001000000000010111001000000 +00011011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001000100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100111000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001000000000110110001000000 +00001011000100000000001011000100 +00000000101000010000000000101100 +01000000000010110001000000000010 +11000100001000101000000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100101000000101 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000011000010000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11101010100000001100100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000011011110010000000000 +11111001000000000011111001000000 +00001111100100000000001011100100 +00000000111010010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110011000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000001011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000101110010000000000111110 +01000000000011111001000000000011 +11110110000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100011000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000100001110000000000000 +10111000000000000010111000000000 +00001011100000000000001011100000 +00000000101110000000000000101110 +00000000000010111000000000000010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000110111000000000000010111000 +00000000001011100000000000001011 +10000000000000101100111000000110 +00100000000000000000000000000000 +00000000000000000000000000000000 +00001000000001011100010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000100101100010000000001101100 +01000000000010110001000000000010 +11000101000000001011000100000000 +00101100010000000000101100010000 +00000000110001000000000010110001 +00000000001011000100000000001010 +00010000000000101101001000000001 +00100000000000000000000000000000 +00000000000000000000000000000000 +00011000000100011010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000011011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011110010000001000 +11111001000000000011111001000000 +00001111100100000000001011100100 +00000001101110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000010111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110100000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +00101000010000011010010000000000 +11111001000000000011111001000000 +00001111100100000010001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111101001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000100000001011100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111100001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010010100000000000 +10111010000000000010111010000000 +00001011101000000001001011101000 +00000000111010100000000000101110 +10000000000010111010000000000010 +11111000000000001011101000000000 +00101110100000001000101110100000 +00000010111010000000000010111010 +00000000001011101000000000001011 +10100000000000101100101000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000001100110000000000001100 +11000000000010110011000000000010 +11000100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100101000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000000010001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11010101000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101110000000000100 +01000000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001111000000000 +11110111100000000011110111100000 +00001111011110000000001111011110 +00000000111101111000000001111101 +11100000010011110111100000100011 +11010110000000001111011110000000 +00111101111000000000111101111000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01111000000000111110001000000010 +00100000000000000000000000000000 +00000000000000000000000000000000 +00001000000011011010110000001000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111010110000000000111110 +11000000000011111011000000000011 +11100100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001011 +10110000000000111100001000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000001011111111000000000 +11111111100100000011111111100100 +00001011111110010000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11110110000000001100111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111100000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110000000000 +10110111000000000010110111000000 +00001011011100000100001011011100 +01010000101101110000000000101101 +11000000000010110111000000000010 +11010101000000001010011100000000 +00101101110000000000101101110000 +00000001100111000000000010110111 +00000000001011011100000000001011 +01110000000000101110001000000110 +00100000000000000000000000000000 +00000000000000000000000000000000 +00000000000000001001110000000000 +10110111000000010010110111000000 +00000010011100000010001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11000100000000001001011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101000000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00100000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000100101100110000001000101100 +11000000000010110011000000000010 +11000100000000001011001100000000 +00101100110000000000101100110000 +00000000100011000000000010110011 +00000000001011001100000000000011 +00110000000000101100100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000101011010110000000000 +11111011000000000011111011000000 +00001111101100000000001011101100 +00000000111110110000000000001110 +11000000000011111011000000000011 +11000100000000001101101100000000 +00111110110000000000101110110000 +00000010111011000000000011111011 +00000000001111101100000000001011 +10110000000000111110101100000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000100111110 +11000000010011111011000000000011 +11101100000000001110101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110000000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +00000001000100001111110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11110100100000001101111100000000 +00111111110000000001111111110000 +00000011101111000000000011111111 +00000000001111111100000000001111 +11110000000000111100100001000100 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000001000001000110110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000111110 +11000000000010111011000000000010 +11101110000000001000101100000000 +00101110110000000000101110110000 +00000011101011000000000010111011 +00000000001011101100000000001011 +10110000000000101110100001000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000000000010101011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101000000000001001101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101110000000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000000000 +10110011000000000010110011000000 +00011011001100000000001011001100 +00000001101100110000000000101000 +11000000000010110011000000000010 +11001100000000001000001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000011011 +00110000000000101100001000000100 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000011010110110000000000 +11111011000000000011101011000000 +00001111101100000000001111101100 +00000000111110110000000000101110 +11000000000011111011000000000011 +11101100000000001101101100000000 +00111110110000000000101110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100000000000011 +00010000000000000000000000000000 +00000000000000000000000000000000 +10100000000110011111110000000000 +11111111000000000011111111000000 +00001111111100000000011111111100 +00000000111111110000000001111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000001111111110000 +00000011101111000000000011111111 +00000000001111111100000000011111 +11110000000000111110100000000101 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11101111100000000011111111100001 +10001111111110000000001101111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111111000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001110111000000000 +10111011100000000011101011100000 +00001011101110000000001011101110 +00000000101110111000000000101110 +11100000000010111011100000000010 +11101110000000001011101110000000 +00101110111000000000101110111000 +00000011111011100000000010111011 +10000000001111101110000000001111 +10111000010000101110000000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10100011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00100100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101110001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010110000000000 +10111011000000000010101011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010101011000000000000111011 +00000000001010101100000000001010 +10110000000001101111000000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000101011110110000000000 +11101011000000000011111011000000 +00001111101100000000001101101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000010111011000000000011111011 +00000000001011101100000000001011 +10110000000000111100000000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11111111000000000011111111000000 +00001111111100000000000111111100 +00000000111111110000000000111111 +11000000000001111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111111100000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000010000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000010001010010110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101111100100000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +01100000000000010001111000000000 +10110111100000000010110111100000 +00001011011110000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101101100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +01001000000010000000110000000000 +11110011000000000011110011000000 +00001111001100000000001111001100 +00000000111100110000000000111100 +11000000000011110011000000000011 +11001100000000001111001100000000 +00111100110000000000111100110000 +00000011110011000000000011110011 +00000000001111001100000000001111 +00110000000000111101001000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000111011011110000000000 +11111111000000000011111111000000 +00001111111100000000011111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111101000000000010 +01100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011110110000000000 +11111011000000000011111011000000 +00001110101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000001111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110101000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000100011001110000000000 +10110111000000000010110111000000 +00001011011100000000001111011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001110011100000000001111 +01110000000000111101001000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000000001001111000000000 +10110111100000000010110111100000 +00001010011110000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +01000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101111000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001010001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000100100110000 +00000010110011000000000010110011 +00000000001010001100000000001010 +00110000000000101001001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11111010000000000011111010000000 +00001110101000000000001011101000 +00000000111110100000000000111110 +10000000000011111010000000000011 +11101000000000001111101000000000 +00111110100000000000111110100000 +00000011111010000000000011111010 +00000000001111101000000000001011 +10100000000000101111101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001110100000000001001111 +10000000000000111101001000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000000000000111001000000 +00001011100100000000001011100100 +00000000100110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101110000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000000000000010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +00100000000000000000000000000000 +00000000000000000000000000000000 +10111000000011000110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000110110010000000000111110 +01000000000011111001000000000010 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110011000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +10011000000001011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110011000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000100001110000000000000 +11111000000000000011101000000000 +00001011100000000000001011100000 +00000000101110000000000000101110 +00000000000010111000000000000010 +11100000000000001011100000000000 +00101110000000000000001110000000 +00000010111000000000000011111000 +00000000001011100000000000001111 +10000000000000101100111000000100 +00010000000000000000000000000000 +00000000000000000000000000000000 +00001000000001011100010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10101001000000000010101001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010101001 +00000000001011100100000000001010 +10010000000000101100011000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011110010000000000 +10111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000010111001 +00000000001111100100000000001011 +10010000000000111110100000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000000011010010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010010100000000000 +10111010000000000010111010000000 +00001011101000000000001011101000 +00000000101110100000000000101110 +10000000000010111010000000000010 +11101000000000001011101000000000 +00101110100000000000101110100000 +00000010111010000000000010111010 +00000000001011101000000000001011 +10100000000000101100101000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100101000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000000010001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101100100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001111000010000 +11110111100000000011110111100000 +00001111011110000000001111011110 +00000000111101111000000000111101 +11100000000011110111100000000011 +11011110000000001111011110000000 +00111101111000000000111101111000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01111000000000111100101000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000111111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000001000111100001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000001011111111000000000 +11111111100000000011111111100000 +00001111111110000000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111101000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110001000000 +10110111000000000010110111000000 +00001011011100000000001110011100 +00000000101101110000000001101101 +11000000000011100111000000000010 +11011100000000011011011100000000 +00101101110000000000101101110000 +00000011110111000000000011110111 +00000000001011011100000000001110 +01110000000000111110101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00010000000000001001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101100010000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01100000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001010001100 +00000000101100110000000000101100 +11000000000010100011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010100011000000000010100011 +00000000001011001100000000001010 +00110000000000101001100100000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10111000000101011010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000001000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000010111011000000000010111011 +00000000001111101100000000001011 +10110000000000101110101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11111011000000000011111011000000 +00001111101100000000001110101100 +00000000111110110000000000111110 +11000000000011101011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000011001110 +10110000000000111110010100000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +10010000000100001111110000000000 +11111111000000000011111111000000 +00001111111100000000001110111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000001111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111110000001000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000001000001000110110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000000011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101110000001100000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000001110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101010110000000000101110110000 +00000010111011000000000110111011 +00000000001011101100000000001011 +10110000000100101110000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000011000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +10000000000011010110110000000000 +11111011000000000011111011000000 +00001111101100000000001110101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000101110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110000000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000010000111111110000 +00000011111111000000000011111111 +00000000001111111100000000011111 +11110000000000111110100000000111 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111011000000000 +11001111100000000011001100000000 +00001000111110000000001100111110 +00000100111111111000010000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111111000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001110010000000000 +10001010000000000010001010000000 +00001000101100000000101000101110 +00000000101110111000000000101110 +11100000000010111011100000000010 +11101110000000001011101110000000 +00101110111000000000101110111000 +00000010111011100000100010111011 +10000000001011101110000000001011 +10111000000000101110000000000110 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011110110000000010 +10001011000000000010000000000000 +01001000001100000000001000001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000110110011000000000010110011 +00000000001011001100000000001011 +00110000000000101110001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010011000000000 +10001011000000000010001011010000 +00001000001100000100001000101100 +00000000101110110000000100101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000010000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111000000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000101011110111110000100 +11000010100000001011001000000000 +00101100101100000000001100101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000001001111101100000100001111 +10110000000000111101000000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011010000000000 +11111110101000100011111100000000 +00101111111100000010001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000100111111110000 +00010011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111111100000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110100000000 +11001011000100000011000011010010 +00001000101100000000001011101100 +00000000111110110000000000111110 +11000000010011111011000001000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000010111011 +00000000001111101100000000001111 +10110000000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010000110010000000 +10001010000000100010001011000011 +00001000101111011000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000001000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100010000000000 +10000011000010010010000001000000 +00101000001110000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101111000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00100000000000010001001000000010 +10001110100000000010000111100100 +00001000011110000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000100010110111 +10000000001011011110000000001011 +01111000000000101100100000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +01001000000010000010110000000000 +11000011000000010011001000000100 +00101100001100010000001111001100 +00000000111100110000000000111100 +11000000000011110011000000000011 +11001100000000001111001100000000 +00111100110000000000111100110000 +00000011110011000100000011110011 +00000000001111001100000000001111 +00110000000000111101001000000010 +00010000000000000000000000000000 +00000000000000000000000000000000 +01000000000111011011110000000010 +11110100000000101011111110000100 +00001111111100010000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000010 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111101000000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011100010000000010 +11001011000000000010001001010010 +01001100101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000000111101100000000001111 +10110000000000111100001000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000100011001010000000000 +10001110000000000010000101000000 +00001000011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000100101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101101001000000110 +01000000000000000000000000000000 +00000000000000000000000000000000 +11000000000000001011111000100000 +10000111100000000010000110100010 +00001000011110000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000001101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101100100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100111000000000 +10000000010010001010000011000000 +00001000001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101101101000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011001100100000000 +11001110010000010011001010010000 +00101100101000000000001111101000 +00010000111110100000000000111110 +10000000000011111010000000000011 +11101000000000001111101000000000 +00101110100000000000111110100000 +00000011111010000000000011111010 +00000000001111101000000000001111 +10100000000000111111101000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000100000 +11111000000000000011110000010010 +00001111100000000000001111100000 +00000100111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111101001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110011000000000 +11001001000100000011001011000100 +00001100100111000100001100100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110011100001000 +10001001110000000010001001110000 +00101000100110000000101000100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000010001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101110000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010001000010 +10000011010000000010001001000000 +01001000000100000000001000100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100111000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000010011000000000 +10000001010000001010000011001000 +00001000000101000010101000000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000010010110001 +00000000001011000100000000001011 +00010000000100101100101000000101 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000011010110000100000000 +11001000010000010011000000000101 +00001100101001000000001100100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +01111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111011111010000100000 +11111101000000000011111001010000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +01000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110011000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000001011110010000000000 +11001001000000000011001001000000 +00001100100100000000000111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000000111100100000000001111 +10010000000000111100011000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000100001100000000000010 +10001000000000001010001000000000 +00001000110000000000001011100000 +00000000101110000000000000101110 +00000000000010111000000000000010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000010111000000000000010111000 +00000000001011100000000000001011 +10000000000000101100111000000110 +00100000000000000000000000000000 +00000000000000000000000000000000 +00001000000001011101010000000010 +10000101000000000010000101000000 +00001000010100000100001001000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001001000100000000 +01101100010000000000001100010000 +00100000110001000000000010110001 +00000000001011000100000000001011 +00010000000000101101001000000001 +00100000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010011000001000 +10000101000000000010000101000000 +00001000111100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000100110010000 +00000000111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011110010010000010 +11001001001000000011001001101000 +00101100100100000000001101100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001101100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110100000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +00101000000000011010010000100100 +11111001100101000011111001001000 +00001111100100000000001111100100 +00000100111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111101001000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000100000000 +11001000110001000011001000100000 +00001111100000000000001100100000 +00001000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000001010011111000 +00000000000111100000000001001111 +10000000010000111100001000000100 +00000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010010101100000000 +10001010000000000010001010001000 +00001011101000000000001000101000 +00000000101110100000000000101110 +10000000000010111010000000000010 +11101000000010001011101000000010 +00101110100000000000101110100000 +00000010111010000000000010111010 +00000000001011101000000000001011 +10100000000000101100101000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010110110101000000 +10000011000000000010000011100000 +00001011001110000000001000001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100101000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000000010001110000000000 +10000111000000001010000111000000 +00001011011111000000001000011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000010 +00101101110000000000101101110000 +01000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101110000000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001101000000010 +11001111100000001011000111100000 +00001111111010010000101100011110 +00001000111101111000000000111101 +11100000100011110111100000000011 +11011110000000001111011110000000 +00011101111000000000111101111000 +00000011110111100000100011110111 +10000000001111011110000000001111 +01111000000000111110001000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010000000000000 +11111000000000000011111010000000 +00001111101000000010001111101100 +00000000111110110000000000111110 +11000000000011111011000000000010 +11101100000001001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001011101100000000001111 +10110000000000111100001000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000001011111111000000000 +11001111100000000011001111100100 +00001100111110000000001010111110 +01000000111111111000001000011111 +11100000100001111111100000000011 +11111110000000001111111110010000 +00111111111000000000111111111001 +00000010111111100100100011111111 +10000000001111111110000000001011 +11111001000000111100000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000000011001110000000000 +10000111001010000010000101000010 +00001000011100100000001000011100 +00000000001101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110001 +00010010010111000000000010110111 +00000000001011011100000000001011 +01110000000000101110101000000110 +00100000000000000000000000000000 +00000000000000000000000000000000 +00000000000100001001100000000000 +10000111000000010110000111000000 +10001000010000000100001000011100 +00000000101101110000000000100101 +11000000000010110111000000000010 +11011100000000001011011100000010 +00101101110000000000101101110000 +00100000110111000000100010110111 +00000000001011011100000000001011 +01110000001000101100000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00100000000101001110001001000000 +10001000000000100100001000110000 +00001000100000000000001000001100 +00000000101100110000000001100100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000010000100100110000 +00000010010011000000000010110011 +00000000001011001100000100001011 +00110000000000101100100100000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000101011010110000000010 +11001001010000010011001011000000 +00001100101100000000100100101100 +00000000111110110000000000110110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000001111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110110100000000 +11111011000000000011111011000000 +00001111100000000000001111101100 +00000000111110110000000100111110 +11000000010011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00010011011011000000000011111011 +00000000001111101100000001001111 +10110000000000111110000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000001000100001111110000100000 +11001101000010000011001101000010 +01001100111100000000001101111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111100100001000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000001000001000110010110010000 +10001000010000000010001000010000 +00001000101000000000011000101100 +00000000101110110000000000101110 +11000000000010111011000001000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101110100001000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010001000000010 +10001000100010000010001010110000 +00001000101110000010001000101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101010110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101110000000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000000000000010 +10000011000000001010000000000000 +01001000000000000000001000001100 +00000100101100110000000000101100 +11000000000010110011000000010010 +11001100000000001011001100000000 +00001100110000000000101100110000 +00000000110011000000000110110011 +00000000001011001100000001001011 +00110000000000101100001000000101 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000001010100100000000000 +11000000000000000011000011000000 +01001100000100000000101100101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100000000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011111000000000000 +11111100000000000011111100000000 +00000111110000000100001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000010000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111110100000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11111111100000000011111111100000 +00001110111110000000001101111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001101111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000001111111110000000001111 +11111000000000111111000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001110111000000000 +10111011100000000010111011100000 +00001011101110000001001011101110 +00000000101110111000000000101110 +11100000100010111011100000000010 +11101110000000001011101110000000 +00101110111000000000101110111000 +00000010111011100000000010111011 +10000000001011101110000000001011 +10111000000000101110000000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10110011000000000010110011000000 +00001010001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00100100110000001000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101110001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000100111011000000000000111011 +00000000001011101100000000001011 +10110000000000101111000000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000101011110110000000000 +11111011000001010011111011000000 +01001110101100000000001101101100 +00000000111110110000000000111110 +11000000000011111011000001000011 +11101100000000001101101100000000 +00111110110000000000111110110000 +00000011111011000001000011111011 +00000000001111101100000000001111 +10110000000000111100100000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11111111000000000011111111000000 +00000111111100000000001011111100 +00000000111111110000000000011111 +11000000000001111111000000000011 +11111100000000001111111100000000 +01111111110000000000111111110000 +00010011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111111100000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011000000000011111011000000 +00001110101100000000001110101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010010110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101111001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10110011000000000010110011000001 +00000011001100000100000011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000001000000110011 +00000000001011001100000000001011 +00110000000000101111000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +01100000000000010001111000000000 +10110111100000000010110111100000 +00001011011110000000001011011110 +00000000101101111000000001101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101101100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +01001000000010000000110000000000 +11110011000000000011110011000000 +00001111001100010000001110001100 +00000000111100110000000001111100 +11000000000011110011000001010011 +11001100000000001111001100000000 +00111100110001000000111100110000 +01000011110011000000000011110011 +00000000001111001100000000001111 +00110000000000111101101000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000111011011110000000000 +11111111000000000011111111000000 +00001111111100000100001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000010000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111101000000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110101000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000100011001110000000000 +10110111000000000010110111000000 +00001011011100000000011011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000001101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101101001000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000001000000001001111000000000 +10110111100000000010110111100000 +00001011011110000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101111000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000100101100110000000000101100 +11000000000010110011000000100010 +11001100000000001011001100000000 +00101100110000000001100100110000 +00000010010011000000000010110011 +00000000001011001100000000001011 +00110000000000101101001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000100101011010100000000000 +11111010000000000011111010000000 +00001111101000000000001111101000 +00000000111110100000000000111110 +10000000000011111010000000000011 +11101000000000001111101000000000 +00111110100000000000111110100000 +00000011111010000000000011111010 +00000000001111101000000000001111 +10100000000000111111101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01001010000000001110000000000000 +11111000000000010011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000001001111 +10000000000000111101001000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001010000100001110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101110000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +00100000000000000000000000000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000010 +11100100000000001011100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110011000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +10011000000001011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110011000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111000000100001110000000000001 +10111000000000000010111000000000 +00001011100000000000001011100000 +00000000101110000000000000101110 +00000000000010111000000000000010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000000111000000000000010111000 +00000000001011100000000000001011 +10000000010000101100111000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000001011100010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +01010000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000100010111001000000000010 +11100100000000001011100100000000 +00101110010000010000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011110010000000000 +10111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110100000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000000011010010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100101000010000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100001010000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000001000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00100000100001010010100000000000 +10111010000000000010111010000000 +00001011101000000000001011101000 +00000000101110100000000000101110 +10000000000010111010000000000010 +11101000000000001011101000000000 +00101110100000000000101110100000 +00000010111010000000000010111010 +00000000001011101000000000001011 +10100000000000101100101000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100101000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000000000010001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000001000010110111 +00000000001011011100000000001011 +01110000000000101100100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001111000000000 +11110111100000000011110111100000 +00001111011110000000001111011110 +00000000111101111000000000111101 +11100000000011110111100000000011 +11011110000000001111011110000000 +00111101111000000000111101111000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01111000000000111100101000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000010 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111000001000 +11111111100000000011111111100000 +00001111111110000000001111111110 +00000000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011111111100000000011111111 +10000000000111111110000000001111 +11111000000000111101000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +11101000000100011001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000100101101 +11000000000110110111000000000010 +11011100000001001011011100000000 +00101101110000000000101101110000 +00000010110111000100000010110111 +00000000001011011100000000011011 +01110000000000101110101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000000001001110000000000 +10110111000000000010110111000000 +00001011011100000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101100010001000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00100000000101001100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000001000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101101101000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000111111011000000000011111011 +00000010001111101100000011001111 +10110000000100111110111000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000010001111101100000100 +00111110110000000000111110110000 +00000011111011000000100011111011 +00000001001111101100000000001111 +10110000001000111110000000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +11000000000100001111110000000000 +11111111000000000011111111000000 +00001111111100000000001111111100 +00000000111111110000000000111011 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111110000001000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000001000001000110110000000000 +10111011000000000010111011000000 +00001011101100000000000011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101110000001000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11101100000000001011101100000001 +00101110110000000000101110110000 +00000010111011000000000010111011 +00000100000001101100000000001011 +10110000000000101110000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000000100 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000100010110011 +00000100001011001100000000001011 +00110000000000101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +10000000000011010110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111010 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110000000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +11100000000111011111110000000000 +11111111000000000011111111000001 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000010000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111110100000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111000000000 +11000100100000100011001111100000 +00001100111010000000001111111110 +00000000110011111000000000111111 +11100000000011111111100000000011 +11111110000000001100111110000110 +00111111111000000000111111111000 +00000011111111100000000011001111 +10000000001111111110000000001111 +11111000000000111111000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001110111000000000 +10001001100001100010001011100001 +00001000101010000000001011101110 +00000010100010111000000000101110 +11100001100010111011100000000010 +11101110000000101000101110000000 +00101110111000000000101110111000 +01000010111011100000010010001011 +10000000001011101110000000001011 +10111000000000101110000000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10011010000000000010010011000000 +00001001001000000000001011001100 +00000000100000110000000000101100 +11000000000010110011000000000010 +11001100000000001000001100000000 +00101100110000001000001100110000 +00000010110011000000001010010011 +00000000001011001100000000001011 +00110000000000101110001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000101011010110000000000 +10011001000000000010011011000000 +01001001101000000010001011101100 +00000000100010110000000000101110 +11000000000010111011000000000010 +11101100000000001000101100000000 +00101110110000010000101110110000 +00000010111011000000000010011011 +00000000001011101100000000001011 +10110000000000101111000000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000101001000110000000000 +11011011100100000011010011000000 +00001101101000000100001111101100 +00000010110010110000000000111110 +11000000000011111011000000000011 +11101100000000001100101100000000 +00111110110000000000101110110000 +00000011111011000000100011011011 +00000000001111101100000000001111 +10110000000000111100000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +11100001000000001011110000001000 +11101100000000010011101111000000 +00001110111000000001001111111100 +00000000111111110000000000110111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000100111111110000 +00010011111111000000000011101111 +00000000001111111100000000001111 +11110000000000111111100000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11001011000000000011001011000000 +00001100101000010010001100101100 +00010000111110110000000000111110 +11000000000011111011000000110011 +11101100000010001111101100000000 +00111110110000000000111110110000 +01100011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001000010110000000100 +10000010000000000010001011000001 +00001000101011000000001000001100 +00000000101110110000000000101110 +11000000000010111011000000000010 +11001100000000001011101100000000 +00101110110000000000101110110000 +00000010110011000000000010111011 +00000000001011101100000000001011 +10110000000000101111001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000000000 +10000000000000000010010011000000 +00001001001010000000001000001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101111000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00100000000000010001111100000000 +10001100110000000010010111110000 +10001001011011000000001000011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000000 +00101101111000000000101101111000 +00100010110111100000010010110111 +10000000001011011110000000001011 +01111000000000101100100000010100 +00000000000000000000000000000000 +00000000000000000000000000000000 +01001000000010000000110000000000 +11000010000000000011010011000100 +00001101001000010000001100001100 +00000000111100110000000000111100 +11000000100011110011000000000011 +11001100000000001111001100000000 +00111100110001000000111100110000 +00000011110011000000000011110011 +00000000001111001100000000001111 +00110000000000111101001000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000111011000110000000000 +11111010000000100011100011000001 +00001010001000000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000010001111101100000000 +00111110110000001000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011110110000000000 +11110000000000000010001011000000 +00001111101000000100001111101100 +00001000011110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000101110110000 +00000011110011100001001011001011 +00000000001111101100000000001111 +10110000000000111100001000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000100011001110000000000 +10110100000000000010000111000000 +00001011011000000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000000 +00101101110000000100101101110000 +00000010110111000000000010000111 +00000000001011011100000000001011 +01110000001000101101001000000100 +01000000000000000000000000000000 +00000000000000000000000000000000 +11000000000000001001111000000000 +10111110100000001010000111100000 +00001011011010000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000001 +00101101111000000000001101111000 +00000010110111100000000010000111 +10000000001011011110000000001011 +01111000000000101100100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10110010000000000010000011000000 +00001011001000000000001011001100 +00000000101100110000000001101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000010000101100110000 +00000010110011000000000010000011 +00000000001011001100000000001011 +00110000000000101101101000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11111110000000000011001010000000 +00001111111000000000001111101000 +00000000111110100000000000111110 +10000000000011111010000000000011 +11101000000000001111101000000010 +00111110100000000000111110100000 +00000011111010000000000011001010 +00000000001111101000000000001111 +10100000000000111111101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000001000 +11111000100000001011111000000000 +00001111100000000000001111100000 +00000100111110000000000000111110 +00000000000011111000000000000011 +11100000000010001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111101001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000000001011001001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000000110010000000000 +10110001000000000010001001000001 +00001011100100000000001110100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000100 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101110000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00011000000001000010011000000001 +10111011100001000010001001100000 +00001011100110000000001011100100 +00000000101110010000000000101010 +01000000000010111001000000000010 +11100100000000001011100100000010 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000010000 +10110001000000000010000001000000 +00001011000100000001001010000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000010011011000100000000 +00101100010000000000101100010000 +00000010110001000000010010110001 +00000000001011000100000000001011 +00010000000100101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000010010110000000000000 +11111000000000000011001000000001 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111011111010000000000 +11111101000000000011111001000000 +00001111100100000000001110100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +01000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110111000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +00011000000001011110010000000000 +11111011000000000011001001000000 +00001111100100000000001111110100 +00000000111110010000000000110110 +01000000000011111001000000000011 +11110100000000001111100100000000 +00111110010000000000111110010000 +00000011111101000000000011001001 +00000000001111100100000000001111 +10010000000000111100111000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +00111100000100001110000000000000 +10111000000000000010001000000000 +00001011110000000000001011100000 +00000000001110000000000000101110 +00000000000010111000000000010010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000010111000000000000010001000 +00000000001011100000000000001011 +10000000000000101100011000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00001000000001011101010000000000 +10111101000000000010010101000001 +00001011010100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000001010000001 +00000000001011000100000000001011 +00010000000000101101001000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10111101100000001010011101000000 +00001011110100000000001011100100 +00010000101110010000000000101110 +01000000000110111001000000100010 +11100100000001000011100100000101 +00101110010000000000100110010000 +00000010111001000000000010001001 +00000000011011100100000000001011 +10010000000000101100011000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000101001010010000010000 +11111001100000000011011001000000 +00001111100100000000001111100100 +00000000111110010000000100110110 +01000000100011111001000000100011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011001001 +00000000001111100100000010001111 +10010000000000111110100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101010000000001010010000000000 +11111001000000000011101001000000 +00001111100100000000001111100100 +00000100111110010000000000101110 +01000000000011111001000000000001 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111101101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101010000100001010000000000000 +11111000000000000011111000000000 +00001111110000100000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000001001111100000000000 +00111110000000000000011110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000100001000010100000000100 +10110010000000000010111010000000 +00001011101000000000001011101000 +00000000101110100000000000101110 +10000000000010111010000000000010 +11101000000000001011101000000000 +00101110100000000000101110100000 +00000010110010000000000010111010 +00000000001011101000000000001011 +10100000000000101100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000000000 +10110011000000100010110011000000 +00001011001000000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000100010110011 +00000000001011001100000000001011 +00110000000000101100001100000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00100000000000010001100000010000 +10110110000000000010110110000000 +00001011011000000000001011011100 +00000000101101110000000000101101 +11000000000010110111000000000010 +11011100000000001011011100000001 +00101101110000000000101101110000 +00000010110111000000000010110111 +00000000001011011100000000001011 +01110000000000101100100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00111000000010000001011000000000 +11110101100000000011110101100000 +00001111010010000000001111011110 +00000000111101111000001000111101 +11100000000011110111100000100011 +11011110000000001111011110000000 +00111101111000000000111101111000 +00000011110111100000000011110111 +10000000001111011110000000001111 +01111000000000111100101000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010000000000000 +11111000000000000011111000000000 +10001111100000000000001111101100 +00010100111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000010 +00111110110000000000111110110000 +01000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000001011111111000000010 +11001111100000000011111111100000 +00001111111110010000001111111110 +00000000111111111001000000111111 +11100000000011111111100000000011 +11111110000000001111111110010000 +00111111111001000000111111111000 +00000011110111100000000011001111 +10000000001111111110000000001111 +11111000000000111101100000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001100001010000 +11010110000100000010110110000000 +00001011011100000000001001011100 +00000100111101110000000100101101 +11000000010010110111000100000010 +11011100000000001011011100000000 +00111101110000000000101101110000 +01010010110111000000010010000111 +00000000001011011100000000001011 +01110000000000101110101000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001011010000000000 +10000101000010000010110101000000 +00001011010110000000011001011100 +00000000101001110000000001101101 +11000000000010110111000000000010 +11011100000000001011011100000010 +01100101110000000001101101110000 +00000010110111000000000010000111 +00000000001011011100000000001011 +01110000000000101100000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01100000000101001100000000000010 +10000000100000000010110000000000 +00001011000100000000001001001100 +00000100101100110000000000101100 +11000000000110110011000001000010 +11001100000100000011001100000100 +00101000110000010000101100110000 +00000010110011000001001010000011 +00000100001011001100000100001011 +00110000000000101101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +10101000000101011010110000000000 +10000011110000000011111011000000 +00001111101000000000001101101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001011101100000000 +00101110110000000000111110110000 +00000011111011000001000011001011 +00000000001111101100000000001111 +10110000001100111110101000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110100000010000 +11111010000010000011111010000000 +01001111101000000000001101101100 +00000000111010110000000100111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +01111110110000000000111110110000 +00000011111011000000000011111011 +00000010001111101100000001001111 +10110000000000111110100000010100 +00110000000000000000000000000000 +00000000000000000000000000000000 +00000001000100001111010000000000 +11111101000000000011001101000000 +00001111110000000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000100111111110000 +00010011111111000000100011111111 +00000000001111111100000000001111 +11110000000000111100000001000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11000001000001000110000000010000 +10111000000000000010001000000000 +00001011100000000100001011101100 +00010000101110110000000000101110 +11000001000110111011000000010010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000010111011000001000010111011 +00000000001011101100000000001011 +10110000000000101110000001000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +11000000000001010010110000001000 +10111011000000000010001011000000 +00001011101100000000001010101100 +00000000101110110000000000101110 +11000000010010101011000000010010 +11101100000010001011101100000000 +00101110110000000000101110110000 +00000000111011000000000010111011 +00000000001011101100000001001011 +10110000000100101110000000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00001000010000000000100000000000 +10111010000000001010000010000000 +01001011001100000001001011001100 +00000000101100110000000000101100 +11000000000010110011000000010010 +11001100000000001011001100000001 +00101100110000000000101100110000 +00000010110011000000010010110011 +00000000001011001100000001001011 +00110000000000101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000011000110010000000000 +11111001000000000011001001000000 +00001111100100000000001110101100 +00000000111110110000000000111110 +11000000000011101011000000000011 +11101100000010001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000011100000000000110 +00000000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011101000000000000 +01111100000001000011111100000001 +00001111110100000100001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000011111111100000000 +00111111110000010000111111110000 +01000011111111000001000011111111 +00000000001111111100000000001111 +11110000010000111110100000000010 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000001011111111000000010 +11001111100000000011111111100000 +10001111111110000000001101111110 +00001000111111111000000000111111 +11100000000011111111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111000 +00000011011111100000011011001111 +10000000001111111110000000001111 +11111000000000111111000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001110111000000000 +10001011100000000010111011100000 +00001011101110000001001011101110 +00001000101110111000001100101110 +11100000010010111011100000010010 +11101110000000001011101110000000 +00101110111000000000101110111000 +00010010011011100000000010001011 +10000000001011101110000000001011 +10111000000000101110000000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10001000000001011100110000000000 +10000011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101100110000 +00000010110011000000000010000011 +00000000001011001100000000001011 +00110000000000101110001000000001 +01110000000000000000000000000000 +00000000000000000000000000000000 +11000000000100011010110000000000 +10001011000001000010111011000000 +00001011101100000000001011101100 +00000000101110110000000000100110 +11000000000000111011000001000010 +11101100000000001011101100000000 +00101110110000001000101110110000 +00000110011011000000000010001011 +00000000001011101100000000000011 +10110000000000101111000000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00000000000101011110110000000000 +11001011000000000011111011000000 +00001111101100000000001101101100 +00000000111110110000000000111110 +11000001000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011011011000000010011001011 +00000100001111101100000000001111 +10110000000000111101000000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +11100000000000011011110000000000 +11111111000001000011111111000000 +00000111111100000100001111111100 +00000000111111110000000000101111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00010011111111000001000011111111 +00000000001111111100000000001111 +11110000000000111111100000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000100001010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00011000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00010011111011000000010011111011 +00000100001111101100000000001111 +10110000000000111101000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +11001000000001010000110000000000 +10111011000001000010111011000000 +00001011101100000100001011101100 +00000000111110110000010000101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000000101110110000 +00000000110011000001000010111011 +00000000001011101100000000001011 +10110000000000101111001000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +11100000000001010100110000010000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000001100110000 +00000010110011000000000010110011 +00000000001011001100000100000011 +00110000000000101111100000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +01100000010000010001111000000000 +10110111100000000110110111100000 +00001011011110000000001011011110 +00000000101101111000000000101101 +11100000000010110111100000000010 +11011110000000001011011110000100 +00101101111000000000101101111000 +00000010110111100000000010110111 +10000000001011011110000000001011 +01111000000000101100100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +01001000000010000000110000000000 +11110011000000000011110011000001 +00001111001100010000001111001100 +00000000111100110000000000111100 +11000000000011110011000000000011 +11001100000000001111001100000000 +00111100110001000100111100110000 +00000011110011000000000011110011 +00000000001111001100000000001111 +00110000000000111101001000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000111011011110000000001 +11111111000000000011111111000000 +00000111111100010100001111111100 +00000000111011110000000001111111 +11000000000011111111000000010011 +11111100010000001111111100010000 +00111111110000000000111111110001 +00010111111111000000000011111111 +00000000001111111100000000001111 +11110000000000111101000000000010 +01100000000000000000000000000000 +00000000000000000000000000000000 +10101000000001011100111000000000 +11001011000000000011111011000000 +00001111101100000000001111001110 +00000000110010110000000000111110 +11000000000011111011000000000011 +11001110000000001100101100000000 +00111110110000001000111110110000 +00000011110011100000000011001011 +00000000001111101100000000001111 +10110000000000111110101000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +01001000000100011001110000000000 +10000111000000000010110111000000 +00001011011100000001001011011100 +00000000100001110000000001101101 +11000000000010110111000000000010 +11011100000000001000011100000100 +00101101110000000000100101110000 +00000010110111000000000010000111 +00000000001011011100000000001011 +01110000000000101101001000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +11000000000000001001111000000010 +10000111100000000010110111100000 +00001011011110000000001011011110 +00010011100101111000000000101101 +11100000000010110111100001100010 +11011110000010101000011110000000 +00101101111000000000101101111000 +00000010110111100000011010000111 +10000100001011011110000000001011 +01111000000000101111000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01001000000101001100110000000000 +10000011000000010010110011000000 +00001011001100000000001011001100 +00000000100100110000000000101100 +11000000000010110011000000000010 +11001100000000001000001100000001 +00101100110000000001100100110000 +00000010110011000000000010000011 +00000000001011001100000000001011 +00110000000000101101001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +11101000000101011010100000000000 +11001010000000000011111010000000 +00001111101000000000001111101000 +00000000110110100000000000111110 +10000000000011111010000000000111 +11101000000000001100101000000000 +00111110100000000000111110100000 +01000011111010000000000011001010 +00000000011111101000000000001111 +10100000000000111111101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +01001000000000001110000000000000 +11111000000000100011111000000000 +00001011100000000000001111100000 +00000000111010000000000000111110 +00000000000011111000000000000111 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000001001111 +10000000000100111101001000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000100001110010000000000 +11111001000000000011101001000000 +00001111100100000000001111100100 +00000000111110010000000000111110 +01000000000011111001000000000011 +11100100000001001111100100000000 +00111110010000000000111110010000 +01100011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100001000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000001000110010000000000 +10111001000000000010111001000000 +00001011100100000000001011100100 +00000000100110010000000000101110 +01000000000010111001000000000010 +11100100000000001011100100000000 +00101110010000000000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101110000000000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +00011000000001010010010000000000 +10111001000000000010111001000001 +00001011100100000000001011100100 +00000000101110010000000000101110 +01000000000010111001000000000010 +10100100000000001011100100000000 +00101110010000000000001110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000010010 +11000100000000001011000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +10111000000011010110000000000000 +11111000000000000011101000000000 +00001111100000000000001111100000 +00000000111110000000000000111110 +00000000000011111000000000000011 +11100000000000001111100000000000 +00111110000000000000111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111110111000000011 +01010000000000000000000000000000 +00000000000000000000000000000000 +10011000000111011110010000000000 +11111001000000000011111001000000 +01001111100100000000001111100100 +00000000110110010000000000111110 +01000000000011111001000000000001 +11100100000001001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110011000000110 +01110000000000000000000000000000 +00000000000000000000000000000000 +10011000000001011111010000000000 +11111001000000000011111001000000 +00001111100100000000001111110100 +00000000111110010000000000110110 +01000000000011111001000000000011 +11110100000000001111100100000000 +00111110010000000000111110010000 +00000011111101000000000011111001 +00000000001111100100000000001111 +10010000000000111100011000000001 +01100000000000000000000000000000 +00000000000000000000000000000000 +00111000000100001110000000000000 +10111000000000000010111000000000 +00001011100000000000001011100000 +00000000101110000000000000101110 +00000000000010111000000000000010 +11100000000000001011100000000000 +00101110000000000000101110000000 +00000010111000000000010010111000 +00000000001011100000000000001011 +10000000000000101100111000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +00001000000000001100010000000000 +10110001000000000010110001000000 +00001011000100000000001011000100 +00000000101100010000000000101100 +01000000000010110001000000000010 +11000100000000001010000100000000 +00101100010000000000101100010000 +00000010110001000000000010110001 +00000000001011000100000000001011 +00010000000000101100001000000001 +00110000000000000000000000000000 +00000000000000000000000000000000 +00011000000101011010010000000000 +10111001000000000010111001000000 +00001011100100000000011011100100 +00000000101110010000000100101110 +01000000000010111001000001000010 +11100100000000001011100100000000 +00101110010000010000101110010000 +00000010111001000000000010111001 +00000000001011100100000000001011 +10010000000000101100011000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10100000000101011110010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00010000111110010000010000110110 +01000000000011111001000000000011 +11100100000000001110100100000000 +00111110010000000000111110010000 +00000010111001000000000011111001 +00000000001111100100000000001111 +10010000000000111110100000000100 +01110000000000000000000000000000 +00000000000000000000000000000000 +00101000000000011010010000000000 +11111001000000000011111001000000 +00001111100100000000001111100100 +00000000111110010000000000101110 +01000000000011111001000000000011 +11100100000000001111100100000000 +00111110010000000000111110010000 +00000011111001000000000011111001 +00000000001111100100000000001111 +10010000000000111100101000000000 +01100000000000000000000000000000 +00000000000000000000000000000000 +00101000000100000010000000000000 +11111000000000000011111000000000 +00001111100000000000001111100000 +00000000111110000000000001111110 +00000001000011111000000000000011 +11100000000000001111100000000000 +00111110000000000001111110000000 +00000011111000000000000011111000 +00000000001111100000000000001111 +10000000000000111100101000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010010100000000000 +10111010000000000010111010000000 +00001011101000000000001011101000 +00000000101110100000000000101110 +10000000000010111010000000000010 +11101000000000001011101000000000 +00101110100000000000101110100000 +00000011101010000000000010111010 +00000000001011101000000000001011 +10100000000000101100101000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00101000000001010100110000010000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000100 +00101100110000000000101100110000 +00000010110011000000000010110011 +00000000001011001100000000001011 +00110000010000101100101000000000 +01010000000000000000000000000000 +00000000000000000000000000000000 +10100000010000010001110000000000 +10110111000000000010110111000000 +00011011011100000000001011011100 +00000000101101110000000000001101 +11000000000010110111000000000010 +11011100000000001011011100000001 +00101101110000000000101101110000 +00000000100111000000000010110111 +00000000001011011100000000001011 +01110000000000101110100000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +10101000000010000001111000000000 +11110111100001000111110111100000 +00001111011110000000001111011110 +00000000111101111000000000101101 +11100000000011110111100000000011 +11011110000000001111011110000000 +00111101111000000000101101111000 +01000011110111100000000011110111 +10000000001111011110000000001111 +01111000000000111110101000000010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000111011010110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000100111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100001000000110 +01100000000000000000000000000000 +00000000000000000000000000000000 +01000000000001011111111000000000 +11111111100000000011111111100100 +00001111111110000000001111111110 +00000000111111111000011000111111 +11100000000011101111100000000011 +11111110000000001111111110000000 +00111111111000000000111111111001 +00000011111111100000000011111111 +00100000001111111110000000001111 +11111000000000111100000000000000 +01110000000000000000000000000000 +00000000000000000000000000000000 +10101000000100011001110000000000 +10110111000100000010110111000000 +00001011011100000000001011011100 +00000000101101110001000000101101 +11000000010010110111000000000010 +11011100000010001011011100000000 +00101101110000000000101101110001 +00000010110111000100000010110111 +00000000001011011100000010001011 +01110000000000101110101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +00011000000000001001110000000000 +10110111000000000010110111000001 +00011011011100000000001011011100 +00000000101101110000000000101101 +11000000000010100111000000000010 +11011100000000001011011100000000 +00101101110000000000101101110000 +00000110110111000000000010110111 +00010000001011011100000000001011 +01110000000000101100000000000000 +00100000000000000000000000000000 +00000000000000000000000000000000 +01100000000100001100110000000000 +10110011000000000010110011000000 +00001011001100000000001011001100 +00000101101100110000000000101100 +11000001000010110011000000000010 +11001100000000001011001100000000 +00101100110000000001101100110000 +01000010110011000000000010110011 +00000000001011001100000000001011 +00110000000000101100100000000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10111000000101011010110000000000 +11111011000000000111111011000000 +00001111101100000010001111101100 +00000000111110110000000000111110 +11000000000011101011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111110101000000100 +01100000000000000000000000000000 +00000000000000000000000000000000 +10000000000000001110110000000000 +11111011000000000011111011000000 +00001111101100000000001111101100 +00000000111110110000000000111110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000111110110000 +00000011111011000000000011111011 +00000001001111101100000000000111 +10110000000000111110000000000000 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000000000100001111110000000000 +11111111000000000011111111000000 +00001111111100000000001110111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000000000111111110000 +00000011111111000000000011111111 +00000000001111111100000000001111 +11110000000000111100000001000100 +00110000000000000000000000000000 +00000000000000000000000000000000 +10000001000001000110110000000000 +10111011000000010011101011000000 +00001011101100000000000011101100 +00000000101110110000000001101110 +11000000000010111011000000000010 +11101100000000001011101100000000 +00101110110000000001111010110000 +00000011101011000000110010111011 +00000100001011101100000000001011 +10110000000000101110000001000000 +00010000000000000000000000000000 +00000000000000000000000000000000 +10000000000001010010110000000000 +10111011000000000010111011000000 +00001011101100000000001011101100 +00000000101110110000010000101110 +11000000000010111011000000000110 +11101100000000001011101100000000 +00101110110000010000101110110000 +00000010111011000000000010111011 +00000000001011101100000000001011 +10110000000000101110000000000000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00001000000001000000110000000100 +10110011000000000010100011000001 +00001011001100000000001011001100 +00000000101100110000000000101100 +11000000000010110011000000000010 +11001100000000001011001100000000 +00101100110000000000101000110000 +00010010100011000001100010110011 +00000100001011001100000000001011 +00110000000000101100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +10000000000011010110110000000100 +11111011000000100011111011000000 +10001111101100000000001110101100 +00000000101110110000000000101110 +11000000000011111011000000000011 +11101100000000001111101100000000 +00111110110000000000101110110000 +00000011111011000000000011111011 +00000000001111101100000000001111 +10110000000000111100000000000011 +00010000000000000000000000000000 +00000000000000000000000000000000 +10100000000111011111110000000000 +11111111000000000011111111000001 +00001111111100000000001111111100 +00000000111111110000000000111111 +11000000000011111111000000000011 +11111100000000001111111100000000 +00111111110000010000111011110000 +00000011101111000000000011111111 +00000000001111111100000000001111 +11110000000000111110100100000011 +01110000000000000000000000000000 +00000000000000000000000000000000 +00000000110001010000000000000010 +01110001010000001001110000010000 +00110111000111000101010111000001 +00000011011100000100000010011100 +00010000001101110001010000001101 +11000111000000110111000111000001 +11011100010100000111011100010100 +00010101110000010000000101110000 +01000000010111000001000001010111 +00000100000111011100000000100001 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000110000010100010000100101 +01110001000000010101110001000000 +01010111000100000001010001000100 +00000101011100010000000001011100 +01000000010101110001000001010101 +11000100000001010011000100000001 +01011100010000000101011100010000 +00011100100001000000010000110001 +00000001110111000100000001010111 +00010000000101011100000000010001 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000000100001000000001000000001 +00100000100000000100100000100000 +00010010000110000000000010000010 +00000001001000001000000001001000 +00100000000100100000100000000100 +10000010000000000010000010000000 +01001000011000000001001000011000 +00000100100000100000000101110000 +10000000010010000010000000010010 +00001000000001001000000000100000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00000000100000000000000000000001 +01100000000000000101100000000000 +00010110000000000000010110000000 +00000001011000000000010001010000 +00000000000101100000000000000101 +10000100000000010110000100000000 +01011000000000000001011000001000 +00000001100000000010010101100000 +00000000010110000000000000010110 +00000000000101011000000000110001 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000000010001010100100101000101 +01110010000000010001110010000000 +01000111001000000000010111001000 +00000101011100100000000000011100 +10000000010101110010000000010101 +11001000000001010111001000000000 +01011100110000000001011100100000 +00000101110010000000010101110010 +00000001010111001000000001000111 +00100000000100011100000000010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +00000000110001010100000000000000 +01100000000000000001100000000000 +00000110000000000000000110000000 +00000000011000000000000100011000 +00010000000001100000000000000001 +10000000000000000110000000000000 +00011000000000000000011000000000 +00000000100001000000000001100000 +00000000000110000000000000000110 +00010000000000011000000000110001 +01000000000000000000000000000000 +00000000000000000000000000000000 +00000000110001010100100000000100 +00100010000000010000100010010000 +01000010000000000000000010001000 +00000100001000000000000100001000 +10000000010000100010000000010000 +10001000000001000010001000000000 +00001000101000000000001000000100 +00000000100001000000010000100000 +00000001000010000000000001000010 +00110000000100001000000000100001 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000110001010100111100000101 +01000010100000010101000011100000 +01010100000000000000010100001010 +00000101010000001000000101010000 +11100000010101000010110000010101 +00001010000001010100001111000001 +01010000111000000101010000000000 +00000100000000100000000101000000 +11000000010100000010000001000100 +00101100000000010000000000010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +00000000100000000001110100000001 +00010011000000000101010111000000 +00010101011100000001010101011100 +00000001000001110000000001000001 +11000000000100000111000000000100 +01011100000000010101001100000000 +01000101110000000001010100110000 +00000101010111000000000101010011 +00000000010001011100000000010101 +00110000000001000100000000100000 +01000000000000000000000000000000 +00000000000000000000000000000000 +00000000100001000000010000000000 +00010000000000000001000001000000 +00000100001110000000000100000000 +00000000000000000000000000000000 +01100001000001000000000000000000 +01000000000000000100000110000000 +00000100010000000000010000110000 +00000001000011000000000001000000 +00000001000001001000000000000100 +00010000000000000100000100100001 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000000110000010110000000000010 +00011000000000001000001000000000 +00100000100000000000100000100000 +00000010000010000000000110000010 +00000000001000001000000010001000 +01100000000000100000100000000000 +10000110000000000010000010000000 +00001000001001000000001000001000 +00000000100001100000000000100000 +10000000000010000100000100010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +00000000110001010001000000000101 +01100000000000010101100100000000 +01010110010000000000110110010000 +00000001001001000000000001001001 +00000000010101100100000000010101 +10010000000000010110000000000000 +01011001000000000001011000000000 +00011101100100100000011101100000 +00000001010110010000000001110110 +00000000000101011000000000010001 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000110001010100000000000001 +01100000000000001101100000000000 +00110110001000000000010110000000 +00000111011000000000000011011000 +00000001001101100000000000001101 +10000000000001110110000000000001 +11011000000000000101011000100000 +00010101100010000000010101110000 +00000000010110001000000001010110 +00000000000111011000000000100001 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000000110001010100001000000100 +00110000100001010000110000100000 +01000011000011000001000011000010 +00000100001100001000000000001100 +00100001010000110000100001010000 +11000010000001000011000010000001 +00001100001000000010001100001000 +00000000110000100000010001100000 +10000001100011000010000001100011 +00001000000100001100000000110001 +01010000000000000000000000000000 +00000000000000000000000000000000 +00000000100000000000000000000000 +00110000000000000000110000000000 +00000011000000000000000011000000 +00000000001100100000000000001100 +00000000000000110000000000000000 +11000000000000000011000000000000 +00001100000000000000001100000000 +00000000110000000000000000100010 +00000000000011000000000000000011 +00000000000000001100000000000001 +01000000000000000000000000000000 +00000000000000000000000000000000 +00000000100000000000001000000001 +00110000100000000100110000100000 +00010011000010000001010011000010 +00000101001100101100000001001100 +00100000000100110000100000000100 +11000010000000010011000010000000 +01001100001000000001001100001100 +00000100110000110000000100110010 +11000000010011000011000000010011 +00001000000001001100000000110001 +01000000000000000000000000000000 +00000000000000000000000000000000 +00000000110001010100001000000101 +01100000100000010101100000100000 +01010110000011000001000110000010 +00000001011000001100000000001000 +00100000010101100000100000010101 +10000010000000010110000010000000 +01011000001000000001011000001100 +00010101100000110000000101100000 +11000001010111000011000001010110 +00001000000001011000000000010000 +01010000000000000000000000000000 +00000000000000000000000000000000 +00000000110001010100001000000000 +00100000100000000000100000100000 +00000010000010000000000011000010 +00000000011000001000000100001000 +00100000000000100000100000000000 +10000010000000000010000010000000 +00001000001000000000001000001000 +00000000110000100000010000110000 +10000000000110000010000000000011 +00001000000000001000000000110001 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000110001010001001000000100 +01100000100000010001100100100000 +01000110010010000001000011010010 +00000000001001001000000100001001 +00100000010001100100100000010001 +10000010000000000110010010000000 +00011001001000000000011001001000 +00010000110100100000010000110100 +10000001000010000010000001000011 +01001000000000011000000000000001 +01000000000000000000000000000000 +00000000000000000000000000000000 +00000000010001010110000000000101 +01011000000000010101011000000000 +01000101100000000000000001100000 +00000001010110000000000100000010 +00000000010101011000000000010101 +01100000000001010101100000000001 +01010110000000000001010110000000 +00010100011000000000010100011000 +00000000010001100000000000010001 +10000000000101010100000000000001 +01010000000000000000000000000000 +00000000000000000000000000000000 +00000000100001000010011000000001 +01000001100000000101000001100000 +00010100000110000000010100000110 +00000001010000011000000001010000 +01100000000101000001100000000101 +00000110000000010100000110000000 +01010000011000000001010000011000 +00000001000000100000000101000001 +10000000010100000110000000010100 +00011000000001010000000000010001 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000000100000000001001000000001 +00000000100000000100000100100000 +00010000010010000000010000010010 +00000001000001001000000001000001 +00100000000100100100100000000100 +00000010000000010000010010000100 +01000001001000000001000001001000 +00010100000100100000000100000100 +10000001010000000010000000010000 +01001000000001000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000110001010100011000000011 +01010001100000001101010001100000 +00110101000110000000110101000110 +00000011010100011000000111000000 +01100000001101010001100000001101 +01000110000000110101000110000000 +11010100011000000001010100011000 +00000101010001100000001101010001 +10000000110101000110000000110101 +00011000000011010100000000110001 +01010000000000000000000000000000 +00000000000000000000000000000000 +00000000110001010100001000000111 +01110001100000010101110001100000 +00010111000110000000110111000110 +00000000011100011000001001011100 +01100000000101110001000000010101 +11000110000000010111000110000000 +01011100011000001110011100011000 +00010101110001100000011101110001 +10000001010111000110000001110111 +00011000000001011100000000010001 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000010001010100011000000011 +01110001100000001101110001100000 +01100111000110000101010111000110 +00000010011100011000000011011100 +01100000011101110001100000001101 +11000110000001100111000110000001 +11011100011000000010011100011000 +00010001110001100000010101110001 +10000000010111000110000001010111 +00011000000011011100000000000001 +01000000000000000000000000000000 +00000000000000000000000000000000 +00000000010001010100011000000101 +01110001100000010101110001100000 +01010111000110000001000011000110 +00000101011100011000000000011100 +01100001010101110001100000010100 +11000110000101010111000110000001 +01011100011000000101011100011000 +00011000110001100000011001110001 +10000001100111000110000001000011 +00011000000101011100000000000001 +01010000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000001000000001 +00100000100000000100100000100000 +00010010000010000000010111000010 +00000001001000001000000001001000 +00100000000100100000100000000101 +10000010000000010010000010000000 +01001000001000000001001000001000 +00000101110000100000000100110000 +10000000010010000010000000010111 +00001000000001001000000000010000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000010000000000011000000001 +01100001100000000101100001100000 +00010110000110000000010110000110 +00000001011000011000000001001000 +01100000000101100001100000000101 +10000110000001010110000110000001 +00011000011000000001011000011000 +00000101100001100000000101100001 +10000000010010000110000000010110 +00011000000001011000000000100001 +01000000000000000000000000000000 +00000000000000000000000000000000 +00000000010001010100000000000101 +01110000000000010101110000000000 +00010011000000000001010011000000 +00000101001100000000000001001100 +00000000000000110000000000010101 +11000000000000010111000000000001 +01011100000000000101011100000000 +00000101110000000000010100110000 +00000001000111000000000000010011 +00000000000101011100000000110001 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000000010001000100001100000000 +01100000100000000001100000110000 +00000010000010000000000010000010 +00000000001000001000000100011000 +00100000000000100000100000000001 +10000010000000000110000010000000 +00011000001000000000011000001000 +00000000000000100000000000100000 +10000000000110000010000000000010 +00001000000000011000000000000001 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000000010001000100001000000100 +00100000100000010000100000100000 +00000110000010000001000110001010 +00000100011000001000000100001000 +10100000000001100100100000010000 +10000010000000000010000010000001 +00001000001000000100001000001000 +00000000100000100000010000100000 +10000001000010000010000000000110 +00001000000100001000000000010001 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000010001000100001100000101 +01000000100000010101000000100000 +01010101000011000001010101000011 +00000101010100001100000101010100 +00110000010101010000100000010101 +00000010000000010100000010000000 +01010000001000000101010000001000 +00000100000100110000000100000000 +10000000010100000011000001000101 +00001000000101010000000000010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +00000000000000010000001100000001 +00010000110000000101010000110000 +00010101000011000000010101001010 +00000001010100001000000001010100 +10100000000101010000100000000101 +01000011000000010101000010000000 +01010100001100000001010100001100 +00000101010000110000000101010000 +10000000010101000011000000010101 +00001000000001010100000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000010000100000000000 +00010010000000000001000000000000 +00000100000000000000000100000000 +00000000011000000000000000011000 +00000000000001000010000000000001 +00001000000000000100001000000000 +00010000100000000000010000100000 +01000001000100000000000001000010 +00000001000110000000000000000100 +00100000000000010000000000010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +00000000010001000100001100000010 +00010000100000001000000010100000 +00100000001010000000100000000010 +00000010000000001000000110000000 +00100000001000000000100000001000 +00000010000000100000000010000000 +10000000001000000010000000001000 +00001000000110100100001000000000 +10000000100000001010000000100000 +00001000000010000000000000110001 +01010000000000000000000000000000 +00000000000000000000000000000000 +00000000000001010100000000001001 +01100000000000010101100000000000 +00010110000000000000110110000000 +00000101011000000000001001011000 +00000000000101100100000010010101 +10000000000000010110000000000001 +01011000000000000101011000000000 +00011101100000000000011101100000 +00000001010110000000000010110110 +00000000001001011000000000010001 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000110001010100000000000010 +01100000000000011101100000000000 +00010110000000000000010111000000 +00000000011000000000000001001000 +00000000001101100000000000000101 +10000000000000010110000000000000 +10011000000000000011011000000000 +00000101110000000000000101110000 +00000000110010000000000000010111 +00000000000011011000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000100 +00110000000000000000110000000000 +01000011000000000000000110000000 +00000100001100000000000000001000 +00000001010000110100000000000000 +11000000000000000011000000000001 +00001100000000000100001100000000 +00010001100000000000010001100000 +00000000100010000000000001000110 +00000000000100001100000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000010000000000 +00110100000000000000110001101000 +00000011010000000001000010000100 +00000000001101000000000000001000 +00000000000000110101000000000000 +11010100000001000011010000000000 +00001101010000000000001101000000 +00000000100101001000000000100100 +00000000000010010000000000000010 +00000000000000001100000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000011000000001 +00110001010000010100110001010000 +00010011000101000001010011000110 +10000001001100010000000001001000 +01000000000100110101100000000100 +11000101000000010011000100000000 +01001100010100000001001100010100 +01010100111001011000010100110001 +00000000010010000101000001010011 +00010000000001001100000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000010001100000101 +01101000110000000101101000110000 +01000110100011000001010100100011 +10000101011010001100000001011010 +00110000010101101101110000010101 +10100011000001010110100011000001 +01011010000100000101001010001100 +00010001101000100000010101101000 +11000001010110100011000001010110 +10001100000100011000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000010000000000 +00100100000000000000100011000000 +00000010011000000000000010000100 +00000000001001000000000100001000 +00000000000000100100000000000000 +10010101000000000010010000000000 +00001001000000000000001001000000 +00000000100111000000000000110100 +00000000000010011000000000000010 +00000000000000001000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000100000000100 +01100010000100000001100000000100 +01000110000000010001000110000000 +01000100011000000001000100011000 +00000100010001100010000000010001 +10001000000001000110001000010001 +00011000100000000100001000100001 +00010001100000000100010000110010 +00010001000110000000010001000110 +00100001000100011000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000001000101 +01010000000100000101010000000000 +01000101000000100000000101000000 +01100101010100000001000100010100 +00000100010001010000000100010101 +01000000010101010101000000010001 +00010100000100000100010100000000 +00000101010000010000000100010000 +00010000010101000000010000000101 +00000001000101010100000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000100000100001 +01000010000000000001000010000010 +00010101001000001000000101001000 +00100001010100100000100000010100 +10000010000101010010000000000101 +00001000000000010100001000000000 +01010000100000000001010000100010 +10000101000010000010000101010010 +00001000010100001000001000010101 +00100000100001010000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000101000000001 +00000010100000000100000010100000 +01000000001010010000010000001010 +00000100000000101000000100000000 +10100000000100000010100000000100 +00001010000000010000001010000000 +01000000101000000001000000101001 +01000100000010100000000100000010 +10000000010000001010000000000000 +00101000000001000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000110010000011 +01010011000000000101010011000000 +00100001001100000000000101001100 +00000010000100110000000000000100 +11001000001000010011000000000101 +01001100000000010101001100100000 +11010100110000000011010100110001 +00001101010011000000001000010011 +00000000010101001100000000100001 +00110010000011010100000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000100010000101 +01110010000000010001110010000000 +01010111001000000001010111001000 +00001101011100100000001101011100 +10001000010101100010000000011001 +11001000000001000111001000001001 +01011100100000000100011100100000 +00001001110010000000011101100010 +00000001010111001000000001110111 +00100000100101011100000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000001100001000 +01001000110001000001000000110000 +10000100000011000000000100000011 +00001000010000001100000000010000 +00110000100001000000110000000001 +00000011000100000100100011000000 +00010000001100000000010010001100 +00000001000000110000000001001000 +11000000000100000011000100000100 +10001100001000010000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +01001111111111111101001111111111 +11110100111111111111110100111111 +11111111010011111111111111010011 +11111111111101000111111111011101 +00011111111111110100111111111111 +11010011111111111111010011111111 +11111101001111111111111101001111 +11111111110100111111111111110100 +11111111111111010000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111011 +00001011001101111101001111111111 +10110000101101111111110100111110 +11011011000010110011011011000010 +11011111101100000111101101011101 +00011110110111110100101101111111 +11010011111111111111010010110111 +11111101001111111111101100001011 +00110110110000101100110110110000 +10110111111011000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111100 +01001100110011111101001111111111 +11000100110011111111110100111111 +00111100010011001100111100010011 +00111111110001000111110011011101 +00011111001111110100110011111111 +11010011111111111111010011001111 +11111101001111111111110001001100 +11001111000100110011001111000100 +11001111111100010000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011101100011110 +01001110110111111001001000110111 +11100100100011011110000100100011 +00011110010010001100011000010010 +00110001111001000110110001011101 +00011011011111100100111011000111 +10010011101101111110010011101101 +11100001001000110111100001001110 +11000110000100100011011110000100 +11101100011110010000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000100000010 +01110000010000001001110000010000 +00100111000001000000100111000001 +00000010011100000100000010011100 +00010000001100110000010000001001 +11000001000000100111000001000001 +10011100000100010110011100000100 +00001001110000010000001001110000 +01000000100111000001000001100111 +00000100000110011100000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000010000000101 +01110001000000010101110001000000 +01010111000100000001010111000100 +00000101011100010000000101011100 +01000000010100110001000000010101 +11000100000001010111000100000001 +01011100010000000101011100010000 +00010101110001000000010101110001 +00000001010111000100000001010111 +00010000000101011100000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000001000000001 +00100000100000000100100000100000 +00010010000010000000010010000010 +00000001001000001000000001001000 +00100000000100100000100000000100 +10000010000000010010000010000000 +01001000001000000001001000001000 +00000100100000100000000100100000 +10000000010010000010000000010010 +00001000000001001000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01100000000000000001100000000000 +00000110000000000000000110000000 +00000000011000000000000000011000 +00000000000001100000000000000001 +10000000000000000110000000000000 +00011000000000010000011000000000 +00000001100000000001000001100000 +00000000000110000000000000000110 +00000000000000011000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000100000000100 +01110010000000010001110010000000 +01000111001000000001000111001000 +00000100011100100000000100011100 +10000000010001110010000000010001 +11001000000001000111001000000000 +00011100100000000000011100100000 +00010001110010000000010001110010 +00000001000111001000000000000111 +00100000000000011100000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01100000000000000001100000000000 +00000110000000000000000110000000 +00000000011000000000000000011000 +00000000000001100000000000000001 +10000000000000000110000000000000 +00011000000000000000011000000000 +00000001100000000000000001100000 +00000000000110000000000000000110 +00000000000000011000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000100000000100 +00100010000000010000100010000000 +01000010001000000001000010001000 +00000100001000100000000100001000 +10000000010000100010000000010000 +10001000000001000010001000000000 +00001000100000000000001000100000 +00010000100010000000010000100010 +00000001000010001000000000000010 +00100000000000001000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000010101000000100 +01001010100000010001001010100000 +01000100101010000001000100101010 +00000100010010101000000100010010 +10100000010001001010100000010001 +00101010000001000100101010000001 +00010010101000000000010010101000 +00010001001010100000010001001010 +10000001000100101010000001000100 +10101000000100010000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000110000000000110000000000 +01010011000000000001010011000000 +00000101001100000000000101001100 +00000000010100110000000000010100 +11000000000001010011000000000001 +01001100000000000101001100000000 +00010100110000000100010100110000 +00000001010011000000000001010011 +00000000000101001100000000000101 +00110000000000010100000000010000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000110000000000000000000000 +01000000000000000001000000000000 +00000100000000000000000100000000 +00000000010000000000000000010000 +00000001000001000000000000000001 +00000000000000000100000000000000 +00010000000000000000010000000000 +00000001000000000000000001000000 +00000000000100000000000000000100 +00000000000000010000000000110000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000110000000100000000000010 +00000000000000001000000000000000 +00100000000000000000100000000000 +00000010000000000000000010000000 +00000000001000000000000000001000 +00000000000000100000000000000000 +10000000000000000010000000000000 +00001000000000000000001000000000 +00000000100000000000000000100000 +00000000000010000000000000110000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000110000000100000000000100 +01100000000000010001100000000000 +01000110000000000000000110000000 +00000000011000000000000100011000 +00000000010001100000000000010001 +10000000000010000110000000000000 +00011000000000000000011000000000 +00010001100000000000000001100000 +00000001000110000000000000000110 +00000000000000011000000000110000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00010000000000010100000000000010 +01100000000000001001100000000000 +00100110000000000000100110000000 +00010110011000000000000010011000 +00000000001001100000000000001001 +10000000000000100110000000000000 +10011000000000000010011000000000 +00001001100000000000001001100000 +00000000100110000000000000100110 +00000000000010011000001000010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +01000000010001010100001000000100 +00110000100000010000110000100000 +01000011000010000001000011000010 +00000100001100001000000100001100 +00100000010000110000100000010000 +11000010000001000011000010000001 +00001100001000000100001100001000 +00010000110000100000010000110000 +10000001000011000010000001000011 +00001000000100001100000000010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +01000000000000000000000000000000 +00110000000000000000110000000000 +00000011000000000000000011000000 +00000000001100000000000000001100 +00000000000000110000000000000000 +11000000000000000011000000000000 +00001100000000000000001100000000 +00000000110000000000000000110000 +00000000000011000000000000000011 +00000000000000001100000000110001 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000000000000001000000000 +00110000100000000000110000100000 +00000011000010000000000011000010 +00000000001100001000000000001100 +00100000000000110000100000000000 +11000010000000000011000010000000 +00001100001000000000001100001000 +00000000110000100000000000110000 +10000000000011000010000000000011 +00001000000000001100000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000010001010100001000000100 +01100000100000010001100000100000 +01000110000010000001000110000010 +00000000011000001000000100011000 +00100000010001100000100000010001 +10000010000001000110000010000001 +00011000001000000100011000001000 +00010001100000100000010001100000 +10000001000110000010000001000110 +00001000000100011000000000010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +01000000000000010100001000000000 +00100000100000000000100000100000 +00000010000010000000000010000010 +00000000001000001000000000001000 +00100000000000100000100000000000 +10000010000000000010000010000000 +00001000001000000000001000001000 +00000000100000100000000000100000 +10000000000010000010000000000010 +00001000000000001000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01010000010000010100001000000100 +01100000100000010001100000100000 +01000110000010000001000110000010 +00000000011000001000000100011000 +00100000010001100000100000010001 +10000010000001000110000010000001 +00011000001000000100011000001000 +00010001100000100000010001100000 +10000001000110000010000001000110 +00001000000100011000000000010000 +01000000000000000000000000000000 +00000000000000000000000000000000 +01000000010001010100000000000100 +01010000000000010001010000000000 +01000101000000000001000101000000 +00000000010100000000000100010100 +00000000010001010000000000010001 +01000000000001000101000000000001 +00010100000000000100010100000000 +00010001010000000000010001010000 +00000001000101000000000001000101 +00000000000100010100001000010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +01001000010000010000011000000000 +01000001100000000001000001100000 +00000100000110000000000100000110 +00000100010000011000000000010000 +01100000000001000001100000000001 +00000110000000000100000110000000 +00010000011000000000010000011000 +00000001000001100000000001000001 +10000000000100000110000000000100 +00011000000000010000000000010000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01001000000001000000001000000001 +00000000100000000100000000100000 +00010000000010000000010000000010 +00000001000000001000000001000000 +00100000000100000000100000000100 +00000010000000010000000010000000 +01000000001000000001000000001000 +00000100000000100000000100000000 +10000000010000000010000000010000 +00001000000001000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000010001010100011000000011 +01010001100000001101010001100000 +00110101000110000000110101000110 +00000011010100011000000011010100 +01100000001101010001100000001101 +01000110000000110101000110000000 +11010100011000000011010100011000 +00001101010001100000001101010001 +10000000110101000110000000110101 +00011000000011010100000000010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +00000000000000010000011000000100 +01110001100000010001110001100000 +01000111000110000001000111000110 +00000100011100011000000100011100 +01100000010001110001100000010001 +11000110000001000111000110000001 +00011100011000000100011100011000 +00010001110001100000010001110001 +10000001000111000110000001000111 +00011000000100011100000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000000010100011000000000 +01110001100000001001110001100000 +00100111000110000000100111000110 +00000010011100011000010110011100 +01100000001001110001100000001001 +11000110000000100111000110000000 +10011100011000000010011100011000 +00011001110001100000001001110001 +10000000100111000110000000100111 +00011000000010011100000000010001 +00010000000000000000000000000000 +00000000000000000000000000000000 +01010000010001010100011000000001 +01110001100000010101110001100000 +01010111000110000001010111000110 +00000101011100011000000101011100 +01100000010101110001100000010101 +11000110000001010111000110000001 +01011100011000000101011100011000 +00010101110001100000010101110001 +10000001010111000110000001010111 +00011000000101011100001000010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +01000000000000010000001000000001 +00100000100000000100100000100000 +00010010000010000000010010000010 +00000001001000001000000001001000 +00100000000100100000100000000100 +10000010000000010010000010000000 +01001000001000000001001000001000 +00000100100000100000000100100000 +10000000010010000010000000010010 +00001000000001001000000000010001 +01000000000000000000000000000000 +00000000000000000000000000000000 +01000000000000000000011000000000 +01100001100000000001100001100000 +00000110000110000000000110000110 +00000000011000011000000000011000 +01100000000001100001100000000001 +10000110000000000110000110000000 +00011000011000000000011000011000 +00000001100001100000000001100001 +10000000000110000110000000000110 +00011000000000011000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000010001010110000000000100 +01111000000000010001111000000000 +01000111100000000001000111100000 +00000100011110000000000000011110 +00000000010001111000000000010001 +11100000000001000111100000000001 +00011110000000000100011110000000 +00000001111000000000010001111000 +00000001000111100000000001000111 +10000000000100011100000000010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +01000000000000010100001000000000 +01100000100000000001100000100000 +00000110000010000000000110000010 +00000000011000001000000000011000 +00100000000001100000100000000001 +10000010000000000110000010000000 +00011000001000000000011000001000 +00000001100000100000000001100000 +10000000000110000010000000000110 +00001000000000011000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000000010100001000000100 +00100000100000010000100000100000 +01000010000010000001000010000010 +00000100001000001000000000001000 +00100000010000100000100000010000 +10000010000001000010000010000001 +00001000001000000100001000001000 +00000000100000100000010000100000 +10000001000010000010000001000010 +00001000000100001000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000010001010100001000000100 +01000000100000010001000000100000 +01000100000010000001000100000010 +00000100010000001000000100010000 +00100001010001000000100000010001 +00000010000001000100000010000001 +00010000001000000100010000001000 +00010001000000100000010001000000 +10000001000100000010000001000100 +00001000000100010000000000010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +01000000000000000000001100000001 +00000000110000000001010000110000 +00000101000011000000000101000011 +00000000010100001100000000010100 +00110000000001010000110000000001 +01000011000000000101000011000000 +00010100001100000000010100001100 +00000001010000110000000001010000 +11000000000101000011000000000101 +00001100000000010100000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000000000000100000000100 +01000010000000000001000010000001 +00000100001000000000000100001000 +00000000010000100000000000010000 +10000000000001000010000000000001 +00001000000000000100001000000000 +00010000100000000000010000100000 +00000000000010000000000001000010 +00000000000100001000000000000100 +00100000000000010000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000010001010100001000000000 +00000000100000001000000000100000 +00100000000010000000100000000010 +00000010000000001000000010000000 +00100000001000000000100000001000 +00000010000000100000000010000000 +10000000001000000010000000001000 +00001000000000100000001000000000 +10000000100000000010000000100000 +00001000000010000000000000010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +01000000000000010100000000000100 +01100000000000010001100000000000 +01000110000000000001000110000000 +00000100011000000000000000011000 +00000000010001100000000000010001 +10000000000001000110000000000001 +00011000000000000100011000000000 +00100100100000000000010001100000 +00000001000110000000000001000110 +00000000000100011000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000000010100000000000010 +01100000000000001001100000000000 +00000110000000000000100110000000 +00000010011000000000000010011000 +00000000001001100000000000001001 +10000000000100100110000000000000 +10011000000000000110011000000000 +00001001100000000000001001100000 +00000000100110000000000100100110 +00000000000010011000000000000001 +00010000000000000000000000000000 +00000000000000000000000000000000 +01000000010001010110000000000100 +00111000000000010000111000000000 +00000011100000000001000011100000 +00000100001110000000000100001110 +00000000010000111000000000010000 +11100000000000000011100000000001 +00001110000000000100001110000000 +00010000111000000000010000111000 +00000001000011100000000001000011 +10000000000100001100000000010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +01010000000000000000000100000000 +00110000010000000000110000010000 +00000011000001000000000011000001 +00000000001100000100000000001100 +00010000000000110000010000000000 +11000001000000000011000001000000 +00001100000100000000001100000100 +00000000110000010000000000110000 +01000000000011000001000000000011 +00000100000000001100000000000001 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000000000000010100000000 +00110001010000000000110001010000 +00000011000101000000000011000101 +00010000001100010100000000001100 +01010000000000110001010000000000 +11000101000000000011000101000000 +00001100010100000000001100010100 +00000000110001010000000000110001 +01000000000011000101000000000011 +00010100000000001100001000010000 +01000000000000000000000000000000 +00000000000000000000000000000000 +01000000010001010100001100000100 +01100000110000010001100000110000 +01000110000011000001000110000011 +00000100011000001100000100011000 +00110000010001100000110000010001 +10000011000001000110000011000001 +00011000001100000000011000001100 +00010001100000110000010001100000 +11000001000110000011000001000110 +00001100000100011000000000010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +01000000000000010100000000000000 +00100000000000000000100000000000 +00000010000000000000000010000000 +00000000001000000000000000001000 +00000000000000100000000000000000 +10000000000000000010000000000000 +00001000000000000000001000000000 +00000000100000000000000000100000 +00000000000010000000000000000010 +00000000000000001000000000110000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000000000010000100001000100 +01100010000100010001100010000100 +01000110001000010001000110001000 +01000100011000100001000100011000 +10000100010001100010000100010001 +10001000010001000110001000010001 +00011000100001000000011000100001 +00010001100010000100010001100010 +00010001000110001000010001000110 +00100001000100011000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +01000000010001010100000001000100 +01010000000100010001010000000100 +01000101000000010001000101000000 +01000100010100000001000100010100 +00000100010001010000000100010001 +01000000010001000101000000010001 +00010100000001000100010100000001 +00010100000000000100010001010000 +00010001000101000000010001000101 +00000001000100010100000000010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +01000000000001010000100000100000 +01000010000010000001000010000010 +00000100001000001000000100001000 +00100000010000100000100000010000 +10000010000001000010000010000001 +00001000001000000100001000001000 +00010000100000100000010000100000 +10000001000010000010000001000010 +00001000000100001000001000000100 +00100000100000010000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000101000000001 +00000010100000000100000010100000 +01010000001010000000010000001010 +00000001000000101000010001000000 +10100000000100000010100000000100 +00001010000000010000001010000000 +01000000101000000001000000101000 +00000100000010100000000100000010 +10000000010000001010000000010000 +00101000000001000000000000010001 +01000000000000000000000000000000 +00000000000000000000000000000000 +01000000010001010100110100000011 +01010011010000001101010011010000 +00010101001101000000110101001101 +00000011010100110100000011010100 +11010000001101010011010000001101 +01001101000000010101001101000000 +11010100110100000011010100110100 +00001101010011010000001101010011 +01000000110101001101000000110101 +00110100000011010100000000010001 +01010000000000000000000000000000 +00000000000000000000000000000000 +01000000000000010100100000000100 +01110010000000010001110010000000 +01000111001000000001000111001000 +00000000011100100000000100011100 +10000000010001110010000000010001 +11001000000001000111001000000001 +00011100100000000000011100100000 +00010001110010000000010001110010 +00000001000101001000000001000111 +00100000000100011100000000110001 +00010000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000010001100011000 +01001000110001100001001000110001 +10000100100011000110000100100011 +00011000010010001100011000010010 +00110001100001001000110001100001 +00100011000110000100100011000110 +00010010001100011000010010001100 +01100001001000110001100001001000 +11000110000100100011000110000100 +10001100011000010000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +01001111111111111101001111111111 +11110100111111111111110100111111 +11111111010011111111111111010011 +11111111111101001111111111111101 +00111111111111110100111111111111 +11010011111111111111010011111111 +11111101001111111111111101001111 +11111111110100111111111111110100 +11111111111111010000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000010110011011011 +00001011001101101100001011001101 +10110000101100110110110000101100 +11011011000010110011011011000010 +11001101101100001011001101101100 +00101100110110110000101100110110 +11000010110011011011000010110011 +01101100001011001101101100001011 +00110110110000101100110110110000 +10110011011011000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011001100111100 +01001100110011110001001100110011 +11000100110011001111000100110011 +00111100010011001100111100010011 +00110011110001001100110011110001 +00110011001111000100110011001111 +00010011001100111100010011001100 +11110001001100110011110001001100 +11001111000100110011001111000100 +11001100111100010000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011101101111110 +01001110110111111001001110110111 +11100100111011011111100100111011 +01111110010011101101111110010011 +10110111111001001110110111111001 +00111011011111100100111011011111 +10010011101101111110010011101101 +11111001001110110111111001001110 +11011111100100111011011111100100 +11101101111110010000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000001010000101 +00100000001000010000000100101000 +01000001000010100001000000010010 +10000010001100001010000011000101 +00101000010000000000101000011000 +00010010100001000010000010100001 +00000000001010000111000100001010 +00010100000000001000010000101100 +10100001000000000010010001000010 +00001001000100001000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000100 +00010000000100010000010000000000 +01000010001010000001000000111000 +00000110000001000000000100001000 +00000000010100110010000000010100 +00011000000001010011010000000001 +11000000000000000111000100000000 +00010000000000000000010000111000 +00000001000000000010010001000000 +00000000000100000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011000010000101 +00100100100000010000100000000000 +01000011000000100001000010000000 +10000101001000000001000100001000 +00001000011000100000001000011000 +10000000100001110011001000100001 +11001010000010000111001000000010 +00010100000100101000010000100000 +00100001000000110000000001000010 +00000001000100001000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000101 +00000000100100010000101100000000 +01000011000000000001000010000000 +00000100001000000001000100001111 +00000000010000110000000000010000 +10000000000001110000010000000001 +10001011000000000101001100000000 +00010100000000000000010000010000 +00000001000000000000000001000010 +00000000000100001000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000010000000 +00010100001000001100110100001000 +00000001000010100000010011000000 +10000001000001000010000011000001 +00001000001100000000001000000000 +00010000100000110001010000100000 +00001000000010000000000000000010 +00000100110100001000000000110000 +00100000000000000000000000000000 +00000010000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000000000000001000000001 +00000000100100000000000000000000 +00000010000000000000010001000010 +00000011000000001000000000001000 +00100000000100000000100000001000 +00000010000000100000000010000000 +00000000001000000000000000001000 +00000100100000100000000100110000 +10000000000000000000000000000000 +00001000000000000000001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000000000001000010000001 +00100010101000000000100110001100 +00000001001000100000100010001000 +10000011000001100010000000001010 +10001000001100000010001000000100 +00001000100000010010111000100000 +00001000100010000000000000100010 +00000000111110001000000100111110 +00100000000010011000110000000010 +00100010000000001000001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000000000000100000000011 +00000010000000001100110110100000 +00000001001010000000010001001000 +00000010000000100000000000001000 +10000000001000000000000000000000 +00001000000000000010001000000000 +00001010100000000000000000100000 +00001000110010000000001100011010 +00000000000010001010010000000010 +00100000000000001000001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000000000011101010000111 +00101010001000010000010010101000 +01000011001000010001000010001000 +10000101000100101010000101000000 +10101000011000000010101000010000 +01001010100001100001001010100001 +10000001101010000100000100101010 +00010100111010001000010100000010 +00100001000000001000100001000000 +00100010000100000000001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000000000001100000000100 +00101110000000010000100010000000 +01000011001010000001000011101000 +00000101000010100000000100000001 +10000000011100000010000000010000 +11101010000001010010011000000001 +00001100100000000100001100100000 +00010100110110100000011100100110 +00000001000001111000000001000001 +00101001000100000000001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000000000000000010000100 +00000000101000010000110100000100 +01000011000000100001000010100010 +10000000001010000010000101001010 +00001000011100000000001000010000 +11010000100001100001100000100000 +01001000000010000101001000000010 +00010100100000001000011100110000 +10100001000010100000100001000010 +00000010000100001000001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000100000000000000000111 +00100000000000010000110000000000 +01000001010010000001000011010010 +00000110000001000000000101001000 +00000000011000110100000000011100 +01110000000001010011010000000001 +01000000000000000101000001000000 +00011100100000100100011000100000 +10000001110001000000000001110001 +00000000000100001000001000000100 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000000000010000010000111 +00000100101000010000100000100000 +01110000010000100001010000010000 +10000101001101000010000111001110 +00001000010100100000001000011100 +01000010100001110000000000100001 +00000001000010000111001110000010 +00011000100000001000011100010000 +00100001110011010000100001000000 +00000001000100001000001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000001001000000001 +00001000000000000000010100000100 +01000010000000000000100010100010 +00000101000110001000000100001000 +00000000001000100100100000010000 +01000000000001000010100010000000 +00000000001000000111000001001000 +00010100100100000000011000100000 +10000001000000000000000000000011 +11000000000000000100000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000010000001 +00100100101000000000100100000000 +01000010010010100000010011000010 +10000111001001000010000100001110 +00001000000100110100001000010000 +10000000100001000011100000100000 +00001000000010000111000001000010 +00010100000000101000010100111000 +10100001000000000000000000000010 +01000010000000001000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000100001000000000000011 +00100000100000000000000100100100 +00000001100010000000000011000000 +00000001001100000000000011001000 +00100000000100101000000000000000 +00100010000000000010000000000000 +00001001000000000010001100000000 +00001100001000100100000100101000 +00000000110011010010000000000001 +00001000000000001000000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000001000000010000 +01000000100000000000000000000000 +00000000000000000001000000010000 +00000000000000000000000000000000 +00000000000100000000000000000000 +10010000000000000000000000000000 +00000000000000000001000000000000 +00000000100100000010000000000000 +00000000000000000000000000000000 +00000000001000001000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00111100001111000011000000000000 +10000000100000000000000000000000 +00010000000000000000000000110000 +10000000000000001000000000000000 +00000000000100000010000000010000 +00110000100000000000000010000000 +00000000000000000000000000100000 +00010000001100000000000000000000 +01000000000000000000000000010000 +00000000000000000000111100001111 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000011001 +10000000000110011000000000111111 +11011001101111111101100110000000 +00011001101111111101100100000000 +00011111101100101011100011001111 +10000000000000000001100110100110 +00000000000000011000111101001011 +01101000010000000001100110000000 +00011001110000000011111111011001 +10111111110110011000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000001000000000111110 +10111110101111101011111010000000 +00000000000000000010000000000000 +00010010000100101000011010000010 +00010110100000000001011010100000 +00000000000001100000010000000000 +00010000000000000000000000000000 +00000000000000000010100000010000 +00111110100101101100000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000010001000 +01000100100000010100000110000000 +00000000000000000000000000000000 +11000000000000000000000000000000 +00000000000000000000000000000000 +00000000110000000000000000000000 +00000000000000000000000000000000 +00000000000000001000000101111000 +01000001101100010000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111101111111111111111111111 +11000000000000000000000000000000 +00000000001111111111111111101111 +11111101110000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000101101 +11111111101011101111111111000000 +00000000000000000000000000000000 +00111111101111111111111111111110 +00000000000000000000000000000000 +00000000001101111111111011111111 +01111111110000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111101 +11111111111111111011111111000000 +00000000000000000000000000000000 +00111111101111111111111111111111 +11000000000000000000000000000000 +00000000001111111111111111111111 +11111111110000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111111111111111111111111111 +11000000000000000000000000000000 +00000000001111111111111111111111 +11111111110000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111111111111111111100111111 +11000000000000000000000000000000 +00000000001111111111111111111111 +11111111110000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111101111111111111111000000 +00000000000000000000000000000000 +00111111111111111011111111111111 +11000000000000000000000000000000 +00000000001111111111111100111111 +11111111110000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000011000111 +00100100101000010000100000001000 +01000001000000100001000010010010 +10000100000000001010000000001000 +00101000010000010000101000011000 +10110010110001010000010010100001 +00001000001010000100000100001010 +00010000101100101000011100000100 +10110001000001000000100001000000 +00000010000100000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000001000111 +00010000100000010000110000000000 +01000011000000000001000001110000 +00000101000010000000000000001001 +00000000010000100000000000011100 +01000000000001100000100000000001 +00000000000000000111001000000000 +00010000001000000000011100101100 +00000001000010000000000001000000 +00000000000100000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000001000011000111 +00101000001000010000100100101100 +01000011000010100001000010000000 +10000110000001000010000000001000 +00001000010000010000001100011100 +10000000100001010000010000100001 +00001000000010000101000000000001 +00010000100000001000011100000000 +00000001000011000000010001000000 +00001010000100000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000001000000000100 +00101000000000010000010100000000 +01000011000000000001000010000000 +00000100000001000000000000001101 +00000000010000000000000000011000 +00000000000001010000010000000001 +00000010000000000110000100000001 +00010000100000000000010000010000 +00010001000010110010000001000000 +00001000000100000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000010001011000000 +00100000101000000000000100001000 +00000010000000100000000010000000 +10000000000000000010000000000101 +00001000001100100000001000000100 +00100000110000000000000000100000 +10001001000010000010000000000010 +00001100000000000100000000000000 +00110000000000010000010000000000 +00000001000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000000000000000001000000 +00000000000000000000010000100000 +00000000000010000000000001000010 +00000000000000001000000000001100 +00100000000100010000100000001000 +00000010000000000000000010000000 +01000000001000000001000000001000 +00001100010000100100000000100000 +10000000000000000010000000000001 +00001000000000000100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000001101000000000 +00100110001000000000100110101100 +00000010001000100000010010001000 +10000001000001100010000000001101 +10001000001100100010001100000100 +10011000100000000000011000100000 +10001001100010000010000000100010 +00001100100010000100000000011110 +00100000000010011000000000000010 +00101010000000001000001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000000000010100000000000 +00000110100000000000000010000000 +00000010001000000000010000001000 +00000001000000100000000000000010 +10000000001000000010000000000000 +10001000000000000000011000000000 +00001000100000000000000000100000 +00000100000110000100000000001010 +00000000000010001000000000000010 +00100000000000001000001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000000000000101010000111 +00101010101000010000010110001000 +01000001001010100001000010001010 +10000101000100101010000110000001 +10101000011000000010101000010000 +01101000100001010001001010100001 +01000001101010000100000000101001 +00010100000010100000011100100010 +10000001000001011010000001000001 +00101001000100000000001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000000000010100000000111 +00110010000000010000110010000000 +01010011001000000001000001101000 +00000111000010100000000101000100 +10000000011100100010000000010000 +10101000000001100010001010000001 +10001000100000000100000000100001 +00011000110010000100011100010110 +00000001000010001000010001000010 +00100001000100000100001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000010000111 +00110000001000010000110100001000 +01000010000000010001000010100000 +10000111001010000010000110001000 +00001000010100010000001000010000 +01000010100001010000100000100001 +01000101000010000101000000000010 +00010100111000001000011100100000 +00100001000001100000000001000001 +00000001000100001000001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000100000001000000000111 +00010100000000011100010000100000 +01100011000000000001110001000000 +00000101000111000000000101001100 +00000000010100100000000000011100 +11000010000001110011010000000001 +11001100000000000101000010000000 +00011100010100000100011100010100 +00000001110011000000010001110010 +00000001000111001100001000000100 +00000000000000000000000000000000 +00000000000000000000000000000000 +00001000000000000000001010000100 +00001000001000010000000000001000 +01000010010000010001000010000000 +10000111000000000010000101000010 +00001000010000100000001000010100 +00010000100001110010100010100001 +01001010000010000101000000000010 +00011100000000001000010100100000 +00110001100001100000010001000010 +01000010000100000000001000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000001000000000000 +00000100100000000000000100100000 +00000010000010000000000011110010 +00000011000010001000000010001001 +00100000000100100000100000001000 +01100010000001000010000000000000 +10000001001000000011000000001000 +00011000100100100000001000101000 +10000000010010010010000000000010 +00001001000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000001000010000000 +00100100001000000000100000101000 +00000011000000100000000010010000 +10000011001001000010000001001100 +00001000000000111100001000000100 +10010010100001000010100000100000 +01001000000010000011000001000001 +00010100100000000100000100101000 +00100000000011000000010000000010 +01000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000100001010001000000000 +00100000000000000000101000000000 +00000010100000010000000011000000 +00000001001000000000000001001000 +00000000001000111000000000000000 +10000000000000110010000010000000 +00000000000000000000000010000001 +00000000100100000000000000110000 +00000000100010000000000000000011 +10000001000000000000000000000100 +00100000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000001000000000000 +01000000000000000000000000000000 +00000000000000000001000000010000 +00000000000000000000000000000000 +00000000000100000000000000000000 +10010000000000000000000000000000 +00000000000000000001000010000000 +00100000100100000000000000000000 +00000000000000000000000000000000 +00000000001000001000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00111100001111000011000000000000 +10100000000000000000000000000000 +00010000000000000000000000110000 +10000000000000001000000000000000 +00000000000000000010000000010000 +10110000100000000000000010000000 +00000000000000000001000000100000 +00010000101100000000000001000000 +11000000000000000000000000010000 +00000000000000000000111100001111 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000100000000111111 +11011001101111111101100110000000 +00100110010110011001100100000000 +00011111001100010111100000011101 +11011001100000000010011001000000 +00000000000010001000001111001000 +01101111100000000001100110000000 +00000000110000000011111111011001 +10111111110110011000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000101000 +00101001001010000010000001000000 +00000000000000000010000010000000 +00000100100001101000010010000110 +00000000000000000000000000100000 +10000000000000101001001000010000 +10000100000000000000000000000000 +00000000100000000010100000000000 +00101000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000010000100 +10000001000000010101000100000000 +00000000000000000000000000000000 +11000000000000000000000000000000 +00000000000000000000000000000000 +00000000100000000000000000000000 +00000000000000000000000000000000 +00000000000000001000000101111000 +01001000101100010100000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000101111 +11111011111111111110111111000000 +00000000000000000000000000000000 +00011111100111111001111111011111 +11000000000000000000000000000000 +00000000001011111111111111111111 +11110111110000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +01011111010011101111111111000000 +00000000000000000000000000000000 +00101111011011110110111111111101 +01000000000000000000000000000000 +00000000001111110011111101001111 +11111111110000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000011111 +11111111101111111111111111000000 +00000000000000000000000000000000 +00101111001111111011111111111111 +11000000000000000000000000000000 +00000000001111110111111110111111 +11111111110000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111111111111111111111111111 +11000000000000000000000000000000 +00000000001111111111111011111111 +11111111110000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111111111111111111110111111 +11000000000000000000000000000000 +00000000001111111111111111111111 +11111111110000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000011111111111111 +11111111111111111100000000000000 +00000000000000000000000000111111 +11111111111111111111111111000000 +00000000000000000000000000000000 +00111111111111111111111111111111 +11000000000000000000000000000000 +00000000001111111111111111111111 +11111111110000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00110000000000000010000000000001 +00000010000000000000000000000000 +00110000000000000100001100001100 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00110000000000000010000000000001 +00000010000000100000000000000000 +00110000000000000100001100000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00110000000000000000000000000001 +00000000000000001010100001101000 +00110000000000001000000000000001 +00000000000000000000000000000011 +00110000000000000100000000001100 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00110000000000001000000000000001 +00000000000000000000000000000101 +00110000000000001010000000000001 +00000000000000000000000000000000 +00110000000000000000000000000001 +00000000000000001110000101011010 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 diff --git a/kernel/wcfxo.c b/kernel/wcfxo.c new file mode 100644 index 0000000..5f48051 --- /dev/null +++ b/kernel/wcfxo.c @@ -0,0 +1,1103 @@ +/* + * Wilcard X100P FXO Interface Driver for Zapata Telephony interface + * + * Written by Mark Spencer + * Matthew Fredrickson + * + * Copyright (C) 2001, Linux Support Services, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef STANDALONE_ZAPATA +#include "zaptel.h" +#else +#include +#endif +#ifdef LINUX26 +#include +#endif + +/* Uncomment to enable tasklet handling in the FXO driver. Not recommended + in general, but may improve interactive performance */ + +/* #define ENABLE_TASKLETS */ + +/* Un-comment the following for POTS line support for Japan */ +/* #define JAPAN */ + +/* Un-comment for lines (eg from and ISDN TA) that remove */ +/* phone power during ringing */ +/* #define ZERO_BATT_RING */ + +#define WC_MAX_IFACES 128 + +#define WC_CNTL 0x00 +#define WC_OPER 0x01 +#define WC_AUXC 0x02 +#define WC_AUXD 0x03 +#define WC_MASK0 0x04 +#define WC_MASK1 0x05 +#define WC_INTSTAT 0x06 + +#define WC_DMAWS 0x08 +#define WC_DMAWI 0x0c +#define WC_DMAWE 0x10 +#define WC_DMARS 0x18 +#define WC_DMARI 0x1c +#define WC_DMARE 0x20 + +#define WC_AUXFUNC 0x2b +#define WC_SERCTL 0x2d +#define WC_FSCDELAY 0x2f + + +/* DAA registers */ +#define WC_DAA_CTL1 1 +#define WC_DAA_CTL2 2 +#define WC_DAA_DCTL1 5 +#define WC_DAA_DCTL2 6 +#define WC_DAA_PLL1_N1 7 +#define WC_DAA_PLL1_M1 8 +#define WC_DAA_PLL2_N2_M2 9 +#define WC_DAA_PLL_CTL 10 +#define WC_DAA_CHIPA_REV 11 +#define WC_DAA_LINE_STAT 12 +#define WC_DAA_CHIPB_REV 13 +#define WC_DAA_DAISY_CTL 14 +#define WC_DAA_TXRX_GCTL 15 +#define WC_DAA_INT_CTL1 16 +#define WC_DAA_INT_CTL2 17 +#define WC_DAA_INT_CTL3 18 +#define WC_DAA_INT_CTL4 19 + + +#define FLAG_EMPTY 0 +#define FLAG_WRITE 1 +#define FLAG_READ 2 + +#ifdef ZERO_BATT_RING /* Need to debounce Off/On hook too */ +#define JAPAN +#endif + +#define RING_DEBOUNCE 64 /* Ringer Debounce (in ms) */ +#ifdef JAPAN +#define BATT_DEBOUNCE 30 /* Battery debounce (in ms) */ +#define OH_DEBOUNCE 350 /* Off/On hook debounce (in ms) */ +#else +#define BATT_DEBOUNCE 80 /* Battery debounce (in ms) */ +#endif + +#define MINPEGTIME 10 * 8 /* 30 ms peak to peak gets us no more than 100 Hz */ +#define PEGTIME 50 * 8 /* 50ms peak to peak gets us rings of 10 Hz or more */ +#define PEGCOUNT 5 /* 5 cycles of pegging means RING */ + +#define wcfxo_printk(level, span, fmt, ...) \ + printk(KERN_ ## level "%s-%s: %s: " fmt, #level, \ + THIS_MODULE->name, (span).name, ## __VA_ARGS__) + +#define wcfxo_notice(span, fmt, ...) \ + wcfxo_printk(NOTICE, span, fmt, ## __VA_ARGS__) + +#define wcfxo_dbg(span, fmt, ...) \ + ((void)((debug) && wcfxo_printk(DEBUG, span, "%s: " fmt, \ + __FUNCTION__, ## __VA_ARGS__) ) ) + +struct reg { + unsigned long flags; + unsigned char index; + unsigned char reg; + unsigned char value; +}; + +static int wecareregs[] = +{ + WC_DAA_DCTL1, WC_DAA_DCTL2, WC_DAA_PLL2_N2_M2, WC_DAA_CHIPA_REV, + WC_DAA_LINE_STAT, WC_DAA_CHIPB_REV, WC_DAA_INT_CTL2, WC_DAA_INT_CTL4, +}; + +struct wcfxo { + struct pci_dev *dev; + char *variety; + struct zt_span span; + struct zt_chan chan; + int usecount; + int dead; + int pos; + unsigned long flags; + int freeregion; + int ring; + int offhook; + int battery; + int wregcount; + int readpos; + int rreadpos; + unsigned int pegtimer; + int pegcount; + int peg; + int battdebounce; + int nobatttimer; + int ringdebounce; +#ifdef JAPAN + int ohdebounce; +#endif + int allread; + int regoffset; /* How far off our registers are from what we expect */ + int alt; + int ignoreread; + int reset; + /* Up to 6 register can be written at a time */ + struct reg regs[ZT_CHUNKSIZE]; + struct reg oldregs[ZT_CHUNKSIZE]; + unsigned char lasttx[ZT_CHUNKSIZE]; + /* Up to 32 registers of whatever we most recently read */ + unsigned char readregs[32]; + unsigned long ioaddr; + dma_addr_t readdma; + dma_addr_t writedma; + volatile int *writechunk; /* Double-word aligned write memory */ + volatile int *readchunk; /* Double-word aligned read memory */ +#ifdef ZERO_BATT_RING + int onhook; +#endif +#ifdef ENABLE_TASKLETS + int taskletrun; + int taskletsched; + int taskletpending; + int taskletexec; + int txerrors; + int ints; + struct tasklet_struct wcfxo_tlet; +#endif +}; + +#define FLAG_INVERTSER (1 << 0) +#define FLAG_USE_XTAL (1 << 1) +#define FLAG_DOUBLE_CLOCK (1 << 2) +#define FLAG_RESET_ON_AUX5 (1 << 3) +#define FLAG_NO_I18N_REGS (1 << 4) /*!< Uses si3035, rather si3034 */ + +struct wcfxo_desc { + char *name; + unsigned long flags; +}; + + +static struct wcfxo_desc wcx100p = { "Wildcard X100P", + FLAG_INVERTSER | FLAG_USE_XTAL | FLAG_DOUBLE_CLOCK }; + +static struct wcfxo_desc wcx101p = { "Wildcard X101P", + FLAG_USE_XTAL | FLAG_DOUBLE_CLOCK }; + +static struct wcfxo_desc generic = { "Generic Clone", + FLAG_USE_XTAL | FLAG_DOUBLE_CLOCK }; + +static struct wcfxo *ifaces[WC_MAX_IFACES]; + +static void wcfxo_release(struct wcfxo *wc); + +static int debug = 0; + +static int monitor = 0; + +static int quiet = 0; + +static int boost = 0; + +static int opermode = 0; + +static struct fxo_mode { + char *name; + int ohs; + int act; + int dct; + int rz; + int rt; + int lim; + int vol; +} fxo_modes[] = +{ + { "FCC", 0, 0, 2, 0, 0, 0, 0 }, /* US */ + { "CTR21", 0, 0, 3, 0, 0, 3, 0 }, /* Austria, Belgium, Denmark, Finland, France, Germany, + Greece, Iceland, Ireland, Italy, Luxembourg, Netherlands, + Norway, Portugal, Spain, Sweden, Switzerland, and UK */ +}; + +static inline void wcfxo_transmitprep(struct wcfxo *wc, unsigned char ints) +{ + volatile int *writechunk; + int x; + int written=0; + unsigned short cmd; + + /* if nothing to transmit, have to do the zt_transmit() anyway */ + if (!(ints & 3)) { + /* Calculate Transmission */ + zt_transmit(&wc->span); + return; + } + + /* Remember what it was we just sent */ + memcpy(wc->lasttx, wc->chan.writechunk, ZT_CHUNKSIZE); + + if (ints & 0x01) { + /* Write is at interrupt address. Start writing from normal offset */ + writechunk = wc->writechunk; + } else { + writechunk = wc->writechunk + ZT_CHUNKSIZE * 2; + } + + zt_transmit(&wc->span); + + for (x=0;xflags & FLAG_INVERTSER) + writechunk[x << 1] = cpu_to_le32( + ~((unsigned short)(ZT_XLAW(wc->chan.writechunk[x], (&wc->chan)))| 0x1) << 16 + ); + else + writechunk[x << 1] = cpu_to_le32( + ((unsigned short)(ZT_XLAW(wc->chan.writechunk[x], (&wc->chan)))| 0x1) << 16 + ); + + /* We always have a command to follow our signal */ + if (!wc->regs[x].flags) { + /* Fill in an empty register command with a read for a potentially useful register */ + wc->regs[x].flags = FLAG_READ; + wc->regs[x].reg = wecareregs[wc->readpos]; + wc->regs[x].index = wc->readpos; + wc->readpos++; + if (wc->readpos >= (sizeof(wecareregs) / sizeof(wecareregs[0]))) { + wc->allread = 1; + wc->readpos = 0; + } + } + + /* Prepare the command to follow it */ + switch(wc->regs[x].flags) { + case FLAG_READ: + cmd = (wc->regs[x].reg | 0x20) << 8; + break; + case FLAG_WRITE: + cmd = (wc->regs[x].reg << 8) | (wc->regs[x].value & 0xff); + written = 1; + /* Wait at least four samples before reading */ + wc->ignoreread = 4; + break; + default: + printk("wcfxo: Huh? No read or write??\n"); + cmd = 0; + } + /* Setup the write chunk */ + if (wc->flags & FLAG_INVERTSER) + writechunk[(x << 1) + 1] = cpu_to_le32(~(cmd << 16)); + else + writechunk[(x << 1) + 1] = cpu_to_le32(cmd << 16); + } + if (written) + wc->readpos = 0; + wc->wregcount = 0; + + for (x=0;xoldregs[x] = wc->regs[x]; + wc->regs[x].flags = FLAG_EMPTY; + } + +} + +static inline void wcfxo_receiveprep(struct wcfxo *wc, unsigned char ints) +{ + volatile int *readchunk; + int x; + int realreg; + int realval; + int sample; + if (ints & 0x04) + /* Read is at interrupt address. Valid data is available at normal offset */ + readchunk = wc->readchunk; + else + readchunk = wc->readchunk + ZT_CHUNKSIZE * 2; + + /* Keep track of how quickly our peg alternates */ + wc->pegtimer+=ZT_CHUNKSIZE; + for (x=0;xoldregs[x].flags == FLAG_READ && !wc->ignoreread) { + realreg = wecareregs[(wc->regs[x].index + wc->regoffset) % + (sizeof(wecareregs) / sizeof(wecareregs[0]))]; + realval = (le32_to_cpu(readchunk[(x << 1) +wc->alt]) >> 16) & 0xff; + if ((realval == 0x89) && (realreg != WC_DAA_PLL2_N2_M2)) { + /* Some sort of slippage, correct for it */ + while(realreg != WC_DAA_PLL2_N2_M2) { + /* Find register 9 */ + realreg = wecareregs[(wc->regs[x].index + ++wc->regoffset) % + (sizeof(wecareregs) / sizeof(wecareregs[0]))]; + wc->regoffset = wc->regoffset % (sizeof(wecareregs) / sizeof(wecareregs[0])); + } + if (debug) + printk("New regoffset: %d\n", wc->regoffset); + } + /* Receive into the proper register */ + wc->readregs[realreg] = realval; + } + /* Look for pegging to indicate ringing */ + sample = (short)(le32_to_cpu(readchunk[(x << 1) + (1 - wc->alt)]) >> 16); + if ((sample > 32000) && (wc->peg != 1)) { + if ((wc->pegtimer < PEGTIME) && (wc->pegtimer > MINPEGTIME)) + wc->pegcount++; + wc->pegtimer = 0; + wc->peg = 1; + } else if ((sample < -32000) && (wc->peg != -1)) { + if ((wc->pegtimer < PEGTIME) && (wc->pegtimer > MINPEGTIME)) + wc->pegcount++; + wc->pegtimer = 0; + wc->peg = -1; + } + wc->chan.readchunk[x] = ZT_LIN2X((sample), (&wc->chan)); + } + if (wc->pegtimer > PEGTIME) { + /* Reset pegcount if our timer expires */ + wc->pegcount = 0; + } + /* Decrement debouncer if appropriate */ + if (wc->ringdebounce) + wc->ringdebounce--; + if (!wc->offhook && !wc->ringdebounce) { + if (!wc->ring && (wc->pegcount > PEGCOUNT)) { + /* It's ringing */ + if (debug) + printk("RING!\n"); + zt_hooksig(&wc->chan, ZT_RXSIG_RING); + wc->ring = 1; + } + if (wc->ring && !wc->pegcount) { + /* No more ring */ + if (debug) + printk("NO RING!\n"); + zt_hooksig(&wc->chan, ZT_RXSIG_OFFHOOK); + wc->ring = 0; + } + } + if (wc->ignoreread) + wc->ignoreread--; + + /* Do the echo cancellation... We are echo cancelling against + what we sent two chunks ago*/ + zt_ec_chunk(&wc->chan, wc->chan.readchunk, wc->lasttx); + + /* Receive the result */ + zt_receive(&wc->span); +} + +#ifdef ENABLE_TASKLETS +static void wcfxo_tasklet(unsigned long data) +{ + struct wcfxo *wc = (struct wcfxo *)data; + wc->taskletrun++; + /* Run tasklet */ + if (wc->taskletpending) { + wc->taskletexec++; + wcfxo_receiveprep(wc, wc->ints); + wcfxo_transmitprep(wc, wc->ints); + } + wc->taskletpending = 0; +} +#endif + +static void wcfxo_stop_dma(struct wcfxo *wc); +static void wcfxo_restart_dma(struct wcfxo *wc); + +ZAP_IRQ_HANDLER(wcfxo_interrupt) +{ + struct wcfxo *wc = dev_id; + unsigned char ints; + unsigned char b; +#ifdef DEBUG_RING + static int oldb = 0; + static int oldcnt = 0; +#endif + + ints = inb(wc->ioaddr + WC_INTSTAT); + + + if (!ints) +#ifdef LINUX26 + return IRQ_NONE; +#else + return; +#endif + + outb(ints, wc->ioaddr + WC_INTSTAT); + + if (ints & 0x0c) { /* if there is a rx interrupt pending */ +#ifdef ENABLE_TASKLETS + wc->ints = ints; + if (!wc->taskletpending) { + wc->taskletpending = 1; + wc->taskletsched++; + tasklet_hi_schedule(&wc->wcfxo_tlet); + } else + wc->txerrors++; +#else + wcfxo_receiveprep(wc, ints); + /* transmitprep looks to see if there is anything to transmit + and returns by itself if there is nothing */ + wcfxo_transmitprep(wc, ints); +#endif + } + + if (ints & 0x10) { + printk("FXO PCI Master abort\n"); + /* Stop DMA andlet the watchdog start it again */ + wcfxo_stop_dma(wc); +#ifdef LINUX26 + return IRQ_RETVAL(1); +#else + return; +#endif + } + + if (ints & 0x20) { + printk("PCI Target abort\n"); +#ifdef LINUX26 + return IRQ_RETVAL(1); +#else + return; +#endif + } + if (1 /* !(wc->report % 0xf) */) { + /* Check for BATTERY from register and debounce for 8 ms */ + b = wc->readregs[WC_DAA_LINE_STAT] & 0xf; + if (!b) { + wc->nobatttimer++; +#if 0 + if (wc->battery) + printk("Battery loss: %d (%d debounce)\n", b, wc->battdebounce); +#endif + if (wc->battery && !wc->battdebounce) { + if (debug) + printk("NO BATTERY!\n"); + wc->battery = 0; +#ifdef JAPAN + if ((!wc->ohdebounce) && wc->offhook) { + zt_hooksig(&wc->chan, ZT_RXSIG_ONHOOK); + if (debug) + printk("Signalled On Hook\n"); +#ifdef ZERO_BATT_RING + wc->onhook++; +#endif + } +#else + zt_hooksig(&wc->chan, ZT_RXSIG_ONHOOK); +#endif + wc->battdebounce = BATT_DEBOUNCE; + } else if (!wc->battery) + wc->battdebounce = BATT_DEBOUNCE; + if ((wc->nobatttimer > 5000) && +#ifdef ZERO_BATT_RING + !(wc->readregs[WC_DAA_DCTL1] & 0x04) && +#endif + (!wc->span.alarms)) { + wc->span.alarms = ZT_ALARM_RED; + zt_alarm_notify(&wc->span); + } + } else if (b == 0xf) { + if (!wc->battery && !wc->battdebounce) { + if (debug) + printk("BATTERY!\n"); +#ifdef ZERO_BATT_RING + if (wc->onhook) { + wc->onhook = 0; + zt_hooksig(&wc->chan, ZT_RXSIG_OFFHOOK); + if (debug) + printk("Signalled Off Hook\n"); + } +#else + zt_hooksig(&wc->chan, ZT_RXSIG_OFFHOOK); +#endif + wc->battery = 1; + wc->nobatttimer = 0; + wc->battdebounce = BATT_DEBOUNCE; + if (wc->span.alarms) { + wc->span.alarms = 0; + zt_alarm_notify(&wc->span); + } + } else if (wc->battery) + wc->battdebounce = BATT_DEBOUNCE; + } else { + /* It's something else... */ + wc->battdebounce = BATT_DEBOUNCE; + } + + if (wc->battdebounce) + wc->battdebounce--; +#ifdef JAPAN + if (wc->ohdebounce) + wc->ohdebounce--; +#endif + + } +#ifdef LINUX26 + return IRQ_RETVAL(1); +#endif +} + +static int wcfxo_setreg(struct wcfxo *wc, unsigned char reg, unsigned char value) +{ + int x; + if (wc->wregcount < ZT_CHUNKSIZE) { + x = wc->wregcount; + wc->regs[x].reg = reg; + wc->regs[x].value = value; + wc->regs[x].flags = FLAG_WRITE; + wc->wregcount++; + return 0; + } + printk("wcfxo: Out of space to write register %02x with %02x\n", reg, value); + return -1; +} + +static int wcfxo_open(struct zt_chan *chan) +{ + struct wcfxo *wc = chan->pvt; + if (wc->dead) + return -ENODEV; + wc->usecount++; +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#endif + return 0; +} + +static int wcfxo_watchdog(struct zt_span *span, int event) +{ + printk("FXO: Restarting DMA\n"); + wcfxo_restart_dma(span->pvt); + return 0; +} + +static int wcfxo_close(struct zt_chan *chan) +{ + struct wcfxo *wc = chan->pvt; + wc->usecount--; +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#endif + /* If we're dead, release us now */ + if (!wc->usecount && wc->dead) + wcfxo_release(wc); + return 0; +} + +static int wcfxo_hooksig(struct zt_chan *chan, zt_txsig_t txsig) +{ + struct wcfxo *wc = chan->pvt; + int reg=0; + switch(txsig) { + case ZT_TXSIG_START: + case ZT_TXSIG_OFFHOOK: + /* Take off hook and enable normal mode reception. This must + be done in two steps because of a hardware bug. */ + reg = wc->readregs[WC_DAA_DCTL1] & ~0x08; + wcfxo_setreg(wc, WC_DAA_DCTL1, reg); + + reg = reg | 0x1; + wcfxo_setreg(wc, WC_DAA_DCTL1, reg); + wc->offhook = 1; +#ifdef JAPAN + wc->battery = 1; + wc->battdebounce = BATT_DEBOUNCE; + wc->ohdebounce = OH_DEBOUNCE; +#endif + break; + case ZT_TXSIG_ONHOOK: + /* Put on hook and enable on hook line monitor */ + reg = wc->readregs[WC_DAA_DCTL1] & 0xfe; + wcfxo_setreg(wc, WC_DAA_DCTL1, reg); + + reg = reg | 0x08; + wcfxo_setreg(wc, WC_DAA_DCTL1, reg); + wc->offhook = 0; + /* Don't accept a ring for another 1000 ms */ + wc->ringdebounce = 1000; +#ifdef JAPAN + wc->ohdebounce = OH_DEBOUNCE; +#endif + break; + default: + printk("wcfxo: Can't set tx state to %d\n", txsig); + } + if (debug) + printk("Setting hook state to %d (%02x)\n", txsig, reg); + return 0; +} + +static int wcfxo_initialize(struct wcfxo *wc) +{ + /* Zapata stuff */ + sprintf(wc->span.name, "WCFXO/%d", wc->pos); + snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1); + sprintf(wc->chan.name, "WCFXO/%d/%d", wc->pos, 0); + snprintf(wc->span.location, sizeof(wc->span.location) - 1, + "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); + wc->span.manufacturer = "Digium"; + strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); + wc->chan.sigcap = ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF; + wc->chan.chanpos = 1; + wc->span.chans = &wc->chan; + wc->span.channels = 1; + wc->span.hooksig = wcfxo_hooksig; + wc->span.irq = wc->dev->irq; + wc->span.open = wcfxo_open; + wc->span.close = wcfxo_close; + wc->span.flags = ZT_FLAG_RBS; + wc->span.deflaw = ZT_LAW_MULAW; + wc->span.watchdog = wcfxo_watchdog; +#ifdef ENABLE_TASKLETS + tasklet_init(&wc->wcfxo_tlet, wcfxo_tasklet, (unsigned long)wc); +#endif + init_waitqueue_head(&wc->span.maintq); + + wc->span.pvt = wc; + wc->chan.pvt = wc; + if (zt_register(&wc->span, 0)) { + printk("Unable to register span with zaptel\n"); + return -1; + } + return 0; +} + +static int wcfxo_hardware_init(struct wcfxo *wc) +{ + /* Hardware stuff */ + /* Reset PCI Interface chip and registers */ + outb(0x0e, wc->ioaddr + WC_CNTL); + if (wc->flags & FLAG_RESET_ON_AUX5) { + /* Set hook state to on hook for when we switch. + Make sure reset is high */ + outb(0x34, wc->ioaddr + WC_AUXD); + } else { + /* Set hook state to on hook for when we switch */ + outb(0x24, wc->ioaddr + WC_AUXD); + } + /* Set all to outputs except AUX 4, which is an input */ + outb(0xef, wc->ioaddr + WC_AUXC); + + /* Back to normal, with automatic DMA wrap around */ + outb(0x01, wc->ioaddr + WC_CNTL); + + /* Make sure serial port and DMA are out of reset */ + outb(inb(wc->ioaddr + WC_CNTL) & 0xf9, wc->ioaddr + WC_CNTL); + + /* Configure serial port for MSB->LSB operation */ + if (wc->flags & FLAG_DOUBLE_CLOCK) + outb(0xc1, wc->ioaddr + WC_SERCTL); + else + outb(0xc0, wc->ioaddr + WC_SERCTL); + + if (wc->flags & FLAG_USE_XTAL) { + /* Use the crystal oscillator */ + outb(0x04, wc->ioaddr + WC_AUXFUNC); + } + + /* Delay FSC by 2 so it's properly aligned */ + outb(0x2, wc->ioaddr + WC_FSCDELAY); + + /* Setup DMA Addresses */ + outl(wc->writedma, wc->ioaddr + WC_DMAWS); /* Write start */ + outl(wc->writedma + ZT_CHUNKSIZE * 8 - 4, wc->ioaddr + WC_DMAWI); /* Middle (interrupt) */ + outl(wc->writedma + ZT_CHUNKSIZE * 16 - 4, wc->ioaddr + WC_DMAWE); /* End */ + + outl(wc->readdma, wc->ioaddr + WC_DMARS); /* Read start */ + outl(wc->readdma + ZT_CHUNKSIZE * 8 - 4, wc->ioaddr + WC_DMARI); /* Middle (interrupt) */ + outl(wc->readdma + ZT_CHUNKSIZE * 16 - 4, wc->ioaddr + WC_DMARE); /* End */ + + /* Clear interrupts */ + outb(0xff, wc->ioaddr + WC_INTSTAT); + return 0; +} + +static void wcfxo_enable_interrupts(struct wcfxo *wc) +{ + /* Enable interrupts (we care about all of them) */ + outb(0x3f, wc->ioaddr + WC_MASK0); + /* No external interrupts */ + outb(0x00, wc->ioaddr + WC_MASK1); +} + +static void wcfxo_start_dma(struct wcfxo *wc) +{ + /* Reset Master and TDM */ + outb(0x0f, wc->ioaddr + WC_CNTL); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + outb(0x01, wc->ioaddr + WC_CNTL); + outb(0x01, wc->ioaddr + WC_OPER); +} + +static void wcfxo_restart_dma(struct wcfxo *wc) +{ + /* Reset Master and TDM */ + outb(0x01, wc->ioaddr + WC_CNTL); + outb(0x01, wc->ioaddr + WC_OPER); +} + + +static void wcfxo_stop_dma(struct wcfxo *wc) +{ + outb(0x00, wc->ioaddr + WC_OPER); +} + +static void wcfxo_reset_tdm(struct wcfxo *wc) +{ + /* Reset TDM */ + outb(0x0f, wc->ioaddr + WC_CNTL); +} + +static void wcfxo_disable_interrupts(struct wcfxo *wc) +{ + outb(0x00, wc->ioaddr + WC_MASK0); + outb(0x00, wc->ioaddr + WC_MASK1); +} + +static void wcfxo_set_daa_mode(struct wcfxo *wc) +{ + /* Set country specific parameters (OHS, ACT, DCT, RZ, RT, LIM, VOL) */ + int reg16 = ((fxo_modes[opermode].ohs & 0x1) << 6) | + ((fxo_modes[opermode].act & 0x1) << 5) | + ((fxo_modes[opermode].dct & 0x3) << 2) | + ((fxo_modes[opermode].rz & 0x1) << 1) | + ((fxo_modes[opermode].rt & 0x1) << 0); + int reg17 = ((fxo_modes[opermode].lim & 0x3) << 3); + int reg18 = ((fxo_modes[opermode].vol & 0x3) << 3); + + if (wc->flags & FLAG_NO_I18N_REGS) { + wcfxo_dbg(wc->span, "This card does not support international settings.\n"); + return; + } + + wcfxo_setreg(wc, WC_DAA_INT_CTL1, reg16); + wcfxo_setreg(wc, WC_DAA_INT_CTL2, reg17); + wcfxo_setreg(wc, WC_DAA_INT_CTL3, reg18); + + + /* Wait a couple of jiffies for our writes to finish */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1 + (ZT_CHUNKSIZE * HZ) / 800); + + printk("wcfxo: DAA mode is '%s'\n", fxo_modes[opermode].name); +} + +static int wcfxo_init_daa(struct wcfxo *wc) +{ + /* This must not be called in an interrupt */ + /* We let things settle for a bit */ + unsigned char reg15; + int chip_revb; +// set_current_state(TASK_INTERRUPTIBLE); +// schedule_timeout(10); + + /* Soft-reset it */ + wcfxo_setreg(wc, WC_DAA_CTL1, 0x80); + + /* Let the reset go */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1 + (ZT_CHUNKSIZE * HZ) / 800); + + /* We have a clock at 18.432 Mhz, so N1=1, M1=2, CGM=0 */ + wcfxo_setreg(wc, WC_DAA_PLL1_N1, 0x0); /* This value is N1 - 1 */ + wcfxo_setreg(wc, WC_DAA_PLL1_M1, 0x1); /* This value is M1 - 1 */ + /* We want to sample at 8khz, so N2 = 9, M2 = 10 (N2-1, M2-1) */ + wcfxo_setreg(wc, WC_DAA_PLL2_N2_M2, 0x89); + + /* Wait until the PLL's are locked. Time is between 100 uSec and 1 mSec */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1 + HZ/1000 + (ZT_CHUNKSIZE * HZ) / 800); + + /* No additional ration is applied to the PLL and faster lock times + * are possible */ + wcfxo_setreg(wc, WC_DAA_PLL_CTL, 0x0); + /* Enable off hook pin */ + wcfxo_setreg(wc, WC_DAA_DCTL1, 0x0a); + if (monitor) { + /* Enable ISOcap and external speaker and charge pump if present */ + wcfxo_setreg(wc, WC_DAA_DCTL2, 0x80); + } else { + /* Enable ISOcap and charge pump if present (leave speaker disabled) */ + wcfxo_setreg(wc, WC_DAA_DCTL2, 0xe0); + } + + /* Wait a couple of jiffies for our writes to finish */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1 + (ZT_CHUNKSIZE * HZ) / 800); + reg15 = 0x0; + /* Go ahead and attenuate transmit signal by 6 db */ + if (quiet) { + printk("wcfxo: Attenuating transmit signal for quiet operation\n"); + reg15 |= (quiet & 0x3) << 4; + } + if (boost) { + printk("wcfxo: Boosting receive signal\n"); + reg15 |= (boost & 0x3); + } + wcfxo_setreg(wc, WC_DAA_TXRX_GCTL, reg15); + + /* REVB: reg. 13, bits 5:2 */ + chip_revb = (wc->readregs[WC_DAA_CHIPB_REV] >> 2) & 0xF; + wcfxo_dbg(wc->span, "DAA chip REVB is %x\n", chip_revb); + switch(chip_revb) { + case 1: case 2: case 3: + /* This is a si3034. Nothing to do */ + break; + case 4: case 5: case 7: + /* This is 3035. Has no support for international registers */ + wc->flags |= FLAG_NO_I18N_REGS; + break; + default: + wcfxo_notice(wc->span, "Unknown DAA chip revision: REVB=%d\n", + chip_revb); + } + + /* Didn't get it right. Register 9 is still garbage */ + if (wc->readregs[WC_DAA_PLL2_N2_M2] != 0x89) + return -1; +#if 0 + { int x; + int y; + for (y=0;y<100;y++) { + printk(" reg dump ====== %d ======\n", y); + for (x=0;xreadregs[wecareregs[x]]); + } + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(100); + } } +#endif + return 0; +} + +static int __devinit wcfxo_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct wcfxo *wc; + struct wcfxo_desc *d = (struct wcfxo_desc *)ent->driver_data; + int x; + + for (x=0;x= WC_MAX_IFACES) { + printk(KERN_ERR "Too many interfaces: Found %d, can only handle %d.\n", + x, WC_MAX_IFACES - 1); + return -EIO; + } + + if (pci_enable_device(pdev)) + return -EIO; + + wc = kmalloc(sizeof(struct wcfxo), GFP_KERNEL); + if (!wc) { + printk(KERN_ERR "wcfxo: Failed initializinf card. Not enough memory."); + return -ENOMEM; + } + + ifaces[x] = wc; + memset(wc, 0, sizeof(struct wcfxo)); + wc->ioaddr = pci_resource_start(pdev, 0); + wc->dev = pdev; + wc->pos = x; + wc->variety = d->name; + wc->flags = d->flags; + /* Keep track of whether we need to free the region */ + if (request_region(wc->ioaddr, 0xff, "wcfxo")) + wc->freeregion = 1; + + /* Allocate enough memory for two zt chunks, receive and transmit. Each sample uses + 32 bits. Allocate an extra set just for control too */ + wc->writechunk = (int *)pci_alloc_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, &wc->writedma); + if (!wc->writechunk) { + printk("wcfxo: Unable to allocate DMA-able memory\n"); + if (wc->freeregion) + release_region(wc->ioaddr, 0xff); + return -ENOMEM; + } + + wc->readchunk = wc->writechunk + ZT_MAX_CHUNKSIZE * 4; /* in doublewords */ + wc->readdma = wc->writedma + ZT_MAX_CHUNKSIZE * 16; /* in bytes */ + + if (wcfxo_initialize(wc)) { + printk("wcfxo: Unable to intialize modem\n"); + if (wc->freeregion) + release_region(wc->ioaddr, 0xff); + kfree(wc); + return -EIO; + } + + /* Enable bus mastering */ + pci_set_master(pdev); + + /* Keep track of which device we are */ + pci_set_drvdata(pdev, wc); + + if (request_irq(pdev->irq, wcfxo_interrupt, ZAP_IRQ_SHARED, "wcfxo", wc)) { + printk("wcfxo: Unable to request IRQ %d\n", pdev->irq); + if (wc->freeregion) + release_region(wc->ioaddr, 0xff); + kfree(wc); + return -EIO; + } + + + wcfxo_hardware_init(wc); + /* Enable interrupts */ + wcfxo_enable_interrupts(wc); + /* Initialize Write/Buffers to all blank data */ + memset((void *)wc->writechunk,0,ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4); + /* Start DMA */ + wcfxo_start_dma(wc); + + /* Initialize DAA (after it's started) */ + if (wcfxo_init_daa(wc)) { + printk("Failed to initailize DAA, giving up...\n"); + wcfxo_stop_dma(wc); + wcfxo_disable_interrupts(wc); + zt_unregister(&wc->span); + free_irq(pdev->irq, wc); + + /* Reset PCI chip and registers */ + outb(0x0e, wc->ioaddr + WC_CNTL); + + if (wc->freeregion) + release_region(wc->ioaddr, 0xff); + kfree(wc); + return -EIO; + } + wcfxo_set_daa_mode(wc); + printk("Found a Wildcard FXO: %s\n", wc->variety); + + return 0; +} + +static void wcfxo_release(struct wcfxo *wc) +{ + zt_unregister(&wc->span); + if (wc->freeregion) + release_region(wc->ioaddr, 0xff); + kfree(wc); + printk("Freed a Wildcard\n"); +} + +static void __devexit wcfxo_remove_one(struct pci_dev *pdev) +{ + struct wcfxo *wc = pci_get_drvdata(pdev); + if (wc) { + + /* Stop any DMA */ + wcfxo_stop_dma(wc); + wcfxo_reset_tdm(wc); + + /* In case hardware is still there */ + wcfxo_disable_interrupts(wc); + + /* Immediately free resources */ + pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma); + free_irq(pdev->irq, wc); + + /* Reset PCI chip and registers */ + outb(0x0e, wc->ioaddr + WC_CNTL); + + /* Release span, possibly delayed */ + if (!wc->usecount) + wcfxo_release(wc); + else + wc->dead = 1; + } +} + +static struct pci_device_id wcfxo_pci_tbl[] = { + { 0xe159, 0x0001, 0x8084, PCI_ANY_ID, 0, 0, (unsigned long) &generic }, + { 0xe159, 0x0001, 0x8085, PCI_ANY_ID, 0, 0, (unsigned long) &wcx101p }, + { 0xe159, 0x0001, 0x8086, PCI_ANY_ID, 0, 0, (unsigned long) &generic }, + { 0xe159, 0x0001, 0x8087, PCI_ANY_ID, 0, 0, (unsigned long) &generic }, + { 0x1057, 0x5608, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcx100p }, + { 0 } +}; + +MODULE_DEVICE_TABLE (pci, wcfxo_pci_tbl); + +static struct pci_driver wcfxo_driver = { + name: "wcfxo", + probe: wcfxo_init_one, +#ifdef LINUX26 + remove: __devexit_p(wcfxo_remove_one), +#else + remove: wcfxo_remove_one, +#endif + id_table: wcfxo_pci_tbl, +}; + +static int __init wcfxo_init(void) +{ + int res; + int x; + if ((opermode >= sizeof(fxo_modes) / sizeof(fxo_modes[0])) || (opermode < 0)) { + printk("Invalid/unknown operating mode specified. Please choose one of:\n"); + for (x=0;x"); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +module_init(wcfxo_init); +module_exit(wcfxo_cleanup); diff --git a/kernel/wct1xxp.c b/kernel/wct1xxp.c new file mode 100644 index 0000000..bcfed97 --- /dev/null +++ b/kernel/wct1xxp.c @@ -0,0 +1,1438 @@ +/* + * Linux Support Services, Inc. Wildcard T100P T1/PRI card Driver + * + * Written by Mark Spencer + * Matthew Fredrickson + * William Meadows + * + * Copyright (C) 2001, Linux Support Services, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef STANDALONE_ZAPATA +#include "zaptel.h" +#else +#include +#endif +#ifdef LINUX26 +#include +#endif + +#define WC_MAX_CARDS 32 + +/* +#define TEST_REGS +*/ + +/* Define to get more attention-grabbing but slightly more I/O using + alarm status */ +#define FANCY_ALARM + + +#define DELAY 0x0 /* 30 = 15 cycles, 10 = 8 cycles, 0 = 3 cycles */ + +#define WC_CNTL 0x00 +#define WC_OPER 0x01 +#define WC_AUXC 0x02 +#define WC_AUXD 0x03 +#define WC_MASK0 0x04 +#define WC_MASK1 0x05 +#define WC_INTSTAT 0x06 + +#define WC_DMAWS 0x08 +#define WC_DMAWI 0x0c +#define WC_DMAWE 0x10 +#define WC_DMARS 0x18 +#define WC_DMARI 0x1c +#define WC_DMARE 0x20 +#define WC_CURPOS 0x24 + +#define WC_SERC 0x2d +#define WC_FSCDELAY 0x2f + +#define WC_USERREG 0xc0 + +#define WC_CLOCK 0x0 +#define WC_LEDTEST 0x1 +#define WC_VERSION 0x2 + +/* Offset between transmit and receive */ +#define WC_OFFSET 4 + +#define BIT_CS (1 << 7) +#define BIT_ADDR (0xf << 3) + +#define BIT_LED0 (1 << 0) +#define BIT_LED1 (1 << 1) +#define BIT_TEST (1 << 2) + +static char *chips[] = +{ + "DS2152", + "DS21352", + "DS21552", + "Unknown Chip (3)", + "DS2154", + "DS21354", + "DS21554", + "Unknown Chip (7)", +}; + +static int chanmap_t1[] = +{ 2,1,0, + 6,5,4, + 10,9,8, + 14,13,12, + 18,17,16, + 22,21,20, + 26,25,24, + 30,29,28 }; + +static int chanmap_e1[] = +{ 2,1,0, + 7,6,5,4, + 11,10,9,8, + 15,14,13,12, + 19,18,17,16, + 23,22,21,20, + 27,26,25,24, + 31,30,29,28 }; + +#ifdef FANCY_ALARM +static int altab[] = { +0, 0, 0, 1, 2, 3, 4, 6, 8, 9, 11, 13, 16, 18, 20, 22, 24, 25, 27, 28, 29, 30, 31, 31, 32, 31, 31, 30, 29, 28, 27, 25, 23, 22, 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0, +}; +#endif + +struct t1xxp { + struct pci_dev *dev; + spinlock_t lock; + int ise1; + int num; + /* Our offset for finding channel 1 */ + int offset; + char *variety; + unsigned int intcount; + int usecount; + int clocktimeout; + int sync; + int dead; + int blinktimer; + int alarmtimer; + int loopupcnt; + int loopdowncnt; + int miss; + int misslast; + int *chanmap; +#ifdef FANCY_ALARM + int alarmpos; +#endif + unsigned char ledtestreg; + unsigned char outbyte; + unsigned long ioaddr; + unsigned short canary; + /* T1 signalling */ + unsigned char txsiga[3]; + unsigned char txsigb[3]; + dma_addr_t readdma; + dma_addr_t writedma; + volatile unsigned char *writechunk; /* Double-word aligned write memory */ + volatile unsigned char *readchunk; /* Double-word aligned read memory */ + unsigned char ec_chunk1[31][ZT_CHUNKSIZE]; + unsigned char ec_chunk2[31][ZT_CHUNKSIZE]; + unsigned char tempo[32]; + struct zt_span span; /* Span */ + struct zt_chan chans[31]; /* Channels */ +}; + +#define CANARY 0xca1e + +int debug = 0; /* doesnt do anything */ + +static struct t1xxp *cards[WC_MAX_CARDS]; + +static inline void start_alarm(struct t1xxp *wc) +{ +#ifdef FANCY_ALARM + wc->alarmpos = 0; +#endif + wc->blinktimer = 0; +} + +static inline void stop_alarm(struct t1xxp *wc) +{ +#ifdef FANCY_ALARM + wc->alarmpos = 0; +#endif + wc->blinktimer = 0; +} + +static inline void __select_framer(struct t1xxp *wc, int reg) +{ + /* Top four bits of address from AUX 6-3 */ + wc->outbyte &= ~BIT_CS; + wc->outbyte &= ~BIT_ADDR; + wc->outbyte |= (reg & 0xf0) >> 1; + outb(wc->outbyte, wc->ioaddr + WC_AUXD); +} + +static inline void __select_control(struct t1xxp *wc) +{ + if (!(wc->outbyte & BIT_CS)) { + wc->outbyte |= BIT_CS; + outb(wc->outbyte, wc->ioaddr + WC_AUXD); + } +} + +static int t1xxp_open(struct zt_chan *chan) +{ + struct t1xxp *wc = chan->pvt; + if (wc->dead) + return -ENODEV; + wc->usecount++; +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#endif + return 0; +} + +static int __t1_get_reg(struct t1xxp *wc, int reg) +{ + unsigned char res; + __select_framer(wc, reg); + /* Get value */ + res = inb(wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2)); + return res; +} + +static int __t1_set_reg(struct t1xxp *wc, int reg, unsigned char val) +{ + __select_framer(wc, reg); + /* Send address */ + outb(val, wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2)); + return 0; +} + +static int __control_set_reg(struct t1xxp *wc, int reg, unsigned char val) +{ + __select_control(wc); + outb(val, wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2)); + return 0; +} + +static int control_set_reg(struct t1xxp *wc, int reg, unsigned char val) +{ + unsigned long flags; + int res; + spin_lock_irqsave(&wc->lock, flags); + res = __control_set_reg(wc, reg, val); + spin_unlock_irqrestore(&wc->lock, flags); + return res; +} + +static int __control_get_reg(struct t1xxp *wc, int reg) +{ + unsigned char res; + /* The following makes UTTERLY no sense, but what was happening + was that reads in some cases were not actually happening + on the physical bus. Why, we dunno. But in debugging, we found + that writing before reading (in this case to an unused position) + seems to get rid of the problem */ + __control_set_reg(wc,3,0x69); /* do magic here */ + /* now get the read byte from the Xilinx part */ + res = inb(wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2)); + return res; +} + +static int control_get_reg(struct t1xxp *wc, int reg) +{ + unsigned long flags; + int res; + spin_lock_irqsave(&wc->lock, flags); + res = __control_get_reg(wc, reg); + spin_unlock_irqrestore(&wc->lock, flags); + return res; +} + +static void t1xxp_release(struct t1xxp *wc) +{ + zt_unregister(&wc->span); + kfree(wc); + printk("Freed a Wildcard\n"); +} + +static int t1xxp_close(struct zt_chan *chan) +{ + struct t1xxp *wc = chan->pvt; + wc->usecount--; +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#endif + /* If we're dead, release us now */ + if (!wc->usecount && wc->dead) + t1xxp_release(wc); + return 0; +} + +static void t1xxp_enable_interrupts(struct t1xxp *wc) +{ + /* Clear interrupts */ + outb(0xff, wc->ioaddr + WC_INTSTAT); + /* Enable interrupts (we care about all of them) */ + outb(0x3c /* 0x3f */, wc->ioaddr + WC_MASK0); + /* No external interrupts */ + outb(0x00, wc->ioaddr + WC_MASK1); +} + +static void t1xxp_start_dma(struct t1xxp *wc) +{ + /* Reset Master and TDM */ + outb(DELAY | 0x0f, wc->ioaddr + WC_CNTL); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + outb(DELAY | 0x01, wc->ioaddr + WC_CNTL); + outb(0x01, wc->ioaddr + WC_OPER); + if (debug) printk("Started DMA\n"); +} + +static void __t1xxp_stop_dma(struct t1xxp *wc) +{ + outb(0x00, wc->ioaddr + WC_OPER); +} + +static void __t1xxp_disable_interrupts(struct t1xxp *wc) +{ + outb(0x00, wc->ioaddr + WC_MASK0); + outb(0x00, wc->ioaddr + WC_MASK1); +} + +static void __t1xxp_set_clear(struct t1xxp *wc) +{ + /* Setup registers */ + int x,y; + unsigned char b; + + /* No such thing under E1 */ + if (wc->ise1) { + printk("Can't set clear mode on an E1!\n"); + return; + } + + for (x=0;x<3;x++) { + b = 0; + for (y=0;y<8;y++) + if (wc->chans[x * 8 + y].sig & ZT_SIG_CLEAR) + b |= (1 << y); + __t1_set_reg(wc, 0x39 + x, b); + } +} + +static void t1xxp_t1_framer_start(struct t1xxp *wc) +{ + int i; + char *coding, *framing; + unsigned long endjiffies; + int alreadyrunning = wc->span.flags & ZT_FLAG_RUNNING; + unsigned long flags; + + spin_lock_irqsave(&wc->lock, flags); + + /* Build up config */ + i = 0x20; + if (wc->span.lineconfig & ZT_CONFIG_ESF) { + coding = "ESF"; + i = 0x88; + } else { + coding = "SF"; + } + if (wc->span.lineconfig & ZT_CONFIG_B8ZS) { + framing = "B8ZS"; + i |= 0x44; + } else { + framing = "AMI"; + } + __t1_set_reg(wc, 0x38, i); + if (!(wc->span.lineconfig & ZT_CONFIG_ESF)) { + /* 1c in FDL bit */ + __t1_set_reg(wc, 0x7e, 0x1c); + } else { + __t1_set_reg(wc, 0x7e, 0x00); + } + + /* Set outgoing LBO */ + __t1_set_reg(wc, 0x7c, wc->span.txlevel << 5); + + printk("Using %s/%s coding/framing\n", coding, framing); + if (!alreadyrunning) { + /* Setup the clear channels */ + __t1xxp_set_clear(wc); + + /* Set LIRST bit to 1 */ + __t1_set_reg(wc, 0x0a, 0x80); + spin_unlock_irqrestore(&wc->lock, flags); + + /* Wait 100ms to give plenty of time for reset */ + endjiffies = jiffies + 10; + while(endjiffies < jiffies); + + spin_lock_irqsave(&wc->lock, flags); + + /* Reset LIRST bit and reset elastic stores */ + __t1_set_reg(wc, 0xa, 0x30); + + wc->span.flags |= ZT_FLAG_RUNNING; + } + spin_unlock_irqrestore(&wc->lock, flags); +} + +static void t1xxp_e1_framer_start(struct t1xxp *wc) +{ + int i; + char *coding, *framing; + unsigned long endjiffies; + int alreadyrunning = wc->span.flags & ZT_FLAG_RUNNING; + unsigned long flags; + char *crcing = ""; + unsigned char ccr1, tcr1, tcr2; + + spin_lock_irqsave(&wc->lock, flags); + + /* Build up config */ + ccr1 = 0; + tcr1 = 8; + tcr2 = 0; + if (wc->span.lineconfig & ZT_CONFIG_CCS) { + coding = "CCS"; /* Receive CCS */ + ccr1 |= 8; + } else { + tcr1 |= 0x20; + coding = "CAS"; + } + if (wc->span.lineconfig & ZT_CONFIG_HDB3) { + ccr1 |= 0x44; /* TX/RX HDB3 */ + framing = "HDB3"; + } else { + framing = "AMI"; + } + if (wc->span.lineconfig & ZT_CONFIG_CRC4) { + ccr1 |= 0x11; + tcr2 |= 0x02; + crcing = " with CRC4"; + } + __t1_set_reg(wc, 0x12, tcr1); + __t1_set_reg(wc, 0x13, tcr2); + __t1_set_reg(wc, 0x14, ccr1); + __t1_set_reg(wc, 0x18, 0x20); /* 120 Ohm */ + + +#if 0 /* XXX Does LBO Matter? XXX */ + /* Set outgoing LBO */ + __t1_set_reg(wc, 0x7c, wc->span.txlevel << 5); +#endif + + printk("Using %s/%s coding/framing%s 120 Ohms\n", coding, framing,crcing); + if (!alreadyrunning) { + + __t1_set_reg(wc,0x1b,0x8a); /* CCR3: LIRST & TSCLKM */ + __t1_set_reg(wc,0x20,0x1b); /* TAFR */ + __t1_set_reg(wc,0x21,0x5f); /* TNAFR */ + __t1_set_reg(wc,0x40,0xb); /* TSR1 */ + for(i = 0x41; i <= 0x4f; i++) __t1_set_reg(wc,i,0x55); + for(i = 0x22; i <= 0x25; i++) __t1_set_reg(wc,i,0xff); + spin_unlock_irqrestore(&wc->lock, flags); + + /* Wait 100ms to give plenty of time for reset */ + endjiffies = jiffies + 10; + while(endjiffies < jiffies); + + spin_lock_irqsave(&wc->lock, flags); + + __t1_set_reg(wc, 0x1b, 0x9a); /* Set ESR */ + __t1_set_reg(wc, 0x1b, 0x82); /* TSCLKM only now */ + + /* Reset LIRST bit and reset elastic stores */ + + wc->span.flags |= ZT_FLAG_RUNNING; + } + spin_unlock_irqrestore(&wc->lock, flags); +} + +static int t1xxp_framer_sanity_check(struct t1xxp *wc) +{ + int res; + int chipid; + unsigned long flags; + int x; + + /* Sanity check */ + spin_lock_irqsave(&wc->lock, flags); + for (x=0x0;x<192;x++) + __t1_set_reg(wc, x, 0); + res = __t1_get_reg(wc, 0x0f); + res = __t1_get_reg(wc, 0x0f); + chipid = ((res & 0x80) >> 5) | ((res & 0x30) >> 4); + wc->ise1 = (res & 0x80) ? (1 << 4) : 0; + spin_unlock_irqrestore(&wc->lock, flags); + + printk("Framer: %s, Revision: %d (%s)\n", chips[chipid], res & 0xf, wc->ise1 ? "E1" : "T1"); + return 0; +} + +static int t1xxp_framer_hard_reset(struct t1xxp *wc) +{ + int x; + unsigned long flags; + + spin_lock_irqsave(&wc->lock, flags); + /* Initialize all registers to 0 */ + for (x=0x0;x<192;x++) + __t1_set_reg(wc, x, 0); + + if (wc->ise1) { + /* Set LOTCMC (switch to RCLCK if TCLK fails) */ + __t1_set_reg(wc, 0x1a, 0x04); + + /* RSYNC is an input */ + __t1_set_reg(wc, 0x10, 0x20); + + /* Rx elastic store enabled, 2.048 Mhz (in theory) */ + __t1_set_reg(wc, 0x11, 0x06); + + /* TSYNC is an input, Tsis mode */ + __t1_set_reg(wc, 0x12, 0x08); + + /* Tx elastic store enabled, 2.048 Mhz (in theory) */ + __t1_set_reg(wc, 0x1b, 0x82); + + + + } else { + /* Full-on sync required for T1 */ + __t1_set_reg(wc, 0x2b, 0x08); + /* RSYNC is an input */ + __t1_set_reg(wc, 0x2c, 0x08); + + /* Enable tx RBS bits */ + __t1_set_reg(wc, 0x35, 0x10); + + /* TSYNC is output */ + __t1_set_reg(wc, 0x36, 0x04); + + /* Tx and Rx elastic store enabled, 2.048 Mhz (in theory) */ + __t1_set_reg(wc, 0x37, 0x9c); + + /* Setup Loopup / Loopdown codes */ + __t1_set_reg(wc, 0x12, 0x22); + __t1_set_reg(wc, 0x14, 0x80); + __t1_set_reg(wc, 0x15, 0x80); + } + + spin_unlock_irqrestore(&wc->lock, flags); + return 0; +} + +static int t1xxp_rbsbits(struct zt_chan *chan, int bits) +{ + struct t1xxp *wc = chan->pvt; + unsigned long flags; + int b,o; + unsigned char mask; + + /* Byte offset */ + spin_lock_irqsave(&wc->lock, flags); + if (wc->ise1) { + if (chan->chanpos < 16) { + mask = ((bits << 4) | wc->chans[chan->chanpos - 1 + 16].txsig); + __t1_set_reg(wc, 0x40 + chan->chanpos, mask); + } + else if (chan->chanpos > 16) { + mask = (bits | (wc->chans[chan->chanpos - 1 - 16].txsig << 4)); + __t1_set_reg(wc, 0x40 + chan->chanpos - 16, mask); + } + wc->chans[chan->chanpos - 1].txsig = bits; + } else { + b = (chan->chanpos - 1) / 8; + o = (chan->chanpos - 1) % 8; + + mask = (1 << o); + + if (bits & ZT_ABIT) { + /* Set A-bit */ + wc->txsiga[b] |= mask; + } else { + /* Clear A-bit */ + wc->txsiga[b] &= ~mask; + } + if (bits & ZT_BBIT) { + /* Set B-bit */ + wc->txsigb[b] |= mask; + } else { + wc->txsigb[b] &= ~mask; + } + /* Output new values */ + __t1_set_reg(wc, 0x70 + b, wc->txsiga[b]); + __t1_set_reg(wc, 0x73 + b, wc->txsigb[b]); + __t1_set_reg(wc, 0x76 + b, wc->txsiga[b]); + __t1_set_reg(wc, 0x79 + b, wc->txsigb[b]); + } + spin_unlock_irqrestore(&wc->lock, flags); + return 0; +} + +static int t1xxp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) +{ + switch(cmd) { + default: + return -ENOTTY; + } +} + +static int t1xxp_startup(struct zt_span *span) +{ + struct t1xxp *wc = span->pvt; + + int i,alreadyrunning = span->flags & ZT_FLAG_RUNNING; + + /* initialize the start value for the entire chunk of last ec buffer */ + for(i = 0; i < span->channels; i++) + { + memset(wc->ec_chunk1[i], + ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); + memset(wc->ec_chunk2[i], + ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); + } + + /* Reset framer with proper parameters and start */ + if (wc->ise1) + t1xxp_e1_framer_start(wc); + else + t1xxp_t1_framer_start(wc); + printk("Calling startup (flags is %d)\n", span->flags); + + if (!alreadyrunning) { + /* Only if we're not already going */ + t1xxp_enable_interrupts(wc); + t1xxp_start_dma(wc); + span->flags |= ZT_FLAG_RUNNING; + } + return 0; +} + +static int t1xxp_shutdown(struct zt_span *span) +{ + struct t1xxp *wc = span->pvt; + unsigned long flags; + + spin_lock_irqsave(&wc->lock, flags); + __t1xxp_stop_dma(wc); + __t1xxp_disable_interrupts(wc); + span->flags &= ~ZT_FLAG_RUNNING; + spin_unlock_irqrestore(&wc->lock, flags); + + t1xxp_framer_hard_reset(wc); + return 0; +} + +static int t1xxp_maint(struct zt_span *span, int cmd) +{ + struct t1xxp *wc = span->pvt; + int res = 0; + unsigned long flags; + spin_lock_irqsave(&wc->lock, flags); + if (wc->ise1) { + switch(cmd) { + case ZT_MAINT_NONE: + __t1_set_reg(wc,0xa8,0); /* no loops */ + break; + case ZT_MAINT_LOCALLOOP: + __t1_set_reg(wc,0xa8,0x40); /* local loop */ + break; + case ZT_MAINT_REMOTELOOP: + __t1_set_reg(wc,0xa8,0x80); /* remote loop */ + break; + case ZT_MAINT_LOOPUP: + case ZT_MAINT_LOOPDOWN: + case ZT_MAINT_LOOPSTOP: + res = -ENOSYS; + break; + default: + printk("wct1xxp/E1: Unknown maint command: %d\n", cmd); + res = -EINVAL; + break; + } + } else { + switch(cmd) { + case ZT_MAINT_NONE: + __t1_set_reg(wc,0x19,0); /* no local loop */ + __t1_set_reg(wc,0x0a,0); /* no remote loop */ + break; + case ZT_MAINT_LOCALLOOP: + __t1_set_reg(wc,0x19,0x40); /* local loop */ + __t1_set_reg(wc,0x0a,0); /* no remote loop */ + break; + case ZT_MAINT_REMOTELOOP: + __t1_set_reg(wc,0x1e,0); /* no local loop */ + __t1_set_reg(wc,0x0a,0x40); /* remote loop */ + break; + case ZT_MAINT_LOOPUP: + __t1_set_reg(wc,0x30,2); /* send loopup code */ + __t1_set_reg(wc,0x12,0x22); /* send loopup code */ + __t1_set_reg(wc,0x13,0x80); /* send loopup code */ + break; + case ZT_MAINT_LOOPDOWN: + __t1_set_reg(wc,0x30,2); /* send loopdown code */ + __t1_set_reg(wc,0x12,0x62); /* send loopdown code */ + __t1_set_reg(wc,0x13,0x90); /* send loopdown code */ + break; + case ZT_MAINT_LOOPSTOP: + __t1_set_reg(wc,0x30,0); /* stop sending loopup code */ + break; + default: + printk("wct1xxp/T1: Unknown maint command: %d\n", cmd); + res = -EINVAL; + } + } + spin_unlock_irqrestore(&wc->lock, flags); + return res; +} + +static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype) +{ + struct t1xxp *wc = chan->pvt; + unsigned long flags; + int alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING; + + spin_lock_irqsave(&wc->lock, flags); + + if (alreadyrunning && !wc->ise1) + __t1xxp_set_clear(wc); + + spin_unlock_irqrestore(&wc->lock, flags); + return 0; +} + +static int t1xxp_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) +{ + struct t1xxp *wc = span->pvt; + + /* Do we want to SYNC on receive or not */ + wc->sync = lc->sync; + /* If already running, apply changes immediately */ + if (span->flags & ZT_FLAG_RUNNING) + return t1xxp_startup(span); + + return 0; +} +static int t1xxp_software_init(struct t1xxp *wc) +{ + int x; + /* Find position */ + for (x=0;x= WC_MAX_CARDS) + return -1; + wc->num = x; + sprintf(wc->span.name, "WCT1/%d", wc->num); + snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num); + wc->span.manufacturer = "Digium"; + strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); + snprintf(wc->span.location, sizeof(wc->span.location) - 1, + "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); + wc->span.spanconfig = t1xxp_spanconfig; + wc->span.chanconfig = t1xxp_chanconfig; + wc->span.irq = wc->dev->irq; + wc->span.startup = t1xxp_startup; + wc->span.shutdown = t1xxp_shutdown; + wc->span.rbsbits = t1xxp_rbsbits; + wc->span.maint = t1xxp_maint; + wc->span.open = t1xxp_open; + wc->span.close = t1xxp_close; + wc->span.chans = wc->chans; + wc->span.flags = ZT_FLAG_RBS; + wc->span.ioctl = t1xxp_ioctl; + wc->span.pvt = wc; + if (wc->ise1) { + wc->span.channels = 31; + wc->span.deflaw = ZT_LAW_ALAW; + wc->span.linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4; + wc->span.spantype = "E1"; + } else { + wc->span.channels = 24; + wc->span.deflaw = ZT_LAW_MULAW; + wc->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; + wc->span.spantype = "T1"; + } + init_waitqueue_head(&wc->span.maintq); + for (x=0;xspan.channels;x++) { + sprintf(wc->chans[x].name, "WCT1/%d/%d", wc->num, x + 1); + wc->chans[x].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_EM_E1 | + ZT_SIG_FXSLS | ZT_SIG_FXSGS | + ZT_SIG_FXSKS | ZT_SIG_FXOLS | ZT_SIG_DACS_RBS | + ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF; + wc->chans[x].pvt = wc; + wc->chans[x].chanpos = x + 1; + } + if (zt_register(&wc->span, 0)) { + printk("Unable to register span with zaptel\n"); + return -1; + } + return 0; +} + +static inline void __handle_leds(struct t1xxp *wc) +{ + int oldreg; + wc->blinktimer++; + + if (wc->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) { + /* Red/Blue alarm */ +#ifdef FANCY_ALARM + if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) { + wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0; + __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); + } + if (wc->blinktimer == 0xf) { + wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1); + __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); + wc->blinktimer = -1; + wc->alarmpos++; + if (wc->alarmpos >= (sizeof(altab) / sizeof(altab[0]))) + wc->alarmpos = 0; + } +#else + if (wc->blinktimer == 160) { + wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0; + __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); + } else if (wc->blinktimer == 480) { + wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1); + __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); + wc->blinktimer = 0; + } +#endif + } else if (wc->span.alarms & ZT_ALARM_YELLOW) { + /* Yellow Alarm */ + if (!(wc->blinktimer % 2)) + wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0; + else + wc->ledtestreg = (wc->ledtestreg | BIT_LED0) & ~BIT_LED1; + __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); + } else { + /* No Alarm */ + oldreg = wc->ledtestreg; + if (wc->span.maintstat != ZT_MAINT_NONE) + wc->ledtestreg |= BIT_TEST; + else + wc->ledtestreg &= ~BIT_TEST; + if (wc->span.flags & ZT_FLAG_RUNNING) + wc->ledtestreg = (wc->ledtestreg | BIT_LED0) & ~BIT_LED1; + else + wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1); + if (oldreg != wc->ledtestreg) + __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); + } +} + +static void t1xxp_transmitprep(struct t1xxp *wc, int ints) +{ + volatile unsigned char *txbuf; + int x,y; + int pos; + if (ints & 0x04 /* 0x01 */) { + /* We just finished sending the first buffer, start filling it + now */ + txbuf = wc->writechunk; + } else { + /* Just finished sending second buffer, fill it now */ + txbuf = wc->writechunk + 32 * ZT_CHUNKSIZE; + } + zt_transmit(&wc->span); + for (x=0;xoffset;x++) + txbuf[x] = wc->tempo[x]; + for (y=0;yspan.channels;x++) { + pos = y * 32 + wc->chanmap[x] + wc->offset; + /* Put channel number as outgoing data */ + if (pos < 32 * ZT_CHUNKSIZE) + txbuf[pos] = wc->chans[x].writechunk[y]; + else + wc->tempo[pos - 32 * ZT_CHUNKSIZE] = wc->chans[x].writechunk[y]; + } + } +} + +static void t1xxp_receiveprep(struct t1xxp *wc, int ints) +{ + volatile unsigned char *rxbuf; + volatile unsigned int *canary; + int x; + int y; + unsigned int oldcan; + if (ints & 0x04) { + /* Just received first buffer */ + rxbuf = wc->readchunk; + canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 64 - 4); + } else { + rxbuf = wc->readchunk + ZT_CHUNKSIZE * 32; + canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 32 - 4); + } + oldcan = *canary; + if (((oldcan & 0xffff0000) >> 16) != CANARY) { + /* Check top part */ + if (debug) printk("Expecting top %04x, got %04x\n", CANARY, (oldcan & 0xffff0000) >> 16); + wc->span.irqmisses++; + } else if ((oldcan & 0xffff) != ((wc->canary - 1) & 0xffff)) { + if (debug) printk("Expecting bottom %d, got %d\n", wc->canary - 1, oldcan & 0xffff); + wc->span.irqmisses++; + } + for (y=0;yspan.channels;x++) { + /* XXX Optimize, remove * and + XXX */ + /* Must map received channels into appropriate data */ + wc->chans[x].readchunk[y] = + rxbuf[32 * y + ((wc->chanmap[x] + WC_OFFSET + wc->offset) & 0x1f)]; + } + if (!wc->ise1) { + for (x=3;x<32;x+=4) { + if (rxbuf[32 * y + ((x + WC_OFFSET) & 0x1f)] == 0x7f) { + if (wc->offset != (x-3)) { + /* Resync */ + control_set_reg(wc, WC_CLOCK, 0x02 | wc->sync | wc->ise1); + wc->clocktimeout = 100; +#if 1 + if (debug) printk("T1: Lost our place, resyncing\n"); +#endif + } + } + } + } else { + if (!wc->clocktimeout && !wc->span.alarms) { + if ((rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)] & 0x7f) != 0x1b) { + if (wc->miss) { + if (debug) printk("Double miss (%d, %d)...\n", wc->misslast, rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)]); + control_set_reg(wc, WC_CLOCK, 0x02 | wc->sync | wc->ise1); + wc->clocktimeout = 100; + } else { + wc->miss = 1; + wc->misslast = rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)]; + } + } else { + wc->miss = 0; + } + } else { + wc->miss = 0; + } + } + } + /* Store the next canary */ + canary = (unsigned int *)(rxbuf + ZT_CHUNKSIZE * 32 - 4); + *canary = (wc->canary++) | (CANARY << 16); + for (x=0;xspan.channels;x++) { + zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, + wc->ec_chunk2[x]); + memcpy(wc->ec_chunk2[x],wc->ec_chunk1[x],ZT_CHUNKSIZE); + memcpy(wc->ec_chunk1[x],wc->chans[x].writechunk,ZT_CHUNKSIZE); + } + zt_receive(&wc->span); +} + +static void t1xxp_check_sigbits(struct t1xxp *wc, int x) +{ + int a,b,i,y,rxs; + unsigned long flags; + + spin_lock_irqsave(&wc->lock, flags); + if (wc->ise1) { + /* Read 5 registers at a time, loading 10 channels at a time */ + for (i = (x * 5); i < (x * 5) + 5; i++) { + a = __t1_get_reg(wc, 0x31 + i); + /* Get high channel in low bits */ + rxs = (a & 0xf); + if (!(wc->chans[i+16].sig & ZT_SIG_CLEAR)) { + if (wc->chans[i+16].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); + zt_rbsbits(&wc->chans[i+16], rxs); + spin_lock_irqsave(&wc->lock, flags); + } + } + rxs = (a >> 4) & 0xf; + if (!(wc->chans[i].sig & ZT_SIG_CLEAR)) { + if (wc->chans[i].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); + zt_rbsbits(&wc->chans[i], rxs); + spin_lock_irqsave(&wc->lock, flags); + } + } + } + } else { + a = __t1_get_reg(wc, 0x60 + x); + b = __t1_get_reg(wc, 0x63 + x); + for (y=0;y<8;y++) { + i = x * 8 + y; + rxs = 0; + if (a & (1 << y)) + rxs |= ZT_ABIT; + if (b & (1 << y)) + rxs |= ZT_BBIT; + if (!(wc->chans[i].sig & ZT_SIG_CLEAR)) { + if (wc->chans[i].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); + zt_rbsbits(&wc->chans[i], rxs); + spin_lock_irqsave(&wc->lock, flags); + } + } + } + } + spin_unlock_irqrestore(&wc->lock, flags); +} + +static void t1xxp_check_alarms(struct t1xxp *wc) +{ + unsigned char c,d; + int alarms; + int x,j; + unsigned long flags; + + spin_lock_irqsave(&wc->lock, flags); + + if (wc->ise1) { + __t1_set_reg(wc, 0x06, 0xff); + c = __t1_get_reg(wc, 0x6); + } else { + /* Get RIR2 */ + c = __t1_get_reg(wc, 0x31); + wc->span.rxlevel = c >> 6; + + /* Get status register s*/ + __t1_set_reg(wc, 0x20, 0xff); + c = __t1_get_reg(wc, 0x20); + } + + /* Assume no alarms */ + alarms = 0; + + /* And consider only carrier alarms */ + wc->span.alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); + + if (wc->ise1) { + /* XXX Implement me XXX */ + } else { + /* Detect loopup code if we're not sending one */ + if ((!wc->span.mainttimer) && (c & 0x80)) { + /* Loop-up code detected */ + if ((wc->loopupcnt++ > 80) && (wc->span.maintstat != ZT_MAINT_REMOTELOOP)) { + __t1_set_reg(wc, 0x1e, 0); /* No local loop */ + __t1_set_reg(wc, 0x0a, 0x40); /* Remote Loop */ + wc->span.maintstat = ZT_MAINT_REMOTELOOP; + } + } else { + wc->loopupcnt = 0; + } + /* Same for loopdown code */ + if ((!wc->span.mainttimer) && (c & 0x40)) { + /* Loop-down code detected */ + if ((wc->loopdowncnt++ > 80) && (wc->span.maintstat == ZT_MAINT_REMOTELOOP)) { + __t1_set_reg(wc, 0x1e, 0); /* No local loop */ + __t1_set_reg(wc, 0x0a, 0x0); /* No remote Loop */ + wc->span.maintstat = ZT_MAINT_NONE; + } + } else + wc->loopdowncnt = 0; + } + + if (wc->span.lineconfig & ZT_CONFIG_NOTOPEN) { + for (x=0,j=0;x < wc->span.channels;x++) + if ((wc->chans[x].flags & ZT_FLAG_OPEN) || + (wc->chans[x].flags & ZT_FLAG_NETDEV)) + j++; + if (!j) + alarms |= ZT_ALARM_NOTOPEN; + } + + if (wc->ise1) { + if (c & 0x9) + alarms |= ZT_ALARM_RED; + if (c & 0x2) + alarms |= ZT_ALARM_BLUE; + } else { + /* Check actual alarm status */ + if (c & 0x3) + alarms |= ZT_ALARM_RED; + if (c & 0x8) + alarms |= ZT_ALARM_BLUE; + } + /* Keep track of recovering */ + if ((!alarms) && wc->span.alarms) + wc->alarmtimer = ZT_ALARMSETTLE_TIME; + + /* If receiving alarms, go into Yellow alarm state */ + if (alarms && (!wc->span.alarms)) { +#if 0 + printk("Going into yellow alarm\n"); +#endif + if (wc->ise1) + __t1_set_reg(wc, 0x21, 0x7f); + else + __t1_set_reg(wc, 0x35, 0x11); + } + + if (wc->span.alarms != alarms) { + d = __control_get_reg(wc, WC_CLOCK); + start_alarm(wc); + if (!(alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK)) && + wc->sync) { + /* Use the recieve signalling */ + wc->span.syncsrc = wc->span.spanno; + d |= 1; + } else { + wc->span.syncsrc = 0; + d &= ~1; + } + __control_set_reg(wc, WC_CLOCK, d); + } + if (wc->alarmtimer) + alarms |= ZT_ALARM_RECOVER; + if (c & 0x4) + alarms |= ZT_ALARM_YELLOW; + + wc->span.alarms = alarms; + + spin_unlock_irqrestore(&wc->lock, flags); + + zt_alarm_notify(&wc->span); +} + +static void t1xxp_do_counters(struct t1xxp *wc) +{ + unsigned long flags; + + spin_lock_irqsave(&wc->lock, flags); + if (wc->alarmtimer) { + if (!--wc->alarmtimer) { + wc->span.alarms &= ~(ZT_ALARM_RECOVER); + /* Clear yellow alarm */ +#if 0 + printk("Coming out of alarm\n"); +#endif + if (wc->ise1) + __t1_set_reg(wc, 0x21, 0x5f); + else + __t1_set_reg(wc, 0x35, 0x10); + spin_unlock_irqrestore(&wc->lock, flags); + zt_alarm_notify(&wc->span); + spin_lock_irqsave(&wc->lock, flags); + } + } + spin_unlock_irqrestore(&wc->lock, flags); +} + +ZAP_IRQ_HANDLER(t1xxp_interrupt) +{ + struct t1xxp *wc = dev_id; + unsigned char ints; + unsigned long flags; + int x; + + ints = inb(wc->ioaddr + WC_INTSTAT); + if (!ints) +#ifdef LINUX26 + return IRQ_NONE; +#else + return; +#endif + + outb(ints, wc->ioaddr + WC_INTSTAT); + + if (!wc->intcount) { + if (debug) printk("Got interrupt: 0x%04x\n", ints); + } + wc->intcount++; + + if (wc->clocktimeout && !--wc->clocktimeout) + control_set_reg(wc, WC_CLOCK, 0x00 | wc->sync | wc->ise1); + + if (ints & 0x0f) { + t1xxp_receiveprep(wc, ints); + t1xxp_transmitprep(wc, ints); + } + spin_lock_irqsave(&wc->lock, flags); + +#if 1 + __handle_leds(wc); +#endif + + spin_unlock_irqrestore(&wc->lock, flags); + + /* Count down timers */ + t1xxp_do_counters(wc); + + /* Do some things that we don't have to do very often */ + x = wc->intcount & 15 /* 63 */; + switch(x) { + case 0: + case 1: + case 2: + t1xxp_check_sigbits(wc, x); + break; + case 4: + /* Check alarms 1/4 as frequently */ + if (!(wc->intcount & 0x30)) + t1xxp_check_alarms(wc); + break; + } + + if (ints & 0x10) + printk("PCI Master abort\n"); + + if (ints & 0x20) + printk("PCI Target abort\n"); + +#ifdef LINUX26 + return IRQ_RETVAL(1); +#endif +} + +static int t1xxp_hardware_init(struct t1xxp *wc) +{ + /* Hardware PCI stuff */ + /* Reset chip and registers */ + outb(DELAY | 0x0e, wc->ioaddr + WC_CNTL); + /* Set all outputs to 0 */ + outb(0x00, wc->ioaddr + WC_AUXD); + /* Set all to outputs except AUX1 (TDO). */ + outb(0xfd, wc->ioaddr + WC_AUXC); + /* Configure the serial port: double clock, 20ns width, no inversion, + MSB first */ + outb(0xc8, wc->ioaddr + WC_SERC); + + /* Internally delay FSC by one */ + outb(0x01, wc->ioaddr + WC_FSCDELAY); + + /* Back to normal, with automatic DMA wrap around */ + outb(DELAY | 0x01, wc->ioaddr + WC_CNTL); + + /* Make sure serial port and DMA are out of reset */ + outb(inb(wc->ioaddr + WC_CNTL) & 0xf9, WC_CNTL); + + /* Setup DMA Addresses */ + /* Start at writedma */ + outl(wc->writedma, wc->ioaddr + WC_DMAWS); /* Write start */ + /* First frame */ + outl(wc->writedma + ZT_CHUNKSIZE * 32 - 4, wc->ioaddr + WC_DMAWI); /* Middle (interrupt) */ + /* Second frame */ + outl(wc->writedma + ZT_CHUNKSIZE * 32 * 2 - 4, wc->ioaddr + WC_DMAWE); /* End */ + + outl(wc->readdma, wc->ioaddr + WC_DMARS); /* Read start */ + /* First frame */ + outl(wc->readdma + ZT_CHUNKSIZE * 32 - 4, wc->ioaddr + WC_DMARI); /* Middle (interrupt) */ + /* Second frame */ + outl(wc->readdma + ZT_CHUNKSIZE * 32 * 2 - 4, wc->ioaddr + WC_DMARE); /* End */ + + if (debug) printk("Setting up DMA (write/read = %08lx/%08lx)\n", (long)wc->writedma, (long)wc->readdma); + + /* Check out the controller */ + if (debug) printk("Controller version: %02x\n", control_get_reg(wc, WC_VERSION)); + + + control_set_reg(wc, WC_LEDTEST, 0x00); + + /* Sanity check also determines e1 or t1 */ + if (t1xxp_framer_sanity_check(wc)) + return -1; + if (wc->ise1) + wc->chanmap = chanmap_e1; + else + wc->chanmap = chanmap_t1; + /* Setup clock appropriately */ + control_set_reg(wc, WC_CLOCK, 0x02 | wc->sync | wc->ise1); + wc->clocktimeout = 100; + + /* Reset the T1 and report */ + t1xxp_framer_hard_reset(wc); + start_alarm(wc); + return 0; + +} + +static int __devinit t1xxp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int res; + struct t1xxp *wc; + unsigned int *canary; + + if (pci_enable_device(pdev)) { + res = -EIO; + } else { + wc = kmalloc(sizeof(struct t1xxp), GFP_KERNEL); + if (wc) { + memset(wc, 0x0, sizeof(struct t1xxp)); + spin_lock_init(&wc->lock); + wc->ioaddr = pci_resource_start(pdev, 0); + wc->dev = pdev; + wc->offset = 28; /* And you thought 42 was the answer */ + + wc->writechunk = + /* 32 channels, Double-buffer, Read/Write */ + (unsigned char *)pci_alloc_consistent(pdev, ZT_MAX_CHUNKSIZE * 32 * 2 * 2, &wc->writedma); + if (!wc->writechunk) { + printk("wct1xxp: Unable to allocate DMA-able memory\n"); + return -ENOMEM; + } + + /* Read is after the whole write piece (in bytes) */ + wc->readchunk = wc->writechunk + ZT_CHUNKSIZE * 32 * 2; + + /* Same thing... */ + wc->readdma = wc->writedma + ZT_CHUNKSIZE * 32 * 2; + + /* Initialize Write/Buffers to all blank data */ + memset((void *)wc->writechunk,0x00,ZT_MAX_CHUNKSIZE * 2 * 2 * 32); + /* Initialize canary */ + canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 64 - 4); + *canary = (CANARY << 16) | (0xffff); + + /* Enable bus mastering */ + pci_set_master(pdev); + + /* Keep track of which device we are */ + pci_set_drvdata(pdev, wc); + + if (request_irq(pdev->irq, t1xxp_interrupt, ZAP_IRQ_SHARED_DISABLED, "t1xxp", wc)) { + printk("t1xxp: Unable to request IRQ %d\n", pdev->irq); + kfree(wc); + return -EIO; + } + /* Initialize hardware */ + t1xxp_hardware_init(wc); + + /* We now know which version of card we have */ + if (wc->ise1) + wc->variety = "Digium Wildcard E100P E1/PRA"; + else + wc->variety = "Digium Wildcard T100P T1/PRI"; + + /* Misc. software stuff */ + t1xxp_software_init(wc); + + printk("Found a Wildcard: %s\n", wc->variety); + res = 0; + } else + res = -ENOMEM; + } + return res; +} + +static void t1xxp_stop_stuff(struct t1xxp *wc) +{ + /* Kill clock */ + control_set_reg(wc, WC_CLOCK, 0); + + /* Turn off LED's */ + control_set_reg(wc, WC_LEDTEST, 0); + + /* Reset the T1 */ + t1xxp_framer_hard_reset(wc); + +} + +static void __devexit t1xxp_remove_one(struct pci_dev *pdev) +{ + struct t1xxp *wc = pci_get_drvdata(pdev); + if (wc) { + + /* Stop any DMA */ + __t1xxp_stop_dma(wc); + + /* In case hardware is still there */ + __t1xxp_disable_interrupts(wc); + + t1xxp_stop_stuff(wc); + + /* Immediately free resources */ + pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 32 * 4, (void *)wc->writechunk, wc->writedma); + free_irq(pdev->irq, wc); + + /* Reset PCI chip and registers */ + outb(DELAY | 0x0e, wc->ioaddr + WC_CNTL); + + /* Release span, possibly delayed */ + if (!wc->usecount) + t1xxp_release(wc); + else + wc->dead = 1; + } +} + +static struct pci_device_id t1xxp_pci_tbl[] = { + { 0xe159, 0x0001, 0x6159, PCI_ANY_ID, 0, 0, (unsigned long) "Digium Wildcard T100P T1/PRI or E100P E1/PRA Board" }, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci,t1xxp_pci_tbl); + +static struct pci_driver t1xxp_driver = { + name: "t1xxp", + probe: t1xxp_init_one, +#ifdef LINUX26 + remove: __devexit_p(t1xxp_remove_one), +#else + remove: t1xxp_remove_one, +#endif + suspend: NULL, + resume: NULL, + id_table: t1xxp_pci_tbl, +}; + +static int __init t1xxp_init(void) +{ + int res; + res = zap_pci_module(&t1xxp_driver); + if (res) + return -ENODEV; + return 0; +} + +static void __exit t1xxp_cleanup(void) +{ + pci_unregister_driver(&t1xxp_driver); +} + +#ifdef LINUX26 +module_param(debug, int, 0600); +#else +MODULE_PARM(debug, "i"); +#endif +MODULE_DESCRIPTION("Wildcard T100P/E100P Zaptel Driver"); +MODULE_AUTHOR("Mark Spencer "); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +module_init(t1xxp_init); +module_exit(t1xxp_cleanup); diff --git a/kernel/wct4xxp/Kbuild b/kernel/wct4xxp/Kbuild new file mode 100644 index 0000000..96909f4 --- /dev/null +++ b/kernel/wct4xxp/Kbuild @@ -0,0 +1,27 @@ +obj-m += wct4xxp.o + +FIRM_DIR := ../../firmware + +EXTRA_CFLAGS := -I$(src)/.. $(shell $(src)/../oct612x/octasic-helper cflags $(src)/../oct612x) -Wno-undef + +ifeq ($(HOTPLUG_FIRMWARE),yes) + EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE +endif + +wct4xxp-objs := base.o vpm450m.o $(shell $(src)/../oct612x/octasic-helper objects ../oct612x) + +ifneq ($(HOTPLUG_FIRMWARE),yes) +wct4xxp-objs += $(FIRM_DIR)/zaptel-fw-oct6114-064.o $(FIRM_DIR)/zaptel-fw-oct6114-128.o +endif + +$(obj)/$(FIRM_DIR)/zaptel-fw-oct6114-064.o: $(obj)/base.o + $(MAKE) -C $(obj)/$(FIRM_DIR) zaptel-fw-oct6114-064.o + +$(obj)/$(FIRM_DIR)/zaptel-fw-oct6114-128.o: $(obj)/base.o + $(MAKE) -C $(obj)/$(FIRM_DIR) zaptel-fw-oct6114-128.o + +$(obj)/base.o: $(src)/vpm450m.h $(src)/wct4xxp.h +$(obj)/base.o: $(src)/../zaptel.h + +$(obj)/vpm450m.o: $(src)/vpm450m.h +$(obj)/vpm450m.o: $(src)/../oct612x/include/oct6100api/oct6100_api.h diff --git a/kernel/wct4xxp/Makefile b/kernel/wct4xxp/Makefile new file mode 100644 index 0000000..4f0961e --- /dev/null +++ b/kernel/wct4xxp/Makefile @@ -0,0 +1,36 @@ +ifneq ($(KBUILD_EXTMOD),) +# We only get here on kernels 2.6.0-2.6.9 . +# For newer kernels, Kbuild will be included directly by the kernel +# build system. +include $(src)/Kbuild + +else + +FIRM_DIR := ../../firmware + +OCTASIC_OBJS:=$(shell ../oct612x/octasic-helper objects ../oct612x) +OCTASIC_CFLAGS:=$(shell ../oct612x/octasic-helper cflags ../oct612x) -Wno-undef + +all: wct4xxp.o + +%.o: %.c + $(CC) $(KFLAGS) $(OCTASIC_CFLAGS) -o $@ -c $< + +base.o: ../zaptel.h vpm450m.h wct4xxp.h + +vpm450m.o: vpm450m.h ../oct612x/include/oct6100api/oct6100_api.h + +$(FIRM_DIR)/zaptel-fw-oct6114-064.o: base.o + $(MAKE) -C $(FIRM_DIR) zaptel-fw-oct6114-064.o + +$(FIRM_DIR)/zaptel-fw-oct6114-128.o: base.o + $(MAKE) -C $(FIRM_DIR) zaptel-fw-oct6114-128.o + +wct4xxp.o: base.o vpm450m.o $(OCTASIC_OBJS) $(FIRM_DIR)/zaptel-fw-oct6114-064.o $(FIRM_DIR)/zaptel-fw-oct6114-128.o + $(LD) -r -o $@ $^ + +clean: + rm -f *.o + rm -f $(OCTASIC_OBJS) + +endif diff --git a/kernel/wct4xxp/base.c b/kernel/wct4xxp/base.c new file mode 100644 index 0000000..0b4a2d9 --- /dev/null +++ b/kernel/wct4xxp/base.c @@ -0,0 +1,3877 @@ +/* + * TE410P Quad-T1/E1 PCI Driver version 0.1, 12/16/02 + * + * Written by Mark Spencer + * Based on previous works, designs, and archetectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001-2005, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "zaptel.h" +#ifdef LINUX26 +#include +#endif + +#include "wct4xxp.h" +#include "vpm450m.h" + +/* Work queues are a way to better distribute load on SMP systems */ +#if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) +/* + * Work queues can significantly improve performance and scalability + * on multi-processor machines, but requires bypassing some kernel + * API's, so it's not guaranteed to be compatible with all kernels. + */ +/* #define ENABLE_WORKQUEUES */ +#endif + +/* Enable prefetching may help performance */ +#define ENABLE_PREFETCH + +/* Support first generation cards? */ +#define SUPPORT_GEN1 + +/* Define to get more attention-grabbing but slightly more I/O using + alarm status */ +#define FANCY_ALARM + +/* Define to support Digium Voice Processing Module expansion card */ +#define VPM_SUPPORT + +#define DEBUG_MAIN (1 << 0) +#define DEBUG_DTMF (1 << 1) +#define DEBUG_REGS (1 << 2) +#define DEBUG_TSI (1 << 3) +#define DEBUG_ECHOCAN (1 << 4) +#define DEBUG_RBS (1 << 5) +#define DEBUG_FRAMER (1 << 6) + +#ifdef ENABLE_WORKQUEUES +#include + +/* XXX UGLY!!!! XXX We have to access the direct structures of the workqueue which + are only defined within workqueue.c because they don't give us a routine to allow us + to nail a work to a particular thread of the CPU. Nailing to threads gives us substantially + higher scalability in multi-CPU environments though! */ + +/* + * The per-CPU workqueue (if single thread, we always use cpu 0's). + * + * The sequence counters are for flush_scheduled_work(). It wants to wait + * until until all currently-scheduled works are completed, but it doesn't + * want to be livelocked by new, incoming ones. So it waits until + * remove_sequence is >= the insert_sequence which pertained when + * flush_scheduled_work() was called. + */ + +struct cpu_workqueue_struct { + + spinlock_t lock; + + long remove_sequence; /* Least-recently added (next to run) */ + long insert_sequence; /* Next to add */ + + struct list_head worklist; + wait_queue_head_t more_work; + wait_queue_head_t work_done; + + struct workqueue_struct *wq; + task_t *thread; + + int run_depth; /* Detect run_workqueue() recursion depth */ +} ____cacheline_aligned; + +/* + * The externally visible workqueue abstraction is an array of + * per-CPU workqueues: + */ +struct workqueue_struct { + /* TODO: Find out exactly where the API changed */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) + struct cpu_workqueue_struct *cpu_wq; +#else + struct cpu_workqueue_struct cpu_wq[NR_CPUS]; +#endif + const char *name; + struct list_head list; /* Empty if single thread */ +}; + +/* Preempt must be disabled. */ +static void __t4_queue_work(struct cpu_workqueue_struct *cwq, + struct work_struct *work) +{ + unsigned long flags; + + spin_lock_irqsave(&cwq->lock, flags); + work->wq_data = cwq; + list_add_tail(&work->entry, &cwq->worklist); + cwq->insert_sequence++; + wake_up(&cwq->more_work); + spin_unlock_irqrestore(&cwq->lock, flags); +} + +/* + * Queue work on a workqueue. Return non-zero if it was successfully + * added. + * + * We queue the work to the CPU it was submitted, but there is no + * guarantee that it will be processed by that CPU. + */ +static inline int t4_queue_work(struct workqueue_struct *wq, struct work_struct *work, int cpu) +{ + int ret = 0; + get_cpu(); + if (!test_and_set_bit(0, &work->pending)) { + BUG_ON(!list_empty(&work->entry)); + __t4_queue_work(wq->cpu_wq + cpu, work); + ret = 1; + } + put_cpu(); + return ret; +} + +#endif + +static int pedanticpci = 1; +static int debug=0; +static int timingcable = 0; +static int highestorder; +static int t1e1override = -1; //0xFF; // -1 = jumper; 0xFF = E1 +static int j1mode = 0; +static int sigmode = FRMR_MODE_NO_ADDR_CMP; +static int loopback = 0; +static int alarmdebounce = 0; +#ifdef VPM_SUPPORT +static int vpmsupport = 1; +/* If set to auto, vpmdtmfsupport is enabled for VPM400M and disabled for VPM450M */ +static int vpmdtmfsupport = -1; /* -1=auto, 0=disabled, 1=enabled*/ +static int vpmspans = 4; +#define VPM_DEFAULT_DTMFTHRESHOLD 1000 +static int dtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD; +static int lastdtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD; +#endif +/* Enabling bursting can more efficiently utilize PCI bus bandwidth, but + can also cause PCI bus starvation, especially in combination with other + aggressive cards. Please note that burst mode has no effect on CPU + utilization / max number of calls / etc. */ +static int noburst = 1; +/* For 56kbps links, set this module parameter to 0x7f */ +static int hardhdlcmode = 0xff; + +#ifdef FANCY_ALARM +static int altab[] = { +0, 0, 0, 1, 2, 3, 4, 6, 8, 9, 11, 13, 16, 18, 20, 22, 24, 25, 27, 28, 29, 30, 31, 31, 32, 31, 31, 30, 29, 28, 27, 25, 23, 22, 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0, +}; +#endif + +#define MAX_SPANS 16 + +#define FLAG_STARTED (1 << 0) +#define FLAG_NMF (1 << 1) +#define FLAG_SENDINGYELLOW (1 << 2) + + +#define TYPE_T1 1 /* is a T1 card */ +#define TYPE_E1 2 /* is an E1 card */ +#define TYPE_J1 3 /* is a running J1 */ + +#define FLAG_2NDGEN (1 << 3) +#define FLAG_2PORT (1 << 4) +#define FLAG_VPM2GEN (1 << 5) +#define FLAG_OCTOPT (1 << 6) +#define FLAG_3RDGEN (1 << 7) +#define FLAG_BURST (1 << 8) +#define FLAG_EXPRESS (1 << 9) + +#define CANARY 0xc0de + +struct devtype { + char *desc; + unsigned int flags; +}; + +static struct devtype wct4xxp = { "Wildcard TE410P/TE405P (1st Gen)", 0 }; +static struct devtype wct420p4 = { "Wildcard TE420 (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_EXPRESS }; +static struct devtype wct410p4 = { "Wildcard TE410P (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN }; +static struct devtype wct410p3 = { "Wildcard TE410P (3rd Gen)", FLAG_2NDGEN | FLAG_3RDGEN }; +static struct devtype wct405p4 = { "Wildcard TE405P (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN }; +static struct devtype wct405p3 = { "Wildcard TE405P (3rd Gen)", FLAG_2NDGEN | FLAG_3RDGEN }; +static struct devtype wct410p2 = { "Wildcard TE410P (2nd Gen)", FLAG_2NDGEN }; +static struct devtype wct405p2 = { "Wildcard TE405P (2nd Gen)", FLAG_2NDGEN }; +static struct devtype wct220p4 = { "Wildcard TE220 (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT | FLAG_EXPRESS }; +static struct devtype wct205p4 = { "Wildcard TE205P (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; +static struct devtype wct205p3 = { "Wildcard TE205P (3rd Gen)", FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; +static struct devtype wct210p4 = { "Wildcard TE210P (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; +static struct devtype wct210p3 = { "Wildcard TE210P (3rd Gen)", FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; +static struct devtype wct205 = { "Wildcard TE205P ", FLAG_2NDGEN | FLAG_2PORT }; +static struct devtype wct210 = { "Wildcard TE210P ", FLAG_2NDGEN | FLAG_2PORT }; + + +struct t4; + +struct t4_span { + struct t4 *owner; + unsigned int *writechunk; /* Double-word aligned write memory */ + unsigned int *readchunk; /* Double-word aligned read memory */ + int spantype; /* card type, T1 or E1 or J1 */ + int sync; + int psync; + int alarmtimer; + int redalarms; + int notclear; + int alarmcount; + int spanflags; + int syncpos; +#ifdef SUPPORT_GEN1 + int e1check; /* E1 check */ +#endif + struct zt_span span; + unsigned char txsigs[16]; /* Transmit sigs */ + int loopupcnt; + int loopdowncnt; +#ifdef SUPPORT_GEN1 + unsigned char ec_chunk1[31][ZT_CHUNKSIZE]; /* first EC chunk buffer */ + unsigned char ec_chunk2[31][ZT_CHUNKSIZE]; /* second EC chunk buffer */ +#endif + int irqmisses; + + /* HDLC controller fields */ + struct zt_chan *sigchan; + unsigned char sigmode; + int sigactive; + int frames_out; + int frames_in; + +#ifdef VPM_SUPPORT + unsigned long dtmfactive; + unsigned long dtmfmask; + unsigned long dtmfmutemask; + short dtmfenergy[31]; + short dtmfdigit[31]; +#endif +#ifdef ENABLE_WORKQUEUES + struct work_struct swork; +#endif + struct zt_chan chans[0]; /* Individual channels */ +}; + +struct t4 { + /* This structure exists one per card */ + struct pci_dev *dev; /* Pointer to PCI device */ + unsigned int intcount; + int num; /* Which card we are */ + int t1e1; /* T1/E1 select pins */ + int globalconfig; /* Whether global setup has been done */ + int syncsrc; /* active sync source */ + struct t4_span *tspans[4]; /* Individual spans */ + int numspans; /* Number of spans on the card */ + int blinktimer; +#ifdef FANCY_ALARM + int alarmpos; +#endif + int irq; /* IRQ used by device */ + int order; /* Order */ + int flags; /* Device flags */ + int master; /* Are we master */ + int ledreg; /* LED Register */ + unsigned int gpio; + unsigned int gpioctl; + int stopdma; /* Set to stop DMA */ + int e1recover; /* E1 recovery timer */ + spinlock_t reglock; /* lock register access */ + int spansstarted; /* number of spans started */ + volatile unsigned int *writechunk; /* Double-word aligned write memory */ + volatile unsigned int *readchunk; /* Double-word aligned read memory */ + unsigned short canary; +#ifdef ENABLE_WORKQUEUES + atomic_t worklist; + struct workqueue_struct *workq; +#endif + unsigned int passno; /* number of interrupt passes */ + char *variety; + int last0; /* for detecting double-missed IRQ */ + int checktiming; /* Set >0 to cause the timing source to be checked */ + + /* DMA related fields */ + unsigned int dmactrl; + dma_addr_t readdma; + dma_addr_t writedma; + unsigned long memaddr; /* Base address of card */ + unsigned long memlen; + volatile unsigned int *membase; /* Base address of card */ + + /* Flags for our bottom half */ + unsigned long checkflag; + struct tasklet_struct t4_tlet; + unsigned int vpm400checkstatus; + +#ifdef VPM_SUPPORT + struct vpm450m *vpm450m; + int vpm; +#endif + +}; + +#define T4_VPM_PRESENT (1 << 28) + + +#ifdef VPM_SUPPORT +static void t4_vpm400_init(struct t4 *wc); +static void t4_vpm450_init(struct t4 *wc); +static void t4_vpm_set_dtmf_threshold(struct t4 *wc, unsigned int threshold); +#endif +static void __set_clear(struct t4 *wc, int span); +static int t4_startup(struct zt_span *span); +static int t4_shutdown(struct zt_span *span); +static int t4_rbsbits(struct zt_chan *chan, int bits); +static int t4_maint(struct zt_span *span, int cmd); +#ifdef SUPPORT_GEN1 +static int t4_reset_dma(struct t4 *wc); +#endif +static void t4_hdlc_hard_xmit(struct zt_chan *chan); +static int t4_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data); +static void t4_tsi_assign(struct t4 *wc, int fromspan, int fromchan, int tospan, int tochan); +static void t4_tsi_unassign(struct t4 *wc, int tospan, int tochan); +static void __t4_set_timing_source(struct t4 *wc, int unit, int master, int slave); +static void t4_check_alarms(struct t4 *wc, int span); +static void t4_check_sigbits(struct t4 *wc, int span); + +#define WC_RDADDR 0 +#define WC_WRADDR 1 +#define WC_COUNT 2 +#define WC_DMACTRL 3 +#define WC_INTR 4 +/* #define WC_GPIO 5 */ +#define WC_VERSION 6 +#define WC_LEDS 7 +#define WC_GPIOCTL 8 +#define WC_GPIO 9 +#define WC_LADDR 10 +#define WC_LDATA 11 +#define WC_LCS (1 << 11) +#define WC_LCS2 (1 << 12) +#define WC_LALE (1 << 13) +#define WC_LFRMR_CS (1 << 10) /* Framer's ChipSelect signal */ +#define WC_ACTIVATE (1 << 12) +#define WC_LREAD (1 << 15) +#define WC_LWRITE (1 << 16) + +#define WC_OFF (0) +#define WC_RED (1) +#define WC_GREEN (2) +#define WC_YELLOW (3) + +#define MAX_T4_CARDS 64 + +static void t4_isr_bh(unsigned long data); + +static struct t4 *cards[MAX_T4_CARDS]; + + +#define MAX_TDM_CHAN 32 +#define MAX_DTMF_DET 16 + +#define HDLC_IMR0_MASK (FRMR_IMR0_RME | FRMR_IMR0_RPF) +#if 0 +#define HDLC_IMR1_MASK (FRMR_IMR1_ALLS | FRMR_IMR1_XDU | FRMR_IMR1_XPR) +#else +#define HDLC_IMR1_MASK (FRMR_IMR1_XDU | FRMR_IMR1_XPR) +#endif + +static inline unsigned int __t4_pci_in(struct t4 *wc, const unsigned int addr) +{ + unsigned int res = readl(&wc->membase[addr]); + return res; +} + +static inline void __t4_pci_out(struct t4 *wc, const unsigned int addr, const unsigned int value) +{ + unsigned int tmp; + writel(value, &wc->membase[addr]); + if (pedanticpci) { + tmp = __t4_pci_in(wc, WC_VERSION); + if ((tmp & 0xffff0000) != 0xc01a0000) + printk("TE4XXP: Version Synchronization Error!\n"); + } +#if 0 + tmp = __t4_pci_in(wc, addr); + if ((value != tmp) && (addr != WC_LEDS) && (addr != WC_LDATA) && + (addr != WC_GPIO) && (addr != WC_INTR)) + printk("Tried to load %08x into %08x, but got %08x instead\n", value, addr, tmp); +#endif +} + +static inline void __t4_gpio_set(struct t4 *wc, unsigned bits, unsigned int val) +{ + unsigned int newgpio; + newgpio = wc->gpio & (~bits); + newgpio |= val; + if (newgpio != wc->gpio) { + wc->gpio = newgpio; + __t4_pci_out(wc, WC_GPIO, wc->gpio); + } +} + +static inline void __t4_gpio_setdir(struct t4 *wc, unsigned int bits, unsigned int val) +{ + unsigned int newgpioctl; + newgpioctl = wc->gpioctl & (~bits); + newgpioctl |= val; + if (newgpioctl != wc->gpioctl) { + wc->gpioctl = newgpioctl; + __t4_pci_out(wc, WC_GPIOCTL, wc->gpioctl); + } +} + +static inline void t4_gpio_setdir(struct t4 *wc, unsigned int bits, unsigned int val) +{ + unsigned long flags; + spin_lock_irqsave(&wc->reglock, flags); + __t4_gpio_setdir(wc, bits, val); + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static inline void t4_gpio_set(struct t4 *wc, unsigned int bits, unsigned int val) +{ + unsigned long flags; + spin_lock_irqsave(&wc->reglock, flags); + __t4_gpio_set(wc, bits, val); + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static inline void t4_pci_out(struct t4 *wc, const unsigned int addr, const unsigned int value) +{ + unsigned long flags; + spin_lock_irqsave(&wc->reglock, flags); + __t4_pci_out(wc, addr, value); + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static inline void __t4_set_led(struct t4 *wc, int span, int color) +{ + int oldreg = wc->ledreg; + wc->ledreg &= ~(0x3 << (span << 1)); + wc->ledreg |= (color << (span << 1)); + if (oldreg != wc->ledreg) + __t4_pci_out(wc, WC_LEDS, wc->ledreg); +} + +static inline void t4_activate(struct t4 *wc) +{ + wc->ledreg |= WC_ACTIVATE; + t4_pci_out(wc, WC_LEDS, wc->ledreg); +} + +static inline unsigned int t4_pci_in(struct t4 *wc, const unsigned int addr) +{ + unsigned int ret; + unsigned long flags; + + spin_lock_irqsave(&wc->reglock, flags); + ret = __t4_pci_in(wc, addr); + spin_unlock_irqrestore(&wc->reglock, flags); + return ret; +} + +static inline unsigned int __t4_framer_in(struct t4 *wc, int unit, const unsigned int addr) +{ + unsigned int ret; + unit &= 0x3; + __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); + __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | WC_LFRMR_CS | WC_LREAD); + if (pedanticpci) { + __t4_pci_out(wc, WC_VERSION, 0); + } + ret = __t4_pci_in(wc, WC_LDATA); + __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); + return ret & 0xff; +} + +static inline unsigned int t4_framer_in(struct t4 *wc, int unit, const unsigned int addr) +{ + unsigned long flags; + unsigned int ret; + spin_lock_irqsave(&wc->reglock, flags); + ret = __t4_framer_in(wc, unit, addr); + spin_unlock_irqrestore(&wc->reglock, flags); + return ret; + +} + +static inline void __t4_framer_out(struct t4 *wc, int unit, const unsigned int addr, const unsigned int value) +{ + unit &= 0x3; + if (unlikely(debug & DEBUG_REGS)) + printk("Writing %02x to address %02x of unit %d\n", value, addr, unit); + __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); + __t4_pci_out(wc, WC_LDATA, value); + __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | WC_LFRMR_CS | WC_LWRITE); + __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); + if (unlikely(debug & DEBUG_REGS)) printk("Write complete\n"); +#if 0 + if ((addr != FRMR_TXFIFO) && (addr != FRMR_CMDR) && (addr != 0xbc)) + { unsigned int tmp; + tmp = __t4_framer_in(wc, unit, addr); + if (tmp != value) { + printk("Expected %d from unit %d register %d but got %d instead\n", value, unit, addr, tmp); + } } +#endif +} + +static inline void t4_framer_out(struct t4 *wc, int unit, const unsigned int addr, const unsigned int value) +{ + unsigned long flags; + spin_lock_irqsave(&wc->reglock, flags); + __t4_framer_out(wc, unit, addr, value); + spin_unlock_irqrestore(&wc->reglock, flags); +} + +#ifdef VPM_SUPPORT + +static inline void wait_a_little(void) +{ + unsigned long newjiffies=jiffies+2; + while(jiffies < newjiffies); +} + +static inline unsigned int __t4_vpm_in(struct t4 *wc, int unit, const unsigned int addr) +{ + unsigned int ret; + unit &= 0x7; + __t4_pci_out(wc, WC_LADDR, (addr & 0x1ff) | ( unit << 12)); + __t4_pci_out(wc, WC_LADDR, (addr & 0x1ff) | ( unit << 12) | (1 << 11) | WC_LREAD); + ret = __t4_pci_in(wc, WC_LDATA); + __t4_pci_out(wc, WC_LADDR, 0); + return ret & 0xff; +} + +static inline void __t4_raw_oct_out(struct t4 *wc, const unsigned int addr, const unsigned int value) +{ + int octopt = wc->tspans[0]->spanflags & FLAG_OCTOPT; + if (!octopt) + __t4_gpio_set(wc, 0xff, (addr >> 8)); + __t4_pci_out(wc, WC_LDATA, 0x10000 | (addr & 0xffff)); + if (!octopt) + __t4_pci_out(wc, WC_LADDR, (WC_LWRITE)); + __t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE)); + if (!octopt) + __t4_gpio_set(wc, 0xff, (value >> 8)); + __t4_pci_out(wc, WC_LDATA, (value & 0xffff)); + __t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE | WC_LCS)); + __t4_pci_out(wc, WC_LADDR, (0)); +} + +static inline unsigned int __t4_raw_oct_in(struct t4 *wc, const unsigned int addr) +{ + unsigned int ret; + int octopt = wc->tspans[0]->spanflags & FLAG_OCTOPT; + if (!octopt) + __t4_gpio_set(wc, 0xff, (addr >> 8)); + __t4_pci_out(wc, WC_LDATA, 0x10000 | (addr & 0xffff)); + if (!octopt) + __t4_pci_out(wc, WC_LADDR, (WC_LWRITE)); + __t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE)); +#ifdef PEDANTIC_OCTASIC_CHECKING + __t4_pci_out(wc, WC_LADDR, (WC_LALE)); +#endif + if (!octopt) { + __t4_gpio_setdir(wc, 0xff, 0x00); + __t4_gpio_set(wc, 0xff, 0x00); + } + __t4_pci_out(wc, WC_LADDR, (WC_LREAD | WC_LALE | WC_LCS)); + if (octopt) { + ret = __t4_pci_in(wc, WC_LDATA) & 0xffff; + } else { + ret = __t4_pci_in(wc, WC_LDATA) & 0xff; + ret |= (__t4_pci_in(wc, WC_GPIO) & 0xff) << 8; + } + __t4_pci_out(wc, WC_LADDR, (0)); + if (!octopt) + __t4_gpio_setdir(wc, 0xff, 0xff); + return ret & 0xffff; +} + +static inline unsigned int __t4_oct_in(struct t4 *wc, unsigned int addr) +{ +#ifdef PEDANTIC_OCTASIC_CHECKING + int count = 1000; +#endif + __t4_raw_oct_out(wc, 0x0008, (addr >> 20)); + __t4_raw_oct_out(wc, 0x000a, (addr >> 4) & ((1 << 16) - 1)); + __t4_raw_oct_out(wc, 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (1)); +#ifdef PEDANTIC_OCTASIC_CHECKING + while((__t4_raw_oct_in(wc, 0x0000) & (1 << 8)) && --count); + if (count != 1000) + printk("Yah, read can be slow...\n"); + if (!count) + printk("Read timed out!\n"); +#endif + return __t4_raw_oct_in(wc, 0x0004); +} + +static inline unsigned int t4_oct_in(struct t4 *wc, const unsigned int addr) +{ + unsigned long flags; + unsigned int ret; + spin_lock_irqsave(&wc->reglock, flags); + ret = __t4_oct_in(wc, addr); + spin_unlock_irqrestore(&wc->reglock, flags); + return ret; +} + +static inline unsigned int t4_vpm_in(struct t4 *wc, int unit, const unsigned int addr) +{ + unsigned long flags; + unsigned int ret; + spin_lock_irqsave(&wc->reglock, flags); + ret = __t4_vpm_in(wc, unit, addr); + spin_unlock_irqrestore(&wc->reglock, flags); + return ret; +} + +static inline void __t4_vpm_out(struct t4 *wc, int unit, const unsigned int addr, const unsigned int value) +{ + unit &= 0x7; + if (debug & DEBUG_REGS) + printk("Writing %02x to address %02x of ec unit %d\n", value, addr, unit); + __t4_pci_out(wc, WC_LADDR, (addr & 0xff)); + __t4_pci_out(wc, WC_LDATA, value); + __t4_pci_out(wc, WC_LADDR, (unit << 12) | (addr & 0x1ff) | (1 << 11)); + __t4_pci_out(wc, WC_LADDR, (unit << 12) | (addr & 0x1ff) | (1 << 11) | WC_LWRITE); + __t4_pci_out(wc, WC_LADDR, (unit << 12) | (addr & 0x1ff) | (1 << 11)); + __t4_pci_out(wc, WC_LADDR, (unit << 12) | (addr & 0x1ff)); + __t4_pci_out(wc, WC_LADDR, 0); + if (debug & DEBUG_REGS) printk("Write complete\n"); + + +#if 0 + { unsigned int tmp; + tmp = t4_vpm_in(wc, unit, addr); + if (tmp != value) { + printk("Expected %d from unit %d echo register %d but got %d instead\n", value, unit, addr, tmp); + } } +#endif +} + +static inline void __t4_oct_out(struct t4 *wc, unsigned int addr, unsigned int value) +{ +#ifdef PEDANTIC_OCTASIC_CHECKING + int count = 1000; +#endif + __t4_raw_oct_out(wc, 0x0008, (addr >> 20)); + __t4_raw_oct_out(wc, 0x000a, (addr >> 4) & ((1 << 16) - 1)); + __t4_raw_oct_out(wc, 0x0004, value); + __t4_raw_oct_out(wc, 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (3 << 12) | 1); +#ifdef PEDANTIC_OCTASIC_CHECKING + while((__t4_raw_oct_in(wc, 0x0000) & (1 << 8)) && --count); + if (count != 1000) + printk("Yah, write can be slow\n"); + if (!count) + printk("Write timed out!\n"); +#endif +} + +static inline void t4_oct_out(struct t4 *wc, const unsigned int addr, const unsigned int value) +{ + unsigned long flags; + spin_lock_irqsave(&wc->reglock, flags); + __t4_oct_out(wc, addr, value); + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static inline void t4_vpm_out(struct t4 *wc, int unit, const unsigned int addr, const unsigned int value) +{ + unsigned long flags; + spin_lock_irqsave(&wc->reglock, flags); + __t4_vpm_out(wc, unit, addr, value); + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static const char vpm_digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', '*', '#'}; + +static void t4_check_vpm450(struct t4 *wc) +{ + int channel, tone, start, span; + + if (vpm450m_checkirq(wc->vpm450m)) { + while(vpm450m_getdtmf(wc->vpm450m, &channel, &tone, &start)) { + span = channel & 0x3; + channel >>= 2; + if (!wc->t1e1) + channel -= 5; + else + channel -= 1; + if (unlikely(debug)) + printk("Got tone %s of '%c' on channel %d of span %d\n", + (start ? "START" : "STOP"), tone, channel, span + 1); + if (test_bit(channel, &wc->tspans[span]->dtmfmask) && (tone != 'u')) { + if (start) { + /* The octasic is supposed to mute us, but... Yah, you + guessed it. */ + if (test_bit(channel, &wc->tspans[span]->dtmfmutemask)) { + unsigned long flags; + struct zt_chan *chan = &wc->tspans[span]->span.chans[channel]; + int y; + spin_lock_irqsave(&chan->lock, flags); + for (y=0;ynumbufs;y++) { + if ((chan->inreadbuf > -1) && (chan->readidx[y])) + memset(chan->readbuf[chan->inreadbuf], ZT_XLAW(0, chan), chan->readidx[y]); + } + spin_unlock_irqrestore(&chan->lock, flags); + } + set_bit(channel, &wc->tspans[span]->dtmfactive); + zt_qevent_lock(&wc->tspans[span]->span.chans[channel], (ZT_EVENT_DTMFDOWN | tone)); + } else { + clear_bit(channel, &wc->tspans[span]->dtmfactive); + zt_qevent_lock(&wc->tspans[span]->span.chans[channel], (ZT_EVENT_DTMFUP | tone)); + } + } + } + } +} + +static void t4_check_vpm400(struct t4 *wc, unsigned int newio) +{ + unsigned int digit, regval = 0; + unsigned int regbyte; + int x, i; + short energy=0; + static unsigned int lastio = 0; + struct t4_span *ts; + + if (debug && (newio != lastio)) + printk("Last was %08x, new is %08x\n", lastio, newio); + + lastio = newio; + + for(x = 0; x < 8; x++) { + if (newio & (1 << (7 - x))) + continue; + ts = wc->tspans[x%4]; + /* Start of DTMF detection process */ + regbyte = t4_vpm_in(wc, x, 0xb8); + t4_vpm_out(wc, x, 0xb8, regbyte); /* Write 1 to clear */ + regval = regbyte << 8; + regbyte = t4_vpm_in(wc, x, 0xb9); + t4_vpm_out(wc, x, 0xb9, regbyte); + regval |= regbyte; + + for(i = 0; (i < MAX_DTMF_DET) && regval; i++) { + if(regval & 0x0001) { + int channel = (i << 1) + (x >> 2); + int base = channel - 1; + + if (!wc->t1e1) + base -= 4; + regbyte = t4_vpm_in(wc, x, 0xa8 + i); + digit = vpm_digits[regbyte]; + if (!(wc->tspans[0]->spanflags & FLAG_VPM2GEN)) { + energy = t4_vpm_in(wc, x, 0x58 + channel); + energy = ZT_XLAW(energy, ts->chans); + ts->dtmfenergy[base] = energy; + } + set_bit(base, &ts->dtmfactive); + if (ts->dtmfdigit[base]) { + if (ts->dtmfmask & (1 << base)) + zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFUP | ts->dtmfdigit[base])); + } + ts->dtmfdigit[base] = digit; + if (test_bit(base, &ts->dtmfmask)) + zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFDOWN | digit)); + if (test_bit(base, &ts->dtmfmutemask)) { + /* Mute active receive buffer*/ + unsigned long flags; + struct zt_chan *chan = &ts->span.chans[base]; + int y; + spin_lock_irqsave(&chan->lock, flags); + for (y=0;ynumbufs;y++) { + if ((chan->inreadbuf > -1) && (chan->readidx[y])) + memset(chan->readbuf[chan->inreadbuf], ZT_XLAW(0, chan), chan->readidx[y]); + } + spin_unlock_irqrestore(&chan->lock, flags); + } + if (debug) + printk("Digit Seen: %d, Span: %d, channel: %d, energy: %02x, 'channel %d' chip %d\n", digit, x % 4, base + 1, energy, channel, x); + + } + regval = regval >> 1; + } + if (!(wc->tspans[0]->spanflags & FLAG_VPM2GEN)) + continue; + + /* Start of DTMF off detection process */ + regbyte = t4_vpm_in(wc, x, 0xbc); + t4_vpm_out(wc, x, 0xbc, regbyte); /* Write 1 to clear */ + regval = regbyte << 8; + regbyte = t4_vpm_in(wc, x, 0xbd); + t4_vpm_out(wc, x, 0xbd, regbyte); + regval |= regbyte; + + for(i = 0; (i < MAX_DTMF_DET) && regval; i++) { + if(regval & 0x0001) { + int channel = (i << 1) + (x >> 2); + int base = channel - 1; + + if (!wc->t1e1) + base -= 4; + clear_bit(base, &ts->dtmfactive); + if (ts->dtmfdigit[base]) { + if (test_bit(base, &ts->dtmfmask)) + zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFUP | ts->dtmfdigit[base])); + } + digit = ts->dtmfdigit[base]; + ts->dtmfdigit[base] = 0; + if (debug) + printk("Digit Gone: %d, Span: %d, channel: %d, energy: %02x, 'channel %d' chip %d\n", digit, x % 4, base + 1, energy, channel, x); + + } + regval = regval >> 1; + } + + } +} +#endif + +static void hdlc_stop(struct t4 *wc, unsigned int span) +{ + struct t4_span *t = wc->tspans[span]; + unsigned char imr0, imr1, mode; + int i = 0; + + if (debug & DEBUG_FRAMER) printk("Stopping HDLC controller on span %d\n", span+1); + + /* Clear receive and transmit timeslots */ + for (i = 0; i < 4; i++) { + t4_framer_out(wc, span, FRMR_RTR_BASE + i, 0x00); + t4_framer_out(wc, span, FRMR_TTR_BASE + i, 0x00); + } + + imr0 = t4_framer_in(wc, span, FRMR_IMR0); + imr1 = t4_framer_in(wc, span, FRMR_IMR1); + + /* Disable HDLC interrupts */ + imr0 |= HDLC_IMR0_MASK; + t4_framer_out(wc, span, FRMR_IMR0, imr0); + + imr1 |= HDLC_IMR1_MASK; + t4_framer_out(wc, span, FRMR_IMR1, imr1); + + mode = t4_framer_in(wc, span, FRMR_MODE); + mode &= ~FRMR_MODE_HRAC; + t4_framer_out(wc, span, FRMR_MODE, mode); + + t->sigactive = 0; +} + +static inline void __t4_framer_cmd(struct t4 *wc, unsigned int span, int cmd) +{ + __t4_framer_out(wc, span, FRMR_CMDR, cmd); +} + +static inline void t4_framer_cmd_wait(struct t4 *wc, unsigned int span, int cmd) +{ + int sis; + int loops = 0; + + /* XXX could be time consuming XXX */ + for (;;) { + sis = t4_framer_in(wc, span, FRMR_SIS); + if (!(sis & 0x04)) + break; + if (!loops++ && (debug & DEBUG_FRAMER)) { + printk("!!!SIS Waiting before cmd %02x\n", cmd); + } + } + if (loops && (debug & DEBUG_FRAMER)) + printk("!!!SIS waited %d loops\n", loops); + + t4_framer_out(wc, span, FRMR_CMDR, cmd); +} + +static int hdlc_start(struct t4 *wc, unsigned int span, struct zt_chan *chan, unsigned char mode) +{ + struct t4_span *t = wc->tspans[span]; + unsigned char imr0, imr1; + int offset = chan->chanpos; + unsigned long flags; + + if (debug & DEBUG_FRAMER) printk("Starting HDLC controller for channel %d span %d\n", offset, span+1); + + if (mode != FRMR_MODE_NO_ADDR_CMP) + return -1; + + mode |= FRMR_MODE_HRAC; + + /* Make sure we're in the right mode */ + t4_framer_out(wc, span, FRMR_MODE, mode); + t4_framer_out(wc, span, FRMR_TSEO, 0x00); + t4_framer_out(wc, span, FRMR_TSBS1, hardhdlcmode); + + /* Set the interframe gaps, etc */ + t4_framer_out(wc, span, FRMR_CCR1, FRMR_CCR1_ITF|FRMR_CCR1_EITS); + + t4_framer_out(wc, span, FRMR_CCR2, FRMR_CCR2_RCRC); + + /* Set up the time slot that we want to tx/rx on */ + t4_framer_out(wc, span, FRMR_TTR_BASE + (offset / 8), (0x80 >> (offset % 8))); + t4_framer_out(wc, span, FRMR_RTR_BASE + (offset / 8), (0x80 >> (offset % 8))); + + imr0 = t4_framer_in(wc, span, FRMR_IMR0); + imr1 = t4_framer_in(wc, span, FRMR_IMR1); + + /* Enable our interrupts again */ + imr0 &= ~HDLC_IMR0_MASK; + t4_framer_out(wc, span, FRMR_IMR0, imr0); + + imr1 &= ~HDLC_IMR1_MASK; + t4_framer_out(wc, span, FRMR_IMR1, imr1); + + /* Reset the signaling controller */ + t4_framer_cmd_wait(wc, span, FRMR_CMDR_SRES); + + spin_lock_irqsave(&wc->reglock, flags); + t->sigchan = chan; + spin_unlock_irqrestore(&wc->reglock, flags); + + t->sigactive = 0; + + return 0; +} + +static void __set_clear(struct t4 *wc, int span) +{ + int i,j; + int oldnotclear; + unsigned short val=0; + struct t4_span *ts = wc->tspans[span]; + + oldnotclear = ts->notclear; + if ((ts->spantype == TYPE_T1) || (ts->spantype == TYPE_J1)) { + for (i=0;i<24;i++) { + j = (i/8); + if (ts->span.chans[i].flags & ZT_FLAG_CLEAR) { + val |= 1 << (7 - (i % 8)); + ts->notclear &= ~(1 << i); + } else + ts->notclear |= (1 << i); + if ((i % 8)==7) { + if (debug) + printk("Putting %d in register %02x on span %d\n", + val, 0x2f + j, span + 1); + __t4_framer_out(wc, span, 0x2f + j, val); + val = 0; + } + } + } else { + for (i=0;i<31;i++) { + if (ts->span.chans[i].flags & ZT_FLAG_CLEAR) + ts->notclear &= ~(1 << i); + else + ts->notclear |= (1 << i); + } + } + if (ts->notclear != oldnotclear) { + unsigned char reg; + reg = __t4_framer_in(wc, span, FRMR_IMR0); + if (ts->notclear) + reg &= ~0x08; + else + reg |= 0x08; + __t4_framer_out(wc, span, FRMR_IMR0, reg); + } +} + +#if 0 +static void set_clear(struct t4 *wc, int span) +{ + unsigned long flags; + spin_lock_irqsave(&wc->reglock, flags); + __set_clear(wc, span); + spin_unlock_irqrestore(&wc->reglock, flags); +} +#endif + +static int t4_dacs(struct zt_chan *dst, struct zt_chan *src) +{ + struct t4 *wc; + struct t4_span *ts; + wc = dst->pvt; + ts = wc->tspans[dst->span->offset]; + if (src && (src->pvt != dst->pvt)) { + if (ts->spanflags & FLAG_2NDGEN) + t4_tsi_unassign(wc, dst->span->offset, dst->chanpos); + wc = src->pvt; + if (ts->spanflags & FLAG_2NDGEN) + t4_tsi_unassign(wc, src->span->offset, src->chanpos); + if (debug) + printk("Unassigning %d/%d by default and...\n", src->span->offset, src->chanpos); + if (debug) + printk("Unassigning %d/%d by default\n", dst->span->offset, dst->chanpos); + return -1; + } + if (src) { + t4_tsi_assign(wc, src->span->offset, src->chanpos, dst->span->offset, dst->chanpos); + if (debug) + printk("Assigning channel %d/%d -> %d/%d!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos); + } else { + t4_tsi_unassign(wc, dst->span->offset, dst->chanpos); + if (debug) + printk("Unassigning channel %d/%d!\n", dst->span->offset, dst->chanpos); + } + return 0; +} + +#ifdef VPM_SUPPORT + +void oct_set_reg(void *data, unsigned int reg, unsigned int val) +{ + struct t4 *wc = data; + t4_oct_out(wc, reg, val); +} + +unsigned int oct_get_reg(void *data, unsigned int reg) +{ + struct t4 *wc = data; + unsigned int ret; + ret = t4_oct_in(wc, reg); + return ret; +} + +static int t4_vpm_unit(int span, int channel) +{ + int unit = 0; + switch(vpmspans) { + case 4: + unit = span; + unit += (channel & 1) << 2; + break; + case 2: + unit = span; + unit += (channel & 0x3) << 1; + break; + case 1: + unit = span; + unit += (channel & 0x7); + } + return unit; +} + +static int t4_echocan(struct zt_chan *chan, int eclen) +{ + struct t4 *wc = chan->pvt; + int channel; + int unit; + + if (!wc->vpm) + return -ENODEV; + + if (chan->span->offset >= vpmspans) + return -ENODEV; + + if (wc->t1e1) + channel = chan->chanpos; + else + channel = chan->chanpos + 4; + if (wc->vpm450m) { + channel = channel << 2; + channel |= chan->span->offset; + if(debug & DEBUG_ECHOCAN) + printk("echocan: Card is %d, Channel is %d, Span is %d, offset is %d length %d\n", + wc->num, chan->chanpos, chan->span->offset, channel, eclen); + vpm450m_setec(wc->vpm450m, channel, eclen); +// Mark msleep(10); +// msleep(100); // longer test + } else { + unit = t4_vpm_unit(chan->span->offset, channel); + if(debug & DEBUG_ECHOCAN) + printk("echocan: Card is %d, Channel is %d, Span is %d, unit is %d, unit offset is %d length %d\n", + wc->num, chan->chanpos, chan->span->offset, unit, channel, eclen); + if (eclen) + t4_vpm_out(wc,unit,channel,0x3e); + else + t4_vpm_out(wc,unit,channel,0x01); + } + return 0; +} +#endif + +static int t4_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) +{ + struct t4_regs regs; + int x; + struct t4 *wc = chan->pvt; +#ifdef VPM_SUPPORT + int j; + int channel; + struct t4_span *ts = wc->tspans[chan->span->offset]; +#endif + +#ifdef VPM_SUPPORT + if (dtmfthreshold == 0) + dtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD; + if (lastdtmfthreshold != dtmfthreshold) { + lastdtmfthreshold = dtmfthreshold; + t4_vpm_set_dtmf_threshold(wc, dtmfthreshold); + } +#endif + + switch(cmd) { + case WCT4_GET_REGS: + for (x=0;xspan->offset, x); + if (copy_to_user((struct t4_regs *)data, ®s, sizeof(regs))) + return -EFAULT; + break; +#ifdef VPM_SUPPORT + case ZT_TONEDETECT: + if (get_user(j, (int *)data)) + return -EFAULT; + if (!wc->vpm) + return -ENOSYS; + if (j && (vpmdtmfsupport == 0)) + return -ENOSYS; + if (j & ZT_TONEDETECT_ON) + set_bit(chan->chanpos - 1, &ts->dtmfmask); + else + clear_bit(chan->chanpos - 1, &ts->dtmfmask); + if (j & ZT_TONEDETECT_MUTE) + set_bit(chan->chanpos - 1, &ts->dtmfmutemask); + else + clear_bit(chan->chanpos - 1, &ts->dtmfmutemask); + if (wc->vpm450m) { + channel = (chan->chanpos) << 2; + if (!wc->t1e1) + channel += (4 << 2); + channel |= chan->span->offset; + vpm450m_setdtmf(wc->vpm450m, channel, j & ZT_TONEDETECT_ON, j & ZT_TONEDETECT_MUTE); + } + return 0; +#endif + default: + return -ENOTTY; + } + return 0; +} + +static void inline t4_hdlc_xmit_fifo(struct t4 *wc, unsigned int span, struct t4_span *ts) +{ + int res, i, size = 32; + unsigned char buf[32]; + + res = zt_hdlc_getbuf(ts->sigchan, buf, &size); + if (debug & DEBUG_FRAMER) printk("Got buffer sized %d and res %d for %d\n", size, res, span); + if (size > 0) { + ts->sigactive = 1; + + if (debug & DEBUG_FRAMER) { + printk("TX("); + for (i = 0; i < size; i++) + printk((i ? " %02x" : "%02x"), buf[i]); + printk(")\n"); + } + + for (i = 0; i < size; i++) + t4_framer_out(wc, span, FRMR_TXFIFO, buf[i]); + + if (res) /* End of message */ { + if (debug & DEBUG_FRAMER) printk("transmiting XHF|XME\n"); + t4_framer_cmd_wait(wc, span, FRMR_CMDR_XHF | FRMR_CMDR_XME); +#if 0 + ts->sigactive = (__t4_framer_in(wc, span, FRMR_SIS) & FRMR_SIS_XFW) ? 0 : 1; +#endif + ++ts->frames_out; + if ((debug & DEBUG_FRAMER) && !(ts->frames_out & 0x0f)) + printk("Transmitted %d frames on span %d\n", ts->frames_out, span); + } else { /* Still more to transmit */ + if (debug & DEBUG_FRAMER) printk("transmiting XHF\n"); + t4_framer_cmd_wait(wc, span, FRMR_CMDR_XHF); + } + } + else if (res < 0) + ts->sigactive = 0; +} + +static void t4_hdlc_hard_xmit(struct zt_chan *chan) +{ + struct t4 *wc = chan->pvt; + int span = chan->span->offset; + struct t4_span *ts = wc->tspans[span]; + unsigned long flags; + + spin_lock_irqsave(&wc->reglock, flags); + if (!ts->sigchan) { + printk("t4_hdlc_hard_xmit: Invalid (NULL) signalling channel\n"); + spin_unlock_irqrestore(&wc->reglock, flags); + return; + } + spin_unlock_irqrestore(&wc->reglock, flags); + + if (debug & DEBUG_FRAMER) printk("t4_hdlc_hard_xmit on channel %s (sigchan %s), sigactive=%d\n", chan->name, ts->sigchan->name, ts->sigactive); + + if ((ts->sigchan == chan) && !ts->sigactive) + t4_hdlc_xmit_fifo(wc, span, ts); +} + +static int t4_maint(struct zt_span *span, int cmd) +{ + struct t4_span *ts = span->pvt; + struct t4 *wc = ts->owner; + + if (ts->spantype == TYPE_E1) { + switch(cmd) { + case ZT_MAINT_NONE: + printk("XXX Turn off local and remote loops E1 XXX\n"); + break; + case ZT_MAINT_LOCALLOOP: + printk("XXX Turn on local loopback E1 XXX\n"); + break; + case ZT_MAINT_REMOTELOOP: + printk("XXX Turn on remote loopback E1 XXX\n"); + break; + case ZT_MAINT_LOOPUP: + printk("XXX Send loopup code E1 XXX\n"); + break; + case ZT_MAINT_LOOPDOWN: + printk("XXX Send loopdown code E1 XXX\n"); + break; + case ZT_MAINT_LOOPSTOP: + printk("XXX Stop sending loop codes E1 XXX\n"); + break; + default: + printk("TE%dXXP: Unknown E1 maint command: %d\n", wc->numspans, cmd); + break; + } + } else { + switch(cmd) { + case ZT_MAINT_NONE: + printk("XXX Turn off local and remote loops T1 XXX\n"); + break; + case ZT_MAINT_LOCALLOOP: + printk("XXX Turn on local loop and no remote loop XXX\n"); + break; + case ZT_MAINT_REMOTELOOP: + printk("XXX Turn on remote loopup XXX\n"); + break; + case ZT_MAINT_LOOPUP: + t4_framer_out(wc, span->offset, 0x21, 0x50); /* FMR5: Nothing but RBS mode */ + break; + case ZT_MAINT_LOOPDOWN: + t4_framer_out(wc, span->offset, 0x21, 0x60); /* FMR5: Nothing but RBS mode */ + break; + case ZT_MAINT_LOOPSTOP: + t4_framer_out(wc, span->offset, 0x21, 0x40); /* FMR5: Nothing but RBS mode */ + break; + default: + printk("TE%dXXP: Unknown T1 maint command: %d\n", wc->numspans, cmd); + break; + } + } + return 0; +} + +static int t4_rbsbits(struct zt_chan *chan, int bits) +{ + u_char m,c; + int k,n,b; + struct t4 *wc = chan->pvt; + struct t4_span *ts = wc->tspans[chan->span->offset]; + unsigned long flags; + + if(debug & DEBUG_RBS) printk("Setting bits to %d on channel %s\n", bits, chan->name); + spin_lock_irqsave(&wc->reglock, flags); + k = chan->span->offset; + if (ts->spantype == TYPE_E1) { /* do it E1 way */ + if (chan->chanpos == 16) { + spin_unlock_irqrestore(&wc->reglock, flags); + return 0; + } + n = chan->chanpos - 1; + if (chan->chanpos > 15) n--; + b = (n % 15); + c = ts->txsigs[b]; + m = (n / 15) << 2; /* nibble selector */ + c &= (0xf << m); /* keep the other nibble */ + c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ + ts->txsigs[b] = c; + /* output them to the chip */ + __t4_framer_out(wc,k,0x71 + b,c); + } else if (ts->span.lineconfig & ZT_CONFIG_D4) { + n = chan->chanpos - 1; + b = (n/4); + c = ts->txsigs[b]; + m = ((3 - (n % 4)) << 1); /* nibble selector */ + c &= ~(0x3 << m); /* keep the other nibble */ + c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */ + ts->txsigs[b] = c; + /* output them to the chip */ + __t4_framer_out(wc,k,0x70 + b,c); + __t4_framer_out(wc,k,0x70 + b + 6,c); + } else if (ts->span.lineconfig & ZT_CONFIG_ESF) { + n = chan->chanpos - 1; + b = (n/2); + c = ts->txsigs[b]; + m = ((n % 2) << 2); /* nibble selector */ + c &= (0xf << m); /* keep the other nibble */ + c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ + ts->txsigs[b] = c; + /* output them to the chip */ + __t4_framer_out(wc,k,0x70 + b,c); + } + spin_unlock_irqrestore(&wc->reglock, flags); + if (debug & DEBUG_RBS) + printk("Finished setting RBS bits\n"); + return 0; +} + +static int t4_shutdown(struct zt_span *span) +{ + int tspan; + int wasrunning; + unsigned long flags; + struct t4_span *ts = span->pvt; + struct t4 *wc = ts->owner; + + tspan = span->offset + 1; + if (tspan < 0) { + printk("T%dXXP: Span '%d' isn't us?\n", wc->numspans, span->spanno); + return -1; + } + + if (debug & DEBUG_MAIN) printk("Shutting down span %d (%s)\n", span->spanno, span->name); + + /* Stop HDLC controller if runned */ + if (ts->sigchan) + hdlc_stop(wc, span->offset); + + spin_lock_irqsave(&wc->reglock, flags); + wasrunning = span->flags & ZT_FLAG_RUNNING; + + span->flags &= ~ZT_FLAG_RUNNING; + __t4_set_led(wc, span->offset, WC_OFF); + if (((wc->numspans == 4) && + (!(wc->tspans[0]->span.flags & ZT_FLAG_RUNNING)) && + (!(wc->tspans[1]->span.flags & ZT_FLAG_RUNNING)) && + (!(wc->tspans[2]->span.flags & ZT_FLAG_RUNNING)) && + (!(wc->tspans[3]->span.flags & ZT_FLAG_RUNNING))) + || + ((wc->numspans == 2) && + (!(wc->tspans[0]->span.flags & ZT_FLAG_RUNNING)) && + (!(wc->tspans[1]->span.flags & ZT_FLAG_RUNNING)))) { + /* No longer in use, disable interrupts */ + printk("TE%dXXP: Disabling interrupts since there are no active spans\n", wc->numspans); + wc->stopdma = 1; + } else wc->checktiming = 1; + spin_unlock_irqrestore(&wc->reglock, flags); + + /* Wait for interrupt routine to shut itself down */ + msleep(10); + if (wasrunning) + wc->spansstarted--; + + if (debug & DEBUG_MAIN) + printk("Span %d (%s) shutdown\n", span->spanno, span->name); + return 0; +} + +static int t4_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) +{ + int i; + struct t4_span *ts = span->pvt; + struct t4 *wc = ts->owner; + + printk("About to enter spanconfig!\n"); + if (debug & DEBUG_MAIN) + printk("TE%dXXP: Configuring span %d\n", wc->numspans, span->spanno); + + if (lc->sync < 0) + lc->sync = 0; + if (lc->sync > 4) + lc->sync = 0; + + /* remove this span number from the current sync sources, if there */ + for(i = 0; i < wc->numspans; i++) { + if (wc->tspans[i]->sync == span->spanno) { + wc->tspans[i]->sync = 0; + wc->tspans[i]->psync = 0; + } + } + wc->tspans[span->offset]->syncpos = lc->sync; + /* if a sync src, put it in proper place */ + if (lc->sync) { + wc->tspans[lc->sync - 1]->sync = span->spanno; + wc->tspans[lc->sync - 1]->psync = span->offset + 1; + } + wc->checktiming = 1; + + /* If we're already running, then go ahead and apply the changes */ + if (span->flags & ZT_FLAG_RUNNING) + return t4_startup(span); + printk("Done with spanconfig!\n"); + return 0; +} + +static int t4_chanconfig(struct zt_chan *chan, int sigtype) +{ + int alreadyrunning; + unsigned long flags; + struct t4 *wc = chan->pvt; + struct t4_span *ts = wc->tspans[chan->span->offset]; + + alreadyrunning = ts->span.flags & ZT_FLAG_RUNNING; + if (debug & DEBUG_MAIN) { + if (alreadyrunning) + printk("TE%dXXP: Reconfigured channel %d (%s) sigtype %d\n", wc->numspans, chan->channo, chan->name, sigtype); + else + printk("TE%dXXP: Configured channel %d (%s) sigtype %d\n", wc->numspans, chan->channo, chan->name, sigtype); + } + + spin_lock_irqsave(&wc->reglock, flags); + + if (alreadyrunning) + __set_clear(wc, chan->span->offset); + + spin_unlock_irqrestore(&wc->reglock, flags); + + /* (re)configure signalling channel */ + if ((sigtype == ZT_SIG_HARDHDLC) || (ts->sigchan == chan)) { + if (debug & DEBUG_FRAMER) + printk("%sonfiguring hardware HDLC on %s\n", ((sigtype == ZT_SIG_HARDHDLC) ? "C" : "Unc"), chan->name); + if (alreadyrunning) { + if (ts->sigchan) + hdlc_stop(wc, ts->sigchan->span->offset); + if (sigtype == ZT_SIG_HARDHDLC) { + if (hdlc_start(wc, chan->span->offset, chan, ts->sigmode)) { + printk("Error initializing signalling controller\n"); + return -1; + } + } else { + spin_lock_irqsave(&wc->reglock, flags); + ts->sigchan = NULL; + spin_unlock_irqrestore(&wc->reglock, flags); + } + + } + else { + spin_lock_irqsave(&wc->reglock, flags); + ts->sigchan = (sigtype == ZT_SIG_HARDHDLC) ? chan : NULL; + spin_unlock_irqrestore(&wc->reglock, flags); + ts->sigactive = 0; + } + } + return 0; +} + +static int t4_open(struct zt_chan *chan) +{ +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#else + try_module_get(THIS_MODULE); +#endif + + return 0; +} + +static int t4_close(struct zt_chan *chan) +{ +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#else + module_put(THIS_MODULE); +#endif + return 0; +} + +/* The number of cards we have seen with each + possible 'order' switch setting. +*/ +static unsigned int order_index[16]; + +static void init_spans(struct t4 *wc) +{ + int x,y; + int gen2; + int offset = 1; + struct t4_span *ts; + + gen2 = (wc->tspans[0]->spanflags & FLAG_2NDGEN); + if (!wc->t1e1) + offset += 4; + for (x = 0; x < wc->numspans; x++) { + ts = wc->tspans[x]; + sprintf(ts->span.name, "TE%d/%d/%d", wc->numspans, wc->num, x + 1); + snprintf(ts->span.desc, sizeof(ts->span.desc) - 1, + "T%dXXP (PCI) Card %d Span %d", wc->numspans, wc->num, x+1); + ts->span.manufacturer = "Digium"; + strncpy(ts->span.devicetype, wc->variety, sizeof(ts->span.devicetype) - 1); + if (wc->vpm == T4_VPM_PRESENT) { + if (!wc->vpm450m) + strncat(ts->span.devicetype, " with VPM400M", sizeof(ts->span.devicetype) - 1); + else + strncat(ts->span.devicetype, (wc->numspans > 2) ? " with VPMOCT128" : " with VPMOCT064", + sizeof(ts->span.devicetype) - 1); + } + if (order_index[wc->order] == 1) + snprintf(ts->span.location, sizeof(ts->span.location) - 1, "Board ID Switch %d", wc->order); + else + snprintf(ts->span.location, sizeof(ts->span.location) - 1, + "PCI%s Bus %02d Slot %02d", (ts->spanflags & FLAG_EXPRESS) ? " Express" : " ", + wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); + switch (ts->spantype) { + case TYPE_T1: + ts->span.spantype = "T1"; + break; + case TYPE_E1: + ts->span.spantype = "E1"; + break; + case TYPE_J1: + ts->span.spantype = "J1"; + break; + } + ts->span.spanconfig = t4_spanconfig; + ts->span.chanconfig = t4_chanconfig; + ts->span.irq = wc->dev->irq; + ts->span.startup = t4_startup; + ts->span.shutdown = t4_shutdown; + ts->span.rbsbits = t4_rbsbits; + ts->span.maint = t4_maint; + ts->span.open = t4_open; + ts->span.close = t4_close; + + /* HDLC Specific init */ + ts->sigchan = NULL; + ts->sigmode = sigmode; + ts->sigactive = 0; + + if (ts->spantype == TYPE_T1 || ts->spantype == TYPE_J1) { + ts->span.channels = 24; + ts->span.deflaw = ZT_LAW_MULAW; + ts->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; + } else { + ts->span.channels = 31; + ts->span.deflaw = ZT_LAW_ALAW; + ts->span.linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4; + } + ts->span.chans = ts->chans; + ts->span.flags = ZT_FLAG_RBS; + ts->span.ioctl = t4_ioctl; + ts->span.hdlc_hard_xmit = t4_hdlc_hard_xmit; + if (gen2) { +#ifdef VPM_SUPPORT + ts->span.echocan = t4_echocan; +#endif + ts->span.dacs = t4_dacs; + } + ts->span.pvt = ts; + ts->owner = wc; + ts->span.offset = x; + ts->writechunk = (void *)(wc->writechunk + x * 32 * 2); + ts->readchunk = (void *)(wc->readchunk + x * 32 * 2); + init_waitqueue_head(&ts->span.maintq); + for (y=0;ytspans[x]->span.channels;y++) { + struct zt_chan *mychans = ts->chans + y; + sprintf(mychans->name, "TE%d/%d/%d/%d", wc->numspans, wc->num, x + 1, y + 1); + mychans->sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS | ZT_SIG_HARDHDLC | + ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_EM_E1 | ZT_SIG_DACS_RBS; + mychans->pvt = wc; + mychans->chanpos = y + 1; + if (gen2) { + mychans->writechunk = (void *)(wc->writechunk + (x * 32 + y + offset) * 2); + mychans->readchunk = (void *)(wc->readchunk + (x * 32 + y + offset) * 2); + } + } + } +} + +static void t4_serial_setup(struct t4 *wc, int unit) +{ + if (!wc->globalconfig) { + wc->globalconfig = 1; + printk("TE%dXXP: Setting up global serial parameters\n", wc->numspans); + t4_framer_out(wc, 0, 0x85, 0xe0); /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0 */ + t4_framer_out(wc, 0, 0x08, 0x01); /* IPC: Interrupt push/pull active low */ + + /* Global clocks (8.192 Mhz CLK) */ + t4_framer_out(wc, 0, 0x92, 0x00); + t4_framer_out(wc, 0, 0x93, 0x18); + t4_framer_out(wc, 0, 0x94, 0xfb); + t4_framer_out(wc, 0, 0x95, 0x0b); + t4_framer_out(wc, 0, 0x96, 0x00); + t4_framer_out(wc, 0, 0x97, 0x0b); + t4_framer_out(wc, 0, 0x98, 0xdb); + t4_framer_out(wc, 0, 0x99, 0xdf); + } + + /* Configure interrupts */ + t4_framer_out(wc, unit, FRMR_GCR, 0x00); /* GCR: Interrupt on Activation/Deactivation of each */ + + /* Configure system interface */ + t4_framer_out(wc, unit, FRMR_SIC1, 0xc2); /* SIC1: 8.192 Mhz clock/bus, double buffer receive / transmit, byte interleaved */ + t4_framer_out(wc, unit, FRMR_SIC2, 0x20 | (unit << 1)); /* SIC2: No FFS, no center receive eliastic buffer, phase */ + t4_framer_out(wc, unit, FRMR_SIC3, 0x04); /* SIC3: Edges for capture */ + t4_framer_out(wc, unit, FRMR_CMR2, 0x00); /* CMR2: We provide sync and clock for tx and rx. */ + if (!wc->t1e1) { /* T1 mode */ + t4_framer_out(wc, unit, FRMR_XC0, 0x03); /* XC0: Normal operation of Sa-bits */ + t4_framer_out(wc, unit, FRMR_XC1, 0x84); /* XC1: 0 offset */ + if (wc->tspans[unit]->spantype == TYPE_J1) + t4_framer_out(wc, unit, FRMR_RC0, 0x83); /* RC0: Just shy of 1023 */ + else + t4_framer_out(wc, unit, FRMR_RC0, 0x03); /* RC0: Just shy of 1023 */ + t4_framer_out(wc, unit, FRMR_RC1, 0x84); /* RC1: The rest of RC0 */ + } else { /* E1 mode */ + t4_framer_out(wc, unit, FRMR_XC0, 0x00); /* XC0: Normal operation of Sa-bits */ + t4_framer_out(wc, unit, FRMR_XC1, 0x04); /* XC1: 0 offset */ + t4_framer_out(wc, unit, FRMR_RC0, 0x04); /* RC0: Just shy of 1023 */ + t4_framer_out(wc, unit, FRMR_RC1, 0x04); /* RC1: The rest of RC0 */ + } + + /* Configure ports */ + t4_framer_out(wc, unit, 0x80, 0x00); /* PC1: SPYR/SPYX input on RPA/XPA */ + t4_framer_out(wc, unit, 0x81, 0x22); /* PC2: RMFB/XSIG output/input on RPB/XPB */ + t4_framer_out(wc, unit, 0x82, 0x65); /* PC3: Some unused stuff */ + t4_framer_out(wc, unit, 0x83, 0x35); /* PC4: Some more unused stuff */ + t4_framer_out(wc, unit, 0x84, 0x01); /* PC5: XMFS active low, SCLKR is input, RCLK is output */ + if (debug & DEBUG_MAIN) + printk("Successfully initialized serial bus for unit %d\n", unit); +} + +static int syncsrc = 0; +static int syncnum = 0 /* -1 */; +static int syncspan = 0; +#ifdef DEFINE_SPINLOCK +static DEFINE_SPINLOCK(synclock); +#else +static spinlock_t synclock = SPIN_LOCK_UNLOCKED; +#endif + +static void __t4_set_timing_source(struct t4 *wc, int unit, int master, int slave) +{ + unsigned int timing; + int x; + if (unit != wc->syncsrc) { + timing = 0x34; /* CMR1: RCLK unit, 8.192 Mhz TCLK, RCLK is 8.192 Mhz */ + if ((unit > -1) && (unit < 4)) { + timing |= (unit << 6); + for (x=0;xnumspans;x++) /* set all 4 receive reference clocks to unit */ + __t4_framer_out(wc, x, 0x44, timing); + wc->dmactrl |= (1 << 29); + } else { + for (x=0;xnumspans;x++) /* set each receive reference clock to itself */ + __t4_framer_out(wc, x, 0x44, timing | (x << 6)); + wc->dmactrl &= ~(1 << 29); + } + if (slave) + wc->dmactrl |= (1 << 25); + else + wc->dmactrl &= ~(1 << 25); + if (master) + wc->dmactrl |= (1 << 24); + else + wc->dmactrl &= ~(1 << 24); + __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); + if (!master && !slave) + wc->syncsrc = unit; + if ((unit < 0) || (unit > 3)) + unit = 0; + else + unit++; + if (!master && !slave) { + for (x=0;xnumspans;x++) + wc->tspans[x]->span.syncsrc = unit; + } + } else { + if (debug & DEBUG_MAIN) + printk("TE%dXXP: Timing source already set to %d\n", wc->numspans, unit); + } +#if 0 + printk("wct4xxp: Timing source set to %d\n",unit); +#endif +} + +static inline void __t4_update_timing(struct t4 *wc) +{ + int i; + /* update sync src info */ + if (wc->syncsrc != syncsrc) { + printk("Swapping card %d from %d to %d\n", wc->num, wc->syncsrc, syncsrc); + wc->syncsrc = syncsrc; + /* Update sync sources */ + for (i = 0; i < wc->numspans; i++) { + wc->tspans[i]->span.syncsrc = wc->syncsrc; + } + if (syncnum == wc->num) { + __t4_set_timing_source(wc, syncspan-1, 1, 0); + if (debug) printk("Card %d, using sync span %d, master\n", wc->num, syncspan); + } else { + __t4_set_timing_source(wc, syncspan-1, 0, 1); + if (debug) printk("Card %d, using Timing Bus, NOT master\n", wc->num); + } + } +} + +static int __t4_findsync(struct t4 *wc) +{ + int i; + int x; + unsigned long flags; + int p; + int nonzero; + int newsyncsrc = 0; /* Zaptel span number */ + int newsyncnum = 0; /* wct4xxp card number */ + int newsyncspan = 0; /* span on given wct4xxp card */ + spin_lock_irqsave(&synclock, flags); +#if 1 + if (!wc->num) { + /* If we're the first card, go through all the motions, up to 8 levels + of sync source */ + p = 1; + while (p < 8) { + nonzero = 0; + for (x=0;cards[x];x++) { + for (i = 0; i < wc->numspans; i++) { + if (cards[x]->tspans[i]->syncpos) { + nonzero = 1; + if ((cards[x]->tspans[i]->syncpos == p) && + !(cards[x]->tspans[i]->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK)) && + (cards[x]->tspans[i]->span.flags & ZT_FLAG_RUNNING)) { + /* This makes a good sync source */ + newsyncsrc = cards[x]->tspans[i]->span.spanno; + newsyncnum = x; + newsyncspan = i + 1; + /* Jump out */ + goto found; + } + } + } + } + if (nonzero) + p++; + else + break; + } +found: + if ((syncnum != newsyncnum) || (syncsrc != newsyncsrc) || (newsyncspan != syncspan)) { + if (debug) printk("New syncnum: %d (was %d), syncsrc: %d (was %d), syncspan: %d (was %d)\n", newsyncnum, syncnum, newsyncsrc, syncsrc, newsyncspan, syncspan); + syncnum = newsyncnum; + syncsrc = newsyncsrc; + syncspan = newsyncspan; + for (x=0;cards[x];x++) { + __t4_update_timing(cards[x]); + } + } + } else + cards[0]->checktiming = 1; +#endif + spin_unlock_irqrestore(&synclock, flags); + return 0; +} + +static void __t4_set_timing_source_auto(struct t4 *wc) +{ + int x; + printk("timing source auto card %d!\n", wc->num); + wc->checktiming = 0; + if (timingcable) { + __t4_findsync(wc); + } else { + for (x=0;xnumspans;x++) { + if (wc->tspans[x]->sync) { + if ((wc->tspans[wc->tspans[x]->psync - 1]->span.flags & ZT_FLAG_RUNNING) && + !(wc->tspans[wc->tspans[x]->psync - 1]->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE) )) { + /* Valid timing source */ + __t4_set_timing_source(wc, wc->tspans[x]->psync - 1, 0, 0); + return; + } + } + } + __t4_set_timing_source(wc, 4, 0, 0); + } +} + +static void __t4_configure_t1(struct t4 *wc, int unit, int lineconfig, int txlevel) +{ + unsigned int fmr4, fmr2, fmr1, fmr0, lim2; + char *framing, *line; + int mytxlevel; + if ((txlevel > 7) || (txlevel < 4)) + mytxlevel = 0; + else + mytxlevel = txlevel - 4; + fmr1 = 0x9c; /* FMR1: Mode 1, T1 mode, CRC on for ESF, 8.192 Mhz system data rate, no XAIS */ + fmr2 = 0x22; /* FMR2: no payload loopback, auto send yellow alarm */ + if (loopback) + fmr2 |= 0x4; + fmr4 = 0x0c; /* FMR4: Lose sync on 2 out of 5 framing bits, auto resync */ + lim2 = 0x21; /* LIM2: 50% peak is a "1", Advanced Loss recovery */ + lim2 |= (mytxlevel << 6); /* LIM2: Add line buildout */ + __t4_framer_out(wc, unit, 0x1d, fmr1); + __t4_framer_out(wc, unit, 0x1e, fmr2); + + /* Configure line interface */ + if (lineconfig & ZT_CONFIG_AMI) { + line = "AMI"; + fmr0 = 0xa0; + } else { + line = "B8ZS"; + fmr0 = 0xf0; + } + if (lineconfig & ZT_CONFIG_D4) { + framing = "D4"; + } else { + framing = "ESF"; + fmr4 |= 0x2; + fmr2 |= 0xc0; + } + __t4_framer_out(wc, unit, 0x1c, fmr0); + __t4_framer_out(wc, unit, 0x20, fmr4); + __t4_framer_out(wc, unit, 0x21, 0x40); /* FMR5: Enable RBS mode */ + + __t4_framer_out(wc, unit, 0x37, 0xf0 ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ + __t4_framer_out(wc, unit, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ + + __t4_framer_out(wc, unit, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ + __t4_framer_out(wc, unit, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ + + __t4_framer_out(wc, unit, 0x3a, lim2); /* LIM2: 50% peak amplitude is a "1" */ + __t4_framer_out(wc, unit, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ + __t4_framer_out(wc, unit, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ + + /* Generate pulse mask for T1 */ + switch(mytxlevel) { + case 3: + __t4_framer_out(wc, unit, 0x26, 0x07); /* XPM0 */ + __t4_framer_out(wc, unit, 0x27, 0x01); /* XPM1 */ + __t4_framer_out(wc, unit, 0x28, 0x00); /* XPM2 */ + break; + case 2: + __t4_framer_out(wc, unit, 0x26, 0x8c); /* XPM0 */ + __t4_framer_out(wc, unit, 0x27, 0x11); /* XPM1 */ + __t4_framer_out(wc, unit, 0x28, 0x01); /* XPM2 */ + break; + case 1: + __t4_framer_out(wc, unit, 0x26, 0x8c); /* XPM0 */ + __t4_framer_out(wc, unit, 0x27, 0x01); /* XPM1 */ + __t4_framer_out(wc, unit, 0x28, 0x00); /* XPM2 */ + break; + case 0: + default: + __t4_framer_out(wc, unit, 0x26, 0xd7); /* XPM0 */ + __t4_framer_out(wc, unit, 0x27, 0x22); /* XPM1 */ + __t4_framer_out(wc, unit, 0x28, 0x01); /* XPM2 */ + break; + } + + /* Don't mask framer interrupts if hardware HDLC is in use */ + __t4_framer_out(wc, unit, FRMR_IMR0, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR0_MASK : 0)); /* IMR0: We care about CAS changes, etc */ + __t4_framer_out(wc, unit, FRMR_IMR1, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR1_MASK : 0)); /* IMR1: We care about nothing */ + __t4_framer_out(wc, unit, 0x16, 0x00); /* IMR2: We care about all the alarm stuff! */ + __t4_framer_out(wc, unit, 0x17, 0xf4); /* IMR3: We care about AIS and friends */ + __t4_framer_out(wc, unit, 0x18, 0x3f); /* IMR4: We care about slips on transmit */ + + printk("TE%dXXP: Span %d configured for %s/%s\n", wc->numspans, unit + 1, framing, line); +} + +static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig) +{ + unsigned int fmr2, fmr1, fmr0; + unsigned int cas = 0; + unsigned int imr3extra=0; + char *crc4 = ""; + char *framing, *line; + fmr1 = 0x44; /* FMR1: E1 mode, Automatic force resync, PCM30 mode, 8.192 Mhz backplane, no XAIS */ + fmr2 = 0x03; /* FMR2: Auto transmit remote alarm, auto loss of multiframe recovery, no payload loopback */ + if (loopback) + fmr2 |= 0x4; + if (lineconfig & ZT_CONFIG_CRC4) { + fmr1 |= 0x08; /* CRC4 transmit */ + fmr2 |= 0xc0; /* CRC4 receive */ + crc4 = "/CRC4"; + } + __t4_framer_out(wc, unit, 0x1d, fmr1); + __t4_framer_out(wc, unit, 0x1e, fmr2); + + /* Configure line interface */ + if (lineconfig & ZT_CONFIG_AMI) { + line = "AMI"; + fmr0 = 0xa0; + } else { + line = "HDB3"; + fmr0 = 0xf0; + } + if (lineconfig & ZT_CONFIG_CCS) { + framing = "CCS"; + imr3extra = 0x28; + } else { + framing = "CAS"; + cas = 0x40; + } + __t4_framer_out(wc, unit, 0x1c, fmr0); + + __t4_framer_out(wc, unit, 0x37, 0xf0 /*| 0x6 */ ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ + __t4_framer_out(wc, unit, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ + + __t4_framer_out(wc, unit, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ + __t4_framer_out(wc, unit, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ + + /* Condition receive line interface for E1 after reset */ + __t4_framer_out(wc, unit, 0xbb, 0x17); + __t4_framer_out(wc, unit, 0xbc, 0x55); + __t4_framer_out(wc, unit, 0xbb, 0x97); + __t4_framer_out(wc, unit, 0xbb, 0x11); + __t4_framer_out(wc, unit, 0xbc, 0xaa); + __t4_framer_out(wc, unit, 0xbb, 0x91); + __t4_framer_out(wc, unit, 0xbb, 0x12); + __t4_framer_out(wc, unit, 0xbc, 0x55); + __t4_framer_out(wc, unit, 0xbb, 0x92); + __t4_framer_out(wc, unit, 0xbb, 0x0c); + __t4_framer_out(wc, unit, 0xbb, 0x00); + __t4_framer_out(wc, unit, 0xbb, 0x8c); + + __t4_framer_out(wc, unit, 0x3a, 0x20); /* LIM2: 50% peak amplitude is a "1" */ + __t4_framer_out(wc, unit, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ + __t4_framer_out(wc, unit, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ + + __t4_framer_out(wc, unit, 0x20, 0x9f); /* XSW: Spare bits all to 1 */ + __t4_framer_out(wc, unit, 0x21, 0x1c|cas); /* XSP: E-bit set when async. AXS auto, XSIF to 1 */ + + + /* Generate pulse mask for E1 */ + __t4_framer_out(wc, unit, 0x26, 0x54); /* XPM0 */ + __t4_framer_out(wc, unit, 0x27, 0x02); /* XPM1 */ + __t4_framer_out(wc, unit, 0x28, 0x00); /* XPM2 */ + + /* Don't mask framer interrupts if hardware HDLC is in use */ + __t4_framer_out(wc, unit, FRMR_IMR0, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR0_MASK : 0)); /* IMR0: We care about CRC errors, CAS changes, etc */ + __t4_framer_out(wc, unit, FRMR_IMR1, 0x3f & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR1_MASK : 0)); /* IMR1: We care about loopup / loopdown */ + __t4_framer_out(wc, unit, 0x16, 0x00); /* IMR2: We care about all the alarm stuff! */ + __t4_framer_out(wc, unit, 0x17, 0xc4 | imr3extra); /* IMR3: We care about AIS and friends */ + __t4_framer_out(wc, unit, 0x18, 0x3f); /* IMR4: We care about slips on transmit */ + + printk("TE%dXXP: Span %d configured for %s/%s%s\n", wc->numspans, unit + 1, framing, line, crc4); +} + +static int t4_startup(struct zt_span *span) +{ +#ifdef SUPPORT_GEN1 + int i; +#endif + int tspan; + unsigned long flags; + int alreadyrunning; + struct t4_span *ts = span->pvt; + struct t4 *wc = ts->owner; + + printk("About to enter startup!\n"); + tspan = span->offset + 1; + if (tspan < 0) { + printk("TE%dXXP: Span '%d' isn't us?\n", wc->numspans, span->spanno); + return -1; + } + + spin_lock_irqsave(&wc->reglock, flags); + + alreadyrunning = span->flags & ZT_FLAG_RUNNING; + +#ifdef SUPPORT_GEN1 + /* initialize the start value for the entire chunk of last ec buffer */ + for(i = 0; i < span->channels; i++) + { + memset(ts->ec_chunk1[i], + ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); + memset(ts->ec_chunk2[i], + ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); + } +#endif + /* Force re-evaluation fo timing source */ + if (timingcable) + wc->syncsrc = -1; + + if (ts->spantype == TYPE_E1) { /* if this is an E1 card */ + __t4_configure_e1(wc, span->offset, span->lineconfig); + } else { /* is a T1 card */ + __t4_configure_t1(wc, span->offset, span->lineconfig, span->txlevel); + } + + /* Note clear channel status */ + wc->tspans[span->offset]->notclear = 0; + __set_clear(wc, span->offset); + + if (!alreadyrunning) { + span->flags |= ZT_FLAG_RUNNING; + wc->spansstarted++; + /* enable interrupts */ + /* Start DMA, enabling DMA interrupts on read only */ + wc->dmactrl = 1 << 29; +#if 0 + /* Enable framer only interrupts */ + wc->dmactrl |= 1 << 27; +#endif + wc->dmactrl |= (ts->spanflags & FLAG_2NDGEN) ? 0xc0000000 : 0xc0000003; +#ifdef VPM_SUPPORT + wc->dmactrl |= wc->vpm; +#endif + /* Seed interrupt register */ + __t4_pci_out(wc, WC_INTR, 0x0c); + if (noburst && !(ts->spanflags & FLAG_BURST)) + wc->dmactrl |= (1 << 26); + __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); + + /* Startup HDLC controller too */ + } + + if (ts->sigchan) { + struct zt_chan *sigchan = ts->sigchan; + + spin_unlock_irqrestore(&wc->reglock, flags); + if (hdlc_start(wc, span->offset, sigchan, ts->sigmode)) { + printk("Error initializing signalling controller\n"); + return -1; + } + spin_lock_irqsave(&wc->reglock, flags); + } + + spin_unlock_irqrestore(&wc->reglock, flags); + + t4_check_alarms(wc, span->offset); + t4_check_sigbits(wc, span->offset); + + if (wc->tspans[0]->sync == span->spanno) printk("SPAN %d: Primary Sync Source\n",span->spanno); + if (wc->tspans[1]->sync == span->spanno) printk("SPAN %d: Secondary Sync Source\n",span->spanno); + if (wc->numspans == 4) { + if (wc->tspans[2]->sync == span->spanno) printk("SPAN %d: Tertiary Sync Source\n",span->spanno); + if (wc->tspans[3]->sync == span->spanno) printk("SPAN %d: Quaternary Sync Source\n",span->spanno); + } +#ifdef VPM_SUPPORT + if (!alreadyrunning && !wc->vpm) { + wait_a_little(); + t4_vpm400_init(wc); + if (!wc->vpm) + t4_vpm450_init(wc); + wc->dmactrl |= wc->vpm; + t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); + } +#endif + printk("Completed startup!\n"); + return 0; +} + +#ifdef SUPPORT_GEN1 +static inline void e1_check(struct t4 *wc, int span, int val) +{ + struct t4_span *ts = wc->tspans[span]; + if ((ts->span.channels > 24) && + (ts->span.flags & ZT_FLAG_RUNNING) && + !(ts->span.alarms) && + (!wc->e1recover)) { + if (val != 0x1b) { + ts->e1check++; + } else + ts->e1check = 0; + if (ts->e1check > 100) { + /* Wait 1000 ms */ + wc->e1recover = 1000 * 8; + wc->tspans[0]->e1check = wc->tspans[1]->e1check = 0; + if (wc->numspans == 4) + wc->tspans[2]->e1check = wc->tspans[3]->e1check = 0; + if (debug & DEBUG_MAIN) + printk("Detected loss of E1 alignment on span %d!\n", span); + t4_reset_dma(wc); + } + } +} + +static void t4_receiveprep(struct t4 *wc, int irq) +{ + volatile unsigned int *readchunk; + int dbl = 0; + int x,y,z; + unsigned int tmp; + int offset=0; + if (!wc->t1e1) + offset = 4; + if (irq & 1) { + /* First part */ + readchunk = wc->readchunk; + if (!wc->last0) + dbl = 1; + wc->last0 = 0; + } else { + readchunk = wc->readchunk + ZT_CHUNKSIZE * 32; + if (wc->last0) + dbl = 1; + wc->last0 = 1; + } + if (dbl) { + for (x=0;xnumspans;x++) + wc->tspans[x]->irqmisses++; + if (debug & DEBUG_MAIN) + printk("TE%dXXP: Double/missed interrupt detected\n", wc->numspans); + } + for (x=0;xnumspans == 4) { + wc->tspans[3]->span.chans[z].readchunk[x] = tmp & 0xff; + wc->tspans[2]->span.chans[z].readchunk[x] = (tmp & 0xff00) >> 8; + } + wc->tspans[1]->span.chans[z].readchunk[x] = (tmp & 0xff0000) >> 16; + wc->tspans[0]->span.chans[z].readchunk[x] = tmp >> 24; + } + if (wc->t1e1) { + if (wc->e1recover > 0) + wc->e1recover--; + tmp = readchunk[0]; + if (wc->numspans == 4) { + e1_check(wc, 3, (tmp & 0x7f)); + e1_check(wc, 2, (tmp & 0x7f00) >> 8); + } + e1_check(wc, 1, (tmp & 0x7f0000) >> 16); + e1_check(wc, 0, (tmp & 0x7f000000) >> 24); + for (z=24;z<31;z++) { + /* Only E1 channels now */ + tmp = readchunk[z+1]; + if (wc->numspans == 4) { + if (wc->tspans[3]->span.channels > 24) + wc->tspans[3]->span.chans[z].readchunk[x] = tmp & 0xff; + if (wc->tspans[2]->span.channels > 24) + wc->tspans[2]->span.chans[z].readchunk[x] = (tmp & 0xff00) >> 8; + } + if (wc->tspans[1]->span.channels > 24) + wc->tspans[1]->span.chans[z].readchunk[x] = (tmp & 0xff0000) >> 16; + if (wc->tspans[0]->span.channels > 24) + wc->tspans[0]->span.chans[z].readchunk[x] = tmp >> 24; + } + } + /* Advance pointer by 4 TDM frame lengths */ + readchunk += 32; + } + for (x=0;xnumspans;x++) { + if (wc->tspans[x]->span.flags & ZT_FLAG_RUNNING) { + for (y=0;ytspans[x]->span.channels;y++) { + /* Echo cancel double buffered data */ + zt_ec_chunk(&wc->tspans[x]->span.chans[y], + wc->tspans[x]->span.chans[y].readchunk, + wc->tspans[x]->ec_chunk2[y]); + memcpy(wc->tspans[x]->ec_chunk2[y],wc->tspans[x]->ec_chunk1[y], + ZT_CHUNKSIZE); + memcpy(wc->tspans[x]->ec_chunk1[y], + wc->tspans[x]->span.chans[y].writechunk, + ZT_CHUNKSIZE); + } + zt_receive(&wc->tspans[x]->span); + } + } +} +#endif + +#if (ZT_CHUNKSIZE != 8) +#error Sorry, nextgen does not support chunksize != 8 +#endif + +static inline void __receive_span(struct t4_span *ts) +{ +#ifdef VPM_SUPPORT + int y; + unsigned long merged; + merged = ts->dtmfactive & ts->dtmfmutemask; + if (merged) { + for (y=0;yspan.channels;y++) { + /* Mute any DTMFs which are supposed to be muted */ + if (test_bit(y, &merged)) { + memset(ts->span.chans[y].readchunk, ZT_XLAW(0, (ts->span.chans + y)), ZT_CHUNKSIZE); + } + } + } +#endif + +#ifdef ENABLE_PREFETCH + prefetch((void *)(ts->readchunk)); + prefetch((void *)(ts->writechunk)); + prefetch((void *)(ts->readchunk + 8)); + prefetch((void *)(ts->writechunk + 8)); + prefetch((void *)(ts->readchunk + 16)); + prefetch((void *)(ts->writechunk + 16)); + prefetch((void *)(ts->readchunk + 24)); + prefetch((void *)(ts->writechunk + 24)); + prefetch((void *)(ts->readchunk + 32)); + prefetch((void *)(ts->writechunk + 32)); + prefetch((void *)(ts->readchunk + 40)); + prefetch((void *)(ts->writechunk + 40)); + prefetch((void *)(ts->readchunk + 48)); + prefetch((void *)(ts->writechunk + 48)); + prefetch((void *)(ts->readchunk + 56)); + prefetch((void *)(ts->writechunk + 56)); +#endif + + zt_ec_span(&ts->span); + zt_receive(&ts->span); +} + +static inline void __transmit_span(struct t4_span *ts) +{ + zt_transmit(&ts->span); +} + +#ifdef ENABLE_WORKQUEUES +static void workq_handlespan(void *data) +{ + struct t4_span *ts = data; + struct t4 *wc = ts->owner; + + __receive_span(ts); + __transmit_span(ts); + atomic_dec(&wc->worklist); + if (!atomic_read(&wc->worklist)) + t4_pci_out(wc, WC_INTR, 0); +} +#else +static void t4_prep_gen2(struct t4 *wc) +{ + int x; + for (x=0;xnumspans;x++) { + if (wc->tspans[x]->span.flags & ZT_FLAG_RUNNING) { + __receive_span(wc->tspans[x]); + __transmit_span(wc->tspans[x]); + } + } +} + +#endif +#ifdef SUPPORT_GEN1 +static void t4_transmitprep(struct t4 *wc, int irq) +{ + volatile unsigned int *writechunk; + int x,y,z; + unsigned int tmp; + int offset=0; + if (!wc->t1e1) + offset = 4; + if (irq & 1) { + /* First part */ + writechunk = wc->writechunk + 1; + } else { + writechunk = wc->writechunk + ZT_CHUNKSIZE * 32 + 1; + } + for (y=0;ynumspans;y++) { + if (wc->tspans[y]->span.flags & ZT_FLAG_RUNNING) + zt_transmit(&wc->tspans[y]->span); + } + + for (x=0;xtspans[3]->span.chans[z].writechunk[x]) | + (wc->tspans[2]->span.chans[z].writechunk[x] << 8) | + (wc->tspans[1]->span.chans[z].writechunk[x] << 16) | + (wc->tspans[0]->span.chans[z].writechunk[x] << 24); + writechunk[z+offset] = tmp; + } + if (wc->t1e1) { + for (z=24;z<31;z++) { + /* Only E1 channels now */ + tmp = 0; + if (wc->numspans == 4) { + if (wc->tspans[3]->span.channels > 24) + tmp |= wc->tspans[3]->span.chans[z].writechunk[x]; + if (wc->tspans[2]->span.channels > 24) + tmp |= (wc->tspans[2]->span.chans[z].writechunk[x] << 8); + } + if (wc->tspans[1]->span.channels > 24) + tmp |= (wc->tspans[1]->span.chans[z].writechunk[x] << 16); + if (wc->tspans[0]->span.channels > 24) + tmp |= (wc->tspans[0]->span.chans[z].writechunk[x] << 24); + writechunk[z] = tmp; + } + } + /* Advance pointer by 4 TDM frame lengths */ + writechunk += 32; + } + +} +#endif + +static void t4_check_sigbits(struct t4 *wc, int span) +{ + int a,i,rxs; + struct t4_span *ts = wc->tspans[span]; + + if (debug & DEBUG_RBS) + printk("Checking sigbits on span %d\n", span + 1); + + if (!(ts->span.flags & ZT_FLAG_RUNNING)) + return; + if (ts->spantype == TYPE_E1) { + for (i = 0; i < 15; i++) { + a = t4_framer_in(wc, span, 0x71 + i); + /* Get high channel in low bits */ + rxs = (a & 0xf); + if (!(ts->span.chans[i+16].sig & ZT_SIG_CLEAR)) { + if (ts->span.chans[i+16].rxsig != rxs) + zt_rbsbits(&ts->span.chans[i+16], rxs); + } + rxs = (a >> 4) & 0xf; + if (!(ts->span.chans[i].sig & ZT_SIG_CLEAR)) { + if (ts->span.chans[i].rxsig != rxs) + zt_rbsbits(&ts->span.chans[i], rxs); + } + } + } else if (ts->span.lineconfig & ZT_CONFIG_D4) { + for (i = 0; i < 24; i+=4) { + a = t4_framer_in(wc, span, 0x70 + (i>>2)); + /* Get high channel in low bits */ + rxs = (a & 0x3) << 2; + if (!(ts->span.chans[i+3].sig & ZT_SIG_CLEAR)) { + if (ts->span.chans[i+3].rxsig != rxs) + zt_rbsbits(&ts->span.chans[i+3], rxs); + } + rxs = (a & 0xc); + if (!(ts->span.chans[i+2].sig & ZT_SIG_CLEAR)) { + if (ts->span.chans[i+2].rxsig != rxs) + zt_rbsbits(&ts->span.chans[i+2], rxs); + } + rxs = (a >> 2) & 0xc; + if (!(ts->span.chans[i+1].sig & ZT_SIG_CLEAR)) { + if (ts->span.chans[i+1].rxsig != rxs) + zt_rbsbits(&ts->span.chans[i+1], rxs); + } + rxs = (a >> 4) & 0xc; + if (!(ts->span.chans[i].sig & ZT_SIG_CLEAR)) { + if (ts->span.chans[i].rxsig != rxs) + zt_rbsbits(&ts->span.chans[i], rxs); + } + } + } else { + for (i = 0; i < 24; i+=2) { + a = t4_framer_in(wc, span, 0x70 + (i>>1)); + /* Get high channel in low bits */ + rxs = (a & 0xf); + if (!(ts->span.chans[i+1].sig & ZT_SIG_CLEAR)) { + /* XXX Not really reset on every trans! XXX */ + if (ts->span.chans[i+1].rxsig != rxs) { + zt_rbsbits(&ts->span.chans[i+1], rxs); + } + } + rxs = (a >> 4) & 0xf; + if (!(ts->span.chans[i].sig & ZT_SIG_CLEAR)) { + /* XXX Not really reset on every trans! XXX */ + if (ts->span.chans[i].rxsig != rxs) { + zt_rbsbits(&ts->span.chans[i], rxs); + } + } + } + } +} + +static void t4_check_alarms(struct t4 *wc, int span) +{ + unsigned char c,d; + int alarms; + int x,j; + struct t4_span *ts = wc->tspans[span]; + unsigned long flags; + + if (!(ts->span.flags & ZT_FLAG_RUNNING)) + return; + + spin_lock_irqsave(&wc->reglock, flags); + + c = __t4_framer_in(wc, span, 0x4c); + d = __t4_framer_in(wc, span, 0x4d); + + /* Assume no alarms */ + alarms = 0; + + /* And consider only carrier alarms */ + ts->span.alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); + + if (ts->spantype == TYPE_E1) { + if (c & 0x04) { + /* No multiframe found, force RAI high after 400ms only if + we haven't found a multiframe since last loss + of frame */ + if (!(ts->spanflags & FLAG_NMF)) { + __t4_framer_out(wc, span, 0x20, 0x9f | 0x20); /* LIM0: Force RAI High */ + ts->spanflags |= FLAG_NMF; + printk("NMF workaround on!\n"); + } + __t4_framer_out(wc, span, 0x1e, 0xc3); /* Reset to CRC4 mode */ + __t4_framer_out(wc, span, 0x1c, 0xf2); /* Force Resync */ + __t4_framer_out(wc, span, 0x1c, 0xf0); /* Force Resync */ + } else if (!(c & 0x02)) { + if ((ts->spanflags & FLAG_NMF)) { + __t4_framer_out(wc, span, 0x20, 0x9f); /* LIM0: Clear forced RAI */ + ts->spanflags &= ~FLAG_NMF; + printk("NMF workaround off!\n"); + } + } + } else { + /* Detect loopup code if we're not sending one */ + if ((!ts->span.mainttimer) && (d & 0x08)) { + /* Loop-up code detected */ + if ((ts->loopupcnt++ > 80) && (ts->span.maintstat != ZT_MAINT_REMOTELOOP)) { + __t4_framer_out(wc, span, 0x36, 0x08); /* LIM0: Disable any local loop */ + __t4_framer_out(wc, span, 0x37, 0xf6 ); /* LIM1: Enable remote loop */ + ts->span.maintstat = ZT_MAINT_REMOTELOOP; + } + } else + ts->loopupcnt = 0; + /* Same for loopdown code */ + if ((!ts->span.mainttimer) && (d & 0x10)) { + /* Loop-down code detected */ + if ((ts->loopdowncnt++ > 80) && (ts->span.maintstat == ZT_MAINT_REMOTELOOP)) { + __t4_framer_out(wc, span, 0x36, 0x08); /* LIM0: Disable any local loop */ + __t4_framer_out(wc, span, 0x37, 0xf0 ); /* LIM1: Disable remote loop */ + ts->span.maintstat = ZT_MAINT_NONE; + } + } else + ts->loopdowncnt = 0; + } + + if (ts->span.lineconfig & ZT_CONFIG_NOTOPEN) { + for (x=0,j=0;x < ts->span.channels;x++) + if ((ts->span.chans[x].flags & ZT_FLAG_OPEN) || + (ts->span.chans[x].flags & ZT_FLAG_NETDEV)) + j++; + if (!j) + alarms |= ZT_ALARM_NOTOPEN; + } + + if (c & 0xa0) { + if (ts->alarmcount >= alarmdebounce) + alarms |= ZT_ALARM_RED; + else + ts->alarmcount++; + } else + ts->alarmcount = 0; + if (c & 0x4) + alarms |= ZT_ALARM_BLUE; + + if (((!ts->span.alarms) && alarms) || + (ts->span.alarms && (!alarms))) + wc->checktiming = 1; + + /* Keep track of recovering */ + if ((!alarms) && ts->span.alarms) + ts->alarmtimer = ZT_ALARMSETTLE_TIME; + if (ts->alarmtimer) + alarms |= ZT_ALARM_RECOVER; + + /* If receiving alarms, go into Yellow alarm state */ + if (alarms && !(ts->spanflags & FLAG_SENDINGYELLOW)) { + unsigned char fmr4; +#if 1 + printk("wct%dxxp: Setting yellow alarm on span %d\n", wc->numspans, span + 1); +#endif + /* We manually do yellow alarm to handle RECOVER and NOTOPEN, otherwise it's auto anyway */ + fmr4 = __t4_framer_in(wc, span, 0x20); + __t4_framer_out(wc, span, 0x20, fmr4 | 0x20); + ts->spanflags |= FLAG_SENDINGYELLOW; + } else if ((!alarms) && (ts->spanflags & FLAG_SENDINGYELLOW)) { + unsigned char fmr4; +#if 1 + printk("wct%dxxp: Clearing yellow alarm on span %d\n", wc->numspans, span + 1); +#endif + /* We manually do yellow alarm to handle RECOVER */ + fmr4 = __t4_framer_in(wc, span, 0x20); + __t4_framer_out(wc, span, 0x20, fmr4 & ~0x20); + ts->spanflags &= ~FLAG_SENDINGYELLOW; + } + + /* Re-check the timing source when we enter/leave alarm, not withstanding + yellow alarm */ + if (c & 0x10) + alarms |= ZT_ALARM_YELLOW; + if (ts->span.mainttimer || ts->span.maintstat) + alarms |= ZT_ALARM_LOOPBACK; + ts->span.alarms = alarms; + spin_unlock_irqrestore(&wc->reglock, flags); + zt_alarm_notify(&ts->span); +} + +static void t4_do_counters(struct t4 *wc) +{ + int span; + for (span=0;spannumspans;span++) { + struct t4_span *ts = wc->tspans[span]; + int docheck=0; + + spin_lock(&wc->reglock); + if (ts->loopupcnt || ts->loopdowncnt) + docheck++; + if (ts->alarmtimer) { + if (!--ts->alarmtimer) { + docheck++; + ts->span.alarms &= ~(ZT_ALARM_RECOVER); + } + } + spin_unlock(&wc->reglock); + if (docheck) { + t4_check_alarms(wc, span); + zt_alarm_notify(&ts->span); + } + } +} + +static inline void __handle_leds(struct t4 *wc) +{ + int x; + + wc->blinktimer++; + for (x=0;xnumspans;x++) { + struct t4_span *ts = wc->tspans[x]; + if (ts->span.flags & ZT_FLAG_RUNNING) { + if (ts->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) { +#ifdef FANCY_ALARM + if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) { + __t4_set_led(wc, x, WC_RED); + } + if (wc->blinktimer == 0xf) { + __t4_set_led(wc, x, WC_OFF); + } +#else + if (wc->blinktimer == 160) { + __t4_set_led(wc, x, WC_RED); + } else if (wc->blinktimer == 480) { + __t4_set_led(wc, x, WC_OFF); + } +#endif + } else if (ts->span.alarms & ZT_ALARM_YELLOW) { + /* Yellow Alarm */ + __t4_set_led(wc, x, WC_YELLOW); + } else if (ts->span.mainttimer || ts->span.maintstat) { +#ifdef FANCY_ALARM + if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) { + __t4_set_led(wc, x, WC_GREEN); + } + if (wc->blinktimer == 0xf) { + __t4_set_led(wc, x, WC_OFF); + } +#else + if (wc->blinktimer == 160) { + __t4_set_led(wc, x, WC_GREEN); + } else if (wc->blinktimer == 480) { + __t4_set_led(wc, x, WC_OFF); + } +#endif + } else { + /* No Alarm */ + __t4_set_led(wc, x, WC_GREEN); + } + } else + __t4_set_led(wc, x, WC_OFF); + + } +#ifdef FANCY_ALARM + if (wc->blinktimer == 0xf) { + wc->blinktimer = -1; + wc->alarmpos++; + if (wc->alarmpos >= (sizeof(altab) / sizeof(altab[0]))) + wc->alarmpos = 0; + } +#else + if (wc->blinktimer == 480) + wc->blinktimer = 0; +#endif +} + +static inline void t4_framer_interrupt(struct t4 *wc, int span) +{ + /* Check interrupts for a given span */ + unsigned char gis, isr0, isr1, isr2, isr3, isr4; + int readsize = -1; + struct t4_span *ts = wc->tspans[span]; + struct zt_chan *sigchan; + unsigned long flags; + + if (debug & DEBUG_FRAMER) + printk("framer interrupt span %d:%d!\n", wc->num, span + 1); + + /* 1st gen cards isn't used interrupts */ + gis = t4_framer_in(wc, span, FRMR_GIS); + isr0 = (gis & FRMR_GIS_ISR0) ? t4_framer_in(wc, span, FRMR_ISR0) : 0; + isr1 = (gis & FRMR_GIS_ISR1) ? t4_framer_in(wc, span, FRMR_ISR1) : 0; + isr2 = (gis & FRMR_GIS_ISR2) ? t4_framer_in(wc, span, FRMR_ISR2) : 0; + isr3 = (gis & FRMR_GIS_ISR3) ? t4_framer_in(wc, span, FRMR_ISR3) : 0; + isr4 = (gis & FRMR_GIS_ISR4) ? t4_framer_in(wc, span, FRMR_ISR4) : 0; + + if (debug & DEBUG_FRAMER) + printk("gis: %02x, isr0: %02x, isr1: %02x, isr2: %02x, isr3: %02x, isr4: %02x\n", gis, isr0, isr1, isr2, isr3, isr4); + + if (isr0) + t4_check_sigbits(wc, span); + + if (ts->spantype == TYPE_E1) { + /* E1 checks */ + if ((isr3 & 0x38) || isr2 || isr1) + t4_check_alarms(wc, span); + } else { + /* T1 checks */ + if (isr2 || (isr3 & 0x08)) + t4_check_alarms(wc, span); + } + if (!ts->span.alarms) { + if ((isr3 & 0x3) || (isr4 & 0xc0)) + ts->span.timingslips++; + + if (debug & DEBUG_MAIN) { + if (isr3 & 0x02) + printk("TE%d10P: RECEIVE slip NEGATIVE on span %d\n", wc->numspans, span + 1); + if (isr3 & 0x01) + printk("TE%d10P: RECEIVE slip POSITIVE on span %d\n", wc->numspans, span + 1); + if (isr4 & 0x80) + printk("TE%dXXP: TRANSMIT slip POSITIVE on span %d\n", wc->numspans, span + 1); + if (isr4 & 0x40) + printk("TE%d10P: TRANSMIT slip NEGATIVE on span %d\n", wc->numspans, span + 1); + } + } else + ts->span.timingslips = 0; + + spin_lock_irqsave(&wc->reglock, flags); + /* HDLC controller checks - receive side */ + if (!ts->sigchan) { + spin_unlock_irqrestore(&wc->reglock, flags); + return; + } + + sigchan = ts->sigchan; + spin_unlock_irqrestore(&wc->reglock, flags); + + if (isr0 & FRMR_ISR0_RME) { + readsize = (t4_framer_in(wc, span, FRMR_RBCH) << 8) | t4_framer_in(wc, span, FRMR_RBCL); + if (debug & DEBUG_FRAMER) printk("Received data length is %d (%d)\n", readsize, readsize & FRMR_RBCL_MAX_SIZE); + /* RPF isn't set on last part of frame */ + if ((readsize > 0) && ((readsize &= FRMR_RBCL_MAX_SIZE) == 0)) + readsize = 32; + } else if (isr0 & FRMR_ISR0_RPF) + readsize = 32; + + if (readsize > 0) { + int i; + unsigned char readbuf[readsize]; + + if (debug & DEBUG_FRAMER) printk("Framer %d: Got RPF/RME! readsize is %d\n", sigchan->span->offset, readsize); + + for (i = 0; i < readsize; i++) + readbuf[i] = t4_framer_in(wc, span, FRMR_RXFIFO); + + /* Tell the framer to clear the RFIFO */ + t4_framer_cmd_wait(wc, span, FRMR_CMDR_RMC); + + if (debug & DEBUG_FRAMER) { + printk("RX("); + for (i = 0; i < readsize; i++) + printk((i ? " %02x" : "%02x"), readbuf[i]); + printk(")\n"); + } + + if (isr0 & FRMR_ISR0_RME) { + /* Do checks for HDLC problems */ + unsigned char rsis = readbuf[readsize-1]; +#if 0 + unsigned int olddebug = debug; +#endif + unsigned char rsis_reg = t4_framer_in(wc, span, FRMR_RSIS); + +#if 0 + if ((rsis != 0xA2) || (rsis != rsis_reg)) + debug |= DEBUG_FRAMER; +#endif + + ++ts->frames_in; + if ((debug & DEBUG_FRAMER) && !(ts->frames_in & 0x0f)) + printk("Received %d frames on span %d\n", ts->frames_in, span); + if (debug & DEBUG_FRAMER) printk("Received HDLC frame %d. RSIS = 0x%x (%x)\n", ts->frames_in, rsis, rsis_reg); + if (!(rsis & FRMR_RSIS_CRC16)) { + if (debug & DEBUG_FRAMER) printk("CRC check failed %d\n", span); + zt_hdlc_abort(sigchan, ZT_EVENT_BADFCS); + } else if (rsis & FRMR_RSIS_RAB) { + if (debug & DEBUG_FRAMER) printk("ABORT of current frame due to overflow %d\n", span); + zt_hdlc_abort(sigchan, ZT_EVENT_ABORT); + } else if (rsis & FRMR_RSIS_RDO) { + if (debug & DEBUG_FRAMER) printk("HDLC overflow occured %d\n", span); + zt_hdlc_abort(sigchan, ZT_EVENT_OVERRUN); + } else if (!(rsis & FRMR_RSIS_VFR)) { + if (debug & DEBUG_FRAMER) printk("Valid Frame check failed on span %d\n", span); + zt_hdlc_abort(sigchan, ZT_EVENT_ABORT); + } else { + zt_hdlc_putbuf(sigchan, readbuf, readsize - 1); + zt_hdlc_finish(sigchan); + if (debug & DEBUG_FRAMER) printk("Received valid HDLC frame on span %d\n", span); + } +#if 0 + debug = olddebug; +#endif + } else if (isr0 & FRMR_ISR0_RPF) + zt_hdlc_putbuf(sigchan, readbuf, readsize); + } + + /* Transmit side */ + if (isr1 & FRMR_ISR1_XDU) { + if (debug & DEBUG_FRAMER) printk("XDU: Resetting signal controler!\n"); + t4_framer_cmd_wait(wc, span, FRMR_CMDR_SRES); + } else if (isr1 & FRMR_ISR1_XPR) { + if (debug & DEBUG_FRAMER) + printk("Sigchan %d is %p\n", sigchan->chanpos, sigchan); + + if (debug & DEBUG_FRAMER) printk("Framer %d: Got XPR!\n", sigchan->span->offset); + t4_hdlc_xmit_fifo(wc, span, ts); + } + + if (isr1 & FRMR_ISR1_ALLS) { + if (debug & DEBUG_FRAMER) printk("ALLS received\n"); + } + +} + +#ifdef SUPPORT_GEN1 +ZAP_IRQ_HANDLER(t4_interrupt) +{ + struct t4 *wc = dev_id; + unsigned long flags; + int x; + + unsigned int status; + unsigned int status2; + +#if 0 + if (wc->intcount < 20) + printk("Pre-interrupt\n"); +#endif + + /* Make sure it's really for us */ + status = __t4_pci_in(wc, WC_INTR); + + /* Process framer interrupts */ + status2 = t4_framer_in(wc, 0, FRMR_CIS); + if (status2 & 0x0f) { + for (x = 0; x < wc->numspans; ++x) { + if (status2 & (1 << x)) + t4_framer_interrupt(wc, x); + } + } + + /* Ignore if it's not for us */ + if (!status) +#ifdef LINUX26 + return IRQ_NONE; +#else + return; +#endif + + __t4_pci_out(wc, WC_INTR, 0); + + if (!wc->spansstarted) { + printk("Not prepped yet!\n"); +#ifdef LINUX26 + return IRQ_NONE; +#else + return; +#endif + } + + wc->intcount++; +#if 0 + if (wc->intcount < 20) + printk("Got interrupt, status = %08x\n", status); +#endif + + if (status & 0x3) { + t4_receiveprep(wc, status); + t4_transmitprep(wc, status); + } + +#if 0 + if ((wc->intcount < 10) || !(wc->intcount % 1000)) { + status2 = t4_framer_in(wc, 0, FRMR_CIS); + printk("Status2: %04x\n", status2); + for (x = 0;x<4;x++) { + status2 = t4_framer_in(wc, x, FRMR_FRS0); + printk("FRS0/%d: %04x\n", x, status2); + } + } +#endif + t4_do_counters(wc); + + x = wc->intcount & 15 /* 63 */; + switch(x) { + case 0: + case 1: + case 2: + case 3: + t4_check_sigbits(wc, x); + break; + case 4: + case 5: + case 6: + case 7: + t4_check_alarms(wc, x - 4); + break; + } + + spin_lock_irqsave(&wc->reglock, flags); + + __handle_leds(wc); + + if (wc->checktiming > 0) + __t4_set_timing_source_auto(wc); + + spin_unlock_irqrestore(&wc->reglock, flags); +#ifdef LINUX26 + return IRQ_RETVAL(1); +#endif +} +#endif + +static void t4_isr_bh(unsigned long data) +{ + struct t4 *wc = (struct t4 *)data; + +#ifdef VPM_SUPPORT + if (wc->vpm) { + if (test_and_clear_bit(T4_CHECK_VPM, &wc->checkflag)) { + if (wc->vpm450m) { + /* How stupid is it that the octasic can't generate an + interrupt when there's a tone, in spite of what their + documentation says? */ + t4_check_vpm450(wc); + } else + t4_check_vpm400(wc, wc->vpm400checkstatus); + } + } +#endif +} + +ZAP_IRQ_HANDLER(t4_interrupt_gen2) +{ + struct t4 *wc = dev_id; + unsigned int status; + + /* Make sure it's really for us */ + status = __t4_pci_in(wc, WC_INTR); + + /* Ignore if it's not for us */ + if (!(status & 0x7)) { +#ifdef LINUX26 + return IRQ_NONE; +#else + return; +#endif + } + +#ifdef ENABLE_WORKQUEUES + __t4_pci_out(wc, WC_INTR, status & 0x00000008); +#endif + + if (unlikely(!wc->spansstarted)) { + printk("Not prepped yet!\n"); +#ifdef LINUX26 + return IRQ_NONE; +#else + return; +#endif + } + + wc->intcount++; + + if (unlikely((wc->intcount < 20) && debug)) + + printk("2G: Got interrupt, status = %08x, CIS = %04x\n", status, t4_framer_in(wc, 0, FRMR_CIS)); + + if (likely(status & 0x2)) { +#ifdef ENABLE_WORKQUEUES + int cpus = num_online_cpus(); + atomic_set(&wc->worklist, wc->numspans); + if (wc->tspans[0]->span.flags & ZT_FLAG_RUNNING) + t4_queue_work(wc->workq, &wc->tspans[0]->swork, 0); + else + atomic_dec(&wc->worklist); + if (wc->tspans[1]->span.flags & ZT_FLAG_RUNNING) + t4_queue_work(wc->workq, &wc->tspans[1]->swork, 1 % cpus); + else + atomic_dec(&wc->worklist); + if (wc->numspans == 4) { + if (wc->tspans[2]->span.flags & ZT_FLAG_RUNNING) + t4_queue_work(wc->workq, &wc->tspans[2]->swork, 2 % cpus); + else + atomic_dec(&wc->worklist); + if (wc->tspans[3]->span.flags & ZT_FLAG_RUNNING) + t4_queue_work(wc->workq, &wc->tspans[3]->swork, 3 % cpus); + else + atomic_dec(&wc->worklist); + } +#else + t4_prep_gen2(wc); +#endif + t4_do_counters(wc); + spin_lock(&wc->reglock); + __handle_leds(wc); + spin_unlock(&wc->reglock); + + } + + if (unlikely(status & 0x1)) { + unsigned char cis; + + cis = t4_framer_in(wc, 0, FRMR_CIS); + if (cis & FRMR_CIS_GIS1) + t4_framer_interrupt(wc, 0); + if (cis & FRMR_CIS_GIS2) + t4_framer_interrupt(wc, 1); + if (cis & FRMR_CIS_GIS3) + t4_framer_interrupt(wc, 2); + if (cis & FRMR_CIS_GIS4) + t4_framer_interrupt(wc, 3); + } + + if (wc->vpm) { + if (wc->vpm450m) { + /* How stupid is it that the octasic can't generate an + interrupt when there's a tone, in spite of what their + documentation says? */ + if (!(wc->intcount & 0xf)) { + set_bit(T4_CHECK_VPM, &wc->checkflag); + } + } else if ((status & 0xff00) != 0xff00) { + wc->vpm400checkstatus = (status & 0xff00) >> 8; + set_bit(T4_CHECK_VPM, &wc->checkflag); + } + } + + spin_lock(&wc->reglock); + + if (unlikely(wc->checktiming > 0)) { + __t4_set_timing_source_auto(wc); + } + + if (unlikely(wc->stopdma)) { + /* Stop DMA cleanly if requested */ + wc->dmactrl = 0x0; + __t4_pci_out(wc, WC_DMACTRL, 0x00000000); + /* Acknowledge any pending interrupts */ + __t4_pci_out(wc, WC_INTR, 0x00000000); + __t4_set_timing_source(wc, 4, 0, 0); + wc->stopdma = 0x0; + } + + spin_unlock(&wc->reglock); + + if (unlikely(test_bit(T4_CHECK_VPM, &wc->checkflag))) + tasklet_schedule(&wc->t4_tlet); + +#ifndef ENABLE_WORKQUEUES + __t4_pci_out(wc, WC_INTR, 0); +#endif +#ifdef LINUX26 + return IRQ_RETVAL(1); +#endif +} + +#ifdef SUPPORT_GEN1 +static int t4_reset_dma(struct t4 *wc) +{ + /* Turn off DMA and such */ + wc->dmactrl = 0x0; + t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); + t4_pci_out(wc, WC_COUNT, 0); + t4_pci_out(wc, WC_RDADDR, 0); + t4_pci_out(wc, WC_WRADDR, 0); + t4_pci_out(wc, WC_INTR, 0); + /* Turn it all back on */ + t4_pci_out(wc, WC_RDADDR, wc->readdma); + t4_pci_out(wc, WC_WRADDR, wc->writedma); + t4_pci_out(wc, WC_COUNT, ((ZT_MAX_CHUNKSIZE * 2 * 32 - 1) << 18) | ((ZT_MAX_CHUNKSIZE * 2 * 32 - 1) << 2)); + t4_pci_out(wc, WC_INTR, 0); +#ifdef VPM_SUPPORT + wc->dmactrl = 0xc0000000 | (1 << 29) | wc->vpm; +#else + wc->dmactrl = 0xc0000000 | (1 << 29); +#endif + if (noburst) + wc->dmactrl |= (1 << 26); + t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); + return 0; +} +#endif + +#ifdef VPM_SUPPORT +static void t4_vpm_set_dtmf_threshold(struct t4 *wc, unsigned int threshold) +{ + unsigned int x; + + for (x = 0; x < 8; x++) { + t4_vpm_out(wc, x, 0xC4, (threshold >> 8) & 0xFF); + t4_vpm_out(wc, x, 0xC5, (threshold & 0xFF)); + } + printk("VPM: DTMF threshold set to %d\n", threshold); +} + +static unsigned int t4_vpm_mask(int chip) +{ + unsigned int mask=0; + switch(vpmspans) { + case 4: + mask = 0x55555555 << (chip >> 2); + break; + case 2: + mask = 0x11111111 << (chip >> 1); + break; + case 1: + mask = 0x01010101 << chip; + break; + } + return mask; +} + +static int t4_vpm_spanno(int chip) +{ + int spanno = 0; + switch(vpmspans) { + case 4: + spanno = chip & 0x3; + break; + case 2: + spanno = chip & 0x1; + break; + /* Case 1 is implicit */ + } + return spanno; +} + +static int t4_vpm_echotail(void) +{ + int echotail = 0x01ff; + switch(vpmspans) { + case 4: + echotail = 0x007f; + break; + case 2: + echotail = 0x00ff; + break; + /* Case 1 is implicit */ + } + return echotail; +} + +static void t4_vpm450_init(struct t4 *wc) +{ + unsigned int check1, check2; + int laws[4] = { 0, }; + int x; + unsigned int vpm_capacity; + struct firmware embedded_firmware; + const struct firmware *firmware = &embedded_firmware; +#if !defined(HOTPLUG_FIRMWARE) + extern void _binary_zaptel_fw_oct6114_064_bin_size; + extern void _binary_zaptel_fw_oct6114_128_bin_size; + extern u8 _binary_zaptel_fw_oct6114_064_bin_start[]; + extern u8 _binary_zaptel_fw_oct6114_128_bin_start[]; +#else + static const char oct064_firmware[] = "zaptel-fw-oct6114-064.bin"; + static const char oct128_firmware[] = "zaptel-fw-oct6114-128.bin"; +#endif + + if (!vpmsupport) { + printk("VPM450: Support Disabled\n"); + return; + } + + /* Turn on GPIO/DATA mux if supported */ + t4_gpio_setdir(wc, (1 << 24), (1 << 24)); + __t4_raw_oct_out(wc, 0x000a, 0x5678); + __t4_raw_oct_out(wc, 0x0004, 0x1234); + check1 = __t4_raw_oct_in(wc, 0x0004); + check2 = __t4_raw_oct_in(wc, 0x000a); + if (debug) + printk("OCT Result: %04x/%04x\n", __t4_raw_oct_in(wc, 0x0004), __t4_raw_oct_in(wc, 0x000a)); + if (__t4_raw_oct_in(wc, 0x0004) != 0x1234) { + printk("VPM450: Not Present\n"); + return; + } + + /* Setup alaw vs ulaw rules */ + for (x = 0;x < wc->numspans; x++) { + if (wc->tspans[x]->span.channels > 24) + laws[x] = 1; + } + + switch ((vpm_capacity = get_vpm450m_capacity(wc))) { + case 64: +#if defined(HOTPLUG_FIRMWARE) + if ((request_firmware(&firmware, oct064_firmware, &wc->dev->dev) != 0) || + !firmware) { + printk("VPM450: firmware %s not available from userspace\n", oct064_firmware); + return; + } +#else + embedded_firmware.data = _binary_zaptel_fw_oct6114_064_bin_start; + /* Yes... this is weird. objcopy gives us a symbol containing + the size of the firmware, not a pointer a variable containing + the size. The only way we can get the value of the symbol + is to take its address, so we define it as a pointer and + then cast that value to the proper type. + */ + embedded_firmware.size = (size_t) &_binary_zaptel_fw_oct6114_064_bin_size; +#endif + break; + case 128: +#if defined(HOTPLUG_FIRMWARE) + if ((request_firmware(&firmware, oct128_firmware, &wc->dev->dev) != 0) || + !firmware) { + printk("VPM450: firmware %s not available from userspace\n", oct128_firmware); + return; + } +#else + embedded_firmware.data = _binary_zaptel_fw_oct6114_128_bin_start; + /* Yes... this is weird. objcopy gives us a symbol containing + the size of the firmware, not a pointer a variable containing + the size. The only way we can get the value of the symbol + is to take its address, so we define it as a pointer and + then cast that value to the proper type. + */ + embedded_firmware.size = (size_t) &_binary_zaptel_fw_oct6114_128_bin_size; +#endif + break; + default: + printk("Unsupported channel capacity found on VPM module (%d).\n", vpm_capacity); + return; + } + + if (!(wc->vpm450m = init_vpm450m(wc, laws, wc->numspans, firmware))) { + printk("VPM450: Failed to initialize\n"); + if (firmware != &embedded_firmware) + release_firmware(firmware); + return; + } + + if (firmware != &embedded_firmware) + release_firmware(firmware); + + if (vpmdtmfsupport == -1) { + printk("VPM450: hardware DTMF disabled.\n"); + vpmdtmfsupport = 0; + } + + wc->vpm = T4_VPM_PRESENT; + printk("VPM450: Present and operational servicing %d span(s)\n", wc->numspans); + +} + +static void t4_vpm400_init(struct t4 *wc) +{ + unsigned char reg; + unsigned int mask; + unsigned int ver; + unsigned int i, x, y, gen2vpm=0; + + if (!vpmsupport) { + printk("VPM400: Support Disabled\n"); + return; + } + + switch(vpmspans) { + case 4: + case 2: + case 1: + break; + default: + printk("VPM400: %d is not a valid vpmspans value, using 4\n", vpmspans); + vpmspans = 4; + } + + for (x=0;x<8;x++) { + int spanno = t4_vpm_spanno(x); + struct t4_span *ts = wc->tspans[spanno]; + int echotail = t4_vpm_echotail(); + + ver = t4_vpm_in(wc, x, 0x1a0); /* revision */ + if ((ver != 0x26) && (ver != 0x33)) { + printk("VPM400: %s\n", x ? "Inoperable" : "Not Present"); + return; + } + if (ver == 0x33) { + if (x && !gen2vpm) { + printk("VPM400: Inconsistent\n"); + return; + } + ts->spanflags |= FLAG_VPM2GEN; + gen2vpm++; + } else if (gen2vpm) { + printk("VPM400: Inconsistent\n"); + return; + } + + + /* Setup GPIO's */ + for (y=0;y<4;y++) { + t4_vpm_out(wc, x, 0x1a8 + y, 0x00); /* GPIO out */ + t4_vpm_out(wc, x, 0x1ac + y, 0x00); /* GPIO dir */ + t4_vpm_out(wc, x, 0x1b0 + y, 0x00); /* GPIO sel */ + } + + /* Setup TDM path - sets fsync and tdm_clk as inputs */ + reg = t4_vpm_in(wc, x, 0x1a3); /* misc_con */ + t4_vpm_out(wc, x, 0x1a3, reg & ~2); + + /* Setup timeslots */ + t4_vpm_out(wc, x, 0x02f, 0x20 | (spanno << 3)); + + /* Setup Echo length (128 taps) */ + t4_vpm_out(wc, x, 0x022, (echotail >> 8)); + t4_vpm_out(wc, x, 0x023, (echotail & 0xff)); + + /* Setup the tdm channel masks for all chips*/ + mask = t4_vpm_mask(x); + for (i = 0; i < 4; i++) + t4_vpm_out(wc, x, 0x30 + i, (mask >> (i << 3)) & 0xff); + + /* Setup convergence rate */ + reg = t4_vpm_in(wc,x,0x20); + reg &= 0xE0; + if (ts->spantype == TYPE_E1) { + if (x < vpmspans) + printk("VPM400: Span %d A-law mode\n", spanno); + reg |= 0x01; + } else { + if (x < vpmspans) + printk("VPM400: Span %d U-law mode\n", spanno); + reg &= ~0x01; + } + t4_vpm_out(wc,x,0x20,(reg | 0x20)); + + /* Initialize echo cans */ + for (i = 0 ; i < MAX_TDM_CHAN; i++) { + if (mask & (0x00000001 << i)) + t4_vpm_out(wc,x,i,0x00); + } + + wait_a_little(); + + /* Put in bypass mode */ + for (i = 0 ; i < MAX_TDM_CHAN ; i++) { + if (mask & (0x00000001 << i)) { + t4_vpm_out(wc,x,i,0x01); + } + } + + /* Enable bypass */ + for (i = 0 ; i < MAX_TDM_CHAN ; i++) { + if (mask & (0x00000001 << i)) + t4_vpm_out(wc,x,0x78 + i,0x01); + } + + /* set DTMF detection threshold */ + t4_vpm_set_dtmf_threshold(wc, dtmfthreshold); + + /* Enable DTMF detectors (always DTMF detect all spans) */ + for (i = 0; i < MAX_DTMF_DET; i++) { + t4_vpm_out(wc, x, 0x98 + i, 0x40 | (i * 2) | ((x < 4) ? 0 : 1)); + } + for (i = 0x34; i < 0x38; i++) + t4_vpm_out(wc, x, i, 0x00); + for (i = 0x3C; i < 0x40; i++) + t4_vpm_out(wc, x, i, 0x00); + + for (i = 0x48; i < 0x4B; i++) + t4_vpm_out(wc, x, i, 0x00); + for (i = 0x50; i < 0x53; i++) + t4_vpm_out(wc, x, i, 0x00); + for (i = 0xB8; i < 0xBE; i++) + t4_vpm_out(wc, x, i, 0xFF); + if (gen2vpm) { + for (i = 0xBE; i < 0xC0; i++) + t4_vpm_out(wc, x, i, 0xFF); + } else { + for (i = 0xBE; i < 0xC0; i++) + t4_vpm_out(wc, x, i, 0x00); + } + for (i = 0xC0; i < 0xC4; i++) + t4_vpm_out(wc, x, i, (x < 4) ? 0x55 : 0xAA); + + } + if (vpmdtmfsupport == -1) { + printk("VPM400: hardware DTMF enabled.\n"); + vpmdtmfsupport = 0; + } + printk("VPM400%s: Present and operational servicing %d span(s)\n", (gen2vpm ? " (2nd Gen)" : ""), wc->numspans); + wc->vpm = T4_VPM_PRESENT; +} + +#endif + +static void t4_tsi_reset(struct t4 *wc) +{ + int x; + for (x=0;x<128;x++) { + wc->dmactrl &= ~0x00007fff; + wc->dmactrl |= (0x00004000 | (x << 7)); + t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); + } + wc->dmactrl &= ~0x00007fff; + t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); +} + +/* Note that channels here start from 1 */ +static void t4_tsi_assign(struct t4 *wc, int fromspan, int fromchan, int tospan, int tochan) +{ + unsigned long flags; + int fromts, tots; + + fromts = (fromspan << 5) |(fromchan); + tots = (tospan << 5) | (tochan); + + if (!wc->t1e1) { + fromts += 4; + tots += 4; + } + spin_lock_irqsave(&wc->reglock, flags); + wc->dmactrl &= ~0x00007fff; + wc->dmactrl |= (0x00004000 | (tots << 7) | (fromts)); + __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); + wc->dmactrl &= ~0x00007fff; + __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static void t4_tsi_unassign(struct t4 *wc, int tospan, int tochan) +{ + unsigned long flags; + int tots; + + tots = (tospan << 5) | (tochan); + + if (!wc->t1e1) + tots += 4; + spin_lock_irqsave(&wc->reglock, flags); + wc->dmactrl &= ~0x00007fff; + wc->dmactrl |= (0x00004000 | (tots << 7)); + __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); + if (debug & DEBUG_TSI) + printk("Sending '%08x\n", wc->dmactrl); + wc->dmactrl &= ~0x00007fff; + __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags) +{ + unsigned int version; + + version = t4_pci_in(wc, WC_VERSION); + printk("TE%dXXP version %08x, burst %s\n", wc->numspans, version, (!(cardflags & FLAG_BURST) && noburst) ? "OFF" : "ON"); +#ifdef ENABLE_WORKQUEUES + printk("TE%dXXP running with work queues.\n", wc->numspans); +#endif + + /* Make sure DMA engine is not running and interrupts are acknowledged */ + wc->dmactrl = 0x0; + t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); + /* Reset Framer and friends */ + t4_pci_out(wc, WC_LEDS, 0x00000000); + + /* Set DMA addresses */ + t4_pci_out(wc, WC_RDADDR, wc->readdma); + t4_pci_out(wc, WC_WRADDR, wc->writedma); + + /* Setup counters, interrupt flags (ignored in Gen2) */ + if (cardflags & FLAG_2NDGEN) { + t4_tsi_reset(wc); + } else { + t4_pci_out(wc, WC_COUNT, ((ZT_MAX_CHUNKSIZE * 2 * 32 - 1) << 18) | ((ZT_MAX_CHUNKSIZE * 2 * 32 - 1) << 2)); + } + + /* Reset pending interrupts */ + t4_pci_out(wc, WC_INTR, 0x00000000); + + /* Read T1/E1 status */ + if (t1e1override > -1) + wc->t1e1 = t1e1override; + else + wc->t1e1 = ((t4_pci_in(wc, WC_LEDS)) & 0x0f00) >> 8; + wc->order = ((t4_pci_in(wc, WC_LEDS)) & 0xf0000000) >> 28; + order_index[wc->order]++; + return 0; +} + +static int t4_hardware_init_2(struct t4 *wc) +{ + int x; + unsigned int falcver; + + if (t4_pci_in(wc, WC_VERSION) >= 0xc01a0165) { + wc->tspans[0]->spanflags |= FLAG_OCTOPT; + printk("Octasic optimized!\n"); + } + /* Setup LEDS, take out of reset */ + t4_pci_out(wc, WC_LEDS, 0x000000ff); + t4_activate(wc); + + t4_framer_out(wc, 0, 0x4a, 0xaa); + falcver = t4_framer_in(wc, 0 ,0x4a); + printk("FALC version: %08x, Board ID: %02x\n", falcver, wc->order); + + for (x=0;x< 11;x++) + printk("Reg %d: 0x%08x\n", x, t4_pci_in(wc, x)); + return 0; +} + +static int __devinit t4_launch(struct t4 *wc) +{ + int x; + unsigned long flags; + if (wc->tspans[0]->span.flags & ZT_FLAG_REGISTERED) + return 0; + printk("TE%dXXP: Launching card: %d\n", wc->numspans, wc->order); + + /* Setup serial parameters and system interface */ + for (x=0;x<4;x++) + t4_serial_setup(wc, x); + + if (zt_register(&wc->tspans[0]->span, 0)) { + printk(KERN_ERR "Unable to register span %s\n", wc->tspans[0]->span.name); + return -1; + } + if (zt_register(&wc->tspans[1]->span, 0)) { + printk(KERN_ERR "Unable to register span %s\n", wc->tspans[1]->span.name); + zt_unregister(&wc->tspans[0]->span); + return -1; + } + + if (wc->numspans == 4) { + if (zt_register(&wc->tspans[2]->span, 0)) { + printk(KERN_ERR "Unable to register span %s\n", wc->tspans[2]->span.name); + zt_unregister(&wc->tspans[0]->span); + zt_unregister(&wc->tspans[1]->span); + return -1; + } + if (zt_register(&wc->tspans[3]->span, 0)) { + printk(KERN_ERR "Unable to register span %s\n", wc->tspans[3]->span.name); + zt_unregister(&wc->tspans[0]->span); + zt_unregister(&wc->tspans[1]->span); + zt_unregister(&wc->tspans[2]->span); + return -1; + } + } + wc->checktiming = 1; + spin_lock_irqsave(&wc->reglock, flags); + __t4_set_timing_source(wc,4, 0, 0); + spin_unlock_irqrestore(&wc->reglock, flags); + tasklet_init(&wc->t4_tlet, t4_isr_bh, (unsigned long)wc); + return 0; +} + +static int __devinit t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int res; + struct t4 *wc; + struct devtype *dt; + int x,f; + int basesize; +#if 0 + int y; + unsigned int *canary; +#endif + + + if (pci_enable_device(pdev)) { + res = -EIO; + } else { + wc = kmalloc(sizeof(struct t4), GFP_KERNEL); + if (wc) { + memset(wc, 0x0, sizeof(struct t4)); + spin_lock_init(&wc->reglock); + dt = (struct devtype *)(ent->driver_data); + if (dt->flags & FLAG_2NDGEN) + basesize = ZT_MAX_CHUNKSIZE * 32 * 4; + else + basesize = ZT_MAX_CHUNKSIZE * 32 * 2 * 4; + + if (dt->flags & FLAG_2PORT) + wc->numspans = 2; + else + wc->numspans = 4; + + wc->variety = dt->desc; + + wc->memaddr = pci_resource_start(pdev, 0); + wc->memlen = pci_resource_len(pdev, 0); + wc->membase = ioremap(wc->memaddr, wc->memlen); + /* This rids of the Double missed interrupt message after loading */ + wc->last0 = 1; +#if 0 + if (!request_mem_region(wc->memaddr, wc->memlen, wc->variety)) + printk("wct4: Unable to request memory region :(, using anyway...\n"); +#endif + if (pci_request_regions(pdev, wc->variety)) + printk("wct%dxxp: Unable to request regions\n", wc->numspans); + + printk("Found TE%dXXP at base address %08lx, remapped to %p\n", wc->numspans, wc->memaddr, wc->membase); + + wc->dev = pdev; + + wc->writechunk = + /* 32 channels, Double-buffer, Read/Write, 4 spans */ + (unsigned int *)pci_alloc_consistent(pdev, basesize * 2, &wc->writedma); + if (!wc->writechunk) { + printk("wct%dxxp: Unable to allocate DMA-able memory\n", wc->numspans); + return -ENOMEM; + } + + /* Read is after the whole write piece (in words) */ + wc->readchunk = wc->writechunk + basesize / 4; + + /* Same thing but in bytes... */ + wc->readdma = wc->writedma + basesize; + + /* Initialize Write/Buffers to all blank data */ + memset((void *)wc->writechunk,0x00, basesize); + memset((void *)wc->readchunk,0xff, basesize); +#if 0 + memset((void *)wc->readchunk,0xff,ZT_MAX_CHUNKSIZE * 2 * 32 * 4); + /* Initialize canary */ + canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 64 * 4 - 4); + *canary = (CANARY << 16) | (0xffff); +#endif + + /* Enable bus mastering */ + pci_set_master(pdev); + + /* Keep track of which device we are */ + pci_set_drvdata(pdev, wc); + + /* Initialize hardware */ + t4_hardware_init_1(wc, dt->flags); + + for(x = 0; x < MAX_T4_CARDS; x++) { + if (!cards[x]) break; + } + + if (x >= MAX_T4_CARDS) { + printk("No cards[] slot available!!\n"); + return -ENOMEM; + } + + wc->num = x; + cards[x] = wc; + + +#ifdef ENABLE_WORKQUEUES + if (dt->flags & FLAG_2NDGEN) { + char tmp[20]; + sprintf(tmp, "te%dxxp[%d]", wc->numspans, wc->num); + wc->workq = create_workqueue(tmp); + } +#endif + + /* Allocate pieces we need here */ + for (x=0;x<4;x++) { + if (wc->t1e1 & (1 << x)) { + wc->tspans[x] = kmalloc(sizeof(struct t4_span) + sizeof(struct zt_chan) * 31, GFP_KERNEL); + if (wc->tspans[x]) { + memset(wc->tspans[x], 0, sizeof(struct t4_span) + sizeof(struct zt_chan) * 31); + wc->tspans[x]->spantype = TYPE_E1; + } + } else { + wc->tspans[x] = kmalloc(sizeof(struct t4_span) + sizeof(struct zt_chan) * 24, GFP_KERNEL); + if (wc->tspans[x]) { + memset(wc->tspans[x], 0, sizeof(struct t4_span) + sizeof(struct zt_chan) * 24); + if (j1mode) + wc->tspans[x]->spantype = TYPE_J1; + else + wc->tspans[x]->spantype = TYPE_T1; + } + } + if (!wc->tspans[x]) + return -ENOMEM; +#ifdef ENABLE_WORKQUEUES + INIT_WORK(&wc->tspans[x]->swork, workq_handlespan, wc->tspans[x]); +#endif + wc->tspans[x]->spanflags |= dt->flags; + } + + + /* Continue hardware intiialization */ + t4_hardware_init_2(wc); + + +#ifdef SUPPORT_GEN1 + if (request_irq(pdev->irq, (dt->flags & FLAG_2NDGEN) ? t4_interrupt_gen2 :t4_interrupt, ZAP_IRQ_SHARED_DISABLED, (wc->numspans == 2) ? "wct2xxp" : "wct4xxp", wc)) +#else + if (!(wc->tspans[0]->spanflags & FLAG_2NDGEN)) { + printk("This driver does not support 1st gen modules\n"); + kfree(wc); + return -ENODEV; + } + if (request_irq(pdev->irq, t4_interrupt_gen2, ZAP_IRQ_SHARED_DISABLED, "t4xxp", wc)) +#endif + { + printk("t4xxp: Unable to request IRQ %d\n", pdev->irq); + kfree(wc); + return -EIO; + } + + init_spans(wc); + + /* Launch cards as appropriate */ + for (;;) { + /* Find a card to activate */ + f = 0; + for (x=0;cards[x];x++) { + if (cards[x]->order <= highestorder) { + t4_launch(cards[x]); + if (cards[x]->order == highestorder) + f = 1; + } + } + /* If we found at least one, increment the highest order and search again, otherwise stop */ + if (f) + highestorder++; + else + break; + } + + printk("Found a Wildcard: %s\n", wc->variety); + wc->gpio = 0x00000000; + t4_pci_out(wc, WC_GPIO, wc->gpio); + t4_gpio_setdir(wc, (1 << 17), (1 << 17)); + t4_gpio_setdir(wc, (0xff), (0xff)); + +#if 0 + for (x=0;x<0x10000;x++) { + __t4_raw_oct_out(wc, 0x0004, x); + __t4_raw_oct_out(wc, 0x000a, x ^ 0xffff); + if (__t4_raw_oct_in(wc, 0x0004) != x) + printk("Register 4 failed %04x\n", x); + if (__t4_raw_oct_in(wc, 0x000a) != (x ^ 0xffff)) + printk("Register 10 failed %04x\n", x); + } +#endif + res = 0; + } else + res = -ENOMEM; + } + return res; +} + +static int t4_hardware_stop(struct t4 *wc) +{ + + /* Turn off DMA, leave interrupts enabled */ + wc->stopdma = 1; + + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout((25 * HZ) / 1000); + + /* Turn off counter, address, etc */ + if (wc->tspans[0]->spanflags & FLAG_2NDGEN) { + t4_tsi_reset(wc); + } else { + t4_pci_out(wc, WC_COUNT, 0x000000); + } + t4_pci_out(wc, WC_RDADDR, 0x0000000); + t4_pci_out(wc, WC_WRADDR, 0x0000000); + wc->gpio = 0x00000000; + t4_pci_out(wc, WC_GPIO, wc->gpio); + t4_pci_out(wc, WC_LEDS, 0x00000000); + + printk("\nStopped TE%dXXP, Turned off DMA\n", wc->numspans); + return 0; +} + +static void __devexit t4_remove_one(struct pci_dev *pdev) +{ + struct t4 *wc = pci_get_drvdata(pdev); + int x; + if (wc) { + /* Stop hardware */ + t4_hardware_stop(wc); + + /* Release vpm450m */ + if (wc->vpm450m) + release_vpm450m(wc->vpm450m); + wc->vpm450m = NULL; + /* Unregister spans */ + if (wc->tspans[0]->span.flags & ZT_FLAG_REGISTERED) + zt_unregister(&wc->tspans[0]->span); + if (wc->tspans[1]->span.flags & ZT_FLAG_REGISTERED) + zt_unregister(&wc->tspans[1]->span); + if (wc->numspans == 4) { + if (wc->tspans[2]->span.flags & ZT_FLAG_REGISTERED) + zt_unregister(&wc->tspans[2]->span); + if (wc->tspans[3]->span.flags & ZT_FLAG_REGISTERED) + zt_unregister(&wc->tspans[3]->span); + } +#ifdef ENABLE_WORKQUEUES + if (wc->workq) { + flush_workqueue(wc->workq); + destroy_workqueue(wc->workq); + } +#endif +#if 0 + /* Stop any DMA */ + __t1xxp_stop_dma(wc); + + /* In case hardware is still there */ + __t1xxp_disable_interrupts(wc); + + t1xxp_stop_stuff(wc); +#endif + + if (wc->membase) + iounmap((void *)wc->membase); + + pci_release_regions(pdev); +#if 0 + if (wc->memaddr) + release_mem_region(wc->memaddr, wc->memlen); +#endif + + /* Immediately free resources */ + pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 32 * 4, (void *)wc->writechunk, wc->writedma); +#if 1 + free_irq(pdev->irq, wc); +#endif + + order_index[wc->order]--; + + cards[wc->num] = NULL; + pci_set_drvdata(pdev, NULL); + for (x=0;xnumspans;x++) { + if (wc->tspans[x]) + kfree(wc->tspans[x]); + } + kfree(wc); + } +} + + +static struct pci_device_id t4_pci_tbl[] __devinitdata = +{ + { 0x10ee, 0x0314, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct4xxp }, + + { 0xd161, 0x0420, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct420p4 }, + { 0xd161, 0x0410, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct410p4 }, + { 0xd161, 0x0405, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct405p4 }, + { 0xd161, 0x0410, 0x0003, PCI_ANY_ID, 0, 0, (unsigned long)&wct410p3 }, + { 0xd161, 0x0405, 0x0003, PCI_ANY_ID, 0, 0, (unsigned long)&wct405p3 }, + { 0xd161, 0x0410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct410p2 }, + { 0xd161, 0x0405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct405p2 }, + + { 0xd161, 0x0220, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct220p4 }, + { 0xd161, 0x0205, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct205p4 }, + { 0xd161, 0x0210, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct210p4 }, + { 0xd161, 0x0205, 0x0003, PCI_ANY_ID, 0, 0, (unsigned long)&wct205p3 }, + { 0xd161, 0x0210, 0x0003, PCI_ANY_ID, 0, 0, (unsigned long)&wct210p3 }, + { 0xd161, 0x0205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct205 }, + { 0xd161, 0x0210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct210 }, + { 0, } +}; + +static struct pci_driver t4_driver = { + name: "wct4xxp", + probe: t4_init_one, +#ifdef LINUX26 + remove: __devexit_p(t4_remove_one), +#else + remove: t4_remove_one, +#endif + suspend: NULL, + resume: NULL, + id_table: t4_pci_tbl, +}; + +static int __init t4_init(void) +{ + int res; + res = zap_pci_module(&t4_driver); + if (res) + return -ENODEV; + return 0; +} + +static void __exit t4_cleanup(void) +{ + pci_unregister_driver(&t4_driver); +} + + +MODULE_AUTHOR("Mark Spencer"); +MODULE_DESCRIPTION("Unified TE4XXP-TE2XXP PCI Driver"); +#if defined(MODULE_ALIAS) +MODULE_ALIAS("wct2xxp"); +#endif +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif +#ifdef LINUX26 +module_param(pedanticpci, int, 0600); +module_param(debug, int, 0600); +module_param(loopback, int, 0600); +module_param(noburst, int, 0600); +module_param(timingcable, int, 0600); +module_param(t1e1override, int, 0600); +module_param(alarmdebounce, int, 0600); +module_param(j1mode, int, 0600); +module_param(sigmode, int, 0600); +#ifdef VPM_SUPPORT +module_param(vpmsupport, int, 0600); +module_param(vpmdtmfsupport, int, 0600); +module_param(vpmspans, int, 0600); +module_param(dtmfthreshold, int, 0600); +#endif +#else +MODULE_PARM(pedanticpci, "i"); +MODULE_PARM(debug, "i"); +MODULE_PARM(loopback, "i"); +MODULE_PARM(noburst, "i"); +MODULE_PARM(hardhdlcmode, "i"); +MODULE_PARM(timingcable, "i"); +MODULE_PARM(t1e1override, "i"); +MODULE_PARM(alarmdebounce, "i"); +MODULE_PARM(j1mode, "i"); +MODULE_PARM(sigmode, "i"); +#ifdef VPM_SUPPORT +MODULE_PARM(vpmsupport, "i"); +MODULE_PARM(vpmdtmfsupport, "i"); +MODULE_PARM(vpmspans, "i"); +MODULE_PARM(dtmfthreshold, "i"); +#endif +#endif + +MODULE_DEVICE_TABLE(pci, t4_pci_tbl); + +module_init(t4_init); +module_exit(t4_cleanup); diff --git a/kernel/wct4xxp/vpm450m.c b/kernel/wct4xxp/vpm450m.c new file mode 100644 index 0000000..674dd49 --- /dev/null +++ b/kernel/wct4xxp/vpm450m.c @@ -0,0 +1,577 @@ +/* + * Copyright (C) 2005-2006 Digium, Inc. + * + * Mark Spencer + * + * All Rights Reserved + */ + +#include +#include +#include +#include +#include + +#include "vpm450m.h" +#include "oct6100api/oct6100_api.h" + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) +#include +#else +#include +#endif + +/* API for Octasic access */ +UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime) +{ + /* Why couldn't they just take a timeval like everyone else? */ + struct timeval tv; + unsigned long long total_usecs; + unsigned int mask = ~0; + + do_gettimeofday(&tv); + total_usecs = (((unsigned long long)(tv.tv_sec)) * 1000000) + + (((unsigned long long)(tv.tv_usec))); + f_pTime->aulWallTimeUs[0] = (total_usecs & mask); + f_pTime->aulWallTimeUs[1] = (total_usecs >> 32); + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserMemSet(PVOID f_pAddress, UINT32 f_ulPattern, UINT32 f_ulLength) +{ + memset(f_pAddress, f_ulPattern, f_ulLength); + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserMemCopy(PVOID f_pDestination, const void *f_pSource, UINT32 f_ulLength) +{ + memcpy(f_pDestination, f_pSource, f_ulLength); + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserCreateSerializeObject(tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate) +{ + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserDestroySerializeObject(tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy) +{ +#ifdef OCTASIC_DEBUG + printk("I should never be called! (destroy serialize object)\n"); +#endif + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserSeizeSerializeObject(tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize) +{ + /* Not needed */ + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserReleaseSerializeObject(tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease) +{ + /* Not needed */ + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserDriverWriteApi(tPOCT6100_WRITE_PARAMS f_pWriteParams) +{ + oct_set_reg(f_pWriteParams->pProcessContext, f_pWriteParams->ulWriteAddress, f_pWriteParams->usWriteData); + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserDriverWriteSmearApi(tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams) +{ + unsigned int x; + for (x=0;xulWriteLength;x++) { + oct_set_reg(f_pSmearParams->pProcessContext, f_pSmearParams->ulWriteAddress + (x << 1), f_pSmearParams->usWriteData); + } + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserDriverWriteBurstApi(tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams) +{ + unsigned int x; + for (x=0;xulWriteLength;x++) { + oct_set_reg(f_pBurstParams->pProcessContext, f_pBurstParams->ulWriteAddress + (x << 1), f_pBurstParams->pusWriteData[x]); + } + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserDriverReadApi(tPOCT6100_READ_PARAMS f_pReadParams) +{ + *(f_pReadParams->pusReadData) = oct_get_reg(f_pReadParams->pProcessContext, f_pReadParams->ulReadAddress); + return cOCT6100_ERR_OK; +} + +UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams) +{ + unsigned int x; + for (x=0;xulReadLength;x++) { + f_pBurstParams->pusReadData[x] = oct_get_reg(f_pBurstParams->pProcessContext, f_pBurstParams->ulReadAddress + (x << 1)); + } + return cOCT6100_ERR_OK; +} + +#define SOUT_G168_1100GB_ON 0x40000004 +#define SOUT_DTMF_1 0x40000011 +#define SOUT_DTMF_2 0x40000012 +#define SOUT_DTMF_3 0x40000013 +#define SOUT_DTMF_A 0x4000001A +#define SOUT_DTMF_4 0x40000014 +#define SOUT_DTMF_5 0x40000015 +#define SOUT_DTMF_6 0x40000016 +#define SOUT_DTMF_B 0x4000001B +#define SOUT_DTMF_7 0x40000017 +#define SOUT_DTMF_8 0x40000018 +#define SOUT_DTMF_9 0x40000019 +#define SOUT_DTMF_C 0x4000001C +#define SOUT_DTMF_STAR 0x4000001E +#define SOUT_DTMF_0 0x40000010 +#define SOUT_DTMF_POUND 0x4000001F +#define SOUT_DTMF_D 0x4000001D + +#define ROUT_G168_2100GB_ON 0x10000000 +#define ROUT_G168_2100GB_WSPR 0x10000002 +#define ROUT_SOUT_G168_2100HB_END 0x50000003 +#define ROUT_G168_1100GB_ON 0x10000004 + +#define ROUT_DTMF_1 0x10000011 +#define ROUT_DTMF_2 0x10000012 +#define ROUT_DTMF_3 0x10000013 +#define ROUT_DTMF_A 0x1000001A +#define ROUT_DTMF_4 0x10000014 +#define ROUT_DTMF_5 0x10000015 +#define ROUT_DTMF_6 0x10000016 +#define ROUT_DTMF_B 0x1000001B +#define ROUT_DTMF_7 0x10000017 +#define ROUT_DTMF_8 0x10000018 +#define ROUT_DTMF_9 0x10000019 +#define ROUT_DTMF_C 0x1000001C +#define ROUT_DTMF_STAR 0x1000001E +#define ROUT_DTMF_0 0x10000010 +#define ROUT_DTMF_POUND 0x1000001F +#define ROUT_DTMF_D 0x1000001D + +#if 0 +#define cOCT6100_ECHO_OP_MODE_DIGITAL cOCT6100_ECHO_OP_MODE_HT_FREEZE +#else +#define cOCT6100_ECHO_OP_MODE_DIGITAL cOCT6100_ECHO_OP_MODE_POWER_DOWN +#endif + +struct vpm450m { + tPOCT6100_INSTANCE_API pApiInstance; + UINT32 aulEchoChanHndl[ 128 ]; + int chanflags[128]; + int ecmode[128]; + int numchans; +}; + +#define FLAG_DTMF (1 << 0) +#define FLAG_MUTE (1 << 1) +#define FLAG_ECHO (1 << 2) + +static unsigned int tones[] = { + SOUT_DTMF_1, + SOUT_DTMF_2, + SOUT_DTMF_3, + SOUT_DTMF_A, + SOUT_DTMF_4, + SOUT_DTMF_5, + SOUT_DTMF_6, + SOUT_DTMF_B, + SOUT_DTMF_7, + SOUT_DTMF_8, + SOUT_DTMF_9, + SOUT_DTMF_C, + SOUT_DTMF_STAR, + SOUT_DTMF_0, + SOUT_DTMF_POUND, + SOUT_DTMF_D, + SOUT_G168_1100GB_ON, + + ROUT_DTMF_1, + ROUT_DTMF_2, + ROUT_DTMF_3, + ROUT_DTMF_A, + ROUT_DTMF_4, + ROUT_DTMF_5, + ROUT_DTMF_6, + ROUT_DTMF_B, + ROUT_DTMF_7, + ROUT_DTMF_8, + ROUT_DTMF_9, + ROUT_DTMF_C, + ROUT_DTMF_STAR, + ROUT_DTMF_0, + ROUT_DTMF_POUND, + ROUT_DTMF_D, + ROUT_G168_1100GB_ON, +}; + +static void vpm450m_setecmode(struct vpm450m *vpm450m, int channel, int mode) +{ + tOCT6100_CHANNEL_MODIFY *modify; + UINT32 ulResult; + + if (vpm450m->ecmode[channel] == mode) + return; + modify = kmalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC); + if (!modify) { + printk("wct4xxp: Unable to allocate memory for setec!\n"); + return; + } + Oct6100ChannelModifyDef(modify); + modify->ulEchoOperationMode = mode; + modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel]; + ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify); + if (ulResult != GENERIC_OK) { + printk("Failed to apply echo can changes on channel %d!\n", channel); + } else { +#ifdef OCTASIC_DEBUG + printk("Echo can on channel %d set to %d\n", channel, mode); +#endif + vpm450m->ecmode[channel] = mode; + } + kfree(modify); +} + +void vpm450m_setdtmf(struct vpm450m *vpm450m, int channel, int detect, int mute) +{ + tOCT6100_CHANNEL_MODIFY *modify; + UINT32 ulResult; + + modify = kmalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_KERNEL); + if (!modify) { + printk("wct4xxp: Unable to allocate memory for setdtmf!\n"); + return; + } + Oct6100ChannelModifyDef(modify); + modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel]; + if (mute) { + vpm450m->chanflags[channel] |= FLAG_MUTE; + modify->VqeConfig.fDtmfToneRemoval = TRUE; + } else { + vpm450m->chanflags[channel] &= ~FLAG_MUTE; + modify->VqeConfig.fDtmfToneRemoval = FALSE; + } + if (detect) + vpm450m->chanflags[channel] |= FLAG_DTMF; + else + vpm450m->chanflags[channel] &= ~FLAG_DTMF; + if (vpm450m->chanflags[channel] & (FLAG_DTMF|FLAG_MUTE)) { + if (!(vpm450m->chanflags[channel] & FLAG_ECHO)) { + vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET); + vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_FREEZE); + } + } else { + if (!(vpm450m->chanflags[channel] & FLAG_ECHO)) + vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_DIGITAL); + } + + ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify); + if (ulResult != GENERIC_OK) { + printk("Failed to apply dtmf mute changes on channel %d!\n", channel); + } +/* printk("VPM450m: Setting DTMF on channel %d: %s / %s\n", channel, (detect ? "DETECT" : "NO DETECT"), (mute ? "MUTE" : "NO MUTE")); */ + kfree(modify); +} + +void vpm450m_setec(struct vpm450m *vpm450m, int channel, int eclen) +{ + if (eclen) { + vpm450m->chanflags[channel] |= FLAG_ECHO; + vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET); + vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_NORMAL); + } else { + vpm450m->chanflags[channel] &= ~FLAG_ECHO; + if (vpm450m->chanflags[channel] & (FLAG_DTMF | FLAG_MUTE)) { + vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET); + vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_FREEZE); + } else + vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_DIGITAL); + } +/* printk("VPM450m: Setting EC on channel %d to %d\n", channel, eclen); */ +} + +int vpm450m_checkirq(struct vpm450m *vpm450m) +{ + tOCT6100_INTERRUPT_FLAGS InterruptFlags; + + Oct6100InterruptServiceRoutineDef(&InterruptFlags); + Oct6100InterruptServiceRoutine(vpm450m->pApiInstance, &InterruptFlags); + + return InterruptFlags.fToneEventsPending ? 1 : 0; +} + +int vpm450m_getdtmf(struct vpm450m *vpm450m, int *channel, int *tone, int *start) +{ + tOCT6100_TONE_EVENT tonefound; + tOCT6100_EVENT_GET_TONE tonesearch; + UINT32 ulResult; + + Oct6100EventGetToneDef(&tonesearch); + tonesearch.pToneEvent = &tonefound; + tonesearch.ulMaxToneEvent = 1; + ulResult = Oct6100EventGetTone(vpm450m->pApiInstance, &tonesearch); + if (tonesearch.ulNumValidToneEvent) { + if (channel) + *channel = tonefound.ulUserChanId; + if (tone) { + switch(tonefound.ulToneDetected) { + case SOUT_DTMF_1: + *tone = '1'; + break; + case SOUT_DTMF_2: + *tone = '2'; + break; + case SOUT_DTMF_3: + *tone = '3'; + break; + case SOUT_DTMF_A: + *tone = 'A'; + break; + case SOUT_DTMF_4: + *tone = '4'; + break; + case SOUT_DTMF_5: + *tone = '5'; + break; + case SOUT_DTMF_6: + *tone = '6'; + break; + case SOUT_DTMF_B: + *tone = 'B'; + break; + case SOUT_DTMF_7: + *tone = '7'; + break; + case SOUT_DTMF_8: + *tone = '8'; + break; + case SOUT_DTMF_9: + *tone = '9'; + break; + case SOUT_DTMF_C: + *tone = 'C'; + break; + case SOUT_DTMF_STAR: + *tone = '*'; + break; + case SOUT_DTMF_0: + *tone = '0'; + break; + case SOUT_DTMF_POUND: + *tone = '#'; + break; + case SOUT_DTMF_D: + *tone = 'D'; + break; + case SOUT_G168_1100GB_ON: + *tone = 'f'; + break; + default: +#ifdef OCTASIC_DEBUG + printk("Unknown tone value %08x\n", tonefound.ulToneDetected); +#endif + *tone = 'u'; + break; + } + } + if (start) + *start = (tonefound.ulEventType == cOCT6100_TONE_PRESENT); + return 1; + } + return 0; +} + +unsigned int get_vpm450m_capacity(void *wc) +{ + UINT32 ulResult; + + tOCT6100_API_GET_CAPACITY_PINS CapacityPins; + + Oct6100ApiGetCapacityPinsDef(&CapacityPins); + CapacityPins.pProcessContext = wc; + CapacityPins.ulMemoryType = cOCT6100_MEM_TYPE_DDR; + CapacityPins.fEnableMemClkOut = TRUE; + CapacityPins.ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ; + + ulResult = Oct6100ApiGetCapacityPins(&CapacityPins); + if (ulResult != cOCT6100_ERR_OK) { + printk("Failed to get chip capacity, code %08x!\n", ulResult); + return 0; + } + + return CapacityPins.ulCapacityValue; +} + +struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct firmware *firmware) +{ + tOCT6100_CHIP_OPEN *ChipOpen; + tOCT6100_GET_INSTANCE_SIZE InstanceSize; + tOCT6100_CHANNEL_OPEN *ChannelOpen; + UINT32 ulResult; + struct vpm450m *vpm450m; + int x,y,law; +#ifdef CONFIG_4KSTACKS + unsigned long flags; +#endif + + if (!(vpm450m = kmalloc(sizeof(struct vpm450m), GFP_KERNEL))) + return NULL; + + memset(vpm450m, 0, sizeof(struct vpm450m)); + + if (!(ChipOpen = kmalloc(sizeof(tOCT6100_CHIP_OPEN), GFP_KERNEL))) { + kfree(vpm450m); + return NULL; + } + + memset(ChipOpen, 0, sizeof(tOCT6100_CHIP_OPEN)); + + if (!(ChannelOpen = kmalloc(sizeof(tOCT6100_CHANNEL_OPEN), GFP_KERNEL))) { + kfree(vpm450m); + kfree(ChipOpen); + return NULL; + } + + memset(ChannelOpen, 0, sizeof(tOCT6100_CHANNEL_OPEN)); + + for (x=0;x<128;x++) + vpm450m->ecmode[x] = -1; + + vpm450m->numchans = numspans * 32; + printk("VPM450: echo cancellation for %d channels\n", vpm450m->numchans); + + Oct6100ChipOpenDef(ChipOpen); + + /* Setup Chip Open Parameters */ + ChipOpen->ulUpclkFreq = cOCT6100_UPCLK_FREQ_33_33_MHZ; + Oct6100GetInstanceSizeDef(&InstanceSize); + + ChipOpen->pProcessContext = wc; + + ChipOpen->pbyImageFile = firmware->data; + ChipOpen->ulImageSize = firmware->size; + ChipOpen->fEnableMemClkOut = TRUE; + ChipOpen->ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ; + ChipOpen->ulMaxChannels = vpm450m->numchans; + ChipOpen->ulMemoryType = cOCT6100_MEM_TYPE_DDR; + ChipOpen->ulMemoryChipSize = cOCT6100_MEMORY_CHIP_SIZE_32MB; + ChipOpen->ulNumMemoryChips = 1; + ChipOpen->ulMaxTdmStreams = 4; + ChipOpen->aulTdmStreamFreqs[0] = cOCT6100_TDM_STREAM_FREQ_8MHZ; + ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE; +#if 0 + ChipOpen->fEnableAcousticEcho = TRUE; +#endif + + ulResult = Oct6100GetInstanceSize(ChipOpen, &InstanceSize); + if (ulResult != cOCT6100_ERR_OK) { + printk("Failed to get instance size, code %08x!\n", ulResult); + kfree(vpm450m); + kfree(ChipOpen); + kfree(ChannelOpen); + return NULL; + } + + + vpm450m->pApiInstance = vmalloc(InstanceSize.ulApiInstanceSize); + if (!vpm450m->pApiInstance) { + printk("Out of memory (can't allocate %d bytes)!\n", InstanceSize.ulApiInstanceSize); + kfree(vpm450m); + kfree(ChipOpen); + kfree(ChannelOpen); + return NULL; + } + + /* I don't know what to curse more in this comment, the problems caused by + * the 4K kernel stack limit change or the octasic API for being so darn + * stack unfriendly. Stupid, stupid, stupid. So we disable IRQs so we + * don't run the risk of overflowing the stack while we initialize the + * octasic. */ +#ifdef CONFIG_4KSTACKS + local_irq_save(flags); +#endif + ulResult = Oct6100ChipOpen(vpm450m->pApiInstance, ChipOpen); + if (ulResult != cOCT6100_ERR_OK) { + printk("Failed to open chip, code %08x!\n", ulResult); +#ifdef CONFIG_4KSTACKS + local_irq_restore(flags); +#endif + kfree(vpm450m); + kfree(ChipOpen); + kfree(ChannelOpen); + return NULL; + } + for (x=0;x<128;x++) { + /* execute this loop always on 4 span cards but + * on 2 span cards only execute for the channels related to our spans */ + if (( numspans > 2) || ((x & 0x03) <2)) { + /* span timeslots are interleaved 12341234... + * therefore, the lower 2 bits tell us which span this + * timeslot/channel + */ + if (isalaw[x & 0x03]) + law = cOCT6100_PCM_A_LAW; + else + law = cOCT6100_PCM_U_LAW; + Oct6100ChannelOpenDef(ChannelOpen); + ChannelOpen->pulChannelHndl = &vpm450m->aulEchoChanHndl[x]; + ChannelOpen->ulUserChanId = x; + ChannelOpen->TdmConfig.ulRinPcmLaw = law; + ChannelOpen->TdmConfig.ulRinStream = 0; + ChannelOpen->TdmConfig.ulRinTimeslot = x; + ChannelOpen->TdmConfig.ulSinPcmLaw = law; + ChannelOpen->TdmConfig.ulSinStream = 1; + ChannelOpen->TdmConfig.ulSinTimeslot = x; + ChannelOpen->TdmConfig.ulSoutPcmLaw = law; + ChannelOpen->TdmConfig.ulSoutStream = 2; + ChannelOpen->TdmConfig.ulSoutTimeslot = x; + ChannelOpen->TdmConfig.ulRoutPcmLaw = law; + ChannelOpen->TdmConfig.ulRoutStream = 3; + ChannelOpen->TdmConfig.ulRoutTimeslot = x; + ChannelOpen->VqeConfig.fEnableNlp = TRUE; + ChannelOpen->VqeConfig.fRinDcOffsetRemoval = TRUE; + ChannelOpen->VqeConfig.fSinDcOffsetRemoval = TRUE; + + ChannelOpen->fEnableToneDisabler = TRUE; + ChannelOpen->ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_DIGITAL; + + ulResult = Oct6100ChannelOpen(vpm450m->pApiInstance, ChannelOpen); + if (ulResult != GENERIC_OK) { + printk("Failed to open channel %d!\n", x); + } + for (y=0;yaulEchoChanHndl[x]; + enable.ulToneNumber = tones[y]; + if (Oct6100ToneDetectionEnable(vpm450m->pApiInstance, &enable) != GENERIC_OK) + printk("Failed to enable tone detection on channel %d for tone %d!\n", x, y); + } + } + } + +#ifdef CONFIG_4KSTACKS + local_irq_restore(flags); +#endif + kfree(ChipOpen); + kfree(ChannelOpen); + return vpm450m; +} + +void release_vpm450m(struct vpm450m *vpm450m) +{ + UINT32 ulResult; + tOCT6100_CHIP_CLOSE ChipClose; + + Oct6100ChipCloseDef(&ChipClose); + ulResult = Oct6100ChipClose(vpm450m->pApiInstance, &ChipClose); + if (ulResult != cOCT6100_ERR_OK) { + printk("Failed to close chip, code %08x!\n", ulResult); + } + vfree(vpm450m->pApiInstance); + kfree(vpm450m); +} diff --git a/kernel/wct4xxp/vpm450m.h b/kernel/wct4xxp/vpm450m.h new file mode 100644 index 0000000..41d7c60 --- /dev/null +++ b/kernel/wct4xxp/vpm450m.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2005-2006 Digium, Inc. + * + * Mark Spencer + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _VPM450M_H +#define _VPM450M_H + +#include + +struct vpm450m; + +/* From driver */ +unsigned int oct_get_reg(void *data, unsigned int reg); +void oct_set_reg(void *data, unsigned int reg, unsigned int val); + +/* From vpm450m */ +struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct firmware *firmware); +unsigned int get_vpm450m_capacity(void *wc); +void vpm450m_setec(struct vpm450m *instance, int channel, int eclen); +void vpm450m_setdtmf(struct vpm450m *instance, int channel, int dtmfdetect, int dtmfmute); +int vpm450m_checkirq(struct vpm450m *vpm450m); +int vpm450m_getdtmf(struct vpm450m *vpm450m, int *channel, int *tone, int *start); +void release_vpm450m(struct vpm450m *instance); + +#endif diff --git a/kernel/wct4xxp/wct4xxp-diag.c b/kernel/wct4xxp/wct4xxp-diag.c new file mode 100644 index 0000000..50a328d --- /dev/null +++ b/kernel/wct4xxp/wct4xxp-diag.c @@ -0,0 +1,414 @@ +#include +#include +#include +#include +#include +#include +#include +#include "zaptel.h" +#include "wct4xxp.h" + +static struct t4_reg_def { + int reg; + char *name; + int global; +}; +static struct t4_reg_def xreginfo[] = { + { 0x00, "RDADDR" }, + { 0x01, "WRADDR" }, + { 0x02, "COUNT" }, + { 0x03, "DMACTRL" }, + { 0x04, "WCINTR" }, + { 0x06, "VERSION" }, + { 0x07, "LEDS" }, + { 0x08, "GPIOCTL" }, + { 0x09, "GPIO" }, + { 0x0A, "LADDR" }, + { 0x0b, "LDATA" }, +}; + +static struct t4_reg_def reginfo[] = { + { 0x00, "XFIFO" }, + { 0x01, "XFIFO" }, + { 0x02, "CMDR" }, + { 0x03, "MODE" }, + { 0x04, "RAH1" }, + { 0x05, "RAH2" }, + { 0x06, "RAL1" }, + { 0x07, "RAL2" }, + { 0x08, "IPC", 1 }, + { 0x09, "CCR1" }, + { 0x0a, "CCR2" }, + { 0x0c, "RTR1" }, + { 0x0d, "RTR2" }, + { 0x0e, "RTR3" }, + { 0x0f, "RTR4" }, + { 0x10, "TTR1" }, + { 0x11, "TTR2" }, + { 0x12, "TTR3" }, + { 0x13, "TTR4" }, + { 0x14, "IMR0" }, + { 0x15, "IMR1" }, + { 0x16, "IMR2" }, + { 0x17, "IMR3" }, + { 0x18, "IMR4" }, + { 0x1b, "IERR" }, + { 0x1c, "FMR0" }, + { 0x1d, "FMR1" }, + { 0x1e, "FMR2" }, + { 0x1f, "LOOP" }, + { 0x20, "XSW" }, + { 0x21, "XSP" }, + { 0x22, "XC0" }, + { 0x23, "XC1" }, + { 0x24, "RC0" }, + { 0x25, "RC1" }, + { 0x26, "XPM0" }, + { 0x27, "XPM1" }, + { 0x28, "XPM2" }, + { 0x29, "TSWM" }, + { 0x2b, "IDLE" }, + { 0x2c, "XSA4" }, + { 0x2d, "XSA5" }, + { 0x2e, "XSA6" }, + { 0x2f, "XSA7" }, + { 0x30, "XSA8" }, + { 0x31, "FMR3" }, + { 0x32, "ICB1" }, + { 0x33, "ICB2" }, + { 0x34, "ICB3" }, + { 0x35, "ICB4" }, + { 0x36, "LIM0" }, + { 0x37, "LIM1" }, + { 0x38, "PCD" }, + { 0x39, "PCR" }, + { 0x3a, "LIM2" }, + { 0x3b, "LCR1" }, + { 0x3c, "LCR2" }, + { 0x3d, "LCR3" }, + { 0x3e, "SIC1" }, + { 0x3f, "SIC2" }, + { 0x40, "SIC3" }, + { 0x44, "CMR1" }, + { 0x45, "CMR2" }, + { 0x46, "GCR" }, + { 0x47, "ESM" }, + { 0x60, "DEC" }, + { 0x70, "XS1" }, + { 0x71, "XS2" }, + { 0x72, "XS3" }, + { 0x73, "XS4" }, + { 0x74, "XS5" }, + { 0x75, "XS6" }, + { 0x76, "XS7" }, + { 0x77, "XS8" }, + { 0x78, "XS9" }, + { 0x79, "XS10" }, + { 0x7a, "XS11" }, + { 0x7b, "XS12" }, + { 0x7c, "XS13" }, + { 0x7d, "XS14" }, + { 0x7e, "XS15" }, + { 0x7f, "XS16" }, + { 0x80, "PC1" }, + { 0x81, "PC2" }, + { 0x82, "PC3" }, + { 0x83, "PC4" }, + { 0x84, "PC5" }, + { 0x85, "GPC1", 1 }, + { 0x87, "CMDR2" }, + { 0x8d, "CCR5" }, + { 0x92, "GCM1", 1 }, + { 0x93, "GCM2", 1 }, + { 0x94, "GCM3", 1 }, + { 0x95, "GCM4", 1 }, + { 0x96, "GCM5", 1 }, + { 0x97, "GCM6", 1 }, + { 0x98, "GCM7", 1 }, + { 0x99, "GCM8", 1 }, + { 0xa0, "TSEO" }, + { 0xa1, "TSBS1" }, + { 0xa8, "TPC0" }, +}; + +static struct t4_reg_def t1_reginfo[] = { + { 0x00, "XFIFO" }, + { 0x01, "XFIFO" }, + { 0x02, "CMDR" }, + { 0x03, "MODE" }, + { 0x04, "RAH1" }, + { 0x05, "RAH2" }, + { 0x06, "RAL1" }, + { 0x07, "RAL2" }, + { 0x08, "IPC", 1 }, + { 0x09, "CCR1" }, + { 0x0a, "CCR2" }, + { 0x0c, "RTR1" }, + { 0x0d, "RTR2" }, + { 0x0e, "RTR3" }, + { 0x0f, "RTR4" }, + { 0x10, "TTR1" }, + { 0x11, "TTR2" }, + { 0x12, "TTR3" }, + { 0x13, "TTR4" }, + { 0x14, "IMR0" }, + { 0x15, "IMR1" }, + { 0x16, "IMR2" }, + { 0x17, "IMR3" }, + { 0x18, "IMR4" }, + { 0x1b, "IERR" }, + { 0x1c, "FMR0" }, + { 0x1d, "FMR1" }, + { 0x1e, "FMR2" }, + { 0x1f, "LOOP" }, + { 0x20, "FMR4" }, + { 0x21, "FMR5" }, + { 0x22, "XC0" }, + { 0x23, "XC1" }, + { 0x24, "RC0" }, + { 0x25, "RC1" }, + { 0x26, "XPM0" }, + { 0x27, "XPM1" }, + { 0x28, "XPM2" }, + { 0x2b, "IDLE" }, + { 0x2c, "XDL1" }, + { 0x2d, "XDL2" }, + { 0x2e, "XDL3" }, + { 0x2f, "CCB1" }, + { 0x30, "CCB2" }, + { 0x31, "CCB3" }, + { 0x32, "ICB1" }, + { 0x33, "ICB2" }, + { 0x34, "ICB3" }, + { 0x36, "LIM0" }, + { 0x37, "LIM1" }, + { 0x38, "PCD" }, + { 0x39, "PCR" }, + { 0x3a, "LIM2" }, + { 0x3b, "LCR1" }, + { 0x3c, "LCR2" }, + { 0x3d, "LCR3" }, + { 0x3e, "SIC1" }, + { 0x3f, "SIC2" }, + { 0x40, "SIC3" }, + { 0x44, "CMR1" }, + { 0x45, "CMR2" }, + { 0x46, "GCR" }, + { 0x47, "ESM" }, + { 0x60, "DEC" }, + { 0x70, "XS1" }, + { 0x71, "XS2" }, + { 0x72, "XS3" }, + { 0x73, "XS4" }, + { 0x74, "XS5" }, + { 0x75, "XS6" }, + { 0x76, "XS7" }, + { 0x77, "XS8" }, + { 0x78, "XS9" }, + { 0x79, "XS10" }, + { 0x7a, "XS11" }, + { 0x7b, "XS12" }, + { 0x80, "PC1" }, + { 0x81, "PC2" }, + { 0x82, "PC3" }, + { 0x83, "PC4" }, + { 0x84, "PC5" }, + { 0x85, "GPC1", 1 }, + { 0x87, "CMDR2" }, + { 0x8d, "CCR5" }, + { 0x92, "GCM1", 1 }, + { 0x93, "GCM2", 1 }, + { 0x94, "GCM3", 1 }, + { 0x95, "GCM4", 1 }, + { 0x96, "GCM5", 1 }, + { 0x97, "GCM6", 1 }, + { 0x98, "GCM7", 1 }, + { 0x99, "GCM8", 1 }, + { 0xa0, "TSEO" }, + { 0xa1, "TSBS1" }, + { 0xa8, "TPC0" }, +}; + +static struct t4_reg_def t1_sreginfo[] = { + { 0x00, "RFIFO" }, + { 0x01, "RFIFO" }, + { 0x49, "RBD" }, + { 0x4a, "VSTR", 1 }, + { 0x4b, "RES" }, + { 0x4c, "FRS0" }, + { 0x4d, "FRS1" }, + { 0x4e, "FRS2" }, + { 0x4f, "Old FRS1" }, + { 0x50, "FECL" }, + { 0x51, "FECH" }, + { 0x52, "CVCL" }, + { 0x53, "CVCH" }, + { 0x54, "CECL" }, + { 0x55, "CECH" }, + { 0x56, "EBCL" }, + { 0x57, "EBCH" }, + { 0x58, "BECL" }, + { 0x59, "BECH" }, + { 0x5a, "COEC" }, + { 0x5c, "RDL1" }, + { 0x5d, "RDL2" }, + { 0x5e, "RDL3" }, + { 0x62, "RSP1" }, + { 0x63, "RSP2" }, + { 0x64, "SIS" }, + { 0x65, "RSIS" }, + { 0x66, "RBCL" }, + { 0x67, "RBCH" }, + { 0x68, "ISR0" }, + { 0x69, "ISR1" }, + { 0x6a, "ISR2" }, + { 0x6b, "ISR3" }, + { 0x6c, "ISR4" }, + { 0x6e, "GIS" }, + { 0x6f, "CIS", 1 }, + { 0x70, "RS1" }, + { 0x71, "RS2" }, + { 0x72, "RS3" }, + { 0x73, "RS4" }, + { 0x74, "RS5" }, + { 0x75, "RS6" }, + { 0x76, "RS7" }, + { 0x77, "RS8" }, + { 0x78, "RS9" }, + { 0x79, "RS10" }, + { 0x7a, "RS11" }, + { 0x7b, "RS12" }, +}; + +static struct t4_reg_def sreginfo[] = { + { 0x00, "RFIFO" }, + { 0x01, "RFIFO" }, + { 0x49, "RBD" }, + { 0x4a, "VSTR", 1 }, + { 0x4b, "RES" }, + { 0x4c, "FRS0" }, + { 0x4d, "FRS1" }, + { 0x4e, "RSW" }, + { 0x4f, "RSP" }, + { 0x50, "FECL" }, + { 0x51, "FECH" }, + { 0x52, "CVCL" }, + { 0x53, "CVCH" }, + { 0x54, "CEC1L" }, + { 0x55, "CEC1H" }, + { 0x56, "EBCL" }, + { 0x57, "EBCH" }, + { 0x58, "CEC2L" }, + { 0x59, "CEC2H" }, + { 0x5a, "CEC3L" }, + { 0x5b, "CEC3H" }, + { 0x5c, "RSA4" }, + { 0x5d, "RSA5" }, + { 0x5e, "RSA6" }, + { 0x5f, "RSA7" }, + { 0x60, "RSA8" }, + { 0x61, "RSA6S" }, + { 0x62, "RSP1" }, + { 0x63, "RSP2" }, + { 0x64, "SIS" }, + { 0x65, "RSIS" }, + { 0x66, "RBCL" }, + { 0x67, "RBCH" }, + { 0x68, "ISR0" }, + { 0x69, "ISR1" }, + { 0x6a, "ISR2" }, + { 0x6b, "ISR3" }, + { 0x6c, "ISR4" }, + { 0x6e, "GIS" }, + { 0x6f, "CIS", 1 }, + { 0x70, "RS1" }, + { 0x71, "RS2" }, + { 0x72, "RS3" }, + { 0x73, "RS4" }, + { 0x74, "RS5" }, + { 0x75, "RS6" }, + { 0x76, "RS7" }, + { 0x77, "RS8" }, + { 0x78, "RS9" }, + { 0x79, "RS10" }, + { 0x7a, "RS11" }, + { 0x7b, "RS12" }, + { 0x7c, "RS13" }, + { 0x7d, "RS14" }, + { 0x7e, "RS15" }, + { 0x7f, "RS16" }, +}; + +static char *tobin(int x) +{ + static char s[9] = ""; + int y,z=0; + for (y=7;y>=0;y--) { + if (x & (1 << y)) + s[z++] = '1'; + else + s[z++] = '0'; + } + s[z] = '\0'; + return s; +} + +static char *tobin32(unsigned int x) +{ + static char s[33] = ""; + int y,z=0; + for (y=31;y>=0;y--) { + if (x & (1 << y)) + s[z++] = '1'; + else + s[z++] = '0'; + } + s[z] = '\0'; + return s; +} + +int main(int argc, char *argv[]) +{ + int fd; + int x; + char fn[256]; + struct t4_regs regs; + if ((argc < 2) || ((*(argv[1]) != '/') && !atoi(argv[1]))) { + fprintf(stderr, "Usage: wct4xxp-diag \n"); + exit(1); + } + if (*(argv[1]) == '/') + strncpy(fn, argv[1], sizeof(fn) - 1); + else + snprintf(fn, sizeof(fn), "/dev/zap/%d", atoi(argv[1])); + fd = open(fn, O_RDWR); + if (fd <0) { + fprintf(stderr, "Unable to open '%s': %s\n", fn, strerror(errno)); + exit(1); + } + if (ioctl(fd, WCT4_GET_REGS, ®s)) { + fprintf(stderr, "Unable to get registers: %s\n", strerror(errno)); + exit(1); + } + printf("PCI Registers:\n"); + for (x=0;x + * + * Copyright (C) 2001, Linux Support Services, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include + +#define FRMR_TTR_BASE 0x10 +#define FRMR_RTR_BASE 0x0c +#define FRMR_TSEO 0xa0 +#define FRMR_TSBS1 0xa1 +#define FRMR_CCR1 0x09 +#define FRMR_CCR1_ITF 0x08 +#define FRMR_CCR1_EITS 0x10 +#define FRMR_CCR2 0x0a +#define FRMR_CCR2_RCRC 0x04 +#define FRMR_CCR2_RADD 0x10 +#define FRMR_MODE 0x03 +#define FRMR_MODE_NO_ADDR_CMP 0x80 +#define FRMR_MODE_SS7 0x20 +#define FRMR_MODE_HRAC 0x08 +#define FRMR_IMR0 0x14 +#define FRMR_IMR0_RME 0x80 +#define FRMR_IMR0_RPF 0x01 +#define FRMR_IMR1 0x15 +#define FRMR_IMR1_ALLS 0x20 +#define FRMR_IMR1_XDU 0x10 +#define FRMR_IMR1_XPR 0x01 +#define FRMR_XC0 0x22 +#define FRMR_XC1 0x23 +#define FRMR_RC0 0x24 +#define FRMR_RC1 0x25 +#define FRMR_SIC1 0x3e +#define FRMR_SIC2 0x3f +#define FRMR_SIC3 0x40 +#define FRMR_CMR1 0x44 +#define FRMR_CMR2 0x45 +#define FRMR_GCR 0x46 +#define FRMR_ISR0 0x68 +#define FRMR_ISR0_RME 0x80 +#define FRMR_ISR0_RPF 0x01 +#define FRMR_ISR1 0x69 +#define FRMR_ISR1_ALLS 0x20 +#define FRMR_ISR1_XDU 0x10 +#define FRMR_ISR1_XPR 0x01 +#define FRMR_ISR2 0x6a +#define FRMR_ISR3 0x6b +#define FRMR_ISR4 0x6c +#define FRMR_GIS 0x6e +#define FRMR_GIS_ISR0 0x01 +#define FRMR_GIS_ISR1 0x02 +#define FRMR_GIS_ISR2 0x04 +#define FRMR_GIS_ISR3 0x08 +#define FRMR_GIS_ISR4 0x10 +#define FRMR_CIS 0x6f +#define FRMR_CIS_GIS1 0x01 +#define FRMR_CIS_GIS2 0x02 +#define FRMR_CIS_GIS3 0x04 +#define FRMR_CIS_GIS4 0x08 +#define FRMR_CMDR 0x02 +#define FRMR_CMDR_SRES 0x01 +#define FRMR_CMDR_XRES 0x10 +#define FRMR_CMDR_RMC 0x80 +#define FRMR_CMDR_XTF 0x04 +#define FRMR_CMDR_XHF 0x08 +#define FRMR_CMDR_XME 0x02 +#define FRMR_RSIS 0x65 +#define FRMR_RSIS_VFR 0x80 +#define FRMR_RSIS_RDO 0x40 +#define FRMR_RSIS_CRC16 0x20 +#define FRMR_RSIS_RAB 0x10 +#define FRMR_RBCL 0x66 +#define FRMR_RBCL_MAX_SIZE 0x1f +#define FRMR_RBCH 0x67 +#define FRMR_RXFIFO 0x00 +#define FRMR_SIS 0x64 +#define FRMR_SIS_XFW 0x40 +#define FRMR_TXFIFO 0x00 + +#define NUM_REGS 0xa9 +#define NUM_PCI 12 + +struct t4_regs { + unsigned int pci[NUM_PCI]; + unsigned char regs[NUM_REGS]; +}; + +#define T4_CHECK_VPM 0 + +#define WCT4_GET_REGS _IOW (ZT_CODE, 60, struct t4_regs) + diff --git a/kernel/wctc4xxp/Kbuild b/kernel/wctc4xxp/Kbuild new file mode 100644 index 0000000..214aae1 --- /dev/null +++ b/kernel/wctc4xxp/Kbuild @@ -0,0 +1,20 @@ +obj-m += wctc4xxp.o + +FIRM_DIR := ../../firmware + +EXTRA_CFLAGS := -I$(src)/.. -Wno-undef -DSTANDALONE_ZAPATA + +ifeq ($(HOTPLUG_FIRMWARE),yes) + EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE +endif + +wctc4xxp-objs := base.o + +ifneq ($(HOTPLUG_FIRMWARE),yes) +wctc4xxp-objs += $(FIRM_DIR)/zaptel-fw-tc400m.o +endif + +$(obj)/base.o: $(src)/../zaptel.h + +$(obj)/$(FIRM_DIR)/zaptel-fw-tc400m.o: $(obj)/base.o + $(MAKE) -C $(obj)/$(FIRM_DIR) zaptel-fw-tc400m.o diff --git a/kernel/wctc4xxp/Makefile b/kernel/wctc4xxp/Makefile new file mode 100644 index 0000000..725abc4 --- /dev/null +++ b/kernel/wctc4xxp/Makefile @@ -0,0 +1,16 @@ +ifneq ($(KBUILD_EXTMOD),) +# We only get here on kernels 2.6.0-2.6.9 . +# For newer kernels, Kbuild will be included directly by the kernel +# build system. +include $(src)/Kbuild + +else + +tests: codec_test + +codec_test: codec_test.c ../zaptel.h + $(CC) -o $@ $< $(CFLAGS) + +clean: + rm -rf codec_test +endif diff --git a/kernel/wctc4xxp/base.c b/kernel/wctc4xxp/base.c new file mode 100644 index 0000000..3dcb1f4 --- /dev/null +++ b/kernel/wctc4xxp/base.c @@ -0,0 +1,2027 @@ +/* + * Wildcard TC400B Driver + * + * Written by John Sloan + * + * Copyright (C) 2006, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_DEVFS_FS +#include +#endif +#ifdef STANDALONE_ZAPATA +#include "zaptel.h" +#else +#include +#endif + +/* #define USE_TEST_HW */ +#define USE_TDM_CONFIG +#define QUIET_DSP + +#define WC_MAX_IFACES 128 + +#define NUM_CARDS 24 +#define NUM_EC 4 + +/* NUM_CHANNELS must be checked if new firmware (dte_firm.h) is used */ +#define NUM_CHANNELS 120 + +#define DTE_FORMAT_ULAW 0x00 +#define DTE_FORMAT_G723_1 0x04 +#define DTE_FORMAT_ALAW 0x08 +#define DTE_FORMAT_G729A 0x12 +#define DTE_FORMAT_UNDEF 0xFF + +#define G729_LENGTH 20 +#define G723_LENGTH 30 + +#define G729_SAMPLES 160 /* G.729 */ +#define G723_SAMPLES 240 /* G.723.1 */ + +#define G729_BYTES 20 /* G.729 */ +#define G723_6K_BYTES 24 /* G.723.1 at 6.3kb/s */ +#define G723_5K_BYTES 20 /* G.723.1 at 5.3kb/s */ +#define G723_SID_BYTES 4 /* G.723.1 SID frame */ + +#define ACK_SPACE 20 + +#define MAX_COMMANDS (NUM_CHANNELS + ACK_SPACE) +#define MAX_RCV_COMMANDS 16 + +/* 1432 for boot, 274 for 30msec ulaw, 194 for 20mec ulaw */ +#define BOOT_CMD_LEN 1500 +#define OTHER_CMD_LEN 300 + +#define MAX_COMMAND_LEN BOOT_CMD_LEN /* Must be the larger of BOOT_CMD_LEN or OTHER_CMD_LEN */ + +#define ERING_SIZE (NUM_CHANNELS / 2) /* Maximum ring size */ + +#define SFRAME_SIZE MAX_COMMAND_LEN + +#define PCI_WINDOW_SIZE ((2* 2 * ERING_SIZE * SFRAME_SIZE) + (2 * ERING_SIZE * 4)) + +#define MDIO_SHIFT_CLK 0x10000 +#define MDIO_DATA_WRITE0 0x00000 +#define MDIO_DATA_WRITE1 0x20000 +#define MDIO_ENB 0x00000 +#define MDIO_ENB_IN 0x40000 +#define MDIO_DATA_READ 0x80000 + +#define RCV_CSMENCAPS 1 +#define RCV_RTP 2 +#define RCV_CSMENCAPS_ACK 3 +#define RCV_OTHER 99 + + +/* TDM Commands */ +#define CMD_MSG_TDM_SELECT_BUS_MODE_LEN 30 +#define CMD_MSG_TDM_SELECT_BUS_MODE(s) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x01, 0x00,0x06,0x17,0x04, 0xFF,0xFF, \ + 0x04,0x00 } +#define CMD_MSG_TDM_ENABLE_BUS_LEN 30 +#define CMD_MSG_TDM_ENABLE_BUS(s) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x02, 0x00,0x06,0x05,0x04, 0xFF,0xFF, \ + 0x04,0x00 } +#define CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN 34 +#define CMD_MSG_SUPVSR_SETUP_TDM_PARMS(s,p1,p2,p3) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x10, p1, 0x00,0x06,0x07,0x04, 0xFF,0xFF, \ + p2,0x83, 0x00,0x0C, 0x00,0x00, p3,0x00 } +#define CMD_MSG_TDM_OPT_LEN 30 +#define CMD_MSG_TDM_OPT(s) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x35,0x04, 0xFF,0xFF, \ + 0x00,0x00 } +#define CMD_MSG_DEVICE_SET_COUNTRY_CODE_LEN 30 +#define CMD_MSG_DEVICE_SET_COUNTRY_CODE(s) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x1B,0x04, 0xFF,0xFF, \ + 0x00,0x00 } + +/* CPU Commands */ +#define CMD_MSG_SET_ARM_CLK_LEN 32 +#define CMD_MSG_SET_ARM_CLK(s) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0C, 0x00, 0x00,0x06,0x11,0x04, 0x00,0x00, \ + 0x2C,0x01, 0x00,0x00 } +#define CMD_MSG_SET_SPU_CLK_LEN 32 +#define CMD_MSG_SET_SPU_CLK(s) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0C, 0x00, 0x00,0x06,0x12,0x04, 0x00,0x00, \ + 0x2C,0x01, 0x00,0x00 } +#define CMD_MSG_SPU_FEATURES_CONTROL_LEN 30 +#define CMD_MSG_SPU_FEATURES_CONTROL(s,p1) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x13,0x00, 0xFF,0xFF, \ + p1,0x00 } +#define CMD_MSG_DEVICE_STATUS_CONFIG_LEN 30 +#define CMD_MSG_DEVICE_STATUS_CONFIG(s) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x0F,0x04, 0xFF,0xFF, \ + 0x05,0x00 } + +/* General IP/RTP Commands */ +#define CMD_MSG_SET_ETH_HEADER_LEN 44 +#define CMD_MSG_SET_ETH_HEADER(s) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x18, 0x00, 0x00,0x06,0x00,0x01, 0xFF,0xFF, \ + 0x01,0x00, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x00,0x11,0x22,0x33,0x44,0x55, 0x08,0x00 } +#define CMD_MSG_IP_SERVICE_CONFIG_LEN 30 +#define CMD_MSG_IP_SERVICE_CONFIG(s) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x02,0x03, 0xFF,0xFF, \ + 0x00,0x02 } +#define CMD_MSG_ARP_SERVICE_CONFIG_LEN 30 +#define CMD_MSG_ARP_SERVICE_CONFIG(s) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x05,0x01, 0xFF,0xFF, \ + 0x01,0x00 } +#define CMD_MSG_ICMP_SERVICE_CONFIG_LEN 30 +#define CMD_MSG_ICMP_SERVICE_CONFIG(s) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x04,0x03, 0xFF,0xFF, \ + 0x01,0xFF } +#define CMD_MSG_IP_OPTIONS_LEN 30 +#define CMD_MSG_IP_OPTIONS(s) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x06,0x03, 0xFF,0xFF, \ + 0x02,0x00 } + +/* Supervisor channel commands */ +#define CMD_MSG_CREATE_CHANNEL_LEN 32 +#define CMD_MSG_CREATE_CHANNEL(s,t) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0C, 0x00, 0x00,0x06,0x10,0x00, 0x00,0x00, \ + 0x02,0x00, (t&0x00FF), ((t&0xFF00) >> 8) } +#define CMD_MSG_QUERY_CHANNEL_LEN 30 +#define CMD_MSG_QUERY_CHANNEL(s,t) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x01,0x06,0x10,0x00, 0x00,0x00, \ + (t&0x00FF), ((t&0xFF00) >> 8) } +#define CMD_MSG_TRANS_CONNECT_LEN 38 +#define CMD_MSG_TRANS_CONNECT(s,e,c1,c2,f1,f2) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x12, 0x00, 0x00,0x06,0x22,0x93, 0x00,0x00, \ + e,0x00, (c1&0x00FF),((c1&0xFF00)>>8), f1,0x00, (c2&0x00FF),((c2&0xFF00)>>8), f2,0x00 } +#define CMD_MSG_DESTROY_CHANNEL_LEN 32 +#define CMD_MSG_DESTROY_CHANNEL(s,t) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x11,0x00, 0x00,0x00, \ + (t&0x00FF),((t&0xFF00)>>8), 0x00, 0x00 } + +/* Individual channel config commands */ +#define CMD_MSG_SET_IP_HDR_CHANNEL_LEN 58 +#define CMD_MSG_SET_IP_HDR_CHANNEL(s,c,t2,t1) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00) >> 8),(c&0x00FF), 0x26, 0x00, 0x00,0x02,0x00,0x90, 0x00,0x00, \ + 0x00,0x00, 0x45,0x00, 0x00,0x00, 0x00,0x00, 0x40,0x00, 0x80,0x11, 0x00,0x00, \ + 0xC0,0xA8,0x09,0x03, 0xC0,0xA8,0x09,0x03, \ + ((t2&0xFF00)>>8)+0x50,(t2&0x00FF), ((t1&0xFF00)>>8)+0x50,(t1&0x00FF), 0x00,0x00, 0x00,0x00 } +#define CMD_MSG_VOIP_VCEOPT_LEN 40 +#define CMD_MSG_VOIP_VCEOPT(s,c,l,w) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x12, 0x00, 0x00,0x02,0x01,0x80, 0x00,0x00, \ + 0x21,l, 0x00,0x1C, 0x04,0x00, 0x00,0x00, w,0x00, 0x80,0x11 } +#define CMD_MSG_VOIP_VOPENA_LEN 44 +#define CMD_MSG_VOIP_VOPENA(s,c,f) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x16, 0x00, 0x00,0x02,0x00,0x80, 0x00,0x00, \ + 0x01,0x00, 0x80,f, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x12,0x34, 0x56,0x78, 0x00,0x00 } +#define CMD_MSG_VOIP_VOPENA_CLOSE_LEN 32 +#define CMD_MSG_VOIP_VOPENA_CLOSE(s,c) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x00,0x80, 0x00,0x00, \ + 0x00,0x00, 0x00,0x00 } +#define CMD_MSG_VOIP_INDCTRL_LEN 32 +#define CMD_MSG_VOIP_INDCTRL(s,c) {0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x84,0x80, 0x00,0x00, \ + 0x07,0x00, 0x00,0x00 } +#define CMD_MSG_VOIP_DTMFOPT_LEN 32 +#define CMD_MSG_VOIP_DTMFOPT(s,c) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x02,0x80, 0x00,0x00, \ + 0x08,0x00, 0x00,0x00 } + +#define CMD_MSG_VOIP_TONECTL_LEN 32 +#define CMD_MSG_VOIP_TONECTL(s,c) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x5B,0x80, 0x00,0x00, \ + 0x00,0x00, 0x00,0x00 } + +/* CPU ACK command */ +#define CMD_MSG_ACK_LEN 20 +#define CMD_MSG_ACK(s,c) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s, 0xE0, (c&0x00FF), ((c>>8)&0x00FF) } + +/* Wrapper for RTP packets */ +#define CMD_MSG_IP_UDP_RTP_LEN 54 +#define CMD_MSG_IP_UDP_RTP(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20,s) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x08,0x00, \ + 0x45,0x00, p1,p2, 0x00,p3, 0x40,0x00, 0x80,0x11, p4,p5, \ + 0xC0,0xA8,0x09,0x03, 0xC0,0xA8,0x09,0x03, p6,p7, p8,p9, p10,p11, p12,p13, \ + 0x80,p14, p15,p16, p17,p18,p19,p20, 0x12,0x34,0x56,(s&0xFF)} + +#define CMD_MSG_DW_WRITE_LEN 38 +#define CMD_MSG_DW_WRITE(s,a,d) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01,s&0x0F,0x00,0x00,0x00,0x00,0x00,0x04,0x17,0x00,0x00, \ + ((a>>24)&0x00FF),((a>>16)&0x00FF), ((a>>8)&0x00FF),(a&0x00FF), \ + ((d>>24)&0x00FF),((d>>16)&0x00FF), ((d>>8)&0x00FF),(d&0x00FF) } + +#define CMD_MSG_FORCE_ALERT_LEN 32 +#define CMD_MSG_FORCE_ALERT(s) { \ + 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ + 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x09,0x04, 0x00,0x00, \ + 0x24,0x00, 0x00,0x00 } + +#define zt_send_cmd(wc, command, length, hex) \ + ({ \ + int ret = 0; \ + do { \ + if (ret == 2) \ + { \ + wc->ztsnd_rtx++; \ + if (hex == 0x0010) \ + wc->ztsnd_0010_rtx++; \ + } \ + down(&wc->cmdqsem); \ + wc->last_command_sent = hex; \ + if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug ) \ + printk("wcdte error: cmdq is full.\n"); \ + else { \ + unsigned char fifo[OTHER_CMD_LEN] = command; \ + int i; \ + wc->cmdq[wc->cmdq_wndx].cmdlen = length; \ + for (i = 0; i < length; i++) \ + wc->cmdq[wc->cmdq_wndx].cmd[i] = fifo[i]; \ + wc->last_seqno = fifo[16]; \ + wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS; \ + } \ + __transmit_demand(wc); \ + up(&wc->cmdqsem); \ + if (hex == 0x0000) \ + ret = wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS_ACK, 2); \ + else { \ + ret = wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS, 0); \ + if (wc->dsp_crashed) \ + return 1; \ + } \ + if (ret == 1) \ + return(1); \ + } while (ret == 2); \ + }) + + +struct cmdq { + unsigned int cmdlen; + unsigned char cmd[MAX_COMMAND_LEN]; +}; + +struct wcdte { + struct pci_dev *dev; + char *variety; + unsigned int intcount; + unsigned int rxints; + unsigned int txints; + unsigned int intmask; + int pos; + int freeregion; + int rdbl; + int tdbl; + int cards; + spinlock_t reglock; + wait_queue_head_t regq; + int rcvflags; + + struct semaphore chansem; + struct semaphore cmdqsem; + struct cmdq cmdq[MAX_COMMANDS]; + unsigned int cmdq_wndx; + unsigned int cmdq_rndx; + + unsigned int last_seqno; + unsigned int last_rseqno; + unsigned int last_command_sent; + unsigned int last_rcommand; + unsigned int last_rparm1; + unsigned int seq_num; + long timeout; + + unsigned int dsp_crashed; + unsigned int dumping; + + unsigned int ztsnd_rtx; + unsigned int ztsnd_0010_rtx; + + unsigned char numchannels; + unsigned char complexname[40]; + + unsigned long iobase; + dma_addr_t readdma; + dma_addr_t writedma; + dma_addr_t descripdma; + volatile unsigned int *writechunk; /* Double-word aligned write memory */ + volatile unsigned int *readchunk; /* Double-word aligned read memory */ + volatile unsigned int *descripchunk; /* Descriptors */ + + int wqueints; + struct workqueue_struct *dte_wq; + struct work_struct dte_work; + + struct zt_transcoder *uencode; + struct zt_transcoder *udecode; +}; + +struct wcdte_desc { + char *name; + int flags; +}; + +static struct wcdte_desc wctc400p = { "Wildcard TC400P+TC400M", 0 }; +static struct wcdte_desc wctce400 = { "Wildcard TCE400+TC400M", 0 }; + +static struct wcdte *ifaces[WC_MAX_IFACES]; + + + +/* + * The following is the definition of the state structure + * used by the G.721/G.723 encoder and decoder to preserve their internal + * state between successive calls. The meanings of the majority + * of the state structure fields are explained in detail in the + * CCITT Recommendation G.721. The field names are essentially indentical + * to variable names in the bit level description of the coding algorithm + * included in this Recommendation. + */ +struct dte_state { + int encoder; /* If we're an encoder */ + struct wcdte *wc; + + unsigned int timestamp; + unsigned int seqno; + + unsigned int cmd_seqno; + + unsigned int timeslot_in_num; /* DTE chennel on which results we be received from */ + unsigned int timeslot_out_num; /* DTE channel to send data to */ + + unsigned int chan_in_num; /* DTE chennel on which results we be received from */ + unsigned int chan_out_num; /* DTE channel to send data to */ + + unsigned int packets_sent; + unsigned int packets_received; + + unsigned int last_dte_seqno; + unsigned int dte_seqno_rcv; + + unsigned char ssrc; +}; + + +static struct zt_transcoder *uencode; +static struct zt_transcoder *udecode; +static struct dte_state *encoders; +static struct dte_state *decoders; +static int debug = 0; +static int debug_des = 0; /* Set the number of descriptor packet bytes to output on errors, 0 disables output */ +static int debug_des_cnt = 0; /* Set the number of times descriptor packets are displayed before the output is disabled */ +static int force_alert = 0; +static int debug_notimeout = 0; +static char *mode; +static int debug_packets = 0; + +static int wcdte_create_channel(struct wcdte *wc, int simple, int complicated, int part1_id, int part2_id, unsigned int *dte_chan1, unsigned int *dte_chan2); +static int wcdte_destroy_channel(struct wcdte *wc, unsigned int chan1, unsigned int chan2); +static int __wcdte_setup_channels(struct wcdte *wc); + +static int __dump_descriptors(struct wcdte *wc) +{ + volatile unsigned char *writechunk, *readchunk; + int o2, i, j; + + if (debug_des_cnt == 0) + return 1; + + printk("Transmit Descriptors (wc->tdbl = %d)\n", wc->tdbl); + for (i = 0; i < ERING_SIZE; i++) + { + writechunk = (volatile unsigned char *)(wc->writechunk); + writechunk += i * SFRAME_SIZE; + o2 = i * 4; + + if (i == wc->tdbl) + printk("->"); + else + printk(" "); + if ((le32_to_cpu(wc->descripchunk[o2]) & 0x80000000)) + printk("AN983 owns : "); + else + printk("Driver owns: "); + + for (j = 0; j < debug_des; j++) + printk("%02X ", writechunk[j]); + printk("\n"); + } + + printk("Receive Descriptors (wc->rdbl = %d)\n", wc->rdbl); + for (i = 0; i < ERING_SIZE; i++) + { + readchunk = (volatile unsigned char *)wc->readchunk; + readchunk += i * SFRAME_SIZE; + o2 = i * 4; + o2 += ERING_SIZE * 4; + + if (i == wc->rdbl) + printk("->"); + else + printk(" "); + if ((le32_to_cpu(wc->descripchunk[o2]) & 0x80000000)) + printk("AN983 owns : "); + else + printk("Driver owns: "); + + for (j = 0; j < debug_des; j++) + printk("%02X ", readchunk[j]); + printk("\n"); + } + if (debug_des_cnt > 0) + debug_des_cnt--; + return 0; +} + +/* Sanity check values */ +static inline int zt_tc_sanitycheck(struct zt_transcode_header *zth, unsigned int outbytes) +{ + if (zth->dstoffset >= sizeof(zth->dstdata)) + return 0; + if (zth->dstlen >= sizeof(zth->dstdata)) + return 0; + if (outbytes >= sizeof(zth->dstdata)) + return 0; + if ((zth->dstoffset + zth->dstlen + outbytes) >= sizeof(zth->dstdata)) + return 0; + if (zth->srcoffset >= sizeof(zth->srcdata)) + return 0; + if (zth->srclen >= sizeof(zth->srcdata)) + return 0; + if ((zth->srcoffset + zth->srclen) > sizeof(zth->srcdata)) + return 0; + return 1; +} + +static void dte_init_state(struct dte_state *state_ptr, int encoder, unsigned int channel, struct wcdte *wc) +{ + state_ptr->encoder = encoder; + state_ptr->wc = wc; + state_ptr->timestamp = 0; + state_ptr->seqno = 0; + + state_ptr->cmd_seqno = 0; + + state_ptr->packets_sent = 0; + state_ptr->packets_received = 0; + state_ptr->last_dte_seqno = 0; + state_ptr->dte_seqno_rcv = 0; + + state_ptr->chan_in_num = 999; + state_ptr->chan_out_num = 999; + + state_ptr->ssrc = 0x78; + + if (encoder == 1) + { + state_ptr->timeslot_in_num = channel * 2; + state_ptr->timeslot_out_num = channel * 2 + 1; + } else { + state_ptr->timeslot_in_num = channel * 2 + 1; + state_ptr->timeslot_out_num = channel * 2; + } +} + +static unsigned int wcdte_zapfmt_to_dtefmt(unsigned int fmt) +{ + unsigned int pt; + + switch(fmt) + { + case ZT_FORMAT_G723_1: + pt = DTE_FORMAT_G723_1; + break; + case ZT_FORMAT_ULAW: + pt = DTE_FORMAT_ULAW; + break; + case ZT_FORMAT_ALAW: + pt = DTE_FORMAT_ALAW; + break; + case ZT_FORMAT_G729A: + pt = DTE_FORMAT_G729A; + break; + default: + pt = DTE_FORMAT_UNDEF; + } + + return(pt); +} + +static inline void __wcdte_setctl(struct wcdte *wc, unsigned int addr, unsigned int val) +{ + outl(val, wc->iobase + addr); +} + +static inline unsigned int __wcdte_getctl(struct wcdte *wc, unsigned int addr) +{ + return inl(wc->iobase + addr); +} + +static inline void wcdte_setctl(struct wcdte *wc, unsigned int addr, unsigned int val) +{ + unsigned long flags; + spin_lock_irqsave(&wc->reglock, flags); + __wcdte_setctl(wc, addr, val); + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static inline void wcdte_reinit_descriptor(struct wcdte *wc, int tx, int dbl, char *s) +{ + int o2 = 0; + o2 += dbl * 4; + + if (!tx) + o2 += ERING_SIZE * 4; + wc->descripchunk[o2] = cpu_to_le32(0x80000000); + + wcdte_setctl(wc, 0x0008, 0x00000000); +} + +static inline unsigned int wcdte_getctl(struct wcdte *wc, unsigned int addr) +{ + unsigned long flags; + unsigned int val; + spin_lock_irqsave(&wc->reglock, flags); + val = __wcdte_getctl(wc, addr); + spin_unlock_irqrestore(&wc->reglock, flags); + return val; +} + +static inline int __transmit_demand(struct wcdte *wc) +{ + volatile unsigned char *writechunk; + int o2,i,j; + unsigned int reg, xmt_length; + + reg = wcdte_getctl(wc, 0x0028) & 0x00700000; + + /* Already transmiting, no need to demand another */ + if (!((reg == 0) || (reg = 6))) + return(1); + + /* Nothing to transmit */ + if (wc->cmdq_rndx == wc->cmdq_wndx) + return(1); + + /* Nothing to transmit */ + if (wc->cmdq[wc->cmdq_rndx].cmdlen == 0 ) + return(1); + + writechunk = (volatile unsigned char *)(wc->writechunk); + + writechunk += wc->tdbl * SFRAME_SIZE; + + o2 = wc->tdbl * 4; + + do + { + } while ((le32_to_cpu(wc->descripchunk[o2]) & 0x80000000)); + + xmt_length = wc->cmdq[wc->cmdq_rndx].cmdlen; + if (xmt_length < 64) + xmt_length = 64; + + wc->descripchunk[o2+1] = cpu_to_le32((le32_to_cpu(wc->descripchunk[o2+1]) & 0xFBFFF800) | xmt_length); + + for(i = 0; i < wc->cmdq[wc->cmdq_rndx].cmdlen; i++) + writechunk[i] = wc->cmdq[wc->cmdq_rndx].cmd[i]; + for (j = i; j < xmt_length; j++) + writechunk[j] = 0; + + if (debug_packets && (writechunk[12] == 0x88) && (writechunk[13] == 0x9B)) + { + printk("wcdte debug: TX: "); + for (i=0; icmdq[wc->cmdq_rndx].cmdlen = 0; + + wc->descripchunk[o2] = cpu_to_le32(0x80000000); + wcdte_setctl(wc, 0x0008, 0x00000000); /* Transmit Poll Demand */ + + wc->tdbl = (wc->tdbl + 1) % ERING_SIZE; + + wc->cmdq_rndx = (wc->cmdq_rndx + 1) % MAX_COMMANDS; + + return(0); +} + +static inline int transmit_demand(struct wcdte *wc) +{ + int val; + down(&wc->cmdqsem); + val = __transmit_demand(wc); + up(&wc->cmdqsem); + return val; +} + +static int dte_operation(struct zt_transcoder_channel *ztc, int op) +{ + struct zt_transcoder_channel *compl_ztc; + struct dte_state *st = ztc->pvt, *compl_st; + struct zt_transcode_header *zth = ztc->tch; + struct wcdte *wc = st->wc; + unsigned char *chars; + unsigned int inbytes = 0; + unsigned int timestamp_inc = 0; + int i = 0; + int res = 0; + unsigned int ipchksum, ndx; + switch(op) { + case ZT_TCOP_ALLOCATE: + down(&wc->chansem); + if (ztc->chan_built == 0) + { + if (st->encoder == 1) + wcdte_create_channel(wc, wcdte_zapfmt_to_dtefmt(zth->srcfmt), wcdte_zapfmt_to_dtefmt(zth->dstfmt), + st->timeslot_in_num, st->timeslot_out_num, &(st->chan_in_num), &(st->chan_out_num)); + else + wcdte_create_channel(wc, wcdte_zapfmt_to_dtefmt(zth->dstfmt), wcdte_zapfmt_to_dtefmt(zth->srcfmt), + st->timeslot_out_num, st->timeslot_in_num, &(st->chan_out_num), &(st->chan_in_num)); + /* Mark this channel as built */ + ztc->chan_built = 1; + ztc->built_fmts = zth->dstfmt | zth->srcfmt; + + /* Mark the channel complement (other half of encoder/decoder pair) as built */ + ndx = st->timeslot_in_num/2; + if (st->encoder == 1) + compl_ztc = &(wc->udecode->channels[ndx]); + else + compl_ztc = &(wc->uencode->channels[ndx]); + compl_ztc->chan_built = 1; + compl_ztc->built_fmts = zth->dstfmt | zth->srcfmt; + compl_st = compl_ztc->pvt; + compl_st->chan_in_num = st->chan_out_num; + compl_st->chan_out_num = st->chan_in_num; + } + up(&wc->chansem); + break; + case ZT_TCOP_RELEASE: + down(&wc->chansem); + ndx = st->timeslot_in_num/2; + + if (st->encoder == 1) + compl_ztc = &(wc->udecode->channels[ndx]); + else + compl_ztc = &(wc->uencode->channels[ndx]); + + /* If the channel complement (other half of the encoder/decoder pair) is not being used... */ + if ((compl_ztc->flags & ZT_TC_FLAG_BUSY) == 0) + { + if (st->encoder == 1) + wcdte_destroy_channel(wc, st->chan_in_num, st->chan_out_num); + else + wcdte_destroy_channel(wc, st->chan_out_num, st->chan_in_num); + + /* Mark this channel as not built */ + ztc->chan_built = 0; + ztc->built_fmts = 0; + st->chan_in_num = 999; + st->chan_out_num = 999; + + /* Mark the channel complement as not built */ + compl_ztc->chan_built = 0; + compl_ztc->built_fmts = 0; + compl_st = compl_ztc->pvt; + compl_st->chan_in_num = 999; + compl_st->chan_out_num = 999; + } + st->dte_seqno_rcv = 0; + up(&wc->chansem); + break; + case ZT_TCOP_TRANSCODE: + if ( (((zth->srcfmt == ZT_FORMAT_ULAW) || (zth->srcfmt == ZT_FORMAT_ALAW)) && ((zth->dstfmt == ZT_FORMAT_G729A && zth->srclen >= G729_SAMPLES) ||(zth->dstfmt == ZT_FORMAT_G723_1 && zth->srclen >= G723_SAMPLES)) ) + || ((zth->srcfmt == ZT_FORMAT_G729A) && (zth->srclen >= G729_BYTES)) + || ((zth->srcfmt == ZT_FORMAT_G723_1) && (zth->srclen >= G723_SID_BYTES)) ) + { + do + { + chars = (unsigned char *)(zth->srcdata + zth->srcoffset); + + if ((zth->srcfmt == ZT_FORMAT_ULAW) || (zth->srcfmt == ZT_FORMAT_ALAW)) { + if (zth->dstfmt == ZT_FORMAT_G729A) { + inbytes = G729_SAMPLES; + timestamp_inc = G729_SAMPLES; + } else if (zth->dstfmt == ZT_FORMAT_G723_1) { + inbytes = G723_SAMPLES; + timestamp_inc = G723_SAMPLES; + } + } else if (zth->srcfmt == ZT_FORMAT_G729A) { + inbytes = G729_BYTES; + timestamp_inc = G729_SAMPLES; + } else if (zth->srcfmt == ZT_FORMAT_G723_1) { + /* determine the size of the frame */ + switch (chars[0] & 0x03) { + case 0x00: + inbytes = G723_6K_BYTES; + break; + case 0x01: + inbytes = G723_5K_BYTES; + break; + case 0x02: + inbytes = G723_SID_BYTES; + break; + case 0x03: + /* this is a 'reserved' value in the G.723.1 + spec and should never occur in real media streams */ + inbytes = G723_SID_BYTES; + break; + } + timestamp_inc = G723_SAMPLES; + } + + zth->srclen -= inbytes; + + { + unsigned char fifo[OTHER_CMD_LEN] = CMD_MSG_IP_UDP_RTP( + ((inbytes+40) >> 8) & 0xFF, + (inbytes+40) & 0xFF, + st->seqno & 0xFF, + 0x00, + 0x00, + (((st->timeslot_out_num) >> 8)+0x50) & 0xFF, + (st->timeslot_out_num) & 0xFF, + (((st->timeslot_in_num) >> 8)+0x50) & 0xFF, + (st->timeslot_in_num) & 0xFF, + ((inbytes+20) >> 8) & 0xFF, + (inbytes+20) & 0xFF, + 0x00, + 0x00, + wcdte_zapfmt_to_dtefmt(zth->srcfmt), + ((st->seqno) >> 8) & 0xFF, + (st->seqno) & 0xFF, + ((st->timestamp) >> 24) & 0xFF, + ((st->timestamp) >> 16) & 0xFF, + ((st->timestamp) >> 8) & 0xFF, + (st->timestamp) & 0xFF, + (st->ssrc) & 0xFF); + + ipchksum = 0x9869 + (fifo[16] << 8) + fifo[17] + + (fifo[18] << 8) + fifo[19]; + while (ipchksum >> 16) + ipchksum = (ipchksum & 0xFFFF) + (ipchksum >> 16); + ipchksum = (~ipchksum) & 0xFFFF; + + fifo[24] = ipchksum >> 8; + fifo[25] = ipchksum & 0xFF; + + st->seqno += 1; + st->timestamp += timestamp_inc; + + for (i = 0; i < inbytes; i++) + fifo[i+CMD_MSG_IP_UDP_RTP_LEN]= chars[i]; + + down(&wc->cmdqsem); + + if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug ) + printk("wcdte error: cmdq is full.\n"); + else + { + wc->cmdq[wc->cmdq_wndx].cmdlen = CMD_MSG_IP_UDP_RTP_LEN+inbytes; + for (i = 0; i < CMD_MSG_IP_UDP_RTP_LEN+inbytes; i++) + wc->cmdq[wc->cmdq_wndx].cmd[i] = fifo[i]; + wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS; + } + + __transmit_demand(wc); + up(&wc->cmdqsem); + } + st->packets_sent++; + + + + zth->srcoffset += inbytes; + + + } while ((((zth->srcfmt == ZT_FORMAT_ULAW) || (zth->srcfmt == ZT_FORMAT_ALAW)) && ((zth->dstfmt == ZT_FORMAT_G729A && zth->srclen >= G729_SAMPLES) ||(zth->dstfmt == ZT_FORMAT_G723_1 && zth->srclen >= G723_SAMPLES)) ) + || ((zth->srcfmt == ZT_FORMAT_G729A) && (zth->srclen >= G729_BYTES)) + || ((zth->srcfmt == ZT_FORMAT_G723_1) && (zth->srclen >= G723_SID_BYTES)) ); + + } else { + zt_transcoder_alert(ztc); + } + + res = 0; + break; + } + return res; +} + +static void wcdte_stop_dma(struct wcdte *wc); + +static inline void wcdte_receiveprep(struct wcdte *wc, int dbl) +{ + volatile unsigned char *readchunk; + struct zt_transcoder_channel *ztc = NULL; + struct zt_transcode_header *zth = NULL; + struct dte_state *st = NULL; + int o2,i; + unsigned char rseq, rcodec; + unsigned int rcommand, rchannel, rlen, rtp_rseq, rtp_eseq; + unsigned char *chars = NULL; + unsigned int ztc_ndx; + + readchunk = (volatile unsigned char *)wc->readchunk; + readchunk += dbl * SFRAME_SIZE; + + o2 = dbl * 4; + o2 += ERING_SIZE * 4; + + /* Control in packet */ + if ((readchunk[12] == 0x88) && (readchunk[13] == 0x9B)) + { + if (debug_packets) + { + printk("wcdte debug: RX: "); + for (i=0; icmdqsem); + if ((readchunk[17] & 0x40) == 0) { + if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug ) + printk("wcdte error: cmdq is full (rndx = %d, wndx = %d).\n", wc->cmdq_rndx, wc->cmdq_wndx); + else + { + unsigned char fifo[OTHER_CMD_LEN] = CMD_MSG_ACK(rseq++, rchannel); + + wc->cmdq[wc->cmdq_wndx].cmdlen = CMD_MSG_ACK_LEN; + for (i = 0; i < wc->cmdq[wc->cmdq_wndx].cmdlen; i++) + wc->cmdq[wc->cmdq_wndx].cmd[i] = fifo[i]; + wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS; + } + + __transmit_demand(wc); + } + + wc->rcvflags = RCV_CSMENCAPS; + if (rcommand == wc->last_command_sent) { + wc->last_rcommand = rcommand; + wc->last_rparm1 = readchunk[28] | (readchunk[29] << 8); + wake_up(&wc->regq); + } else { + if (debug) + printk("wcdte error: unexpected command response received (sent: %04X, received: %04X)\n", wc->last_command_sent, rcommand); + } + up(&wc->cmdqsem); + } + else + { + wc->last_rseqno = readchunk[16]; + wc->rcvflags = RCV_CSMENCAPS_ACK; + if (!wc->dumping) + wake_up_interruptible(&wc->regq); + else + wake_up(&wc->regq); + } + + if ((readchunk[22] == 0x75) && (readchunk[23] = 0xC1)) + { + if (debug) + printk("wcdte error: received alert (0x%02X%02X) from dsp\n", readchunk[29], readchunk[28]); + if (debug_des) { + down(&wc->cmdqsem); + __dump_descriptors(wc); + up(&wc->cmdqsem); + } + } + + if (wc->dumping && (readchunk[22] == 0x04) && (readchunk[23] = 0x14)) { + for (i = 27; i < 227; i++) + printk("%02X ", readchunk[i]); + printk("\n"); + } + } + + /* IP/UDP in packet */ + else if ((readchunk[12] == 0x08) && (readchunk[13] == 0x00) + && (readchunk[50] == 0x12) && (readchunk[51] == 0x34) && (readchunk[52] = 0x56) && (readchunk[53] == 0x78)) + { + rchannel = (readchunk[37] | (readchunk[36] << 8)) - 0x5000; + rlen = (readchunk[39] | (readchunk[38] << 8)) - 20; + rtp_rseq = (readchunk[45] | (readchunk[44] << 8)); + rcodec = readchunk[43]; + + ztc_ndx = rchannel/2; + + if (ztc_ndx >= wc->numchannels) + { + if (debug) + printk("wcdte error: Invalid channel number received (ztc_ndx = %d) (numchannels = %d)\n", ztc_ndx, wc->numchannels); + rcodec = DTE_FORMAT_UNDEF; + } + + if ((rcodec == 0x00) || (rcodec == 0x08)) /* ulaw or alaw (decoders) */ + { + ztc = &(wc->udecode->channels[ztc_ndx]); + zth = ztc->tch; + st = ztc->pvt; + + if (zth == NULL) + { + if (debug) + printk("wcdte error: Tried to put DTE data into a freed zth header! (ztc_ndx = %d, ztc->chan_built = %d)\n", ztc_ndx, ztc->chan_built); + if (debug_des) { + down(&wc->cmdqsem); + __dump_descriptors(wc); + up(&wc->cmdqsem); + } + rcodec = DTE_FORMAT_UNDEF; + } else { + chars = (unsigned char *)(zth->dstdata + zth->dstoffset + zth->dstlen); + st->packets_received++; + } + + } + + if ((rcodec == 0x04) || (rcodec == 0x12)) /* g.723 or g.729 (encoders) */ + { + ztc = &(wc->uencode->channels[ztc_ndx]); + zth = ztc->tch; + st = ztc->pvt; + + if (zth == NULL) + { + if (debug) + printk("wcdte error: Tried to put DTE data into a freed zth header! (ztc_ndx = %d, ztc->chan_built = %d)\n", ztc_ndx, ztc->chan_built); + if (debug_des) { + down(&wc->cmdqsem); + __dump_descriptors(wc); + up(&wc->cmdqsem); + } + rcodec = DTE_FORMAT_UNDEF; + } else { + chars = (unsigned char *)(zth->dstdata + zth->dstoffset + zth->dstlen); + st->packets_received++; + } + + } + + if (st->dte_seqno_rcv == 0) + { + st->dte_seqno_rcv = 1; + st->last_dte_seqno = rtp_rseq; + } else { + rtp_eseq = (st->last_dte_seqno + 1) & 0xFFFF; + if ( (rtp_rseq != rtp_eseq) && debug ) + printk("wcdte error: Bad seqno from DTE! [%04X][%d][%d][%d]\n", (readchunk[37] | (readchunk[36] << 8)), rchannel, rtp_rseq, st->last_dte_seqno); + + st->last_dte_seqno = rtp_rseq; + } + + if (rcodec == 0x00) /* ulaw */ + { + if (zt_tc_sanitycheck(zth, rlen) && ((zth->srcfmt == ZT_FORMAT_G729A && rlen == G729_SAMPLES) || (zth->srcfmt == ZT_FORMAT_G723_1 && rlen == G723_SAMPLES))) { + for (i = 0; i < rlen; i++) + chars[i] = readchunk[i+54]; + + zth->dstlen += rlen; + zth->dstsamples = zth->dstlen; + + } else { + ztc->errorstatus = -EOVERFLOW; + } + zt_transcoder_alert(ztc); + } + else if (rcodec == 0x08) /* alaw */ + { + if (zt_tc_sanitycheck(zth, rlen) && ((zth->srcfmt == ZT_FORMAT_G729A && rlen == G729_SAMPLES) || (zth->srcfmt == ZT_FORMAT_G723_1 && rlen == G723_SAMPLES))) { + + for (i = 0; i < rlen; i++) + chars[i] = readchunk[i+54]; + + zth->dstlen += rlen; + zth->dstsamples = zth->dstlen; + + } else { + ztc->errorstatus = -EOVERFLOW; + } + zt_transcoder_alert(ztc); + } + else if (rcodec == 0x04) /* G.723.1 */ + { + if (zt_tc_sanitycheck(zth, rlen) && + ((rlen == G723_6K_BYTES) || (rlen == G723_5K_BYTES) || (rlen == G723_SID_BYTES))) + { + for (i = 0; i < rlen; i++) + chars[i] = readchunk[i+54]; + + zth->dstlen += rlen; + zth->dstsamples += G723_SAMPLES; + + } else { + ztc->errorstatus = -EOVERFLOW; + } + + if (!(zth->dstsamples % G723_SAMPLES)) + { + zt_transcoder_alert(ztc); + } + } + else if (rcodec == 0x12) /* G.729a */ + { + if (zt_tc_sanitycheck(zth, rlen) && (rlen == G729_BYTES)) + { + for (i = 0; i < rlen; i++) + chars[i] = readchunk[i+54]; + + zth->dstlen += rlen; + zth->dstsamples = zth->dstlen * 8; + + } else { + ztc->errorstatus = -EOVERFLOW; + } + + if (!(zth->dstsamples % G729_SAMPLES)) + { + zt_transcoder_alert(ztc); + } + } + } +} + + + + + +/* static inline int wcdte_check_descriptor(struct wcdte *wc) */ +static int wcdte_check_descriptor(struct wcdte *wc) +{ + int o2 = 0; + + o2 += ERING_SIZE * 4; + o2 += wc->rdbl * 4; + + if (!(le32_to_cpu(wc->descripchunk[o2]) & 0x80000000)) { + wc->rxints++; + wcdte_receiveprep(wc, wc->rdbl); + wcdte_reinit_descriptor(wc, 0, wc->rdbl, "rxchk"); + wc->rdbl = (wc->rdbl + 1) % ERING_SIZE; + + return 1; + } + return 0; +} + +static void wcdte_init_descriptors(struct wcdte *wc) +{ + volatile unsigned int *descrip; + dma_addr_t descripdma; + dma_addr_t writedma; + dma_addr_t readdma; + int x; + + descrip = wc->descripchunk; + descripdma = wc->descripdma; + writedma = wc->writedma; + readdma = wc->readdma; + + for (x=0;xdescripdma; + + /* Transmit descriptor */ + descrip[0 ] = cpu_to_le32(0x00000000); + descrip[1 ] = cpu_to_le32(0xe5800000 | (SFRAME_SIZE)); + descrip[2 ] = cpu_to_le32(writedma + x*SFRAME_SIZE); + descrip[3 ] = cpu_to_le32(descripdma); + + /* Receive descriptor */ + descrip[0 + ERING_SIZE * 4] = cpu_to_le32(0x80000000); + descrip[1 + ERING_SIZE * 4] = cpu_to_le32(0x01000000 | (SFRAME_SIZE)); + descrip[2 + ERING_SIZE * 4] = cpu_to_le32(readdma + x*SFRAME_SIZE); + descrip[3 + ERING_SIZE * 4] = cpu_to_le32(descripdma + ERING_SIZE * 16); + + /* Advance descriptor */ + descrip += 4; + } +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) +static void dte_wque_run(struct work_struct *work) +{ + struct wcdte *wc = container_of(work, struct wcdte, dte_work); +#else +static void dte_wque_run(void *work_data) +{ + struct wcdte *wc = work_data; +#endif + int res; + + do { + res = wcdte_check_descriptor(wc); + } while(res); + + transmit_demand(wc); +} + +ZAP_IRQ_HANDLER(wcdte_interrupt) +{ + struct wcdte *wc = dev_id; + unsigned int ints; + + /* Read and clear interrupts */ + ints = wcdte_getctl(wc, 0x0028); + wcdte_setctl(wc, 0x0028, ints); + + if (!ints) + return IRQ_NONE; + ints &= wc->intmask; + + if (ints & 0x00000041) { + wc->wqueints = ints; + queue_work(wc->dte_wq, &wc->dte_work); + } + + if ((ints & 0x00008000) && debug) + printk("wcdte: Abnormal Interrupt: "); + + if ((ints & 0x00002000) && debug) + printk("wcdte: Fatal Bus Error INT\n"); + + if ((ints & 0x00000100) && debug) + printk("wcdte: Receive Stopped INT\n"); + + if ((ints & 0x00000080) && debug) + printk("wcdte: Receive Desciptor Unavailable INT\n"); + + if ((ints & 0x00000020) && debug) + printk("wcdte: Transmit Under-flow INT\n"); + + if ((ints & 0x00000008) && debug) + printk("wcdte: Jabber Timer Time-out INT\n"); + + if ((ints & 0x00000004) && debug) + printk("wcdte: Transmit Descriptor Unavailable INT\n"); + + if ((ints & 0x00000002) && debug) + printk("wcdte: Transmit Processor Stopped INT\n"); + + return IRQ_RETVAL(1); + +} + +static int wcdte_hardware_init(struct wcdte *wc) +{ + /* Hardware stuff */ + unsigned int reg; + unsigned long newjiffies; + + /* Initialize descriptors */ + wcdte_init_descriptors(wc); + + /* Enable I/O Access */ + pci_read_config_dword(wc->dev, 0x0004, ®); + reg |= 0x00000007; + pci_write_config_dword(wc->dev, 0x0004, reg); + + wcdte_setctl(wc, 0x0000, 0xFFF88001); + + newjiffies = jiffies + HZ/10; + while(((reg = wcdte_getctl(wc,0x0000)) & 0x00000001) && (newjiffies > jiffies)); + + wcdte_setctl(wc, 0x0000, 0xFFFA0000); + + /* Configure watchdogs, access, etc */ + wcdte_setctl(wc, 0x0030, 0x00280048); + wcdte_setctl(wc, 0x0078, 0x00000013 /* | (1 << 28) */); + + reg = wcdte_getctl(wc, 0x00fc); + wcdte_setctl(wc, 0x00fc, (reg & ~0x7) | 0x7); + + reg = wcdte_getctl(wc, 0x00fc); + + return 0; +} + +static void wcdte_setintmask(struct wcdte *wc, unsigned int intmask) +{ + wc->intmask = intmask; + wcdte_setctl(wc, 0x0038, intmask); +} + +static void wcdte_enable_interrupts(struct wcdte *wc) +{ + /* Enable interrupts */ + if (!debug) + wcdte_setintmask(wc, 0x00010041); + else + wcdte_setintmask(wc, 0x0001A1EB); +} + +static void wcdte_start_dma(struct wcdte *wc) +{ + unsigned int reg; + wmb(); + wcdte_setctl(wc, 0x0020, wc->descripdma); + wcdte_setctl(wc, 0x0018, wc->descripdma + (16 * ERING_SIZE)); + /* Start receiver/transmitter */ + reg = wcdte_getctl(wc, 0x0030); + wcdte_setctl(wc, 0x0030, reg | 0x00002002); /* Start XMT and RCD */ + wcdte_setctl(wc, 0x0010, 0x00000000); /* Receive Poll Demand */ + reg = wcdte_getctl(wc, 0x0028); + wcdte_setctl(wc, 0x0028, reg); + +} + +static void wcdte_stop_dma(struct wcdte *wc) +{ + /* Disable interrupts and reset */ + unsigned int reg; + /* Disable interrupts */ + wcdte_setintmask(wc, 0x00000000); + wcdte_setctl(wc, 0x0084, 0x00000000); + wcdte_setctl(wc, 0x0048, 0x00000000); + /* Reset the part to be on the safe side */ + reg = wcdte_getctl(wc, 0x0000); + reg |= 0x00000001; + wcdte_setctl(wc, 0x0000, reg); +} + +static void wcdte_disable_interrupts(struct wcdte *wc) +{ + /* Disable interrupts */ + wcdte_setintmask(wc, 0x00000000); + wcdte_setctl(wc, 0x0084, 0x00000000); +} + +static int wcdte_waitfor_csmencaps(struct wcdte *wc, unsigned int mask, int wait_mode) +{ + int ret; + + + if (wait_mode == 1) + ret = wait_event_interruptible_timeout(wc->regq, (wc->rcvflags == mask), wc->timeout); + else if (wait_mode == 2) + ret = wait_event_timeout(wc->regq, (wc->rcvflags == mask), wc->timeout); + else { + if (!debug_notimeout) { + ret = wait_event_timeout(wc->regq, ((wc->last_rcommand == wc->last_command_sent) && (wc->last_seqno == wc->last_rseqno) && (wc->rcvflags == mask)), wc->timeout); + } + else { + ret = wait_event_interruptible(wc->regq, ((wc->last_rcommand == wc->last_command_sent) && (wc->last_seqno == wc->last_rseqno) && (wc->rcvflags == mask))); + if (ret == 0) + ret = 1; + } + } + wc->rcvflags = 0; + wc->last_rcommand = 0; + wc->last_seqno = 0; + + if (ret < 0) + { + if (debug) + printk("wcdte error: Wait interrupted, need to stop boot (ret = %d)\n", ret); + return(1); + } + if (ret == 0) + { + if (debug) + printk("wcdte error: Waitfor CSMENCAPS response timed out (ret = %d) (cmd_snt = %04X)\n", ret, wc->last_command_sent); + if (debug_des) { + down(&wc->cmdqsem); + __dump_descriptors(wc); + up(&wc->cmdqsem); + } + return(2); + } + if (wait_mode == 0) + wc->last_command_sent = 999; + wc->last_rseqno = 999; + return(0); +} + + +static int wcdte_read_phy(struct wcdte *wc, int location) +{ + int i; + long mdio_addr = 0x0048; + int read_cmd = (0xf6 << 10) | (1 << 5) | location; + int retval = 0; + + /* Establish sync by sending at least 32 logic ones. */ + for (i = 32; i >= 0; i--) { + wcdte_setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1); + wcdte_getctl(wc, mdio_addr); + wcdte_setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK); + wcdte_getctl(wc, mdio_addr); + } + /* Shift the read command bits out. */ + for (i = 17; i >= 0; i--) { + int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; + + wcdte_setctl(wc, mdio_addr, MDIO_ENB | dataval); + wcdte_getctl(wc, mdio_addr); + wcdte_setctl(wc, mdio_addr, MDIO_ENB | dataval | MDIO_SHIFT_CLK); + wcdte_getctl(wc, mdio_addr); + } + + /* Read the two transition, 16 data, and wire-idle bits. */ + for (i = 19; i > 0; i--) { + wcdte_setctl(wc, mdio_addr, MDIO_ENB_IN); + wcdte_getctl(wc, mdio_addr); + retval = (retval << 1) | ((wcdte_getctl(wc, mdio_addr) & MDIO_DATA_READ) ? 1 : 0); + wcdte_setctl(wc, mdio_addr, MDIO_ENB_IN | MDIO_SHIFT_CLK); + wcdte_getctl(wc, mdio_addr); + } + retval = (retval>>1) & 0xffff; + return retval; +} + +void wcdte_write_phy(struct wcdte *wc, int location, int value) +{ + int i; + int cmd = (0x5002 << 16) | (1 << 23) | (location<<18) | value; + long mdio_addr = 0x0048; + + /* Establish sync by sending 32 logic ones. */ + for (i = 32; i >= 0; i--) { + wcdte_setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1); + wcdte_getctl(wc, mdio_addr); + wcdte_setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK); + wcdte_getctl(wc, mdio_addr); + } + /* Shift the command bits out. */ + for (i = 31; i >= 0; i--) { + int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; + wcdte_setctl(wc, mdio_addr, MDIO_ENB | dataval); + wcdte_getctl(wc, mdio_addr); + wcdte_setctl(wc, mdio_addr, MDIO_ENB | dataval | MDIO_SHIFT_CLK); + wcdte_getctl(wc, mdio_addr); + } + /* Clear out extra bits. */ + for (i = 2; i > 0; i--) { + wcdte_setctl(wc, mdio_addr, MDIO_ENB_IN); + wcdte_getctl(wc, mdio_addr); + wcdte_setctl(wc, mdio_addr, MDIO_ENB_IN | MDIO_SHIFT_CLK); + wcdte_getctl(wc, mdio_addr); + } + return; +} + +static int wcdte_boot_processor(struct wcdte *wc, const struct firmware *firmware, int full) +{ + int i, j, byteloc, last_byteloc, length, delay_count; + unsigned int reg, ret; + +#ifndef USE_TEST_HW + /* Turn off auto negotiation */ + wcdte_write_phy(wc, 0, 0x2100); + if (debug) + printk("wcdte: PHY register 0 = %X", wcdte_read_phy(wc, 0)); + + /* Set reset */ + wcdte_setctl(wc, 0x00A0, 0x04000000); + + /* Wait 1000msec to ensure processor reset */ + mdelay(4); + + /* Clear reset */ + wcdte_setctl(wc, 0x00A0, 0x04080000); + + /* Waitfor ethernet link */ + delay_count = 0; + do + { + reg = wcdte_getctl(wc, 0x00fc); + mdelay(2); + delay_count++; + + if (delay_count >= 5000) + { + printk("wcdte error: Failed to link to DTE processor!\n"); + return(1); + } + } while ((reg & 0xE0000000) != 0xE0000000); + + + /* Turn off booted LED */ + wcdte_setctl(wc, 0x00A0, 0x04084000); + + +#endif + + reg = wcdte_getctl(wc, 0x00fc); + if (debug) + printk("wcdte: LINK STATUS: reg(0xfc) = %X\n", reg); + + reg = wcdte_getctl(wc, 0x00A0); + + byteloc = 17; + j = 0; + do + { + last_byteloc = byteloc; + + length = (firmware->data[byteloc] << 8) |firmware->data[byteloc+1]; + byteloc += 2; + + down(&wc->cmdqsem); + if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug ) + printk("wcdte error: cmdq is full.\n"); + else + { + wc->cmdq[wc->cmdq_wndx].cmdlen = length; + for (i = 0; i < length; i++) + wc->cmdq[wc->cmdq_wndx].cmd[i] = firmware->data[byteloc++]; + wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS; + } + + ret = __transmit_demand(wc); + up(&wc->cmdqsem); + + ret = wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS_ACK, 1); + if (ret == 1) + return(1); + else if (ret == 2) /* Retransmit if dte processor times out */ + byteloc = last_byteloc; + j++; + + if (!full && (byteloc > 189)) { /* Quit if not fully booting */ + wcdte_setctl(wc, 0x00A0, 0x04080000); + return 0; + } + + + } while (byteloc < firmware->size-20); + wc->timeout = 10 * HZ; + wc->last_command_sent = 0; + if (wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS, 1)) + return(1); + + /* Turn on booted LED */ + wcdte_setctl(wc, 0x00A0, 0x04080000); + if(debug) + printk("wcdte: Successfully booted DTE processor.\n"); + + return(0); +} + +static int wcdte_create_channel(struct wcdte *wc, int simple, int complicated, int part1_id, int part2_id, unsigned int *dte_chan1, unsigned int *dte_chan2) +{ + int length = 0; + unsigned char chan1, chan2; + struct zt_transcoder_channel *ztc1, *ztc2; + struct dte_state *st1, *st2; + if(complicated == DTE_FORMAT_G729A) + length = G729_LENGTH; + else if (complicated == DTE_FORMAT_G723_1) + length = G723_LENGTH; + + /* Create complex channel */ + zt_send_cmd(wc, CMD_MSG_CREATE_CHANNEL(wc->seq_num++, part1_id), CMD_MSG_CREATE_CHANNEL_LEN, 0x0010); + zt_send_cmd(wc, CMD_MSG_QUERY_CHANNEL(wc->seq_num++, part1_id), CMD_MSG_QUERY_CHANNEL_LEN, 0x0010); + chan1 = wc->last_rparm1; + + /* Create simple channel */ + zt_send_cmd(wc, CMD_MSG_CREATE_CHANNEL(wc->seq_num++, part2_id), CMD_MSG_CREATE_CHANNEL_LEN, 0x0010); + zt_send_cmd(wc, CMD_MSG_QUERY_CHANNEL(wc->seq_num++, part2_id), CMD_MSG_QUERY_CHANNEL_LEN, 0x0010); + chan2 = wc->last_rparm1; + + ztc1 = &(wc->uencode->channels[part1_id/2]); + ztc2 = &(wc->udecode->channels[part2_id/2]); + st1 = ztc1->pvt; + st2 = ztc2->pvt; + + /* Configure complex channel */ + zt_send_cmd(wc, CMD_MSG_SET_IP_HDR_CHANNEL(st1->cmd_seqno++, chan1, part2_id, part1_id), CMD_MSG_SET_IP_HDR_CHANNEL_LEN, 0x9000); + zt_send_cmd(wc, CMD_MSG_VOIP_VCEOPT(st1->cmd_seqno++, chan1, length, 0), CMD_MSG_VOIP_VCEOPT_LEN, 0x8001); + + /* Configure simple channel */ + zt_send_cmd(wc, CMD_MSG_SET_IP_HDR_CHANNEL(st2->cmd_seqno++, chan2, part1_id, part2_id), CMD_MSG_SET_IP_HDR_CHANNEL_LEN, 0x9000); + zt_send_cmd(wc, CMD_MSG_VOIP_VCEOPT(st2->cmd_seqno++, chan2, length, 0), CMD_MSG_VOIP_VCEOPT_LEN, 0x8001); + +#ifdef QUIET_DSP + zt_send_cmd(wc, CMD_MSG_VOIP_TONECTL(st1->cmd_seqno++, chan1), CMD_MSG_VOIP_TONECTL_LEN, 0x805B); + zt_send_cmd(wc, CMD_MSG_VOIP_DTMFOPT(st1->cmd_seqno++, chan1), CMD_MSG_VOIP_DTMFOPT_LEN, 0x8002); + zt_send_cmd(wc, CMD_MSG_VOIP_TONECTL(st2->cmd_seqno++, chan2), CMD_MSG_VOIP_TONECTL_LEN, 0x805B); + zt_send_cmd(wc, CMD_MSG_VOIP_DTMFOPT(st2->cmd_seqno++, chan2), CMD_MSG_VOIP_DTMFOPT_LEN, 0x8002); + zt_send_cmd(wc, CMD_MSG_VOIP_INDCTRL(st1->cmd_seqno++, chan1), CMD_MSG_VOIP_INDCTRL_LEN, 0x8084); + zt_send_cmd(wc, CMD_MSG_VOIP_INDCTRL(st2->cmd_seqno++, chan2), CMD_MSG_VOIP_INDCTRL_LEN, 0x8084); +#endif + + zt_send_cmd(wc, CMD_MSG_TRANS_CONNECT(wc->seq_num++, 1, chan1, chan2, complicated, simple), CMD_MSG_TRANS_CONNECT_LEN, 0x9322); + zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA(st1->cmd_seqno++, chan1, complicated), CMD_MSG_VOIP_VOPENA_LEN, 0x8000); + zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA(st2->cmd_seqno++, chan2, simple), CMD_MSG_VOIP_VOPENA_LEN, 0x8000); + + *dte_chan1 = chan1; + *dte_chan2 = chan2; + + return 1; +} + +static int wcdte_destroy_channel(struct wcdte *wc, unsigned int chan1, unsigned int chan2) +{ + struct zt_transcoder_channel *ztc1, *ztc2; + struct dte_state *st1, *st2; + + ztc1 = &(wc->uencode->channels[chan1/2]); + ztc2 = &(wc->udecode->channels[chan2/2]); + st1 = ztc1->pvt; + st2 = ztc2->pvt; + + /* Turn off both channels */ + zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA_CLOSE(st1->cmd_seqno++, chan1), CMD_MSG_VOIP_VOPENA_CLOSE_LEN, 0x8000); + zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA_CLOSE(st2->cmd_seqno++, chan2), CMD_MSG_VOIP_VOPENA_CLOSE_LEN, 0x8000); + + /* Disconnect the channels */ + zt_send_cmd(wc, CMD_MSG_TRANS_CONNECT(wc->seq_num++, 0, chan1, chan2, 0, 0), CMD_MSG_TRANS_CONNECT_LEN, 0x9322); + + /* Remove the channels */ + zt_send_cmd(wc, CMD_MSG_DESTROY_CHANNEL(wc->seq_num++, chan1), CMD_MSG_DESTROY_CHANNEL_LEN, 0x0011); + zt_send_cmd(wc, CMD_MSG_DESTROY_CHANNEL(wc->seq_num++, chan2), CMD_MSG_DESTROY_CHANNEL_LEN, 0x0011); + + return 1; +} + + +static int __wcdte_setup_channels(struct wcdte *wc) +{ + wc->seq_num = 6; + +#ifndef USE_TEST_HW + zt_send_cmd(wc, CMD_MSG_SET_ARM_CLK(wc->seq_num++), CMD_MSG_SET_ARM_CLK_LEN, 0x0411); + zt_send_cmd(wc, CMD_MSG_SET_SPU_CLK(wc->seq_num++), CMD_MSG_SET_SPU_CLK_LEN, 0x0412); +#endif + +#ifdef USE_TDM_CONFIG + zt_send_cmd(wc, CMD_MSG_TDM_SELECT_BUS_MODE(wc->seq_num++), CMD_MSG_TDM_SELECT_BUS_MODE_LEN, 0x0417); + zt_send_cmd(wc, CMD_MSG_TDM_ENABLE_BUS(wc->seq_num++), CMD_MSG_TDM_ENABLE_BUS_LEN, 0x0405); + zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x03, 0x20, 0x00), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); + zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x04, 0x80, 0x04), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); + zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x05, 0x20, 0x08), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); + zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x06, 0x80, 0x0C), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); +#endif + + zt_send_cmd(wc, CMD_MSG_SET_ETH_HEADER(wc->seq_num++), CMD_MSG_SET_ETH_HEADER_LEN, 0x0100); + zt_send_cmd(wc, CMD_MSG_IP_SERVICE_CONFIG(wc->seq_num++), CMD_MSG_IP_SERVICE_CONFIG_LEN, 0x0302); + zt_send_cmd(wc, CMD_MSG_ARP_SERVICE_CONFIG(wc->seq_num++), CMD_MSG_ARP_SERVICE_CONFIG_LEN, 0x0105); + zt_send_cmd(wc, CMD_MSG_ICMP_SERVICE_CONFIG(wc->seq_num++), CMD_MSG_ICMP_SERVICE_CONFIG_LEN, 0x0304); + +#ifdef USE_TDM_CONFIG + zt_send_cmd(wc, CMD_MSG_DEVICE_SET_COUNTRY_CODE(wc->seq_num++), CMD_MSG_DEVICE_SET_COUNTRY_CODE_LEN, 0x041B); +#endif + + zt_send_cmd(wc, CMD_MSG_SPU_FEATURES_CONTROL(wc->seq_num++, 0x02), CMD_MSG_SPU_FEATURES_CONTROL_LEN, 0x0013); + zt_send_cmd(wc, CMD_MSG_IP_OPTIONS(wc->seq_num++), CMD_MSG_IP_OPTIONS_LEN, 0x0306); + zt_send_cmd(wc, CMD_MSG_SPU_FEATURES_CONTROL(wc->seq_num++, 0x04), CMD_MSG_SPU_FEATURES_CONTROL_LEN, 0x0013); + +#ifdef USE_TDM_CONFIG + zt_send_cmd(wc, CMD_MSG_TDM_OPT(wc->seq_num++), CMD_MSG_TDM_OPT_LEN, 0x0435); +#endif + + wc->timeout = HZ/10 + 1; /* 100msec */ + + return(0); +} + +static int wcdte_setup_channels(struct wcdte *wc) +{ + down(&wc->chansem); + __wcdte_setup_channels(wc); + up(&wc->chansem); + + return 0; +} + +static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int res, reg; + struct wcdte *wc; + struct wcdte_desc *d = (struct wcdte_desc *)ent->driver_data; + int x; + static int initd_ifaces=0; + unsigned char g729_numchannels, g723_numchannels, min_numchannels, dte_firmware_ver, dte_firmware_ver_minor; + unsigned int complexfmts; + + struct firmware embedded_firmware; + const struct firmware *firmware = &embedded_firmware; +#if !defined(HOTPLUG_FIRMWARE) + extern void _binary_zaptel_fw_tc400m_bin_size; + extern u8 _binary_zaptel_fw_tc400m_bin_start[]; +#else + static const char tc400m_firmware[] = "zaptel-fw-tc400m.bin"; +#endif + + if (!initd_ifaces) { + memset((void *)ifaces,0,(sizeof(struct wcdte *))*WC_MAX_IFACES); + initd_ifaces=1; + } + for (x=0;x= WC_MAX_IFACES) { + printk("wcdte: Too many interfaces\n"); + return -EIO; + } + + if (pci_enable_device(pdev)) { + res = -EIO; + } else { + + wc = vmalloc(sizeof(struct wcdte)); + if (wc) { + ifaces[x] = wc; + memset(wc, 0, sizeof(struct wcdte)); + spin_lock_init(&wc->reglock); + sema_init(&wc->chansem, 1); + sema_init(&wc->cmdqsem, 1); + wc->cards = NUM_CARDS; + wc->iobase = pci_resource_start(pdev, 0); + wc->dev = pdev; + wc->pos = x; + wc->variety = d->name; + + wc->tdbl = 0; + wc->rdbl = 0; + wc->rcvflags = 0; + wc->last_seqno = 999; + wc->last_command_sent = 0; + wc->last_rcommand = 0; + wc->last_rparm1 = 0; + wc->cmdq_wndx = 0; + wc->cmdq_rndx = 0; + wc->seq_num = 6; + wc->timeout = 1 * HZ; /* 1 sec */ + wc->dsp_crashed = 0; + wc->dumping = 0; + wc->ztsnd_rtx = 0; + wc->ztsnd_0010_rtx = 0; + + /* Keep track of whether we need to free the region */ + if (request_region(wc->iobase, 0xff, "wcdte")) + wc->freeregion = 1; + + /* Allocate enought memory for all TX buffers, RX buffers, and descriptors */ + wc->writechunk = (int *)pci_alloc_consistent(pdev, PCI_WINDOW_SIZE, &wc->writedma); + if (!wc->writechunk) { + printk("wcdte error: Unable to allocate DMA-able memory\n"); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + return -ENOMEM; + } + + wc->readchunk = wc->writechunk + (SFRAME_SIZE * ERING_SIZE) / 4; /* in doublewords */ + wc->readdma = wc->writedma + (SFRAME_SIZE * ERING_SIZE); /* in bytes */ + + wc->descripchunk = wc->readchunk + (SFRAME_SIZE * ERING_SIZE) / 4; /* in doublewords */ + wc->descripdma = wc->readdma + (SFRAME_SIZE * ERING_SIZE); /* in bytes */ + + /* Initialize Write/Buffers to all blank data */ + memset((void *)wc->writechunk,0x00, SFRAME_SIZE * 2); + memset((void *)wc->readchunk, 0x00, SFRAME_SIZE * 2); + + init_waitqueue_head(&wc->regq); + + /* Initialize the work queue */ + wc->dte_wq = create_singlethread_workqueue("tc400b"); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) + INIT_WORK(&wc->dte_work, dte_wque_run); +#else + INIT_WORK(&wc->dte_work, dte_wque_run, wc); +#endif + +#if defined(HOTPLUG_FIRMWARE) + if ((request_firmware(&firmware, tc400m_firmware, &wc->dev->dev) != 0) || + !firmware) { + printk("TC400M: firmware %s not available from userspace\n", tc400m_firmware); + return -EIO; + } +#else + embedded_firmware.data = _binary_zaptel_fw_tc400m_bin_start; + embedded_firmware.size = (size_t) &_binary_zaptel_fw_tc400m_bin_size; +#endif + + dte_firmware_ver = firmware->data[0]; + dte_firmware_ver_minor = firmware->data[16]; + g729_numchannels = firmware->data[1]; + g723_numchannels = firmware->data[2]; + + if (g723_numchannels < g729_numchannels) + min_numchannels = g723_numchannels; + else + min_numchannels = g729_numchannels; + + /* Setup Encoders and Decoders */ + + if (!mode || strlen(mode) < 4) { + sprintf(wc->complexname, "G.729a / G.723.1"); + complexfmts = ZT_FORMAT_G729A | ZT_FORMAT_G723_1; + wc->numchannels = min_numchannels; + } else if (mode[3] == '9') { /* "G.729" */ + sprintf(wc->complexname, "G.729a"); + complexfmts = ZT_FORMAT_G729A; + wc->numchannels = g729_numchannels; + } else if (mode[3] == '3') { /* "G.723.1" */ + sprintf(wc->complexname, "G.723.1"); + complexfmts = ZT_FORMAT_G723_1; + wc->numchannels = g723_numchannels; + } else { + sprintf(wc->complexname, "G.729a / G.723.1"); + complexfmts = ZT_FORMAT_G729A | ZT_FORMAT_G723_1; + wc->numchannels = min_numchannels; + } + + uencode = zt_transcoder_alloc(wc->numchannels); + udecode = zt_transcoder_alloc(wc->numchannels); + encoders = vmalloc(sizeof(struct dte_state) * wc->numchannels); + decoders = vmalloc(sizeof(struct dte_state) * wc->numchannels); + memset(encoders, 0, sizeof(struct dte_state) * wc->numchannels); + memset(decoders, 0, sizeof(struct dte_state) * wc->numchannels); + if (!uencode || !udecode || !encoders || !decoders) { + if (uencode) + zt_transcoder_free(uencode); + if (udecode) + zt_transcoder_free(udecode); + if (encoders) + vfree(encoders); + if (decoders) + vfree(decoders); + return -ENOMEM; + } + sprintf(udecode->name, "DTE Decoder"); + sprintf(uencode->name, "DTE Encoder"); + + udecode->srcfmts = uencode->dstfmts = complexfmts; + udecode->dstfmts = uencode->srcfmts = ZT_FORMAT_ULAW | ZT_FORMAT_ALAW; + + udecode->operation = uencode->operation = dte_operation; + + for (x=0;xnumchannels;x++) { + dte_init_state(encoders + x, 1, x, wc); + encoders[x].encoder = 1; + decoders[x].encoder = 0; + dte_init_state(decoders + x, 0, x, wc); + uencode->channels[x].pvt = encoders + x; + udecode->channels[x].pvt = decoders + x; + } + + wc->uencode = uencode; + wc->udecode = udecode; + + zt_transcoder_register(uencode); + zt_transcoder_register(udecode); + + printk("Zaptel DTE (%s) Transcoder support LOADED (firm ver = %d.%d)\n", wc->complexname, dte_firmware_ver, dte_firmware_ver_minor); + + + /* Enable bus mastering */ + pci_set_master(pdev); + + /* Keep track of which device we are */ + pci_set_drvdata(pdev, wc); + + if (request_irq(pdev->irq, wcdte_interrupt, ZAP_IRQ_SHARED, "tc400b", wc)) { + printk("wcdte error: Unable to request IRQ %d\n", pdev->irq); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); + pci_set_drvdata(pdev, NULL); + vfree(wc); + return -EIO; + } + + + if (wcdte_hardware_init(wc)) { + /* Set Reset Low */ + wcdte_stop_dma(wc); + /* Free Resources */ + free_irq(pdev->irq, wc); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); + pci_set_drvdata(pdev, NULL); + vfree(wc); + return -EIO; + + } + + /* Enable interrupts */ + wcdte_enable_interrupts(wc); + + /* Start DMA */ + wcdte_start_dma(wc); + + if (wcdte_boot_processor(wc,firmware,1)) { + if (firmware != &embedded_firmware) + release_firmware(firmware); + + /* Set Reset Low */ + wcdte_stop_dma(wc); + /* Free Resources */ + free_irq(pdev->irq, wc); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); + pci_set_drvdata(pdev, NULL); + vfree(wc); + return -EIO; + } + if (firmware != &embedded_firmware) + release_firmware(firmware); + + if (wcdte_setup_channels(wc)) { + /* Set Reset Low */ + wcdte_stop_dma(wc); + /* Free Resources */ + free_irq(pdev->irq, wc); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); + pci_set_drvdata(pdev, NULL); + vfree(wc); + return -EIO; + } + + reg = wcdte_getctl(wc, 0x00fc); + if (debug) + printk("wcdte debug: (post-boot) Reg fc is %08x\n", reg); + + printk("Found and successfully installed a Wildcard TC: %s \n", wc->variety); + if (debug) { + printk("TC400B operating in DEBUG mode\n"); + printk("debug_des = %d, debug_des_cnt = %d, force_alert = %d,\n debug_notimeout = %d, debug_packets = %d\n", + debug_des, debug_des_cnt, force_alert, debug_notimeout, debug_packets); + } + res = 0; + } else + res = -ENOMEM; + } + return res; +} + +static void wcdte_release(struct wcdte *wc) +{ + if (wc->freeregion) + release_region(wc->iobase, 0xff); + vfree(wc); +} + +static void __devexit wcdte_remove_one(struct pci_dev *pdev) +{ + int i; + struct wcdte *wc = pci_get_drvdata(pdev); + struct zt_transcoder_channel *ztc_en, *ztc_de; + struct dte_state *st_en, *st_de; + + if (wc) { + if (debug) + { + printk("wcdte debug: wc->ztsnd_rtx = %d\n", wc->ztsnd_rtx); + printk("wcdte debug: wc->ztsnd_0010_rtx = %d\n", wc->ztsnd_0010_rtx); + + for(i = 0; i < wc->numchannels; i++) + { + ztc_en = &(wc->uencode->channels[i]); + st_en = ztc_en->pvt; + + ztc_de = &(wc->udecode->channels[i]); + st_de = ztc_de->pvt; + + printk("wcdte debug: en[%d] snt = %d, rcv = %d [%d]\n", i, st_en->packets_sent, st_en->packets_received, st_en->packets_sent - st_en->packets_received); + printk("wcdte debug: de[%d] snt = %d, rcv = %d [%d]\n", i, st_de->packets_sent, st_de->packets_received, st_de->packets_sent - st_de->packets_received); + } + } + + zt_transcoder_unregister(wc->udecode); + zt_transcoder_unregister(wc->uencode); + zt_transcoder_free(wc->uencode); + zt_transcoder_free(wc->udecode); + vfree(wc->uencode->channels[0].pvt); + vfree(wc->udecode->channels[0].pvt); + + /* Stop any DMA */ + wcdte_stop_dma(wc); + + /* In case hardware is still there */ + wcdte_disable_interrupts(wc); + + /* Kill workqueue */ + destroy_workqueue(wc->dte_wq); + + /* Immediately free resources */ + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); + free_irq(pdev->irq, wc); + + /* Release span, possibly delayed */ + wcdte_release(wc); + } +} + +static struct pci_device_id wcdte_pci_tbl[] = { +#ifndef USE_TEST_HW + { 0xd161, 0x3400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctc400p }, /* Digium board */ + { 0xd161, 0x8004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctce400 }, /* Digium board */ +#else + { 0x1317, 0x0985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctc400p }, /* reference board */ +#endif + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, wcdte_pci_tbl); + +static struct pci_driver wcdte_driver = { + name: "wctc4xxp", + probe: wcdte_init_one, + remove: __devexit_p(wcdte_remove_one), + suspend: NULL, + resume: NULL, + id_table: wcdte_pci_tbl, +}; + +int ztdte_init(void) +{ + int res; + + res = zap_pci_module(&wcdte_driver); + if (res) + return -ENODEV; + return 0; +} + +void ztdte_cleanup(void) +{ + pci_unregister_driver(&wcdte_driver); +} + +module_param(debug, int, S_IRUGO | S_IWUSR); +module_param(debug_des, int, S_IRUGO | S_IWUSR); +module_param(debug_des_cnt, int, S_IRUGO | S_IWUSR); +module_param(debug_notimeout, int, S_IRUGO | S_IWUSR); +module_param(force_alert, int, S_IRUGO | S_IWUSR); +module_param(mode, charp, S_IRUGO | S_IWUSR); +MODULE_DESCRIPTION("Wildcard TC400P+TC400M Driver"); +MODULE_AUTHOR("John Sloan "); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +module_init(ztdte_init); +module_exit(ztdte_cleanup); diff --git a/kernel/wctc4xxp/codec_test.c b/kernel/wctc4xxp/codec_test.c new file mode 100644 index 0000000..287979d --- /dev/null +++ b/kernel/wctc4xxp/codec_test.c @@ -0,0 +1,332 @@ +/* + * Wilcard TC400B Digium Transcoder Engine Interface Driver for Zapata Telephony interface test tool. + * + * Written by Matt O'Gorman + * + * Copyright (C) 2006-2007, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef STANDALONE_ZAPATA +#include "zaptel.h" +#else +#include +#endif + +#define MAX_CARDS_TO_TEST 6 +#define MAX_CHANNELS_PER_CARD 96 + +#define AST_FORMAT_ULAW (1 << 2) +#define AST_FORMAT_G729A (1 << 8) + +#define AST_FRIENDLY_OFFSET 64 + +static int debug = 0; + +static unsigned char ulaw_slin_ex[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned char g729a_expected[] = { + 0xE9, 0x88, 0x4C, 0xA0, 0x00, 0xFA, 0xDD, 0xA2, 0x06, 0x2D, + 0x69, 0x88, 0x00, 0x60, 0x68, 0xD5, 0x9E, 0x20, 0x80, 0x50 +}; + + +struct format_map { + unsigned int map[32][32]; +}; + + +struct tcpvt { + int fd; + int fake; + int inuse; + struct zt_transcode_header *hdr; +// struct ast_frame f; +}; + +struct tctest_info { + int numcards; + int numchans[MAX_CARDS_TO_TEST]; + int total_chans; + int errors; + int overcnt_error; /* Too many cards found */ + int undercnt_error; /* Too few cards found */ + int timeout_error[MAX_CARDS_TO_TEST]; + int data_error[MAX_CARDS_TO_TEST]; + int numcards_werrors; +}; + + +static int find_transcoders(struct tctest_info *tctest_info) +{ + struct zt_transcode_info info = { 0, }; + int fd, res; + + if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0) { + printf("Warning: No Zaptel transcoder support!\n"); + return 0; + } + + tctest_info->total_chans = 0; + info.op = ZT_TCOP_GETINFO; + for (info.tcnum = 0; !(res = ioctl(fd, ZT_TRANSCODE_OP, &info)); info.tcnum++) { + if (debug) + printf("Found transcoder %d, '%s' with %d channels.\n", info.tcnum, info.name, info.numchannels); + if ((info.tcnum % 2) == 0) + { + tctest_info->numchans[info.tcnum/2] = info.numchannels; + tctest_info->total_chans += info.numchannels; + } + } + tctest_info->numcards = info.tcnum / 2; + + close(fd); + if (!info.tcnum) + printf("No hardware transcoders found.\n"); + return 0; +} + + +static int open_transcoder(struct tcpvt *ztp, int dest, int source) +{ + int fd; + unsigned int x = ZT_TCOP_ALLOCATE; + struct zt_transcode_header *hdr; + int flags; + + if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0) + return -1; + flags = fcntl(fd, F_GETFL); + if (flags > - 1) { + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) + printf("Could not set non-block mode!\n"); + } + + if ((hdr = mmap(NULL, sizeof(*hdr), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { + printf("Memory Map failed for transcoding (%s)\n", strerror(errno)); + close(fd); + + return -1; + } + + if (hdr->magic != ZT_TRANSCODE_MAGIC) { + printf("Transcoder header (%08x) wasn't magic. Abandoning\n", hdr->magic); + munmap(hdr, sizeof(*hdr)); + close(fd); + + return -1; + } + + hdr->srcfmt = source; + hdr->dstfmt = dest; + + if (ioctl(fd, ZT_TRANSCODE_OP, &x)) { + printf("Unable to attach transcoder: %s\n", strerror(errno)); + munmap(hdr, sizeof(*hdr)); + close(fd); + + return -1; + } + + ztp->fd = fd; + ztp->hdr = hdr; + + return 0; +} + + +static void close_transcoder(struct tcpvt *ztp) +{ + unsigned int x; + + x = ZT_TCOP_RELEASE; + if (ioctl(ztp->fd, ZT_TRANSCODE_OP, &x)) + printf("Failed to release transcoder channel: %s\n", strerror(errno)); + + munmap(ztp->hdr, sizeof(*ztp->hdr)); + close(ztp->fd); +} + + +static int encode_packet(struct tcpvt *ztp, unsigned char *packet_in, unsigned char *packet_out) +{ + struct zt_transcode_header *hdr = ztp->hdr; + unsigned int x; + + hdr->srcoffset = 0; + + memcpy(hdr->srcdata + hdr->srcoffset + hdr->srclen, packet_in, 160); + hdr->srclen += 160; + + + hdr->dstoffset = AST_FRIENDLY_OFFSET; + x = ZT_TCOP_TRANSCODE; + if (ioctl(ztp->fd, ZT_TRANSCODE_OP, &x)) + printf("Failed to transcode: %s\n", strerror(errno)); + + usleep(20000); + if (hdr->dstlen) + { + memcpy(packet_out, hdr->dstdata + hdr->dstoffset, hdr->dstlen); + return 0; + } + else + return -1; +} + + +static void print_failed() +{ + printf("______ ___ _____ _ _____ ______\n"); + printf("| ___| / _ \\ |_ _| | | | ___| | _ \\\n"); + printf("| |_ / /_\\ \\ | | | | | |__ | | | |\n"); + printf("| _| | _ | | | | | | __| | | | |\n"); + printf("| | | | | | _| |_ | |____ | |___ | |/ /\n"); + printf("\\_| \\_| |_/ \\___/ \\_____/ \\____/ |___/ \n"); +} + + +int main(int argc, char *argv[]) +{ + int arg1, arg2, i, j, card_testing, chan_testing; + struct tcpvt ztp[MAX_CHANNELS_PER_CARD * MAX_CARDS_TO_TEST]; + unsigned char packet_out[200]; + struct tctest_info tctest_info; + + memset(&tctest_info, 0, sizeof(tctest_info)); + + if ((argc < 2) || (argc > 3)) + { + printf("codec_test requires one argument.\n"); + printf(" arg1 = number of cards to test\n"); + return -1; + } + + if (argc == 2) + sscanf(argv[1], "%d", &arg1); + else if (argc == 3) + { + sscanf(argv[1], "%d %d", &arg1, &arg2); + debug = arg2; + } + + printf("Beginning test of %d TC400B cards\n", arg1); + + + /* Search for TC400Bs */ + find_transcoders(&tctest_info); + + if (tctest_info.numcards > arg1) + { + tctest_info.errors++; + tctest_info.overcnt_error = 1; + } + if (tctest_info.numcards < arg1) + { + tctest_info.errors++; + tctest_info.undercnt_error = 1; + } + + if (tctest_info.errors == 0) + { + /* Begin testing transcoder channels */ + for (card_testing = 0; card_testing < tctest_info.numcards; card_testing++) + { + tctest_info.data_error[card_testing] = 0; + tctest_info.timeout_error[card_testing] = 0; + for (chan_testing = 0; chan_testing < tctest_info.numchans[card_testing]; chan_testing++) + { + i = chan_testing; + for(j = 0; j < card_testing; j++) + i += tctest_info.numchans[j]; + + open_transcoder(&ztp[i], AST_FORMAT_G729A, AST_FORMAT_ULAW); + + if ((tctest_info.timeout_error[card_testing] = encode_packet(&ztp[i], ulaw_slin_ex, packet_out) == -1)) + tctest_info.errors++; + + if (memcmp(g729a_expected, packet_out, 20) != 0) + { + tctest_info.errors++; + tctest_info.data_error[card_testing] += 1; + } + } + if ( (tctest_info.data_error[card_testing]) || (tctest_info.timeout_error[card_testing]) ) + tctest_info.numcards_werrors++; + } + + for (i = 0; i < tctest_info.total_chans; i++) + close_transcoder(&ztp[i]); + } + + if (debug) + { + printf("\n\n"); + printf("tctest_info.errors = %d\n", tctest_info.errors); + printf("tctest_info.overcnt_error = %d\n", tctest_info.overcnt_error); + printf("tctest_info.undercnt_error = %d\n", tctest_info.undercnt_error); + printf("tctest_info.numcards_werrors = %d\n", tctest_info.numcards_werrors); + + for (i = 0; i < tctest_info.numcards; i++) + { + printf("tctest_info.data_error[%d] = %d\n", i, tctest_info.data_error[i]); + printf("tctest_info.timeout_error[%d] = %d\n", i, tctest_info.timeout_error[i]); + } + } + + if (tctest_info.errors) + { + printf("\n\n\n"); + if (tctest_info.numcards_werrors) + printf("%d of %d cards\n", tctest_info.numcards_werrors, tctest_info.numcards); + print_failed(); + if (tctest_info.overcnt_error) + printf("\n%d cards found, %d expected\n", tctest_info.numcards, arg1); + if (tctest_info.undercnt_error) + printf("\n%d cards found, %d expected\n", tctest_info.numcards, arg1); + printf("\n\n\n"); + } + else + printf("%d of %d cards PASSED\n", tctest_info.numcards - tctest_info.numcards_werrors, tctest_info.numcards); + + return 0; +} diff --git a/kernel/wctdm.c b/kernel/wctdm.c new file mode 100644 index 0000000..68a21e7 --- /dev/null +++ b/kernel/wctdm.c @@ -0,0 +1,2602 @@ +/* + * Wilcard TDM400P TDM FXS/FXO Interface Driver for Zapata Telephony interface + * + * Written by Mark Spencer + * Matthew Fredrickson + * + * Copyright (C) 2001, Linux Support Services, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "proslic.h" +#include "wctdm.h" +/* + * Define for audio vs. register based ring detection + * + */ +/* #define AUDIO_RINGCHECK */ + +/* + Experimental max loop current limit for the proslic + Loop current limit is from 20 mA to 41 mA in steps of 3 + (according to datasheet) + So set the value below to: + 0x00 : 20mA (default) + 0x01 : 23mA + 0x02 : 26mA + 0x03 : 29mA + 0x04 : 32mA + 0x05 : 35mA + 0x06 : 37mA + 0x07 : 41mA +*/ +static int loopcurrent = 20; + +static int reversepolarity = 0; + +static alpha indirect_regs[] = +{ +{0,255,"DTMF_ROW_0_PEAK",0x55C2}, +{1,255,"DTMF_ROW_1_PEAK",0x51E6}, +{2,255,"DTMF_ROW2_PEAK",0x4B85}, +{3,255,"DTMF_ROW3_PEAK",0x4937}, +{4,255,"DTMF_COL1_PEAK",0x3333}, +{5,255,"DTMF_FWD_TWIST",0x0202}, +{6,255,"DTMF_RVS_TWIST",0x0202}, +{7,255,"DTMF_ROW_RATIO_TRES",0x0198}, +{8,255,"DTMF_COL_RATIO_TRES",0x0198}, +{9,255,"DTMF_ROW_2ND_ARM",0x0611}, +{10,255,"DTMF_COL_2ND_ARM",0x0202}, +{11,255,"DTMF_PWR_MIN_TRES",0x00E5}, +{12,255,"DTMF_OT_LIM_TRES",0x0A1C}, +{13,0,"OSC1_COEF",0x7B30}, +{14,1,"OSC1X",0x0063}, +{15,2,"OSC1Y",0x0000}, +{16,3,"OSC2_COEF",0x7870}, +{17,4,"OSC2X",0x007D}, +{18,5,"OSC2Y",0x0000}, +{19,6,"RING_V_OFF",0x0000}, +{20,7,"RING_OSC",0x7EF0}, +{21,8,"RING_X",0x0160}, +{22,9,"RING_Y",0x0000}, +{23,255,"PULSE_ENVEL",0x2000}, +{24,255,"PULSE_X",0x2000}, +{25,255,"PULSE_Y",0x0000}, +//{26,13,"RECV_DIGITAL_GAIN",0x4000}, // playback volume set lower +{26,13,"RECV_DIGITAL_GAIN",0x2000}, // playback volume set lower +{27,14,"XMIT_DIGITAL_GAIN",0x4000}, +//{27,14,"XMIT_DIGITAL_GAIN",0x2000}, +{28,15,"LOOP_CLOSE_TRES",0x1000}, +{29,16,"RING_TRIP_TRES",0x3600}, +{30,17,"COMMON_MIN_TRES",0x1000}, +{31,18,"COMMON_MAX_TRES",0x0200}, +{32,19,"PWR_ALARM_Q1Q2",0x07C0}, +{33,20,"PWR_ALARM_Q3Q4",0x2600}, +{34,21,"PWR_ALARM_Q5Q6",0x1B80}, +{35,22,"LOOP_CLOSURE_FILTER",0x8000}, +{36,23,"RING_TRIP_FILTER",0x0320}, +{37,24,"TERM_LP_POLE_Q1Q2",0x008C}, +{38,25,"TERM_LP_POLE_Q3Q4",0x0100}, +{39,26,"TERM_LP_POLE_Q5Q6",0x0010}, +{40,27,"CM_BIAS_RINGING",0x0C00}, +{41,64,"DCDC_MIN_V",0x0C00}, +{42,255,"DCDC_XTRA",0x1000}, +{43,66,"LOOP_CLOSE_TRES_LOW",0x1000}, +}; + +static struct fxo_mode { + char *name; + /* FXO */ + int ohs; + int ohs2; + int rz; + int rt; + int ilim; + int dcv; + int mini; + int acim; + int ring_osc; + int ring_x; +} fxo_modes[] = +{ + { "FCC", 0, 0, 0, 1, 0, 0x3, 0, 0, }, /* US, Canada */ + { "TBR21", 0, 0, 0, 0, 1, 0x3, 0, 0x2, 0x7e6c, 0x023a, }, + /* Austria, Belgium, Denmark, Finland, France, Germany, + Greece, Iceland, Ireland, Italy, Luxembourg, Netherlands, + Norway, Portugal, Spain, Sweden, Switzerland, and UK */ + { "ARGENTINA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "AUSTRALIA", 1, 0, 0, 0, 0, 0, 0x3, 0x3, }, + { "AUSTRIA", 0, 1, 0, 0, 1, 0x3, 0, 0x3, }, + { "BAHRAIN", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "BELGIUM", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "BRAZIL", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "BULGARIA", 0, 0, 0, 0, 1, 0x3, 0x0, 0x3, }, + { "CANADA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "CHILE", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "CHINA", 0, 0, 0, 0, 0, 0, 0x3, 0xf, }, + { "COLUMBIA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "CROATIA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "CYRPUS", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "CZECH", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "DENMARK", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "ECUADOR", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "EGYPT", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "ELSALVADOR", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "FINLAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "FRANCE", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "GERMANY", 0, 1, 0, 0, 1, 0x3, 0, 0x3, }, + { "GREECE", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "GUAM", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "HONGKONG", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "HUNGARY", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "ICELAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "INDIA", 0, 0, 0, 0, 0, 0x3, 0, 0x4, }, + { "INDONESIA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "IRELAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "ISRAEL", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "ITALY", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "JAPAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "JORDAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "KAZAKHSTAN", 0, 0, 0, 0, 0, 0x3, 0, }, + { "KUWAIT", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "LATVIA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "LEBANON", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "LUXEMBOURG", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "MACAO", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "MALAYSIA", 0, 0, 0, 0, 0, 0, 0x3, 0, }, /* Current loop >= 20ma */ + { "MALTA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "MEXICO", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "MOROCCO", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "NETHERLANDS", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "NEWZEALAND", 0, 0, 0, 0, 0, 0x3, 0, 0x4, }, + { "NIGERIA", 0, 0, 0, 0, 0x1, 0x3, 0, 0x2, }, + { "NORWAY", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "OMAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "PAKISTAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "PERU", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "PHILIPPINES", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "POLAND", 0, 0, 1, 1, 0, 0x3, 0, 0, }, + { "PORTUGAL", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "ROMANIA", 0, 0, 0, 0, 0, 3, 0, 0, }, + { "RUSSIA", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "SAUDIARABIA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "SINGAPORE", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "SLOVAKIA", 0, 0, 0, 0, 0, 0x3, 0, 0x3, }, + { "SLOVENIA", 0, 0, 0, 0, 0, 0x3, 0, 0x2, }, + { "SOUTHAFRICA", 1, 0, 1, 0, 0, 0x3, 0, 0x3, }, + { "SOUTHKOREA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "SPAIN", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "SWEDEN", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "SWITZERLAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "SYRIA", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "TAIWAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "THAILAND", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "UAE", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "UK", 0, 1, 0, 0, 1, 0x3, 0, 0x5, }, + { "USA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "YEMEN", 0, 0, 0, 0, 0, 0x3, 0, 0, }, +}; + +#include "zaptel.h" + +#ifdef LINUX26 +#include +#endif + +#define NUM_FXO_REGS 60 + +#define WC_MAX_IFACES 128 + +#define WC_CNTL 0x00 +#define WC_OPER 0x01 +#define WC_AUXC 0x02 +#define WC_AUXD 0x03 +#define WC_MASK0 0x04 +#define WC_MASK1 0x05 +#define WC_INTSTAT 0x06 +#define WC_AUXR 0x07 + +#define WC_DMAWS 0x08 +#define WC_DMAWI 0x0c +#define WC_DMAWE 0x10 +#define WC_DMARS 0x18 +#define WC_DMARI 0x1c +#define WC_DMARE 0x20 + +#define WC_AUXFUNC 0x2b +#define WC_SERCTL 0x2d +#define WC_FSCDELAY 0x2f + +#define WC_REGBASE 0xc0 + +#define WC_SYNC 0x0 +#define WC_TEST 0x1 +#define WC_CS 0x2 +#define WC_VER 0x3 + +#define BIT_CS (1 << 2) +#define BIT_SCLK (1 << 3) +#define BIT_SDI (1 << 4) +#define BIT_SDO (1 << 5) + +#define FLAG_EMPTY 0 +#define FLAG_WRITE 1 +#define FLAG_READ 2 + +#define DEFAULT_RING_DEBOUNCE 64 /* Ringer Debounce (64 ms) */ + +/* the constants below control the 'debounce' periods enforced by the + check_hook routines; these routines are called once every 4 interrupts + (the interrupt cycles around the four modules), so the periods are + specified in _4 millisecond_ increments +*/ +#define DEFAULT_BATT_DEBOUNCE 4 /* Battery debounce (64 ms) */ +#define POLARITY_DEBOUNCE 4 /* Polarity debounce (64 ms) */ +#define DEFAULT_BATT_THRESH 3 /* Anything under this is "no battery" */ + +#define OHT_TIMER 6000 /* How long after RING to retain OHT */ + +#define FLAG_3215 (1 << 0) + +#define NUM_CARDS 4 + +#define MAX_ALARMS 10 + +#define MOD_TYPE_FXS 0 +#define MOD_TYPE_FXO 1 + +#define MINPEGTIME 10 * 8 /* 30 ms peak to peak gets us no more than 100 Hz */ +#define PEGTIME 50 * 8 /* 50ms peak to peak gets us rings of 10 Hz or more */ +#define PEGCOUNT 5 /* 5 cycles of pegging means RING */ + +#define NUM_CAL_REGS 12 + +struct calregs { + unsigned char vals[NUM_CAL_REGS]; +}; + +enum proslic_power_warn { + PROSLIC_POWER_UNKNOWN = 0, + PROSLIC_POWER_ON, + PROSLIC_POWER_WARNED, +}; + +struct wctdm { + struct pci_dev *dev; + char *variety; + struct zt_span span; + unsigned char ios; + int usecount; + unsigned int intcount; + int dead; + int pos; + int flags[NUM_CARDS]; + int freeregion; + int alt; + int curcard; + int cardflag; /* Bit-map of present cards */ + enum proslic_power_warn proslic_power; + spinlock_t lock; + + union { + struct { +#ifdef AUDIO_RINGCHECK + unsigned int pegtimer; + int pegcount; + int peg; + int ring; +#else + int wasringing; + int lastrdtx; +#endif + int ringdebounce; + int offhook; + int battdebounce; + int nobatttimer; + int battery; + int lastpol; + int polarity; + int polaritydebounce; + } fxo; + struct { + int oldrxhook; + int debouncehook; + int lastrxhook; + int debounce; + int ohttimer; + int idletxhookstate; /* IDLE changing hook state */ + int lasttxhook; + int palarms; + struct calregs calregs; + } fxs; + } mod[NUM_CARDS]; + + /* Receive hook state and debouncing */ + int modtype[NUM_CARDS]; + unsigned char reg0shadow[NUM_CARDS]; + unsigned char reg1shadow[NUM_CARDS]; + + unsigned long ioaddr; + dma_addr_t readdma; + dma_addr_t writedma; + volatile unsigned int *writechunk; /* Double-word aligned write memory */ + volatile unsigned int *readchunk; /* Double-word aligned read memory */ + struct zt_chan chans[NUM_CARDS]; +}; + + +struct wctdm_desc { + char *name; + int flags; +}; + +static struct wctdm_desc wctdm = { "Wildcard S400P Prototype", 0 }; +static struct wctdm_desc wctdme = { "Wildcard TDM400P REV E/F", 0 }; +static struct wctdm_desc wctdmh = { "Wildcard TDM400P REV H", 0 }; +static struct wctdm_desc wctdmi = { "Wildcard TDM400P REV I", 0 }; +static int acim2tiss[16] = { 0x0, 0x1, 0x4, 0x5, 0x7, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0, 0x3 }; + +static struct wctdm *ifaces[WC_MAX_IFACES]; + +static void wctdm_release(struct wctdm *wc); + +static int battdebounce = DEFAULT_BATT_DEBOUNCE; +static int battthresh = DEFAULT_BATT_THRESH; +static int ringdebounce = DEFAULT_RING_DEBOUNCE; +static int fwringdetect = 0; +static int debug = 0; +static int robust = 0; +static int timingonly = 0; +static int lowpower = 0; +static int boostringer = 0; +static int fastringer = 0; +static int _opermode = 0; +static char *opermode = "FCC"; +static int fxshonormode = 0; +static int alawoverride = 0; +static int fastpickup = 0; +static int fxotxgain = 0; +static int fxorxgain = 0; +static int fxstxgain = 0; +static int fxsrxgain = 0; + +static int wctdm_init_proslic(struct wctdm *wc, int card, int fast , int manual, int sane); + +static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char ints) +{ + volatile unsigned int *writechunk; + int x; + if (ints & 0x01) + /* Write is at interrupt address. Start writing from normal offset */ + writechunk = wc->writechunk; + else + writechunk = wc->writechunk + ZT_CHUNKSIZE; + /* Calculate Transmission */ + zt_transmit(&wc->span); + + for (x=0;xcardflag & (1 << 3)) + writechunk[x] |= (wc->chans[3].writechunk[x]); + if (wc->cardflag & (1 << 2)) + writechunk[x] |= (wc->chans[2].writechunk[x] << 8); + if (wc->cardflag & (1 << 1)) + writechunk[x] |= (wc->chans[1].writechunk[x] << 16); + if (wc->cardflag & (1 << 0)) + writechunk[x] |= (wc->chans[0].writechunk[x] << 24); +#else + if (wc->cardflag & (1 << 3)) + writechunk[x] |= (wc->chans[3].writechunk[x] << 24); + if (wc->cardflag & (1 << 2)) + writechunk[x] |= (wc->chans[2].writechunk[x] << 16); + if (wc->cardflag & (1 << 1)) + writechunk[x] |= (wc->chans[1].writechunk[x] << 8); + if (wc->cardflag & (1 << 0)) + writechunk[x] |= (wc->chans[0].writechunk[x]); +#endif + } + +} + +#ifdef AUDIO_RINGCHECK +static inline void ring_check(struct wctdm *wc, int card) +{ + int x; + short sample; + if (wc->modtype[card] != MOD_TYPE_FXO) + return; + wc->mod[card].fxo.pegtimer += ZT_CHUNKSIZE; + for (x=0;xchans[card].readchunk[x], (&(wc->chans[card]))); + if ((sample > 10000) && (wc->mod[card].fxo.peg != 1)) { + if (debug > 1) printk("High peg!\n"); + if ((wc->mod[card].fxo.pegtimer < PEGTIME) && (wc->mod[card].fxo.pegtimer > MINPEGTIME)) + wc->mod[card].fxo.pegcount++; + wc->mod[card].fxo.pegtimer = 0; + wc->mod[card].fxo.peg = 1; + } else if ((sample < -10000) && (wc->mod[card].fxo.peg != -1)) { + if (debug > 1) printk("Low peg!\n"); + if ((wc->mod[card].fxo.pegtimer < (PEGTIME >> 2)) && (wc->mod[card].fxo.pegtimer > (MINPEGTIME >> 2))) + wc->mod[card].fxo.pegcount++; + wc->mod[card].fxo.pegtimer = 0; + wc->mod[card].fxo.peg = -1; + } + } + if (wc->mod[card].fxo.pegtimer > PEGTIME) { + /* Reset pegcount if our timer expires */ + wc->mod[card].fxo.pegcount = 0; + } + /* Decrement debouncer if appropriate */ + if (wc->mod[card].fxo.ringdebounce) + wc->mod[card].fxo.ringdebounce--; + if (!wc->mod[card].fxo.offhook && !wc->mod[card].fxo.ringdebounce) { + if (!wc->mod[card].fxo.ring && (wc->mod[card].fxo.pegcount > PEGCOUNT)) { + /* It's ringing */ + if (debug) + printk("RING on %d/%d!\n", wc->span.spanno, card + 1); + if (!wc->mod[card].fxo.offhook) + zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); + wc->mod[card].fxo.ring = 1; + } + if (wc->mod[card].fxo.ring && !wc->mod[card].fxo.pegcount) { + /* No more ring */ + if (debug) + printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); + zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); + wc->mod[card].fxo.ring = 0; + } + } +} +#endif +static inline void wctdm_receiveprep(struct wctdm *wc, unsigned char ints) +{ + volatile unsigned int *readchunk; + int x; + + if (ints & 0x08) + readchunk = wc->readchunk + ZT_CHUNKSIZE; + else + /* Read is at interrupt address. Valid data is available at normal offset */ + readchunk = wc->readchunk; + for (x=0;xcardflag & (1 << 3)) + wc->chans[3].readchunk[x] = (readchunk[x]) & 0xff; + if (wc->cardflag & (1 << 2)) + wc->chans[2].readchunk[x] = (readchunk[x] >> 8) & 0xff; + if (wc->cardflag & (1 << 1)) + wc->chans[1].readchunk[x] = (readchunk[x] >> 16) & 0xff; + if (wc->cardflag & (1 << 0)) + wc->chans[0].readchunk[x] = (readchunk[x] >> 24) & 0xff; +#else + if (wc->cardflag & (1 << 3)) + wc->chans[3].readchunk[x] = (readchunk[x] >> 24) & 0xff; + if (wc->cardflag & (1 << 2)) + wc->chans[2].readchunk[x] = (readchunk[x] >> 16) & 0xff; + if (wc->cardflag & (1 << 1)) + wc->chans[1].readchunk[x] = (readchunk[x] >> 8) & 0xff; + if (wc->cardflag & (1 << 0)) + wc->chans[0].readchunk[x] = (readchunk[x]) & 0xff; +#endif + } +#ifdef AUDIO_RINGCHECK + for (x=0;xcards;x++) + ring_check(wc, x); +#endif + /* XXX We're wasting 8 taps. We should get closer :( */ + for (x = 0; x < NUM_CARDS; x++) { + if (wc->cardflag & (1 << x)) + zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->chans[x].writechunk); + } + zt_receive(&wc->span); +} + +static void wctdm_stop_dma(struct wctdm *wc); +static void wctdm_reset_tdm(struct wctdm *wc); +static void wctdm_restart_dma(struct wctdm *wc); + +static inline void __write_8bits(struct wctdm *wc, unsigned char bits) +{ + /* Drop chip select */ + int x; + wc->ios |= BIT_SCLK; + outb(wc->ios, wc->ioaddr + WC_AUXD); + wc->ios &= ~BIT_CS; + outb(wc->ios, wc->ioaddr + WC_AUXD); + for (x=0;x<8;x++) { + /* Send out each bit, MSB first, drop SCLK as we do so */ + if (bits & 0x80) + wc->ios |= BIT_SDI; + else + wc->ios &= ~BIT_SDI; + wc->ios &= ~BIT_SCLK; + outb(wc->ios, wc->ioaddr + WC_AUXD); + /* Now raise SCLK high again and repeat */ + wc->ios |= BIT_SCLK; + outb(wc->ios, wc->ioaddr + WC_AUXD); + bits <<= 1; + } + /* Finally raise CS back high again */ + wc->ios |= BIT_CS; + outb(wc->ios, wc->ioaddr + WC_AUXD); + +} + +static inline void __reset_spi(struct wctdm *wc) +{ + /* Drop chip select and clock once and raise and clock once */ + wc->ios |= BIT_SCLK; + outb(wc->ios, wc->ioaddr + WC_AUXD); + wc->ios &= ~BIT_CS; + outb(wc->ios, wc->ioaddr + WC_AUXD); + wc->ios |= BIT_SDI; + wc->ios &= ~BIT_SCLK; + outb(wc->ios, wc->ioaddr + WC_AUXD); + /* Now raise SCLK high again and repeat */ + wc->ios |= BIT_SCLK; + outb(wc->ios, wc->ioaddr + WC_AUXD); + /* Finally raise CS back high again */ + wc->ios |= BIT_CS; + outb(wc->ios, wc->ioaddr + WC_AUXD); + /* Clock again */ + wc->ios &= ~BIT_SCLK; + outb(wc->ios, wc->ioaddr + WC_AUXD); + /* Now raise SCLK high again and repeat */ + wc->ios |= BIT_SCLK; + outb(wc->ios, wc->ioaddr + WC_AUXD); + +} + +static inline unsigned char __read_8bits(struct wctdm *wc) +{ + unsigned char res=0, c; + int x; + wc->ios |= BIT_SCLK; + outb(wc->ios, wc->ioaddr + WC_AUXD); + /* Drop chip select */ + wc->ios &= ~BIT_CS; + outb(wc->ios, wc->ioaddr + WC_AUXD); + for (x=0;x<8;x++) { + res <<= 1; + /* Get SCLK */ + wc->ios &= ~BIT_SCLK; + outb(wc->ios, wc->ioaddr + WC_AUXD); + /* Read back the value */ + c = inb(wc->ioaddr + WC_AUXR); + if (c & BIT_SDO) + res |= 1; + /* Now raise SCLK high again */ + wc->ios |= BIT_SCLK; + outb(wc->ios, wc->ioaddr + WC_AUXD); + } + /* Finally raise CS back high again */ + wc->ios |= BIT_CS; + outb(wc->ios, wc->ioaddr + WC_AUXD); + wc->ios &= ~BIT_SCLK; + outb(wc->ios, wc->ioaddr + WC_AUXD); + + /* And return our result */ + return res; +} + +static void __wctdm_setcreg(struct wctdm *wc, unsigned char reg, unsigned char val) +{ + outb(val, wc->ioaddr + WC_REGBASE + ((reg & 0xf) << 2)); +} + +static unsigned char __wctdm_getcreg(struct wctdm *wc, unsigned char reg) +{ + return inb(wc->ioaddr + WC_REGBASE + ((reg & 0xf) << 2)); +} + +static inline void __wctdm_setcard(struct wctdm *wc, int card) +{ + if (wc->curcard != card) { + __wctdm_setcreg(wc, WC_CS, (1 << card)); + wc->curcard = card; + } +} + +static void __wctdm_setreg(struct wctdm *wc, int card, unsigned char reg, unsigned char value) +{ + __wctdm_setcard(wc, card); + if (wc->modtype[card] == MOD_TYPE_FXO) { + __write_8bits(wc, 0x20); + __write_8bits(wc, reg & 0x7f); + } else { + __write_8bits(wc, reg & 0x7f); + } + __write_8bits(wc, value); +} + +static void wctdm_setreg(struct wctdm *wc, int card, unsigned char reg, unsigned char value) +{ + unsigned long flags; + spin_lock_irqsave(&wc->lock, flags); + __wctdm_setreg(wc, card, reg, value); + spin_unlock_irqrestore(&wc->lock, flags); +} + +static unsigned char __wctdm_getreg(struct wctdm *wc, int card, unsigned char reg) +{ + __wctdm_setcard(wc, card); + if (wc->modtype[card] == MOD_TYPE_FXO) { + __write_8bits(wc, 0x60); + __write_8bits(wc, reg & 0x7f); + } else { + __write_8bits(wc, reg | 0x80); + } + return __read_8bits(wc); +} + +static inline void reset_spi(struct wctdm *wc, int card) +{ + unsigned long flags; + spin_lock_irqsave(&wc->lock, flags); + __wctdm_setcard(wc, card); + __reset_spi(wc); + __reset_spi(wc); + spin_unlock_irqrestore(&wc->lock, flags); +} + +static unsigned char wctdm_getreg(struct wctdm *wc, int card, unsigned char reg) +{ + unsigned long flags; + unsigned char res; + spin_lock_irqsave(&wc->lock, flags); + res = __wctdm_getreg(wc, card, reg); + spin_unlock_irqrestore(&wc->lock, flags); + return res; +} + +static int __wait_access(struct wctdm *wc, int card) +{ + unsigned char data = 0; + long origjiffies; + int count = 0; + + #define MAX 6000 /* attempts */ + + + origjiffies = jiffies; + /* Wait for indirect access */ + while (count++ < MAX) + { + data = __wctdm_getreg(wc, card, I_STATUS); + + if (!data) + return 0; + + } + + if(count > (MAX-1)) printk(" ##### Loop error (%02x) #####\n", data); + + return 0; +} + +static unsigned char translate_3215(unsigned char address) +{ + int x; + for (x=0;xflags[card] & FLAG_3215) { + address = translate_3215(address); + if (address == 255) + return 0; + } + spin_lock_irqsave(&wc->lock, flags); + if(!__wait_access(wc, card)) { + __wctdm_setreg(wc, card, IDA_LO,(unsigned char)(data & 0xFF)); + __wctdm_setreg(wc, card, IDA_HI,(unsigned char)((data & 0xFF00)>>8)); + __wctdm_setreg(wc, card, IAA,address); + res = 0; + }; + spin_unlock_irqrestore(&wc->lock, flags); + return res; +} + +static int wctdm_proslic_getreg_indirect(struct wctdm *wc, int card, unsigned char address) +{ + unsigned long flags; + int res = -1; + char *p=NULL; + /* Translate 3215 addresses */ + if (wc->flags[card] & FLAG_3215) { + address = translate_3215(address); + if (address == 255) + return 0; + } + spin_lock_irqsave(&wc->lock, flags); + if (!__wait_access(wc, card)) { + __wctdm_setreg(wc, card, IAA, address); + if (!__wait_access(wc, card)) { + unsigned char data1, data2; + data1 = __wctdm_getreg(wc, card, IDA_LO); + data2 = __wctdm_getreg(wc, card, IDA_HI); + res = data1 | (data2 << 8); + } else + p = "Failed to wait inside\n"; + } else + p = "failed to wait\n"; + spin_unlock_irqrestore(&wc->lock, flags); + if (p) + printk(p); + return res; +} + +static int wctdm_proslic_init_indirect_regs(struct wctdm *wc, int card) +{ + unsigned char i; + + for (i=0; iflags[card] & FLAG_3215) || (indirect_regs[i].altaddr != 255))) + { + printk("!!!!!!! %s iREG %X = %X should be %X\n", + indirect_regs[i].name,indirect_regs[i].address,j,initial ); + passed = 0; + } + } + + if (passed) { + if (debug) + printk("Init Indirect Registers completed successfully.\n"); + } else { + printk(" !!!!! Init Indirect Registers UNSUCCESSFULLY.\n"); + return -1; + } + return 0; +} + +static inline void wctdm_proslic_recheck_sanity(struct wctdm *wc, int card) +{ + int res; + /* Check loopback */ + res = wc->reg1shadow[card]; + if (!res && (res != wc->mod[card].fxs.lasttxhook)) { + res = wctdm_getreg(wc, card, 8); + if (res) { + printk("Ouch, part reset, quickly restoring reality (%d)\n", card); + wctdm_init_proslic(wc, card, 1, 0, 1); + } else { + if (wc->mod[card].fxs.palarms++ < MAX_ALARMS) { + printk("Power alarm on module %d, resetting!\n", card + 1); + if (wc->mod[card].fxs.lasttxhook == 4) + wc->mod[card].fxs.lasttxhook = 1; + wctdm_setreg(wc, card, 64, wc->mod[card].fxs.lasttxhook); + } else { + if (wc->mod[card].fxs.palarms == MAX_ALARMS) + printk("Too many power alarms on card %d, NOT resetting!\n", card + 1); + } + } + } +} + +static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card) +{ +#ifndef AUDIO_RINGCHECK + unsigned char res; +#endif + signed char b; + int poopy = 0; + /* Try to track issues that plague slot one FXO's */ + b = wc->reg0shadow[card]; + if ((b & 0x2) || !(b & 0x8)) { + /* Not good -- don't look at anything else */ + if (debug) + printk("Poopy (%02x) on card %d!\n", b, card + 1); + poopy++; + } + b &= 0x9b; + if (wc->mod[card].fxo.offhook) { + if (b != 0x9) + wctdm_setreg(wc, card, 5, 0x9); + } else { + if (b != 0x8) + wctdm_setreg(wc, card, 5, 0x8); + } + if (poopy) + return; +#ifndef AUDIO_RINGCHECK + if (!wc->mod[card].fxo.offhook) { + if (fwringdetect) { + res = wc->reg0shadow[card] & 0x60; + if (wc->mod[card].fxo.ringdebounce--) { + if (res && (res != wc->mod[card].fxo.lastrdtx) && (wc->mod[card].fxo.battery == 1)) { + if (!wc->mod[card].fxo.wasringing) { + wc->mod[card].fxo.wasringing = 1; + if (debug) + printk("RING on %d/%d!\n", wc->span.spanno, card + 1); + zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); + } + wc->mod[card].fxo.lastrdtx = res; + wc->mod[card].fxo.ringdebounce = 10; + } else if (!res) { + if ((wc->mod[card].fxo.ringdebounce == 0) && wc->mod[card].fxo.wasringing) { + wc->mod[card].fxo.wasringing = 0; + if (debug) + printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); + zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); + } + } + } else if (res && (wc->mod[card].fxo.battery == 1)) { + wc->mod[card].fxo.lastrdtx = res; + wc->mod[card].fxo.ringdebounce = 10; + } + } else { + res = wc->reg0shadow[card]; + if ((res & 0x60) && (wc->mod[card].fxo.battery == 1)) { + wc->mod[card].fxo.ringdebounce += (ZT_CHUNKSIZE * 16); + if (wc->mod[card].fxo.ringdebounce >= ZT_CHUNKSIZE * ringdebounce) { + if (!wc->mod[card].fxo.wasringing) { + wc->mod[card].fxo.wasringing = 1; + zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); + if (debug) + printk("RING on %d/%d!\n", wc->span.spanno, card + 1); + } + wc->mod[card].fxo.ringdebounce = ZT_CHUNKSIZE * ringdebounce; + } + } else { + wc->mod[card].fxo.ringdebounce -= ZT_CHUNKSIZE * 4; + if (wc->mod[card].fxo.ringdebounce <= 0) { + if (wc->mod[card].fxo.wasringing) { + wc->mod[card].fxo.wasringing = 0; + zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); + if (debug) + printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); + } + wc->mod[card].fxo.ringdebounce = 0; + } + } + } + } +#endif + b = wc->reg1shadow[card]; +#if 0 + { + static int count = 0; + if (!(count++ % 100)) { + printk("Card %d: Voltage: %d Debounce %d\n", card + 1, + b, wc->mod[card].fxo.battdebounce); + } + } +#endif + if (abs(b) < battthresh) { + wc->mod[card].fxo.nobatttimer++; +#if 0 + if (wc->mod[card].fxo.battery == 1) + printk("Battery loss: %d (%d debounce)\n", b, wc->mod[card].fxo.battdebounce); +#endif + if (wc->mod[card].fxo.battery && !wc->mod[card].fxo.battdebounce) { + if (debug) + printk("NO BATTERY on %d/%d!\n", wc->span.spanno, card + 1); + wc->mod[card].fxo.battery = 0; +#ifdef JAPAN + if ((!wc->ohdebounce) && wc->offhook) { + zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); + if (debug) + printk("Signalled On Hook\n"); +#ifdef ZERO_BATT_RING + wc->onhook++; +#endif + } +#else + zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); + zt_alarm_channel(&wc->chans[card], ZT_ALARM_RED); +#endif + wc->mod[card].fxo.battdebounce = battdebounce; + } else if (!wc->mod[card].fxo.battery) + wc->mod[card].fxo.battdebounce = battdebounce; + } else if (abs(b) > battthresh) { + if ((wc->mod[card].fxo.battery < 1) && !wc->mod[card].fxo.battdebounce) { + if (debug) + printk("BATTERY on %d/%d (%s)!\n", wc->span.spanno, card + 1, + (b < 0) ? "-" : "+"); +#ifdef ZERO_BATT_RING + if (wc->onhook) { + wc->onhook = 0; + zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); + if (debug) + printk("Signalled Off Hook\n"); + } +#else + zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); + zt_alarm_channel(&wc->chans[card], ZT_ALARM_NONE); +#endif + wc->mod[card].fxo.battery = 1; + wc->mod[card].fxo.nobatttimer = 0; + wc->mod[card].fxo.battdebounce = battdebounce; + } else if (wc->mod[card].fxo.battery == 1) + wc->mod[card].fxo.battdebounce = battdebounce; + + if (wc->mod[card].fxo.lastpol >= 0) { + if (b < 0) { + wc->mod[card].fxo.lastpol = -1; + wc->mod[card].fxo.polaritydebounce = POLARITY_DEBOUNCE; + } + } + if (wc->mod[card].fxo.lastpol <= 0) { + if (b > 0) { + wc->mod[card].fxo.lastpol = 1; + wc->mod[card].fxo.polaritydebounce = POLARITY_DEBOUNCE; + } + } + } else { + /* It's something else... */ + wc->mod[card].fxo.battdebounce = battdebounce; + } + if (wc->mod[card].fxo.battdebounce) + wc->mod[card].fxo.battdebounce--; + if (wc->mod[card].fxo.polaritydebounce) { + wc->mod[card].fxo.polaritydebounce--; + if (wc->mod[card].fxo.polaritydebounce < 1) { + if (wc->mod[card].fxo.lastpol != wc->mod[card].fxo.polarity) { + if (debug) + printk("%lu Polarity reversed (%d -> %d)\n", jiffies, + wc->mod[card].fxo.polarity, + wc->mod[card].fxo.lastpol); + if (wc->mod[card].fxo.polarity) + zt_qevent_lock(&wc->chans[card], ZT_EVENT_POLARITY); + wc->mod[card].fxo.polarity = wc->mod[card].fxo.lastpol; + } + } + } +} + +static inline void wctdm_proslic_check_hook(struct wctdm *wc, int card) +{ + char res; + int hook; + + /* For some reason we have to debounce the + hook detector. */ + + res = wc->reg0shadow[card]; + hook = (res & 1); + if (hook != wc->mod[card].fxs.lastrxhook) { + /* Reset the debounce (must be multiple of 4ms) */ + wc->mod[card].fxs.debounce = 8 * (4 * 8); +#if 0 + printk("Resetting debounce card %d hook %d, %d\n", card, hook, wc->mod[card].fxs.debounce); +#endif + } else { + if (wc->mod[card].fxs.debounce > 0) { + wc->mod[card].fxs.debounce-= 16 * ZT_CHUNKSIZE; +#if 0 + printk("Sustaining hook %d, %d\n", hook, wc->mod[card].fxs.debounce); +#endif + if (!wc->mod[card].fxs.debounce) { +#if 0 + printk("Counted down debounce, newhook: %d...\n", hook); +#endif + wc->mod[card].fxs.debouncehook = hook; + } + if (!wc->mod[card].fxs.oldrxhook && wc->mod[card].fxs.debouncehook) { + /* Off hook */ +#if 1 + if (debug) +#endif + printk("wctdm: Card %d Going off hook\n", card); + zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); + if (robust) + wctdm_init_proslic(wc, card, 1, 0, 1); + wc->mod[card].fxs.oldrxhook = 1; + + } else if (wc->mod[card].fxs.oldrxhook && !wc->mod[card].fxs.debouncehook) { + /* On hook */ +#if 1 + if (debug) +#endif + printk("wctdm: Card %d Going on hook\n", card); + zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); + wc->mod[card].fxs.oldrxhook = 0; + } + } + } + wc->mod[card].fxs.lastrxhook = hook; +} + +ZAP_IRQ_HANDLER(wctdm_interrupt) +{ + struct wctdm *wc = dev_id; + unsigned char ints; + int x; + int mode; + + ints = inb(wc->ioaddr + WC_INTSTAT); + + if (!ints) +#ifdef LINUX26 + return IRQ_NONE; +#else + return; +#endif + + outb(ints, wc->ioaddr + WC_INTSTAT); + + if (ints & 0x10) { + /* Stop DMA, wait for watchdog */ + printk("TDM PCI Master abort\n"); + wctdm_stop_dma(wc); +#ifdef LINUX26 + return IRQ_RETVAL(1); +#else + return; +#endif + } + + if (ints & 0x20) { + printk("PCI Target abort\n"); +#ifdef LINUX26 + return IRQ_RETVAL(1); +#else + return; +#endif + } + + for (x=0;x<4;x++) { + if (wc->cardflag & (1 << x) && + (wc->modtype[x] == MOD_TYPE_FXS)) { + if (wc->mod[x].fxs.lasttxhook == 0x4) { + /* RINGing, prepare for OHT */ + wc->mod[x].fxs.ohttimer = OHT_TIMER << 3; + if (reversepolarity) + wc->mod[x].fxs.idletxhookstate = 0x6; /* OHT mode when idle */ + else + wc->mod[x].fxs.idletxhookstate = 0x2; + } else { + if (wc->mod[x].fxs.ohttimer) { + wc->mod[x].fxs.ohttimer-= ZT_CHUNKSIZE; + if (!wc->mod[x].fxs.ohttimer) { + if (reversepolarity) + wc->mod[x].fxs.idletxhookstate = 0x5; /* Switch to active */ + else + wc->mod[x].fxs.idletxhookstate = 0x1; + if ((wc->mod[x].fxs.lasttxhook == 0x2) || (wc->mod[x].fxs.lasttxhook == 0x6)) { + /* Apply the change if appropriate */ + if (reversepolarity) + wc->mod[x].fxs.lasttxhook = 0x5; + else + wc->mod[x].fxs.lasttxhook = 0x1; + wctdm_setreg(wc, x, 64, wc->mod[x].fxs.lasttxhook); + } + } + } + } + } + } + + if (ints & 0x0f) { + wc->intcount++; + x = wc->intcount & 0x3; + mode = wc->intcount & 0xc; + if (wc->cardflag & (1 << x)) { + switch(mode) { + case 0: + /* Rest */ + break; + case 4: + /* Read first shadow reg */ + if (wc->modtype[x] == MOD_TYPE_FXS) + wc->reg0shadow[x] = wctdm_getreg(wc, x, 68); + else if (wc->modtype[x] == MOD_TYPE_FXO) + wc->reg0shadow[x] = wctdm_getreg(wc, x, 5); + break; + case 8: + /* Read second shadow reg */ + if (wc->modtype[x] == MOD_TYPE_FXS) + wc->reg1shadow[x] = wctdm_getreg(wc, x, 64); + else if (wc->modtype[x] == MOD_TYPE_FXO) + wc->reg1shadow[x] = wctdm_getreg(wc, x, 29); + break; + case 12: + /* Perform processing */ + if (wc->modtype[x] == MOD_TYPE_FXS) { + wctdm_proslic_check_hook(wc, x); + if (!(wc->intcount & 0xf0)) + wctdm_proslic_recheck_sanity(wc, x); + } else if (wc->modtype[x] == MOD_TYPE_FXO) { + wctdm_voicedaa_check_hook(wc, x); + } + break; + } + } + if (!(wc->intcount % 10000)) { + /* Accept an alarm once per 10 seconds */ + for (x=0;x<4;x++) + if (wc->modtype[x] == MOD_TYPE_FXS) { + if (wc->mod[x].fxs.palarms) + wc->mod[x].fxs.palarms--; + } + } + wctdm_receiveprep(wc, ints); + wctdm_transmitprep(wc, ints); + } +#ifdef LINUX26 + return IRQ_RETVAL(1); +#endif + +} + +static int wctdm_voicedaa_insane(struct wctdm *wc, int card) +{ + int blah; + blah = wctdm_getreg(wc, card, 2); + if (blah != 0x3) + return -2; + blah = wctdm_getreg(wc, card, 11); + if (debug) + printk("VoiceDAA System: %02x\n", blah & 0xf); + return 0; +} + +static int wctdm_proslic_insane(struct wctdm *wc, int card) +{ + int blah,insane_report; + insane_report=0; + + blah = wctdm_getreg(wc, card, 0); + if (debug) + printk("ProSLIC on module %d, product %d, version %d\n", card, (blah & 0x30) >> 4, (blah & 0xf)); + +#if 0 + if ((blah & 0x30) >> 4) { + printk("ProSLIC on module %d is not a 3210.\n", card); + return -1; + } +#endif + if (((blah & 0xf) == 0) || ((blah & 0xf) == 0xf)) { + /* SLIC not loaded */ + return -1; + } + if ((blah & 0xf) < 2) { + printk("ProSLIC 3210 version %d is too old\n", blah & 0xf); + return -1; + } + if (wctdm_getreg(wc, card, 1) & 0x80) + /* ProSLIC 3215, not a 3210 */ + wc->flags[card] |= FLAG_3215; + + blah = wctdm_getreg(wc, card, 8); + if (blah != 0x2) { + printk("ProSLIC on module %d insane (1) %d should be 2\n", card, blah); + return -1; + } else if ( insane_report) + printk("ProSLIC on module %d Reg 8 Reads %d Expected is 0x2\n",card,blah); + + blah = wctdm_getreg(wc, card, 64); + if (blah != 0x0) { + printk("ProSLIC on module %d insane (2)\n", card); + return -1; + } else if ( insane_report) + printk("ProSLIC on module %d Reg 64 Reads %d Expected is 0x0\n",card,blah); + + blah = wctdm_getreg(wc, card, 11); + if (blah != 0x33) { + printk("ProSLIC on module %d insane (3)\n", card); + return -1; + } else if ( insane_report) + printk("ProSLIC on module %d Reg 11 Reads %d Expected is 0x33\n",card,blah); + + /* Just be sure it's setup right. */ + wctdm_setreg(wc, card, 30, 0); + + if (debug) + printk("ProSLIC on module %d seems sane.\n", card); + return 0; +} + +static int wctdm_proslic_powerleak_test(struct wctdm *wc, int card) +{ + unsigned long origjiffies; + unsigned char vbat; + + /* Turn off linefeed */ + wctdm_setreg(wc, card, 64, 0); + + /* Power down */ + wctdm_setreg(wc, card, 14, 0x10); + + /* Wait for one second */ + origjiffies = jiffies; + + while((vbat = wctdm_getreg(wc, card, 82)) > 0x6) { + if ((jiffies - origjiffies) >= (HZ/2)) + break;; + } + + if (vbat < 0x06) { + printk("Excessive leakage detected on module %d: %d volts (%02x) after %d ms\n", card, + 376 * vbat / 1000, vbat, (int)((jiffies - origjiffies) * 1000 / HZ)); + return -1; + } else if (debug) { + printk("Post-leakage voltage: %d volts\n", 376 * vbat / 1000); + } + return 0; +} + +static int wctdm_powerup_proslic(struct wctdm *wc, int card, int fast) +{ + unsigned char vbat; + unsigned long origjiffies; + int lim; + + /* Set period of DC-DC converter to 1/64 khz */ + wctdm_setreg(wc, card, 92, 0xff /* was 0xff */); + + /* Wait for VBat to powerup */ + origjiffies = jiffies; + + /* Disable powerdown */ + wctdm_setreg(wc, card, 14, 0); + + /* If fast, don't bother checking anymore */ + if (fast) + return 0; + + while((vbat = wctdm_getreg(wc, card, 82)) < 0xc0) { + /* Wait no more than 500ms */ + if ((jiffies - origjiffies) > HZ/2) { + break; + } + } + + if (vbat < 0xc0) { + if (wc->proslic_power == PROSLIC_POWER_UNKNOWN) + printk("ProSLIC on module %d failed to powerup within %d ms (%d mV only)\n\n -- DID YOU REMEMBER TO PLUG IN THE HD POWER CABLE TO THE TDM400P??\n", + card, (int)(((jiffies - origjiffies) * 1000 / HZ)), + vbat * 375); + wc->proslic_power = PROSLIC_POWER_WARNED; + return -1; + } else if (debug) { + printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n", + card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ))); + } + wc->proslic_power = PROSLIC_POWER_ON; + + /* Proslic max allowed loop current, reg 71 LOOP_I_LIMIT */ + /* If out of range, just set it to the default value */ + lim = (loopcurrent - 20) / 3; + if ( loopcurrent > 41 ) { + lim = 0; + if (debug) + printk("Loop current out of range! Setting to default 20mA!\n"); + } + else if (debug) + printk("Loop current set to %dmA!\n",(lim*3)+20); + wctdm_setreg(wc,card,LOOP_I_LIMIT,lim); + + /* Engage DC-DC converter */ + wctdm_setreg(wc, card, 93, 0x19 /* was 0x19 */); +#if 0 + origjiffies = jiffies; + while(0x80 & wctdm_getreg(wc, card, 93)) { + if ((jiffies - origjiffies) > 2 * HZ) { + printk("Timeout waiting for DC-DC calibration on module %d\n", card); + return -1; + } + } + +#if 0 + /* Wait a full two seconds */ + while((jiffies - origjiffies) < 2 * HZ); + + /* Just check to be sure */ + vbat = wctdm_getreg(wc, card, 82); + printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n", + card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ))); +#endif +#endif + return 0; + +} + +static int wctdm_proslic_manual_calibrate(struct wctdm *wc, int card){ + unsigned long origjiffies; + unsigned char i; + + wctdm_setreg(wc, card, 21, 0);//(0) Disable all interupts in DR21 + wctdm_setreg(wc, card, 22, 0);//(0)Disable all interupts in DR21 + wctdm_setreg(wc, card, 23, 0);//(0)Disable all interupts in DR21 + wctdm_setreg(wc, card, 64, 0);//(0) + + wctdm_setreg(wc, card, 97, 0x18); //(0x18)Calibrations without the ADC and DAC offset and without common mode calibration. + wctdm_setreg(wc, card, 96, 0x47); //(0x47) Calibrate common mode and differential DAC mode DAC + ILIM + + origjiffies=jiffies; + while( wctdm_getreg(wc,card,96)!=0 ){ + if((jiffies-origjiffies)>80) + return -1; + } +//Initialized DR 98 and 99 to get consistant results. +// 98 and 99 are the results registers and the search should have same intial conditions. + +/*******************************The following is the manual gain mismatch calibration****************************/ +/*******************************This is also available as a function *******************************************/ + // Delay 10ms + origjiffies=jiffies; + while((jiffies-origjiffies)<1); + wctdm_proslic_setreg_indirect(wc, card, 88,0); + wctdm_proslic_setreg_indirect(wc,card,89,0); + wctdm_proslic_setreg_indirect(wc,card,90,0); + wctdm_proslic_setreg_indirect(wc,card,91,0); + wctdm_proslic_setreg_indirect(wc,card,92,0); + wctdm_proslic_setreg_indirect(wc,card,93,0); + + wctdm_setreg(wc, card, 98,0x10); // This is necessary if the calibration occurs other than at reset time + wctdm_setreg(wc, card, 99,0x10); + + for ( i=0x1f; i>0; i--) + { + wctdm_setreg(wc, card, 98,i); + origjiffies=jiffies; + while((jiffies-origjiffies)<4); + if((wctdm_getreg(wc,card,88)) == 0) + break; + } // for + + for ( i=0x1f; i>0; i--) + { + wctdm_setreg(wc, card, 99,i); + origjiffies=jiffies; + while((jiffies-origjiffies)<4); + if((wctdm_getreg(wc,card,89)) == 0) + break; + }//for + +/*******************************The preceding is the manual gain mismatch calibration****************************/ +/**********************************The following is the longitudinal Balance Cal***********************************/ + wctdm_setreg(wc,card,64,1); + while((jiffies-origjiffies)<10); // Sleep 100? + + wctdm_setreg(wc, card, 64, 0); + wctdm_setreg(wc, card, 23, 0x4); // enable interrupt for the balance Cal + wctdm_setreg(wc, card, 97, 0x1); // this is a singular calibration bit for longitudinal calibration + wctdm_setreg(wc, card, 96,0x40); + + wctdm_getreg(wc,card,96); /* Read Reg 96 just cause */ + + wctdm_setreg(wc, card, 21, 0xFF); + wctdm_setreg(wc, card, 22, 0xFF); + wctdm_setreg(wc, card, 23, 0xFF); + + /**The preceding is the longitudinal Balance Cal***/ + return(0); + +} +#if 1 +static int wctdm_proslic_calibrate(struct wctdm *wc, int card) +{ + unsigned long origjiffies; + int x; + /* Perform all calibrations */ + wctdm_setreg(wc, card, 97, 0x1f); + + /* Begin, no speedup */ + wctdm_setreg(wc, card, 96, 0x5f); + + /* Wait for it to finish */ + origjiffies = jiffies; + while(wctdm_getreg(wc, card, 96)) { + if ((jiffies - origjiffies) > 2 * HZ) { + printk("Timeout waiting for calibration of module %d\n", card); + return -1; + } + } + + if (debug) { + /* Print calibration parameters */ + printk("Calibration Vector Regs 98 - 107: \n"); + for (x=98;x<108;x++) { + printk("%d: %02x\n", x, wctdm_getreg(wc, card, x)); + } + } + return 0; +} +#endif + +static void wait_just_a_bit(int foo) +{ + long newjiffies; + newjiffies = jiffies + foo; + while(jiffies < newjiffies); +} + +/********************************************************************* + * Set the hwgain on the analog modules + * + * card = the card position for this module (0-23) + * gain = gain in dB x10 (e.g. -3.5dB would be gain=-35) + * tx = (0 for rx; 1 for tx) + * + *******************************************************************/ +static int wctdm_set_hwgain(struct wctdm *wc, int card, __s32 gain, __u32 tx) +{ + if (!(wc->modtype[card] == MOD_TYPE_FXO)) { + printk("Cannot adjust gain. Unsupported module type!\n"); + return -1; + } + if (tx) { + if (debug) + printk("setting FXO tx gain for card=%d to %d\n", card, gain); + if (gain >= -150 && gain <= 0) { + wctdm_setreg(wc, card, 38, 16 + (gain/-10)); + wctdm_setreg(wc, card, 40, 16 + (-gain%10)); + } else if (gain <= 120 && gain > 0) { + wctdm_setreg(wc, card, 38, gain/10); + wctdm_setreg(wc, card, 40, (gain%10)); + } else { + printk("FXO tx gain is out of range (%d)\n", gain); + return -1; + } + } else { /* rx */ + if (debug) + printk("setting FXO rx gain for card=%d to %d\n", card, gain); + if (gain >= -150 && gain <= 0) { + wctdm_setreg(wc, card, 39, 16+ (gain/-10)); + wctdm_setreg(wc, card, 41, 16 + (-gain%10)); + } else if (gain <= 120 && gain > 0) { + wctdm_setreg(wc, card, 39, gain/10); + wctdm_setreg(wc, card, 41, (gain%10)); + } else { + printk("FXO rx gain is out of range (%d)\n", gain); + return -1; + } + } + + return 0; +} + +static int wctdm_init_voicedaa(struct wctdm *wc, int card, int fast, int manual, int sane) +{ + unsigned char reg16=0, reg26=0, reg30=0, reg31=0; + long newjiffies; + wc->modtype[card] = MOD_TYPE_FXO; + /* Sanity check the ProSLIC */ + reset_spi(wc, card); + if (!sane && wctdm_voicedaa_insane(wc, card)) + return -2; + + /* Software reset */ + wctdm_setreg(wc, card, 1, 0x80); + + /* Wait just a bit */ + wait_just_a_bit(HZ/10); + + /* Enable PCM, ulaw */ + if (alawoverride) + wctdm_setreg(wc, card, 33, 0x20); + else + wctdm_setreg(wc, card, 33, 0x28); + + /* Set On-hook speed, Ringer impedence, and ringer threshold */ + reg16 |= (fxo_modes[_opermode].ohs << 6); + reg16 |= (fxo_modes[_opermode].rz << 1); + reg16 |= (fxo_modes[_opermode].rt); + wctdm_setreg(wc, card, 16, reg16); + + if(fwringdetect) { + /* Enable ring detector full-wave rectifier mode */ + wctdm_setreg(wc, card, 18, 2); + wctdm_setreg(wc, card, 24, 0); + } else { + /* Set to the device defaults */ + wctdm_setreg(wc, card, 18, 0); + wctdm_setreg(wc, card, 24, 0x19); + } + + /* Set DC Termination: + Tip/Ring voltage adjust, minimum operational current, current limitation */ + reg26 |= (fxo_modes[_opermode].dcv << 6); + reg26 |= (fxo_modes[_opermode].mini << 4); + reg26 |= (fxo_modes[_opermode].ilim << 1); + wctdm_setreg(wc, card, 26, reg26); + + /* Set AC Impedence */ + reg30 = (fxo_modes[_opermode].acim); + wctdm_setreg(wc, card, 30, reg30); + + /* Misc. DAA parameters */ + if (fastpickup) + reg31 = 0xb3; + else + reg31 = 0xa3; + + reg31 |= (fxo_modes[_opermode].ohs2 << 3); + wctdm_setreg(wc, card, 31, reg31); + + /* Set Transmit/Receive timeslot */ + wctdm_setreg(wc, card, 34, (3-card) * 8); + wctdm_setreg(wc, card, 35, 0x00); + wctdm_setreg(wc, card, 36, (3-card) * 8); + wctdm_setreg(wc, card, 37, 0x00); + + /* Enable ISO-Cap */ + wctdm_setreg(wc, card, 6, 0x00); + + if (fastpickup) + wctdm_setreg(wc, card, 17, wctdm_getreg(wc, card, 17) | 0x20); + + /* Wait 1000ms for ISO-cap to come up */ + newjiffies = jiffies; + newjiffies += 2 * HZ; + while((jiffies < newjiffies) && !(wctdm_getreg(wc, card, 11) & 0xf0)) + wait_just_a_bit(HZ/10); + + if (!(wctdm_getreg(wc, card, 11) & 0xf0)) { + printk("VoiceDAA did not bring up ISO link properly!\n"); + return -1; + } + if (debug) + printk("ISO-Cap is now up, line side: %02x rev %02x\n", + wctdm_getreg(wc, card, 11) >> 4, + (wctdm_getreg(wc, card, 13) >> 2) & 0xf); + /* Enable on-hook line monitor */ + wctdm_setreg(wc, card, 5, 0x08); + + /* Take values for fxotxgain and fxorxgain and apply them to module */ + wctdm_set_hwgain(wc, card, fxotxgain, 1); + wctdm_set_hwgain(wc, card, fxorxgain, 0); + + /* NZ -- crank the tx gain up by 7 dB */ + if (!strcmp(fxo_modes[_opermode].name, "NEWZEALAND")) { + printk("Adjusting gain\n"); + wctdm_set_hwgain(wc, card, 7, 1); + } + + if(debug) + printk("DEBUG fxotxgain:%i.%i fxorxgain:%i.%i\n", (wctdm_getreg(wc, card, 38)/16)?-(wctdm_getreg(wc, card, 38) - 16) : wctdm_getreg(wc, card, 38), (wctdm_getreg(wc, card, 40)/16)? -(wctdm_getreg(wc, card, 40) - 16):wctdm_getreg(wc, card, 40), (wctdm_getreg(wc, card, 39)/16)? -(wctdm_getreg(wc, card, 39) - 16) : wctdm_getreg(wc, card, 39),(wctdm_getreg(wc, card, 41)/16)?-(wctdm_getreg(wc, card, 41) - 16):wctdm_getreg(wc, card, 41)); + + /* battery state still unknown */ + wc->mod[card].fxo.battery = -1; + + return 0; + +} + +static int wctdm_init_proslic(struct wctdm *wc, int card, int fast, int manual, int sane) +{ + + unsigned short tmp[5]; + unsigned char r19,r9; + int x; + int fxsmode=0; + + /* Sanity check the ProSLIC */ + if (!sane && wctdm_proslic_insane(wc, card)) + return -2; + + /* By default, don't send on hook */ + if (reversepolarity) + wc->mod[card].fxs.idletxhookstate = 5; + else + wc->mod[card].fxs.idletxhookstate = 1; + + if (sane) { + /* Make sure we turn off the DC->DC converter to prevent anything from blowing up */ + wctdm_setreg(wc, card, 14, 0x10); + } + + if (wctdm_proslic_init_indirect_regs(wc, card)) { + printk(KERN_INFO "Indirect Registers failed to initialize on module %d.\n", card); + return -1; + } + + /* Clear scratch pad area */ + wctdm_proslic_setreg_indirect(wc, card, 97,0); + + /* Clear digital loopback */ + wctdm_setreg(wc, card, 8, 0); + + /* Revision C optimization */ + wctdm_setreg(wc, card, 108, 0xeb); + + /* Disable automatic VBat switching for safety to prevent + Q7 from accidently turning on and burning out. */ + wctdm_setreg(wc, card, 67, 0x07); /* Note, if pulse dialing has problems at high REN loads + change this to 0x17 */ + + /* Turn off Q7 */ + wctdm_setreg(wc, card, 66, 1); + + /* Flush ProSLIC digital filters by setting to clear, while + saving old values */ + for (x=0;x<5;x++) { + tmp[x] = wctdm_proslic_getreg_indirect(wc, card, x + 35); + wctdm_proslic_setreg_indirect(wc, card, x + 35, 0x8000); + } + + /* Power up the DC-DC converter */ + if (wctdm_powerup_proslic(wc, card, fast)) { + printk("Unable to do INITIAL ProSLIC powerup on module %d\n", card); + return -1; + } + + if (!fast) { + + /* Check for power leaks */ + if (wctdm_proslic_powerleak_test(wc, card)) { + printk("ProSLIC module %d failed leakage test. Check for short circuit\n", card); + } + /* Power up again */ + if (wctdm_powerup_proslic(wc, card, fast)) { + printk("Unable to do FINAL ProSLIC powerup on module %d\n", card); + return -1; + } +#ifndef NO_CALIBRATION + /* Perform calibration */ + if(manual) { + if (wctdm_proslic_manual_calibrate(wc, card)) { + //printk("Proslic failed on Manual Calibration\n"); + if (wctdm_proslic_manual_calibrate(wc, card)) { + printk("Proslic Failed on Second Attempt to Calibrate Manually. (Try -DNO_CALIBRATION in Makefile)\n"); + return -1; + } + printk("Proslic Passed Manual Calibration on Second Attempt\n"); + } + } + else { + if(wctdm_proslic_calibrate(wc, card)) { + //printk("ProSlic died on Auto Calibration.\n"); + if (wctdm_proslic_calibrate(wc, card)) { + printk("Proslic Failed on Second Attempt to Auto Calibrate\n"); + return -1; + } + printk("Proslic Passed Auto Calibration on Second Attempt\n"); + } + } + /* Perform DC-DC calibration */ + wctdm_setreg(wc, card, 93, 0x99); + r19 = wctdm_getreg(wc, card, 107); + if ((r19 < 0x2) || (r19 > 0xd)) { + printk("DC-DC cal has a surprising direct 107 of 0x%02x!\n", r19); + wctdm_setreg(wc, card, 107, 0x8); + } + + /* Save calibration vectors */ + for (x=0;xmod[card].fxs.calregs.vals[x] = wctdm_getreg(wc, card, 96 + x); +#endif + + } else { + /* Restore calibration registers */ + for (x=0;xmod[card].fxs.calregs.vals[x]); + } + /* Calibration complete, restore original values */ + for (x=0;x<5;x++) { + wctdm_proslic_setreg_indirect(wc, card, x + 35, tmp[x]); + } + + if (wctdm_proslic_verify_indirect_regs(wc, card)) { + printk(KERN_INFO "Indirect Registers failed verification.\n"); + return -1; + } + + +#if 0 + /* Disable Auto Power Alarm Detect and other "features" */ + wctdm_setreg(wc, card, 67, 0x0e); + blah = wctdm_getreg(wc, card, 67); +#endif + +#if 0 + if (wctdm_proslic_setreg_indirect(wc, card, 97, 0x0)) { // Stanley: for the bad recording fix + printk(KERN_INFO "ProSlic IndirectReg Died.\n"); + return -1; + } +#endif + + if (alawoverride) + wctdm_setreg(wc, card, 1, 0x20); + else + wctdm_setreg(wc, card, 1, 0x28); + // U-Law 8-bit interface + wctdm_setreg(wc, card, 2, (3-card) * 8); // Tx Start count low byte 0 + wctdm_setreg(wc, card, 3, 0); // Tx Start count high byte 0 + wctdm_setreg(wc, card, 4, (3-card) * 8); // Rx Start count low byte 0 + wctdm_setreg(wc, card, 5, 0); // Rx Start count high byte 0 + wctdm_setreg(wc, card, 18, 0xff); // clear all interrupt + wctdm_setreg(wc, card, 19, 0xff); + wctdm_setreg(wc, card, 20, 0xff); + wctdm_setreg(wc, card, 73, 0x04); + if (fxshonormode) { + fxsmode = acim2tiss[fxo_modes[_opermode].acim]; + wctdm_setreg(wc, card, 10, 0x08 | fxsmode); + if (fxo_modes[_opermode].ring_osc) + wctdm_proslic_setreg_indirect(wc, card, 20, fxo_modes[_opermode].ring_osc); + if (fxo_modes[_opermode].ring_x) + wctdm_proslic_setreg_indirect(wc, card, 21, fxo_modes[_opermode].ring_x); + } + if (lowpower) + wctdm_setreg(wc, card, 72, 0x10); + +#if 0 + wctdm_setreg(wc, card, 21, 0x00); // enable interrupt + wctdm_setreg(wc, card, 22, 0x02); // Loop detection interrupt + wctdm_setreg(wc, card, 23, 0x01); // DTMF detection interrupt +#endif + +#if 0 + /* Enable loopback */ + wctdm_setreg(wc, card, 8, 0x2); + wctdm_setreg(wc, card, 14, 0x0); + wctdm_setreg(wc, card, 64, 0x0); + wctdm_setreg(wc, card, 1, 0x08); +#endif + + if (fastringer) { + /* Speed up Ringer */ + wctdm_proslic_setreg_indirect(wc, card, 20, 0x7e6d); + wctdm_proslic_setreg_indirect(wc, card, 21, 0x01b9); + /* Beef up Ringing voltage to 89V */ + if (boostringer) { + wctdm_setreg(wc, card, 74, 0x3f); + if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x247)) + return -1; + printk("Boosting fast ringer on slot %d (89V peak)\n", card + 1); + } else if (lowpower) { + if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x14b)) + return -1; + printk("Reducing fast ring power on slot %d (50V peak)\n", card + 1); + } else + printk("Speeding up ringer on slot %d (25Hz)\n", card + 1); + } else { + /* Beef up Ringing voltage to 89V */ + if (boostringer) { + wctdm_setreg(wc, card, 74, 0x3f); + if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x1d1)) + return -1; + printk("Boosting ringer on slot %d (89V peak)\n", card + 1); + } else if (lowpower) { + if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x108)) + return -1; + printk("Reducing ring power on slot %d (50V peak)\n", card + 1); + } + } + + if(fxstxgain || fxsrxgain) { + r9 = wctdm_getreg(wc, card, 9); + switch (fxstxgain) { + + case 35: + r9+=8; + break; + case -35: + r9+=4; + break; + case 0: + break; + } + + switch (fxsrxgain) { + + case 35: + r9+=2; + break; + case -35: + r9+=1; + break; + case 0: + break; + } + wctdm_setreg(wc,card,9,r9); + } + + if(debug) + printk("DEBUG: fxstxgain:%s fxsrxgain:%s\n",((wctdm_getreg(wc, card, 9)/8) == 1)?"3.5":(((wctdm_getreg(wc,card,9)/4) == 1)?"-3.5":"0.0"),((wctdm_getreg(wc, card, 9)/2) == 1)?"3.5":((wctdm_getreg(wc,card,9)%2)?"-3.5":"0.0")); + + wctdm_setreg(wc, card, 64, 0x01); + return 0; +} + + +static int wctdm_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) +{ + struct wctdm_stats stats; + struct wctdm_regs regs; + struct wctdm_regop regop; + struct wctdm_echo_coefs echoregs; + struct zt_hwgain hwgain; + struct wctdm *wc = chan->pvt; + int x; + switch (cmd) { + case ZT_ONHOOKTRANSFER: + if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) + return -EINVAL; + if (get_user(x, (int *)data)) + return -EFAULT; + wc->mod[chan->chanpos - 1].fxs.ohttimer = x << 3; + if (reversepolarity) + wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 0x6; /* OHT mode when idle */ + else + wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 0x2; + if (wc->mod[chan->chanpos - 1].fxs.lasttxhook == 0x1 || wc->mod[chan->chanpos - 1].fxs.lasttxhook == 0x5) { + /* Apply the change if appropriate */ + if (reversepolarity) + wc->mod[chan->chanpos - 1].fxs.lasttxhook = 0x6; + else + wc->mod[chan->chanpos - 1].fxs.lasttxhook = 0x2; + wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook); + } + break; + case ZT_SETPOLARITY: + if (get_user(x, (int *)data)) + return -EFAULT; + if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) + return -EINVAL; + /* Can't change polarity while ringing or when open */ + if ((wc->mod[chan->chanpos -1 ].fxs.lasttxhook == 0x04) || + (wc->mod[chan->chanpos -1 ].fxs.lasttxhook == 0x00)) + return -EINVAL; + + if ((x && !reversepolarity) || (!x && reversepolarity)) + wc->mod[chan->chanpos - 1].fxs.lasttxhook |= 0x04; + else + wc->mod[chan->chanpos - 1].fxs.lasttxhook &= ~0x04; + wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook); + break; + case WCTDM_GET_STATS: + if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { + stats.tipvolt = wctdm_getreg(wc, chan->chanpos - 1, 80) * -376; + stats.ringvolt = wctdm_getreg(wc, chan->chanpos - 1, 81) * -376; + stats.batvolt = wctdm_getreg(wc, chan->chanpos - 1, 82) * -376; + } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { + stats.tipvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; + stats.ringvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; + stats.batvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; + } else + return -EINVAL; + if (copy_to_user((struct wctdm_stats *)data, &stats, sizeof(stats))) + return -EFAULT; + break; + case WCTDM_GET_REGS: + if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { + for (x=0;xchanpos -1, x); + for (x=0;xchanpos - 1, x); + } else { + memset(®s, 0, sizeof(regs)); + for (x=0;xchanpos - 1, x); + } + if (copy_to_user((struct wctdm_regs *)data, ®s, sizeof(regs))) + return -EFAULT; + break; + case WCTDM_SET_REG: + if (copy_from_user(®op, (struct wctdm_regop *)data, sizeof(regop))) + return -EFAULT; + if (regop.indirect) { + if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) + return -EINVAL; + printk("Setting indirect %d to 0x%04x on %d\n", regop.reg, regop.val, chan->chanpos); + wctdm_proslic_setreg_indirect(wc, chan->chanpos - 1, regop.reg, regop.val); + } else { + regop.val &= 0xff; + printk("Setting direct %d to %04x on %d\n", regop.reg, regop.val, chan->chanpos); + wctdm_setreg(wc, chan->chanpos - 1, regop.reg, regop.val); + } + break; + case WCTDM_SET_ECHOTUNE: + printk("-- Setting echo registers: \n"); + if (copy_from_user(&echoregs, (struct wctdm_echo_coefs*)data, sizeof(echoregs))) + return -EFAULT; + + if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { + /* Set the ACIM register */ + wctdm_setreg(wc, chan->chanpos - 1, 30, echoregs.acim); + + /* Set the digital echo canceller registers */ + wctdm_setreg(wc, chan->chanpos - 1, 45, echoregs.coef1); + wctdm_setreg(wc, chan->chanpos - 1, 46, echoregs.coef2); + wctdm_setreg(wc, chan->chanpos - 1, 47, echoregs.coef3); + wctdm_setreg(wc, chan->chanpos - 1, 48, echoregs.coef4); + wctdm_setreg(wc, chan->chanpos - 1, 49, echoregs.coef5); + wctdm_setreg(wc, chan->chanpos - 1, 50, echoregs.coef6); + wctdm_setreg(wc, chan->chanpos - 1, 51, echoregs.coef7); + wctdm_setreg(wc, chan->chanpos - 1, 52, echoregs.coef8); + + printk("-- Set echo registers successfully\n"); + + break; + } else { + return -EINVAL; + + } + break; + case ZT_SET_HWGAIN: + if (copy_from_user(&hwgain, (struct zt_hwgain*) data, sizeof(hwgain))) + return -EFAULT; + + wctdm_set_hwgain(wc, chan->chanpos-1, hwgain.newgain, hwgain.tx); + + if (debug) + printk("Setting hwgain on channel %d to %d for %s direction\n", + chan->chanpos-1, hwgain.newgain, hwgain.tx ? "tx" : "rx"); + break; + default: + return -ENOTTY; + } + return 0; + +} + +static int wctdm_open(struct zt_chan *chan) +{ + struct wctdm *wc = chan->pvt; + if (!(wc->cardflag & (1 << (chan->chanpos - 1)))) + return -ENODEV; + if (wc->dead) + return -ENODEV; + wc->usecount++; +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#else + try_module_get(THIS_MODULE); +#endif + return 0; +} + +static int wctdm_watchdog(struct zt_span *span, int event) +{ + printk("TDM: Restarting DMA\n"); + wctdm_restart_dma(span->pvt); + return 0; +} + +static int wctdm_close(struct zt_chan *chan) +{ + struct wctdm *wc = chan->pvt; + wc->usecount--; +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#else + module_put(THIS_MODULE); +#endif + if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { + if (reversepolarity) + wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 5; + else + wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 1; + } + /* If we're dead, release us now */ + if (!wc->usecount && wc->dead) + wctdm_release(wc); + return 0; +} + +static int wctdm_hooksig(struct zt_chan *chan, zt_txsig_t txsig) +{ + struct wctdm *wc = chan->pvt; + int reg=0; + if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { + /* XXX Enable hooksig for FXO XXX */ + switch(txsig) { + case ZT_TXSIG_START: + case ZT_TXSIG_OFFHOOK: + wc->mod[chan->chanpos - 1].fxo.offhook = 1; + wctdm_setreg(wc, chan->chanpos - 1, 5, 0x9); + break; + case ZT_TXSIG_ONHOOK: + wc->mod[chan->chanpos - 1].fxo.offhook = 0; + wctdm_setreg(wc, chan->chanpos - 1, 5, 0x8); + break; + default: + printk("wcfxo: Can't set tx state to %d\n", txsig); + } + } else { + switch(txsig) { + case ZT_TXSIG_ONHOOK: + switch(chan->sig) { + case ZT_SIG_EM: + case ZT_SIG_FXOKS: + case ZT_SIG_FXOLS: + wc->mod[chan->chanpos-1].fxs.lasttxhook = wc->mod[chan->chanpos-1].fxs.idletxhookstate; + break; + case ZT_SIG_FXOGS: + wc->mod[chan->chanpos-1].fxs.lasttxhook = 3; + break; + } + break; + case ZT_TXSIG_OFFHOOK: + switch(chan->sig) { + case ZT_SIG_EM: + wc->mod[chan->chanpos-1].fxs.lasttxhook = 5; + break; + default: + wc->mod[chan->chanpos-1].fxs.lasttxhook = wc->mod[chan->chanpos-1].fxs.idletxhookstate; + break; + } + break; + case ZT_TXSIG_START: + wc->mod[chan->chanpos-1].fxs.lasttxhook = 4; + break; + case ZT_TXSIG_KEWL: + wc->mod[chan->chanpos-1].fxs.lasttxhook = 0; + break; + default: + printk("wctdm: Can't set tx state to %d\n", txsig); + } + if (debug) + printk("Setting FXS hook state to %d (%02x)\n", txsig, reg); + +#if 1 + wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos-1].fxs.lasttxhook); +#endif + } + return 0; +} + +static int wctdm_initialize(struct wctdm *wc) +{ + int x; + + /* Zapata stuff */ + sprintf(wc->span.name, "WCTDM/%d", wc->pos); + snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1); + snprintf(wc->span.location, sizeof(wc->span.location) - 1, + "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); + wc->span.manufacturer = "Digium"; + strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); + if (alawoverride) { + printk("ALAW override parameter detected. Device will be operating in ALAW\n"); + wc->span.deflaw = ZT_LAW_ALAW; + } else + wc->span.deflaw = ZT_LAW_MULAW; + for (x = 0; x < NUM_CARDS; x++) { + sprintf(wc->chans[x].name, "WCTDM/%d/%d", wc->pos, x); + wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR; + wc->chans[x].sigcap |= ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR; + wc->chans[x].chanpos = x+1; + wc->chans[x].pvt = wc; + } + wc->span.chans = wc->chans; + wc->span.channels = NUM_CARDS; + wc->span.hooksig = wctdm_hooksig; + wc->span.irq = wc->dev->irq; + wc->span.open = wctdm_open; + wc->span.close = wctdm_close; + wc->span.flags = ZT_FLAG_RBS; + wc->span.ioctl = wctdm_ioctl; + wc->span.watchdog = wctdm_watchdog; + init_waitqueue_head(&wc->span.maintq); + + wc->span.pvt = wc; + if (zt_register(&wc->span, 0)) { + printk("Unable to register span with zaptel\n"); + return -1; + } + return 0; +} + +static void wctdm_post_initialize(struct wctdm *wc) +{ + int x; + + /* Finalize signalling */ + for (x = 0; x < NUM_CARDS; x++) { + if (wc->cardflag & (1 << x)) { + if (wc->modtype[x] == MOD_TYPE_FXO) + wc->chans[x].sigcap = ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR; + else + wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR; + } else if (!(wc->chans[x].sigcap & ZT_SIG_BROKEN)) { + wc->chans[x].sigcap = 0; + } + } +} + +static int wctdm_hardware_init(struct wctdm *wc) +{ + /* Hardware stuff */ + unsigned char ver; + unsigned char x,y; + int failed; + + /* Signal Reset */ + outb(0x01, wc->ioaddr + WC_CNTL); + + /* Check Freshmaker chip */ + x=inb(wc->ioaddr + WC_CNTL); + ver = __wctdm_getcreg(wc, WC_VER); + failed = 0; + if (ver != 0x59) { + printk("Freshmaker version: %02x\n", ver); + for (x=0;x<255;x++) { + /* Test registers */ + if (ver >= 0x70) { + __wctdm_setcreg(wc, WC_CS, x); + y = __wctdm_getcreg(wc, WC_CS); + } else { + __wctdm_setcreg(wc, WC_TEST, x); + y = __wctdm_getcreg(wc, WC_TEST); + } + if (x != y) { + printk("%02x != %02x\n", x, y); + failed++; + } + } + if (!failed) { + printk("Freshmaker passed register test\n"); + } else { + printk("Freshmaker failed register test\n"); + return -1; + } + /* Go to half-duty FSYNC */ + __wctdm_setcreg(wc, WC_SYNC, 0x01); + y = __wctdm_getcreg(wc, WC_SYNC); + } else { + printk("No freshmaker chip\n"); + } + + /* Reset PCI Interface chip and registers (and serial) */ + outb(0x06, wc->ioaddr + WC_CNTL); + /* Setup our proper outputs for when we switch for our "serial" port */ + wc->ios = BIT_CS | BIT_SCLK | BIT_SDI; + + outb(wc->ios, wc->ioaddr + WC_AUXD); + + /* Set all to outputs except AUX 5, which is an input */ + outb(0xdf, wc->ioaddr + WC_AUXC); + + /* Select alternate function for AUX0 */ + outb(0x4, wc->ioaddr + WC_AUXFUNC); + + /* Wait 1/4 of a sec */ + wait_just_a_bit(HZ/4); + + /* Back to normal, with automatic DMA wrap around */ + outb(0x30 | 0x01, wc->ioaddr + WC_CNTL); + + /* Make sure serial port and DMA are out of reset */ + outb(inb(wc->ioaddr + WC_CNTL) & 0xf9, wc->ioaddr + WC_CNTL); + + /* Configure serial port for MSB->LSB operation */ + outb(0xc1, wc->ioaddr + WC_SERCTL); + + /* Delay FSC by 0 so it's properly aligned */ + outb(0x0, wc->ioaddr + WC_FSCDELAY); + + /* Setup DMA Addresses */ + outl(wc->writedma, wc->ioaddr + WC_DMAWS); /* Write start */ + outl(wc->writedma + ZT_CHUNKSIZE * 4 - 4, wc->ioaddr + WC_DMAWI); /* Middle (interrupt) */ + outl(wc->writedma + ZT_CHUNKSIZE * 8 - 4, wc->ioaddr + WC_DMAWE); /* End */ + + outl(wc->readdma, wc->ioaddr + WC_DMARS); /* Read start */ + outl(wc->readdma + ZT_CHUNKSIZE * 4 - 4, wc->ioaddr + WC_DMARI); /* Middle (interrupt) */ + outl(wc->readdma + ZT_CHUNKSIZE * 8 - 4, wc->ioaddr + WC_DMARE); /* End */ + + /* Clear interrupts */ + outb(0xff, wc->ioaddr + WC_INTSTAT); + + /* Wait 1/4 of a second more */ + wait_just_a_bit(HZ/4); + + for (x = 0; x < NUM_CARDS; x++) { + int sane=0,ret=0,readi=0; +#if 1 + /* Init with Auto Calibration */ + if (!(ret=wctdm_init_proslic(wc, x, 0, 0, sane))) { + wc->cardflag |= (1 << x); + if (debug) { + readi = wctdm_getreg(wc,x,LOOP_I_LIMIT); + printk("Proslic module %d loop current is %dmA\n",x, + ((readi*3)+20)); + } + printk("Module %d: Installed -- AUTO FXS/DPO\n",x); + } else { + if(ret!=-2) { + sane=1; + /* Init with Manual Calibration */ + if (!wctdm_init_proslic(wc, x, 0, 1, sane)) { + wc->cardflag |= (1 << x); + if (debug) { + readi = wctdm_getreg(wc,x,LOOP_I_LIMIT); + printk("Proslic module %d loop current is %dmA\n",x, + ((readi*3)+20)); + } + printk("Module %d: Installed -- MANUAL FXS\n",x); + } else { + printk("Module %d: FAILED FXS (%s)\n", x, fxshonormode ? fxo_modes[_opermode].name : "FCC"); + wc->chans[x].sigcap = __ZT_SIG_FXO | ZT_SIG_BROKEN; + } + } else if (!(ret = wctdm_init_voicedaa(wc, x, 0, 0, sane))) { + wc->cardflag |= (1 << x); + printk("Module %d: Installed -- AUTO FXO (%s mode)\n",x, fxo_modes[_opermode].name); + } else + printk("Module %d: Not installed\n", x); + } +#endif + } + + /* Return error if nothing initialized okay. */ + if (!wc->cardflag && !timingonly) + return -1; + __wctdm_setcreg(wc, WC_SYNC, (wc->cardflag << 1) | 0x1); + return 0; +} + +static void wctdm_enable_interrupts(struct wctdm *wc) +{ + /* Enable interrupts (we care about all of them) */ + outb(0x3f, wc->ioaddr + WC_MASK0); + /* No external interrupts */ + outb(0x00, wc->ioaddr + WC_MASK1); +} + +static void wctdm_restart_dma(struct wctdm *wc) +{ + /* Reset Master and TDM */ + outb(0x01, wc->ioaddr + WC_CNTL); + outb(0x01, wc->ioaddr + WC_OPER); +} + +static void wctdm_start_dma(struct wctdm *wc) +{ + /* Reset Master and TDM */ + outb(0x0f, wc->ioaddr + WC_CNTL); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + outb(0x01, wc->ioaddr + WC_CNTL); + outb(0x01, wc->ioaddr + WC_OPER); +} + +static void wctdm_stop_dma(struct wctdm *wc) +{ + outb(0x00, wc->ioaddr + WC_OPER); +} + +static void wctdm_reset_tdm(struct wctdm *wc) +{ + /* Reset TDM */ + outb(0x0f, wc->ioaddr + WC_CNTL); +} + +static void wctdm_disable_interrupts(struct wctdm *wc) +{ + outb(0x00, wc->ioaddr + WC_MASK0); + outb(0x00, wc->ioaddr + WC_MASK1); +} + +static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int res; + struct wctdm *wc; + struct wctdm_desc *d = (struct wctdm_desc *)ent->driver_data; + int x; + int y; + + for (x=0;x= WC_MAX_IFACES) { + printk("Too many interfaces\n"); + return -EIO; + } + + if (pci_enable_device(pdev)) { + res = -EIO; + } else { + wc = kmalloc(sizeof(struct wctdm), GFP_KERNEL); + if (wc) { + int cardcount = 0; + + ifaces[x] = wc; + memset(wc, 0, sizeof(struct wctdm)); + spin_lock_init(&wc->lock); + wc->curcard = -1; + wc->ioaddr = pci_resource_start(pdev, 0); + wc->dev = pdev; + wc->pos = x; + wc->variety = d->name; + for (y=0;yflags[y] = d->flags; + /* Keep track of whether we need to free the region */ + if (request_region(wc->ioaddr, 0xff, "wctdm")) + wc->freeregion = 1; + + /* Allocate enough memory for two zt chunks, receive and transmit. Each sample uses + 32 bits. Allocate an extra set just for control too */ + wc->writechunk = pci_alloc_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, &wc->writedma); + if (!wc->writechunk) { + printk("wctdm: Unable to allocate DMA-able memory\n"); + if (wc->freeregion) + release_region(wc->ioaddr, 0xff); + return -ENOMEM; + } + + wc->readchunk = wc->writechunk + ZT_MAX_CHUNKSIZE * 2; /* in doublewords */ + wc->readdma = wc->writedma + ZT_MAX_CHUNKSIZE * 8; /* in bytes */ + + if (wctdm_initialize(wc)) { + printk("wctdm: Unable to intialize FXS\n"); + /* Set Reset Low */ + x=inb(wc->ioaddr + WC_CNTL); + outb((~0x1)&x, wc->ioaddr + WC_CNTL); + /* Free Resources */ + free_irq(pdev->irq, wc); + if (wc->freeregion) + release_region(wc->ioaddr, 0xff); + pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma); + kfree(wc); + return -EIO; + } + + /* Enable bus mastering */ + pci_set_master(pdev); + + /* Keep track of which device we are */ + pci_set_drvdata(pdev, wc); + + if (request_irq(pdev->irq, wctdm_interrupt, ZAP_IRQ_SHARED, "wctdm", wc)) { + printk("wctdm: Unable to request IRQ %d\n", pdev->irq); + if (wc->freeregion) + release_region(wc->ioaddr, 0xff); + pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma); + pci_set_drvdata(pdev, NULL); + kfree(wc); + return -EIO; + } + + + if (wctdm_hardware_init(wc)) { + unsigned char x; + + /* Set Reset Low */ + x=inb(wc->ioaddr + WC_CNTL); + outb((~0x1)&x, wc->ioaddr + WC_CNTL); + /* Free Resources */ + free_irq(pdev->irq, wc); + if (wc->freeregion) + release_region(wc->ioaddr, 0xff); + pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma); + pci_set_drvdata(pdev, NULL); + zt_unregister(&wc->span); + kfree(wc); + return -EIO; + + } + + wctdm_post_initialize(wc); + + /* Enable interrupts */ + wctdm_enable_interrupts(wc); + /* Initialize Write/Buffers to all blank data */ + memset((void *)wc->writechunk,0,ZT_MAX_CHUNKSIZE * 2 * 2 * 4); + + /* Start DMA */ + wctdm_start_dma(wc); + + for (x = 0; x < NUM_CARDS; x++) { + if (wc->cardflag & (1 << x)) + cardcount++; + } + + printk("Found a Wildcard TDM: %s (%d modules)\n", wc->variety, cardcount); + res = 0; + } else + res = -ENOMEM; + } + return res; +} + +static void wctdm_release(struct wctdm *wc) +{ + zt_unregister(&wc->span); + if (wc->freeregion) + release_region(wc->ioaddr, 0xff); + kfree(wc); + printk("Freed a Wildcard\n"); +} + +static void __devexit wctdm_remove_one(struct pci_dev *pdev) +{ + struct wctdm *wc = pci_get_drvdata(pdev); + if (wc) { + + /* Stop any DMA */ + wctdm_stop_dma(wc); + wctdm_reset_tdm(wc); + + /* In case hardware is still there */ + wctdm_disable_interrupts(wc); + + /* Immediately free resources */ + pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma); + free_irq(pdev->irq, wc); + + /* Reset PCI chip and registers */ + outb(0x0e, wc->ioaddr + WC_CNTL); + + /* Release span, possibly delayed */ + if (!wc->usecount) + wctdm_release(wc); + else + wc->dead = 1; + } +} + +static struct pci_device_id wctdm_pci_tbl[] = { + { 0xe159, 0x0001, 0xa159, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm }, + { 0xe159, 0x0001, 0xe159, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm }, + { 0xe159, 0x0001, 0xb100, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme }, + { 0xe159, 0x0001, 0xb1d9, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmi }, + { 0xe159, 0x0001, 0xb118, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmi }, + { 0xe159, 0x0001, 0xb119, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmi }, + { 0xe159, 0x0001, 0xa9fd, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, + { 0xe159, 0x0001, 0xa8fd, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, + { 0xe159, 0x0001, 0xa800, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, + { 0xe159, 0x0001, 0xa801, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, + { 0xe159, 0x0001, 0xa908, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, + { 0xe159, 0x0001, 0xa901, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, +#ifdef TDM_REVH_MATCHALL + { 0xe159, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, +#endif + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, wctdm_pci_tbl); + +static struct pci_driver wctdm_driver = { + name: "wctdm", + probe: wctdm_init_one, +#ifdef LINUX26 + remove: __devexit_p(wctdm_remove_one), +#else + remove: wctdm_remove_one, +#endif + suspend: NULL, + resume: NULL, + id_table: wctdm_pci_tbl, +}; + +static int __init wctdm_init(void) +{ + int res; + int x; + for (x=0;x<(sizeof(fxo_modes) / sizeof(fxo_modes[0])); x++) { + if (!strcmp(fxo_modes[x].name, opermode)) + break; + } + if (x < sizeof(fxo_modes) / sizeof(fxo_modes[0])) { + _opermode = x; + } else { + printk("Invalid/unknown operating mode '%s' specified. Please choose one of:\n", opermode); + for (x=0;x"); +#if defined(MODULE_ALIAS) +MODULE_ALIAS("wcfxs"); +#endif +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +module_init(wctdm_init); +module_exit(wctdm_cleanup); diff --git a/kernel/wctdm.h b/kernel/wctdm.h new file mode 100644 index 0000000..73703aa --- /dev/null +++ b/kernel/wctdm.h @@ -0,0 +1,69 @@ +/* + * Wilcard S100P FXS Interface Driver for Zapata Telephony interface + * + * Written by Mark Spencer + * + * Copyright (C) 2001, Linux Support Services, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _WCTDM_H +#define _WCTDM_H + +#include + +#define NUM_REGS 109 +#define NUM_INDIRECT_REGS 105 + +struct wctdm_stats { + int tipvolt; /* TIP voltage (mV) */ + int ringvolt; /* RING voltage (mV) */ + int batvolt; /* VBAT voltage (mV) */ +}; + +struct wctdm_regs { + unsigned char direct[NUM_REGS]; + unsigned short indirect[NUM_INDIRECT_REGS]; +}; + +struct wctdm_regop { + int indirect; + unsigned char reg; + unsigned short val; +}; + +struct wctdm_echo_coefs { + unsigned char acim; + unsigned char coef1; + unsigned char coef2; + unsigned char coef3; + unsigned char coef4; + unsigned char coef5; + unsigned char coef6; + unsigned char coef7; + unsigned char coef8; +}; + +#define WCTDM_GET_STATS _IOR (ZT_CODE, 60, struct wctdm_stats) +#define WCTDM_GET_REGS _IOR (ZT_CODE, 61, struct wctdm_regs) +#define WCTDM_SET_REG _IOW (ZT_CODE, 62, struct wctdm_regop) +#define WCTDM_SET_ECHOTUNE _IOW (ZT_CODE, 63, struct wctdm_echo_coefs) + + +#endif /* _WCTDM_H */ diff --git a/kernel/wctdm24xxp/GpakApi.c b/kernel/wctdm24xxp/GpakApi.c new file mode 100644 index 0000000..abdb09f --- /dev/null +++ b/kernel/wctdm24xxp/GpakApi.c @@ -0,0 +1,1636 @@ +/* + * Copyright (c) 2005, Adaptive Digital Technologies, Inc. + * + * File Name: GpakApi.c + * + * Description: + * This file contains user API functions to communicate with DSPs executing + * G.PAK software. The file is integrated into the host processor connected + * to C55X G.PAK DSPs via a Host Port Interface. + * + * Version: 1.0 + * + * Revision History: + * 06/15/05 - Initial release. + * 11/15/2006 - 24 TDM-TDM Channels EC release + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. The standard + * GPL disclaimer is given inline below for your convenience. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include "zaptel.h" + +#include "GpakHpi.h" +#include "GpakCust.h" +#include "GpakApi.h" +#include "gpakenum.h" + +/* DSP to Host interface block offsets. */ +#define REPLY_MSG_PNTR_OFFSET 0 /* I/F blk offset to Reply Msg Pointer */ +#define CMD_MSG_PNTR_OFFSET 2 /* I/F blk offset to Command Msg Pointer */ +#define EVENT_MSG_PNTR_OFFSET 4 /* I/F blk offset to Event Msg Pointer */ +#define PKT_BUFR_MEM_OFFSET 6 /* I/F blk offset to Packet Buffer memory */ +#define DSP_STATUS_OFFSET 8 /* I/F blk offset to DSP Status */ +#define VERSION_ID_OFFSET 9 /* I/F blk offset to G.PAK Version Id */ +#define MAX_CMD_MSG_LEN_OFFSET 10 /* I/F blk offset to Max Cmd Msg Length */ +#define CMD_MSG_LEN_OFFSET 11 /* I/F blk offset to Command Msg Length */ +#define REPLY_MSG_LEN_OFFSET 12 /* I/F blk offset to Reply Msg Length */ +#define NUM_CHANNELS_OFFSET 13 /* I/F blk offset to Num Built Channels */ +#define NUM_PKT_CHANNELS_OFFSET 14 /* I/F blk offset to Num Pkt Channels */ +#define NUM_CONFERENCES_OFFSET 15 /* I/F blk offset to Num Conferences */ +//#define CPU_USAGE_OFFSET_1MS 16 /* I/F blk offset to CPU Usage statistics */ +#define CPU_USAGE_OFFSET 18 /* I/F blk offset to CPU Usage statistics */ +//#define CPU_USAGE_OFFSET_10MS 20 /* I/F blk offset to CPU Usage statistics */ +#define FRAMING_STATS_OFFSET 22 /* I/F blk offset to Framing statistics */ + +//#define GPAK_RELEASE_Rate rate10ms +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// Macro to reconstruct a 32-bit value from two 16-bit values. +// Parameter p32: 32-bit-wide destination +// Parameter p16: 16-bit-wide source array of length 2 words +#define RECONSTRUCT_LONGWORD(p32, p16) p32 = (DSP_ADDRESS)p16[0]<<16; \ + p32 |= (unsigned long)p16[1] +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +/* DSP Status value definitions. */ +#define DSP_INIT_STATUS 0x5555 /* DSP Initialized status value */ +#define HOST_INIT_STATUS 0xAAAA /* Host Initialized status value */ + +/* Circular packet buffer information structure offsets. */ +#define CB_BUFR_BASE 0 /* pointer to base of circular buffer */ +#define CB_BUFR_SIZE 2 /* size of buffer (words) */ +#define CB_BUFR_PUT_INDEX 3 /* offset in buffer for next write */ +#define CB_BUFR_TAKE_INDEX 4 /* offset in buffer for next read */ +#define CIRC_BUFFER_INFO_STRUCT_SIZE 6 + +/* Miscellaneous definitions. */ +#define MSG_BUFFER_SIZE 100 /* size (words) of Host msg buffer */ +#define WORD_BUFFER_SIZE 84 /* size of DSP Word buffer (words) */ + +#ifdef __TMS320C55XX__ // debug sections if not on host +#pragma DATA_SECTION(pDspIfBlk,"GPAKAPIDEBUG_SECT") +#pragma DATA_SECTION(MaxCmdMsgLen,"GPAKAPIDEBUG_SECT") +#pragma DATA_SECTION(MaxChannels,"GPAKAPIDEBUG_SECT") +#pragma DATA_SECTION(DlByteBufr,"GPAKAPIDEBUG_SECT") +#pragma DATA_SECTION(DlWordBufr,"GPAKAPIDEBUG_SECT") +#pragma DATA_SECTION(pEventFifoAddress,"GPAKAPIDEBUG_SECT") +#endif + +/* Host variables related to Host to DSP interface. */ +static DSP_ADDRESS pDspIfBlk[MAX_DSP_CORES]; /* DSP address of I/F block */ +static DSP_WORD MaxCmdMsgLen[MAX_DSP_CORES]; /* max Cmd msg length (octets) */ +static unsigned short int MaxChannels[MAX_DSP_CORES]; /* max num channels */ + +//static unsigned short int MaxPktChannels[MAX_DSP_CORES]; /* max num pkt channels */ +//static unsigned short int MaxConfs[MAX_DSP_CORES]; /* max num conferences */ +//static DSP_ADDRESS pPktInBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt In buffer */ +//static DSP_ADDRESS pPktOutBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt Out buffer */ +static DSP_ADDRESS pEventFifoAddress[MAX_DSP_CORES]; /* event fifo */ + +static unsigned char DlByteBufr[DOWNLOAD_BLOCK_SIZE * 2]; /* Dowload byte buf */ +static DSP_WORD DlWordBufr[DOWNLOAD_BLOCK_SIZE]; /* Dowload word buffer */ + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * CheckDspReset - Check if the DSP was reset. + * + * FUNCTION + * This function determines if the DSP was reset and is ready. If reset + * occurred, it reads interface parameters and calculates DSP addresses. + * + * RETURNS + * -1 = DSP is not ready. + * 0 = Reset did not occur. + * 1 = Reset occurred. + * + */ +static int CheckDspReset( + int DspId /* DSP Identifier (0 to MaxDSPCores-1) */ + ) +{ + DSP_ADDRESS IfBlockPntr; /* Interface Block pointer */ + DSP_WORD DspStatus; /* DSP Status */ + DSP_WORD DspChannels; /* number of DSP channels */ + DSP_WORD Temp[2]; +#if 0 + DSP_WORD DspConfs; /* number of DSP conferences */ + DSP_ADDRESS PktBufrMem; /* address of Packet Buffer */ + unsigned short int i; /* loop index / counter */ +#endif + + /* Read the pointer to the Interface Block. */ + gpakReadDspMemory(DspId, DSP_IFBLK_ADDRESS, 2, Temp); + RECONSTRUCT_LONGWORD(IfBlockPntr, Temp); + + /* If the pointer is zero, return with an indication the DSP is not + ready. */ + if (IfBlockPntr == 0) + return (-1); + + /* Read the DSP's Status. */ + gpakReadDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, &DspStatus); + + /* If status indicates the DSP was reset, read the DSP's interface + parameters and calculate DSP addresses. */ + if (DspStatus == DSP_INIT_STATUS || + ((DspStatus == HOST_INIT_STATUS) && (pDspIfBlk[DspId] == 0))) + { + /* Save the address of the DSP's Interface Block. */ + pDspIfBlk[DspId] = IfBlockPntr; + + /* Read the DSP's interface parameters. */ + gpakReadDspMemory(DspId, IfBlockPntr + MAX_CMD_MSG_LEN_OFFSET, 1, + &(MaxCmdMsgLen[DspId])); + + /* read the number of configured DSP channels */ + gpakReadDspMemory(DspId, IfBlockPntr + NUM_CHANNELS_OFFSET, 1, + &DspChannels); + if (DspChannels > MAX_CHANNELS) + MaxChannels[DspId] = MAX_CHANNELS; + else + MaxChannels[DspId] = (unsigned short int) DspChannels; +#if 0 + /* read the number of configured DSP conferences */ + gpakReadDspMemory(DspId, IfBlockPntr + NUM_CONFERENCES_OFFSET, 1, + &DspConfs); + if (DspConfs > MAX_CONFS) + MaxConfs[DspId] = MAX_CONFS; + else + MaxConfs[DspId] = (unsigned short int) DspConfs; + + + /* read the number of configured DSP packet channels */ + gpakReadDspMemory(DspId, IfBlockPntr + NUM_PKT_CHANNELS_OFFSET, 1, + &DspChannels); + if (DspChannels > MAX_PKT_CHANNELS) + MaxPktChannels[DspId] = MAX_PKT_CHANNELS; + else + MaxPktChannels[DspId] = (unsigned short int) DspChannels; + + + /* read the pointer to the circular buffer infor struct table */ + gpakReadDspMemory(DspId, IfBlockPntr + PKT_BUFR_MEM_OFFSET, 2, Temp); + RECONSTRUCT_LONGWORD(PktBufrMem, Temp); + + + /* Determine the addresses of each channel's Packet buffers. */ + for (i = 0; i < MaxPktChannels[DspId]; i++) + { + pPktInBufr[DspId][i] = PktBufrMem; + pPktOutBufr[DspId][i] = PktBufrMem + CIRC_BUFFER_INFO_STRUCT_SIZE; + PktBufrMem += (CIRC_BUFFER_INFO_STRUCT_SIZE*2); + } +#endif + + /* read the pointer to the event fifo info struct */ + gpakReadDspMemory(DspId, IfBlockPntr + EVENT_MSG_PNTR_OFFSET, 2, Temp); + RECONSTRUCT_LONGWORD(pEventFifoAddress[DspId], Temp); + + /* Set the DSP Status to indicate the host recognized the reset. */ + DspStatus = HOST_INIT_STATUS; + gpakWriteDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, + &DspStatus); + + /* Return with an indication that a reset occurred. */ + return (1); + } + + /* If status doesn't indicate the host recognized a reset, return with an + indication the DSP is not ready. */ + if ((DspStatus != HOST_INIT_STATUS) || (pDspIfBlk[DspId] == 0)) + return (-1); + + /* Return with an indication that a reset did not occur. */ + return (0); +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * WriteDspCmdMessage - Write a Host Command/Request message to DSP. + * + * FUNCTION + * This function writes a Host Command/Request message into DSP memory and + * informs the DSP of the presence of the message. + * + * RETURNS + * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) + * 0 = Temporarily unable to write message (previous Cmd Msg busy) + * 1 = Message written successfully + * + */ +static int WriteDspCmdMessage( + int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ + DSP_WORD *pMessage, /* pointer to Command message */ + DSP_WORD MsgLength /* length of message (octets) */ + ) +{ + DSP_WORD CmdMsgLength; /* current Cmd message length */ + DSP_WORD Temp[2]; + DSP_ADDRESS BufferPointer; /* message buffer pointer */ + + /* Check if the DSP was reset and is ready. */ + if (CheckDspReset(DspId) == -1) + return (-1); + + /* Make sure the message length is valid. */ + if ((MsgLength < 1) || (MsgLength > MaxCmdMsgLen[DspId])) + return (-1); + + /* Make sure a previous Command message is not in use by the DSP. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, + &CmdMsgLength); + if (CmdMsgLength != 0) + return (0); + + /* Purge any previous Reply message that wasn't read. */ + gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, + &CmdMsgLength); + + /* Copy the Command message into DSP memory. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_PNTR_OFFSET, 2, Temp); + RECONSTRUCT_LONGWORD(BufferPointer, Temp); + gpakWriteDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); + + /* Store the message length in DSP's Command message length (flags DSP that + a Command message is ready). */ + CmdMsgLength = MsgLength; + gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, + &CmdMsgLength); + + /* Return with an indication the message was written. */ + return (1); +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * ReadDspReplyMessage - Read a DSP Reply message from DSP. + * + * FUNCTION + * This function reads a DSP Reply message from DSP memory. + * + * RETURNS + * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) + * 0 = No message available (DSP Reply message empty) + * 1 = Message read successfully (message and length stored in variables) + * + */ +static int ReadDspReplyMessage( + int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ + DSP_WORD *pMessage, /* pointer to Reply message buffer */ + DSP_WORD *pMsgLength /* pointer to msg length var (octets) */ + ) +{ + DSP_WORD MsgLength; /* message length */ + DSP_ADDRESS BufferPointer; /* message buffer pointer */ + DSP_WORD Temp[2]; + + /* Check if the DSP was reset and is ready. */ + if (CheckDspReset(DspId) == -1) + return (-1); + + /* Check if a Reply message is ready. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, + &MsgLength); + if (MsgLength == 0) + return (0); + + /* Make sure the message length is valid. */ + if (MsgLength > *pMsgLength) + return (-1); + + /* Copy the Reply message from DSP memory. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_PNTR_OFFSET, 2, Temp); + RECONSTRUCT_LONGWORD(BufferPointer, Temp); + gpakReadDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); + + /* Store the message length in the message length variable. */ + *pMsgLength = MsgLength; + + /* Indicate a Reply message is not ready. */ + MsgLength = 0; + gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, + &MsgLength); + + /* Return with an indication the message was read. */ + return (1); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * ReadCircBuffer - Read from a DSP circular buffer. + * + * FUNCTION + * This function reads a block of words from a DSP circular buffer. The Take + * address is incremented by the number of words read adjusting for buffer + * wrap. + * + * RETURNS + * nothing + * + */ +static void ReadCircBuffer( + int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ + DSP_ADDRESS BufrBaseAddress, /* address of base of circular buffer */ + DSP_ADDRESS BufrLastAddress, /* address of last word in buffer */ + DSP_ADDRESS *TakeAddress, /* pointer to address in buffer for read */ + DSP_WORD *pWordBuffer, /* pointer to buffer for words read */ + DSP_WORD NumWords /* number of words to read */ + ) +{ + DSP_WORD WordsTillEnd; /* number of words until end of buffer */ + + /* Determine the number of words from the start address until the end of the + buffer. */ + WordsTillEnd = BufrLastAddress - *TakeAddress + 1; + + /* If a buffer wrap will occur, read the first part at the end of the + buffer followed by the second part at the beginning of the buffer. */ + if (NumWords > WordsTillEnd) + { + gpakReadDspMemory(DspId, *TakeAddress, WordsTillEnd, pWordBuffer); + gpakReadDspMemory(DspId, BufrBaseAddress, NumWords - WordsTillEnd, + &(pWordBuffer[WordsTillEnd])); + *TakeAddress = BufrBaseAddress + NumWords - WordsTillEnd; + } + + /* If a buffer wrap will not occur, read all words starting at the current + take address in the buffer. */ + else + { + gpakReadDspMemory(DspId, *TakeAddress, NumWords, pWordBuffer); + if (NumWords == WordsTillEnd) + *TakeAddress = BufrBaseAddress; + else + *TakeAddress = *TakeAddress + NumWords; + } + return; +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * VerifyReply - Verify the reply message is correct for the command sent. + * + * FUNCTION + * This function verifies correct reply message content for the command that + * was just sent. + * + * RETURNS + * 0 = Incorrect + * 1 = Correct + * + */ +static int VerifyReply( + DSP_WORD *pMsgBufr, /* pointer to Reply message buffer */ + int CheckType, /* reply check type */ + DSP_WORD CheckValue /* reply check value */ + ) +{ + + /* Verify Channel or Conference Id. */ + if (CheckType == 1) + { + if (((pMsgBufr[1] >> 8) & 0xFF) != CheckValue) + return (0); + } + + /* Verify Test Mode Id. */ + else if (CheckType == 2) + { + if (pMsgBufr[1] != CheckValue) + return (0); + } + + /* Return with an indication of correct reply. */ + return (1); +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * TransactCmd - Send a command to the DSP and receive it's reply. + * + * FUNCTION + * This function sends the specified command to the DSP and receives the DSP's + * reply. + * + * RETURNS + * Length of reply message (0 = Failure) + * + */ +static unsigned int TransactCmd( + int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ + DSP_WORD *pMsgBufr, /* pointer to Cmd/Reply message buffer */ + DSP_WORD CmdLength, /* length of command message (octets) */ + DSP_WORD ReplyType, /* required type of reply message */ + DSP_WORD ReplyLength, /* required length of reply message (octets) */ + int ReplyCheckType, /* reply check type */ + DSP_WORD ReplyCheckValue /* reply check value */ + ) +{ + int FuncStatus; /* function status */ + int LoopCount; /* wait loop counter */ + DSP_WORD RcvReplyLength; /* received Reply message length */ + DSP_WORD RcvReplyType; /* received Reply message type code */ + DSP_WORD RetValue; /* return value */ + + /* Default the return value to indicate a failure. */ + RetValue = 0; + + /* Lock access to the DSP. */ + gpakLockAccess(DspId); + + /* Attempt to write the command message to the DSP. */ + LoopCount = 0; + while ((FuncStatus = WriteDspCmdMessage(DspId, pMsgBufr, CmdLength)) != 1) + { + if (FuncStatus == -1) + break; + if (++LoopCount > MAX_WAIT_LOOPS) + break; + gpakHostDelay(); + } + + /* Attempt to read the reply message from the DSP if the command message was + sent successfully. */ + if (FuncStatus == 1) + { + for (LoopCount = 0; LoopCount < MAX_WAIT_LOOPS; LoopCount++) + { + RcvReplyLength = MSG_BUFFER_SIZE * 2; + FuncStatus = ReadDspReplyMessage(DspId, pMsgBufr, &RcvReplyLength); + if (FuncStatus == 1) + { + RcvReplyType = (pMsgBufr[0] >> 8) & 0xFF; + if ((RcvReplyLength >= ReplyLength) && + (RcvReplyType == ReplyType) && + VerifyReply(pMsgBufr, ReplyCheckType, ReplyCheckValue)) + { + RetValue = RcvReplyLength; + break; + } + else if (RcvReplyType == MSG_NULL_REPLY) + break; + } + else if (FuncStatus == -1) + break; + gpakHostDelay(); + } + } + + /* Unlock access to the DSP. */ + gpakUnlockAccess(DspId); + + /* Return the length of the reply message (0 = failure). */ + return (RetValue); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakConfigurePorts - Configure a DSP's serial ports. + * + * FUNCTION + * This function configures a DSP's serial ports. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakConfigPortStatus_t gpakConfigurePorts( + unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ + GpakPortConfig_t *pPortConfig, /* pointer to Port Config info */ + GPAK_PortConfigStat_t *pStatus /* pointer to Port Config Status */ + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (CpsInvalidDsp); + + /* Build the Configure Serial Ports message. */ + MsgBuffer[0] = MSG_CONFIGURE_PORTS << 8; + MsgBuffer[1] = (DSP_WORD) + ((pPortConfig->SlotsSelect1 << 12) | + ((pPortConfig->FirstBlockNum1 << 8) & 0x0F00) | + ((pPortConfig->SecBlockNum1 << 4) & 0x00F0)); + MsgBuffer[2] = (DSP_WORD) pPortConfig->FirstSlotMask1; + MsgBuffer[3] = (DSP_WORD) pPortConfig->SecSlotMask1; + MsgBuffer[4] = (DSP_WORD) + ((pPortConfig->SlotsSelect2 << 12) | + ((pPortConfig->FirstBlockNum2 << 8) & 0x0F00) | + ((pPortConfig->SecBlockNum2 << 4) & 0x00F0)); + MsgBuffer[5] = (DSP_WORD) pPortConfig->FirstSlotMask2; + MsgBuffer[6] = (DSP_WORD) pPortConfig->SecSlotMask2; + MsgBuffer[7] = (DSP_WORD) + ((pPortConfig->SlotsSelect3 << 12) | + ((pPortConfig->FirstBlockNum3 << 8) & 0x0F00) | + ((pPortConfig->SecBlockNum3 << 4) & 0x00F0)); + MsgBuffer[8] = (DSP_WORD) pPortConfig->FirstSlotMask3; + MsgBuffer[9] = (DSP_WORD) pPortConfig->SecSlotMask3; + + MsgBuffer[10] = (DSP_WORD) + (((pPortConfig->DxDelay1 << 11) & 0x0800) | + ((pPortConfig->RxDataDelay1 << 9) & 0x0600) | + ((pPortConfig->TxDataDelay1 << 7) & 0x0180) | + ((pPortConfig->RxClockPolarity1 << 6) & 0x0040) | + ((pPortConfig->TxClockPolarity1 << 5) & 0x0020) | + ((pPortConfig->RxFrameSyncPolarity1 << 4) & 0x0010) | + ((pPortConfig->TxFrameSyncPolarity1 << 3) & 0x0008) | + ((pPortConfig->CompandingMode1 << 1) & 0x0006) | + (pPortConfig->SerialWordSize1 & 0x0001)); + + MsgBuffer[11] = (DSP_WORD) + (((pPortConfig->DxDelay2 << 11) & 0x0800) | + ((pPortConfig->RxDataDelay2 << 9) & 0x0600) | + ((pPortConfig->TxDataDelay2 << 7) & 0x0180) | + ((pPortConfig->RxClockPolarity2 << 6) & 0x0040) | + ((pPortConfig->TxClockPolarity2 << 5) & 0x0020) | + ((pPortConfig->RxFrameSyncPolarity2 << 4) & 0x0010) | + ((pPortConfig->TxFrameSyncPolarity2 << 3) & 0x0008) | + ((pPortConfig->CompandingMode2 << 1) & 0x0006) | + (pPortConfig->SerialWordSize1 & 0x0001)); + + MsgBuffer[12] = (DSP_WORD) + (((pPortConfig->DxDelay3 << 11) & 0x0800) | + ((pPortConfig->RxDataDelay3 << 9) & 0x0600) | + ((pPortConfig->TxDataDelay3 << 7) & 0x0180) | + ((pPortConfig->RxClockPolarity3 << 6) & 0x0040) | + ((pPortConfig->TxClockPolarity3 << 5) & 0x0020) | + ((pPortConfig->RxFrameSyncPolarity3 << 4) & 0x0010) | + ((pPortConfig->TxFrameSyncPolarity3 << 3) & 0x0008) | + ((pPortConfig->CompandingMode3 << 1) & 0x0006) | + (pPortConfig->SerialWordSize3 & 0x0001)); + + MsgBuffer[13] = (DSP_WORD) pPortConfig->ThirdSlotMask1; + MsgBuffer[14] = (DSP_WORD) pPortConfig->FouthSlotMask1; + MsgBuffer[15] = (DSP_WORD) pPortConfig->FifthSlotMask1; + MsgBuffer[16] = (DSP_WORD) pPortConfig->SixthSlotMask1; + MsgBuffer[17] = (DSP_WORD) pPortConfig->SevenSlotMask1; + MsgBuffer[18] = (DSP_WORD) pPortConfig->EightSlotMask1; + + MsgBuffer[19] = (DSP_WORD) pPortConfig->ThirdSlotMask2;; + MsgBuffer[20] = (DSP_WORD) pPortConfig->FouthSlotMask2; + MsgBuffer[21] = (DSP_WORD) pPortConfig->FifthSlotMask2;; + MsgBuffer[22] = (DSP_WORD) pPortConfig->SixthSlotMask2; + MsgBuffer[23] = (DSP_WORD) pPortConfig->SevenSlotMask2;; + MsgBuffer[24] = (DSP_WORD) pPortConfig->EightSlotMask2; + + MsgBuffer[25] = (DSP_WORD) pPortConfig->ThirdSlotMask3;; + MsgBuffer[26] = (DSP_WORD) pPortConfig->FouthSlotMask3; + MsgBuffer[27] = (DSP_WORD) pPortConfig->FifthSlotMask3;; + MsgBuffer[28] = (DSP_WORD) pPortConfig->SixthSlotMask3; + MsgBuffer[29] = (DSP_WORD) pPortConfig->SevenSlotMask3;; + MsgBuffer[30] = (DSP_WORD) pPortConfig->EightSlotMask3; + + + /* Attempt to send the Configure Serial Ports message to the DSP and receive + it's reply. */ + if (!TransactCmd(DspId, MsgBuffer, 62, MSG_CONFIG_PORTS_REPLY, 4, 0, 0)) + return (CpsDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + *pStatus = (GPAK_PortConfigStat_t) (MsgBuffer[1] & 0xFF); + if (*pStatus == Pc_Success) + return (CpsSuccess); + else + return (CpsParmError); +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakConfigureChannel - Configure a DSP's Channel. + * + * FUNCTION + * This function configures a DSP's Channel. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakConfigChanStatus_t gpakConfigureChannel( + unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ + unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ + GpakChanType ChannelType, /* Channel Type */ + GpakChannelConfig_t *pChanConfig, /* pointer to Channel Config info */ + GPAK_ChannelConfigStat_t *pStatus /* pointer to Channel Config Status */ + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD MsgLength; /* message length */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (CcsInvalidDsp); + + /* Make sure the Channel Id is valid. */ + if (ChannelId >= MaxChannels[DspId]) + return (CcsInvalidChannel); + + /* Build the Configure Channel message based on the Channel Type. */ + switch (ChannelType) + { + + /* PCM to Packet channel type. */ + case tdmToTdm: + + MsgBuffer[2] = (DSP_WORD) + ((pChanConfig->PcmInPortA << 8) | + (pChanConfig->PcmInSlotA & 0xFF)); + MsgBuffer[3] = (DSP_WORD) + ((pChanConfig->PcmOutPortA << 8) | + (pChanConfig->PcmOutSlotA & 0xFF)); + + MsgBuffer[4] = (DSP_WORD) + ((pChanConfig->PcmInPortB << 8) | + (pChanConfig->PcmInSlotB & 0xFF)); + MsgBuffer[5] = (DSP_WORD) + ((pChanConfig->PcmOutPortB << 8) | + (pChanConfig->PcmOutSlotB & 0xFF)); + + MsgBuffer[6] = (DSP_WORD) + ( + ((pChanConfig->FaxCngDetB <<11) & 0x0800) | + ((pChanConfig->FaxCngDetA <<10) & 0x0400) | + ((pChanConfig->MuteToneB << 9) & 0x0200) | + ((pChanConfig->MuteToneA << 8) & 0x0100) | + ((pChanConfig->FrameRate << 6) & 0x00C0) | + ((pChanConfig->ToneTypesB << 5) & 0x0020) | + ((pChanConfig->ToneTypesA << 4) & 0x0010) | + ((pChanConfig->SoftwareCompand & 3) << 2) | + (pChanConfig->EcanEnableB << 1) | + (pChanConfig->EcanEnableA & 1) + ); + + MsgBuffer[7] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanTapLength; + MsgBuffer[8] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNlpType; + MsgBuffer[9] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanAdaptEnable; + MsgBuffer[10] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanG165DetEnable; + MsgBuffer[11] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanDblTalkThresh; + MsgBuffer[12] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNlpThreshold; + MsgBuffer[13] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNlpConv; + MsgBuffer[14] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNlpUnConv; + MsgBuffer[15] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNlpMaxSuppress; + + MsgBuffer[16] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanCngThreshold; + MsgBuffer[17] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanAdaptLimit; + MsgBuffer[18] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanCrossCorrLimit; + MsgBuffer[19] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNumFirSegments; + MsgBuffer[20] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanFirSegmentLen; + + MsgBuffer[21] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanTapLength; + MsgBuffer[22] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNlpType; + MsgBuffer[23] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanAdaptEnable; + MsgBuffer[24] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanG165DetEnable; + MsgBuffer[25] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanDblTalkThresh; + MsgBuffer[26] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNlpThreshold; + MsgBuffer[27] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNlpConv; + MsgBuffer[28] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNlpUnConv; + MsgBuffer[29] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNlpMaxSuppress; + MsgBuffer[30] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanCngThreshold; + MsgBuffer[31] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanAdaptLimit; + MsgBuffer[32] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanCrossCorrLimit; + MsgBuffer[33] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNumFirSegments; + MsgBuffer[34] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanFirSegmentLen; + + MsgLength = 70; // byte number == 35*2 + break; + + + /* Unknown (invalid) channel type. */ + default: + *pStatus = Cc_InvalidChannelType; + return (CcsParmError); + } + + MsgBuffer[0] = MSG_CONFIGURE_CHANNEL << 8; + MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ChannelType & 0xFF)); + + /* Attempt to send the Configure Channel message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, MsgLength, MSG_CONFIG_CHAN_REPLY, 4, 1, + (DSP_WORD) ChannelId)) + return (CcsDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + *pStatus = (GPAK_ChannelConfigStat_t) (MsgBuffer[1] & 0xFF); + if (*pStatus == Cc_Success) + return (CcsSuccess); + else + return (CcsParmError); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakTearDownChannel - Tear Down a DSP's Channel. + * + * FUNCTION + * This function tears down a DSP's Channel. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakTearDownStatus_t gpakTearDownChannel( + unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ + unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ + GPAK_TearDownChanStat_t *pStatus /* pointer to Tear Down Status */ + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (TdsInvalidDsp); + + /* Make sure the Channel Id is valid. */ + if (ChannelId >= MaxChannels[DspId]) + return (TdsInvalidChannel); + + /* Build the Tear Down Channel message. */ + MsgBuffer[0] = MSG_TEAR_DOWN_CHANNEL << 8; + MsgBuffer[1] = (DSP_WORD) (ChannelId << 8); + + /* Attempt to send the Tear Down Channel message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, 3, MSG_TEAR_DOWN_REPLY, 4, 1, + (DSP_WORD) ChannelId)) + return (TdsDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + *pStatus = (GPAK_TearDownChanStat_t) (MsgBuffer[1] & 0xFF); + if (*pStatus == Td_Success) + return (TdsSuccess); + else + return (TdsError); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakAlgControl - Control an Algorithm. + * + * FUNCTION + * This function controls an Algorithm + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakAlgControlStat_t gpakAlgControl( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GpakAlgCtrl_t ControlCode, // algorithm control code + GPAK_AlgControlStat_t *pStatus // pointer to return status + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (AcInvalidDsp); + + /* Make sure the Channel Id is valid. */ + if (ChannelId >= MaxChannels[DspId]) + return (AcInvalidChannel); + + MsgBuffer[0] = MSG_ALG_CONTROL << 8; + MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ControlCode & 0xFF)); + + /* Attempt to send the Tear Down Channel message to the DSP and receive it's + reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ALG_CONTROL_REPLY, 4, 1, + (DSP_WORD) ChannelId)) + return (AcDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + *pStatus = (GPAK_AlgControlStat_t) (MsgBuffer[1] & 0xFF); + if (*pStatus == Ac_Success) + return (AcSuccess); + else + return (AcParmError); + +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadEventFIFOMessage - read from the event fifo + * + * FUNCTION + * This function reads a single event from the event fifo if one is available + * + * RETURNS + * Status code indicating success or a specific error. + * + * Notes: This function should be called in a loop until the return status + * indicates that the fifo is empty. + * + * If the event code equals "EventLoopbackTeardownComplete", then the + * contents of *pChannelId hold the coderBlockId that was assigned to + * the loopback coder that was torn down. + */ +gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( + unsigned short int DspId, // DSP identifier + unsigned short int *pChannelId, // pointer to channel identifier + GpakAsyncEventCode_t *pEventCode, // pointer to Event Code + GpakAsyncEventData_t *pEventData // pointer to Event Data Struct + ) +{ + DSP_WORD WordBuffer[WORD_BUFFER_SIZE]; /* DSP words buffer */ + GpakAsyncEventCode_t EventCode; /* DSP's event code */ + DSP_WORD EventDataLength; /* Length of event to read */ + DSP_WORD ChannelId; /* DSP's channel Id */ + DSP_ADDRESS EventInfoAddress; /* address of EventFIFO info structure */ + DSP_ADDRESS BufrBaseAddress; /* base address of EventFIFO buffer */ + DSP_ADDRESS BufrLastAddress; /* last address of EventFIFO buffer */ + DSP_ADDRESS TakeAddress; /* current take address in fifo buffer */ + DSP_WORD BufrSize; /* size (in words) of event FIFO buffer */ + DSP_WORD PutIndex; /* event fifo put index */ + DSP_WORD TakeIndex; /* event fifo take index */ + DSP_WORD WordsReady; /* number words ready for read out of event fifo */ + DSP_WORD EventError; /* flag indicating error with event fifo msg */ +#if 0 + DSP_WORD *pDebugData; /* debug data buffer pointer in event data struct */ +#endif + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) { +#if 0 + printk("Invalid DSP\n"); +#endif + return (RefInvalidDsp); + } + + /* Lock access to the DSP. */ + gpakLockAccess(DspId); + +#if 1 + /* Check if the DSP was reset and is ready. */ + if (CheckDspReset(DspId) == -1) + { + gpakUnlockAccess(DspId); +#if 0 + printk("CheckDspReset failed (DspId %d)\n", DspId); +#endif + return (RefDspCommFailure); + } +#endif + + /* Check if an event message is ready in the DSP. */ + EventInfoAddress = pEventFifoAddress[DspId]; + gpakReadDspMemory(DspId, EventInfoAddress, CIRC_BUFFER_INFO_STRUCT_SIZE, + WordBuffer); + RECONSTRUCT_LONGWORD(BufrBaseAddress, ((DSP_WORD *)&WordBuffer[CB_BUFR_BASE])); + BufrSize = WordBuffer[CB_BUFR_SIZE]; + PutIndex = WordBuffer[CB_BUFR_PUT_INDEX]; + TakeIndex = WordBuffer[CB_BUFR_TAKE_INDEX]; + if (PutIndex >= TakeIndex) + WordsReady = PutIndex - TakeIndex; + else + WordsReady = PutIndex + BufrSize - TakeIndex; + + if (WordsReady < 2) + { + gpakUnlockAccess(DspId); + return (RefNoEventAvail); + } + + /* Read the event header from the DSP's Event FIFO. */ + TakeAddress = BufrBaseAddress + TakeIndex; + BufrLastAddress = BufrBaseAddress + BufrSize - 1; + ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, + WordBuffer, 2); + TakeIndex += 2; + if (TakeIndex >= BufrSize) + TakeIndex -= BufrSize; + + ChannelId = (WordBuffer[0] >> 8) & 0xFF; + EventCode = (GpakAsyncEventCode_t)(WordBuffer[0] & 0xFF); + EventDataLength = WordBuffer[1]; + EventError = 0; + + switch (EventCode) + { + case EventToneDetect: + if (EventDataLength > WORD_BUFFER_SIZE) + { + gpakUnlockAccess(DspId); +#if 0 + printk("EventDataLength > WORD_BUFFER_SIZE (%d)\n", EventDataLength); +#endif + return (RefInvalidEvent); + } + ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, + WordBuffer, EventDataLength); + pEventData->toneEvent.ToneCode = (GpakToneCodes_t) + (WordBuffer[0] & 0xFF); + pEventData->toneEvent.ToneDuration = WordBuffer[1]; + pEventData->toneEvent.Direction = WordBuffer[2]; + pEventData->toneEvent.DebugToneStatus = WordBuffer[3]; + TakeIndex += EventDataLength; + if (TakeIndex >= BufrSize) + TakeIndex -= BufrSize; + if (EventDataLength != 4) { +#if 0 + printk("EventDataLength != 4 it's %d\n", EventDataLength); +#endif + EventError = 1; + } + break; + + default: +#if 0 + printk("Event Code not in switch\n"); +#endif + EventError = 1; + break; + }; + + /* Update the Take index in the DSP's Packet Out buffer information. */ + gpakWriteDspMemory(DspId, EventInfoAddress + CB_BUFR_TAKE_INDEX, 1, + &TakeIndex); + + /* Unlock access to the DSP. */ + gpakUnlockAccess(DspId); + + if (EventError) + return(RefInvalidEvent); + + *pChannelId = ChannelId; + *pEventCode = EventCode; + return(RefEventAvail); + +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakPingDsp - ping the DSP to see if it's alive + * + * FUNCTION + * This function checks if the DSP is still communicating with the host + * and returns the DSP SW version + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakPingDspStat_t gpakPingDsp( + unsigned short int DspId, // DSP identifier + unsigned short int *pDspSwVersion // DSP software version + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (PngInvalidDsp); + + /* send value of 1, DSP increments it */ + MsgBuffer[0] = (MSG_PING << 8); + + /* Attempt to send the ping message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, 1, MSG_PING_REPLY, 6, 0, 0)) + return (PngDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + { + *pDspSwVersion = MsgBuffer[2]; + return (PngSuccess); + } + else + return (PngDspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakSerialTxFixedValue - transmit a fixed value on a timeslot + * + * FUNCTION + * This function controls transmission of a fixed value out onto a serial + * port's timeslot. + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id + unsigned short int PcmOutSlot, // PCM Output Time Slot + unsigned short int Value, // 16-bit value + GpakActivation State // activation state + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (TfvInvalidDsp); + + /* Make sure the Channel Id is valid. */ + if (ChannelId >= MaxChannels[DspId]) + return (TfvInvalidChannel); + + + /* Build the message. */ + MsgBuffer[0] = MSG_SERIAL_TXVAL << 8; + MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (State & 0xFF)); + MsgBuffer[2] = (DSP_WORD) ((PcmOutPort << 8) | (PcmOutSlot & 0xFF)); + MsgBuffer[3] = (DSP_WORD) Value; + + /* Attempt to send the message to the DSP and receive it's + reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 8, MSG_SERIAL_TXVAL_REPLY, 4, + 1, ChannelId)) + return (TfvDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + return (TfvSuccess); + else + return (TfvDspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakControlTdmLoopBack - control a serial port's loopback state + * + * FUNCTION + * This function enables/disables the tdm input to output looback mode on a + * serial port + * + * RETURNS + * Status code indicating success or a specific error. + */ + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ +gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( + unsigned short int DspId, // DSP identifier + GpakSerialPort_t SerialPort, // Serial Port Id + GpakActivation LoopBackState // Loopback State + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (ClbInvalidDsp); + + /* Build the message. */ + MsgBuffer[0] = MSG_TDM_LOOPBACK << 8; + MsgBuffer[1] = (DSP_WORD) ((SerialPort << 8) | (LoopBackState & 0xFF)); + + /* Attempt to send the message to the DSP and receive it's + reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 4, MSG_TDM_LOOPBACK_REPLY, 4, 0, 0)) + return (ClbDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + return (ClbSuccess); + else + return (ClbDspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadCpuUsage - Read CPU usage statistics from a DSP. + * + * FUNCTION + * This function reads the CPU usage statistics from a DSP's memory. The + * average CPU usage in units of .1 percent are obtained for each of the frame + * rates. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakReadCpuUsageStat_t gpakReadCpuUsage( + unsigned short int DspId, // Dsp Identifier + unsigned short int *pPeakUsage, // pointer to peak usage variable + unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second + ) +{ + DSP_WORD ReadBuffer[2]; /* DSP read buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RcuInvalidDsp); + + /* Lock access to the DSP. */ + gpakLockAccess(DspId); + + /* Check if the DSP was reset and is ready. */ + if (CheckDspReset(DspId) == -1) + return (RcuDspCommFailure); + + /* Read the CPU Usage statistics from the DSP. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CPU_USAGE_OFFSET, 2, + ReadBuffer); + + /* Unlock access to the DSP. */ + gpakUnlockAccess(DspId); + + /* Store the usage statistics in the specified variables. */ + *pPrev1SecPeakUsage = ReadBuffer[0]; + *pPeakUsage = ReadBuffer[1]; + + /* Return with an indication the usage staistics were read successfully. */ + return (RcuSuccess); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakResetCpuUsageStats - reset the cpu usage statistics + * + * FUNCTION + * This function resets the cpu utilization statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakResetCpuUsageStat_t gpakResetCpuUsageStats( + unsigned short int DspId // DSP identifier + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RstcInvalidDsp); + + MsgBuffer[0] = (MSG_RESET_USAGE_STATS << 8); + + /* Attempt to send the message to the DSP and receive it's reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_USAGE_STATS_REPLY, 4, 0, 0)) + return (RstcDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + return (RstcSuccess); + else + return (RstcDspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadFramingStats + * + * FUNCTION + * This function reads a DSP's framing interrupt statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakReadFramingStatsStatus_t gpakReadFramingStats( + unsigned short int DspId, // DSP identifier + unsigned short int *pFramingError1Count, // port 1 Framing error count + unsigned short int *pFramingError2Count, // port 2 Framing error count + unsigned short int *pFramingError3Count, // port 3 Framing error count + unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count + unsigned short int *pDmaSlipStatsBuffer // DMA slips count + ) +{ + DSP_WORD ReadBuffer[10]; /* DSP read buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RfsInvalidDsp); + + /* Lock access to the DSP. */ + gpakLockAccess(DspId); + + /* Check if the DSP was reset and is ready. */ + if (CheckDspReset(DspId) == -1) + return (RfsDspCommFailure); + + /* Read the framing interrupt statistics from the DSP. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + FRAMING_STATS_OFFSET, 10, + ReadBuffer); + + /* Unlock access to the DSP. */ + gpakUnlockAccess(DspId); + + /* Store the framing statistics in the specified variables. */ + *pFramingError1Count = ReadBuffer[0]; + *pFramingError2Count = ReadBuffer[1]; + *pFramingError3Count = ReadBuffer[2]; + *pDmaStopErrorCount = ReadBuffer[3]; + + if(pDmaSlipStatsBuffer != 0) + // If users want to get the DMA slips count + { + pDmaSlipStatsBuffer[0] = ReadBuffer[4]; + pDmaSlipStatsBuffer[1] = ReadBuffer[5]; + pDmaSlipStatsBuffer[2] = ReadBuffer[6]; + pDmaSlipStatsBuffer[3] = ReadBuffer[7]; + pDmaSlipStatsBuffer[4] = ReadBuffer[8]; + pDmaSlipStatsBuffer[5] = ReadBuffer[9]; + + } + /* Return with an indication the statistics were read successfully. */ + return (RfsSuccess); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakResetFramingStats - reset a DSP's framing interrupt statistics + * + * FUNCTION + * This function resets a DSP's framing interrupt statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakResetFramingStatsStatus_t gpakResetFramingStats( + unsigned short int DspId // DSP identifier + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RstfInvalidDsp); + + MsgBuffer[0] = (MSG_RESET_FRAME_STATS << 8); + + /* Attempt to send the message to the DSP and receive it's reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_FRAME_STATS_REPLY, 4, 0, 0)) + return (RstfDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + return (RstfSuccess); + else + return (RstfDspCommFailure); +} + +/* + * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. + * + * FUNCTION + * This function reads a DSP's Program and Data memory image from the + * specified file and writes the image to the DSP's memory. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakDownloadStatus_t gpakDownloadDsp( + unsigned short DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ + GPAK_FILE_ID FileId /* G.PAK Download File Identifier */ + ) +{ + gpakDownloadStatus_t RetStatus; /* function return status */ + int NumRead; /* number of file bytes read */ + DSP_ADDRESS Address; /* DSP address */ + unsigned int WordCount; /* number of words in record */ + unsigned int NumWords; /* number of words to read/write */ + unsigned int i; /* loop index / counter */ + unsigned int j; /* loop index */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (GdlInvalidDsp); + + /* Lock access to the DSP. */ + gpakLockAccess(DspId); + + RetStatus = GdlSuccess; + while (RetStatus == GdlSuccess) + { + + /* Read a record header from the file. */ + NumRead = gpakReadFile(FileId, DlByteBufr, 6); + if (NumRead == -1) + { + RetStatus = GdlFileReadError; + break; + } + if (NumRead != 6) + { + RetStatus = GdlInvalidFile; + break; + } + Address = (((DSP_ADDRESS) DlByteBufr[1]) << 16) | + (((DSP_ADDRESS) DlByteBufr[2]) << 8) | + ((DSP_ADDRESS) DlByteBufr[3]); + WordCount = (((unsigned int) DlByteBufr[4]) << 8) | + ((unsigned int) DlByteBufr[5]); + + /* Check for the End Of File record. */ + if (DlByteBufr[0] == 0xFF) + break; + + /* Verify the record is for a valid memory type. */ + if ((DlByteBufr[0] != 0x00) && (DlByteBufr[0] != 0x01)) + { + RetStatus = GdlInvalidFile; + break; + } + + /* Read a block of words at a time from the file and write to the + DSP's memory .*/ + while (WordCount != 0) + { + if (WordCount < DOWNLOAD_BLOCK_SIZE) + NumWords = WordCount; + else + NumWords = DOWNLOAD_BLOCK_SIZE; + WordCount -= NumWords; + NumRead = gpakReadFile(FileId, DlByteBufr, NumWords * 2); + if (NumRead == -1) + { + RetStatus = GdlFileReadError; + break; + } + if (NumRead != (NumWords * 2)) + { + RetStatus = GdlInvalidFile; + break; + } + for (i = 0, j = 0; i < NumWords; i++, j += 2) + DlWordBufr[i] = (((DSP_WORD) DlByteBufr[j]) << 8) | + ((DSP_WORD) DlByteBufr[j + 1]); + gpakWriteDspMemory(DspId, Address, NumWords, DlWordBufr); + Address += ((DSP_ADDRESS) NumWords); + } + } + + /* Unlock access to the DSP. */ + gpakUnlockAccess(DspId); + + /* Return with an indication of success or failure. */ + return (RetStatus); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadCpuUsage - Read CPU usage statistics from a DSP. + * + * FUNCTION + * This function reads the memory map register section of DSP memory. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( + unsigned short int DspId, // Dsp Identifier + unsigned short int *pDest, // Buffer on host to hold DSP memory map + DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out + unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP reply's status */ + int i; /* loop index / counter */ + + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RmmInvalidDsp); + + /* Verify the message buffer is large enough */ + if (MSG_BUFFER_SIZE < MemoryLength_Word16 ) + return (RmmSizeTooBig); + + MsgBuffer[0] = MSG_READ_DSP_MEMORY << 8; + MsgBuffer[1] = (DSP_WORD) ((BufrBaseAddress >> 16) & 0xFFFF); + MsgBuffer[2] = (DSP_WORD) (BufrBaseAddress & 0xFFFF); + MsgBuffer[3] = (DSP_WORD) MemoryLength_Word16; + + /* Attempt to send the Read memory section message to the DSP and receive it's + reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 8, MSG_READ_DSP_MEMORY_REPLY, + (MemoryLength_Word16+2)*2, 0, 0) ) + return (RmmInvalidAddress); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus != 0) + return (RmmFailure); + + for (i = 0; i < MemoryLength_Word16; i++) + pDest[i] = (short int) MsgBuffer[2 + i]; + + + return (RmmSuccess); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakAccessGPIO - change Direction/read/write the GPIO on DSP + * + * FUNCTION + * This function read/write GPIO and change the GPIO direction + * + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakAccessGPIOStat_t gpakAccessGPIO( + unsigned short int DspId, // DSP identifier + GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read + unsigned short int *pGPIOValue // DSP software version + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (GPIOInvalidDsp); + + /* send value of 1, DSP increments it */ + MsgBuffer[0] = (MSG_ACCESSGPIO << 8); + MsgBuffer[1] = (DSP_WORD) ((gpakControlGPIO << 8) | (*pGPIOValue & 0xFF) ); + /* Attempt to send the ping message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ACCESSGPIO_REPLY, 6, 0, 0)) + return (GPIODspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + { + *pGPIOValue = MsgBuffer[2]; + return (GPIOSuccess); + } + else + return (GPIODspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakWriteSystemParms - Write a DSP's System Parameters. + * + * FUNCTION + * This function writes a DSP's System Parameters information. + * + * Note: + * Or-together the desired bit-mask #defines that are listed below. Only + * those algorithm parameters whose bit-mask is selected in the UpdateBits + * function parameter will be updated. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ + +gpakWriteSysParmsStatus_t gpakWriteSystemParms( + unsigned short int DspId, // DSP identifier + GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ + unsigned short int UpdateBits, /* input: flags indicating which parms to update */ + GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (WspInvalidDsp); + + /* Build the Write System Parameters message. */ + MsgBuffer[0] = MSG_WRITE_SYS_PARMS << 8; + + if (UpdateBits & DTMF_UPDATE_MASK) + { + MsgBuffer[1] |= DTMF_UPDATE_MASK; + MsgBuffer[8] = (DSP_WORD) pSysParms->MinSigLevel; + MsgBuffer[9] = (DSP_WORD) (pSysParms->FreqDeviation & 0xff); + if (pSysParms->SNRFlag) + MsgBuffer[9] |= (1<<8); + } + + MsgBuffer[10] = (DSP_WORD) 0; + if (UpdateBits & DTMF_TWIST_UPDATE_MASK) + { + MsgBuffer[1] |= DTMF_TWIST_UPDATE_MASK; + MsgBuffer[10] |= (DSP_WORD) (pSysParms->DtmfFwdTwist & 0x000f); + MsgBuffer[10] |= (DSP_WORD) ((pSysParms->DtmfRevTwist << 4) & 0x00f0); + } + + + if (UpdateBits & DTMF_VALID_MASK) + { + MsgBuffer[1] |= DTMF_VALID_MASK; + MsgBuffer[11] = (DSP_WORD) (pSysParms->DtmfValidityMask & 0x00ff); + } + + /* Attempt to send the ping message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, 24, MSG_WRITE_SYS_PARMS_REPLY, 6, 0, 0)) + return (WspDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + *pStatus = (GPAK_SysParmsStat_t) (MsgBuffer[2] ); + + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + return (WspSuccess); + else + return (WspDspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadSystemParms - Read a DSP's System Parameters. + * + * FUNCTION + * This function reads a DSP's System Parameters information. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakReadSysParmsStatus_t gpakReadSystemParms( + unsigned short int DspId, // DSP identifier + GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ + ) +{ + + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RspInvalidDsp); + + /* Build the Read System Parameters message. */ + MsgBuffer[0] = MSG_READ_SYS_PARMS << 8; + + /* Attempt to send the ping message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, 2, MSG_READ_SYS_PARMS_REPLY, 22, 0, 0)) + return (RspDspCommFailure); + + /* Extract the System Parameters information from the message. */ + pSysParms->DtmfValidityMask = (short int)(MsgBuffer[7]) ; + + pSysParms->MinSigLevel = (short int)MsgBuffer[8]; + pSysParms->SNRFlag = (short int)((MsgBuffer[9]>>8) & 0x1); + pSysParms->FreqDeviation = (short int)(MsgBuffer[9] & 0xff); + pSysParms->DtmfFwdTwist = (short int)MsgBuffer[10] & 0x000f; + pSysParms->DtmfRevTwist = (short int)(MsgBuffer[10] >> 4) & 0x000f; + + /* Return with an indication that System Parameters info was obtained. */ + return (RspSuccess); +} diff --git a/kernel/wctdm24xxp/GpakApi.h b/kernel/wctdm24xxp/GpakApi.h new file mode 100644 index 0000000..df57c09 --- /dev/null +++ b/kernel/wctdm24xxp/GpakApi.h @@ -0,0 +1,637 @@ +/* + * Copyright (c) 2005 , Adaptive Digital Technologies, Inc. + * + * File Name: GpakApi.h + * + * Description: + * This file contains the function prototypes and data types for the user + * API functions that communicate with DSPs executing G.PAK software. The + * file is used by application software in the host processor connected to + * C55X G.PAK DSPs via a Host Port Interface. + * + * Version: 1.0 + * + * Revision History: + * 06/15/05 - Initial release. + * 11/15/2006 - 24 TDM-TDM Channels EC release + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. The standard + * GPL disclaimer is given inline below for your convenience. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GPAKAPI_H /* prevent multiple inclusion */ +#define _GPAKAPI_H +#include "gpakErrs.h" +#include "gpakenum.h" + +// Bit masks to select which algorithm's parameters to update: Or-together the +// desired masks into the UpdateBits function parameter. +#define DTMF_UPDATE_MASK 0x0010 // update DTMF params, MinLevel, SNRFlag and Freq +#define DTMF_TWIST_UPDATE_MASK 0x0020 // update DTMF TWIST system params +#define DTMF_VALID_MASK 0x0080 // update DTMF ValidMask params + +#define DSP_DEBUG_BUFF_SIZE 42 // units of 16-bit words + +/* Definition of an Asynchronous Event Data Structure */ +typedef union +{ + struct + { + GpakToneCodes_t ToneCode; // detected tone code + unsigned short int ToneDuration; // tone duration + GpakTdmDirection Direction; // detected on A r B side + short int DebugToneStatus;// reserved for debug info + } toneEvent; + +} GpakAsyncEventData_t; + +/* Definition of an Echo Canceller Parameters information structure. */ +typedef struct +{ + short int EcanTapLength; // Echo Can Num Taps (tail length) + short int EcanNlpType; // Echo Can NLP Type + short int EcanAdaptEnable; // Echo Can Adapt Enable flag + short int EcanG165DetEnable; // Echo Can G165 Detect Enable flag + short int EcanDblTalkThresh; // Echo Can Double Talk threshold + short int EcanNlpThreshold; // Echo Can NLP threshold + short int EcanNlpConv; // Dynamic NLP control, NLP limit when EC about to converged + short int EcanNlpUnConv;// Dynamic NLP control, NLP limit when EC not converged yet + short int EcanNlpMaxSuppress; // suppression level for NLP_SUPP mode + short int EcanCngThreshold; // Echo Can CNG Noise threshold + short int EcanAdaptLimit; // Echo Can Max Adapts per frame + short int EcanCrossCorrLimit; // Echo Can Cross Correlation limit + short int EcanNumFirSegments; // Echo Can Num FIR Segments + short int EcanFirSegmentLen; // Echo Can FIR Segment Length +} GpakEcanParms_t; + +/* Definition of a Channel Configuration information structure. */ +typedef struct +{ + GpakSerialPort_t PcmInPortA; // A side PCM Input Serial Port Id + unsigned short int PcmInSlotA; // A side PCM Input Time Slot + GpakSerialPort_t PcmOutPortA; // A side PCM Output Serial Port Id + unsigned short int PcmOutSlotA; // A side PCM Output Time Slot + GpakSerialPort_t PcmInPortB; // B side PCM Input Serial Port Id + unsigned short int PcmInSlotB; // B side PCM Input Time Slot + GpakSerialPort_t PcmOutPortB; // B side PCM Output Serial Port Id + unsigned short int PcmOutSlotB; // B side PCM Output Time Slot + GpakToneTypes ToneTypesA; // A side Tone Detect Types + GpakToneTypes ToneTypesB; // B side Tone Detect Types + GpakActivation EcanEnableA; // Echo Cancel A Enabled + GpakActivation EcanEnableB; // Echo Cancel B Enabled + GpakEcanParms_t EcanParametersA; // Echo Cancel parameters + GpakEcanParms_t EcanParametersB; // Echo Cancel parameters + GpakCompandModes SoftwareCompand; // software companding + GpakRate_t FrameRate; // Gpak Frame Rate + GpakActivation MuteToneA; // A side mute DTMF Enabled + GpakActivation MuteToneB; // B side mute DTMF Enabled + GpakActivation FaxCngDetA; // A side FaxCng Tone Detector Enabled + GpakActivation FaxCngDetB; // B side FaxCng Tone Detector Enabled + +} GpakChannelConfig_t; + + +/* Definition of a Serial Port Configuration Structure */ +typedef struct +{ + GpakSlotCfg_t SlotsSelect1; // port 1 Slot selection + unsigned short int FirstBlockNum1; // port 1 first group Block Number + unsigned short int FirstSlotMask1; // port 1 first group Slot Mask + unsigned short int SecBlockNum1; // port 1 second group Block Number + unsigned short int SecSlotMask1; // port 1 second group Slot Mask + + GpakSerWordSize_t SerialWordSize1; // port 1 serial word size + GpakCompandModes CompandingMode1; // port 1 companding mode + GpakSerFrameSyncPol_t TxFrameSyncPolarity1; // port 1 Tx Frame Sync Polarity + GpakSerFrameSyncPol_t RxFrameSyncPolarity1; // port 1 Rx Frame Sync Polarity + GpakSerClockPol_t TxClockPolarity1; // port 1 Tx Clock Polarity + GpakSerClockPol_t RxClockPolarity1; // port 1 Rx Clock Polarity + GpakSerDataDelay_t TxDataDelay1; // port 1 Tx data delay + GpakSerDataDelay_t RxDataDelay1; // port 1 Rx data delay + GpakActivation DxDelay1; // port 1 DX Delay + + unsigned short int ThirdSlotMask1; // port 1 3rd group Slot Mask + unsigned short int FouthSlotMask1; // port 1 4th group Slot Mask + unsigned short int FifthSlotMask1; // port 1 5th group Slot Mask + unsigned short int SixthSlotMask1; // port 1 6th group Slot Mask + unsigned short int SevenSlotMask1; // port 1 7th group Slot Mask + unsigned short int EightSlotMask1; // port 1 8th group Slot Mask + + + GpakSlotCfg_t SlotsSelect2; // port 2 Slot selection + unsigned short int FirstBlockNum2; // port 2 first group Block Number + unsigned short int FirstSlotMask2; // port 2 first group Slot Mask + unsigned short int SecBlockNum2; // port 2 second group Block Number + unsigned short int SecSlotMask2; // port 2 second group Slot Mask + GpakSerWordSize_t SerialWordSize2; // port 2 serial word size + GpakCompandModes CompandingMode2; // port 2 companding mode + GpakSerFrameSyncPol_t TxFrameSyncPolarity2; // port 2 Tx Frame Sync Polarity + GpakSerFrameSyncPol_t RxFrameSyncPolarity2; // port 2 Rx Frame Sync Polarity + GpakSerClockPol_t TxClockPolarity2; // port 2 Tx Clock Polarity + GpakSerClockPol_t RxClockPolarity2; // port 2 Rx Clock Polarity + GpakSerDataDelay_t TxDataDelay2; // port 2 Tx data delay + GpakSerDataDelay_t RxDataDelay2; // port 2 Rx data delay + GpakActivation DxDelay2; // port 2 DX Delay + + unsigned short int ThirdSlotMask2; // port 2 3rd group Slot Mask + unsigned short int FouthSlotMask2; // port 2 4th group Slot Mask + unsigned short int FifthSlotMask2; // port 2 5th group Slot Mask + unsigned short int SixthSlotMask2; // port 2 6th group Slot Mask + unsigned short int SevenSlotMask2; // port 2 7th group Slot Mask + unsigned short int EightSlotMask2; // port 2 8th group Slot Mask + + GpakSlotCfg_t SlotsSelect3; // port 3 Slot selection + unsigned short int FirstBlockNum3; // port 3 first group Block Number + unsigned short int FirstSlotMask3; // port 3 first group Slot Mask + unsigned short int SecBlockNum3; // port 3 second group Block Number + unsigned short int SecSlotMask3; // port 3 second group Slot Mask + GpakSerWordSize_t SerialWordSize3; // port 3 serial word size + GpakCompandModes CompandingMode3; // port 3 companding mode + GpakSerFrameSyncPol_t TxFrameSyncPolarity3; // port 3 Tx Frame Sync Polarity + GpakSerFrameSyncPol_t RxFrameSyncPolarity3; // port 3 Rx Frame Sync Polarity + GpakSerClockPol_t TxClockPolarity3; // port 3 Tx Clock Polarity + GpakSerClockPol_t RxClockPolarity3; // port 3 Rx Clock Polarity + GpakSerDataDelay_t TxDataDelay3; // port 3 Tx data delay + GpakSerDataDelay_t RxDataDelay3; // port 3 Rx data delay + GpakActivation DxDelay3; // port 3 DX Delay + + unsigned short int ThirdSlotMask3; // port 3 3rd group Slot Mask + unsigned short int FouthSlotMask3; // port 3 4th group Slot Mask + unsigned short int FifthSlotMask3; // port 3 5th group Slot Mask + unsigned short int SixthSlotMask3; // port 3 6th group Slot Mask + unsigned short int SevenSlotMask3; // port 3 7th group Slot Mask + unsigned short int EightSlotMask3; // port 3 8th group Slot Mask + +} GpakPortConfig_t; + +/* Definition of a Tone Generation Parameter Structure */ +/* +typedef struct +{ + GpakToneGenType_t ToneType; // Tone Type + unsigned short int Frequency[4]; // Frequency (Hz) + short int Level[4]; // Frequency's Level (1 dBm) + unsigned short int OnTime[4]; // On Times (msecs) + unsigned short int OffTime[4]; // Off Times (msecs) +} GpakToneGenParms_t; +*/ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakConfigureChannel return status. */ +typedef enum +{ + CcsSuccess = 0, /* Channel Configured successfully */ + CcsParmError = 1, /* Channel Config Parameter error */ + CcsInvalidChannel = 2, /* invalid channel */ + CcsInvalidDsp = 3, /* invalid DSP */ + CcsDspCommFailure = 4 /* failed to communicate with DSP */ +} gpakConfigChanStatus_t; + +/* + * gpakConfigureChannel - Configure a DSP's Channel. + * + * FUNCTION + * This function configures a DSP's Channel. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +extern gpakConfigChanStatus_t gpakConfigureChannel( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GpakChanType ChannelType, // channel type + GpakChannelConfig_t *pChanConfig, // pointer to channel config info + GPAK_ChannelConfigStat_t *pStatus // pointer to Channel Config Status + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakTearDownChannel return status. */ +typedef enum +{ + TdsSuccess = 0, /* Channel Tear Down successful */ + TdsError = 1, /* Channel Tear Down error */ + TdsInvalidChannel = 2, /* invalid channel */ + TdsInvalidDsp = 3, /* invalid DSP */ + TdsDspCommFailure = 4 /* failed to communicate with DSP */ +} gpakTearDownStatus_t; + +/* + * gpakTearDownChannel - Tear Down a DSP's Channel. + * + * FUNCTION + * This function tears down a DSP's Channel. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ + +extern gpakTearDownStatus_t gpakTearDownChannel( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GPAK_TearDownChanStat_t *pStatus // pointer to Tear Down Status + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakAlgControl return status. */ +typedef enum +{ + AcSuccess = 0, /* control successful */ + AcInvalidChannel = 1, /* invalid channel identifier */ + AcInvalidDsp = 2, /* invalid DSP */ + AcParmError = 3, /* invalid control parameter */ + AcDspCommFailure = 4 /* failed to communicate with DSP */ +} gpakAlgControlStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakAlgControl - Control an Algorithm. + * + * FUNCTION + * This function controls an Algorithm + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +extern gpakAlgControlStat_t gpakAlgControl( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GpakAlgCtrl_t ControlCode, // algorithm control code + GPAK_AlgControlStat_t *pStatus // pointer to return status + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakConfigurePorts return status. */ +typedef enum +{ + CpsSuccess = 0, /* Serial Ports configured successfully */ + CpsParmError = 1, /* Configure Ports Parameter error */ + CpsInvalidDsp = 2, /* invalid DSP */ + CpsDspCommFailure = 3 /* failed to communicate with DSP */ +} gpakConfigPortStatus_t; + +/* + * gpakConfigurePorts - Configure a DSP's serial ports. + * + * FUNCTION + * This function configures a DSP's serial ports. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +extern gpakConfigPortStatus_t gpakConfigurePorts( + unsigned short int DspId, // DSP identifier + GpakPortConfig_t *pPortConfig, // pointer to Port Config info + GPAK_PortConfigStat_t *pStatus // pointer to Port Config Status + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakDownloadDsp return status. */ +typedef enum +{ + GdlSuccess = 0, /* DSP download successful */ + GdlFileReadError = 1, /* error reading Download file */ + GdlInvalidFile = 2, /* invalid Download file content */ + GdlInvalidDsp = 3 /* invalid DSP */ +} gpakDownloadStatus_t; + +/* + * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. + * + * FUNCTION + * This function reads a DSP's Program and Data memory image from the + * specified file and writes the image to the DSP's memory. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +extern gpakDownloadStatus_t gpakDownloadDsp( + unsigned short int DspId, // DSP identifier + GPAK_FILE_ID FileId // G.PAK download file identifier + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakReadEventFIFOMessage return status */ +typedef enum +{ + RefEventAvail = 0, /* an event was successfully read from the fifo */ + RefNoEventAvail = 1, /* no event was in the fifo */ + RefInvalidDsp = 2, /* invalid DSP identifier */ + RefInvalidEvent = 3, /* invalid event */ + RefDspCommFailure = 4 /* error communicating with DSP */ +} gpakReadEventFIFOMessageStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadEventFIFOMessage - read from the event fifo + * + * FUNCTION + * This function reads a single event from the event fifo if one is available + * + * RETURNS + * Status code indicating success or a specific error. + * + * Note: This function should be called in a loop until the return status + * indicates that the fifo is empty. + */ +extern gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( + unsigned short int DspId, // DSP identifier + unsigned short int *pChannelId, // pointer to channel identifier + GpakAsyncEventCode_t *pEventCode, // pointer to Event Code + GpakAsyncEventData_t *pEventData // pointer to Event Data Struct + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakPingDsp return status values */ +typedef enum +{ + PngSuccess = 0, /* DSP responded successfully */ + PngInvalidDsp = 1, /* invalid DSP identifier */ + PngDspCommFailure = 2 /* error communicating with DSP */ +} gpakPingDspStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakPingDsp - ping the DSP to see if it's alive + * + * FUNCTION + * This function checks if the DSP is still communicating with the host + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakPingDspStat_t gpakPingDsp( + unsigned short int DspId, // DSP identifier + unsigned short int *pDspSwVersion // DSP software version + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakSerialTxFixedValue return status values */ +typedef enum +{ + TfvSuccess = 0, /* operation successful */ + TfvInvalidChannel = 1, /* invalid channel identifier */ + TfvInvalidDsp = 2, /* invalid DSP identifier */ + TfvDspCommFailure = 3 /* failed to communicate with DSP */ +} gpakSerialTxFixedValueStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakSerialTxFixedValue - transmit a fixed value on a timeslot + * + * FUNCTION + * This function controls transmission of a fixed value out onto a serial + * port's timeslot. + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id + unsigned short int PcmOutSlot, // PCM Output Time Slot + unsigned short int Value, // 16-bit value + GpakActivation State // activation state + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakControlTdmLoopBack return status values */ +typedef enum +{ + ClbSuccess = 0, /* operation successful */ + ClbSerPortInactive = 1, /* serial port is inactive */ + ClbInvalidDsp = 2, /* invalid DSP identifier */ + ClbDspCommFailure = 3 /* failed to communicate with DSP */ +} gpakControlTdmLoopBackStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakControlTdmLoopBack - control a serial port's loopback state + * + * FUNCTION + * This function enables/disables the tdm input to output looback mode on a + * serial port + * + * RETURNS + * Status code indicating success or a specific error. + */ + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ +gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( + unsigned short int DspId, // DSP identifier + GpakSerialPort_t SerialPort, // Serial Port Id + GpakActivation LoopBackState // Loopback State + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakReadCpuUsage return status values */ +typedef enum +{ + RcuSuccess = 0, /* operation successful */ + RcuInvalidDsp = 1, /* invalid DSP identifier */ + RcuDspCommFailure = 2 /* communication failure */ +} gpakReadCpuUsageStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadCpuUsage - read the cpu usage statistics + * + * FUNCTION + * This function reads cpu utilization from the DSP. + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakReadCpuUsageStat_t gpakReadCpuUsage( + unsigned short int DspId, // DSP identifier + unsigned short int *pPeakUsage, // pointer to peak usage variable + unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakResetCpuUsageStats return status values */ +typedef enum +{ + RstcSuccess = 0, /* operation successful */ + RstcInvalidDsp = 1, /* invalid DSP identifier */ + RstcDspCommFailure = 2 /* communication failure */ +} gpakResetCpuUsageStat_t; +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakResetCpuUsageStats - reset the cpu usage statistics + * + * FUNCTION + * This function resets the cpu utilization statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakResetCpuUsageStat_t gpakResetCpuUsageStats( + unsigned short int DspId // DSP identifier + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakReadFramingStats return status values */ +typedef enum +{ + RfsSuccess = 0, /* operation successful */ + RfsInvalidDsp = 1, /* invalid DSP identifier */ + RfsDspCommFailure = 2 /* communication failure */ +} gpakReadFramingStatsStatus_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadFramingStats + * + * FUNCTION + * This function reads a DSP's framing interrupt statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakReadFramingStatsStatus_t gpakReadFramingStats( + unsigned short int DspId, // DSP identifier + unsigned short int *pFramingError1Count, // port 1 Framing error count + unsigned short int *pFramingError2Count, // port 2 Framing error count + unsigned short int *pFramingError3Count, // port 3 Framing error count + unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count + unsigned short int *pDmaSlipStatsBuffer // DMA slips count + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakResetFramingStats return values */ +typedef enum +{ + RstfSuccess = 0, /* operation successful */ + RstfInvalidDsp = 1, /* invalid DSP identifier */ + RstfDspCommFailure = 2 /* communication failure */ +} gpakResetFramingStatsStatus_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakResetFramingStats - reset a DSP's framing interrupt statistics + * + * FUNCTION + * This function resets a DSP's framing interrupt statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakResetFramingStatsStatus_t gpakResetFramingStats( + unsigned short int DspId // DSP identifier + ); + + +typedef enum +{ + RmmSuccess =0, + RmmInvalidDsp = 1, + RmmSizeTooBig = 2, + RmmFailure = 3, + RmmInvalidAddress = 4 + +} gpakReadDSPMemoryStat_t; +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakResetFramingStats - read a section of DSP memory + * to get access DSP registers, since 0x00--0x60 not HPI-accessable + * + * FUNCTION + * This function resets a DSP's framing interrupt statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ + +extern gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( + unsigned short int DspId, // Dsp Identifier + unsigned short int *pDest, // Buffer on host to hold DSP memory map + DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out + unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word + ); + +typedef enum +{ + GPIOSuccess =0, + GPIOInvalidDsp = 1, + GPIODspCommFailure = 2 +}gpakAccessGPIOStat_t; + +extern gpakAccessGPIOStat_t gpakAccessGPIO( + unsigned short int DspId, // DSP identifier + GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read + unsigned short int *pGPIOValue // pointer for the read/write value or DIR mask + ); + +/* gpakWriteSystemParms return status. */ +typedef enum +{ + WspSuccess = 0, /* System Parameters written successfully */ + WspParmError = 1, /* Write System Parms's Parameter error */ + WspInvalidDsp = 2, /* invalid DSP */ + WspDspCommFailure = 3 /* failed to communicate with DSP */ +} gpakWriteSysParmsStatus_t; + +/* Definition of a System Parameters information structure. */ +typedef struct +{ + /* DTMF Parameters */ + short int MinSigLevel; /* 0 = Disabled, Min Sig Power Level for detection */ + short int SNRFlag; /* 0 = Disabled, relax SNR tolerances */ + short int FreqDeviation; /* 0 = Disabled, X Percent Deviation times 10 (e.g. 1.7% is entered as 17) */ + short int DtmfFwdTwist; /* 0 to 8 db */ + short int DtmfRevTwist; /* 0 to 8 db */ + + short int DtmfValidityMask; /* This flag allows users to relax the trailing conditions of the tone */ + +} GpakSystemParms_t; +/* gpakReadSystemParms return status. */ +typedef enum +{ + RspSuccess = 0, /* System Parameters read successfully */ + RspInvalidDsp = 1, /* invalid DSP */ + RspDspCommFailure = 2 /* failed to communicate with DSP */ +} gpakReadSysParmsStatus_t; + +extern gpakReadSysParmsStatus_t gpakReadSystemParms( + unsigned short int DspId, // DSP identifier + GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ + ); + +extern gpakWriteSysParmsStatus_t gpakWriteSystemParms( + unsigned short int DspId, // DSP identifier + GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ + unsigned short int UpdateBits, /* input: flags indicating which parms to update */ + GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ + ); + +#endif // end multiple inclusion + diff --git a/kernel/wctdm24xxp/GpakCust.c b/kernel/wctdm24xxp/GpakCust.c new file mode 100644 index 0000000..23f2096 --- /dev/null +++ b/kernel/wctdm24xxp/GpakCust.c @@ -0,0 +1,476 @@ +/* + * Copyright (c) 2005, Adaptive Digital Technologies, Inc. + * + * File Name: GpakCust.c + * + * Description: + * This file contains host system dependent functions to support generic + * G.PAK API functions. The file is integrated into the host processor + * connected to C55x G.PAK DSPs via a Host Port Interface. + * + * Note: This file needs to be modified by the G.PAK system integrator. + * + * Version: 1.0 + * + * Revision History: + * 06/15/05 - Initial release. + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. The standard + * GPL disclaimer is given inline below for your convenience. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include + +#include "zaptel.h" +#include "wctdm24xxp.h" +#include "GpakCust.h" + +char vpm150mtone_to_zaptone(GpakToneCodes_t tone) +{ + switch (tone) { + case DtmfDigit0: + return '0'; + case DtmfDigit1: + return '1'; + case DtmfDigit2: + return '2'; + case DtmfDigit3: + return '3'; + case DtmfDigit4: + return '4'; + case DtmfDigit5: + return '5'; + case DtmfDigit6: + return '6'; + case DtmfDigit7: + return '7'; + case DtmfDigit8: + return '8'; + case DtmfDigit9: + return '9'; + case DtmfDigitPnd: + return '#'; + case DtmfDigitSt: + return '*'; + case DtmfDigitA: + return 'A'; + case DtmfDigitB: + return 'B'; + case DtmfDigitC: + return 'C'; + case DtmfDigitD: + return 'D'; + case EndofCngDigit: + return 'f'; + default: + return 0; + } +} + +static inline struct wctdm * wc_find_iface(unsigned short dspid) +{ + int i; + struct wctdm *ret = NULL; + unsigned long flags; + + spin_lock_irqsave(&ifacelock, flags); + for (i = 0; i < WC_MAX_IFACES; i++) + if (ifaces[i] && ifaces[i]->vpm150m && (ifaces[i]->vpm150m->dspid == dspid)) + ret = ifaces[i]; + spin_unlock_irqrestore(&ifacelock, flags); + + return ret; +} + +static inline struct vpm150m_cmd * vpm150m_empty_slot(struct wctdm *wc) +{ + int x; + + for (x = 0; x < VPM150M_MAX_COMMANDS; x++) + if (!wc->vpm150m->cmdq[x].desc) { + return &wc->vpm150m->cmdq[x]; + } + return NULL; +} + +/* Wait for any outstanding commands to be completed. */ +static inline int vpm150m_io_wait(struct wctdm *wc) +{ + int x; + int ret=0; + for (x=0; x < VPM150M_MAX_COMMANDS;) { + if (wc->vpm150m->cmdq[x].desc) { + if ((ret=schluffen(&wc->regq))) { + return ret; + } + x=0; + } + else { + ++x; + } + } + return ret; +} + +int wctdm_vpm150m_getreg_full_async(struct wctdm *wc, int pagechange, unsigned int len, + unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) +{ + int ret=0; + unsigned long flags; + BUG_ON(!hit_p); + spin_lock_irqsave(&wc->reglock, flags); + (*hit_p) = vpm150m_empty_slot(wc); + if (*hit_p) { + (*hit_p)->desc = __VPM150M_RD; + if (pagechange) { + (*hit_p)->desc |= __VPM150M_RWPAGE; + } + (*hit_p)->datalen = len; + (*hit_p)->addr = addr; + memset((*hit_p)->data, 0, len*sizeof(outbuf[0])); + } + else { + ret = -EBUSY; + } + spin_unlock_irqrestore(&wc->reglock, flags); + return ret; +} + +int wctdm_vpm150m_getreg_full_return(struct wctdm *wc, int pagechange, unsigned int len, + unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) +{ + int ret = 0; + unsigned long flags; + BUG_ON(!hit_p); + spin_lock_irqsave(&wc->reglock, flags); + do { + if ((*hit_p)->desc & __VPM150M_FIN) { + memcpy(outbuf, (*hit_p)->data, len*(sizeof(outbuf[0]))); + (*hit_p)->desc = 0; + (*hit_p) = NULL; + ret = 0; + } + else { + spin_unlock_irqrestore(&wc->reglock, flags); + if ((ret=schluffen(&wc->regq))) { + return ret; + } + spin_lock_irqsave(&wc->reglock, flags); + ret = -EBUSY; + } + } while (-EBUSY == ret); + spin_unlock_irqrestore(&wc->reglock, flags); + return ret; +} + +int wctdm_vpm150m_getreg_full(struct wctdm *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf) +{ + struct vpm150m_cmd *hit = 0; + int ret = 0; + do { + ret = wctdm_vpm150m_getreg_full_async(wc, pagechange, len, addr, outbuf, &hit); + if (!hit) { + if ( -EBUSY == ret ) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + BUG_ON(0 != ret); + } + } while (!hit); + ret = wctdm_vpm150m_getreg_full_return(wc, pagechange, len, addr, outbuf, &hit); + return ret; +} + +int wctdm_vpm150m_setreg_full(struct wctdm *wc, int pagechange, unsigned int len, unsigned int addr, unsigned short *data) +{ + unsigned long flags; + struct vpm150m_cmd *hit; + int ret, i; + do { + spin_lock_irqsave(&wc->reglock, flags); + hit = vpm150m_empty_slot(wc); + if (hit) { + hit->desc = __VPM150M_WR; + if (pagechange) + hit->desc |= __VPM150M_RWPAGE; + hit->addr = addr; + hit->datalen = len; + for (i = 0; i < len; i++) + hit->data[i] = data[i]; + } + spin_unlock_irqrestore(&wc->reglock, flags); + if (!hit) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (!hit); + return (hit) ? 0 : -1; +} + +int wctdm_vpm150m_setpage(struct wctdm *wc, unsigned short addr) +{ + addr &= 0xf; + /* Let's optimize this a little bit */ + if (wc->vpm150m->curpage == addr) + return 0; + else { + wc->vpm150m->curpage = addr; + } + + return wctdm_vpm150m_setreg_full(wc, 1, 1, 0, &addr); +} + +unsigned char wctdm_vpm150m_getpage(struct wctdm *wc) +{ + unsigned short res; + wctdm_vpm150m_getreg_full(wc, 1, 1, 0, &res); + return res; +} + +unsigned short wctdm_vpm150m_getreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data) +{ + unsigned short res; + wctdm_vpm150m_setpage(wc, addr >> 16); + if ((addr >> 16) != ((addr + len) >> 16)) + printk("getreg: You found it!\n"); + res = wctdm_vpm150m_getreg_full(wc, 0, len, addr & 0xffff, data); + return res; +} + +int wctdm_vpm150m_setreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data) +{ + int res; + wctdm_vpm150m_setpage(wc, addr >> 16); + if ((addr >> 16) != ((addr + len) >> 16)) + printk("getreg: You found it!\n"); + res = wctdm_vpm150m_setreg_full(wc, 0, len, addr & 0xffff, data); + return res; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadDspMemory - Read DSP memory. + * + * FUNCTION + * This function reads a contiguous block of words from DSP memory starting at + * the specified address. + * + * RETURNS + * nothing + * + */ +void gpakReadDspMemory( + unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ + unsigned int NumWords, /* number of contiguous words to read */ + DSP_WORD *pWordValues /* pointer to array of word values variable */ + ) +{ + struct wctdm *wc = wc_find_iface(DspId); + int i; + int transcount; + int ret; + + vpm150m_io_wait(wc); + if ( NumWords < VPM150M_MAX_COMMANDS ) { + struct vpm150m_cmd* cmds[VPM150M_MAX_COMMANDS] = {0}; + wctdm_vpm150m_setpage(wc, DspAddress >> 16); + DspAddress &= 0xffff; + for (i=0; i < NumWords; ++i) { + ret = wctdm_vpm150m_getreg_full_async(wc,0,1,DspAddress+i,&pWordValues[i], + &cmds[i]); + if (0 != ret) { + return; + } + } + for (i=NumWords-1; i >=0; --i) { + ret = wctdm_vpm150m_getreg_full_return(wc,0,1,DspAddress+i,&pWordValues[i], + &cmds[i]); + if (0 != ret) { + return; + } + } + } + else { + for (i = 0; i < NumWords;) { + if ((NumWords - i) > VPM150M_MAX_DATA) + transcount = VPM150M_MAX_DATA; + else + transcount = NumWords - i; + wctdm_vpm150m_getreg(wc, transcount, DspAddress + i, &pWordValues[i]); + i += transcount; + } + } + return; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakWriteDspMemory - Write DSP memory. + * + * FUNCTION + * This function writes a contiguous block of words to DSP memory starting at + * the specified address. + * + * RETURNS + * nothing + * + */ +void gpakWriteDspMemory( + unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ + unsigned int NumWords, /* number of contiguous words to write */ + DSP_WORD *pWordValues /* pointer to array of word values to write */ + ) +{ + + struct wctdm *wc = wc_find_iface(DspId); + int i; + int transcount; + + //printk("Writing %d words to memory\n", NumWords); + if (wc && wc->vpm150m) { + for (i = 0; i < NumWords;) { + if ((NumWords - i) > VPM150M_MAX_DATA) + transcount = VPM150M_MAX_DATA; + else + transcount = NumWords - i; + + wctdm_vpm150m_setreg(wc, transcount, DspAddress + i, &pWordValues[i]); + i += transcount; + } +#if 0 + for (i = 0; i < NumWords; i++) { + if (wctdm_vpm150m_getreg(wc, DspAddress + i) != pWordValues[i]) { + printk("Error in write. Address %x is not %x\n", DspAddress + i, pWordValues[i]); + } + } +#endif + } + return; + +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakHostDelay - Delay for a fixed time interval. + * + * FUNCTION + * This function delays for a fixed time interval before returning. The time + * interval is the Host Port Interface sampling period when polling a DSP for + * replies to command messages. + * + * RETURNS + * nothing + * + */ +void gpakHostDelay(void) +{ +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakLockAccess - Lock access to the specified DSP. + * + * FUNCTION + * This function aquires exclusive access to the specified DSP. + * + * RETURNS + * nothing + * + */ +void gpakLockAccess(unsigned short DspId) +{ + struct wctdm *wc; + + wc = wc_find_iface(DspId); + + if (wc) { + struct vpm150m *vpm = wc->vpm150m; + + if (vpm) + down_interruptible(&vpm->sem); + } +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakUnlockAccess - Unlock access to the specified DSP. + * + * FUNCTION + * This function releases exclusive access to the specified DSP. + * + * RETURNS + * nothing + * + */ +void gpakUnlockAccess(unsigned short DspId) +{ + struct wctdm *wc; + + wc = wc_find_iface(DspId); + + if (wc) { + struct vpm150m *vpm = wc->vpm150m; + + if (vpm) + up(&vpm->sem); + } +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadFile - Read a block of bytes from a G.PAK Download file. + * + * FUNCTION + * This function reads a contiguous block of bytes from a G.PAK Download file + * starting at the current file position. + * + * RETURNS + * The number of bytes read from the file. + * -1 indicates an error occurred. + * 0 indicates all bytes have been read (end of file) + * + */ +int gpakReadFile( + GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ + unsigned char *pBuffer, /* pointer to buffer for storing bytes */ + unsigned int NumBytes /* number of bytes to read */ + ) +{ +#ifdef VPM150M_SUPPORT + struct wctdm_firmware *fw = FileId; + unsigned int i, count; + + if (!fw || !fw->fw) + return -1; + + if (NumBytes > (fw->fw->size - fw->offset)) + count = fw->fw->size - fw->offset; + else + count = NumBytes; + + for (i = 0; i < count; i++) + pBuffer[i] = fw->fw->data[fw->offset + i]; + + fw->offset += count; + + return count; +#endif +} diff --git a/kernel/wctdm24xxp/GpakCust.h b/kernel/wctdm24xxp/GpakCust.h new file mode 100644 index 0000000..418d6a7 --- /dev/null +++ b/kernel/wctdm24xxp/GpakCust.h @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2005, Adaptive Digital Technologies, Inc. + * + * File Name: GpakCust.h + * + * Description: + * This file contains host system dependent definitions and prototypes of + * functions to support generic G.PAK API functions. The file is used when + * integrating G.PAK API functions in a specific host processor environment. + * + * Note: This file may need to be modified by the G.PAK system integrator. + * + * Version: 1.0 + * + * Revision History: + * 06/15/05 - Initial release. + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. The standard + * GPL disclaimer is given inline below for your convenience. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GPAKCUST_H /* prevent multiple inclusion */ +#define _GPAKCUST_H + +#include "wctdm24xxp.h" +#ifdef VPM150M_SUPPORT +#include +#include +#endif +#include "gpakenum.h" + + +struct wctdm_firmware { + const struct firmware *fw; + unsigned int offset; +}; + +/* Host and DSP system dependent related definitions. */ +#define MAX_DSP_CORES 128 /* maximum number of DSP cores */ +//#define MAX_CONFS 1 /* maximum number of conferences */ +//#define MAX_PKT_CHANNELS 8 /* maximum number of packet channels */ +#define MAX_CHANNELS 32 /* maximum number of channels */ +#define MAX_WAIT_LOOPS 50 /* max number of wait delay loops */ +#define DSP_IFBLK_ADDRESS 0x0100 /* DSP address of I/F block pointer */ +#define DOWNLOAD_BLOCK_SIZE 512 /* download block size (DSP words) */ +//#define MAX_CIDPAYLOAD_BYTES 512 /* max size of a CID payload (octets) */ +typedef unsigned short DSP_WORD; /* 16 bit DSP word */ +typedef unsigned int DSP_ADDRESS; /* 32 bit DSP address */ +typedef struct wctdm_firmware* GPAK_FILE_ID; /* G.PAK Download file identifier */ + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadDspMemory - Read DSP memory. + * + * FUNCTION + * This function reads a contiguous block of words from DSP memory starting at + * the specified address. + * + * RETURNS + * nothing + * + */ +extern void gpakReadDspMemory( + unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ + unsigned int NumWords, /* number of contiguous words to read */ + DSP_WORD *pWordValues /* pointer to array of word values variable */ + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakWriteDspMemory - Write DSP memory. + * + * FUNCTION + * This function writes a contiguous block of words to DSP memory starting at + * the specified address. + * + * RETURNS + * nothing + * + */ +extern void gpakWriteDspMemory( + unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ + unsigned int NumWords, /* number of contiguous words to write */ + DSP_WORD *pWordValues /* pointer to array of word values to write */ + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakHostDelay - Delay for a fixed time interval. + * + * FUNCTION + * This function delays for a fixed time interval before returning. The time + * interval is the Host Port Interface sampling period when polling a DSP for + * replies to command messages. + * + * RETURNS + * nothing + * + */ +extern void gpakHostDelay(void); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakLockAccess - Lock access to the specified DSP. + * + * FUNCTION + * This function aquires exclusive access to the specified DSP. + * + * RETURNS + * nothing + * + */ +extern void gpakLockAccess( + unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakUnlockAccess - Unlock access to the specified DSP. + * + * FUNCTION + * This function releases exclusive access to the specified DSP. + * + * RETURNS + * nothing + * + */ +extern void gpakUnlockAccess( + unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadFile - Read a block of bytes from a G.PAK Download file. + * + * FUNCTION + * This function reads a contiguous block of bytes from a G.PAK Download file + * starting at the current file position. + * + * RETURNS + * The number of bytes read from the file. + * -1 indicates an error occurred. + * 0 indicates all bytes have been read (end of file) + * + */ +extern int gpakReadFile( + GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ + unsigned char *pBuffer, /* pointer to buffer for storing bytes */ + unsigned int NumBytes /* number of bytes to read */ + ); + + +unsigned char wctdm_vpm150m_getpage(struct wctdm *wc); + +int wctdm_vpm150m_setpage(struct wctdm *wc, unsigned short addr); + +int wctdm_vpm150m_setreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data); + +unsigned short wctdm_vpm150m_getreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data); + +char vpm150mtone_to_zaptone(GpakToneCodes_t tone); + +#endif /* prevent multiple inclusion */ + + diff --git a/kernel/wctdm24xxp/GpakHpi.h b/kernel/wctdm24xxp/GpakHpi.h new file mode 100644 index 0000000..49e4ef9 --- /dev/null +++ b/kernel/wctdm24xxp/GpakHpi.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2001, Adaptive Digital Technologies, Inc. + * + * File Name: GpakHpi.h + * + * Description: + * This file contains common definitions related to the G.PAK interface + * between a host processor and a DSP processor via the Host Port Interface. + * + * Version: 1.0 + * + * Revision History: + * 10/17/01 - Initial release. + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. The standard + * GPL disclaimer is given inline below for your convenience. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GPAKHPI_H /* prevent multiple inclusion */ +#define _GPAKHPI_H + + +/* Definition of G.PAK Command/Reply message type codes. */ +#define MSG_NULL_REPLY 0 /* Null Reply (unsupported Command) */ +#define MSG_SYS_CONFIG_RQST 1 /* System Configuration Request */ +#define MSG_SYS_CONFIG_REPLY 2 /* System Configuration Reply */ +#define MSG_READ_SYS_PARMS 3 /* Read System Parameters */ +#define MSG_READ_SYS_PARMS_REPLY 4 /* Read System Parameters Reply */ +#define MSG_WRITE_SYS_PARMS 5 /* Write System Parameters */ +#define MSG_WRITE_SYS_PARMS_REPLY 6 /* Write System Parameters Reply */ +#define MSG_CONFIGURE_PORTS 7 /* Configure Serial Ports */ +#define MSG_CONFIG_PORTS_REPLY 8 /* Configure Serial Ports Reply */ +#define MSG_CONFIGURE_CHANNEL 9 /* Configure Channel */ +#define MSG_CONFIG_CHAN_REPLY 10 /* Configure Channel Reply */ +#define MSG_TEAR_DOWN_CHANNEL 11 /* Tear Down Channel */ +#define MSG_TEAR_DOWN_REPLY 12 /* Tear Down Channel Reply */ +#define MSG_CHAN_STATUS_RQST 13 /* Channel Status Request */ +#define MSG_CHAN_STATUS_REPLY 14 /* Channel Status Reply */ + +#define MSG_TEST_MODE 17 /* Configure/Perform Test Mode */ +#define MSG_TEST_REPLY 18 /* Configure/Perform Test Mode Reply */ + +#define MSG_ALG_CONTROL 27 /* algorithm control */ +#define MSG_ALG_CONTROL_REPLY 28 /* algorithm control reply */ +#define MSG_GET_TXCID_ADDRESS 29 /* get tx cid buffer start address */ +#define MSG_GET_TXCID_ADDRESS_REPLY 30 /* get tx cid buffer start addr reply */ + +#define MSG_PING 35 /* ping command */ +#define MSG_PING_REPLY 36 /* ping command reply */ +#define MSG_SERIAL_TXVAL 37 /* transmit serial fixed value */ +#define MSG_SERIAL_TXVAL_REPLY 38 /* transmit serial fixed value reply */ +#define MSG_TDM_LOOPBACK 39 /* tdm loopback control */ +#define MSG_TDM_LOOPBACK_REPLY 40 /* tdm loopback control reply */ +#define MSG_RESET_USAGE_STATS 41 /* reset cpu usage stats */ +#define MSG_RESET_USAGE_STATS_REPLY 42 /* reset cpu usage stats reply */ + +#define MSG_RESET_FRAME_STATS 47 /* reset framing stats */ +#define MSG_RESET_FRAME_STATS_REPLY 48 /* reset framing stats reply */ + +#define MSG_READ_DSP_MEMORY 49 /* read small section of DSP's memory */ +#define MSG_READ_DSP_MEMORY_REPLY 50 /* read memory reply */ + +#define MSG_ACCESSGPIO 51 +#define MSG_ACCESSGPIO_REPLY 52 +#endif /* prevent multiple inclusion */ diff --git a/kernel/wctdm24xxp/Kbuild b/kernel/wctdm24xxp/Kbuild new file mode 100644 index 0000000..3bdbe19 --- /dev/null +++ b/kernel/wctdm24xxp/Kbuild @@ -0,0 +1,25 @@ +obj-m += wctdm24xxp.o + +FIRM_DIR := ../../firmware + +EXTRA_CFLAGS := -I$(src)/.. -Wno-undef + +ifeq ($(HOTPLUG_FIRMWARE),yes) + EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE +endif + +wctdm24xxp-objs := base.o GpakCust.o GpakApi.o + +ifneq ($(HOTPLUG_FIRMWARE),yes) +wctdm24xxp-objs += $(FIRM_DIR)/zaptel-fw-vpmadt032.o +endif + +$(obj)/$(FIRM_DIR)/zaptel-fw-vpmadt032.o: $(obj)/base.o + $(MAKE) -C $(obj)/$(FIRM_DIR) zaptel-fw-vpmadt032.o + +$(obj)/base.o: $(src)/GpakCust.h $(src)/wctdm24xxp.h +$(obj)/base.o: $(src)/../zaptel.h + +$(obj)/GpakCust.o: $(src)/GpakCust.h + +$(obj)/GpakApi.o: $(src)/GpakApi.h diff --git a/kernel/wctdm24xxp/Makefile b/kernel/wctdm24xxp/Makefile new file mode 100644 index 0000000..9c4cd51 --- /dev/null +++ b/kernel/wctdm24xxp/Makefile @@ -0,0 +1,27 @@ +ifneq ($(KBUILD_EXTMOD),) +# We only get here on kernels 2.6.0-2.6.9 . +# For newer kernels, Kbuild will be included directly by the kernel +# build system. +include $(src)/Kbuild + +else + +all: wctdm24xxp.o + +%.o: %.c + $(CC) $(KFLAGS) -o $@ -c $< + +base.o: ../zaptel.h GpakCust.h ../wctdm.h + +GpakCust.o: GpakCust.h + +../firmware/zaptel-fw-vpmadt032.o: base.o + $(MAKE) -C ../firmware zaptel-fw-vpmadt032.o + +wctdm24xxp.o: base.o GpakCust.o GpakApi.o ../firmware/zaptel-fw-vpmadt032.o + $(LD) -r -o $@ $^ + +clean: + rm -f *.o + +endif diff --git a/kernel/wctdm24xxp/base.c b/kernel/wctdm24xxp/base.c new file mode 100644 index 0000000..886bdab --- /dev/null +++ b/kernel/wctdm24xxp/base.c @@ -0,0 +1,4484 @@ +/* + * Wildcard TDM2400P TDM FXS/FXO Interface Driver for Zapata Telephony interface + * + * Written by Mark Spencer + * Support for TDM800P and VPM150M by Matthew Fredrickson + * + * Copyright (C) 2005,2006, Digium, Inc. + * All rights reserved. + * + * Sections for QRV cards written by Jim Dixon + * Copyright (C) 2006, Jim Dixon and QRV Communications + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +/* For QRV DRI cards, gain is signed short, expressed in hundredths of +db (in reference to 1v Peak @ 1000Hz) , as follows: + +Rx Gain: -11.99 to 15.52 db +Tx Gain - No Pre-Emphasis: -35.99 to 12.00 db +Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef LINUX26 +#include +#endif + +#include "zaptel.h" +#include "proslic.h" +#include "wctdm.h" + +#include "wctdm24xxp.h" + +#ifdef VPM150M_SUPPORT +#include "adt_lec.h" +#endif + +#include "GpakCust.h" +#include "GpakApi.h" + +/* + Experimental max loop current limit for the proslic + Loop current limit is from 20 mA to 41 mA in steps of 3 + (according to datasheet) + So set the value below to: + 0x00 : 20mA (default) + 0x01 : 23mA + 0x02 : 26mA + 0x03 : 29mA + 0x04 : 32mA + 0x05 : 35mA + 0x06 : 37mA + 0x07 : 41mA +*/ +static int loopcurrent = 20; + +static alpha indirect_regs[] = +{ +{0,255,"DTMF_ROW_0_PEAK",0x55C2}, +{1,255,"DTMF_ROW_1_PEAK",0x51E6}, +{2,255,"DTMF_ROW2_PEAK",0x4B85}, +{3,255,"DTMF_ROW3_PEAK",0x4937}, +{4,255,"DTMF_COL1_PEAK",0x3333}, +{5,255,"DTMF_FWD_TWIST",0x0202}, +{6,255,"DTMF_RVS_TWIST",0x0202}, +{7,255,"DTMF_ROW_RATIO_TRES",0x0198}, +{8,255,"DTMF_COL_RATIO_TRES",0x0198}, +{9,255,"DTMF_ROW_2ND_ARM",0x0611}, +{10,255,"DTMF_COL_2ND_ARM",0x0202}, +{11,255,"DTMF_PWR_MIN_TRES",0x00E5}, +{12,255,"DTMF_OT_LIM_TRES",0x0A1C}, +{13,0,"OSC1_COEF",0x7B30}, +{14,1,"OSC1X",0x0063}, +{15,2,"OSC1Y",0x0000}, +{16,3,"OSC2_COEF",0x7870}, +{17,4,"OSC2X",0x007D}, +{18,5,"OSC2Y",0x0000}, +{19,6,"RING_V_OFF",0x0000}, +{20,7,"RING_OSC",0x7EF0}, +{21,8,"RING_X",0x0160}, +{22,9,"RING_Y",0x0000}, +{23,255,"PULSE_ENVEL",0x2000}, +{24,255,"PULSE_X",0x2000}, +{25,255,"PULSE_Y",0x0000}, +//{26,13,"RECV_DIGITAL_GAIN",0x4000}, // playback volume set lower +{26,13,"RECV_DIGITAL_GAIN",0x2000}, // playback volume set lower +{27,14,"XMIT_DIGITAL_GAIN",0x4000}, +//{27,14,"XMIT_DIGITAL_GAIN",0x2000}, +{28,15,"LOOP_CLOSE_TRES",0x1000}, +{29,16,"RING_TRIP_TRES",0x3600}, +{30,17,"COMMON_MIN_TRES",0x1000}, +{31,18,"COMMON_MAX_TRES",0x0200}, +{32,19,"PWR_ALARM_Q1Q2",0x07C0}, +{33,20,"PWR_ALARM_Q3Q4", 0x4C00 /* 0x2600 */}, +{34,21,"PWR_ALARM_Q5Q6",0x1B80}, +{35,22,"LOOP_CLOSURE_FILTER",0x8000}, +{36,23,"RING_TRIP_FILTER",0x0320}, +{37,24,"TERM_LP_POLE_Q1Q2",0x008C}, +{38,25,"TERM_LP_POLE_Q3Q4",0x0100}, +{39,26,"TERM_LP_POLE_Q5Q6",0x0010}, +{40,27,"CM_BIAS_RINGING",0x0C00}, +{41,64,"DCDC_MIN_V",0x0C00}, +{42,255,"DCDC_XTRA",0x1000}, +{43,66,"LOOP_CLOSE_TRES_LOW",0x1000}, +}; + +#ifdef FANCY_ECHOCAN +static char ectab[] = { +0, 0, 0, 1, 2, 3, 4, 6, 8, 9, 11, 13, 16, 18, 20, 22, 24, 25, 27, 28, 29, 30, 31, 31, 32, +32, 32, 32, 32, 32, 32, 32, 32, 32, 32 ,32 ,32, 32, +32, 32, 32, 32, 32, 32, 32, 32, 32, 32 ,32 ,32, 32, +32, 32, 32, 32, 32, 32, 32, 32, 32, 32 ,32 ,32, 32, +31, 31, 30, 29, 28, 27, 25, 23, 22, 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0, +}; +static int ectrans[4] = { 0, 1, 3, 2 }; +#define EC_SIZE (sizeof(ectab)) +#define EC_SIZE_Q (sizeof(ectab) / 4) +#endif + +/* Undefine to enable Power alarm / Transistor debug -- note: do not + enable for normal operation! */ +/* #define PAQ_DEBUG */ + +static struct fxo_mode { + char *name; + /* FXO */ + int ohs; + int ohs2; + int rz; + int rt; + int ilim; + int dcv; + int mini; + int acim; + int ring_osc; + int ring_x; +} fxo_modes[] = +{ + { "FCC", 0, 0, 0, 1, 0, 0x3, 0, 0, }, /* US, Canada */ + { "TBR21", 0, 0, 0, 0, 1, 0x3, 0, 0x2, 0x7e6c, 0x023a, }, + /* Austria, Belgium, Denmark, Finland, France, Germany, + Greece, Iceland, Ireland, Italy, Luxembourg, Netherlands, + Norway, Portugal, Spain, Sweden, Switzerland, and UK */ + { "ARGENTINA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "AUSTRALIA", 1, 0, 0, 0, 0, 0, 0x3, 0x3, }, + { "AUSTRIA", 0, 1, 0, 0, 1, 0x3, 0, 0x3, }, + { "BAHRAIN", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "BELGIUM", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "BRAZIL", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "BULGARIA", 0, 0, 0, 0, 1, 0x3, 0x0, 0x3, }, + { "CANADA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "CHILE", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "CHINA", 0, 0, 0, 0, 0, 0, 0x3, 0xf, }, + { "COLUMBIA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "CROATIA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "CYRPUS", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "CZECH", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "DENMARK", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "ECUADOR", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "EGYPT", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "ELSALVADOR", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "FINLAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "FRANCE", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "GERMANY", 0, 1, 0, 0, 1, 0x3, 0, 0x3, }, + { "GREECE", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "GUAM", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "HONGKONG", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "HUNGARY", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "ICELAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "INDIA", 0, 0, 0, 0, 0, 0x3, 0, 0x4, }, + { "INDONESIA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "IRELAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "ISRAEL", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "ITALY", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "JAPAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "JORDAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "KAZAKHSTAN", 0, 0, 0, 0, 0, 0x3, 0, }, + { "KUWAIT", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "LATVIA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "LEBANON", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "LUXEMBOURG", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "MACAO", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "MALAYSIA", 0, 0, 0, 0, 0, 0, 0x3, 0, }, /* Current loop >= 20ma */ + { "MALTA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "MEXICO", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "MOROCCO", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, + { "NETHERLANDS", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "NEWZEALAND", 0, 0, 0, 0, 0, 0x3, 0, 0x4, }, + { "NIGERIA", 0, 0, 0, 0, 0x1, 0x3, 0, 0x2, }, + { "NORWAY", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "OMAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "PAKISTAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "PERU", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "PHILIPPINES", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "POLAND", 0, 0, 1, 1, 0, 0x3, 0, 0, }, + { "PORTUGAL", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "ROMANIA", 0, 0, 0, 0, 0, 3, 0, 0, }, + { "RUSSIA", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "SAUDIARABIA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "SINGAPORE", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "SLOVAKIA", 0, 0, 0, 0, 0, 0x3, 0, 0x3, }, + { "SLOVENIA", 0, 0, 0, 0, 0, 0x3, 0, 0x2, }, + { "SOUTHAFRICA", 1, 0, 1, 0, 0, 0x3, 0, 0x3, }, + { "SOUTHKOREA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "SPAIN", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "SWEDEN", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "SWITZERLAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, + { "SYRIA", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "TAIWAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "THAILAND", 0, 0, 0, 0, 0, 0, 0x3, 0, }, + { "UAE", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "UK", 0, 1, 0, 0, 1, 0x3, 0, 0x5, }, + { "USA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, + { "YEMEN", 0, 0, 0, 0, 0, 0x3, 0, 0, }, +}; + +#define DEBUG_CARD (1 << 0) +#define DEBUG_ECHOCAN (1 << 1) + +struct wctdm_desc { + char *name; + int flags; + int ports; +}; + +static struct wctdm_desc wctdm2400 = { "Wildcard TDM2400P", 0, 24 }; +static struct wctdm_desc wctdm800 = { "Wildcard TDM800P", 0, 8 }; +static struct wctdm_desc wctdm410 = { "Wildcard TDM410P", 0, 4 }; +static struct wctdm_desc wcaex2400 = { "Wildcard AEX2400", FLAG_EXPRESS, 24 }; +static struct wctdm_desc wcaex800 = { "Wildcard AEX800", FLAG_EXPRESS, 8 }; + +static int acim2tiss[16] = { 0x0, 0x1, 0x4, 0x5, 0x7, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0, 0x3 }; + +struct wctdm *ifaces[WC_MAX_IFACES]; +spinlock_t ifacelock = SPIN_LOCK_UNLOCKED; + +static void wctdm_release(struct wctdm *wc); + +static int fxovoltage = 0; +static int battdebounce = DEFAULT_BATT_DEBOUNCE; +static int battthresh = DEFAULT_BATT_THRESH; +static int debug = 0; +static int robust = 0; +static int lowpower = 0; +static int boostringer = 0; +static int fastringer = 0; +static int _opermode = 0; +static char *opermode = "FCC"; +static int fxshonormode = 0; +static int alawoverride = 0; +static int fxo_addrs[4] = { 0x00, 0x08, 0x04, 0x0c }; +static int fxotxgain = 0; +static int fxorxgain = 0; +static int fxstxgain = 0; +static int fxsrxgain = 0; +static int nativebridge = 0; +static int ringdebounce = DEFAULT_RING_DEBOUNCE; +static int fwringdetect = 0; +#ifdef VPM_SUPPORT +static int vpmsupport = 1; +static int vpmdtmfsupport = 0; +#define VPM_DEFAULT_DTMFTHRESHOLD 1250 +static int dtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD; +/* + * This parameter is used to adjust the NLP type used. The options are: + * 0 : None + * 1 : Mute + * 2 : Random Noise + * 3 : Hoth Noise + * 4 : Suppression NLP - In order to use this, you must set the vpmnlpmaxsupp parameter to + * some value in order to give the amount of dB to suppress to the suppressor + */ +static int vpmnlptype = 1; +/* This is the threshold (in dB) for enabling and disabling of the NLP */ +static int vpmnlpthresh = 24; +/* See vpmnlptype = 4 for more info */ +static int vpmnlpmaxsupp = 0; +#endif + +static int wctdm_init_proslic(struct wctdm *wc, int card, int fast , int manual, int sane); + +static inline int CMD_BYTE(int card, int bit, int altcs) +{ + /* Let's add some trickery to make the TDM410 work */ + if (altcs == 3) { + if (card == 2) { + card = 4; + altcs = 0; + } else if (card == 3) { + card = 5; + altcs = 2; + } + } + + return (((((card) & 0x3) * 3 + (bit)) * 7) \ + + ((card) >> 2) + (altcs) + ((altcs) ? -21 : 0)); +} + +/* sleep in user space until woken up. Equivilant of tsleep() in BSD */ +int schluffen(wait_queue_head_t *q) +{ + DECLARE_WAITQUEUE(wait, current); + add_wait_queue(q, &wait); + current->state = TASK_INTERRUPTIBLE; + if (!signal_pending(current)) schedule(); + current->state = TASK_RUNNING; + remove_wait_queue(q, &wait); + if (signal_pending(current)) return -ERESTARTSYS; + return(0); +} + +static inline int empty_slot(struct wctdm *wc, int card) +{ + int x; + for (x=0;xcmdq[card].cmds[x]) + return x; + } + return -1; +} + +#ifdef VPM_SUPPORT +static inline void cmd_dequeue_vpm150m(struct wctdm *wc, volatile unsigned char *writechunk, int whichframe) +{ + unsigned long flags; + struct vpm150m_cmd *curcmd = NULL; + struct vpm150m *vpm150m = wc->vpm150m; + int x; + unsigned char leds = ~((wc->intcount / 1000) % 8) & 0x7; + + /* Skip audio */ + writechunk += 24; + + spin_lock_irqsave(&wc->reglock, flags); + + if (test_bit(VPM150M_SPIRESET, &vpm150m->control) || test_bit(VPM150M_HPIRESET, &vpm150m->control)) { + if (debug & DEBUG_ECHOCAN) + printk("HW Resetting VPMADT032...\n"); + for (x = 24; x < 28; x++) { + if (x == 24) { + if (test_and_clear_bit(VPM150M_SPIRESET, &vpm150m->control)) + writechunk[CMD_BYTE(x, 0, 0)] = 0x08; + else if (test_and_clear_bit(VPM150M_HPIRESET, &vpm150m->control)) + writechunk[CMD_BYTE(x, 0, 0)] = 0x0b; + } else + writechunk[CMD_BYTE(x, 0, 0)] = 0x00 | leds; + writechunk[CMD_BYTE(x, 1, 0)] = 0; + writechunk[CMD_BYTE(x, 2, 0)] = 0x00; + } + spin_unlock_irqrestore(&wc->reglock, flags); + return; + } + + + /* Search for something waiting to transmit */ + for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { + if ((vpm150m->cmdq[x].desc & (__VPM150M_RD | __VPM150M_WR)) && + !(vpm150m->cmdq[x].desc & (__VPM150M_FIN | __VPM150M_TX))) { + curcmd = &vpm150m->cmdq[x]; + curcmd->txident = wc->txident; + curcmd->desc |= __VPM150M_TX; + break; + } + } + if (curcmd) { +#if 0 + printk("Found command txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", curcmd->txident, curcmd->desc, curcmd->addr, curcmd->data); +#endif + if (curcmd->desc & __VPM150M_RWPAGE) { + /* Set CTRL access to page*/ + writechunk[CMD_BYTE(24, 0, 0)] = (0x8 << 4); + writechunk[CMD_BYTE(24, 1, 0)] = 0; + writechunk[CMD_BYTE(24, 2, 0)] = 0x20; + + /* Do a page write */ + if (curcmd->desc & __VPM150M_WR) + writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | 0x4) << 4); + else + writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | 0x4 | 0x1) << 4); + writechunk[CMD_BYTE(25, 1, 0)] = 0; + if (curcmd->desc & __VPM150M_WR) + writechunk[CMD_BYTE(25, 2, 0)] = curcmd->data[0] & 0xf; + else + writechunk[CMD_BYTE(25, 2, 0)] = 0; + + /* Clear XADD */ + writechunk[CMD_BYTE(26, 0, 0)] = (0x8 << 4); + writechunk[CMD_BYTE(26, 1, 0)] = 0; + writechunk[CMD_BYTE(26, 2, 0)] = 0; + + /* Fill in to buffer to size */ + writechunk[CMD_BYTE(27, 0, 0)] = 0; + writechunk[CMD_BYTE(27, 1, 0)] = 0; + writechunk[CMD_BYTE(27, 2, 0)] = 0; + + } else { + /* Set address */ + writechunk[CMD_BYTE(24, 0, 0)] = ((0x8 | 0x4) << 4); + writechunk[CMD_BYTE(24, 1, 0)] = (curcmd->addr >> 8) & 0xff; + writechunk[CMD_BYTE(24, 2, 0)] = curcmd->addr & 0xff; + + /* Send/Get our data */ + if (curcmd->desc & __VPM150M_WR) { + if (curcmd->datalen > 1) + writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | (0x1 << 1)) << 4); + else + writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | (0x3 << 1)) << 4); + } else + if (curcmd->datalen > 1) + writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | (0x1 << 1) | 0x1) << 4); + else + writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | (0x3 << 1) | 0x1) << 4); + writechunk[CMD_BYTE(25, 1, 0)] = (curcmd->data[0] >> 8) & 0xff; + writechunk[CMD_BYTE(25, 2, 0)] = curcmd->data[0] & 0xff; + + if (curcmd->datalen > 1) { + if (curcmd->desc & __VPM150M_WR) + writechunk[CMD_BYTE(26, 0, 0)] = ((0x8 | (0x1 << 1)) << 4); + else + writechunk[CMD_BYTE(26, 0, 0)] = ((0x8 | (0x1 << 1) | 0x1) << 4); + writechunk[CMD_BYTE(26, 1, 0)] = (curcmd->data[1] >> 8) & 0xff; + writechunk[CMD_BYTE(26, 2, 0)] = curcmd->data[1] & 0xff; + } else { + /* Fill in the rest */ + writechunk[CMD_BYTE(26, 0, 0)] = 0; + writechunk[CMD_BYTE(26, 1, 0)] = 0; + writechunk[CMD_BYTE(26, 2, 0)] = 0; + } + + if (curcmd->datalen > 2) { + if (curcmd->desc & __VPM150M_WR) + writechunk[CMD_BYTE(27, 0, 0)] = ((0x8 | (0x1 << 1)) << 4); + else + writechunk[CMD_BYTE(27, 0, 0)] = ((0x8 | (0x1 << 1) | 0x1) << 4); + writechunk[CMD_BYTE(27, 1, 0)] = (curcmd->data[2] >> 8) & 0xff; + writechunk[CMD_BYTE(27, 2, 0)] = curcmd->data[2] & 0xff; + } else { + /* Fill in the rest */ + writechunk[CMD_BYTE(27, 0, 0)] = 0; + writechunk[CMD_BYTE(27, 1, 0)] = 0; + writechunk[CMD_BYTE(27, 2, 0)] = 0; + } + + + } + } else if (test_and_clear_bit(VPM150M_SWRESET, &vpm150m->control)) { + printk("Booting VPMADT032\n"); + for (x = 24; x < 28; x++) { + if (x == 24) + writechunk[CMD_BYTE(x, 0, 0)] = (0x8 << 4); + else + writechunk[CMD_BYTE(x, 0, 0)] = 0x00; + writechunk[CMD_BYTE(x, 1, 0)] = 0; + if (x == 24) + writechunk[CMD_BYTE(x, 2, 0)] = 0x01; + else + writechunk[CMD_BYTE(x, 2, 0)] = 0x00; + } + } else { + for (x = 24; x < 28; x++) { + writechunk[CMD_BYTE(x, 0, 0)] = 0x00; + writechunk[CMD_BYTE(x, 1, 0)] = 0x00; + writechunk[CMD_BYTE(x, 2, 0)] = 0x00; + } + } + +#ifdef VPM150M_SUPPORT + /* Add our leds in */ + for (x = 24; x < 28; x++) + writechunk[CMD_BYTE(x, 0, 0)] |= leds; + + /* Now let's figure out if we need to check for DTMF */ + if (test_bit(VPM150M_ACTIVE, &vpm150m->control) && !whichframe && !(wc->intcount % 100)) + queue_work(vpm150m->wq, &vpm150m->work); +#endif + + spin_unlock_irqrestore(&wc->reglock, flags); +} +#endif /* VPM_SUPPORT */ + +static inline void cmd_dequeue(struct wctdm *wc, volatile unsigned char *writechunk, int card, int pos) +{ + unsigned long flags; + unsigned int curcmd=0; + int x; + int subaddr = card & 0x3; +#ifdef FANCY_ECHOCAN + int ecval; + ecval = wc->echocanpos; + ecval += EC_SIZE_Q * ectrans[(card & 0x3)]; + ecval = ecval % EC_SIZE; +#endif + + /* if a QRV card, map it to its first channel */ + if ((wc->modtype[card] == MOD_TYPE_QRV) && (card & 3)) + { + return; + } + if (wc->altcs[card]) + subaddr = 0; + + + + /* Skip audio */ + writechunk += 24; + spin_lock_irqsave(&wc->reglock, flags); + /* Search for something waiting to transmit */ + if (pos) { + for (x=0;xcmdq[card].cmds[x] & (__CMD_RD | __CMD_WR)) && + !(wc->cmdq[card].cmds[x] & (__CMD_TX | __CMD_FIN))) { + curcmd = wc->cmdq[card].cmds[x]; +#if 0 + printk("Transmitting command '%08x' in slot %d\n", wc->cmdq[card].cmds[x], wc->txident); +#endif + wc->cmdq[card].cmds[x] |= (wc->txident << 24) | __CMD_TX; + break; + } + } + } + if (!curcmd) { + /* If nothing else, use filler */ + if (wc->modtype[card] == MOD_TYPE_FXS) + curcmd = CMD_RD(64); + else if (wc->modtype[card] == MOD_TYPE_FXO) + curcmd = CMD_RD(12); + else if (wc->modtype[card] == MOD_TYPE_QRV) + curcmd = CMD_RD(3); + else if (wc->modtype[card] == MOD_TYPE_VPM) { +#ifdef FANCY_ECHOCAN + if (wc->blinktimer >= 0xf) { + curcmd = CMD_WR(0x1ab, 0x0f); + } else if (wc->blinktimer == (ectab[ecval] >> 1)) { + curcmd = CMD_WR(0x1ab, 0x00); + } else +#endif + curcmd = CMD_RD(0x1a0); + } + } + if (wc->modtype[card] == MOD_TYPE_FXS) { + writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = (1 << (subaddr)); + if (curcmd & __CMD_WR) + writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0x7f; + else + writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x80 | ((curcmd >> 8) & 0x7f); + writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff; + } else if (wc->modtype[card] == MOD_TYPE_FXO) { + if (curcmd & __CMD_WR) + writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x20 | fxo_addrs[subaddr]; + else + writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x60 | fxo_addrs[subaddr]; + writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0xff; + writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff; + } else if (wc->modtype[card] == MOD_TYPE_FXSINIT) { + /* Special case, we initialize the FXS's into the three-byte command mode then + switch to the regular mode. To send it into thee byte mode, treat the path as + 6 two-byte commands and in the last one we initialize register 0 to 0x80. All modules + read this as the command to switch to daisy chain mode and we're done. */ + writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00; + writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00; + if ((card & 0x1) == 0x1) + writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x80; + else + writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00; +#ifdef VPM_SUPPORT + } else if (wc->modtype[card] == MOD_TYPE_VPM) { + if (curcmd & __CMD_WR) + writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = ((card & 0x3) << 4) | 0xc | ((curcmd >> 16) & 0x1); + else + writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = ((card & 0x3) << 4) | 0xa | ((curcmd >> 16) & 0x1); + writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0xff; + writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff; + } else if (wc->modtype[card] == MOD_TYPE_VPM150M) { +#endif + } else if (wc->modtype[card] == MOD_TYPE_QRV) { + + writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00; + if (!curcmd) + { + writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00; + writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00; + } + else + { + if (curcmd & __CMD_WR) + writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x40 | ((curcmd >> 8) & 0x3f); + else + writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0xc0 | ((curcmd >> 8) & 0x3f); + writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff; + } + } else if (wc->modtype[card] == MOD_TYPE_NONE) { + writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00; + writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00; + writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00; + } +#if 0 + /* XXX */ + if (cmddesc < 40) + printk("Pass %d, card = %d (modtype=%d), pos = %d, CMD_BYTES = %d,%d,%d, (%02x,%02x,%02x) curcmd = %08x\n", cmddesc, card, wc->modtype[card], pos, CMD_BYTE(card, 0), CMD_BYTE(card, 1), CMD_BYTE(card, 2), writechunk[CMD_BYTE(card, 0)], writechunk[CMD_BYTE(card, 1)], writechunk[CMD_BYTE(card, 2)], curcmd); +#endif + spin_unlock_irqrestore(&wc->reglock, flags); +#if 0 + /* XXX */ + cmddesc++; +#endif +} + +#ifdef VPM_SUPPORT +static inline void cmd_decifer_vpm150m(struct wctdm *wc, volatile unsigned char *readchunk) +{ + unsigned long flags; + unsigned char ident; + int x, i; + + /* Skip audio */ + readchunk += 24; + spin_lock_irqsave(&wc->reglock, flags); + /* Search for any pending results */ + for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { + if ((wc->vpm150m->cmdq[x].desc & (__VPM150M_RD | __VPM150M_WR)) && + (wc->vpm150m->cmdq[x].desc & (__VPM150M_TX)) && + !(wc->vpm150m->cmdq[x].desc & (__VPM150M_FIN))) { + ident = wc->vpm150m->cmdq[x].txident; + if (ident == wc->rxident) { + /* Store result */ + for (i = 0; i < wc->vpm150m->cmdq[x].datalen; i++) { + wc->vpm150m->cmdq[x].data[i] = (0xff & readchunk[CMD_BYTE((25 + i), 1, 0)]) << 8; + wc->vpm150m->cmdq[x].data[i] |= readchunk[CMD_BYTE((25 + i), 2, 0)]; + } + if (wc->vpm150m->cmdq[x].desc & __VPM150M_WR) { + /* Go ahead and clear out writes since they need no acknowledgement */ + wc->vpm150m->cmdq[x].desc = 0; + } else + wc->vpm150m->cmdq[x].desc |= __VPM150M_FIN; + break; + } + } + } + spin_unlock_irqrestore(&wc->reglock, flags); +} +#endif /* VPM_SUPPORT */ + +static inline void cmd_decifer(struct wctdm *wc, volatile unsigned char *readchunk, int card) +{ + unsigned long flags; + unsigned char ident; + int x; + + /* if a QRV card, map it to its first channel */ + if ((wc->modtype[card] == MOD_TYPE_QRV) && (card & 3)) + { + return; + } + /* Skip audio */ + readchunk += 24; + spin_lock_irqsave(&wc->reglock, flags); + /* Search for any pending results */ + for (x=0;xcmdq[card].cmds[x] & (__CMD_RD | __CMD_WR)) && + (wc->cmdq[card].cmds[x] & (__CMD_TX)) && + !(wc->cmdq[card].cmds[x] & (__CMD_FIN))) { + ident = (wc->cmdq[card].cmds[x] >> 24) & 0xff; + if (ident == wc->rxident) { + /* Store result */ + wc->cmdq[card].cmds[x] |= readchunk[CMD_BYTE(card, 2, wc->altcs[card])]; + wc->cmdq[card].cmds[x] |= __CMD_FIN; + if (wc->cmdq[card].cmds[x] & __CMD_WR) { + /* Go ahead and clear out writes since they need no acknowledgement */ + wc->cmdq[card].cmds[x] = 0x00000000; + } else if (x >= USER_COMMANDS) { + /* Clear out ISR reads */ + wc->cmdq[card].isrshadow[x - USER_COMMANDS] = wc->cmdq[card].cmds[x] & 0xff; + wc->cmdq[card].cmds[x] = 0x00000000; + } + break; + } + } + } +#if 0 + /* XXX */ + if (!pos && (cmddesc < 256)) + printk("Card %d: Command '%08x' => %02x\n",card, wc->cmdq[card].lasttx[pos], wc->cmdq[card].lastrd[pos]); +#endif + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static inline void cmd_checkisr(struct wctdm *wc, int card) +{ + if (!wc->cmdq[card].cmds[USER_COMMANDS + 0]) { + if (wc->sethook[card]) { + wc->cmdq[card].cmds[USER_COMMANDS + 0] = wc->sethook[card]; + wc->sethook[card] = 0; + } else if (wc->modtype[card] == MOD_TYPE_FXS) { + wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(68); /* Hook state */ + } else if (wc->modtype[card] == MOD_TYPE_FXO) { + wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(5); /* Hook/Ring state */ + } else if (wc->modtype[card] == MOD_TYPE_QRV) { + wc->cmdq[card & 0xfc].cmds[USER_COMMANDS + 0] = CMD_RD(3); /* COR/CTCSS state */ +#ifdef VPM_SUPPORT + } else if (wc->modtype[card] == MOD_TYPE_VPM) { + wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(0xb9); /* DTMF interrupt */ +#endif + } + } + if (!wc->cmdq[card].cmds[USER_COMMANDS + 1]) { + if (wc->modtype[card] == MOD_TYPE_FXS) { +#ifdef PAQ_DEBUG + wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(19); /* Transistor interrupts */ +#else + wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(64); /* Battery mode */ +#endif + } else if (wc->modtype[card] == MOD_TYPE_FXO) { + wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(29); /* Battery */ + } else if (wc->modtype[card] == MOD_TYPE_QRV) { + wc->cmdq[card & 0xfc].cmds[USER_COMMANDS + 1] = CMD_RD(3); /* Battery */ +#ifdef VPM_SUPPORT + } else if (wc->modtype[card] == MOD_TYPE_VPM) { + wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(0xbd); /* DTMF interrupt */ +#endif + } + } +} + +static inline void wctdm_transmitprep(struct wctdm *wc, int dbl) +{ + volatile unsigned char *writechunk; + int x,y; + + dbl = dbl % 2; + + writechunk = (volatile unsigned char *)(wc->writechunk); + if (dbl) + /* Write is at interrupt address. Start writing from normal offset */ + writechunk += SFRAME_SIZE; + + /* Calculate Transmission */ + zt_transmit(&wc->span); + + for (x=0;xcards;y++) { + if (!x) + cmd_checkisr(wc, y); + + if (y < wc->type) + writechunk[y] = wc->chans[y].writechunk[x]; + cmd_dequeue(wc, writechunk, y, x); + } +#ifdef VPM_SUPPORT + if (!x) + wc->blinktimer++; + if (wc->vpm) { + for (y=24;y<28;y++) { + if (!x) + cmd_checkisr(wc, y); + cmd_dequeue(wc, writechunk, y, x); + } +#ifdef FANCY_ECHOCAN + if (wc->vpm && wc->blinktimer >= 0xf) { + wc->blinktimer = -1; + wc->echocanpos++; + } +#endif + } else if (wc->vpm150m) { + cmd_dequeue_vpm150m(wc, writechunk, x); + } +#endif + if (x < ZT_CHUNKSIZE - 1) { + writechunk[EFRAME_SIZE] = wc->ctlreg; + writechunk[EFRAME_SIZE + 1] = wc->txident++; +#if 1 + if ((wc->type == 4) && ((wc->ctlreg & 0x10) || (wc->modtype[NUM_CARDS] == MOD_TYPE_NONE))) { + writechunk[EFRAME_SIZE + 2] = 0; + for (y = 0; y < 4; y++) { + if (wc->modtype[y] == MOD_TYPE_NONE) + writechunk[EFRAME_SIZE + 2] |= (1 << y); + } + } else + writechunk[EFRAME_SIZE + 2] = 0xf; +#endif + } + writechunk += (EFRAME_SIZE + EFRAME_GAP); + } +} + +static inline void __wctdm_setctl(struct wctdm *wc, unsigned int addr, unsigned int val) +{ + outl(val, wc->iobase + addr); +} + +static inline unsigned int __wctdm_getctl(struct wctdm *wc, unsigned int addr) +{ + return inl(wc->iobase + addr); +} + +static inline void wctdm_setctl(struct wctdm *wc, unsigned int addr, unsigned int val) +{ + unsigned long flags; + spin_lock_irqsave(&wc->reglock, flags); + __wctdm_setctl(wc, addr, val); + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static inline int wctdm_setreg_full(struct wctdm *wc, int card, int addr, int val, int inisr) +{ + unsigned long flags; + int hit=0; + int ret; + + /* if a QRV card, use only its first channel */ + if (wc->modtype[card] == MOD_TYPE_QRV) + { + if (card & 3) return(0); + } + do { + spin_lock_irqsave(&wc->reglock, flags); + hit = empty_slot(wc, card); + if (hit > -1) { + wc->cmdq[card].cmds[hit] = CMD_WR(addr, val); + } + spin_unlock_irqrestore(&wc->reglock, flags); + if (inisr) + break; + if (hit < 0) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (hit < 0); + return (hit > -1) ? 0 : -1; +} + +static inline int wctdm_setreg_intr(struct wctdm *wc, int card, int addr, int val) +{ + return wctdm_setreg_full(wc, card, addr, val, 1); +} +static inline int wctdm_setreg(struct wctdm *wc, int card, int addr, int val) +{ + return wctdm_setreg_full(wc, card, addr, val, 0); +} + +static inline int wctdm_getreg(struct wctdm *wc, int card, int addr) +{ + unsigned long flags; + int hit; + int ret=0; + + /* if a QRV card, use only its first channel */ + if (wc->modtype[card] == MOD_TYPE_QRV) + { + if (card & 3) return(0); + } + do { + spin_lock_irqsave(&wc->reglock, flags); + hit = empty_slot(wc, card); + if (hit > -1) { + wc->cmdq[card].cmds[hit] = CMD_RD(addr); + } + spin_unlock_irqrestore(&wc->reglock, flags); + if (hit < 0) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (hit < 0); + do { + spin_lock_irqsave(&wc->reglock, flags); + if (wc->cmdq[card].cmds[hit] & __CMD_FIN) { + ret = wc->cmdq[card].cmds[hit] & 0xff; + wc->cmdq[card].cmds[hit] = 0x00000000; + hit = -1; + } + spin_unlock_irqrestore(&wc->reglock, flags); + if (hit > -1) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (hit > -1); + return ret; +} + +static inline unsigned int wctdm_getctl(struct wctdm *wc, unsigned int addr) +{ + unsigned long flags; + unsigned int val; + spin_lock_irqsave(&wc->reglock, flags); + val = __wctdm_getctl(wc, addr); + spin_unlock_irqrestore(&wc->reglock, flags); + return val; +} + +static inline int __wctdm_sdi_clk(struct wctdm *wc) +{ + unsigned int ret; + wc->sdi &= ~SDI_CLK; + __wctdm_setctl(wc, 0x0048, wc->sdi); + ret = __wctdm_getctl(wc, 0x0048); + wc->sdi |= SDI_CLK; + __wctdm_setctl(wc, 0x0048, wc->sdi); + return ret & SDI_DIN; +} + +static inline void __wctdm_sdi_sendbits(struct wctdm *wc, unsigned int bits, int count) +{ + wc->sdi &= ~SDI_DREAD; + __wctdm_setctl(wc, 0x0048, wc->sdi); + while(count--) { + if (bits & (1 << count)) + wc->sdi |= SDI_DOUT; + else + wc->sdi &= ~SDI_DOUT; + __wctdm_sdi_clk(wc); + } +} + +static inline unsigned int __wctdm_sdi_recvbits(struct wctdm *wc, int count) +{ + unsigned int bits=0; + wc->sdi |= SDI_DREAD; + __wctdm_setctl(wc, 0x0048, wc->sdi); + while(count--) { + bits <<= 1; + if (__wctdm_sdi_clk(wc)) + bits |= 1; + else + bits &= ~1; + } + return bits; +} + +static inline void __wctdm_setsdi(struct wctdm *wc, unsigned char addr, unsigned short value) +{ + unsigned int bits; + /* Send preamble */ + bits = 0xffffffff; + __wctdm_sdi_sendbits(wc, bits, 32); + bits = (0x5 << 12) | (1 << 7) | (addr << 2) | 0x2; + __wctdm_sdi_sendbits(wc, bits, 16); + __wctdm_sdi_sendbits(wc, value, 16); + +} + +static inline unsigned short __wctdm_getsdi(struct wctdm *wc, unsigned char addr) +{ + unsigned int bits; + /* Send preamble */ + bits = 0xffffffff; + __wctdm_sdi_sendbits(wc, bits, 32); + bits = (0x6 << 10) | (1 << 5) | (addr); + __wctdm_sdi_sendbits(wc, bits, 14); + return __wctdm_sdi_recvbits(wc, 18); +} + +static inline void wctdm_setsdi(struct wctdm *wc, unsigned char addr, unsigned short value) +{ + unsigned long flags; + spin_lock_irqsave(&wc->reglock, flags); + __wctdm_setsdi(wc, addr, value); + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static inline unsigned short wctdm_getsdi(struct wctdm *wc, unsigned char addr) +{ + unsigned long flags; + unsigned short val; + spin_lock_irqsave(&wc->reglock, flags); + val = __wctdm_getsdi(wc, addr); + spin_unlock_irqrestore(&wc->reglock, flags); + return val; +} + +#ifdef VPM_SUPPORT +static inline unsigned char wctdm_vpm_in(struct wctdm *wc, int unit, const unsigned int addr) +{ + return wctdm_getreg(wc, unit + NUM_CARDS, addr); +} + +static inline void wctdm_vpm_out(struct wctdm *wc, int unit, const unsigned int addr, const unsigned char val) +{ + wctdm_setreg(wc, unit + NUM_CARDS, addr, val); +} + +static inline void cmd_vpm150m_retransmit(struct wctdm *wc) +{ + unsigned long flags; + int x; + + spin_lock_irqsave(&wc->reglock, flags); + for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { + if (!(wc->vpm150m->cmdq[x].desc & __VPM150M_FIN)) { + //printk("Retransmit!\n"); + wc->vpm150m->cmdq[x].desc &= ~(__VPM150M_TX); + } + } + spin_unlock_irqrestore(&wc->reglock, flags); + +} +#endif + +static inline void cmd_retransmit(struct wctdm *wc) +{ + int x,y; + unsigned long flags; + /* Force retransmissions */ + spin_lock_irqsave(&wc->reglock, flags); + for (x=0;xcards;y++) { + if (!(wc->cmdq[y].cmds[x] & __CMD_FIN)) + wc->cmdq[y].cmds[x] &= ~(__CMD_TX | (0xff << 24)); + } + } + spin_unlock_irqrestore(&wc->reglock, flags); +#ifdef VPM_SUPPORT + if (wc->vpm150m) + cmd_vpm150m_retransmit(wc); +#endif +} + +static inline void wctdm_receiveprep(struct wctdm *wc, int dbl) +{ + volatile unsigned char *readchunk; + int x,y; + unsigned char expected; + + dbl = dbl % 2; + + readchunk = (volatile unsigned char *)wc->readchunk; + if (dbl) + readchunk += SFRAME_SIZE; + for (x=0;xrxident+1; + wc->rxident = readchunk[EFRAME_SIZE + 1]; + if (wc->rxident != expected) { + wc->span.irqmisses++; + cmd_retransmit(wc); + } + } + for (y=0;y < wc->cards;y++) { + if (y < wc->type) { + wc->chans[y].readchunk[x] = readchunk[y]; + } + cmd_decifer(wc, readchunk, y); + } +#ifdef VPM_SUPPORT + if (wc->vpm) { + for (y=NUM_CARDS;y < NUM_CARDS + NUM_EC; y++) + cmd_decifer(wc, readchunk, y); + } else if (wc->vpm150m) + cmd_decifer_vpm150m(wc, readchunk); +#endif +#if 0 + if (cmddesc < 1024) { + printk("RC Result: %02x\n", readchunk[EFRAME_SIZE+1]); + } +#endif + readchunk += (EFRAME_SIZE + EFRAME_GAP); + } + /* XXX We're wasting 8 taps. We should get closer :( */ + for (x=0;xtype;x++) { + if (wc->cardflag & (1 << x)) + zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->chans[x].writechunk); + } + zt_receive(&wc->span); + /* Wake up anyone sleeping to read/write a new register */ + wake_up_interruptible(&wc->regq); +} + +static void wctdm_stop_dma(struct wctdm *wc); +static void wctdm_restart_dma(struct wctdm *wc); + +static int wait_access(struct wctdm *wc, int card) +{ + unsigned char data=0; + long origjiffies; + int count = 0; + + #define MAX 10 /* attempts */ + + + origjiffies = jiffies; + /* Wait for indirect access */ + while (count++ < MAX) + { + data = wctdm_getreg(wc, card, I_STATUS); + + if (!data) + return 0; + + } + + if(count > (MAX-1)) printk(" ##### Loop error (%02x) #####\n", data); + + return 0; +} + +static unsigned char translate_3215(unsigned char address) +{ + int x; + for (x=0;xflags[card] & FLAG_3215) { + address = translate_3215(address); + if (address == 255) + return 0; + } + if(!wait_access(wc, card)) { + wctdm_setreg(wc, card, IDA_LO,(unsigned char)(data & 0xFF)); + wctdm_setreg(wc, card, IDA_HI,(unsigned char)((data & 0xFF00)>>8)); + wctdm_setreg(wc, card, IAA,address); + res = 0; + }; + return res; +} + +static int wctdm_proslic_getreg_indirect(struct wctdm *wc, int card, unsigned char address) +{ + int res = -1; + char *p=NULL; + /* Translate 3215 addresses */ + if (wc->flags[card] & FLAG_3215) { + address = translate_3215(address); + if (address == 255) + return 0; + } + if (!wait_access(wc, card)) { + wctdm_setreg(wc, card, IAA, address); + if (!wait_access(wc, card)) { + unsigned char data1, data2; + data1 = wctdm_getreg(wc, card, IDA_LO); + data2 = wctdm_getreg(wc, card, IDA_HI); + res = data1 | (data2 << 8); + } else + p = "Failed to wait inside\n"; + } else + p = "failed to wait\n"; + if (p) + printk(p); + return res; +} + +static int wctdm_proslic_init_indirect_regs(struct wctdm *wc, int card) +{ + unsigned char i; + + for (i=0; iflags[card] & FLAG_3215) || (indirect_regs[i].altaddr != 255))) + { + printk("!!!!!!! %s iREG %X = %X should be %X\n", + indirect_regs[i].name,indirect_regs[i].address,j,initial ); + passed = 0; + } + } + + if (passed) { + if (debug & DEBUG_CARD) + printk("Init Indirect Registers completed successfully.\n"); + } else { + printk(" !!!!! Init Indirect Registers UNSUCCESSFULLY.\n"); + return -1; + } + return 0; +} + +static inline void wctdm_proslic_recheck_sanity(struct wctdm *wc, int card) +{ + int res; +#ifdef PAQ_DEBUG + res = wc->cmdq[card].isrshadow[1]; + res &= ~0x3; + if (res) { + wc->cmdq[card].isrshadow[1]=0; + wc->mods[card].fxs.palarms++; + if (wc->mods[card].fxs.palarms < MAX_ALARMS) { + printk("Power alarm (%02x) on module %d, resetting!\n", res, card + 1); + if (wc->mods[card].fxs.lasttxhook == 4) + wc->mods[card].fxs.lasttxhook = 0x11; + wc->sethook[card] = CMD_WR(19, res); +#if 0 + wc->sethook[card] = CMD_WR(64, wc->mods[card].fxs.lasttxhook); +#endif + + /* wctdm_setreg_intr(wc, card, 64, wc->mods[card].fxs.lasttxhook); */ + /* Update shadow register to avoid extra power alarms until next read */ + wc->cmdq[card].isrshadow[1] = 0; + } else { + if (wc->mods[card].fxs.palarms == MAX_ALARMS) + printk("Too many power alarms on card %d, NOT resetting!\n", card + 1); + } + } +#else + res = wc->cmdq[card].isrshadow[1]; + /* This makes sure the lasthook was put in reg 64 the linefeed reg */ + if (((res & 0x0f) | 0x10) == wc->mods[card].fxs.lasttxhook) + wc->mods[card].fxs.lasttxhook &= 0x0f; + + res = !res && /* reg 64 has to be zero at last isr read */ + !(wc->mods[card].fxs.lasttxhook & 0x10 ) && /* not a transition */ + wc->mods[card].fxs.lasttxhook; /* not an intended zero */ + + if (res) { + wc->mods[card].fxs.palarms++; + if (wc->mods[card].fxs.palarms < MAX_ALARMS) { + printk("Power alarm on module %d, resetting!\n", card + 1); + if (wc->mods[card].fxs.lasttxhook == 4) + wc->mods[card].fxs.lasttxhook = 0x11; + wc->mods[card].fxs.lasttxhook |= 0x10; + wc->sethook[card] = CMD_WR(64, wc->mods[card].fxs.lasttxhook); + + /* wctdm_setreg_intr(wc, card, 64, wc->mods[card].fxs.lasttxhook); */ + /* Update shadow register to avoid extra power alarms until next read */ + wc->cmdq[card].isrshadow[1] = wc->mods[card].fxs.lasttxhook; + } else { + if (wc->mods[card].fxs.palarms == MAX_ALARMS) + printk("Too many power alarms on card %d, NOT resetting!\n", card + 1); + } + } +#endif +} + +static inline void wctdm_qrvdri_check_hook(struct wctdm *wc, int card) +{ + signed char b,b1; + int qrvcard = card & 0xfc; + + + if (wc->qrvdebtime[card] >= 2) wc->qrvdebtime[card]--; + b = wc->cmdq[qrvcard].isrshadow[0]; /* Hook/Ring state */ + b &= 0xcc; /* use bits 3-4 and 6-7 only */ + + if (wc->radmode[qrvcard] & RADMODE_IGNORECOR) b &= ~4; + else if (!(wc->radmode[qrvcard] & RADMODE_INVERTCOR)) b ^= 4; + if (wc->radmode[qrvcard + 1] | RADMODE_IGNORECOR) b &= ~0x40; + else if (!(wc->radmode[qrvcard + 1] | RADMODE_INVERTCOR)) b ^= 0x40; + + if ((wc->radmode[qrvcard] & RADMODE_IGNORECT) || + (!(wc->radmode[qrvcard] & RADMODE_EXTTONE))) b &= ~8; + else if (!(wc->radmode[qrvcard] & RADMODE_EXTINVERT)) b ^= 8; + if ((wc->radmode[qrvcard + 1] & RADMODE_IGNORECT) || + (!(wc->radmode[qrvcard + 1] & RADMODE_EXTTONE))) b &= ~0x80; + else if (!(wc->radmode[qrvcard + 1] & RADMODE_EXTINVERT)) b ^= 0x80; + /* now b & MASK should be zero, if its active */ + /* check for change in chan 0 */ + if ((!(b & 0xc)) != wc->qrvhook[qrvcard + 2]) + { + wc->qrvdebtime[qrvcard] = wc->debouncetime[qrvcard]; + wc->qrvhook[qrvcard + 2] = !(b & 0xc); + } + /* if timed-out and ready */ + if (wc->qrvdebtime[qrvcard] == 1) + { + b1 = wc->qrvhook[qrvcard + 2]; +if (debug) printk("QRV channel %d rx state changed to %d\n",qrvcard,wc->qrvhook[qrvcard + 2]); + zt_hooksig(&wc->chans[qrvcard], + (b1) ? ZT_RXSIG_OFFHOOK : ZT_RXSIG_ONHOOK); + wc->qrvdebtime[card] = 0; + } + /* check for change in chan 1 */ + if ((!(b & 0xc0)) != wc->qrvhook[qrvcard + 3]) + { + wc->qrvdebtime[qrvcard + 1] = QRV_DEBOUNCETIME; + wc->qrvhook[qrvcard + 3] = !(b & 0xc0); + } + if (wc->qrvdebtime[qrvcard + 1] == 1) + { + b1 = wc->qrvhook[qrvcard + 3]; +if (debug) printk("QRV channel %d rx state changed to %d\n",qrvcard + 1,wc->qrvhook[qrvcard + 3]); + zt_hooksig(&wc->chans[qrvcard + 1], + (b1) ? ZT_RXSIG_OFFHOOK : ZT_RXSIG_ONHOOK); + wc->qrvdebtime[card] = 0; + } + return; +} + +static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card) +{ + unsigned char res; + signed char b; + /* Try to track issues that plague slot one FXO's */ + b = wc->cmdq[card].isrshadow[0]; /* Hook/Ring state */ + b &= 0x9b; + if (wc->mods[card].fxo.offhook) { + if (b != 0x9) + wctdm_setreg_intr(wc, card, 5, 0x9); + } else { + if (b != 0x8) + wctdm_setreg_intr(wc, card, 5, 0x8); + } + if (!wc->mods[card].fxo.offhook) { + if (fwringdetect) { + res = wc->cmdq[card].isrshadow[0] & 0x60; + if (wc->mods[card].fxo.ringdebounce--) { + if (res && (res != wc->mods[card].fxo.lastrdtx) && (wc->mods[card].fxo.battery == 1)) { + if (!wc->mods[card].fxo.wasringing) { + wc->mods[card].fxo.wasringing = 1; + if (debug) + printk("RING on %d/%d!\n", wc->span.spanno, card + 1); + zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); + } + wc->mods[card].fxo.lastrdtx = res; + wc->mods[card].fxo.ringdebounce = 10; + } else if (!res) { + if ((wc->mods[card].fxo.ringdebounce == 0) && wc->mods[card].fxo.wasringing) { + wc->mods[card].fxo.wasringing = 0; + if (debug) + printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); + zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); + } + } + } else if (res && (wc->mods[card].fxo.battery == 1)) { + wc->mods[card].fxo.lastrdtx = res; + wc->mods[card].fxo.ringdebounce = 10; + } + } else { + res = wc->cmdq[card].isrshadow[0]; + if ((res & 0x60) && (wc->mods[card].fxo.battery == 1)) { + wc->mods[card].fxo.ringdebounce += (ZT_CHUNKSIZE * 16); + if (wc->mods[card].fxo.ringdebounce >= ZT_CHUNKSIZE * ringdebounce) { + if (!wc->mods[card].fxo.wasringing) { + wc->mods[card].fxo.wasringing = 1; + zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); + if (debug) + printk("RING on %d/%d!\n", wc->span.spanno, card + 1); + } + wc->mods[card].fxo.ringdebounce = ZT_CHUNKSIZE * ringdebounce; + } + } else { + wc->mods[card].fxo.ringdebounce -= ZT_CHUNKSIZE * 4; + if (wc->mods[card].fxo.ringdebounce <= 0) { + if (wc->mods[card].fxo.wasringing) { + wc->mods[card].fxo.wasringing = 0; + zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); + if (debug) + printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); + } + wc->mods[card].fxo.ringdebounce = 0; + } + + } + } + } + b = wc->cmdq[card].isrshadow[1]; /* Voltage */ + + if (fxovoltage) { + if (!(wc->intcount % 100)) { + printk("Port %d: Voltage: %d Debounce %d\n", card + 1, + b, wc->mods[card].fxo.battdebounce); + } + } + + if (abs(b) < battthresh) { + wc->mods[card].fxo.nobatttimer++; +#if 0 + if (wc->mods[card].fxo.battery == 1) + printk("Battery loss: %d (%d debounce)\n", b, wc->mods[card].fxo.battdebounce); +#endif + if (wc->mods[card].fxo.battery && !wc->mods[card].fxo.battdebounce) { + if (debug & DEBUG_CARD) + printk("NO BATTERY on %d/%d!\n", wc->span.spanno, card + 1); + wc->mods[card].fxo.battery = 0; +#ifdef JAPAN + if ((!wc->ohdebounce) && wc->offhook) { + zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); + if (debug & DEBUG_CARD) + printk("Signalled On Hook\n"); +#ifdef ZERO_BATT_RING + wc->onhook++; +#endif + } +#else + zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); + zt_alarm_channel(&wc->chans[card], ZT_ALARM_RED); +#endif + wc->mods[card].fxo.battdebounce = battdebounce; + } else if (!wc->mods[card].fxo.battery) + wc->mods[card].fxo.battdebounce = battdebounce; + } else if (abs(b) > battthresh) { + if ((wc->mods[card].fxo.battery < 1) && !wc->mods[card].fxo.battdebounce) { + if (debug & DEBUG_CARD) + printk("BATTERY on %d/%d (%s)!\n", wc->span.spanno, card + 1, + (b < 0) ? "-" : "+"); +#ifdef ZERO_BATT_RING + if (wc->onhook) { + wc->onhook = 0; + zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); + if (debug & DEBUG_CARD) + printk("Signalled Off Hook\n"); + } +#else + zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); + zt_alarm_channel(&wc->chans[card], ZT_ALARM_NONE); +#endif + wc->mods[card].fxo.battery = 1; + wc->mods[card].fxo.nobatttimer = 0; + wc->mods[card].fxo.battdebounce = battdebounce; + } else if (wc->mods[card].fxo.battery == 1) + wc->mods[card].fxo.battdebounce = battdebounce; + + if (wc->mods[card].fxo.lastpol >= 0) { + if (b < 0) { + wc->mods[card].fxo.lastpol = -1; + wc->mods[card].fxo.polaritydebounce = POLARITY_DEBOUNCE; + } + } + if (wc->mods[card].fxo.lastpol <= 0) { + if (b > 0) { + wc->mods[card].fxo.lastpol = 1; + wc->mods[card].fxo.polaritydebounce = POLARITY_DEBOUNCE; + } + } + } else { + /* It's something else... */ + wc->mods[card].fxo.battdebounce = battdebounce; + } + if (wc->mods[card].fxo.battdebounce) + wc->mods[card].fxo.battdebounce--; + if (wc->mods[card].fxo.polaritydebounce) { + wc->mods[card].fxo.polaritydebounce--; + if (wc->mods[card].fxo.polaritydebounce < 1) { + if (wc->mods[card].fxo.lastpol != wc->mods[card].fxo.polarity) { + if (debug & DEBUG_CARD) + printk("%lu Polarity reversed (%d -> %d)\n", jiffies, + wc->mods[card].fxo.polarity, + wc->mods[card].fxo.lastpol); + if (wc->mods[card].fxo.polarity) + zt_qevent_lock(&wc->chans[card], ZT_EVENT_POLARITY); + wc->mods[card].fxo.polarity = wc->mods[card].fxo.lastpol; + } + } + } +} + +static inline void wctdm_proslic_check_hook(struct wctdm *wc, int card) +{ + char res; + int hook; + + /* For some reason we have to debounce the + hook detector. */ + + res = wc->cmdq[card].isrshadow[0]; /* Hook state */ + hook = (res & 1); + + if (hook != wc->mods[card].fxs.lastrxhook) { + /* Reset the debounce (must be multiple of 4ms) */ + wc->mods[card].fxs.debounce = 8 * (4 * 8); +#if 0 + printk("Resetting debounce card %d hook %d, %d\n", card, hook, wc->mods[card].fxs.debounce); +#endif + } else { + if (wc->mods[card].fxs.debounce > 0) { + wc->mods[card].fxs.debounce-= 4 * ZT_CHUNKSIZE; +#if 0 + printk("Sustaining hook %d, %d\n", hook, wc->mods[card].fxs.debounce); +#endif + if (!wc->mods[card].fxs.debounce) { +#if 0 + printk("Counted down debounce, newhook: %d...\n", hook); +#endif + wc->mods[card].fxs.debouncehook = hook; + } + if (!wc->mods[card].fxs.oldrxhook && wc->mods[card].fxs.debouncehook) { + /* Off hook */ + if (debug & DEBUG_CARD) + printk("wctdm: Card %d Going off hook\n", card); + zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); + if (robust) + wctdm_init_proslic(wc, card, 1, 0, 1); + wc->mods[card].fxs.oldrxhook = 1; + + } else if (wc->mods[card].fxs.oldrxhook && !wc->mods[card].fxs.debouncehook) { + /* On hook */ + if (debug & DEBUG_CARD) + printk("wctdm: Card %d Going on hook\n", card); + zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); + wc->mods[card].fxs.oldrxhook = 0; + } + } + } + wc->mods[card].fxs.lastrxhook = hook; +} + + +static inline void wctdm_reinit_descriptor(struct wctdm *wc, int tx, int dbl, char *s) +{ + int o2 = 0; + o2 += dbl * 4; + if (!tx) + o2 += ERING_SIZE * 4; + wc->descripchunk[o2] = 0x80000000; +} + +#ifdef VPM_SUPPORT +static inline void wctdm_vpm_check(struct wctdm *wc, int x) +{ + if (wc->cmdq[x].isrshadow[0]) { + if (debug & DEBUG_ECHOCAN) + printk("VPM: Detected dtmf ON channel %02x on chip %d!\n", wc->cmdq[x].isrshadow[0], x - NUM_CARDS); + wc->sethook[x] = CMD_WR(0xb9, wc->cmdq[x].isrshadow[0]); + wc->cmdq[x].isrshadow[0] = 0; + /* Cancel most recent lookup, if there is one */ + wc->cmdq[x].cmds[USER_COMMANDS+0] = 0x00000000; + } else if (wc->cmdq[x].isrshadow[1]) { + if (debug & DEBUG_ECHOCAN) + printk("VPM: Detected dtmf OFF channel %02x on chip %d!\n", wc->cmdq[x].isrshadow[1], x - NUM_CARDS); + wc->sethook[x] = CMD_WR(0xbd, wc->cmdq[x].isrshadow[1]); + wc->cmdq[x].isrshadow[1] = 0; + /* Cancel most recent lookup, if there is one */ + wc->cmdq[x].cmds[USER_COMMANDS+1] = 0x00000000; + } +} + +#include "adt_lec.c" + +static int wctdm_echocan_with_params(struct zt_chan *chan, struct zt_echocanparams *ecp, struct zt_echocanparam *p) +{ + struct wctdm *wc = chan->pvt; + + if (wc->vpm) { + int channel; + int unit; + + channel = (chan->chanpos - 1); + unit = (chan->chanpos - 1) & 0x3; + if (wc->vpm < 2) + channel >>= 2; + + if(debug & DEBUG_ECHOCAN) + printk("echocan: Unit is %d, Channel is %d length %d\n", + unit, channel, ecp->tap_length); + if (ecp->tap_length) + wctdm_vpm_out(wc,unit,channel,0x3e); + else + wctdm_vpm_out(wc,unit,channel,0x01); + + return 0; +#ifdef VPM150M_SUPPORT + } else if (wc->vpm150m) { + struct vpm150m *vpm150m = wc->vpm150m; + unsigned int ret; + int channo = chan->chanpos - 1; + + if ((ret = adt_lec_parse_params(&vpm150m->desiredecstate[channo], ecp, p))) + return ret; + + vpm150m->desiredecstate[channo].tap_length = ecp->tap_length; + + if (memcmp(&vpm150m->curecstate[channo], &vpm150m->desiredecstate[channo], sizeof(vpm150m->curecstate[channo])) + && test_bit(VPM150M_ACTIVE, &vpm150m->control)) + queue_work(vpm150m->wq, &vpm150m->work); + + return 0; +#endif + } else + return -ENODEV; +} +#endif + +static inline void wctdm_isr_misc(struct wctdm *wc) +{ + int x; + + for (x=0;xcards;x++) { + if (wc->cardflag & (1 << x)) { + if (wc->modtype[x] == MOD_TYPE_FXS) { + if (!(wc->intcount % 10000)) { + /* Accept an alarm once per 10 seconds */ + if (wc->mods[x].fxs.palarms) + wc->mods[x].fxs.palarms--; + } + wctdm_proslic_check_hook(wc, x); + if (!(wc->intcount & 0xfc)) + wctdm_proslic_recheck_sanity(wc, x); + if (wc->mods[x].fxs.lasttxhook == 0x4) { + /* RINGing, prepare for OHT */ + wc->mods[x].fxs.ohttimer = OHT_TIMER << 3; + wc->mods[x].fxs.idletxhookstate = 0x2; /* OHT mode when idle */ + } else { + if (wc->mods[x].fxs.ohttimer) { + wc->mods[x].fxs.ohttimer-= ZT_CHUNKSIZE; + if (!wc->mods[x].fxs.ohttimer) { + wc->mods[x].fxs.idletxhookstate = 0x1; /* Switch to active */ + if (wc->mods[x].fxs.lasttxhook == 0x2) { + /* Apply the change if appropriate */ + wc->mods[x].fxs.lasttxhook = 0x11; + wc->sethook[x] = CMD_WR(64, wc->mods[x].fxs.lasttxhook); + /* wctdm_setreg_intr(wc, x, 64, wc->mods[x].fxs.lasttxhook); */ + } + } + } + } + } else if (wc->modtype[x] == MOD_TYPE_FXO) { + wctdm_voicedaa_check_hook(wc, x); + } else if (wc->modtype[x] == MOD_TYPE_QRV) { + wctdm_qrvdri_check_hook(wc, x); + } + } + } +#ifdef VPM_SUPPORT + if (wc->vpm > 0) { + for (x=NUM_CARDS;xrdbl * 4; + } else { + o2 += wc->tdbl * 4; + } + if (!(wc->descripchunk[o2] & 0x80000000)) { + if (tx) { + wc->txints++; + wctdm_transmitprep(wc, wc->tdbl); + wctdm_reinit_descriptor(wc, tx, wc->tdbl, "txchk"); + wc->tdbl = (wc->tdbl + 1) % ERING_SIZE; + wctdm_isr_misc(wc); + wc->intcount++; + } else { + wc->rxints++; + wctdm_receiveprep(wc, wc->rdbl); + wctdm_reinit_descriptor(wc, tx, wc->rdbl, "rxchk"); + wc->rdbl = (wc->rdbl + 1) % ERING_SIZE; + } + return 1; + } + return 0; +} + +static void wctdm_init_descriptors(struct wctdm *wc) +{ + volatile unsigned int *descrip; + dma_addr_t descripdma; + dma_addr_t writedma; + dma_addr_t readdma; + int x; + + descrip = wc->descripchunk; + descripdma = wc->descripdma; + writedma = wc->writedma; + readdma = wc->readdma; + + for (x=0;xdescripdma; + + /* Transmit descriptor */ + descrip[0 ] = 0x80000000; + descrip[1 ] = 0xe5800000 | (SFRAME_SIZE); + if (x % 2) + descrip[2 ] = writedma + SFRAME_SIZE; + else + descrip[2 ] = writedma; + descrip[3 ] = descripdma; + + /* Receive descriptor */ + descrip[0 + ERING_SIZE * 4] = 0x80000000; + descrip[1 + ERING_SIZE * 4] = 0x01000000 | (SFRAME_SIZE); + if (x % 2) + descrip[2 + ERING_SIZE * 4] = readdma + SFRAME_SIZE; + else + descrip[2 + ERING_SIZE * 4] = readdma; + descrip[3 + ERING_SIZE * 4] = descripdma + ERING_SIZE * 16; + + /* Advance descriptor */ + descrip += 4; + } +} + +ZAP_IRQ_HANDLER(wctdm_interrupt) +{ + struct wctdm *wc = dev_id; + unsigned int ints; + int res; + + /* Read and clear interrupts */ + ints = wctdm_getctl(wc, 0x0028); + + if (!ints) +#ifdef LINUX26 + return IRQ_NONE; +#else + return; +#endif + + wctdm_setctl(wc, 0x0028, ints); + + ints &= wc->intmask; + if (ints & 0x00000041) { + do { + res = wctdm_check_descriptor(wc, 0); + res |= wctdm_check_descriptor(wc, 1); + } while(res); +#if 0 + while(wctdm_check_descriptor(wc, 0)); + wctdm_setctl(wc, 0x0010, 0x00000000); + } + if (ints & 0x00000005) { + while(wctdm_check_descriptor(wc, 1)); + wctdm_setctl(wc, 0x0008, 0x00000000); +#endif + } + + if (ints & 0x0000a3ae) { + /* This will allow us to recover if interrupts are held for a long period of time */ + if (debug & DEBUG_CARD) + printk("Abnormal interrupt %08x detected\n", ints); + wctdm_setctl(wc, 0x0008, 0x00000000); + wctdm_setctl(wc, 0x0010, 0x00000000); + } + +#ifdef LINUX26 + return IRQ_RETVAL(1); +#endif + +} + +static int wctdm_voicedaa_insane(struct wctdm *wc, int card) +{ + int blah; + blah = wctdm_getreg(wc, card, 2); + if (blah != 0x3) + return -2; + blah = wctdm_getreg(wc, card, 11); + if (debug & DEBUG_CARD) + printk("VoiceDAA System: %02x\n", blah & 0xf); + return 0; +} + +static int wctdm_proslic_insane(struct wctdm *wc, int card) +{ + int blah,insane_report; + insane_report=0; + + blah = wctdm_getreg(wc, card, 0); + if (debug & DEBUG_CARD) + printk("ProSLIC on module %d, product %d, version %d\n", card, (blah & 0x30) >> 4, (blah & 0xf)); + +#if 0 + if ((blah & 0x30) >> 4) { + printk("ProSLIC on module %d is not a 3210.\n", card); + return -1; + } +#endif + if (((blah & 0xf) == 0) || ((blah & 0xf) == 0xf)) { + /* SLIC not loaded */ + return -1; + } + if ((blah & 0xf) < 2) { + printk("ProSLIC 3210 version %d is too old\n", blah & 0xf); + return -1; + } + if (wctdm_getreg(wc, card, 1) & 0x80) + /* ProSLIC 3215, not a 3210 */ + wc->flags[card] |= FLAG_3215; + + blah = wctdm_getreg(wc, card, 8); + if (blah != 0x2) { + printk("ProSLIC on module %d insane (1) %d should be 2\n", card, blah); + return -1; + } else if ( insane_report) + printk("ProSLIC on module %d Reg 8 Reads %d Expected is 0x2\n",card,blah); + + blah = wctdm_getreg(wc, card, 64); + if (blah != 0x0) { + printk("ProSLIC on module %d insane (2)\n", card); + return -1; + } else if ( insane_report) + printk("ProSLIC on module %d Reg 64 Reads %d Expected is 0x0\n",card,blah); + + blah = wctdm_getreg(wc, card, 11); + if (blah != 0x33) { + printk("ProSLIC on module %d insane (3)\n", card); + return -1; + } else if ( insane_report) + printk("ProSLIC on module %d Reg 11 Reads %d Expected is 0x33\n",card,blah); + + /* Just be sure it's setup right. */ + wctdm_setreg(wc, card, 30, 0); + + if (debug & DEBUG_CARD) + printk("ProSLIC on module %d seems sane.\n", card); + return 0; +} + +static int wctdm_proslic_powerleak_test(struct wctdm *wc, int card) +{ + unsigned long origjiffies; + unsigned char vbat; + + /* Turn off linefeed */ + wctdm_setreg(wc, card, 64, 0); + + /* Power down */ + wctdm_setreg(wc, card, 14, 0x10); + + /* Wait for one second */ + origjiffies = jiffies; + + while((vbat = wctdm_getreg(wc, card, 82)) > 0x6) { + if ((jiffies - origjiffies) >= (HZ/2)) + break;; + } + + if (vbat < 0x06) { + printk("Excessive leakage detected on module %d: %d volts (%02x) after %d ms\n", card, + 376 * vbat / 1000, vbat, (int)((jiffies - origjiffies) * 1000 / HZ)); + return -1; + } else if (debug & DEBUG_CARD) { + printk("Post-leakage voltage: %d volts\n", 376 * vbat / 1000); + } + return 0; +} + +static int wctdm_powerup_proslic(struct wctdm *wc, int card, int fast) +{ + unsigned char vbat; + unsigned long origjiffies; + int lim; + + /* Set period of DC-DC converter to 1/64 khz */ + wctdm_setreg(wc, card, 92, 0xc0 /* was 0xff */); + + /* Wait for VBat to powerup */ + origjiffies = jiffies; + + /* Disable powerdown */ + wctdm_setreg(wc, card, 14, 0); + + /* If fast, don't bother checking anymore */ + if (fast) + return 0; + + while((vbat = wctdm_getreg(wc, card, 82)) < 0xc0) { + /* Wait no more than 500ms */ + if ((jiffies - origjiffies) > HZ/2) { + break; + } + } + + if (vbat < 0xc0) { + printk("ProSLIC on module %d failed to powerup within %d ms (%d mV only)\n\n -- DID YOU REMEMBER TO PLUG IN THE HD POWER CABLE TO THE TDM CARD??\n", + card, (int)(((jiffies - origjiffies) * 1000 / HZ)), + vbat * 375); + return -1; + } else if (debug & DEBUG_CARD) { + printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n", + card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ))); + } + + /* Proslic max allowed loop current, reg 71 LOOP_I_LIMIT */ + /* If out of range, just set it to the default value */ + lim = (loopcurrent - 20) / 3; + if ( loopcurrent > 41 ) { + lim = 0; + if (debug & DEBUG_CARD) + printk("Loop current out of range! Setting to default 20mA!\n"); + } + else if (debug & DEBUG_CARD) + printk("Loop current set to %dmA!\n",(lim*3)+20); + wctdm_setreg(wc,card,LOOP_I_LIMIT,lim); + + /* Engage DC-DC converter */ + wctdm_setreg(wc, card, 93, 0x19 /* was 0x19 */); +#if 0 + origjiffies = jiffies; + while(0x80 & wctdm_getreg(wc, card, 93)) { + if ((jiffies - origjiffies) > 2 * HZ) { + printk("Timeout waiting for DC-DC calibration on module %d\n", card); + return -1; + } + } + +#if 0 + /* Wait a full two seconds */ + while((jiffies - origjiffies) < 2 * HZ); + + /* Just check to be sure */ + vbat = wctdm_getreg(wc, card, 82); + printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n", + card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ))); +#endif +#endif + return 0; + +} + +static int wctdm_proslic_manual_calibrate(struct wctdm *wc, int card) +{ + unsigned long origjiffies; + unsigned char i; + + wctdm_setreg(wc, card, 21, 0);//(0) Disable all interupts in DR21 + wctdm_setreg(wc, card, 22, 0);//(0)Disable all interupts in DR21 + wctdm_setreg(wc, card, 23, 0);//(0)Disable all interupts in DR21 + wctdm_setreg(wc, card, 64, 0);//(0) + + wctdm_setreg(wc, card, 97, 0x18); //(0x18)Calibrations without the ADC and DAC offset and without common mode calibration. + wctdm_setreg(wc, card, 96, 0x47); //(0x47) Calibrate common mode and differential DAC mode DAC + ILIM + + origjiffies=jiffies; + while( wctdm_getreg(wc,card,96)!=0 ){ + if((jiffies-origjiffies)>80) + return -1; + } +//Initialized DR 98 and 99 to get consistant results. +// 98 and 99 are the results registers and the search should have same intial conditions. + +/*******************************The following is the manual gain mismatch calibration****************************/ +/*******************************This is also available as a function *******************************************/ + // Delay 10ms + origjiffies=jiffies; + while((jiffies-origjiffies)<1); + wctdm_proslic_setreg_indirect(wc, card, 88,0); + wctdm_proslic_setreg_indirect(wc,card,89,0); + wctdm_proslic_setreg_indirect(wc,card,90,0); + wctdm_proslic_setreg_indirect(wc,card,91,0); + wctdm_proslic_setreg_indirect(wc,card,92,0); + wctdm_proslic_setreg_indirect(wc,card,93,0); + + wctdm_setreg(wc, card, 98,0x10); // This is necessary if the calibration occurs other than at reset time + wctdm_setreg(wc, card, 99,0x10); + + for ( i=0x1f; i>0; i--) + { + wctdm_setreg(wc, card, 98,i); + origjiffies=jiffies; + while((jiffies-origjiffies)<4); + if((wctdm_getreg(wc,card,88)) == 0) + break; + } // for + + for ( i=0x1f; i>0; i--) + { + wctdm_setreg(wc, card, 99,i); + origjiffies=jiffies; + while((jiffies-origjiffies)<4); + if((wctdm_getreg(wc,card,89)) == 0) + break; + }//for + +/*******************************The preceding is the manual gain mismatch calibration****************************/ +/**********************************The following is the longitudinal Balance Cal***********************************/ + wctdm_setreg(wc,card,64,1); + while((jiffies-origjiffies)<10); // Sleep 100? + + wctdm_setreg(wc, card, 64, 0); + wctdm_setreg(wc, card, 23, 0x4); // enable interrupt for the balance Cal + wctdm_setreg(wc, card, 97, 0x1); // this is a singular calibration bit for longitudinal calibration + wctdm_setreg(wc, card, 96,0x40); + + wctdm_getreg(wc,card,96); /* Read Reg 96 just cause */ + + wctdm_setreg(wc, card, 21, 0xFF); + wctdm_setreg(wc, card, 22, 0xFF); + wctdm_setreg(wc, card, 23, 0xFF); + + /**The preceding is the longitudinal Balance Cal***/ + return(0); + +} + +static int wctdm_proslic_calibrate(struct wctdm *wc, int card) +{ + unsigned long origjiffies; + int x; + /* Perform all calibrations */ + wctdm_setreg(wc, card, 97, 0x1f); + + /* Begin, no speedup */ + wctdm_setreg(wc, card, 96, 0x5f); + + /* Wait for it to finish */ + origjiffies = jiffies; + while(wctdm_getreg(wc, card, 96)) { + if ((jiffies - origjiffies) > 2 * HZ) { + printk("Timeout waiting for calibration of module %d\n", card); + return -1; + } + } + + if (debug & DEBUG_CARD) { + /* Print calibration parameters */ + printk("Calibration Vector Regs 98 - 107: \n"); + for (x=98;x<108;x++) { + printk("%d: %02x\n", x, wctdm_getreg(wc, card, x)); + } + } + return 0; +} + +static void wait_just_a_bit(int foo) +{ + long newjiffies; + newjiffies = jiffies + foo; + while(jiffies < newjiffies); +} + +/********************************************************************* + * Set the hwgain on the analog modules + * + * card = the card position for this module (0-23) + * gain = gain in dB x10 (e.g. -3.5dB would be gain=-35) + * tx = (0 for rx; 1 for tx) + * + *******************************************************************/ +static int wctdm_set_hwgain(struct wctdm *wc, int card, __s32 gain, __u32 tx) +{ + if (!(wc->modtype[card] == MOD_TYPE_FXO)) { + printk("Cannot adjust gain. Unsupported module type!\n"); + return -1; + } + if (tx) { + if (debug) + printk("setting FXO tx gain for card=%d to %d\n", card, gain); + if (gain >= -150 && gain <= 0) { + wctdm_setreg(wc, card, 38, 16 + (gain/-10)); + wctdm_setreg(wc, card, 40, 16 + (-gain%10)); + } else if (gain <= 120 && gain > 0) { + wctdm_setreg(wc, card, 38, gain/10); + wctdm_setreg(wc, card, 40, (gain%10)); + } else { + printk("FXO tx gain is out of range (%d)\n", gain); + return -1; + } + } else { /* rx */ + if (debug) + printk("setting FXO rx gain for card=%d to %d\n", card, gain); + if (gain >= -150 && gain <= 0) { + wctdm_setreg(wc, card, 39, 16+ (gain/-10)); + wctdm_setreg(wc, card, 41, 16 + (-gain%10)); + } else if (gain <= 120 && gain > 0) { + wctdm_setreg(wc, card, 39, gain/10); + wctdm_setreg(wc, card, 41, (gain%10)); + } else { + printk("FXO rx gain is out of range (%d)\n", gain); + return -1; + } + } + + return 0; +} + +static int wctdm_init_voicedaa(struct wctdm *wc, int card, int fast, int manual, int sane) +{ + unsigned char reg16=0, reg26=0, reg30=0, reg31=0; + long newjiffies; + + if (wc->modtype[card & 0xfc] == MOD_TYPE_QRV) return -2; + + wc->modtype[card] = MOD_TYPE_NONE; + /* Wait just a bit */ + wait_just_a_bit(HZ/10); + + wc->modtype[card] = MOD_TYPE_FXO; + wait_just_a_bit(HZ/10); + + if (!sane && wctdm_voicedaa_insane(wc, card)) + return -2; + + /* Software reset */ + wctdm_setreg(wc, card, 1, 0x80); + + /* Wait just a bit */ + wait_just_a_bit(HZ/10); + + /* Enable PCM, ulaw */ + if (alawoverride) + wctdm_setreg(wc, card, 33, 0x20); + else + wctdm_setreg(wc, card, 33, 0x28); + + /* Set On-hook speed, Ringer impedence, and ringer threshold */ + reg16 |= (fxo_modes[_opermode].ohs << 6); + reg16 |= (fxo_modes[_opermode].rz << 1); + reg16 |= (fxo_modes[_opermode].rt); + wctdm_setreg(wc, card, 16, reg16); + + if(fwringdetect) { + /* Enable ring detector full-wave rectifier mode */ + wctdm_setreg(wc, card, 18, 2); + wctdm_setreg(wc, card, 24, 0); + } else { + /* Set to the device defaults */ + wctdm_setreg(wc, card, 18, 0); + wctdm_setreg(wc, card, 24, 0x19); + } + + /* Set DC Termination: + Tip/Ring voltage adjust, minimum operational current, current limitation */ + reg26 |= (fxo_modes[_opermode].dcv << 6); + reg26 |= (fxo_modes[_opermode].mini << 4); + reg26 |= (fxo_modes[_opermode].ilim << 1); + wctdm_setreg(wc, card, 26, reg26); + + /* Set AC Impedence */ + reg30 = (fxo_modes[_opermode].acim); + wctdm_setreg(wc, card, 30, reg30); + + /* Misc. DAA parameters */ + reg31 = 0xa3; + reg31 |= (fxo_modes[_opermode].ohs2 << 3); + wctdm_setreg(wc, card, 31, reg31); + + /* Set Transmit/Receive timeslot */ + wctdm_setreg(wc, card, 34, (card * 8) & 0xff); + wctdm_setreg(wc, card, 35, (card * 8) >> 8); + wctdm_setreg(wc, card, 36, (card * 8) & 0xff); + wctdm_setreg(wc, card, 37, (card * 8) >> 8); + + /* Enable ISO-Cap */ + wctdm_setreg(wc, card, 6, 0x00); + + /* Wait 1000ms for ISO-cap to come up */ + newjiffies = jiffies; + newjiffies += 2 * HZ; + while((jiffies < newjiffies) && !(wctdm_getreg(wc, card, 11) & 0xf0)) + wait_just_a_bit(HZ/10); + + if (!(wctdm_getreg(wc, card, 11) & 0xf0)) { + printk("VoiceDAA did not bring up ISO link properly!\n"); + return -1; + } + if (debug & DEBUG_CARD) + printk("ISO-Cap is now up, line side: %02x rev %02x\n", + wctdm_getreg(wc, card, 11) >> 4, + (wctdm_getreg(wc, card, 13) >> 2) & 0xf); + /* Enable on-hook line monitor */ + wctdm_setreg(wc, card, 5, 0x08); + + /* Take values for fxotxgain and fxorxgain and apply them to module */ + wctdm_set_hwgain(wc, card, fxotxgain, 1); + wctdm_set_hwgain(wc, card, fxorxgain, 0); + + if(debug) + printk("DEBUG fxotxgain:%i.%i fxorxgain:%i.%i\n", (wctdm_getreg(wc, card, 38)/16) ? -(wctdm_getreg(wc, card, 38) - 16) : wctdm_getreg(wc, card, 38), (wctdm_getreg(wc, card, 40)/16) ? -(wctdm_getreg(wc, card, 40) - 16) : wctdm_getreg(wc, card, 40), (wctdm_getreg(wc, card, 39)/16) ? -(wctdm_getreg(wc, card, 39) - 16): wctdm_getreg(wc, card, 39), (wctdm_getreg(wc, card, 41)/16)?-(wctdm_getreg(wc, card, 41) - 16) : wctdm_getreg(wc, card, 41)); + + /* battery state still unknown */ + wc->mods[card].fxo.battery = -1; + + return 0; + +} + +static int wctdm_init_proslic(struct wctdm *wc, int card, int fast, int manual, int sane) +{ + + unsigned short tmp[5]; + unsigned char r19,r9; + int x; + int fxsmode=0; + + if (wc->modtype[card & 0xfc] == MOD_TYPE_QRV) return -2; + + /* Sanity check the ProSLIC */ + if (!sane && wctdm_proslic_insane(wc, card)) + return -2; + + /* By default, don't send on hook */ + wc->mods[card].fxs.idletxhookstate = 1; + wc->mods[card].fxs.lasttxhook = 0x10; + + if (sane) { + /* Make sure we turn off the DC->DC converter to prevent anything from blowing up */ + wctdm_setreg(wc, card, 14, 0x10); + } + + if (wctdm_proslic_init_indirect_regs(wc, card)) { + printk(KERN_INFO "Indirect Registers failed to initialize on module %d.\n", card); + return -1; + } + + /* Clear scratch pad area */ + wctdm_proslic_setreg_indirect(wc, card, 97,0); + + /* Clear digital loopback */ + wctdm_setreg(wc, card, 8, 0); + + /* Revision C optimization */ + wctdm_setreg(wc, card, 108, 0xeb); + + /* Disable automatic VBat switching for safety to prevent + Q7 from accidently turning on and burning out. */ + wctdm_setreg(wc, card, 67, 0x07); /* If pulse dialing has trouble at high REN + loads change this to 0x17 */ + + /* Turn off Q7 */ + wctdm_setreg(wc, card, 66, 1); + + /* Flush ProSLIC digital filters by setting to clear, while + saving old values */ + for (x=0;x<5;x++) { + tmp[x] = wctdm_proslic_getreg_indirect(wc, card, x + 35); + wctdm_proslic_setreg_indirect(wc, card, x + 35, 0x8000); + } + + /* Power up the DC-DC converter */ + if (wctdm_powerup_proslic(wc, card, fast)) { + printk("Unable to do INITIAL ProSLIC powerup on module %d\n", card); + return -1; + } + + if (!fast) { + + /* Check for power leaks */ + if (wctdm_proslic_powerleak_test(wc, card)) { + printk("ProSLIC module %d failed leakage test. Check for short circuit\n", card); + } + /* Power up again */ + if (wctdm_powerup_proslic(wc, card, fast)) { + printk("Unable to do FINAL ProSLIC powerup on module %d\n", card); + return -1; + } +#ifndef NO_CALIBRATION + /* Perform calibration */ + if(manual) { + if (wctdm_proslic_manual_calibrate(wc, card)) { + //printk("Proslic failed on Manual Calibration\n"); + if (wctdm_proslic_manual_calibrate(wc, card)) { + printk("Proslic Failed on Second Attempt to Calibrate Manually. (Try -DNO_CALIBRATION in Makefile)\n"); + return -1; + } + printk("Proslic Passed Manual Calibration on Second Attempt\n"); + } + } + else { + if(wctdm_proslic_calibrate(wc, card)) { + //printk("ProSlic died on Auto Calibration.\n"); + if (wctdm_proslic_calibrate(wc, card)) { + printk("Proslic Failed on Second Attempt to Auto Calibrate\n"); + return -1; + } + printk("Proslic Passed Auto Calibration on Second Attempt\n"); + } + } + /* Perform DC-DC calibration */ + wctdm_setreg(wc, card, 93, 0x99); + r19 = wctdm_getreg(wc, card, 107); + if ((r19 < 0x2) || (r19 > 0xd)) { + printk("DC-DC cal has a surprising direct 107 of 0x%02x!\n", r19); + wctdm_setreg(wc, card, 107, 0x8); + } + + /* Save calibration vectors */ + for (x=0;xmods[card].fxs.calregs.vals[x] = wctdm_getreg(wc, card, 96 + x); +#endif + + } else { + /* Restore calibration registers */ + for (x=0;xmods[card].fxs.calregs.vals[x]); + } + /* Calibration complete, restore original values */ + for (x=0;x<5;x++) { + wctdm_proslic_setreg_indirect(wc, card, x + 35, tmp[x]); + } + + if (wctdm_proslic_verify_indirect_regs(wc, card)) { + printk(KERN_INFO "Indirect Registers failed verification.\n"); + return -1; + } + + +#if 0 + /* Disable Auto Power Alarm Detect and other "features" */ + wctdm_setreg(wc, card, 67, 0x0e); + blah = wctdm_getreg(wc, card, 67); +#endif + +#if 0 + if (wctdm_proslic_setreg_indirect(wc, card, 97, 0x0)) { // Stanley: for the bad recording fix + printk(KERN_INFO "ProSlic IndirectReg Died.\n"); + return -1; + } +#endif + + if (alawoverride) + wctdm_setreg(wc, card, 1, 0x20); + else + wctdm_setreg(wc, card, 1, 0x28); + // U-Law 8-bit interface + wctdm_setreg(wc, card, 2, (card * 8) & 0xff); // Tx Start count low byte 0 + wctdm_setreg(wc, card, 3, (card * 8) >> 8); // Tx Start count high byte 0 + wctdm_setreg(wc, card, 4, (card * 8) & 0xff); // Rx Start count low byte 0 + wctdm_setreg(wc, card, 5, (card * 8) >> 8); // Rx Start count high byte 0 + wctdm_setreg(wc, card, 18, 0xff); // clear all interrupt + wctdm_setreg(wc, card, 19, 0xff); + wctdm_setreg(wc, card, 20, 0xff); + wctdm_setreg(wc, card, 22, 0xff); + wctdm_setreg(wc, card, 73, 0x04); + if (fxshonormode) { + fxsmode = acim2tiss[fxo_modes[_opermode].acim]; + wctdm_setreg(wc, card, 10, 0x08 | fxsmode); + if (fxo_modes[_opermode].ring_osc) + wctdm_proslic_setreg_indirect(wc, card, 20, fxo_modes[_opermode].ring_osc); + if (fxo_modes[_opermode].ring_x) + wctdm_proslic_setreg_indirect(wc, card, 21, fxo_modes[_opermode].ring_x); + } + if (lowpower) + wctdm_setreg(wc, card, 72, 0x10); + +#if 0 + wctdm_setreg(wc, card, 21, 0x00); // enable interrupt + wctdm_setreg(wc, card, 22, 0x02); // Loop detection interrupt + wctdm_setreg(wc, card, 23, 0x01); // DTMF detection interrupt +#endif + +#if 0 + /* Enable loopback */ + wctdm_setreg(wc, card, 8, 0x2); + wctdm_setreg(wc, card, 14, 0x0); + wctdm_setreg(wc, card, 64, 0x0); + wctdm_setreg(wc, card, 1, 0x08); +#endif + + if (fastringer) { + /* Speed up Ringer */ + wctdm_proslic_setreg_indirect(wc, card, 20, 0x7e6d); + wctdm_proslic_setreg_indirect(wc, card, 21, 0x01b9); + /* Beef up Ringing voltage to 89V */ + if (boostringer) { + wctdm_setreg(wc, card, 74, 0x3f); + if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x247)) + return -1; + printk("Boosting fast ringer on slot %d (89V peak)\n", card + 1); + } else if (lowpower) { + if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x14b)) + return -1; + printk("Reducing fast ring power on slot %d (50V peak)\n", card + 1); + } else + printk("Speeding up ringer on slot %d (25Hz)\n", card + 1); + } else { + /* Beef up Ringing voltage to 89V */ + if (boostringer) { + wctdm_setreg(wc, card, 74, 0x3f); + if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x1d1)) + return -1; + printk("Boosting ringer on slot %d (89V peak)\n", card + 1); + } else if (lowpower) { + if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x108)) + return -1; + printk("Reducing ring power on slot %d (50V peak)\n", card + 1); + } + } + + if (fxstxgain || fxsrxgain) { + r9 = wctdm_getreg(wc, card, 9); + switch (fxstxgain) { + + case 35: + r9+=8; + break; + case -35: + r9+=4; + break; + case 0: + break; + } + + switch (fxsrxgain) { + + case 35: + r9+=2; + break; + case -35: + r9+=1; + break; + case 0: + break; + } + wctdm_setreg(wc, card, 9, r9); + } + + if (debug) + printk("DEBUG: fxstxgain:%s fxsrxgain:%s\n",((wctdm_getreg(wc, card, 9)/8) == 1)?"3.5":(((wctdm_getreg(wc,card,9)/4) == 1)?"-3.5":"0.0"),((wctdm_getreg(wc, card, 9)/2) == 1)?"3.5":((wctdm_getreg(wc,card,9)%2)?"-3.5":"0.0")); + + wc->mods[card].fxs.lasttxhook = 0x11; + wctdm_setreg(wc, card, 64, 0x01); + return 0; +} + +static int wctdm_init_qrvdri(struct wctdm *wc, int card) +{ + unsigned char x,y; + unsigned long endjif; + + /* have to set this, at least for now */ + wc->modtype[card] = MOD_TYPE_QRV; + if (!(card & 3)) /* if at base of card, reset and write it */ + { + wctdm_setreg(wc,card,0,0x80); + wctdm_setreg(wc,card,0,0x55); + wctdm_setreg(wc,card,1,0x69); + wc->qrvhook[card] = wc->qrvhook[card + 1] = 0; + wc->qrvhook[card + 2] = wc->qrvhook[card + 3] = 0xff; + wc->debouncetime[card] = wc->debouncetime[card + 1] = QRV_DEBOUNCETIME; + wc->qrvdebtime[card] = wc->qrvdebtime[card + 1] = 0; + wc->radmode[card] = wc->radmode[card + 1] = 0; + wc->txgain[card] = wc->txgain[card + 1] = 3599; + wc->rxgain[card] = wc->rxgain[card + 1] = 1199; + } else { /* channel is on same card as base, no need to test */ + if (wc->modtype[card & 0x7c] == MOD_TYPE_QRV) + { + /* only lower 2 are valid */ + if (!(card & 2)) return 0; + } + wc->modtype[card] = MOD_TYPE_NONE; + return 1; + } + x = wctdm_getreg(wc,card,0); + y = wctdm_getreg(wc,card,1); + /* if not a QRV card, return as such */ + if ((x != 0x55) || (y != 0x69)) + { + wc->modtype[card] = MOD_TYPE_NONE; + return 1; + } + for(x = 0; x < 0x30; x++) + { + if ((x >= 0x1c) && (x <= 0x1e)) wctdm_setreg(wc,card,x,0xff); + else wctdm_setreg(wc,card,x,0); + } + wctdm_setreg(wc,card,0,0x80); + endjif = jiffies + (HZ/10); + while(endjif > jiffies); + wctdm_setreg(wc,card,0,0x10); + wctdm_setreg(wc,card,0,0x10); + endjif = jiffies + (HZ/10); + while(endjif > jiffies); + /* set up modes */ + wctdm_setreg(wc,card,0,0x1c); + /* set up I/O directions */ + wctdm_setreg(wc,card,1,0x33); + wctdm_setreg(wc,card,2,0x0f); + wctdm_setreg(wc,card,5,0x0f); + /* set up I/O to quiescent state */ + wctdm_setreg(wc,card,3,0x11); /* D0-7 */ + wctdm_setreg(wc,card,4,0xa); /* D8-11 */ + wctdm_setreg(wc,card,7,0); /* CS outputs */ + /* set up timeslots */ + wctdm_setreg(wc,card,0x13,card + 0x80); /* codec 2 tx, ts0 */ + wctdm_setreg(wc,card,0x17,card + 0x80); /* codec 0 rx, ts0 */ + wctdm_setreg(wc,card,0x14,card + 0x81); /* codec 1 tx, ts1 */ + wctdm_setreg(wc,card,0x18,card + 0x81); /* codec 1 rx, ts1 */ + /* set up for max gains */ + wctdm_setreg(wc,card,0x26,0x24); + wctdm_setreg(wc,card,0x27,0x24); + wctdm_setreg(wc,card,0x0b,0x01); /* "Transmit" gain codec 0 */ + wctdm_setreg(wc,card,0x0c,0x01); /* "Transmit" gain codec 1 */ + wctdm_setreg(wc,card,0x0f,0xff); /* "Receive" gain codec 0 */ + wctdm_setreg(wc,card,0x10,0xff); /* "Receive" gain codec 1 */ + return 0; +} + +static void qrv_dosetup(struct zt_chan *chan,struct wctdm *wc) +{ +int qrvcard; +unsigned char r; +long l; + + /* actually do something with the values */ + qrvcard = (chan->chanpos - 1) & 0xfc; + if (debug) printk("@@@@@ radmodes: %d,%d rxgains: %d,%d txgains: %d,%d\n", + wc->radmode[qrvcard],wc->radmode[qrvcard + 1], + wc->rxgain[qrvcard],wc->rxgain[qrvcard + 1], + wc->txgain[qrvcard],wc->txgain[qrvcard + 1]); + r = 0; + if (wc->radmode[qrvcard] & RADMODE_DEEMP) r |= 4; + if (wc->radmode[qrvcard + 1] & RADMODE_DEEMP) r |= 8; + if (wc->rxgain[qrvcard] < 1200) r |= 1; + if (wc->rxgain[qrvcard + 1] < 1200) r |= 2; + wctdm_setreg(wc, qrvcard, 7, r); + if (debug) printk("@@@@@ setting reg 7 to %02x hex\n",r); + r = 0; + if (wc->radmode[qrvcard] & RADMODE_PREEMP) r |= 3; + else if (wc->txgain[qrvcard] >= 3600) r |= 1; + else if (wc->txgain[qrvcard] >= 1200) r |= 2; + if (wc->radmode[qrvcard + 1] & RADMODE_PREEMP) r |= 0xc; + else if (wc->txgain[qrvcard + 1] >= 3600) r |= 4; + else if (wc->txgain[qrvcard + 1] >= 1200) r |= 8; + wctdm_setreg(wc, qrvcard, 4, r); + if (debug) printk("@@@@@ setting reg 4 to %02x hex\n",r); + r = 0; + if (wc->rxgain[qrvcard] >= 2400) r |= 1; + if (wc->rxgain[qrvcard + 1] >= 2400) r |= 2; + wctdm_setreg(wc, qrvcard, 0x25, r); + if (debug) printk("@@@@@ setting reg 0x25 to %02x hex\n",r); + r = 0; + if (wc->txgain[qrvcard] < 2400) r |= 1; else r |= 4; + if (wc->txgain[qrvcard + 1] < 2400) r |= 8; else r |= 0x20; + wctdm_setreg(wc, qrvcard, 0x26, r); + if (debug) printk("@@@@@ setting reg 0x26 to %02x hex\n",r); + l = ((long)(wc->rxgain[qrvcard] % 1200) * 10000) / 46875; + if (l == 0) l = 1; + if (wc->rxgain[qrvcard] >= 2400) l += 181; + wctdm_setreg(wc, qrvcard, 0x0b, (unsigned char)l); + if (debug) printk("@@@@@ setting reg 0x0b to %02x hex\n",(unsigned char)l); + l = ((long)(wc->rxgain[qrvcard + 1] % 1200) * 10000) / 46875; + if (l == 0) l = 1; + if (wc->rxgain[qrvcard + 1] >= 2400) l += 181; + wctdm_setreg(wc, qrvcard, 0x0c, (unsigned char)l); + if (debug) printk("@@@@@ setting reg 0x0c to %02x hex\n",(unsigned char)l); + l = ((long)(wc->txgain[qrvcard] % 1200) * 10000) / 46875; + if (l == 0) l = 1; + wctdm_setreg(wc, qrvcard, 0x0f, (unsigned char)l); + if (debug) printk("@@@@@ setting reg 0x0f to %02x hex\n", (unsigned char)l); + l = ((long)(wc->txgain[qrvcard + 1] % 1200) * 10000) / 46875; + if (l == 0) l = 1; + wctdm_setreg(wc, qrvcard, 0x10,(unsigned char)l); + if (debug) printk("@@@@@ setting reg 0x10 to %02x hex\n",(unsigned char)l); + return; +} + +static int wctdm_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) +{ + struct wctdm_stats stats; + struct wctdm_regs regs; + struct wctdm_regop regop; + struct wctdm_echo_coefs echoregs; + struct zt_hwgain hwgain; + struct wctdm *wc = chan->pvt; + int x; + union { + struct zt_radio_stat s; + struct zt_radio_param p; + } stack; + +#if 0 + /* XXX */ + printk("RxInts: %d, TxInts: %d\n", wc->rxints, wc->txints); + printk("RxIdent: %d, TxIdent: %d\n", wc->rxident, wc->txident); + for (x=0;xcards;x++) + printk("Card %d isrshadow: %02x/%02x\n", x, wc->cmdq[x].isrshadow[0], wc->cmdq[x].isrshadow[1]); + cmddesc = 0; +#endif +#if 0 + if (wc->vpm) { + char tmp[80]; + for (x=0;x<0x200;x++) { + switch (x & 0xf) { + case 0: + sprintf(tmp, "%03x: %02x ", x, wctdm_vpm_in(wc, 0, x)); + break; + case 0xf: + printk("%s%02x\n", tmp, wctdm_vpm_in(wc, 0, x)); + break; + default: + sprintf(tmp + strlen(tmp), "%02x ", wctdm_vpm_in(wc, 0, x)); + break; + } + } + } + +#endif + switch (cmd) { + case ZT_ONHOOKTRANSFER: + if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) + return -EINVAL; + if (get_user(x, (int *)data)) + return -EFAULT; + wc->mods[chan->chanpos - 1].fxs.ohttimer = x << 3; + wc->mods[chan->chanpos - 1].fxs.idletxhookstate = 0x2; /* OHT mode when idle */ + if (wc->mods[chan->chanpos - 1].fxs.lasttxhook == 0x1) { + /* Apply the change if appropriate */ + wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x12; + wc->sethook[chan->chanpos - 1] = CMD_WR(64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); + /* wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); */ + } + break; + case WCTDM_GET_STATS: + if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { + stats.tipvolt = wctdm_getreg(wc, chan->chanpos - 1, 80) * -376; + stats.ringvolt = wctdm_getreg(wc, chan->chanpos - 1, 81) * -376; + stats.batvolt = wctdm_getreg(wc, chan->chanpos - 1, 82) * -376; + } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { + stats.tipvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; + stats.ringvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; + stats.batvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; + } else + return -EINVAL; + if (copy_to_user((struct wctdm_stats *)data, &stats, sizeof(stats))) + return -EFAULT; + break; + case WCTDM_GET_REGS: + if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { + for (x=0;xchanpos -1, x); + for (x=0;xchanpos - 1, x); + } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_QRV) { + memset(®s, 0, sizeof(regs)); + for (x=0;x<0x32;x++) + regs.direct[x] = wctdm_getreg(wc, chan->chanpos - 1, x); + } else { + memset(®s, 0, sizeof(regs)); + for (x=0;xchanpos - 1, x); + } + if (copy_to_user((struct wctdm_regs *)data, ®s, sizeof(regs))) + return -EFAULT; + break; + case WCTDM_SET_REG: + if (copy_from_user(®op, (struct wctdm_regop *)data, sizeof(regop))) + return -EFAULT; + if (regop.indirect) { + if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) + return -EINVAL; + printk("Setting indirect %d to 0x%04x on %d\n", regop.reg, regop.val, chan->chanpos); + wctdm_proslic_setreg_indirect(wc, chan->chanpos - 1, regop.reg, regop.val); + } else { + regop.val &= 0xff; + if (regop.reg == 64) + wc->mods[chan->chanpos-1].fxs.lasttxhook = (regop.val & 0x0f) | 0x10; + + printk("Setting direct %d to %04x on %d\n", regop.reg, regop.val, chan->chanpos); + wctdm_setreg(wc, chan->chanpos - 1, regop.reg, regop.val); + } + break; + case WCTDM_SET_ECHOTUNE: + printk("-- Setting echo registers: \n"); + if (copy_from_user(&echoregs, (struct wctdm_echo_coefs*)data, sizeof(echoregs))) + return -EFAULT; + + if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { + /* Set the ACIM register */ + wctdm_setreg(wc, chan->chanpos - 1, 30, echoregs.acim); + + /* Set the digital echo canceller registers */ + wctdm_setreg(wc, chan->chanpos - 1, 45, echoregs.coef1); + wctdm_setreg(wc, chan->chanpos - 1, 46, echoregs.coef2); + wctdm_setreg(wc, chan->chanpos - 1, 47, echoregs.coef3); + wctdm_setreg(wc, chan->chanpos - 1, 48, echoregs.coef4); + wctdm_setreg(wc, chan->chanpos - 1, 49, echoregs.coef5); + wctdm_setreg(wc, chan->chanpos - 1, 50, echoregs.coef6); + wctdm_setreg(wc, chan->chanpos - 1, 51, echoregs.coef7); + wctdm_setreg(wc, chan->chanpos - 1, 52, echoregs.coef8); + + printk("-- Set echo registers successfully\n"); + + break; + } else { + return -EINVAL; + + } + break; + case ZT_SET_HWGAIN: + if (copy_from_user(&hwgain, (struct zt_hwgain*) data, sizeof(hwgain))) + return -EFAULT; + + wctdm_set_hwgain(wc, chan->chanpos-1, hwgain.newgain, hwgain.tx); + + if (debug) + printk("Setting hwgain on channel %d to %d for %s direction\n", + chan->chanpos-1, hwgain.newgain, hwgain.tx ? "tx" : "rx"); + break; +#ifdef VPM_SUPPORT + case ZT_TONEDETECT: + if (get_user(x, (int *) data)) + return -EFAULT; + if (!wc->vpm && !wc->vpm150m) + return -ENOSYS; + if ((wc->vpm || wc->vpm150m) && (x && !vpmdtmfsupport)) + return -ENOSYS; + if (x & ZT_TONEDETECT_ON) { + set_bit(chan->chanpos - 1, &wc->dtmfmask); + } else { + clear_bit(chan->chanpos - 1, &wc->dtmfmask); + } + if (x & ZT_TONEDETECT_MUTE) { + if (wc->vpm150m) { + set_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); + } + } else { + if (wc->vpm150m) { + clear_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); + } + } + return 0; +#endif + case ZT_RADIO_GETPARAM: + if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_QRV) + return -ENOTTY; + if (copy_from_user(&stack.p,(struct zt_radio_param *)data,sizeof(struct zt_radio_param))) return -EFAULT; + stack.p.data = 0; /* start with 0 value in output */ + switch(stack.p.radpar) { + case ZT_RADPAR_INVERTCOR: + if (wc->radmode[chan->chanpos - 1] & RADMODE_INVERTCOR) + stack.p.data = 1; + break; + case ZT_RADPAR_IGNORECOR: + if (wc->radmode[chan->chanpos - 1] & RADMODE_IGNORECOR) + stack.p.data = 1; + break; + case ZT_RADPAR_IGNORECT: + if (wc->radmode[chan->chanpos - 1] & RADMODE_IGNORECT) + stack.p.data = 1; + break; + case ZT_RADPAR_EXTRXTONE: + stack.p.data = 0; + if (wc->radmode[chan->chanpos - 1] & RADMODE_EXTTONE) + { + stack.p.data = 1; + if (wc->radmode[chan->chanpos - 1] & RADMODE_EXTINVERT) + { + stack.p.data = 2; + } + } + break; + case ZT_RADPAR_DEBOUNCETIME: + stack.p.data = wc->debouncetime[chan->chanpos - 1]; + break; + case ZT_RADPAR_RXGAIN: + stack.p.data = wc->rxgain[chan->chanpos - 1] - 1199; + break; + case ZT_RADPAR_TXGAIN: + stack.p.data = wc->txgain[chan->chanpos - 1] - 3599; + break; + case ZT_RADPAR_DEEMP: + stack.p.data = 0; + if (wc->radmode[chan->chanpos - 1] & RADMODE_DEEMP) + { + stack.p.data = 1; + } + break; + case ZT_RADPAR_PREEMP: + stack.p.data = 0; + if (wc->radmode[chan->chanpos - 1] & RADMODE_PREEMP) + { + stack.p.data = 1; + } + break; + default: + return -EINVAL; + } + if (copy_to_user((struct zt_radio_param *)data,&stack.p,sizeof(struct zt_radio_param))) return -EFAULT; + break; + case ZT_RADIO_SETPARAM: + if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_QRV) + return -ENOTTY; + if (copy_from_user(&stack.p,(struct zt_radio_param *)data,sizeof(struct zt_radio_param))) return -EFAULT; + switch(stack.p.radpar) { + case ZT_RADPAR_INVERTCOR: + if (stack.p.data) + wc->radmode[chan->chanpos - 1] |= RADMODE_INVERTCOR; + else + wc->radmode[chan->chanpos - 1] &= ~RADMODE_INVERTCOR; + return 0; + case ZT_RADPAR_IGNORECOR: + if (stack.p.data) + wc->radmode[chan->chanpos - 1] |= RADMODE_IGNORECOR; + else + wc->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECOR; + return 0; + case ZT_RADPAR_IGNORECT: + if (stack.p.data) + wc->radmode[chan->chanpos - 1] |= RADMODE_IGNORECT; + else + wc->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECT; + return 0; + case ZT_RADPAR_EXTRXTONE: + if (stack.p.data) + wc->radmode[chan->chanpos - 1] |= RADMODE_EXTTONE; + else + wc->radmode[chan->chanpos - 1] &= ~RADMODE_EXTTONE; + if (stack.p.data > 1) + wc->radmode[chan->chanpos - 1] |= RADMODE_EXTINVERT; + else + wc->radmode[chan->chanpos - 1] &= ~RADMODE_EXTINVERT; + return 0; + case ZT_RADPAR_DEBOUNCETIME: + wc->debouncetime[chan->chanpos - 1] = stack.p.data; + return 0; + case ZT_RADPAR_RXGAIN: + /* if out of range */ + if ((stack.p.data <= -1200) || (stack.p.data > 1552)) + { + return -EINVAL; + } + wc->rxgain[chan->chanpos - 1] = stack.p.data + 1199; + break; + case ZT_RADPAR_TXGAIN: + /* if out of range */ + if (wc->radmode[chan->chanpos -1] & RADMODE_PREEMP) + { + if ((stack.p.data <= -2400) || (stack.p.data > 0)) + { + return -EINVAL; + } + } + else + { + if ((stack.p.data <= -3600) || (stack.p.data > 1200)) + { + return -EINVAL; + } + } + wc->txgain[chan->chanpos - 1] = stack.p.data + 3599; + break; + case ZT_RADPAR_DEEMP: + if (stack.p.data) + wc->radmode[chan->chanpos - 1] |= RADMODE_DEEMP; + else + wc->radmode[chan->chanpos - 1] &= ~RADMODE_DEEMP; + wc->rxgain[chan->chanpos - 1] = 1199; + break; + case ZT_RADPAR_PREEMP: + if (stack.p.data) + wc->radmode[chan->chanpos - 1] |= RADMODE_PREEMP; + else + wc->radmode[chan->chanpos - 1] &= ~RADMODE_PREEMP; + wc->txgain[chan->chanpos - 1] = 3599; + break; + default: + return -EINVAL; + } + qrv_dosetup(chan,wc); + return 0; + default: + return -ENOTTY; + } + return 0; +} + +static int wctdm_open(struct zt_chan *chan) +{ + struct wctdm *wc = chan->pvt; + if (!(wc->cardflag & (1 << (chan->chanpos - 1)))) + return -ENODEV; + if (wc->dead) + return -ENODEV; + wc->usecount++; +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#else + try_module_get(THIS_MODULE); +#endif + return 0; +} + +static int wctdm_watchdog(struct zt_span *span, int event) +{ + printk("TDM: Restarting DMA\n"); + wctdm_restart_dma(span->pvt); + return 0; +} + +static int wctdm_close(struct zt_chan *chan) +{ + struct wctdm *wc = chan->pvt; + int x; + signed char reg; + wc->usecount--; +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#else + module_put(THIS_MODULE); +#endif + for (x=0;xcards;x++) { + if (wc->modtype[x] == MOD_TYPE_FXS) + wc->mods[x].fxs.idletxhookstate = 1; + if (wc->modtype[x] == MOD_TYPE_QRV) + { + int qrvcard = x & 0xfc; + + wc->qrvhook[x] = 0; + wc->qrvhook[x + 2] = 0xff; + wc->debouncetime[x] = QRV_DEBOUNCETIME; + wc->qrvdebtime[x] = 0; + wc->radmode[x] = 0; + wc->txgain[x] = 3599; + wc->rxgain[x] = 1199; + reg = 0; + if (!wc->qrvhook[qrvcard]) reg |= 1; + if (!wc->qrvhook[qrvcard + 1]) reg |= 0x10; + wc->sethook[qrvcard] = CMD_WR(3, reg); + qrv_dosetup(chan,wc); + } + } + /* If we're dead, release us now */ + if (!wc->usecount && wc->dead) + wctdm_release(wc); + return 0; +} + +static int wctdm_hooksig(struct zt_chan *chan, zt_txsig_t txsig) +{ + struct wctdm *wc = chan->pvt; + int reg=0,qrvcard; + if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_QRV) { + qrvcard = (chan->chanpos - 1) & 0xfc; + switch(txsig) { + case ZT_TXSIG_START: + case ZT_TXSIG_OFFHOOK: + wc->qrvhook[chan->chanpos - 1] = 1; + break; + case ZT_TXSIG_ONHOOK: + wc->qrvhook[chan->chanpos - 1] = 0; + break; + default: + printk("wctdm24xxp: Can't set tx state to %d\n", txsig); + } + reg = 0; + if (!wc->qrvhook[qrvcard]) reg |= 1; + if (!wc->qrvhook[qrvcard + 1]) reg |= 0x10; + wc->sethook[qrvcard] = CMD_WR(3, reg); + /* wctdm_setreg(wc, qrvcard, 3, reg); */ + } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { + switch(txsig) { + case ZT_TXSIG_START: + case ZT_TXSIG_OFFHOOK: + wc->mods[chan->chanpos - 1].fxo.offhook = 1; + wc->sethook[chan->chanpos - 1] = CMD_WR(5, 0x9); + /* wctdm_setreg(wc, chan->chanpos - 1, 5, 0x9); */ + break; + case ZT_TXSIG_ONHOOK: + wc->mods[chan->chanpos - 1].fxo.offhook = 0; + wc->sethook[chan->chanpos - 1] = CMD_WR(5, 0x8); + /* wctdm_setreg(wc, chan->chanpos - 1, 5, 0x8); */ + break; + default: + printk("wctdm24xxp: Can't set tx state to %d\n", txsig); + } + } else { + switch(txsig) { + case ZT_TXSIG_ONHOOK: + switch(chan->sig) { + case ZT_SIG_EM: + case ZT_SIG_FXOKS: + case ZT_SIG_FXOLS: + wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x10 | + wc->mods[chan->chanpos - 1].fxs.idletxhookstate; + break; + case ZT_SIG_FXOGS: + wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x13; + break; + } + break; + case ZT_TXSIG_OFFHOOK: + switch(chan->sig) { + case ZT_SIG_EM: + wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x15; + break; + default: + wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x10 | + wc->mods[chan->chanpos - 1].fxs.idletxhookstate; + break; + } + break; + case ZT_TXSIG_START: + wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x14; + break; + case ZT_TXSIG_KEWL: + wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x10; + break; + default: + printk("wctdm24xxp: Can't set tx state to %d\n", txsig); + } + if (debug & DEBUG_CARD) + printk("Setting FXS hook state to %d (%02x)\n", txsig, reg); + + + wc->sethook[chan->chanpos - 1] = CMD_WR(64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); + /* wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); */ + } + return 0; +} + +static void wctdm_dacs_connect(struct wctdm *wc, int srccard, int dstcard) +{ + + if (wc->dacssrc[dstcard] > - 1) { + printk("wctdm_dacs_connect: Can't have double sourcing yet!\n"); + return; + } + if (!((wc->modtype[srccard] == MOD_TYPE_FXS)||(wc->modtype[srccard] == MOD_TYPE_FXO))){ + printk("wctdm_dacs_connect: Unsupported modtype for card %d\n", srccard); + return; + } + if (!((wc->modtype[dstcard] == MOD_TYPE_FXS)||(wc->modtype[dstcard] == MOD_TYPE_FXO))){ + printk("wctdm_dacs_connect: Unsupported modtype for card %d\n", dstcard); + return; + } + if (debug) + printk("connect %d => %d\n", srccard, dstcard); + wc->dacssrc[dstcard] = srccard; + + /* make srccard transmit to srccard+24 on the TDM bus */ + if (wc->modtype[srccard] == MOD_TYPE_FXS) { + /* proslic */ + wctdm_setreg(wc, srccard, PCM_XMIT_START_COUNT_LSB, ((srccard+24) * 8) & 0xff); + wctdm_setreg(wc, srccard, PCM_XMIT_START_COUNT_MSB, ((srccard+24) * 8) >> 8); + } else if(wc->modtype[srccard] == MOD_TYPE_FXO) { + /* daa */ + wctdm_setreg(wc, srccard, 34, ((srccard+24) * 8) & 0xff); /* TX */ + wctdm_setreg(wc, srccard, 35, ((srccard+24) * 8) >> 8); /* TX */ + } + + /* have dstcard receive from srccard+24 on the TDM bus */ + if (wc->modtype[dstcard] == MOD_TYPE_FXS) { + /* proslic */ + wctdm_setreg(wc, dstcard, PCM_RCV_START_COUNT_LSB, ((srccard+24) * 8) & 0xff); + wctdm_setreg(wc, dstcard, PCM_RCV_START_COUNT_MSB, ((srccard+24) * 8) >> 8); + } else if(wc->modtype[dstcard] == MOD_TYPE_FXO) { + /* daa */ + wctdm_setreg(wc, dstcard, 36, ((srccard+24) * 8) & 0xff); /* RX */ + wctdm_setreg(wc, dstcard, 37, ((srccard+24) * 8) >> 8); /* RX */ + } + +} + +static void wctdm_dacs_disconnect(struct wctdm *wc, int card) +{ + if (wc->dacssrc[card] > -1) { + if (debug) + printk("wctdm_dacs_disconnect: restoring TX for %d and RX for %d\n",wc->dacssrc[card], card); + + /* restore TX (source card) */ + if(wc->modtype[wc->dacssrc[card]] == MOD_TYPE_FXS){ + wctdm_setreg(wc, wc->dacssrc[card], PCM_XMIT_START_COUNT_LSB, (wc->dacssrc[card] * 8) & 0xff); + wctdm_setreg(wc, wc->dacssrc[card], PCM_XMIT_START_COUNT_MSB, (wc->dacssrc[card] * 8) >> 8); + } else if(wc->modtype[wc->dacssrc[card]] == MOD_TYPE_FXO){ + wctdm_setreg(wc, card, 34, (card * 8) & 0xff); + wctdm_setreg(wc, card, 35, (card * 8) >> 8); + } else { + printk("WARNING: wctdm_dacs_disconnect() called on unsupported modtype\n"); + } + + /* restore RX (this card) */ + if(wc->modtype[card] == MOD_TYPE_FXS){ + wctdm_setreg(wc, card, PCM_RCV_START_COUNT_LSB, (card * 8) & 0xff); + wctdm_setreg(wc, card, PCM_RCV_START_COUNT_MSB, (card * 8) >> 8); + } else if(wc->modtype[card] == MOD_TYPE_FXO){ + wctdm_setreg(wc, card, 36, (card * 8) & 0xff); + wctdm_setreg(wc, card, 37, (card * 8) >> 8); + } else { + printk("WARNING: wctdm_dacs_disconnect() called on unsupported modtype\n"); + } + + wc->dacssrc[card] = -1; + } +} + +static int wctdm_dacs(struct zt_chan *dst, struct zt_chan *src) +{ + struct wctdm *wc; + + if(!nativebridge) + return 0; /* should this return -1 since unsuccessful? */ + + wc = dst->pvt; + + if(src) { + wctdm_dacs_connect(wc, src->chanpos - 1, dst->chanpos - 1); + if (debug) + printk("dacs connecct: %d -> %d!\n\n", src->chanpos, dst->chanpos); + } else { + wctdm_dacs_disconnect(wc, dst->chanpos - 1); + if (debug) + printk("dacs disconnect: %d!\n", dst->chanpos); + } + return 0; +} + +static int wctdm_initialize(struct wctdm *wc) +{ + int x; + + /* Zapata stuff */ + sprintf(wc->span.name, "WCTDM/%d", wc->pos); + snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1); + snprintf(wc->span.location, sizeof(wc->span.location) - 1, + "PCI%s Bus %02d Slot %02d", (wc->flags[0] & FLAG_EXPRESS) ? " Express" : "", + wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); + wc->span.manufacturer = "Digium"; + strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); + if (alawoverride) { + printk("ALAW override parameter detected. Device will be operating in ALAW\n"); + wc->span.deflaw = ZT_LAW_ALAW; + } else + wc->span.deflaw = ZT_LAW_MULAW; + for (x=0;xcards;x++) { + sprintf(wc->chans[x].name, "WCTDM/%d/%d", wc->pos, x); + wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR; + wc->chans[x].sigcap |= ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR; + wc->chans[x].chanpos = x+1; + wc->chans[x].pvt = wc; + } + wc->span.chans = wc->chans; + wc->span.channels = wc->type; + wc->span.irq = wc->dev->irq; + wc->span.hooksig = wctdm_hooksig; + wc->span.open = wctdm_open; + wc->span.close = wctdm_close; + wc->span.flags = ZT_FLAG_RBS; + wc->span.ioctl = wctdm_ioctl; + wc->span.watchdog = wctdm_watchdog; + wc->span.dacs= wctdm_dacs; +#ifdef VPM_SUPPORT + wc->span.echocan_with_params = wctdm_echocan_with_params; +#endif + init_waitqueue_head(&wc->span.maintq); + + wc->span.pvt = wc; + if (zt_register(&wc->span, 0)) { + printk("Unable to register span with zaptel\n"); + return -1; + } + return 0; +} + +static void wctdm_post_initialize(struct wctdm *wc) +{ + int x; + + /* Finalize signalling */ + for (x = 0; x cards; x++) { + if (wc->cardflag & (1 << x)) { + if (wc->modtype[x] == MOD_TYPE_FXO) + wc->chans[x].sigcap = ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR; + else if (wc->modtype[x] == MOD_TYPE_FXS) + wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR; + else if (wc->modtype[x] == MOD_TYPE_QRV) + wc->chans[x].sigcap = ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR; + } else if (!(wc->chans[x].sigcap & ZT_SIG_BROKEN)) { + wc->chans[x].sigcap = 0; + } + } + + if (wc->vpm) + strncat(wc->span.devicetype, " with VPM100M", sizeof(wc->span.devicetype) - 1); + else if (wc->vpm150m) + strncat(wc->span.devicetype, " with VPMADT032", sizeof(wc->span.devicetype) - 1); +} + +static int wctdm_hardware_init(struct wctdm *wc) +{ + /* Hardware stuff */ + unsigned int reg; + unsigned long newjiffies; + + /* Initialize descriptors */ + wctdm_init_descriptors(wc); + + /* Enable I/O Access */ + pci_read_config_dword(wc->dev, 0x0004, ®); + reg |= 0x00000007; + pci_write_config_dword(wc->dev, 0x0004, reg); + printk("PCI Config reg is %08x\n", reg); + + wctdm_setctl(wc, 0x0000, 0xfff88001); + + newjiffies = jiffies + HZ/10; + while(((reg = wctdm_getctl(wc,0x0000)) & 0x00000001) && (newjiffies > jiffies)); + printk("%s: New Reg: %08x!\n", wc->variety, reg); + wctdm_setctl(wc, 0x0000, 0xfff88000); + + + /* Configure watchdogs, access, etc */ + wctdm_setctl(wc, 0x0030, 0x00080048); + wctdm_setctl(wc, 0x0078, 0x00000013 /* | (1 << 28) */); + +#if 0 + /* XXX Enable loopback XXX */ + reg = wctdm_getctl(wc, 0x0030); + wctdm_setctl(wc, 0x0030, reg | 0x00000400); + +#else + reg = wctdm_getctl(wc, 0x00fc); + wctdm_setctl(wc, 0x00fc, (reg & ~0x7) | 0x7); + wctdm_setsdi(wc, 0x00, 0x0100); + wctdm_setsdi(wc, 0x16, 0x2100); + printk("Detected REG0: %08x\n", wctdm_getsdi(wc, 0x00)); + printk("Detected REG1: %08x\n", wctdm_getsdi(wc, 0x01)); + printk("Detected REG2: %08x\n", wctdm_getsdi(wc, 0x02)); + + reg = wctdm_getctl(wc, 0x00fc); + printk("(pre) Reg fc is %08x\n", reg); + + wctdm_setctl(wc, 0x00fc, (reg & ~0x7) | 0x4); + wctdm_setsdi(wc, 0x00, 0x0100); + wctdm_setsdi(wc, 0x16, 0x2100); + reg = wctdm_getctl(wc, 0x00fc); + printk("(post) Reg fc is %08x\n", reg); + printk("Detected REG2: %08x\n", wctdm_getsdi(wc, 0x02)); +#endif + printk("wctdm24xxp: reg is %08x\n", wctdm_getctl(wc, 0x0088)); + + return 0; +} + +static void wctdm_setintmask(struct wctdm *wc, unsigned int intmask) +{ + wc->intmask = intmask; + wctdm_setctl(wc, 0x0038, intmask); +} + +static void wctdm_enable_interrupts(struct wctdm *wc) +{ + /* Enable interrupts */ + wctdm_setintmask(wc, 0x00010041); +} + +static void wctdm_restart_dma(struct wctdm *wc) +{ +} + +static void wctdm_start_dma(struct wctdm *wc) +{ + unsigned int reg; + wmb(); + wctdm_setctl(wc, 0x0020, wc->descripdma); + wctdm_setctl(wc, 0x0018, wc->descripdma + (16 * ERING_SIZE)); + /* Start receiver/transmitter */ + reg = wctdm_getctl(wc, 0x0030); + wctdm_setctl(wc, 0x0030, reg | 0x00002002); + wctdm_setctl(wc, 0x0008, 0x00000000); + wctdm_setctl(wc, 0x0010, 0x00000000); + reg = wctdm_getctl(wc, 0x0028); + wctdm_setctl(wc, 0x0028, reg); + +} + +static void wctdm_stop_dma(struct wctdm *wc) +{ + /* Disable interrupts and reset */ + unsigned int reg; + /* Disable interrupts */ + wctdm_setintmask(wc, 0x00000000); + wctdm_setctl(wc, 0x0084, 0x00000000); + wctdm_setctl(wc, 0x0048, 0x00000000); + /* Reset the part to be on the safe side */ + reg = wctdm_getctl(wc, 0x0000); + reg |= 0x00000001; + wctdm_setctl(wc, 0x0000, reg); +} + +static void wctdm_disable_interrupts(struct wctdm *wc) +{ + /* Disable interrupts */ + wctdm_setintmask(wc, 0x00000000); + wctdm_setctl(wc, 0x0084, 0x00000000); +} + +#ifdef VPM_SUPPORT + +#ifdef VPM150M_SUPPORT + +void vpm150m_set_chanconfig_from_state(struct adt_lec_params * parms, int channum, GpakChannelConfig_t *chanconfig) +{ + chanconfig->PcmInPortA = 3; + chanconfig->PcmInSlotA = channum; + chanconfig->PcmOutPortA = SerialPortNull; + chanconfig->PcmOutSlotA = channum; + chanconfig->PcmInPortB = 2; + chanconfig->PcmInSlotB = channum; + chanconfig->PcmOutPortB = 3; + chanconfig->PcmOutSlotB = channum; + if (vpmdtmfsupport) { + chanconfig->ToneTypesA = DTMF_tone; + chanconfig->MuteToneA = Enabled; + chanconfig->FaxCngDetA = Enabled; + } else { + chanconfig->ToneTypesA = Null_tone; + chanconfig->MuteToneA = Disabled; + chanconfig->FaxCngDetA = Disabled; + } + chanconfig->ToneTypesB = Null_tone; + chanconfig->EcanEnableA = Enabled; + chanconfig->EcanEnableB = Disabled; + chanconfig->MuteToneB = Disabled; + chanconfig->FaxCngDetB = Disabled; + + if (alawoverride) + chanconfig->SoftwareCompand = cmpPCMA; + else + chanconfig->SoftwareCompand = cmpPCMU; + + chanconfig->FrameRate = rate2ms; + chanconfig->EcanParametersA.EcanTapLength = 1024; + chanconfig->EcanParametersA.EcanNlpType = parms->nlp_type; + chanconfig->EcanParametersA.EcanAdaptEnable = 1; + chanconfig->EcanParametersA.EcanG165DetEnable = 1; + chanconfig->EcanParametersA.EcanDblTalkThresh = 6; + chanconfig->EcanParametersA.EcanNlpThreshold = parms->nlp_threshold; + chanconfig->EcanParametersA.EcanNlpConv = 0; + chanconfig->EcanParametersA.EcanNlpUnConv = 0; + chanconfig->EcanParametersA.EcanNlpMaxSuppress = parms->nlp_max_suppress; + chanconfig->EcanParametersA.EcanCngThreshold = 43; + chanconfig->EcanParametersA.EcanAdaptLimit = 50; + chanconfig->EcanParametersA.EcanCrossCorrLimit = 15; + chanconfig->EcanParametersA.EcanNumFirSegments = 3; + chanconfig->EcanParametersA.EcanFirSegmentLen = 64; + + chanconfig->EcanParametersB.EcanTapLength = 1024; + chanconfig->EcanParametersB.EcanNlpType = parms->nlp_type; + chanconfig->EcanParametersB.EcanAdaptEnable = 1; + chanconfig->EcanParametersB.EcanG165DetEnable = 1; + chanconfig->EcanParametersB.EcanDblTalkThresh = 6; + chanconfig->EcanParametersB.EcanNlpThreshold = parms->nlp_threshold; + chanconfig->EcanParametersB.EcanNlpConv = 0; + chanconfig->EcanParametersB.EcanNlpUnConv = 0; + chanconfig->EcanParametersB.EcanNlpMaxSuppress = parms->nlp_max_suppress; + chanconfig->EcanParametersB.EcanCngThreshold = 43; + chanconfig->EcanParametersB.EcanAdaptLimit = 50; + chanconfig->EcanParametersB.EcanCrossCorrLimit = 15; + chanconfig->EcanParametersB.EcanNumFirSegments = 3; + chanconfig->EcanParametersB.EcanFirSegmentLen = 64; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void vpm150m_bh(void *data) +{ + struct vpm150m *vpm150m = data; +#else +static void vpm150m_bh(struct work_struct *data) +{ + struct vpm150m *vpm150m = container_of(data, struct vpm150m, work); +#endif + struct wctdm *wc = vpm150m->wc; + int i; + + for (i = 0; i < wc->type; i++) { + int enable = -1; + if (test_bit(i, &vpm150m->desireddtmfmutestate)) { + if (!test_bit(i, &vpm150m->curdtmfmutestate)) { + enable = 1; + } + } else { + if (test_bit(i, &vpm150m->curdtmfmutestate)) { + enable = 0; + } + } + if (enable > -1) { + unsigned int start = wc->intcount; + GPAK_AlgControlStat_t pstatus; + int res; + + if (enable) { + res = gpakAlgControl(vpm150m->dspid, i, EnableDTMFMuteA, &pstatus); + if (debug & DEBUG_ECHOCAN) + printk("DTMF mute enable took %d ms\n", wc->intcount - start); + } else { + res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &pstatus); + if (debug & DEBUG_ECHOCAN) + printk("DTMF mute disable took %d ms\n", wc->intcount - start); + } + if (!res) + change_bit(i, &vpm150m->curdtmfmutestate); + } + } + + if (test_bit(VPM150M_DTMFDETECT, &vpm150m->control)) { + unsigned short channel; + GpakAsyncEventCode_t eventcode; + GpakAsyncEventData_t eventdata; + gpakReadEventFIFOMessageStat_t res; + unsigned int start = wc->intcount; + + do { + res = gpakReadEventFIFOMessage(vpm150m->dspid, &channel, &eventcode, &eventdata); + + if (debug & DEBUG_ECHOCAN) + printk("ReadEventFIFOMessage took %d ms\n", wc->intcount - start); + + if (res == RefInvalidEvent || res == RefDspCommFailure) { + printk("Uh oh (%d)\n", res); + continue; + } + + if (eventcode == EventToneDetect) { + GpakToneCodes_t tone = eventdata.toneEvent.ToneCode; + int duration = eventdata.toneEvent.ToneDuration; + char zaptone = vpm150mtone_to_zaptone(tone); + + if (debug & DEBUG_ECHOCAN) + printk("Channel %d: Detected DTMF tone %d of duration %d!!!\n", channel + 1, tone, duration); + + if (test_bit(channel, &wc->dtmfmask) && (eventdata.toneEvent.ToneDuration > 0)) { + struct zt_chan *chan = &wc->chans[channel]; + + if ((tone != EndofMFDigit) && (zaptone != 0)) { + vpm150m->curtone[channel] = tone; + + if (test_bit(channel, &vpm150m->curdtmfmutestate)) { + unsigned long flags; + int y; + + /* Mute the audio data buffers */ + spin_lock_irqsave(&chan->lock, flags); + for (y = 0; y < chan->numbufs; y++) { + if ((chan->inreadbuf > -1) && (chan->readidx[y])) + memset(chan->readbuf[chan->inreadbuf], ZT_XLAW(0, chan), chan->readidx[y]); + } + spin_unlock_irqrestore(&chan->lock, flags); + } + if (!test_bit(channel, &wc->dtmfactive)) { + if (debug & DEBUG_ECHOCAN) + printk("Queuing DTMFDOWN %c\n", zaptone); + set_bit(channel, &wc->dtmfactive); + zt_qevent_lock(chan, (ZT_EVENT_DTMFDOWN | zaptone)); + } + } else if ((tone == EndofMFDigit) && test_bit(channel, &wc->dtmfactive)) { + if (debug & DEBUG_ECHOCAN) + printk("Queuing DTMFUP %c\n", vpm150mtone_to_zaptone(vpm150m->curtone[channel])); + zt_qevent_lock(chan, (ZT_EVENT_DTMFUP | vpm150mtone_to_zaptone(vpm150m->curtone[channel]))); + clear_bit(channel, &wc->dtmfactive); + } + } + } + } while ((res != RefNoEventAvail) && (res != RefInvalidEvent) && (res != RefDspCommFailure)); + } + + for (i = 0; i < wc->type; i++) { + unsigned int start = wc->intcount; + GPAK_AlgControlStat_t pstatus; + int res = 1; + + if ((vpm150m->desiredecstate[i].nlp_type != vpm150m->curecstate[i].nlp_type) + || (vpm150m->desiredecstate[i].nlp_threshold != vpm150m->curecstate[i].nlp_threshold) + || (vpm150m->desiredecstate[i].nlp_max_suppress != vpm150m->curecstate[i].nlp_max_suppress)) { + + GPAK_ChannelConfigStat_t cstatus; + GPAK_TearDownChanStat_t tstatus; + GpakChannelConfig_t chanconfig; + + if (debug & DEBUG_ECHOCAN) + printk("Reconfiguring chan %d for nlp %d, nlp_thresh %d, and max_supp %d\n", i + 1, vpm150m->desiredecstate[i].nlp_type, + vpm150m->desiredecstate[i].nlp_threshold, vpm150m->desiredecstate[i].nlp_max_suppress); + + vpm150m_set_chanconfig_from_state(&vpm150m->desiredecstate[i], i, &chanconfig); + + if ((res = gpakTearDownChannel(vpm150m->dspid, i, &tstatus))) { + goto vpm_bh_out; + } + + if ((res = gpakConfigureChannel(vpm150m->dspid, i, tdmToTdm, &chanconfig, &cstatus))) { + goto vpm_bh_out; + } + + if (!vpm150m->desiredecstate[i].tap_length) + res = gpakAlgControl(vpm150m->dspid, i, BypassEcanA, &pstatus); + + } else if (vpm150m->desiredecstate[i].tap_length != vpm150m->curecstate[i].tap_length) { + if (vpm150m->desiredecstate[i].tap_length) { + res = gpakAlgControl(vpm150m->dspid, i, EnableEcanA, &pstatus); + if (debug & DEBUG_ECHOCAN) + printk("Echocan enable took %d ms\n", wc->intcount - start); + } else { + if (debug & DEBUG_ECHOCAN) + printk("Echocan disable took %d ms\n", wc->intcount - start); + } + } + +vpm_bh_out: + if (!res) + vpm150m->curecstate[i] = vpm150m->desiredecstate[i]; + } + + return; +} + +static int vpm150m_config_hw(struct wctdm *wc) +{ + struct vpm150m *vpm150m = wc->vpm150m; + gpakConfigPortStatus_t configportstatus; + GpakPortConfig_t portconfig; + GPAK_PortConfigStat_t pstatus; + GpakChannelConfig_t chanconfig; + GPAK_ChannelConfigStat_t cstatus; + GPAK_AlgControlStat_t algstatus; + + int res, i; + + memset(&portconfig, 0, sizeof(GpakPortConfig_t)); + + /* First Serial Port config */ + portconfig.SlotsSelect1 = SlotCfgNone; + portconfig.FirstBlockNum1 = 0; + portconfig.FirstSlotMask1 = 0x0000; + portconfig.SecBlockNum1 = 1; + portconfig.SecSlotMask1 = 0x0000; + portconfig.SerialWordSize1 = SerWordSize8; + portconfig.CompandingMode1 = cmpNone; + portconfig.TxFrameSyncPolarity1 = FrameSyncActHigh; + portconfig.RxFrameSyncPolarity1 = FrameSyncActHigh; + portconfig.TxClockPolarity1 = SerClockActHigh; + portconfig.RxClockPolarity1 = SerClockActHigh; + portconfig.TxDataDelay1 = DataDelay0; + portconfig.RxDataDelay1 = DataDelay0; + portconfig.DxDelay1 = Disabled; + portconfig.ThirdSlotMask1 = 0x0000; + portconfig.FouthSlotMask1 = 0x0000; + portconfig.FifthSlotMask1 = 0x0000; + portconfig.SixthSlotMask1 = 0x0000; + portconfig.SevenSlotMask1 = 0x0000; + portconfig.EightSlotMask1 = 0x0000; + + /* Second Serial Port config */ + portconfig.SlotsSelect2 = SlotCfg2Groups; + portconfig.FirstBlockNum2 = 0; + portconfig.FirstSlotMask2 = 0xffff; + portconfig.SecBlockNum2 = 1; + portconfig.SecSlotMask2 = 0xffff; + portconfig.SerialWordSize2 = SerWordSize8; + portconfig.CompandingMode2 = cmpNone; + portconfig.TxFrameSyncPolarity2 = FrameSyncActHigh; + portconfig.RxFrameSyncPolarity2 = FrameSyncActHigh; + portconfig.TxClockPolarity2 = SerClockActHigh; + portconfig.RxClockPolarity2 = SerClockActLow; + portconfig.TxDataDelay2 = DataDelay0; + portconfig.RxDataDelay2 = DataDelay0; + portconfig.DxDelay2 = Disabled; + portconfig.ThirdSlotMask2 = 0x0000; + portconfig.FouthSlotMask2 = 0x0000; + portconfig.FifthSlotMask2 = 0x0000; + portconfig.SixthSlotMask2 = 0x0000; + portconfig.SevenSlotMask2 = 0x0000; + portconfig.EightSlotMask2 = 0x0000; + + /* Third Serial Port Config */ + portconfig.SlotsSelect3 = SlotCfg2Groups; + portconfig.FirstBlockNum3 = 0; + portconfig.FirstSlotMask3 = 0xffff; + portconfig.SecBlockNum3 = 1; + portconfig.SecSlotMask3 = 0xffff; + portconfig.SerialWordSize3 = SerWordSize8; + portconfig.CompandingMode3 = cmpNone; + portconfig.TxFrameSyncPolarity3 = FrameSyncActHigh; + portconfig.RxFrameSyncPolarity3 = FrameSyncActHigh; + portconfig.TxClockPolarity3 = SerClockActHigh; + portconfig.RxClockPolarity3 = SerClockActLow; + portconfig.TxDataDelay3 = DataDelay0; + portconfig.RxDataDelay3 = DataDelay0; + portconfig.DxDelay3 = Disabled; + portconfig.ThirdSlotMask3 = 0x0000; + portconfig.FouthSlotMask3 = 0x0000; + portconfig.FifthSlotMask3 = 0x0000; + portconfig.SixthSlotMask3 = 0x0000; + portconfig.SevenSlotMask3 = 0x0000; + portconfig.EightSlotMask3 = 0x0000; + + if ((configportstatus = gpakConfigurePorts(vpm150m->dspid, &portconfig, &pstatus))) { + printk("Configuration of ports failed (%d)!\n", configportstatus); + return -1; + } else { + if (debug & DEBUG_ECHOCAN) + printk("Configured McBSP ports successfully\n"); + } + + if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { + printk("Error pinging DSP (%d)\n", res); + return -1; + } + + for (i = 0; i < wc->type; i++) { + vpm150m->curecstate[i].tap_length = 0; + vpm150m->curecstate[i].nlp_type = vpmnlptype; + vpm150m->curecstate[i].nlp_threshold = vpmnlpthresh; + vpm150m->curecstate[i].nlp_max_suppress = vpmnlpmaxsupp; + + vpm150m->desiredecstate[i].tap_length = 0; + vpm150m->desiredecstate[i].nlp_type = vpmnlptype; + vpm150m->desiredecstate[i].nlp_threshold = vpmnlpthresh; + vpm150m->desiredecstate[i].nlp_max_suppress = vpmnlpmaxsupp; + + vpm150m_set_chanconfig_from_state(&vpm150m->curecstate[i], i, &chanconfig); + + if ((res = gpakConfigureChannel(vpm150m->dspid, i, tdmToTdm, &chanconfig, &cstatus))) { + printk("Unable to configure channel (%d)\n", res); + if (res == 1) { + printk("Reason %d\n", cstatus); + } + + return -1; + } + + if ((res = gpakAlgControl(vpm150m->dspid, i, BypassEcanA, &algstatus))) { + printk("Unable to disable echo can on channel %d (reason %d:%d)\n", i + 1, res, algstatus); + return -1; + } + + if (vpmdtmfsupport) { + if ((res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &algstatus))) { + printk("Unable to disable dtmf muting on channel %d (reason %d:%d)\n", i + 1, res, algstatus); + return -1; + } + } + } + + if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { + printk("Error pinging DSP (%d)\n", res); + return -1; + } + + vpm150m->wq = create_singlethread_workqueue("wctdm24xxp"); + vpm150m->wc = wc; + + if (!vpm150m->wq) { + printk("Unable to create work queue!\n"); + return -1; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + INIT_WORK(&vpm150m->work, vpm150m_bh, vpm150m); +#else + INIT_WORK(&vpm150m->work, vpm150m_bh); +#endif + + /* Turn on DTMF detection */ + if (vpmdtmfsupport) + set_bit(VPM150M_DTMFDETECT, &vpm150m->control); + + set_bit(VPM150M_ACTIVE, &vpm150m->control); + + return 0; +} +#endif /* VPM150M_SUPPORT */ + +enum vpmadt032_init_result { + VPMADT032_SUCCESS, + VPMADT032_NOT_FOUND, + VPMADT032_FAILED, + VPMADT032_DISABLED, +}; + +static enum vpmadt032_init_result wctdm_vpm150m_init(struct wctdm *wc) +{ + unsigned short i; + struct vpm150m *vpm150m; + unsigned short reg; + unsigned long flags; + enum vpmadt032_init_result res = VPMADT032_FAILED; + +#ifdef VPM150M_SUPPORT + struct wctdm_firmware fw; + struct firmware embedded_firmware; + const struct firmware *firmware = &embedded_firmware; +#if !defined(HOTPLUG_FIRMWARE) + extern void _binary_zaptel_fw_vpmadt032_bin_size; + extern u8 _binary_zaptel_fw_vpmadt032_bin_start[]; +#else + static const char vpmadt032_firmware[] = "zaptel-fw-vpmadt032.bin"; +#endif + gpakDownloadStatus_t downloadstatus; + gpakPingDspStat_t pingstatus; +#endif + + if (!vpmsupport) { + printk("VPM: Support Disabled\n"); + wc->vpm150m = NULL; + return VPMADT032_DISABLED; + } + + vpm150m = kmalloc(sizeof(struct vpm150m), GFP_KERNEL); + + if (!vpm150m) { + printk("Unable to allocate VPM150M!\n"); + return VPMADT032_FAILED; + } + + memset(vpm150m, 0, sizeof(struct vpm150m)); + + /* Init our vpm150m struct */ + sema_init(&vpm150m->sem, 1); + vpm150m->curpage = 0x80; + + for (i = 0; i < WC_MAX_IFACES; i++) { + if (ifaces[i] == wc) + vpm150m->dspid = i; + } + + if (debug & DEBUG_ECHOCAN) + printk("Setting VPMADT032 DSP ID to %d\n", vpm150m->dspid); + + spin_lock_irqsave(&wc->reglock, flags); + wc->vpm150m = vpm150m; + spin_unlock_irqrestore(&wc->reglock, flags); + + for (i = 0; i < 10; i++) + schluffen(&wc->regq); + + if (debug & DEBUG_ECHOCAN) + printk("VPMADT032 Testing page access: "); + for (i = 0; i < 0xf; i++) { + int x; + for (x = 0; x < 3; x++) { + wctdm_vpm150m_setpage(wc, i); + reg = wctdm_vpm150m_getpage(wc); + if (reg != i) { + if (debug & DEBUG_ECHOCAN) + printk("Failed: Sent %x != %x VPMADT032 Failed HI page test\n", i, reg); + res = VPMADT032_NOT_FOUND; + goto failed_exit; + } + } + } + if (debug & DEBUG_ECHOCAN) + printk("Passed\n"); + + /* Set us up to page 0 */ + wctdm_vpm150m_setpage(wc, 0); + if (debug & DEBUG_ECHOCAN) + printk("VPMADT032 now doing address test: "); + for (i = 0; i < 16; i++) { + int x; + for (x = 0; x < 2; x++) { + wctdm_vpm150m_setreg(wc, 1, 0x1000, &i); + wctdm_vpm150m_getreg(wc, 1, 0x1000, ®); + if (reg != i) { + printk("VPMADT032 Failed address test\n"); + goto failed_exit; + } + + } + } + if (debug & DEBUG_ECHOCAN) + printk("Passed\n"); + +#ifndef VPM150M_SUPPORT + printk("Found VPMADT032 module but it is not able to function in anything less than a version 2.6 kernel\n"); + printk("Please update your kernel to a 2.6 or later kernel to enable it\n"); + goto failed_exit; +#else + +#if 0 + /* Load the firmware */ + set_bit(VPM150M_SPIRESET, &vpm150m->control); + + /* Wait for it to boot */ + msleep(7000); + + pingstatus = gpakPingDsp(vpm150m->dspid, &version); + + if (pingstatus || (version != 0x106)) { +#endif +#if defined(HOTPLUG_FIRMWARE) + if ((request_firmware(&firmware, vpmadt032_firmware, &wc->dev->dev) != 0) || + !firmware) { + printk("VPMADT032: firmware %s not available from userspace\n", vpmadt032_firmware); + goto failed_exit; + } +#else + embedded_firmware.data = _binary_zaptel_fw_vpmadt032_bin_start; + embedded_firmware.size = (size_t) &_binary_zaptel_fw_vpmadt032_bin_size; +#endif + fw.fw = firmware; + fw.offset = 0; + + set_bit(VPM150M_HPIRESET, &vpm150m->control); + + while (test_bit(VPM150M_HPIRESET, &vpm150m->control)) + schluffen(&wc->regq); + + printk("VPMADT032 Loading firwmare... "); + downloadstatus = gpakDownloadDsp(vpm150m->dspid, &fw); + + if (firmware != &embedded_firmware) + release_firmware(firmware); + + if (downloadstatus != 0) { + printk("Unable to download firmware to VPMADT032 with cause %d\n", downloadstatus); + goto failed_exit; + } else { + printk("Success\n"); + } + + set_bit(VPM150M_SWRESET, &vpm150m->control); + + while (test_bit(VPM150M_SWRESET, &vpm150m->control)) + schluffen(&wc->regq); + +#if 0 + } +#endif + + pingstatus = gpakPingDsp(vpm150m->dspid, &vpm150m->version); + + if (!pingstatus) { + if (debug & DEBUG_ECHOCAN) + printk("Version of DSP is %x\n", vpm150m->version); + } else { + printk("VPMADT032 Failed! Unable to ping the DSP (%d)!\n", pingstatus); + goto failed_exit; + } + + if (vpm150m_config_hw(wc)) { + goto failed_exit; + } + + return VPMADT032_SUCCESS; +#endif /* VPM150M_SUPPORT */ + +failed_exit: + spin_lock_irqsave(&wc->reglock, flags); + wc->vpm150m = NULL; + spin_unlock_irqrestore(&wc->reglock, flags); + kfree(vpm150m); + + return res; +} + +static void wctdm_vpm_set_dtmf_threshold(struct wctdm *wc, unsigned int threshold) +{ + unsigned int x; + + for (x = 0; x < 4; x++) { + wctdm_vpm_out(wc, x, 0xC4, (threshold >> 8) & 0xFF); + wctdm_vpm_out(wc, x, 0xC5, (threshold & 0xFF)); + } + printk("VPM: DTMF threshold set to %d\n", threshold); +} + +static void wctdm_vpm_init(struct wctdm *wc) +{ + unsigned char reg; + unsigned int mask; + unsigned int ver; + unsigned char vpmver=0; + unsigned int i, x, y; + + if (!vpmsupport) { + printk("VPM: Support Disabled\n"); + wc->vpm = 0; + return; + } + + for (x=0;xvpm = 0; + return; + } + + if (!x) { + vpmver = wctdm_vpm_in(wc, x, 0x1a6) & 0xf; + printk("VPM Revision: %02x\n", vpmver); + } + + + /* Setup GPIO's */ + for (y=0;y<4;y++) { + wctdm_vpm_out(wc, x, 0x1a8 + y, 0x00); /* GPIO out */ + if (y == 3) + wctdm_vpm_out(wc, x, 0x1ac + y, 0x00); /* GPIO dir */ + else + wctdm_vpm_out(wc, x, 0x1ac + y, 0xff); /* GPIO dir */ + wctdm_vpm_out(wc, x, 0x1b0 + y, 0x00); /* GPIO sel */ + } + + /* Setup TDM path - sets fsync and tdm_clk as inputs */ + reg = wctdm_vpm_in(wc, x, 0x1a3); /* misc_con */ + wctdm_vpm_out(wc, x, 0x1a3, reg & ~2); + + /* Setup Echo length (256 taps) */ + wctdm_vpm_out(wc, x, 0x022, 0); + + /* Setup timeslots */ + if (vpmver == 0x01) { + wctdm_vpm_out(wc, x, 0x02f, 0x00); + wctdm_vpm_out(wc, x, 0x023, 0xff); + mask = 0x11111111 << x; + } else { + wctdm_vpm_out(wc, x, 0x02f, 0x20 | (x << 3)); + wctdm_vpm_out(wc, x, 0x023, 0x3f); + mask = 0x0000003f; + } + + /* Setup the tdm channel masks for all chips*/ + for (i = 0; i < 4; i++) + wctdm_vpm_out(wc, x, 0x33 - i, (mask >> (i << 3)) & 0xff); + + /* Setup convergence rate */ + reg = wctdm_vpm_in(wc,x,0x20); + reg &= 0xE0; + if (alawoverride) { + if (!x) + printk("VPM: A-law mode\n"); + reg |= 0x01; + } else { + if (!x) + printk("VPM: U-law mode\n"); + reg &= ~0x01; + } + wctdm_vpm_out(wc,x,0x20,(reg | 0x20)); + + /* Initialize echo cans */ + for (i = 0 ; i < MAX_TDM_CHAN; i++) { + if (mask & (0x00000001 << i)) + wctdm_vpm_out(wc,x,i,0x00); + } + + for (i=0;i<30;i++) + schluffen(&wc->regq); + + /* Put in bypass mode */ + for (i = 0 ; i < MAX_TDM_CHAN ; i++) { + if (mask & (0x00000001 << i)) { + wctdm_vpm_out(wc,x,i,0x01); + } + } + + /* Enable bypass */ + for (i = 0 ; i < MAX_TDM_CHAN ; i++) { + if (mask & (0x00000001 << i)) + wctdm_vpm_out(wc,x,0x78 + i,0x01); + } + + /* Enable DTMF detectors (always DTMF detect all spans) */ + for (i = 0; i < 6; i++) { + if (vpmver == 0x01) + wctdm_vpm_out(wc, x, 0x98 + i, 0x40 | (i << 2) | x); + else + wctdm_vpm_out(wc, x, 0x98 + i, 0x40 | i); + } + + for (i = 0xB8; i < 0xC0; i++) + wctdm_vpm_out(wc, x, i, 0xFF); + for (i = 0xC0; i < 0xC4; i++) + wctdm_vpm_out(wc, x, i, 0xff); + + } + /* set DTMF detection threshold */ + wctdm_vpm_set_dtmf_threshold(wc, dtmfthreshold); + + if (vpmver == 0x01) + wc->vpm = 2; + else + wc->vpm = 1; + + printk("Enabling VPM100 gain adjustments on any FXO ports found\n"); + for (i = 0; i < wc->type; i++) { + if (wc->modtype[i] == MOD_TYPE_FXO) { + /* Apply negative Tx gain of 4.5db to DAA */ + wctdm_setreg(wc, i, 38, 0x14); /* 4db */ + wctdm_setreg(wc, i, 40, 0x15); /* 0.5db */ + + /* Apply negative Rx gain of 4.5db to DAA */ + wctdm_setreg(wc, i, 39, 0x14); /* 4db */ + wctdm_setreg(wc, i, 41, 0x15); /* 0.5db */ + } + } + +} + +#endif + +static int wctdm_locate_modules(struct wctdm *wc) +{ + int x; + unsigned long flags; + printk("Resetting the modules...\n"); + /* Initialize control register */ + wc->ctlreg = 0x00; + /* Set Reset */ + wctdm_setctl(wc, 0x0048, 0x00000000); + for (x=0;x<10;x++) + schluffen(&wc->regq); + printk("During Resetting the modules...\n"); + /* Clear reset */ + wctdm_setctl(wc, 0x0048, 0x00010000); + for (x=0;x<10;x++) + schluffen(&wc->regq); + printk("After resetting the modules...\n"); + + wctdm_setintmask(wc, 0x0001f7fe); + + /* Make sure all units go into daisy chain mode */ + spin_lock_irqsave(&wc->reglock, flags); + wc->span.irqmisses = 0; + for (x=0;xcards;x++) + wc->modtype[x] = MOD_TYPE_FXSINIT; +#ifdef VPM_SUPPORT + wc->vpm = -1; + for (x = wc->cards; x < wc->cards+NUM_EC; x++) + wc->modtype[x] = MOD_TYPE_VPM; +#endif + spin_unlock_irqrestore(&wc->reglock, flags); + /* Wait just a bit */ + for (x=0;x<10;x++) + schluffen(&wc->regq); + spin_lock_irqsave(&wc->reglock, flags); + for (x=0;xcards;x++) + wc->modtype[x] = MOD_TYPE_FXS; + spin_unlock_irqrestore(&wc->reglock, flags); + +#if 0 + /* XXX */ + cmddesc = 0; +#endif + /* Now that all the cards have been reset, we can stop checking them all if there aren't as many */ + spin_lock_irqsave(&wc->reglock, flags); + wc->cards = wc->type; + spin_unlock_irqrestore(&wc->reglock, flags); + + /* Reset modules */ + for (x=0;xcards;x++) { + int sane=0,ret=0,readi=0; +retry: + /* Init with Auto Calibration */ + if (!(ret = wctdm_init_proslic(wc, x, 0, 0, sane))) { + wc->cardflag |= (1 << x); + if (debug & DEBUG_CARD) { + readi = wctdm_getreg(wc,x,LOOP_I_LIMIT); + printk("Proslic module %d loop current is %dmA\n",x, + ((readi*3)+20)); + } + printk("Port %d: Installed -- AUTO FXS/DPO\n", x + 1); + } else { + if(ret!=-2) { + sane=1; + /* Init with Manual Calibration */ + if (!wctdm_init_proslic(wc, x, 0, 1, sane)) { + wc->cardflag |= (1 << x); + if (debug & DEBUG_CARD) { + readi = wctdm_getreg(wc,x,LOOP_I_LIMIT); + printk("Proslic module %d loop current is %dmA\n",x, + ((readi*3)+20)); + } + printk("Port %d: Installed -- MANUAL FXS\n",x + 1); + } else { + printk("Port %d: FAILED FXS (%s)\n", x + 1, fxshonormode ? fxo_modes[_opermode].name : "FCC"); + wc->chans[x].sigcap = ZT_SIG_BROKEN | __ZT_SIG_FXO; + } + } else if (!(ret = wctdm_init_voicedaa(wc, x, 0, 0, sane))) { + wc->cardflag |= (1 << x); + printk("Port %d: Installed -- AUTO FXO (%s mode)\n",x + 1, fxo_modes[_opermode].name); + } else if (!wctdm_init_qrvdri(wc,x)) { + wc->cardflag |= 1 << x; + printk("Port %d: Installed -- QRV DRI card\n",x + 1); + } else { + if ((wc->type != 24) && ((x & 0x3) == 1) && !wc->altcs[x]) { + spin_lock_irqsave(&wc->reglock, flags); + wc->altcs[x] = 2; + if (wc->type == 4) { + wc->altcs[x+1] = 3; + wc->altcs[x+2] = 3; + } + wc->modtype[x] = MOD_TYPE_FXSINIT; + spin_unlock_irqrestore(&wc->reglock, flags); + + schluffen(&wc->regq); + schluffen(&wc->regq); + spin_lock_irqsave(&wc->reglock, flags); + wc->modtype[x] = MOD_TYPE_FXS; + spin_unlock_irqrestore(&wc->reglock, flags); + if (debug & DEBUG_CARD) + printk("Trying port %d with alternate chip select\n", x + 1); + goto retry; + } else { + printk("Port %d: Not installed\n", x + 1); + wc->modtype[x] = MOD_TYPE_NONE; + wc->cardflag |= (1 << x); + } + } + } + } +#ifdef VPM_SUPPORT + wctdm_vpm_init(wc); + if (wc->vpm) { + printk("VPM: Present and operational (Rev %c)\n", 'A' + wc->vpm - 1); + wc->ctlreg |= 0x10; + } else { + spin_lock_irqsave(&wc->reglock, flags); + for (x = NUM_CARDS; x < NUM_CARDS + NUM_EC; x++) + wc->modtype[x] = MOD_TYPE_NONE; + spin_unlock_irqrestore(&wc->reglock, flags); + switch (wctdm_vpm150m_init(wc)) { + case VPMADT032_SUCCESS: + printk("VPMADT032: Present and operational (Firmware version %x)\n", wc->vpm150m->version); + wc->ctlreg |= 0x10; + break; + case VPMADT032_DISABLED: + case VPMADT032_NOT_FOUND: + /* nothing */ + break; + default: + return -1; + } + } +#endif + + return 0; +} + +static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct wctdm *wc; + struct wctdm_desc *d = (struct wctdm_desc *)ent->driver_data; + int x; + int y; + + if (pci_enable_device(pdev)) + return -EIO; + + if (!(wc = kmalloc(sizeof(struct wctdm), GFP_KERNEL))) + return -ENOMEM; + + spin_lock(&ifacelock); + for (x = 0; x < WC_MAX_IFACES; x++) + if (!ifaces[x]) break; + + ifaces[x] = wc; + spin_unlock(&ifacelock); + + memset(wc, 0, sizeof(struct wctdm)); + spin_lock_init(&wc->reglock); + wc->curcard = -1; + wc->cards = NUM_CARDS; + wc->iobase = pci_resource_start(pdev, 0); + wc->type = d->ports; + wc->dev = pdev; + wc->pos = x; + wc->variety = d->name; + for (y=0;yflags[y] = d->flags; + wc->dacssrc[y] = -1; + } + /* Keep track of whether we need to free the region */ + if (request_region(wc->iobase, 0xff, "wctdm24xxp")) + wc->freeregion = 1; + + /* Allocate enough memory for two zt chunks, receive and transmit. Each sample uses + 32 bits. Allocate an extra set just for control too */ + wc->writechunk = pci_alloc_consistent(pdev, PCI_WINDOW_SIZE, &wc->writedma); + if (!wc->writechunk) { + printk("wctdm: Unable to allocate DMA-able memory\n"); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + return -ENOMEM; + } + + wc->readchunk = wc->writechunk + SFRAME_SIZE / 2; /* in doublewords */ + wc->readdma = wc->writedma + SFRAME_SIZE * 2; /* in bytes */ + + wc->descripchunk = wc->readchunk + SFRAME_SIZE / 2; /* in doublewords */ + wc->descripdma = wc->readdma + SFRAME_SIZE * 2; /* in bytes */ + + /* Initialize Write/Buffers to all blank data */ + memset((void *)wc->writechunk,0x00, SFRAME_SIZE * 2); + memset((void *)wc->readchunk, 0x00, SFRAME_SIZE * 2); + + init_waitqueue_head(&wc->regq); + + if (wctdm_initialize(wc)) { + printk("%s: Unable to register span with zaptel\n", wc->variety); + /* Set Reset Low */ + wctdm_stop_dma(wc); + /* Free Resources */ + if (wc->freeregion) + release_region(wc->iobase, 0xff); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); + zt_unregister(&wc->span); + kfree(wc); + return -EIO; + } + + /* Enable bus mastering */ + pci_set_master(pdev); + + /* Keep track of which device we are */ + pci_set_drvdata(pdev, wc); + + if (request_irq(pdev->irq, wctdm_interrupt, ZAP_IRQ_SHARED, wc->variety, wc)) { + printk("wctdm24xxp: Unable to request IRQ %d\n", pdev->irq); + /* Set Reset Low */ + wctdm_stop_dma(wc); + /* Free Resources */ + if (wc->freeregion) + release_region(wc->iobase, 0xff); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); + pci_set_drvdata(pdev, NULL); + zt_unregister(&wc->span); + kfree(wc); + return -EIO; + } + + + if (wctdm_hardware_init(wc)) { + /* Set Reset Low */ + wctdm_stop_dma(wc); + /* Free Resources */ + free_irq(pdev->irq, wc); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); + pci_set_drvdata(pdev, NULL); + zt_unregister(&wc->span); + kfree(wc); + return -EIO; + + } + + /* Enable interrupts */ + wctdm_enable_interrupts(wc); + + /* Start DMA */ + wctdm_start_dma(wc); + + /* Now track down what modules are installed */ + if (wctdm_locate_modules(wc)) { + wctdm_disable_interrupts(wc); + /* Set Reset Low */ + wctdm_stop_dma(wc); + /* Free Resources */ + free_irq(pdev->irq, wc); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); + pci_set_drvdata(pdev, NULL); + zt_unregister(&wc->span); + kfree(wc); + return -EIO; + } + + /* Final initialization */ + wctdm_post_initialize(wc); + + printk("Found a Wildcard TDM: %s (%d modules)\n", wc->variety, wc->type); + + return 0; +} + +static void wctdm_release(struct wctdm *wc) +{ + int i; + + zt_unregister(&wc->span); + + if (wc->freeregion) + release_region(wc->iobase, 0xff); + + spin_lock(&ifacelock); + + for (i = 0; i < WC_MAX_IFACES; i++) + if (ifaces[i] == wc) + break; + + ifaces[i] = NULL; + + spin_unlock(&ifacelock); + + kfree(wc); + printk("Freed a Wildcard\n"); +} + +static void __devexit wctdm_remove_one(struct pci_dev *pdev) +{ + struct wctdm *wc = pci_get_drvdata(pdev); + +#ifdef VPM150M_SUPPORT + unsigned long flags; + struct vpm150m *vpm150m = wc->vpm150m; +#endif + + if (wc) { + +#ifdef VPM150M_SUPPORT + if (vpm150m) { + clear_bit(VPM150M_DTMFDETECT, &vpm150m->control); + clear_bit(VPM150M_ACTIVE, &vpm150m->control); + flush_workqueue(vpm150m->wq); + destroy_workqueue(vpm150m->wq); + } +#endif + + /* Stop any DMA */ + wctdm_stop_dma(wc); + + /* In case hardware is still there */ + wctdm_disable_interrupts(wc); + + /* Immediately free resources */ + free_irq(pdev->irq, wc); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); + +#ifdef VPM150M_SUPPORT + if (vpm150m) { + spin_lock_irqsave(&wc->reglock, flags); + wc->vpm150m = NULL; + vpm150m->wc = NULL; + spin_unlock_irqrestore(&wc->reglock, flags); + kfree(wc->vpm150m); + } +#endif + /* Release span, possibly delayed */ + if (!wc->usecount) + wctdm_release(wc); + else + wc->dead = 1; + } +} + +static struct pci_device_id wctdm_pci_tbl[] = { + { 0xd161, 0x2400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm2400 }, + { 0xd161, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm800 }, + { 0xd161, 0x8002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcaex800 }, + { 0xd161, 0x8003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcaex2400 }, + { 0xd161, 0x8005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm410 }, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, wctdm_pci_tbl); + +static struct pci_driver wctdm_driver = { + name: "wctdm24xxp", + probe: wctdm_init_one, +#ifdef LINUX26 + remove: __devexit_p(wctdm_remove_one), +#else + remove: wctdm_remove_one, +#endif + suspend: NULL, + resume: NULL, + id_table: wctdm_pci_tbl, +}; + +static int __init wctdm_init(void) +{ + int res; + int x; + + for (x=0;x<(sizeof(fxo_modes) / sizeof(fxo_modes[0])); x++) { + if (!strcmp(fxo_modes[x].name, opermode)) + break; + } + if (x < sizeof(fxo_modes) / sizeof(fxo_modes[0])) { + _opermode = x; + } else { + printk("Invalid/unknown operating mode '%s' specified. Please choose one of:\n", opermode); + for (x=0;x"); +#if defined(MODULE_ALIAS) +MODULE_ALIAS("wctdm8xxp"); +#endif +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +module_init(wctdm_init); +module_exit(wctdm_cleanup); diff --git a/kernel/wctdm24xxp/gpakErrs.h b/kernel/wctdm24xxp/gpakErrs.h new file mode 100644 index 0000000..3413f97 --- /dev/null +++ b/kernel/wctdm24xxp/gpakErrs.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2002 - 2004, Adaptive Digital Technologies, Inc. + * + * File Name: GpakErrs.h + * + * Description: + * This file contains DSP reply status codes used by G.PAK API functions to + * indicate specific errors. + * + * Version: 1.0 + * + * Revision History: + * 10/17/01 - Initial release. + * 07/03/02 - Updates for conferencing. + * 06/15/04 - Tone type updates. + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. The standard + * GPL disclaimer is given inline below for your convenience. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GPAKERRS_H /* prevent multiple inclusion */ +#define _GPAKERRS_H + +/* Configure Serial Ports reply status codes. */ +typedef enum +{ + Pc_Success = 0, /* serial ports configured successfully */ + Pc_ChannelsActive = 1, /* unable to configure while channels active */ + Pc_TooManySlots1 = 2, /* too many slots selected for port 1 */ + Pc_InvalidBlockCombo1 = 3, /* invalid combination of blocks for port 1 */ + Pc_NoSlots1 = 4, /* no slots selected for port 1 */ + Pc_InvalidSlots1 = 5, /* invalid slot (> max) selected for port 1 */ + Pc_TooManySlots2 = 6, /* too many slots selected for port 2 */ + Pc_InvalidBlockCombo2 = 7, /* invalid combination of blocks for port 2 */ + Pc_NoSlots2 = 8, /* no slots selected for port 2 */ + Pc_InvalidSlots2 = 9, /* invalid slot (> max) selected for port 2 */ + Pc_TooManySlots3 = 10, /* too many slots selected for port 3 */ + Pc_InvalidBlockCombo3 = 11, /* invalid combination of blocks for port 3 */ + Pc_NoSlots3 = 12, /* no slots selected for port 3 */ + Pc_InvalidSlots3 = 13 /* invalid slot (> max) selected for port 3 */ +} GPAK_PortConfigStat_t; + +/* Configure Channel reply status codes. */ +typedef enum +{ + Cc_Success = 0, /* channel configured successfully */ + Cc_InvalidChannelType = 1, /* invalid Channel Type */ + Cc_InvalidChannel = 2, /* invalid Channel A Id */ + Cc_ChannelActiveA = 3, /* Channel A is currently active */ + Cc_InvalidInputPortA = 4, /* invalid Input A Port */ + Cc_InvalidInputSlotA = 5, /* invalid Input A Slot */ + Cc_BusyInputSlotA = 6, /* busy Input A Slot */ + Cc_InvalidOutputPortA = 7, /* invalid Output A Port */ + Cc_InvalidOutputSlotA = 8, /* invalid Output A Slot */ + Cc_BusyOutputSlotA = 9, /* busy Output A Slot */ + Cc_InvalidInputPortB = 10, /* invalid Input B Port */ + Cc_InvalidInputSlotB = 11, /* invalid Input B Slot */ + Cc_BusyInputSlotB = 12, /* busy Input B Slot */ + Cc_InvalidPktInCodingA = 13, /* invalid Packet In A Coding */ + Cc_InvalidPktOutCodingA = 14, /* invalid Packet Out A Coding */ + Cc_InvalidPktInSizeA = 15, /* invalid Packet In A Frame Size */ + Cc_InvalidPktOutSizeA = 16, /* invalid Packet Out A Frame Size */ + + Cc_ChanTypeNotConfigured = 21, /* channel type was not configured */ + Cc_InsuffECResources = 22, /* insufficient ecan resources avail. */ + Cc_InsuffTDMResources = 23, /* insufficient tdm block resources avail. */ + + Cc_InsuffPktBufResources = 25, /* insufficient pkt buffer resources avail. */ + Cc_InsuffPcmBufResources = 26, /* insufficient pcm buffer resources avail. */ + + Cc_BadPcmEcNlpType = 30, /* invalid EC Nlp type */ + Cc_BadPcmEcTapLength = 31, /* invalid EC tap length */ + Cc_BadPcmEcDblTalkThresh = 32, /* invalid EC double-talk threshold */ + Cc_BadPcmEcNlpThreshold = 33, /* invalid EC Nlp threshold */ + Cc_BadPcmEcCngThreshold = 34, /* invalid EC Cng threshold */ + Cc_BadPcmEcAdaptLimit = 35, /* invalid EC Adapt Limit */ + Cc_BadPcmEcCrossCorrLim = 36, /* invalid EC Cross Correlation Limit */ + Cc_BadPcmEcNumFirSegs = 37, /* invalid EC Number of FirSegments */ + Cc_BadPcmEcFirSegLen = 38, /* invalid EC Fir Segment Length */ + + /*Cc_InvalidNumEcsEnabled = 48, */ /* more than 1 Ec enabled on channel */ + Cc_InvalidFrameRate = 49, /* invalid gpak frame rate */ + Cc_InvalidSoftCompand = 50, /* invalid softCompanding type */ + + Cc_InvalidMuteToneA = 51, /* invalid MuteToneA set, no detector */ + Cc_InvalidMuteToneB = 52, /* invalid MuteToneB set, no detector */ + Cc_InsuffFaxCngDetResources = 53 /* insufficient tdm block resources avail. */ + +} GPAK_ChannelConfigStat_t; + +/* Tear Down Channel reply status codes. */ +typedef enum +{ + Td_Success = 0, /* channel torn down successfully */ + Td_InvalidChannel = 1, /* invalid Channel Id */ + Td_ChannelNotActive = 2 /* channel is not active */ +} GPAK_TearDownChanStat_t; + + +typedef enum +{ + Ac_Success = 0, /* algorithm control is successfull */ + Ac_InvalidChannel = 1, /* invalid channel identifier */ + Ac_InvalidCode = 2, /* invalid algorithm control code */ + Ac_ECNotEnabled = 3, /* echo canceller was not allocated */ + Ac_InvalidSoftComp = 4, /* invalid softcompanding, 'cause serial port not in companding mode */ + Ac_InvalidDTMFMuteA = 5, /* A side invalid Mute, since no dtmf detector */ + Ac_InvalidDTMFMuteB = 6, /* B side invalid Mute, since no dtmf detector */ + Ac_InvalidFaxCngA = 7, /* A side FAXCNG detector not available */ + Ac_InvalidFaxCngB = 8, /* B side FAXCNG detector not available */ + Ac_InvalidSysConfig = 9 /* No new system parameters (DTMF config) wrriten yet */ +} GPAK_AlgControlStat_t; + +/* Write System Parameters reply status codes. */ +typedef enum +{ + Sp_Success = 0, /* System Parameters written successfully */ + Sp_BadTwistThresh = 29 /* invalid twist threshold */ + +} GPAK_SysParmsStat_t; + +#endif /* prevent multiple inclusion */ + + + + + + + + + + + + + + + + + + + diff --git a/kernel/wctdm24xxp/gpakenum.h b/kernel/wctdm24xxp/gpakenum.h new file mode 100644 index 0000000..91e4311 --- /dev/null +++ b/kernel/wctdm24xxp/gpakenum.h @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2005, Adaptive Digital Technologies, Inc. + * + * File Name: gpakenum.h + * + * Description: + * This file contains common enumerations related to G.PAK application + * software. + * + * Version: 1.0 + * + * Revision History: + * 06/15/05 - Initial release. + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. The standard + * GPL disclaimer is given inline below for your convenience. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GPAKENUM_H /* prevent multiple inclusion */ +#define _GPAKENUM_H + +/* G.PAK Serial Port Word Size */ +typedef enum +{ + SerWordSize8 = 0, // 8-bit seial word + SerWordSize16 = 1 // 16-bit serial word +} GpakSerWordSize_t; + +/* G.PAK Serial Port FrameSync Polarity */ +typedef enum +{ + FrameSyncActLow = 0, // active low frame sync signal + FrameSyncActHigh = 1 // active high frame sync signal +} GpakSerFrameSyncPol_t; + +/* G.PAK Serial Port Clock Polarity */ +typedef enum +{ + SerClockActLow = 0, // active low serial clock + SerClockActHigh = 1 // active high serial clock +} GpakSerClockPol_t; + +/* G.PAK Serial Port Data Delay */ +typedef enum +{ + DataDelay0 = 0, // no data delay + DataDelay1 = 1, // 1-bit data delay + DataDelay2 = 2 // 2-bit data delay +} GpakSerDataDelay_t; + +/* G.PAK Serial Port Ids. */ +typedef enum +{ + SerialPortNull = 0, // null serial port + SerialPort1 = 1, // first PCM serial stream port (McBSP0) + SerialPort2 = 2, // second PCM serial stream port (McBSP1) + SerialPort3 = 3 // third PCM serial stream port (McBSP2) +} GpakSerialPort_t; + +/* G.PAK serial port Slot Configuration selection codes. */ +typedef enum +{ + SlotCfgNone = 0, // no time slots used + SlotCfg2Groups = 2, // 2 groups of 16 time slots used, 32 Channels system + SlotCfg8Groups = 8 // 8-partition mode for 128-channel system +} GpakSlotCfg_t; + +/* G.PAK serial port Companding Mode codes. */ +typedef enum +{ + cmpPCMU=0, // u-Law + cmpPCMA=1, // A-Law + cmpNone=2 // none +} GpakCompandModes; + +/* G.PAK Active/Inactive selection codes. */ +typedef enum +{ + Disabled=0, // Inactive + Enabled=1 // Active +} GpakActivation; + +/* G.PAK Channel Type codes. */ +typedef enum +{ + inactive=0, // channel inactive + tdmToTdm=1 // tdmToTdm +} GpakChanType; + +/* G.PAK Algorithm control commands */ +typedef enum +{ + EnableEcanA = 0, // Enable A side echo canceller + BypassEcanA = 1, // Bypass A side echo canceller + ResetEcanA = 2, // Reset A side echo canceller + EnableEcanB = 3, // Enable B side echo canceller + BypassEcanB = 4, // Bypass B side echo canceller + ResetEcanB = 5, // Reset B side echo canceller + + EnableMuLawSwCompanding = 6,// Enable Mu-law Software companding + EnableALawSwCompanding = 7, // Enable Mu-law Software companding + BypassSwCompanding = 8, // Bypass Software companding + EnableDTMFMuteA = 9, // Mute A side Dtmf digit after tone detected + DisableDTMFMuteA = 10, // Do not mute A side Dtmf digit once tone detected + EnableDTMFMuteB = 11, // Mute B side Dtmf digit after tone detected + DisableDTMFMuteB = 12, // Do not mute B side Dtmf digit once tone detected + EnableFaxCngDetectA = 13, // Enable A side Fax CNG detector, channel must be configed already + DisableFaxCngDetectA = 14, // Disable A side Fax CNG detector, channel must be configed already + EnableFaxCngDetectB = 15, // Enable B side Fax CNG detector, channel must be configed already + DisableFaxCngDetectB = 16 // Disable B side Fax CNG detector, channel must be configed already +} GpakAlgCtrl_t; + +/* G.PAK Tone types. */ +typedef enum +{ + Null_tone = 0, // no tone detection + DTMF_tone = 1 // DTMF tone +} GpakToneTypes; + +/* G.PAK direction. */ +typedef enum +{ + TDMAToB = 0, // A to B + TDMBToA = 1 // B to A +} GpakTdmDirection; + + +typedef enum +{ + rate1ms=0, + rate2ms=1, + rate10ms=2 +} GpakRate_t; + +/* G.PAK Asynchronous Event Codes */ +typedef enum +{ + EventToneDetect = 0, // Tone detection event + EventDSPDebug = 7 // DSP debug data event +} GpakAsyncEventCode_t; + +/* G.PAK MF Tone Code Indices */ +typedef enum +{ + DtmfDigit1 = 0, // DTMF Digit 1 + DtmfDigit2 = 1, // DTMF Digit 2 + DtmfDigit3 = 2, // DTMF Digit 3 + DtmfDigitA = 3, // DTMF Digit A + DtmfDigit4 = 4, // DTMF Digit 4 + DtmfDigit5 = 5, // DTMF Digit 5 + DtmfDigit6 = 6, // DTMF Digit 6 + DtmfDigitB = 7, // DTMF Digit B + DtmfDigit7 = 8, // DTMF Digit 7 + DtmfDigit8 = 9, // DTMF Digit 8 + DtmfDigit9 = 10, // DTMF Digit 9 + DtmfDigitC = 11, // DTMF Digit C + DtmfDigitSt = 12, // DTMF Digit * + DtmfDigit0 = 13, // DTMF Digit 0 + DtmfDigitPnd = 14, // DTMF Digit # + DtmfDigitD = 15, // DTMF Digit D + + FaxCngDigit = 90, // Fax Calling Tone (1100 Hz) + + EndofMFDigit = 100, // End of MF digit + EndofCngDigit = 101 // End of Cng Digit +} GpakToneCodes_t; + +/* GPIO control code*/ +typedef enum +{ + GPIO_READ = 0, + GPIO_WRITE = 1, + GPIO_DIR = 2 +} GpakGPIOCotrol_t; + + +#endif // end multiple inclusion diff --git a/kernel/wctdm24xxp/wctdm24xxp.h b/kernel/wctdm24xxp/wctdm24xxp.h new file mode 100644 index 0000000..fd7f39b --- /dev/null +++ b/kernel/wctdm24xxp/wctdm24xxp.h @@ -0,0 +1,280 @@ +/* + * Wildcard TDM2400P TDM FXS/FXO Interface Driver for Zapata Telephony interface + * + * Written by Mark Spencer + * Support for TDM800P and VPM150M by Matthew Fredrickson + * + * Copyright (C) 2005, 2006, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _WCTDM24XXP_H +#define _WCTDM24XXP_H + +#define NUM_FXO_REGS 60 + +#define WC_MAX_IFACES 128 + +/*! + * \brief Default ringer debounce (in ms) + * + * \todo This value differs from that in wctdm. In that module, it is 64 ms + * instead of 128 ms. Which one is more appropriate? + */ +#define DEFAULT_RING_DEBOUNCE 128 +#define DEFAULT_BATT_DEBOUNCE 64 /* Battery debounce (in ms) */ +#define POLARITY_DEBOUNCE 64 /* Polarity debounce (in ms) */ +#define DEFAULT_BATT_THRESH 3 /* Anything under this is "no battery" */ + +#define OHT_TIMER 6000 /* How long after RING to retain OHT */ + +#define FLAG_3215 (1 << 0) +#define FLAG_EXPRESS (1 << 1) + +#define EFRAME_SIZE 108 +#define ERING_SIZE 16 /* Maximum ring size */ +#define EFRAME_GAP 20 +#define SFRAME_SIZE ((EFRAME_SIZE * ZT_CHUNKSIZE) + (EFRAME_GAP * (ZT_CHUNKSIZE - 1))) + +#define MAX_ALARMS 10 + +#define MOD_TYPE_NONE 0 +#define MOD_TYPE_FXS 1 +#define MOD_TYPE_FXO 2 +#define MOD_TYPE_FXSINIT 3 +#define MOD_TYPE_VPM 4 +#define MOD_TYPE_QRV 5 +#define MOD_TYPE_VPM150M 6 + +#define MINPEGTIME 10 * 8 /* 30 ms peak to peak gets us no more than 100 Hz */ +#define PEGTIME 50 * 8 /* 50ms peak to peak gets us rings of 10 Hz or more */ +#define PEGCOUNT 5 /* 5 cycles of pegging means RING */ + +#define SDI_CLK (0x00010000) +#define SDI_DOUT (0x00020000) +#define SDI_DREAD (0x00040000) +#define SDI_DIN (0x00080000) + +#define PCI_WINDOW_SIZE ((2 * 2 * 2 * SFRAME_SIZE) + (2 * ERING_SIZE * 4)) + +#define __CMD_RD (1 << 20) /* Read Operation */ +#define __CMD_WR (1 << 21) /* Write Operation */ +#define __CMD_FIN (1 << 22) /* Has finished receive */ +#define __CMD_TX (1 << 23) /* Has been transmitted */ + +#define CMD_WR(a,b) (((a) << 8) | (b) | __CMD_WR) +#define CMD_RD(a) (((a) << 8) | __CMD_RD) + +#if 0 +#define CMD_BYTE(card,bit,altcs) (((((card) & 0x3) * 3 + (bit)) * 7) \ + + ((card) >> 2) + (altcs) + ((altcs) ? -21 : 0)) +#endif +#define NUM_CARDS 24 +#define NUM_EC 4 +#define NUM_SLOTS 6 +#define MAX_TDM_CHAN 31 + +#define NUM_CAL_REGS 12 + +#define USER_COMMANDS 8 +#define ISR_COMMANDS 2 +#define QRV_DEBOUNCETIME 20 + +#define MAX_COMMANDS (USER_COMMANDS + ISR_COMMANDS) + +#define __VPM150M_RWPAGE (1 << 4) +#define __VPM150M_RD (1 << 3) +#define __VPM150M_WR (1 << 2) +#define __VPM150M_FIN (1 << 1) +#define __VPM150M_TX (1 << 0) + +#define VPM150M_HPI_CONTROL 0x00 +#define VPM150M_HPI_ADDRESS 0x02 +#define VPM150M_HPI_DATA 0x03 + +#define VPM150M_MAX_COMMANDS 8 + +/* Some Bit ops for different operations */ +#define VPM150M_SPIRESET 0 +#define VPM150M_HPIRESET 1 +#define VPM150M_SWRESET 2 +#define VPM150M_DTMFDETECT 3 +#define VPM150M_ACTIVE 4 + +#define VPM150M_MAX_DATA 1 + +#define VPM_SUPPORT + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#define VPM150M_SUPPORT +#endif + +#ifdef VPM_SUPPORT + +/* Define to get more attention-grabbing but slightly more CPU using echocan status */ +#define FANCY_ECHOCAN + +#endif + +#ifdef VPM150M_SUPPORT +#include "adt_lec.h" +#endif + +struct vpm150m_cmd { + unsigned int addr; + unsigned char datalen; + unsigned char desc; + unsigned char txident; + unsigned short data[VPM150M_MAX_DATA]; +}; + +struct vpm150m { +#ifdef VPM150M_SUPPORT + struct workqueue_struct *wq; + struct work_struct work; +#endif + struct wctdm *wc; + + int dspid; + struct semaphore sem; + unsigned long control; + unsigned char curpage; + unsigned short version; + struct adt_lec_params curecstate[24]; + struct adt_lec_params desiredecstate[24]; + unsigned long curdtmfmutestate; + unsigned long desireddtmfmutestate; + struct vpm150m_cmd cmdq[VPM150M_MAX_COMMANDS]; + unsigned char curtone[24]; +}; + +struct calregs { + unsigned char vals[NUM_CAL_REGS]; +}; + +struct cmdq { + unsigned int cmds[MAX_COMMANDS]; + unsigned char isrshadow[ISR_COMMANDS]; +}; + +struct wctdm { + struct pci_dev *dev; + char *variety; + struct zt_span span; + unsigned char ios; + unsigned int sdi; + int usecount; + unsigned int intcount; + unsigned int rxints; + unsigned int txints; + unsigned int intmask; + unsigned char txident; + unsigned char rxident; + int dead; + int pos; + int flags[NUM_CARDS]; + int freeregion; + int alt; + int rdbl; + int tdbl; + int curcard; + unsigned char ctlreg; + int cards; + int cardflag; /* Bit-map of present cards */ + int altcs[NUM_CARDS + NUM_EC]; + char qrvhook[NUM_CARDS]; + unsigned short qrvdebtime[NUM_CARDS]; + int radmode[NUM_CARDS]; +#define RADMODE_INVERTCOR 1 +#define RADMODE_IGNORECOR 2 +#define RADMODE_EXTTONE 4 +#define RADMODE_EXTINVERT 8 +#define RADMODE_IGNORECT 16 +#define RADMODE_PREEMP 32 +#define RADMODE_DEEMP 64 + unsigned short debouncetime[NUM_CARDS]; + signed short rxgain[NUM_CARDS]; + signed short txgain[NUM_CARDS]; + spinlock_t reglock; + wait_queue_head_t regq; + /* FXO Stuff */ + union { + struct { + int wasringing; + int lastrdtx; + int ringdebounce; + int offhook; + int battdebounce; + int nobatttimer; + int battery; + int lastpol; + int polarity; + int polaritydebounce; + } fxo; + struct { + int oldrxhook; + int debouncehook; + int lastrxhook; + int debounce; + int ohttimer; + int idletxhookstate; /* IDLE changing hook state */ + int lasttxhook; + int palarms; + struct calregs calregs; + } fxs; + } mods[NUM_CARDS]; + struct cmdq cmdq[NUM_CARDS + NUM_EC]; + /* Receive hook state and debouncing */ + int modtype[NUM_CARDS + NUM_EC]; + /* Set hook */ + int sethook[NUM_CARDS + NUM_EC]; + int dacssrc[NUM_CARDS]; + int type; + +#ifdef VPM_SUPPORT + int vpm; + unsigned long dtmfactive; + unsigned long dtmfmask; + unsigned long dtmfmutemask; + short dtmfenergy[NUM_CARDS]; + short dtmfdigit[NUM_CARDS]; + + struct vpm150m *vpm150m; +#ifdef FANCY_ECHOCAN + int echocanpos; + int blinktimer; +#endif +#endif + unsigned long iobase; + dma_addr_t readdma; + dma_addr_t writedma; + dma_addr_t descripdma; + volatile unsigned int *writechunk; /* Double-word aligned write memory */ + volatile unsigned int *readchunk; /* Double-word aligned read memory */ + volatile unsigned int *descripchunk; /* Descriptors */ + struct zt_chan chans[NUM_CARDS]; +}; + + +int schluffen(wait_queue_head_t *q); + +extern spinlock_t ifacelock; +extern struct wctdm *ifaces[WC_MAX_IFACES]; + +#endif diff --git a/kernel/wcte11xp.c b/kernel/wcte11xp.c new file mode 100644 index 0000000..68cc827 --- /dev/null +++ b/kernel/wcte11xp.c @@ -0,0 +1,1644 @@ +/* + * Digium, Inc. Wildcard TE110P T1/PRI card Driver + * + * Written by Mark Spencer + * Matthew Fredrickson + * William Meadows + * + * Copyright (C) 2004, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "zaptel.h" +#ifdef LINUX26 +#include +#endif + +/* XXX: fix this */ +#include "wct4xxp/wct4xxp.h" /* For certain definitions */ + +#define WC_MAX_CARDS 32 + +/* +#define TEST_REGS +*/ + +/* Define to get more attention-grabbing but slightly more I/O using + alarm status */ +#define FANCY_ALARM + +/* Define to enable the V2.1 errata register settings */ +#if 0 +#define TRUST_INFINEON_ERRATA +#endif + +#define DELAY 0x0 /* 30 = 15 cycles, 10 = 8 cycles, 0 = 3 cycles */ + +#define WC_CNTL 0x00 +#define WC_OPER 0x01 +#define WC_AUXC 0x02 +#define WC_AUXD 0x03 +#define WC_MASK0 0x04 +#define WC_MASK1 0x05 +#define WC_INTSTAT 0x06 + +#define WC_DMAWS 0x08 +#define WC_DMAWI 0x0c +#define WC_DMAWE 0x10 +#define WC_DMARS 0x18 +#define WC_DMARI 0x1c +#define WC_DMARE 0x20 +#define WC_CURPOS 0x24 + +#define WC_SERC 0x2d +#define WC_FSCDELAY 0x2f + +#define WC_USERREG 0xc0 + +#define WC_CLOCK 0x0 +#define WC_LEDTEST 0x1 +#define WC_VERSION 0x2 + +/* Offset between transmit and receive */ +#define WC_OFFSET 4 + +#define BIT_CS (1 << 7) +#define BIT_ADDR (0xf << 3) + +#define BIT_LED1 (1 << 0) +#define BIT_LED0 (1 << 1) +#define BIT_TEST (1 << 2) + +#define FLAG_STARTED (1 << 0) +#define FLAG_NMF (1 << 1) +#define FLAG_SENDINGYELLOW (1 << 2) +#define FLAG_FALC12 (1 << 3) + +#define TYPE_T1 1 /* is a T1 card */ +#define TYPE_E1 2 /* is an E1 card */ + +static int chanmap_t1[] = +{ 2,1,0, + 6,5,4, + 10,9,8, + 14,13,12, + 18,17,16, + 22,21,20, + 26,25,24, + 30,29,28 }; + +static int chanmap_e1[] = +{ 2,1,0, + 7,6,5,4, + 11,10,9,8, + 15,14,13,12, + 19,18,17,16, + 23,22,21,20, + 27,26,25,24, + 31,30,29,28 }; + +static int chanmap_e1uc[] = +{ 3,2,1,0, + 7,6,5,4, + 11,10,9,8, + 15,14,13,12, + 19,18,17,16, + 23,22,21,20, + 27,26,25,24, + 31,30,29,28 }; + + +#ifdef FANCY_ALARM +static int altab[] = { +0, 0, 0, 1, 2, 3, 4, 6, 8, 9, 11, 13, 16, 18, 20, 22, 24, 25, 27, 28, 29, 30, 31, 31, 32, 31, 31, 30, 29, 28, 27, 25, 23, 22, 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0, +}; +#endif + +struct t1 { + struct pci_dev *dev; + spinlock_t lock; + int spantype; + int spanflags; /* Span flags */ + unsigned char txsigs[16]; /* Copy of tx sig registers */ + int num; + int alarmcount; /* How much red alarm we've seen */ + int alarmdebounce; + /* Our offset for finding channel 1 */ + int offset; + char *variety; + unsigned int intcount; + int usecount; + int clocktimeout; + int sync; + int dead; + int blinktimer; + int alarmtimer; + int checktiming; /* Set >0 to cause the timing source to be checked */ + int loopupcnt; + int loopdowncnt; + int miss; + int misslast; + int *chanmap; +#ifdef FANCY_ALARM + int alarmpos; +#endif + unsigned char ledtestreg; + unsigned char outbyte; + unsigned long ioaddr; + unsigned short canary; + /* T1 signalling */ + dma_addr_t readdma; + dma_addr_t writedma; + volatile unsigned char *writechunk; /* Double-word aligned write memory */ + volatile unsigned char *readchunk; /* Double-word aligned read memory */ + unsigned char ec_chunk1[32][ZT_CHUNKSIZE]; + unsigned char ec_chunk2[32][ZT_CHUNKSIZE]; + unsigned char tempo[33]; + struct zt_span span; /* Span */ + struct zt_chan chans[32]; /* Channels */ +}; + +#define CANARY 0xca1e + +static int debug = 0; /* doesnt do anything */ +static int j1mode = 0; +static int alarmdebounce = 0; +static int loopback = 0; +static int clockextra = 0; +static int t1e1override = -1; +static int unchannelized = 0; + +static struct t1 *cards[WC_MAX_CARDS]; + +static inline void start_alarm(struct t1 *wc) +{ +#ifdef FANCY_ALARM + wc->alarmpos = 0; +#endif + wc->blinktimer = 0; +} + +static inline void stop_alarm(struct t1 *wc) +{ +#ifdef FANCY_ALARM + wc->alarmpos = 0; +#endif + wc->blinktimer = 0; +} + +static inline void __select_framer(struct t1 *wc, int reg) +{ + /* Top four bits of address from AUX 6-3 */ + wc->outbyte &= ~BIT_CS; + wc->outbyte &= ~BIT_ADDR; + wc->outbyte |= (reg & 0xf0) >> 1; + outb(wc->outbyte, wc->ioaddr + WC_AUXD); +} + +static inline void __select_control(struct t1 *wc) +{ + if (!(wc->outbyte & BIT_CS)) { + wc->outbyte |= BIT_CS; + outb(wc->outbyte, wc->ioaddr + WC_AUXD); + } +} + +static int t1xxp_open(struct zt_chan *chan) +{ + struct t1 *wc = chan->pvt; + if (wc->dead) + return -ENODEV; + wc->usecount++; +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#else + try_module_get(THIS_MODULE); +#endif + return 0; +} + +static int __control_set_reg(struct t1 *wc, int reg, unsigned char val) +{ + __select_control(wc); + outb(val, wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2)); + return 0; +} + +static int control_set_reg(struct t1 *wc, int reg, unsigned char val) +{ + unsigned long flags; + int res; + spin_lock_irqsave(&wc->lock, flags); + res = __control_set_reg(wc, reg, val); + spin_unlock_irqrestore(&wc->lock, flags); + return res; +} + +static int __control_get_reg(struct t1 *wc, int reg) +{ + unsigned char res; + /* The following makes UTTERLY no sense, but what was happening + was that reads in some cases were not actually happening + on the physical bus. Why, we dunno. But in debugging, we found + that writing before reading (in this case to an unused position) + seems to get rid of the problem */ + __control_set_reg(wc,3,0x69); /* do magic here */ + /* now get the read byte from the Xilinx part */ + res = inb(wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2)); + return res; +} + +static int control_get_reg(struct t1 *wc, int reg) +{ + unsigned long flags; + int res; + spin_lock_irqsave(&wc->lock, flags); + res = __control_get_reg(wc, reg); + spin_unlock_irqrestore(&wc->lock, flags); + return res; +} + +static inline unsigned int __t1_framer_in(struct t1 *wc, const unsigned int reg) +{ + unsigned char res; + __select_framer(wc, reg); + /* Get value */ + res = inb(wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2)); + return res; +#if 0 + unsigned int ret; + __t1_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); + __t1_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | ( 1 << 10) | WC_LREAD); + ret = __t1_pci_in(wc, WC_LDATA); + __t1_pci_out(wc, WC_LADDR, 0); + return ret & 0xff; +#endif +} + +static inline unsigned int t1_framer_in(struct t1 *wc, const unsigned int addr) +{ + unsigned long flags; + unsigned int ret; + spin_lock_irqsave(&wc->lock, flags); + ret = __t1_framer_in(wc, addr); + spin_unlock_irqrestore(&wc->lock, flags); + return ret; + +} + +static inline void __t1_framer_out(struct t1 *wc, const unsigned int reg, const unsigned int val) +{ + if (debug > 1) + printk("Writing %02x to address %02x\n", val, reg); + __select_framer(wc, reg); + /* Send address */ + outb(val, wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2)); +#if 0 + __t1_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); + __t1_pci_out(wc, WC_LDATA, value); + __t1_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | (1 << 10)); + __t1_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | (1 << 10) | WC_LWRITE); + __t1_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | (1 << 10)); + __t1_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); + __t1_pci_out(wc, WC_LADDR, 0); + if (debug) printk("Write complete\n"); +#endif +#if 0 + { unsigned int tmp; + tmp = t1_framer_in(wc, unit, addr); + if (tmp != value) { + printk("Expected %d from unit %d register %d but got %d instead\n", value, unit, addr, tmp); + } } +#endif +} + +static inline void t1_framer_out(struct t1 *wc, const unsigned int addr, const unsigned int value) +{ + unsigned long flags; + spin_lock_irqsave(&wc->lock, flags); + __t1_framer_out(wc, addr, value); + spin_unlock_irqrestore(&wc->lock, flags); +} + +static void t1xxp_release(struct t1 *wc) +{ + zt_unregister(&wc->span); + kfree(wc); + printk("Freed a Wildcard\n"); +} + +static int t1xxp_close(struct zt_chan *chan) +{ + struct t1 *wc = chan->pvt; + wc->usecount--; +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#else + module_put(THIS_MODULE); +#endif + /* If we're dead, release us now */ + if (!wc->usecount && wc->dead) + t1xxp_release(wc); + return 0; +} + +static void t1xxp_enable_interrupts(struct t1 *wc) +{ + /* Clear interrupts */ + outb(0xff, wc->ioaddr + WC_INTSTAT); + /* Enable interrupts (we care about all of them) */ + outb(0x3c /* 0x3f */, wc->ioaddr + WC_MASK0); + /* No external interrupts */ + outb(0x00, wc->ioaddr + WC_MASK1); + if (debug) printk("Enabled interrupts!\n"); +} + +static void t1xxp_start_dma(struct t1 *wc) +{ + /* Reset Master and TDM */ + outb(DELAY | 0x0f, wc->ioaddr + WC_CNTL); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + outb(DELAY | 0x01, wc->ioaddr + WC_CNTL); + outb(0x01, wc->ioaddr + WC_OPER); + if (debug) printk("Started DMA\n"); + outb(0x03, wc->ioaddr + WC_OPER); + outb(0x01, wc->ioaddr + WC_OPER); +} + +static void __t1xxp_stop_dma(struct t1 *wc) +{ + outb(0x00, wc->ioaddr + WC_OPER); +} + +static void __t1xxp_disable_interrupts(struct t1 *wc) +{ + outb(0x00, wc->ioaddr + WC_MASK0); + outb(0x00, wc->ioaddr + WC_MASK1); +} + +static void __t1xxp_set_clear(struct t1 *wc) +{ + int i,j; + unsigned short val=0; + for (i=0;i<24;i++) { + j = (i/8); + if (wc->span.chans[i].flags & ZT_FLAG_CLEAR) + val |= 1 << (7 - (i % 8)); + if ((i % 8)==7) { + if (debug > 1) + printk("Putting %d in register %02x\n", + val, 0x2f + j); + __t1_framer_out(wc, 0x2f + j, val); + val = 0; + } + } +} + +static int t1xxp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) +{ + struct t4_regs regs; + int x; + struct t1 *wc; + switch(cmd) { + case WCT4_GET_REGS: + wc = chan->pvt; + for (x=0;xioaddr + (x << 2))) | + (inb(wc->ioaddr + (x << 2) + 1) << 8) | + (inb(wc->ioaddr + (x << 2) + 2) << 16) | + (inb(wc->ioaddr + (x << 2) + 3) << 24); +#else + regs.pci[x] = (inb(wc->ioaddr + x)); +#endif + + for (x=0;xpvt; + + if (wc->spantype == TYPE_E1) { + switch(cmd) { + case ZT_MAINT_NONE: + printk("XXX Turn off local and remote loops E1 XXX\n"); + break; + case ZT_MAINT_LOCALLOOP: + printk("XXX Turn on local loopback E1 XXX\n"); + break; + case ZT_MAINT_REMOTELOOP: + printk("XXX Turn on remote loopback E1 XXX\n"); + break; + case ZT_MAINT_LOOPUP: + printk("XXX Send loopup code E1 XXX\n"); + break; + case ZT_MAINT_LOOPDOWN: + printk("XXX Send loopdown code E1 XXX\n"); + break; + case ZT_MAINT_LOOPSTOP: + printk("XXX Stop sending loop codes E1 XXX\n"); + break; + default: + printk("TE110P: Unknown E1 maint command: %d\n", cmd); + break; + } + } else { + switch(cmd) { + case ZT_MAINT_NONE: + printk("XXX Turn off local and remote loops T1 XXX\n"); + break; + case ZT_MAINT_LOCALLOOP: + printk("XXX Turn on local loop and no remote loop XXX\n"); + break; + case ZT_MAINT_REMOTELOOP: + printk("XXX Turn on remote loopup XXX\n"); + break; + case ZT_MAINT_LOOPUP: + t1_framer_out(wc, 0x21, 0x50); /* FMR5: Nothing but RBS mode */ + break; + case ZT_MAINT_LOOPDOWN: + t1_framer_out(wc, 0x21, 0x60); /* FMR5: Nothing but RBS mode */ + break; + case ZT_MAINT_LOOPSTOP: + t1_framer_out(wc, 0x21, 0x40); /* FMR5: Nothing but RBS mode */ + break; + default: + printk("TE110P: Unknown T1 maint command: %d\n", cmd); + break; + } + } + return 0; +} + +static int t1xxp_rbsbits(struct zt_chan *chan, int bits) +{ + u_char m,c; + int n,b; + struct t1 *wc = chan->pvt; + unsigned long flags; + + if(debug > 1) printk("Setting bits to %d on channel %s\n", bits, chan->name); + spin_lock_irqsave(&wc->lock, flags); + if (wc->spantype == TYPE_E1) { /* do it E1 way */ + if (chan->chanpos == 16) { + spin_unlock_irqrestore(&wc->lock, flags); + return 0; + } + n = chan->chanpos - 1; + if (chan->chanpos > 15) n--; + b = (n % 15); + c = wc->txsigs[b]; + m = (n / 15) << 2; /* nibble selector */ + c &= (0xf << m); /* keep the other nibble */ + c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ + wc->txsigs[b] = c; + /* output them to the chip */ + __t1_framer_out(wc,0x71 + b,c); + } else if (wc->span.lineconfig & ZT_CONFIG_D4) { + n = chan->chanpos - 1; + b = (n/4); + c = wc->txsigs[b]; + m = ((3 - (n % 4)) << 1); /* nibble selector */ + c &= ~(0x3 << m); /* keep the other nibble */ + c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */ + wc->txsigs[b] = c; + /* output them to the chip */ + __t1_framer_out(wc,0x70 + b,c); + __t1_framer_out(wc,0x70 + b + 6,c); + } else if (wc->span.lineconfig & ZT_CONFIG_ESF) { + n = chan->chanpos - 1; + b = (n/2); + c = wc->txsigs[b]; + m = ((n % 2) << 2); /* nibble selector */ + c &= (0xf << m); /* keep the other nibble */ + c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ + wc->txsigs[b] = c; + /* output them to the chip */ + __t1_framer_out(wc,0x70 + b,c); + } + spin_unlock_irqrestore(&wc->lock, flags); + if (debug > 1) + printk("Finished setting RBS bits\n"); + return 0; +} + +static void t1_check_sigbits(struct t1 *wc) +{ + int a,i,rxs; + unsigned long flags; + + if (!(wc->span.flags & ZT_FLAG_RUNNING)) + return; + + spin_lock_irqsave(&wc->lock, flags); + + if (wc->spantype == TYPE_E1) { + for (i = 0; i < 15; i++) { + a = __t1_framer_in(wc, 0x71 + i); + /* Get high channel in low bits */ + rxs = (a & 0xf); + if (!(wc->span.chans[i+16].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i+16].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); + zt_rbsbits(&wc->span.chans[i+16], rxs); + spin_lock_irqsave(&wc->lock, flags); + } + } + rxs = (a >> 4) & 0xf; + if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); + zt_rbsbits(&wc->span.chans[i], rxs); + spin_lock_irqsave(&wc->lock, flags); + } + } + } + } else if (wc->span.lineconfig & ZT_CONFIG_D4) { + for (i = 0; i < 24; i+=4) { + a = __t1_framer_in(wc, 0x70 + (i>>2)); + /* Get high channel in low bits */ + rxs = (a & 0x3) << 2; + if (!(wc->span.chans[i+3].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i+3].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); + zt_rbsbits(&wc->span.chans[i+3], rxs); + spin_lock_irqsave(&wc->lock, flags); + } + } + rxs = (a & 0xc); + if (!(wc->span.chans[i+2].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i+2].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); + zt_rbsbits(&wc->span.chans[i+2], rxs); + spin_lock_irqsave(&wc->lock, flags); + } + } + rxs = (a >> 2) & 0xc; + if (!(wc->span.chans[i+1].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i+1].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); + zt_rbsbits(&wc->span.chans[i+1], rxs); + spin_lock_irqsave(&wc->lock, flags); + } + } + rxs = (a >> 4) & 0xc; + if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); + zt_rbsbits(&wc->span.chans[i], rxs); + spin_lock_irqsave(&wc->lock, flags); + } + } + } + } else { + for (i = 0; i < 24; i+=2) { + a = __t1_framer_in(wc, 0x70 + (i>>1)); + /* Get high channel in low bits */ + rxs = (a & 0xf); + if (!(wc->span.chans[i+1].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i+1].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); + zt_rbsbits(&wc->span.chans[i+1], rxs); + spin_lock_irqsave(&wc->lock, flags); + } + } + rxs = (a >> 4) & 0xf; + if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i].rxsig != rxs) { + spin_unlock_irqrestore(&wc->lock, flags); + zt_rbsbits(&wc->span.chans[i], rxs); + spin_lock_irqsave(&wc->lock, flags); + } + } + } + } + spin_unlock_irqrestore(&wc->lock, flags); +} + +static void t4_serial_setup(struct t1 *wc) +{ + printk("TE110P: Setting up global serial parameters for %s %s\n", + wc->spantype == TYPE_E1 ? (unchannelized ? "Unchannelized E1" : "E1") : "T1", + wc->spanflags & FLAG_FALC12 ? "FALC V1.2" : "FALC V2.2"); + t1_framer_out(wc, 0x85, 0xe0); /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0 */ + t1_framer_out(wc, 0x08, 0x05); /* IPC: Interrupt push/pull active low */ + if (wc->spanflags & FLAG_FALC12) { + t1_framer_out(wc, 0x92, 0x00); + t1_framer_out(wc, 0x93, 0x58); + t1_framer_out(wc, 0x94, 0xd2); + t1_framer_out(wc, 0x95, 0xc2); + t1_framer_out(wc, 0x96, 0x03); + t1_framer_out(wc, 0x97, 0x10); + } else { + /* Global clocks (8.192 Mhz CLK) */ + t1_framer_out(wc, 0x92, 0x00); + t1_framer_out(wc, 0x93, 0x18); + t1_framer_out(wc, 0x94, 0xfb); + t1_framer_out(wc, 0x95, 0x0b); + t1_framer_out(wc, 0x96, 0x00); + t1_framer_out(wc, 0x97, 0x0b); + t1_framer_out(wc, 0x98, 0xdb); + t1_framer_out(wc, 0x99, 0xdf); + } + /* Configure interrupts */ + t1_framer_out(wc, 0x46, 0x40); /* GCR: Interrupt on Activation/Deactivation of AIX, LOS */ + + /* Configure system interface */ + t1_framer_out(wc, 0x3e, 0x02); /* SIC1: 4.096 Mhz clock/bus, double buffer receive / transmit, byte interleaved */ + t1_framer_out(wc, 0x3f, 0x00); /* SIC2: No FFS, no center receive eliastic buffer, phase 0 */ + t1_framer_out(wc, 0x40, 0x04); /* SIC3: Edges for capture */ + t1_framer_out(wc, 0x44, 0x30); /* CMR1: RCLK is at 8.192 Mhz dejittered */ + t1_framer_out(wc, 0x45, 0x00); /* CMR2: We provide sync and clock for tx and rx. */ + t1_framer_out(wc, 0x22, 0x00); /* XC0: Normal operation of Sa-bits */ + t1_framer_out(wc, 0x23, 0x04); /* XC1: 0 offset */ + t1_framer_out(wc, 0x24, 0x07); /* RC0: Just shy of 255 */ + if (wc->spanflags & FLAG_FALC12) + t1_framer_out(wc, 0x25, 0x04); /* RC1: The rest of RC0 */ + else + t1_framer_out(wc, 0x25, 0x05); /* RC1: The rest of RC0 */ + + /* Configure ports */ + t1_framer_out(wc, 0x80, 0x00); /* PC1: SPYR/SPYX input on RPA/XPA */ + t1_framer_out(wc, 0x81, 0x22); /* PC2: RMFB/XSIG output/input on RPB/XPB */ + t1_framer_out(wc, 0x82, 0x65); /* PC3: Some unused stuff */ + t1_framer_out(wc, 0x83, 0x35); /* PC4: Some more unused stuff */ + t1_framer_out(wc, 0x84, 0x31); /* PC5: XMFS active low, SCLKR is input, RCLK is output */ + t1_framer_out(wc, 0x86, 0x03); /* PC6: CLK1 is Tx Clock output, CLK2 is 8.192 Mhz from DCO-R */ + t1_framer_out(wc, 0x3b, 0x00); /* Clear LCR1 */ + printk("TE110P: Successfully initialized serial bus for card\n"); +} + +static void __t1_configure_t1(struct t1 *wc, int lineconfig, int txlevel) +{ + unsigned int fmr4, fmr2, fmr1, fmr0, lim2; + char *framing, *line; + int mytxlevel; + if ((txlevel > 7) || (txlevel < 4)) + mytxlevel = 0; + else + mytxlevel = txlevel - 4; + fmr1 = 0x1c; /* FMR1: Mode 0, T1 mode, CRC on for ESF, 2.048 Mhz system data rate, no XAIS */ + fmr2 = 0x22; /* FMR2: no payload loopback, auto send yellow alarm */ + if (loopback) + fmr2 |= 0x4; + + if (j1mode) + fmr4 = 0x1c; + else + fmr4 = 0x0c; /* FMR4: Lose sync on 2 out of 5 framing bits, auto resync */ + + + lim2 = 0x21; /* LIM2: 50% peak is a "1", Advanced Loss recovery */ + lim2 |= (mytxlevel << 6); /* LIM2: Add line buildout */ + __t1_framer_out(wc, 0x1d, fmr1); + __t1_framer_out(wc, 0x1e, fmr2); + + /* Configure line interface */ + if (lineconfig & ZT_CONFIG_AMI) { + line = "AMI"; + fmr0 = 0xa0; + } else { + line = "B8ZS"; + fmr0 = 0xf0; + } + if (lineconfig & ZT_CONFIG_D4) { + framing = "D4"; + } else { + framing = "ESF"; + fmr4 |= 0x2; + fmr2 |= 0xc0; + } + __t1_framer_out(wc, 0x1c, fmr0); + + __t1_framer_out(wc, 0x20, fmr4); + __t1_framer_out(wc, 0x21, 0x40); /* FMR5: Enable RBS mode */ + + __t1_framer_out(wc, 0x37, 0xf8); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ + __t1_framer_out(wc, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ + + __t1_framer_out(wc, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ + __t1_framer_out(wc, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ + + __t1_framer_out(wc, 0x3a, lim2); /* LIM2: 50% peak amplitude is a "1" */ + __t1_framer_out(wc, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ + __t1_framer_out(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ + + if (j1mode) + __t1_framer_out(wc, 0x24, 0x80); /* J1 overide */ + + /* Generate pulse mask for T1 */ + switch(mytxlevel) { + case 3: + __t1_framer_out(wc, 0x26, 0x07); /* XPM0 */ + __t1_framer_out(wc, 0x27, 0x01); /* XPM1 */ + __t1_framer_out(wc, 0x28, 0x00); /* XPM2 */ + break; + case 2: + __t1_framer_out(wc, 0x26, 0x8c); /* XPM0 */ + __t1_framer_out(wc, 0x27, 0x11); /* XPM1 */ + __t1_framer_out(wc, 0x28, 0x01); /* XPM2 */ + break; + case 1: + __t1_framer_out(wc, 0x26, 0x8c); /* XPM0 */ + __t1_framer_out(wc, 0x27, 0x01); /* XPM1 */ + __t1_framer_out(wc, 0x28, 0x00); /* XPM2 */ + break; + case 0: + default: + __t1_framer_out(wc, 0x26, 0xd7); /* XPM0 */ + __t1_framer_out(wc, 0x27, 0x22); /* XPM1 */ + __t1_framer_out(wc, 0x28, 0x01); /* XPM2 */ + break; + } + printk("TE110P: Span configured for %s/%s\n", framing, line); +} + +static void __t1_configure_e1(struct t1 *wc, int lineconfig) +{ + unsigned int fmr2, fmr1, fmr0; + unsigned int cas = 0; + char *crc4 = ""; + char *framing, *line; + fmr1 = 0x44; /* FMR1: E1 mode, Automatic force resync, PCM30 mode, 8.192 Mhz backplane, no XAIS */ + fmr2 = 0x03; /* FMR2: Auto transmit remote alarm, auto loss of multiframe recovery, no payload loopback */ + if (unchannelized) + fmr2 |= 0x30; + if (loopback) + fmr2 |= 0x4; + if (lineconfig & ZT_CONFIG_CRC4) { + fmr1 |= 0x08; /* CRC4 transmit */ + fmr2 |= 0xc0; /* CRC4 receive */ + crc4 = "/CRC4"; + } + __t1_framer_out(wc, 0x1d, fmr1); + __t1_framer_out(wc, 0x1e, fmr2); + + /* Configure line interface */ + if (lineconfig & ZT_CONFIG_AMI) { + line = "AMI"; + fmr0 = 0xa0; + } else { + line = "HDB3"; + fmr0 = 0xf0; + } + if (lineconfig & ZT_CONFIG_CCS) { + framing = "CCS"; + } else { + framing = "CAS"; + cas = 0x40; + } + __t1_framer_out(wc, 0x1c, fmr0); + + if (unchannelized) + __t1_framer_out(wc, 0x1f, 0x40); + + __t1_framer_out(wc, 0x37, 0xf0 /*| 0x6 */ ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ + __t1_framer_out(wc, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ + + __t1_framer_out(wc, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ + __t1_framer_out(wc, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ + + /* Condition receive line interface for E1 after reset */ + __t1_framer_out(wc, 0xbb, 0x17); + __t1_framer_out(wc, 0xbc, 0x55); + __t1_framer_out(wc, 0xbb, 0x97); + __t1_framer_out(wc, 0xbb, 0x11); + __t1_framer_out(wc, 0xbc, 0xaa); + __t1_framer_out(wc, 0xbb, 0x91); + __t1_framer_out(wc, 0xbb, 0x12); + __t1_framer_out(wc, 0xbc, 0x55); + __t1_framer_out(wc, 0xbb, 0x92); + __t1_framer_out(wc, 0xbb, 0x0c); + __t1_framer_out(wc, 0xbb, 0x00); + __t1_framer_out(wc, 0xbb, 0x8c); + + __t1_framer_out(wc, 0x3a, 0x20); /* LIM2: 50% peak amplitude is a "1" */ + __t1_framer_out(wc, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ + __t1_framer_out(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ + + __t1_framer_out(wc, 0x20, 0x9f); /* XSW: Spare bits all to 1 */ + if (unchannelized) + __t1_framer_out(wc, 0x21, 0x3c); + else + __t1_framer_out(wc, 0x21, 0x1c|cas); /* XSP: E-bit set when async. AXS auto, XSIF to 1 */ + + + /* Generate pulse mask for E1 */ + __t1_framer_out(wc, 0x26, 0x54); /* XPM0 */ + __t1_framer_out(wc, 0x27, 0x02); /* XPM1 */ + __t1_framer_out(wc, 0x28, 0x00); /* XPM2 */ + printk("TE110P: Span configured for %s/%s%s\n", framing, line, crc4); +} + +static void t1xxp_framer_start(struct t1 *wc, struct zt_span *span) +{ + int alreadyrunning = wc->span.flags & ZT_FLAG_RUNNING; + unsigned long flags; + + spin_lock_irqsave(&wc->lock, flags); + + if (wc->spantype == TYPE_E1) { /* if this is an E1 card */ + __t1_configure_e1(wc, span->lineconfig); + } else { /* is a T1 card */ + __t1_configure_t1(wc, span->lineconfig, span->txlevel); + __t1xxp_set_clear(wc); + } + + if (!alreadyrunning) + wc->span.flags |= ZT_FLAG_RUNNING; + + spin_unlock_irqrestore(&wc->lock, flags); +} + + +static int t1xxp_startup(struct zt_span *span) +{ + struct t1 *wc = span->pvt; + + int i,alreadyrunning = span->flags & ZT_FLAG_RUNNING; + + /* initialize the start value for the entire chunk of last ec buffer */ + for(i = 0; i < span->channels; i++) + { + memset(wc->ec_chunk1[i], + ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); + memset(wc->ec_chunk2[i], + ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); + } + + /* Reset framer with proper parameters and start */ + t1xxp_framer_start(wc, span); + printk("Calling startup (flags is %d)\n", span->flags); + + if (!alreadyrunning) { + /* Only if we're not already going */ + t1xxp_enable_interrupts(wc); + t1xxp_start_dma(wc); + span->flags |= ZT_FLAG_RUNNING; + } + return 0; +} + +static int t1xxp_shutdown(struct zt_span *span) +{ + struct t1 *wc = span->pvt; + unsigned long flags; + + spin_lock_irqsave(&wc->lock, flags); + __t1_framer_out(wc, 0x46, 0x41); /* GCR: Interrupt on Activation/Deactivation of AIX, LOS */ + __t1xxp_stop_dma(wc); + __t1xxp_disable_interrupts(wc); + span->flags &= ~ZT_FLAG_RUNNING; + spin_unlock_irqrestore(&wc->lock, flags); + return 0; +} + + +static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype) +{ + struct t1 *wc = chan->pvt; + unsigned long flags; + int alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING; + + spin_lock_irqsave(&wc->lock, flags); + + if (alreadyrunning && (wc->spantype != TYPE_E1)) + __t1xxp_set_clear(wc); + + spin_unlock_irqrestore(&wc->lock, flags); + return 0; +} + +static int t1xxp_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) +{ + struct t1 *wc = span->pvt; + + /* Do we want to SYNC on receive or not */ + wc->sync = lc->sync; + /* If already running, apply changes immediately */ + if (span->flags & ZT_FLAG_RUNNING) + return t1xxp_startup(span); + + return 0; +} + +static int t1xxp_software_init(struct t1 *wc) +{ + int x; + /* Find position */ + for (x=0;x= WC_MAX_CARDS) + return -1; + t4_serial_setup(wc); + wc->num = x; + sprintf(wc->span.name, "WCT1/%d", wc->num); + snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num); + wc->span.manufacturer = "Digium"; + strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); + snprintf(wc->span.location, sizeof(wc->span.location) - 1, + "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); + wc->span.spanconfig = t1xxp_spanconfig; + wc->span.chanconfig = t1xxp_chanconfig; + wc->span.irq = wc->dev->irq; + wc->span.startup = t1xxp_startup; + wc->span.shutdown = t1xxp_shutdown; + wc->span.rbsbits = t1xxp_rbsbits; + wc->span.maint = t1xxp_maint; + wc->span.open = t1xxp_open; + wc->span.close = t1xxp_close; + if (wc->spantype == TYPE_E1) { + if (unchannelized) + wc->span.channels = 32; + else + wc->span.channels = 31; + wc->span.deflaw = ZT_LAW_ALAW; + wc->span.spantype = "E1"; + wc->span.linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4; + } else { + wc->span.channels = 24; + wc->span.deflaw = ZT_LAW_MULAW; + wc->span.spantype = "T1"; + wc->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; + } + wc->span.chans = wc->chans; + wc->span.flags = ZT_FLAG_RBS; + wc->span.ioctl = t1xxp_ioctl; + wc->span.pvt = wc; + init_waitqueue_head(&wc->span.maintq); + for (x=0;xspan.channels;x++) { + sprintf(wc->chans[x].name, "WCT1/%d/%d", wc->num, x + 1); + wc->chans[x].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_EM_E1 | + ZT_SIG_FXSLS | ZT_SIG_FXSGS | + ZT_SIG_FXSKS | ZT_SIG_FXOLS | ZT_SIG_DACS_RBS | + ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF; + wc->chans[x].pvt = wc; + wc->chans[x].chanpos = x + 1; + } + if (zt_register(&wc->span, 0)) { + printk("Unable to register span with zaptel\n"); + return -1; + } + return 0; +} + +static inline void __handle_leds(struct t1 *wc) +{ + int oldreg; + + if (wc->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) { + /* Red/Blue alarm */ + wc->blinktimer++; +#ifdef FANCY_ALARM + if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) { + wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0; + __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); + } + if (wc->blinktimer >= 0xf) { + wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1); + __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); + wc->blinktimer = -1; + wc->alarmpos++; + if (wc->alarmpos >= (sizeof(altab) / sizeof(altab[0]))) + wc->alarmpos = 0; + } +#else + if (wc->blinktimer == 160) { + wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0; + __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); + } else if (wc->blinktimer == 480) { + wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1); + __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); + wc->blinktimer = 0; + } +#endif + } else if (wc->span.alarms & ZT_ALARM_YELLOW) { + /* Yellow Alarm */ + if (!(wc->blinktimer % 2)) + wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0; + else + wc->ledtestreg = (wc->ledtestreg | BIT_LED0) & ~BIT_LED1; + __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); + } else { + /* No Alarm */ + oldreg = wc->ledtestreg; + if (wc->span.maintstat != ZT_MAINT_NONE) + wc->ledtestreg |= BIT_TEST; + else + wc->ledtestreg &= ~BIT_TEST; + if (wc->span.flags & ZT_FLAG_RUNNING) + wc->ledtestreg = (wc->ledtestreg | BIT_LED0) & ~BIT_LED1; + else + wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1); + if (oldreg != wc->ledtestreg) + __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); + } +} + +static void t1xxp_transmitprep(struct t1 *wc, int ints) +{ + volatile unsigned char *txbuf; + int x,y; + int pos; + if (ints & 0x04 /* 0x01 */) { + /* We just finished sending the first buffer, start filling it + now */ + txbuf = wc->writechunk; + } else { + /* Just finished sending second buffer, fill it now */ + txbuf = wc->writechunk + 32 * ZT_CHUNKSIZE; + } + zt_transmit(&wc->span); + for (x=0;xoffset;x++) + txbuf[x] = wc->tempo[x]; + for (y=0;yspan.channels;x++) { + pos = y * 32 + wc->chanmap[x] + wc->offset; + /* Put channel number as outgoing data */ + if (pos < 32 * ZT_CHUNKSIZE) + txbuf[pos] = wc->chans[x].writechunk[y]; + else + wc->tempo[pos - 32 * ZT_CHUNKSIZE] = wc->chans[x].writechunk[y]; + } + } +} + +static void t1xxp_receiveprep(struct t1 *wc, int ints) +{ + volatile unsigned char *rxbuf; + volatile unsigned int *canary; + int x; + int y; + unsigned int oldcan; + if (ints & 0x04) { + /* Just received first buffer */ + rxbuf = wc->readchunk; + canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 64 - 4); + } else { + rxbuf = wc->readchunk + ZT_CHUNKSIZE * 32; + canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 32 - 4); + } + oldcan = *canary; + if (((oldcan & 0xffff0000) >> 16) != CANARY) { + /* Check top part */ + if (debug) printk("Expecting top %04x, got %04x\n", CANARY, (oldcan & 0xffff0000) >> 16); + wc->span.irqmisses++; + } else if ((oldcan & 0xffff) != ((wc->canary - 1) & 0xffff)) { + if (debug) printk("Expecting bottom %d, got %d\n", wc->canary - 1, oldcan & 0xffff); + wc->span.irqmisses++; + } + for (y=0;yspan.channels;x++) { + /* XXX Optimize, remove * and + XXX */ + /* Must map received channels into appropriate data */ + wc->chans[x].readchunk[y] = + rxbuf[32 * y + ((wc->chanmap[x] + WC_OFFSET + wc->offset) & 0x1f)]; + } + if (wc->spantype != TYPE_E1) { + for (x=3;x<32;x+=4) { + if (rxbuf[32 * y + ((x + WC_OFFSET) & 0x1f)] == 0x7f) { + if (wc->offset != (x-3)) { + /* Resync */ + control_set_reg(wc, WC_CLOCK, 0x06 | wc->sync | clockextra); + wc->clocktimeout = 100; +#if 1 + if (debug) printk("T1: Lost our place, resyncing\n"); +#endif + } + } + } + } else if (!unchannelized) { + if (!wc->clocktimeout && !wc->span.alarms) { + if ((rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)] & 0x7f) != 0x1b) { + if (wc->miss) { + if (debug) printk("Double miss (%d, %d)...\n", wc->misslast, rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)]); + control_set_reg(wc, WC_CLOCK, 0x06 | wc->sync | clockextra); + wc->clocktimeout = 100; + } else { + wc->miss = 1; + wc->misslast = rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)]; + } + } else { + wc->miss = 0; + } + } else { + wc->miss = 0; + } + } + } + /* Store the next canary */ + canary = (unsigned int *)(rxbuf + ZT_CHUNKSIZE * 32 - 4); + *canary = (wc->canary++) | (CANARY << 16); + for (x=0;xspan.channels;x++) { + zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, + wc->ec_chunk2[x]); + memcpy(wc->ec_chunk2[x],wc->ec_chunk1[x],ZT_CHUNKSIZE); + memcpy(wc->ec_chunk1[x],wc->chans[x].writechunk,ZT_CHUNKSIZE); + } + zt_receive(&wc->span); +} + +static void t1_check_alarms(struct t1 *wc) +{ + unsigned char c,d; + int alarms; + int x,j; + unsigned long flags; + + if (!(wc->span.flags & ZT_FLAG_RUNNING)) + return; + + spin_lock_irqsave(&wc->lock, flags); + + c = __t1_framer_in(wc, 0x4c); + if (wc->spanflags & FLAG_FALC12) + d = __t1_framer_in(wc, 0x4f); + else + d = __t1_framer_in(wc, 0x4d); + + /* Assume no alarms */ + alarms = 0; + + /* And consider only carrier alarms */ + wc->span.alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); + + if (wc->spantype == TYPE_E1) { + if (c & 0x04) { + /* No multiframe found, force RAI high after 400ms only if + we haven't found a multiframe since last loss + of frame */ + if (!(wc->spanflags & FLAG_NMF)) { + __t1_framer_out(wc, 0x20, 0x9f | 0x20); /* LIM0: Force RAI High */ + wc->spanflags |= FLAG_NMF; + printk("NMF workaround on!\n"); + } + __t1_framer_out(wc, 0x1e, 0xc3); /* Reset to CRC4 mode */ + __t1_framer_out(wc, 0x1c, 0xf2); /* Force Resync */ + __t1_framer_out(wc, 0x1c, 0xf0); /* Force Resync */ + } else if (!(c & 0x02)) { + if ((wc->spanflags & FLAG_NMF)) { + __t1_framer_out(wc, 0x20, 0x9f); /* LIM0: Clear forced RAI */ + wc->spanflags &= ~FLAG_NMF; + printk("NMF workaround off!\n"); + } + } + } else { + /* Detect loopup code if we're not sending one */ + if ((!wc->span.mainttimer) && (d & 0x08)) { + /* Loop-up code detected */ + if ((wc->loopupcnt++ > 80) && (wc->span.maintstat != ZT_MAINT_REMOTELOOP)) { + __t1_framer_out(wc, 0x36, 0x08); /* LIM0: Disable any local loop */ + __t1_framer_out(wc, 0x37, 0xf6 ); /* LIM1: Enable remote loop */ + wc->span.maintstat = ZT_MAINT_REMOTELOOP; + } + } else + wc->loopupcnt = 0; + /* Same for loopdown code */ + if ((!wc->span.mainttimer) && (d & 0x10)) { + /* Loop-down code detected */ + if ((wc->loopdowncnt++ > 80) && (wc->span.maintstat == ZT_MAINT_REMOTELOOP)) { + __t1_framer_out(wc, 0x36, 0x08); /* LIM0: Disable any local loop */ + __t1_framer_out(wc, 0x37, 0xf0 ); /* LIM1: Disable remote loop */ + wc->span.maintstat = ZT_MAINT_NONE; + } + } else + wc->loopdowncnt = 0; + } + + if (wc->span.lineconfig & ZT_CONFIG_NOTOPEN) { + for (x=0,j=0;x < wc->span.channels;x++) + if ((wc->span.chans[x].flags & ZT_FLAG_OPEN) || + (wc->span.chans[x].flags & ZT_FLAG_NETDEV)) + j++; + if (!j) + alarms |= ZT_ALARM_NOTOPEN; + } + + if (c & 0xa0) { + if (wc->alarmcount >= alarmdebounce) { + if (!unchannelized) + alarms |= ZT_ALARM_RED; + } else + wc->alarmcount++; + } else + wc->alarmcount = 0; + if (c & 0x4) + alarms |= ZT_ALARM_BLUE; + + if (((!wc->span.alarms) && alarms) || + (wc->span.alarms && (!alarms))) + wc->checktiming = 1; + + /* Keep track of recovering */ + if ((!alarms) && wc->span.alarms) + wc->alarmtimer = ZT_ALARMSETTLE_TIME; + if (wc->alarmtimer) + alarms |= ZT_ALARM_RECOVER; + + /* If receiving alarms, go into Yellow alarm state */ + if (alarms && !(wc->spanflags & FLAG_SENDINGYELLOW)) { + unsigned char fmr4; +#if 1 + printk("wcte1xxp: Setting yellow alarm\n"); +#endif + /* We manually do yellow alarm to handle RECOVER and NOTOPEN, otherwise it's auto anyway */ + fmr4 = __t1_framer_in(wc, 0x20); + __t1_framer_out(wc, 0x20, fmr4 | 0x20); + wc->spanflags |= FLAG_SENDINGYELLOW; + } else if ((!alarms) && (wc->spanflags & FLAG_SENDINGYELLOW)) { + unsigned char fmr4; +#if 1 + printk("wcte1xxp: Clearing yellow alarm\n"); +#endif + /* We manually do yellow alarm to handle RECOVER */ + fmr4 = __t1_framer_in(wc, 0x20); + __t1_framer_out(wc, 0x20, fmr4 & ~0x20); + wc->spanflags &= ~FLAG_SENDINGYELLOW; + } + + /* Re-check the timing source when we enter/leave alarm, not withstanding + yellow alarm */ + if ((c & 0x10) && !unchannelized) + alarms |= ZT_ALARM_YELLOW; + if (wc->span.mainttimer || wc->span.maintstat) + alarms |= ZT_ALARM_LOOPBACK; + wc->span.alarms = alarms; + spin_unlock_irqrestore(&wc->lock, flags); + zt_alarm_notify(&wc->span); +} + + +static void t1_do_counters(struct t1 *wc) +{ + unsigned long flags; + + spin_lock_irqsave(&wc->lock, flags); + if (wc->alarmtimer) { + if (!--wc->alarmtimer) { + wc->span.alarms &= ~(ZT_ALARM_RECOVER); + spin_unlock_irqrestore(&wc->lock, flags); + zt_alarm_notify(&wc->span); + spin_lock_irqsave(&wc->lock, flags); + } + } + spin_unlock_irqrestore(&wc->lock, flags); +} + +ZAP_IRQ_HANDLER(t1xxp_interrupt) +{ + struct t1 *wc = dev_id; + unsigned char ints; + unsigned long flags; + int x; + + ints = inb(wc->ioaddr + WC_INTSTAT); + if (!ints) +#ifdef LINUX26 + return IRQ_NONE; +#else + return; +#endif + + outb(ints, wc->ioaddr + WC_INTSTAT); + + if (!wc->intcount) { + if (debug) printk("Got interrupt: 0x%04x\n", ints); + } + wc->intcount++; + + if (wc->clocktimeout && !--wc->clocktimeout) + control_set_reg(wc, WC_CLOCK, 0x04 | wc->sync | clockextra); + + if (ints & 0x0f) { + t1xxp_receiveprep(wc, ints); + t1xxp_transmitprep(wc, ints); + } + spin_lock_irqsave(&wc->lock, flags); + +#if 1 + __handle_leds(wc); +#endif + + spin_unlock_irqrestore(&wc->lock, flags); + + /* Count down timers */ + t1_do_counters(wc); + + /* Do some things that we don't have to do very often */ + x = wc->intcount & 15 /* 63 */; + switch(x) { + case 0: + case 1: + break; + case 2: + t1_check_sigbits(wc); + break; + case 4: + /* Check alarms 1/4 as frequently */ + if (!(wc->intcount & 0x30)) + t1_check_alarms(wc); + break; + } + + if (ints & 0x10) + printk("PCI Master abort\n"); + + if (ints & 0x20) + printk("PCI Target abort\n"); + +#ifdef LINUX26 + return IRQ_RETVAL(1); +#endif +} + +static int t1xxp_hardware_init(struct t1 *wc) +{ + unsigned int falcver; + unsigned int x; + /* Hardware PCI stuff */ + /* Reset chip and registers */ + outb(DELAY | 0x0e, wc->ioaddr + WC_CNTL); + /* Set all outputs to 0 */ + outb(0x00, wc->ioaddr + WC_AUXD); + /* Set all to outputs except AUX1 (TDO). */ + outb(0xfd, wc->ioaddr + WC_AUXC); + /* Configure the serial port: double clock, 20ns width, no inversion, + MSB first */ + outb(0xc8, wc->ioaddr + WC_SERC); + + /* Internally delay FSC by one */ + outb(0x01, wc->ioaddr + WC_FSCDELAY); + + /* Back to normal, with automatic DMA wrap around */ + outb(DELAY | 0x01, wc->ioaddr + WC_CNTL); + + /* Make sure serial port and DMA are out of reset */ + outb(inb(wc->ioaddr + WC_CNTL) & 0xf9, WC_CNTL); + + /* Setup DMA Addresses */ + /* Start at writedma */ + outl(wc->writedma, wc->ioaddr + WC_DMAWS); /* Write start */ + /* First frame */ + outl(wc->writedma + ZT_CHUNKSIZE * 32 - 4, wc->ioaddr + WC_DMAWI); /* Middle (interrupt) */ + /* Second frame */ + outl(wc->writedma + ZT_CHUNKSIZE * 32 * 2 - 4, wc->ioaddr + WC_DMAWE); /* End */ + + outl(wc->readdma, wc->ioaddr + WC_DMARS); /* Read start */ + /* First frame */ + outl(wc->readdma + ZT_CHUNKSIZE * 32 - 4, wc->ioaddr + WC_DMARI); /* Middle (interrupt) */ + /* Second frame */ + outl(wc->readdma + ZT_CHUNKSIZE * 32 * 2 - 4, wc->ioaddr + WC_DMARE); /* End */ + + if (debug) printk("Setting up DMA (write/read = %08lx/%08lx)\n", (long)wc->writedma, (long)wc->readdma); + + if (t1e1override > -1) { + if (t1e1override) + wc->spantype = TYPE_E1; + else + wc->spantype = TYPE_T1; + } else { + if (control_get_reg(wc, WC_CLOCK) & 0x20) + wc->spantype = TYPE_T1; + else + wc->spantype = TYPE_E1; + } + + /* Check out the controller */ + if (debug) printk("Controller version: %02x\n", control_get_reg(wc, WC_VERSION)); + + + control_set_reg(wc, WC_LEDTEST, 0x00); + + if (wc->spantype == TYPE_E1) { + if (unchannelized) + wc->chanmap = chanmap_e1uc; + else + wc->chanmap = chanmap_e1; + } else + wc->chanmap = chanmap_t1; + /* Setup clock appropriately */ + control_set_reg(wc, WC_CLOCK, 0x06 | wc->sync | clockextra); + wc->clocktimeout = 100; + + /* Perform register test on FALC */ + for (x=0;x<256;x++) { + t1_framer_out(wc, 0x14, x); + if ((falcver = t1_framer_in(wc, 0x14)) != x) + printk("Wrote '%x' but read '%x'\n", x, falcver); + } + + t1_framer_out(wc, 0x4a, 0xaa); + falcver = t1_framer_in(wc ,0x4a); + printk("FALC version: %08x\n", falcver); + if (!falcver) + wc->spanflags |= FLAG_FALC12; + + + start_alarm(wc); + return 0; + +} + +static int __devinit t1xxp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int res; + struct t1 *wc; + unsigned int *canary; + + if (pci_enable_device(pdev)) { + res = -EIO; + } else { + wc = kmalloc(sizeof(struct t1), GFP_KERNEL); + if (wc) { + memset(wc, 0x0, sizeof(struct t1)); + spin_lock_init(&wc->lock); + wc->ioaddr = pci_resource_start(pdev, 0); + wc->dev = pdev; + wc->offset = 28; /* And you thought 42 was the answer */ + + wc->writechunk = + /* 32 channels, Double-buffer, Read/Write */ + (unsigned char *)pci_alloc_consistent(pdev, ZT_MAX_CHUNKSIZE * 32 * 2 * 2, &wc->writedma); + if (!wc->writechunk) { + printk("wcte11xp: Unable to allocate DMA-able memory\n"); + return -ENOMEM; + } + + /* Read is after the whole write piece (in bytes) */ + wc->readchunk = wc->writechunk + ZT_CHUNKSIZE * 32 * 2; + + /* Same thing... */ + wc->readdma = wc->writedma + ZT_CHUNKSIZE * 32 * 2; + + /* Initialize Write/Buffers to all blank data */ + memset((void *)wc->writechunk,0x00,ZT_MAX_CHUNKSIZE * 2 * 2 * 32); + /* Initialize canary */ + canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 64 - 4); + *canary = (CANARY << 16) | (0xffff); + + /* Enable bus mastering */ + pci_set_master(pdev); + + /* Keep track of which device we are */ + pci_set_drvdata(pdev, wc); + + if (request_irq(pdev->irq, t1xxp_interrupt, ZAP_IRQ_SHARED_DISABLED, "wcte11xp", wc)) { + printk("wcte11xp: Unable to request IRQ %d\n", pdev->irq); + kfree(wc); + return -EIO; + } + /* Initialize hardware */ + t1xxp_hardware_init(wc); + + /* We now know which version of card we have */ + wc->variety = "Digium Wildcard TE110P T1/E1"; + + /* Misc. software stuff */ + t1xxp_software_init(wc); + + printk("Found a Wildcard: %s\n", wc->variety); + res = 0; + } else + res = -ENOMEM; + } + return res; +} + +static void t1xxp_stop_stuff(struct t1 *wc) +{ + /* Kill clock */ + control_set_reg(wc, WC_CLOCK, 0); + + /* Turn off LED's */ + control_set_reg(wc, WC_LEDTEST, 0); + +} + +static void __devexit t1xxp_remove_one(struct pci_dev *pdev) +{ + struct t1 *wc = pci_get_drvdata(pdev); + if (wc) { + + /* Stop any DMA */ + __t1xxp_stop_dma(wc); + + /* In case hardware is still there */ + __t1xxp_disable_interrupts(wc); + + t1xxp_stop_stuff(wc); + + /* Immediately free resources */ + pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 32 * 4, (void *)wc->writechunk, wc->writedma); + free_irq(pdev->irq, wc); + + /* Reset PCI chip and registers */ + outb(DELAY | 0x0e, wc->ioaddr + WC_CNTL); + + /* Release span, possibly delayed */ + if (!wc->usecount) + t1xxp_release(wc); + else + wc->dead = 1; + } +} + +static struct pci_device_id t1xxp_pci_tbl[] = { + { 0xe159, 0x0001, 0x71fe, PCI_ANY_ID, 0, 0, (unsigned long) "Digium Wildcard TE110P T1/E1 Board" }, + { 0xe159, 0x0001, 0x79fe, PCI_ANY_ID, 0, 0, (unsigned long) "Digium Wildcard TE110P T1/E1 Board" }, + { 0xe159, 0x0001, 0x795e, PCI_ANY_ID, 0, 0, (unsigned long) "Digium Wildcard TE110P T1/E1 Board" }, + { 0xe159, 0x0001, 0x79de, PCI_ANY_ID, 0, 0, (unsigned long) "Digium Wildcard TE110P T1/E1 Board" }, + { 0xe159, 0x0001, 0x797e, PCI_ANY_ID, 0, 0, (unsigned long) "Digium Wildcard TE110P T1/E1 Board" }, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci,t1xxp_pci_tbl); + +static struct pci_driver t1xxp_driver = { + name: "wcte11xp", + probe: t1xxp_init_one, +#ifdef LINUX26 + remove: __devexit_p(t1xxp_remove_one), +#else + remove: t1xxp_remove_one, +#endif + suspend: NULL, + resume: NULL, + id_table: t1xxp_pci_tbl, +}; + +static int __init t1xxp_init(void) +{ + int res; + res = zap_pci_module(&t1xxp_driver); + if (res) + return -ENODEV; + return 0; +} + +static void __exit t1xxp_cleanup(void) +{ + pci_unregister_driver(&t1xxp_driver); +} + +#ifdef LINUX26 +module_param(alarmdebounce, int, 0600); +module_param(loopback, int, 0600); +module_param(t1e1override, int, 0600); +module_param(unchannelized, int, 0600); +module_param(clockextra, int, 0600); +module_param(debug, int, 0600); +module_param(j1mode, int, 0600); +#else +MODULE_PARM(alarmdebounce, "i"); +MODULE_PARM(loopback, "i"); +MODULE_PARM(t1e1override, "i"); +MODULE_PARM(unchannelized, "i"); +MODULE_PARM(clockextra, "i"); +MODULE_PARM(debug, "i"); +MODULE_PARM(j1mode, "i"); +#endif +MODULE_DESCRIPTION("Wildcard TE110P Zaptel Driver"); +MODULE_AUTHOR("Mark Spencer "); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +module_init(t1xxp_init); +module_exit(t1xxp_cleanup); diff --git a/kernel/wcte12xp/GpakApi.c b/kernel/wcte12xp/GpakApi.c new file mode 100644 index 0000000..43b844a --- /dev/null +++ b/kernel/wcte12xp/GpakApi.c @@ -0,0 +1,1613 @@ +/* + * Copyright (c) 2005, Adaptive Digital Technologies, Inc. + * + * File Name: GpakApi.c + * + * Description: + * This file contains user API functions to communicate with DSPs executing + * G.PAK software. The file is integrated into the host processor connected + * to C55X G.PAK DSPs via a Host Port Interface. + * + * Version: 1.0 + * + * Revision History: + * 06/15/05 - Initial release. + * 11/15/2006 - 24 TDM-TDM Channels EC release + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. The standard + * GPL disclaimer is given inline below for your convenience. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "zaptel.h" + +#include "GpakHpi.h" +#include "vpmadt032.h" +#include "GpakApi.h" +#include "gpakenum.h" + +#ifdef VPM_SUPPORT + +/* DSP to Host interface block offsets. */ +#define REPLY_MSG_PNTR_OFFSET 0 /* I/F blk offset to Reply Msg Pointer */ +#define CMD_MSG_PNTR_OFFSET 2 /* I/F blk offset to Command Msg Pointer */ +#define EVENT_MSG_PNTR_OFFSET 4 /* I/F blk offset to Event Msg Pointer */ +#define PKT_BUFR_MEM_OFFSET 6 /* I/F blk offset to Packet Buffer memory */ +#define DSP_STATUS_OFFSET 8 /* I/F blk offset to DSP Status */ +#define VERSION_ID_OFFSET 9 /* I/F blk offset to G.PAK Version Id */ +#define MAX_CMD_MSG_LEN_OFFSET 10 /* I/F blk offset to Max Cmd Msg Length */ +#define CMD_MSG_LEN_OFFSET 11 /* I/F blk offset to Command Msg Length */ +#define REPLY_MSG_LEN_OFFSET 12 /* I/F blk offset to Reply Msg Length */ +#define NUM_CHANNELS_OFFSET 13 /* I/F blk offset to Num Built Channels */ +#define NUM_PKT_CHANNELS_OFFSET 14 /* I/F blk offset to Num Pkt Channels */ +#define NUM_CONFERENCES_OFFSET 15 /* I/F blk offset to Num Conferences */ +//#define CPU_USAGE_OFFSET_1MS 16 /* I/F blk offset to CPU Usage statistics */ +#define CPU_USAGE_OFFSET 18 /* I/F blk offset to CPU Usage statistics */ +//#define CPU_USAGE_OFFSET_10MS 20 /* I/F blk offset to CPU Usage statistics */ +#define FRAMING_STATS_OFFSET 22 /* I/F blk offset to Framing statistics */ + +//#define GPAK_RELEASE_Rate rate10ms +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = +// Macro to reconstruct a 32-bit value from two 16-bit values. +// Parameter p32: 32-bit-wide destination +// Parameter p16: 16-bit-wide source array of length 2 words +#define RECONSTRUCT_LONGWORD(p32, p16) p32 = (DSP_ADDRESS)p16[0]<<16; \ + p32 |= (unsigned long)p16[1] +// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = + +/* DSP Status value definitions. */ +#define DSP_INIT_STATUS 0x5555 /* DSP Initialized status value */ +#define HOST_INIT_STATUS 0xAAAA /* Host Initialized status value */ + +/* Circular packet buffer information structure offsets. */ +#define CB_BUFR_BASE 0 /* pointer to base of circular buffer */ +#define CB_BUFR_SIZE 2 /* size of buffer (words) */ +#define CB_BUFR_PUT_INDEX 3 /* offset in buffer for next write */ +#define CB_BUFR_TAKE_INDEX 4 /* offset in buffer for next read */ +#define CIRC_BUFFER_INFO_STRUCT_SIZE 6 + +/* Miscellaneous definitions. */ +#define MSG_BUFFER_SIZE 100 /* size (words) of Host msg buffer */ +#define WORD_BUFFER_SIZE 84 /* size of DSP Word buffer (words) */ + +#ifdef __TMS320C55XX__ // debug sections if not on host +#pragma DATA_SECTION(pDspIfBlk,"GPAKAPIDEBUG_SECT") +#pragma DATA_SECTION(MaxCmdMsgLen,"GPAKAPIDEBUG_SECT") +#pragma DATA_SECTION(MaxChannels,"GPAKAPIDEBUG_SECT") +#pragma DATA_SECTION(DlByteBufr,"GPAKAPIDEBUG_SECT") +#pragma DATA_SECTION(DlWordBufr,"GPAKAPIDEBUG_SECT") +#pragma DATA_SECTION(pEventFifoAddress,"GPAKAPIDEBUG_SECT") +#endif + +/* Host variables related to Host to DSP interface. */ +static DSP_ADDRESS pDspIfBlk[MAX_DSP_CORES]; /* DSP address of I/F block */ +static DSP_WORD MaxCmdMsgLen[MAX_DSP_CORES]; /* max Cmd msg length (octets) */ +static unsigned short int MaxChannels[MAX_DSP_CORES]; /* max num channels */ + +//static unsigned short int MaxPktChannels[MAX_DSP_CORES]; /* max num pkt channels */ +//static unsigned short int MaxConfs[MAX_DSP_CORES]; /* max num conferences */ +//static DSP_ADDRESS pPktInBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt In buffer */ +//static DSP_ADDRESS pPktOutBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt Out buffer */ +static DSP_ADDRESS pEventFifoAddress[MAX_DSP_CORES]; /* event fifo */ + +static unsigned char DlByteBufr[DOWNLOAD_BLOCK_SIZE * 2]; /* Dowload byte buf */ +static DSP_WORD DlWordBufr[DOWNLOAD_BLOCK_SIZE]; /* Dowload word buffer */ + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * CheckDspReset - Check if the DSP was reset. + * + * FUNCTION + * This function determines if the DSP was reset and is ready. If reset + * occurred, it reads interface parameters and calculates DSP addresses. + * + * RETURNS + * -1 = DSP is not ready. + * 0 = Reset did not occur. + * 1 = Reset occurred. + * + */ +static int CheckDspReset( + int DspId /* DSP Identifier (0 to MaxDSPCores-1) */ + ) +{ + DSP_ADDRESS IfBlockPntr; /* Interface Block pointer */ + DSP_WORD DspStatus; /* DSP Status */ + DSP_WORD DspChannels; /* number of DSP channels */ + //DSP_WORD DspConfs; /* number of DSP conferences */ + //DSP_ADDRESS PktBufrMem; /* address of Packet Buffer */ + DSP_WORD Temp[2]; + //unsigned short int i; /* loop index / counter */ + + /* Read the pointer to the Interface Block. */ + gpakReadDspMemory(DspId, DSP_IFBLK_ADDRESS, 2, Temp); + RECONSTRUCT_LONGWORD(IfBlockPntr, Temp); + + /* If the pointer is zero, return with an indication the DSP is not + ready. */ + if (IfBlockPntr == 0) + return (-1); + + /* Read the DSP's Status. */ + gpakReadDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, &DspStatus); + + /* If status indicates the DSP was reset, read the DSP's interface + parameters and calculate DSP addresses. */ + if (DspStatus == DSP_INIT_STATUS || + ((DspStatus == HOST_INIT_STATUS) && (pDspIfBlk[DspId] == 0))) + { + /* Save the address of the DSP's Interface Block. */ + pDspIfBlk[DspId] = IfBlockPntr; + + /* Read the DSP's interface parameters. */ + gpakReadDspMemory(DspId, IfBlockPntr + MAX_CMD_MSG_LEN_OFFSET, 1, + &(MaxCmdMsgLen[DspId])); + + /* read the number of configured DSP channels */ + gpakReadDspMemory(DspId, IfBlockPntr + NUM_CHANNELS_OFFSET, 1, + &DspChannels); + if (DspChannels > MAX_CHANNELS) + MaxChannels[DspId] = MAX_CHANNELS; + else + MaxChannels[DspId] = (unsigned short int) DspChannels; +#if 0 + /* read the number of configured DSP conferences */ + gpakReadDspMemory(DspId, IfBlockPntr + NUM_CONFERENCES_OFFSET, 1, + &DspConfs); + if (DspConfs > MAX_CONFS) + MaxConfs[DspId] = MAX_CONFS; + else + MaxConfs[DspId] = (unsigned short int) DspConfs; + + + /* read the number of configured DSP packet channels */ + gpakReadDspMemory(DspId, IfBlockPntr + NUM_PKT_CHANNELS_OFFSET, 1, + &DspChannels); + if (DspChannels > MAX_PKT_CHANNELS) + MaxPktChannels[DspId] = MAX_PKT_CHANNELS; + else + MaxPktChannels[DspId] = (unsigned short int) DspChannels; + + + /* read the pointer to the circular buffer infor struct table */ + gpakReadDspMemory(DspId, IfBlockPntr + PKT_BUFR_MEM_OFFSET, 2, Temp); + RECONSTRUCT_LONGWORD(PktBufrMem, Temp); + + + /* Determine the addresses of each channel's Packet buffers. */ + for (i = 0; i < MaxPktChannels[DspId]; i++) + { + pPktInBufr[DspId][i] = PktBufrMem; + pPktOutBufr[DspId][i] = PktBufrMem + CIRC_BUFFER_INFO_STRUCT_SIZE; + PktBufrMem += (CIRC_BUFFER_INFO_STRUCT_SIZE*2); + } +#endif + + /* read the pointer to the event fifo info struct */ + gpakReadDspMemory(DspId, IfBlockPntr + EVENT_MSG_PNTR_OFFSET, 2, Temp); + RECONSTRUCT_LONGWORD(pEventFifoAddress[DspId], Temp); + + /* Set the DSP Status to indicate the host recognized the reset. */ + DspStatus = HOST_INIT_STATUS; + gpakWriteDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, + &DspStatus); + + /* Return with an indication that a reset occurred. */ + return (1); + } + + /* If status doesn't indicate the host recognized a reset, return with an + indication the DSP is not ready. */ + if ((DspStatus != HOST_INIT_STATUS) || (pDspIfBlk[DspId] == 0)) + return (-1); + + /* Return with an indication that a reset did not occur. */ + return (0); +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * WriteDspCmdMessage - Write a Host Command/Request message to DSP. + * + * FUNCTION + * This function writes a Host Command/Request message into DSP memory and + * informs the DSP of the presence of the message. + * + * RETURNS + * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) + * 0 = Temporarily unable to write message (previous Cmd Msg busy) + * 1 = Message written successfully + * + */ +static int WriteDspCmdMessage( + int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ + DSP_WORD *pMessage, /* pointer to Command message */ + DSP_WORD MsgLength /* length of message (octets) */ + ) +{ + DSP_WORD CmdMsgLength; /* current Cmd message length */ + DSP_WORD Temp[2]; + DSP_ADDRESS BufferPointer; /* message buffer pointer */ + + /* Check if the DSP was reset and is ready. */ + if (CheckDspReset(DspId) == -1) + return (-1); + + /* Make sure the message length is valid. */ + if ((MsgLength < 1) || (MsgLength > MaxCmdMsgLen[DspId])) + return (-1); + + /* Make sure a previous Command message is not in use by the DSP. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, + &CmdMsgLength); + if (CmdMsgLength != 0) + return (0); + + /* Purge any previous Reply message that wasn't read. */ + gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, + &CmdMsgLength); + + /* Copy the Command message into DSP memory. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_PNTR_OFFSET, 2, Temp); + RECONSTRUCT_LONGWORD(BufferPointer, Temp); + gpakWriteDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); + + /* Store the message length in DSP's Command message length (flags DSP that + a Command message is ready). */ + CmdMsgLength = MsgLength; + gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, + &CmdMsgLength); + + /* Return with an indication the message was written. */ + return (1); +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * ReadDspReplyMessage - Read a DSP Reply message from DSP. + * + * FUNCTION + * This function reads a DSP Reply message from DSP memory. + * + * RETURNS + * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) + * 0 = No message available (DSP Reply message empty) + * 1 = Message read successfully (message and length stored in variables) + * + */ +static int ReadDspReplyMessage( + int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ + DSP_WORD *pMessage, /* pointer to Reply message buffer */ + DSP_WORD *pMsgLength /* pointer to msg length var (octets) */ + ) +{ + DSP_WORD MsgLength; /* message length */ + DSP_ADDRESS BufferPointer; /* message buffer pointer */ + DSP_WORD Temp[2]; + + /* Check if the DSP was reset and is ready. */ + if (CheckDspReset(DspId) == -1) + return (-1); + + /* Check if a Reply message is ready. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, + &MsgLength); + if (MsgLength == 0) + return (0); + + /* Make sure the message length is valid. */ + if (MsgLength > *pMsgLength) + return (-1); + + /* Copy the Reply message from DSP memory. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_PNTR_OFFSET, 2, Temp); + RECONSTRUCT_LONGWORD(BufferPointer, Temp); + gpakReadDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); + + /* Store the message length in the message length variable. */ + *pMsgLength = MsgLength; + + /* Indicate a Reply message is not ready. */ + MsgLength = 0; + gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, + &MsgLength); + + /* Return with an indication the message was read. */ + return (1); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * ReadCircBuffer - Read from a DSP circular buffer. + * + * FUNCTION + * This function reads a block of words from a DSP circular buffer. The Take + * address is incremented by the number of words read adjusting for buffer + * wrap. + * + * RETURNS + * nothing + * + */ +static void ReadCircBuffer( + int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ + DSP_ADDRESS BufrBaseAddress, /* address of base of circular buffer */ + DSP_ADDRESS BufrLastAddress, /* address of last word in buffer */ + DSP_ADDRESS *TakeAddress, /* pointer to address in buffer for read */ + DSP_WORD *pWordBuffer, /* pointer to buffer for words read */ + DSP_WORD NumWords /* number of words to read */ + ) +{ + DSP_WORD WordsTillEnd; /* number of words until end of buffer */ + + /* Determine the number of words from the start address until the end of the + buffer. */ + WordsTillEnd = BufrLastAddress - *TakeAddress + 1; + + /* If a buffer wrap will occur, read the first part at the end of the + buffer followed by the second part at the beginning of the buffer. */ + if (NumWords > WordsTillEnd) + { + gpakReadDspMemory(DspId, *TakeAddress, WordsTillEnd, pWordBuffer); + gpakReadDspMemory(DspId, BufrBaseAddress, NumWords - WordsTillEnd, + &(pWordBuffer[WordsTillEnd])); + *TakeAddress = BufrBaseAddress + NumWords - WordsTillEnd; + } + + /* If a buffer wrap will not occur, read all words starting at the current + take address in the buffer. */ + else + { + gpakReadDspMemory(DspId, *TakeAddress, NumWords, pWordBuffer); + if (NumWords == WordsTillEnd) + *TakeAddress = BufrBaseAddress; + else + *TakeAddress = *TakeAddress + NumWords; + } + return; +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * VerifyReply - Verify the reply message is correct for the command sent. + * + * FUNCTION + * This function verifies correct reply message content for the command that + * was just sent. + * + * RETURNS + * 0 = Incorrect + * 1 = Correct + * + */ +static int VerifyReply( + DSP_WORD *pMsgBufr, /* pointer to Reply message buffer */ + int CheckType, /* reply check type */ + DSP_WORD CheckValue /* reply check value */ + ) +{ + + /* Verify Channel or Conference Id. */ + if (CheckType == 1) + { + if (((pMsgBufr[1] >> 8) & 0xFF) != CheckValue) + return (0); + } + + /* Verify Test Mode Id. */ + else if (CheckType == 2) + { + if (pMsgBufr[1] != CheckValue) + return (0); + } + + /* Return with an indication of correct reply. */ + return (1); +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * TransactCmd - Send a command to the DSP and receive it's reply. + * + * FUNCTION + * This function sends the specified command to the DSP and receives the DSP's + * reply. + * + * RETURNS + * Length of reply message (0 = Failure) + * + */ +static unsigned int TransactCmd( + int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ + DSP_WORD *pMsgBufr, /* pointer to Cmd/Reply message buffer */ + DSP_WORD CmdLength, /* length of command message (octets) */ + DSP_WORD ReplyType, /* required type of reply message */ + DSP_WORD ReplyLength, /* required length of reply message (octets) */ + int ReplyCheckType, /* reply check type */ + DSP_WORD ReplyCheckValue /* reply check value */ + ) +{ + int FuncStatus; /* function status */ + int LoopCount; /* wait loop counter */ + DSP_WORD RcvReplyLength; /* received Reply message length */ + DSP_WORD RcvReplyType; /* received Reply message type code */ + DSP_WORD RetValue; /* return value */ + + /* Default the return value to indicate a failure. */ + RetValue = 0; + + /* Lock access to the DSP. */ + gpakLockAccess(DspId); + + /* Attempt to write the command message to the DSP. */ + LoopCount = 0; + while ((FuncStatus = WriteDspCmdMessage(DspId, pMsgBufr, CmdLength)) != 1) + { + if (FuncStatus == -1) + break; + if (++LoopCount > MAX_WAIT_LOOPS) + break; + gpakHostDelay(); + } + + /* Attempt to read the reply message from the DSP if the command message was + sent successfully. */ + if (FuncStatus == 1) + { + for (LoopCount = 0; LoopCount < MAX_WAIT_LOOPS; LoopCount++) + { + RcvReplyLength = MSG_BUFFER_SIZE * 2; + FuncStatus = ReadDspReplyMessage(DspId, pMsgBufr, &RcvReplyLength); + if (FuncStatus == 1) + { + RcvReplyType = (pMsgBufr[0] >> 8) & 0xFF; + if ((RcvReplyLength >= ReplyLength) && + (RcvReplyType == ReplyType) && + VerifyReply(pMsgBufr, ReplyCheckType, ReplyCheckValue)) + { + RetValue = RcvReplyLength; + break; + } + else if (RcvReplyType == MSG_NULL_REPLY) + break; + } + else if (FuncStatus == -1) + break; + gpakHostDelay(); + } + } + + /* Unlock access to the DSP. */ + gpakUnlockAccess(DspId); + + /* Return the length of the reply message (0 = failure). */ + return (RetValue); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakConfigurePorts - Configure a DSP's serial ports. + * + * FUNCTION + * This function configures a DSP's serial ports. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakConfigPortStatus_t gpakConfigurePorts( + unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ + GpakPortConfig_t *pPortConfig, /* pointer to Port Config info */ + GPAK_PortConfigStat_t *pStatus /* pointer to Port Config Status */ + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (CpsInvalidDsp); + + /* Build the Configure Serial Ports message. */ + MsgBuffer[0] = MSG_CONFIGURE_PORTS << 8; + MsgBuffer[1] = (DSP_WORD) + ((pPortConfig->SlotsSelect1 << 12) | + ((pPortConfig->FirstBlockNum1 << 8) & 0x0F00) | + ((pPortConfig->SecBlockNum1 << 4) & 0x00F0)); + MsgBuffer[2] = (DSP_WORD) pPortConfig->FirstSlotMask1; + MsgBuffer[3] = (DSP_WORD) pPortConfig->SecSlotMask1; + MsgBuffer[4] = (DSP_WORD) + ((pPortConfig->SlotsSelect2 << 12) | + ((pPortConfig->FirstBlockNum2 << 8) & 0x0F00) | + ((pPortConfig->SecBlockNum2 << 4) & 0x00F0)); + MsgBuffer[5] = (DSP_WORD) pPortConfig->FirstSlotMask2; + MsgBuffer[6] = (DSP_WORD) pPortConfig->SecSlotMask2; + MsgBuffer[7] = (DSP_WORD) + ((pPortConfig->SlotsSelect3 << 12) | + ((pPortConfig->FirstBlockNum3 << 8) & 0x0F00) | + ((pPortConfig->SecBlockNum3 << 4) & 0x00F0)); + MsgBuffer[8] = (DSP_WORD) pPortConfig->FirstSlotMask3; + MsgBuffer[9] = (DSP_WORD) pPortConfig->SecSlotMask3; + + MsgBuffer[10] = (DSP_WORD) + (((pPortConfig->DxDelay1 << 11) & 0x0800) | + ((pPortConfig->RxDataDelay1 << 9) & 0x0600) | + ((pPortConfig->TxDataDelay1 << 7) & 0x0180) | + ((pPortConfig->RxClockPolarity1 << 6) & 0x0040) | + ((pPortConfig->TxClockPolarity1 << 5) & 0x0020) | + ((pPortConfig->RxFrameSyncPolarity1 << 4) & 0x0010) | + ((pPortConfig->TxFrameSyncPolarity1 << 3) & 0x0008) | + ((pPortConfig->CompandingMode1 << 1) & 0x0006) | + (pPortConfig->SerialWordSize1 & 0x0001)); + + MsgBuffer[11] = (DSP_WORD) + (((pPortConfig->DxDelay2 << 11) & 0x0800) | + ((pPortConfig->RxDataDelay2 << 9) & 0x0600) | + ((pPortConfig->TxDataDelay2 << 7) & 0x0180) | + ((pPortConfig->RxClockPolarity2 << 6) & 0x0040) | + ((pPortConfig->TxClockPolarity2 << 5) & 0x0020) | + ((pPortConfig->RxFrameSyncPolarity2 << 4) & 0x0010) | + ((pPortConfig->TxFrameSyncPolarity2 << 3) & 0x0008) | + ((pPortConfig->CompandingMode2 << 1) & 0x0006) | + (pPortConfig->SerialWordSize1 & 0x0001)); + + MsgBuffer[12] = (DSP_WORD) + (((pPortConfig->DxDelay3 << 11) & 0x0800) | + ((pPortConfig->RxDataDelay3 << 9) & 0x0600) | + ((pPortConfig->TxDataDelay3 << 7) & 0x0180) | + ((pPortConfig->RxClockPolarity3 << 6) & 0x0040) | + ((pPortConfig->TxClockPolarity3 << 5) & 0x0020) | + ((pPortConfig->RxFrameSyncPolarity3 << 4) & 0x0010) | + ((pPortConfig->TxFrameSyncPolarity3 << 3) & 0x0008) | + ((pPortConfig->CompandingMode3 << 1) & 0x0006) | + (pPortConfig->SerialWordSize3 & 0x0001)); + + MsgBuffer[13] = (DSP_WORD) pPortConfig->ThirdSlotMask1; + MsgBuffer[14] = (DSP_WORD) pPortConfig->FouthSlotMask1; + MsgBuffer[15] = (DSP_WORD) pPortConfig->FifthSlotMask1; + MsgBuffer[16] = (DSP_WORD) pPortConfig->SixthSlotMask1; + MsgBuffer[17] = (DSP_WORD) pPortConfig->SevenSlotMask1; + MsgBuffer[18] = (DSP_WORD) pPortConfig->EightSlotMask1; + + MsgBuffer[19] = (DSP_WORD) pPortConfig->ThirdSlotMask2;; + MsgBuffer[20] = (DSP_WORD) pPortConfig->FouthSlotMask2; + MsgBuffer[21] = (DSP_WORD) pPortConfig->FifthSlotMask2;; + MsgBuffer[22] = (DSP_WORD) pPortConfig->SixthSlotMask2; + MsgBuffer[23] = (DSP_WORD) pPortConfig->SevenSlotMask2;; + MsgBuffer[24] = (DSP_WORD) pPortConfig->EightSlotMask2; + + MsgBuffer[25] = (DSP_WORD) pPortConfig->ThirdSlotMask3;; + MsgBuffer[26] = (DSP_WORD) pPortConfig->FouthSlotMask3; + MsgBuffer[27] = (DSP_WORD) pPortConfig->FifthSlotMask3;; + MsgBuffer[28] = (DSP_WORD) pPortConfig->SixthSlotMask3; + MsgBuffer[29] = (DSP_WORD) pPortConfig->SevenSlotMask3;; + MsgBuffer[30] = (DSP_WORD) pPortConfig->EightSlotMask3; + + + /* Attempt to send the Configure Serial Ports message to the DSP and receive + it's reply. */ + if (!TransactCmd(DspId, MsgBuffer, 62, MSG_CONFIG_PORTS_REPLY, 4, 0, 0)) + return (CpsDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + *pStatus = (GPAK_PortConfigStat_t) (MsgBuffer[1] & 0xFF); + if (*pStatus == Pc_Success) + return (CpsSuccess); + else + return (CpsParmError); +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakConfigureChannel - Configure a DSP's Channel. + * + * FUNCTION + * This function configures a DSP's Channel. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakConfigChanStatus_t gpakConfigureChannel( + unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ + unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ + GpakChanType ChannelType, /* Channel Type */ + GpakChannelConfig_t *pChanConfig, /* pointer to Channel Config info */ + GPAK_ChannelConfigStat_t *pStatus /* pointer to Channel Config Status */ + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD MsgLength; /* message length */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (CcsInvalidDsp); + + /* Make sure the Channel Id is valid. */ + if (ChannelId >= MaxChannels[DspId]) + return (CcsInvalidChannel); + + /* Build the Configure Channel message based on the Channel Type. */ + switch (ChannelType) + { + + /* PCM to Packet channel type. */ + case tdmToTdm: + + MsgBuffer[2] = (DSP_WORD) + ((pChanConfig->PcmInPortA << 8) | + (pChanConfig->PcmInSlotA & 0xFF)); + MsgBuffer[3] = (DSP_WORD) + ((pChanConfig->PcmOutPortA << 8) | + (pChanConfig->PcmOutSlotA & 0xFF)); + + MsgBuffer[4] = (DSP_WORD) + ((pChanConfig->PcmInPortB << 8) | + (pChanConfig->PcmInSlotB & 0xFF)); + MsgBuffer[5] = (DSP_WORD) + ((pChanConfig->PcmOutPortB << 8) | + (pChanConfig->PcmOutSlotB & 0xFF)); + + MsgBuffer[6] = (DSP_WORD) + ( + ((pChanConfig->FaxCngDetB <<11) & 0x0800) | + ((pChanConfig->FaxCngDetA <<10) & 0x0400) | + ((pChanConfig->MuteToneB << 9) & 0x0200) | + ((pChanConfig->MuteToneA << 8) & 0x0100) | + ((pChanConfig->FrameRate << 6) & 0x00C0) | + ((pChanConfig->ToneTypesB << 5) & 0x0020) | + ((pChanConfig->ToneTypesA << 4) & 0x0010) | + ((pChanConfig->SoftwareCompand & 3) << 2) | + (pChanConfig->EcanEnableB << 1) | + (pChanConfig->EcanEnableA & 1) + ); + + MsgBuffer[7] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanTapLength; + MsgBuffer[8] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNlpType; + MsgBuffer[9] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanAdaptEnable; + MsgBuffer[10] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanG165DetEnable; + MsgBuffer[11] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanDblTalkThresh; + MsgBuffer[12] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNlpThreshold; + MsgBuffer[13] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNlpConv; + MsgBuffer[14] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNlpUnConv; + MsgBuffer[15] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNlpMaxSuppress; + + MsgBuffer[16] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanCngThreshold; + MsgBuffer[17] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanAdaptLimit; + MsgBuffer[18] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanCrossCorrLimit; + MsgBuffer[19] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanNumFirSegments; + MsgBuffer[20] = (DSP_WORD) + pChanConfig->EcanParametersA.EcanFirSegmentLen; + + MsgBuffer[21] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanTapLength; + MsgBuffer[22] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNlpType; + MsgBuffer[23] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanAdaptEnable; + MsgBuffer[24] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanG165DetEnable; + MsgBuffer[25] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanDblTalkThresh; + MsgBuffer[26] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNlpThreshold; + MsgBuffer[27] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNlpConv; + MsgBuffer[28] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNlpUnConv; + MsgBuffer[29] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNlpMaxSuppress; + MsgBuffer[30] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanCngThreshold; + MsgBuffer[31] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanAdaptLimit; + MsgBuffer[32] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanCrossCorrLimit; + MsgBuffer[33] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanNumFirSegments; + MsgBuffer[34] = (DSP_WORD) + pChanConfig->EcanParametersB.EcanFirSegmentLen; + + MsgLength = 70; // byte number == 35*2 + break; + + + /* Unknown (invalid) channel type. */ + default: + *pStatus = Cc_InvalidChannelType; + return (CcsParmError); + } + + MsgBuffer[0] = MSG_CONFIGURE_CHANNEL << 8; + MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ChannelType & 0xFF)); + + /* Attempt to send the Configure Channel message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, MsgLength, MSG_CONFIG_CHAN_REPLY, 4, 1, + (DSP_WORD) ChannelId)) + return (CcsDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + *pStatus = (GPAK_ChannelConfigStat_t) (MsgBuffer[1] & 0xFF); + if (*pStatus == Cc_Success) + return (CcsSuccess); + else + return (CcsParmError); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakTearDownChannel - Tear Down a DSP's Channel. + * + * FUNCTION + * This function tears down a DSP's Channel. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakTearDownStatus_t gpakTearDownChannel( + unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ + unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ + GPAK_TearDownChanStat_t *pStatus /* pointer to Tear Down Status */ + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (TdsInvalidDsp); + + /* Make sure the Channel Id is valid. */ + if (ChannelId >= MaxChannels[DspId]) + return (TdsInvalidChannel); + + /* Build the Tear Down Channel message. */ + MsgBuffer[0] = MSG_TEAR_DOWN_CHANNEL << 8; + MsgBuffer[1] = (DSP_WORD) (ChannelId << 8); + + /* Attempt to send the Tear Down Channel message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, 3, MSG_TEAR_DOWN_REPLY, 4, 1, + (DSP_WORD) ChannelId)) + return (TdsDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + *pStatus = (GPAK_TearDownChanStat_t) (MsgBuffer[1] & 0xFF); + if (*pStatus == Td_Success) + return (TdsSuccess); + else + return (TdsError); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakAlgControl - Control an Algorithm. + * + * FUNCTION + * This function controls an Algorithm + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakAlgControlStat_t gpakAlgControl( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GpakAlgCtrl_t ControlCode, // algorithm control code + GPAK_AlgControlStat_t *pStatus // pointer to return status + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (AcInvalidDsp); + + /* Make sure the Channel Id is valid. */ + if (ChannelId >= MaxChannels[DspId]) + return (AcInvalidChannel); + + MsgBuffer[0] = MSG_ALG_CONTROL << 8; + MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ControlCode & 0xFF)); + + /* Attempt to send the Tear Down Channel message to the DSP and receive it's + reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ALG_CONTROL_REPLY, 4, 1, + (DSP_WORD) ChannelId)) + return (AcDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + *pStatus = (GPAK_AlgControlStat_t) (MsgBuffer[1] & 0xFF); + if (*pStatus == Ac_Success) + return (AcSuccess); + else + return (AcParmError); + +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadEventFIFOMessage - read from the event fifo + * + * FUNCTION + * This function reads a single event from the event fifo if one is available + * + * RETURNS + * Status code indicating success or a specific error. + * + * Notes: This function should be called in a loop until the return status + * indicates that the fifo is empty. + * + * If the event code equals "EventLoopbackTeardownComplete", then the + * contents of *pChannelId hold the coderBlockId that was assigned to + * the loopback coder that was torn down. + */ +gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( + unsigned short int DspId, // DSP identifier + unsigned short int *pChannelId, // pointer to channel identifier + GpakAsyncEventCode_t *pEventCode, // pointer to Event Code + GpakAsyncEventData_t *pEventData // pointer to Event Data Struct + ) +{ + DSP_WORD WordBuffer[WORD_BUFFER_SIZE]; /* DSP words buffer */ + GpakAsyncEventCode_t EventCode; /* DSP's event code */ + DSP_WORD EventDataLength; /* Length of event to read */ + DSP_WORD ChannelId; /* DSP's channel Id */ + DSP_ADDRESS EventInfoAddress; /* address of EventFIFO info structure */ + DSP_ADDRESS BufrBaseAddress; /* base address of EventFIFO buffer */ + DSP_ADDRESS BufrLastAddress; /* last address of EventFIFO buffer */ + DSP_ADDRESS TakeAddress; /* current take address in fifo buffer */ + DSP_WORD BufrSize; /* size (in words) of event FIFO buffer */ + DSP_WORD PutIndex; /* event fifo put index */ + DSP_WORD TakeIndex; /* event fifo take index */ + DSP_WORD WordsReady; /* number words ready for read out of event fifo */ + DSP_WORD EventError; /* flag indicating error with event fifo msg */ + //DSP_WORD *pDebugData; /* debug data buffer pointer in event data struct */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RefInvalidDsp); + + /* Lock access to the DSP. */ + gpakLockAccess(DspId); + + /* Check if the DSP was reset and is ready. */ + if (CheckDspReset(DspId) == -1) + { + gpakUnlockAccess(DspId); + return (RefDspCommFailure); + } + + /* Check if an event message is ready in the DSP. */ + EventInfoAddress = pEventFifoAddress[DspId]; + gpakReadDspMemory(DspId, EventInfoAddress, CIRC_BUFFER_INFO_STRUCT_SIZE, + WordBuffer); + RECONSTRUCT_LONGWORD(BufrBaseAddress, ((DSP_WORD *)&WordBuffer[CB_BUFR_BASE])); + BufrSize = WordBuffer[CB_BUFR_SIZE]; + PutIndex = WordBuffer[CB_BUFR_PUT_INDEX]; + TakeIndex = WordBuffer[CB_BUFR_TAKE_INDEX]; + if (PutIndex >= TakeIndex) + WordsReady = PutIndex - TakeIndex; + else + WordsReady = PutIndex + BufrSize - TakeIndex; + + if (WordsReady < 2) + { + gpakUnlockAccess(DspId); + return (RefNoEventAvail); + } + + /* Read the event header from the DSP's Event FIFO. */ + TakeAddress = BufrBaseAddress + TakeIndex; + BufrLastAddress = BufrBaseAddress + BufrSize - 1; + ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, + WordBuffer, 2); + TakeIndex += 2; + if (TakeIndex >= BufrSize) + TakeIndex -= BufrSize; + + ChannelId = (WordBuffer[0] >> 8) & 0xFF; + EventCode = (GpakAsyncEventCode_t)(WordBuffer[0] & 0xFF); + EventDataLength = WordBuffer[1]; + EventError = 0; + + switch (EventCode) + { + case EventToneDetect: + if (EventDataLength > WORD_BUFFER_SIZE) + { + gpakUnlockAccess(DspId); + return (RefInvalidEvent); + } + ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, + WordBuffer, EventDataLength); + pEventData->toneEvent.ToneCode = (GpakToneCodes_t) + (WordBuffer[0] & 0xFF); + pEventData->toneEvent.ToneDuration = WordBuffer[1]; + pEventData->toneEvent.Direction = WordBuffer[2]; + pEventData->toneEvent.DebugToneStatus = WordBuffer[3]; + TakeIndex += EventDataLength; + if (TakeIndex >= BufrSize) + TakeIndex -= BufrSize; + if (EventDataLength != 4) + EventError = 1; + break; + + default: + EventError = 1; + break; + }; + + /* Update the Take index in the DSP's Packet Out buffer information. */ + gpakWriteDspMemory(DspId, EventInfoAddress + CB_BUFR_TAKE_INDEX, 1, + &TakeIndex); + + /* Unlock access to the DSP. */ + gpakUnlockAccess(DspId); + + if (EventError) + return(RefInvalidEvent); + + *pChannelId = ChannelId; + *pEventCode = EventCode; + return(RefEventAvail); + +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakPingDsp - ping the DSP to see if it's alive + * + * FUNCTION + * This function checks if the DSP is still communicating with the host + * and returns the DSP SW version + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakPingDspStat_t gpakPingDsp( + unsigned short int DspId, // DSP identifier + unsigned short int *pDspSwVersion // DSP software version + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (PngInvalidDsp); + + /* send value of 1, DSP increments it */ + MsgBuffer[0] = (MSG_PING << 8); + + /* Attempt to send the ping message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, 1, MSG_PING_REPLY, 6, 0, 0)) + return (PngDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + { + *pDspSwVersion = MsgBuffer[2]; + return (PngSuccess); + } + else + return (PngDspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakSerialTxFixedValue - transmit a fixed value on a timeslot + * + * FUNCTION + * This function controls transmission of a fixed value out onto a serial + * port's timeslot. + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id + unsigned short int PcmOutSlot, // PCM Output Time Slot + unsigned short int Value, // 16-bit value + GpakActivation State // activation state + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (TfvInvalidDsp); + + /* Make sure the Channel Id is valid. */ + if (ChannelId >= MaxChannels[DspId]) + return (TfvInvalidChannel); + + + /* Build the message. */ + MsgBuffer[0] = MSG_SERIAL_TXVAL << 8; + MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (State & 0xFF)); + MsgBuffer[2] = (DSP_WORD) ((PcmOutPort << 8) | (PcmOutSlot & 0xFF)); + MsgBuffer[3] = (DSP_WORD) Value; + + /* Attempt to send the message to the DSP and receive it's + reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 8, MSG_SERIAL_TXVAL_REPLY, 4, + 1, ChannelId)) + return (TfvDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + return (TfvSuccess); + else + return (TfvDspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakControlTdmLoopBack - control a serial port's loopback state + * + * FUNCTION + * This function enables/disables the tdm input to output looback mode on a + * serial port + * + * RETURNS + * Status code indicating success or a specific error. + */ + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ +gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( + unsigned short int DspId, // DSP identifier + GpakSerialPort_t SerialPort, // Serial Port Id + GpakActivation LoopBackState // Loopback State + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (ClbInvalidDsp); + + /* Build the message. */ + MsgBuffer[0] = MSG_TDM_LOOPBACK << 8; + MsgBuffer[1] = (DSP_WORD) ((SerialPort << 8) | (LoopBackState & 0xFF)); + + /* Attempt to send the message to the DSP and receive it's + reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 4, MSG_TDM_LOOPBACK_REPLY, 4, 0, 0)) + return (ClbDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + return (ClbSuccess); + else + return (ClbDspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadCpuUsage - Read CPU usage statistics from a DSP. + * + * FUNCTION + * This function reads the CPU usage statistics from a DSP's memory. The + * average CPU usage in units of .1 percent are obtained for each of the frame + * rates. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakReadCpuUsageStat_t gpakReadCpuUsage( + unsigned short int DspId, // Dsp Identifier + unsigned short int *pPeakUsage, // pointer to peak usage variable + unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second + ) +{ + DSP_WORD ReadBuffer[2]; /* DSP read buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RcuInvalidDsp); + + /* Lock access to the DSP. */ + gpakLockAccess(DspId); + + /* Check if the DSP was reset and is ready. */ + if (CheckDspReset(DspId) == -1) + return (RcuDspCommFailure); + + /* Read the CPU Usage statistics from the DSP. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CPU_USAGE_OFFSET, 2, + ReadBuffer); + + /* Unlock access to the DSP. */ + gpakUnlockAccess(DspId); + + /* Store the usage statistics in the specified variables. */ + *pPrev1SecPeakUsage = ReadBuffer[0]; + *pPeakUsage = ReadBuffer[1]; + + /* Return with an indication the usage staistics were read successfully. */ + return (RcuSuccess); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakResetCpuUsageStats - reset the cpu usage statistics + * + * FUNCTION + * This function resets the cpu utilization statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakResetCpuUsageStat_t gpakResetCpuUsageStats( + unsigned short int DspId // DSP identifier + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RstcInvalidDsp); + + MsgBuffer[0] = (MSG_RESET_USAGE_STATS << 8); + + /* Attempt to send the message to the DSP and receive it's reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_USAGE_STATS_REPLY, 4, 0, 0)) + return (RstcDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + return (RstcSuccess); + else + return (RstcDspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadFramingStats + * + * FUNCTION + * This function reads a DSP's framing interrupt statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakReadFramingStatsStatus_t gpakReadFramingStats( + unsigned short int DspId, // DSP identifier + unsigned short int *pFramingError1Count, // port 1 Framing error count + unsigned short int *pFramingError2Count, // port 2 Framing error count + unsigned short int *pFramingError3Count, // port 3 Framing error count + unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count + unsigned short int *pDmaSlipStatsBuffer // DMA slips count + ) +{ + DSP_WORD ReadBuffer[10]; /* DSP read buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RfsInvalidDsp); + + /* Lock access to the DSP. */ + gpakLockAccess(DspId); + + /* Check if the DSP was reset and is ready. */ + if (CheckDspReset(DspId) == -1) + return (RfsDspCommFailure); + + /* Read the framing interrupt statistics from the DSP. */ + gpakReadDspMemory(DspId, pDspIfBlk[DspId] + FRAMING_STATS_OFFSET, 10, + ReadBuffer); + + /* Unlock access to the DSP. */ + gpakUnlockAccess(DspId); + + /* Store the framing statistics in the specified variables. */ + *pFramingError1Count = ReadBuffer[0]; + *pFramingError2Count = ReadBuffer[1]; + *pFramingError3Count = ReadBuffer[2]; + *pDmaStopErrorCount = ReadBuffer[3]; + + if(pDmaSlipStatsBuffer != 0) + // If users want to get the DMA slips count + { + pDmaSlipStatsBuffer[0] = ReadBuffer[4]; + pDmaSlipStatsBuffer[1] = ReadBuffer[5]; + pDmaSlipStatsBuffer[2] = ReadBuffer[6]; + pDmaSlipStatsBuffer[3] = ReadBuffer[7]; + pDmaSlipStatsBuffer[4] = ReadBuffer[8]; + pDmaSlipStatsBuffer[5] = ReadBuffer[9]; + + } + /* Return with an indication the statistics were read successfully. */ + return (RfsSuccess); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakResetFramingStats - reset a DSP's framing interrupt statistics + * + * FUNCTION + * This function resets a DSP's framing interrupt statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakResetFramingStatsStatus_t gpakResetFramingStats( + unsigned short int DspId // DSP identifier + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RstfInvalidDsp); + + MsgBuffer[0] = (MSG_RESET_FRAME_STATS << 8); + + /* Attempt to send the message to the DSP and receive it's reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_FRAME_STATS_REPLY, 4, 0, 0)) + return (RstfDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + return (RstfSuccess); + else + return (RstfDspCommFailure); +} + +/* + * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. + * + * FUNCTION + * This function reads a DSP's Program and Data memory image from the + * specified file and writes the image to the DSP's memory. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakDownloadStatus_t gpakDownloadDsp( + unsigned short DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ + GPAK_FILE_ID FileId /* G.PAK Download File Identifier */ + ) +{ + gpakDownloadStatus_t RetStatus; /* function return status */ + int NumRead; /* number of file bytes read */ + DSP_ADDRESS Address; /* DSP address */ + unsigned int WordCount; /* number of words in record */ + unsigned int NumWords; /* number of words to read/write */ + unsigned int i; /* loop index / counter */ + unsigned int j; /* loop index */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (GdlInvalidDsp); + + /* Lock access to the DSP. */ + gpakLockAccess(DspId); + + RetStatus = GdlSuccess; + while (RetStatus == GdlSuccess) + { + + /* Read a record header from the file. */ + NumRead = gpakReadFile(FileId, DlByteBufr, 6); + if (NumRead == -1) + { + RetStatus = GdlFileReadError; + break; + } + if (NumRead != 6) + { + RetStatus = GdlInvalidFile; + break; + } + Address = (((DSP_ADDRESS) DlByteBufr[1]) << 16) | + (((DSP_ADDRESS) DlByteBufr[2]) << 8) | + ((DSP_ADDRESS) DlByteBufr[3]); + WordCount = (((unsigned int) DlByteBufr[4]) << 8) | + ((unsigned int) DlByteBufr[5]); + + /* Check for the End Of File record. */ + if (DlByteBufr[0] == 0xFF) + break; + + /* Verify the record is for a valid memory type. */ + if ((DlByteBufr[0] != 0x00) && (DlByteBufr[0] != 0x01)) + { + RetStatus = GdlInvalidFile; + break; + } + + /* Read a block of words at a time from the file and write to the + DSP's memory .*/ + while (WordCount != 0) + { + if (WordCount < DOWNLOAD_BLOCK_SIZE) + NumWords = WordCount; + else + NumWords = DOWNLOAD_BLOCK_SIZE; + WordCount -= NumWords; + NumRead = gpakReadFile(FileId, DlByteBufr, NumWords * 2); + if (NumRead == -1) + { + RetStatus = GdlFileReadError; + break; + } + if (NumRead != (NumWords * 2)) + { + RetStatus = GdlInvalidFile; + break; + } + for (i = 0, j = 0; i < NumWords; i++, j += 2) + DlWordBufr[i] = (((DSP_WORD) DlByteBufr[j]) << 8) | + ((DSP_WORD) DlByteBufr[j + 1]); + gpakWriteDspMemory(DspId, Address, NumWords, DlWordBufr); + Address += ((DSP_ADDRESS) NumWords); + } + } + + /* Unlock access to the DSP. */ + gpakUnlockAccess(DspId); + + /* Return with an indication of success or failure. */ + return (RetStatus); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadCpuUsage - Read CPU usage statistics from a DSP. + * + * FUNCTION + * This function reads the memory map register section of DSP memory. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( + unsigned short int DspId, // Dsp Identifier + unsigned short int *pDest, // Buffer on host to hold DSP memory map + DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out + unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP reply's status */ + int i; /* loop index / counter */ + + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RmmInvalidDsp); + + /* Verify the message buffer is large enough */ + if (MSG_BUFFER_SIZE < MemoryLength_Word16 ) + return (RmmSizeTooBig); + + MsgBuffer[0] = MSG_READ_DSP_MEMORY << 8; + MsgBuffer[1] = (DSP_WORD) ((BufrBaseAddress >> 16) & 0xFFFF); + MsgBuffer[2] = (DSP_WORD) (BufrBaseAddress & 0xFFFF); + MsgBuffer[3] = (DSP_WORD) MemoryLength_Word16; + + /* Attempt to send the Read memory section message to the DSP and receive it's + reply. */ + //need_reply_len; + if (!TransactCmd(DspId, MsgBuffer, 8, MSG_READ_DSP_MEMORY_REPLY, + (MemoryLength_Word16+2)*2, 0, 0) ) + return (RmmInvalidAddress); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus != 0) + return (RmmFailure); + + for (i = 0; i < MemoryLength_Word16; i++) + pDest[i] = (short int) MsgBuffer[2 + i]; + + + return (RmmSuccess); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakAccessGPIO - change Direction/read/write the GPIO on DSP + * + * FUNCTION + * This function read/write GPIO and change the GPIO direction + * + * + * RETURNS + * Status code indicating success or a specific error. + */ +gpakAccessGPIOStat_t gpakAccessGPIO( + unsigned short int DspId, // DSP identifier + GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read + unsigned short int *pGPIOValue // DSP software version + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (GPIOInvalidDsp); + + /* send value of 1, DSP increments it */ + MsgBuffer[0] = (MSG_ACCESSGPIO << 8); + MsgBuffer[1] = (DSP_WORD) ((gpakControlGPIO << 8) | (*pGPIOValue & 0xFF) ); + /* Attempt to send the ping message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ACCESSGPIO_REPLY, 6, 0, 0)) + return (GPIODspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + { + *pGPIOValue = MsgBuffer[2]; + return (GPIOSuccess); + } + else + return (GPIODspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakWriteSystemParms - Write a DSP's System Parameters. + * + * FUNCTION + * This function writes a DSP's System Parameters information. + * + * Note: + * Or-together the desired bit-mask #defines that are listed below. Only + * those algorithm parameters whose bit-mask is selected in the UpdateBits + * function parameter will be updated. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ + +gpakWriteSysParmsStatus_t gpakWriteSystemParms( + unsigned short int DspId, // DSP identifier + GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ + unsigned short int UpdateBits, /* input: flags indicating which parms to update */ + GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ + ) +{ + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + DSP_WORD DspStatus; /* DSP's reply status */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (WspInvalidDsp); + + /* Build the Write System Parameters message. */ + MsgBuffer[0] = MSG_WRITE_SYS_PARMS << 8; + + if (UpdateBits & DTMF_UPDATE_MASK) + { + MsgBuffer[1] |= DTMF_UPDATE_MASK; + MsgBuffer[8] = (DSP_WORD) pSysParms->MinSigLevel; + MsgBuffer[9] = (DSP_WORD) (pSysParms->FreqDeviation & 0xff); + if (pSysParms->SNRFlag) + MsgBuffer[9] |= (1<<8); + } + + MsgBuffer[10] = (DSP_WORD) 0; + if (UpdateBits & DTMF_TWIST_UPDATE_MASK) + { + MsgBuffer[1] |= DTMF_TWIST_UPDATE_MASK; + MsgBuffer[10] |= (DSP_WORD) (pSysParms->DtmfFwdTwist & 0x000f); + MsgBuffer[10] |= (DSP_WORD) ((pSysParms->DtmfRevTwist << 4) & 0x00f0); + } + + + if (UpdateBits & DTMF_VALID_MASK) + { + MsgBuffer[1] |= DTMF_VALID_MASK; + MsgBuffer[11] = (DSP_WORD) (pSysParms->DtmfValidityMask & 0x00ff); + } + + /* Attempt to send the ping message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, 24, MSG_WRITE_SYS_PARMS_REPLY, 6, 0, 0)) + return (WspDspCommFailure); + + /* Return with an indication of success or failure based on the return + status in the reply message. */ + *pStatus = (GPAK_SysParmsStat_t) (MsgBuffer[2] ); + + DspStatus = (MsgBuffer[1] & 0xFF); + if (DspStatus == 0) + return (WspSuccess); + else + return (WspDspCommFailure); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadSystemParms - Read a DSP's System Parameters. + * + * FUNCTION + * This function reads a DSP's System Parameters information. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +gpakReadSysParmsStatus_t gpakReadSystemParms( + unsigned short int DspId, // DSP identifier + GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ + ) +{ + + DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ + + /* Make sure the DSP Id is valid. */ + if (DspId >= MAX_DSP_CORES) + return (RspInvalidDsp); + + /* Build the Read System Parameters message. */ + MsgBuffer[0] = MSG_READ_SYS_PARMS << 8; + + /* Attempt to send the ping message to the DSP and receive it's + reply. */ + if (!TransactCmd(DspId, MsgBuffer, 2, MSG_READ_SYS_PARMS_REPLY, 22, 0, 0)) + return (RspDspCommFailure); + + /* Extract the System Parameters information from the message. */ + pSysParms->DtmfValidityMask = (short int)(MsgBuffer[7]) ; + + pSysParms->MinSigLevel = (short int)MsgBuffer[8]; + pSysParms->SNRFlag = (short int)((MsgBuffer[9]>>8) & 0x1); + pSysParms->FreqDeviation = (short int)(MsgBuffer[9] & 0xff); + pSysParms->DtmfFwdTwist = (short int)MsgBuffer[10] & 0x000f; + pSysParms->DtmfRevTwist = (short int)(MsgBuffer[10] >> 4) & 0x000f; + + /* Return with an indication that System Parameters info was obtained. */ + return (RspSuccess); +} +#endif diff --git a/kernel/wcte12xp/GpakApi.h b/kernel/wcte12xp/GpakApi.h new file mode 100644 index 0000000..e676b32 --- /dev/null +++ b/kernel/wcte12xp/GpakApi.h @@ -0,0 +1,637 @@ +/* + * Copyright (c) 2005 , Adaptive Digital Technologies, Inc. + * + * File Name: GpakApi.h + * + * Description: + * This file contains the function prototypes and data types for the user + * API functions that communicate with DSPs executing G.PAK software. The + * file is used by application software in the host processor connected to + * C55X G.PAK DSPs via a Host Port Interface. + * + * Version: 1.0 + * + * Revision History: + * 06/15/05 - Initial release. + * 11/15/2006 - 24 TDM-TDM Channels EC release + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. The standard + * GPL disclaimer is given inline below for your convenience. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GPAKAPI_H /* prevent multiple inclusion */ +#define _GPAKAPI_H +#include "GpakErrs.h" +#include "gpakenum.h" + +// Bit masks to select which algorithm's parameters to update: Or-together the +// desired masks into the UpdateBits function parameter. +#define DTMF_UPDATE_MASK 0x0010 // update DTMF params, MinLevel, SNRFlag and Freq +#define DTMF_TWIST_UPDATE_MASK 0x0020 // update DTMF TWIST system params +#define DTMF_VALID_MASK 0x0080 // update DTMF ValidMask params + +#define DSP_DEBUG_BUFF_SIZE 42 // units of 16-bit words + +/* Definition of an Asynchronous Event Data Structure */ +typedef union +{ + struct + { + GpakToneCodes_t ToneCode; // detected tone code + unsigned short int ToneDuration; // tone duration + GpakTdmDirection Direction; // detected on A r B side + short int DebugToneStatus;// reserved for debug info + } toneEvent; + +} GpakAsyncEventData_t; + +/* Definition of an Echo Canceller Parameters information structure. */ +typedef struct +{ + short int EcanTapLength; // Echo Can Num Taps (tail length) + short int EcanNlpType; // Echo Can NLP Type + short int EcanAdaptEnable; // Echo Can Adapt Enable flag + short int EcanG165DetEnable; // Echo Can G165 Detect Enable flag + short int EcanDblTalkThresh; // Echo Can Double Talk threshold + short int EcanNlpThreshold; // Echo Can NLP threshold + short int EcanNlpConv; // Dynamic NLP control, NLP limit when EC about to converged + short int EcanNlpUnConv;// Dynamic NLP control, NLP limit when EC not converged yet + short int EcanNlpMaxSuppress; // suppression level for NLP_SUPP mode + short int EcanCngThreshold; // Echo Can CNG Noise threshold + short int EcanAdaptLimit; // Echo Can Max Adapts per frame + short int EcanCrossCorrLimit; // Echo Can Cross Correlation limit + short int EcanNumFirSegments; // Echo Can Num FIR Segments + short int EcanFirSegmentLen; // Echo Can FIR Segment Length +} GpakEcanParms_t; + +/* Definition of a Channel Configuration information structure. */ +typedef struct +{ + GpakSerialPort_t PcmInPortA; // A side PCM Input Serial Port Id + unsigned short int PcmInSlotA; // A side PCM Input Time Slot + GpakSerialPort_t PcmOutPortA; // A side PCM Output Serial Port Id + unsigned short int PcmOutSlotA; // A side PCM Output Time Slot + GpakSerialPort_t PcmInPortB; // B side PCM Input Serial Port Id + unsigned short int PcmInSlotB; // B side PCM Input Time Slot + GpakSerialPort_t PcmOutPortB; // B side PCM Output Serial Port Id + unsigned short int PcmOutSlotB; // B side PCM Output Time Slot + GpakToneTypes ToneTypesA; // A side Tone Detect Types + GpakToneTypes ToneTypesB; // B side Tone Detect Types + GpakActivation EcanEnableA; // Echo Cancel A Enabled + GpakActivation EcanEnableB; // Echo Cancel B Enabled + GpakEcanParms_t EcanParametersA; // Echo Cancel parameters + GpakEcanParms_t EcanParametersB; // Echo Cancel parameters + GpakCompandModes SoftwareCompand; // software companding + GpakRate_t FrameRate; // Gpak Frame Rate + GpakActivation MuteToneA; // A side mute DTMF Enabled + GpakActivation MuteToneB; // B side mute DTMF Enabled + GpakActivation FaxCngDetA; // A side FaxCng Tone Detector Enabled + GpakActivation FaxCngDetB; // B side FaxCng Tone Detector Enabled + +} GpakChannelConfig_t; + + +/* Definition of a Serial Port Configuration Structure */ +typedef struct +{ + GpakSlotCfg_t SlotsSelect1; // port 1 Slot selection + unsigned short int FirstBlockNum1; // port 1 first group Block Number + unsigned short int FirstSlotMask1; // port 1 first group Slot Mask + unsigned short int SecBlockNum1; // port 1 second group Block Number + unsigned short int SecSlotMask1; // port 1 second group Slot Mask + + GpakSerWordSize_t SerialWordSize1; // port 1 serial word size + GpakCompandModes CompandingMode1; // port 1 companding mode + GpakSerFrameSyncPol_t TxFrameSyncPolarity1; // port 1 Tx Frame Sync Polarity + GpakSerFrameSyncPol_t RxFrameSyncPolarity1; // port 1 Rx Frame Sync Polarity + GpakSerClockPol_t TxClockPolarity1; // port 1 Tx Clock Polarity + GpakSerClockPol_t RxClockPolarity1; // port 1 Rx Clock Polarity + GpakSerDataDelay_t TxDataDelay1; // port 1 Tx data delay + GpakSerDataDelay_t RxDataDelay1; // port 1 Rx data delay + GpakActivation DxDelay1; // port 1 DX Delay + + unsigned short int ThirdSlotMask1; // port 1 3rd group Slot Mask + unsigned short int FouthSlotMask1; // port 1 4th group Slot Mask + unsigned short int FifthSlotMask1; // port 1 5th group Slot Mask + unsigned short int SixthSlotMask1; // port 1 6th group Slot Mask + unsigned short int SevenSlotMask1; // port 1 7th group Slot Mask + unsigned short int EightSlotMask1; // port 1 8th group Slot Mask + + + GpakSlotCfg_t SlotsSelect2; // port 2 Slot selection + unsigned short int FirstBlockNum2; // port 2 first group Block Number + unsigned short int FirstSlotMask2; // port 2 first group Slot Mask + unsigned short int SecBlockNum2; // port 2 second group Block Number + unsigned short int SecSlotMask2; // port 2 second group Slot Mask + GpakSerWordSize_t SerialWordSize2; // port 2 serial word size + GpakCompandModes CompandingMode2; // port 2 companding mode + GpakSerFrameSyncPol_t TxFrameSyncPolarity2; // port 2 Tx Frame Sync Polarity + GpakSerFrameSyncPol_t RxFrameSyncPolarity2; // port 2 Rx Frame Sync Polarity + GpakSerClockPol_t TxClockPolarity2; // port 2 Tx Clock Polarity + GpakSerClockPol_t RxClockPolarity2; // port 2 Rx Clock Polarity + GpakSerDataDelay_t TxDataDelay2; // port 2 Tx data delay + GpakSerDataDelay_t RxDataDelay2; // port 2 Rx data delay + GpakActivation DxDelay2; // port 2 DX Delay + + unsigned short int ThirdSlotMask2; // port 2 3rd group Slot Mask + unsigned short int FouthSlotMask2; // port 2 4th group Slot Mask + unsigned short int FifthSlotMask2; // port 2 5th group Slot Mask + unsigned short int SixthSlotMask2; // port 2 6th group Slot Mask + unsigned short int SevenSlotMask2; // port 2 7th group Slot Mask + unsigned short int EightSlotMask2; // port 2 8th group Slot Mask + + GpakSlotCfg_t SlotsSelect3; // port 3 Slot selection + unsigned short int FirstBlockNum3; // port 3 first group Block Number + unsigned short int FirstSlotMask3; // port 3 first group Slot Mask + unsigned short int SecBlockNum3; // port 3 second group Block Number + unsigned short int SecSlotMask3; // port 3 second group Slot Mask + GpakSerWordSize_t SerialWordSize3; // port 3 serial word size + GpakCompandModes CompandingMode3; // port 3 companding mode + GpakSerFrameSyncPol_t TxFrameSyncPolarity3; // port 3 Tx Frame Sync Polarity + GpakSerFrameSyncPol_t RxFrameSyncPolarity3; // port 3 Rx Frame Sync Polarity + GpakSerClockPol_t TxClockPolarity3; // port 3 Tx Clock Polarity + GpakSerClockPol_t RxClockPolarity3; // port 3 Rx Clock Polarity + GpakSerDataDelay_t TxDataDelay3; // port 3 Tx data delay + GpakSerDataDelay_t RxDataDelay3; // port 3 Rx data delay + GpakActivation DxDelay3; // port 3 DX Delay + + unsigned short int ThirdSlotMask3; // port 3 3rd group Slot Mask + unsigned short int FouthSlotMask3; // port 3 4th group Slot Mask + unsigned short int FifthSlotMask3; // port 3 5th group Slot Mask + unsigned short int SixthSlotMask3; // port 3 6th group Slot Mask + unsigned short int SevenSlotMask3; // port 3 7th group Slot Mask + unsigned short int EightSlotMask3; // port 3 8th group Slot Mask + +} GpakPortConfig_t; + +/* Definition of a Tone Generation Parameter Structure */ +/* +typedef struct +{ + GpakToneGenType_t ToneType; // Tone Type + unsigned short int Frequency[4]; // Frequency (Hz) + short int Level[4]; // Frequency's Level (1 dBm) + unsigned short int OnTime[4]; // On Times (msecs) + unsigned short int OffTime[4]; // Off Times (msecs) +} GpakToneGenParms_t; +*/ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakConfigureChannel return status. */ +typedef enum +{ + CcsSuccess = 0, /* Channel Configured successfully */ + CcsParmError = 1, /* Channel Config Parameter error */ + CcsInvalidChannel = 2, /* invalid channel */ + CcsInvalidDsp = 3, /* invalid DSP */ + CcsDspCommFailure = 4 /* failed to communicate with DSP */ +} gpakConfigChanStatus_t; + +/* + * gpakConfigureChannel - Configure a DSP's Channel. + * + * FUNCTION + * This function configures a DSP's Channel. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +extern gpakConfigChanStatus_t gpakConfigureChannel( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GpakChanType ChannelType, // channel type + GpakChannelConfig_t *pChanConfig, // pointer to channel config info + GPAK_ChannelConfigStat_t *pStatus // pointer to Channel Config Status + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakTearDownChannel return status. */ +typedef enum +{ + TdsSuccess = 0, /* Channel Tear Down successful */ + TdsError = 1, /* Channel Tear Down error */ + TdsInvalidChannel = 2, /* invalid channel */ + TdsInvalidDsp = 3, /* invalid DSP */ + TdsDspCommFailure = 4 /* failed to communicate with DSP */ +} gpakTearDownStatus_t; + +/* + * gpakTearDownChannel - Tear Down a DSP's Channel. + * + * FUNCTION + * This function tears down a DSP's Channel. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ + +extern gpakTearDownStatus_t gpakTearDownChannel( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GPAK_TearDownChanStat_t *pStatus // pointer to Tear Down Status + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakAlgControl return status. */ +typedef enum +{ + AcSuccess = 0, /* control successful */ + AcInvalidChannel = 1, /* invalid channel identifier */ + AcInvalidDsp = 2, /* invalid DSP */ + AcParmError = 3, /* invalid control parameter */ + AcDspCommFailure = 4 /* failed to communicate with DSP */ +} gpakAlgControlStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakAlgControl - Control an Algorithm. + * + * FUNCTION + * This function controls an Algorithm + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +extern gpakAlgControlStat_t gpakAlgControl( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GpakAlgCtrl_t ControlCode, // algorithm control code + GPAK_AlgControlStat_t *pStatus // pointer to return status + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakConfigurePorts return status. */ +typedef enum +{ + CpsSuccess = 0, /* Serial Ports configured successfully */ + CpsParmError = 1, /* Configure Ports Parameter error */ + CpsInvalidDsp = 2, /* invalid DSP */ + CpsDspCommFailure = 3 /* failed to communicate with DSP */ +} gpakConfigPortStatus_t; + +/* + * gpakConfigurePorts - Configure a DSP's serial ports. + * + * FUNCTION + * This function configures a DSP's serial ports. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +extern gpakConfigPortStatus_t gpakConfigurePorts( + unsigned short int DspId, // DSP identifier + GpakPortConfig_t *pPortConfig, // pointer to Port Config info + GPAK_PortConfigStat_t *pStatus // pointer to Port Config Status + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakDownloadDsp return status. */ +typedef enum +{ + GdlSuccess = 0, /* DSP download successful */ + GdlFileReadError = 1, /* error reading Download file */ + GdlInvalidFile = 2, /* invalid Download file content */ + GdlInvalidDsp = 3 /* invalid DSP */ +} gpakDownloadStatus_t; + +/* + * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. + * + * FUNCTION + * This function reads a DSP's Program and Data memory image from the + * specified file and writes the image to the DSP's memory. + * + * RETURNS + * Status code indicating success or a specific error. + * + */ +extern gpakDownloadStatus_t gpakDownloadDsp( + unsigned short int DspId, // DSP identifier + GPAK_FILE_ID FileId // G.PAK download file identifier + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* gpakReadEventFIFOMessage return status */ +typedef enum +{ + RefEventAvail = 0, /* an event was successfully read from the fifo */ + RefNoEventAvail = 1, /* no event was in the fifo */ + RefInvalidDsp = 2, /* invalid DSP identifier */ + RefInvalidEvent = 3, /* invalid event */ + RefDspCommFailure = 4 /* error communicating with DSP */ +} gpakReadEventFIFOMessageStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadEventFIFOMessage - read from the event fifo + * + * FUNCTION + * This function reads a single event from the event fifo if one is available + * + * RETURNS + * Status code indicating success or a specific error. + * + * Note: This function should be called in a loop until the return status + * indicates that the fifo is empty. + */ +extern gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( + unsigned short int DspId, // DSP identifier + unsigned short int *pChannelId, // pointer to channel identifier + GpakAsyncEventCode_t *pEventCode, // pointer to Event Code + GpakAsyncEventData_t *pEventData // pointer to Event Data Struct + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakPingDsp return status values */ +typedef enum +{ + PngSuccess = 0, /* DSP responded successfully */ + PngInvalidDsp = 1, /* invalid DSP identifier */ + PngDspCommFailure = 2 /* error communicating with DSP */ +} gpakPingDspStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakPingDsp - ping the DSP to see if it's alive + * + * FUNCTION + * This function checks if the DSP is still communicating with the host + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakPingDspStat_t gpakPingDsp( + unsigned short int DspId, // DSP identifier + unsigned short int *pDspSwVersion // DSP software version + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakSerialTxFixedValue return status values */ +typedef enum +{ + TfvSuccess = 0, /* operation successful */ + TfvInvalidChannel = 1, /* invalid channel identifier */ + TfvInvalidDsp = 2, /* invalid DSP identifier */ + TfvDspCommFailure = 3 /* failed to communicate with DSP */ +} gpakSerialTxFixedValueStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakSerialTxFixedValue - transmit a fixed value on a timeslot + * + * FUNCTION + * This function controls transmission of a fixed value out onto a serial + * port's timeslot. + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( + unsigned short int DspId, // DSP identifier + unsigned short int ChannelId, // channel identifier + GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id + unsigned short int PcmOutSlot, // PCM Output Time Slot + unsigned short int Value, // 16-bit value + GpakActivation State // activation state + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakControlTdmLoopBack return status values */ +typedef enum +{ + ClbSuccess = 0, /* operation successful */ + ClbSerPortInactive = 1, /* serial port is inactive */ + ClbInvalidDsp = 2, /* invalid DSP identifier */ + ClbDspCommFailure = 3 /* failed to communicate with DSP */ +} gpakControlTdmLoopBackStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakControlTdmLoopBack - control a serial port's loopback state + * + * FUNCTION + * This function enables/disables the tdm input to output looback mode on a + * serial port + * + * RETURNS + * Status code indicating success or a specific error. + */ + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ +gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( + unsigned short int DspId, // DSP identifier + GpakSerialPort_t SerialPort, // Serial Port Id + GpakActivation LoopBackState // Loopback State + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakReadCpuUsage return status values */ +typedef enum +{ + RcuSuccess = 0, /* operation successful */ + RcuInvalidDsp = 1, /* invalid DSP identifier */ + RcuDspCommFailure = 2 /* communication failure */ +} gpakReadCpuUsageStat_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadCpuUsage - read the cpu usage statistics + * + * FUNCTION + * This function reads cpu utilization from the DSP. + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakReadCpuUsageStat_t gpakReadCpuUsage( + unsigned short int DspId, // DSP identifier + unsigned short int *pPeakUsage, // pointer to peak usage variable + unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakResetCpuUsageStats return status values */ +typedef enum +{ + RstcSuccess = 0, /* operation successful */ + RstcInvalidDsp = 1, /* invalid DSP identifier */ + RstcDspCommFailure = 2 /* communication failure */ +} gpakResetCpuUsageStat_t; +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakResetCpuUsageStats - reset the cpu usage statistics + * + * FUNCTION + * This function resets the cpu utilization statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakResetCpuUsageStat_t gpakResetCpuUsageStats( + unsigned short int DspId // DSP identifier + ); + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakReadFramingStats return status values */ +typedef enum +{ + RfsSuccess = 0, /* operation successful */ + RfsInvalidDsp = 1, /* invalid DSP identifier */ + RfsDspCommFailure = 2 /* communication failure */ +} gpakReadFramingStatsStatus_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadFramingStats + * + * FUNCTION + * This function reads a DSP's framing interrupt statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakReadFramingStatsStatus_t gpakReadFramingStats( + unsigned short int DspId, // DSP identifier + unsigned short int *pFramingError1Count, // port 1 Framing error count + unsigned short int *pFramingError2Count, // port 2 Framing error count + unsigned short int *pFramingError3Count, // port 3 Framing error count + unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count + unsigned short int *pDmaSlipStatsBuffer // DMA slips count + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/* gpakResetFramingStats return values */ +typedef enum +{ + RstfSuccess = 0, /* operation successful */ + RstfInvalidDsp = 1, /* invalid DSP identifier */ + RstfDspCommFailure = 2 /* communication failure */ +} gpakResetFramingStatsStatus_t; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakResetFramingStats - reset a DSP's framing interrupt statistics + * + * FUNCTION + * This function resets a DSP's framing interrupt statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ +extern gpakResetFramingStatsStatus_t gpakResetFramingStats( + unsigned short int DspId // DSP identifier + ); + + +typedef enum +{ + RmmSuccess =0, + RmmInvalidDsp = 1, + RmmSizeTooBig = 2, + RmmFailure = 3, + RmmInvalidAddress = 4 + +} gpakReadDSPMemoryStat_t; +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakResetFramingStats - read a section of DSP memory + * to get access DSP registers, since 0x00--0x60 not HPI-accessable + * + * FUNCTION + * This function resets a DSP's framing interrupt statistics + * + * RETURNS + * Status code indicating success or a specific error. + */ + +extern gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( + unsigned short int DspId, // Dsp Identifier + unsigned short int *pDest, // Buffer on host to hold DSP memory map + DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out + unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word + ); + +typedef enum +{ + GPIOSuccess =0, + GPIOInvalidDsp = 1, + GPIODspCommFailure = 2 +}gpakAccessGPIOStat_t; + +extern gpakAccessGPIOStat_t gpakAccessGPIO( + unsigned short int DspId, // DSP identifier + GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read + unsigned short int *pGPIOValue // pointer for the read/write value or DIR mask + ); + +/* gpakWriteSystemParms return status. */ +typedef enum +{ + WspSuccess = 0, /* System Parameters written successfully */ + WspParmError = 1, /* Write System Parms's Parameter error */ + WspInvalidDsp = 2, /* invalid DSP */ + WspDspCommFailure = 3 /* failed to communicate with DSP */ +} gpakWriteSysParmsStatus_t; + +/* Definition of a System Parameters information structure. */ +typedef struct +{ + /* DTMF Parameters */ + short int MinSigLevel; /* 0 = Disabled, Min Sig Power Level for detection */ + short int SNRFlag; /* 0 = Disabled, relax SNR tolerances */ + short int FreqDeviation; /* 0 = Disabled, X Percent Deviation times 10 (e.g. 1.7% is entered as 17) */ + short int DtmfFwdTwist; /* 0 to 8 db */ + short int DtmfRevTwist; /* 0 to 8 db */ + + short int DtmfValidityMask; /* This flag allows users to relax the trailing conditions of the tone */ + +} GpakSystemParms_t; +/* gpakReadSystemParms return status. */ +typedef enum +{ + RspSuccess = 0, /* System Parameters read successfully */ + RspInvalidDsp = 1, /* invalid DSP */ + RspDspCommFailure = 2 /* failed to communicate with DSP */ +} gpakReadSysParmsStatus_t; + +extern gpakReadSysParmsStatus_t gpakReadSystemParms( + unsigned short int DspId, // DSP identifier + GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ + ); + +extern gpakWriteSysParmsStatus_t gpakWriteSystemParms( + unsigned short int DspId, // DSP identifier + GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ + unsigned short int UpdateBits, /* input: flags indicating which parms to update */ + GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ + ); + +#endif // end multiple inclusion + diff --git a/kernel/wcte12xp/GpakErrs.h b/kernel/wcte12xp/GpakErrs.h new file mode 100644 index 0000000..3413f97 --- /dev/null +++ b/kernel/wcte12xp/GpakErrs.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2002 - 2004, Adaptive Digital Technologies, Inc. + * + * File Name: GpakErrs.h + * + * Description: + * This file contains DSP reply status codes used by G.PAK API functions to + * indicate specific errors. + * + * Version: 1.0 + * + * Revision History: + * 10/17/01 - Initial release. + * 07/03/02 - Updates for conferencing. + * 06/15/04 - Tone type updates. + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. The standard + * GPL disclaimer is given inline below for your convenience. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GPAKERRS_H /* prevent multiple inclusion */ +#define _GPAKERRS_H + +/* Configure Serial Ports reply status codes. */ +typedef enum +{ + Pc_Success = 0, /* serial ports configured successfully */ + Pc_ChannelsActive = 1, /* unable to configure while channels active */ + Pc_TooManySlots1 = 2, /* too many slots selected for port 1 */ + Pc_InvalidBlockCombo1 = 3, /* invalid combination of blocks for port 1 */ + Pc_NoSlots1 = 4, /* no slots selected for port 1 */ + Pc_InvalidSlots1 = 5, /* invalid slot (> max) selected for port 1 */ + Pc_TooManySlots2 = 6, /* too many slots selected for port 2 */ + Pc_InvalidBlockCombo2 = 7, /* invalid combination of blocks for port 2 */ + Pc_NoSlots2 = 8, /* no slots selected for port 2 */ + Pc_InvalidSlots2 = 9, /* invalid slot (> max) selected for port 2 */ + Pc_TooManySlots3 = 10, /* too many slots selected for port 3 */ + Pc_InvalidBlockCombo3 = 11, /* invalid combination of blocks for port 3 */ + Pc_NoSlots3 = 12, /* no slots selected for port 3 */ + Pc_InvalidSlots3 = 13 /* invalid slot (> max) selected for port 3 */ +} GPAK_PortConfigStat_t; + +/* Configure Channel reply status codes. */ +typedef enum +{ + Cc_Success = 0, /* channel configured successfully */ + Cc_InvalidChannelType = 1, /* invalid Channel Type */ + Cc_InvalidChannel = 2, /* invalid Channel A Id */ + Cc_ChannelActiveA = 3, /* Channel A is currently active */ + Cc_InvalidInputPortA = 4, /* invalid Input A Port */ + Cc_InvalidInputSlotA = 5, /* invalid Input A Slot */ + Cc_BusyInputSlotA = 6, /* busy Input A Slot */ + Cc_InvalidOutputPortA = 7, /* invalid Output A Port */ + Cc_InvalidOutputSlotA = 8, /* invalid Output A Slot */ + Cc_BusyOutputSlotA = 9, /* busy Output A Slot */ + Cc_InvalidInputPortB = 10, /* invalid Input B Port */ + Cc_InvalidInputSlotB = 11, /* invalid Input B Slot */ + Cc_BusyInputSlotB = 12, /* busy Input B Slot */ + Cc_InvalidPktInCodingA = 13, /* invalid Packet In A Coding */ + Cc_InvalidPktOutCodingA = 14, /* invalid Packet Out A Coding */ + Cc_InvalidPktInSizeA = 15, /* invalid Packet In A Frame Size */ + Cc_InvalidPktOutSizeA = 16, /* invalid Packet Out A Frame Size */ + + Cc_ChanTypeNotConfigured = 21, /* channel type was not configured */ + Cc_InsuffECResources = 22, /* insufficient ecan resources avail. */ + Cc_InsuffTDMResources = 23, /* insufficient tdm block resources avail. */ + + Cc_InsuffPktBufResources = 25, /* insufficient pkt buffer resources avail. */ + Cc_InsuffPcmBufResources = 26, /* insufficient pcm buffer resources avail. */ + + Cc_BadPcmEcNlpType = 30, /* invalid EC Nlp type */ + Cc_BadPcmEcTapLength = 31, /* invalid EC tap length */ + Cc_BadPcmEcDblTalkThresh = 32, /* invalid EC double-talk threshold */ + Cc_BadPcmEcNlpThreshold = 33, /* invalid EC Nlp threshold */ + Cc_BadPcmEcCngThreshold = 34, /* invalid EC Cng threshold */ + Cc_BadPcmEcAdaptLimit = 35, /* invalid EC Adapt Limit */ + Cc_BadPcmEcCrossCorrLim = 36, /* invalid EC Cross Correlation Limit */ + Cc_BadPcmEcNumFirSegs = 37, /* invalid EC Number of FirSegments */ + Cc_BadPcmEcFirSegLen = 38, /* invalid EC Fir Segment Length */ + + /*Cc_InvalidNumEcsEnabled = 48, */ /* more than 1 Ec enabled on channel */ + Cc_InvalidFrameRate = 49, /* invalid gpak frame rate */ + Cc_InvalidSoftCompand = 50, /* invalid softCompanding type */ + + Cc_InvalidMuteToneA = 51, /* invalid MuteToneA set, no detector */ + Cc_InvalidMuteToneB = 52, /* invalid MuteToneB set, no detector */ + Cc_InsuffFaxCngDetResources = 53 /* insufficient tdm block resources avail. */ + +} GPAK_ChannelConfigStat_t; + +/* Tear Down Channel reply status codes. */ +typedef enum +{ + Td_Success = 0, /* channel torn down successfully */ + Td_InvalidChannel = 1, /* invalid Channel Id */ + Td_ChannelNotActive = 2 /* channel is not active */ +} GPAK_TearDownChanStat_t; + + +typedef enum +{ + Ac_Success = 0, /* algorithm control is successfull */ + Ac_InvalidChannel = 1, /* invalid channel identifier */ + Ac_InvalidCode = 2, /* invalid algorithm control code */ + Ac_ECNotEnabled = 3, /* echo canceller was not allocated */ + Ac_InvalidSoftComp = 4, /* invalid softcompanding, 'cause serial port not in companding mode */ + Ac_InvalidDTMFMuteA = 5, /* A side invalid Mute, since no dtmf detector */ + Ac_InvalidDTMFMuteB = 6, /* B side invalid Mute, since no dtmf detector */ + Ac_InvalidFaxCngA = 7, /* A side FAXCNG detector not available */ + Ac_InvalidFaxCngB = 8, /* B side FAXCNG detector not available */ + Ac_InvalidSysConfig = 9 /* No new system parameters (DTMF config) wrriten yet */ +} GPAK_AlgControlStat_t; + +/* Write System Parameters reply status codes. */ +typedef enum +{ + Sp_Success = 0, /* System Parameters written successfully */ + Sp_BadTwistThresh = 29 /* invalid twist threshold */ + +} GPAK_SysParmsStat_t; + +#endif /* prevent multiple inclusion */ + + + + + + + + + + + + + + + + + + + diff --git a/kernel/wcte12xp/GpakHpi.h b/kernel/wcte12xp/GpakHpi.h new file mode 100644 index 0000000..790bb3c --- /dev/null +++ b/kernel/wcte12xp/GpakHpi.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2001, Adaptive Digital Technologies, Inc. + * + * File Name: GpakHpi.h + * + * Description: + * This file contains common definitions related to the G.PAK interface + * between a host processor and a DSP processor via the Host Port Interface. + * + * Version: 1.0 + * + * Revision History: + * 10/17/01 - Initial release. + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. The standard + * GPL disclaimer is given inline below for your convenience. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GPAKHPI_H /* prevent multiple inclusion */ +#define _GPAKHPI_H + + +/* Definition of G.PAK Command/Reply message type codes. */ +#define MSG_NULL_REPLY 0 /* Null Reply (unsupported Command) */ +#define MSG_SYS_CONFIG_RQST 1 /* System Configuration Request */ +#define MSG_SYS_CONFIG_REPLY 2 /* System Configuration Reply */ +#define MSG_READ_SYS_PARMS 3 /* Read System Parameters */ +#define MSG_READ_SYS_PARMS_REPLY 4 /* Read System Parameters Reply */ +#define MSG_WRITE_SYS_PARMS 5 /* Write System Parameters */ +#define MSG_WRITE_SYS_PARMS_REPLY 6 /* Write System Parameters Reply */ +#define MSG_CONFIGURE_PORTS 7 /* Configure Serial Ports */ +#define MSG_CONFIG_PORTS_REPLY 8 /* Configure Serial Ports Reply */ +#define MSG_CONFIGURE_CHANNEL 9 /* Configure Channel */ +#define MSG_CONFIG_CHAN_REPLY 10 /* Configure Channel Reply */ +#define MSG_TEAR_DOWN_CHANNEL 11 /* Tear Down Channel */ +#define MSG_TEAR_DOWN_REPLY 12 /* Tear Down Channel Reply */ +#define MSG_CHAN_STATUS_RQST 13 /* Channel Status Request */ +#define MSG_CHAN_STATUS_REPLY 14 /* Channel Status Reply */ + +#define MSG_TEST_MODE 17 /* Configure/Perform Test Mode */ +#define MSG_TEST_REPLY 18 /* Configure/Perform Test Mode Reply */ + +#define MSG_ALG_CONTROL 27 /* algorithm control */ +#define MSG_ALG_CONTROL_REPLY 28 /* algorithm control reply */ +#define MSG_GET_TXCID_ADDRESS 29 /* get tx cid buffer start address */ +#define MSG_GET_TXCID_ADDRESS_REPLY 30 /* get tx cid buffer start addr reply */ + +#define MSG_PING 35 /* ping command */ +#define MSG_PING_REPLY 36 /* ping command reply */ +#define MSG_SERIAL_TXVAL 37 /* transmit serial fixed value */ +#define MSG_SERIAL_TXVAL_REPLY 38 /* transmit serial fixed value reply */ +#define MSG_TDM_LOOPBACK 39 /* tdm loopback control */ +#define MSG_TDM_LOOPBACK_REPLY 40 /* tdm loopback control reply */ +#define MSG_RESET_USAGE_STATS 41 /* reset cpu usage stats */ +#define MSG_RESET_USAGE_STATS_REPLY 42 /* reset cpu usage stats reply */ + +#define MSG_RESET_FRAME_STATS 47 /* reset framing stats */ +#define MSG_RESET_FRAME_STATS_REPLY 48 /* reset framing stats reply */ + +#define MSG_READ_DSP_MEMORY 49 /* read small section of DSP's memory */ +#define MSG_READ_DSP_MEMORY_REPLY 50 /* read memory reply */ + +#define MSG_ACCESSGPIO 51 +#define MSG_ACCESSGPIO_REPLY 52 +#endif /* prevent multiple inclusion */ diff --git a/kernel/wcte12xp/Kbuild b/kernel/wcte12xp/Kbuild new file mode 100644 index 0000000..b145e6a --- /dev/null +++ b/kernel/wcte12xp/Kbuild @@ -0,0 +1,25 @@ +obj-m += wcte12xp.o + +FIRM_DIR := ../../firmware + +EXTRA_CFLAGS := -I$(src)/.. -Wno-undef + +ifeq ($(HOTPLUG_FIRMWARE),yes) + EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE +endif + +wcte12xp-objs := base.o vpmadt032.o GpakApi.o + +ifneq ($(HOTPLUG_FIRMWARE),yes) +wcte12xp-objs += $(FIRM_DIR)/zaptel-fw-vpmadt032.o +endif + +$(obj)/$(FIRM_DIR)/zaptel-fw-vpmadt032.o: $(obj)/base.o + $(MAKE) -C $(obj)/$(FIRM_DIR) zaptel-fw-vpmadt032.o + +$(obj)/base.o: $(src)/vpmadt032.h $(src)/wcte12xp.h +$(obj)/base.o: $(src)/../zaptel.h + +$(obj)/vpmadt032.o: $(src)/vpmadt032.h + +$(obj)/GpakApi.o: $(src)/GpakApi.h diff --git a/kernel/wcte12xp/Makefile b/kernel/wcte12xp/Makefile new file mode 100644 index 0000000..fb0fbc5 --- /dev/null +++ b/kernel/wcte12xp/Makefile @@ -0,0 +1,25 @@ +ifneq ($(KBUILD_EXTMOD),) +# We only get here on kernels 2.6.0-2.6.9 . +# For newer kernels, Kbuild will be included directly by the kernel +# build system. +include $(src)/Kbuild + +else + +# building for 2.4 kernels means no VPM support, so none of the VPM support +# modules are included in the Makefile rules + +all: wcte12xp.o + +%.o: %.c + $(CC) $(KFLAGS) -o $@ -c $< + +base.o: ../zaptel.h + +wcte12xp.o: base.o + $(LD) -r -o $@ $^ + +clean: + rm -f *.o + +endif diff --git a/kernel/wcte12xp/base.c b/kernel/wcte12xp/base.c new file mode 100644 index 0000000..5dd83db --- /dev/null +++ b/kernel/wcte12xp/base.c @@ -0,0 +1,2139 @@ +/* + * Digium, Inc. Wildcard TE12xP T1/E1 card Driver + * + * Written by Michael Spiceland + * + * Adapted from the wctdm24xxp and wcte11xp drivers originally + * written by Mark Spencer + * Matthew Fredrickson + * William Meadows + * + * Copyright (C) 2007, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef LINUX26 +#include +#endif + +#include "zaptel.h" + +#include "../wct4xxp/wct4xxp.h" /* For certain definitions */ + +#include "wcte12xp.h" + +#if defined(VPM_SUPPORT) +#include "vpmadt032.h" +#include "GpakApi.h" +#endif + +struct pci_driver te12xp_driver; + +static int chanmap_t1[] = +{ 2,1,0, + 6,5,4, + 10,9,8, + 14,13,12, + 18,17,16, + 22,21,20, + 26,25,24, + 30,29,28 }; + +static int chanmap_e1[] = +{ 2,1,0, + 7,6,5,4, + 11,10,9,8, + 15,14,13,12, + 19,18,17,16, + 23,22,21,20, + 27,26,25,24, + 31,30,29,28 }; + +static int chanmap_e1uc[] = +{ 3,2,1,0, + 7,6,5,4, + 11,10,9,8, + 15,14,13,12, + 19,18,17,16, + 23,22,21,20, + 27,26,25,24, + 31,30,29,28 }; + +int debug = 0; +static int j1mode = 0; +static int alarmdebounce = 0; +static int loopback = 0; +static int t1e1override = -1; +static int unchannelized = 0; +#ifdef VPM_SUPPORT +int vpmsupport = 1; +int vpmdtmfsupport = 0; +int vpmtsisupport = 0; +int vpmnlptype = 1; +int vpmnlpthresh = 24; +int vpmnlpmaxsupp = 0; +#endif + +struct t1 *ifaces[WC_MAX_IFACES]; +spinlock_t ifacelock = SPIN_LOCK_UNLOCKED; + +struct t1_desc { + char *name; + int flags; +}; + +static struct t1_desc te120p = { "Wildcard TE120P", 0 }; +static struct t1_desc te122 = { "Wildcard TE122", 0 }; +static struct t1_desc te121 = { "Wildcard TE121", 0 }; + +int schluffen(wait_queue_head_t *q) +{ + DECLARE_WAITQUEUE(wait, current); + add_wait_queue(q, &wait); + current->state = TASK_INTERRUPTIBLE; + if (!signal_pending(current)) schedule(); + current->state = TASK_RUNNING; + remove_wait_queue(q, &wait); + if (signal_pending(current)) return -ERESTARTSYS; + return(0); +} + +static inline int empty_slot(struct t1 *wc) +{ + unsigned int x; + + for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { + if (!wc->cmdq.cmds[x].flags && !wc->cmdq.cmds[x].address) + return x; + } + return -1; +} + +static inline void __t1_setctl(struct t1 *wc, unsigned int addr, unsigned int val) +{ + outl(val, wc->iobase + addr); +} + +static inline void t1_setctl(struct t1 *wc, unsigned int addr, unsigned int val) +{ + unsigned long flags; + + spin_lock_irqsave(&wc->reglock, flags); + __t1_setctl(wc, addr, val); + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static inline unsigned int __t1_getctl(struct t1 *wc, unsigned int addr) +{ + return inl(wc->iobase + addr); +} + +static inline unsigned int t1_getctl(struct t1 *wc, unsigned int addr) +{ + unsigned long flags; + unsigned int val; + + spin_lock_irqsave(&wc->reglock, flags); + val = __t1_getctl(wc, addr); + spin_unlock_irqrestore(&wc->reglock, flags); + + return val; +} + +static void t1_init_descriptors(struct t1 *wc) +{ + volatile unsigned int *descrip; + dma_addr_t descripdma; + dma_addr_t writedma; + dma_addr_t readdma; + int x; + + descrip = wc->descripchunk; + descripdma = wc->descripdma; + writedma = wc->writedma; + readdma = wc->readdma; + + for (x = 0; x < ERING_SIZE; x++) { + if (x < ERING_SIZE - 1) + descripdma += 16; + else + descripdma = wc->descripdma; + + /* Transmit descriptor */ + descrip[0] = 0x80000000; + descrip[1] = 0xe5800000 | (SFRAME_SIZE); + if (x % 2) + descrip[2] = writedma + SFRAME_SIZE; + else + descrip[2] = writedma; + descrip[3] = descripdma; + + /* Receive descriptor */ + descrip[0 + ERING_SIZE * 4] = 0x80000000; + descrip[1 + ERING_SIZE * 4] = 0x01000000 | (SFRAME_SIZE); + if (x % 2) + descrip[2 + ERING_SIZE * 4] = readdma + SFRAME_SIZE; + else + descrip[2 + ERING_SIZE * 4] = readdma; + descrip[3 + ERING_SIZE * 4] = descripdma + ERING_SIZE * 16; + + /* Advance descriptor */ + descrip += 4; + } +} + +static inline void t1_reinit_descriptor(struct t1 *wc, int tx, int dbl, char *s) +{ + int o2 = dbl * 4; + + if (!tx) + o2 += ERING_SIZE * 4; + + wc->descripchunk[o2] = 0x80000000; +} + +static inline void cmd_dequeue(struct t1 *wc, volatile unsigned char *writechunk, int eframe, int slot) +{ + struct command *curcmd=NULL; + unsigned int x; + + /* Skip audio */ + writechunk += 66; + /* Search for something waiting to transmit */ + if ((slot < 6) && (eframe) && (eframe < ZT_CHUNKSIZE - 1)) { + /* only 6 useable cs slots per */ + + /* framer */ + for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { + if ((wc->cmdq.cmds[x].flags & (__CMD_RD | __CMD_WR | __CMD_LEDS | __CMD_PINS)) && + !(wc->cmdq.cmds[x].flags & (__CMD_TX | __CMD_FIN))) { + curcmd = &wc->cmdq.cmds[x]; + wc->cmdq.cmds[x].flags |= __CMD_TX; + wc->cmdq.cmds[x].ident = wc->txident; + break; + } + } + if (!curcmd) { + curcmd = &wc->dummy; + /* If nothing else, use filler */ + curcmd->address = 0x4a; + curcmd->data = 0x00; + curcmd->flags = __CMD_RD; + } + curcmd->cs_slot = slot; + if (curcmd->flags & __CMD_WR) + writechunk[CMD_BYTE(slot,0,0)] = 0x0c; /* 0c write command */ + else if (curcmd->flags & __CMD_LEDS) + writechunk[CMD_BYTE(slot,0,0)] = 0x10 | ((curcmd->address) & 0x0E); /* led set command */ + else if (curcmd->flags & __CMD_PINS) + writechunk[CMD_BYTE(slot,0,0)] = 0x30; /* CPLD2 pin state */ + else + writechunk[CMD_BYTE(slot,0,0)] = 0x0a; /* read command */ + writechunk[CMD_BYTE(slot,1,0)] = curcmd->address; + writechunk[CMD_BYTE(slot,2,0)] = curcmd->data; + } + +} + +static inline void cmd_decipher(struct t1 *wc, volatile unsigned char *readchunk) +{ + unsigned char ident, cs_slot; + unsigned int x; + unsigned int is_vpm = 0; + + /* Skip audio */ + readchunk += 66; + /* Search for any pending results */ + for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { + if ((wc->cmdq.cmds[x].flags & (__CMD_RD | __CMD_WR | __CMD_LEDS | __CMD_PINS)) && + (wc->cmdq.cmds[x].flags & (__CMD_TX)) && + !(wc->cmdq.cmds[x].flags & (__CMD_FIN))) { + ident = wc->cmdq.cmds[x].ident; + cs_slot = wc->cmdq.cmds[x].cs_slot; + + if (ident == wc->rxident) { + /* Store result */ + wc->cmdq.cmds[x].data |= readchunk[CMD_BYTE(cs_slot,2,is_vpm)]; + /*printk("answer in rxident=%d cs_slot=%d is %d CMD_BYTE=%d jiffies=%d\n", ident, cs_slot, last_read_command, CMD_BYTE(cs_slot, 2), jiffies); */ + wc->cmdq.cmds[x].flags |= __CMD_FIN; + if (wc->cmdq.cmds[x].flags & (__CMD_WR | __CMD_LEDS)) + /* clear out writes (and leds) since they need no ack */ + memset(&wc->cmdq.cmds[x], 0, sizeof(wc->cmdq.cmds[x])); + } + } + } +} + +static inline unsigned int __t1_sdi_clk(struct t1 *wc) +{ + unsigned int ret; + + wc->sdi &= ~SDI_CLK; + __t1_setctl(wc, 0x0048, wc->sdi); + ret = __t1_getctl(wc, 0x0048); + wc->sdi |= SDI_CLK; + __t1_setctl(wc, 0x0048, wc->sdi); + return ret & SDI_DIN; +} + +static inline void __t1_sdi_sendbits(struct t1 *wc, unsigned int bits, int count) +{ + wc->sdi &= ~SDI_DREAD; + __t1_setctl(wc, 0x0048, wc->sdi); + while (count--) { + if (bits & (1 << count)) + wc->sdi |= SDI_DOUT; + else + wc->sdi &= ~SDI_DOUT; + __t1_sdi_clk(wc); + } +} + +static inline unsigned int __t1_sdi_recvbits(struct t1 *wc, int count) +{ + unsigned int bits=0; + + wc->sdi |= SDI_DREAD; + __t1_setctl(wc, 0x0048, wc->sdi); + while (count--) { + bits <<= 1; + if (__t1_sdi_clk(wc)) + bits |= 1; + else + bits &= ~1; + } + return bits; +} + +static inline unsigned short __t1_getsdi(struct t1 *wc, unsigned char addr) +{ + unsigned int bits; + + /* Send preamble */ + bits = 0xffffffff; + __t1_sdi_sendbits(wc, bits, 32); + bits = (0x6 << 10) | (1 << 5) | (addr); + __t1_sdi_sendbits(wc, bits, 14); + + return __t1_sdi_recvbits(wc, 18); +} + +static inline unsigned short t1_getsdi(struct t1 *wc, unsigned char addr) +{ + unsigned long flags; + unsigned short val; + + spin_lock_irqsave(&wc->reglock, flags); + val = __t1_getsdi(wc, addr); + spin_unlock_irqrestore(&wc->reglock, flags); + + return val; +} + +static inline void __t1_setsdi(struct t1 *wc, unsigned char addr, unsigned short value) +{ + unsigned int bits; + + /* Send preamble */ + bits = 0xffffffff; + __t1_sdi_sendbits(wc, bits, 32); + bits = (0x5 << 12) | (1 << 7) | (addr << 2) | 0x2; + __t1_sdi_sendbits(wc, bits, 16); + __t1_sdi_sendbits(wc, value, 16); +} + +static inline void t1_setsdi(struct t1 *wc, unsigned char addr, unsigned short value) +{ + unsigned long flags; + + spin_lock_irqsave(&wc->reglock, flags); + __t1_setsdi(wc, addr, value); + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static inline int t1_setreg_full(struct t1 *wc, int addr, int val, int inisr, int vpm_num) +{ + unsigned long flags; + int hit; + int ret; + + + do { + if (!inisr) + spin_lock_irqsave(&wc->reglock, flags); + hit = empty_slot(wc); + if (hit > -1) { + wc->cmdq.cmds[hit].address = addr; + wc->cmdq.cmds[hit].data = val; + wc->cmdq.cmds[hit].flags |= __CMD_WR; + if(vpm_num >= 0) { + wc->cmdq.cmds[hit].flags |= __CMD_VPM; + wc->cmdq.cmds[hit].vpm_num = vpm_num; + } + } + if (inisr) + break; + + spin_unlock_irqrestore(&wc->reglock, flags); + if (hit < 0) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (hit < 0); + + return (hit > -1) ? 0 : -1; +} + +static inline int t1_setreg(struct t1 *wc, int addr, int val) +{ + return t1_setreg_full(wc, addr, val, 0, NOT_VPM); +} + +/*************************************************************************** + * clean_leftovers() + * + * Check for unconsumed isr register reads and clean them up. + **************************************************************************/ +static inline void clean_leftovers(struct t1 *wc) +{ + unsigned int x; + int count = 0; + + /* find our requested command */ + for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { + if ((wc->cmdq.cmds[x].flags & __CMD_RD) && + (wc->cmdq.cmds[x].flags & __CMD_ISR) && + !(wc->cmdq.cmds[x].flags & __CMD_FIN)) { + debug_printk(1,"leftover isr read! %d", count); + memset(&wc->cmdq.cmds[x], 0, sizeof(wc->cmdq.cmds[x])); + } + } +} + +/******************************************************************** + * t1_getreg_isr() + * + * Called in interrupt context to retrieve a value already requested + * by the normal t1_getreg(). + *******************************************************************/ +static inline int t1_getreg_isr(struct t1 *wc, int addr) +{ + int hit=-1; + int ret; + unsigned int x; + + /* find our requested command */ + for (x = 0;x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { + if ((wc->cmdq.cmds[x].flags & __CMD_RD) && + (wc->cmdq.cmds[x].flags & __CMD_FIN) && + (wc->cmdq.cmds[x].address==addr)) { + hit = x; + break; + } + } + + if (hit < 0) { + debug_printk(2, "t1_getreg_isr() no addr=%02x\n", addr); + return -1; /* oops, couldn't find it */ + } + + ret = wc->cmdq.cmds[hit].data; + memset(&wc->cmdq.cmds[hit], 0, sizeof(struct command)); + + return ret; +} + +static inline int t1_getreg_full(struct t1 *wc, int addr, int inisr, int vpm_num) +{ + unsigned long flags; + int hit; + int ret = 0; + + do { + if (!inisr) { + spin_lock_irqsave(&wc->reglock, flags); + } + hit = empty_slot(wc); + if (hit > -1) { + wc->cmdq.cmds[hit].address = addr; + wc->cmdq.cmds[hit].data = 0x00; + wc->cmdq.cmds[hit].flags |= __CMD_RD; + if(vpm_num >= 0) { + wc->cmdq.cmds[hit].flags |= __CMD_VPM; + wc->cmdq.cmds[hit].vpm_num = vpm_num; + } + if (inisr) + wc->cmdq.cmds[hit].flags |= __CMD_ISR; + } + if (inisr) /* must be requested in t1_getreg_isr() */ + return (hit > -1) ? 0 : -1; + else { + spin_unlock_irqrestore(&wc->reglock, flags); + } + if (hit < 0) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (hit < 0); + + do { + spin_lock_irqsave(&wc->reglock, flags); + if (wc->cmdq.cmds[hit].flags & __CMD_FIN) { + ret = wc->cmdq.cmds[hit].data; + memset(&wc->cmdq.cmds[hit], 0, sizeof(wc->cmdq.cmds[hit])); + hit = -1; + } + spin_unlock_irqrestore(&wc->reglock, flags); + if (hit > -1) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (hit > -1); + + return ret; +} + +static inline int t1_getreg(struct t1 *wc, int addr, int inisr) +{ + return t1_getreg_full(wc, addr, inisr, NOT_VPM); +} + +static inline int t1_setleds(struct t1 *wc, int leds, int inisr) +{ + unsigned long flags; + int hit; + int ret = 0; + + leds = ~leds & 0x0E; /* invert the LED bits (3 downto 1)*/ + + do { + if (!inisr) { + spin_lock_irqsave(&wc->reglock, flags); + } + hit = empty_slot(wc); + if (hit > -1) { + wc->cmdq.cmds[hit].flags |= __CMD_LEDS; + wc->cmdq.cmds[hit].address = leds; + } + if (inisr) { + break; + } else { + spin_unlock_irqrestore(&wc->reglock, flags); + } + if (hit < 0) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (hit < 0); + + return (hit > -1) ? 0 : -1; +} + +static inline int t1_getpins(struct t1 *wc, int inisr) +{ + unsigned long flags; + int hit; + int ret = 0; + + do { + spin_lock_irqsave(&wc->reglock, flags); + hit = empty_slot(wc); + if (hit > -1) { + wc->cmdq.cmds[hit].address = 0x00; + wc->cmdq.cmds[hit].data = 0x00; + wc->cmdq.cmds[hit].flags |= __CMD_PINS; + } + spin_unlock_irqrestore(&wc->reglock, flags); + if (inisr) + return (hit > -1) ? 0 : -1; + if (hit < 0) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (hit < 0); + + do { + spin_lock_irqsave(&wc->reglock, flags); + if (wc->cmdq.cmds[hit].flags & __CMD_FIN) { + ret = wc->cmdq.cmds[hit].data; + memset(&wc->cmdq.cmds[hit], 0, sizeof(wc->cmdq.cmds[hit])); + hit = -1; + } + spin_unlock_irqrestore(&wc->reglock, flags); + if (hit > -1) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (hit > -1); + + return ret; +} + +static void t1_setintmask(struct t1 *wc, unsigned int intmask) +{ + wc->intmask = intmask; + t1_setctl(wc, 0x0038, intmask); +} + +static void t1_enable_interrupts(struct t1 *wc) +{ + /* Enable interrupts */ + t1_setintmask(wc, 0x00010041); /* only RX */ +} + +static void t1_disable_interrupts(struct t1 *wc) +{ + /* Disable interrupts */ + t1_setintmask(wc, 0x00000000); + t1_setctl(wc, 0x0084, 0x00000000); +} + +static void t1_start_dma(struct t1 *wc) +{ + unsigned int reg; + int x; + + wmb(); + t1_setctl(wc, 0x0020, wc->descripdma); + t1_setctl(wc, 0x0018, wc->descripdma + (16 * ERING_SIZE)); + /* Start receiver/transmitter */ + reg = t1_getctl(wc, 0x0030); + t1_setctl(wc, 0x0030, reg | 0x00002002); + t1_setctl(wc, 0x0008, 0x00000000); + t1_setctl(wc, 0x0010, 0x00000000); + reg = t1_getctl(wc, 0x0028); + t1_setctl(wc, 0x0028, reg); + + /* Set Reset - now with MAGIC TIPS */ + t1_setctl(wc, 0x0048, 0x00000000); + for (x = 0; x < 10; x++) + schluffen(&wc->regq); + /* Clear reset */ + t1_setctl(wc, 0x0048, 0x00010000); + for (x = 0; x < 10; x++) + schluffen(&wc->regq); + /* Switch to caring only about receive interrupts */ + t1_setintmask(wc, 0x00010040); +} + +static void t1_stop_dma(struct t1 *wc) +{ + /* Disable interrupts and reset */ + unsigned int reg; + + /* Disable interrupts */ + t1_setintmask(wc, 0x00000000); + t1_setctl(wc, 0x0084, 0x00000000); + t1_setctl(wc, 0x0048, 0x00000000); + /* Reset the part to be on the safe side */ + reg = t1_getctl(wc, 0x0000); + reg |= 0x00000001; + t1_setctl(wc, 0x0000, reg); +} + +static void __t1xxp_set_clear(struct t1 *wc, int channo) +{ + int i,j; + int ret; + unsigned short val=0; + + for (i = 0; i < 24; i++) { + j = (i / 8); + if (wc->span.chans[i].flags & ZT_FLAG_CLEAR) + val |= 1 << (7 - (i % 8)); + if (((i % 8)==7) && /* write byte every 8 channels */ + ((channo < 0) || /* channo=-1 means all channels */ + (j == (channo-1)/8) )) { /* only the register for this channo */ + ret = t1_setreg_full(wc, 0x2f + j, val, 1, NOT_VPM); + if (ret < 0) + module_printk("set_clear failed for chan %d!\n",i); + val = 0; + } + } +} + +static void t1_release(struct t1 *wc) +{ + zt_unregister(&wc->span); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + kfree(wc); + printk("Freed a Wildcard TE12xP\n"); +} + +static void t4_serial_setup(struct t1 *wc) +{ + module_printk("Setting up global serial parameters for %s\n", + wc->spantype == TYPE_E1 ? (unchannelized ? "Unchannelized E1" : "E1") : "T1"); + + t1_setreg(wc, 0x85, 0xe0); /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0 */ + t1_setreg(wc, 0x08, 0x05); /* IPC: Interrupt push/pull active low */ + + /* Global clocks (8.192 Mhz CLK) */ + t1_setreg(wc, 0x92, 0x00); + t1_setreg(wc, 0x93, 0x18); + t1_setreg(wc, 0x94, 0xfb); + t1_setreg(wc, 0x95, 0x0b); + t1_setreg(wc, 0x96, 0x00); + t1_setreg(wc, 0x97, 0x0b); + t1_setreg(wc, 0x98, 0xdb); + t1_setreg(wc, 0x99, 0xdf); + + /* Configure interrupts */ + t1_setreg(wc, 0x46, 0xc0); /* GCR: Interrupt on Activation/Deactivation of AIX, LOS */ + + /* Configure system interface */ + t1_setreg(wc, 0x3e, 0x0a /* 0x02 */); /* SIC1: 4.096 Mhz clock/bus, double buffer receive / transmit, byte interleaved */ + t1_setreg(wc, 0x3f, 0x00); /* SIC2: No FFS, no center receive eliastic buffer, phase 0 */ + t1_setreg(wc, 0x40, 0x04); /* SIC3: Edges for capture */ + t1_setreg(wc, 0x44, 0x30); /* CMR1: RCLK is at 8.192 Mhz dejittered */ + t1_setreg(wc, 0x45, 0x00); /* CMR2: We provide sync and clock for tx and rx. */ + t1_setreg(wc, 0x22, 0x00); /* XC0: Normal operation of Sa-bits */ + t1_setreg(wc, 0x23, 0x04); /* XC1: 0 offset */ + t1_setreg(wc, 0x24, 0x00); /* RC0: Just shy of 255 */ + t1_setreg(wc, 0x25, 0x05); /* RC1: The rest of RC0 */ + + /* Configure ports */ + t1_setreg(wc, 0x80, 0x00); /* PC1: SPYR/SPYX input on RPA/XPA */ + t1_setreg(wc, 0x81, 0x22); /* PC2: RMFB/XSIG output/input on RPB/XPB */ + t1_setreg(wc, 0x82, 0x65); /* PC3: Some unused stuff */ + t1_setreg(wc, 0x83, 0x35); /* PC4: Some more unused stuff */ + t1_setreg(wc, 0x84, 0x31); /* PC5: XMFS active low, SCLKR is input, RCLK is output */ + t1_setreg(wc, 0x86, 0x03); /* PC6: CLK1 is Tx Clock output, CLK2 is 8.192 Mhz from DCO-R */ + t1_setreg(wc, 0x3b, 0x00); /* Clear LCR1 */ +} + +static void t1_configure_t1(struct t1 *wc, int lineconfig, int txlevel) +{ + unsigned int fmr4, fmr2, fmr1, fmr0, lim2; + char *framing, *line; + int mytxlevel; + + if ((txlevel > 7) || (txlevel < 4)) + mytxlevel = 0; + else + mytxlevel = txlevel - 4; + fmr1 = 0x9e; /* FMR1: Mode 0, T1 mode, CRC on for ESF, 2.048 Mhz system data rate, no XAIS */ + fmr2 = 0x22; /* FMR2: no payload loopback, auto send yellow alarm */ + if (loopback) + fmr2 |= 0x4; + + if (j1mode) + fmr4 = 0x1c; + else + fmr4 = 0x0c; /* FMR4: Lose sync on 2 out of 5 framing bits, auto resync */ + + lim2 = 0x21; /* LIM2: 50% peak is a "1", Advanced Loss recovery */ + lim2 |= (mytxlevel << 6); /* LIM2: Add line buildout */ + t1_setreg(wc, 0x1d, fmr1); + t1_setreg(wc, 0x1e, fmr2); + + /* Configure line interface */ + if (lineconfig & ZT_CONFIG_AMI) { + line = "AMI"; + fmr0 = 0xa0; + } else { + line = "B8ZS"; + fmr0 = 0xf0; + } + if (lineconfig & ZT_CONFIG_D4) { + framing = "D4"; + } else { + framing = "ESF"; + fmr4 |= 0x2; + fmr2 |= 0xc0; + } + t1_setreg(wc, 0x1c, fmr0); + + t1_setreg(wc, 0x20, fmr4); + t1_setreg(wc, 0x21, 0x40); /* FMR5: Enable RBS mode */ + + t1_setreg(wc, 0x37, 0xf8); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ + t1_setreg(wc, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ + + t1_setreg(wc, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ + t1_setreg(wc, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ + + t1_setreg(wc, 0x3a, lim2); /* LIM2: 50% peak amplitude is a "1" */ + t1_setreg(wc, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ + t1_setreg(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ + + if (j1mode) + t1_setreg(wc, 0x24, 0x80); /* J1 overide */ + + /* Generate pulse mask for T1 */ + switch (mytxlevel) { + case 3: + t1_setreg(wc, 0x26, 0x07); /* XPM0 */ + t1_setreg(wc, 0x27, 0x01); /* XPM1 */ + t1_setreg(wc, 0x28, 0x00); /* XPM2 */ + break; + case 2: + t1_setreg(wc, 0x26, 0x8c); /* XPM0 */ + t1_setreg(wc, 0x27, 0x11); /* XPM1 */ + t1_setreg(wc, 0x28, 0x01); /* XPM2 */ + break; + case 1: + t1_setreg(wc, 0x26, 0x8c); /* XPM0 */ + t1_setreg(wc, 0x27, 0x01); /* XPM1 */ + t1_setreg(wc, 0x28, 0x00); /* XPM2 */ + break; + case 0: + default: + t1_setreg(wc, 0x26, 0xd7); /* XPM0 */ + t1_setreg(wc, 0x27, 0x22); /* XPM1 */ + t1_setreg(wc, 0x28, 0x01); /* XPM2 */ + break; + } + + module_printk("Span configured for %s/%s\n", framing, line); +} + +static void t1_configure_e1(struct t1 *wc, int lineconfig) +{ + unsigned int fmr2, fmr1, fmr0; + unsigned int cas = 0; + char *crc4 = ""; + char *framing, *line; + + fmr1 = 0x46; /* FMR1: E1 mode, Automatic force resync, PCM30 mode, 8.192 Mhz backplane, no XAIS */ + fmr2 = 0x03; /* FMR2: Auto transmit remote alarm, auto loss of multiframe recovery, no payload loopback */ + if (unchannelized) + fmr2 |= 0x30; + if (loopback) + fmr2 |= 0x4; + if (lineconfig & ZT_CONFIG_CRC4) { + fmr1 |= 0x08; /* CRC4 transmit */ + fmr2 |= 0xc0; /* CRC4 receive */ + crc4 = "/CRC4"; + } + t1_setreg(wc, 0x1d, fmr1); + t1_setreg(wc, 0x1e, fmr2); + + /* Configure line interface */ + if (lineconfig & ZT_CONFIG_AMI) { + line = "AMI"; + fmr0 = 0xa0; + } else { + line = "HDB3"; + fmr0 = 0xf0; + } + if (lineconfig & ZT_CONFIG_CCS) { + framing = "CCS"; + } else { + framing = "CAS"; + cas = 0x40; + } + t1_setreg(wc, 0x1c, fmr0); + + if (unchannelized) + t1_setreg(wc, 0x1f, 0x40); + + t1_setreg(wc, 0x37, 0xf0 /*| 0x6 */ ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ + t1_setreg(wc, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ + + t1_setreg(wc, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ + t1_setreg(wc, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ + + /* Condition receive line interface for E1 after reset */ + t1_setreg(wc, 0xbb, 0x17); + t1_setreg(wc, 0xbc, 0x55); + t1_setreg(wc, 0xbb, 0x97); + t1_setreg(wc, 0xbb, 0x11); + t1_setreg(wc, 0xbc, 0xaa); + t1_setreg(wc, 0xbb, 0x91); + t1_setreg(wc, 0xbb, 0x12); + t1_setreg(wc, 0xbc, 0x55); + t1_setreg(wc, 0xbb, 0x92); + t1_setreg(wc, 0xbb, 0x0c); + t1_setreg(wc, 0xbb, 0x00); + t1_setreg(wc, 0xbb, 0x8c); + + t1_setreg(wc, 0x3a, 0x20); /* LIM2: 50% peak amplitude is a "1" */ + t1_setreg(wc, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ + t1_setreg(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ + + t1_setreg(wc, 0x20, 0x9f); /* XSW: Spare bits all to 1 */ + if (unchannelized) + t1_setreg(wc, 0x21, 0x3c); + else + t1_setreg(wc, 0x21, 0x1c|cas); /* XSP: E-bit set when async. AXS auto, XSIF to 1 */ + + + /* Generate pulse mask for E1 */ + t1_setreg(wc, 0x26, 0x54); /* XPM0 */ + t1_setreg(wc, 0x27, 0x02); /* XPM1 */ + t1_setreg(wc, 0x28, 0x00); /* XPM2 */ + module_printk("Span configured for %s/%s%s\n", framing, line, crc4); +} + +static void t1xxp_framer_start(struct t1 *wc, struct zt_span *span) +{ + int alreadyrunning = wc->span.flags & ZT_FLAG_RUNNING; + unsigned long flags; + + if (wc->spantype == TYPE_E1) { /* if this is an E1 card */ + t1_configure_e1(wc, span->lineconfig); + } else { /* is a T1 card */ + t1_configure_t1(wc, span->lineconfig, span->txlevel); + __t1xxp_set_clear(wc, -1); + } + + spin_lock_irqsave(&wc->reglock, flags); + if (!alreadyrunning) + wc->span.flags |= ZT_FLAG_RUNNING; + spin_unlock_irqrestore(&wc->reglock, flags); +} + +static int t1xxp_startup(struct zt_span *span) +{ + struct t1 *wc = span->pvt; + int i; + + /* initialize the start value for the entire chunk of last ec buffer */ + for (i = 0; i < span->channels; i++) { + memset(wc->ec_chunk1[i], ZT_LIN2X(0, &span->chans[i]), ZT_CHUNKSIZE); + memset(wc->ec_chunk2[i], ZT_LIN2X(0, &span->chans[i]), ZT_CHUNKSIZE); + } + + /* Reset framer with proper parameters and start */ + t1xxp_framer_start(wc, span); + debug_printk(1, "Calling startup (flags is %d)\n", span->flags); + + return 0; +} + +static int t1xxp_shutdown(struct zt_span *span) +{ + struct t1 *wc = span->pvt; + unsigned long flags; + + t1_setreg(wc, 0x46, 0x41); /* GCR: Interrupt on Activation/Deactivation of AIX, LOS */ + spin_lock_irqsave(&wc->reglock, flags); + span->flags &= ~ZT_FLAG_RUNNING; + spin_unlock_irqrestore(&wc->reglock, flags); + return 0; +} + +static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype) +{ + struct t1 *wc = chan->pvt; + int alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING; + + if (alreadyrunning && (wc->spantype != TYPE_E1)) + __t1xxp_set_clear(wc, chan->channo); + + return 0; +} + +static int t1xxp_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) +{ + struct t1 *wc = span->pvt; + + /* Do we want to SYNC on receive or not */ + wc->sync = lc->sync; + if (wc->sync) + wc->ctlreg |= 0x80; + else + wc->ctlreg &= ~0x80; + + /* If already running, apply changes immediately */ + if (span->flags & ZT_FLAG_RUNNING) + return t1xxp_startup(span); + + return 0; +} + +static int t1xxp_rbsbits(struct zt_chan *chan, int bits) +{ + u_char m,c; + int n,b; + struct t1 *wc = chan->pvt; + unsigned long flags; + + debug_printk(2, "Setting bits to %d on channel %s\n", bits, chan->name); + if (wc->spantype == TYPE_E1) { /* do it E1 way */ + if (chan->chanpos == 16) + return 0; + + n = chan->chanpos - 1; + if (chan->chanpos > 15) n--; + b = (n % 15); + spin_lock_irqsave(&wc->reglock, flags); + c = wc->txsigs[b]; + m = (n / 15) << 2; /* nibble selector */ + c &= (0xf << m); /* keep the other nibble */ + c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ + wc->txsigs[b] = c; + spin_unlock_irqrestore(&wc->reglock, flags); + /* output them to the chip */ + t1_setreg_full(wc,0x71 + b,c,1,NOT_VPM); + } else if (wc->span.lineconfig & ZT_CONFIG_D4) { + n = chan->chanpos - 1; + b = (n / 4); + spin_lock_irqsave(&wc->reglock, flags); + c = wc->txsigs[b]; + m = ((3 - (n % 4)) << 1); /* nibble selector */ + c &= ~(0x3 << m); /* keep the other nibble */ + c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */ + wc->txsigs[b] = c; + spin_unlock_irqrestore(&wc->reglock, flags); + /* output them to the chip */ + t1_setreg_full(wc,0x70 + b,c,1,NOT_VPM); + t1_setreg_full(wc,0x70 + b + 6,c,1,NOT_VPM); + } else if (wc->span.lineconfig & ZT_CONFIG_ESF) { + n = chan->chanpos - 1; + b = (n / 2); + spin_lock_irqsave(&wc->reglock, flags); + c = wc->txsigs[b]; + m = ((n % 2) << 2); /* nibble selector */ + c &= (0xf << m); /* keep the other nibble */ + c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ + wc->txsigs[b] = c; + spin_unlock_irqrestore(&wc->reglock, flags); + /* output them to the chip */ + t1_setreg_full(wc,0x70 + b,c,1,NOT_VPM); + } + debug_printk(2,"Finished setting RBS bits\n"); + + return 0; +} + +static inline void __t1_check_sigbits_reads(struct t1 *wc) +{ + int i; + + if (!(wc->span.flags & ZT_FLAG_RUNNING)) + return; + if (wc->spantype == TYPE_E1) { + for (i = 0; i < 15; i++) { + if (t1_getreg(wc, 0x71 + i, 1)) + wc->isrreaderrors++; + } + } else if (wc->span.lineconfig & ZT_CONFIG_D4) { + for (i = 0; i < 24; i+=4) { + if (t1_getreg(wc, 0x70 + (i >> 2), 1)) + wc->isrreaderrors++; + } + } else { + for (i = 0; i < 24; i+=2) { + if (t1_getreg(wc, 0x70 + (i >> 1), 1)) + wc->isrreaderrors++; + } + } +} + +static inline void __t1_check_sigbits(struct t1 *wc) +{ + int a,i,rxs; + + if (!(wc->span.flags & ZT_FLAG_RUNNING)) + return; + if (wc->spantype == TYPE_E1) { + for (i = 0; i < 15; i++) { + a = t1_getreg_isr(wc, 0x71 + i); + if (a > -1) { + /* Get high channel in low bits */ + rxs = (a & 0xf); + if (!(wc->span.chans[i+16].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i+16].rxsig != rxs) { + spin_unlock(&wc->reglock); + zt_rbsbits(&wc->span.chans[i+16], rxs); + spin_lock(&wc->reglock); + } + } + rxs = (a >> 4) & 0xf; + if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i].rxsig != rxs) { + spin_unlock(&wc->reglock); + zt_rbsbits(&wc->span.chans[i], rxs); + spin_lock(&wc->reglock); + } + } + } else { + debug_printk(1, "no space to request register in isr\n"); + } + } + } else if (wc->span.lineconfig & ZT_CONFIG_D4) { + for (i = 0; i < 24; i+=4) { + a = t1_getreg_isr(wc, 0x70 + (i>>2)); + if (a > -1) { + /* Get high channel in low bits */ + rxs = (a & 0x3) << 2; + if (!(wc->span.chans[i+3].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i+3].rxsig != rxs) { + spin_unlock(&wc->reglock); + zt_rbsbits(&wc->span.chans[i+3], rxs); + spin_lock(&wc->reglock); + } + } + rxs = (a & 0xc); + if (!(wc->span.chans[i+2].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i+2].rxsig != rxs) { + spin_unlock(&wc->reglock); + zt_rbsbits(&wc->span.chans[i+2], rxs); + spin_lock(&wc->reglock); + } + } + rxs = (a >> 2) & 0xc; + if (!(wc->span.chans[i+1].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i+1].rxsig != rxs) { + spin_unlock(&wc->reglock); + zt_rbsbits(&wc->span.chans[i+1], rxs); + spin_lock(&wc->reglock); + } + } + rxs = (a >> 4) & 0xc; + if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i].rxsig != rxs) { + spin_unlock(&wc->reglock); + zt_rbsbits(&wc->span.chans[i], rxs); + spin_lock(&wc->reglock); + } + } + } + } + } else { + for (i = 0; i < 24; i+=2) { + a = t1_getreg_isr(wc, 0x70 + (i>>1)); + if (a > -1) { + /* Get high channel in low bits */ + rxs = (a & 0xf); + if (!(wc->span.chans[i+1].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i+1].rxsig != rxs) { + spin_unlock(&wc->reglock); + zt_rbsbits(&wc->span.chans[i+1], rxs); + spin_lock(&wc->reglock); + } + } + rxs = (a >> 4) & 0xf; + if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { + if (wc->span.chans[i].rxsig != rxs) { + spin_unlock(&wc->reglock); + zt_rbsbits(&wc->span.chans[i], rxs); + spin_lock(&wc->reglock); + } + } + } + } + } +} + +static int t1xxp_maint(struct zt_span *span, int cmd) +{ + struct t1 *wc = span->pvt; + + if (wc->spantype == TYPE_E1) { + switch (cmd) { + case ZT_MAINT_NONE: + module_printk("XXX Turn off local and remote loops E1 XXX\n"); + break; + case ZT_MAINT_LOCALLOOP: + module_printk("XXX Turn on local loopback E1 XXX\n"); + break; + case ZT_MAINT_REMOTELOOP: + module_printk("XXX Turn on remote loopback E1 XXX\n"); + break; + case ZT_MAINT_LOOPUP: + module_printk("XXX Send loopup code E1 XXX\n"); + break; + case ZT_MAINT_LOOPDOWN: + module_printk("XXX Send loopdown code E1 XXX\n"); + break; + case ZT_MAINT_LOOPSTOP: + module_printk("XXX Stop sending loop codes E1 XXX\n"); + break; + default: + module_printk("Unknown E1 maint command: %d\n", cmd); + break; + } + } else { + switch (cmd) { + case ZT_MAINT_NONE: + module_printk("XXX Turn off local and remote loops T1 XXX\n"); + break; + case ZT_MAINT_LOCALLOOP: + module_printk("XXX Turn on local loop and no remote loop XXX\n"); + break; + case ZT_MAINT_REMOTELOOP: + module_printk("XXX Turn on remote loopup XXX\n"); + break; + case ZT_MAINT_LOOPUP: + t1_setreg(wc, 0x21, 0x50); /* FMR5: Nothing but RBS mode */ + break; + case ZT_MAINT_LOOPDOWN: + t1_setreg(wc, 0x21, 0x60); /* FMR5: Nothing but RBS mode */ + break; + case ZT_MAINT_LOOPSTOP: + t1_setreg(wc, 0x21, 0x40); /* FMR5: Nothing but RBS mode */ + break; + default: + module_printk("Unknown T1 maint command: %d\n", cmd); + break; + } + } + + return 0; +} + +static int t1xxp_open(struct zt_chan *chan) +{ + struct t1 *wc = chan->pvt; + + if (wc->dead) + return -ENODEV; + wc->usecount++; + +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#else + try_module_get(THIS_MODULE); +#endif + + return 0; +} + +static int t1xxp_close(struct zt_chan *chan) +{ + struct t1 *wc = chan->pvt; + + wc->usecount--; + +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#else + module_put(THIS_MODULE); +#endif + + /* If we're dead, release us now */ + if (!wc->usecount && wc->dead) + t1_release(wc); + + return 0; +} + +static int t1xxp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) +{ + struct t4_regs regs; + unsigned int x; + struct t1 *wc = chan->pvt; + + switch (cmd) { + case WCT4_GET_REGS: + wc = chan->pvt; + for (x = 0; x < sizeof(regs.pci) / sizeof(regs.pci[0]); x++) +#if 1 + regs.pci[x] = (inb(wc->iobase + (x << 2))) | + (inb(wc->iobase + (x << 2) + 1) << 8) | + (inb(wc->iobase + (x << 2) + 2) << 16) | + (inb(wc->iobase + (x << 2) + 3) << 24); +#else + regs.pci[x] = (inb(wc->iobase + x)); +#endif + + for (x = 0; x < sizeof(regs.regs) / sizeof(regs.regs[0]); x++) + regs.regs[x] = t1_getreg(wc, x, 0); + + if (copy_to_user((struct t4_regs *) data, ®s, sizeof(regs))) + return -EFAULT; + break; +#ifdef VPM_SUPPORT + case ZT_TONEDETECT: + if (get_user(x, (int *) data)) + return -EFAULT; + if (!wc->vpm150m) + return -ENOSYS; + if (wc->vpm150m && (x && !vpmdtmfsupport)) + return -ENOSYS; + if (x & ZT_TONEDETECT_ON) { + set_bit(chan->chanpos - 1, &wc->dtmfmask); + module_printk("turning on tone detection\n"); + } else { + clear_bit(chan->chanpos - 1, &wc->dtmfmask); + module_printk("turning off tone detection\n"); + } + if (x & ZT_TONEDETECT_MUTE) { + if(wc->vpm150m) + set_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); + } else { + if(wc->vpm150m) + clear_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); + } + return 0; +#endif + default: + return -ENOTTY; + } + return 0; +} + +#ifdef VPM_SUPPORT + +#include "adt_lec.c" + +static int t1xxp_echocan_with_params(struct zt_chan *chan, struct zt_echocanparams *ecp, struct zt_echocanparam *p) +{ + struct adt_lec_params params; + struct t1 *wc = chan->pvt; + struct vpm150m *vpm150m = wc->vpm150m; + unsigned int flags; + struct vpm150m_workentry *work; + unsigned int ret; + + if (!wc->vpm150m) + return -ENODEV; + + adt_lec_init_defaults(¶ms, 32); + + if ((ret = adt_lec_parse_params(¶ms, ecp, p))) + return ret; + + /* we can't really control the tap length, but the value is used + to control whether the ec is on or off, so translate it */ + params.tap_length = ecp->tap_length ? 1 : 0; + + if (!(work = kmalloc(sizeof(*work), GFP_KERNEL))) + return -ENOMEM; + + work->params = params; + work->wc = wc; + work->chan = chan; + spin_lock_irqsave(&vpm150m->lock, flags); + list_add_tail(&work->list, &vpm150m->worklist); + spin_unlock_irqrestore(&vpm150m->lock, flags); + + /* we must do this later since we cannot sleep in the echocan function */ + if (test_bit(VPM150M_ACTIVE, &vpm150m->control)) + queue_work(vpm150m->wq, &vpm150m->work_echocan); + + return 0; /* how do I return the status since it is done later by the workqueue? */ +} +#endif + +static int t1_software_init(struct t1 *wc) +{ + int x; + + /* Find position */ + for (x = 0; x < sizeof(ifaces) / sizeof(ifaces[0]); x++) { + if (ifaces[x] == wc) { + debug_printk(1, "software init for card %d\n",x); + break; + } + } + + if (x == sizeof(ifaces) / sizeof(ifaces[0])) + return -1; + + t4_serial_setup(wc); + + wc->num = x; + sprintf(wc->span.name, "WCT1/%d", wc->num); + snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num); + wc->span.manufacturer = "Digium"; + strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); + +#if defined(VPM_SUPPORT) + if (wc->vpm150m) + strncat(wc->span.devicetype, " with VPMADT032", sizeof(wc->span.devicetype) - 1); +#endif + + snprintf(wc->span.location, sizeof(wc->span.location) - 1, + "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); + + wc->span.spanconfig = t1xxp_spanconfig; + wc->span.chanconfig = t1xxp_chanconfig; + wc->span.irq = wc->dev->irq; + wc->span.startup = t1xxp_startup; + wc->span.shutdown = t1xxp_shutdown; + wc->span.rbsbits = t1xxp_rbsbits; + wc->span.maint = t1xxp_maint; + wc->span.open = t1xxp_open; + wc->span.close = t1xxp_close; + wc->span.ioctl = t1xxp_ioctl; +#ifdef VPM_SUPPORT + wc->span.echocan_with_params = t1xxp_echocan_with_params; +#endif + + if (wc->spantype == TYPE_E1) { + if (unchannelized) + wc->span.channels = 32; + else + wc->span.channels = 31; + wc->span.spantype = "E1"; + wc->span.linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4; + wc->span.deflaw = ZT_LAW_ALAW; + } else { + wc->span.channels = 24; + wc->span.spantype = "T1"; + wc->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; + wc->span.deflaw = ZT_LAW_MULAW; + } + wc->span.chans = wc->chans; + wc->span.flags = ZT_FLAG_RBS; + wc->span.pvt = wc; + init_waitqueue_head(&wc->span.maintq); + for (x = 0; x < wc->span.channels; x++) { + sprintf(wc->chans[x].name, "WCT1/%d/%d", wc->num, x + 1); + wc->chans[x].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_EM_E1 | + ZT_SIG_FXSLS | ZT_SIG_FXSGS | + ZT_SIG_FXSKS | ZT_SIG_FXOLS | ZT_SIG_DACS_RBS | + ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF; + wc->chans[x].pvt = wc; + wc->chans[x].chanpos = x + 1; + } + if (zt_register(&wc->span, 0)) { + module_printk("Unable to register span with Zaptel\n"); + return -1; + } + wc->initialized = 1; + + return 0; +} + +#ifdef VPM_SUPPORT +static inline unsigned char t1_vpm_in(struct t1 *wc, int unit, const unsigned int addr) +{ + return t1_getreg_full(wc, addr, 0, unit); +} + +static inline unsigned char t1_vpm_out(struct t1 *wc, int unit, const unsigned int addr, const unsigned char val) +{ + return t1_setreg_full(wc, addr, val, 0, unit); +} + +#endif + +static int t1_hardware_post_init(struct t1 *wc) +{ + unsigned int reg; + int x; + + /* T1 or E1 */ + if (t1e1override > -1) { + if (t1e1override) + wc->spantype = TYPE_E1; + else + wc->spantype = TYPE_T1; + } else { + if (t1_getpins(wc,0) & 0x01) /* returns 1 for T1 mode */ + wc->spantype = TYPE_T1; + else + wc->spantype = TYPE_E1; + } + debug_printk(1, "spantype: %s\n", wc->spantype==1 ? "T1" : "E1"); + + if (wc->spantype == TYPE_E1) { + if (unchannelized) + wc->chanmap = chanmap_e1uc; + else + wc->chanmap = chanmap_e1; + } else + wc->chanmap = chanmap_t1; + /* what version of the FALC are we using? */ + reg = t1_setreg(wc, 0x4a, 0xaa); + reg = t1_getreg(wc, 0x4a, 0); + debug_printk(1, "FALC version: %08x\n", reg); + + /* make sure reads and writes work */ + for (x = 0; x < 256; x++) { + t1_setreg(wc, 0x14, x); + if ((reg = t1_getreg(wc, 0x14, 0)) != x) + module_printk("Wrote '%x' but read '%x'\n", x, reg); + } + + /* all LED's blank */ + wc->ledtestreg = UNSET_LED_ORANGE(wc->ledtestreg); + wc->ledtestreg = UNSET_LED_REDGREEN(wc->ledtestreg); + t1_setleds(wc, wc->ledtestreg, 0); + +#ifdef VPM_SUPPORT + t1_vpm150m_init(wc); + if (wc->vpm150m) { + module_printk("VPM present and operational (Firmware version %x)\n", wc->vpm150m->version); + wc->ctlreg |= 0x10; /* turn on vpm (RX audio from vpm module) */ + if (vpmtsisupport) { + debug_printk(1, "enabling VPM TSI pin\n"); + wc->ctlreg |= 0x01; /* turn on vpm timeslot interchange pin */ + } + } +#endif + + return 0; +} + +static inline void __t1_check_alarms_reads(struct t1 *wc) +{ + if (!(wc->span.flags & ZT_FLAG_RUNNING)) + return; + + if (t1_getreg(wc, 0x4c, 1)) + wc->isrreaderrors++; + if (t1_getreg(wc, 0x20, 1)) + wc->isrreaderrors++; + if (t1_getreg(wc, 0x4d, 1)) + wc->isrreaderrors++; +} + +static inline void __t1_check_alarms(struct t1 *wc) +{ + unsigned char c,d; + int alarms; + int x,j; + unsigned char fmr4; /* must read this always */ + + if (!(wc->span.flags & ZT_FLAG_RUNNING)) + return; + + c = t1_getreg_isr(wc, 0x4c); + fmr4 = t1_getreg_isr(wc, 0x20); /* must read this even if we don't use it */ + d = t1_getreg_isr(wc, 0x4d); + + /* Assume no alarms */ + alarms = 0; + + /* And consider only carrier alarms */ + wc->span.alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); + + if (wc->spantype == TYPE_E1) { + if (c & 0x04) { + /* No multiframe found, force RAI high after 400ms only if + we haven't found a multiframe since last loss + of frame */ + if (!wc->flags.nmf) { + t1_setreg_full(wc, 0x20, 0x9f | 0x20, 1, NOT_VPM); /* LIM0: Force RAI High */ + wc->flags.nmf = 1; + module_printk("NMF workaround on!\n"); + } + t1_setreg_full(wc, 0x1e, 0xc3, 1, NOT_VPM); /* Reset to CRC4 mode */ + t1_setreg_full(wc, 0x1c, 0xf2, 1, NOT_VPM); /* Force Resync */ + t1_setreg_full(wc, 0x1c, 0xf0, 1, NOT_VPM); /* Force Resync */ + } else if (!(c & 0x02)) { + if (wc->flags.nmf) { + t1_setreg_full(wc, 0x20, 0x9f, 1, NOT_VPM); /* LIM0: Clear forced RAI */ + wc->flags.nmf = 0; + module_printk("NMF workaround off!\n"); + } + } + } else { + /* Detect loopup code if we're not sending one */ + if ((!wc->span.mainttimer) && (d & 0x08)) { + /* Loop-up code detected */ + if ((wc->loopupcnt++ > 80) && (wc->span.maintstat != ZT_MAINT_REMOTELOOP)) { + t1_setreg_full(wc, 0x36, 0x08, 1, NOT_VPM); /* LIM0: Disable any local loop */ + t1_setreg_full(wc, 0x37, 0xf6, 1, NOT_VPM); /* LIM1: Enable remote loop */ + wc->span.maintstat = ZT_MAINT_REMOTELOOP; + } + } else + wc->loopupcnt = 0; + /* Same for loopdown code */ + if ((!wc->span.mainttimer) && (d & 0x10)) { + /* Loop-down code detected */ + if ((wc->loopdowncnt++ > 80) && (wc->span.maintstat == ZT_MAINT_REMOTELOOP)) { + t1_setreg_full(wc, 0x36, 0x08, 1, NOT_VPM); /* LIM0: Disable any local loop */ + t1_setreg_full(wc, 0x37, 0xf0, 1, NOT_VPM); /* LIM1: Disable remote loop */ + wc->span.maintstat = ZT_MAINT_NONE; + } + } else + wc->loopdowncnt = 0; + } + + if (wc->span.lineconfig & ZT_CONFIG_NOTOPEN) { + for (x=0,j=0;x < wc->span.channels;x++) + if ((wc->span.chans[x].flags & ZT_FLAG_OPEN) || + (wc->span.chans[x].flags & ZT_FLAG_NETDEV)) + j++; + if (!j) + alarms |= ZT_ALARM_NOTOPEN; + } + + if (c & 0xa0) { + if (wc->alarmcount >= alarmdebounce) { + if (!unchannelized) + alarms |= ZT_ALARM_RED; + } else + wc->alarmcount++; + } else + wc->alarmcount = 0; + if (c & 0x4) + alarms |= ZT_ALARM_BLUE; + + /* Keep track of recovering */ + if ((!alarms) && wc->span.alarms) + wc->alarmtimer = ZT_ALARMSETTLE_TIME; + if (wc->alarmtimer) + alarms |= ZT_ALARM_RECOVER; + + /* If receiving alarms, go into Yellow alarm state */ + if (alarms && !wc->flags.sendingyellow) { + module_printk("Setting yellow alarm\n"); + + /* We manually do yellow alarm to handle RECOVER and NOTOPEN, otherwise it's auto anyway */ + t1_setreg_full(wc, 0x20, fmr4 | 0x20, 1, NOT_VPM); + wc->flags.sendingyellow = 1; + } else if (!alarms && wc->flags.sendingyellow) { + module_printk("Clearing yellow alarm\n"); + /* We manually do yellow alarm to handle RECOVER */ + t1_setreg_full(wc, 0x20, fmr4 & ~0x20, 1, NOT_VPM); + wc->flags.sendingyellow = 0; + } + + if ((c & 0x10) && !unchannelized) + alarms |= ZT_ALARM_YELLOW; + if (wc->span.mainttimer || wc->span.maintstat) + alarms |= ZT_ALARM_LOOPBACK; + wc->span.alarms = alarms; + spin_unlock(&wc->reglock); + zt_alarm_notify(&wc->span); + spin_lock(&wc->reglock); +} + +static inline void __handle_leds(struct t1 *wc) +{ + if (wc->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) { + wc->blinktimer++; + if (wc->blinktimer == 160) + wc->ledtestreg = SET_LED_RED(wc->ledtestreg); + if (wc->blinktimer == 480) { + wc->ledtestreg = UNSET_LED_REDGREEN(wc->ledtestreg); + wc->blinktimer = 0; + } + } else if (wc->span.alarms & ZT_ALARM_YELLOW) { + wc->yellowtimer++; + if (!(wc->yellowtimer % 2)) + wc->ledtestreg = SET_LED_RED(wc->ledtestreg); + else + wc->ledtestreg = SET_LED_GREEN(wc->ledtestreg); + } else { + if (wc->span.maintstat != ZT_MAINT_NONE) + wc->ledtestreg = SET_LED_ORANGE(wc->ledtestreg); + else + wc->ledtestreg = UNSET_LED_ORANGE(wc->ledtestreg); + if (wc->span.flags & ZT_FLAG_RUNNING) + wc->ledtestreg = SET_LED_GREEN(wc->ledtestreg); + else + wc->ledtestreg = UNSET_LED_REDGREEN(wc->ledtestreg); + } + + if (wc->ledtestreg != wc->ledlastvalue) { + t1_setleds(wc, wc->ledtestreg, 1); + wc->ledlastvalue = wc->ledtestreg; + } +} + + +static void __t1_do_counters(struct t1 *wc) +{ + if (wc->alarmtimer) { + if (!--wc->alarmtimer) { + wc->span.alarms &= ~(ZT_ALARM_RECOVER); + zt_alarm_notify(&wc->span); + } + } +} + +static inline void t1_isr_misc(struct t1 *wc) +{ + unsigned int x; + + if (unlikely(!wc->initialized)) return; + + __handle_leds(wc); + + __t1_do_counters(wc); + + x = wc->intcount & 0xF; + switch (x) { + case 0: + __t1_check_sigbits_reads(wc); + break; + case 1: + if (!(wc->intcount & 0x30)) { + __t1_check_alarms_reads(wc); + wc->alarms_read=1; + } + break; + case 2: + break; + case 4: + break; + case 5: + break; + case 7: + __t1_check_sigbits(wc); + break; + case 8: + if (wc->alarms_read) { + __t1_check_alarms(wc); + wc->alarms_read=0; + } + break; + case 9: + clean_leftovers(wc); + break; + } +} + +static inline void t1_transmitprep(struct t1 *wc, int dbl) +{ + volatile unsigned char *writechunk; + int x; + int y; + int chan; + + dbl = dbl % 2; + + writechunk = (volatile unsigned char *)(wc->writechunk); + if (dbl) + /* Write is at interrupt address. Start writing from normal offset */ + writechunk += SFRAME_SIZE; + + /* Calculate Transmission */ + if (likely(wc->initialized)) { + spin_unlock(&wc->reglock); + zt_transmit(&wc->span); + spin_lock(&wc->reglock); + } + + for (x = 0; x < ZT_CHUNKSIZE; x++) { + if (likely(wc->initialized)) { + for (chan = 0; chan < wc->span.channels; chan++) + writechunk[(chan+1)*2] = wc->chans[chan].writechunk[x]; + } + + /* process the command queue */ + for (y = 0; y < 7; y++) { + cmd_dequeue(wc, writechunk, x, y); + } +#ifdef VPM_SUPPORT + if(likely(wc->vpm150m)) { + vpm150m_cmd_dequeue(wc, writechunk, x); + } +#endif + + if (x < ZT_CHUNKSIZE - 1) { + writechunk[EFRAME_SIZE] = wc->ctlreg; + writechunk[EFRAME_SIZE + 1] = wc->txident++; + } + writechunk += (EFRAME_SIZE + EFRAME_GAP); + } +} + +static inline void cmd_retransmit(struct t1 *wc) +{ + unsigned int x; + + for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { + if (!(wc->cmdq.cmds[x].flags & __CMD_FIN)) { + wc->cmdq.cmds[x].flags &= ~(__CMD_TX) ; /* clear __CMD_TX */ + wc->cmdq.cmds[x].ident = 0; + } + } +} + +static inline void t1_receiveprep(struct t1 *wc, int dbl) +{ + volatile unsigned char *readchunk; + int x,chan; + unsigned char expected; + + dbl = dbl % 2; + + readchunk = (volatile unsigned char *)wc->readchunk; + if (dbl) + readchunk += SFRAME_SIZE; + for (x = 0; x < ZT_CHUNKSIZE; x++) { + if (likely(wc->initialized)) { + for (chan = 0; chan < wc->span.channels; chan++) { + wc->chans[chan].readchunk[x]= readchunk[(chan+1)*2]; + } + } + if (x < ZT_CHUNKSIZE - 1) { + expected = wc->rxident+1; + wc->rxident = readchunk[EFRAME_SIZE + 1]; + wc->statreg = readchunk[EFRAME_SIZE + 2]; + if (wc->rxident != expected) { + wc->span.irqmisses++; + cmd_retransmit(wc); + if (unlikely(debug && wc->initialized)) + module_printk("oops: rxident=%d expected=%d\n", wc->rxident, expected); + } + } + cmd_decipher(wc, readchunk); +#ifdef VPM_SUPPORT + if(wc->vpm150m) + vpm150m_cmd_decipher(wc, readchunk); +#endif + readchunk += (EFRAME_SIZE + EFRAME_GAP); + } + + /* echo cancel */ + if (likely(wc->initialized)) { + spin_unlock(&wc->reglock); + for (x = 0; x < wc->span.channels; x++) { + zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->ec_chunk2[x]); + memcpy(wc->ec_chunk2[x],wc->ec_chunk1[x],ZT_CHUNKSIZE); + memcpy(wc->ec_chunk1[x],wc->chans[x].writechunk,ZT_CHUNKSIZE); + } + zt_receive(&wc->span); + spin_lock(&wc->reglock); + } + + /* Wake up anyone sleeping to read/write a new register */ + wake_up_interruptible(&wc->regq); +} + +static inline int t1_check_descriptor(struct t1 *wc, int tx) +{ + int o2 = 0; + + if (!tx) { + o2 += ERING_SIZE * 4; + o2 += wc->rdbl * 4; + } else { + o2 += wc->tdbl * 4; + } + + if (!(wc->descripchunk[o2] & 0x80000000)) { + if (tx) { + wc->txints++; + t1_transmitprep(wc, wc->tdbl); + t1_reinit_descriptor(wc, tx, wc->tdbl, "txchk"); + wc->tdbl = (wc->tdbl + 1) % ERING_SIZE; + wc->intcount++; + t1_isr_misc(wc); + } else { + wc->rxints++; + t1_receiveprep(wc, wc->rdbl); + t1_reinit_descriptor(wc, tx, wc->rdbl, "rxchk"); + wc->rdbl = (wc->rdbl + 1) % ERING_SIZE; + } + return 1; + } + return 0; +} + +static int t1_hardware_init(struct t1 *wc) +{ + /* Hardware stuff */ + unsigned int reg; + unsigned long newjiffies; + + /* Initialize descriptors */ + t1_init_descriptors(wc); + + /* Enable I/O Access */ + pci_read_config_dword(wc->dev, PCI_COMMAND, ®); + reg |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + pci_write_config_dword(wc->dev, PCI_COMMAND, reg); + debug_printk(1, "PCI Config reg is %08x\n", reg); + + t1_setctl(wc, 0x0000, 0xfff88001); + + newjiffies = jiffies + HZ/10; + while(((reg = t1_getctl(wc,0x0000)) & 0x00000001) && ( time_after(newjiffies,jiffies) )); + debug_printk(1, "ctlreg 0x0000 now=%08x!\n", reg); + + t1_setctl(wc, 0x0000, 0xfff88000); + + /* Configure watchdogs, access, etc */ + t1_setctl(wc, 0x0030, 0x00280048); + t1_setctl(wc, 0x0078, 0x00000013 /* | (1 << 28) */); + + reg = t1_getctl(wc, 0x00fc); + t1_setctl(wc, 0x00fc, (reg & ~0x7) | 0x7); /* normal mode */ + t1_setsdi(wc, 0x00, 0x0100); + t1_setsdi(wc, 0x16, 0x2100); + debug_printk(1, "Detected SDI REG0: %08x\n", t1_getsdi(wc, 0x00)); + debug_printk(1, "Detected SDI REG1: %08x\n", t1_getsdi(wc, 0x01)); + debug_printk(1, "Detected SDI REG2: %08x\n", t1_getsdi(wc, 0x02)); + + reg = t1_getctl(wc, 0x00fc); + debug_printk(1, "(pre) Reg fc is %08x\n", reg); + + t1_setctl(wc, 0x00fc, (reg & ~0x7) | 0x4); /* mac only */ + t1_setsdi(wc, 0x00, 0x0100); /* full duplex */ + t1_setsdi(wc, 0x16, 0x2100); + reg = t1_getctl(wc, 0x00fc); + debug_printk(1, "(post) ctlreg 0xfc=%08x\n", reg); + debug_printk(1, "Detected SDI REG2: %08x\n", t1_getsdi(wc, 0x02)); + debug_printk(1, "ctlreg 0x0088=%08x\n", t1_getctl(wc, 0x0088)); + + return 0; +} + + +ZAP_IRQ_HANDLER(te12xp_interrupt) +{ + struct t1 *wc = dev_id; + unsigned int ints; + int res; + + /* Read interrupts */ + spin_lock(&wc->reglock); + ints = __t1_getctl(wc, 0x0028); + + if (!ints) { + spin_unlock(&wc->reglock); +#ifdef LINUX26 + return IRQ_NONE; +#else + return; +#endif + } + + /* clear interrupts interrupts (we only get here if interrupt is for us) */ + __t1_setctl(wc, 0x0028, ints); + ints &= wc->intmask; + + if (ints & 0x00000041) { + do { + res = t1_check_descriptor(wc, 0); + res |= t1_check_descriptor(wc, 1); + } while(res); + } + spin_unlock(&wc->reglock); + +#ifdef LINUX26 + return IRQ_RETVAL(1); +#endif +} + +static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct t1 *wc; + struct t1_desc *d = (struct t1_desc *) ent->driver_data; + unsigned int x; + + for (x = 0; x < sizeof(ifaces) / sizeof(ifaces[0]); x++) + if (!ifaces[x]) break; + + if (x >= sizeof(ifaces) / sizeof(ifaces[0])) { + module_printk("Too many interfaces\n"); + return -EIO; + } + + if (pci_enable_device(pdev)) + return -EIO; + + wc = kmalloc(sizeof(*wc), GFP_KERNEL); + if (!wc) + return -ENOMEM; + + ifaces[x] = wc; + memset(wc, 0, sizeof(*wc)); + spin_lock_init(&wc->reglock); + wc->iobase = pci_resource_start(pdev, 0); + wc->dev = pdev; + wc->variety = d->name; + /* Keep track of whether we need to free the region */ + if (request_region(wc->iobase, 0xff, te12xp_driver.name)) + wc->freeregion = 1; + + /* Allocate enough memory for two zt chunks, receive and transmit. + * Each sample uses 32 bits. Allocate an extra set just for + * control too */ + wc->writechunk = (int *) pci_alloc_consistent(pdev, PCI_WINDOW_SIZE, &wc->writedma); + if (!wc->writechunk) { + module_printk("Unable to allocate DMA-able memory\n"); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + kfree(wc); + return -ENOMEM; + } + + wc->readchunk = wc->writechunk + SFRAME_SIZE / 2; /* in doublewords */ + wc->readdma = wc->writedma + SFRAME_SIZE * 2; /* in bytes */ + + wc->descripchunk = wc->readchunk + SFRAME_SIZE / 2; /* in doublewords */ + wc->descripdma = wc->readdma + SFRAME_SIZE * 2; /* in bytes */ + + /* Initialize Write/Buffers to all blank data */ + memset((void *)wc->writechunk, 0x00, SFRAME_SIZE * 2); + memset((void *)wc->readchunk, 0x00, SFRAME_SIZE * 2); + + init_waitqueue_head(&wc->regq); + + /* Enable bus mastering */ + pci_set_master(pdev); + + /* Keep track of which device we are */ + pci_set_drvdata(pdev, wc); + + if (request_irq(pdev->irq, te12xp_interrupt, ZAP_IRQ_SHARED, te12xp_driver.name, wc)) { + module_printk("Unable to request IRQ %d\n", pdev->irq); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *) wc->writechunk, wc->writedma); + pci_set_drvdata(pdev, NULL); + kfree(wc); + return -EIO; + } + + if (t1_hardware_init(wc)) { + /* Set Reset Low */ + t1_stop_dma(wc); + /* Free Resources */ + free_irq(pdev->irq, wc); + if (wc->freeregion) + release_region(wc->iobase, 0xff); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *) wc->writechunk, wc->writedma); + pci_set_drvdata(pdev, NULL); + + kfree(wc); + return -EIO; + + } + + t1_enable_interrupts(wc); + t1_start_dma(wc); + t1_hardware_post_init(wc); + t1_software_init(wc); + module_printk("Found a %s\n", wc->variety); + + return 0; +} + +static void __devexit te12xp_remove_one(struct pci_dev *pdev) +{ + struct t1 *wc = pci_get_drvdata(pdev); +#ifdef VPM_SUPPORT + unsigned long flags; + struct vpm150m *vpm150m = wc->vpm150m; +#endif + if (!wc) + return; + +#ifdef VPM_SUPPORT + if(vpm150m) { + clear_bit(VPM150M_DTMFDETECT, &vpm150m->control); + clear_bit(VPM150M_ACTIVE, &vpm150m->control); + flush_workqueue(vpm150m->wq); + destroy_workqueue(vpm150m->wq); + } +#endif + /* Stop any DMA */ + t1_stop_dma(wc); + + /* In case hardware is still there */ + t1_disable_interrupts(wc); + + if (debug && wc->isrreaderrors) + debug_printk(1, "isrreaderrors=%d\n", wc->isrreaderrors); + + /* Immediately free resources */ + free_irq(pdev->irq, wc); + pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); + +#ifdef VPM_SUPPORT + if(vpm150m) { + spin_lock_irqsave(&wc->reglock, flags); + wc->vpm150m = NULL; + vpm150m->wc = NULL; + spin_unlock_irqrestore(&wc->reglock, flags); + kfree(wc->vpm150m); + } +#endif + /* Release span, possibly delayed */ + if (!wc->usecount) + t1_release(wc); + else + wc->dead = 1; +} + +static struct pci_device_id te12xp_pci_tbl[] = { + { 0xd161, 0x0120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &te120p}, + { 0xd161, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &te121}, + { 0xd161, 0x8001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &te122}, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, te12xp_pci_tbl); + +struct pci_driver te12xp_driver = { + name: "wcte12x[p]", + probe: te12xp_init_one, +#ifdef LINUX26 + remove: __devexit_p(te12xp_remove_one), +#else + remove: te12xp_remove_one, +#endif + suspend: NULL, + resume: NULL, + id_table: te12xp_pci_tbl, +}; + +static int __init te12xp_init(void) +{ + int res; + + res = zap_pci_module(&te12xp_driver); + + return res ? -ENODEV : 0; +} + + +static void __exit te12xp_cleanup(void) +{ + pci_unregister_driver(&te12xp_driver); +} + +#ifdef LINUX26 +module_param(debug, int, S_IRUGO | S_IWUSR); +module_param(loopback, int, S_IRUGO | S_IWUSR); +module_param(t1e1override, int, S_IRUGO | S_IWUSR); +module_param(j1mode, int, S_IRUGO | S_IWUSR); +module_param(alarmdebounce, int, S_IRUGO | S_IWUSR); +#ifdef VPM_SUPPORT +module_param(vpmsupport, int, S_IRUGO | S_IWUSR); +module_param(vpmdtmfsupport, int, S_IRUGO | S_IWUSR); +module_param(vpmtsisupport, int, S_IRUGO | S_IWUSR); +#endif +#else +MODULE_PARM(debug, "i"); +MODULE_PARM(loopback, "i"); +MODULE_PARM(t1e1override, "i"); +MODULE_PARM(j1mode, "i"); +MODULE_PARM(alarmdebounce, "i"); +#ifdef VPM_SUPPORT +MODULE_PARM(vpmsupport, "i"); +MODULE_PARM(vpmdtmfsupport, "i"); +MODULE_PARM(vpmtsisupport, "i"); +MODULE_PARM(vpmnlptype, "i"); +MODULE_PARM(vpmnlpthresh, "i"); +MODULE_PARM(vpmnlpmaxsupp, "i"); +#endif +#endif + +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +module_init(te12xp_init); +module_exit(te12xp_cleanup); diff --git a/kernel/wcte12xp/gpakenum.h b/kernel/wcte12xp/gpakenum.h new file mode 100644 index 0000000..ed14a1a --- /dev/null +++ b/kernel/wcte12xp/gpakenum.h @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2005, Adaptive Digital Technologies, Inc. + * + * File Name: gpakenum.h + * + * Description: + * This file contains common enumerations related to G.PAK application + * software. + * + * Version: 1.0 + * + * Revision History: + * 06/15/05 - Initial release. + * + * This program has been released under the terms of the GPL version 2 by + * permission of Adaptive Digital Technologies, Inc. The standard + * GPL disclaimer is given inline below for your convenience. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _GPAKENUM_H /* prevent multiple inclusion */ +#define _GPAKENUM_H + +/* G.PAK Serial Port Word Size */ +typedef enum +{ + SerWordSize8 = 0, // 8-bit seial word + SerWordSize16 = 1 // 16-bit serial word +} GpakSerWordSize_t; + +/* G.PAK Serial Port FrameSync Polarity */ +typedef enum +{ + FrameSyncActLow = 0, // active low frame sync signal + FrameSyncActHigh = 1 // active high frame sync signal +} GpakSerFrameSyncPol_t; + +/* G.PAK Serial Port Clock Polarity */ +typedef enum +{ + SerClockActLow = 0, // active low serial clock + SerClockActHigh = 1 // active high serial clock +} GpakSerClockPol_t; + +/* G.PAK Serial Port Data Delay */ +typedef enum +{ + DataDelay0 = 0, // no data delay + DataDelay1 = 1, // 1-bit data delay + DataDelay2 = 2 // 2-bit data delay +} GpakSerDataDelay_t; + +/* G.PAK Serial Port Ids. */ +typedef enum +{ + SerialPortNull = 0, // null serial port + SerialPort1 = 1, // first PCM serial stream port (McBSP0) + SerialPort2 = 2, // second PCM serial stream port (McBSP1) + SerialPort3 = 3 // third PCM serial stream port (McBSP2) +} GpakSerialPort_t; + +/* G.PAK serial port Slot Configuration selection codes. */ +typedef enum +{ + SlotCfgNone = 0, // no time slots used + SlotCfg2Groups = 2, // 2 groups of 16 time slots used, 32 Channels system + SlotCfg8Groups = 8 // 8-partition mode for 128-channel system +} GpakSlotCfg_t; + +/* G.PAK serial port Companding Mode codes. */ +typedef enum +{ + cmpPCMU=0, // u-Law + cmpPCMA=1, // A-Law + cmpNone=2 // none +} GpakCompandModes; + +/* G.PAK Active/Inactive selection codes. */ +typedef enum +{ + Disabled=0, // Inactive + Enabled=1 // Active +} GpakActivation; + +/* G.PAK Channel Type codes. */ +typedef enum +{ + inactive=0, // channel inactive + tdmToTdm=1 // tdmToTdm +} GpakChanType; + +/* G.PAK Algorithm control commands */ +typedef enum +{ + EnableEcanA = 0, // Enable A side echo canceller + BypassEcanA = 1, // Bypass A side echo canceller + ResetEcanA = 2, // Reset A side echo canceller + EnableEcanB = 3, // Enable B side echo canceller + BypassEcanB = 4, // Bypass B side echo canceller + ResetEcanB = 5, // Reset B side echo canceller + + EnableMuLawSwCompanding = 6,// Enable Mu-law Software companding + EnableALawSwCompanding = 7, // Enable Mu-law Software companding + BypassSwCompanding = 8, // Bypass Software companding + EnableDTMFMuteA = 9, // Mute A side Dtmf digit after tone detected + DisableDTMFMuteA = 10, // Do not mute A side Dtmf digit once tone detected + EnableDTMFMuteB = 11, // Mute B side Dtmf digit after tone detected + DisableDTMFMuteB = 12, // Do not mute B side Dtmf digit once tone detected + EnableFaxCngDetectA = 13, // Enable A side Fax CNG detector, channel must be configed already + DisableFaxCngDetectA = 14, // Disable A side Fax CNG detector, channel must be configed already + EnableFaxCngDetectB = 15, // Enable B side Fax CNG detector, channel must be configed already + DisableFaxCngDetectB = 16 // Disable B side Fax CNG detector, channel must be configed already +} GpakAlgCtrl_t; + +/* G.PAK Tone types. */ +typedef enum +{ + Null_tone = 0, // no tone detection + DTMF_tone = 1 // DTMF tone +} GpakToneTypes; + +/* G.PAK direction. */ +typedef enum +{ + TDMAToB = 0, // A to B + TDMBToA = 1 // B to A +} GpakTdmDirection; + + +typedef enum +{ + rate1ms=0, + rate2ms=1, + rate10ms=2 +} GpakRate_t; + +/* G.PAK Asynchronous Event Codes */ +typedef enum +{ + EventToneDetect = 0, // Tone detection event + EventDSPDebug = 7 // DSP debug data event +} GpakAsyncEventCode_t; + +/* G.PAK MF Tone Code Indices */ +typedef enum +{ + DtmfDigit1 = 0, // DTMF Digit 1 + DtmfDigit2 = 1, // DTMF Digit 2 + DtmfDigit3 = 2, // DTMF Digit 3 + DtmfDigitA = 3, // DTMF Digit A + DtmfDigit4 = 4, // DTMF Digit 4 + DtmfDigit5 = 5, // DTMF Digit 5 + DtmfDigit6 = 6, // DTMF Digit 6 + DtmfDigitB = 7, // DTMF Digit B + DtmfDigit7 = 8, // DTMF Digit 7 + DtmfDigit8 = 9, // DTMF Digit 8 + DtmfDigit9 = 10, // DTMF Digit 9 + DtmfDigitC = 11, // DTMF Digit C + DtmfDigitSt = 12, // DTMF Digit * + DtmfDigit0 = 13, // DTMF Digit 0 + DtmfDigitPnd = 14, // DTMF Digit # + DtmfDigitD = 15, // DTMF Digit D + + FaxCngDigit = 90, // Fax Calling Tone (1100 Hz) + + EndofMFDigit = 100, // End of MF digit + EndofCngDigit = 101 // End of Cng Digit +} GpakToneCodes_t; + +/* GPIO control code*/ +typedef enum +{ + GPIO_READ = 0, + GPIO_WRITE = 1, + GPIO_DIR = 2 +} GpakGPIOCotrol_t; + +#endif // end multiple inclusion diff --git a/kernel/wcte12xp/vpmadt032.c b/kernel/wcte12xp/vpmadt032.c new file mode 100644 index 0000000..89fd372 --- /dev/null +++ b/kernel/wcte12xp/vpmadt032.c @@ -0,0 +1,1385 @@ +/* + * Digium, Inc. Wildcard TE12xP T1/E1 card Driver + * + * Written by Michael Spiceland + * + * Adapted from the wctdm24xxp and wcte11xp drivers originally + * written by Mark Spencer + * Matthew Fredrickson + * William Meadows + * + * Copyright (C) 2007, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include + +#include "zaptel.h" + +#include "wcte12xp.h" +#include "vpmadt032.h" +#include "GpakApi.h" + +extern struct t1 *ifaces[WC_MAX_IFACES]; + +extern int vpmnlptype; +extern int vpmnlpthresh; +extern int vpmnlpmaxsupp; + +#ifdef VPM_SUPPORT + +inline void vpm150m_cmd_dequeue(struct t1 *wc, volatile unsigned char *writechunk, int whichframe) +{ + struct vpm150m_cmd *curcmd = NULL; + struct vpm150m *vpm150m = wc->vpm150m; + int x; + unsigned char leds = ~((wc->intcount / 1000) % 8) & 0x7; + + /* Skip audio */ + writechunk += 66; + + if (test_bit(VPM150M_SPIRESET, &vpm150m->control) || test_bit(VPM150M_HPIRESET, &vpm150m->control)) { + debug_printk(1, "HW Resetting VPMADT032 ...\n"); + for (x = 0; x < 4; x++) { + if (!x) { + if (test_and_clear_bit(VPM150M_SPIRESET, &vpm150m->control)) + writechunk[CMD_BYTE(x, 0, 1)] = 0x08; + else if (test_and_clear_bit(VPM150M_HPIRESET, &vpm150m->control)) + writechunk[CMD_BYTE(x, 0, 1)] = 0x0b; + } else + writechunk[CMD_BYTE(x, 0, 1)] = 0x00 | leds; + writechunk[CMD_BYTE(x, 1, 1)] = 0; + writechunk[CMD_BYTE(x, 2, 1)] = 0x00; + } + return; + } + + /* Search for something waiting to transmit */ + for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { + if ((vpm150m->cmdq[x].flags & (__VPM150M_RD | __VPM150M_WR)) && + !(vpm150m->cmdq[x].flags & (__VPM150M_FIN | __VPM150M_TX))) { + curcmd = &vpm150m->cmdq[x]; + curcmd->ident = wc->txident; + curcmd->flags |= __VPM150M_TX; + break; + } + } + if (curcmd) { +#if 0 + printk("Found command txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", curcmd->txident, curcmd->desc, curcmd->addr, curcmd->data); +#endif + if (curcmd->flags & __VPM150M_RWPAGE) { + /* Set CTRL access to page*/ + writechunk[CMD_BYTE(0, 0, 1)] = (0x8 << 4); + writechunk[CMD_BYTE(0, 1, 1)] = 0; + writechunk[CMD_BYTE(0, 2, 1)] = 0x20; + + /* Do a page write */ + if (curcmd->flags & __VPM150M_WR) + writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | 0x4) << 4); + else + writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | 0x4 | 0x1) << 4); + writechunk[CMD_BYTE(1, 1, 1)] = 0; + if (curcmd->flags & __VPM150M_WR) + writechunk[CMD_BYTE(1, 2, 1)] = curcmd->data[0] & 0xf; + else + writechunk[CMD_BYTE(1, 2, 1)] = 0; + + if (curcmd->flags & __VPM150M_WR) { + /* Fill in buffer to size */ + writechunk[CMD_BYTE(2, 0, 1)] = 0; + writechunk[CMD_BYTE(2, 1, 1)] = 0; + writechunk[CMD_BYTE(2, 2, 1)] = 0; + } else { + /* Do reads twice b/c of vpmadt032 bug */ + writechunk[CMD_BYTE(2, 0, 1)] = ((0x8 | 0x4 | 0x1) << 4); + writechunk[CMD_BYTE(2, 1, 1)] = 0; + writechunk[CMD_BYTE(2, 2, 1)] = 0; + } + + /* Clear XADD */ + writechunk[CMD_BYTE(3, 0, 1)] = (0x8 << 4); + writechunk[CMD_BYTE(3, 1, 1)] = 0; + writechunk[CMD_BYTE(3, 2, 1)] = 0; + + /* Fill in buffer to size */ + writechunk[CMD_BYTE(4, 0, 1)] = 0; + writechunk[CMD_BYTE(4, 1, 1)] = 0; + writechunk[CMD_BYTE(4, 2, 1)] = 0; + + } else { + /* Set address */ + writechunk[CMD_BYTE(0, 0, 1)] = ((0x8 | 0x4) << 4); + writechunk[CMD_BYTE(0, 1, 1)] = (curcmd->address >> 8) & 0xff; + writechunk[CMD_BYTE(0, 2, 1)] = curcmd->address & 0xff; + + /* Send/Get our data */ + if (curcmd->flags & __VPM150M_WR) { + if (curcmd->datalen > 1) + writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x1 << 1)) << 4); + else + writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x3 << 1)) << 4); + } else + if (curcmd->datalen > 1) + writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x1 << 1) | 0x1) << 4); + else + writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x3 << 1) | 0x1) << 4); + writechunk[CMD_BYTE(1, 1, 1)] = (curcmd->data[0] >> 8) & 0xff; + writechunk[CMD_BYTE(1, 2, 1)] = curcmd->data[0] & 0xff; + + if (curcmd->flags & __VPM150M_WR) { + /* Fill in */ + writechunk[CMD_BYTE(2, 0, 1)] = 0; + writechunk[CMD_BYTE(2, 1, 1)] = 0; + writechunk[CMD_BYTE(2, 2, 1)] = 0; + } else { + /* Do this again for reads b/c of the bug in vpmadt032 */ + writechunk[CMD_BYTE(2, 0, 1)] = ((0x8 | (0x3 << 1) | 0x1) << 4); + writechunk[CMD_BYTE(2, 1, 1)] = (curcmd->data[0] >> 8) & 0xff; + writechunk[CMD_BYTE(2, 2, 1)] = curcmd->data[0] & 0xff; + } + + if (curcmd->datalen > 1) { + if (curcmd->flags & __VPM150M_WR) + writechunk[CMD_BYTE(3, 0, 1)] = ((0x8 | (0x1 << 1)) << 4); + else + writechunk[CMD_BYTE(3, 0, 1)] = ((0x8 | (0x1 << 1) | 0x1) << 4); + writechunk[CMD_BYTE(3, 1, 1)] = (curcmd->data[1] >> 8) & 0xff; + writechunk[CMD_BYTE(3, 2, 1)] = curcmd->data[1] & 0xff; + } else { + /* Fill in the rest */ + writechunk[CMD_BYTE(3, 0, 1)] = 0; + writechunk[CMD_BYTE(3, 1, 1)] = 0; + writechunk[CMD_BYTE(3, 2, 1)] = 0; + } + + if (curcmd->datalen > 2) { + if (curcmd->flags & __VPM150M_WR) + writechunk[CMD_BYTE(4, 0, 1)] = ((0x8 | (0x1 << 1)) << 4); + else + writechunk[CMD_BYTE(4, 0, 1)] = ((0x8 | (0x1 << 1) | 0x1) << 4); + writechunk[CMD_BYTE(4, 1, 1)] = (curcmd->data[2] >> 8) & 0xff; + writechunk[CMD_BYTE(4, 2, 1)] = curcmd->data[2] & 0xff; + } else { + /* Fill in the rest */ + writechunk[CMD_BYTE(4, 0, 1)] = 0; + writechunk[CMD_BYTE(4, 1, 1)] = 0; + writechunk[CMD_BYTE(4, 2, 1)] = 0; + } + } + } else if (test_and_clear_bit(VPM150M_SWRESET, &vpm150m->control)) { + debug_printk(1, "Booting VPMADT032\n"); + for (x = 0; x < 7; x++) { + if (x == 0) + writechunk[CMD_BYTE(x, 0, 1)] = (0x8 << 4); + else + writechunk[CMD_BYTE(x, 0, 1)] = 0x00; + writechunk[CMD_BYTE(x, 1, 1)] = 0; + if (x == 0) + writechunk[CMD_BYTE(x, 2, 1)] = 0x01; + else + writechunk[CMD_BYTE(x, 2, 1)] = 0x00; + } + } else { + for (x = 0; x < 7; x++) { + writechunk[CMD_BYTE(x, 0, 1)] = 0x00; + writechunk[CMD_BYTE(x, 1, 1)] = 0x00; + writechunk[CMD_BYTE(x, 2, 1)] = 0x00; + } + } + + /* Add our leds in */ + for (x = 0; x < 7; x++) + writechunk[CMD_BYTE(x, 0, 1)] |= leds; + +#if 0 + int y; + for (x = 0; x < 7; x++) { + for (y = 0; y < 3; y++) { + if (writechunk[CMD_BYTE(x, y, 1)] & 0x2) { + module_printk("the test bit is high for byte %d\n", y); + } + } + } +#endif + + /* Now let's figure out if we need to check for DTMF */ + /* polling */ + if (test_bit(VPM150M_ACTIVE, &vpm150m->control) && !whichframe && !(wc->intcount % 100)) + queue_work(vpm150m->wq, &vpm150m->work_dtmf); + +#if 0 + /* This may be needed sometime in the future to troubleshoot ADT related issues. */ + if (test_bit(VPM150M_ACTIVE, &vpm150m->control) && !whichframe && !(wc->intcount % 10000)) + queue_work(vpm150m->wq, &vpm150m->work_debug); +#endif +} + +inline void vpm150m_cmd_decipher(struct t1 *wc, volatile unsigned char *readchunk) +{ + unsigned char ident; + int x, i; + + /* Skip audio */ + readchunk += 66; + /* Search for any pending results */ + for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { + if ((wc->vpm150m->cmdq[x].flags & (__VPM150M_RD | __VPM150M_WR)) && + (wc->vpm150m->cmdq[x].flags & (__VPM150M_TX)) && + !(wc->vpm150m->cmdq[x].flags & (__VPM150M_FIN))) { + ident = wc->vpm150m->cmdq[x].ident; + if (ident == wc->rxident) { + /* Store result */ + for (i = 0; i < wc->vpm150m->cmdq[x].datalen; i++) { + wc->vpm150m->cmdq[x].data[i] = (0xff & readchunk[CMD_BYTE((2 + i), 1, 1)]) << 8; + wc->vpm150m->cmdq[x].data[i] |= readchunk[CMD_BYTE((2 + i), 2, 1)]; + } + if (wc->vpm150m->cmdq[x].flags & __VPM150M_WR) { + /* Go ahead and clear out writes since they need no acknowledgement */ + wc->vpm150m->cmdq[x].flags = 0; + } else + wc->vpm150m->cmdq[x].flags |= __VPM150M_FIN; + break; + } + } + } +} + +static inline struct t1 * wc_find_iface(unsigned short dspid) +{ + int i; + struct t1 *ret = NULL; + unsigned long flags; + + spin_lock_irqsave(&ifacelock, flags); + for (i = 0; i < WC_MAX_IFACES; i++) + if (ifaces[i] && ifaces[i]->vpm150m && (ifaces[i]->vpm150m->dspid == dspid)) + ret = ifaces[i]; + spin_unlock_irqrestore(&ifacelock, flags); + + return ret; +} + +static struct vpm150m_cmd * vpm150m_empty_slot(struct t1 *wc) +{ + unsigned int x; + + for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { + if (!wc->vpm150m->cmdq[x].flags) { + return &wc->vpm150m->cmdq[x]; + } + } + return NULL; +} + +/* Wait for any outstanding commands to be completed. */ +static inline int vpm150m_io_wait(struct t1 *wc) +{ + int x; + int ret=0; + for (x=0; x < VPM150M_MAX_COMMANDS;) { + if (wc->vpm150m->cmdq[x].flags) { + if ((ret=schluffen(&wc->regq))) { + return ret; + } + x=0; + } + else { + ++x; + } + } + return ret; +} + +int t1_vpm150m_getreg_full_async(struct t1 *wc, int pagechange, unsigned int len, + unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) +{ + int ret=0; + unsigned long flags; + BUG_ON(!hit_p); + spin_lock_irqsave(&wc->reglock, flags); + (*hit_p) = vpm150m_empty_slot(wc); + if (*hit_p) { + (*hit_p)->flags = __VPM150M_RD; + if (pagechange) { + (*hit_p)->flags |= __VPM150M_RWPAGE; + } + (*hit_p)->datalen = len; + (*hit_p)->address = addr; + memset((*hit_p)->data, 0, len*sizeof(outbuf[0])); + } + else { + ret = -EBUSY; + } + spin_unlock_irqrestore(&wc->reglock, flags); + return ret; +} + +int t1_vpm150m_getreg_full_return(struct t1 *wc, int pagechange, unsigned int len, + unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) +{ + int ret = 0; + unsigned long flags; + BUG_ON(!hit_p); + spin_lock_irqsave(&wc->reglock, flags); + do { + if ((*hit_p)->flags & __VPM150M_FIN) { + memcpy(outbuf, (*hit_p)->data, len*(sizeof(outbuf[0]))); + (*hit_p)->flags = 0; + (*hit_p) = NULL; + ret = 0; + } + else { + spin_unlock_irqrestore(&wc->reglock, flags); + if ((ret=schluffen(&wc->regq))) { + return ret; + } + spin_lock_irqsave(&wc->reglock, flags); + ret = -EBUSY; + } + } while (-EBUSY == ret); + spin_unlock_irqrestore(&wc->reglock, flags); + return ret; +} + +int t1_vpm150m_getreg_full(struct t1 *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf) +{ + struct vpm150m_cmd *hit = 0; + int ret = 0; + do { + ret = t1_vpm150m_getreg_full_async(wc, pagechange, len, addr, outbuf, &hit); + if (!hit) { + if ( -EBUSY == ret ) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + BUG_ON( 0 != ret); + } + } while (!hit); + + ret = t1_vpm150m_getreg_full_return(wc, pagechange, len, addr, outbuf, &hit); + return ret; +} + +int t1_vpm150m_setreg_full(struct t1 *wc, int pagechange, unsigned int len, unsigned int addr, unsigned short *data) +{ + unsigned long flags; + struct vpm150m_cmd *hit; + int ret, i; + do { + spin_lock_irqsave(&wc->reglock, flags); + hit = vpm150m_empty_slot(wc); + if (hit) { + hit->flags = __VPM150M_WR; + if (pagechange) + hit->flags |= __VPM150M_RWPAGE; + hit->address = addr; + hit->datalen = len; + for (i = 0; i < len; i++) + hit->data[i] = data[i]; + } + spin_unlock_irqrestore(&wc->reglock, flags); + if (!hit) { + if ((ret = schluffen(&wc->regq))) + return ret; + } + } while (!hit); + return (hit) ? 0 : -1; +} + +int t1_vpm150m_setpage(struct t1 *wc, unsigned short addr) +{ + addr &= 0xf; + /* Let's optimize this a little bit */ + if (wc->vpm150m->curpage == addr) + return 0; + else { + wc->vpm150m->curpage = addr; + } + + return t1_vpm150m_setreg_full(wc, 1, 1, 0, &addr); +} + +unsigned char t1_vpm150m_getpage(struct t1 *wc) +{ + unsigned short res; + t1_vpm150m_getreg_full(wc, 1, 1, 0, &res); + return res; +} + +int t1_vpm150m_setreg(struct t1 *wc, unsigned int len, unsigned int addr, unsigned short *data) +{ + int res; + t1_vpm150m_setpage(wc, addr >> 16); + if ((addr >> 16) != ((addr + len) >> 16)) + module_printk("setreg: You found it!\n"); + res = t1_vpm150m_setreg_full(wc, 0, len, addr & 0xffff, data); + return res; +} + +unsigned short t1_vpm150m_getreg(struct t1 *wc, unsigned int len, unsigned int addr, unsigned short *data) +{ + unsigned short res; + t1_vpm150m_setpage(wc, addr >> 16); + if ((addr >> 16) != ((addr + len) >> 16)) + module_printk("getreg: You found it!\n"); + res = t1_vpm150m_getreg_full(wc, 0, len, addr & 0xffff, data); + return res; +} + +static char vpm150mtone_to_zaptone(GpakToneCodes_t tone) +{ + switch (tone) { + case DtmfDigit0: + return '0'; + case DtmfDigit1: + return '1'; + case DtmfDigit2: + return '2'; + case DtmfDigit3: + return '3'; + case DtmfDigit4: + return '4'; + case DtmfDigit5: + return '5'; + case DtmfDigit6: + return '6'; + case DtmfDigit7: + return '7'; + case DtmfDigit8: + return '8'; + case DtmfDigit9: + return '9'; + case DtmfDigitPnd: + return '#'; + case DtmfDigitSt: + return '*'; + case DtmfDigitA: + return 'A'; + case DtmfDigitB: + return 'B'; + case DtmfDigitC: + return 'C'; + case DtmfDigitD: + return 'D'; + case EndofCngDigit: + return 'f'; + default: + return 0; + } +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void vpm150m_echocan_bh(void *data) +{ + struct vpm150m *vpm150m = data; +#else +static void vpm150m_echocan_bh(struct work_struct *data) +{ + struct vpm150m *vpm150m = container_of(data, struct vpm150m, work_echocan); +#endif + struct t1 *wc = vpm150m->wc; + struct list_head *task; + struct list_head *next_task; + unsigned long flags; + + list_for_each_safe(task, next_task, &vpm150m->worklist) { + struct vpm150m_workentry *we = list_entry(task, struct vpm150m_workentry, list); + struct zt_chan *chan = we->chan; + int deflaw; + int res; + GPAK_AlgControlStat_t pstatus; + + if (we->params.tap_length) { + /* configure channel for the ulaw/alaw */ + unsigned int start = wc->intcount; + + if (memcmp(&we->params, &vpm150m->chan_params[chan->chanpos - 1], sizeof(we->params))) { + /* set parameters */ + vpm150m->chan_params[chan->chanpos - 1] = we->params; + } + + deflaw = chan->span->deflaw; + debug_printk(1, "Enabling EC on channel %d (law %d)\n", chan->chanpos, deflaw); + if (deflaw == 2) /* alaw */ + res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, EnableALawSwCompanding, &pstatus); + else if (deflaw == 1) /* alaw */ + res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, EnableMuLawSwCompanding, &pstatus); + else { + module_printk("Undefined law for channel %d.\n", chan->chanpos); + res = -1; + } + + if (res) { + module_printk("Unable to set SW Companding on channel %d (reason %d)\n", chan->chanpos, res); + } + + res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, EnableEcanA, &pstatus); + debug_printk(2, "Echo can enable took %d ms\n", wc->intcount - start); + } else { + unsigned int start = wc->intcount; + debug_printk(1, "Disabling EC on channel %d\n", chan->chanpos); + res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, BypassSwCompanding, &pstatus); + if (res) + module_printk("Unable to disable sw companding on echo cancellation channel %d (reason %d)\n", chan->chanpos, res); + res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, BypassEcanA, &pstatus); + if (res) + module_printk("Unable to disable echo can on channel %d (reason %d)\n", chan->chanpos, res); + debug_printk(2, "Echocan disable took %d ms\n", wc->intcount - start); + } + if (res) { + module_printk("Unable to toggle echo cancellation on channel %d (reason %d)\n", chan->chanpos, res); + } + + spin_lock_irqsave(&vpm150m->lock, flags); + list_del(task); + spin_unlock_irqrestore(&vpm150m->lock, flags); + kfree(we); + } +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void vpm150m_debug_bh(void *data) +{ + struct vpm150m *vpm150m = data; +#else +static void vpm150m_debug_bh(struct work_struct *data) +{ + struct vpm150m *vpm150m = container_of(data, struct vpm150m, work_debug); +#endif + unsigned short int FrammingError1Count, FramingError2Count, FramingError3Count, + DmaStopErrorCount, DmaSlipStatsBuffer; + + if (gpakReadFramingStats(vpm150m->dspid, &FrammingError1Count, &FramingError2Count, &FramingError3Count, + &DmaStopErrorCount, &DmaSlipStatsBuffer)) + { + module_printk("There was an error getting framing stats.\n"); + } + if (FrammingError1Count||FramingError2Count||FramingError3Count||DmaStopErrorCount||DmaSlipStatsBuffer) + { + module_printk("FramingStats Error: %d %d %d %d %d\n", + FrammingError1Count, FramingError2Count, FramingError3Count, DmaStopErrorCount, DmaSlipStatsBuffer); + } +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +static void vpm150m_dtmf_bh(void *data) +{ + struct vpm150m *vpm150m = data; +#else +static void vpm150m_dtmf_bh(struct work_struct *data) +{ + struct vpm150m *vpm150m = container_of(data, struct vpm150m, work_dtmf); +#endif + struct t1 *wc = vpm150m->wc; + int i; + + for (i = 0; i < wc->span.channels; i++) { + int enable = -1; + if (test_bit(i, &vpm150m->desireddtmfmutestate)) { + if (!test_bit(i, &vpm150m->curdtmfmutestate)) { + enable = 1; + } + } else { + if (test_bit(i, &vpm150m->curdtmfmutestate)) { + enable = 0; + } + } + if (enable > -1) { + unsigned int start = wc->intcount; + GPAK_AlgControlStat_t pstatus; + int res; + + if (enable) { + res = gpakAlgControl(vpm150m->dspid, i, EnableDTMFMuteA, &pstatus); + debug_printk(2, "DTMF mute enable took %d ms\n", wc->intcount - start); + } else { + res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &pstatus); + debug_printk(2, "DTMF mute disable took %d ms\n", wc->intcount - start); + } + if (!res) + change_bit(i, &vpm150m->curdtmfmutestate); + } + } + + if (test_bit(VPM150M_DTMFDETECT, &vpm150m->control)) { + unsigned short channel; + GpakAsyncEventCode_t eventcode; + GpakAsyncEventData_t eventdata; + gpakReadEventFIFOMessageStat_t res; + unsigned int start = wc->intcount; + + do { + res = gpakReadEventFIFOMessage(vpm150m->dspid, &channel, &eventcode, &eventdata); + debug_printk(3, "ReadEventFIFOMessage took %d ms\n", wc->intcount - start); + + if (res == RefInvalidEvent || res == RefDspCommFailure) { + module_printk("Uh oh (%d)\n", res); + continue; + } + + if (eventcode == EventToneDetect) { + GpakToneCodes_t tone = eventdata.toneEvent.ToneCode; + int duration = eventdata.toneEvent.ToneDuration; + char zaptone = vpm150mtone_to_zaptone(tone); + + debug_printk(1, "Channel %d: Detected DTMF tone %d of duration %d\n", channel + 1, tone, duration); + + if (test_bit(channel, &wc->dtmfmask) && (eventdata.toneEvent.ToneDuration > 0)) { + struct zt_chan *chan = &wc->chans[channel]; + + module_printk("DTMF detected channel=%d tone=%d duration=%d\n", channel + 1, tone, duration); + + if ((tone != EndofMFDigit) && (zaptone != 0)) { + vpm150m->curtone[channel] = tone; + + if (test_bit(channel, &vpm150m->curdtmfmutestate)) { + unsigned long flags; + int y; + + /* Mute the audio data buffers */ + spin_lock_irqsave(&chan->lock, flags); + for (y = 0; y < chan->numbufs; y++) { + if ((chan->inreadbuf > -1) && (chan->readidx[y])) + memset(chan->readbuf[chan->inreadbuf], ZT_XLAW(0, chan), chan->readidx[y]); + } + spin_unlock_irqrestore(&chan->lock, flags); + } + if (!test_bit(channel, &wc->dtmfactive)) { + debug_printk(1,"Queuing DTMFDOWN %c\n", zaptone); + set_bit(channel, &wc->dtmfactive); + zt_qevent_lock(chan, (ZT_EVENT_DTMFDOWN | zaptone)); + } + } else if ((tone == EndofMFDigit) && test_bit(channel, &wc->dtmfactive)) { + debug_printk(1,"Queuing DTMFUP %c\n", vpm150mtone_to_zaptone(vpm150m->curtone[channel])); + zt_qevent_lock(chan, (ZT_EVENT_DTMFUP | vpm150mtone_to_zaptone(vpm150m->curtone[channel]))); + clear_bit(channel, &wc->dtmfactive); + } + } + } + } while ((res == RefEventAvail)); + } + + return; +} + +void t1_vpm150m_init(struct t1 *wc) { + struct vpm150m *vpm150m; + unsigned short i; + unsigned short reg; + unsigned long flags; + gpakPingDspStat_t pingstatus; + gpakDownloadStatus_t downloadstatus; + struct t1_firmware fw; + struct firmware embedded_firmware; + const struct firmware *firmware = &embedded_firmware; +#if !defined(HOTPLUG_FIRMWARE) + extern void _binary_zaptel_fw_vpmadt032_bin_size; + extern u8 _binary_zaptel_fw_vpmadt032_bin_start[]; +#else + static const char vpmadt032_firmware[] = "zaptel-fw-vpmadt032.bin"; +#endif + +#if 0 + unsigned short omsg[4] = { 0xdead, 0xbeef, 0x1111, 0x2222}; + unsigned short imsg[4]; +#endif + + if (!vpmsupport) { + module_printk("VPM Support Disabled\n"); + wc->vpm150m = NULL; + return; + } + + vpm150m = kmalloc(sizeof(struct vpm150m), GFP_KERNEL); + + if (!vpm150m) { + module_printk("Unable to allocate VPMADT032!\n"); + return; + } + memset(vpm150m, 0, sizeof(struct vpm150m)); + + /* Init our vpm150m struct */ + sema_init(&vpm150m->sem, 1); + vpm150m->curpage = 0x80; + + for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++) { + if (ifaces[i] == wc) + vpm150m->dspid = i; + } + + debug_printk(1, "Setting VPMADT032 DSP ID to %d\n", vpm150m->dspid); + spin_lock_irqsave(&wc->reglock, flags); + wc->vpm150m = vpm150m; + spin_unlock_irqrestore(&wc->reglock, flags); + + for (i = 0; i < 10; i++) + schluffen(&wc->regq); + + debug_printk(1, "Looking for VPMADT032 by testing page access: "); + for (i = 0; i < 0xf; i++) { + int x; + for (x = 0; x < 3; x++) { + t1_vpm150m_setpage(wc, i); + reg = t1_vpm150m_getpage(wc); + if (reg != i) { + /* If they have debug turned on we want them to be able to + * report where in the code the module failed to come up. */ + debug_printk(1, "Either no VPMADT032 module present or the module failed VPM page access test (%x != %x)\n", i, reg); + goto failed_exit; + } + } + } + debug_printk(1, "Passed\n"); + + set_bit(VPM150M_HPIRESET, &vpm150m->control); + msleep(2000); + + /* Set us up to page 0 */ + t1_vpm150m_setpage(wc, 0); + debug_printk(1, "VPMADT032 now doing address test: "); + for (i = 0; i < 16; i++) { + int x; + for (x = 0; x < 2; x++) { + t1_vpm150m_setreg(wc, 1, 0x1000, &i); + t1_vpm150m_getreg(wc, 1, 0x1000, ®); + if (reg != i) { + module_printk("VPMADT032 Failed address test: sent %x != %x on try %d\n", i, reg, x); + goto failed_exit; + } + } + } + debug_printk(1, "Passed\n"); + +#if 0 + /* begin short test */ +#define TEST_SIZE 1 + { + int i; + unsigned short msg[TEST_SIZE]; + + set_bit(VPM150M_HPIRESET, &vpm150m->control); + msleep(2000); + + /* lets see whats in there to start with*/ + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + printk("at first :"); + for (i = 0; i< TEST_SIZE; i++) + printk("%04x ", msg[i]); + printk("\n"); + + /* what if we put dead in there*/ + for (i = 0; i< TEST_SIZE; i++) + msg[i] = 0xdead; + gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + printk("now :"); + for (i = 0; i< TEST_SIZE; i++) + printk("%04x ", msg[i]); + printk("\n"); + + /* lets see if its in there now */ + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + printk("try again:"); + for (i = 0; i< TEST_SIZE; i++) + printk("%04x ", msg[i]); + printk("\n"); + } + + goto failed_exit; +#endif + +#define TEST_SIZE 2 + if (debug) { + int i; + unsigned short msg[TEST_SIZE]; + + set_bit(VPM150M_HPIRESET, &vpm150m->control); + msleep(2000); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + for (i = 0; i< TEST_SIZE; i++) + msg[i] = 0xdead; + gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + for (i = 0; i< TEST_SIZE; i++) + msg[i] = 0xbeef; + gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + for (i = 0; i< TEST_SIZE; i++) + msg[i] = 0x1111; + gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + for (i = 0; i< TEST_SIZE; i++) + msg[i] = 0x2222; + gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); + for (i = 0; i< TEST_SIZE; i++) + printk("%x ", msg[i]); + printk("\n"); + } +#if 0 + printk("Sending\n"); + + for (i = 0; i < 4; i++) { + unsigned short x = 0xffff; + t1_vpm150m_setreg(wc, 1, 0x1000 + i, &x); + } + + gpakReadDspMemory(vpm150m->dspid, 0x1000, 4, imsg); + + printk("Read back:\n"); + for (i = 0; i < 4; i++) + printk("%x ", imsg[i]); + printk("\n"); + + printk("Sending\n"); + gpakWriteDspMemory(vpm150m->dspid, 0x1000, 4, omsg); + for (i = 0; i < 4; i++) + t1_vpm150m_getreg(wc, 1, 0x1000 + i, &imsg[i]); + + printk("Read back\n"); + for (i = 0; i < 4; i++) + printk("%x ", imsg[i]); + printk("\n"); + +#endif + +#if 0 + /* Load the firmware */ + set_bit(VPM150M_SPIRESET, &vpm150m->control); + + /* Wait for it to boot */ + msleep(7000); + + pingstatus = gpakPingDsp(vpm150m->dspid, &version); + + if (pingstatus) { + module_printk("Pingstatus %d, you failed!!! Ha ha ha ha\n", pingstatus); + } else + module_printk("version is 0x%08x\n", version); + + if (pingstatus || (version != 0x106)) { +#endif +#if defined(HOTPLUG_FIRMWARE) + if ((request_firmware(&firmware, vpmadt032_firmware, &wc->dev->dev) != 0) || + !firmware) { + printk("VPMADT032: firmware %s not available from userspace\n", vpmadt032_firmware); + goto failed_exit; + } +#else + embedded_firmware.data = _binary_zaptel_fw_vpmadt032_bin_start; + embedded_firmware.size = (size_t) &_binary_zaptel_fw_vpmadt032_bin_size; +#endif + fw.fw = firmware; + fw.offset = 0; + + set_bit(VPM150M_HPIRESET, &vpm150m->control); + + while (test_bit(VPM150M_HPIRESET, &vpm150m->control)) + schluffen(&wc->regq); + + module_printk("VPMADT032 Loading firwmare... "); + downloadstatus = gpakDownloadDsp(vpm150m->dspid, &fw); + + if (firmware != &embedded_firmware) + release_firmware(firmware); + + if (downloadstatus != 0) { + module_printk("Unable to download firmware to VPMADT032 with cause %d\n", downloadstatus); + goto failed_exit; + } else { + module_printk("Success\n"); + } + + set_bit(VPM150M_SWRESET, &vpm150m->control); + + while (test_bit(VPM150M_SWRESET, &vpm150m->control)) + schluffen(&wc->regq); + + msleep(700); +#if 0 + } +#endif + + pingstatus = gpakPingDsp(vpm150m->dspid, &vpm150m->version); + + if (!pingstatus) { + debug_printk(1, "Version of DSP is %x\n", vpm150m->version); + } else { + module_printk("Unable to ping the DSP (%d)!\n", pingstatus); + goto failed_exit; + } + + /* workqueue for DTMF and wc->span functions that cannot sleep */ + spin_lock_init(&vpm150m->lock); + vpm150m->wq = create_singlethread_workqueue("wcte12xp"); + vpm150m->wc = wc; + if (!vpm150m->wq) { + module_printk("Unable to create work queue!\n"); + goto failed_exit; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + INIT_WORK(&vpm150m->work_echocan, vpm150m_echocan_bh, vpm150m); + INIT_WORK(&vpm150m->work_dtmf, vpm150m_dtmf_bh, vpm150m); + INIT_WORK(&vpm150m->work_debug, vpm150m_debug_bh, vpm150m); +#else + INIT_WORK(&vpm150m->work_echocan, vpm150m_echocan_bh); + INIT_WORK(&vpm150m->work_dtmf, vpm150m_dtmf_bh); + INIT_WORK(&vpm150m->work_debug, vpm150m_debug_bh); +#endif + INIT_LIST_HEAD(&wc->vpm150m->worklist); /* list of echocan tasks */ + + if (vpm150m_config_hw(wc)) { + goto failed_exit; + } + + return; + +failed_exit: + if (vpm150m->wq) { + destroy_workqueue(vpm150m->wq); + } + spin_lock_irqsave(&wc->reglock, flags); + wc->vpm150m = NULL; + spin_unlock_irqrestore(&wc->reglock, flags); + kfree(vpm150m); + + return; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadDspMemory - Read DSP memory. + * + * FUNCTION + * This function reads a contiguous block of words from DSP memory starting at + * the specified address. + * + * RETURNS + * nothing + * + */ +void gpakReadDspMemory( + unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ + unsigned int NumWords, /* number of contiguous words to read */ + DSP_WORD *pWordValues /* pointer to array of word values variable */ + ) +{ + struct t1 *wc = wc_find_iface(DspId); + int i; + int transcount; + int ret; + + vpm150m_io_wait(wc); + if ( NumWords < VPM150M_MAX_COMMANDS ) { + struct vpm150m_cmd* cmds[VPM150M_MAX_COMMANDS] = {0}; + t1_vpm150m_setpage(wc, DspAddress >> 16); + DspAddress &= 0xffff; + for (i=0; i < NumWords; ++i) { + ret = t1_vpm150m_getreg_full_async(wc,0,1,DspAddress+i,&pWordValues[i], + &cmds[i]); + if (0 != ret) { + return; + } + } + for (i=NumWords-1; i >=0; --i) { + ret = t1_vpm150m_getreg_full_return(wc,0,1,DspAddress+i,&pWordValues[i], + &cmds[i]); + if (0 != ret) { + return; + } + } + } + else { + for (i = 0; i < NumWords;) { + if ((NumWords - i) > VPM150M_MAX_DATA) + transcount = VPM150M_MAX_DATA; + else + transcount = NumWords - i; + t1_vpm150m_getreg(wc, transcount, DspAddress + i, &pWordValues[i]); + i += transcount; + } + } + return; +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakWriteDspMemory - Write DSP memory. + * + * FUNCTION + * This function writes a contiguous block of words to DSP memory starting at + * the specified address. + * + * RETURNS + * nothing + * + */ +void gpakWriteDspMemory( + unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ + unsigned int NumWords, /* number of contiguous words to write */ + DSP_WORD *pWordValues /* pointer to array of word values to write */ + ) +{ + + struct t1 *wc = wc_find_iface(DspId); + int i; + int transcount; + + if (wc && wc->vpm150m) { + for (i = 0; i < NumWords;) { + if ((NumWords - i) > VPM150M_MAX_DATA) + transcount = VPM150M_MAX_DATA; + else + transcount = NumWords - i; + t1_vpm150m_setreg(wc, transcount, DspAddress + i, &pWordValues[i]); + i += transcount; + } + } + return; + +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakHostDelay - Delay for a fixed time interval. + * + * FUNCTION + * This function delays for a fixed time interval before returning. The time + * interval is the Host Port Interface sampling period when polling a DSP for + * replies to command messages. + * + * RETURNS + * nothing + * + */ +void gpakHostDelay(void) +{ +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakLockAccess - Lock access to the specified DSP. + * + * FUNCTION + * This function aquires exclusive access to the specified DSP. + * + * RETURNS + * nothing + * + */ +void gpakLockAccess(unsigned short DspId) +{ + struct t1 *wc; + + wc = wc_find_iface(DspId); + + if (wc) { + struct vpm150m *vpm = wc->vpm150m; + + if (vpm) + down_interruptible(&vpm->sem); + } +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakUnlockAccess - Unlock access to the specified DSP. + * + * FUNCTION + * This function releases exclusive access to the specified DSP. + * + * RETURNS + * nothing + * + */ +void gpakUnlockAccess(unsigned short DspId) +{ + struct t1 *wc; + + wc = wc_find_iface(DspId); + + if (wc) { + struct vpm150m *vpm = wc->vpm150m; + + if (vpm) + up(&vpm->sem); + } +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * gpakReadFile - Read a block of bytes from a G.PAK Download file. + * + * FUNCTION + * This function reads a contiguous block of bytes from a G.PAK Download file + * starting at the current file position. + * + * RETURNS + * The number of bytes read from the file. + * -1 indicates an error occurred. + * 0 indicates all bytes have been read (end of file) + * + */ +int gpakReadFile( + GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ + unsigned char *pBuffer, /* pointer to buffer for storing bytes */ + unsigned int NumBytes /* number of bytes to read */ + ) +{ + struct t1_firmware *fw = FileId; + unsigned int i, count; + + if (!fw || !fw->fw) + return -1; + + if (NumBytes > (fw->fw->size - fw->offset)) + count = fw->fw->size - fw->offset; + else + count = NumBytes; + + for (i = 0; i < count; i++) + pBuffer[i] = fw->fw->data[fw->offset + i]; + + fw->offset += count; + + return count; +} + +int vpm150m_config_hw(struct t1 *wc) +{ + struct vpm150m *vpm150m = wc->vpm150m; + gpakConfigPortStatus_t configportstatus; + GpakPortConfig_t portconfig; + GPAK_PortConfigStat_t pstatus; + GpakChannelConfig_t chanconfig; + GPAK_ChannelConfigStat_t cstatus; + GPAK_AlgControlStat_t algstatus; + + int res, i; + + memset(&portconfig, 0, sizeof(GpakPortConfig_t)); + + /* First Serial Port config */ + portconfig.SlotsSelect1 = SlotCfgNone; + portconfig.FirstBlockNum1 = 0; + portconfig.FirstSlotMask1 = 0x0000; + portconfig.SecBlockNum1 = 1; + portconfig.SecSlotMask1 = 0x0000; + portconfig.SerialWordSize1 = SerWordSize8; + portconfig.CompandingMode1 = cmpNone; + portconfig.TxFrameSyncPolarity1 = FrameSyncActHigh; + portconfig.RxFrameSyncPolarity1 = FrameSyncActHigh; + portconfig.TxClockPolarity1 = SerClockActHigh; + portconfig.RxClockPolarity1 = SerClockActHigh; + portconfig.TxDataDelay1 = DataDelay0; + portconfig.RxDataDelay1 = DataDelay0; + portconfig.DxDelay1 = Disabled; + portconfig.ThirdSlotMask1 = 0x0000; + portconfig.FouthSlotMask1 = 0x0000; + portconfig.FifthSlotMask1 = 0x0000; + portconfig.SixthSlotMask1 = 0x0000; + portconfig.SevenSlotMask1 = 0x0000; + portconfig.EightSlotMask1 = 0x0000; + + /* Second Serial Port config */ + portconfig.SlotsSelect2 = SlotCfg8Groups; + portconfig.FirstBlockNum2 = 0; + portconfig.FirstSlotMask2 = 0x5554; + portconfig.SecBlockNum2 = 1; + portconfig.SecSlotMask2 = 0x5555; + portconfig.ThirdSlotMask2 = 0x5555; + portconfig.FouthSlotMask2 = 0x5555; + portconfig.SerialWordSize2 = SerWordSize8; + portconfig.CompandingMode2 = cmpNone; + portconfig.TxFrameSyncPolarity2 = FrameSyncActHigh; + portconfig.RxFrameSyncPolarity2 = FrameSyncActHigh; + portconfig.TxClockPolarity2 = SerClockActHigh; + portconfig.RxClockPolarity2 = SerClockActHigh; + portconfig.TxDataDelay2 = DataDelay0; + portconfig.RxDataDelay2 = DataDelay0; + portconfig.DxDelay2 = Disabled; + portconfig.FifthSlotMask2 = 0x0001; + portconfig.SixthSlotMask2 = 0x0000; + portconfig.SevenSlotMask2 = 0x0000; + portconfig.EightSlotMask2 = 0x0000; + + /* Third Serial Port Config */ + portconfig.SlotsSelect3 = SlotCfg8Groups; + portconfig.FirstBlockNum3 = 0; + portconfig.FirstSlotMask3 = 0x5554; + portconfig.SecBlockNum3 = 1; + portconfig.SecSlotMask3 = 0x5555; + portconfig.SerialWordSize3 = SerWordSize8; + portconfig.CompandingMode3 = cmpNone; + portconfig.TxFrameSyncPolarity3 = FrameSyncActHigh; + portconfig.RxFrameSyncPolarity3 = FrameSyncActHigh; + portconfig.TxClockPolarity3 = SerClockActHigh; + portconfig.RxClockPolarity3 = SerClockActLow; + portconfig.TxDataDelay3 = DataDelay0; + portconfig.RxDataDelay3 = DataDelay0; + portconfig.DxDelay3 = Disabled; + portconfig.ThirdSlotMask3 = 0x5555; + portconfig.FouthSlotMask3 = 0x5555; + portconfig.FifthSlotMask3 = 0x0001; + portconfig.SixthSlotMask3 = 0x0000; + portconfig.SevenSlotMask3 = 0x0000; + portconfig.EightSlotMask3 = 0x0000; + + if ((configportstatus = gpakConfigurePorts(vpm150m->dspid, &portconfig, &pstatus))) { + module_printk("Configuration of ports failed (%d)!\n", configportstatus); + return -1; + } else { + debug_printk(1, "Configured McBSP ports successfully\n"); + } + + if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { + module_printk("Error pinging DSP (%d)\n", res); + return -1; + } + + for (i = 0; i < 32; i++) { + /* Let's configure a channel */ + chanconfig.PcmInPortA = 3; + chanconfig.PcmInSlotA = (i + 1) * 2; + chanconfig.PcmOutPortA = 2; + chanconfig.PcmOutSlotA = (i + 1) * 2; + chanconfig.PcmInPortB = 2; + chanconfig.PcmInSlotB = (i + 1) * 2; + chanconfig.PcmOutPortB = 3; + chanconfig.PcmOutSlotB = (i + 1) * 2; + if (vpmdtmfsupport) { + chanconfig.ToneTypesA = DTMF_tone; + chanconfig.MuteToneA = Enabled; + chanconfig.FaxCngDetA = Enabled; + } else { + chanconfig.ToneTypesA = Null_tone; + chanconfig.MuteToneA = Disabled; + chanconfig.FaxCngDetA = Disabled; + } + chanconfig.ToneTypesB = Null_tone; + chanconfig.EcanEnableA = Enabled; + chanconfig.EcanEnableB = Disabled; + chanconfig.MuteToneB = Disabled; + chanconfig.FaxCngDetB = Disabled; + + chanconfig.SoftwareCompand = cmpNone; + + chanconfig.FrameRate = rate10ms; + + chanconfig.EcanParametersA.EcanTapLength = 1024; + chanconfig.EcanParametersA.EcanNlpType = vpmnlptype; + chanconfig.EcanParametersA.EcanAdaptEnable = 1; + chanconfig.EcanParametersA.EcanG165DetEnable = 1; + chanconfig.EcanParametersA.EcanDblTalkThresh = 6; + chanconfig.EcanParametersA.EcanNlpThreshold = vpmnlpthresh; + chanconfig.EcanParametersA.EcanNlpConv = 0; + chanconfig.EcanParametersA.EcanNlpUnConv = 0; + chanconfig.EcanParametersA.EcanNlpMaxSuppress = vpmnlpmaxsupp; + chanconfig.EcanParametersA.EcanCngThreshold = 43; + chanconfig.EcanParametersA.EcanAdaptLimit = 50; + chanconfig.EcanParametersA.EcanCrossCorrLimit = 15; + chanconfig.EcanParametersA.EcanNumFirSegments = 3; + chanconfig.EcanParametersA.EcanFirSegmentLen = 64; + + chanconfig.EcanParametersB.EcanTapLength = 1024; + chanconfig.EcanParametersB.EcanNlpType = vpmnlptype; + chanconfig.EcanParametersB.EcanAdaptEnable = 1; + chanconfig.EcanParametersB.EcanG165DetEnable = 1; + chanconfig.EcanParametersB.EcanDblTalkThresh = 6; + chanconfig.EcanParametersB.EcanNlpThreshold = vpmnlpthresh; + chanconfig.EcanParametersB.EcanNlpConv = 0; + chanconfig.EcanParametersB.EcanNlpUnConv = 0; + chanconfig.EcanParametersB.EcanNlpMaxSuppress = vpmnlpmaxsupp; + chanconfig.EcanParametersB.EcanCngThreshold = 43; + chanconfig.EcanParametersB.EcanAdaptLimit = 50; + chanconfig.EcanParametersB.EcanCrossCorrLimit = 15; + chanconfig.EcanParametersB.EcanNumFirSegments = 3; + chanconfig.EcanParametersB.EcanFirSegmentLen = 64; + + if ((res = gpakConfigureChannel(vpm150m->dspid, i, tdmToTdm, &chanconfig, &cstatus))) { + module_printk("Unable to configure channel (%d)\n", res); + if (res == 1) { + module_printk("Reason %d\n", cstatus); + } + + return -1; + } + + if ((res = gpakAlgControl(vpm150m->dspid, i, BypassEcanA, &algstatus))) { + module_printk("Unable to disable echo can on channel %d (reason %d:%d)\n", i + 1, res, algstatus); + return -1; + } + + if (vpmdtmfsupport) { + if ((res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &algstatus))) { + module_printk("Unable to disable dtmf muting on channel %d (reason %d:%d)\n", i + 1, res, algstatus); + return -1; + } + } + } + + if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { + module_printk("Error pinging DSP (%d)\n", res); + return -1; + } + + /* Turn on DTMF detection */ + if (vpmdtmfsupport) + set_bit(VPM150M_DTMFDETECT, &vpm150m->control); + set_bit(VPM150M_ACTIVE, &vpm150m->control); + + return 0; +} + +#endif diff --git a/kernel/wcte12xp/vpmadt032.h b/kernel/wcte12xp/vpmadt032.h new file mode 100644 index 0000000..e103e05 --- /dev/null +++ b/kernel/wcte12xp/vpmadt032.h @@ -0,0 +1,148 @@ +/* + * Digium, Inc. Wildcard TE12xP T1/E1 card Driver + * + * Written by Michael Spiceland + * + * Adapted from the wctdm24xxp and wcte11xp drivers originally + * written by Mark Spencer + * Matthew Fredrickson + * William Meadows + * + * Copyright (C) 2007, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _VPM150M_H +#define _VPM150M_H + +#include "wcte12xp.h" +#include "adt_lec.h" + +struct t1_firmware { + const struct firmware *fw; + unsigned int offset; +}; + +/* Host and DSP system dependent related definitions. */ +#define MAX_DSP_CORES 128 /* maximum number of DSP cores */ +//#define MAX_CONFS 1 /* maximum number of conferences */ +//#define MAX_PKT_CHANNELS 8 /* maximum number of packet channels */ +#define MAX_CHANNELS 32 /* maximum number of channels */ +#define MAX_WAIT_LOOPS 50 /* max number of wait delay loops */ +#define DSP_IFBLK_ADDRESS 0x0100 /* DSP address of I/F block pointer */ +#define DOWNLOAD_BLOCK_SIZE 512 /* download block size (DSP words) */ +//#define MAX_CIDPAYLOAD_BYTES 512 /* max size of a CID payload (octets) */ +typedef unsigned short DSP_WORD; /* 16 bit DSP word */ +typedef unsigned int DSP_ADDRESS; /* 32 bit DSP address */ +typedef struct t1_firmware* GPAK_FILE_ID; /* G.PAK Download file identifier */ + +#define __VPM150M_RWPAGE (1 << 4) +#define __VPM150M_RD (1 << 3) +#define __VPM150M_WR (1 << 2) +#define __VPM150M_FIN (1 << 1) +#define __VPM150M_TX (1 << 0) + +#define VPM150M_HPI_CONTROL 0x00 +#define VPM150M_HPI_ADDRESS 0x02 +#define VPM150M_HPI_DATA 0x03 + +#define VPM150M_MAX_COMMANDS 8 + +/* Some Bit ops for different operations */ +#define VPM150M_SPIRESET 0 +#define VPM150M_HPIRESET 1 +#define VPM150M_SWRESET 2 +#define VPM150M_DTMFDETECT 3 +#define VPM150M_ACTIVE 4 +#define VPM150M_MAX_DATA 1 + +struct vpm150m_cmd { + unsigned short address; + unsigned short data[VPM150M_MAX_DATA]; + unsigned char ident; + unsigned char datalen; + unsigned int flags; + unsigned char cs_slot; +}; + +struct vpm150m { + unsigned short dspid; + unsigned long control; + unsigned char curpage; + unsigned short version; + struct vpm150m_cmd cmdq[VPM150M_MAX_COMMANDS]; + spinlock_t lock; /* control access to list of bottom half tasks */ + struct semaphore sem; + struct workqueue_struct *wq; + struct work_struct work_dtmf; + struct work_struct work_debug; + struct work_struct work_echocan; + struct list_head worklist; + unsigned char curtone[32]; + unsigned long curdtmfmutestate; + unsigned long desireddtmfmutestate; + struct adt_lec_params chan_params[32]; + struct t1 *wc; +}; + +/* linked list for vpm echocan workqueue*/ +struct vpm150m_workentry { + struct list_head list; + struct t1 *wc; /* what card are we dealing with? */ + struct zt_chan *chan; /* what channels are we going to deal with? */ + struct adt_lec_params params; /* how should we behave? */ +}; + +extern int debug; +extern int vpmsupport; +extern int vpmdtmfsupport; +extern struct pci_driver te12xp_driver; + +void t1_vpm150m_init(struct t1 *wc); +void vpm150m_cmd_dequeue(struct t1 *wc, volatile unsigned char *writechunk, int whichframe); +void vpm150m_cmd_decipher(struct t1 *wc, volatile unsigned char *readchunk); +int vpm150m_config_hw(struct t1 *wc); + +/* gpak API functions */ +void gpakReadDspMemory( + unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ + unsigned int NumWords, /* number of contiguous words to read */ + DSP_WORD *pWordValues /* pointer to array of word values variable */ + ); +void gpakWriteDspMemory( + unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ + unsigned int NumWords, /* number of contiguous words to write */ + DSP_WORD *pWordValues /* pointer to array of word values to write */ + ); +void gpakHostDelay(void); +void gpakLockAccess( + unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + ); +void gpakUnlockAccess( + unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ + ); +int gpakReadFile( + GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ + unsigned char *pBuffer, /* pointer to buffer for storing bytes */ + unsigned int NumBytes /* number of bytes to read */ + ); + +#endif diff --git a/kernel/wcte12xp/wcte12xp.h b/kernel/wcte12xp/wcte12xp.h new file mode 100644 index 0000000..20e0558 --- /dev/null +++ b/kernel/wcte12xp/wcte12xp.h @@ -0,0 +1,179 @@ +/* + * Digium, Inc. Wildcard TE12xP T1/E1 card Driver + * + * Written by Michael Spiceland + * + * Adapted from the wctdm24xxp and wcte11xp drivers originally + * written by Mark Spencer + * Matthew Fredrickson + * William Meadows + * + * Copyright (C) 2007, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _WCTE12XP_H +#define _WCTE12XP_H + +#ifdef LINUX26 +/* Comment to disable VPM support */ +#define VPM_SUPPORT 1 +#endif + +#define WC_MAX_IFACES 8 + +#ifdef VPM_SUPPORT +#define MAX_TDM_CHAN 31 +#endif + +#define SDI_CLK (0x00010000) +#define SDI_DOUT (0x00020000) +#define SDI_DREAD (0x00040000) +#define SDI_DIN (0x00080000) + +#define EFRAME_SIZE 108 +#define ERING_SIZE 16 /* Maximum ring size */ +#define EFRAME_GAP 20 +#define SFRAME_SIZE ((EFRAME_SIZE * ZT_CHUNKSIZE) + (EFRAME_GAP * (ZT_CHUNKSIZE - 1))) + +#define PCI_WINDOW_SIZE ((2 * 2 * 2 * SFRAME_SIZE) + (2 * ERING_SIZE * 4)) + +#define MAX_COMMANDS 7*7*2 /* 42 bytes /3 (cntl,addr,data) /2 (cs) */ + +#define ISR_COMMANDS 2 +#define NUM_EC 4 + +#define __CMD_VPM (1 << 16) /* flag for VPM action */ +#define __CMD_ISR (1 << 17) /* flag for ISR reads */ +#define __CMD_PINS (1 << 18) /* CPLD pin read */ +#define __CMD_LEDS (1 << 19) /* LED Operation */ +#define __CMD_RD (1 << 20) /* Read Operation */ +#define __CMD_WR (1 << 21) /* Write Operation */ +#define __CMD_FIN (1 << 22) /* Has finished receive */ +#define __CMD_TX (1 << 23) /* Has been transmitted */ + +#define __LED_ORANGE (1<<3) +#define __LED_GREEN (1<<2) +#define __LED_RED (1<<1) + +#define SET_LED_ORANGE(a) a | __LED_ORANGE +#define SET_LED_RED(a) (a | __LED_RED) & ~__LED_GREEN +#define SET_LED_GREEN(a) (a | __LED_GREEN) & ~__LED_RED + +#define UNSET_LED_ORANGE(a) a & ~__LED_ORANGE +#define UNSET_LED_REDGREEN(a) a | __LED_RED | __LED_GREEN + +#define CMD_WR(a,b) (((a) << 8) | (b) | __CMD_WR) +#define CMD_RD(a) (((a) << 8) | __CMD_RD) +#define CMD_LEDS(a) (((a) << 8) | __CMD_LEDS) +//#define CMD_BYTE(slot, a) (slot*6)+(a*2) /* only even slots */ +#define CMD_BYTE(slot, a, is_vpm) (slot*6)+(a*2)+is_vpm /* only even slots */ +//TODO: make a separate macro + +#define TYPE_T1 1 +#define TYPE_E1 2 + +#define NOT_VPM -1 + +#define module_printk(fmt, args...) printk("%s: " fmt, te12xp_driver.name, ## args) +#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, te12xp_driver.name, __FUNCTION__, ## args) +extern spinlock_t ifacelock; + +struct command { + unsigned short address; + unsigned char data; + unsigned char ident; + unsigned int flags; + unsigned char cs_slot; + unsigned char vpm_num; /* ignored for all but vpm commmands */ +}; + +struct cmdq { + struct command cmds[MAX_COMMANDS]; + unsigned char isrshadow[ISR_COMMANDS]; +}; + +struct vpm150m; + +struct t1 { + struct pci_dev *dev; + spinlock_t reglock; + unsigned char txident; + unsigned char rxident; + unsigned char statreg; /* bit 0 = vpmadt032 int */ + int spantype; + struct { + unsigned int nmf:1; + unsigned int sendingyellow:1; + } flags; + unsigned char txsigs[16]; /* Copy of tx sig registers */ + int num; + int alarmcount; /* How much red alarm we've seen */ + int alarmdebounce; + char *variety; + unsigned int intcount; + int sync; + int dead; + int blinktimer; + int alarmtimer; + int yellowtimer; + int ledlastvalue; + int alarms_read; + int checktiming; /* Set >0 to cause the timing source to be checked */ + int loopupcnt; + int loopdowncnt; + int initialized; + int *chanmap; + unsigned char ledtestreg; + unsigned long iobase; + unsigned char ec_chunk1[32][ZT_CHUNKSIZE]; + unsigned char ec_chunk2[32][ZT_CHUNKSIZE]; + struct zt_span span; /* Span */ + struct zt_chan chans[32]; /* Channels */ + int freeregion; + unsigned int intmask; + wait_queue_head_t regq; + struct cmdq cmdq; + struct command dummy; /* preallocate for dummy noop command */ + unsigned char ctlreg; + int rdbl; + int tdbl; + unsigned int rxints; + unsigned int txints; + unsigned int sdi; + int usecount; + dma_addr_t readdma; + dma_addr_t writedma; + dma_addr_t descripdma; + volatile unsigned int *writechunk; + volatile unsigned int *readchunk; + volatile unsigned int *descripchunk; + unsigned int isrreaderrors; +#ifdef VPM_SUPPORT + int vpm; + struct vpm150m *vpm150m; + unsigned long dtmfactive; + unsigned long dtmfmask; + unsigned long dtmfmutemask; +#endif +}; + +int schluffen(wait_queue_head_t *q); + +#endif diff --git a/kernel/wcusb.c b/kernel/wcusb.c new file mode 100644 index 0000000..615d4c0 --- /dev/null +++ b/kernel/wcusb.c @@ -0,0 +1,1490 @@ +/* + * Wildcard S100U USB FXS Interface Zapata Telephony Driver + * + * Written by Mark Spencer + * Matthew Fredrickson + * + * Copyright (C) 2001, Linux Support Services, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* Save power at the expense of not always being able to transmit on hook. If + this is set, we only transit on hook for some time after a ring + (POWERSAVE_TIMEOUT) */ + +/* #define PROSLIC_POWERSAVE */ +#define POWERSAVE_TIME 4000 + +#include +#include +#include +#include +#include +#include +#include + +#include +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19) +#define USB2420 +#endif + +#ifdef STANDALONE_ZAPATA +#include "zaptel.h" +#else +#include +#endif /* STANDALONE_ZAPATA */ + +#include "wcusb.h" +#include "proslic.h" + +#ifndef FILL_CONTROL_URB +#define FILL_CONTROL_URB usb_fill_control_urb +#endif + +#ifdef DEBUG_WILDCARD +#define DPRINTK(x) printk x +#else +#define DPRINTK(x) +#endif + +// Function prototypes +static int readProSlicDirectReg(struct usb_device *dev, unsigned char address, unsigned char* data); +static int initializeIndirectRegisters(struct usb_device *dev); +static int verifyIndirectRegisters(struct usb_device *dev); +static int writeProSlicDirectReg(struct usb_device *dev, unsigned char address, unsigned char data); +static int writeProSlicInDirectReg(struct usb_device *dev, unsigned char address, unsigned short data); +static int readProSlicInDirectReg(struct usb_device *dev, unsigned char address, unsigned short *data); +static int writeProSlicInDirectReg(struct usb_device *dev, unsigned char address, unsigned short data); + +static alpha indirect_regs[] = +{ +{0,255,"DTMF_ROW_0_PEAK",0x55C2}, +{1,255,"DTMF_ROW_1_PEAK",0x51E6}, +{2,255,"DTMF_ROW2_PEAK",0x4B85}, +{3,255,"DTMF_ROW3_PEAK",0x4937}, +{4,255,"DTMF_COL1_PEAK",0x3333}, +{5,255,"DTMF_FWD_TWIST",0x0202}, +{6,255,"DTMF_RVS_TWIST",0x0202}, +{7,255,"DTMF_ROW_RATIO_TRES",0x0198}, +{8,255,"DTMF_COL_RATIO_TRES",0x0198}, +{9,255,"DTMF_ROW_2ND_ARM",0x0611}, +{10,255,"DTMF_COL_2ND_ARM",0x0202}, +{11,255,"DTMF_PWR_MIN_TRES",0x00E5}, +{12,255,"DTMF_OT_LIM_TRES",0x0A1C}, +{13,0,"OSC1_COEF",0x7B30}, +{14,1,"OSC1X",0x0063}, +{15,2,"OSC1Y",0x0000}, +{16,3,"OSC2_COEF",0x7870}, +{17,4,"OSC2X",0x007D}, +{18,5,"OSC2Y",0x0000}, +{19,6,"RING_V_OFF",0x0000}, +{20,7,"RING_OSC",0x7EF0}, +{21,8,"RING_X",0x0160}, +{22,9,"RING_Y",0x0000}, +{23,255,"PULSE_ENVEL",0x2000}, +{24,255,"PULSE_X",0x2000}, +{25,255,"PULSE_Y",0x0000}, +//{26,"RECV_DIGITAL_GAIN",0x4000}, // playback volume set lower +{26,13,"RECV_DIGITAL_GAIN",0x2000}, // playback volume set lower +{27,14,"XMIT_DIGITAL_GAIN",0x4000}, +//{27,"XMIT_DIGITAL_GAIN",0x2000}, +{28,15,"LOOP_CLOSE_TRES",0x1000}, +{29,16,"RING_TRIP_TRES",0x3600}, +{30,17,"COMMON_MIN_TRES",0x1000}, +{31,18,"COMMON_MAX_TRES",0x0200}, +{32,19,"PWR_ALARM_Q1Q2",0x07C0}, +{33,20,"PWR_ALARM_Q3Q4",0x2600}, +{34,21,"PWR_ALARM_Q5Q6",0x1B80}, +{35,22,"LOOP_CLOSURE_FILTER",0x8000}, +{36,23,"RING_TRIP_FILTER",0x0320}, +{37,24,"TERM_LP_POLE_Q1Q2",0x008C}, +{38,25,"TERM_LP_POLE_Q3Q4",0x0100}, +{39,26,"TERM_LP_POLE_Q5Q6",0x0010}, +{40,27,"CM_BIAS_RINGING",0x0C00}, +{41,64,"DCDC_MIN_V",0x0C00}, +{42,255,"DCDC_XTRA",0x1000}, +{43,66,"LOOP_CLOSE_TRES_LOW",0x1000}, +}; + +static int debug = 0; + +#define FLAG_FLIP_RELAYS (1 << 0) + +static struct wc_usb_desc wcusb = { "Wildcard S100U USB FXS Interface" }; +static struct wc_usb_desc wcusb2 = { "Wildcard S110U USB FXS Interface", FLAG_FLIP_RELAYS }; +static struct wc_usb_desc wc_usb_phone = { "Wildcard Phone Test driver" }; +static struct wc_usb_pvt *ifaces[WC_MAX_IFACES]; + + + +static void wcusb_check_keypad(struct wc_usb_pvt *p); +static int set_aux_ctrl(struct wc_usb_pvt *p, char auxpins, int on); + + + +static int Wcusb_WriteWcRegs(struct usb_device *dev, unsigned char index, + unsigned char *data, int len) +{ + unsigned int pipe = usb_sndctrlpipe(dev, 0); + int requesttype; + int res; + + requesttype = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; + + res = usb_control_msg(dev, pipe, REQUEST_NORMAL, requesttype, + 0, index, data, len, CONTROL_TIMEOUT_JIFFIES); + if (res == -ETIMEDOUT) { + printk("wcusb: timeout on vendor write\n"); + return -1; + } else if (res < 0) { + printk("wcusb: Error executing control: status=%d\n", le32_to_cpu(res)); + return -1; + } + return 0; +} + +static int Wcusb_ReadWcRegs(struct usb_device *dev, unsigned char index, + unsigned char *data, int len) +{ + unsigned int pipe = usb_rcvctrlpipe(dev, 0); + int requesttype; + int res; + + requesttype = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; + + res = usb_control_msg(dev, pipe, REQUEST_NORMAL, requesttype, + 0, index, data, len, CONTROL_TIMEOUT_JIFFIES); + if (res == -ETIMEDOUT) { + printk("wcusb: timeout on vendor write\n"); + return -1; + } else if (res < 0) { + printk("wcusb: Error executing control: status=%d\n", le32_to_cpu(res)); + return -1; + } else { + DPRINTK(("wcusb: Executed read, result = %d (data = %04x)\n", le32_to_cpu(res), (int) *data)); + } + return 0; +} + +#ifdef USB2420 +#if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) +static int wcusb_async_read(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb, struct pt_regs *regs)); +static int wcusb_async_write(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb, struct pt_regs *regs)); +static void wcusb_async_control(struct urb *urb, struct pt_regs *regs); +#else +static int wcusb_async_read(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb)); +static int wcusb_async_write(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb)); +static void wcusb_async_control(struct urb *urb); +#endif /* LINUX26 */ +#else +static int wcusb_async_read(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(urb_t *urb)); +static int wcusb_async_write(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(urb_t *urb)); +static void wcusb_async_control(urb_t *urb); +#endif + +static void proslic_read_direct_async(struct wc_usb_pvt *p, unsigned char address) +{ + p->wcregindex = address; + p->wcregbuf[0] = address | 0x80; + p->wcregbuf[1] = 0; + p->wcregbuf[2] = 0; + p->wcregbuf[3] = 0x67; + wcusb_async_write(p, WCUSB_SPORT0, p->wcregbuf, 4, STATE_WCREAD_WRITEREG, wcusb_async_control); +} + +static void proslic_write_direct_async(struct wc_usb_pvt *p, unsigned char address, unsigned char val) +{ + p->wcregindex = address; + p->wcregbuf[0] = address & 0x7f; + p->wcregbuf[1] = val; + p->wcregbuf[2] = 0; + p->wcregbuf[3] = 0x27; + wcusb_async_write(p, WCUSB_SPORT0, p->wcregbuf, 4, STATE_WCWRITE_WRITERES, wcusb_async_control); +} + +#ifdef USB2420 +#if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) +static void wcusb_async_control(struct urb *urb, struct pt_regs *regs) +#else +static void wcusb_async_control(struct urb *urb) +#endif +#else +static void wcusb_async_control(urb_t *urb) +#endif +{ + struct wc_usb_pvt *p = urb->context; + p->urbcount--; + if (urb->status) { + printk("Error in transfer...\n"); + /* return is the "right thing", but don't... */ + p->timer = 50; + /* return; */ + } + if (!(p->flags & FLAG_RUNNING)) { + return; + } + switch (p->controlstate) { + case STATE_WCREAD_WRITEREG: + /* We've written the register to sport0, now read form sport 1 */ + wcusb_async_read(p, WCUSB_SPORT1, &p->wcregval, 1, STATE_WCREAD_READRES, wcusb_async_control); + return; + case STATE_WCREAD_READRES: + switch(p->wcregindex) { + case 68: + if (!p->hookstate && (p->wcregval & 1)) { + p->hookstate = 1; + if (debug) + printk("Going off hook...\n"); + zt_hooksig(&p->chan, ZT_RXSIG_OFFHOOK); + } else if (p->hookstate && !(p->wcregval & 1)) { + p->hookstate = 0; + if (debug) + printk("Going on hook...\n"); + zt_hooksig(&p->chan, ZT_RXSIG_ONHOOK); + } + /* Set outgoing hook state if necessary */ + if (p->txhook != p->newtxhook) { + if (debug) + printk("Really setting hook state to %d\n", p->newtxhook); + p->txhook = p->newtxhook; + proslic_write_direct_async(p, 64, p->newtxhook); + } else + p->timer = 50; + break; + case 64: + if (debug) + printk("Read hook state as %02x\n", p->wcregval); + p->timer = 50; + break; + default: + printk("dunno what to do with read/regindex %d\n", p->wcregindex); + p->wcregindex = 0; + } + return; + case STATE_WCWRITE_WRITERES: + switch(p->wcregindex) { + case 64: + if (debug) { + printk("Hook transition complete to %d\n", ((char *)(urb->transfer_buffer))[1]); +#ifdef BOOST_RINGER + } + if (p->txhook == 4) { + /* Ringing -- boost battery to 96V */ + proslic_write_direct_async(p, 74, 0x3f); + } else { + /* Leave battery at default 75V */ + proslic_write_direct_async(p, 74, 0x32); + } + break; + case 74: + if (debug) { + printk("Battery set to -%dV\n", ((char *)(urb->transfer_buffer))[1] * 3 / 2); +#endif + proslic_read_direct_async(p, 64); + } else + p->timer = 50; + break; + default: + printk("dunno what to do with write/regindex %d\n", p->wcregindex); + p->wcregindex = 0; + } + return; + default: + printk("async control in unknown state %d\n", p->controlstate); + } +} + +#ifdef USB2420 +#if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) +static void keypad_check_done(struct urb *urb, struct pt_regs *regs) +#else +static void keypad_check_done(struct urb *urb) +#endif +#else +static void keypad_check_done(urb_t *urb) +#endif +{ + struct wc_usb_pvt *p = urb->context; + struct wc_keypad_data *d = p->pvt_data; + static char aux_pattern[] = {0x1e, 0x1d, 0x17, 0xf}; + char digit = 'z'; + + p->urbcount--; + if (!d->running) { + printk("Stopping stream (check_done)\n"); + return; + } + + if (urb->status) { + printk("status %d\n", urb->status); + } + + if (debug) printk("i is %d\n", d->i); + switch (d->state) { +loop_start: + case STATE_FOR_LOOP_1_OUT: + if (debug) printk("data12 is %x\n", d->data12); + if(d->i < sizeof(aux_pattern) / sizeof(char)) { + d->tmp = aux_pattern[d->i] | (d->data12 & 0xe0); + d->state = STATE_FOR_LOOP_2_IN; + if (debug) printk("tmp is %x\n", d->tmp); + wcusb_async_write(p, 0x12, &d->tmp, 1, 0, keypad_check_done); + return; + } else { + goto func_end; + } + case STATE_FOR_LOOP_2_IN: + d->state = STATE_FOR_LOOP_PROC_DATA; + wcusb_async_read(p, 0xc0, &d->data, 1, 0, keypad_check_done); + return; + case STATE_FOR_LOOP_PROC_DATA: + d->state = STATE_FOR_LOOP_CLEAR_DIGIT; + if(debug) printk("data is %x\n", d->data); + if ((d->data & 0x1f) != 0x1f) { + if(d->data == 0xe && aux_pattern[d->i] == 0x1e) { digit = '1';} + else if(d->data == 0xd && aux_pattern[d->i] == 0x1e) { digit = '2';} + else if(d->data == 0xb && aux_pattern[d->i] == 0x1e) { digit = '3';} + else if(d->data == 0x7 && aux_pattern[d->i] == 0x1e) { + p->hookstate = 0; /* On||Off */ + zt_hooksig(&p->chan, ZT_RXSIG_ONHOOK); + } + + else if(d->data == 0xe && aux_pattern[d->i] == 0x1d) { digit = '4';} + else if(d->data == 0xd && aux_pattern[d->i] == 0x1d) { digit = '5';} + else if(d->data == 0xb && aux_pattern[d->i] == 0x1d) { digit = '6';} + else if(d->data == 0x7 && aux_pattern[d->i] == 0x1d) { + p->hookstate = 1;/* Dial */ + zt_hooksig(&p->chan, ZT_RXSIG_OFFHOOK); + } + + else if(d->data == 0xe && aux_pattern[d->i] == 0x17) { digit = '7';} + else if(d->data == 0xd && aux_pattern[d->i] == 0x17) { digit = '8';} + else if(d->data == 0xb && aux_pattern[d->i] == 0x17) { digit = '9';} + else if(d->data == 0x7 && aux_pattern[d->i] == 0x17) d->scanned_event = 15; /* ReDial */ + + else if(d->data == 0xe && aux_pattern[d->i] == 0xf) { digit = '*';}/* '*' */ + else if(d->data == 0xd && aux_pattern[d->i] == 0xf) { digit = '0';} + else if(d->data == 0xb && aux_pattern[d->i] == 0xf) { digit = '#';} /* '#' */ + else if(d->data == 0x7 && aux_pattern[d->i] == 0xf) d->scanned_event = 16; /* Volume? */ + else { + (d->i)++; + if (debug) printk("Scanned event %d; data = %x\n", d->scanned_event, d->data); + goto loop_start; + } + } else { + if(debug) printk("Hit new if\n"); + goto func_end; + } + if (debug) printk("wcusb: got digit %d\n", d->scanned_event); + if (digit != 'z') { + d->tone = zt_dtmf_tone(&p->chan, digit); + if (!d->tone) { + printk("wcusb: Didn't get a tone structure\n"); + goto func_end; + } + zt_init_tone_state(&d->ts, d->tone); + p->sample = STREAM_DTMF; + } + d->count = 0; + case STATE_FOR_LOOP_CLEAR_DIGIT: + if (((d->data & 0xf) != 0xf) && d->count < 200) { + wcusb_async_read(p, 0xc0, &d->data, 1, 0, keypad_check_done); + return; + } + (d->i)++; + p->sample = STREAM_NORMAL; + goto loop_start; + } +func_end: + p->timer = 100; + return; +} + +static void wcusb_check_interrupt(struct wc_usb_pvt *p) +{ + /* Start checking for interrupts */ + if (p->devclass == WC_KEYPAD) { + wcusb_check_keypad(p); + } else { + proslic_read_direct_async(p, 68); + } + return; +} + +#ifdef USB2420 +#if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) +static int wcusb_async_read(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb, struct pt_regs *regs)) +#else +static int wcusb_async_read(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb)) +#endif /* LINUX26 */ +#else +static int wcusb_async_read(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(urb_t *urb)) +#endif +{ + __u16 size = len; + __u16 ind = index; +#ifdef USB2420 + struct urb *urb = &p->control; + memset(urb, 0, sizeof(struct urb)); + + p->dr.bRequestType = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; + p->dr.bRequest = REQUEST_NORMAL; + p->dr.wValue = 0; + p->dr.wIndex = cpu_to_le16(ind); + p->dr.wLength = cpu_to_le16(size); +#else + urb_t *urb = &p->control; + memset(urb, 0, sizeof(urb_t)); + + p->dr.requesttype = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; + p->dr.request = REQUEST_NORMAL; + p->dr.value = 0; + p->dr.index = cpu_to_le16(ind); + p->dr.length = cpu_to_le16(size); +#endif + + FILL_CONTROL_URB(urb, p->dev, usb_rcvctrlpipe(p->dev, 0), (unsigned char *)&p->dr, data, len, complete, p); +#ifdef LINUX26 + if (usb_submit_urb(urb, GFP_KERNEL)) +#else + if (usb_submit_urb(urb)) +#endif + { + printk("wcusb_async_read: control URB died\n"); + p->timer = 50; + return -1; + } + p->controlstate = state; + p->urbcount++; + return 0; +} + +#ifdef USB2420 +#if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) +static int wcusb_async_write(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb, struct pt_regs *regs)) +#else +static int wcusb_async_write(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb)) +#endif /* LINUX26 */ +#else +static int wcusb_async_write(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(urb_t *urb)) +#endif +{ + __u16 size = len; + __u16 ind = index; +#ifdef USB2420 + struct urb *urb = &p->control; + memset(urb, 0, sizeof(struct urb)); + + p->dr.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; + p->dr.bRequest = REQUEST_NORMAL; + p->dr.wValue = 0; + p->dr.wIndex = cpu_to_le16(ind); + p->dr.wLength = cpu_to_le16(size); +#else + urb_t *urb = &p->control; + memset(urb, 0, sizeof(urb_t)); + + p->dr.requesttype = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; + p->dr.request = REQUEST_NORMAL; + p->dr.value = 0; + p->dr.index = cpu_to_le16(ind); + p->dr.length = cpu_to_le16(size); +#endif + + FILL_CONTROL_URB(urb, p->dev, usb_sndctrlpipe(p->dev, 0), (unsigned char *)&p->dr, data, len, complete, p); +#ifdef LINUX26 + if (usb_submit_urb(urb, GFP_KERNEL)) +#else + if (usb_submit_urb(urb)) +#endif + { + printk("wcusb_async_write: control URB died\n"); + return -1; + } + p->controlstate = state; + p->urbcount++; + return 0; +} + +/* +** Write register to Wc560 +*/ +static int wcoutp(struct usb_device *dev, unsigned char address, unsigned char data) +{ + if (!Wcusb_WriteWcRegs(dev, address, &data, 1)) + return 0; + + return -1; +} + +/* +** read register from Wc560 +*/ +static int wcinp(struct usb_device *dev, unsigned char address, unsigned char* data ) +{ + if (!Wcusb_ReadWcRegs(dev, address, data, 1)) + return 0; + + return -1; +} + +static int waitForProSlicIndirectRegAccess(struct usb_device *dev) +{ + unsigned char count, data; + count = 0; + while (count++ < 3) + { + data = 0; + readProSlicDirectReg(dev, I_STATUS, &data); + + if (!data) + return 0; + + } + + if(count > 2) printk(" ##### Loop error #####\n"); + + return -1; +} + +static int writeProSlicInDirectReg(struct usb_device *dev, unsigned char address, unsigned short data) +{ + + if(!waitForProSlicIndirectRegAccess(dev)) + { + if (!writeProSlicDirectReg(dev, IDA_LO,(unsigned char)(data & 0xFF))) + { + if(!writeProSlicDirectReg(dev, IDA_HI,(unsigned char)((data & 0xFF00)>>8))) + { + if(!writeProSlicDirectReg(dev, IAA,address)) + return 0; + } + } + } + + return -1; +} + +/* +** Read register from ProSlic +*/ +int readProSlicDirectReg(struct usb_device *dev, unsigned char address, unsigned char* dataRead) +{ + unsigned char data[4]; + + data[0] = address | 0x80; + data[1] = 0; + data[2] = 0; + data[3] = 0x67; + + // write to WC register 0x26 + Wcusb_WriteWcRegs(dev, WCUSB_SPORT0, data, 4); + Wcusb_ReadWcRegs(dev, WCUSB_SPORT1, data, 1); + *dataRead = data[0]; + + return 0; +} + +/* +** Write register to ProSlic +*/ +int writeProSlicDirectReg(struct usb_device *dev, unsigned char address, unsigned char RegValue) +{ + unsigned char data[4]; + + data[0] = address & 0x7f; + data[1] = RegValue; + data[2] = 0; + data[3] = 0x27; + + // write to WC register 0x26 + return Wcusb_WriteWcRegs(dev, WCUSB_SPORT0, data, 4); +} + +static int readProSlicInDirectReg(struct usb_device *dev, unsigned char address, unsigned short *data) +{ + if (!waitForProSlicIndirectRegAccess(dev)) + { + if (!writeProSlicDirectReg(dev,IAA,address)) + { + if(!waitForProSlicIndirectRegAccess(dev)) + { + unsigned char data1, data2; + + if (!readProSlicDirectReg(dev,IDA_LO, &data1) && !readProSlicDirectReg (dev, IDA_HI, &data2)) + { + *data = data1 | (data2 << 8); + return 0; + } else + printk("Failed to read direct reg\n"); + } else + printk("Failed to wait inside\n"); + } else + printk("failed write direct IAA\n"); + } else + printk("failed to wait\n"); + + return -1; +} + +static int initializeIndirectRegisters(struct usb_device *dev) +{ + unsigned char i; + + for (i=0; i<43; i++) + { + if(writeProSlicInDirectReg(dev, i,indirect_regs[i].initial)) + return -1; + } + + return 0; +} + +static int verifyIndirectRegisters(struct usb_device *dev) +{ + int passed = 1; + unsigned short i,j, initial; + + for (i=0; i<43; i++) + { + if(readProSlicInDirectReg(dev, (unsigned char) i, &j)) { + printk("Failed to read indirect register %d\n", i); + return -1; + } + initial= indirect_regs[i].initial; + + if ( j != initial ) + { + printk("!!!!!!! %s iREG %X = %X should be %X\n", + indirect_regs[i].name,i,j,initial ); + passed = 0; + } + } + + if (passed) { + if (debug) + printk("Init Indirect Registers completed successfully.\n"); + } else { + printk(" !!!!! Init Indirect Registers UNSUCCESSFULLY.\n"); + } + + return 0; +} + +static int calibrateAndActivateProSlic(struct usb_device *dev) +{ + unsigned char x; + + if(writeProSlicDirectReg(dev, 92, 0xc8)) + return -1; + + if(writeProSlicDirectReg(dev, 97, 0)) + return -1; + + if(writeProSlicDirectReg(dev, 93, 0x19)) + return -1; + + if(writeProSlicDirectReg(dev, 14, 0)) + return -1; + + if(writeProSlicDirectReg(dev, 93, 0x99)) + return -1; + + if(!readProSlicDirectReg (dev, 93, &x)) + { + if (debug) + printk("DC Cal x=%x\n",x); + + if (!writeProSlicDirectReg(dev, 97, 0)) + { + if(!writeProSlicDirectReg(dev, CALIBR1, CALIBRATE_LINE)) + { + unsigned char data; + + if(!readProSlicDirectReg(dev, CALIBR1, &data)) + return writeProSlicDirectReg(dev, LINE_STATE,ACTIVATE_LINE); + } + } + } + + return -1; +} + +static int InitProSlic(struct usb_device *dev) +{ + if (writeProSlicDirectReg(dev, 67, 0x0e)) + /* Disable Auto Power Alarm Detect and other "features" */ + return -1; + if (initializeIndirectRegisters(dev)) { + printk(KERN_INFO "Indirect Registers failed to initialize.\n"); + return -1; + } + if (verifyIndirectRegisters(dev)) { + printk(KERN_INFO "Indirect Registers failed verification.\n"); + return -1; + } + if (calibrateAndActivateProSlic(dev)) { + printk(KERN_INFO "ProSlic Died on Activation.\n"); + return -1; + } + if (writeProSlicInDirectReg(dev, 97, 0x0)) { // Stanley: for the bad recording fix + printk(KERN_INFO "ProSlic IndirectReg Died.\n"); + return -1; + } + if (writeProSlicDirectReg(dev, 1, 0x2a)) { // U-Law GCI 8-bit interface + printk(KERN_INFO "ProSlic DirectReg Died.\n"); + return -1; + } + if (writeProSlicDirectReg(dev, 2, 0)) // Tx Start count low byte 0 + return -1; + if (writeProSlicDirectReg(dev, 3, 0)) // Tx Start count high byte 0 + return -1; + if (writeProSlicDirectReg(dev, 4, 0)) // Rx Start count low byte 0 + return -1; + if (writeProSlicDirectReg(dev, 5, 0)) // Rx Start count high byte 0 + return -1; + if (writeProSlicDirectReg(dev, 8, 0x0)) // disable loopback + return -1; + if (writeProSlicDirectReg(dev, 18, 0xff)) // clear all interrupt + return -1; + if (writeProSlicDirectReg(dev, 19, 0xff)) + return -1; + if (writeProSlicDirectReg(dev, 20, 0xff)) + return -1; + if (writeProSlicDirectReg(dev, 21, 0x00)) // enable interrupt + return -1; + if (writeProSlicDirectReg(dev, 22, 0x02)) // Loop detection interrupt + return -1; + if (writeProSlicDirectReg(dev, 23, 0x01)) // DTMF detection interrupt + return -1; + if (writeProSlicDirectReg(dev, 72, 0x20)) + return -1; +#ifdef BOOST_RINGER + /* Beef up Ringing voltage to 89V */ + if (writeProSlicInDirectReg(dev, 23, 0x1d1)) + return -1; +#endif + return 0; +} + +static int init_hardware(struct wc_usb_pvt *p) +{ + struct usb_device *dev = p->dev; + + switch (p->devclass) { + case WC_PROSLIC: + if (wcoutp(dev, 0x12, 0x00)) /* AUX6 as output, set to low */ + return -1; + if (wcoutp(dev, 0x13, 0x40)) /* AUX6 is output */ + return -1; + if (wcoutp(dev, 0, 0x50)) /* extrst, AUX2 is suspend */ + return -1; + if (wcoutp(dev, 0x29, 0x20)) /* enable SerialUP AUX pin definition */ + return -1; + if (wcoutp(dev, 0, 0x51)) /* no extrst, AUX2 is suspend */ + return -1; + /* Make sure there is no gain */ + if (wcoutp(dev, 0x22, 0x00)) + return -1; + if (wcoutp(dev, 0x23, 0xf2)) + return -1; + if (wcoutp(dev, 0x24, 0x00)) + return -1; + if (wcoutp(dev, 0x25, 0xc9)) + return -1; + if (InitProSlic(dev)) { + printk("wcusb: Failed to initialize proslic\n"); + return -1; + } + case WC_KEYPAD: + set_aux_ctrl(p, WC_AUX0, 1); + set_aux_ctrl(p, WC_AUX1, 1); + set_aux_ctrl(p, WC_AUX2, 1); + set_aux_ctrl(p, WC_AUX3, 1); + } + + if (debug) printk("wcusb: Setting correct interfaces.\n"); + + /* Setup correct settings (8000 Hz, signed linear) */ + if (usb_set_interface(dev, 2, 1)) { + printk("wcusb: Unable to setup USB interface 2 to altsetting 1\n"); + return -1; + } + if (usb_set_interface(dev, 3, 1)) { + printk("wcusb: Unable to setup USB interface 3 to altsetting 1\n"); + return -1; + } + return 0; +} + +/* Don't call from an interrupt context */ +static int set_aux_ctrl(struct wc_usb_pvt *p, char uauxpins, int on) +{ + char udata12 = 0; + char udata13 = 0; + + wcinp(p->dev, 0x12, &udata12); + wcinp(p->dev, 0x13, &udata13); + + wcoutp(p->dev, 0x12, on ? (uauxpins | udata12) : (~uauxpins & udata12)); + wcoutp(p->dev, 0x13, uauxpins | udata13); + + return 0; +} + +static void wcusb_check_keypad(struct wc_usb_pvt *p) +{ + struct wc_keypad_data *d = p->pvt_data; + + if (!d->running) { + printk("Stopping keypad stream\n"); + return; + } + if (debug) printk("Launched a packet\n"); + d->state = STATE_FOR_LOOP_1_OUT; + d->data = -1; + d->data12 = -1; + d->scanned_event = -1; + d->i = 0; + wcusb_async_read(p, 0x12, &d->data12, 1, 0, keypad_check_done); + return; +} + +static char wc_dtmf(struct wc_usb_pvt *p) +{ + struct wc_keypad_data *d = p->pvt_data; + short linsample = 0; + + if (!d) { + printk("NULL pointer, go away\n"); + return 0; + } + + linsample = zt_tone_nextsample(&d->ts, d->tone); + + + return ZT_LIN2MU(linsample); +} + +#if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) +static void wcusb_read_complete(struct urb *q, struct pt_regs *regs) +#else +static void wcusb_read_complete(struct urb *q) +#endif +{ + struct wc_usb_pvt *p = q->context; + short *chunk = q->transfer_buffer; + int x; + + if (!p->flags & FLAG_RUNNING) { + /* Stop sending URBs since we're not running anymore */ + p->urbcount--; + return; + } + + switch (p->sample) { + case STREAM_NORMAL: + for (x = 0; x < ZT_CHUNKSIZE; x++) { + p->chan.readchunk[x] = ZT_LIN2MU(le16_to_cpu(chunk[x])); + } + break; + case STREAM_DTMF: + for (x = 0; x < ZT_CHUNKSIZE; x++) { + p->chan.readchunk[x] = wc_dtmf(p); + } + break; + } + /* XXX We could probably optimize some here XXX */ + zt_ec_chunk(&p->chan, p->chan.readchunk, p->chan.writechunk); + + zt_receive(&p->span); + + q->dev = p->dev; + +#ifdef LINUX26 + if (usb_submit_urb(q, GFP_KERNEL)) +#else + if (usb_submit_urb(q)) +#endif + { + printk("wcusb: Read cycle failed\n"); + } + + if (p->timer && !--p->timer) { + if (p->devclass == WC_KEYPAD) { + if(debug) printk("Checking keypad\n"); + wcusb_check_keypad(p); + } else { + wcusb_check_interrupt(p); + } + } + +#ifdef PROSLIC_POWERSAVE + if (p->devclass != WC_KEYPAD) { + if (p->lowpowertimer && !--p->lowpowertimer) { + /* Switch back into low power mode */ + p->idletxhookstate = 1; + if (p->txhook == 2) + p->newtxhook = p->idletxhookstate; + } + } +#endif + return; +} + +#if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) +static void wcusb_write_complete(struct urb *q, struct pt_regs *regs) +#else +static void wcusb_write_complete(struct urb *q) +#endif +{ + struct wc_usb_pvt *p = q->context; + short *chunk = q->transfer_buffer; + int x; + + if (!p->flags & FLAG_RUNNING) { + /* Stop sending URBs since we're not running anymore */ + p->urbcount--; + return; + } + + zt_transmit(&p->span); + for (x = 0; x < ZT_CHUNKSIZE; x++) { + chunk[x] = cpu_to_le16(ZT_MULAW(p->chan.writechunk[x])); + } + q->dev = p->dev; + +#ifdef LINUX26 + if (usb_submit_urb(q, GFP_KERNEL)) +#else + if (usb_submit_urb(q)) +#endif + { + printk("wcusb: Write cycle failed\n"); + } + + return; +} + +static int StopTransmit(struct wc_usb_pvt *p) +{ + p->flags &= ~FLAG_RUNNING; + + if (p->devclass == WC_KEYPAD) { + struct wc_keypad_data *d = p->pvt_data; + d->running = 0; + } + while(p->urbcount) { + schedule_timeout(1); + } + printk("ending transmit\n"); + return 0; +} + +static int flip_relays(struct wc_usb_pvt *p, int onoff) +{ + unsigned char ctl; + unsigned char data; + /* Read data */ + if (wcinp(p->dev, 0x12, &data)) + return -1; + /* Read control */ + if (wcinp(p->dev, 0x13, &ctl)) + return -1; + /* Setup values properly -- Pins AUX3 & AUX4 control the relays */ + ctl |= 0x18; + if (onoff) { + data |= 0x18; + } else { + data &= 0xe7; + } + if (wcoutp(p->dev, 0x12, data)) + return -1; + if (wcoutp(p->dev, 0x13, ctl)) + return -1; + return 0; +} + +static int prepare_transfer_urbs(struct wc_usb_pvt *p) +{ + int x; + /* Endpoint 6 is the wave-in device */ + unsigned int readpipe = usb_rcvisocpipe(p->dev, 0x06); + /* Endpoint 7 is the wave-out device */ + unsigned int writepipe = usb_sndisocpipe(p->dev, 0x07); + + for (x = 0; x < 2; x++) { + p->dataread[x].urb.dev = p->dev; + p->dataread[x].urb.pipe = readpipe; +#ifdef LINUX26 + p->dataread[x].urb.transfer_flags = URB_ISO_ASAP; +#else + p->dataread[x].urb.transfer_flags = USB_ISO_ASAP; +#endif + p->dataread[x].urb.number_of_packets = 1; + p->dataread[x].urb.context = p; + p->dataread[x].urb.complete = wcusb_read_complete; + p->dataread[x].urb.iso_frame_desc[0].length = ZT_CHUNKSIZE * 2; + p->dataread[x].urb.iso_frame_desc[0].offset = 0; + p->dataread[x].urb.transfer_buffer = p->readchunk + ZT_CHUNKSIZE * x; + p->dataread[x].urb.transfer_buffer_length = ZT_CHUNKSIZE * 2; + + p->datawrite[x].urb.dev = p->dev; + p->datawrite[x].urb.pipe = writepipe; +#ifdef LINUX26 + p->datawrite[x].urb.transfer_flags = URB_ISO_ASAP; +#else + p->datawrite[x].urb.transfer_flags = USB_ISO_ASAP; +#endif + p->datawrite[x].urb.number_of_packets = 1; + p->datawrite[x].urb.context = p; + p->datawrite[x].urb.complete = wcusb_write_complete; + p->datawrite[x].urb.iso_frame_desc[0].length = ZT_CHUNKSIZE * 2; + p->datawrite[x].urb.iso_frame_desc[0].offset = 0; + p->datawrite[x].urb.transfer_buffer = p->writechunk + ZT_CHUNKSIZE * x; + p->datawrite[x].urb.transfer_buffer_length = ZT_CHUNKSIZE * 2; + + } + return 0; +} + +static int begin_transfer(struct wc_usb_pvt *p) +{ + + int x; + p->urbcount = 4; + p->flags |= FLAG_RUNNING; + + for (x = 0; x < 2; x++) { +#ifdef LINUX26 + if (usb_submit_urb(&p->dataread[x].urb, GFP_KERNEL)) +#else + if (usb_submit_urb(&p->dataread[x].urb)) +#endif + { + printk(KERN_ERR "wcusb: Read submit failed\n"); + return -1; + } +#ifdef LINUX26 + if (usb_submit_urb(&p->datawrite[x].urb, GFP_KERNEL)) +#else + if (usb_submit_urb(&p->datawrite[x].urb)) +#endif + { + printk(KERN_ERR "wcusb: Write submit failed\n"); + return -1; + } + } + /* Start checking for interrupts */ + wcusb_check_interrupt(p); + return 0; +} + +static int wc_usb_hooksig(struct zt_chan *chan, zt_txsig_t txsig) +{ + struct wc_usb_pvt *p = chan->pvt; + + switch (p->devclass) { + case WC_PROSLIC: +#ifdef PROSLIC_POWERSAVE + if (p->txhook == 4) { + /* Switching out of ring... Be sure we idle at 2, not 1 at least + for a bit so we can transmit caller*ID */ + p->idletxhookstate = 2; + p->lowpowertimer = POWERSAVE_TIME; + } +#endif + + p->txhook = -1; + switch(txsig) { + case ZT_TXSIG_ONHOOK: + switch(chan->sig) { + case ZT_SIG_FXOKS: + case ZT_SIG_FXOLS: + p->newtxhook = p->idletxhookstate; + break; + case ZT_SIG_FXOGS: + p->newtxhook = 3; + break; + } + break; + case ZT_TXSIG_OFFHOOK: + p->newtxhook = p->idletxhookstate; + break; + case ZT_TXSIG_START: + p->newtxhook = 4; + break; + case ZT_TXSIG_KEWL: + p->newtxhook = 0; + break; + } + case WC_KEYPAD: + switch (txsig) { + case ZT_TXSIG_ONHOOK: + break; + case ZT_TXSIG_OFFHOOK: + break; + case ZT_TXSIG_START: + break; + case ZT_TXSIG_KEWL: + break; + } + break; + } + return 0; +} + +static int wc_usb_open(struct zt_chan *chan) +{ + struct wc_usb_pvt *p = chan->pvt; + if (p->dead) + return -1; + switch (p->devclass) { + case WC_KEYPAD: + p->hookstate = 0; + zt_hooksig(&p->chan, ZT_RXSIG_ONHOOK); + break; + default: + break; + } +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#endif + p->usecount++; + return 0; +} + +static int wc_usb_close(struct zt_chan *chan) +{ + struct wc_usb_pvt *p = chan->pvt; + p->usecount--; + if (!p->usecount && p->dead) { + /* Someone unplugged us while we were running, so now + that the program exited, we can release our resources */ + zt_unregister(&p->span); + ifaces[p->pos] = NULL; + if (p->pvt_data) + kfree(p->pvt_data); + kfree(p); + } +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#endif + return 0; +} + +static struct wc_usb_pvt *wc_detect_device(struct usb_device *dev, struct wc_usb_pvt *orig) +{ + struct wc_usb_pvt *p; + + p = orig; + if (!p) { + p = kmalloc(sizeof(struct wc_usb_pvt), GFP_KERNEL); + if (!p) { + printk("wcusb: kmalloc failed\n"); + return NULL; + } + + memset(p, 0, sizeof(struct wc_usb_pvt)); + } + p->dev = dev; + +#ifdef PROSLIC_POWERSAVE + /* By default we can't send on hook */ + p->idletxhookstate = 1; +#else + /* By default we can always send on hook */ + p->idletxhookstate = 2; +#endif + + printk("wcusb: wc_detect_device\n"); + if (dev->descriptor.idProduct == 0xb210) { + struct wc_keypad_data *d = kmalloc(sizeof(struct wc_keypad_data), GFP_KERNEL); + printk("wcusb: Found a WC Keyed Phone\n"); + p->devclass = WC_KEYPAD; + if (!d) { + printk("wcusb: kmalloc failed in init_device_pvt\n"); + return NULL; + } + memset(d, 0, sizeof(struct wc_keypad_data)); + p->pvt_data = d; + d->count = 0; + d->running = 1; + d->tone = NULL; + return p; + } else { + p->pvt_data = NULL; + p->devclass = WC_PROSLIC; + } + printk("Second exit\n"); + return p; +} + +static int wc_set_zaptel(struct wc_usb_pvt *p) +{ + int x; + + for (x = 0; x < WC_MAX_IFACES; x++) + if (!ifaces[x]) break; + if (x >= WC_MAX_IFACES) { + printk("wcusb: Too many interfaces\n"); + return -1; + } + + sprintf(p->span.name, "WCUSB/%d", x); + snprintf(p->span.desc, sizeof(p->span.desc) - 1, "%s %d", p->span.name, x); + sprintf(p->chan.name, "WCUSB/%d/%d", x, 0); + p->span.manufacturer = "Digium"; + strncpy(p->span.devicetype, p->variety, sizeof(p->span.devicetype) - 1); + + p->chan.sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS; /* We're capabable of both FXOKS and FXOLS */ + p->chan.chanpos = 1; + p->span.deflaw = ZT_LAW_MULAW; + p->span.chans = &p->chan; + p->span.channels = 1; + p->span.hooksig = wc_usb_hooksig; + p->span.open = wc_usb_open; + p->span.close = wc_usb_close; + + ifaces[x] = p; + p->pos = x; + p->span.flags = ZT_FLAG_RBS; + init_waitqueue_head(&p->span.maintq); + p->span.pvt = p; + p->chan.pvt = p; + + /* Set the stream to just pass the data from the device uninhibited */ + p->sample = STREAM_NORMAL; + + if (zt_register(&p->span, 0)) { + printk("wcusb: Unable to register span %s\n", p->span.name); + return -1; + } + + return 0; +} + +#ifdef LINUX26 +static int wc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) +#else +static void *wc_usb_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id) +#endif +{ + struct wc_usb_pvt *p = NULL; + struct wc_usb_desc *d = (struct wc_usb_desc *)id->driver_info; +#ifdef LINUX26 + struct usb_device *dev = interface_to_usbdev(intf); +#endif + + int x; + for (x=0;xdead) { + if (debug) + printk("Device slot %d can be revived\n", x); + break; + } + if (debug) + printk("Device slot %d is still in use\n", x); + } + + if (!(p = wc_detect_device(dev, p))) { + printk("wcusb: No wcusb devices found\n"); +#ifdef LINUX26 + return -ENODEV; +#else + return NULL; +#endif + } + +#ifndef LINUX26 + if (usb_set_configuration(dev, dev->config[0].bConfigurationValue) < 0) { + printk("wcusb: set_configuration failed (ConfigValue 0x%x)\n", dev->config[0].bConfigurationValue); + return NULL; + } +#endif + + if (init_hardware(p)) { + printk("wcusb: Hardware intialization failed.\n"); + goto cleanup; + } + + if (prepare_transfer_urbs(p)) { + printk("wcusb: problem preparing the urbs for transfer\n"); + goto cleanup; + } + + if (d->flags & FLAG_FLIP_RELAYS) { + flip_relays(p, 1); + } + + if (!p->dead && wc_set_zaptel(p)) { + printk("wcusb: Error in starting the zaptel stuff\n"); + goto cleanup; + } + + if (begin_transfer(p)) { + printk("wcusb: Something went wrong when starting the transfer\n"); + goto cleanup; + } + + if (p->dead) + printk("wcusb: Rekindling a %s (%s)\n", d->name, p->span.name); + else + printk("wcusb: Found a %s (%s)\n", d->name, p->span.name); + + /* Reset deadness */ + p->dead = 0; + /* Clear alarms */ + p->span.alarms = 0; + p->variety = d->name; + zt_alarm_notify(&p->span); +#ifdef LINUX26 + usb_set_intfdata(intf, p); + return 0; +#else + return p; +#endif + +cleanup: + printk("cleanup\n"); + if (p) { + if (p->pvt_data) { + kfree(p->pvt_data); + } + kfree(p); + } +#ifdef LINUX26 + return -ENODEV; +#else + return NULL; +#endif +} + +#ifdef LINUX26 +static void wc_usb_disconnect(struct usb_interface *intf) +#else +static void wc_usb_disconnect(struct usb_device *dev, void *ptr) +#endif +{ + /* Doesn't handle removal if we're in use right */ +#ifdef LINUX26 + struct wc_usb_pvt *p = usb_get_intfdata(intf); +#else + struct wc_usb_pvt *p = ptr; +#endif + if (p) { + StopTransmit(p); + p->dev = NULL; + if (!p->usecount) { + zt_unregister(&p->span); + if (p->pvt_data) + kfree(p->pvt_data); + ifaces[p->pos] = NULL; + kfree(p); + } else { + /* Generate alarm and note that we're dead */ + p->span.alarms = ZT_ALARM_RED; + zt_alarm_notify(&p->span); + p->dead = 1; + } + } + printk("wcusb: Removed a Wildcard device\n"); +#ifdef LINUX26 + usb_set_intfdata(intf, NULL); +#endif + return; +} + +static struct usb_device_id wc_dev_ids[] = { + /* This needs to be a USB audio device, and it needs to be made by us and have the right device ID */ + { + match_flags: (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_DEVICE), + bInterfaceClass: USB_CLASS_AUDIO, + bInterfaceSubClass: 1, + idVendor: 0x06e6, + idProduct: 0x831c, /* Product ID / Chip configuration (you can't change this) */ + driver_info: (unsigned long)&wcusb, + }, + { + match_flags: (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_DEVICE), + bInterfaceClass: USB_CLASS_AUDIO, + bInterfaceSubClass: 1, + idVendor: 0x06e6, + idProduct: 0x831e, + driver_info: (unsigned long)&wcusb2, + }, + { + match_flags: (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_DEVICE), + bInterfaceClass: USB_CLASS_AUDIO, + bInterfaceSubClass: 1, + idVendor: 0x06e6, + idProduct: 0xb210, + driver_info: (unsigned long)&wc_usb_phone, + }, + { } /* Terminating Entry */ +}; + +static struct usb_driver wc_usb_driver = +{ +#ifdef LINUX26 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) + owner: THIS_MODULE, +#endif +#else + fops: NULL, + minor: 0, +#endif + name: "wcusb", + probe: wc_usb_probe, + disconnect: wc_usb_disconnect, + id_table: wc_dev_ids, +}; + +static int __init wc_init (void) +{ + int res; + res = usb_register(&wc_usb_driver); + if (res) + return res; + printk("Wildcard USB FXS Interface driver registered\n"); + return 0; +} + +static void __exit wc_cleanup(void) +{ + usb_deregister(&wc_usb_driver); +} + +MODULE_AUTHOR("Matthew Fredrickson "); +MODULE_DESCRIPTION("Wildcard USB FXS Interface driver"); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +MODULE_DEVICE_TABLE(usb, wc_dev_ids); + +module_init(wc_init); +module_exit(wc_cleanup); diff --git a/kernel/wcusb.h b/kernel/wcusb.h new file mode 100644 index 0000000..f22d0ac --- /dev/null +++ b/kernel/wcusb.h @@ -0,0 +1,142 @@ + +#ifndef _WCUSB_H +#define _WCUSB_H + +#include +#include +#include +#include + +#include +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19) +#define USB2420 +#endif + +#include "zaptel.h" + +#define WC_MAX_IFACES 128 + +#define POWERSAVE_TIME 4000 /* Powersaving timeout for devices with a proslic */ + +/* Various registers and data ports on the tigerjet part */ +#define WCUSB_SPORT0 0x26 +#define WCUSB_SPORT1 0x27 +#define WCUSB_SPORT2 0x28 +#define WCUSB_SPORT_CTRL 0x29 + +#define WC_AUX0 0x1 +#define WC_AUX1 0x2 +#define WC_AUX2 0x4 +#define WC_AUX3 0x8 + +#define CONTROL_TIMEOUT_MS (500) /* msec */ +#define CONTROL_TIMEOUT_JIFFIES ((CONTROL_TIMEOUT_MS * HZ) / 1000) + +#define REQUEST_NORMAL 4 + +#define FLAG_RUNNING (1 << 0) + +/* Important data structures and data types */ + + +/* States for the Proslic read state machine */ +typedef enum { + STATE_WCREAD_WRITEREG, + STATE_WCREAD_READRES, + STATE_WCWRITE_WRITEREG, + STATE_WCWRITE_WRITERES, +} proslic_state_t; + +/* Used for current stream state */ +typedef enum { + STREAM_NORMAL, /* Sends normal (unmodified) audio data */ + STREAM_DTMF, /* (For keypad device) Sends dtmf data */ +} stream_t; + +/* States for the Keypad state machine */ +typedef enum { + STATE_FOR_LOOP_1_OUT, + STATE_FOR_LOOP_2_IN, + STATE_FOR_LOOP_PROC_DATA, + STATE_FOR_LOOP_CLEAR_DIGIT, +} keypad_state_t; + +/* Device types. For radical changes in a new device, use a switch based on the device type */ +typedef enum { + WC_KEYPAD, /* The tigerjet phone with the keypad. That was a bugger to implement */ + WC_PROSLIC, /* For various devices with a proslic */ +} dev_type_t; + +struct wc_keypad_data { + keypad_state_t state; /* Current state in the keypad detect routine */ +#ifdef USB2420 + struct urb urb; /* urb used for the keypad data transport ... can't remember whether it is used or not */ +#else + urb_t urb; /* urb used for the keypad data transport ... can't remember whether it is used or not */ +#endif + int running; + char data; + char data12; + char tmp; + int scanned_event; + int i; + int count; + /* DTMF tone generation stuff for zaptel */ + struct zt_tone_state ts; + struct zt_tone *tone; +}; + +struct stinky_urb { +#ifdef USB2420 + struct urb urb; +#ifndef LINUX26 + struct iso_packet_descriptor isoframe[1]; +#endif +#else + urb_t urb; + iso_packet_descriptor_t isoframe[1]; +#endif +}; + +struct wc_usb_pvt { + const char *variety; + struct usb_device *dev; + dev_type_t devclass; + int usecount; + int dead; + struct zt_span span; + struct zt_chan chan; + struct stinky_urb dataread[2]; + struct stinky_urb datawrite[2]; +#ifdef USB2420 + struct urb control; + struct usb_ctrlrequest dr; +#else + urb_t control; + devrequest dr; +#endif + proslic_state_t controlstate; + int urbcount; + int flags; + int timer; + int lowpowertimer; + int idletxhookstate; + int hookstate; + __u8 newtxhook; + __u8 txhook; + int pos; + unsigned char auxstatus; + unsigned char wcregindex; + unsigned char wcregbuf[4]; + unsigned char wcregval; + short readchunk[ZT_MAX_CHUNKSIZE * 2]; + short writechunk[ZT_MAX_CHUNKSIZE * 2]; + stream_t sample; + void *pvt_data; +}; + +struct wc_usb_desc { + char *name; + int flags; +}; +#endif diff --git a/kernel/xpp/.version b/kernel/xpp/.version new file mode 100644 index 0000000..d658f52 --- /dev/null +++ b/kernel/xpp/.version @@ -0,0 +1 @@ +trunk-r5254 diff --git a/kernel/xpp/Changelog_xpp b/kernel/xpp/Changelog_xpp new file mode 100644 index 0000000..31684e0 --- /dev/null +++ b/kernel/xpp/Changelog_xpp @@ -0,0 +1,232 @@ +Thu Jan 10 2008 Oron Peled - xpp.r5254 + * Improved polarity reversal hangups in FXO (r5194). + Fixed false detection of polarity reversals. + * Optimize xframe allocation, by not zeroing the whole + memory (in get_xframe()). + * Fixed erronous error message that appeared sometimes + from fpga_load during USB renumeration. + * Zaptel::Chans now provides battery() reporting for some FXO + channels (Astribank FXO and wcfxo). + +Tue Dec 25 2007 Tzafrir Cohen - xpp.r5179 + * xpd_pri: Basically ready. + * PCM synchronization changes: + - Each Astribank unit ticks independently. Each with its own PLL. + - HOST synchronization is gone. Loading of xpp will no longer cause + useless 250 ticks per second if you have no Astribank. + - Synchronization from the zaptel sync master requires setting + ZAPTEL as sync source (xpp_sync ZAPTEL). + * rx_tasklet is now a parameter of the module xpp, rather than of xpp_usb. + * New FPGA firmware: 5128 (1151) / 5122 (1141, 1131): + - Fixes synchronization issues. + - PRI module: E1/T1 should now work. + * perl module and utilities: + - Modules no longer magically scan system on initialization. + - Scanning is by calling explicit methods. + - "Serial" has been renamed "Label". It is basically unique, but + should be modifieble. + - Some basic documentation of zaptel perl modules. + * Default sort order of zt_registration is back to SORT_CONNCTOR. + * zt_registration proc file now shows the number of span registered to + if registered. Try: grep . /proc/xpp/XBUS-*/XPD-*/zt_registration + * genzaptelconf: Allow using a custom command instead of + /etc/init.d/asterisk to start/stop asterisk. + * Fixed the typo "Slagish". + +Wed Nov 14 2007 Tzafrir Cohen - xpp.r5010 + * Fix a deadlock spotted on some SMP installations. + * increase FXS ring detect debounce interval. + * Improve (reduce) signal attenuation on FXO ports. + * zaptel-perl: further fixes to handling of empty slots. + +Wed Oct 3 2007 Tzafrir Cohen - xpp.r4900 + * Zaptel/Hardware perl modules: + - Use sysfs directly. Don't rely on lspci/lsusb. + - Each device has a description and driver name. + - Zaptel::Hardware::drivers() to show the list of required drivers + for this system (see zaptel_drivers). + - zaptel_hardware shows a description and a (suggested?) driver. + * zt_registration sorts by Serial first and only then by connector. + * USB_FW.hex replaces all the USB_11x0.hex . + - Separate USB interface for the management processor. + - Hence fpga_load can now work even with drivers loaded. + * Fix firmware upgrading. + * Fix manual firmware loading while auto-loading. + * Fix opermode parameter for FXO initialization (broken in r4648). + +Wed Oct 3 2007 Oron Peled - xpp.r4786 + * New firmware protocol version: 2.9 . + * fpga_load: initial clean-ups before interface split. + * genzaptelconf: Don't leave an empty directory behind (4784) + * Increase xpp poll_timeout to 1000ms - useful for CentOS 4 (r4781). + * Fix initialization anoyance: if AB don't answer to polls, don't + waitfor_xpds, and show no waiting XPDs (r4725). + * Disable dtmf_detect by default once again (r4712). + * Don't check twice for asterisk to stop. The second test was done + while Asterisk was still stopping (r4708). + * Support building the kernel with M= instead of with SUBDIRS= , as + used in some newer build systems (r4677). + +Tue Sep 11 2007 Oron Peled - xpp.r4648 + * New firmware protocol version: 2.8 . + * Cleanup INFO() messages during module loading. + + * USB: Receive queue with TASKLETS [r4600]. Controlled by rx_tasklet + parameter to xpp_usb module (can be changed in runtime). + * The pcm_tasklet parameter in xpp module is deprecated: + - Does not actually do anything. + - If set during module loading, shows an ERR() message. + - Also appears in /proc/xpp/sync + + * FXS: Hardware DTMF detection by default, can be disabled + by setting dtmf_detection=0 parameter to xpd_fxs. + PCM is muted when DTMF key is pressed. + + * zapconf: + - Can now generate users.conf compatible with asterisk-gui. + - Optional command-line arguments denoting which files to generate. + Possible values are 'zaptel', 'zapata' and 'users'. + - Defaults to creating zaptel and zapata. + + * Update to zaptel-1.4.5.1, zaptel-1.2.20.1 + * Fix building on kernel 2.6.23rc1, from Axel Thimm. + * New firmware to fix FXS leds irregularities. + * Less noise at build time - don't echo version, test compile ony once. + * zapconf can generate users.conf snippets. + +Thu Aug 16 2007 Tzafrir Cohen - xpp.r4515 + * Don't use Astribanks connected to USB1 interfaces + Unless the user set the option usb1=1 for xpp_usb (r4504). + * README.Astribank can now be generated from the makefile (r4503). + * Demote the messages about PCM in non-PCM from notice to debug (r4501). + * Fix sample BRI zapata.conf: NT instead of TE (r4498). + * Disable FXS hardware DTMF detection by default (r4492). + * Extra Zaptel PCI IDs (from Philipp Kempgen) (r4466). + +Thu Aug 2 2007 Oron Peled - xpp.r4464 + * Jump to zaptel-1.2.19 and zaptel-1.4.4 (with/without bristuff) + * BRI improvement: an 'nt_keepalive' parameter to xpd_bri forces + a BRI_NT to retry a connection indefinitely (this is our default). + When false it revert to the behaviour in changeset:4415 ("Bezeq like") + * Improvement in DBG macros. The print_dbg parameter is now set of + flags to debug. They are defined in zap_debug.h + * PRI configuration improvements (r4462): + - Hardcoded default (in init_card_9_26) is TE. + - The variable XPP_PRI_SETUP (in /etc/default/zaptel) may config + all PRI ports or some of them as we wish. Full docs are in + the utils/example_default_zaptel. + * PRI D-channel indication: Similar to BRI (r4464). + +Thu Jul 30 2007 Oron Peled - xpp.r4415 + * Show Astribank 6+2 as 6/2 channels and not 8/8 channels. + - Added as a "subtype" to the device type (r4391). + * Fixed a panic in BRI span shutdown method (r4393). + * Changes to debug macros. + * Add proper sysfs support (r4406) + - A bus on whuch all of the Astribanks reside. + - Replaces useless sysfs code that existed in the module. + - Currently used to set the sync source automatically at device + adition / removal. + * BRI: We do need the T1 timer in NT. If it gets into G2 state (rr4407). + +Thu Jul 12 2007 Oron Peled - xpp.r4372 + * Update to zaptel-1.2.18 and zaptel-1.4.3 (r4308 onward) + * Fix a critical race with zaptel synchronization (r4362) + * Added a /proc/xpp/cmds for statistics about command timing (r4360) + * Fix a digit mapping bug with hardware dtmf detection (r4357) + * In xpp/utils/Makefile add perl syntax checks to our scripts (r4337) + * Better USB data error checking (r4336) + * udev rules (xpp.rules) avoid false calls from wrong nodes (r4331) + * Improve hardware detection and reporting in lszaptel, + zaptel_hardware. zapconf is basically functional. + * Leds are blinked synchronously on all Astribanks now (r4262) + * Fix a BRI bug if OPTIMIZE_CHANMUTE was compiled into zaptel (r4258) + (This feature was not yet accepted into official zaptel) + * Removed compile warning about HZ != 1000 (r4218) + * Firmware updates. + * xpd_pri: the PRI module + * fpga_load now supports USB pathes without zeros (r4211) + * XPD numbers have changed to '' (r4196) + * Proper support for ZT_VMWI ioctl, if used in zaptel (r4092) + * Fix FXO power denial detection (r4054) + * FXO could accidentally go off-hook with some compilers (r4048) + +Tue May 1 2007 Oron Peled - xpp.r3898 + * Tested with zaptel-1.2.17.1 + * Add D-Channel TX, RX and BAD frames count in /proc/xpp/XBUS-*/XPD-*/bri_info + * Adjust output of xpp_sync script. Pad for 8 port BRI. + * Added a debugging module parport_debug (not compiled by default). + * Added an optional patch to zaptel: + - compiles only if ZAPTEL_SYNC_TICK is defined + - Allow interested driver to register for "sync" notification. + - Does not affect drivers that do not use this feature. + * Added external synchronization feature: + - Only if ZAPTEL_SYNC_TICK feature is compiled in + - Than XPP may be synchronized by another card (e.g: an Astribank + with FXS can be synchronized by a Digium PRI card). + - May be enabled/disabled in runtime via the 'sync_tick_active' module + parameter to the xpp.ko module. + * Fixed a potential bug in D-Channel hexdump printing. + * New visual indications in BRI leds: + - Constant ON RED/GREEN: Shows the port type -- NT/TE. + - Very fast "double blink": Layer1 work, no D-Channel yet. + - Steady blinking (1/2 sec): D-Channel trafic detected. + * xpp_fxloader moved to /usr/share/zaptel . + * adj_clock removed: never really used. + +Thu, 19 Apr 2007 Tzafrir Cohen - xpp.r3814 + * No need for extra patch beyond bristuff for Astribank BRI. + * Protocol no. 2.6: syncing improvements. + * Default poll intervals changed: 500 in BRI and FXO. + * Allow changing FXS polls interval at run time. + * BRI initalization fixed on SUSE (path to logger). + * When using the SUSE zaptel rpm package, set modules_var=ZAPTEL_MODULES in + /etc/sysconfig/zaptel . + * zt_registration not verbose by default. + * xpp_sync warns if FXO is sync slave. + * Extra PCM metrics data in /proc/xpp/XBUS-NN/summary . + * Extra USB metrics data in /proc/xpp/XBUS-NN/usb_info . + +Wed, 11 Apr 2007 Tzafrir Cohen - xpp.r3768 + * Removed "go away" notice and solved sync of a restarted device. + * Resetting firmware: rmmod xpp_usb; /etc/hotplug/usb/xpp_fxloader reset + * Perl modules use strict. + * genzaptelconf -F will not generate zapata configuration for NT spans. + * genzaptelconf uses perl utilities to start. + * Initial support for 2nd XHFC (BRI) chip. + +Sun, 1 Apr 2007 Tzafrir Cohen - xpp.r3712 + * New protocol version (2.5). + * Luckily firmware unloading now works. + * Solves "multiple ticks" bug. No need for pcm_tasklets workaround. + * genzaptelconf -z will generate zapscan.conf for the asterisk-gui. + * Fixed hardware detection for the BRI. + +Wed, 14 Mar 2007 Tzafrir Cohen - xpp.r3608 + * Initial verssion of firmware unloading. + * PCM bugfixes. + * Defaults of kernel parameters are now part of parameter description. + * Removed zaptel sync code for now. + * genzaptelconf will detect vzaphfc. + * genzaptelconf defaults to ptmp for BRI. + * Documentation updates. + +Mon, 26 Feb 2007 Tzafrir Cohen - xpp.r3517 + * genzaptelconf now uses ls for FXS lines by default . + * World-readable kernel parameters. + +Thu, 22 Feb 2007 Tzafrir Cohen - xpp.r3440 + * /proc/xpp/sync: 'm 0' is, while depracated, can still be used. + * New firmware with PCM improvements. + * Improvements to the xpp helper scripts. + * Bug fixes. + * zaptel/perl is now installed by xpp/utils/Makefile. + +Wed, 14 Feb 2007 Tzafrir Cohen - xpp.r3365 + * Kewlstart support on the FXS ports (already existed on the FXO ports). + * The format of /proc/xpp/sync has changed (still self-documented). + * Better notification of FXS lines that were off-hook on registration time. + * Parallel polling of Astribanks (faster startup when there are multiple + devices) + * zconf: scripts and perl modules to automate the work with Zaptel and the + Astribank. Current scripts: zt_registration, xpp_sync. diff --git a/kernel/xpp/Kbuild b/kernel/xpp/Kbuild new file mode 100644 index 0000000..9ec225f --- /dev/null +++ b/kernel/xpp/Kbuild @@ -0,0 +1,58 @@ +ifdef SUBDIRS + ZAPTEL_DIR = $(SUBDIRS) +else + ZAPTEL_DIR = $(M) +endif + +EXTRA_CFLAGS = $(XPP_LOCAL_CFLAGS) \ + -I$(ZAPTEL_DIR) \ + -DDEBUG \ + -DPOLL_DIGITAL_INPUTS \ + -DWITH_ECHO_SUPPRESSION \ + -DDEBUG_PCMTX \ + -DPROTOCOL_DEBUG \ + -g + # + +ifneq (,$(shell grep -w echo_can_state_t $(ZAPTEL_DIR)/zaptel.h)) +EXTRA_CFLAGS += -DZAPTEL_EC_TYPEDEF +endif + +obj-m += xpp.o xpd_fxs.o xpd_fxo.o xpd_pri.o + +HAS_BRISTUFF := $(shell cpp $(CPPFLAGS) -dM $(ZAPTEL_DIR)/zconfig.h | sed -n 's/^.*CONFIG_ZAPATA_BRI_DCHANS/y/p') + +# Build only supported modules +ifneq (,$(filter y m,$(CONFIG_USB))) +obj-m += xpp_usb.o +endif +ifneq (,$(HAS_BRISTUFF)) +obj-m += xpd_bri.o +endif + +xpp-y += xbus-core.o xbus-sysfs.o xbus-pcm.o xframe_queue.o xpp_zap.o xproto.o card_global.o zap_debug.o +xpd_fxs-y += card_fxs.o +xpd_fxo-y += card_fxo.o +xpd_bri-y += card_bri.o +xpd_pri-y += card_pri.o + +ifeq (y,$(PARPORT_DEBUG)) +EXTRA_CFLAGS += -DDEBUG_SYNC_PARPORT +obj-m += parport_debug.o +endif + +# Handle versioning +XPP_VERSION_STR ?= $(shell if [ -r $(obj)/.version ]; then echo "\"`cat $(obj)/.version`\""; else echo '"Unknown"'; fi) +clean-files := xpp_version.h + +$(obj)/card_fxs.o $(obj)/card_fxo.o $(obj)/card_bri.o $(obj)/card_pri.o $(obj)/xpp_usb.o $(obj)/xpp.o: $(obj)/xpp_version.h + +$(obj)/xpp_version.h: FORCE + $(Q)echo '#define XPP_VERSION $(XPP_VERSION_STR)' > $@.tmp + $(Q)if cmp -s $@.tmp $@ ; then echo; else \ + mv $@.tmp $@ ; \ + fi + $(Q)rm -f $@.tmp + +.PHONY: FORCE +FORCE: diff --git a/kernel/xpp/Makefile b/kernel/xpp/Makefile new file mode 100644 index 0000000..00fc5ee --- /dev/null +++ b/kernel/xpp/Makefile @@ -0,0 +1,7 @@ +# We only get here on kernels 2.6.0-2.6.9 . +# For newer kernels, Kbuild will be included directly by the kernel +# build system. +-include $(src)/Kbuild + +ctags: + ctags *.[ch] diff --git a/kernel/xpp/README.Astribank b/kernel/xpp/README.Astribank new file mode 100644 index 0000000..342c6a9 --- /dev/null +++ b/kernel/xpp/README.Astribank @@ -0,0 +1,1131 @@ +Xorcom Astribank Documentation +============================== +Xorcom Team +$Revision$, $Date$ + +This file documents the Zaptel drivers for the Xorcom Channel Bank. +The drivers reside in a separate subdirectory, xpp/ . + +It is generally a more technical document than the +http://www.xorcom.com/documentation/manuals/[Astribank User Manual] + +An HTML version of the latest version of this document could be found at +http://zaptel.tzafrir.org.il/README.Astribank.html[] + +Building and Installation +------------------------- +Building and installation is basically like the normal procedure of +installing Zaptel with some additions. + +Building drivers +~~~~~~~~~~~~~~~~ +On zaptel 1.2 you will need to run the following extra step to build the +Astribank drivers, apart from the standard 'make': + + make -C xpp/utils install + +In order to build the user space utilities, you will need the libusb-dev +package on Debian (and derivatives like Ubuntu) or libusb-devel on RedHat +(and derivatives like CentOS/Trixbox). + +Apart from the standard 'make install' in the zaptel directory, +run: + + make -C xpp/utils install + +Though this should be done automatically on zaptel >= 1.4.1 . + +PRI Port Setup +~~~~~~~~~~~~~~ +A port in the PRI module can be either E1 (default) or T1. It can also be +either "TE" or "NT". + +TE:: + Use the bottom port (green LED) and don't invert any wiring. Hint to + higher layers that this will be the TE (CPE) side of the connection. + This is the default setup. + +NT:: + Use the top port (orange LED) and invert wiring (this is done to allow + connecting an NT port and a TE port using a standard straight 8 wires + "ethernet" cable). Hint to higher layers that this will be the NT (Net) + side of the connection. + +The value XPP_PRI_SETUP in the init configuration file (see example +below) can be used to change those defaults. This value is a +whitelist-separated list of conditions. When a port is initialized it +checks those conditions and uses the firs one that matches. + +Match expressions may be: +- CONNECTOR/usb..../XPD-nn To identify by physical connector +- NUM/XBUS-mm/XPD-nn To identify by bus number + +Match expressions may contain "wildcards": +- * matches zero or more characters. +- ? matches one charater +- [xyz] - any of 'x', 'y', or 'z'. + +For each line you should define both if it is E1 or T1 and if it is NT +or TE. + +The list implicitly contains an 'NUM/*=TE,E1' catch all default, appended +to its end. + + +Sample Configurations +--------------------- +We generally recommend to generate the configuration by using utility +genzaptelconf. The following reference configuration will work for a +system where Astribank devices are used. + + +[[sect-default]] +Zaptel Init Configuration File +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The zaptel init.d script, genzaptelconf and the XPD init scripts uses the +parameters located in file /etc/default/zaptel (on Debian) or +/etc/sysconfig/zaptel (on RedHats). There is a number of useful parameters +that may be defined there: + +----------------------------------------------------------- +# Lines beginning with '#' are considered comments and ignored. + +# A two-letter country code. genzaptelconf uses it to better guess +# the configuration it generates. E.g: the signalling of E1 spans, and +# a few other country-specific settings. +#lc_country=us + +# See genzaptelconf(8) and the script itself for a longer list of +# variables. + +# Equivalent to the parameter opermode to the module wctdm: country-specific +# settings to the FXO lines. For a complete list of possible values, see +# /usr/share/zaptel/init_fxo_mode . +#opermode=FRANCE + +# xpp_sync runs with the value of 'XPP_SYNC' as its parameter to set the +# synchronization source. The default is 'auto' that selects the best +# Astribank. 'ZAPTEL' gets synchronization from the Zaptel sync master +# span. Or a specific xbus number. +#XPP_SYNC=ZAPTEL + +# Disables hotplug firmware loading +#XPP_HOTPLUG_DISABLED=yes +# + +# Disables udev hook called when an astribank is added and ready +# or removed. +#ASTRIBANK_HOOK_DISABLED=yes + +# Setup for the Astribank PRI module: +# All the ports in the unit connected to the USB port 0000:00:1d.7-1 +# will be NT and E1. Ports no. 1 and 3 of all the other Astribanks will +# be NT and E1 (and thus ports 0 and 2 will be TE and E1). +#XPP_PRI_SETUP=' +# CONNECTOR/usb-0000:00:1d.7-1/XPD-01=NT,E1 +# NUM/*/XPD-0[13]=NT,E1 +# ' +----------------------------------------------------------- + +/etc/zaptel.conf +~~~~~~~~~~~~~~~~ + +Astribank 8 +^^^^^^^^^^^ + fxoks=1-14 + +Astribank 6FXS/2FXO +^^^^^^^^^^^^^^^^^^^ + fxoks=1-12 + fxsks=13-14 + +Astribank 16: 8FXS/8FXO +^^^^^^^^^^^^^^^^^^^^^^^ + fxoks=1-14 + fxsks=15-22 + +Astribank 4 BRI +^^^^^^^^^^^^^^^ + # Assumed ports settings: + # Ports 1,3: TE + # Ports 2,4: NT + span=1,1,1,ccs,ami + span=2,0,1,ccs,ami + span=3,2,1,ccs,ami + span=4,0,1,ccs,ami + bchan=1-2,4-5,7-8,10-11 + dchan=3,6,9,12 + +Astribank 4 PRI E1 +^^^^^^^^^^^^^^^^^^ + # Assumed ports settings: + # Ports 1,3: TE (CPE) + # Ports 2,4: NT (Net) + span=1,1,1,ccs,hdb3,crc4 + span=2,0,1,ccs,hdb3,crc4 + span=3,2,1,ccs,hdb3,crc4 + span=4,0,1,ccs,hdb3,crc4 + bchan=1-15,17-30,31-45,47-60,61-75,77-90,91-105,107-120 + dchan=16,46,76,106 + +Astribank 4 PRI T1 +^^^^^^^^^^^^^^^^^^ + # Assumed ports settings: + # Ports 1,3: TE (CPE) + # Ports 2,4: NT (Net) + span=1,1,1,esf,b8zs + span=2,0,1,esf,b8zs + span=3,2,1,esf,b8zs + span=4,0,1,esf,b8zs + bchan=1-23,25-47,49-71,73-95 + dchan=24,48,72,96 + + +/etc/asterisk/zapata.conf +~~~~~~~~~~~~~~~~~~~~~~~~~ +Astribank 8 +^^^^^^^^^^^ + [channels] + signalling=fxo_ks + ; The real analog ports: + context=from-internal + echocancel=yes + ; echocancelwhenbriged=yes + ; echotraining=no + channel => 1-8 + + ; output ports: + context=astbank-output + channel => 9-10 + ; input ports: + immediate=yes + context=astbank-input + channel => 11-14 + immediate=no + +Astribank 6FXS/2FXO +^^^^^^^^^^^^^^^^^^^ + [channels] + signalling=fxo_ks + ; The real analog ports: + context=from-internal + echocancel=yes + ; echocancelwhenbriged=yes + ; echotraining=no + channel => 1-6 + + ; output ports: + context=astbank-output + channel => 7-8 + ; input ports: + immediate=yes + context=astbank-input + channel => 9-12 + immediate=no + + ; FXO ports + signalling=fxs_ks + context=from-pstn + callerid=asreceived + channel => 13-14 + +Astribank 16: 8FXS/8FXO +^^^^^^^^^^^^^^^^^^^^^^^ + [channels] + signalling=fxo_ks + ; The real analog ports: + context=from-internal + echocancel=yes + ; echocancelwhenbriged=yes + ; echotraining=no + channel => 1-8 + + ; output ports: + context=astbank-output + channel => 9-10 + ; input ports: + immediate=yes + context=astbank-input + channel => 11-14 + immediate=no + + ; FXO ports + signalling=fxs_ks + context=from-pstn + callerid=asreceived + channel => 15-22 + +Astribank 4 BRI +^^^^^^^^^^^^^^^ + ; Assumed ports settings: + ; Ports 1,3: TE + ; Ports 2,4: NT + [channels] + switchtype = euroisdn + callerid = asreceived + + ; TE ports: + signalling = bri_cpe_ptmp + ;signalling = bri_cpe + context = from-pstn + group = 1,11 + channel => 1,2 + + group = 1,13 + channel => 7,8 + + ; NT ports: + signalling = bri_net_ptmp + ;signalling = bri_net + context = from-internal + group = 2,12 + channel => 4,5 + + group = 2,14 + channel => 10,11 + +Astribank 4 PRI E1 +^^^^^^^^^^^^^^^^^^ + ; Assumed ports settings: + ; Ports 1,3: TE + ; Ports 2,4: NT + [channels] + switchtype = euroisdn + callerid = asreceived + + ; TE ports: + signalling = pri_cpe + context = from-pstn + group = 1,11 + channel => 1-15,17-30 + + group = 1,13 + channel => 61-75,77-90 + + ; NT ports: + signalling = bri_net_ptmp + ;signalling = bri_net + context = from-internal + group = 2,12 + channel => 31-45,47-60 + + group = 2,14 + channel => 91-105,107-120 + +Astribank 4 PRI T1 +^^^^^^^^^^^^^^^^^^ + ; Assumed ports settings: + ; Ports 1,3: TE + ; Ports 2,4: NT + [channels] + switchtype = national + callerid = asreceived + + ; TE ports: + signalling = pri_cpe + context = from-pstn + group = 1,11 + channel => 1-23 + + group = 1,13 + channel => 49-71 + + ; NT ports: + signalling = bri_net_ptmp + ;signalling = bri_net + context = from-internal + group = 2,12 + channel => 25-47 + + group = 2,14 + channel => 73-95 + + +Please check, that the mailbox and callerid parameters generated by +genzaptelconf are good for you and change them if necessary. + + +If you have Astribank device with 8 FXS and 8FXO ports connected and set +up, then the Zaptel channels will be allocated as the following: + + root@rapid:~# cat /proc/zaptel/* + Span 1: XBUS-00/XPD-00 "Xorcom XPD #00/00: FXS" + + 1 XPP_FXS/00/00/0 FXOLS (In use) + 2 XPP_FXS/00/00/1 FXOLS (In use) + 3 XPP_FXS/00/00/2 FXOLS (In use) + 4 XPP_FXS/00/00/3 FXOLS (In use) + 5 XPP_FXS/00/00/4 FXOLS (In use) + 6 XPP_FXS/00/00/5 FXOLS (In use) + 7 XPP_FXS/00/00/6 FXOLS (In use) + 8 XPP_FXS/00/00/7 FXOLS (In use) + 9 XPP_OUT/00/00/8 FXOLS (In use) (no pcm) + 10 XPP_OUT/00/00/9 FXOLS (In use) (no pcm) + 11 XPP_IN/00/00/10 FXOLS (In use) (no pcm) + 12 XPP_IN/00/00/11 FXOLS (In use) (no pcm) + 13 XPP_IN/00/00/12 FXOLS (In use) (no pcm) + 14 XPP_IN/00/00/13 FXOLS (In use) (no pcm) + Span 2: XBUS-00/XPD-01 "Xorcom XPD #00/01: FXO" (MASTER) + + 15 XPP_FXO/00/01/0 FXSKS (In use) + 16 XPP_FXO/00/01/1 FXSKS (In use) (no pcm) + 17 XPP_FXO/00/01/2 FXSKS (In use) (no pcm) + 18 XPP_FXO/00/01/3 FXSKS (In use) (no pcm) + 19 XPP_FXO/00/01/4 FXSKS (In use) (no pcm) + 20 XPP_FXO/00/01/5 FXSKS (In use) (no pcm) + 21 XPP_FXO/00/01/6 FXSKS (In use) (no pcm) + 22 XPP_FXO/00/01/7 FXSKS (In use) (no pcm) + + + +/etc/asterisk/extensions.conf +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Sample dialplan (extensions.conf) for all the above: + +----------------------------------------------------------- +[phones-zap] +; 6001 will dial to channel 1, 6020, to zaptel channel 20, etc. +exten => _6XXX,1,Dial(ZAP/${EXTEN:1}) +; Useful for debugging trunks. Will potentially allow users to +; bypass context limitations. +;exten => _6XXX.,1,Dial(ZAP/${EXTEN:1:3}/${EXTEN:4}) + +[trunk] +; A number that begins with 9: dial it through a trunk +; (we put FXO channels and TE channels in group 0). +; The leading 9 is stripped. +exten => _9.,1,Dial(Zap/g0/${EXTEN:1}) +; dialing a number that begins with 83 will dial it through +; span 3, and so forth. The two leading digits are stripped. +; (Each digital span is also added to group 10+span number). +exten => _8X.,1,Dial(Zap/g1${EXTEN:1:1}/${EXTEN:2}) + +[from-internal] +; The context of FXS ports: analog phones. +; They are allowed to dial to all other phones +include => phones-zap +; They are also allowed to call through the trunk: +include => trunk +; some simple tests: +include => astbank-test + +[from-pstn] +; Calls from the PSTN enter here. Redirect calls to an IVR +; or a default extension in the s context here. In this case we +; redirect calls to Zaptel channel 1: +exten => s,1,Dial(Zap/1) + +; Alternatively, the following will redirect you to the demo IVR +; from the sample extensions.conf of Asterisk: +include => demo + +; An extra context with some simple tests +[astbank-test] +; 200: echo test +exten => 200,1,Answer +exten => 200,n,Wait(1) +exten => 200,n,Echo() +exten => 200,n,Hangup + +; 203: say extension number. Will only work if caller ID +; is properly set in zapata.conf / zapata-channels.conf +exten => 203,1,Answer +exten => 203,n,Wait(1) +exten => 203,n,SayNumber(${CALLERID(num)}) +exten => 203,n,Hangup + +[astbank-input] +exten => s,1,Set(ZAP_CHAN=${CUT(CHANNEL,-,1)}) +exten => s,n,Set(ZAP_CHAN=${CUT(ZAP_CHAN,/,2)}) +; 11 is the number of the first input port. At least in the sample +; configuration below. +;exten => s,n,Set(INPUT_NUM=$[${ZAP_CHAN}-11)]) +; The sample below just logs the signal. +exten => s,n,NoOp(Got signal from Zaptel Channel ${ZAP_CHAN}) +; Alternatively: +;exten => s,n,System(run something) + +; No. We did not forget the context astbank-outputs. Output +; ports only get calls from the PBX. Thus they don't need a context +; of their own. Sending them to a context of their on makes +; 'zap show channels' in the CLI provide useful display, though. +----------------------------------------------------------- + + + + +Troubleshhoting +--------------- +The following commands provide useful information for debugging: + +* Check USB level status. You can use one of the following utilities for it: + + zaptel_hardware -v + or + lsusb | grep e4e4 + + - Look for the USB Product ID (the second number after e4e4). + - If you see *11x2* (e.g: 1152)- the FPGA firmware has been loaded. + Move on. + zaptel_hardware will also show you some more details if the driver + is loaded while the lsusb will just list the device. + - If it shows something as product ID *11x0* - the USB firmware is not + loaded. Maybe you need to run fxload. Or maybe just unplug and plug again + the device. Also make sure that you have fxload installed. + - If lsusb shows the Product ID as *11x1* - only the USB firmware is loaded + and not the FPGA firmware is loaded. If this is still the case after + a while - either the firmware loading has failed or you don't have + fpga_load. Make sure you have libusb-dev(el) installed when + building Zaptel. + - It should list all of your Astribank devices. If it doesn't (for + more than period of time needed for the initial firmware + loading) - Check that the Astribank is connected indeed. + +* Check if the Astribank spans are registered in Zaptel + + zt_registration + + - This should give useful results after the drivers have identified + and your devices are initialized. + - It should list all Astribank XPDs. For each of them it should write + "on" or "off". If the registration status is "off", then it means that + the span has not been registered in Zaptel and therefore can not be used + yet. + - Registration is normally done as part of `/etc/init.d/zaptel start`. + If you want to register the spans manually, then run command: + `zt_registration on` . + - Disabling of the automatic Astribank spans registration give you full + control on the order of Zaptel spans. See the module parameter + **zap_autoreg** for the further details. + +* Check the Zaptel information: + You can get some information regarding Zaptel channels by running one of the + following commands: + + lszaptel + or + cat /proc/zaptel/* + + - Those two are almost the same. The lszaptel produced more correctly sorted + output if you have more than 10 spans, and also make the output listing + looks a little bit nicer. + - You can see if your Zaptel spans and channels were loaded, if + they were configured by ztcfg and if they are in use (typically by + Asterisk). + For example: + Not configured Astribank FXS channel will be displayed as: + + 42 FXS + + When a channel has been configured with *ztcfg* (that applies + /etc/zaptel.conf), you will see an extra column for the signalling + type of the channel. The same channel after it has been configured: + + 42 FXS FXOKS + + If a program (which is typically Asterisk) uses it, you'll see: + + 42 FXS FXOKS (In use) + +* Check the Asterisk information: + + asterisk -rx 'zap show channels' + + - If you get error "Unable to connect to remote asterisk" then it + means that the Asterisk is not running. It is possible that Asterisk + has failed to start due to misconfigured zapata.conf or whatever reason. + Check /var/log/asterisk/messages or /var/log/asterisk/full . + - If you get the error that "there is no such command" then it means that + chan_zap.so is not loaded. There are two reasons for such problem: + (a) chan_zap.so is not even built. Check if the file exists: + + ls -l /usr/lib/asterisk/modules/chan_zap.so + + (b) the chan_zap.so file exists but it is not loaded. Try to load it manually: + + asterisk -rx 'load module chan_zap.so' + + - You see "pseudo" channel only. It means that you have not configured any + channels. If you have configured channels in zapata.conf, you may + need either to restart the Asterisk or unload/load chan_zap.so manually. + You can use the following Asterisk CLI commands for it: `unload chan_zap.so` and + `load chan_zap.so` + + +Reference +--------- +LEDs Indication +~~~~~~~~~~~~~~~ +The Astribank has 4 global indication leds and one or two per-port leds. +On some of the models the LEDs are located on the left side on the front +panel. If there are no separate LEDs there, then the red LEDs of the +upper left-most ports of the device are used as the indication leds. Don't +confuse them with green port status leds. + +The first led is the "Power" led. It is on if the unit gets power. +The second led is the "Active" led, which is on when there is at +least one "active" port (in a call / off-hook, though the meaning of this is +different in BRI). +The last led is called "Hardware OK", but is actually only is on in case of +the hardware failure. + +The third led is the "Sync" led. If it blinks, the device is synchronized +with the driver on the computer. If the device is selected to be the +synchronization source for all of the Astribank devices then it will blink +a quick single blink. +If the device gets synchronization from the driver, it will blink in a +more steady frequency. + +"Double blink" indicates that the unit has an FXO module, and still is +getting synchronization from the computer, and is not the synchronization +source. + +The per-port green led on analog (both FXS and FXO) indicates that the +port is off-hook. + +On the BRI, the green led indicates a TE port whereas an orange led +indicates an NT port. If the led is solid, the port is down (not even +layer-1 connection is up). If it is blinking a double blink, layer 1 +is up. A slower single blinking indicates that layer 2 is up as well +(which means that Asterisk is driving the port). + + +Device Startup +~~~~~~~~~~~~~~ +This section describes in great depth the initialization of the Xorcom +Astribank. Normally it would not be really needed, as the standard +installation of Zaptel should put everything in place. + +Terminology +^^^^^^^^^^^ +There are some technical terms that are used in this document and in the +driver / zaptel. + +span: +Zaptel breaks the channels it knows about to logical units called +"spans". A port in a E1/T1/ISDN card is usually a span. An whole +analog card is also a "span". You can see the list of spans as the list +of files under /proc/zaptel directory or in output of the zttool +utility. + +XBUS: +A funny way to call an Astribank device. + +XPD: +Basically this is a logical unit of the Astribank. It will be registered in +Zaptel as a single span. This can be either an analog (FXS or FXO) +module or a single port in case of a BRI module. + + +Loading Firmware +^^^^^^^^^^^^^^^^ +Normally this is done using the script /usr/share/zaptel/xpp_fxloader. +If it works fine, you don't need to bother reading this section. +Once the firmware is loaded the USB Vendor ID and Product ID of the Astribank +became to be e4e4 11x2, and now the driver can pick it up. + +First and foremost: the simplest and most useful tool to debug problems +is lsusb. The output of lsusb should show you if the device is connected +if its firmware is loaded. + +The firmware files are named *.hex. They are presented in the text +hexadecimal format The files are copied from xpp/utils to /usr/share/zaptel +folder during the Zaptel installation. + +The Astribank needs a firmware loaded into it. Without the firmware, +the device will appear in lsusb with Vendor ID e4e4 and Product ID 1130. +The firmware loading process consists of two stages. In the first stage the +"USB" firmware is loaded by using program fxload. When the first stage is +completed the Vendor ID is e4e4 and the Product ID is 1131. + +You can use the following command in order to load the "USB" firmware +manually: + + fxload -t fx2 -D /proc/bus/usb/MMM/NNN -I /usr/share/zaptel/USB_FW.hex + +where, + +fxload:: + A standard program that is typically part either of package 'fxload' + or 'hotplug-utils' . +/proc/bus/usb:: + The mount point of the USB file-system (usbfs). +MMM:: + the first number (bus number) +NNN:: + the second number (device number) you see for the device in lsusb + +If the loading process has been completed successfully, the device +disconnects and then connects again itself with USB Product ID 1131 +(and a new device number). + +In the second stage, the "FPGA" firmware is loaded. +The second-stage firmware loading is performed by using program fpga_load, +which is built in the directory xpp/utils and then copied to folder +/usr/sbin during Zaptel installation. + +The command syntax is similar to the syntax of fxload. You can use the +following command in order to load the FPGA firmware manually: + + fpga_load -D /proc/bus/usb/MMM/NNN -I /usr/share/zaptel/FPGA_1151.hex + +Please note, that NNN value differs from that that was used for the +fxload command due to the fact that device has "reconnected" itself +with another Product ID number. So you need to run lsusb again and get +the new NNN value. Usually, the new value is equal to the old value +incremented by 1. + + +Firmware Loading with Hotplug +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The Hotplug framework was popular for hotplugging different devices and +usually also for automatic device drivers loading. If Hotplug is used in +your system, you'll see many files in folder /etc/hotplug. Hotplug will +automatically load the most relevant USB and PCI kernel modules according +to the USB and PCI IDs provided by devices. Please note, that if the +Hotplug framework is in place and the correct configuration files are +located in the right place, then the firmware should be loaded automatically. + +In order to get the Hotplug framework to load the firmware into the +Astribank automatically, the configuration file xpp_fxloader.usermap and +the script xpp_fxloader should be copied into /etc/hotplug/usb/ . This is +done by 'make -C xpp/utils install'. + +File xpp_fxloader.usermap includes a map of USB IDs and the command to run +when such devices are encountered. It instructs the Hotplug to run the script +xpp_fxloader from that directory. This is also done by 'make -C +xpp/utils install' . + +When xpp_fxloader is run without any parameters it assumes that it was +run by the hotplug scripts. Then it will check if the "add" event was +accepted and if so, xpp_fxloader will install the required firmware file. +The xpp_fxloader will be called twice, as after the load of the USB +firmware the device will re-enumerate itself and thus "unplug" and +"replug" in order to load the FPGA firmware. + + +Firmware Loading with UDEV +^^^^^^^^^^^^^^^^^^^^^^^^^^ +The UDEV framework has replaced Hotplug in most recent systems. If you +have a recent 2.6 system without Hotplug and with many files in folder +/etc/udev, then there are good chances that are you using udev. +As in case of Hotplug, if your udev framework is configured properly +then the firmware should be loaded automatically. + +In order to get udev to automatically load the firmware into the Astribank, +the configuration file xpp.rules should be copied into folder /etc/udev/rules.d +and the script xpp_fxloader should be copied into folder /etc/hotplug/usb/ . +This is done by 'make -C xpp/utils install' during Zaptel installation. + +File xpp.rules instructs the udevd daemon to run xpp_fxloader script with +the option "udev" and with the Astribank USB ID obtained from the +device when it is plugged in. +Please note, that exactly like in case of Hotplug, the xpp_fxloader will be +called twice by the udevd. First time for the USB firmware loading and the +second time for FPGA firmware loading. + + +Firmware Resetting +^^^^^^^^^^^^^^^^^^ +Newer versions of the USB firmware can now be reset using 'fpga_load -r'. + +Also you can try the following: + + /usr/share/zaptel/xpp_fxloader reset + # if asterisk was running: you may need to stop/restart it now. + # if there are some "disconnected" spans in /proc/xpp/xbuses + # wait a while, until you see the 1152 IDs again, and then: + /etc/init.d/zaptel start + # and start/restart asterisk. + + +Loading The Modules +^^^^^^^^^^^^^^^^^^^ +Here is what should happen: +In short: you should plug the Astribank device(s) or have them plugged in at +the boot time. Then all the modules should be loaded automatically. +You will see xpp_usb , xpd_fxs and, possibly, xpd_fxo in the modules list +(the output of lsmod). + +After the module xpp is loaded, you'll also be able to see the directory +/proc/xpp. For any Astribank device discovered, you will see there a +directory /proc/xpp/XBUS-n (where n is a number: typically 0). Once a unit have +been discovered you'll see subdirectories: /proc/xpp/XBUS-n/XPD-m (where +m may be another number: 0, 1 ,etc). + +Now to the ugly details: + +The driver of the Astribank is composed of several modules: +* xpp - the basic module, that communicates with Zaptel and provides + some common services to other modules. +* xpd_fxs - the module for controlling FXS modules. +* xpd_fxo - the module for controlling FXO modules. +* xpd_bri - the module for controlling BRI modules. +* xpd_pri - the module for controlling E1/T1 modules. +* xpd_usb - the module that holds the functionality needed to connect to the + USB bus. + +All modules depend on xpp, and modprobing them will install xpp as well. +However the xpd_* modules are installed on-demand: no need to install +the xpd_fxo if you have only Astribank FXS. + +Once an Astribank device connected and the firmware is loaded, the +Vendor-ID/Product-ID of the device will be e4e4/1132 . The handler for that +combination is listed as the kernel module xpp_usb. Therefore, the system +runs 'modprobe xpp_usb' if that module is not already loaded. + +The module xpp_usb depends on the zaptel and xpp modules. Both of them +are loaded before xpp_usb. As usual, parameters and rules form +/etc/modprobe.conf and/or from /etc/modprobe.d/* will be applied to +the module. + +When command 'modprobe xpp_usb' returns, the span type specific modules +(e.g., xpd_fxs, xpd_fxo) may or may not have been loaded yet. + +At this point the xpp driver "asks" the box about type of telephony modules +it has. According to the answers it receives, the xpp driver will "modprobe" +the required xpd_* modules. + + +Device Initializations Scripts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The chips in the device need to be initialized. This requires sending a +bunch of values to certain registers in those chips. We decided that +hardwriting those values in the driver code is not a good idea. +Before registering a XPD as a span in Zaptel, we run an initialization +script: /usr/share/zaptel/init_card_N_MM ( +where, + +* N - is 3 for an FXS span and 4 for an FXO span, and 6 or 7 for BRI. +* MM - is a version number. Currently it equals 26 + +If because of some reasons this fails (the script is not in the place, or the +file doesn't have the executable permissions), then you will get an error +message in the logs and the XPD will then be removed (you won't see directory +for that XPD under the corresponding /proc/xpp/XBUS-* directory) and will not +be registered in Zaptel. + +As the XPD is initialized, you'll see the green LEDs of the ports steadily +turn on and later off ("a train of lights"). This is a bit slower than the +faster "blinking" when the XPDs register as Zaptel spans. The initializaton +of an FXS XPD may take a few seconds. + + +Astribank in Sysfs +^^^^^^^^^^^^^^^^^^ +When an Astribank device loads it generates a device node in the bus +'astribanks' in sysfs. You can see a directory for each device under +/sys/bus/astribanks/devices/ and under it there are several attributes +for each Astribank (such as its connector string). + +On each time an Astribank is initialized or destroyed a udev event is +generated. The rules from our sample udev rules file (xpp/utils/xpp.rules) +make that event run the script /usr/share/zaptel/astribank_hook with the +parameter 'add' or 'remove', if such script exists. An example script +that just adjusts the Astribank sync settings is included in xpp/utils. + + +Registering in Zaptel +^^^^^^^^^^^^^^^^^^^^^ +The XPDs will not automatically register as zaptel spans. This is +intended to allow you to set the registration order (and hence the order +of Zaptel spans and channels) among multiple Astribank devices, +or between an Astribank and a different Zaptel device. + +When the XPD registers to Zaptel, all the green LEDs will be lit for a +short while. + +Spans are normally registered with the utility zt_registration. Simply +running 'zt_registration' shows the available XPDs and whether or not +they are registered. To register: + + zt_registration on + +For a system with several spans you'll see a "fast train of lights". + +If you have multiple Astribank devices, zt_registration will register +them by the order of the "connector" field. This means that as long as +the same Astribank is connected to the same port, the order of plugging +is not important.. + +zt_registration checks if a span is registered or tries to register a +span using the file /proc/xpp/XBUS-nn/XPD-mm/zt_registration . Reading +from that file returns 0 if the span is unregisteres or 1 if it is +registered. You can register a span or ask to unregister it by writing 1 +(register) or 0 (unregister) to that file. Registeration should +generally always succeed. Unregistration may fail if a span is in use. + +You may choose to register the XPDs in Zaptel automatically, in order to +allow finer control of the process. This behavior may be defined by setting +parameter zap_autoreg in the modprobe configuration file (A file under +/etc/modprobe.d or /etc/modprobe.conf): + + options xpp zap_autoreg=1 + + +Zaptel And Above +^^^^^^^^^^^^^^^^ +From here you get a standard Zaptel span. It still needs to be +configured by ztcfg and used by a program such as Asterisk like any +other Zaptel device. In order for you to get a dialtone in a phone +connected to the FXS port or a fully synchronized BRI port (layer 2 +activated, as signalled by a more steady blink) you will actually need +both the span configured by Zaptel and the channels configured in +Asterisk. + +You should generally refer to the general Zaptel documentation on how to +configure those levels. e.g, the README file in the toplevel directory, +and + + http://voip-info.org/wiki/view/Asterisk+config+zapata.conf[] + + +Zaptel now includes a utility called genzaptelconf (written as a big +ugly shell script) to configure Zaptel automatically as good as +possible. For analog channels it works quite well (because, IMHO, the +"configuration" level on Zaptel should be optional there - there are +already sane defaults). For digital spans - BRI and PRI , it may take +some tuning. + +Alternatively, write you own configuration, based on the sample from the +"Sample Configurations" section. + + +/proc Interface +~~~~~~~~~~~~~~~ +The Astribank drivers provide their own /proc interface under /proc/xpp. +(Note that the details of this interface are still potentially subject to +changes) + + +/proc/xpp/xbuses +^^^^^^^^^^^^^^^^ +File /proc/xpp/xbuses lists the connected Astribank devices (one line +per device). + +A device is normally has status "connected". The status "missing" means that +the device has been disconnected, but Asterisk still holds channels from it +open. + + +/proc/xpp/sync +^^^^^^^^^^^^^^ +A read/write file. It contains information about current synchronization +source. You can change the synchronization source by writing special +command to the file. For example, command + echo SYNC=01 > /proc/xpp/sync + +Possible values are: + +:: + Make the Astribank XBUS- the sync source for other Astribanks. + +ZAPTEL:: + Make the astribanks synchronize with the Zaptel timing master span. + You probably ned this to get faxes from a non-Astribank adapter to an + Astribank. + +Though you'll normally use xpp_sync(8) for that. + +For each Astribank device there is folder /proc/xpp/XBUS-nn and for each device +module (span in the therms of Zaptel) there is folder /proc/XBUS-nn/XPD-mm. + + +/proc/xpp/XBUS-nn/XPD-mm/zt_registration +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +is a read/write file. Reading from it gives 0 if the span is +unregistered, or the span number if it is registered. + +Writing to it allows manual registration / unregistration from Zaptel: +writing 1 registers a span (if it wasn't already registered) and writing +0 attempts to unregister it (if it is registered. Span unregistration +will fail if some channels from the span are used (e.g: by Asterisk). + +A more convient interface to this is the command zt_registration that +registers or unregisters all the spans at once with a predefined order, +and this is what you should normally use. + +Alternatively you can use the parameter zap_autoreg to register spans +automatically. But this is only recommended on a system with a single +Astribank and no other Zaptel device. + + +/proc/xpp/XBUS-nn/XPD-mm/summary +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Contains detailed information about port statuses of the device module +(off-hook, on-hook etc.) For example, you can run the following command +in order to monitor the port statuses in the real time: + + watch -n1 cat /proc/xpp/XBUS-00/XPD-00/summary + + +/proc/xpp/XBUS-nn/XPD-mm/slics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Provides direct read/write interface to the registers of each chip. +Reading from the file shows the result of the last read request. To make +either a read request or a write request you need to write to that file. + +It is mainly used by the initialization scripts (card_init_*). + + +/proc/xpp/XBUS-nn/XPD-mm/fxo_info +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Only for FXO modules. Apart from showing the status of the LEDs, it also +shows for each FXO port if it is connected to a provider: look for the +value of "battery" for that specific port. + + +/proc/xpp/XBUS-nn/XPD-mm/bri_info +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In addition to the usual information about the LEDs, this file also +provides useful information regarding ISDN Layer 1 and Layer 2 status. +For example, you can run the following command in order to monitor +the Layer 1 port statuses for all BRI devices in the real time: + + watch -n1 -d 'grep "Layer 1:" /proc/xpp/XBUS-*/XPD-*/bri_info' + +For the status of the D channel of the ports on all BRI spans, run: + + watch -n1 -d 'grep D-Channel: /proc/xpp/XBUS-*/XPD-*/bri_info' + + +/proc/xpp/XBUS-nn/XPD-mm/pri_info +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In addition to the usual information about the LEDs, this file also +provides useful information regarding ISDN Layer 1 and Layer 2 status. +For example, you can run the following command in order to monitor +the Layer 1 port statuses for all E1/T1 devices in the real time: + + watch -n1 -d 'grep "Layer 1:" /proc/xpp/XBUS-*/XPD-*/pri_info' + +For the status of the D channel of the ports on all PRI spans, run: + + watch -n1 -d 'grep D-Channel: /proc/xpp/XBUS-*/XPD-*/pri_info' + +Note: the layer 2 status is much more of a guesswork based on changes in +the contents of the channel that is supposed to be the D channel. + +Writing to this file can be used to change the type of the device. The +device type can only be changed when the XPD is not registered as a +Zaptel span. The value is a whitespace-separated list of values that can +be of: + +E1:: + Provides 31 channels, of which channel 16 is normally the D-channel. + Common in places outside of North America and Japan. This is the + default setup. + +T1:: + T1 provides 24 channels. The last one is normally the D-Channel. + Common in North America. + +TE:: + Use the bottom port (green LED) and don't invert any wiring. Hint to + higher layers that this will be the TE side of the connection. This is + the default setup. + +NT:: + Use the top port (orange LED) and invert wiring (this is done to allow + connecting an NT port and a TE port using a standard straight 8 wires + "ethernet" cable). Hint to higher layers that this will be the NT side + of the connection. + +LOCALOOP:: + Set the device into local loop mode: loops the transmitted channels + directly into the recieved channels. + +NOLOCALLOOP:: + Ends local loop mode. + +Normally those are set by the PRI initialization script . See the +definition of XPP_PRI_SETUP in xref:sect-default[the sample Zaptel init +configuration file] . + +There are a bunch of other status files under /proc/xpp/. + + +Useful Module Parameters +~~~~~~~~~~~~~~~~~~~~~~~~ +Compilation-time defaults for the all modules can be shown as part of the +description line for the parameter in the "modinfo" command output. + +zap_autoreg (xpp):: + Register spans automatically (1) or not (0). Default: 0. + Setting it simplifies operations with a single Astribank and no other + zaptel hardware. However if you have such systems, automatic + registration can cause the order of spans to be unpredictable. + The standard startup scripts use 'zt_registration on' instead of this. + +initdir (xpp):: + This is the directory containing the initialization scripts. + The default is /usr/share/zaptel . + Setting this value could be useful if that location is inconvenient for you. + +rx_tasklet (xpp):: + Enable (1) or disable (0) doing most of the packets processing in + separate tasklets. This should probably help on higher-end systes with + multiple Astribanks. + +print_dbg (all modules):: + It will make the driver to print tons of debugging messages. You can + set/unset the parameter at run-time. + + The parameter value is a bitmask of several values. The different bits + meaning as it defined in xpp/zap_debug.h: + + * 0 - Disable debug messages + * 1 - GENERAL - General debug comments. + * 2 - PCM - PCM-related messages. Tend to flood logs. + * 4 - LEDS - Anything related to the leds status control. The driver + produces a lot of messages when the option is enabled. + * 8 - SYNC - Synchronization related messages. + * 16 - SIGNAL - Zaptel signalling related messages. + * 32 - PROC - procfs interface related messages. + * 64 - REGS - Reading and writing to chip registers. The driver produces + a lot of messages when the option is enabled. + + For example, + + echo 33 >/sys/modules/xpp/parameters/print_dbg + + forces module xpp to print general debugging messages (1) and procfs + debugging messages (32). + +vmwineon (xpd_fxs):: + Enable (1) or disable (0) sending the voicemail message waiting indication + signal to phones equipped with the Message Wainting neon lamp. It is + disabled by default because the feature requires extra work of the driver + even when such a phone is not used and also may cause some unusual + side effects with some phone models. + +usb1 (xpp_usb):: + Enable (1) or disable (0) support of USB1 devices. Disabled by default. + + + + + USB1 devices are not well-tested. It seems that they don't work at all + for Astribank BRI. Generally they should work with the current code, but + we expect the voice quality issues. Hence we would like to make it very clear that + you if you have a USB1 port (rather than a USB2 one, as recommended) you + will have to take an action to enable the device. + +poll intervals (various):: + There are various values which the driver occasionally polls the device + for. For instance, the parameter poll_battery_interval for xpd_fxo + to poll the battery (in order to know if the telco line is actually + connected.) + + + + + The value of those parameters is typically a number in milliseconds or 0 + to disable. Under normal operation there should be no reason to play + with those parameters. + +dtmf_detection (xpd_fxs):: + Enable (1) or disable (0) support of hardware DTMF detection by the + Astribank. + + +NOTE: XPP here does not stand for X Printing Panel, XML Pull Parser, +X-Windows Phase Plane or XML Professional Publisher. It is simply the +Xorcom Peripheral Protocol, which connects a computer to a XPD (Xorcom +Peripheral Device). An XBUS (originally XPP Bus) is actually a single +Astribank device and the XPDs have become the single modules in it. diff --git a/kernel/xpp/calibrate_slics b/kernel/xpp/calibrate_slics new file mode 100755 index 0000000..c1e6064 --- /dev/null +++ b/kernel/xpp/calibrate_slics @@ -0,0 +1,308 @@ +#!/usr/bin/perl -w + +# +# $Id$ +# + +use strict; + +my $SlicsFile = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/$ENV{XPD_NAME}/slics"; + +my @SlicNums = (0 .. 7); + +if ( ! -f $SlicsFile ) { + exit 1 +} + +my $debug = 0; +# set DEBUG_CALIBRATION in /etc/default/zaptel or similar +if (exists $ENV{DEBUG_CALIBRATION}) { + $debug = 1; +} + +sub mysleep($) { + my $timeout = shift; + select(undef,undef,undef,$timeout); +} + +sub logger($) { + print STDERR "LOG: @_\n"; + system("logger @_"); +} + +sub debug($) { + logger(@_) if ($debug); +} + +sub write_to_slic_file($) { + my $write_str = shift; + + open(SLICS,">$SlicsFile") or + die("Failed writing to slics file $SlicsFile"); + print SLICS $write_str; + close(SLICS); + mysleep(0.001); + +} + +sub read_reg($$$) { + my $read_slic = shift; + my $read_reg = shift; + my $direct = shift; + + write_to_slic_file( + sprintf("%d R%s %02X", $read_slic, $direct, $read_reg)); + mysleep(0.001); + open(SLICS,$SlicsFile) or + die("Failed reading from slics file $SlicsFile"); + #awk '/^SLIC_REPLY:/{print $5}' $SLICS | cut -dx -f2 + my @reply = (); + while(){ + #if (/^ /) { + # debug "answer line: $_"; + #} + if (/^ \d*\s+[RW][DIS]\s+[[:xdigit:]]+\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)/){ + @reply = (hex($1), hex($2)); + #debug "got [$reply]\n"; + last; + } + } + close(SLICS); + if ($direct eq 'I') { + return @reply; + } else { + return $reply[0]; + } +} + +# TODO: rearange arguments +sub write_reg{#($$$$$) { + my $read_slic = shift; + my $read_reg = shift; + my $direct = shift; + my $reg_val_low = shift; + my $reg_val_hi = shift; + + my $str = sprintf "%d W%s %02X %02X", + $read_slic, $direct, $read_reg, $reg_val_low; + if ($direct eq 'I') { + $str .= sprintf " %02X", $reg_val_hi; + } + write_to_slic_file($str); +} + +sub log_calib_params() { + for my $i (100 .. 107) { + my $line="Calib Reg $i: "; + for my $slic (@SlicNums) { + $line .= " ".read_reg($slic, $i, 'D'); + } + debug($line); + } +} + +sub init_indirect_registers() { + return write_to_slic_file("# +31 WI 00 C2 55 +31 WI 01 E6 51 +31 WI 02 85 4B +31 WI 03 37 49 + +31 WI 04 33 33 +31 WI 05 02 02 +31 WI 06 02 02 +31 WI 07 98 01 + +31 WI 08 98 01 +31 WI 09 11 06 +31 WI 0A 02 02 +31 WI 0B E5 00 + +31 WI 0C 1C 0A +31 WI 0D 30 7B +31 WI 0E 63 00 +31 WI 0F 00 00 + +31 WI 10 70 78 +31 WI 11 7D 00 +31 WI 12 00 00 +31 WI 13 00 00 + +31 WI 14 F0 7E +31 WI 15 60 01 +31 WI 16 00 00 +31 WI 17 00 20 + +31 WI 18 00 20 +31 WI 19 00 00 +31 WI 1A 00 20 +31 WI 1B 00 40 + +31 WI 1C 00 10 +31 WI 1D 00 36 +31 WI 1E 00 10 +31 WI 1F 00 02 + +31 WI 20 C0 07 +31 WI 21 00 26 +31 WI 22 F4 0F +31 WI 23 00 80 + +#31 WI 24 20 03 +#31 WI 25 8C 08 +#31 WI 26 00 01 +#31 WI 27 10 00 + +31 WI 24 00 08 +31 WI 25 00 08 +31 WI 26 00 08 +31 WI 27 00 08 + +31 WI 28 00 0C +31 WI 29 00 0C +31 WI 2B 00 01 + +31 WI 63 DA 00 +31 WI 64 60 6B +31 WI 65 74 00 +31 WI 66 C0 79 + +31 WI 67 20 11 +31 WI 68 E0 3B +#"); +} + +sub init_early_direct_regs() { + return write_to_slic_file("# +31 WD 08 00 +31 WD 4A 34 +31 WD 4B 10 +31 WD 40 00 +#") +} + +my @FilterParams = (); + +sub save_indirect_filter_params() { + for my $slic (@SlicNums) { + for my $reg (35 .. 39) { + $FilterParams[$slic][$reg] = + [read_reg($slic, $reg, 'I')]; + write_reg($slic, $reg, 'I', 0, 0x80); + } + } + +} + +sub restore_indirect_filter_params() { + for my $slic (@SlicNums) { + for my $reg (35 .. 39) { + write_reg($slic, $reg, 'I', + @{$FilterParams[$slic][$reg]}); + } + } +} + +my $ManualCalibrationSleepTime = 0.04; # 40ms + +sub manual_calibrate_loop($$) { + my $write_reg = shift; + my $read_reg = shift; + + # counters to count down to (at most) 0 + my @slic_counters = (); + for my $i (0 .. $#SlicNums) { + $slic_counters[$i] = 0x1F; + } + + # start calibration: + my $calibration_in_progress = 1; + write_reg(31, $write_reg, 'D', 0x1F); + mysleep $ManualCalibrationSleepTime; + + # wait until all slics have finished calibration, or for timeout + while ($calibration_in_progress) { + $calibration_in_progress = 0; # until proven otherwise + my $debug_calib_str = "ManualCalib:: "; + for my $slic(@SlicNums) { + my $value = read_reg($slic, $read_reg, 'D'); + $debug_calib_str .= " [$slic_counters[$slic]:$value]"; + if ($value != 0 && $slic_counters[$slic] >= 0) { + $calibration_in_progress = 1; + $slic_counters[$slic]--; + write_reg($slic,$write_reg,'D',$slic_counters[$slic]); + } + } + debug($debug_calib_str); + # TODO: unnecessary sleep in the last round: + mysleep $ManualCalibrationSleepTime; + } +} + +sub manual_calibrate() { + manual_calibrate_loop(98, 88); + manual_calibrate_loop(99, 89); +} + +sub auto_calibrate($$) { + my $calib_96 = shift; + my $calib_97 = shift; + + #log_calib_params(); + # start calibration: + write_to_slic_file( + sprintf + "31 WD 61 %02X\n". + "31 WD 60 %02X\n". + "", $calib_96, $calib_97 + + ); + # wait until all slics have finished calibration, or for timeout + my $sleep_cnt = 0; + # time periods in seconds: + my $sleep_time = 0.1; + my $timeout_time = 2; + CALIB_LOOP: for my $slic (@SlicNums) { + debug("checking slic $slic"); + while(1) { + if ((read_reg($slic, 60, 'D')) == 0) { + # move to next register + debug("slic $slic calibrated"); + last; + } + if ( $sleep_cnt > $timeout_time/$sleep_time) { + debug("Auto Calibration: Exiting on timeout: $timeout_time."); + last CALIB_LOOP; + } + debug("auto_calibrate not done yet: slic #$slic\n"); + mysleep(0.1); + $sleep_cnt++; + } + } + #log_calib_params(); +} + +########################################################### +# +# main +# + +# TODO: for all slics check the following reads to check communication +#read_reg($slic, 0x08, 'D'): 0x02 +#read_reg($slic, 0x0B, 'D'): 0x33 +#read_reg($slic, 0x40, 'D'): 0x00 (?) + +debug "starting\n"; + +init_indirect_registers(); +debug "after init_indirect_registers\n"; +init_early_direct_regs(); +debug "after init_early_direct_regs\n"; +auto_calibrate(0x47, 0x1E); +debug "after auto_calibrate\n"; +manual_calibrate(); +debug "after manul_calibrate\n"; +auto_calibrate(0x40, 0x01); +debug "after auto_calibrate 2\n"; + + diff --git a/kernel/xpp/card_bri.c b/kernel/xpp/card_bri.c new file mode 100644 index 0000000..998d22a --- /dev/null +++ b/kernel/xpp/card_bri.c @@ -0,0 +1,1731 @@ +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * Parts derived from Cologne demo driver for the chip. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include "xpd.h" +#include "xproto.h" +#include "xpp_zap.h" +#include "card_bri.h" +#include "zap_debug.h" +#include "xpd.h" +#include "xbus-core.h" + +static const char rcsid[] = "$Id$"; + +#ifndef CONFIG_ZAPATA_BRI_DCHANS +#error CONFIG_ZAPATA_BRI_DCHANS is not defined +#endif + +DEF_PARM(int, print_dbg, 0, 0644, "Print DBG statements"); /* must be before zap_debug.h */ +DEF_PARM(uint, poll_interval, 500, 0644, "Poll channel state interval in milliseconds (0 - disable)"); +DEF_PARM_BOOL(nt_keepalive, 1, 0644, "Force BRI_NT to keep trying connection"); +#ifdef DEBUG_PCMTX +DEF_PARM(int, pcmtx, -1, 0644, "Forced PCM value to transmit (negative to disable)"); +DEF_PARM(int, pcmtx_chan, 0, 0644, "channel to force PCM value"); +#endif + +enum xhfc_states { + ST_RESET = 0, /* G/F0 */ + /* TE */ + ST_TE_SENSING = 2, /* F2 */ + ST_TE_DEACTIVATED = 3, /* F3 */ + ST_TE_SIGWAIT = 4, /* F4 */ + ST_TE_IDENT = 5, /* F5 */ + ST_TE_SYNCED = 6, /* F6 */ + ST_TE_ACTIVATED = 7, /* F7 */ + ST_TE_LOST_FRAMING = 8, /* F8 */ + /* NT */ + ST_NT_DEACTIVATED = 1, /* G1 */ + ST_NT_ACTIVATING = 2, /* G2 */ + ST_NT_ACTIVATED = 3, /* G3 */ + ST_NT_DEACTIVTING = 4, /* G4 */ +}; + +static const char *xhfc_state_name(xpd_type_t xpd_type, enum xhfc_states state) +{ + const char *p; + +#define _E(x) [ST_ ## x] = #x + static const char *te_names[] = { + _E(RESET), + _E(TE_SENSING), + _E(TE_DEACTIVATED), + _E(TE_SIGWAIT), + _E(TE_IDENT), + _E(TE_SYNCED), + _E(TE_ACTIVATED), + _E(TE_LOST_FRAMING), + }; + static const char *nt_names[] = { + _E(RESET), + _E(NT_DEACTIVATED), + _E(NT_ACTIVATING), + _E(NT_ACTIVATED), + _E(NT_DEACTIVTING), + }; +#undef _E + if(xpd_type == XPD_TYPE_BRI_TE) { + if ((state < ST_RESET) || (state > ST_TE_LOST_FRAMING)) + p = "TE ???"; + else + p = te_names[state]; + } else { + if ((state < ST_RESET) || (state > ST_NT_DEACTIVTING)) + p = "NT ???"; + else + p = nt_names[state]; + } + return p; +} + +/* xhfc Layer1 physical commands */ +#define HFC_L1_ACTIVATE_TE 0x01 +#define HFC_L1_FORCE_DEACTIVATE_TE 0x02 +#define HFC_L1_ACTIVATE_NT 0x03 +#define HFC_L1_DEACTIVATE_NT 0x04 + +#define HFC_L1_ACTIVATING 1 +#define HFC_L1_ACTIVATED 2 +#define TIMER_T1_MAX 2500 +#define HFC_TIMER_T3 8000 /* 8s activation timer T3 */ +#define HFC_TIMER_T4 500 /* 500ms deactivation timer T4 */ +#define HFC_TIMER_OFF -1 /* timer disabled */ + +#define A_SU_WR_STA 0x30 /* ST/Up state machine register */ +#define V_SU_LD_STA 0x10 +#define V_SU_ACT 0x60 /* start activation/deactivation */ +#define STA_DEACTIVATE 0x40 /* start deactivation in A_SU_WR_STA */ +#define STA_ACTIVATE 0x60 /* start activation in A_SU_WR_STA */ +#define V_SU_SET_G2_G3 0x80 + +#define A_SU_RD_STA 0x30 +typedef union { + struct { + byte v_su_sta:4; + byte v_su_fr_sync:1; + byte v_su_t2_exp:1; + byte v_su_info0:1; + byte v_g2_g3:1; + } bits; + byte reg; +} su_rd_sta_t; + +#define REG30_LOST 3 /* in polls */ +#define DCHAN_LOST 15000 /* in ticks */ + +#define BRI_DCHAN_SIGCAP ( \ + ZT_SIG_EM | \ + ZT_SIG_CLEAR | \ + ZT_SIG_FXSLS | \ + ZT_SIG_FXSGS | \ + ZT_SIG_FXSKS | \ + ZT_SIG_FXOLS | \ + ZT_SIG_FXOGS | \ + ZT_SIG_FXOKS | \ + ZT_SIG_CAS | \ + ZT_SIG_SF \ + ) +#define BRI_BCHAN_SIGCAP ZT_SIG_CLEAR + +#define IS_NT(xpd) ((xpd)->type == XPD_TYPE_BRI_NT) + +/* shift in PCM highway */ +#define SUBUNIT_PCM_SHIFT 4 +#define PCM_SHIFT(mask, sunit) ((mask) << (SUBUNIT_PCM_SHIFT * (sunit))) + +/*---------------- BRI Protocol Commands ----------------------------------*/ + +static int write_state_register(xpd_t *xpd, byte value); +static bool bri_packet_is_valid(xpacket_t *pack); +static void bri_packet_dump(const char *msg, xpacket_t *pack); +static int proc_bri_info_read(char *page, char **start, off_t off, int count, int *eof, void *data); +static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data); +static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data); +static int bri_spanconfig(struct zt_span *span, struct zt_lineconfig *lc); +static int bri_chanconfig(struct zt_chan *chan, int sigtype); +static int bri_startup(struct zt_span *span); +static int bri_shutdown(struct zt_span *span); + +#define PROC_REGISTER_FNAME "slics" +#define PROC_BRI_INFO_FNAME "bri_info" + +#define VALID_CHIPSEL(x) ((x) == 0) + +enum led_state { + BRI_LED_OFF = 0x0, + BRI_LED_ON = 0x1, + /* + * We blink by software from driver, so that + * if the driver malfunction that blink would stop. + */ + // BRI_LED_BLINK_SLOW = 0x2, /* 1/2 a second blink cycle */ + // BRI_LED_BLINK_FAST = 0x3 /* 1/4 a second blink cycle */ +}; + +enum bri_led_names { + GREEN_LED = 0, + RED_LED = 1 +}; + +#define NUM_LEDS 2 +#define LED_TICKS 100 + + +struct bri_leds { + byte state:2; + byte led_sel:1; /* 0 - GREEN, 1 - RED */ + byte reserved:5; +}; + +#ifndef MAX_DFRAME_LEN_L1 +#define MAX_DFRAME_LEN_L1 300 +#endif + +#define DCHAN_BUFSIZE MAX_DFRAME_LEN_L1 + +struct BRI_priv_data { + struct proc_dir_entry *regfile; + struct proc_dir_entry *bri_info; + su_rd_sta_t state_register; + bool initialized; + int t1; /* timer 1 for NT deactivation */ + int t3; /* timer 3 for activation */ + int t4; /* timer 4 for deactivation */ + ulong l1_flags; + bool reg30_good; + uint reg30_ticks; + bool layer1_up; + xpp_line_t card_pcm_mask; + + /* + * D-Chan: buffers + extra state info. + */ + int dchan_r_idx; + byte dchan_rbuf[DCHAN_BUFSIZE]; + byte dchan_tbuf[DCHAN_BUFSIZE]; + bool txframe_begin; + + reg_cmd_t requested_reply; + reg_cmd_t last_reply; + uint tick_counter; + uint poll_counter; + uint dchan_tx_counter; + uint dchan_rx_counter; + uint dchan_rx_drops; + bool dchan_alive; + uint dchan_alive_ticks; + uint dchan_notx_ticks; + uint dchan_norx_ticks; + enum led_state ledstate[NUM_LEDS]; +}; + +static xproto_table_t PROTO_TABLE(BRI_NT); +static xproto_table_t PROTO_TABLE(BRI_TE); + + +DEF_RPACKET_DATA(BRI, SET_LED, /* Set one of the LED's */ + struct bri_leds bri_leds; + ); + +static /* 0x33 */ DECLARE_CMD(BRI, SET_LED, enum bri_led_names which_led, enum led_state to_led_state); + +#define DO_LED(xpd, which, tostate) \ + CALL_PROTO(BRI, SET_LED, (xpd)->xbus, (xpd), (which), (tostate)) + +#define DEBUG_BUF_SIZE (100) +static void dump_hex_buf(xpd_t *xpd, char *msg, byte *buf, size_t len) +{ + char debug_buf[DEBUG_BUF_SIZE + 1]; + int i; + int n = 0; + + debug_buf[0] = '\0'; + for(i = 0; i < len && n < DEBUG_BUF_SIZE; i++) + n += snprintf(&debug_buf[n], DEBUG_BUF_SIZE - n, "%02X ", buf[i]); + XPD_DBG(GENERAL, xpd, "%s[0..%zd]: %s%s\n", msg, len-1, debug_buf, + (n >= DEBUG_BUF_SIZE)?"...":""); +} + +static void dump_dchan_packet(xpd_t *xpd, bool transmit, byte *buf, int len) +{ + struct BRI_priv_data *priv; + char msgbuf[MAX_PROC_WRITE]; + char ftype = '?'; + char *direction; + int frame_begin; + + priv = xpd->priv; + BUG_ON(!priv); + if(transmit) { + direction = "TX"; + frame_begin = priv->txframe_begin; + } else { + direction = "RX"; + frame_begin = 1; + } + if(frame_begin) { /* Packet start */ + if(!IS_SET(buf[0], 7)) + ftype = 'I'; /* Information */ + else if(IS_SET(buf[0], 7) && !IS_SET(buf[0], 6)) + ftype = 'S'; /* Supervisory */ + else if(IS_SET(buf[0], 7) && IS_SET(buf[0], 6)) + ftype = 'U'; /* Unnumbered */ + else + XPD_NOTICE(xpd, "Unknown frame type 0x%X\n", buf[0]); + + snprintf(msgbuf, MAX_PROC_WRITE, "D-Chan %s = (%c) ", direction, ftype); + } else { + snprintf(msgbuf, MAX_PROC_WRITE, "D-Chan %s = ", direction); + } + dump_hex_buf(xpd, msgbuf, buf, len); +} + +static void layer1_state(xpd_t *xpd, bool up) +{ + struct BRI_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + if(priv->layer1_up == up) + return; + priv->layer1_up = up; + XPD_DBG(SIGNAL, xpd, "STATE CHANGE: Layer1 %s\n", (up)?"UP":"DOWN"); +} + +static void dchan_state(xpd_t *xpd, bool up) +{ + struct BRI_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + if(priv->dchan_alive == up) + return; + if(up) { + XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel RUNNING\n"); + priv->dchan_alive = 1; + } else { + XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel STOPPED\n"); + priv->dchan_rx_counter = priv->dchan_tx_counter = priv->dchan_rx_drops = 0; + priv->dchan_alive = 0; + priv->dchan_alive_ticks = 0; + } +} + +static void xpd_activation(xpd_t *xpd, bool on) +{ + struct BRI_priv_data *priv; + xbus_t *xbus; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + xbus = xpd->xbus; + XPD_DBG(SIGNAL, xpd, "%s\n", (on)?"ON":"OFF"); + switch(xpd->type) { + case XPD_TYPE_BRI_TE: + if(on) { + XPD_DBG(SIGNAL, xpd, "HFC_L1_ACTIVATE_TE\n"); + set_bit(HFC_L1_ACTIVATING, &priv->l1_flags); + write_state_register(xpd, STA_ACTIVATE); + priv->t3 = HFC_TIMER_T3; + } else { + XPD_DBG(SIGNAL, xpd, "HFC_L1_FORCE_DEACTIVATE_TE\n"); + write_state_register(xpd, STA_DEACTIVATE); + } + break; + case XPD_TYPE_BRI_NT: + if(on) { + XPD_DBG(SIGNAL, xpd, "HFC_L1_ACTIVATE_NT\n"); + priv->t1 = TIMER_T1_MAX; + set_bit(HFC_L1_ACTIVATING, &priv->l1_flags); + write_state_register(xpd, STA_ACTIVATE | V_SU_SET_G2_G3); + } else { + XPD_DBG(SIGNAL, xpd, "HFC_L1_DEACTIVATE_NT\n"); + write_state_register(xpd, STA_DEACTIVATE); + } + break; + default: + XPD_ERR(xpd, "%s: Bad xpd type %d\n", __FUNCTION__, xpd->type); + BUG(); + } +} + + +/* + * D-Chan receive + */ +static int rx_dchan(xpd_t *xpd, reg_cmd_t *regcmd) +{ + xbus_t *xbus; + struct BRI_priv_data *priv; + byte *src; + byte *dst; + byte *dchan_buf; + struct zt_chan *dchan; + uint len; + bool eoframe; + int idx; + int ret = 0; + + src = REG_XDATA(regcmd); + len = regcmd->bytes; + eoframe = regcmd->eoframe; + if(len <= 0) + return 0; + if(!SPAN_REGISTERED(xpd)) /* Nowhere to copy data */ + return 0; + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + xbus = xpd->xbus; +#ifdef XPP_DEBUGFS + xbus_log(xbus, xpd, 0, regcmd, sizeof(reg_cmd_t)); /* 0 = RX */ +#endif + dchan = &xpd->span.chans[2]; + if(!IS_SET(xpd->offhook, 2)) { /* D-chan is used? */ + static int rate_limit; + + if((rate_limit++ % 1000) == 0) + XPD_DBG(SIGNAL, xpd, "D-Chan unused\n"); + dchan->bytes2receive = 0; + dchan->bytes2transmit = 0; + goto out; + } + dchan_buf = dchan->readchunk; + idx = priv->dchan_r_idx; + if(idx + len >= DCHAN_BUFSIZE) { + XPD_ERR(xpd, "D-Chan RX overflow: %d\n", idx); + dump_hex_buf(xpd, " current packet", src, len); + dump_hex_buf(xpd, " dchan_buf", dchan_buf, idx); + ret = -ENOSPC; + if(eoframe) + goto drop; + goto out; + } + dst = dchan_buf + idx; + idx += len; + priv->dchan_r_idx = idx; + memcpy(dst, src, len); + if(!eoframe) + goto out; + if(idx < 4) { + XPD_NOTICE(xpd, "D-Chan RX short frame (idx=%d)\n", idx); + dump_hex_buf(xpd, "D-Chan RX: current packet", src, len); + dump_hex_buf(xpd, "D-Chan RX: chan_buf", dchan_buf, idx); + ret = -EPROTO; + goto drop; + } + if(dchan_buf[idx-1]) { + XPD_NOTICE(xpd, "D-Chan RX Bad checksum: [%02X:%02X=%02X] (%d)\n", + dchan_buf[idx-3], dchan_buf[idx-2], dchan_buf[idx-1], dchan_buf[idx-1]); + dump_hex_buf(xpd, "D-Chan RX: current packet", src, len); + dump_hex_buf(xpd, "D-Chan RX: chan_buf", dchan_buf, idx); + ret = -EPROTO; + goto drop; + } + if(print_dbg) + dump_dchan_packet(xpd, 0, dchan_buf, idx /* - 3 */); /* Print checksum? */ + /* + * Tell Zaptel that we received idx-1 bytes. They include the data and a 2-byte checksum. + * The last byte (that we don't pass on) is 0 if the checksum is correct. If it were wrong, + * we would drop the packet in the "if(dchan_buf[idx-1])" above. + */ + dchan->bytes2receive = idx - 1; + dchan->eofrx = 1; + priv->dchan_rx_counter++; + priv->dchan_norx_ticks = 0; +drop: + priv->dchan_r_idx = 0; +out: + return ret; +} + +static int send_bri_multibyte(xpd_t *xpd, byte *buf, int len, bool eoftx) +{ + xbus_t *xbus = xpd->xbus; + xframe_t *xframe; + xpacket_t *pack; + reg_cmd_t *reg_cmd; + int ret; + + BUG_ON(len < 0); + /* + * Zero length multibyte is legal and has special meaning for the + * firmware: + * eoftx==1: Start sending us D-channel packets. + * eoftx==0: Stop sending us D-channel packets. + */ + if(len > MULTIBYTE_MAX_LEN) { + XPD_ERR(xpd, "%s: len=%d is too long. dropping.\n", __FUNCTION__, len); + return -EINVAL; + } + XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx); + reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd); + reg_cmd->bytes = len; + reg_cmd->eoframe = eoftx; + reg_cmd->multibyte = 1; + if(len > 0) { + memcpy(REG_XDATA(reg_cmd), (byte *)buf, len); + } else { + XPD_DBG(REGS, xpd, "Magic Packet (eoftx=%d)\n", eoftx); + } +#ifdef XPP_DEBUGFS + xbus_log(xbus, xpd, 1, reg_cmd, sizeof(reg_cmd_t)); /* 1 = TX */ +#else + if(print_dbg) + dump_xframe("SEND_BRI_MULTI", xbus, xframe); +#endif + ret = send_cmd_frame(xbus, xframe); + if(ret < 0) + XPD_NOTICE(xpd, "%s: failed sending xframe\n", __FUNCTION__); + return ret; +} + +/* + * D-Chan transmit + */ +static int tx_dchan(xpd_t *xpd) +{ + struct BRI_priv_data *priv; + struct zt_chan *dchan; + int len; + int eoframe; + int ret; + + priv = xpd->priv; + BUG_ON(!priv); + if(!IS_NT(xpd)) { + static int rate_limit; + + if (priv->t3 > HFC_TIMER_OFF) { + /* timer expired ? */ + if (--priv->t3 == 0) { + if ((rate_limit % 1003) >= 5) + XPD_DBG(SIGNAL, xpd, "T3 expired\n"); + priv->t3 = HFC_TIMER_OFF; + clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); + xpd_activation(xpd, 0); /* Deactivate TE */ + } + } + if (priv->t4 > HFC_TIMER_OFF) { + /* timer expired ? */ + if (--priv->t4 == 0) { + if ((rate_limit % 1003) >= 5) + XPD_DBG(SIGNAL, xpd, "T4 expired\n"); + priv->t4 = HFC_TIMER_OFF; + } + } + rate_limit++; + } + if(!SPAN_REGISTERED(xpd) || !(xpd->span.flags & ZT_FLAG_RUNNING)) + return 0; + dchan = &xpd->chans[2]; + len = dchan->bytes2transmit; /* dchan's hdlc package len */ + eoframe = dchan->eoftx; /* dchan's end of frame */ + dchan->bytes2transmit = 0; + dchan->eoftx = 0; + dchan->bytes2receive = 0; + dchan->eofrx = 0; + if(len <= 0) + return 0; /* Nothing to transmit on D channel */ + if(len > MULTIBYTE_MAX_LEN) { + XPD_ERR(xpd, "%s: len=%d. need to split. Unimplemented.\n", __FUNCTION__, len); + return -EINVAL; + } + if(!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags) && !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) { + XPD_DBG(SIGNAL, xpd, "Want to transmit: Kick D-Channel transmiter\n"); + xpd_activation(xpd, 1); + return 0; + } + if(print_dbg) + dump_dchan_packet(xpd, 1, priv->dchan_tbuf, len); + if(eoframe) + priv->txframe_begin = 1; + else + priv->txframe_begin = 0; + ret = send_bri_multibyte(xpd, priv->dchan_tbuf, len, eoframe); + if(ret < 0) + XPD_NOTICE(xpd, "%s: failed sending xframe\n", __FUNCTION__); + if(eoframe) + priv->dchan_tx_counter++; + priv->dchan_notx_ticks = 0; + return ret; +} + +/*---------------- BRI: Methods -------------------------------------------*/ + +static xpd_t *BRI_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table, byte subtype, byte revision) +{ + xpd_t *xpd = NULL; + int channels = min(3, CHANNELS_PERXPD); + + XBUS_DBG(GENERAL, xbus, "\n"); + xpd = xpd_alloc(sizeof(struct BRI_priv_data), proto_table, channels); + if(!xpd) + return NULL; + xpd->direction = (proto_table == &PROTO_TABLE(BRI_NT)) ? TO_PHONE : TO_PSTN; + xpd->revision = revision; + xpd->type_name = proto_table->name; + return xpd; +} + +static void clean_proc(xbus_t *xbus, xpd_t *xpd) +{ + struct BRI_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + XPD_DBG(PROC, xpd, "\n"); +#ifdef CONFIG_PROC_FS + if(priv->regfile) { + XPD_DBG(PROC, xpd, "Removing registers file\n"); + priv->regfile->data = NULL; + remove_proc_entry(PROC_REGISTER_FNAME, xpd->proc_xpd_dir); + } + if(priv->bri_info) { + XPD_DBG(PROC, xpd, "Removing xpd BRI_INFO file\n"); + remove_proc_entry(PROC_BRI_INFO_FNAME, xpd->proc_xpd_dir); + } +#endif +} + +static int BRI_card_init(xbus_t *xbus, xpd_t *xpd) +{ + struct BRI_priv_data *priv; + int ret = 0; + + BUG_ON(!xpd); + XPD_DBG(GENERAL, xpd, "\n"); + priv = xpd->priv; +#ifdef CONFIG_PROC_FS + XPD_DBG(PROC, xpd, "Creating BRI_INFO file\n"); + priv->bri_info = create_proc_read_entry(PROC_BRI_INFO_FNAME, 0444, xpd->proc_xpd_dir, proc_bri_info_read, xpd); + if(!priv->bri_info) { + XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_BRI_INFO_FNAME); + ret = -ENOENT; + goto err; + } + priv->bri_info->owner = THIS_MODULE; + XPD_DBG(PROC, xpd, "Creating registers file\n"); + priv->regfile = create_proc_entry(PROC_REGISTER_FNAME, 0644, xpd->proc_xpd_dir); + if(!priv->regfile) { + XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_REGISTER_FNAME); + goto err; + } + priv->regfile->owner = THIS_MODULE; + priv->regfile->write_proc = proc_xpd_register_write; + priv->regfile->read_proc = proc_xpd_register_read; + priv->regfile->data = xpd; +#endif + priv->t1 = HFC_TIMER_OFF; + ret = run_initialize_registers(xpd); + if(ret < 0) + goto err; + XPD_DBG(PROC, xpd, "done\n"); + priv->initialized = 1; + return 0; +err: + clean_proc(xbus, xpd); + XPD_ERR(xpd, "Failed initializing registers (%d)\n", ret); + return ret; +} + +static int BRI_card_remove(xbus_t *xbus, xpd_t *xpd) +{ + struct BRI_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + XPD_DBG(GENERAL, xpd, "\n"); + clean_proc(xbus, xpd); + return 0; +} + +static int BRI_card_zaptel_preregistration(xpd_t *xpd, bool on) +{ + xbus_t *xbus; + struct BRI_priv_data *priv; + xpp_line_t tmp_pcm_mask; + int tmp_pcm_len; + unsigned long flags; + int i; + + BUG_ON(!xpd); + xbus = xpd->xbus; + priv = xpd->priv; + BUG_ON(!xbus); + XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off"); + if(!on) { + /* Nothing to do yet */ + return 0; + } + xpd->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_CCS; + xpd->span.deflaw = ZT_LAW_ALAW; + BIT_SET(xpd->digital_signalling, 2); /* D-Channel */ + for_each_line(xpd, i) { + struct zt_chan *cur_chan = &xpd->chans[i]; + + XPD_DBG(GENERAL, xpd, "setting BRI channel %d\n", i); + snprintf(cur_chan->name, MAX_CHANNAME, "XPP_%s/%02d/%1d%1d/%d", + xpd->xproto->name, xbus->num, + xpd->addr.unit, xpd->addr.subunit, i); + cur_chan->chanpos = i + 1; + cur_chan->pvt = xpd; + if(i == 2) { /* D-CHAN */ + cur_chan->sigcap = BRI_DCHAN_SIGCAP; + cur_chan->flags |= ZT_FLAG_BRIDCHAN; + cur_chan->flags &= ~ZT_FLAG_HDLC; + + /* Setup big buffers for D-Channel rx/tx */ + cur_chan->readchunk = priv->dchan_rbuf; + cur_chan->writechunk = priv->dchan_tbuf; + priv->dchan_r_idx = 0; + priv->txframe_begin = 1; + + cur_chan->maxbytes2transmit = MULTIBYTE_MAX_LEN; + cur_chan->bytes2transmit = 0; + cur_chan->bytes2receive = 0; + } else + cur_chan->sigcap = BRI_BCHAN_SIGCAP; + } + xpd->offhook = BIT(0) | BIT(1); /* 2*bchan */ + + /* + * Compute PCM lentgh and mask + * We know all cards have been initialized until now + */ + tmp_pcm_mask = 0; + if(xpd->addr.subunit == 0) { + int line_count = 0; + + for(i = 0; i < MAX_SUBUNIT; i++) { + xpd_t *sub_xpd = xpd_byaddr(xbus, xpd->addr.unit, i); + if(sub_xpd) { + tmp_pcm_mask |= PCM_SHIFT(sub_xpd->wanted_pcm_mask, i); + line_count += 2; + } + } + tmp_pcm_len = RPACKET_HEADERSIZE + sizeof(xpp_line_t) + line_count * ZT_CHUNKSIZE; + } else + tmp_pcm_len = 0; + spin_lock_irqsave(&xpd->lock, flags); + xpd->pcm_len = tmp_pcm_len; + xpd->wanted_pcm_mask = xpd->offhook; + priv->card_pcm_mask = tmp_pcm_mask; + xpd->span.spanconfig = bri_spanconfig; + xpd->span.chanconfig = bri_chanconfig; + xpd->span.startup = bri_startup; + xpd->span.shutdown = bri_shutdown; + spin_unlock_irqrestore(&xpd->lock, flags); + return 0; +} + +static int BRI_card_zaptel_postregistration(xpd_t *xpd, bool on) +{ + xbus_t *xbus; + struct BRI_priv_data *priv; + + BUG_ON(!xpd); + xbus = xpd->xbus; + priv = xpd->priv; + BUG_ON(!xbus); + XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off"); + return(0); +} + +static int BRI_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig) +{ + LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig)); + return 0; +} + +/* + * LED managment is done by the driver now: + * - Turn constant ON RED/GREEN led to indicate NT/TE port + * - Very fast "Double Blink" to indicate Layer1 alive (without D-Channel) + * - Constant blink (1/2 sec cycle) to indicate D-Channel alive. + */ +static void handle_leds(xbus_t *xbus, xpd_t *xpd) +{ + struct BRI_priv_data *priv; + unsigned int timer_count; + int which_led; + int other_led; + int mod; + + BUG_ON(!xpd); + if(IS_NT(xpd)) { + which_led = RED_LED; + other_led = GREEN_LED; + } else { + which_led = GREEN_LED; + other_led = RED_LED; + } + priv = xpd->priv; + BUG_ON(!priv); + timer_count = xpd->timer_count; + if(xpd->blink_mode) { + if((timer_count % DEFAULT_LED_PERIOD) == 0) { + // led state is toggled + if(priv->ledstate[which_led] == BRI_LED_OFF) { + DO_LED(xpd, which_led, BRI_LED_ON); + DO_LED(xpd, other_led, BRI_LED_ON); + } else { + DO_LED(xpd, which_led, BRI_LED_OFF); + DO_LED(xpd, other_led, BRI_LED_OFF); + } + } + return; + } + if(priv->ledstate[other_led] != BRI_LED_OFF) + DO_LED(xpd, other_led, BRI_LED_OFF); + if(priv->dchan_alive) { + mod = timer_count % 1000; + switch(mod) { + case 0: + DO_LED(xpd, which_led, BRI_LED_ON); + break; + case 500: + DO_LED(xpd, which_led, BRI_LED_OFF); + break; + } + } else if(priv->layer1_up) { + mod = timer_count % 1000; + switch(mod) { + case 0: + case 100: + DO_LED(xpd, which_led, BRI_LED_ON); + break; + case 50: + case 150: + DO_LED(xpd, which_led, BRI_LED_OFF); + break; + } + } else { + if(priv->ledstate[which_led] != BRI_LED_ON) + DO_LED(xpd, which_led, BRI_LED_ON); + } +} + +/* Poll the register ST/Up-State-machine Register, to see if the cable + * if a cable is connected to the port. + */ +static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd) +{ + struct BRI_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + if(!priv->initialized || !xbus->self_ticking) + return 0; + if(poll_interval != 0 && (priv->tick_counter % poll_interval) == 0) { + // XPD_DBG(GENERAL, xpd, "%d\n", priv->tick_counter); + priv->poll_counter++; + xpp_register_request(xbus, xpd, 0, 0, 0, A_SU_RD_STA, 0, 0, 0); + + if(IS_NT(xpd) && nt_keepalive && + !test_bit(HFC_L1_ACTIVATED, &priv->l1_flags) && + !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) { + XPD_DBG(SIGNAL, xpd, "Kick NT D-Channel\n"); + xpd_activation(xpd, 1); + } + } + /* Detect D-Channel disconnect heuristic */ + priv->dchan_notx_ticks++; + priv->dchan_norx_ticks++; + priv->dchan_alive_ticks++; + if(priv->dchan_alive && (priv->dchan_notx_ticks > DCHAN_LOST || priv->dchan_norx_ticks > DCHAN_LOST)) { + /* + * No tx_dchan() or rx_dchan() for many ticks + * This D-Channel is probabelly dead. + */ + dchan_state(xpd, 0); + } else if(priv->dchan_rx_counter > 1 && priv->dchan_tx_counter > 1) { + if(!priv->dchan_alive) + dchan_state(xpd, 1); + } + /* Detect Layer1 disconnect */ + if(priv->reg30_good && priv->reg30_ticks > poll_interval * REG30_LOST) { + /* No reply for 1/2 a second */ + XPD_ERR(xpd, "Lost state tracking for %d ticks\n", priv->reg30_ticks); + priv->reg30_good = 0; + layer1_state(xpd, 0); + dchan_state(xpd, 0); + } + handle_leds(xbus, xpd); + tx_dchan(xpd); + /* Detect T1 timer expiry on NT */ + if(IS_NT(xpd) && !nt_keepalive) { + if (priv->t1 > HFC_TIMER_OFF) { + if (--priv->t1 == 0) { + XPD_DBG(SIGNAL, xpd, "T1 Expired. Deactivate NT\n"); + priv->t1 = HFC_TIMER_OFF; + clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); + write_state_register(xpd, STA_DEACTIVATE); + } + } + } + priv->tick_counter++; + priv->reg30_ticks++; + return 0; +} + +static int BRI_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg) +{ + BUG_ON(!xpd); + if(!TRANSPORT_RUNNING(xpd->xbus)) + return -ENODEV; + switch (cmd) { + case ZT_TONEDETECT: + /* + * Asterisk call all span types with this (FXS specific) + * call. Silently ignore it. + */ + LINE_DBG(SIGNAL, xpd, pos, "BRI: Starting a call\n"); + return -ENOTTY; + default: + report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd); + return -ENOTTY; + } + return 0; +} + +static int BRI_card_close(xpd_t *xpd, lineno_t pos) +{ + struct zt_chan *chan = &xpd->span.chans[pos]; + + /* Clear D-Channel pending data */ + chan->bytes2receive = 0; + chan->eofrx = 0; + chan->bytes2transmit = 0; + chan->eoftx = 0; + return 0; +} + +/* + * Called only for 'span' keyword in /etc/zaptel.conf + */ +static int bri_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) +{ + xpd_t *xpd = span->pvt; + const char *framingstr = ""; + const char *codingstr = ""; + const char *crcstr = ""; + + /* framing first */ + if (lc->lineconfig & ZT_CONFIG_B8ZS) + framingstr = "B8ZS"; + else if (lc->lineconfig & ZT_CONFIG_AMI) + framingstr = "AMI"; + else if (lc->lineconfig & ZT_CONFIG_HDB3) + framingstr = "HDB3"; + /* then coding */ + if (lc->lineconfig & ZT_CONFIG_ESF) + codingstr = "ESF"; + else if (lc->lineconfig & ZT_CONFIG_D4) + codingstr = "D4"; + else if (lc->lineconfig & ZT_CONFIG_CCS) + codingstr = "CCS"; + /* E1's can enable CRC checking */ + if (lc->lineconfig & ZT_CONFIG_CRC4) + crcstr = "CRC4"; + XPD_DBG(GENERAL, xpd, "[%s]: span=%d (%s) lbo=%d lineconfig=%s/%s/%s (0x%X) sync=%d\n", + IS_NT(xpd)?"NT":"TE", + lc->span, + lc->name, + lc->lbo, + framingstr, codingstr, crcstr, + lc->lineconfig, + lc->sync); + /* + * FIXME: validate + */ + span->lineconfig = lc->lineconfig; + return 0; +} + +/* + * Set signalling type (if appropriate) + * Called from zaptel with spinlock held on chan. Must not call back + * zaptel functions. + */ +static int bri_chanconfig(struct zt_chan *chan, int sigtype) +{ + DBG(GENERAL, "channel %d (%s) -> %s\n", chan->channo, chan->name, sig2str(sigtype)); + // FIXME: sanity checks: + // - should be supported (within the sigcap) + // - should not replace fxs <->fxo ??? (covered by previous?) + return 0; +} + +/* + * Called only for 'span' keyword in /etc/zaptel.conf + */ +static int bri_startup(struct zt_span *span) +{ + xpd_t *xpd = span->pvt; + struct BRI_priv_data *priv; + struct zt_chan *dchan; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + if(!TRANSPORT_RUNNING(xpd->xbus)) { + XPD_DBG(GENERAL, xpd, "Startup called by zaptel. No Hardware. Ignored\n"); + return -ENODEV; + } + XPD_DBG(GENERAL, xpd, "STARTUP\n"); + // Turn on all channels + CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 1); + write_state_register(xpd, 0); /* Enable L1 state machine */ + xpd_activation(xpd, 1); + if(SPAN_REGISTERED(xpd)) { + dchan = &span->chans[2]; + span->flags |= ZT_FLAG_RUNNING; + /* + * Zaptel (wrongly) assume that D-Channel need HDLC decoding + * and during zaptel registration override our flags. + * + * Don't Get Mad, Get Even: Now we override zaptel :-) + */ + dchan->flags |= ZT_FLAG_BRIDCHAN; + dchan->flags &= ~ZT_FLAG_HDLC; + } + return 0; +} + +/* + * Called only for 'span' keyword in /etc/zaptel.conf + */ +static int bri_shutdown(struct zt_span *span) +{ + xpd_t *xpd = span->pvt; + struct BRI_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + if(!TRANSPORT_RUNNING(xpd->xbus)) { + XPD_DBG(GENERAL, xpd, "Shutdown called by zaptel. No Hardware. Ignored\n"); + return -ENODEV; + } + XPD_DBG(GENERAL, xpd, "SHUTDOWN\n"); + // Turn off all channels + CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 0); + if(IS_NT(xpd)) + xpd_activation(xpd, 0); + return 0; +} + +static void BRI_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpp_line_t wanted_lines, xpacket_t *pack) +{ + byte *pcm; + struct zt_chan *chans; + unsigned long flags; + int i; + int subunit; + xpp_line_t pcm_mask = 0; + + + BUG_ON(!xbus); + BUG_ON(!xpd); + BUG_ON(!pack); + pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm); + for(subunit = 0; subunit < MAX_SUBUNIT; subunit++) { + xpd_t *tmp_xpd; + + tmp_xpd = xpd_byaddr(xbus, xpd->addr.unit, subunit); + if(!tmp_xpd || !tmp_xpd->card_present) + continue; + spin_lock_irqsave(&tmp_xpd->lock, flags); + chans = tmp_xpd->span.chans; + for_each_line(tmp_xpd, i) { + if(IS_SET(wanted_lines, i)) { + if(SPAN_REGISTERED(tmp_xpd)) { +#ifdef DEBUG_PCMTX + if(pcmtx >= 0 && pcmtx_chan == i) + memset((u_char *)pcm, pcmtx, ZT_CHUNKSIZE); + else +#endif + memcpy((u_char *)pcm, chans[i].writechunk, ZT_CHUNKSIZE); + // fill_beep((u_char *)pcm, tmp_xpd->addr.subunit, 2); + } else + memset((u_char *)pcm, 0x7F, ZT_CHUNKSIZE); + pcm += ZT_CHUNKSIZE; + } + } + pcm_mask |= PCM_SHIFT(wanted_lines, subunit); + XPD_COUNTER(tmp_xpd, PCM_WRITE)++; + spin_unlock_irqrestore(&tmp_xpd->lock, flags); + } + RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = pcm_mask; +} + +static void BRI_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack) +{ + byte *pcm; + xpp_line_t pcm_mask; + unsigned long flags; + int subunit; + int i; + + /* + * Subunit 0 handle all other subunits + */ + if(xpd->addr.subunit != 0) + return; + if(!SPAN_REGISTERED(xpd)) + return; + pcm = RPACKET_FIELD(pack, GLOBAL, PCM_READ, pcm); + pcm_mask = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines); + for(subunit = 0; subunit < MAX_SUBUNIT; subunit++, pcm_mask >>= SUBUNIT_PCM_SHIFT) { + xpd_t *tmp_xpd; + + if(!pcm_mask) + break; /* optimize */ + tmp_xpd = xpd_byaddr(xbus, xpd->addr.unit, subunit); + if(!tmp_xpd || !tmp_xpd->card_present || !SPAN_REGISTERED(tmp_xpd)) + continue; + spin_lock_irqsave(&tmp_xpd->lock, flags); + for (i = 0; i < 2; i++) { + xpp_line_t tmp_mask = pcm_mask & (BIT(0) | BIT(1)); + volatile u_char *r; + + if(IS_SET(tmp_mask, i)) { + r = tmp_xpd->span.chans[i].readchunk; + // memset((u_char *)r, 0x5A, ZT_CHUNKSIZE); // DEBUG + // fill_beep((u_char *)r, 1, 1); // DEBUG: BEEP + memcpy((u_char *)r, pcm, ZT_CHUNKSIZE); + pcm += ZT_CHUNKSIZE; + } + } + XPD_COUNTER(tmp_xpd, PCM_READ)++; + spin_unlock_irqrestore(&tmp_xpd->lock, flags); + } +} + +/*---------------- BRI: HOST COMMANDS -------------------------------------*/ + +static /* 0x0F */ HOSTCMD(BRI, XPD_STATE, bool on) +{ + BUG_ON(!xpd); + XPD_DBG(GENERAL, xpd, "%s\n", (on)?"ON":"OFF"); + xpd_activation(xpd, on); + return 0; +} + +static /* 0x0F */ HOSTCMD(BRI, RING, lineno_t chan, bool on) +{ + XPD_ERR(xpd, "%s: Unsupported\n", __FUNCTION__); + return -ENOSYS; +} + +static /* 0x0F */ HOSTCMD(BRI, RELAY_OUT, byte which, bool on) +{ + XPD_ERR(xpd, "%s: Unsupported\n", __FUNCTION__); + return -ENOSYS; +} + +static /* 0x33 */ HOSTCMD(BRI, SET_LED, enum bri_led_names which_led, enum led_state to_led_state) +{ + int ret = 0; + xframe_t *xframe; + xpacket_t *pack; + struct bri_leds *bri_leds; + struct BRI_priv_data *priv; + + BUG_ON(!xbus); + priv = xpd->priv; + BUG_ON(!priv); + XPD_DBG(LEDS, xpd, "%s -> %d\n", + (which_led)?"RED":"GREEN", + to_led_state); + XFRAME_NEW_CMD(xframe, pack, xbus, BRI, SET_LED, xpd->xbus_idx); + bri_leds = &RPACKET_FIELD(pack, BRI, SET_LED, bri_leds); + bri_leds->state = to_led_state; + bri_leds->led_sel = which_led; + XPACKET_LEN(pack) = RPACKET_SIZE(BRI, SET_LED); + ret = send_cmd_frame(xbus, xframe); + priv->ledstate[which_led] = to_led_state; + return ret; +} + +static int write_state_register(xpd_t *xpd, byte value) +{ + int ret; + + XPD_DBG(REGS, xpd, "value = 0x%02X\n", value); + ret = xpp_register_request(xpd->xbus, xpd, + 0, /* chipsel */ + 1, /* writing */ + 0, /* do_subreg */ + A_SU_WR_STA, /* regnum */ + 0, /* subreg */ + value, /* data_low */ + 0 /* data_high */ + ); + return ret; +} + +/*---------------- BRI: Astribank Reply Handlers --------------------------*/ +static void su_new_state(xpd_t *xpd, byte reg_x30) +{ + xbus_t *xbus; + struct BRI_priv_data *priv; + su_rd_sta_t new_state; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + xbus = xpd->xbus; + if(!priv->initialized) { + XPD_ERR(xpd, "%s called on uninitialized AB\n", __FUNCTION__); + return; + } + new_state.reg = reg_x30; + priv->reg30_ticks = 0; + priv->reg30_good = 1; + if((!IS_NT(xpd) && new_state.bits.v_su_sta == ST_TE_ACTIVATED) || + (IS_NT(xpd) && new_state.bits.v_su_sta == ST_NT_ACTIVATED)) { + if(!priv->layer1_up) { + layer1_state(xpd, 1); + update_xpd_status(xpd, ZT_ALARM_NONE); + } + } else { + /* + * Layer 1 disconnected + */ + if(priv->layer1_up) { + layer1_state(xpd, 0); + dchan_state(xpd, 0); + } + /* + * Do NOT notify Zaptel about the disconnection. + * If we do, Asterisk stops transmitting on the D-channel and + * we can't reactivate layer-1. + * Without the notification, Asterisk thinks that we are active + * (although the PSTN stopped layer-1) and on call setup, sends + * us D-channel data, which triggers the layer-1 activation. + */ +#if 0 + update_xpd_status(xpd, ZT_ALARM_RED); +#endif + } + if (priv->state_register.bits.v_su_sta == new_state.bits.v_su_sta) + return; /* same same */ + DBG(SIGNAL, "%02X ---> %02X\n", priv->state_register.reg, reg_x30); + XPD_DBG(SIGNAL, xpd, "%s%i\n", IS_NT(xpd)?"G":"F", new_state.bits.v_su_sta); + + if(!IS_NT(xpd)) { + /* disable T3 ? */ + if ((new_state.bits.v_su_sta <= ST_TE_DEACTIVATED) || (new_state.bits.v_su_sta >= ST_TE_ACTIVATED)) { + XPD_DBG(SIGNAL, xpd, "Disable T3 ?\n"); + priv->t3 = HFC_TIMER_OFF; + } + switch (new_state.bits.v_su_sta) { + case ST_TE_DEACTIVATED: /* F3 */ + XPD_DBG(SIGNAL, xpd, "State ST_TE_DEACTIVATED (F3)\n"); + if (test_and_clear_bit(HFC_L1_ACTIVATED, &priv->l1_flags)) + priv->t4 = HFC_TIMER_T4; + break; + case ST_TE_SIGWAIT: /* F4 */ + XPD_DBG(SIGNAL, xpd, "State ST_TE_SIGWAIT (F4)\n"); + break; + case ST_TE_IDENT: /* F5 */ + XPD_DBG(SIGNAL, xpd, "State ST_TE_IDENT (F5)\n"); + break; + case ST_TE_SYNCED: /* F6 */ + XPD_DBG(SIGNAL, xpd, "State ST_TE_SYNCED (F6)\n"); + break; + case ST_TE_ACTIVATED: /* F7 */ + XPD_DBG(SIGNAL, xpd, "State ST_TE_ACTIVATED (F7)\n"); + if (priv->t4 > HFC_TIMER_OFF) + priv->t4 = HFC_TIMER_OFF; + clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); + set_bit(HFC_L1_ACTIVATED, &priv->l1_flags); + update_xpd_status(xpd, ZT_ALARM_NONE); + break; + + case ST_TE_LOST_FRAMING: /* F8 */ + XPD_DBG(SIGNAL, xpd, "State ST_TE_LOST_FRAMING (F8)\n"); + priv->t4 = HFC_TIMER_OFF; + break; + default: + XPD_NOTICE(xpd, "Bad TE state: %d\n", new_state.bits.v_su_sta); + break; + } + + } else if(IS_NT(xpd)) { + switch (new_state.bits.v_su_sta) { + case ST_NT_DEACTIVATED: /* G1 */ + XPD_DBG(SIGNAL, xpd, "State ST_NT_DEACTIVATED (G1)\n"); + clear_bit(HFC_L1_ACTIVATED, &priv->l1_flags); + priv->t1 = HFC_TIMER_OFF; + break; + case ST_NT_ACTIVATING: /* G2 */ + XPD_DBG(SIGNAL, xpd, "State ST_NT_ACTIVATING (G2)\n"); + xpd_activation(xpd, 1); + break; + case ST_NT_ACTIVATED: /* G3 */ + XPD_DBG(SIGNAL, xpd, "State ST_NT_ACTIVATED (G3)\n"); + clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); + set_bit(HFC_L1_ACTIVATED, &priv->l1_flags); + priv->t1 = HFC_TIMER_OFF; + break; + case ST_NT_DEACTIVTING: /* G4 */ + XPD_DBG(SIGNAL, xpd, "State ST_NT_DEACTIVTING (G4)\n"); + priv->t1 = HFC_TIMER_OFF; + break; + default: + XPD_NOTICE(xpd, "Bad NT state: %d\n", new_state.bits.v_su_sta); + break; + } + } else + XPD_ERR(xpd, "%s: Unknown xpd type %d\n", __FUNCTION__, xpd->type); + priv->state_register.reg = new_state.reg; +} + +static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) +{ + unsigned long flags; + struct BRI_priv_data *priv; + int ret; + + spin_lock_irqsave(&xpd->lock, flags); + priv = xpd->priv; + BUG_ON(!priv); + if(REG_FIELD(info, do_subreg)) { + XPD_DBG(REGS, xpd, "RS %02X %02X %02X\n", + REG_FIELD(info, regnum), REG_FIELD(info, subreg), REG_FIELD(info, data_low)); + } else { + if (REG_FIELD(info, regnum) != A_SU_RD_STA) + XPD_DBG(REGS, xpd, "RD %02X %02X\n", + REG_FIELD(info, regnum), REG_FIELD(info, data_low)); + } + if(info->multibyte) { + XPD_DBG(REGS, xpd, "Got Multibyte: %d bytes, eoframe: %d\n", + info->bytes, info->eoframe); + ret = rx_dchan(xpd, info); + if (ret < 0) { + priv->dchan_rx_drops++; + if(atomic_read(&xpd->open_counter) > 0) + XPD_NOTICE(xpd, "Multibyte Drop: errno=%d\n", ret); + } + goto end; + } + if(REG_FIELD(info, regnum) == A_SU_RD_STA) { + su_new_state(xpd, REG_FIELD(info, data_low)); + } + + /* Update /proc info only if reply relate to the last slic read request */ + if( + REG_FIELD(&priv->requested_reply, regnum) == REG_FIELD(info, regnum) && + REG_FIELD(&priv->requested_reply, do_subreg) == REG_FIELD(info, do_subreg) && + REG_FIELD(&priv->requested_reply, subreg) == REG_FIELD(info, subreg)) { + priv->last_reply = *info; + } + +end: + spin_unlock_irqrestore(&xpd->lock, flags); + return 0; +} + +static xproto_table_t PROTO_TABLE(BRI_NT) = { + .owner = THIS_MODULE, + .entries = { + /* Table Card Opcode */ + }, + .name = "BRI_NT", + .type = XPD_TYPE_BRI_NT, + .xops = { + .card_new = BRI_card_new, + .card_init = BRI_card_init, + .card_remove = BRI_card_remove, + .card_zaptel_preregistration = BRI_card_zaptel_preregistration, + .card_zaptel_postregistration = BRI_card_zaptel_postregistration, + .card_hooksig = BRI_card_hooksig, + .card_tick = BRI_card_tick, + .card_pcm_fromspan = BRI_card_pcm_fromspan, + .card_pcm_tospan = BRI_card_pcm_tospan, + .card_ioctl = BRI_card_ioctl, + .card_close = BRI_card_close, + .card_register_reply = BRI_card_register_reply, + + .RING = XPROTO_CALLER(BRI, RING), + .RELAY_OUT = XPROTO_CALLER(BRI, RELAY_OUT), + .XPD_STATE = XPROTO_CALLER(BRI, XPD_STATE), + }, + .packet_is_valid = bri_packet_is_valid, + .packet_dump = bri_packet_dump, +}; + +static xproto_table_t PROTO_TABLE(BRI_TE) = { + .owner = THIS_MODULE, + .entries = { + /* Table Card Opcode */ + }, + .name = "BRI_TE", + .type = XPD_TYPE_BRI_TE, + .xops = { + .card_new = BRI_card_new, + .card_init = BRI_card_init, + .card_remove = BRI_card_remove, + .card_zaptel_preregistration = BRI_card_zaptel_preregistration, + .card_zaptel_postregistration = BRI_card_zaptel_postregistration, + .card_hooksig = BRI_card_hooksig, + .card_tick = BRI_card_tick, + .card_pcm_fromspan = BRI_card_pcm_fromspan, + .card_pcm_tospan = BRI_card_pcm_tospan, + .card_ioctl = BRI_card_ioctl, + .card_close = BRI_card_close, + .card_register_reply = BRI_card_register_reply, + + .RING = XPROTO_CALLER(BRI, RING), + .RELAY_OUT = XPROTO_CALLER(BRI, RELAY_OUT), + .XPD_STATE = XPROTO_CALLER(BRI, XPD_STATE), + }, + .packet_is_valid = bri_packet_is_valid, + .packet_dump = bri_packet_dump, +}; + +static bool bri_packet_is_valid(xpacket_t *pack) +{ + const xproto_entry_t *xe_nt = NULL; + const xproto_entry_t *xe_te = NULL; + // DBG(GENERAL, "\n"); + xe_nt = xproto_card_entry(&PROTO_TABLE(BRI_NT), XPACKET_OP(pack)); + xe_te = xproto_card_entry(&PROTO_TABLE(BRI_TE), XPACKET_OP(pack)); + return xe_nt != NULL || xe_te != NULL; +} + +static void bri_packet_dump(const char *msg, xpacket_t *pack) +{ + DBG(GENERAL, "%s\n", msg); +} +/*------------------------- REGISTER Handling --------------------------*/ + +static int proc_bri_info_read(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + unsigned long flags; + xpd_t *xpd = data; + struct BRI_priv_data *priv; + + DBG(PROC, "\n"); + if(!xpd) + return -ENODEV; + spin_lock_irqsave(&xpd->lock, flags); + priv = xpd->priv; + BUG_ON(!priv); + len += sprintf(page + len, "%05d Layer 1: ", priv->poll_counter); + if(priv->reg30_good) { + len += sprintf(page + len, "%-5s ", (priv->layer1_up) ? "UP" : "DOWN"); + len += sprintf(page + len, "%c%d %-15s -- fr_sync=%d t2_exp=%d info0=%d g2_g3=%d\n", + IS_NT(xpd)?'G':'F', + priv->state_register.bits.v_su_sta, + xhfc_state_name(xpd->type, priv->state_register.bits.v_su_sta), + priv->state_register.bits.v_su_fr_sync, + priv->state_register.bits.v_su_t2_exp, + priv->state_register.bits.v_su_info0, + priv->state_register.bits.v_g2_g3); + } else + len += sprintf(page + len, "Unkown\n"); + if(IS_NT(xpd)) + len += sprintf(page + len, "T1 Timer: %d\n", priv->t1); + len += sprintf(page + len, "Tick Counter: %d\n", priv->tick_counter); + len += sprintf(page + len, "Last Poll Reply: %d ticks ago\n", priv->reg30_ticks); + len += sprintf(page + len, "reg30_good=%d\n", priv->reg30_good); + len += sprintf(page + len, "D-Channel: TX=[%5d] RX=[%5d] BAD=[%5d] ", + priv->dchan_tx_counter, priv->dchan_rx_counter, priv->dchan_rx_drops); + if(priv->dchan_alive) { + len += sprintf(page + len, "(alive %d K-ticks)\n", + priv->dchan_alive_ticks/1000); + } else { + len += sprintf(page + len, "(dead)\n"); + } + len += sprintf(page + len, "dchan_notx_ticks: %d\n", priv->dchan_notx_ticks); + len += sprintf(page + len, "dchan_norx_ticks: %d\n", priv->dchan_norx_ticks); + len += sprintf(page + len, "LED: %-10s = %d\n", "GREEN", priv->ledstate[GREEN_LED]); + len += sprintf(page + len, "LED: %-10s = %d\n", "RED", priv->ledstate[RED_LED]); + len += sprintf(page + len, "\nDCHAN:\n"); + len += sprintf(page + len, "\n"); + spin_unlock_irqrestore(&xpd->lock, flags); + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; +} + +/* + * + * Direct/Indirect + * | + * | Reg# + * | | + * | | Data (only in Write) + * | | | + * | | +-+-+ + * v v v v + * FF WD 06 01 05 + * ^ ^ + * | | + * | Write/Read + * | + * Chan# + * + */ +static int handle_register_command(xpd_t *xpd, char *cmdline) +{ + unsigned chipsel; + unsigned data = 0; + unsigned xdata1 = 0; + unsigned xdata2 = 0; + char op; /* [W]rite, [R]ead */ + char reg_type; /* [D]irect, [S]ubregister */ + int reg_num; + int subreg; + int elements; + bool writing; + char *p; + reg_cmd_t regcmd; + xbus_t *xbus; + int ret = -EINVAL; + struct BRI_priv_data *priv; + byte buf[MAX_PROC_WRITE]; + + BUG_ON(!xpd); + xbus = xpd->xbus; + BUG_ON(!xbus); + priv = xpd->priv; + BUG_ON(!priv); + if((p = strchr(cmdline, '#')) != NULL) /* Truncate comments */ + *p = '\0'; + if((p = strchr(cmdline, ';')) != NULL) /* Truncate comments */ + *p = '\0'; + for(p = cmdline; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */ + ; + if(*p == '\0') + return 0; + + if(!XBUS_GET(xbus)) { + XBUS_DBG(GENERAL, xbus, "Dropped packet. Is shutting down.\n"); + return -EBUSY; + } + memset(buf, 0, MAX_PROC_WRITE); + elements = sscanf(cmdline, "%d %c%c %x %x %x %x %x", + &chipsel, + &op, ®_type, ®_num, + &subreg, + &data, &xdata1, &xdata2); + XPD_DBG(PROC, xpd, "'%s': %d %c%c %02X %02X %02X\n", cmdline, chipsel, op, reg_type, reg_num, subreg, data); + if(elements < 3) { // At least: chipsel, op, reg_type, reg_num + ERR("Not enough arguments: (%d args) '%s'\n", elements, cmdline); + goto out; + } + if(!VALID_CHIPSEL(chipsel)) { + ERR("Bad chip select number: %d\n", chipsel); + goto out; + } + REG_FIELD(®cmd, chipsel) = chipsel; + switch(op) { + case 'W': + writing = 1; + break; + case 'R': + writing = 0; + break; + default: + ERR("Unkown operation type '%c'\n", op); + goto out; + } + if( + (op == 'W' && reg_type == 'D' && elements != 5) || + (op == 'W' && reg_type == 'S' && elements != 6) || + (op == 'R' && reg_type == 'D' && elements != 4) || + (op == 'R' && reg_type == 'S' && elements != 4) + ) { + ERR("Bad number of elements: '%s' (%d elements): %d %c%c %02X %02X %02X\n", + cmdline, elements, + chipsel, op, reg_type, reg_num, subreg, data); + goto out; + } + switch(reg_type) { + case 'S': + REG_FIELD(®cmd, do_subreg) = 1; + REG_FIELD(®cmd, regnum) = reg_num; + REG_FIELD(®cmd, subreg) = subreg; + REG_FIELD(®cmd, data_low) = data; + break; + case 'D': + REG_FIELD(®cmd, do_subreg) = 0; + REG_FIELD(®cmd, regnum) = reg_num; + REG_FIELD(®cmd, subreg) = 0; + REG_FIELD(®cmd, data_low) = subreg; + break; + case 'M': /* Multi without eoftx */ + case 'm': /* Multi with eoftx */ + if(!writing) { + ERR("Read multibyte is not implemented\n"); + goto out; + } + elements -= 3; + REG_XDATA(®cmd)[0] = reg_num; + REG_XDATA(®cmd)[1] = subreg; + REG_XDATA(®cmd)[2] = data; + REG_XDATA(®cmd)[3] = xdata1; + REG_XDATA(®cmd)[4] = xdata2; + ret = send_bri_multibyte(xpd, REG_XDATA(®cmd), elements, (reg_type == 'm')); + goto out; + default: + ERR("Unkown register type '%c'\n", reg_type); + goto out; + } + regcmd.bytes = sizeof(regcmd) - 1; + REG_FIELD(®cmd, read_request) = writing; + REG_FIELD(®cmd, data_high) = 0; + priv->requested_reply = regcmd; + if(print_dbg) + dump_reg_cmd("BRI", ®cmd, 1); + ret = xpp_register_request(xpd->xbus, xpd, + REG_FIELD(®cmd, chipsel), + writing, + REG_FIELD(®cmd, do_subreg), + REG_FIELD(®cmd, regnum), + REG_FIELD(®cmd, subreg), + REG_FIELD(®cmd, data_low), + REG_FIELD(®cmd, data_high)); +out: + XBUS_PUT(xbus); + return ret; +} + +static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data) +{ + xpd_t *xpd = data; + char buf[MAX_PROC_WRITE]; + char *p; + int i; + int ret; + + if(!xpd) + return -ENODEV; + for(i = 0; i < count; /* noop */) { + for(p = buf; p < buf + MAX_PROC_WRITE; p++) { /* read a line */ + if(i >= count) + break; + if(get_user(*p, buffer + i)) + return -EFAULT; + i++; + if(*p == '\n' || *p == '\r') /* whatever */ + break; + } + if(p >= buf + MAX_PROC_WRITE) + return -E2BIG; + *p = '\0'; + ret = handle_register_command(xpd, buf); + if(ret < 0) + return ret; + msleep(1); + } + return count; +} + + +static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + unsigned long flags; + xpd_t *xpd = data; + reg_cmd_t *info; + struct BRI_priv_data *priv; + + if(!xpd) + return -ENODEV; + priv = xpd->priv; + BUG_ON(!priv); + spin_lock_irqsave(&xpd->lock, flags); + info = &priv->last_reply; + len += sprintf(page + len, "# Writing bad data into this file may damage your hardware!\n"); + len += sprintf(page + len, "# Consult firmware docs first\n"); + len += sprintf(page + len, "#\n"); + if(REG_FIELD(info, do_subreg)) { + len += sprintf(page + len, "#CH\tOP\tReg.\tSub\tDL\n"); + len += sprintf(page + len, "%2d\tRS\t%02X\t%02X\t%02X\n", + REG_FIELD(info, chipsel), + REG_FIELD(info, regnum), REG_FIELD(info, subreg), REG_FIELD(info, data_low)); + } else { + len += sprintf(page + len, "#CH\tOP\tReg.\tDL\n"); + len += sprintf(page + len, "%2d\tRD\t%02X\t%02X\n", + REG_FIELD(info, chipsel), + REG_FIELD(info, regnum), REG_FIELD(info, data_low)); + } + spin_unlock_irqrestore(&xpd->lock, flags); + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; +} + +int __init card_bri_startup(void) +{ + DBG(GENERAL, "\n"); + + INFO("revision %s\n", XPP_VERSION); + xproto_register(&PROTO_TABLE(BRI_NT)); + xproto_register(&PROTO_TABLE(BRI_TE)); + return 0; +} + +void __exit card_bri_cleanup(void) +{ + DBG(GENERAL, "\n"); + xproto_unregister(&PROTO_TABLE(BRI_NT)); + xproto_unregister(&PROTO_TABLE(BRI_TE)); +} + +MODULE_DESCRIPTION("XPP BRI Card Driver"); +MODULE_AUTHOR("Oron Peled "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(XPP_VERSION); +MODULE_ALIAS_XPD(XPD_TYPE_BRI_NT); +MODULE_ALIAS_XPD(XPD_TYPE_BRI_TE); + +module_init(card_bri_startup); +module_exit(card_bri_cleanup); diff --git a/kernel/xpp/card_bri.h b/kernel/xpp/card_bri.h new file mode 100644 index 0000000..a7b69de --- /dev/null +++ b/kernel/xpp/card_bri.h @@ -0,0 +1,31 @@ +#ifndef CARD_BRI_H +#define CARD_BRI_H +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "xpd.h" + +enum bri_opcodes { + XPROTO_NAME(BRI, SET_LED) = 0x33, +}; + +#endif /* CARD_BRI_H */ diff --git a/kernel/xpp/card_fxo.c b/kernel/xpp/card_fxo.c new file mode 100644 index 0000000..cbe953b --- /dev/null +++ b/kernel/xpp/card_fxo.c @@ -0,0 +1,1218 @@ +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include "xpd.h" +#include "xproto.h" +#include "xpp_zap.h" +#include "card_fxo.h" +#include "zap_debug.h" +#include "xbus-core.h" + +static const char rcsid[] = "$Id$"; + +DEF_PARM(int, print_dbg, 0, 0644, "Print DBG statements"); +DEF_PARM(uint, poll_battery_interval, 500, 0644, "Poll battery interval in milliseconds (0 - disable)"); +DEF_PARM(uint, poll_power_denial_interval, 40, 0644, "Power denial detection poll interval in milliseconds (0 - disable)"); +#ifdef WITH_METERING +DEF_PARM(uint, poll_metering_interval, 500, 0644, "Poll metering interval in milliseconds (0 - disable)"); +#endif +DEF_PARM(int, ring_debounce, 50, 0644, "Number of ticks to debounce a false RING indication"); + +/* Signaling is opposite (fxs signalling for fxo card) */ +#if 1 +#define FXO_DEFAULT_SIGCAP (ZT_SIG_FXSKS | ZT_SIG_FXSLS) +#else +#define FXO_DEFAULT_SIGCAP (ZT_SIG_SF) +#endif + +enum fxo_leds { + LED_GREEN, +}; + +#define NUM_LEDS 1 +#define DELAY_UNTIL_DIALTONE 3000 + +#define POLREV_THRESHOLD 1000 /* minimum duration for polarity reversal detection (in ticks) */ +#define BAT_THRESHOLD 3 +#define BAT_DEBOUNCE 1000 /* compensate for battery voltage fluctuation (in ticks) */ + +/* Shortcuts */ +#define DAA_WRITE 1 +#define DAA_READ 0 +#define DAA_DIRECT_REQUEST(xbus,xpd,chipsel,writing,reg,dL) \ + xpp_register_request((xbus), (xpd), (chipsel), (writing), 0, (reg), 0, (dL), 0) + +#define VALID_CHIPSEL(x) (((chipsel) >= 0 && (chipsel) <= 7) || (chipsel) == ALL_CHANS) + +/*---------------- FXO Protocol Commands ----------------------------------*/ + +static /* 0x0F */ DECLARE_CMD(FXO, XPD_STATE, bool on); +static /* 0x0F */ DECLARE_CMD(FXO, RING, lineno_t chan, bool on); +static /* 0x0F */ DECLARE_CMD(FXO, RELAY_OUT, byte which, bool on); + +static bool fxo_packet_is_valid(xpacket_t *pack); +static void fxo_packet_dump(const char *msg, xpacket_t *pack); +static int proc_fxo_info_read(char *page, char **start, off_t off, int count, int *eof, void *data); +#ifdef WITH_METERING +static int proc_xpd_metering_read(char *page, char **start, off_t off, int count, int *eof, void *data); +#endif +static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data); +static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data); +static int handle_register_command(xpd_t *xpd, char *cmdline); + +#define PROC_REGISTER_FNAME "slics" +#define PROC_FXO_INFO_FNAME "fxo_info" +#ifdef WITH_METERING +#define PROC_METERING_FNAME "metering_read" +#endif + +#define DAA_REG_RING 0x05 +#define DAA_REG_METERING 0x11 /* 17 */ +#define DAA_REG_CURRENT 0x1C /* 28 */ +#define DAA_REG_VBAT 0x1D /* 29 */ + +#define POWER_DENIAL_CURRENT 3 +#define POWER_DENIAL_TIME 80 /* ticks */ + +struct FXO_priv_data { + struct proc_dir_entry *regfile; +#ifdef WITH_METERING + struct proc_dir_entry *meteringfile; +#endif + struct proc_dir_entry *fxo_info; + uint poll_counter; + signed char battery_voltage[CHANNELS_PERXPD]; + xpp_line_t battery; + ushort battery_debounce[CHANNELS_PERXPD]; + xpp_line_t polarity; + ushort polarity_counter[CHANNELS_PERXPD]; + ushort current_counter[CHANNELS_PERXPD]; + xpp_line_t ledstate[NUM_LEDS]; /* 0 - OFF, 1 - ON */ + xpp_line_t ledcontrol[NUM_LEDS]; /* 0 - OFF, 1 - ON */ + int led_counter[NUM_LEDS][CHANNELS_PERXPD]; + atomic_t ring_debounce[CHANNELS_PERXPD]; +#ifdef WITH_METERING + uint metering_count[CHANNELS_PERXPD]; + xpp_line_t metering_tone_state; +#endif +}; + +/* + * LED counter values: + * n>1 : BLINK every n'th tick + */ +#define LED_COUNTER(priv,pos,color) ((priv)->led_counter[color][pos]) +#define IS_BLINKING(priv,pos,color) (LED_COUNTER(priv,pos,color) > 0) +#define MARK_BLINK(priv,pos,color,t) ((priv)->led_counter[color][pos] = (t)) +#define MARK_OFF(priv,pos,color) do { BIT_CLR((priv)->ledcontrol[color],(pos)); MARK_BLINK((priv),(pos),(color),0); } while(0) +#define MARK_ON(priv,pos,color) do { BIT_SET((priv)->ledcontrol[color],(pos)); MARK_BLINK((priv),(pos),(color),0); } while(0) + +#define LED_BLINK_RING (1000/8) /* in ticks */ + +/*---------------- FXO: Static functions ----------------------------------*/ + +/* + * LED control is done via DAA register 0x20 + */ +static int do_led(xpd_t *xpd, lineno_t chan, byte which, bool on) +{ + int ret = 0; + struct FXO_priv_data *priv; + xbus_t *xbus; + + BUG_ON(!xpd); + xbus = xpd->xbus; + priv = xpd->priv; + which = which % NUM_LEDS; + if(IS_SET(xpd->digital_outputs, chan) || IS_SET(xpd->digital_inputs, chan)) + goto out; + if(chan == ALL_CHANS) { + priv->ledstate[which] = (on) ? ~0 : 0; + } else { + if(on) { + BIT_SET(priv->ledstate[which], chan); + } else { + BIT_CLR(priv->ledstate[which], chan); + } + } + LINE_DBG(LEDS, xpd, chan, "LED: which=%d -- %s\n", which, (on) ? "on" : "off"); + ret = DAA_DIRECT_REQUEST(xbus, xpd, chan, DAA_WRITE, 0x20, on); +out: + return ret; +} + +static void handle_fxo_leds(xpd_t *xpd) +{ + int i; + unsigned long flags; + const enum fxo_leds color = LED_GREEN; + unsigned int timer_count; + struct FXO_priv_data *priv; + + BUG_ON(!xpd); + spin_lock_irqsave(&xpd->lock, flags); + priv = xpd->priv; + timer_count = xpd->timer_count; + for_each_line(xpd, i) { + if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i)) + continue; + if(xpd->blink_mode || IS_BLINKING(priv,i,color)) { + int mod_value = LED_COUNTER(priv, i, color); + + if(!mod_value) + mod_value = DEFAULT_LED_PERIOD; /* safety value */ + // led state is toggled + if((timer_count % mod_value) == 0) { + LINE_DBG(LEDS, xpd, i, "ledstate=%s\n", (IS_SET(priv->ledstate[color], i))?"ON":"OFF"); + if(!IS_SET(priv->ledstate[color], i)) { + do_led(xpd, i, color, 1); + } else { + do_led(xpd, i, color, 0); + } + } + } else if(IS_SET(priv->ledcontrol[color], i) && !IS_SET(priv->ledstate[color], i)) { + do_led(xpd, i, color, 1); + } else if(!IS_SET(priv->ledcontrol[color], i) && IS_SET(priv->ledstate[color], i)) { + do_led(xpd, i, color, 0); + } + } + spin_unlock_irqrestore(&xpd->lock, flags); +} + +static void update_zap_ring(xpd_t *xpd, int pos, bool on) +{ + zt_rxsig_t rxsig; + + BUG_ON(!xpd); + if(on) { + BIT_CLR(xpd->cid_on, pos); + rxsig = ZT_RXSIG_RING; + } else { + BIT_SET(xpd->cid_on, pos); + rxsig = ZT_RXSIG_OFFHOOK; + } + pcm_recompute(xpd, 0); + /* + * We should not spinlock before calling zt_hooksig() as + * it may call back into our xpp_hooksig() and cause + * a nested spinlock scenario + */ + if(SPAN_REGISTERED(xpd)) + zt_hooksig(&xpd->chans[pos], rxsig); +} + +static void mark_ring(xpd_t *xpd, lineno_t pos, bool on, bool update_zap) +{ + struct FXO_priv_data *priv; + + priv = xpd->priv; + BUG_ON(!priv); + atomic_set(&priv->ring_debounce[pos], 0); /* Stop debouncing */ + /* + * We don't want to check battery during ringing + * due to voltage fluctuations. + */ + priv->battery_debounce[pos] = 0; + if(on && !xpd->ringing[pos]) { + LINE_DBG(SIGNAL, xpd, pos, "START\n"); + xpd->ringing[pos] = 1; + MARK_BLINK(priv, pos, LED_GREEN, LED_BLINK_RING); + if(update_zap) + update_zap_ring(xpd, pos, on); + } else if(!on && xpd->ringing[pos]) { + LINE_DBG(SIGNAL, xpd, pos, "STOP\n"); + xpd->ringing[pos] = 0; + if(IS_BLINKING(priv, pos, LED_GREEN)) + MARK_BLINK(priv, pos, LED_GREEN, 0); + if(update_zap) + update_zap_ring(xpd, pos, on); + } +} + +static int do_sethook(xpd_t *xpd, int pos, bool to_offhook) +{ + unsigned long flags; + xbus_t *xbus; + struct FXO_priv_data *priv; + int ret = 0; + byte value; + + BUG_ON(!xpd); + BUG_ON(xpd->direction == TO_PHONE); // We can SETHOOK state only on PSTN + xbus = xpd->xbus; + priv = xpd->priv; + BUG_ON(!priv); + if(!IS_SET(priv->battery, pos)) { + LINE_DBG(SIGNAL, xpd, pos, "WARNING: called while battery is off\n"); + } + spin_lock_irqsave(&xpd->lock, flags); + mark_ring(xpd, pos, 0, 0); // No more rings + value = (to_offhook) ? 0x09 : 0x08; /* Bit 3 is for CID */ + LINE_DBG(SIGNAL, xpd, pos, "SETHOOK: value=0x%02X %s\n", value, (to_offhook)?"OFFHOOK":"ONHOOK"); + if(to_offhook) + MARK_ON(priv, pos, LED_GREEN); + else + MARK_OFF(priv, pos, LED_GREEN); + ret = DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, DAA_REG_RING, value); + if(to_offhook) { + BIT_SET(xpd->offhook, pos); + } else { + BIT_CLR(xpd->offhook, pos); + BIT_CLR(xpd->cid_on, pos); + } +#ifdef WITH_METERING + priv->metering_count[pos] = 0; + priv->metering_tone_state = 0L; + DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, DAA_REG_METERING, 0x2D); +#endif + spin_unlock_irqrestore(&xpd->lock, flags); + return ret; +} + +/*---------------- FXO: Methods -------------------------------------------*/ + +static xpd_t *FXO_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table, byte subtype, byte revision) +{ + xpd_t *xpd = NULL; + int channels; + + if(subtype == 2) + channels = min(2, CHANNELS_PERXPD); + else + channels = min(8, CHANNELS_PERXPD); + xpd = xpd_alloc(sizeof(struct FXO_priv_data), proto_table, channels); + if(!xpd) + return NULL; + xpd->direction = TO_PSTN; + xpd->revision = revision; + xpd->type_name = proto_table->name; + return xpd; +} + +static void clean_proc(xbus_t *xbus, xpd_t *xpd) +{ + struct FXO_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + XPD_DBG(PROC, xpd, "\n"); +#ifdef CONFIG_PROC_FS + if(priv->regfile) { + XPD_DBG(PROC, xpd, "Removing xpd DAA file\n"); + remove_proc_entry(PROC_REGISTER_FNAME, xpd->proc_xpd_dir); + priv->regfile->data = NULL; + } +#ifdef WITH_METERING + if(priv->meteringfile) { + XPD_DBG(PROC, xpd, "Removing xpd metering tone file\n"); + priv->meteringfile->data = NULL; + remove_proc_entry(PROC_METERING_FNAME, xpd->proc_xpd_dir); + priv->meteringfile = NULL; + } +#endif + if(priv->fxo_info) { + XPD_DBG(PROC, xpd, "Removing xpd FXO_INFO file\n"); + remove_proc_entry(PROC_FXO_INFO_FNAME, xpd->proc_xpd_dir); + priv->fxo_info = NULL; + } +#endif +} + +static int FXO_card_init(xbus_t *xbus, xpd_t *xpd) +{ + struct FXO_priv_data *priv; + int ret = 0; + int i; + + BUG_ON(!xpd); + priv = xpd->priv; +#ifdef CONFIG_PROC_FS + XPD_DBG(PROC, xpd, "Creating FXO_INFO file\n"); + priv->fxo_info = create_proc_read_entry(PROC_FXO_INFO_FNAME, 0444, xpd->proc_xpd_dir, proc_fxo_info_read, xpd); + if(!priv->fxo_info) { + XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_FXO_INFO_FNAME); + ret = -ENOENT; + goto err; + } + priv->fxo_info->owner = THIS_MODULE; +#ifdef WITH_METERING + XPD_DBG(PROC, xpd, "Creating Metering tone file\n"); + priv->meteringfile = create_proc_read_entry(PROC_METERING_FNAME, 0444, xpd->proc_xpd_dir, + proc_xpd_metering_read, xpd); + if(!priv->meteringfile) { + XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_METERING_FNAME); + ret = -ENOENT; + goto err; + } + priv->meteringfile->owner = THIS_MODULE; +#endif + XPD_DBG(PROC, xpd, "Creating DAAs file\n"); + priv->regfile = create_proc_entry(PROC_REGISTER_FNAME, 0644, xpd->proc_xpd_dir); + if(!priv->regfile) { + XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_REGISTER_FNAME); + ret = -ENOENT; + goto err; + } + priv->regfile->owner = THIS_MODULE; + priv->regfile->write_proc = proc_xpd_register_write; + priv->regfile->read_proc = proc_xpd_register_read; + priv->regfile->data = xpd; +#endif + ret = run_initialize_registers(xpd); + if(ret < 0) + goto err; + // Hanghup all lines + for_each_line(xpd, i) { + do_sethook(xpd, i, 0); + } + XPD_DBG(GENERAL, xpd, "done\n"); + for_each_line(xpd, i) { + do_led(xpd, i, LED_GREEN, 0); + } + for_each_line(xpd, i) { + do_led(xpd, i, LED_GREEN, 1); + msleep(50); + } + for_each_line(xpd, i) { + do_led(xpd, i, LED_GREEN, 0); + msleep(50); + } + pcm_recompute(xpd, 0); + return 0; +err: + clean_proc(xbus, xpd); + XPD_ERR(xpd, "Failed initializing registers (%d)\n", ret); + return ret; +} + +static int FXO_card_remove(xbus_t *xbus, xpd_t *xpd) +{ + struct FXO_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + XPD_DBG(GENERAL, xpd, "\n"); + clean_proc(xbus, xpd); + return 0; +} + +static int FXO_card_zaptel_preregistration(xpd_t *xpd, bool on) +{ + xbus_t *xbus; + struct FXO_priv_data *priv; + int i; + + BUG_ON(!xpd); + xbus = xpd->xbus; + BUG_ON(!xbus); + priv = xpd->priv; + BUG_ON(!priv); + XPD_DBG(GENERAL, xpd, "%s\n", (on)?"ON":"OFF"); + for_each_line(xpd, i) { + struct zt_chan *cur_chan = &xpd->chans[i]; + + XPD_DBG(GENERAL, xpd, "setting FXO channel %d\n", i); + snprintf(cur_chan->name, MAX_CHANNAME, "XPP_FXO/%02d/%1d%1d/%d", + xbus->num, xpd->addr.unit, xpd->addr.subunit, i); + cur_chan->chanpos = i + 1; + cur_chan->pvt = xpd; + cur_chan->sigcap = FXO_DEFAULT_SIGCAP; + } + for_each_line(xpd, i) { + MARK_ON(priv, i, LED_GREEN); + msleep(4); + } + return 0; +} + +static int FXO_card_zaptel_postregistration(xpd_t *xpd, bool on) +{ + xbus_t *xbus; + struct FXO_priv_data *priv; + int i; + + BUG_ON(!xpd); + xbus = xpd->xbus; + BUG_ON(!xbus); + priv = xpd->priv; + BUG_ON(!priv); + XPD_DBG(GENERAL, xpd, "%s\n", (on)?"ON":"OFF"); + for_each_line(xpd, i) { + MARK_OFF(priv, i, LED_GREEN); + msleep(2); + // MARK_OFF(priv, i, LED_RED); + msleep(2); + } + return 0; +} + +static int FXO_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig) +{ + struct FXO_priv_data *priv; + + priv = xpd->priv; + BUG_ON(!priv); + LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig)); + BUG_ON(xpd->direction != TO_PSTN); + /* XXX Enable hooksig for FXO XXX */ + switch(txsig) { + case ZT_TXSIG_START: + break; + case ZT_TXSIG_OFFHOOK: + do_sethook(xpd, pos, 1); + break; + case ZT_TXSIG_ONHOOK: + do_sethook(xpd, pos, 0); + break; + default: + XPD_NOTICE(xpd, "Can't set tx state to %s (%d)\n", + txsig2str(txsig), txsig); + return -EINVAL; + } + pcm_recompute(xpd, 0); + return 0; +} + +static int FXO_card_open(xpd_t *xpd, lineno_t chan) +{ + struct FXO_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + /* + * We pretend to have battery. If this is really the case + * than next calls to update_battery_status() won't change it. + * If we don't have battery, than on the next calls to + * update_battery_status() a battery_debounce[] cycle would start. + * Than, if no-battery is persistent, asterisk would be notified. + */ + BIT_SET(priv->battery, chan); + return 0; +} + +static void poll_battery(xbus_t *xbus, xpd_t *xpd) +{ + int i; + + for_each_line(xpd, i) { + DAA_DIRECT_REQUEST(xbus, xpd, i, DAA_READ, DAA_REG_VBAT, 0); + } +} + +static void poll_current(xbus_t *xbus, xpd_t *xpd) +{ + int i; + + for_each_line(xpd, i) { + if (IS_SET(xpd->offhook, i)) + DAA_DIRECT_REQUEST(xbus, xpd, i, DAA_READ, DAA_REG_CURRENT, 0); + } +} + +#ifdef WITH_METERING +static void poll_metering(xbus_t *xbus, xpd_t *xpd) +{ + int i; + + for_each_line(xpd, i) { + if (IS_SET(xpd->offhook, i)) + DAA_DIRECT_REQUEST(xbus, xpd, i, DAA_READ, DAA_REG_METERING, 0); + } +} +#endif + +static void handle_fxo_ring(xpd_t *xpd) +{ + struct FXO_priv_data *priv; + int i; + + priv = xpd->priv; + for_each_line(xpd, i) { + if(atomic_read(&priv->ring_debounce[i]) > 0) { + /* Maybe start ring */ + if(atomic_dec_and_test(&priv->ring_debounce[i])) + mark_ring(xpd, i, 1, 1); + } else if (atomic_read(&priv->ring_debounce[i]) < 0) { + /* Maybe stop ring */ + if(atomic_inc_and_test(&priv->ring_debounce[i])) + mark_ring(xpd, i, 0, 1); + } + } +} + +static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd) +{ + struct FXO_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + if(poll_battery_interval != 0 && (priv->poll_counter % poll_battery_interval) == 0) + poll_battery(xbus, xpd); + if(poll_power_denial_interval != 0 && (priv->poll_counter % poll_power_denial_interval) == 0) + poll_current(xbus, xpd); +#ifdef WITH_METERING + if(poll_metering_interval != 0 && (priv->poll_counter % poll_metering_interval) == 0) + poll_metering(xbus, xpd); +#endif + handle_fxo_leds(xpd); + handle_fxo_ring(xpd); + priv->poll_counter++; + return 0; +} + +/* FIXME: based on data from from wctdm.h */ +#include +/* + * The first register is the ACIM, the other are coefficient registers. + * We define the array size explicitly to track possible inconsistencies + * if the struct is modified. + */ +static const char echotune_regs[sizeof(struct wctdm_echo_coefs)] = {30, 45, 46, 47, 48, 49, 50, 51, 52}; + +static int FXO_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg) +{ + int i,ret; + unsigned char echotune_data[ARRAY_SIZE(echotune_regs)]; + + BUG_ON(!xpd); + if(!TRANSPORT_RUNNING(xpd->xbus)) + return -ENODEV; + switch (cmd) { + case WCTDM_SET_ECHOTUNE: + XPD_DBG(GENERAL, xpd, "-- Setting echo registers: \n"); + /* first off: check if this span is fxs. If not: -EINVALID */ + if (copy_from_user(&echotune_data, (void __user *)arg, sizeof(echotune_data))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(echotune_regs); i++) { + XPD_DBG(REGS, xpd, "Reg=0x%02X, data=0x%02X\n", echotune_regs[i], echotune_data[i]); + ret = DAA_DIRECT_REQUEST(xpd->xbus, xpd, pos, DAA_WRITE, echotune_regs[i], echotune_data[i]); + if (ret < 0) { + LINE_NOTICE(xpd, pos, "Couldn't write %0x02X to register %0x02X\n", + echotune_data[i], echotune_regs[i]); + return ret; + } + msleep(1); + } + + XPD_DBG(GENERAL, xpd, "-- Set echo registers successfully\n"); + break; + case ZT_TONEDETECT: + /* + * Asterisk call all span types with this (FXS specific) + * call. Silently ignore it. + */ + LINE_DBG(GENERAL, xpd, pos, + "ZT_TONEDETECT (FXO: NOTIMPLEMENTED)\n"); + return -ENOTTY; + default: + report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd); + return -ENOTTY; + } + return 0; +} + +/*---------------- FXO: HOST COMMANDS -------------------------------------*/ + +/* 0x0F */ HOSTCMD(FXO, XPD_STATE, bool on) +{ + int ret = 0; + struct FXO_priv_data *priv; + + BUG_ON(!xbus); + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off"); + return ret; +} + +/* 0x0F */ HOSTCMD(FXO, RING, lineno_t chan, bool on) +{ + BUG_ON(!xbus); + BUG_ON(!xpd); + LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on) ? "on" : "off"); + return DAA_DIRECT_REQUEST(xbus, xpd, chan, DAA_WRITE, 0x40, (on)?0x04:0x01); +} + +/* 0x0F */ HOSTCMD(FXO, RELAY_OUT, byte which, bool on) +{ + return -ENOSYS; +} + +/*---------------- FXO: Astribank Reply Handlers --------------------------*/ + +HANDLER_DEF(FXO, SIG_CHANGED) +{ + xpp_line_t sig_status = RPACKET_FIELD(pack, FXO, SIG_CHANGED, sig_status); + xpp_line_t sig_toggles = RPACKET_FIELD(pack, FXO, SIG_CHANGED, sig_toggles); + unsigned long flags; + int i; + struct FXO_priv_data *priv; + + if(!xpd) { + notify_bad_xpd(__FUNCTION__, xbus, XPACKET_ADDR(pack), cmd->name); + return -EPROTO; + } + priv = xpd->priv; + BUG_ON(!priv); + XPD_DBG(SIGNAL, xpd, "(PSTN) sig_toggles=0x%04X sig_status=0x%04X\n", sig_toggles, sig_status); + spin_lock_irqsave(&xpd->lock, flags); + for_each_line(xpd, i) { + int debounce; + + if(IS_SET(sig_toggles, i)) { + if(!IS_SET(priv->battery, i)) { + LINE_DBG(SIGNAL, xpd, i, "SIG_CHANGED while battery is off.\n"); + // FIXME: allow dialing without battery polling... + // continue; + } + /* First report false ring alarms */ + debounce = atomic_read(&priv->ring_debounce[i]); + if(debounce) + LINE_NOTICE(xpd, i, "debounced false ring (only %d ticks)\n", debounce); + /* + * Now set a new ring alarm. + * It will be checked in handle_fxo_ring() + */ + debounce = (IS_SET(sig_status, i)) ? ring_debounce : -ring_debounce; + atomic_set(&priv->ring_debounce[i], debounce); + } + } + spin_unlock_irqrestore(&xpd->lock, flags); + return 0; +} + +#ifndef ZT_GET_PARAMS_V1 +#define zt_alarm_channel(a,b) zt_qevent_lock(a,( (b)==ZT_ALARM_NONE )? \ + ZT_EVENT_NOALARM : ZT_EVENT_ALARM) +#endif +static void update_battery_status(xpd_t *xpd, byte data_low, lineno_t chipsel) +{ + struct FXO_priv_data *priv; + byte bat = abs((signed char)data_low); + byte pol = IS_SET(data_low, 7); + int msec; + + + priv = xpd->priv; + BUG_ON(!priv); + priv->battery_voltage[chipsel] = data_low; + if(bat < BAT_THRESHOLD) { + /* + * Check for battery voltage fluctuations + */ + if(IS_SET(priv->battery, chipsel)) { + int milliseconds; + + milliseconds = priv->battery_debounce[chipsel]++ * + poll_battery_interval; + if(milliseconds > BAT_DEBOUNCE) { + LINE_DBG(SIGNAL, xpd, chipsel, "BATTERY OFF voltage=%d\n", bat); + BIT_CLR(priv->battery, chipsel); + if(SPAN_REGISTERED(xpd)) + zt_alarm_channel(&xpd->chans[chipsel], ZT_ALARM_RED); + } + + } + } else { + priv->battery_debounce[chipsel] = 0; + if(!IS_SET(priv->battery, chipsel)) { + LINE_DBG(SIGNAL, xpd, chipsel, "BATTERY ON voltage=%d\n", bat); + BIT_SET(priv->battery, chipsel); + if(SPAN_REGISTERED(xpd)) + zt_alarm_channel(&xpd->chans[chipsel], ZT_ALARM_NONE); + } + } + /* + * Handle reverse polarity + */ + if(IS_SET(priv->polarity, chipsel) == pol) { + /* same, same, nothing to see here, move on */ + priv->polarity_counter[chipsel] = 0; + return; + } + /* + * Track polarity reversals and debounce spikes. + * Only reversals with long duration count. + */ + msec = priv->polarity_counter[chipsel]++ * poll_battery_interval; + if (msec >= POLREV_THRESHOLD) { + LINE_DBG(SIGNAL, xpd, chipsel, "Polarity is %s\n", + (pol)?"Positive":"Negative"); + priv->polarity_counter[chipsel] = 0; + if (pol) + BIT_SET(priv->polarity, chipsel); + else + BIT_CLR(priv->polarity, chipsel); + /* polarity reversal during offhook should be reported to zaptel */ + if(IS_SET(xpd->offhook, chipsel)) { + /* Inform Zaptel */ + LINE_DBG(SIGNAL, xpd, chipsel, "Send ZT_EVENT_POLARITY\n"); + zt_qevent_lock(&xpd->chans[chipsel], ZT_EVENT_POLARITY); +#if 0 + /* + * These two lines hangup the channel (by sending a message to + * the firmware), and inform Zaptel that the line has been hung-up. + * They are not needed if Asterisk does the hangup after receiving + * a notification from Zaptel (which is sent by the above zt_qevent_lock(). + * Asterisk does that if it has "hanguponpolarityswitch=1" in zapata.conf. + */ + do_sethook(xpd, chipsel, 0); + update_line_status(xpd, chipsel, 0); + pcm_recompute(xpd, 0); +#endif + } + } +} + +static void update_power_denial(xpd_t *xpd, byte data_low, lineno_t chipsel) +{ + struct FXO_priv_data *priv; + + priv = xpd->priv; + BUG_ON(!priv); + if (IS_SET(xpd->offhook, chipsel) && data_low < POWER_DENIAL_CURRENT) { + /* Current dropped */ + priv->current_counter[chipsel]++; + if (priv->current_counter[chipsel] * poll_battery_interval >= POWER_DENIAL_TIME) { + LINE_DBG(SIGNAL, xpd, chipsel, "Power Denial Hangup\n"); + priv->current_counter[chipsel] = 0; + do_sethook(xpd, chipsel, 0); + update_line_status(xpd, chipsel, 0); + pcm_recompute(xpd, 0); + } + } else + priv->current_counter[chipsel] = 0; +} + +#ifdef WITH_METERING +#define BTD_BIT BIT(0) + +static void update_metering_state(xpd_t *xpd, byte data_low, lineno_t chipsel) +{ + struct FXO_priv_data *priv; + bool metering_tone = data_low & BTD_BIT; + bool old_metering_tone; + + priv = xpd->priv; + BUG_ON(!priv); + old_metering_tone = IS_SET(priv->metering_tone_state, chipsel); + LINE_DBG(SIGNAL, xpd, chipsel, "METERING: %s [dL=0x%X] (%d)\n", + (metering_tone) ? "ON" : "OFF", + data_low, priv->metering_count[chipsel]); + if(metering_tone && !old_metering_tone) { + /* Rising edge */ + priv->metering_count[chipsel]++; + BIT_SET(priv->metering_tone_state, chipsel); + } else if(!metering_tone && old_metering_tone) + BIT_CLR(priv->metering_tone_state, chipsel); + if(metering_tone) { + /* Clear the BTD bit */ + data_low &= ~BTD_BIT; + DAA_DIRECT_REQUEST(xpd->xbus, xpd, chipsel, DAA_WRITE, DAA_REG_METERING, data_low); + } +} +#endif + +static int FXO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) +{ + struct FXO_priv_data *priv; + lineno_t chipsel; + + priv = xpd->priv; + BUG_ON(!priv); + chipsel = REG_FIELD(info, chipsel); + switch(REG_FIELD(info, regnum)) { + case DAA_REG_VBAT: + update_battery_status(xpd, REG_FIELD(info, data_low), chipsel); + break; + case DAA_REG_CURRENT: + update_power_denial(xpd, REG_FIELD(info, data_low), chipsel); + break; +#ifdef WITH_METERING + case DAA_REG_METERING: + update_metering_state(xpd, REG_FIELD(info, data_low), chipsel); + break; +#endif + } + LINE_DBG(REGS, xpd, chipsel, "%c reg_num=0x%X, dataL=0x%X dataH=0x%X\n", + ((info->bytes == 3)?'I':'D'), + REG_FIELD(info, regnum), + REG_FIELD(info, data_low), + REG_FIELD(info, data_high)); + /* Update /proc info only if reply relate to the last slic read request */ + if( + REG_FIELD(&xpd->requested_reply, regnum) == REG_FIELD(info, regnum) && + REG_FIELD(&xpd->requested_reply, do_subreg) == REG_FIELD(info, do_subreg) && + REG_FIELD(&xpd->requested_reply, subreg) == REG_FIELD(info, subreg)) { + xpd->last_reply = *info; + } + return 0; +} + + +static xproto_table_t PROTO_TABLE(FXO) = { + .owner = THIS_MODULE, + .entries = { + /* Prototable Card Opcode */ + XENTRY( FXO, FXO, SIG_CHANGED ), + }, + .name = "FXO", + .type = XPD_TYPE_FXO, + .xops = { + .card_new = FXO_card_new, + .card_init = FXO_card_init, + .card_remove = FXO_card_remove, + .card_zaptel_preregistration = FXO_card_zaptel_preregistration, + .card_zaptel_postregistration = FXO_card_zaptel_postregistration, + .card_hooksig = FXO_card_hooksig, + .card_tick = FXO_card_tick, + .card_pcm_fromspan = generic_card_pcm_fromspan, + .card_pcm_tospan = generic_card_pcm_tospan, + .card_ioctl = FXO_card_ioctl, + .card_open = FXO_card_open, + .card_register_reply = FXO_card_register_reply, + + .RING = XPROTO_CALLER(FXO, RING), + .RELAY_OUT = XPROTO_CALLER(FXO, RELAY_OUT), + .XPD_STATE = XPROTO_CALLER(FXO, XPD_STATE), + }, + .packet_is_valid = fxo_packet_is_valid, + .packet_dump = fxo_packet_dump, +}; + +static bool fxo_packet_is_valid(xpacket_t *pack) +{ + const xproto_entry_t *xe; + + //DBG(GENERAL, "\n"); + xe = xproto_card_entry(&PROTO_TABLE(FXO), XPACKET_OP(pack)); + return xe != NULL; +} + +static void fxo_packet_dump(const char *msg, xpacket_t *pack) +{ + DBG(GENERAL, "%s\n", msg); +} + +/*------------------------- DAA Handling --------------------------*/ + +static int proc_fxo_info_read(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + unsigned long flags; + xpd_t *xpd = data; + struct FXO_priv_data *priv; + int i; + + if(!xpd) + return -ENODEV; + spin_lock_irqsave(&xpd->lock, flags); + priv = xpd->priv; + BUG_ON(!priv); + len += sprintf(page + len, "\t%-17s: ", "Channel"); + for_each_line(xpd, i) { + if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) + len += sprintf(page + len, "%3d ", i % 10); + } + len += sprintf(page + len, "\n\t%-17s: ", "ledstate"); + for_each_line(xpd, i) { + if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) + len += sprintf(page + len, "%3d ", IS_SET(priv->ledstate[LED_GREEN], i)); + } + len += sprintf(page + len, "\n\t%-17s: ", "blinking"); + for_each_line(xpd, i) { + if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) + len += sprintf(page + len, "%3d ", IS_BLINKING(priv,i,LED_GREEN)); + } + len += sprintf(page + len, "\n\t%-17s: ", "battery"); + for_each_line(xpd, i) { + len += sprintf(page + len, "%3d ", IS_SET(priv->battery, i)); + } + len += sprintf(page + len, "\n\t%-17s: ", "polarity"); + for_each_line(xpd, i) { + len += sprintf(page + len, "%3d ", IS_SET(priv->polarity, i)); + } + len += sprintf(page + len, "\n\t%-17s: ", "polarity_counter"); + for_each_line(xpd, i) { + len += sprintf(page + len, "%3d ", priv->polarity_counter[i]); + } + len += sprintf(page + len, "\n\t%-17s: ", "battery_voltage"); + for_each_line(xpd, i) { + len += sprintf(page + len, "%3d ", priv->battery_voltage[i]); + } +#ifdef WITH_METERING + len += sprintf(page + len, "\n\t%-17s: ", "metering"); + for_each_line(xpd, i) { + len += sprintf(page + len, "%3d ", priv->metering_count[i]); + } +#endif + len += sprintf(page + len, "\n"); + spin_unlock_irqrestore(&xpd->lock, flags); + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; +} + +/* + * + * Direct/Indirect + * | + * | Reg# + * | | + * | | Data (only in Write) + * | | | + * | | +-+-+ + * v v v v + * FF WD 06 01 05 + * ^ ^ + * | | + * | Write/Read + * | + * Chan# + * + */ +static int handle_register_command(xpd_t *xpd, char *cmdline) +{ + unsigned chipsel; + unsigned data_low = 0; + char op; /* [W]rite, [R]ead */ + char reg_type; /* [D]irect */ + int reg_num; + int elements; + bool writing; + char *p; + reg_cmd_t regcmd; + xbus_t *xbus; + int ret = -EINVAL; + + BUG_ON(!xpd); + xbus = xpd->xbus; + if((p = strchr(cmdline, '#')) != NULL) /* Truncate comments */ + *p = '\0'; + if((p = strchr(cmdline, ';')) != NULL) /* Truncate comments */ + *p = '\0'; + for(p = cmdline; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */ + ; + if(*p == '\0') + return 0; + + if(!XBUS_GET(xbus)) { + XBUS_DBG(GENERAL, xbus, "Dropped packet. Is shutting down.\n"); + return -EBUSY; + } + elements = sscanf(cmdline, "%d %c%c %x %x", + &chipsel, + &op, ®_type, ®_num, + &data_low); + XPD_DBG(PROC, xpd, "'%s': %d %c%c %02X %02X\n", cmdline, chipsel, op, reg_type, reg_num, data_low); + if(elements < 4) { // At least: chipsel, op, reg_type, reg_num + ERR("Not enough arguments: (%d args) '%s'\n", elements, cmdline); + goto out; + } + if(!VALID_CHIPSEL(chipsel)) { + ERR("Bad chipsel number: %d\n", chipsel); + goto out; + } + REG_FIELD(®cmd, chipsel) = chipsel; + REG_FIELD(®cmd, do_subreg) = 0; + switch(op) { + case 'W': + writing = 1; + break; + case 'R': + writing = 0; + break; + default: + ERR("Unkown operation type '%c'\n", op); + goto out; + } + switch(reg_type) { + case 'D': + REG_FIELD(®cmd, regnum) = reg_num; + REG_FIELD(®cmd, subreg) = 0; + break; + default: + ERR("Unkown register type '%c'\n", reg_type); + goto out; + } + if( + (op == 'W' && reg_type == 'D' && elements != 5) || + (op == 'R' && reg_type == 'D' && elements != 4) + ) { + ERR("%s: '%s' (%d elements): %d %c%c %02X %02X\n", __FUNCTION__, + cmdline, elements, + chipsel, op, reg_type, reg_num, data_low); + goto out; + } + regcmd.bytes = sizeof(regcmd) - 1; + REG_FIELD(®cmd, data_low) = data_low; + REG_FIELD(®cmd, data_high) = 0; + REG_FIELD(®cmd, read_request) = writing; + xpd->requested_reply = regcmd; + if(print_dbg) + dump_reg_cmd("FXO", ®cmd, 1); + ret = DAA_DIRECT_REQUEST(xpd->xbus, xpd, REG_FIELD(®cmd, chipsel), writing, REG_FIELD(®cmd, regnum), REG_FIELD(®cmd, data_low)); +out: + XBUS_PUT(xbus); + return ret; +} + +static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data) +{ + xpd_t *xpd = data; + char buf[MAX_PROC_WRITE]; + char *p; + int i; + int ret; + + if(!xpd) + return -ENODEV; + for(i = 0; i < count; /* noop */) { + for(p = buf; p < buf + MAX_PROC_WRITE; p++) { /* read a line */ + if(i >= count) + break; + if(get_user(*p, buffer + i)) + return -EFAULT; + i++; + if(*p == '\n' || *p == '\r') /* whatever */ + break; + } + if(p >= buf + MAX_PROC_WRITE) + return -E2BIG; + *p = '\0'; + ret = handle_register_command(xpd, buf); + if(ret < 0) + return ret; + msleep(1); + } + return count; +} + +static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + unsigned long flags; + xpd_t *xpd = data; + reg_cmd_t *info; + byte regnum; + + if(!xpd) + return -ENODEV; + spin_lock_irqsave(&xpd->lock, flags); + info = &xpd->last_reply; + regnum = REG_FIELD(info, regnum); + len += sprintf(page + len, "# Writing bad data into this file may damage your hardware!\n"); + len += sprintf(page + len, "# Consult firmware docs first\n"); + len += sprintf(page + len, "#\n"); + len += sprintf(page + len, "#CH\tD/I\tReg.\tDL\n"); + len += sprintf(page + len, "%2d\tRD\t%02X\t%02X\n", + REG_FIELD(info, chipsel), + regnum, REG_FIELD(info, data_low)); + spin_unlock_irqrestore(&xpd->lock, flags); + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; +} + +#ifdef WITH_METERING +static int proc_xpd_metering_read(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + unsigned long flags; + xpd_t *xpd = data; + struct FXO_priv_data *priv; + int i; + + if(!xpd) + return -ENODEV; + priv = xpd->priv; + BUG_ON(!priv); + spin_lock_irqsave(&xpd->lock, flags); + len += sprintf(page + len, "# Chan\tMeter (since last read)\n"); + for_each_line(xpd, i) { + len += sprintf(page + len, "%d\t%d\n", + i, priv->metering_count[i]); + } + spin_unlock_irqrestore(&xpd->lock, flags); + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + /* Zero meters */ + for_each_line(xpd, i) + priv->metering_count[i] = 0; + return len; +} +#endif + +int __init card_fxo_startup(void) +{ + if(ring_debounce <= 0) { + ERR("ring_debounce=%d. Must be positive number of ticks\n", ring_debounce); + return -EINVAL; + } + INFO("revision %s\n", XPP_VERSION); +#ifdef WITH_METERING + INFO("FEATURE: WITH METERING Detection\n"); +#else + INFO("FEATURE: NO METERING Detection\n"); +#endif + xproto_register(&PROTO_TABLE(FXO)); + return 0; +} + +void __exit card_fxo_cleanup(void) +{ + xproto_unregister(&PROTO_TABLE(FXO)); +} + +MODULE_DESCRIPTION("XPP FXO Card Driver"); +MODULE_AUTHOR("Oron Peled "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(XPP_VERSION); +MODULE_ALIAS_XPD(XPD_TYPE_FXO); + +module_init(card_fxo_startup); +module_exit(card_fxo_cleanup); diff --git a/kernel/xpp/card_fxo.h b/kernel/xpp/card_fxo.h new file mode 100644 index 0000000..4d0bd25 --- /dev/null +++ b/kernel/xpp/card_fxo.h @@ -0,0 +1,45 @@ +#ifndef CARD_FXO_H +#define CARD_FXO_H +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "xpd.h" + +enum fxo_opcodes { + XPROTO_NAME(FXO, SIG_CHANGED) = 0x06, +/**/ + XPROTO_NAME(FXO, DAA_WRITE) = 0x0F, /* Write to DAA */ + XPROTO_NAME(FXO, XPD_STATE) = 0x0F, /* Write to DAA */ + XPROTO_NAME(FXO, CHAN_CID) = 0x0F, /* Write to DAA */ + XPROTO_NAME(FXO, RING) = 0x0F, /* Write to DAA */ + XPROTO_NAME(FXO, LED) = 0x0F, /* Write to DAA */ + XPROTO_NAME(FXO, RELAY_OUT) = 0x0F, /* Write to DAA */ +}; + + +DEF_RPACKET_DATA(FXO, SIG_CHANGED, + byte type; /* unused -- we have it from DEV_DESC */ + xpp_line_t sig_status; /* channels: lsb=1, msb=8 */ + xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */ + ); + +#endif /* CARD_FXO_H */ diff --git a/kernel/xpp/card_fxs.c b/kernel/xpp/card_fxs.c new file mode 100644 index 0000000..f2251e0 --- /dev/null +++ b/kernel/xpp/card_fxs.c @@ -0,0 +1,1620 @@ +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include "xpd.h" +#include "xproto.h" +#include "xpp_zap.h" +#include "card_fxo.h" +#include "zap_debug.h" +#include "xbus-core.h" + +static const char rcsid[] = "$Id$"; + +DEF_PARM(int, print_dbg, 0, 0644, "Print DBG statements"); /* must be before zap_debug.h */ +DEF_PARM(uint, poll_digital_inputs, 1000, 0644, "Poll Digital Inputs"); +DEF_PARM_BOOL(reversepolarity, 0, 0644, "Reverse Line Polarity"); +DEF_PARM_BOOL(vmwineon, 0, 0644, "Indicate voicemail to a neon lamp"); +DEF_PARM_BOOL(dtmf_detection, 0, 0644, "Do DTMF detection in hardware"); + +#ifdef ZT_VMWI +DEF_PARM_BOOL(vmwi_ioctl, 0, 0644, "Asterisk support VMWI notification via ioctl"); +#else +#define vmwi_ioctl 0 /* not supported */ +#endif + +/* Signaling is opposite (fxo signalling for fxs card) */ +#if 1 +#define FXS_DEFAULT_SIGCAP (ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS) +#else +#define FXS_DEFAULT_SIGCAP (ZT_SIG_SF | ZT_SIG_EM) +#endif + +#define LINES_DIGI_OUT 2 +#define LINES_DIGI_INP 4 + +enum fxs_leds { + LED_GREEN, + LED_RED, + OUTPUT_RELAY, +}; + +#define NUM_LEDS 2 + +/* Shortcuts */ +#define SLIC_WRITE 1 +#define SLIC_READ 0 +#define SLIC_DIRECT_REQUEST(xbus,xpd,chipsel,writing,reg,dL) \ + xpp_register_request((xbus), (xpd), (chipsel), (writing), 0, (reg), 0, (dL), 0) +#define SLIC_INDIRECT_REQUEST(xbus,xpd,chipsel,writing,reg,dL,dH) \ + xpp_register_request((xbus), (xpd), (chipsel), (writing), 1, 0x1E, (reg), (dL), (dH)) + +#define VALID_CHIPSEL(x) (((chipsel) >= 0 && (chipsel) <= 7) || (chipsel) == ALL_CHANS) + +/* Values of SLIC linefeed control register (0x40) */ +enum fxs_state { + FXS_LINE_OPEN = 0x00, /* Open */ + FXS_LINE_ACTIVE = 0x01, /* Forward active */ + FXS_LINE_OHTRANS = 0x02, /* Forward on-hook transmission */ + FXS_LINE_TIPOPEN = 0x03, /* TIP open */ + FXS_LINE_RING = 0x04, /* Ringing */ + FXS_LINE_REV_ACTIVE = 0x05, /* Reverse active */ + FXS_LINE_REV_OHTRANS = 0x06, /* Reverse on-hook transmission */ + FXS_LINE_RING_OPEN = 0x07 /* RING open */ +}; + +#define FXS_LINE_POL_ACTIVE ((reversepolarity) ? FXS_LINE_REV_ACTIVE : FXS_LINE_ACTIVE) +#define FXS_LINE_POL_OHTRANS ((reversepolarity) ? FXS_LINE_REV_OHTRANS : FXS_LINE_OHTRANS) + +/* + * DTMF detection + */ +#define SLIC_REG_DTMF 0x18 /* 24 */ +#define SLIC_REG_VOLTAGE 0x42 /* 66 */ + +/*---------------- FXS Protocol Commands ----------------------------------*/ + +static /* 0x0F */ DECLARE_CMD(FXS, XPD_STATE, bool on); +static /* 0x0F */ DECLARE_CMD(FXS, RING, lineno_t chan, bool on); +static /* 0x0F */ DECLARE_CMD(FXS, RELAY_OUT, byte which, bool on); + +static bool fxs_packet_is_valid(xpacket_t *pack); +static void fxs_packet_dump(const char *msg, xpacket_t *pack); +static int proc_fxs_info_read(char *page, char **start, off_t off, int count, int *eof, void *data); +#ifdef WITH_METERING +static int proc_xpd_metering_write(struct file *file, const char __user *buffer, unsigned long count, void *data); +#endif +static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data); +static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data); +static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos); + +#define PROC_REGISTER_FNAME "slics" +#define PROC_FXS_INFO_FNAME "fxs_info" +#ifdef WITH_METERING +#define PROC_METERING_FNAME "metering_gen" +#endif + +struct FXS_priv_data { + struct proc_dir_entry *regfile; +#ifdef WITH_METERING + struct proc_dir_entry *meteringfile; +#endif + struct proc_dir_entry *fxs_info; + xpp_line_t ledstate[NUM_LEDS]; /* 0 - OFF, 1 - ON */ + xpp_line_t ledcontrol[NUM_LEDS]; /* 0 - OFF, 1 - ON */ + xpp_line_t search_fsk_pattern; + xpp_line_t found_fsk_pattern; + xpp_line_t update_offhook_state; + xpp_line_t want_dtmf_events; /* what zaptel want */ + xpp_line_t want_dtmf_mute; /* what zaptel want */ + int led_counter[NUM_LEDS][CHANNELS_PERXPD]; + int ohttimer[CHANNELS_PERXPD]; +#define OHT_TIMER 6000 /* How long after RING to retain OHT */ + enum fxs_state idletxhookstate[CHANNELS_PERXPD]; /* IDLE changing hook state */ + enum fxs_state lasttxhook[CHANNELS_PERXPD]; +}; + +/* + * LED counter values: + * n>1 : BLINK every n'th tick + */ +#define LED_COUNTER(priv,pos,color) ((priv)->led_counter[color][pos]) +#define IS_BLINKING(priv,pos,color) (LED_COUNTER(priv,pos,color) > 0) +#define MARK_BLINK(priv,pos,color,t) ((priv)->led_counter[color][pos] = (t)) +#define MARK_OFF(priv,pos,color) do { BIT_CLR((priv)->ledcontrol[color],(pos)); MARK_BLINK((priv),(pos),(color),0); } while(0) +#define MARK_ON(priv,pos,color) do { BIT_SET((priv)->ledcontrol[color],(pos)); MARK_BLINK((priv),(pos),(color),0); } while(0) + +#define LED_BLINK_RING (1000/8) /* in ticks */ + +/*---------------- FXS: Static functions ----------------------------------*/ +static int linefeed_control(xbus_t *xbus, xpd_t *xpd, lineno_t chan, enum fxs_state value) +{ + struct FXS_priv_data *priv; + + priv = xpd->priv; + LINE_DBG(SIGNAL, xpd, chan, "value=0x%02X\n", value); + priv->lasttxhook[chan] = value; + return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, 0x40, value); +} + +static int do_chan_power(xbus_t *xbus, xpd_t *xpd, lineno_t chan, bool on) +{ + int value = (on) ? 0x06 : 0x00; + + BUG_ON(!xbus); + BUG_ON(!xpd); + LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on) ? "up" : "down"); + return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, SLIC_REG_VOLTAGE, value); +} + +/* + * LED and RELAY control is done via SLIC register 0x06: + * 7 6 5 4 3 2 1 0 + * +-----+-----+-----+-----+-----+-----+-----+-----+ + * | M2 | M1 | M3 | C2 | O1 | O3 | C1 | C3 | + * +-----+-----+-----+-----+-----+-----+-----+-----+ + * + * Cn - Control bit (control one digital line) + * On - Output bit (program a digital line for output) + * Mn - Mask bit (only the matching output control bit is affected) + * + * C3 - OUTPUT RELAY (0 - OFF, 1 - ON) + * C1 - GREEN LED (0 - OFF, 1 - ON) + * O3 - Output RELAY (this line is output) + * O1 - Output GREEN (this line is output) + * C2 - RED LED (0 - OFF, 1 - ON) + * M3 - Mask RELAY. (1 - C3 effect the OUTPUT RELAY) + * M2 - Mask RED. (1 - C2 effect the RED LED) + * M1 - Mask GREEN. (1 - C1 effect the GREEN LED) + * + * The OUTPUT RELAY (actually a relay out) is connected to line 0 and 4 only. + */ + +// GREEN RED OUTPUT RELAY +static const int led_register_mask[] = { BIT(7), BIT(6), BIT(5) }; +static const int led_register_vals[] = { BIT(4), BIT(1), BIT(0) }; + +/* + * pos can be: + * - A line number + * - ALL_LINES. This is not valid anymore since 8-Jan-2007. + */ +static int do_led(xpd_t *xpd, lineno_t chan, byte which, bool on) +{ + int ret = 0; + struct FXS_priv_data *priv; + int value; + xbus_t *xbus; + + BUG_ON(!xpd); + BUG_ON(chan == ALL_LINES); + xbus = xpd->xbus; + priv = xpd->priv; + which = which % NUM_LEDS; + if(IS_SET(xpd->digital_outputs, chan) || IS_SET(xpd->digital_inputs, chan)) + goto out; + if(chan == ALL_CHANS) { + priv->ledstate[which] = (on) ? ~0 : 0; + } else { + if(on) { + BIT_SET(priv->ledstate[which], chan); + } else { + BIT_CLR(priv->ledstate[which], chan); + } + } + LINE_DBG(LEDS, xpd, chan, "LED: which=%d -- %s\n", which, (on) ? "on" : "off"); + value = BIT(2) | BIT(3); + value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[which]); + if(on) + value |= led_register_vals[which]; + ret = SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, 0x06, value); +out: + return ret; +} + +static void handle_fxs_leds(xpd_t *xpd) +{ + int i; + const enum fxs_leds colors[] = { LED_GREEN, LED_RED }; + int color; + unsigned int timer_count; + struct FXS_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + timer_count = xpd->timer_count; + for(color = 0; color < ARRAY_SIZE(colors); color++) { + for_each_line(xpd, i) { + if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i)) + continue; + if(xpd->blink_mode || IS_BLINKING(priv, i, color)) { // Blinking + int mod_value = LED_COUNTER(priv, i, color); + + if(!mod_value) + mod_value = DEFAULT_LED_PERIOD; /* safety value */ + // led state is toggled + if((timer_count % mod_value) == 0) { + LINE_DBG(LEDS, xpd, i, "ledstate=%s\n", (IS_SET(priv->ledstate[color], i))?"ON":"OFF"); + if(!IS_SET(priv->ledstate[color], i)) { + do_led(xpd, i, color, 1); + } else { + do_led(xpd, i, color, 0); + } + } + } else if(IS_SET(priv->ledcontrol[color], i) && !IS_SET(priv->ledstate[color], i)) { + do_led(xpd, i, color, 1); + } else if(!IS_SET(priv->ledcontrol[color], i) && IS_SET(priv->ledstate[color], i)) { + do_led(xpd, i, color, 0); + } + + } + } +} + +static void restore_leds(xpd_t *xpd) +{ + struct FXS_priv_data *priv; + int i; + + priv = xpd->priv; + for_each_line(xpd, i) { + if(IS_SET(xpd->offhook, i)) + MARK_ON(priv, i, LED_GREEN); + else + MARK_OFF(priv, i, LED_GREEN); + } +} + +#ifdef WITH_METERING +static int metering_gen(xpd_t *xpd, lineno_t chan, bool on) +{ + byte value = (on) ? 0x94 : 0x00; + + LINE_DBG(SIGNAL, xpd, chan, "METERING Generate: %s\n", (on)?"ON":"OFF"); + return SLIC_DIRECT_REQUEST(xpd->xbus, xpd, chan, SLIC_WRITE, 0x23, value); +} +#endif + +/*---------------- FXS: Methods -------------------------------------------*/ + +static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table, byte subtype, byte revision) +{ + xpd_t *xpd = NULL; + int channels; + int regular_channels; + + if(subtype == 2) + regular_channels = min(6, CHANNELS_PERXPD); + else + regular_channels = min(8, CHANNELS_PERXPD); + channels = regular_channels; + if(unit == 0) + channels += 6; /* 2 DIGITAL OUTPUTS, 4 DIGITAL INPUTS */ + xpd = xpd_alloc(sizeof(struct FXS_priv_data), proto_table, channels); + if(!xpd) + return NULL; + if(unit == 0) { + XBUS_DBG(GENERAL, xbus, "First XPD detected. Initialize digital outputs/inputs\n"); + xpd->digital_outputs = BITMASK(LINES_DIGI_OUT) << regular_channels; + xpd->digital_inputs = BITMASK(LINES_DIGI_INP) << (regular_channels + LINES_DIGI_OUT); + } + xpd->direction = TO_PHONE; + xpd->revision = revision; + xpd->type_name = proto_table->name; + return xpd; +} + +static void clean_proc(xbus_t *xbus, xpd_t *xpd) +{ + struct FXS_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; +#ifdef CONFIG_PROC_FS + if(priv->regfile) { + XPD_DBG(PROC, xpd, "Removing xpd SLIC file\n"); + priv->regfile->data = NULL; + remove_proc_entry(PROC_REGISTER_FNAME, xpd->proc_xpd_dir); + priv->regfile = NULL; + } +#ifdef WITH_METERING + if(priv->meteringfile) { + XPD_DBG(PROC, xpd, "Removing xpd metering tone file\n"); + priv->meteringfile->data = NULL; + remove_proc_entry(PROC_METERING_FNAME, xpd->proc_xpd_dir); + priv->meteringfile = NULL; + } +#endif + if(priv->fxs_info) { + XPD_DBG(PROC, xpd, "Removing xpd FXS_INFO file\n"); + remove_proc_entry(PROC_FXS_INFO_FNAME, xpd->proc_xpd_dir); + priv->fxs_info = NULL; + } +#endif +} + +static int FXS_card_init(xbus_t *xbus, xpd_t *xpd) +{ + struct FXS_priv_data *priv; + int ret = 0; + int i; + + BUG_ON(!xpd); + priv = xpd->priv; +#ifdef CONFIG_PROC_FS + XPD_DBG(PROC, xpd, "Creating FXS_INFO file\n"); + priv->fxs_info = create_proc_read_entry(PROC_FXS_INFO_FNAME, 0444, xpd->proc_xpd_dir, proc_fxs_info_read, xpd); + if(!priv->fxs_info) { + XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_FXS_INFO_FNAME); + ret = -ENOENT; + goto err; + } + priv->fxs_info->owner = THIS_MODULE; +#ifdef WITH_METERING + XPD_DBG(PROC, xpd, "Creating Metering tone file\n"); + priv->meteringfile = create_proc_entry(PROC_METERING_FNAME, 0200, xpd->proc_xpd_dir); + if(!priv->meteringfile) { + XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_METERING_FNAME); + ret = -ENOENT; + goto err; + } + priv->meteringfile->owner = THIS_MODULE; + priv->meteringfile->write_proc = proc_xpd_metering_write; + priv->meteringfile->read_proc = NULL; + priv->meteringfile->data = xpd; +#endif + XPD_DBG(PROC, xpd, "Creating SLICs file\n"); + priv->regfile = create_proc_entry(PROC_REGISTER_FNAME, 0644, xpd->proc_xpd_dir); + if(!priv->regfile) { + XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_REGISTER_FNAME); + ret = -ENOENT; + goto err; + } + priv->regfile->owner = THIS_MODULE; + priv->regfile->write_proc = proc_xpd_register_write; + priv->regfile->read_proc = proc_xpd_register_read; + priv->regfile->data = xpd; +#endif + for_each_line(xpd, i) { + priv->idletxhookstate[i] = FXS_LINE_POL_ACTIVE; + } + ret = run_initialize_registers(xpd); + if(ret < 0) + goto err; + /* + * Setup ring timers + */ + /* Software controled ringing (for CID) */ + ret = SLIC_DIRECT_REQUEST(xbus, xpd, ALL_CHANS, SLIC_WRITE, 0x22, 0x00); /* Ringing Oscilator Control */ + if(ret < 0) + goto err; + XPD_DBG(GENERAL, xpd, "done\n"); + for_each_line(xpd, i) { + do_led(xpd, i, LED_GREEN, 0); + do_led(xpd, i, LED_RED, 0); + } + for_each_line(xpd, i) { + do_led(xpd, i, LED_GREEN, 1); + msleep(50); + } + for_each_line(xpd, i) { + do_led(xpd, i, LED_GREEN, 0); + msleep(50); + } + restore_leds(xpd); + pcm_recompute(xpd, 0); + return 0; +err: + clean_proc(xbus, xpd); + XPD_ERR(xpd, "Failed initializing registers (%d)\n", ret); + return ret; +} + +static int FXS_card_remove(xbus_t *xbus, xpd_t *xpd) +{ + struct FXS_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + XPD_DBG(GENERAL, xpd, "\n"); + clean_proc(xbus, xpd); + return 0; +} + +static int FXS_card_zaptel_preregistration(xpd_t *xpd, bool on) +{ + xbus_t *xbus; + struct FXS_priv_data *priv; + int i; + + BUG_ON(!xpd); + xbus = xpd->xbus; + BUG_ON(!xbus); + priv = xpd->priv; + BUG_ON(!priv); + XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off"); + for_each_line(xpd, i) { + struct zt_chan *cur_chan = &xpd->chans[i]; + + XPD_DBG(GENERAL, xpd, "setting FXS channel %d\n", i); + if(IS_SET(xpd->digital_outputs, i)) { + snprintf(cur_chan->name, MAX_CHANNAME, "XPP_OUT/%02d/%1d%1d/%d", + xbus->num, xpd->addr.unit, xpd->addr.subunit, i); + } else if(IS_SET(xpd->digital_inputs, i)) { + snprintf(cur_chan->name, MAX_CHANNAME, "XPP_IN/%02d/%1d%1d/%d", + xbus->num, xpd->addr.unit, xpd->addr.subunit, i); + } else { + snprintf(cur_chan->name, MAX_CHANNAME, "XPP_FXS/%02d/%1d%1d/%d", + xbus->num, xpd->addr.unit, xpd->addr.subunit, i); + } + cur_chan->chanpos = i + 1; + cur_chan->pvt = xpd; + cur_chan->sigcap = FXS_DEFAULT_SIGCAP; + } + for_each_line(xpd, i) { + MARK_ON(priv, i, LED_GREEN); + msleep(4); + } + return 0; +} + +static int FXS_card_zaptel_postregistration(xpd_t *xpd, bool on) +{ + xbus_t *xbus; + struct FXS_priv_data *priv; + int i; + + BUG_ON(!xpd); + xbus = xpd->xbus; + BUG_ON(!xbus); + priv = xpd->priv; + BUG_ON(!priv); + XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off"); + for_each_line(xpd, i) { + MARK_OFF(priv, i, LED_GREEN); + msleep(2); + MARK_OFF(priv, i, LED_RED); + msleep(2); + } + restore_leds(xpd); + return 0; +} + +/* + * Called with XPD spinlocked + */ +static void __do_mute_dtmf(xpd_t *xpd, int pos, bool muteit) +{ + LINE_DBG(SIGNAL, xpd, pos, "%s\n", (muteit) ? "MUTE" : "UNMUTE"); + if(muteit) + BIT_SET(xpd->mute_dtmf, pos); + else + BIT_CLR(xpd->mute_dtmf, pos); +} + +static int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig) +{ + struct FXS_priv_data *priv; + int ret = 0; + struct zt_chan *chan = NULL; + enum fxs_state txhook; + unsigned long flags; + + LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig)); + priv = xpd->priv; + BUG_ON(xpd->direction != TO_PHONE); + if (IS_SET(xpd->digital_inputs, pos)) { + LINE_DBG(SIGNAL, xpd, pos, "Ignoring signal sent to digital input line\n"); + return 0; + } + if(SPAN_REGISTERED(xpd)) + chan = &xpd->span.chans[pos]; + switch(txsig) { + case ZT_TXSIG_ONHOOK: + spin_lock_irqsave(&xpd->lock, flags); + xpd->ringing[pos] = 0; + BIT_CLR(xpd->cid_on, pos); + BIT_CLR(priv->search_fsk_pattern, pos); + BIT_CLR(priv->want_dtmf_events, pos); + BIT_CLR(priv->want_dtmf_mute, pos); + __do_mute_dtmf(xpd, pos, 0); + __pcm_recompute(xpd, 0); /* already spinlocked */ + spin_unlock_irqrestore(&xpd->lock, flags); + if(IS_SET(xpd->digital_outputs, pos)) { + LINE_DBG(SIGNAL, xpd, pos, "digital output OFF\n"); + ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 0); + return ret; + } + if (priv->lasttxhook[pos] == FXS_LINE_OPEN) { + /* + * Restore state after KEWL hangup. + */ + LINE_DBG(SIGNAL, xpd, pos, "KEWL STOP\n"); + linefeed_control(xbus, xpd, pos, FXS_LINE_POL_ACTIVE); + if(IS_SET(xpd->offhook, pos)) + MARK_ON(priv, pos, LED_GREEN); + } + ret = CALL_XMETHOD(RING, xbus, xpd, pos, 0); // RING off + if (!IS_SET(xpd->offhook, pos)) + start_stop_vm_led(xbus, xpd, pos); + txhook = priv->lasttxhook[pos]; + if(chan) { + switch(chan->sig) { + case ZT_SIG_EM: + case ZT_SIG_FXOKS: + case ZT_SIG_FXOLS: + txhook = priv->idletxhookstate[pos]; + break; + case ZT_SIG_FXOGS: + txhook = FXS_LINE_TIPOPEN; + break; + } + } + ret = linefeed_control(xbus, xpd, pos, txhook); + break; + case ZT_TXSIG_OFFHOOK: + txhook = priv->lasttxhook[pos]; + if(xpd->ringing[pos]) { + BIT_SET(xpd->cid_on, pos); + pcm_recompute(xpd, 0); + txhook = FXS_LINE_OHTRANS; + } + xpd->ringing[pos] = 0; + if(chan) { + switch(chan->sig) { + case ZT_SIG_EM: + txhook = FXS_LINE_POL_ACTIVE; + break; + default: + txhook = priv->idletxhookstate[pos]; + break; + } + } + ret = linefeed_control(xbus, xpd, pos, txhook); + break; + case ZT_TXSIG_START: + xpd->ringing[pos] = 1; + BIT_CLR(xpd->cid_on, pos); + BIT_CLR(priv->search_fsk_pattern, pos); + pcm_recompute(xpd, 0); + if(IS_SET(xpd->digital_outputs, pos)) { + LINE_DBG(SIGNAL, xpd, pos, "%s digital output ON\n", txsig2str(txsig)); + ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 1); + return ret; + } + ret = CALL_XMETHOD(RING, xbus, xpd, pos, 1); // RING on + break; + case ZT_TXSIG_KEWL: + LINE_DBG(SIGNAL, xpd, pos, "KEWL START\n"); + linefeed_control(xbus, xpd, pos, FXS_LINE_OPEN); + MARK_OFF(priv, pos, LED_GREEN); + break; + default: + XPD_NOTICE(xpd, "%s: Can't set tx state to %s (%d)\n", + __FUNCTION__, txsig2str(txsig), txsig); + ret = -EINVAL; + } + return ret; +} + +/* + * Private ioctl() + * We don't need it now, since we detect vmwi via FSK patterns + */ +static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg) +{ + struct FXS_priv_data *priv; + xbus_t *xbus; + int val; + unsigned long flags; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + xbus = xpd->xbus; + BUG_ON(!xbus); + if(!TRANSPORT_RUNNING(xbus)) + return -ENODEV; + if (pos < 0 || pos >= xpd->channels) { + XPD_NOTICE(xpd, "Bad channel number %d in %s(), cmd=%u\n", + pos, __FUNCTION__, cmd); + return -EINVAL; + } + + switch (cmd) { + case ZT_ONHOOKTRANSFER: + if (get_user(val, (int __user *)arg)) + return -EFAULT; + LINE_DBG(SIGNAL, xpd, pos, "ZT_ONHOOKTRANSFER (%d millis)\n", val); + BUG_ON(pos == ALL_CHANS); + if (IS_SET(xpd->digital_inputs | xpd->digital_outputs, pos)) + return 0; /* Nothing to do */ + BIT_CLR(xpd->cid_on, pos); + if(priv->lasttxhook[pos] == FXS_LINE_POL_ACTIVE) { + priv->ohttimer[pos] = OHT_TIMER; + priv->idletxhookstate[pos] = FXS_LINE_POL_OHTRANS; + BIT_SET(priv->search_fsk_pattern, pos); + pcm_recompute(xpd, priv->search_fsk_pattern); + } + if(!IS_SET(xpd->offhook, pos)) + start_stop_vm_led(xbus, xpd, pos); + return 0; + case ZT_TONEDETECT: + if (get_user(val, (int __user *)arg)) + return -EFAULT; + LINE_DBG(SIGNAL, xpd, pos, "ZT_TONEDETECT: %s %s (dtmf_detection=%s)\n", + (val & ZT_TONEDETECT_ON) ? "ON" : "OFF", + (val & ZT_TONEDETECT_MUTE) ? "MUTE" : "NO-MUTE", + (dtmf_detection ? "YES" : "NO")); + if(!dtmf_detection) { + spin_lock_irqsave(&xpd->lock, flags); + if(IS_SET(priv->want_dtmf_events, pos)) { + /* Detection mode changed: Disable DTMF interrupts */ + SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x17, 0); + } + BIT_CLR(priv->want_dtmf_events, pos); + BIT_CLR(priv->want_dtmf_mute, pos); + __do_mute_dtmf(xpd, pos, 0); + __pcm_recompute(xpd, 0); /* already spinlocked */ + spin_unlock_irqrestore(&xpd->lock, flags); + return -ENOTTY; + } + /* + * During natively bridged calls, Asterisk + * will request one of the sides to stop sending + * dtmf events. Check the requested state. + */ + spin_lock_irqsave(&xpd->lock, flags); + if(val & ZT_TONEDETECT_ON) { + if(!IS_SET(priv->want_dtmf_events, pos)) { + /* Detection mode changed: Enable DTMF interrupts */ + LINE_DBG(SIGNAL, xpd, pos, + "ZT_TONEDETECT: Enable Hardware DTMF\n"); + SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x17, 1); + } + BIT_SET(priv->want_dtmf_events, pos); + } else { + if(IS_SET(priv->want_dtmf_events, pos)) { + /* Detection mode changed: Disable DTMF interrupts */ + LINE_DBG(SIGNAL, xpd, pos, + "ZT_TONEDETECT: Disable Hardware DTMF\n"); + SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x17, 0); + } + BIT_CLR(priv->want_dtmf_events, pos); + } + if(val & ZT_TONEDETECT_MUTE) { + BIT_SET(priv->want_dtmf_mute, pos); + } else { + BIT_CLR(priv->want_dtmf_mute, pos); + __do_mute_dtmf(xpd, pos, 0); + __pcm_recompute(xpd, 0); + } + spin_unlock_irqrestore(&xpd->lock, flags); + return 0; + case ZT_SETPOLARITY: + if (get_user(val, (int __user *)arg)) + return -EFAULT; + /* Can't change polarity while ringing or when open */ + if (priv->lasttxhook[pos] == FXS_LINE_RING || priv->lasttxhook[pos] == FXS_LINE_OPEN) { + LINE_ERR(xpd, pos, "ZT_SETPOLARITY: %s Cannot change when lasttxhook=0x%X\n", + (val)?"ON":"OFF", priv->lasttxhook[pos]); + return -EINVAL; + } + LINE_DBG(SIGNAL, xpd, pos, "ZT_SETPOLARITY: %s\n", (val)?"ON":"OFF"); + if ((val && !reversepolarity) || (!val && reversepolarity)) + priv->lasttxhook[pos] |= FXS_LINE_RING; + else + priv->lasttxhook[pos] &= ~FXS_LINE_RING; + linefeed_control(xbus, xpd, pos, priv->lasttxhook[pos]); + return 0; +#ifdef ZT_VMWI + case ZT_VMWI: /* message-waiting led control */ + if (get_user(val, (int __user *)arg)) + return -EFAULT; + if(!vmwi_ioctl) { + LINE_NOTICE(xpd, pos, "Got ZT_VMWI notification but vmwi_ioctl parameter is off. Ignoring.\n"); + return 0; + } + /* Digital inputs/outputs don't have VM leds */ + if (IS_SET(xpd->digital_inputs | xpd->digital_outputs, pos)) + return 0; + if (val) + BIT_SET(xpd->msg_waiting, pos); + else + BIT_CLR(xpd->msg_waiting, pos); + return 0; +#endif + default: + report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd); + } + return -ENOTTY; +} + +static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos, int on) +{ + int ret = 0; + BUG_ON(!xbus); + BUG_ON(!xpd); + + LINE_DBG(SIGNAL, xpd, pos, "%s%s\n", (on)?"ON":"OFF", (vmwineon)?"":" (Ignored)"); + if (!vmwineon) + return 0; + if (on) { + /* A write to register 0x40 will now turn on/off the VM led */ + ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16, 0xE8, 0x03); + ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15, 0xEF, 0x7B); + ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14, 0x9F, 0x00); + ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x19); + ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x4A, 0x34); + ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0xE0); + ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x01); + ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0xF0); + ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x05); + ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D, 0x00, 0x46); + } else { + /* A write to register 0x40 will now turn on/off the ringer */ + ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16, 0x00, 0x00); + ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15, 0x60, 0x01); + ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14, 0xF0, 0x7E); + ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x00); + ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x4A, 0x34); + ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0x00); + ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x00); + ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0x00); + ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x00); + ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D, 0x00, 0x36); + } + + return (ret ? -EPROTO : 0); +} + +static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos) +{ + struct FXS_priv_data *priv; + bool on; + + BUG_ON(!xpd); + if (IS_SET(xpd->digital_outputs | xpd->digital_inputs, pos)) + return; + priv = xpd->priv; + on = IS_SET(xpd->msg_waiting, pos); + LINE_DBG(SIGNAL, xpd, pos, "%s\n", (on)?"ON":"OFF"); + set_vm_led_mode(xbus, xpd, pos, on); + do_chan_power(xbus, xpd, pos, on); + linefeed_control(xbus, xpd, pos, (on) ? FXS_LINE_RING : priv->idletxhookstate[pos]); +} + +static int FXS_card_open(xpd_t *xpd, lineno_t chan) +{ + struct FXS_priv_data *priv; + bool is_offhook; + + BUG_ON(!xpd); + priv = xpd->priv; + is_offhook = IS_SET(xpd->offhook, chan); + LINE_DBG(GENERAL, xpd, chan, "(is %shook)\n", (is_offhook)?"off":"on"); + /* + * Delegate updating zaptel to FXS_card_tick(): + * The problem is that zt_hooksig() is spinlocking the channel and + * we are called by zaptel with the spinlock already held on the + * same channel. + */ + BIT_SET(priv->update_offhook_state, chan); + return 0; +} + +static int FXS_card_close(xpd_t *xpd, lineno_t chan) +{ + struct FXS_priv_data *priv; + + BUG_ON(!xpd); + LINE_DBG(GENERAL, xpd, chan, "\n"); + priv = xpd->priv; + priv->idletxhookstate[chan] = FXS_LINE_POL_ACTIVE; + return 0; +} + +/* + * INPUT polling is done via SLIC register 0x06 (same as LEDS): + * 7 6 5 4 3 2 1 0 + * +-----+-----+-----+-----+-----+-----+-----+-----+ + * | I1 | I3 | | | I2 | I4 | | | + * +-----+-----+-----+-----+-----+-----+-----+-----+ + * + */ +static int input_channels[] = { 6, 7, 2, 3 }; // Slic numbers of input relays + +static void poll_inputs(xpd_t *xpd) +{ + int i; + + BUG_ON(xpd->xbus_idx != 0); // Only unit #0 has digital inputs + for(i = 0; i < ARRAY_SIZE(input_channels); i++) { + byte pos = input_channels[i]; + + SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_READ, 0x06, 0); + } +} + +static void handle_linefeed(xpd_t *xpd) +{ + struct FXS_priv_data *priv; + int i; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + for_each_line(xpd, i) { + if (priv->lasttxhook[i] == FXS_LINE_RING) { + /* RINGing, prepare for OHT */ + priv->ohttimer[i] = OHT_TIMER; + priv->idletxhookstate[i] = FXS_LINE_POL_OHTRANS; + } else { + if (priv->ohttimer[i]) { + priv->ohttimer[i]--; + if (!priv->ohttimer[i]) { + priv->idletxhookstate[i] = FXS_LINE_POL_ACTIVE; + if (priv->lasttxhook[i] == FXS_LINE_POL_OHTRANS) { + enum fxs_state txhook = FXS_LINE_POL_ACTIVE; + /* Apply the change if appropriate */ + BIT_CLR(xpd->cid_on, i); + BIT_CLR(priv->search_fsk_pattern, i); + pcm_recompute(xpd, 0); + linefeed_control(xpd->xbus, xpd, i, txhook); + } + } + } + } + } +} + +/* + * Optimized memcmp() like function. Only test for equality (true/false). + * This optimization reduced the detect_vmwi() runtime by a factor of 3. + */ +static inline bool mem_equal(const char a[], const char b[], size_t len) +{ + int i; + + for(i = 0; i < len; i++) + if(a[i] != b[i]) + return 0; + return 1; +} + +/* + * Detect Voice Mail Waiting Indication + */ +static void detect_vmwi(xpd_t *xpd) +{ + struct FXS_priv_data *priv; + xbus_t *xbus; + static const byte FSK_COMMON_PATTERN[] = { 0xA8, 0x49, 0x22, 0x3B, 0x9F, 0xFF, 0x1F, 0xBB }; + static const byte FSK_ON_PATTERN[] = { 0xA2, 0x2C, 0x1F, 0x2C, 0xBB, 0xA1, 0xA5, 0xFF }; + static const byte FSK_OFF_PATTERN[] = { 0xA2, 0x2C, 0x28, 0xA5, 0xB1, 0x21, 0x49, 0x9F }; + int i; + + BUG_ON(!xpd); + xbus = xpd->xbus; + priv = xpd->priv; + BUG_ON(!priv); + for_each_line(xpd, i) { + struct zt_chan *chan = &xpd->span.chans[i]; + byte *writechunk = chan->writechunk; + + if(IS_SET(xpd->offhook | xpd->cid_on | xpd->digital_inputs | xpd->digital_outputs, i)) + continue; +#if 0 + if(writechunk[0] != 0x7F && writechunk[0] != 0) { + int j; + + LINE_DBG(GENERAL, xpd, pos, "MSG:"); + for(j = 0; j < ZT_CHUNKSIZE; j++) { + if(print_dbg) + printk(" %02X", writechunk[j]); + } + if(print_dbg) + printk("\n"); + } +#endif + if(unlikely(mem_equal(writechunk, FSK_COMMON_PATTERN, ZT_CHUNKSIZE))) + BIT_SET(priv->found_fsk_pattern, i); + else if(unlikely(IS_SET(priv->found_fsk_pattern, i))) { + BIT_CLR(priv->found_fsk_pattern, i); + if(unlikely(mem_equal(writechunk, FSK_ON_PATTERN, ZT_CHUNKSIZE))) { + LINE_DBG(SIGNAL, xpd, i, "MSG WAITING ON\n"); + BIT_SET(xpd->msg_waiting, i); + start_stop_vm_led(xbus, xpd, i); + } else if(unlikely(mem_equal(writechunk, FSK_OFF_PATTERN, ZT_CHUNKSIZE))) { + LINE_DBG(SIGNAL, xpd, i, "MSG WAITING OFF\n"); + BIT_CLR(xpd->msg_waiting, i); + start_stop_vm_led(xbus, xpd, i); + } else { + int j; + + LINE_NOTICE(xpd, i, "MSG WAITING Unexpected:"); + for(j = 0; j < ZT_CHUNKSIZE; j++) { + printk(" %02X", writechunk[j]); + } + printk("\n"); + } + } + } +} + +static int FXS_card_tick(xbus_t *xbus, xpd_t *xpd) +{ + struct FXS_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); +#if POLL_DIGITAL_INPUTS + if(poll_digital_inputs && xpd->xbus_idx == 0) { + if((xpd->timer_count % poll_digital_inputs) == 0) + poll_inputs(xpd); + } +#endif + handle_fxs_leds(xpd); + handle_linefeed(xpd); + if(priv->update_offhook_state) { /* set in FXS_card_open() */ + int i; + + for_each_line(xpd, i) { + if(!IS_SET(priv->update_offhook_state, i)) + continue; + /* + * Update LEDs and zaptel with current state of line. + */ + if(IS_SET(xpd->offhook, i)) { + LINE_NOTICE(xpd, i, "Already offhook during open. OK.\n"); + MARK_ON(priv, i, LED_GREEN); + update_line_status(xpd, i, 1); + } else { + MARK_OFF(priv, i, LED_GREEN); + update_line_status(xpd, i, 0); + } + BIT_CLR(priv->update_offhook_state, i); + } + } + if(SPAN_REGISTERED(xpd)) { + if(vmwineon && !vmwi_ioctl) + detect_vmwi(xpd); /* Detect via FSK modulation */ + } + return 0; +} + +/*---------------- FXS: HOST COMMANDS -------------------------------------*/ + +/* 0x0F */ HOSTCMD(FXS, XPD_STATE, bool on) +{ + int i; + enum fxs_state value = (on) ? FXS_LINE_POL_ACTIVE : FXS_LINE_OPEN; + unsigned long flags; + struct FXS_priv_data *priv; + + BUG_ON(!xbus); + BUG_ON(!xpd); + priv = xpd->priv; + spin_lock_irqsave(&xpd->lock, flags); + XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off"); + for_each_line(xpd, i) + linefeed_control(xbus, xpd, i, value); + if(on) { + MARK_ON(priv, ALL_CHANS, LED_GREEN); + } else { + MARK_OFF(priv, ALL_CHANS, LED_GREEN); + } + spin_unlock_irqrestore(&xpd->lock, flags); + return 0; +} + +/* 0x0F */ HOSTCMD(FXS, RING, lineno_t chan, bool on) +{ + int ret = 0; + struct FXS_priv_data *priv; + enum fxs_state value = (on) ? FXS_LINE_RING : FXS_LINE_POL_ACTIVE; + + BUG_ON(!xbus); + BUG_ON(!xpd); + LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on)?"on":"off"); + priv = xpd->priv; + set_vm_led_mode(xbus, xpd, chan, 0); + do_chan_power(xbus, xpd, chan, on); // Power up (for ring) + ret = linefeed_control(xbus, xpd, chan, value); + if(on) { + MARK_BLINK(priv, chan, LED_GREEN, LED_BLINK_RING); + } else { + if(IS_BLINKING(priv, chan, LED_GREEN)) + MARK_BLINK(priv, chan, LED_GREEN, 0); + } + return ret; +} + +/* 0x0F */ HOSTCMD(FXS, RELAY_OUT, byte which, bool on) +{ + int value; + int relay_channels[] = { 0, 4 }; + + BUG_ON(!xbus); + BUG_ON(!xpd); + XPD_DBG(SIGNAL, xpd, "RELAY_OUT: which=%d -- %s\n", which, (on) ? "on" : "off"); + which = which % ARRAY_SIZE(relay_channels); + value = BIT(2) | BIT(3); + value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[OUTPUT_RELAY]); + if(on) + value |= led_register_vals[OUTPUT_RELAY]; + return SLIC_DIRECT_REQUEST(xbus, xpd, relay_channels[which], SLIC_WRITE, 0x06, value); +} + +/*---------------- FXS: Astribank Reply Handlers --------------------------*/ + +HANDLER_DEF(FXS, SIG_CHANGED) +{ + xpp_line_t sig_status = RPACKET_FIELD(pack, FXS, SIG_CHANGED, sig_status); + xpp_line_t sig_toggles = RPACKET_FIELD(pack, FXS, SIG_CHANGED, sig_toggles); + struct FXS_priv_data *priv; + int i; + unsigned long flags; + + BUG_ON(!xpd); + BUG_ON(xpd->direction != TO_PHONE); + priv = xpd->priv; + XPD_DBG(SIGNAL, xpd, "(PHONE) sig_toggles=0x%04X sig_status=0x%04X\n", sig_toggles, sig_status); +#if 0 + Is this needed? + for_each_line(xpd, i) { + if(IS_SET(sig_toggles, i)) + do_chan_power(xpd->xbus, xpd, BIT(i), 0); // Power down (prevent overheating!!!) + } +#endif + spin_lock_irqsave(&xpd->lock, flags); + for_each_line(xpd, i) { + if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i)) + continue; + if(IS_SET(sig_toggles, i)) { + xpd->ringing[i] = 0; /* No more ringing... */ +#ifdef WITH_METERING + metering_gen(xpd, i, 0); /* Stop metering... */ +#endif + MARK_BLINK(priv, i, LED_GREEN, 0); + if(IS_SET(sig_status, i)) { + LINE_DBG(SIGNAL, xpd, i, "OFFHOOK\n"); + MARK_ON(priv, i, LED_GREEN); + update_line_status(xpd, i, 1); + } else { + LINE_DBG(SIGNAL, xpd, i, "ONHOOK\n"); + MARK_OFF(priv, i, LED_GREEN); + update_line_status(xpd, i, 0); + } + } + } + __pcm_recompute(xpd, 0); /* in a spinlock */ + spin_unlock_irqrestore(&xpd->lock, flags); + return 0; +} + +static void process_digital_inputs(xpd_t *xpd, const reg_cmd_t *info) +{ + int i; + bool offhook = (REG_FIELD(info, data_low) & 0x1) == 0; + xpp_line_t lines = BIT(REG_FIELD(info, chipsel)); + + /* Map SLIC number into line number */ + for(i = 0; i < ARRAY_SIZE(input_channels); i++) { + int channo = input_channels[i]; + int newchanno; + + if(IS_SET(lines, channo)) { + newchanno = xpd->channels - LINES_DIGI_INP + i; + BIT_CLR(lines, channo); + BIT_SET(lines, newchanno); + xpd->ringing[newchanno] = 0; // Stop ringing. No leds for digital inputs. + if(offhook && !IS_SET(xpd->offhook, newchanno)) { // OFFHOOK + LINE_DBG(SIGNAL, xpd, newchanno, "OFFHOOK\n"); + update_line_status(xpd, newchanno, 1); + } else if(!offhook && IS_SET(xpd->offhook, newchanno)) { // ONHOOK + LINE_DBG(SIGNAL, xpd, newchanno, "ONHOOK\n"); + update_line_status(xpd, newchanno, 0); + } + } + } +} + +static const char dtmf_digits[] = { + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '*', '#', 'A', 'B', 'C', 'D' +}; + +/* + * This function is called with spinlocked XPD + */ +static void process_dtmf(xpd_t *xpd, xpp_line_t lines, byte val) +{ + int i; + byte digit; + bool is_down = val & 0x10; + struct FXS_priv_data *priv; + + if(!dtmf_detection) + return; + priv = xpd->priv; + val &= 0xF; + if(val <= 0) { + if(is_down) + XPD_NOTICE(xpd, "Bad DTMF value %d. Ignored\n", val); + return; + } + val--; + digit = dtmf_digits[val]; + for_each_line(xpd, i) { + if(IS_SET(lines, i)) { + int event = (is_down) ? ZT_EVENT_DTMFDOWN : ZT_EVENT_DTMFUP; + bool want_mute = IS_SET(priv->want_dtmf_mute, i); + bool want_event = IS_SET(priv->want_dtmf_events, i); + + if(want_event) { + LINE_DBG(SIGNAL, xpd, i, + "DTMF digit %s (val=%d) '%c' (want_mute=%s)\n", + (is_down)?"DOWN":"UP", val, digit, + (want_mute) ? "yes" : "no"); + } else { + LINE_DBG(SIGNAL, xpd, i, + "Ignored DTMF digit %s '%c'\n", + (is_down)?"DOWN":"UP", digit); + } + /* + * FIXME: we currently don't use the want_dtmf_mute until + * we are sure about the logic in Asterisk native bridging. + * Meanwhile, simply mute it on button press. + */ + if(is_down && want_mute) + __do_mute_dtmf(xpd, i, 1); + else + __do_mute_dtmf(xpd, i, 0); + __pcm_recompute(xpd, 0); /* XPD is locked */ + if(want_event) + zt_qevent_lock(&xpd->chans[i], event | digit); + break; + } + } +} + +static int FXS_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) +{ + unsigned long flags; + struct FXS_priv_data *priv; + byte regnum; + bool indirect; + + spin_lock_irqsave(&xpd->lock, flags); + priv = xpd->priv; + BUG_ON(!priv); + indirect = (REG_FIELD(info, regnum) == 0x1E); + regnum = (indirect) ? REG_FIELD(info, subreg) : REG_FIELD(info, regnum); + XPD_DBG(REGS, xpd, "%s reg_num=0x%X, dataL=0x%X dataH=0x%X\n", + (indirect)?"I":"D", + regnum, REG_FIELD(info, data_low), REG_FIELD(info, data_high)); + if(!SPAN_REGISTERED(xpd)) + goto out; + /* + * Process digital inputs polling results + */ + if(xpd->xbus_idx == 0 && !indirect && regnum == 0x06) + process_digital_inputs(xpd, info); + if(!indirect && regnum == SLIC_REG_DTMF) { + byte val = REG_FIELD(info, data_low); + xpp_line_t lines = BIT(REG_FIELD(info, chipsel)); + +#if 0 + XPD_DBG(SIGNAL, xpd, "DTMF result lines=0x%04X val=%d\n", + lines, val); +#endif + process_dtmf(xpd, lines, val); + } +out: + /* Update /proc info only if reply relate to the last slic read request */ + if( + REG_FIELD(&xpd->requested_reply, regnum) == REG_FIELD(info, regnum) && + REG_FIELD(&xpd->requested_reply, do_subreg) == REG_FIELD(info, do_subreg) && + REG_FIELD(&xpd->requested_reply, subreg) == REG_FIELD(info, subreg)) { + xpd->last_reply = *info; + } + spin_unlock_irqrestore(&xpd->lock, flags); + return 0; +} + +static xproto_table_t PROTO_TABLE(FXS) = { + .owner = THIS_MODULE, + .entries = { + /* Prototable Card Opcode */ + XENTRY( FXS, FXS, SIG_CHANGED ), + }, + .name = "FXS", + .type = XPD_TYPE_FXS, + .xops = { + .card_new = FXS_card_new, + .card_init = FXS_card_init, + .card_remove = FXS_card_remove, + .card_zaptel_preregistration = FXS_card_zaptel_preregistration, + .card_zaptel_postregistration = FXS_card_zaptel_postregistration, + .card_hooksig = FXS_card_hooksig, + .card_tick = FXS_card_tick, + .card_pcm_fromspan = generic_card_pcm_fromspan, + .card_pcm_tospan = generic_card_pcm_tospan, + .card_open = FXS_card_open, + .card_close = FXS_card_close, + .card_ioctl = FXS_card_ioctl, + .card_register_reply = FXS_card_register_reply, + + .RING = XPROTO_CALLER(FXS, RING), + .RELAY_OUT = XPROTO_CALLER(FXS, RELAY_OUT), + .XPD_STATE = XPROTO_CALLER(FXS, XPD_STATE), + }, + .packet_is_valid = fxs_packet_is_valid, + .packet_dump = fxs_packet_dump, +}; + +static bool fxs_packet_is_valid(xpacket_t *pack) +{ + const xproto_entry_t *xe; + + // DBG(GENERAL, "\n"); + xe = xproto_card_entry(&PROTO_TABLE(FXS), XPACKET_OP(pack)); + return xe != NULL; +} + +static void fxs_packet_dump(const char *msg, xpacket_t *pack) +{ + DBG(GENERAL, "%s\n", msg); +} + +/*------------------------- SLIC Handling --------------------------*/ + +static int proc_fxs_info_read(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + unsigned long flags; + xpd_t *xpd = data; + struct FXS_priv_data *priv; + int i; + int led; + + if(!xpd) + return -ENODEV; + spin_lock_irqsave(&xpd->lock, flags); + priv = xpd->priv; + BUG_ON(!priv); + len += sprintf(page + len, "%-8s %-10s %-10s %-10s\n", + "Channel", + "idletxhookstate", + "lasttxhook", + "ohttimer" + ); + for_each_line(xpd, i) { + char pref; + + if(IS_SET(xpd->digital_outputs, i)) + pref = 'O'; + else if(IS_SET(xpd->digital_inputs, i)) + pref = 'I'; + else + pref = ' '; + len += sprintf(page + len, "%c%7d %10d %10d %10d\n", + pref, + i, + priv->idletxhookstate[i], + priv->lasttxhook[i], + priv->ohttimer[i] + ); + } + len += sprintf(page + len, "\n"); + for(led = 0; led < NUM_LEDS; led++) { + len += sprintf(page + len, "LED #%d", led); + len += sprintf(page + len, "\n\t%-17s: ", "ledstate"); + for_each_line(xpd, i) { + if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) + len += sprintf(page + len, "%d ", IS_SET(priv->ledstate[led], i)); + } + len += sprintf(page + len, "\n\t%-17s: ", "ledcontrol"); + for_each_line(xpd, i) { + if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) + len += sprintf(page + len, "%d ", IS_SET(priv->ledcontrol[led], i)); + } + len += sprintf(page + len, "\n\t%-17s: ", "led_counter"); + for_each_line(xpd, i) { + if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) + len += sprintf(page + len, "%d ", LED_COUNTER(priv,i,led)); + } + len += sprintf(page + len, "\n"); + } + spin_unlock_irqrestore(&xpd->lock, flags); + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; +} + +/* + * + * Direct/Indirect + * | + * | Reg# + * | | + * | | Data (only in Write) + * | | | + * | | +-+-+ + * v v v v + * FF WD 06 01 05 + * ^ ^ + * | | + * | Write/Read + * | + * Chan# + * + */ +static int handle_register_command(xpd_t *xpd, char *cmdline) +{ + unsigned chipsel; + unsigned data_low = 0; + unsigned data_high = 0; + char op; /* [W]rite, [R]ead */ + char reg_type; /* [D]irect, [I]ndirect */ + int reg_num; + int elements; + bool writing; + char *p; + reg_cmd_t regcmd; + xbus_t *xbus; + int ret = -EINVAL; + + BUG_ON(!xpd); + xbus = xpd->xbus; + if((p = strchr(cmdline, '#')) != NULL) /* Truncate comments */ + *p = '\0'; + if((p = strchr(cmdline, ';')) != NULL) /* Truncate comments */ + *p = '\0'; + for(p = cmdline; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */ + ; + if(*p == '\0') + return 0; + if(!XBUS_GET(xbus)) { + XBUS_DBG(GENERAL, xbus, "Dropped packet. Is shutting down.\n"); + return -EBUSY; + } + elements = sscanf(cmdline, "%d %c%c %x %x %x", + &chipsel, + &op, ®_type, ®_num, + &data_low, + &data_high); + XPD_DBG(REGS, xpd, "'%s': %d %c%c %02X %02X %02X\n", cmdline, chipsel, op, reg_type, reg_num, data_low, data_high); + if(elements < 4) { // At least: chipsel, op, reg_type, reg_num + ERR("Not enough arguments: (%d args) '%s'\n", elements, cmdline); + goto out; + } + if(!VALID_CHIPSEL(chipsel)) { + ERR("Bad chipsel number: %d\n", chipsel); + goto out; + } + REG_FIELD(®cmd, chipsel) = chipsel; + switch(op) { + case 'W': + writing = 1; + break; + case 'R': + writing = 0; + break; + default: + ERR("Unkown operation type '%c'\n", op); + goto out; + } + switch(reg_type) { + case 'I': + REG_FIELD(®cmd, do_subreg) = 1; + REG_FIELD(®cmd, regnum) = 0x1E; // FIXME: card dependent... + REG_FIELD(®cmd, subreg) = reg_num; + break; + case 'D': + REG_FIELD(®cmd, do_subreg) = 0; + REG_FIELD(®cmd, regnum) = reg_num; + REG_FIELD(®cmd, subreg) = 0; + break; + default: + ERR("Unkown register type '%c'\n", reg_type); + goto out; + } + if( + (op == 'W' && reg_type == 'D' && elements != 5) || + (op == 'W' && reg_type == 'I' && elements != 6) || + (op == 'R' && reg_type == 'D' && elements != 4) || + (op == 'R' && reg_type == 'I' && elements != 4) + ) { + ERR("%s: '%s' (%d elements): %d %c%c %02X %02X %02X\n", __FUNCTION__, + cmdline, elements, + chipsel, op, reg_type, reg_num, data_low, data_high); + goto out; + } + regcmd.bytes = sizeof(regcmd) - 1; + REG_FIELD(®cmd, data_low) = data_low; + REG_FIELD(®cmd, data_high) = data_high; + REG_FIELD(®cmd, read_request) = writing; + xpd->requested_reply = regcmd; + if(print_dbg) + dump_reg_cmd("FXS", ®cmd, 1); + ret = xpp_register_request(xpd->xbus, xpd, + REG_FIELD(®cmd, chipsel), + writing, + REG_FIELD(®cmd, do_subreg), + REG_FIELD(®cmd, regnum), + REG_FIELD(®cmd, subreg), + REG_FIELD(®cmd, data_low), + REG_FIELD(®cmd, data_high)); +out: + XBUS_PUT(xbus); + return ret; +} + +static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data) +{ + xpd_t *xpd = data; + char buf[MAX_PROC_WRITE]; + char *p; + int i; + int ret; + + if(!xpd) + return -ENODEV; + for(i = 0; i < count; /* noop */) { + for(p = buf; p < buf + MAX_PROC_WRITE; p++) { /* read a line */ + if(i >= count) + break; + if(get_user(*p, buffer + i)) + return -EFAULT; + i++; + if(*p == '\n' || *p == '\r') /* whatever */ + break; + } + if(p >= buf + MAX_PROC_WRITE) + return -E2BIG; + *p = '\0'; + ret = handle_register_command(xpd, buf); + if(ret < 0) + return ret; + msleep(1); + } + return count; +} + +static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + unsigned long flags; + xpd_t *xpd = data; + reg_cmd_t *info; + byte regnum; + bool indirect; + + if(!xpd) + return -ENODEV; + spin_lock_irqsave(&xpd->lock, flags); + info = &xpd->last_reply; + indirect = (REG_FIELD(info, regnum) == 0x1E); + regnum = (indirect) ? REG_FIELD(info, subreg) : REG_FIELD(info, regnum); + len += sprintf(page + len, "# Writing bad data into this file may damage your hardware!\n"); + len += sprintf(page + len, "# Consult firmware docs first\n"); + len += sprintf(page + len, "#\n"); + len += sprintf(page + len, "#CH\tD/I\tReg.\tDL DH\n"); + len += sprintf(page + len, "%2d\tR%c\t%02X\t%02X %02X\n", + REG_FIELD(info, chipsel), + (indirect)?'I':'D', + regnum, REG_FIELD(info, data_low), REG_FIELD(info, data_high)); + spin_unlock_irqrestore(&xpd->lock, flags); + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; +} + +#ifdef WITH_METERING +static int proc_xpd_metering_write(struct file *file, const char __user *buffer, unsigned long count, void *data) +{ + xpd_t *xpd = data; + char buf[MAX_PROC_WRITE]; + lineno_t chan; + int num; + int ret; + + if(!xpd) + return -ENODEV; + if(count >= MAX_PROC_WRITE - 1) { + XPD_ERR(xpd, "Metering string too long (%lu)\n", count); + return -EINVAL; + } + if(copy_from_user(&buf, buffer, count)) + return -EFAULT; + buf[count] = '\0'; + ret = sscanf(buf, "%d", &num); + if(ret != 1) { + XPD_ERR(xpd, "Metering value should be number. Got '%s'\n", buf); + return -EINVAL; + } + chan = num; + if(chan != ALL_CHANS && chan > xpd->channels) { + XPD_ERR(xpd, "Metering tone: bad channel number %d\n", chan); + return -EINVAL; + } + if((ret = metering_gen(xpd, chan, 1)) < 0) { + XPD_ERR(xpd, "Failed sending metering tone\n"); + return ret; + } + return count; +} +#endif + +int __init card_fxs_startup(void) +{ + INFO("revision %s\n", XPP_VERSION); +#ifdef POLL_DIGITAL_INPUTS + INFO("FEATURE: with DIGITAL INPUTS support (polled every %d msec)\n", + poll_digital_inputs); +#else + INFO("FEATURE: without DIGITAL INPUTS support\n"); +#endif +#ifdef ZT_VMWI + INFO("FEATURE: ZT_VMWI\n"); +#else + INFO("FEATURE: NO ZT_VMWI\n"); +#endif +#ifdef WITH_METERING + INFO("FEATURE: WITH METERING Generation\n"); +#else + INFO("FEATURE: NO METERING Generation\n"); +#endif + xproto_register(&PROTO_TABLE(FXS)); + return 0; +} + +void __exit card_fxs_cleanup(void) +{ + xproto_unregister(&PROTO_TABLE(FXS)); +} + +MODULE_DESCRIPTION("XPP FXS Card Driver"); +MODULE_AUTHOR("Oron Peled "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(XPP_VERSION); +MODULE_ALIAS_XPD(XPD_TYPE_FXS); + +module_init(card_fxs_startup); +module_exit(card_fxs_cleanup); diff --git a/kernel/xpp/card_fxs.h b/kernel/xpp/card_fxs.h new file mode 100644 index 0000000..6a89228 --- /dev/null +++ b/kernel/xpp/card_fxs.h @@ -0,0 +1,45 @@ +#ifndef CARD_FXS_H +#define CARD_FXS_H +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "xpd.h" + +enum fxs_opcodes { + XPROTO_NAME(FXS, SIG_CHANGED) = 0x06, +/**/ + XPROTO_NAME(FXS, XPD_STATE) = 0x0F, /* Write to SLIC */ + XPROTO_NAME(FXS, CHAN_POWER) = 0x0F, /* Write to SLIC */ + XPROTO_NAME(FXS, CHAN_CID) = 0x0F, /* Write to SLIC */ + XPROTO_NAME(FXS, RING) = 0x0F, /* Write to SLIC */ + XPROTO_NAME(FXS, LED) = 0x0F, /* Write to SLIC */ + XPROTO_NAME(FXS, RELAY_OUT) = 0x0F, /* Write to SLIC */ +}; + + +DEF_RPACKET_DATA(FXS, SIG_CHANGED, + byte type; /* unused -- we have it from DEV_DESC */ + xpp_line_t sig_status; /* channels: lsb=1, msb=8 */ + xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */ + ); + +#endif /* CARD_FXS_H */ diff --git a/kernel/xpp/card_global.c b/kernel/xpp/card_global.c new file mode 100644 index 0000000..05f4008 --- /dev/null +++ b/kernel/xpp/card_global.c @@ -0,0 +1,342 @@ +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include "xdefs.h" +#include "xpd.h" +#include "xpp_zap.h" +#include "xproto.h" +#include "zap_debug.h" +#include "xbus-core.h" +#include "parport_debug.h" + +static const char rcsid[] = "$Id$"; + +DEF_PARM(charp,initdir, "/usr/share/zaptel", 0644, "The directory of card initialization scripts"); + +extern int print_dbg; + +/*---------------- GLOBAL Protocol Commands -------------------------------*/ + +static bool global_packet_is_valid(xpacket_t *pack); +static void global_packet_dump(const char *msg, xpacket_t *pack); + +/*---------------- GLOBAL: HOST COMMANDS ----------------------------------*/ + +/* 0x04 */ HOSTCMD(GLOBAL, DESC_REQ, int xpd_num) +{ + int ret = 0; + xframe_t *xframe; + xpacket_t *pack; + + if(!xbus) { + DBG(GENERAL, "NO XBUS\n"); + return -EINVAL; + } + XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, DESC_REQ, xpd_num); + XBUS_DBG(GENERAL, xbus, "to %1d%1d\n", XBUS_UNIT(xpd_num), XBUS_SUBUNIT(xpd_num)); + ret = send_cmd_frame(xbus, xframe); + XBUS_COUNTER(xbus, DESC_REQ)++; + return ret; +} + +int xpp_register_request(xbus_t *xbus, xpd_t *xpd, + byte chipsel, bool writing, bool do_subreg, byte regnum, byte subreg, byte data_low, byte data_high) +{ + int ret = 0; + xframe_t *xframe; + xpacket_t *pack; + reg_cmd_t *reg_cmd; + + if(!xbus) { + DBG(REGS, "NO XBUS\n"); + return -EINVAL; + } + XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx); + LINE_DBG(REGS, xpd, chipsel, "%c%c R%02X S%02X %02X %02X\n", + (writing)?'W':'R', + (do_subreg)?'S':'D', + regnum, subreg, data_low, data_high); + reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd); + reg_cmd->bytes = sizeof(*reg_cmd) - 1; // do not count the 'bytes' field + reg_cmd->eoframe = 0; + reg_cmd->multibyte = 0; + REG_FIELD(reg_cmd, chipsel) = chipsel; + REG_FIELD(reg_cmd, reserved) = 0; /* force reserved bits to 0 */ + REG_FIELD(reg_cmd, read_request) = (writing) ? 0 : 1; + REG_FIELD(reg_cmd, do_subreg) = do_subreg; + REG_FIELD(reg_cmd, regnum) = regnum; + REG_FIELD(reg_cmd, subreg) = subreg; + REG_FIELD(reg_cmd, data_low) = data_low; + REG_FIELD(reg_cmd, data_high) = data_high; + ret = send_cmd_frame(xbus, xframe); + return ret; +} + +/* + * The XPD parameter is totaly ignored by the driver and firmware as well. + */ +/* 0x19 */ HOSTCMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift) +{ + xframe_t *xframe; + xpacket_t *pack; + const char *mode_name; + + BUG_ON(!xbus); + if((mode_name = sync_mode_name(mode)) == NULL) { + XBUS_ERR(xbus, "SYNC_SOURCE: bad sync_mode=0x%X\n", mode); + return -EINVAL; + } + XBUS_DBG(SYNC, xbus, "%s (0x%X), drift=%d\n", mode_name, mode, drift); + XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, SYNC_SOURCE, 0); + RPACKET_FIELD(pack, GLOBAL, SYNC_SOURCE, sync_mode) = mode; + RPACKET_FIELD(pack, GLOBAL, SYNC_SOURCE, drift) = drift; + send_cmd_frame(xbus, xframe); + return 0; +} + +/* 0x23 */ HOSTCMD(GLOBAL, RESET_SYNC_COUNTERS) +{ + xframe_t *xframe; + xpacket_t *pack; + + BUG_ON(!xbus); + //XBUS_DBG(SYNC, xbus, "\n"); + XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, RESET_SYNC_COUNTERS, 0); + RPACKET_FIELD(pack, GLOBAL, RESET_SYNC_COUNTERS, mask) = 0x10; + send_cmd_frame(xbus, xframe); + return 0; +} + +/*---------------- GLOBAL: Astribank Reply Handlers -----------------------*/ + +HANDLER_DEF(GLOBAL, NULL_REPLY) +{ + XBUS_DBG(GENERAL, xbus, "got len=%d\n", XPACKET_LEN(pack)); + return 0; +} + +HANDLER_DEF(GLOBAL, DEV_DESC) +{ + struct card_desc_struct *card_desc; + + BUG_ON(!xbus); + if((card_desc = KZALLOC(sizeof(struct card_desc_struct), GFP_ATOMIC)) == NULL) { + XBUS_ERR(xbus, "Card description allocation failed.\n"); + return -ENOMEM; + } + card_desc->magic = CARD_DESC_MAGIC; + INIT_LIST_HEAD(&card_desc->card_list); + card_desc->xbus = xbus; + card_desc->type = RPACKET_FIELD(pack, GLOBAL, DEV_DESC, type); + card_desc->subtype = RPACKET_FIELD(pack, GLOBAL, DEV_DESC, subtype); + card_desc->rev = RPACKET_FIELD(pack, GLOBAL, DEV_DESC, rev); + card_desc->xpd_addr = RPACKET_FIELD(pack, GLOBAL, DEV_DESC, head.addr); + card_desc->line_status = RPACKET_FIELD(pack, GLOBAL, DEV_DESC, line_status); + XBUS_DBG(GENERAL, xbus, "XPD=%d%d type=%d.%d rev=%d line_status=0x%04X\n", + card_desc->xpd_addr.unit, + card_desc->xpd_addr.subunit, + card_desc->type, + card_desc->subtype, + card_desc->rev, + card_desc->line_status); + xbus_poller_notify(xbus, card_desc); + return 0; +} + +HANDLER_DEF(GLOBAL, REGISTER_REPLY) +{ + reg_cmd_t *reg = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REPLY, regcmd); + + if(!xpd) { + XBUS_NOTICE(xbus, "%s: received %s for non-existing unit (%1d%1d)\n", + __FUNCTION__, cmd->name, + XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack)); + return -EPROTO; + } + return CALL_XMETHOD(card_register_reply, xbus, xpd, reg); +} + +HANDLER_DEF(GLOBAL, SYNC_REPLY) +{ + byte mode = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, sync_mode); + byte drift = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, drift); + const char *mode_name; + + BUG_ON(!xbus); + if((mode_name = sync_mode_name(mode)) == NULL) { + XBUS_ERR(xbus, "SYNC_REPLY: bad sync_mode=0x%X\n", mode); + return -EINVAL; + } + XBUS_DBG(SYNC, xbus, "%s (0x%X), drift=%d\n", mode_name, mode, drift); + //dump_packet("SYNC_REPLY", pack, print_dbg & DBG_SYNC); + got_new_syncer(xbus, mode, drift); + return 0; +} + +#define TMP_NAME_LEN (XBUS_NAMELEN + XPD_NAMELEN + 5) + +HANDLER_DEF(GLOBAL, ERROR_CODE) +{ + byte errorcode = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, errorcode); + reg_cmd_t *bad_cmd; + char tmp_name[TMP_NAME_LEN]; + static long rate_limit; + + BUG_ON(!xbus); + if((rate_limit++ % 5003) > 200) + return 0; + if(!xpd) { + snprintf(tmp_name, TMP_NAME_LEN, "%s(%1d%1d)", xbus->busname, + XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack)); + } else { + snprintf(tmp_name, TMP_NAME_LEN, "%s/%s", xbus->busname, xpd->xpdname); + } + NOTICE("%s: FIRMWARE: %s CODE = 0x%X (rate_limit=%ld)\n", + tmp_name, cmd->name, errorcode, rate_limit); + switch(errorcode) { + case 1: + bad_cmd = &RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, info.bad_spi_cmd); + dump_packet("FIRMWARE: BAD_SPI_CMD", pack, 1); + break; + case 0xAB: + dump_packet("FIRMWARE: BAD_PACKET_LEN", pack, 1); + break; + default: + NOTICE("%s: FIRMWARE: %s UNKNOWN CODE = 0x%X\n", tmp_name, cmd->name, errorcode); + dump_packet("PACKET", pack, 1); + } + /* + * FIXME: Should implement an error recovery plan + */ + return 0; +} + + +xproto_table_t PROTO_TABLE(GLOBAL) = { + .entries = { + /* Prototable Card Opcode */ + XENTRY( GLOBAL, GLOBAL, NULL_REPLY ), + XENTRY( GLOBAL, GLOBAL, DEV_DESC ), + XENTRY( GLOBAL, GLOBAL, SYNC_REPLY ), + XENTRY( GLOBAL, GLOBAL, ERROR_CODE ), + XENTRY( GLOBAL, GLOBAL, REGISTER_REPLY ), + }, + .name = "GLOBAL", + .packet_is_valid = global_packet_is_valid, + .packet_dump = global_packet_dump, +}; + +static bool global_packet_is_valid(xpacket_t *pack) +{ + const xproto_entry_t *xe; + + //DBG(GENERAL, "\n"); + xe = xproto_global_entry(XPACKET_OP(pack)); + return xe != NULL; +} + +static void global_packet_dump(const char *msg, xpacket_t *pack) +{ + DBG(GENERAL, "%s\n", msg); +} + +#define MAX_ENV_STR 40 +#define MAX_PATH_STR 60 + +int run_initialize_registers(xpd_t *xpd) +{ + int ret; + xbus_t *xbus; + char busstr[MAX_ENV_STR]; + char xpdstr[MAX_ENV_STR]; + char unitstr[MAX_ENV_STR]; + char subunitstr[MAX_ENV_STR]; + char typestr[MAX_ENV_STR]; + char revstr[MAX_ENV_STR]; + char connectorstr[MAX_ENV_STR]; + char init_card[MAX_PATH_STR]; + char *argv[] = { + init_card, + NULL + }; + char *envp[] = { + busstr, + xpdstr, + unitstr, + subunitstr, + typestr, + revstr, + connectorstr, + NULL + }; + + BUG_ON(!xpd); + xbus = xpd->xbus; + if(!initdir || !initdir[0]) { + XPD_NOTICE(xpd, "Missing initdir parameter\n"); + return -EINVAL; + } + snprintf(busstr, MAX_ENV_STR, "XPD_BUS=%s", xbus->busname); + snprintf(xpdstr, MAX_ENV_STR, "XPD_NAME=%s", xpd->xpdname); + snprintf(unitstr, MAX_ENV_STR, "XPD_UNIT=%d", xpd->addr.unit); + snprintf(subunitstr, MAX_ENV_STR, "XPD_SUBUNIT=%d", xpd->addr.subunit); + snprintf(typestr, MAX_ENV_STR, "XPD_TYPE=%d", xpd->type); + snprintf(revstr, MAX_ENV_STR, "XPD_REVISION=%d", xpd->revision); + snprintf(connectorstr, MAX_ENV_STR, "XBUS_CONNECTOR=%s", xbus->busdesc); + if(snprintf(init_card, MAX_PATH_STR, "%s/init_card_%d_%d", + initdir, xpd->type, xpd->revision) > MAX_PATH_STR) { + XPD_NOTICE(xpd, "Cannot initialize. pathname is longer than %d characters.\n", MAX_PATH_STR); + return -E2BIG; + } + if(!XBUS_GET(xbus)) { + XBUS_ERR(xbus, "Skipped register initialization. XBUS is going down\n"); + return -ENODEV; + } + XPD_DBG(GENERAL, xpd, "running '%s' for type=%d revision=%d\n", + init_card, xpd->type, xpd->revision); + ret = call_usermodehelper(init_card, argv, envp, 1); + /* + * Carefully report results + */ + if(ret == 0) + XPD_DBG(GENERAL, xpd, "'%s' finished OK\n", init_card); + else if(ret < 0) { + XPD_ERR(xpd, "Failed running '%s' (errno %d)\n", init_card, ret); + } else { + byte exitval = ((unsigned)ret >> 8) & 0xFF; + byte sigval = ret & 0xFF; + + if(!exitval) { + XPD_ERR(xpd, "'%s' killed by signal %d\n", init_card, sigval); + } else { + XPD_ERR(xpd, "'%s' aborted with exitval %d\n", init_card, exitval); + } + ret = -EINVAL; + } + XBUS_PUT(xbus); + return ret; +} + +EXPORT_SYMBOL(sync_mode_name); +EXPORT_SYMBOL(run_initialize_registers); +EXPORT_SYMBOL(xpp_register_request); diff --git a/kernel/xpp/card_global.h b/kernel/xpp/card_global.h new file mode 100644 index 0000000..250f4f4 --- /dev/null +++ b/kernel/xpp/card_global.h @@ -0,0 +1,94 @@ +#ifndef CARD_GLOBAL_H +#define CARD_GLOBAL_H +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "xdefs.h" +#include "xbus-pcm.h" + +enum global_opcodes { + XPROTO_NAME(GLOBAL, DESC_REQ) = 0x04, + XPROTO_NAME(GLOBAL, DEV_DESC) = 0x05, + XPROTO_NAME(GLOBAL, REGISTER_REQUEST) = 0x0F, + XPROTO_NAME(GLOBAL, REGISTER_REPLY) = 0x10, +/**/ + XPROTO_NAME(GLOBAL, PCM_WRITE) = 0x11, + XPROTO_NAME(GLOBAL, PCM_READ) = 0x12, +/**/ + XPROTO_NAME(GLOBAL, SYNC_SOURCE) = 0x19, + XPROTO_NAME(GLOBAL, SYNC_REPLY) = 0x1A, +/**/ + XPROTO_NAME(GLOBAL, ERROR_CODE) = 0x22, + XPROTO_NAME(GLOBAL, RESET_SYNC_COUNTERS) = 0x23, + XPROTO_NAME(GLOBAL, NULL_REPLY) = 0xFE, +}; + +DEF_RPACKET_DATA(GLOBAL, NULL_REPLY); +DEF_RPACKET_DATA(GLOBAL, DESC_REQ); +DEF_RPACKET_DATA(GLOBAL, DEV_DESC, + byte rev; /* Revision number */ + byte type:4; /* LSB: 1 - to_phone, 0 - to_line */ + byte subtype:4; /* default 0 */ + xpp_line_t line_status; /* hook/ring status, depending on unit */ + ); +DEF_RPACKET_DATA(GLOBAL, REGISTER_REQUEST, + reg_cmd_t reg_cmd; + ); +DEF_RPACKET_DATA(GLOBAL, PCM_WRITE, + xpp_line_t lines; + byte pcm[PCM_CHUNKSIZE]; + ); +DEF_RPACKET_DATA(GLOBAL, PCM_READ, + xpp_line_t lines; + byte pcm[PCM_CHUNKSIZE]; + ); +DEF_RPACKET_DATA(GLOBAL, SYNC_SOURCE, + byte sync_mode; + byte drift; + ); +DEF_RPACKET_DATA(GLOBAL, SYNC_REPLY, + byte sync_mode; + byte drift; + ); +DEF_RPACKET_DATA(GLOBAL, REGISTER_REPLY, + reg_cmd_t regcmd; + ); +DEF_RPACKET_DATA(GLOBAL, RESET_SYNC_COUNTERS, + byte mask; + ); +DEF_RPACKET_DATA(GLOBAL, ERROR_CODE, + byte errorcode; + union { + reg_cmd_t bad_spi_cmd; + } info; + ); + +/* 0x04 */ DECLARE_CMD(GLOBAL, DESC_REQ, int xpd_num); +/* 0x19 */ DECLARE_CMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift); +/* 0x23 */ DECLARE_CMD(GLOBAL, RESET_SYNC_COUNTERS); + +int xpp_register_request(xbus_t *xbus, xpd_t *xpd, + byte chipsel, bool writing, bool do_subreg, byte regnum, byte subreg, byte data_low, byte data_high); +extern xproto_table_t PROTO_TABLE(GLOBAL); +int run_initialize_registers(xpd_t *xpd); + +#endif /* CARD_GLOBAL_H */ diff --git a/kernel/xpp/card_pri.c b/kernel/xpp/card_pri.c new file mode 100644 index 0000000..e055953 --- /dev/null +++ b/kernel/xpp/card_pri.c @@ -0,0 +1,1673 @@ +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * Parts derived from Cologne demo driver for the chip. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include "xpd.h" +#include "xproto.h" +#include "xpp_zap.h" +#include "card_pri.h" +#include "zap_debug.h" +#include "xpd.h" +#include "xbus-core.h" + +static const char rcsid[] = "$Id$"; + +DEF_PARM(int, print_dbg, 0, 0644, "Print DBG statements"); /* must be before zap_debug.h */ +DEF_PARM(uint, poll_interval, 500, 0644, "Poll channel state interval in milliseconds (0 - disable)"); +#ifdef DEBUG_PCMTX +DEF_PARM(int, pcmtx, -1, 0644, "Forced PCM value to transmit (negative to disable)"); +DEF_PARM(int, pcmtx_chan, 0, 0644, "channel to force PCM value"); +#endif + +#define PRI_LINES_BITMASK BITMASK(31) +#define PRI_DCHAN_SIGCAP ( \ + ZT_SIG_EM | \ + ZT_SIG_CLEAR | \ + ZT_SIG_FXSLS | \ + ZT_SIG_FXSGS | \ + ZT_SIG_FXSKS | \ + ZT_SIG_FXOLS | \ + ZT_SIG_FXOGS | \ + ZT_SIG_FXOKS | \ + ZT_SIG_CAS | \ + ZT_SIG_SF \ + ) +#define PRI_BCHAN_SIGCAP ZT_SIG_CLEAR + + +/*---------------- PRI Protocol Commands ----------------------------------*/ + +static bool pri_packet_is_valid(xpacket_t *pack); +static void pri_packet_dump(const char *msg, xpacket_t *pack); +static int proc_pri_info_read(char *page, char **start, off_t off, int count, int *eof, void *data); +static int proc_pri_info_write(struct file *file, const char __user *buffer, unsigned long count, void *data); +static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data); +static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data); +static int pri_startup(struct zt_span *span); +static int pri_shutdown(struct zt_span *span); + +#define PROC_REGISTER_FNAME "slics" +#define PROC_PRI_INFO_FNAME "pri_info" + +#define VALID_CHIPSEL(x) ((x) == 0) + +enum pri_protocol { + PRI_PROTO_0 = 0, + PRI_PROTO_E1 = 1, + PRI_PROTO_T1 = 2, + PRI_PROTO_J1 = 3 +}; + +static const char *pri_protocol_name(enum pri_protocol pri_protocol) +{ + static const char *protocol_names[] = { + [PRI_PROTO_0] = "Unknown", + [PRI_PROTO_E1] = "E1", + [PRI_PROTO_T1] = "T1", + [PRI_PROTO_J1] = "J1" + }; + return protocol_names[pri_protocol]; +} + +static int pri_num_channels(enum pri_protocol pri_protocol) +{ + static int num_channels[] = { + [PRI_PROTO_0] = 0, + [PRI_PROTO_E1] = 31, + [PRI_PROTO_T1] = 24, + [PRI_PROTO_J1] = 0 + }; + return num_channels[pri_protocol]; +} + +static const char *type_name(enum pri_protocol pri_protocol, bool is_nt) +{ + static const char *names[2][4] = { + /* TE */ [0] = { + [PRI_PROTO_0] = "Unknown_TE", + [PRI_PROTO_E1] = "E1_TE", + [PRI_PROTO_T1] = "T1_TE", + [PRI_PROTO_J1] = "J1_TE" + }, + /* NT */ [1] = { + [PRI_PROTO_0] = "Unknown_NT", + [PRI_PROTO_E1] = "E1_NT", + [PRI_PROTO_T1] = "T1_NT", + [PRI_PROTO_J1] = "J1_NT" + } + }; + int term = (is_nt) ? 1 : 0; + + return names[term][pri_protocol]; +} + +static int pri_linecompat(enum pri_protocol pri_protocol) +{ + static const int linecompat[] = { + [PRI_PROTO_0] = 0, + [PRI_PROTO_E1] = + /* coding */ + ZT_CONFIG_CCS | + // CAS | + ZT_CONFIG_CRC4 | + /* framing */ + ZT_CONFIG_AMI | ZT_CONFIG_HDB3, + [PRI_PROTO_T1] = + /* coding */ + // ZT_CONFIG_D4 | + ZT_CONFIG_ESF | + /* framing */ + ZT_CONFIG_AMI | ZT_CONFIG_B8ZS, + [PRI_PROTO_J1] = 0 + }; + + DBG(GENERAL, "pri_linecompat: pri_protocol=%d\n", pri_protocol); + return linecompat[pri_protocol]; +} + +#define PRI_DCHAN_IDX(priv) ((priv)->dchan_num - 1) + +enum pri_led_state { + PRI_LED_OFF = 0x0, + PRI_LED_ON = 0x1, + /* + * We blink by software from driver, so that + * if the driver malfunction that blink would stop. + */ + // PRI_LED_BLINK_SLOW = 0x2, /* 1/2 a second blink cycle */ + // PRI_LED_BLINK_FAST = 0x3 /* 1/4 a second blink cycle */ +}; + +enum pri_led_selectors { + TE_RED_LED = 0, + TE_GREEN_LED = 1, + NT_RED_LED = 2, + NT_GREEN_LED = 3, +}; + +#define NUM_LEDS 4 + +struct pri_leds { + byte state:2; /* enum pri_led_state */ + byte led_sel:2; /* enum pri_led_selectors */ + byte reserved:4; +}; + +#define REG_FRS0 0x4C /* Framer Receive Status Register 0 */ +#define REG_FRS0_RRA BIT(4) /* Receive Remote Alarm: T1-YELLOW-Alarm */ +#define REG_FRS0_LFA BIT(5) /* Loss of Frame Alignment */ +#define REG_FRS0_AIS BIT(6) /* Alarm Indication Signal: T1-BLUE-Alarm */ +#define REG_FRS0_LOS BIT(7) /* Los Of Signal: T1-RED-Alarm */ + +#define REG_FRS1 0x4D /* Framer Receive Status Register 1 */ + +#define REG_LIM0 0x36 +#define REG_LIM0_MAS BIT(0) /* Master Mode, DCO-R circuitry is frequency + synchronized to the clock supplied by SYNC */ +#define REG_LIM0_RTRS BIT(5) /* + * Receive Termination Resistance Selection: + * integrated resistor to create 75 Ohm termination (100 || 300 = 75) + * 0 = 100 Ohm + * 1 = 75 Ohm + */ +#define REG_LIM0_LL BIT(1) /* LL (Local Loopback) */ + +#define REG_FMR0 0x1C +#define REG_FMR0_E_RC0 BIT(4) /* Receive Code - LSB */ +#define REG_FMR0_E_RC1 BIT(5) /* Receive Code - MSB */ +#define REG_FMR0_E_XC0 BIT(6) /* Transmit Code - LSB */ +#define REG_FMR0_E_XC1 BIT(7) /* Transmit Code - MSB */ + +#define REG_FMR1 0x1D +#define REG_FMR1_XAIS BIT(0) /* Transmit AIS toward transmit end */ +#define REG_FMR1_SSD0 BIT(1) +#define REG_FMR1_ECM BIT(2) +#define REG_FMR1_XFS BIT(3) +#define REG_FMR1_PMOD BIT(4) /* E1 = 0, T1/J1 = 1 */ +#define REG_FMR1_EDL BIT(5) +#define REG_FMR1_AFR BIT(6) + +#define REG_FMR2 0x1E +#define REG_FMR2_E_ALMF BIT(0) /* Automatic Loss of Multiframe */ +#define REG_FMR2_T_EXZE BIT(0) /* Excessive Zeros Detection Enable */ +#define REG_FMR2_E_AXRA BIT(1) /* Automatic Transmit Remote Alarm */ +#define REG_FMR2_T_AXRA BIT(1) /* Automatic Transmit Remote Alarm */ +#define REG_FMR2_E_PLB BIT(2) /* Payload Loop-Back */ +#define REG_FMR2_E_RFS0 BIT(6) /* Receive Framing Select - LSB */ +#define REG_FMR2_E_RFS1 BIT(7) /* Receive Framing Select - MSB */ +#define REG_FMR2_T_SSP BIT(5) /* Select Synchronization/Resynchronization Procedure */ +#define REG_FMR2_T_MCSP BIT(6) /* Multiple Candidates Synchronization Procedure */ +#define REG_FMR2_T_AFRS BIT(7) /* Automatic Force Resynchronization */ + +#define REG_FMR4 0x20 +#define REG_FMR4_FM1 BIT(1) + +#define REG_XSP_E 0x21 +#define REG_FMR5_T 0x21 +#define REG_XSP_E_XSIF BIT(2) /* Transmit Spare Bit For International Use (FAS Word) */ +#define REG_FMR5_T_XTM BIT(2) /* Transmit Transparent Mode */ +#define REG_XSP_E_AXS BIT(3) /* Automatic Transmission of Submultiframe Status */ +#define REG_XSP_E_EBP BIT(4) /* E-Bit Polarity, Si-bit position of every outgoing CRC multiframe */ +#define REG_XSP_E_CASEN BIT(7) /* Channel Associated Signaling Enable */ + +#define REG_RC0 0x24 +#define REG_RC0_SJR BIT(7) /* T1 = 0, J1 = 1 */ + + +struct PRI_priv_data { + bool is_nt; + struct proc_dir_entry *regfile; + struct proc_dir_entry *pri_info; + enum pri_protocol pri_protocol; + int deflaw; + unsigned int dchan_num; + bool initialized; + bool local_loopback; + reg_cmd_t requested_reply; + reg_cmd_t last_reply; + uint poll_noreplies; + uint layer1_replies; + byte reg_frs0; + byte reg_frs1; + bool layer1_up; + byte dchan_tx_sample; + byte dchan_rx_sample; + uint dchan_tx_counter; + uint dchan_rx_counter; + bool dchan_alive; + uint dchan_alive_ticks; + enum pri_led_state ledstate[NUM_LEDS]; +}; + +static xproto_table_t PROTO_TABLE(PRI); + +DEF_RPACKET_DATA(PRI, SET_LED, /* Set one of the LED's */ + struct pri_leds pri_leds; + ); + + +static /* 0x33 */ DECLARE_CMD(PRI, SET_LED, enum pri_led_selectors led_sel, enum pri_led_state to_led_state); + +#define DO_LED(xpd, which, tostate) \ + CALL_PROTO(PRI, SET_LED, (xpd)->xbus, (xpd), (which), (tostate)) + +/*---------------- PRI: Methods -------------------------------------------*/ + +static int query_subunit(xpd_t *xpd, byte regnum) +{ +#if 0 + XPD_DBG(GENERAL, xpd, "(%d%d): REG=0x%02X\n", + xpd->addr.unit, xpd->addr.subunit, + regnum); +#endif + return xpp_register_request( + xpd->xbus, xpd, + 0, /* chipsel */ + 0, /* writing */ + 1, /* do_subreg */ + regnum, + xpd->addr.subunit, /* subreg */ + 0, /* data_L */ + 0); /* data_H */ +} + + +static int write_subunit(xpd_t *xpd, byte regnum, byte val) +{ + XPD_DBG(REGS, xpd, "(%d%d): REG=0x%02X dataL=0x%02X\n", + xpd->addr.unit, xpd->addr.subunit, + regnum, val); + return xpp_register_request( + xpd->xbus, xpd, + 0, /* chipsel */ + 1, /* writing */ + 1, /* do_subreg */ + regnum, + xpd->addr.subunit, /* subreg */ + val, /* data_L */ + 0); /* data_H */ +} + +static xpd_t *PRI_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table, byte subtype, byte revision) +{ + xpd_t *xpd = NULL; + struct PRI_priv_data *priv; + int channels = min(31, CHANNELS_PERXPD); /* worst case */ + + XBUS_DBG(GENERAL, xbus, "\n"); + xpd = xpd_alloc(sizeof(struct PRI_priv_data), proto_table, channels); + if(!xpd) + return NULL; + priv = xpd->priv; + xpd->revision = revision; + priv->pri_protocol = PRI_PROTO_0; /* Default, changes in set_pri_proto() */ + priv->deflaw = ZT_LAW_DEFAULT; /* Default, changes in set_pri_proto() */ + xpd->type_name = + type_name(priv->pri_protocol, 0); /* Default, changes in set_nt() */ + return xpd; +} + +static void clean_proc(xbus_t *xbus, xpd_t *xpd) +{ + struct PRI_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + XPD_DBG(PROC, xpd, "\n"); +#ifdef CONFIG_PROC_FS + if(priv->regfile) { + XPD_DBG(PROC, xpd, "Removing registers file\n"); + priv->regfile->data = NULL; + remove_proc_entry(PROC_REGISTER_FNAME, xpd->proc_xpd_dir); + } + if(priv->pri_info) { + XPD_DBG(PROC, xpd, "Removing xpd PRI_INFO file\n"); + remove_proc_entry(PROC_PRI_INFO_FNAME, xpd->proc_xpd_dir); + } +#endif +} + +static bool valid_pri_modes(const xpd_t *xpd) +{ + struct PRI_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + if( + priv->pri_protocol != PRI_PROTO_E1 && + priv->pri_protocol != PRI_PROTO_T1 && + priv->pri_protocol != PRI_PROTO_J1) + return 0; + return 1; +} + +/* + * Set E1/T1/J1 + * May only be called on unregistered xpd's + * (the span and channel description are set according to this) + */ +static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto) +{ + struct PRI_priv_data *priv; + int deflaw; + unsigned int dchan_num; + byte fmr1 = + REG_FMR1_AFR | + REG_FMR1_XFS | + REG_FMR1_ECM; + byte rc0 = 0; /* FIXME: PCM offsets */ + + BUG_ON(!xpd); + priv = xpd->priv; + if(SPAN_REGISTERED(xpd)) { + XPD_NOTICE(xpd, "Registered as span %d. Cannot do setup pri protocol (%s)\n", + xpd->span.spanno, __FUNCTION__); + return -EBUSY; + } + switch(set_proto) { + case PRI_PROTO_E1: + deflaw = ZT_LAW_ALAW; + dchan_num = 16; + break; + case PRI_PROTO_T1: + deflaw = ZT_LAW_MULAW; + dchan_num = 24; + fmr1 |= REG_FMR1_PMOD; + break; + case PRI_PROTO_J1: + /* + * Check all assumptions + */ + deflaw = ZT_LAW_MULAW; + dchan_num = 24; + fmr1 |= REG_FMR1_PMOD; + rc0 |= REG_RC0_SJR; + XPD_NOTICE(xpd, "J1 is not supported yet\n"); + return -ENOSYS; + default: + XPD_ERR(xpd, "%s: Unknown pri protocol = %d\n", + __FUNCTION__, set_proto); + return -EINVAL; + } + priv->pri_protocol = set_proto; + xpd->channels = pri_num_channels(set_proto); + xpd->pcm_len = RPACKET_HEADERSIZE + sizeof(xpp_line_t) + xpd->channels * ZT_CHUNKSIZE; + xpd->wanted_pcm_mask = BITMASK(xpd->channels); + priv->deflaw = deflaw; + priv->dchan_num = dchan_num; + xpd->type_name = type_name(priv->pri_protocol, priv->is_nt); + XPD_DBG(GENERAL, xpd, "%s, channels=%d, dchan_num=%d, deflaw=%d\n", + pri_protocol_name(set_proto), + xpd->channels, + priv->dchan_num, + priv->deflaw + ); + write_subunit(xpd, REG_FMR1, fmr1); +#ifdef JAPANEZE_SUPPORT + if(rc0) + write_subunit(xpd, REG_RC0, rc0); +#endif + return 0; +} + +/* + * Normally set by the timing parameter in zaptel.conf + * If this is called by ztcfg, than it's too late to change + * zaptel sync priority (we are already registered) + * There are two workarounds to mitigate this problem: + * 1. So we set *our* sync master at least. + * 2. And we try to call it with a sane default from set_nt() + * which is called before zaptel registration. + */ +static int set_master_mode(const char *msg, xpd_t *xpd, bool is_master_mode) +{ + struct PRI_priv_data *priv; + byte lim0 = 0; + byte xsp = 0; + + BUG_ON(!xpd); + priv = xpd->priv; + lim0 |= (priv->local_loopback) ? REG_LIM0_LL : 0; + if(is_master_mode) + lim0 |= REG_LIM0_MAS; + else + lim0 &= ~REG_LIM0_MAS; + if(priv->pri_protocol == PRI_PROTO_E1) + { + lim0 |= REG_LIM0_RTRS; /* Receive termination: Integrated resistor is switched on (100 Ohm || 300 Ohm = 75 Ohm) */ + xsp |= REG_XSP_E_EBP | REG_XSP_E_AXS | REG_XSP_E_XSIF; + } else if(priv->pri_protocol == PRI_PROTO_T1) { + lim0 &= ~REG_LIM0_RTRS; /* Receive termination: Integrated resistor is switched off (100 Ohm, no internal 300 Ohm) */; + xsp |= REG_FMR5_T_XTM; + } + XPD_DBG(SIGNAL, xpd, "%s(%s): %s\n", __FUNCTION__, msg, (is_master_mode) ? "MASTER" : "SLAVE"); + write_subunit(xpd, REG_LIM0 , lim0); + write_subunit(xpd, REG_XSP_E, xsp); + return 0; +} + +static int set_nt(const char *msg, xpd_t *xpd, bool is_nt) +{ + struct PRI_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + if(SPAN_REGISTERED(xpd)) { + XPD_NOTICE(xpd, "Registered as span %d. Cannot do %s(%s)\n", + xpd->span.spanno, __FUNCTION__, msg); + return -EBUSY; + } + priv->is_nt = is_nt; + xpd->type_name = type_name(priv->pri_protocol, is_nt); + xpd->direction = (is_nt) ? TO_PHONE : TO_PSTN; + XPD_DBG(SIGNAL, xpd, "%s(%s): %s %s\n", __FUNCTION__, msg, xpd->type_name, (is_nt) ? "NT" : "TE"); + set_master_mode(msg, xpd, is_nt); /* by default set master-mode from NT/TE */ + return 0; +} + +static int set_localloop(const char *msg, xpd_t *xpd, bool localloop) +{ + struct PRI_priv_data *priv; + byte lim0 = 0; + byte xsp = 0; + + BUG_ON(!xpd); + priv = xpd->priv; + if(SPAN_REGISTERED(xpd)) { + XPD_NOTICE(xpd, "Registered as span %d. Cannot do %s(%s)\n", + xpd->span.spanno, __FUNCTION__, msg); + return -EBUSY; + } + lim0 |= (localloop) ? REG_LIM0_LL : 0; + if(priv->is_nt) + lim0 |= REG_LIM0_MAS; + else + lim0 &= ~REG_LIM0_MAS; + if(priv->pri_protocol == PRI_PROTO_E1) + { + lim0 |= REG_LIM0_RTRS; /* Receive termination: Integrated resistor is switched on (100 Ohm || 300 Ohm = 75 Ohm) */ + xsp |= REG_XSP_E_EBP | REG_XSP_E_AXS | REG_XSP_E_XSIF; + } else if(priv->pri_protocol == PRI_PROTO_T1) { + lim0 &= ~REG_LIM0_RTRS ; /* Receive termination: Integrated resistor is switched off (100 Ohm, no internal 300 Ohm) */; + xsp |= REG_FMR5_T_XTM; + } + priv->local_loopback = localloop; + XPD_DBG(SIGNAL, xpd, "%s(%s): %s\n", __FUNCTION__, msg, (localloop) ? "LOCALLOOP" : "NO"); + write_subunit(xpd, REG_LIM0 , lim0); + write_subunit(xpd, REG_XSP_E, xsp); + return 0; +} + +#define VALID_CONFIG(bit,flg,str) [bit] = { .flags = flg, .name = str } + +static const struct { + const char *name; + const int flags; +} valid_spanconfigs[sizeof(unsigned int)*8] = { + /* These apply to T1 */ +// VALID_CONFIG(4, ZT_CONFIG_D4, "D4"), FIXME: should support + VALID_CONFIG(5, ZT_CONFIG_ESF, "ESF"), + VALID_CONFIG(6, ZT_CONFIG_AMI, "AMI"), + VALID_CONFIG(7, ZT_CONFIG_B8ZS, "B8ZS"), + /* These apply to E1 */ + VALID_CONFIG(8, ZT_CONFIG_CCS, "CCS"), + VALID_CONFIG(9, ZT_CONFIG_HDB3, "HDB3"), + VALID_CONFIG(10, ZT_CONFIG_CRC4, "CRC4"), +}; + +/* + * Called only for 'span' keyword in /etc/zaptel.conf + */ + +static int pri_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) +{ + xpd_t *xpd = span->pvt; + struct PRI_priv_data *priv; + const char *framingstr = ""; + const char *codingstr = ""; + const char *crcstr = ""; + byte fmr0 = 0; /* Dummy initilizations to */ + byte fmr2 = 0; /* silense false gcc warnings */ + byte fmr4 = 0x0C; + unsigned int bad_bits; + int i; + + BUG_ON(!xpd); + priv = xpd->priv; + /* + * validate + */ + bad_bits = lc->lineconfig & pri_linecompat(priv->pri_protocol); + bad_bits = bad_bits ^ lc->lineconfig; + for(i = 0; i < ARRAY_SIZE(valid_spanconfigs); i++) { + unsigned int flags = valid_spanconfigs[i].flags; + + if(bad_bits & BIT(i)) { + if(flags) { + XPD_ERR(xpd, + "Bad config item '%s' for %s. Ignore\n", + valid_spanconfigs[i].name, + pri_protocol_name(priv->pri_protocol)); + } else { + /* we got real garbage */ + XPD_ERR(xpd, + "Unknown config item 0x%X for %s. Ignore\n", + BIT(i), + pri_protocol_name(priv->pri_protocol)); + } + } + if(flags && flags != BIT(i)) { + ERR("%s: BUG: i=%d flags=0x%X\n", + __FUNCTION__, i, flags); + // BUG(); + } + } + if(bad_bits) + goto bad_lineconfig; + if(lc->span != xpd->span.spanno) { + XPD_ERR(xpd, "I am span %d but got spanconfig for span %d\n", + xpd->span.spanno, lc->span); + return -EINVAL; + } + /* + * FIXME: lc->name is unused by ztcfg and zaptel... + * We currently ignore it also. + */ + if(priv->pri_protocol == PRI_PROTO_E1) + fmr2 = REG_FMR2_E_AXRA | REG_FMR2_E_ALMF; /* 0x03 */ + else if(priv->pri_protocol == PRI_PROTO_T1) + fmr2 = REG_FMR2_T_SSP | REG_FMR2_T_AXRA; /* 0x22 */ + else if(priv->pri_protocol == PRI_PROTO_J1) { + XPD_ERR(xpd, "J1 unsupported yet\n"); + return -ENOSYS; + } + if(priv->local_loopback) + fmr2 |= REG_FMR2_E_PLB; + /* framing first */ + if (lc->lineconfig & ZT_CONFIG_B8ZS) { + framingstr = "B8ZS"; + fmr0 = REG_FMR0_E_XC1 | REG_FMR0_E_XC0 | REG_FMR0_E_RC1 | REG_FMR0_E_RC0; + } else if (lc->lineconfig & ZT_CONFIG_AMI) { + framingstr = "AMI"; + fmr0 = REG_FMR0_E_XC1 | REG_FMR0_E_RC1; + } else if (lc->lineconfig & ZT_CONFIG_HDB3) { + framingstr = "HDB3"; + fmr0 = REG_FMR0_E_XC1 | REG_FMR0_E_XC0 | REG_FMR0_E_RC1 | REG_FMR0_E_RC0; + } + /* then coding */ + if (lc->lineconfig & ZT_CONFIG_ESF) { + codingstr = "ESF"; + fmr4 |= REG_FMR4_FM1; + fmr2 |= REG_FMR2_T_AXRA | REG_FMR2_T_MCSP | REG_FMR2_T_SSP; + } else if (lc->lineconfig & ZT_CONFIG_D4) { + codingstr = "D4"; + } else if (lc->lineconfig & ZT_CONFIG_CCS) { + codingstr = "CCS"; + /* do nothing */ + } + /* E1's can enable CRC checking */ + if (lc->lineconfig & ZT_CONFIG_CRC4) { + crcstr = "CRC4"; + fmr2 |= REG_FMR2_E_RFS1; + } + XPD_DBG(GENERAL, xpd, "[%s] lbo=%d lineconfig=%s/%s/%s %s (0x%X) sync=%d\n", + (priv->is_nt)?"NT":"TE", + lc->lbo, + framingstr, codingstr, crcstr, + (lc->lineconfig & ZT_CONFIG_NOTOPEN)?"YELLOW":"", + lc->lineconfig, + lc->sync); + span->lineconfig = lc->lineconfig; + xpd->timing_priority = lc->sync; + if(fmr0 != 0) { + XPD_DBG(GENERAL, xpd, "%s: fmr0(0x%02X) = 0x%02X\n", __FUNCTION__, REG_FMR0, fmr0); + write_subunit(xpd, REG_FMR0, fmr0); + } + XPD_DBG(GENERAL, xpd, "%s: fmr4(0x%02X) = 0x%02X\n", __FUNCTION__, REG_FMR4, fmr4); + write_subunit(xpd, REG_FMR4, fmr4); + XPD_DBG(GENERAL, xpd, "%s: fmr2(0x%02X) = 0x%02X\n", __FUNCTION__, REG_FMR2, fmr2); + write_subunit(xpd, REG_FMR2, fmr2); + set_master_mode("spanconfig", xpd, xpd->timing_priority == 0); + elect_syncer("PRI-master_mode"); + return 0; +bad_lineconfig: + XPD_ERR(xpd, "Bad span configuration. Abort\n"); + return -EINVAL; +} + +/* + * Set signalling type (if appropriate) + * Called from zaptel with spinlock held on chan. Must not call back + * zaptel functions. + */ +static int pri_chanconfig(struct zt_chan *chan, int sigtype) +{ + DBG(GENERAL, "channel %d (%s) -> %s\n", chan->channo, chan->name, sig2str(sigtype)); + // FIXME: sanity checks: + // - should be supported (within the sigcap) + // - should not replace fxs <->fxo ??? (covered by previous?) + return 0; +} + +static int PRI_card_init(xbus_t *xbus, xpd_t *xpd) +{ + struct PRI_priv_data *priv; + int ret = 0; + xproto_table_t *proto_table; + + BUG_ON(!xpd); + XPD_DBG(GENERAL, xpd, "\n"); + xpd->type = XPD_TYPE_PRI; + proto_table = &PROTO_TABLE(PRI); + priv = xpd->priv; + xpd->xops = &proto_table->xops; +#ifdef CONFIG_PROC_FS + XPD_DBG(PROC, xpd, "Creating PRI_INFO file\n"); + priv->pri_info = create_proc_entry(PROC_PRI_INFO_FNAME, 0644, xpd->proc_xpd_dir); + if(!priv->pri_info) { + XPD_ERR(xpd, "Failed to create proc '%s'\n", PROC_PRI_INFO_FNAME); + ret = -ENOENT; + goto err; + } + priv->pri_info->owner = THIS_MODULE; + priv->pri_info->write_proc = proc_pri_info_write; + priv->pri_info->read_proc = proc_pri_info_read; + priv->pri_info->data = xpd; + XPD_DBG(PROC, xpd, "Creating registers file\n"); + priv->regfile = create_proc_entry(PROC_REGISTER_FNAME, 0644, xpd->proc_xpd_dir); + if(!priv->regfile) { + XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_REGISTER_FNAME); + ret = -ENOENT; + goto err; + } + priv->regfile->owner = THIS_MODULE; + priv->regfile->write_proc = proc_xpd_register_write; + priv->regfile->read_proc = proc_xpd_register_read; + priv->regfile->data = xpd; +#endif + /* Assume E1, changes later from user space */ + ret = set_pri_proto(xpd, PRI_PROTO_E1); + if(ret < 0) + goto err; + ret = run_initialize_registers(xpd); + if(ret < 0) + goto err; + /* + * initialization script should have set correct + * operating modes. + */ + if(!valid_pri_modes(xpd)) { + XPD_NOTICE(xpd, "PRI protocol not set\n"); + goto err; + } + XPD_DBG(GENERAL, xpd, "done\n"); + for(ret = 0; ret < NUM_LEDS; ret++) { + DO_LED(xpd, ret, PRI_LED_ON); + msleep(20); + DO_LED(xpd, ret, PRI_LED_OFF); + } + priv->initialized = 1; + return 0; +err: + clean_proc(xbus, xpd); + XPD_ERR(xpd, "Failed initializing registers (%d)\n", ret); + return ret; +} + +static int PRI_card_remove(xbus_t *xbus, xpd_t *xpd) +{ + struct PRI_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + XPD_DBG(GENERAL, xpd, "\n"); + clean_proc(xbus, xpd); + return 0; +} + +static int PRI_card_zaptel_preregistration(xpd_t *xpd, bool on) +{ + xbus_t *xbus; + struct PRI_priv_data *priv; + int i; + + BUG_ON(!xpd); + xbus = xpd->xbus; + priv = xpd->priv; + BUG_ON(!xbus); + XPD_DBG(GENERAL, xpd, "%s (proto=%s, channels=%d, deflaw=%d)\n", + (on)?"on":"off", + pri_protocol_name(priv->pri_protocol), + xpd->channels, + priv->deflaw); + if(!on) { + /* Nothing to do yet */ + return 0; + } + xpd->span.linecompat = pri_linecompat(priv->pri_protocol); + xpd->span.deflaw = priv->deflaw; + for_each_line(xpd, i) { + struct zt_chan *cur_chan = &xpd->chans[i]; + bool is_dchan = i == PRI_DCHAN_IDX(priv); + + XPD_DBG(GENERAL, xpd, "setting PRI channel %d (%s)\n", i, + (is_dchan)?"DCHAN":"CLEAR"); + snprintf(cur_chan->name, MAX_CHANNAME, "XPP_%s/%02d/%1d%1d/%d", + xpd->type_name, xbus->num, xpd->addr.unit, xpd->addr.subunit, i); + cur_chan->chanpos = i + 1; + cur_chan->pvt = xpd; + if(is_dchan) { /* D-CHAN */ + cur_chan->sigcap = PRI_DCHAN_SIGCAP; + //FIXME: cur_chan->flags |= ZT_FLAG_PRIDCHAN; + cur_chan->flags &= ~ZT_FLAG_HDLC; + } else + cur_chan->sigcap = PRI_BCHAN_SIGCAP; + } + xpd->offhook = xpd->wanted_pcm_mask; + xpd->span.spanconfig = pri_spanconfig; + xpd->span.chanconfig = pri_chanconfig; + xpd->span.startup = pri_startup; + xpd->span.shutdown = pri_shutdown; + return 0; +} + +static int PRI_card_zaptel_postregistration(xpd_t *xpd, bool on) +{ + xbus_t *xbus; + struct PRI_priv_data *priv; + + BUG_ON(!xpd); + xbus = xpd->xbus; + priv = xpd->priv; + BUG_ON(!xbus); + XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off"); + return(0); +} + +static int PRI_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig) +{ + LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig)); + return 0; +} + +static void dchan_state(xpd_t *xpd, bool up) +{ + struct PRI_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + if(priv->dchan_alive == up) + return; + if(!priv->layer1_up) /* No layer1, kill dchan */ + up = 0; + if(up) { + XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel RUNNING\n"); + priv->dchan_alive = 1; + } else { + byte *pcm; + + if(SPAN_REGISTERED(xpd)) { + pcm = (byte *)&xpd->span.chans[PRI_DCHAN_IDX(priv)].readchunk; + pcm[0] = 0x00; + pcm = (byte *)&xpd->span.chans[PRI_DCHAN_IDX(priv)].writechunk; + pcm[0] = 0x00; + } + XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel STOPPED\n"); + priv->dchan_rx_counter = priv->dchan_tx_counter = 0; + priv->dchan_alive = 0; + priv->dchan_alive_ticks = 0; + priv->dchan_rx_sample = priv->dchan_tx_sample = 0x00; + } +} + +/* + * LED managment is done by the driver now: + * - Turn constant ON RED/GREEN led to indicate NT/TE port + * - Very fast "Double Blink" to indicate Layer1 alive (without D-Channel) + * - Constant blink (1/2 sec cycle) to indicate D-Channel alive. + */ +static void handle_leds(xbus_t *xbus, xpd_t *xpd) +{ + struct PRI_priv_data *priv; + unsigned int timer_count; + int which_led; + int other_led; + enum pri_led_state ledstate; + int mod; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + if(priv->is_nt) { + which_led = NT_RED_LED; + other_led = TE_GREEN_LED; + } else { + which_led = TE_GREEN_LED; + other_led = NT_RED_LED; + } + ledstate = priv->ledstate[which_led]; + timer_count = xpd->timer_count; + if(xpd->blink_mode) { + if((timer_count % DEFAULT_LED_PERIOD) == 0) { + // led state is toggled + if(ledstate == PRI_LED_OFF) { + DO_LED(xpd, which_led, PRI_LED_ON); + DO_LED(xpd, other_led, PRI_LED_ON); + } else { + DO_LED(xpd, which_led, PRI_LED_OFF); + DO_LED(xpd, other_led, PRI_LED_OFF); + } + } + return; + } + if(priv->ledstate[other_led] != PRI_LED_OFF) + DO_LED(xpd, other_led, PRI_LED_OFF); + if(priv->dchan_alive) { + mod = timer_count % 1000; + switch(mod) { + case 0: + DO_LED(xpd, which_led, PRI_LED_ON); + break; + case 500: + DO_LED(xpd, which_led, PRI_LED_OFF); + break; + } + } else if(priv->layer1_up) { + mod = timer_count % 1000; + switch(mod) { + case 0: + case 100: + DO_LED(xpd, which_led, PRI_LED_ON); + break; + case 50: + case 150: + DO_LED(xpd, which_led, PRI_LED_OFF); + break; + } + } else { + if(priv->ledstate[which_led] != PRI_LED_ON) + DO_LED(xpd, which_led, PRI_LED_ON); + } +} + +static int PRI_card_tick(xbus_t *xbus, xpd_t *xpd) +{ + struct PRI_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + if(!priv->initialized || !xbus->self_ticking) + return 0; + /* + * Poll layer1 status (cascade subunits) + */ + if(poll_interval != 0 && + ((xpd->timer_count % poll_interval) == 0)) { + priv->poll_noreplies++; + query_subunit(xpd, REG_FRS0); + //query_subunit(xpd, REG_FRS1); + } + if(priv->dchan_tx_counter >= 1 && priv->dchan_rx_counter > 1) { + dchan_state(xpd, 1); + priv->dchan_alive_ticks++; + } + handle_leds(xbus, xpd); + return 0; +} + +static int PRI_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg) +{ + BUG_ON(!xpd); + if(!TRANSPORT_RUNNING(xpd->xbus)) + return -ENODEV; + switch (cmd) { + case ZT_TONEDETECT: + /* + * Asterisk call all span types with this (FXS specific) + * call. Silently ignore it. + */ + LINE_DBG(SIGNAL, xpd, pos, "PRI: Starting a call\n"); + return -ENOTTY; + default: + report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd); + return -ENOTTY; + } + return 0; +} + +static int PRI_card_close(xpd_t *xpd, lineno_t pos) +{ + //struct zt_chan *chan = &xpd->span.chans[pos]; + dchan_state(xpd, 0); + return 0; +} + +/* + * Called only for 'span' keyword in /etc/zaptel.conf + */ +static int pri_startup(struct zt_span *span) +{ + xpd_t *xpd = span->pvt; + struct PRI_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + if(!TRANSPORT_RUNNING(xpd->xbus)) { + XPD_DBG(GENERAL, xpd, "Startup called by zaptel. No Hardware. Ignored\n"); + return -ENODEV; + } + XPD_DBG(GENERAL, xpd, "STARTUP\n"); + // Turn on all channels + CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 1); + return 0; +} + +/* + * Called only for 'span' keyword in /etc/zaptel.conf + */ +static int pri_shutdown(struct zt_span *span) +{ + xpd_t *xpd = span->pvt; + struct PRI_priv_data *priv; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + if(!TRANSPORT_RUNNING(xpd->xbus)) { + XPD_DBG(GENERAL, xpd, "Shutdown called by zaptel. No Hardware. Ignored\n"); + return -ENODEV; + } + XPD_DBG(GENERAL, xpd, "SHUTDOWN\n"); + // Turn off all channels + CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 0); + return 0; +} + +/*! Copy PCM chunks from the buffers of the xpd to a new packet + * \param xbus xbus of source xpd. + * \param xpd source xpd. + * \param lines a bitmask of the active channels that need to be copied. + * \param pack packet to be filled. + * + * On PRI this function is should also shift the lines mask one bit, as + * channel 0 on the wire is an internal chip control channel. We only + * send 31 channels to the device, but they should be called 1-31 rather + * than 0-30 . + */ +static void PRI_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, xpacket_t *pack) +{ + struct PRI_priv_data *priv; + byte *pcm; + struct zt_chan *chans; + unsigned long flags; + int i; + int physical_chan; + int physical_mask = 0; + + BUG_ON(!xbus); + BUG_ON(!xpd); + BUG_ON(!pack); + priv = xpd->priv; + BUG_ON(!priv); + pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm); + spin_lock_irqsave(&xpd->lock, flags); + chans = xpd->span.chans; + physical_chan = 0; + for_each_line(xpd, i) { + if(priv->pri_protocol == PRI_PROTO_E1) { + /* In E1 - Only 0'th channel is unused */ + if(i == 0) { + physical_chan++; + } + } else if(priv->pri_protocol == PRI_PROTO_T1) { + /* In T1 - Every 4'th channel is unused */ + if((i % 3) == 0) { + physical_chan++; + } + } + if(IS_SET(lines, i)) { + physical_mask |= BIT(physical_chan); + if(SPAN_REGISTERED(xpd)) { + if(i == PRI_DCHAN_IDX(priv)) { + if(priv->dchan_tx_sample != chans[i].writechunk[0]) { + priv->dchan_tx_sample = chans[i].writechunk[0]; + priv->dchan_tx_counter++; + } else if(chans[i].writechunk[0] == 0xFF) + dchan_state(xpd, 0); + } +#ifdef DEBUG_PCMTX + if(pcmtx >= 0 && pcmtx_chan == i) + memset((u_char *)pcm, pcmtx, ZT_CHUNKSIZE); + else +#endif + memcpy((u_char *)pcm, chans[i].writechunk, ZT_CHUNKSIZE); + // fill_beep((u_char *)pcm, xpd->addr.subunit, 2); + } else + memset((u_char *)pcm, 0x7F, ZT_CHUNKSIZE); + pcm += ZT_CHUNKSIZE; + } + physical_chan++; + } + RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = physical_mask; + XPD_COUNTER(xpd, PCM_WRITE)++; + spin_unlock_irqrestore(&xpd->lock, flags); +} + +/*! Copy PCM chunks from the packet we recieved to the xpd struct. + * \param xbus xbus of target xpd. + * \param xpd target xpd. + * \param pack Source packet. + * + * On PRI this function is should also shift the lines back mask one bit, as + * channel 0 on the wire is an internal chip control channel. + * + * \see PRI_card_pcm_fromspan + */ +static void PRI_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack) +{ + struct PRI_priv_data *priv; + byte *pcm; + struct zt_chan *chans; + xpp_line_t physical_mask; + unsigned long flags; + int i; + int logical_chan; + + if(!SPAN_REGISTERED(xpd)) + return; + priv = xpd->priv; + BUG_ON(!priv); + pcm = RPACKET_FIELD(pack, GLOBAL, PCM_READ, pcm); + physical_mask = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines); + spin_lock_irqsave(&xpd->lock, flags); + chans = xpd->span.chans; + logical_chan = 0; + for (i = 0; i < CHANNELS_PERXPD; i++) { + volatile u_char *r; + + if(priv->pri_protocol == PRI_PROTO_E1) { + /* In E1 - Only 0'th channel is unused */ + if(i == 0) + continue; + } else if(priv->pri_protocol == PRI_PROTO_T1) { + /* In T1 - Every 4'th channel is unused */ + if((i % 4) == 0) + continue; + } + if(logical_chan == PRI_DCHAN_IDX(priv)) { + if(priv->dchan_rx_sample != pcm[0]) { + if(print_dbg & DBG_PCM) { + XPD_INFO(xpd, "RX-D-Chan: prev=0x%X now=0x%X\n", + priv->dchan_rx_sample, pcm[0]); + dump_packet("RX-D-Chan", pack, 1); + } + priv->dchan_rx_sample = pcm[0]; + priv->dchan_rx_counter++; + } else if(pcm[0] == 0xFF) + dchan_state(xpd, 0); + } + if(IS_SET(physical_mask, i)) { + r = chans[logical_chan].readchunk; + // memset((u_char *)r, 0x5A, ZT_CHUNKSIZE); // DEBUG + // fill_beep((u_char *)r, 1, 1); // DEBUG: BEEP + memcpy((u_char *)r, pcm, ZT_CHUNKSIZE); + pcm += ZT_CHUNKSIZE; + } + logical_chan++; + } + XPD_COUNTER(xpd, PCM_READ)++; + spin_unlock_irqrestore(&xpd->lock, flags); +} + +/*---------------- PRI: HOST COMMANDS -------------------------------------*/ + +static /* 0x0F */ HOSTCMD(PRI, XPD_STATE, bool on) +{ + BUG_ON(!xpd); + XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off"); + return 0; +} + +static /* 0x0F */ HOSTCMD(PRI, RING, lineno_t chan, bool on) +{ + XPD_ERR(xpd, "%s: Unsupported\n", __FUNCTION__); + return -ENOSYS; +} + +static /* 0x0F */ HOSTCMD(PRI, RELAY_OUT, byte which, bool on) +{ + XPD_ERR(xpd, "%s: Unsupported\n", __FUNCTION__); + return -ENOSYS; +} + +/* 0x33 */ HOSTCMD(PRI, SET_LED, enum pri_led_selectors led_sel, enum pri_led_state to_led_state) +{ + int ret = 0; + xframe_t *xframe; + xpacket_t *pack; + struct pri_leds *pri_leds; + struct PRI_priv_data *priv; + + BUG_ON(!xbus); + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + XPD_DBG(LEDS, xpd, "led_sel=%d to_state=%d\n", led_sel, to_led_state); + XFRAME_NEW_CMD(xframe, pack, xbus, PRI, SET_LED, xpd->xbus_idx); + pri_leds = &RPACKET_FIELD(pack, PRI, SET_LED, pri_leds); + pri_leds->state = to_led_state; + pri_leds->led_sel = led_sel; + XPACKET_LEN(pack) = RPACKET_SIZE(PRI, SET_LED); + ret = send_cmd_frame(xbus, xframe); + priv->ledstate[led_sel] = to_led_state; + return ret; +} + +/*---------------- PRI: Astribank Reply Handlers --------------------------*/ +static void layer1_state(xpd_t *xpd, byte subunit, byte data_low) +{ + struct PRI_priv_data *priv; + int alarms = 0; + + BUG_ON(!xpd); + priv = xpd->priv; + BUG_ON(!priv); + if(xpd->addr.subunit != subunit) { + XPD_NOTICE(xpd, "layer1_state got wrong subunit=%d. Ignored.\n", subunit); + return; + } + priv->poll_noreplies = 0; + if(data_low & REG_FRS0_LOS) + alarms |= ZT_ALARM_RED; + if(data_low & REG_FRS0_AIS) + alarms |= ZT_ALARM_BLUE; + if(data_low & REG_FRS0_RRA) + alarms |= ZT_ALARM_YELLOW; + priv->layer1_up = alarms == 0; + if(!priv->layer1_up) + dchan_state(xpd, 0); + if(SPAN_REGISTERED(xpd) && xpd->span.alarms != alarms) { + char str1[MAX_PROC_WRITE]; + char str2[MAX_PROC_WRITE]; + + alarm2str(xpd->span.alarms, str1, sizeof(str1)); + alarm2str(alarms, str2, sizeof(str2)); + XPD_NOTICE(xpd, "Alarms: 0x%X (%s) => 0x%X (%s)\n", + xpd->span.alarms, str1, + alarms, str2); + xpd->span.alarms = alarms; + zt_alarm_notify(&xpd->span); + } + priv->reg_frs0 = data_low; + priv->layer1_replies++; + XPD_DBG(REGS, xpd, "subunit=%d data_low=0x%02X\n", subunit, data_low); +} + +static int PRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) +{ + unsigned long flags; + struct PRI_priv_data *priv; + + spin_lock_irqsave(&xpd->lock, flags); + priv = xpd->priv; + BUG_ON(!priv); +#if 1 + if(print_dbg) + dump_reg_cmd("PRI", info, 0); +#endif + if(info->multibyte) { + XPD_NOTICE(xpd, "Got Multibyte: %d bytes, eoframe: %d\n", + info->bytes, info->eoframe); + goto end; + } + if(REG_FIELD(info, regnum) == REG_FRS0 && REG_FIELD(info, do_subreg)) + layer1_state(xpd, REG_FIELD(info, subreg), REG_FIELD(info, data_low)); + if(REG_FIELD(info, regnum) == REG_FRS1 && REG_FIELD(info, do_subreg)) + priv->reg_frs1 = REG_FIELD(info, data_low); + /* Update /proc info only if reply relate to the last slic read request */ + if( + REG_FIELD(&priv->requested_reply, regnum) == REG_FIELD(info, regnum) && + REG_FIELD(&priv->requested_reply, do_subreg) == REG_FIELD(info, do_subreg) && + REG_FIELD(&priv->requested_reply, subreg) == REG_FIELD(info, subreg)) { + priv->last_reply = *info; + } + +end: + spin_unlock_irqrestore(&xpd->lock, flags); + return 0; +} + +static xproto_table_t PROTO_TABLE(PRI) = { + .owner = THIS_MODULE, + .entries = { + /* Table Card Opcode */ + }, + .name = "PRI_xx", /* xpd->type_name is set in set_nt() */ + .type = XPD_TYPE_PRI, + .xops = { + .card_new = PRI_card_new, + .card_init = PRI_card_init, + .card_remove = PRI_card_remove, + .card_zaptel_preregistration = PRI_card_zaptel_preregistration, + .card_zaptel_postregistration = PRI_card_zaptel_postregistration, + .card_hooksig = PRI_card_hooksig, + .card_tick = PRI_card_tick, + .card_pcm_fromspan = PRI_card_pcm_fromspan, + .card_pcm_tospan = PRI_card_pcm_tospan, + .card_ioctl = PRI_card_ioctl, + .card_close = PRI_card_close, + .card_register_reply = PRI_card_register_reply, + + .RING = XPROTO_CALLER(PRI, RING), + .RELAY_OUT = XPROTO_CALLER(PRI, RELAY_OUT), + .XPD_STATE = XPROTO_CALLER(PRI, XPD_STATE), + }, + .packet_is_valid = pri_packet_is_valid, + .packet_dump = pri_packet_dump, +}; + +static bool pri_packet_is_valid(xpacket_t *pack) +{ + const xproto_entry_t *xe_nt = NULL; + const xproto_entry_t *xe_te = NULL; + // DBG(GENERAL, "\n"); + xe_nt = xproto_card_entry(&PROTO_TABLE(PRI), XPACKET_OP(pack)); + return xe_nt != NULL || xe_te != NULL; +} + +static void pri_packet_dump(const char *msg, xpacket_t *pack) +{ + DBG(GENERAL, "%s\n", msg); +} +/*------------------------- REGISTER Handling --------------------------*/ +static int proc_pri_info_write(struct file *file, const char __user *buffer, unsigned long count, void *data) +{ + xpd_t *xpd = data; + struct PRI_priv_data *priv; + char buf[MAX_PROC_WRITE]; + char *p; + char *tok; + static const char *msg = "PROC"; /* for logs */ + int ret = 0; + bool got_localloop = 0; + bool got_nolocalloop = 0; + bool got_te = 0; + bool got_nt = 0; + bool got_e1 = 0; + bool got_t1 = 0; + bool got_j1 = 0; + + if(!xpd) + return -ENODEV; + priv = xpd->priv; + if(count >= MAX_PROC_WRITE) { /* leave room for null */ + XPD_ERR(xpd, "write too long (%ld)\n", count); + return -E2BIG; + } + if(copy_from_user(buf, buffer, count)) { + XPD_ERR(xpd, "Failed reading user data\n"); + return -EFAULT; + } + buf[count] = '\0'; + XPD_DBG(PROC, xpd, "PRI-SETUP: got %s\n", buf); + /* + * First parse. Act only of *everything* is good. + */ + p = buf; + while((tok = strsep(&p, " \t\v\n")) != NULL) { + if(*tok == '\0') + continue; + XPD_DBG(PROC, xpd, "Got token='%s'\n", tok); + if(strnicmp(tok, "LOCALLOOP", 8) == 0) + got_localloop = 1; + else if(strnicmp(tok, "NOLOCALLOOP", 8) == 0) + got_nolocalloop = 1; + else if(strnicmp(tok, "NT", 2) == 0) + got_nt = 1; + else if(strnicmp(tok, "TE", 2) == 0) + got_te = 1; + else if(strnicmp(tok, "E1", 2) == 0) + got_e1 = 1; + else if(strnicmp(tok, "T1", 2) == 0) + got_t1 = 1; + else if(strnicmp(tok, "J1", 2) == 0) { + got_j1 = 1; + } else { + XPD_NOTICE(xpd, "PRI-SETUP: unknown keyword: '%s'\n", tok); + return -EINVAL; + } + } + if(got_e1) + ret = set_pri_proto(xpd, PRI_PROTO_E1); + else if(got_t1) + ret = set_pri_proto(xpd, PRI_PROTO_T1); + else if(got_j1) + ret = set_pri_proto(xpd, PRI_PROTO_J1); + if(priv->pri_protocol == PRI_PROTO_0) { + XPD_ERR(xpd, + "Must set PRI protocol (E1/T1/J1) before setting other parameters\n"); + return -EINVAL; + } + if(got_localloop) + ret = set_localloop(msg, xpd, 1); + if(got_nolocalloop) + ret = set_localloop(msg, xpd, 0); + if(got_nt) + ret = set_nt(msg, xpd, 1); + if(got_te) + ret = set_nt(msg, xpd, 0); + return (ret) ? ret : count; +} + + +static int proc_pri_info_read(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + unsigned long flags; + xpd_t *xpd = data; + struct PRI_priv_data *priv; + int i; + + DBG(PROC, "\n"); + if(!xpd) + return -ENODEV; + spin_lock_irqsave(&xpd->lock, flags); + priv = xpd->priv; + BUG_ON(!priv); + len += sprintf(page + len, "PRI: %s %s%s (deflaw=%d, dchan=%d)\n", + (priv->is_nt) ? "NT" : "TE", + pri_protocol_name(priv->pri_protocol), + (priv->local_loopback) ? " LOCALLOOP" : "", + priv->deflaw, priv->dchan_num); + len += sprintf(page + len, "%05d Layer1: ", priv->layer1_replies); + if(priv->poll_noreplies > 1) + len += sprintf(page + len, "No Replies [%d]\n", + priv->poll_noreplies); + else { + len += sprintf(page + len, "%s\n", + ((priv->layer1_up) ? "UP" : "DOWN")); + len += sprintf(page + len, + "Framer Status: FRS0=0x%02X, FRS1=0x%02X ALARMS:", + priv->reg_frs0, priv->reg_frs1); + if(priv->reg_frs0 & REG_FRS0_LOS) + len += sprintf(page + len, " RED"); + if(priv->reg_frs0 & REG_FRS0_AIS) + len += sprintf(page + len, " BLUE"); + if(priv->reg_frs0 & REG_FRS0_RRA) + len += sprintf(page + len, " YELLOW"); + len += sprintf(page + len, "\n"); + } + len += sprintf(page + len, "D-Channel: TX=[%5d] (0x%02X) RX=[%5d] (0x%02X) ", + priv->dchan_tx_counter, priv->dchan_tx_sample, + priv->dchan_rx_counter, priv->dchan_rx_sample); + if(priv->dchan_alive) { + len += sprintf(page + len, "(alive %d K-ticks)\n", + priv->dchan_alive_ticks/1000); + } else { + len += sprintf(page + len, "(dead)\n"); + } + for(i = 0; i < NUM_LEDS; i++) + len += sprintf(page + len, "LED #%d: %d\n", i, priv->ledstate[i]); + spin_unlock_irqrestore(&xpd->lock, flags); + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; +} + +/* + * + * Direct/Indirect + * | + * | Reg# + * | | + * | | Data (only in Write) + * | | | + * | | +-+-+ + * v v v v + * FF WD 06 01 05 + * ^ ^ + * | | + * | Write/Read + * | + * Chan# + * + */ +static int handle_register_command(xpd_t *xpd, char *cmdline) +{ + unsigned chipsel; + unsigned data = 0; + unsigned xdata1 = 0; + unsigned xdata2 = 0; + char op; /* [W]rite, [R]ead */ + char reg_type; /* [D]irect, [S]ubregister */ + int reg_num; + int subreg; + int elements; + bool writing; + char *p; + reg_cmd_t regcmd; + xbus_t *xbus; + int ret = -EINVAL; + struct PRI_priv_data *priv; + byte buf[MAX_PROC_WRITE]; + + BUG_ON(!xpd); + xbus = xpd->xbus; + priv = xpd->priv; + BUG_ON(!priv); + if((p = strchr(cmdline, '#')) != NULL) /* Truncate comments */ + *p = '\0'; + if((p = strchr(cmdline, ';')) != NULL) /* Truncate comments */ + *p = '\0'; + for(p = cmdline; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */ + ; + if(*p == '\0') + return 0; + if(!XBUS_GET(xbus)) { + XBUS_DBG(GENERAL, xbus, "Dropped packet. Is shutting down.\n"); + return -EBUSY; + } + memset(buf, 0, MAX_PROC_WRITE); + elements = sscanf(cmdline, "%d %c%c %x %x %x %x %x", + &chipsel, + &op, ®_type, ®_num, + &subreg, + &data, &xdata1, &xdata2); + XPD_DBG(PROC, xpd, "'%s': %d %c%c %02X %02X %02X\n", cmdline, chipsel, op, reg_type, reg_num, subreg, data); + if(elements < 3) { // At least: chipsel, op, reg_type, reg_num + ERR("Not enough arguments: (%d args) '%s'\n", elements, cmdline); + goto out; + } + if(!VALID_CHIPSEL(chipsel)) { + ERR("Bad chip select number: %d\n", chipsel); + goto out; + } + REG_FIELD(®cmd, chipsel) = chipsel; + switch(op) { + case 'W': + writing = 1; + break; + case 'R': + writing = 0; + break; + default: + ERR("Unkown operation type '%c'\n", op); + goto out; + } + if( + (op == 'W' && reg_type == 'D' && elements != 5) || + (op == 'W' && reg_type == 'S' && elements != 6) || + (op == 'R' && reg_type == 'D' && elements != 4) || + (op == 'R' && reg_type == 'S' && elements != 5) + ) { + ERR("Bad number of elements: '%s' (%d elements): %d %c%c %02X %02X %02X\n", + cmdline, elements, + chipsel, op, reg_type, reg_num, subreg, data); + goto out; + } + switch(reg_type) { + case 'S': + REG_FIELD(®cmd, do_subreg) = 1; + REG_FIELD(®cmd, regnum) = reg_num; + REG_FIELD(®cmd, subreg) = subreg; + REG_FIELD(®cmd, data_low) = data; + XPD_DBG(PROC, xpd, "SUBREG\n"); + break; + case 'D': + REG_FIELD(®cmd, do_subreg) = 0; + REG_FIELD(®cmd, regnum) = reg_num; + REG_FIELD(®cmd, subreg) = 0; + REG_FIELD(®cmd, data_low) = subreg; + XPD_DBG(PROC, xpd, "DIRECT\n"); + break; + default: + ERR("Unkown register type '%c'\n", reg_type); + goto out; + } + regcmd.bytes = sizeof(regcmd) - 1; + REG_FIELD(®cmd, read_request) = writing; + REG_FIELD(®cmd, data_high) = 0; + priv->requested_reply = regcmd; + if(print_dbg) + dump_reg_cmd("PRI", ®cmd, 1); + ret = xpp_register_request(xpd->xbus, xpd, + REG_FIELD(®cmd, chipsel), + writing, + REG_FIELD(®cmd, do_subreg), + REG_FIELD(®cmd, regnum), + REG_FIELD(®cmd, subreg), + REG_FIELD(®cmd, data_low), + REG_FIELD(®cmd, data_high)); +out: + XBUS_PUT(xbus); + return ret; +} + +static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data) +{ + xpd_t *xpd = data; + char buf[MAX_PROC_WRITE]; + char *p; + int i; + int ret; + + if(!xpd) + return -ENODEV; + for(i = 0; i < count; /* noop */) { + for(p = buf; p < buf + MAX_PROC_WRITE; p++) { /* read a line */ + if(i >= count) + break; + if(get_user(*p, buffer + i)) + return -EFAULT; + i++; + if(*p == '\n' || *p == '\r') /* whatever */ + break; + } + if(p >= buf + MAX_PROC_WRITE) + return -E2BIG; + *p = '\0'; + ret = handle_register_command(xpd, buf); + if(ret < 0) + return ret; + msleep(1); + } + return count; +} + + +static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + unsigned long flags; + xpd_t *xpd = data; + reg_cmd_t *info; + struct PRI_priv_data *priv; + + if(!xpd) + return -ENODEV; + priv = xpd->priv; + BUG_ON(!priv); + spin_lock_irqsave(&xpd->lock, flags); + info = &priv->last_reply; + len += sprintf(page + len, "# Writing bad data into this file may damage your hardware!\n"); + len += sprintf(page + len, "# Consult firmware docs first\n"); + len += sprintf(page + len, "#\n"); + if(REG_FIELD(info, do_subreg)) { + len += sprintf(page + len, "#CH\tOP\tReg.\tSub\tDL\n"); + len += sprintf(page + len, "%2d\tRS\t%02X\t%02X\t%02X\n", + REG_FIELD(info, chipsel), + REG_FIELD(info, regnum), REG_FIELD(info, subreg), REG_FIELD(info, data_low)); + } else { + len += sprintf(page + len, "#CH\tOP\tReg.\tDL\n"); + len += sprintf(page + len, "%2d\tRD\t%02X\t%02X\n", + REG_FIELD(info, chipsel), + REG_FIELD(info, regnum), REG_FIELD(info, data_low)); + } + spin_unlock_irqrestore(&xpd->lock, flags); + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; +} + +int __init card_pri_startup(void) +{ + DBG(GENERAL, "\n"); + + INFO("revision %s\n", XPP_VERSION); + xproto_register(&PROTO_TABLE(PRI)); + return 0; +} + +void __exit card_pri_cleanup(void) +{ + DBG(GENERAL, "\n"); + xproto_unregister(&PROTO_TABLE(PRI)); +} + +MODULE_DESCRIPTION("XPP PRI Card Driver"); +MODULE_AUTHOR("Oron Peled "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(XPP_VERSION); +MODULE_ALIAS_XPD(XPD_TYPE_PRI); + +module_init(card_pri_startup); +module_exit(card_pri_cleanup); diff --git a/kernel/xpp/card_pri.h b/kernel/xpp/card_pri.h new file mode 100644 index 0000000..dbe83c0 --- /dev/null +++ b/kernel/xpp/card_pri.h @@ -0,0 +1,32 @@ +#ifndef CARD_PRI_H +#define CARD_PRI_H +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "xpd.h" + +enum pri_opcodes { + XPROTO_NAME(PRI, SET_LED) = 0x33, +}; + + +#endif /* CARD_PRI_H */ diff --git a/kernel/xpp/firmwares/FPGA_1141.hex b/kernel/xpp/firmwares/FPGA_1141.hex new file mode 100644 index 0000000..512df60 --- /dev/null +++ b/kernel/xpp/firmwares/FPGA_1141.hex @@ -0,0 +1,658 @@ +# +# $Id: FPGA_1141.hex 5122 2007-12-12 10:07:59Z dima $ +# +:020000040000FA +:80000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6AD6FF4000782C0A006AD6FF4000782C0A006AD6FF4000782C0A0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4455544455557475577775577675577775577765566665563625523235D2E37C2B5111155111155111155111C4 +:80008000155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111000000000000000000000000000000000000002552222552222552220025522225522200000000001AA1111AA1110025522200001AA1111AA111001AA11100001AA1111AA11100001AA1111AA1111AA113 +:80010000110000002552222552222F21F112122F21F112122552222552222552222552220000001AA111255222255222255222255222255222255222255222255222255222255222000000002F21F112122F21F1121200002552222552221AA1111AA1112552222F21F1121200001AA1112F21F1121200002F21F112122F21F112121AA100 +:80018000110025522225522200000000002552220000000025522225522200000000002552220000FFF9F99F9F7F78F8878700000000000000000000000000000000000000000000000000000000002552220000000025522225522200002552222552222552222552222552222552222552222552222552220025522200000000004F44D4 +:80020000F444444F44F44444000000004F44F444444F44F44444004F44F4444400004F44F444444F44F444440000004F44F444446F64F446466F64F44646000000004F48F884846F69F996962F21F11212000000CAACCC2F2DFDD2D22F21F112124F48F884842F21F11212004F4CFCC4C46F6DFDD6D62F21F1121200006F6DFDD6D66F6DF0 +:80028000FDD6D66F6DFDD6D6000000008AA8882F29F992922F21F112120000004F4CFCC4C46F6DFDD6D62F21F112128AA8882F21F11212004F4CFCC4C46F6DFDD6D62F21F1121200006F6DFDD6D6CFC5F55C5CBFBEFEEBEB006F6DFDD6D66F6DFDD6D6000000008F8CFCC8C8AFACFCCACA255222000000CFC4F44C4CCFC4F44C4C008F8C66 +:80030000FCC8C825522200CFC4F44C4CCFC4F44C4C000000CFC4F44C4CCFC4F44C4CCFC4F44C4C00000000CFCCFCCCCCCFCCFCCCCC000000008F84F44848AFA4F44A4A255222CFCCFCCCCC0000CFC4F44C4CEFE4F44E4E2552220000EFE4F44E4EEFE4F44E4EEFE4F44E4E00000000CFC8F88C8CCFC8F88C8C000000008F84F44848AFA4A9 +:80038000F44A4A255222CFC8F88C8C0000CFC4F44C4CEFE4F44E4E2552220000EFE4F44E4EEFE4F44E4EEFE4F44E4E00000000CFC8F88C8CCFC8F88C8C000000008F8CFCC8C8AFACFCCACA255222CFC8F88C8C0000CFCCFCCCCCEFECFCCECE2552220000EFECFCCECEEFECFCCECEEFECFCCECE00000000CFC8F88C8CCFCBFBBCBC3AA33379 +:800400000000008F8CFCC8C8AFADFDDADA2F21F11212CFC8F88C8C3AA33300CFCCFCCCCCEFEDFDDEDE2F21F112120000AFA9F99A9AFFFEFEEFEF00EFEDFDDEDEEFEDFDDEDEEFEDFDDEDE000000008AA888BAABBB3AA333000000CFCCFCCCCCEFEEFEEEEE2F22F222228AA8883AA33300CFCCFCCCCCEFEEFEEEEE2F22F222220000EFEEFEFD +:80048000EEEEEFEEFEEEEEEFEEFEEEEE000000004AA4441F14F44141155111000000CFCCFCCCCCFFFFFFFFFF3F33F333334AA44415511100CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000008F84F448489F95F559591F11F11111000000CFCCFCCCCCFFFEFEEFEF3F32F223238F84F448481F11AF +:80050000F1111100CFCCFCCCCCFFFEFEEFEF3F32F223230000FFFEFEEFEFFFFEFEEFEFFFFEFEEFEF00000000CFC4F44C4CFFF4F44F4F3553330000008F8CFCC8C8BFBFFFFBFB3F33F33333CFC4F44C4C35533300CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004554444F42F224242AA2220092 +:8005800000008F8CFCC8C8BFBFFFFBFB3F33F333334554442AA22200CFCCFCCCCCFFFFFFFFFF3F33F33333008F81F118189F9EFEE9E90000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004AA4446AA6662AA222000000CFCCFCCCCCFFFFFFFFFF3F33F333334AA4442AA22200CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFF8D +:80060000FFFFFFFFFFFFFFFFFF00000000CFC4F44C4CCFC6F66C6C2AA2220000008F8CFCC8C8BFBFFFFBFB3F33F33333CFC4F44C4C2AA22200CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F48F884846F68F886862552220000008F8CFCC8C8BFBFFFFBFB3F33F333334F48F884842552221B +:80068000008F8CFCC8C8BFBFFFFBFB3F33F333330000BFBFFFFBFBBFBFFFFBFBBFBFFFFBFB000000004F48F884846F68F88686255222000000CFCCFCCCCCFFFFFFFFFF3F33F333334F48F8848425522200CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F48F884846F68F8868625522200009B +:8007000000CFCCFCCCCCFFFFFFFFFF3F33F333334F48F8848425522200CFCCFCCCCCFFFFFFFFFF3F33F33333EAAEEE7F75F55757000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F44F444447F75F557573F31F11313000000CFC8F88C8CDFDBFBBDBD1F13F331314F44F444443F31F1131300CFC8F88C8CDFDBFBBDBD1F13F33105 +:80078000310000DFDBFBBDBDDFDBFBBDBDDFDBFBBDBD000000004F44F444445F55F555551F11F111110000008F8CFCC8C88F8FFFF8F83AA3334F44F444441F11F11111008F8CFCC8C88F8FFFF8F83AA33300008F8FFFF8F88F8FFFF8F88F8FFFF8F8000000004F44F444444F47F774743AA333000000CFCCFCCCCCDFDEFEEDED1F12F221F9 +:80080000214F44F444441F13F3313100CFCCFCCCCCCFCEFEECEC2AA2220000CFCEFEECECCFCEFEECECCFCEFEECEC000000004F44F444445F57F775751F13F33131000000CFCCFCCCCCCFCFFFFCFC3AA3334F44F444441F13F3313100CFCCFCCCCCCFCFFFFCFC3AA3330000CFCFFFFCFCCFCFFFFCFCCFCFFFFCFC00000000000000000000AE +:800880000000000000000000FFFBFBBFBF7F77F7777700008001000000000000000000000000004001000000000000000000000000DF8D07480000000000000000000000000000000000000000000000000000000000BE4E000000000000000000000000000000000000000000000000000000000000FFE40F480080010000000000000066 +:8009000000000000000040010000000000000000000000002F820C0000000000000000000000000000000000000000000000000000000000F04FFE8002004001008004148002800414800200008002800400002148400100800400002148000010F2A6CE000000000000000000000000000000000000000000000000000000000000FFE44F +:800980000F0000000000000000000000000000000000000000000000000000000000F04FFE80840180020000001002000010024001002100140000000028000014882880080088280028009A0F0080840100002001000000000000001200004001000040010000400100000000009F31094818148002800414182810820416012810A2115B +:800A000040012810A2414001002B11484001280048408188022148008828108204F05C6580840180020000001002000010024001002100140000000028000014882800008088020000EFF80F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000000000008827 +:800A800028000000280000F0B32B00002002000000100200002400000024120018000000002800000000000088000000FFA60A0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000200100000000000000000000000000F07CBE0000000000000000000000000000120039 +:800B00000000000000000020080000000000004F330B000000000000000000000000001002000000000022000000000000000000F04F4A000000000000002100000000000000000000000000000000220000000000005F2E060000000000000000000000000000000000000000000000000000000000F04FFE0000200200000000000000CE +:800B8000210000000000000000000000000000002028020000AF950C000000000000000000000000000000004002000000000000880000000000F09CC320010000002400000000800400000000400200220000200100000000008002004200EFDE0D00000000240000000000000000000010024002000000000000000080020000F0A3BEEA +:800C0000800100000000000000004800000000000000220000200100000088000000004800BF170E00000000A0110000000000000088008001000080010000000000000000002008F0AD1A000000000000000000000082000000000000000000000000000000000000A0430000800200000020040000000000002002800200000082000069 +:800C800000000000000000F0B25B8001382001002088021240022200828081024200200442000000282222800200200482002004200448F0A82C002002120000008001242002000000480000002200008002820000004200008004200442F01C39800118200200202802800400008220810200004A0242000000802202220000008200008A +:800D0000000000FFA70400000022108224020000200880022800000000000000000000220000000000800228F0293700000010013288000080218201482008000000001280028280022800008002200800000020045E4500000000902220020000800848000000000080012200000000000000000000800200FF150D000000190212C20098 +:800D8000008081220120222802000000000080082820020028200220080000002006DF770F800428000080014A01222002280082211218882816220880010080011200188800242004284200000042227016018004120060222800002A040000221002182120280318001828182448200380022024086214004800481002289F280328007D +:800E0000001800000000181800000000002200002242000000200A240000002800000000B0520C00A0210080322200588024A112800222001224001818202121A21422122420A112A0212A08C04288484214422004002004F0D53F20020020010012000000000088008028823222000000800100200810020000000080048022726D0620A5 +:800E80000448000000000000008002008008210000009021824210022028820200004002000000F01E712002208101800128800180088232882004A82024020082800182200480011812002200000000800400F0A19C0028000000280022980020010026820A28002200002022288908800A8800002100000028002A04008F2208208184F3 +:800F000002288001184A01208122010000182C01002082888128218802002004680022002800880080048004F084B6000000200800D2000000B2008800000000C882003081200A18202808800200A08400000000683FFA0D1220012800000012800288002800200820020000A21280828284042212800220020000282228228002E03C0480 +:800F800022111122184001002084011280018800222A04288081A4818001001848A04224182800240029020021103242488004F056742021210122002002002A04208804808202002824280018A04280022840222202280024220000280028200214F03CF700221C84011E2100A01200A0212021081A02121022820188290100241400244A +:80100000A0428001C042800424A0282424240011481002BF5A041AA1121A8185220200202185212102A0112A0A4A81CA822088022901488083A82A1D216A8A86E225A1212AA29228222B222822200820022213A2224A4481F441CB80A22115013A8112012AA21258223280A1881AA822182A2222A2682AA224A023A088008A248328AB4898 +:8010800082808AA1882012C242212121602840B2220248204221F27568209241A0233011A011A0214A88218C21A811CA812808A82921032226128226A1999A682300982442263222225A218884022228004A782212022B64424A04002BA5002601260126012021820400120028122848281A848204290518800198800100212004460200D2 +:801100002400820000142004F06C9DA0233AE313F221211F110A1F11818183A399187A051AA2185AA5A9AA28A29DFAAB335A24A626184AA4884A85E124B482A8B91F16E625BFA20A1AA145BAEA28BE2266242944B22202A0442F22B222F222222B222AA6426A066AF6F722A0333AA7331F13D3112AA211003AA199185A07A0995AA5AAAA09 +:801180000AFABBF2AB777A25A6BC184A8CA844F041632BA8BEB11F16E627B7E22AA2175AA5EF8EE22B624A82062AA222E024F6222225722232221B626E622B62B062F65AD9A0231F13B731031AD211A211121AA2319AA9444AA611189AA155AAABBB229ABDA2A866382AA4A25AB412A1995AAC895E532B912AFA71711F31B3A28EE223B3BB +:8012000012A1F7AAEB26B262E22216E2229222824E422F22B222F222222B222A22B662066AF67216A0331F13F131311AA1311F12F211111AA1313AA3991AA1551AA1111AA9551AA39B2AA2FB3AA3336AA7423AAA452B199AA9551AE137B732B321F271711F33B3A28EA2337AA5BBAAEB267242F2226227222F229222826E422F2252222FB1 +:801280002232222AA6662B26246AF65C1620022280010000000000200800820000280088200288422A082200A0922002000024C02280820400F0E1F900120022110022128084012088210280220322400200002A0822C011001082020030220080082C028084820422AFB3062AB41122B21122B611324219B26291212B961B682B9413B86D +:801300004229F24291222F142BF242B13AE414EB2AE414EA2264152F22E419E22264192CA4292CBC91C2521B29241B292B841B6923B481364219B64298212B8413B84228B24228B24228B242A842882E429776A0421AE612A42166A1212F14B11132621B282B921B692BA41B692B84322D811AF442A1B22DB123D312EA28C1B12E821CD8A6 +:8013800022E118E22261183CC1212DD21B29581B6929B88192921B2925B2810219F2428219A2A41B282928B24228B24228B24318B242EA22E4EB0A20080000800200210000000000000000004001008004000000008002000000501214EF760B2840014001402101C6024882002282281262284280220129880188222A01880000008200A0 +:80140000228800242280A428008082F418A520A138803111181E21294802A812240028190811180012008002202641622920120221100220062220420242C021148022866814702D0118CA1101121CA12121008AC2C222002819289281382C2122A34120A81230824A011328A2210042000020062228A2228024021488284E22882601CF97 +:80148000D8072228204101148234122041828408000080040022002022412219829282100221008200002440021C828402004248BBC50080013420822222010000000080034200A0242250222829010080220200002C8804482C080000002800702E0D228002282218121062121818888021024A8B21A4121220042021820128A012200284 +:80150000008A0228622A040000304228482880A8242A84F2476B0080022C022081828102128800001A0C1A04188004482002242880020028200822622C0200002442224228002A8406CF660B2220011428322824108101001222808221A22142002022032721281820012828002800A04842208418020000800A20F277792001000028265B +:801580008122016820224182820148322100160112D28800280040022082064800428A2222924240222224A2844221006FB7041C024222120010820420A882422800001002281A08602880A21214C2241901A0182981812102290240022A0822004800212242EDBC00001C010000800121001280321128822022A442102302122024012245 +:8016000092220020028008000000420000A880F2DB36902100262101220012184602A0411A8282036892002AA48230126888321242582419813122122383A12142A082802812A24820B22204488248A880F2F6918001200100193222488082280810021C012880024601142C0180222208288848882006221082240224000048284800283E +:8016800048471210218102002002001200C02212200212208208242846033063A01822A8304224280082190C42808442020040021002F081C9001100281100248A0210221882011221108281042082A812E818822A054001146886011411002440010022211002202404DFC60D808262132001160113A118802181210182221A82A2421832 +:801700004229A284422024028221C2200C9220E822A848224228482842800442806622482220F219EB000000282124121022220228002812409211211922081882184812800200B2001400000010424101200600002CF4D6C88081031828182C02350221204102A02100244280C112100200904228421A42C222D02222942220420223821D +:80178000220220042200C021282260FE8012818122112121820228280020021812002222221842183238321982044001160114902220A28214C0418084020010028004AF1C05114001001400889898102281081342E218222124088219210288881829010000001041411121140140018004000010F2248E008211002219D21231112A01BF +:80180000400200002412001022024246024810226421200E20241C02A048258204283022004800001426F2161F8002488008002820820838102102006210021823820800886011C800B0120C31240014002024440122A024226248211CF4873DA0219A33111E31923E312C622124188A6223C0121838A0B11AE112A9142F11A516222B226D +:8018800025B152A133BAAB132CA24F2B858AC482822D41BAB842A488248A82B2438622A4624A52311480E4246626224AA4622681F25172601217182A22A2221113E212B11121A882B81A232922A112268252223A862231C2885A8E542123A4642A8C21E22428A2443A19421191223D412681888466142A24B46246A2248084026014F0EBF3 +:80190000971411221400241691232F12F232A32B1182242123F121821A4261221A122286EA316228222AA24C4886F2D3112982A53315E1225A212CF321822F34F2218188196C383726311502481128228052222A32422CE426F4E1E414400100146032402201122C2881081C083C0A1C28C1212114400142218A028A028A12A228218A4291 +:801980002208400200200822000042003F4C06281B11A033221B13D021B332E32ABA828BA91B23B89213E11BFAB1B11F1B99323F3AF9A1911F11F5B2423F18F861711F13E311E413F5E1B316A2A9BA2B2FFA41E32BBB173B23FA41C1AA2AFCE1233D812A7243A12217121F28F8C3C1284A26A264C0426AA6442F36F67F5B143AB3F1B7112B +:801A0000A3733AB131B311F133323B112F28B892A12B9EB223B882B1B1E91B2BA2333F3AFAA3B12BAB1AF5A1533F3AA8EE7AE317E71DFDF1F38E8237121AEF14EF2AFAE3432F25FF11B33F2AFAE1612D822BA61F3EFAE3613F16F663216A56111F38F8E3C12AA2462AE226E422A2242B662AE222F62614B011F331713AA3333AF131113E1D +:801A8000323F31F332322F2BBB82ABB38AD322B812B181E913A3321E323F1ABB22B332A3DC1F36F5C2E22BC45AB151F5F1D23F3CFCB39326A1A55AFB41411F3EF413F33F315B223F1ED622B862FEE1632F16EE26F263211F16D61152111F14A44462624E626E426AB422A6666E624F6F41F131311F1BF711317AA3331F13F311113F33F372 +:801B000013312F2ABA92A93B9E822F2199121B33BEB11F18EA23D322F3A3911F13A7CD6E423F3EFE61E17AB171F7B1F23F3FFB33132F19AF541B5F1F3EF443E33F31F5B113373A1F14FC23222B6E1F3EFEE3633F36F263211F16764151111F14A4644AA6666E426E624AA6262AE632F66CFA2002222002200182002001112812301130816F +:801B8000281100421180A824208401218001001440010024481400400200002FCD0C260126019021261221223122800121321C21CB13224A0138484A3222142CA12C989012402244022440024240820448002304802424220442F01452C0411B21141B2146B311726293212F34B111F242931B212F2439112F2429F24293222F3429D21255 +:801C0000AB431CE922C4A12F2264112F22641D2E4296F122C29AF222C21B292EC21B292F22B891F262821B292B841B282F2498212F2498212B84112F2428F242A2222BA4222B842A84E822C4E4C0511B611CB511E23631112F3691216E1313E134B891E224BA91F24292824EB3222F3429CAB12B432D91AAC5B13DC21AFA23429237221248 +:801C80002F326C112F222CF122C11AF42281122F3238116E8219F26282282F3688E234BA816224E0240A4A2AB242B822B4426A22BF8A0A2088040000000010020000000000800800001C080000000000002280020000004001CF540A8AE112611211182D12281902200B2001628048A2824222388880321120242101182C2102290A92210D +:801D00003A082A0488484848428092424822288004346F160622821228800850221904664262244082818202A242802486344223828982288422A2412B248082A252422C8388CC22200824488A042223842422C2212AF42A9914A03C1361121286222212C241B86222460228200223E2288422238D229412A81A8C8239416022784A324236 +:801D8000288E1248882888C88842C24824684E2242424222244A6212286F4C042A112102241210410200252201482921882288820420246214218001A0211810A22880A2121AC6126880120280048220922248280048EFCA0C14001122602230420048000042320042481800210028181288A0821223022A0126022C882206800600484225 +:801E000020040020E23D0C1A021B922021D21201A08211360200212381880322286880242202182C64262A812101C2282032827682A248822B4228002924C882284890422A248402CFDE08289011A0212CA22121A028113221400223A5922820064A014222282063254E328A038220288281622820BA82A6482924A2241022682422004803 +:801E8000224200CF830C19018A120110012904200400008001A042220021000000122A213162800223C2720022280080048842484602482022627910012800240090123828488004800220B142222224A12423A4292242001800400282482148884082062220840A0022622100AFC90D222240012A812232220010224222128204281002E5 +:801F00002CA24320212C3812A248B042822684260821002C82840220024082020030C28846F25D38800111280080010014808881012921080000000000122848001821180014008842A02421480048424002800456091C0328116021222229024023041E42260278882212626022484823812328A581621842682C248281184201A223C4DA +:801F80006268248024843862002C22A2844846F2E3E80068142880021224122A81028220410200002848282242482821282034228001290C4602428008800600228004200488F052EF8002168183D2128102382218241800211288187032028022040000A012002424226022001A02620000B022042128422902212828CF2B0F1812280034 +:802000004042028228822088212228028282A23A04822C8184010000292202D0220A42880000232222041002202234224820F4E6D81412008012322211100126012511121262280028128014A224189082A8122D12282C458285044022824102282200002822102284222204DF430E902140012818282830820000182280A812002412580E +:80208000002A0412230212280080A281A0412128004248800200000010027FE20240611242114091321218322128000038120028284200220000002024A2A420042004200400000000284200F0971F2082A141180021008A0222801202210000804422024222008A8402240000368202268222140228482810220822002200E7E1100148D0 +:80210000806112404201148E1212128A8102008A820420080092C824808C984220189282880020A4280000000042000022703701800662132191111220112201202428282108200122C04238108264210020A32440824402002442808402002A8402004234422F1C431101481100401141718102821A0212382121128A8114022C2382882F +:80218000642100822F1221A9481A0848A0246E92708282C82248108202282120044830421C52851415F12121181AE52171316321255112E038681A888E1216E2210280A823AAA84A5E422CA24428A0189224A0389632422B6C27244221299622882E128222216280040021C042262224C2214AF42BFEA0325200171229F321212CA2138E47 +:80220000221B11233132271198236822249AA188282381A2842318B212E22294822B688A3132183A42A2C148AAA8886E42CAA3252CC2824A84062342427222A2A4A024A022294481F2652C2081F131211F16820229B13191211F13B922C2B21830422AB192ABBB212CA15138222AA5226E526AA52548122F23C4C22B222C2DA33A2F2AC2FE +:80228000227E12F032422123B6C2E62212A26642808622E22622A264484AA2462722EF264501000000344001200882000000202804422084080029081890820048244002244880044002800400006FCA09181F12721111D121F82322311B312B111F2BB9922942F292922F2CB682BAA2E229B9B2AB339E12EAAFD82F27B622E626B762E462 +:8023000027B692A9DD9AE926AEB35E722F28F812922AAAA8BEB27AA7772B648ABAA20A2B646632224AA464CABE42A6226AE416E62284A4662D224FB90F19F161611F13B1317311B23333333B233B131F3BB9B2AA222AEA28F9D2522F2BB992E129B8B2AB335AB5F2AFDD2C94427EB22B753EE22BDDEAAEFF1F35C5B25E712DA22DA22CA6A7 +:80238000A8BEB22B155E622B452BC62B8A2CB262E62692224AA444EEC22B646AA6461B666AB462A46626F289D314381D711E2119D321D323B233F131332F21F2B3323BB93ACBB22F29F1D2D22F28B8A2AABB2BABBAA99B2B5FDAE12CADE82EC22F26F672723AA3FFAAEB36BEE2EF25F7A2922F21B982A4A81E322BEE2BEF2B67AEA22BAAAE +:80240000212B622E222B644A042B8A2B6422666222222B446AE222F48CA5141F12F321711F13F131311F2BF2333337233F33F333333F3BFA33B13ADB22FA82122F2DFDB2B22B89BABBB2A3BBFAAE7FDAE526A2421E222F27F7F272FAEF26A6FE4E532F2EFF53722F22FB22F22F2ABAA2EA23F3C2C22F2FFE52422F26FCC2822F22B24266C5 +:80248000262B444A44F2A2822B646AE626E626A6666AA6226E42DF5E0E14C011400222122622290220412249228902200182102204002818100222302280082A0800008044020028A02400D04505902190212E12D0320114D032888201211022822281A34242002E424229A1282B42B02224652280042430421A9212482304216800004AE0 +:80250000082448A042008F240D1CB411021B21421B21272419F2421119F2429119F24291112F1429F24291222F3429D212A9424E912E424E812E4256E12264192EC296C1429AD222B491C2521B2925B29162241B6927241B28272419B24298612F2498412F2428F24282222B842A94822A84E82274560F1CB511061B21421B21272419F224 +:802580004213284E918AF242318AD212012F142BF24293A21CB1A2D412C1521CABC21E81272216E1226D112EC316D122BC81C2D21B612D821B292E121369241B282F2698212C98212C9A214E82222F2422D222288298422BA426F279920082480000000000288004000000800100000014000000000000008002800400001424D30218009C +:802600002E111602181542012583220400289A02A024000048002904702282C6421A8403001290220000208484E42802C0A228004826F242C2001B1A002092221AC6121C02242411E028220516A282A04912622904122712884E12488081098820126214221880A4A4298404882440022D4124424001EF4D06181B3C6013182D2218181286 +:802680002603232206C082328021682252125223240C26812854221912622D52124200182232002C28042282422C0AA02829C2424081F2EF860000002092612503145022112022244B2222240822001225228421045A02A08260226014100242688024844402243043100242245FFE0A18001100242002A04124488004009242000022C0FB +:802700004230228229012A81A2828220018200002282000000218242AA04486F570A19021C2342A2121C8845A2812C831A2349220168181984A818224A02422982015622212282988260212A11B2228123012E828282808428242886A2A4220028F01E7A80012219022A6118212220B182139192200162B04101122800228045E22261214A +:802780002A81A2A182A2182C229112B2128088282A2824088828282B84008A8482E49A091C021C0124004A41A218222C04422448001888C888A042C042222420240840820286820128006022000080044880222A2402F09578002280A1421448250200428008A84A082C4102232221081022C82280042C212226812201202802291802B0B3 +:80280000620820081120880880F82E9A00803121200200102112621200A0120028290420A1A4121220211181040048190AA014A0242084822402482A04209422902228F0AA16A014902100202382210220085810324248200848A0841420022082820800001221800100000000881C0800424242AF580E5860113260122229222142A142C4 +:802880008280853842281642828A8401481932121A428201228A15822281E2128811A214222282218004006A8888889422824A2226F4D9270068221162A014100200211B2820C2821A240420222488880480025A022022048005208881148224022B84200400200800827E850022601226D112911252214691422012128221C8929229329F +:80290000822818254202002901A028888E118082A2121812222200800800000080222804F0CF12803411008024044229A281A08420D22388024213A8240019A88211111391211823294102272824248A94822C0821502210022D821002211082180260221F5B0C0000422214200114428027011C2442012681C5812B421480010020AA128D +:8029800028130219011324341152114AB28122948142A08400000000827F4108140010010000002921288882810800000042202728044221C26014828022A248148A024081048822802482040082F0677D8022848224A2241A448213028A01A0212240028A0420220C2001220020280188281A1A8289A828882002200248000088682100A5 +:802A00008FEE0F42121A04100223061E421A084A982210022901218002182C0B108201002460282224A08120028008008002008002821002BF7A090048200400004880018218221400888621810214141414188622210200420020012100101201860286028824200CD01C05288228426011348096216028281A0C2424221AAC4210220269 +:802A800000212240022129012981B8820128228088820A20080000203221484021F8DE7300221C352100002001528002A01820022028084A21A4844223A4244A2164144AA22452C04150122081C4410020A8688088A4C2484828822D82486F934121621D2AC1412A7211B351E52432626E414AA4411AE824CC821B1A2ABA2203AEC2CAA857 +:802B000014382B85230452382B16225AB82228D712B242B282A18B2BAA288EE22CAA622CEA1A4692418692C12C2C7E8282E828041D426A021423F818A9A0448A2331212CB44247B312E421A5111146F2A26223A139282B111CF852C23B24242AE228A828243F3444F26143284E5282CE7238FE52126EC24AA3113A61121813186224882032 +:802B80000482004A14A2E68224CA6418A8BF810D1922C2214A7241210280D223B292A9984AA1182227211F2864291B38B021E21838311B421BAAD01121F11181122D12122F2888E83A98212543F3C2812B11F6A191AE41882E21822D81A602C8002A022ABA828C8888F4354610810120084800000000144001144814481C02000000000092 +:802C00001110011123161112314211230421100221D0120200F03E26141F14B411621222A0135E523E324AA1A81F1CED24FC42128E928E9233B1C1ACDF1F1431611F28AC641F151FB141E634F143511F35FD13416E624AA4645E722B771F35B2C2E434F8A2833F12B251F6F3F33F3FF923633B4637323F34F442423F16D822F442E227288C +:802C80002B8CCE622F2CBC42A68248F0C2C2DF6C0E4AB471E712B221E226F271322CE527A7161F1EFF8191242B3518243B331BDF1F17FD411113BE81FCE1611F1FBF13B141F4C1833F34F563D33F13E426A7DD1F15E624FF42C11F3DF2C3415EF32F3AF323611B232F21B372F3A1E11BC42F2AB8827881A1A42F28BCC22CE82CF8E2422F4C +:802D00002EFC6261EEA22B44A0CC9F630D6AB411E611F1212115F111111F31E123A3571F17F6C1D32F219CF28AED287912A12A1F1BE827E238A8AE3DE11AE91CED14F441C33F15F421633F17A667CAEC1DEB25B372E72DF6E3612E623F2ABAB1E333A1BB2BBF1B622E23EABE82081F3CAAC82B8882CEC22B6EEAEC2EB222BAC2084AFCABDE +:802D80005FF061411B73141F12F261A11F13F311517E727AF571713F387912B252A55C182F12A31AAAF86361AEE1EA8ADE31E814FD42613F34FC53433F3BB653E427A75DDE217EB21B771F3DA66E2E621F2AB2E1EB32A3463F3FB2A3EE38A8EE3F38F8C341CE828AFC828223A8CCEE422BCECE222BCA2BCC88CAFCFC7E2002002602182026 +:802E0000A248A049241A04122089A2482812288210028002800988800988909280092A08200882200800824200824F38032001286611714202181351220010022DB2482410029826023D424211122C242422F1224242A02121282220020088000048A0484A022882003FDC041CB511C2111B21421B212394612B1419B24299212B94112B89 +:802E80009413F2429113F2429113F242911B424E911F22C4A12E4216E12264192F226C192CA4292CB491C2431B29341B2966B3917642B381764293612F3498612F3498412F2428F24282222F242892A22A84E822F488B3C051681CB11122B4111292212B1419F24292112BB413B84231212939212B9413B24239232B941F2281E922CC811C +:802F00002B5296D1226C193CE419C2421AC2C39AC6439A62329A44A3684683E63488E6349A614E82224E82224E8222A82B4229A8428FA60220080000004001008002000010021800000040010080040000000000200400100225015F960E901180036E12421641013602808818022CA88480842304001002821A12A2122282822A088601D4 +:802F8000880046A2428200802848A24280260242243F4F0B46A12832A04240212284A38420612160216A016022009213128282810222800858298202AE112C12A1218002004288002822204CC281E018A242AF310430D120234482C4211C24A396212296C28230222C884402381A3C1221821800201221E314B22288AAA48AF22142A01A57 +:803000002022A4248820028800284AC82214C0412D221F14011C84A21220A261141200001800124A01882242001302223022A0821229081800C011821400400280840820CA224880840AA848EA0F226012005022112C0120D1228144012008114220840433021B4228881229810212212814120026020022400124A02422288A84024A0242 +:803080007F334181210180A22122222812180014C2142A94222306808A0200D02281042AA44227214A02221230822B822F2A1161262A143281298C14C24142802484222402228F710F00190220211223028011021C48A12429386220042A84042712242E114A022AA512382386112213512282299A2123A62421139A4213146224424A82BA +:80310000A242AA842602225EED14321200282C02281829210116621448002810012A0800002C0482242C040022001A886221002100880011004800004A024F1B0518481C218302801201190252141880848309282902C28A22022C4102800423020086220B2AA182000048C220C8A2E82C8484120200EF8701114800003012422180122280 +:8031800002212B82004223110224001A04880022529021482A84014800283944A2820048200400002908281FEA08100100142280A224520048002024028842480042112848184A010048C0120022008082042400008008002200EF5E051111162183422192221C84A261281A440120A2348A012B1A4A82C442A0241A847182822125C4120B +:8032000030414826822828A421A828622CA4824223842428B882C2824826028820F2221C8001000020612248141082C612B0420828480020880A142242002242222820C1521A22020025010088002A2484040022003F8F0C100148C0218003000020224102111001142411004A020048282C41A312113811001021022110420280322228B3 +:80328000422200504F004011111102002819C121100321181CB21252120000802401130115029682220340632412218220083022828038220010820480745B0A0000802101212400272124107182820110028002150220028A41020021A8212A0488882C8A081001110040A284282180049F440B80040010024A61154242222085420100D5 +:803300001220110222141602242008002C228484011E224A0242A82C0800400221002002F01996A0121120F2211222200222112A012CD1218289434282011C0120024826012024032331121221111280085021002214D01204224082044240F3E4A210010010210200211413024A01001382D2210129210221224810410100001B2482B0C9 +:803380001102808A220400800800282C0200485FE30C201241010018161201001420061C8241110200140010814142028A8202824814213823850480022100282100208482021F9F02190228808131112024A114181110111101008042012392211B4380212421018200400200183148222B840021000000004870BB0A00481228242800FB +:803400002100183840822A01001911924118803811221682A8848E2140611416828422022054124222111119120120924200902222AB3E001942D111F221223B12182C21913313810215D231B513E221C3213F317122D1310119A1221D221B226AC7212A61211D8229F822122F2BF333112CA3261591212383B11262382BE42E42282225CA +:8034800041E218283222242B6A00484E214AF44F7BB01182140116E121B222A221582693421B111AE211B112E22671A1F131122A9211121F13214122225413199123589AE529260830121A74A2F23212189EA24AA8A215A124E2250114212C82B22262242F24A224282A043FF804264121A241181416216224524E1166F3211321621C98BA +:8035000082214012023419541214127A64111425A114A8882CE212F48383184E411D22228E521B44A229D822D82172811271410224002A94422260227E7300000024200200224083440224400200000000100221100221100280044800000000000000F08FAB141A61122A7231513115B222A2326AF731311F12F351511F31513115E33365 +:80358000F31113257111E33252332A022F160617121D511F17F721314AD511A15C2B2229E221B373F721133B111F12A3112F29B392E5163222EAEE2CFC232335F181831F2C5C2225E22282A4224AA442A0448D2E141B116E612AF231111B221B133A82A3761F37F771711F15F511311731141F39F98181371117111F1353113B22E017E722 +:8036000022F2A3911F17F651F11F12F351513F18F9C1512B991E113E321B661F3AFF91913F12F321112F29BB72A76E2B6EAEE22F2CDE33F223211F38F8C1E3272225E222B242A4264E422B464AF662628B41141AA1422A723151311D132F12A3136AF751511B776E711F31D33351333F37F793933F32F223233E32212B23F0615117323F25 +:8036800012FA71717AE712F351511F18E933F3B2222F2BFA33333F37F7A3F33F13F121311D132F2AFB7272EEE22F2ABA22A2EE3F32D21352333F1CDC225222257222E222B242B6228684F455B6141B112AE612F2311115F331132F1382A1761F35F573717AB7115131357131F393813F127223E32313A232F061711F32F233A11B771F1F29 +:80370000E712F351533F1CED3637921F297811F371631F3AFB31133F12F321132F2BF3B272EEA22F26F6A2E22F2C5C323D2135F3E3C12F2252222E2223E222B242B662E624E626F6D797A0120080012E1112220048144032812412301110018012830210012A012A09002F12093C012E82601248224003340000A02420043F4F0E001428D8 +:8037800034194221612611182818112981843321002180414201563121D021214C2241022E1113410222D02281D422082C0824130880022B243042224073A90C481B21B01162241B21272619B24291212F2699212F2419F142932AF44293222F3429D212A9421CE922E414E82264112F2264192F2264192D429AD222B491D222B4915222B1 +:803800001B2923B49132421B682394612B841B282B84112B84222B84A22B842229A842882E425E5880B411061B2146B2116224114A91212F2419F142B2C0932AF44293224E93221CB922D412E922C1912AE811F8224296712262192D439E2129B49112B29156221B2923B49132421B2823942129B881B24292212B84222B84A22B84222921 +:80388000B82294822E421FCF0500000000000000002100000080018800004001000000000000002800000000003FE90A180012C011298162122812240000111932C2108322A2424022912129682220A12126A22180082824114042022CA268008004A29022298202F0CF5C0026210180021C014260125880512280911123040086220C428C +:8039000012800120240162181022498231A1602800408284820462422044019FDC0D184E2180018031218024012302122111169181294403A085828229652282260219810122424A08221234128A022D82224222244862808A94422D222A04F0EDF6008001B011122261122890214A010021222B1410228262224200190118004AE222210A +:80398000212241022C08101102248A02002004282200007F2C06000000002A812212011A04902200124200484200130200200C402101122C210120042100108204224248280022DF8242818222022AD121A21222109112868201183888384AC22213A2410020E414C242682984948228281AA6422818202A86C462282A044223044A0888A5 +:803A000088A280044A0A1FE603002280429132221AC22121191802002B8238808204808484844283964200882033211820012B42002222602400824280AA864248808AF2F28C14222200182200001A021252181A02A0422CC1214A010060142A04C04282682848422212A03818426823C442004224488008002820047F880B11488A21025A +:803A80002100208402203242488880288231421AA44812E02204221810210800002800C8A0484228282088248806008004885F370512481118002138282302A0812601222842003022001A0600824091211812808C050082306240024222212002208C0221003FBE070088001400008002008004000000001118A042C84821224A010018B1 +:803B00002823012400004242000022000048AF9F061901132102142118222302804101684A028800424280022A04A0421C2C94821A82A14800322818C8468224044A622448208A02A2004220F435F920082041028002482228883042808804221822188A24041429A128182022014220810424822428883022008A22044220240200821FEC +:803B80007107002812122A110200000000282028822202002682028001282024040042288A02004800000000001002F09F870000008002000000800A1C8241113141100100482242304100A82004C042808462221448C04200802422024800F0D53614821422280080020011001A02821A88022220A8348818001800202682210400400284 +:803C00002C0824222C024622C42240A2242C82A22400BF550214124800826200288002000030410090128880042880220800481480A6250014002200000000000000DFBE01384800202304222200140080084280082A8104220000802208A0488A0412200800284822280020248204004826F1EE550080042280014280034218800800883E +:803C8000203142282220120262224214141818200820810280040020240600484200F0184800800110022800100180012219328111111C08209441306138121388084882808204120029A82C1110024002240024A02428F06D2A80220962402201002002182002A0212224426221C81002002280260216022400000020020080040080028F +:803D00002C047F1B0392281C05280048282002800200928004A2238888038800001948218882088E612246014A22C28100002800002004902248FFC5072AA32D2A02282F22A1418002800280A18822321BD2E8A0AA3AA614226E21210080A8482219AA281A88A2882A418228A6AAAE8168222002B0220228226842E01684F4946C1412866B +:803D800021012A21A1222A26840222421A012A021F180A171230419062CA26A1222E61226A051BA64A24A2478E12482C82E21744926125E22442A2642E2248244AC4424A54224246A2424A82028E311081C1112A07282B142022A23215110132A0A818DE21F021A31CA59C1B8A882C4422A4311AE21A42A1284A84B941246C125A04B20053 +:803E00007061012124422004226890222B4230223FB90D1100204882040000000000480020410146116214400100423041221118112111211002211082140221100200F096D8141F1AB32162122A83A128006A26A2311D216A8481232272A1B181F1A1A11F1ABA61EC12B881B8E1A4661F16541117137AF481814AAEE6EAAE65BE622D815D +:803E8000AEA33F12B241F693B33F3C7C83728251223F3656222125F242422F26B262E622F222222B222A2622E222B6DC0E221B6326A13218BAA3212AA244283AF321214A8681A322881F12F1A1311F1A28F262411F1AB8A1BBE1F8E1E11F1686A8134AF4A1A16AAEE61BEE1F11F4B1E32D418E8335B141F692B22BCC1BA246D122F24361FF +:803F0000A0662F24B442A2666E622F22D22292222CB662A64248DD5CA0321B7314E02892222A82A466A0112AA26420A1888AF8B1A11F19F9A1E11BCC3BDFAE812EB14AF461C16E422B664AF46141EAE616A6A2AAFEC1B11F38B422FEA1A23B225E535AB5C2BCC1643815F163616AE624A6442B442AE624B462A6222C92222B66222AF68AB9 +:803F80008570A1B13163122AA2223AA3312AA6442AA21115F14141183AA1AA2AFA21B11F18F9A1C14AE416F481812EE14AACE61F16F6E1617AF75151EAAEE66AAEEEBAEB29BC22F281A23B224E435AF5C3C33BC64EA31D213F34B642E624A6442F22B462A6444E622B242E222B222B662A84F4C16CA0120000200200220012208822883225 +:804000008128124A0242008002282A082A0818800818A082200226010000288082840242D0E40B001828002B14000040010020418144A14800A82E4280240542208804C8200280242408484220840448800420042814DFB1011CB41142B11162241B292394612B1419B24299212B94112B94222F1429F242912AD412B931C4911F22E414B7 +:80408000F8214256F1234296F1214296C142DAC2421B2D3CB49142B391E234B1917242B381724293212F2498212F2418F142822AF44282222F242892822A84E822F41F4FC0411AC64119E226311190612B121B612B9419B2429B612B94222F1429F242912AD412B933D412F821521CF921821E81372296F1214296C1439E21249AE212A4E9 +:804100006925A3292F3621E834A1284693214E8219E2249A214E82224E82224E8222882B4229A842B78D0082200800000000280000000028008008410022144002000000000000280000000021F03C830024181400211124A888C04180014321612A882088A482284A2204468224020023AA418A810880820610228404294102438226081C +:80418000802248F23A4D008604324D220089081211A81082B8AA812802132684221201A0121A8201C8299342382088323481C281122E484883032200528B2D0020C444481CA4249F8C4201433C12142604218D81242886011B4220B8A2A1182A61224AC84288481A2AA24A2AA5121820382120A3829AA41438A0848CA21600268884622220 +:8042000080F422D8008830444A829442CF3A0600A02124000092A028248041480488130222281100004229A4242D124224008A92848400C068462201482081014CA24280048028F2DE9310140140922120119661214001290100181218000000100860229A322410A2212E11281400206481002100C0829242228812003645C311284CE8FC +:8042800022D11411B815C449508210121228548249492224C2442021F64AA2222D5523B216F4422412294482A112418880B144622313248992224E2232482D4246A21248282E8A8A11246A88225F93093114413821814C944860124012015602490952124304124AA28623B24411524A292601A84303441211902532130400422A314240FC +:8043000022219C822C8CCB841A3288228F7E4931142288C01527121C911161A7242400842181002128180024812411225844242C6621C032A082322A8144029868A3831242622442222063820082001F340830441042C421105284251C01259614411044948830148A82B28864C140281448143248252C91142136440456084002304828E2 +:80438000278244418A12E482A1828504288C21F1F49D00482D288C81C4148140018074288484682858428004214C04124C0C80C128484128211548044A020048221D94A0818C042044946224809222E3644212EFDF4F021045012528025810480814161802C01481A922C418440046C21844582228002A8401128C02C91114081280A141D9 +:804400006081400858608900416E35004141279141AD1185021F24111C2814DA43E568012381D44888B41C824C344445984446384A85642328CD22C3129265612E141A2222149444226928618866AA415084472A28842B58CCB232E8840241B7B21002A71220C42422100C1484008182461484411822B2486388008021D184248404181215 +:8044800018104498181608841C014A219128414A01874432281018D448031F85040085410340021001004145484C4804202404400120C8444C246C44230415440400444241C03289041984024902222342342844604184AF150A1240C4144901138101811819118311921221104A1C118A1474421298461602120028224216A8214C023EE7 +:8045000048000044840068182280C41888222280F1831720544210021229D422014484188021941800160543154481242464445684411225911465C2425240D2242281411806212400541024A14128441A48388849F2A44410814104465841403118105642131123011285012440A1211018941184411961818100381044C81810044A51A8 +:8045800084811348082888401204004C2802BF7F4122588211274418814311088593112440625213428801181123D114017094010084502843B2580254583024604412C0480010B142012244C0828D14800114FDE680459218951264541054182110084651284464A0412001101814028004514418104438242E44002991444112003028A1 +:804600004CC21218604218884B212818448D181004806194904819941400808582011C01255261C048485100160112414A010016884608124904220082A0420017424304508442290841D0A1021424001562844110161411183444004416412101118400118450821018429812282200502280114241C413C08181B08281280152814C81C9 +:8046800028F85BF64048A84181800148172440424482023490284502491204117911084002884051241115082C04118411161824C888150C2D31201404222290882962824F510816748868D187812D545F21D134F4414247A551164162212447C1856751F04C115439018341D4417458B44851488334522B44463A3A4B22A9716111C82867 +:804700002931444B451C22D4487184C81A3B44D091512422417AF3342829723A446452283F95031F1411145B14E084A41416D158414F36125C31531B12239316A75111A3D134569B1F1654A4473447886F41E424F912549CD1C909C01A5E254975447424A2214C51424E1A67C143D3485811942E8243B4A19224246D4489E88CA928CF83D2 +:80478000E389524C7787242CD422D124F14316D7B5857518D44A1113DA83D19831434D55AD425D1885F8211A27614D1256F4445449714151823551111241457494711EF444362F41F425421E243A43742CF6324B8C71148461B429B48898289D212F41E441F1D2541EA4C014CF4394948A9894AE18FFAD071100140000001200000060829B +:8048000060824604800448800558A042200218118111A11912922123843242304230423042100200812FFA447181734153398F21F558D97F11FC4A4E7F71F1535115F115131E125E545F35F11212BF23F3181AEFF3F25E56AF21B352F218197E7897A59FA4744CFA525A6FA5F55652CF64F5D7D76FE5F1363EE7E56F65F112111F11F319B8 +:804880001F2F7163F33FF1F67B763FB2D22BF267227E73BFBCFC6B4BEF64F544662F6FFFD4562F24B4C6BD54F79C98CDA849F116A45FA8447115F71D4E17711E568F45F5DF45EFE4751FFF5F59D5F111171F21B173F75551EFA1F33F35DFA1F13B398F35F51C367F31F369294FD5F5495BBFA4F4CE5A2FA5F596CE6F65F51C56EFEDFD5FB9 +:804900005F6FE3F37A3FAFF3F376141F57F7191FAFF3F3325B7FD1F35B567F94D4EBF3EBAF7F67F3CBC9BFE4F24E567F75F1F2F66F6DF172746FAEFB5EF8CFABF93EBC8F82D966FA449C7045D775D57D51648FE5F51356B5FE1717BF95F51919BFF1711BFB53716F65F11216BF22F31A1AFF91F1747B6F61F13D5D7F51E197F749191F24A1 +:80498000D4C9F8585CCFE1F55656BF71F5D1D38FB3F3763CEFE5F7165C1B314D643E16AFE1F33312BB35AF7555D2AFF6F147645E1FBF9EFE4A2AAB5457342F4F7CF4B646F6CED2EBFFCB99AF8AA89ACFCAFBCD2634777DDF61F113134765AFECF51B1EFFE4F11C1FFF95F51C159F31F11B123B757F35F43F1BFF73F3171EBF91E1B7F7140B +:804A000016FF93F137754FD5F54D4DDFB4F45E8DCFC5F59C1E6F65F51E16DFFDFD682F2FE7F37F7E3FE3F316644CF63C1E2F63F37716FF41F378776FD4F4681FBFFCFE1196BF8E5EACFF74F515172F6FED6BF176744FAEFB7EEAEF4BF9BE9CCFEAF9ACACBF7B052901618421484D1184452241424883441101154804301181001185048500 +:804A80001403413022501460125014501450140040414821890264828D24824482BEBA4042C41215885181211B412115182241013C31142041024E154118404528011224446D188B252456041A42428481A41412E08854188410044120421284618240F93A87C0421F4152281F417248F11124A3D441B24AF11124AB9419B24A19F54A92AA +:804B00004F82F44A9343F24A914782AF14F924484E954FA2E414F8264A56F1264AD6E1A2655D2EDA9E242E4A1F49C2421F49D228F1912C83F4912CA3F4812CAB141D24AB9419B24A3995AB9443B24A39342B94478229F9344889F9244A4F4D06ACF411648D421E24C7141F41324A1D24AB141F41F64A941D24ABB451AF64D984F448B341EF +:804B80008F149944AF1419F242954F82E114F926885E8167A2D6E1A261542E9B9E252E4A1FC9C24A1F49C6521FC92276913C6217C8AB161741AF467881B46AB195B24A3924AB9443BB4A792498926F83949A4F22F53DEB402808008200000080820100000021008008000014008400000000004400001002308400B0F40340C21415E21162 +:804C0000C4184601481994481A043018008C5428C181410026282471444282C13610C2882816046C81A2828C0417822AC99A70823141C08880C8281823840140F492EE10B1812312CC288615D4415112441885C1482584CC15178941C04219285448874411257A41041504118C83224235C2148445A2414712484148481222188E142124A3 +:804C8000434186B88CD24A041C44F8EA5B10E18C9314D43B43C961145D12194411DC812142E4816C111B8185447A4CC28A43142455298994414918237121B611028C52144B854679147A24A2C14D614845A16856522426A1524489483294EC2258486D1A0084CBAA0011230281191804C0444A81744802101488044001814588426241481C +:804D0000442112A428882821002042088C826188188214922100C012AA240442413F9D0C222861805141403844008A44234824C11412292302000010081229014B52838421BC2241941240D241A2148424484248241220422601002A04482727241691142601469418453115126AC1A13210981185C2E12618D822E1C8644F844398AC2725 +:804D80001616445484B042018A922822441A82D848F3A41810B6124A84888181042522B122FC4428274C238A0A7024F26BB930222215044415041C911412A28A1411D24181F112811A323823914C4A02402202444412124C87E481E2222C82911243512C2CC2148B2141C2002418A012224D6A8A14026860664FEE0919311429021AC4187B +:804E000015148CA424142A018308844916188232824B81814CB88C9241160C16189242E0820860412684C828B251422308214A818544424292C42911A4282A08007B4350424A811224A4821614423C8C1068C14126C2142948228A311429121428293425440048248C614247A2464234584931128818206821412412234208121884221019 +:804E8000827438E45201244A321818320020021D1813624A18412618081244291A0E7014D814CA12D081B138A42119522489440812427044B82821F42C128C8244584230284848408A418211C224127F840422108212E41831286011003042A116081243518440088486041088021062412280042228804214085048929884821883912226 +:804F000041008C286281F01C99244C82B31892144B211C1108167D88C411341A544249F12A16922CA1184423CB2C448D84C113321963321836AA42222E16C143869424842C61844B12421884437598C2828321B818C4421AD268112822288211B8D4068602212842284F22012210C828896881811018D44822514810088849C42440812451 +:804F8000D12411A8425022122A41B424618889C12C2B82842112248460810018901AF0482443F2B17420922418008121A426212201141820092088413AAC82003818A85048449024C0284228A02412299218A9328441128489428221022284221004429F350A848141441B41489180215112892111A8121914228881288441024282304119 +:805000008362241A7221886164182E12240022830882128B128008381012A41C4120849224F0EC8320088721100814004008846C04448210B2642889084410141224234242140A40044C81112801448482812E824440849112812361888E128440F8EE8800106121B08401442487414014111A984289110484211118A418910000284200B4 +:8050800044144CC14244D0484405A28180A418C99228499428411084248421FAD139304516084A81410A4008140010688100100A442200302C18450860880042239118254804418001481812821218002048048034129F3F0C1200504100B06101442D1C800180C8182041943882848445224408121A981134C412240012301240588441F8 +:805100002880210441241088252111048D4E00C0481098124E161821200148008247A1D042048490481004602252A18304181A460444282412888A31A22081080000444200A04232F07FCE203184502630829014244D2800A74146A414A514D24A414A140236480684224B144262A1235122102A8404A512048634145022222F2204257233 +:80518000A8642482A4A01444189489F4CB881001198632844124404492482504286180842221A418112111890198002321644485012C44144805850181482AA14A4004680000289128C4292CBA7F06137388E813219481A72125D882E121F1283AC1F0411521D029B84ED842E129816184C11E882544D848DA82D541D82497162F2B71268E +:805200007C286864278341472343E18344783844EA4A23E84218C26216A25147224F2443B84A029F8186F448488D174AE665055C74A4548D16D62491941667611B2245E425B11A11FA5416A7C56F81C112C783426F6C3A923F53AB484532424512E42667816E484B641CD124D182D624F1724227C48161AD1186D845098D8C5E68AC638E02 +:805280002D98242BB14467418654424D84CAF332144E21BE884BAE8021419236AFD1C44C1314744E3112354968818D482CE34C64898612FE1848C969888B329518CC193A721438688F2152889F2D341243F148441D1489D172C21647236B9483F91EC84F23B38CA183984B288744858CA4821E4A8F81AA141694244BC3817FBB0D139414A3 +:805300001143924110111411140148644854124448441A041A44854481410114800289021992141902193242282304632468246024602422462212280810F89EFD141F12E296F2393F1D13FFD4F454559F14F41911BF95F53A37FFB555BABFD4D48CD1A8F3189BAF91F178F8AFA17988E8A8F449C88F9EFE524B3D418FA2F673733F27F7BA +:8053800013725FB7F59F9BCF89BB34F3323EBF72F251633FB3F32F2CC5F55C6BEFEEF6FF6FE764EAB6F2B3DCB988F4DAD88FCDF95A1CED4C8F8EFE7CB84F8FF9B5D48FE8FB3C7C4BBB2F8EFEAF37141F12F2656D9FF3F31152FFF4F45F55FF55B51BF15B5BBFF3F35B5FBD19BFB3538E8FA1F71AD3EFF9F972FAEFC17D18F88C4EAF96FDF0 +:8054000039398D1B7D4DDFFAF77777FFEFFF5774DFB4F71F3BFF69FB34367F61F116162F24F6232D9FA1F16E67CFB1F2AF2DAFAFF6DE9EEFCBF73E448F45B7D8F39AFCCFC8FD5E7CEFC7F394DA6F83FFF4D84FDFF9D8BCEFC7B7B4EBA7FC85E5F065453AF4393F5F61F35F1D4F45F15959FD1CFFF6F43A16BFF5F51A1BBF95F74C1AEFE4D8 +:80548000F59F9EB781CFE6FF1298CFC8F9D898FFC1FD38B9DD1E37A4FFF4BA12F374472FA5F5745EEFEAF8BE854F41F3525A65FE76467D668FB1F11A12F762EFCB714FFFAEF48FA3F7BA78AFEBFB7A382F21FF86D4EFC17146F68AC8CFE1FED6ACCF43F55434AFC7F6B8BCEEF81B34145F53F53C559FF3F35636FFD5F15E1BFFD5F51E1CD6 +:80550000FFF5F53A3FBFB5D493F15B3B6FA5F17E5EFFE9FD9F9EEFE6FE56DCCFC5FDDC9CEDDD9F975FED77E4EFE5F85351CFFFF75A78CFE5F71E3EEF5BDDCCF27E7E6F61F57353FD24AFF3F35A16FFE3F1FFDD8FE5F9AAFECFE3F3FA3CAFADF9BA78EFA9F9CE9CEFC7F11656EFEBFB5EAE6FCDFEFC9C4F4DFB7C7CCFCBED82FD457F2002AD +:8055800000000020412201122482444024482449041092282189921283948442219014100218844909224042486281404864812001124A02EFF40C438802446D121E486041C024A140425848418971141812847124481144312287512154E05192824424444890184421446049454248A2282443114818528421848F44381481226FEF0559 +:805600004D421F41522C1FC132481F41364E1D24EB141D24AB9419F24A9251AF443935AF5439A42F547934F842B54F83E414F9244A4E854FA264114FA265192E4A96E5A2E449E2A2F491244F32F491248F32F1912487161F49766AF1816CEB141D64AF249961AF249945AF24B934F44AB24B42ABB44F8A94B24F8294984FA2B4630845D22E +:8056800081D624F1114483F41164E5D2C1961619D64AF91164ADA213D1483A35AF44B9A4D45AF334482F54FB36488F14F926528F54E922EC54E8A2615D266A592E4B8E252E528F49F2244B9E648F32E5497268E1497662F1816CEB1419764AD641F66A825B68AF24B9A4F448224B4A8BB44B4AA9BBA6941A4F22F5E9C440080000000000BE +:80570000000000000000008800800214008480048008220000800200000040017F514A2294112411404544C8481D121986791108D449245224124F832443082220B212D28441024881272230821F288431812584C22620116B882A019E42888484884528A14112430849F29E557011248831282ADD2233584712308440294485C41283C811 +:80578000488A4222B864886188214480F212888416A48210C8122230382C78942831144422434198228001267441289822144483C125819FDB0F4671410880FC16214CC521425B1867168D11264954944B4129189C828CF3A2128C82F1388260621AB218C898251894212185C2821B8427848F38428481229114B145383C28D2239828853F +:8058000024183C1246C112811428DBF69016122CD181A212104A1C0820A81411429028483849044B48000070240220C58828211222121882EB8216140622922400122072482188224134944C52847F3C071410420884831481C148244021482103C02113CA34221014080012238242428401401416911A4480324C00820042478142206456 +:8058800082444301A2BF680C6B341226E922C129715302423B128B25B28252427016781A61814C3148462422048B2449334AC14E1890582024BA44A13816E181C8421678974204A92C2415AAC11C216888282A38124A2884042BCFC05412111602A575480452130100582092142D188C61184A21044884A01221C128281800A21886240100 +:805900008C91122338244598C8428E12804C41C8882882A142002AD8AF4D3221702298289C02131201A3E6A285CB81881C642181111CB214322C438212042E48448C64211E48C04A445890443865F181182354844D13201402488112529624044AA22149B8442104BF6D031C31442C9228160B182225183213228F497282022144124728B1 +:80598000241688064243312449420410B221810184882626288125082021914428228200121E426A412458825216F2F932504242214014481464112850B2444C0389C22840B84C81D84A982824568A48022D98C3C1121165F28864C425158254C22120124E449214AC31381E448C0126180C242AD1424128B522040050214844100A100830 +:805A00004049C816102621220418818810489824400800122820C121C0284788188449042048281818064489012844F0E6E2C015442342F91E429014E962B12C12D881B21A78830E6C514823C18827C41AF484288361A44394264D22859638856281124C916A43F1268129A281671123E588C22CC116E841844598928E4C98818B21C38539 +:805A8000D568818863C4B03E0D21408242410C10023C01205128268812C41432A988840289088160484901272290840044218C02C082124110A2218112815042D04202384588C1425F72064210198924C1488CB2184408833124608649416845481428456821200448224A8882C48550A424881129211182021A0820294182718488C18657 +:805B00004B124301422212888FB20C8C022D224A02938201A082242211450884A2882D124482801804C40081867884022028483284438822018410442402490122230800224004121FF70600008420021004A4400228120026820140180645180200842E8421C42042823818881012144202648041040040280442DFD806A490411021589C +:805B8000221C1113B11A0CC92121281886866881140080682248A48C4502258284012041582410044394184A1288024B242034184210220110F2AD7E3081124126485C282084023C0224002722C032168282341248C04216084440826641408204849018A442808204428A0486948460C421478C8304214528F163CFC0288430422E4280C8 +:805C0000444AC2188C0840A81248128C2832892885447488040012120080112151827012018008834128416441A021308A30142001169412483FD50540E28204001890442AAC142A64848A92488C211862448008009810023084430121C444459214822141818841208862820090140000128882885F75071D442830112428C041404201DD +:805C80002B1898214C08218810A2614BC11002B06861484A02B08424E588222418282814DA28641CE0411418A8428A9448428004004004EFCC08A4814880825121C0321745281DC42449223842106C8243D88504848A8491448949028428894501488485811408428881308A2C684482192261828A01E025028221228E9CA0468788B53C8F +:805D0000536490528D122E54812DC12F26F214BE27A8AE884B9238AB138B486552388741C7412534866085268AC8222744944C58C94D2A21B7D12B112B835624428855648C6188A9C386511632AA122F4183A8222D124F4441A212DB9EC021C0238F82F448682F23633417962D286F2D7881DA89541A8D84A9F4122A29E8A4F44492A6BC58 +:805D800092DC84856D8848A4ED424B618F48F4A8CC48242F2BC4528B4964A6F2888A47A818CF84B8C878C77C18E84FF448222243F7421483A445CFE8B94424741228A5284D1CDAFCD6D250252F2122C2211352981E28297451F2217D8B3792424B114E328F4C7494FA84A42B239DB11F462222DC2CEC24F81C6490182F85014F23FA1ED447 +:805E000043B414F84284C849199518A5BA8244B2182A94864B835EC8A0C94FC8DBC4290447C14A4588A881F0AD1850414044418441440100002041840412004220044218422084218421044200184C14C2442148214823A248214821482148290240082F2D4DF161475FF5515D5F51F5484AEFF1731A5B9BAF83F12B19FF11F589321F5F77 +:805E80003D98EFCCF4DC1C8F8D7B68F85848CF27FDBA98CF4AFA8C88ED8629D8A831128F26F21612AFA6F2A6A4AF88D924F9CA8AAF2BEB2878165C158F69FC869665E628F4BFB7DE9AEFA1F936322F2BEB63D533D12AF63AB28FA1F95216AF89FD3C3DCFE7B754FDDCD8AFA7F64747F061657F43D799E281F56C4EEFF3F37A73AB73EF457B +:805F0000F5FBD1BF5BF9A932BFDFEFA8F88E8C8D1889B328F35CECCF26746BFABCB4CFCDF91E162B8CCFC849F838AA6FA9F9A2A26F4CF88A8F2D96AFE8F9F6BE6F68A8CDCF28F988C68F29D92A7C8AF2AFB72FE8F98A9CAFEAFFAAB22D327F51F81E926F62D3AE99166B98DFE3F37674EFC4ACD56E72EFFB0F5F32F4115795F31311CFE4A7 +:805F8000F45B7BFFD7F37F3FAF83F33F3D9F4DF591323F1DDF64F1DEDECFCEF2F8B8CFCEF8D858CFE3F9B89CEFCEFE1C5CCFC8FD84C48FA2FE366E2FA7B636FF785A6F63FD18CB6F21F5DECE2FABF3C2C21A5D848761AFACDD82F8C44EBF17F3D89AEF8DFDF2D6AF8FEF2577C3F5CAC6AF86FA5CDE2F45F1DAD8CFE1F13E7C2BD1DAED221F +:80600000F39FC9F065633F63D3FDF253391F96F47F7FFFF7F73F7DFFD5F5BDFD9F9BF1B13AFF9DFF1C1E6FCDFDECACCFCEFBECBCEFCDFFBCBEAFCFFDEEFCCFE4F54C5E2F2CFC7EEE6FE3F6F26A6F83FFFCDE2BD5EFE5FD1656AFEDFDF6766F6CFC16D4CFA8795AF6CEDE2FA4FCCC4EBF37F3DC9EEFCDFDF8FAAF2BEB2DFDD715CF2DFD6610 +:80608000AECFA4FD56144F6DFD5E5E6F43F61CDCCFC5AD229D2A200261702641782403260326016088A0482C22898204820010022181698102908210042908988440882828420812400800124E248281F01C8F204804283412904141134842581241853214105422224C391420082144218A52248241502244490818860882208148040023 +:806100008244C01441814121844604EFAC042CF4112485F2112C87161F41B24AD141F24A111D24AB9619B24A19B54A3924AF5439342F147B24D812F924481CF9244A8D814FA27418F1244A96E1A27498E5A2F49824ACF491242E421F49722CF29124EB161F49324E1F48B26AD141B26A9921AB9451AB9443B24A7924B8427B2498B24F82F8 +:8061800084FB244ACFE20CACD141D628D141D618E141F442111D2C65D1C1D24A3881AD2553F148A443D2527914F84A855782AF447926F848B12FA2E114F824925EA52E12D661A2C6E532E15CF224129F4DE2A2E149F42C4113B92CB191362E1B69E7121FC1F42A841F41962A59D61A99442D344B4929BA2494326F81D442FA344A7F5204DD +:806200008480040000008100280048002004210080080000140084800400000040040000000040016F1807800144232194322A018B4222390D488074C4C182902820E584014825423414884334841628822231141AA8822349289988842200204522082922B8124A0A4846A848FE271418A67121783229C2215036224531122608160E8A74 +:8062800062814C827384821544D428022E442883860224F012488165820218478220A61247221845484818C8844A614A8C5D48145AC888819E21C1EFE447014E29AC52781AE21462214F3201C73249B22321721C8222F881584C0A8F2862214B1483242334E2F01468824CD4247811CA48836221124E982C3284A018884D2A22C18481874E +:8063000046641A6C422F8A514819C3882532488F11CC845F360F1812141A023022208284E1880448A0424490324142C014A450244C022800A02124444302981E2881688B12800100188220282498821A948880C2485F5B034110022215681244411124150800304284288488100840E21112E21402C018200225024B82284AA128E0810298 +:806380003048908210284204A04144436244F03D5E804284421131122C912124B0A2248251628420D242225842222A34118396242F9254484425F44224361634544314C41412848612488A84285684218C25E4418488416885260C8CAA1420F69C7600442114143D18224C0214E8281245420870222C1824AA248381C424A4164E64422713 +:8064000044284CE1412444644140A482836428A01A28C4A3848198448112816082100842229F11074C02282002165112645022942400306260228400142648E21432212419846261819024249012890A236182488142008C344212822844834524E542B8241584F4E7C980240545014D1890188420C82244815642095982421841982122D9 +:8064800021184200282942841241A8484440982AC18489024E124F88021618088B24223022109842A025DFE50D2034184008414071440291C41F280300AC014502690841448A11931241005024918CC22442899122521AA22424160849A18260430045188421012F422164A1CF9F0800C0281A0228432211081A04211190144028120445C0 +:806500000846420C8D64214A51848421441880024100124501804408481212421A1208523024D0714D81041638212E18CC014C43C844884E1AD02128146A414FB221624221504143D262145423CC11A4252D288421C42AB1248892182D2889C2385E28556281242E9826C8188D14B058926C2646882165414996483F36068212400C302419 +:80658000841C411892218562811C1101104848758498280084422E420044414C1202484440B44241048C021A242408481800123810A84220F24ADEA01221209112872389C12C818592A883322880124808288128188012082180022148614125124404108202830441A9010040044B1238181885042B121F5A04C42830C844C024122823E8 +:806600000216062902127024187222144241410416042200844483821128C228A4800118184E148B1800F0C1221812188622846282A012F02EC7601B46429224161C24110860220041102242C124188C8282410884408802A4403818301600221612A441443042005800180022200840F8C97340C814110048003502414C440283322411E8 +:80668000219140544940D248820218848C42140840440318C440480184400584428424422548420228005F7B05404C225128430141288110088184000000220040682200842222004902840040449824610000849028442A0118C0184964124FE20C4121848C3222899224000028440010440400402282111202412722424984621200413D +:80670000252412042283241324031859A22144284444306C44321AF439720000410081248001006C0185551881120050128901224185044180014412840024004C045028818C1801242C0810D248022810D84408848A1202118825018122911001420026123C281284122400262206413829C11624C012181869018C1104846890288CC24B +:806780001284C04821C9014C0141F027BD40981848A02800290448212546840225023111120025042E128008258A61442814844048C2455094220046110244488C622290144042024221F0CA63A022CB68F03E1426EC214978187823B82862A8813C120C491266822E3526A43236C11785382C2C5126CFA2B42C7224E865B414B218524836 +:8068000025EA423114456461497112B448A4411CF48E22B301118D412E221E124F21E5227318D4847134C4282E212E284FB40455A61AA1A4871828CD2744D0A2A5225E288425C42AD426D24F128F5384911361222D2A2D24282942586225C84423F212224F416221A762212A721AD584F21134C3B41EE3458493A88B4547AC1A312CA37637 +:8068800016542236F28848C9F414141AF129EDA01127E11582B616736EBC32F124428D22505A27226584316AA3519934A487A1C02CE04102878222122489B32CB26A51C45D181047E8B1110E8312C42C464E484CE8823111A5D8424834884B722992322E1448A9F47BB8100111102114A114114A1181012C012C0118403214100541001202 +:80690000218001188011811181119112151812811881082C088880080000F0B247141F39F3622C1E1ADFF3F3FC795F65FF5B781F54F31B799F81B739F348599FD1F11E1EAF25F522329F93F33C3BDFB2F22E3E6F427215F53D39E7C24FC2722AFA3616AFA7EFA3F22E1A474219846291CB322AF2242345F527219F83F22D2917353F13F348 +:8069800051123F37FB9581AAFAD99DDFD1F991936F6AFB8A9AAFA3FB36BAEFE2F172543E187AF57A6A4FE44DE162F363659F91F12F3D8FB3FB1736BF47F76935AFA1F52B6ABFC6F62839BFD353CE8F84F421399F93F33D3B7FB2F22222A7A27751DF93F33A182B22EF6A1AF26AE8CFC3F22C3ECFE4F42C3D4D248FD2F22B273F72F26C6B08 +:806A0000CD1FFFF2F62926AFE2F26A6EFF53F37D3EAFE7FBB6A41F12F27878DFD1F991936F62F23A3A6F63F932BAEFE3F3565E6FC7A711AFA6F7CB31144B334F63F7353FCFF3F31912EF61F97E3B5F73963A8F84D2D8F2584B3D3165F64E4637319D199FB2F23B39AF82F33A38EF93F331358D18A42FA2782EFE6A6A87A3EFE2F136162F10 +:806A800031F41C3E16F835391F11F214763F63F2333687F1EFC3735CFC79722D5BEFEBF31A9C8F83F359395FF9D5AAE922D3AEF1EA7A4FABF33E1EAF47F53E18CFC6F4687ABF29075F7BF33676CFE3F33E3F9FA3F35E7EEF76F33C66BD19AFA7F34A698FB1D29FF31E1EEFE4F4332B7FD2F3292B7FD3F1363CEFC3F33F391F73F3281A6FB7 +:806B0000E2F226AEA5FAFA7AEFE3F22E3E6FE5F5727E1E36DFC3F3343E2F61F31E76BFE3F37B3E8F51F1383C9FD7F73D36EFF6F7FA3EBFD3FBB9B18F85F79D5F2D926F6AFA3E3A6F6FF7B63EEFE3F35C5CEF87F71C1E8F86F614ED40016F12012501144001140040044C125128803211280080125248B04812062120022170220245022202 +:806B80008C240280444348028D22200485044FD709221504118B1213011D24A7221518C828A10010382420912284408242082240428481E2A241846141C024896141238412421408890121433248224C31241826082E433F65022CF4112485F2112483F41124A3D4C1B26AF18124AB9419B24A19B54A7924F84A9143F2429347822D955FCA +:806C000082C4954FA2C4854FA2E451F2244A96E1A2E459E2A2E449C24A1F49C2421F4952281FC932481F49324A1F48B24AD141B24A9921AF2419B54A3934AB9443B242F9A44829FB2448B84FA2F4944CC04A1F4146F2116CC11B21811D24E11318DE41B24A1AB548BA25B44838244E8147821CF92748986FA2C5814DDA4E81478286C14A39 +:806C800096C54B96D5A4F491283CF4916C3CF4912CC7141B29E7141B29A7141F417248D541F24A3353F14A2443B24A21D242F1844829F91648886FA3F4D69340280800000000448082810200000080010000000040080000000040042800000000004F9C01223011842E5268302124998442094021328883844454488042C8421449A6240B +:806D00006228488C815128801184511886088921C48DCB285883084C018984B28421A11228844D2846F259B480F18314F0A612818218F0128849C8881219E45804868492A484424A62865D488828472281C721843024A827463AB824A42822886148C3964216A41248A92287210C4C32984841462435C41C44F4FA6580F2C619F0861A5E18 +:806D800028230E1123584322112655411CA28282C31628542C50948349627A4CE443344AB04472919816A400478424C18CB4241482748469224F8421A21258288D6489694116C4242E522042F6BA5F80011C8102808192188E48896881428A044189222814A4242E484A024A028942882202224AA2924E242A8982198148B84861412AE1DD +:806E0000C824E28904430880A248A041F084488744484EA6004001830289912121482284000021002044080045021812AC2404128002100481000020C2288112004A21181284118442F82AB9242443C3182332522269842454248CE819244402418B144B289A522C4044346C90481C849482493314C396266314043902287244C3922462A1 +:806E80004B288308184CD484312422288A24322C891204A77C4002182992422458683044C041001024B1842258482304604460C4480049036230464C020020044400A28388220100622C820C83122C12F8DFF624E044430989235284142304A33A9846C422002D48A02100E14426082C61181E4298469A5445EA41028424266144288B12FD +:806F00004426C82462444312382843751864421282302416342244187F74012AA112400289824661842C231A084054432A819328814B21881A042C0230181880082306498182C28289223121C821301C944A82B4822484814224083260447072061012844108800188804108008224422A286442224441469444409858800248A0844100FF +:806F80000020030020086082921A040020014F6D0611100900124031488448109A488B84C1901400002800264A140422001A02206141888C128802004A224858481084142862C24508005FE20617231A0212A1811290412C6B8A8110C244B74C8B382E128F4132A81A868292244722C04887418321218282841324341486C4A82E18208CD8 +:807000000285C441488678C42814A425C1828574180418F0A55D00501C0028621311C848A0418184814004424034844A0190444C1242C44882242848122A88C212001D282622011283A22846026083881A8422820246041FC906250200211008222002200884881082042220084800800420089A1284820122002002188011042220C21407 +:80708000414C722448A4422F520F16C424B0128201304400202C290100208429048248504812444844443220422412C22432009024802A28010044C01468488924815484EFB7072442208301812002284A48840800108281848228044985014248412800322604438122020022A24988A1124100203314424C8202812F2D07ED188F46A4A3 +:807100004425020046045044444BB22A2312880848C2242552229AA1118B888A68484004132188D28C58A88B646AA414009024004D14444B2228224C02442A4464A4E7212D463E54FFE8020000002002200100008185042008006042000020042002008222000000002028042021420440F4621310781288840400A0140041CC228302002A +:8071800012002502211898828800264431211C4298288C644448000082004144222800000025C22429B1D8098424481800000040048C0200000010021880684244442042410484284841A028000088442A888284880420044421288FE902298144021218000044800300000010061880080020414104860C482200000050448002004004E6 +:80720000201802186F1B0C001210222101000000480000000000800200004042042604228200000000000020040084411605A5384C12422244000041B024E28222023088124052222412A08B8A22082218131231218538188B44CA24248802800C4514382420220100401252281AF3367340D2888484140200524044544CA0220000001094 +:8072800092122A81018A0800411414508484224A0400820044444584A22242200880382421212E2C40041022018418001200100884002800000010044441C02220222201448008000088842044820430440028F0B3FF001280018001141210084820010000000000284820021004002008448002888820280400001004008F6C4442061AD9 +:8073000041321200B051011A112861848001841A010000224C226242702424A1224562222812124B2249AA82002004821028044A810480E44828D2C812F456EE10B2121182011A212182040030184250888D840082440000104404266444C0244F4288022028E84208008880A8882004802895244004D0360C18442423814394181880013E +:80738000508810080020020000222828489034A0224160422E248244A028A0288A088881008AA448234404424141222E24BF64042F22D222A2122B111229012C512329F812131F11B189F991898F84F888418F842454911148955C884E488F44F424444B242E24222E2480524445A6222F227212C2122B191AB88228E828592229F81213E8 +:807400001F11B188E999F848888B488F8424E4840448855C884AF68D8DF0262625A2123A2111021C5122213CF1111119ED897818F88841CA2464941501848588F4484445B444A22622448052424584F3262625A2321AA1812B8982502229C81B1B1119E889F818888B48CA244408405888483FA90100141100000000000000000000000028 +:807480000000401808000000848100000000000000F07D9C0040110100000000004042024002255222250240424202008481000081810000000000000000005F7A0E0014110000000010024002502224000024250885020040588840180810080081000000000000005F180D00141100000000400210020021240010028518080040085001 +:8075000088000010181808000000000000F0746C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000E7 +:8075800000005022212100240000002125021012020000008100000000000000000000EF7B0F0014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000CF +:80760000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000E7 +:80768000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C0040110100000000000000000000000000008481000000401808000000DB +:8077000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C0040110100000000000000000000EB +:8077800000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07DF4 +:807800009C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F540800141100000000000000000000000000004018FF +:8078800008000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F5408001411005D +:8079000000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C0040110100000000000000004042420200000040180800000084A4 +:8079800000000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C0040110100000000000000AE +:807A000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC70900141100000000000000000000000000004018080000008481000000000000DE +:807A800000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000068 +:807B000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC70900A7 +:807B800014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C0040110100000000000000000000000000008481000011 +:807C00000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C0040110100000086 +:807C80000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100005C +:807D00000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000002424400221212140020000400881008100000000000000000000FF680700141100000000000000A3 +:807D800000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000020 +:807E000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000021212140020000002163 +:807E8000210081240000100800001008000000000000002F75090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000002421404202004012425828000010088481001018088100000085 +:807F0000000000001FEF0D001411000000004002100200212400100285180800400850880000008181000000000000006F47080014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000073 +:807F8000000024242400002400401808001008818400000000000000009FC8050014110000000000002125120224210010120221A10000841048080000818100000000000000DFFB090014110000000000000000000000000000401808000000848100000000000000F07D9C0040110100000000000000004042420200000040180800008A +:80800000008400000000000000009F54080014110000000000002421404202004012425828000010088481008181101808000000000000F076DA00401101000000002400210010420200215088810000840085080000101808000000000000F07684004011010000000000000000000000000000848100000040180800000000000000DFCA +:80808000C7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000024242400002400004042020081818400000000841008000000000000F0731D004011010000000000002121002100002121840000100881840000101808000000000000F0BB1A00401101000000002512120200EB +:80810000240000002481240000818100810000841008000000000000F07EB60040110100000000000025022100000025028100008400848100000000000000000000F02C44004011010000000000401202240000502240185A220081008184810000848100000000000000F0BFA7004011010000000024242421000024000021855A2A24E1 +:8081800025020000818110181818181808000000000000D0840E0014110000000000000000000000000000401808000000848100000000000000F07D9C00401101000000002400002125121212121202A48548425A828484854808008100001008000000000000F04E9E0040110100000000004052222421251202002552222502A552227B +:80820000000081008100008400000000000000F0162A004011010000000024241012120221000050228184A542020000818400000000000000000000F0C431004011010000000000000000404242020000004018080000008400000000000000009F5408001411000000001002000021000000250A0000845088400800004018080000008B +:80828000000000F0573600401101000000000050220021250200502240180A00401808848100840000000000000000002FEB09001411000000000000100200212502240081002502100885480800000000000000000000F05C8D004011010000000000000000000000000000848100000040180800000000000000DFC709005011400100FC +:80830000000000000000000000000000848100000040180800000000000000DFD10A0010010000000024000040021012120224814002008481001008000081000000000000009FE707001411000000000000400240420200100210020084008100001048180800000000000070C50F001411000000000000000000000000000040180800CA +:808380000000848100000000000000F07D9C004011010000000024242400000024000040022400840081000040181808000000000000F042F400401101000000000040120224240000244058280000100810080040181808000000000000F0B857004011010000000024002100104202002150888140024008508800001018080000000014 +:808400000000004DEA004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C000015414101000000000000000000000000008481000000401808000000000000008F5A0200141100000000000000000024242453 +:80848000000000008481000000400800000000000000F04985004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000040424202000040020000244002400810080000848181000000000000002F440F001411000000000000242140420200400284850224001008100800401808000021 +:8085000000000000008F1C0D00104141010000002400210010420200215088810000840085080000811008000000000000F0D343004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000A2 +:80858000000000000000000000848100000040180800000000000000DFC7090010011400000040424202000000000000008181840081000040180800000000000000AFC8030050111400000000000000000000000000008481000000401808000000000000008F410C0014110000000000000000000000000000401808000000848100005B +:808600000000000000F07D9C004011010000000021000000100200000000005088000000401808000000000000008E3B004011010000000000000000404242020000004018080000008400000000000000009F5408001411000000000000244042020000244002000084000000008400000000000000008FBF040014100100000010024070 +:80868000022424242100400240420A40480800000040180800000000000000FFDA07001411000000000000250210020000212440180A008400401808008400000000000000004DCD0040110100000000240025022110022502002481104202000000000085088100000000000000BFD14B0116410148488C34242028225858442884805244 +:80870000482001128282A290928001224C282414420882C0482A1184240282202884C224C483A129892209126F6E061964848146591C45D824324866946417413832869884433224C921A329E8988E425646C2523830922388ED4489C484412AA4248146F8984441C364862AB814C4242A8112C4A443043A3424481A088F2CD148BC520C20 +:8087800011994531415443D428E6421484641120018800842822422044041E2226420218A0124B480080028884B0283128A0212200822200462821440842F074B700100800008088A281918948342C2828818A01181852A0480082201804444522464828B49404004A082009414CAC243034848222188378C8B452040040C84810148884AB +:8088000012044084020000288888860221181218211200C8000081802414243244412002000080810124241FBF09420000840022412092240010C4144C019800218200828028A48400428004004548240400220040342430242888881218AFDE0300180000000000004002000000000000004800000000002008000000000000E038043045 +:808880001181138134618C322881CC223E68C0114A08E01102218E48268818844C4A88832414626492A2121A44A282897318048AB41242B844822A88080000001648942442CF99054A031684C222168C1534442181141A143A18121A44A64387441644C4444224221846F5822CC042284902A0280044683624422408114281C3044AA818C8 +:80890000C0346A81B4288584F27EA9A0141883012E424B241E68492214AAC219866481CA21A14136B5127642EC8861C2434464242C82F12156868454224E242F482188A187B022382C874549A148234368442E8182888C044288208234182E1462628FC20B2211411B2170110884C14C1248C8121181000060448088844818088B242004DA +:808980002822000012222822448828801418048218C01432428C44041F7A0224001A02001181824E811962140043210420029028222002002081280144C800001084322848220012004A228122C22482001FA10A18542313F622182CC1348D441D1249E38201844898888328E2821164162AE44148E48482D48456846F8403E9C42243A678 +:808A000042222E144F11024983384422432538248A61368144D81E2C8CD142B244981448284348F4ABD600F01222228C021A120423C98128008A41B44888120819A4241241201614588224468C4824C62449E912014C024443A2168C4A2462161024381C5249A2844B21624014D4A20E18716041236121441784871143E2841371488104EE +:808A80001A0880332428B08C223268E08442B4240512282B25004A4204128842400462922481124A21722822312440A48282F07916206124200210542511818CA1144CC2854E1492181284A0812F4804C9048A156242A0144181A28241812212322882241C13E224210810028A41E82835144C22B1840423F1C2F260424A220241210020E9 +:808B000033822244280000284D484CC22220E843A4284A3218A8108232442601A31884028441004E8889528428208224820428424128482F81F2B347001014028B122688C228000081214E28CDA214800300508284444210488A84011A2284012011922420418404528B4884850210A8180080F46677302428433222806382599228A49878 +:808B800058C087424AB2188A2162C196840AC3B842A2242742CC222855422D284B243034484CA3212A4112C4242CC288244A8822358242A284CA31383624C1C4488B24DFF4091810024542180425A121812840C81496481611A84228490448854428848542188824A982908200B028214832114AE1C11608C0488116384250428A442402EF +:808C0000F011D7202101002444000010042800267124210121C31422A4614186180446244804402402008D44422E445110081046982490449044102412F22CD7C022C022322828208102221280021AA8824880C68400844430288004902489044C84448862424F2104C120748204AC12E4AC425628608889041012B854F295520050414490 +:808C800015C414442022020020840290241843225284904410044148488A240400448041A4C21031810040024304422141622002F09E6640810600481410814481120883822802001848214800888A054302812848D0840200004002602442830424002C444222224404CFD20F18182001E08182440884488004288848800480840428804A +:808D000024220210982842100800A8A8A0611002844822400822220020F814AD1052821E2848A1000041002228140000A0184800281200008100412004490281204412240280D12882C14244841A04422238F0FC6E2044840420814404184A02174418000012A8001008418860844880040084002810483241904690880080881404826554 +:808D8000088A24F299B840210221C02416814221440114402104004410044C02002800C90849821404004100908600188004484C2283424464434440F446D240081C8542012024046046A024430446644242882210021887248841901890181480422882044220088842264A2682228244424202484823A484AF1F4DC2438B41172147245C +:808E0000114B121CA1458714267429A14455A5446681AA2C424AB3E4614323143846425A058BC648448784878A424E444E44448B22442E244E128B44844E428AA4282A7528428EF4222A222149F44A4629FC46246249B2C4F8924680018B3240813251441158421200288A04193221688A09F028482E44848120E48426B844D14844084873 +:808E80004122188D4486A84437581D876F444488B86A65AC4D444D6A8D6287A449716462824992982AF739A830312F4243B53273286465CD24282A2284A2226688D1C124E342B82454441A982449F6444C10F424224D24437924AC124D44C84F828292244B24842841414BA24F283A246B34502A2784504A4AF142844B14274A224C82D5F9 +:808F000042A44625E41F08174410011190414991411819849141184118484C9141850444400444604120810888810000188421C081C082800888804888488848884808AFDC43736757B3B5FA1233E7D21F14D588F53421979357528F83E713F2314115F451554B67BE2417569F91F178984B914AC44C2A16F4286E2F81E3C6D688F52878ED +:808F80004F41F4A874CF48FA84C42AE246E242D244D244C3142F4AD24254677F75F9E624BE32AF22F29ADCE788EFADF52E2E2B9F6F6AF2D61AE7E4EF89FFACAC5E58CFC7F4947C246F62F15353FFE3F31736EFD6D455F129291B2387815F51F5393D13E143E251E145B574E64B7A21F139398F83A3B82B4485F84858428FA6FB12387EF879 +:809000002AF36C7C4F41F4297D4F48FAA4E54FC2D644F4646C45F424744D546FCAF6E2267F66F277776F4AF2F47E2FAEFEFABEE7ECEFEDF1EEAE6F6FF9A62E6FEBF78EAE6F69FFE6E44FC1F5283A7F8E4BB262F63566E5FD1436FFC3F375749FD5F564348F86F675349FD6A6364AB651F145414BB6EE644F57F144414F47B114B126F224D2 +:80908000244F4213F42CEEE5F83C3CC5F83C2C4F4BFA8C7DCFC4724CFC242C47444F42D644F214344F67F7EC2E4F62FEA6A66F21F926A42FE3F1AA8AAFA1D74CF81E14EF6AFA3E7EEF62FE5E166FECF836746F42F2DCD44FC6FDAF72243F16F73477EFF3F31636FFC7F73435CFC6F664749F96F664658F87A7745F14E614B454B544EB4EA7 +:80910000FE74554F56F6F4F44F49FB2424CFC6F64C4C4F44F47C6EEFC1F1AC2C4F46F67C6C4F4FFACCFD4FC4F66D6C4F46F64444CF4256447AF37C7E4FEEF2E4E67F6EFEF7F76F66FE3A1EA7A2CF8DFF4CCEEF65F56E66EFEFFF6EEEEF67F7642EEFCBFF6664CF4BFDA4EC8FE806230221B026012A01000000A048000042200442B0480279 +:80918000008B24224243222402430200240048C048248C0484244880840200CF1A0B48124722440042446220064200A02443621443881304414C02857424084882100844004180C1684AB8812202221002836482A180022324227424F16A75C0521F417228F2112487241F41324A1D24AB141D24AB9419B24A5985AB944782AF1439252F43 +:80920000147B24D812FB24481CF9244A1CF8244A16F1244A96E1A26459ACE449C24A1F49C2421F497228F291248B141F49324A1FC8F24A111D24AB9419B24A19B54A3924AB9443B2427924B842F92448984FA2F48EA4C04A1E64241ECC241E2C428CB24EC1282F44C9282F445B84ABB44782AF1419B14249D812F922482DB12E528D812E22 +:80928000D216F122CA87192E4216C1439E212CF4912C2CF491688D4217484AB19122E481F24A111B21A7441B21AF443311AB34322324B3426183297132086D585FEE050049040000004004280000000028008008800100000048200200004004280000000021F031A7808101263122812082A21828182034482A289A54608A00222088C4F1 +:809300001141100820D248A242322C1224826232458802180020110242223034802224FABE47241420238121A621992115222814928900A0828852288E4CA0422C243228802286222D2444220C28A0488CA1841A28A4242A0420088C0142228118C8A6018FE304184A2162222280024A233924462262148C822A9A74A09226C288221AE664 +:8093800024A8482E1144200611684E2C89266D26002226212C8AA414412082992218A04250842482489AC2F75012803111188C86F11128248028018628042088C848904400201208288428D80030223024284A6881E112802206004028042832182A840ACF1B0F2215044CA2161A8201218C168AA2849018842009928111814889082042DF +:809400004468412A6148808261410026028002168421A184008218806288428608AE4A7B9190142A81C21182A18062A14CE128E33184511AC84AE3A4C822A2224B2142824988424C9248624A92622B482AA1284443248ABA84B212D424A3529AB4C8E388A486AA049DC4C28CA5284B188A810149E244034FB60541132292214A2203C018FC +:80948000A18E1219821C31188CC482A28A2228013084884508262864842F2204448A322441A2884CE2224194428826684142BA04481088292122811424622C6FB504384C014CA181252821126247A9A24123112AAC2189841122732498418C88648240829424284CA1E13A08A0141624622848321AA252D24E882A09C2C7184A882D328466 +:809500009886088E284B1426F8FC6F202404284A3228F01622426C014662442181298802134A1892A650484886282192241E28CA2298228C62848230D8814889C8161C22847194C112984608881A2628B348032842F08819244CA12416161824C128C098C028284CA14820C21812001221A029412A1C1898124470280148458824614450E9 +:8095800024C06800224304209284284308890812460212DB2E8002301400108828020081602148144901838A01008042441802441882282100281222820042200880A114B01802E0822888086F9E052A84028B12421E282638262F84612222682B142784843AA84213A138842B124B2190A84984E281524827831E2450481AE28822228C71 +:809600003198284725824FA82582A4428A41220949A8C2F2A21EA889321862C8F078A6F08618D024413424001608161408204802A9015490888210048C04224425A82C2E82806444211044088C221201124621098C8421416481A041A882009F360942200128200284422448482184288A2502429A722228D882882831240084008668180B +:80968000AC842228682A82830200818128202102828128829A842228F817B500224142834543688142238104411C1101001A0823241108222284292212648421291296822424414002301824223018803248818180C822801188F4348560885284008A02230228C02841420021424284810022800424814A12480883044210088410082609 +:80970000088284C638488200224842483024F01674501200181489E114421152281225470816066028200620014280E444C14420288494122088032F8401499514415084424400444212818F22918826248481F15D8E008002224A01004A08002C0100282C0200282012D2280222840080140210120200280044200222A80000882324E823 +:8097800018F17D7EA06110C8512F8104121C02272246440700AC58481844894884480C4C08440020C2218718282A842428A32849A1212800A8824444280018204902882904CE9D40CC2A0049C821C148133614284C73585381141840B288C41220013A1C4202848042C24421825042608816A22800C4414C012F486428122410883242401D +:809800002802F08F3524228728C0220080840288008146882A88418268498C280A41224242898404008440222142B82801008182818A1214A841422A088410242824F2BFFD00C04140E1286435400936484481622183E141847838048422274181244288264484912289C361008C0158101474148A248284C4448002824044324818F0120A +:8098800024481FAF493222A69A2A182F48F588412E613E288B448B83424810F949198F8811A2182F86F882622F85B39AC32CAD2886B422C56A66D888926C8B86248BA4A14E282CF112822AD122FA142A8C72147214ECC252CC8E888B2444122A12A22184AB93CAE24129F56415CAD477025A3288145A5681248D1E271415937249C8333738 +:80990000942F9561212CBA84A185CF68A59447488843AA43496624439262656482ACD2437522B81446A24A2A11F8681823F234144C8242A2DA4B441E884B4883A414AA94184B22AC12528490482AF86C2AD04184D78451218F17B27133531D422E2846F63A72B3D26C056123F358C42E221A52888968828B918E822E8228874447416AE462 +:8099800024018F86E228E4BC98C22744826FA92AF98894428D1889148812B8A2E482D882F184484E888E8881CAD4A8FCE242AAAEA91AB1BF4452412444148604441844404802244110044190449044100621830116146241604140044400230427149012901248211618022141100445087F364E7181F15716EFB3F33D6A3F21F2BF2DDFCA +:809A0000D7F23C249F83F224348F88EF21F11B1815F151532F6A53EA6596662FE3FBF2B4CFCEBA24EAEEFEA2266F2AF23274CD26EF6293364F81E5A5F694B64F21F9BEA2AEB26FEBBABEBA94F8E4E4E761AF61F43D675F54F196FEEFAFFF62B22F44ED25744E7E2ABA3AEB2AFA666CEFD6F6A8284E448F4DF57CE6ED79246F65F11D3CCF14 +:809A800093F31F58DFE6F2FF3D9F96F439611F37F6A6A62F4A5E13BFB75755DF55F7A632AFEDF41696EF26FEEEAA2F6EFA6EBCCDA84F8FEE4EEE49E943F71C96EFE4F546584FA1F5574F4FCAFAEEE2CFA3F266766F63BEBEFABCE84F4FFF7E76EF62F63D67DF56D3EEFE6A6CEAF7E8F2EF65741AF868C88BB3AEAAEFC6D6CDD864F82E88E6 +:809B00008F45FD7CE42F3547D246B411E473F2392AFFF7F67363BFB7F2683ACFE6A7748FCFEF25F15A7AFF54F54D4FAFAAFBEEF84F24FD521E2FACBA96FFA6A8EEE48FAAFB86A26F22EA62F27C744FC2E6E3E627F6467FAF2CFEC2CCFEEA4F68FF82F2AFE8FA1294EFE8FA4C4CE5F476244E1A4FC8FEEAE45AECA1F29298CF4C38A88FAB99 +:809B8000FBA6A48FAFFF6E6AEFCFB3E2F6E4784BF6CF810D1F1DF71D262F53F25B189FAEF63F3FFFC6F62979DFF6F3EAAAAF8E7E41F1597B1D13AF37F5AABAEF8FCF962FE5F9C2AAEF88FEA2ACFEE48FAAFBE6E25EE6AFE7F7CA4C45ECE7F67862AFB4F5AEEC8FEBEFAFFE82F26F69FB98AE2F6DFBCEEECF81F33E3C6FC7F26C3ECFC9FFE7 +:809C0000EAE2AF8DF4D8E8CFEDFDDAD2ABC68FA3FBA6AC8FAFF9EAAE2BBBAF8AFAE4F86EB48FDC022A012E1180013C8124E2812402E081442149A2412CA24889220100A0241008830481002B82B022016941484228420886484208482C6281288242924282BFDA07000080062881122C8804842186C8A2102A08A2888688820443022A041B +:809C80002602C828488240B828283124100480220481800842260822001D16C0421F4152281F41B248F11124AB141F41B24AD141F24A9219B24A19B54A3924AF1439242F147924D812F924481CF9244A1CF8244A16F1245A96E1A265592EDA9E24ACF591242CF5912485F2912483F49124A3F48124AB161D24AB9419B24A9945AB94478305 +:809D0000AB9443BA42792498924F8284F9244AEFC90E1CB411068C66141D28A3C428A71419F242968CF248A559F24A924B422F1479A4F84211478A27146F82E414F9265A1CF824DA8D816F2264182FA26458BC6C48BCF4812CACF491648D421F497248F2916483E448F64A121D448D1619D648BB95F44AA247838B84222F246183882B43FD +:809D800029A8527FF60E848248100200004024C82400000000001800000040010000000000004480020080010025012FDC0B4800215281489053204CE2813488848E1200E08801008982E24402222A044008820012888281828922E3820846A842884820A448002BA52002C8DF3402B08201182832188820222282084521A44A43128202F3 +:809E00004A18040000602284802281E21132228116422492840049A882124281480022178C80A88414F0C4EB2074D208215289A2418813259284222BC340AC814A88021EA82440648328C60420820215282239282E124A8328018AE288028A32844F84A224A2484A2224042CA4E124E214884F990C00202122011002621068881448291231 +:809E80001402A048002002224224810000141028180E411A12088812428400882299088800484B88002008880080080000000000000000000000000000000000000000110010011400775E200231181285C4216228846B121C74118238828CB234A1483CB82151421A82F8854854428542A8241A047368488F82A5A400311816D148B441DD +:809F000088021E287F128144C2846B28841AA14A29484204A89E488D25B02242D281A141894864144C12C4282F1281F491828421839154422E87116B381A782838844E45221D228D18124A2C1803188F42822814C71412896A18669C249127121AF588828423A44149239282248E148B818C223818002008200880080000000000000000F7 +:809F8000000000000000000000000000110010011400FFF4024840031C0100002302148688A84229218881841181B32504000026285182441880410400484B12008281102841228812C4140082C04815071F22D124A3128D12282AA14247824E22C38721B448011C04221E6828A28AE682A448001CA4241E224A2335244CA4242249C2E49C +:80A00000803A248B526B1A8843B9549222D223280546D14825BC12BE4898448849644149B28902582229C1121322834604251C22D481918819280216084888622A2C0213A44216A2168B244C13CC241A42A486448810B882C2A4982E14218A31828304F04284422339844130844C41FCFF47302163C12381180026A8243A84034280C442C0 +:80A0800032AAA412A82A45299145008002122448428032148062424AB314241124249A488021C14189A1824B248C858488044AD27D4F2241B1483218C018000042322C082081681431CC4298426014228001112810012280588414144602830113214224024608284F82A814808101E084F3F22C004810A21420221301100C2283A98200C0 +:80A100008C01908211884230248800D081A28600128C8603D048248806444448AA21880400890B23622218187F8605280049021048982838964802C24C0484818A22A14800840042A8419011421882220088122832481800588D110020911200284200F07A68001128A3A21481848341889398835322488B49328908B67818A4484A48C133 +:80A18000884820051110A1245A2A0A9243E2139811284381244241041786888C28C4328F42286481B012862231486FA8062B121068412021826212200488824482D08154122281001984024C22422422410880020060248C96981A8481A214121848001812A8320020F2961D304218201208422501424B1442228911D212228421822808EE +:80A20000882348021C0240E1618829484104200820E421222228028018A282A04100420024427F7A0F12288142248082410A2822C8298888C1822E821224421C082822001126244801184B288A3185821123F811448A124534412741193222188A820422214901008249F2F6778001001334188180352881009028800122809182108806AA +:80A2800020242A04120020A421001200828C01A818688200880018188A8481F15D8F008014A8282830280024248901524048E4288458414212484C3842122812002100899221A113212198162220081810011828224C9142814880045F2B04868162114212211A8201124321C644424E1219E889B44988A1148021528120440286228884CF +:80A30000C242208821A2284A51411A34C14289832F1802601182423024E8828042B17846622280A2212086641481422A18A8182C018D1228180011280011A02412174416D141A848223A24044B41492402602118748411E8D012240A109288800112481F370FC012484008102202848E14A48DA18D814810422192221411005014114004EB +:80A38000004D814443082D42499842403424424142604880342444414884220044AF7E0E1120414801A04262818001C02122002084098A21022001124381011212121860414821A288004A48A818440025C288322028A22148E0A20784F021482094481088A1122C542880028308266E281880716A14A19428C82B52482904601821688CF4 +:80A40000948248002180210212444AA134148218248301002382F285A3241E22928B122A5421A9E7A2E2110483F1241C4AD22872DAF2313B2D91A6F254812B9A6E52221B128D2421493242472219E161A2884C18E221F18244445F48E944B984E844E724B414FE819627427E144F4A3A9829D14408AEA1B02E4894828D9820E2157442F413 +:80A480002E9F90127011E985D28824A6443B168F23A454E83E122B49118A3CB11ED8AFEAA241927D112719FA7949E11A041B71482EC12D511E531A84AE924F88EE2196221F41E129B81731824322C4EA2B112A8BA81C13F411524BA8CA7234F25844A23A042A91648F4F0217142E3228815E2184128D284E382E288725ADC84F84C998A3EC +:80A50000F44828A384C12329A88D4A48E18AE224A84246F172214B1C574553A8B8825F11A2174671B8C2232186A5165E214BB197188B441734FAF211622BC942221E5229F124184A84AB858AA2129F150E11100184211042180200144834400110045181450245021502241004101114111411121152812111211221504212002001002FDF +:80A580009B4DF3212337A1BF12F211319F364212D839F3637B6E7A8F2CD922135A33BF9111F321226F62F813113F3ABAE2FA6184EEE45F7EF482815F52F657753F76FCD643475C6F71F146C64F4BBAC27C74F575667565512E211F26F253136E472F7AFAE1B27F66D2ADF153631F75F4C3C29E822B57EFE4F4A2B26FC4F148885AA7CFFAD0 +:80A60000FE24426FB34ED231D113F421291E799FB5E581F17A5ABFB6F67B332E22CFAEF8E2FACB768D8A8F88E818F8D1DB7FF6F4A2E27F79FDE6263F57E14EFCF4766F7CFEA3F31F15F466E62F6CE774F5C4C54F56FEA6346F18F3E1E9EE633F2EBF33F2B1A17E773F68F8E3C23F7FFED2F37F79F2EA5F2F2EFEE3F73DC23F31B872F74ACD +:80A68000EA4F2AFA7C6C8F82EA2EBE72A4476F23F7B4C8243F32F23262B5F111119F96F272785E122B24BF96F66A682FEDDD22F39AAA1F3CF59B13AF37FF28BAFF76FDD6967F7EFBF7F53BD6DF13FF21534D873F12EE25F761474F1DF4C6455751DEC3BAFA46444FC7FD44C77F69FC97862F6BFBE4A77F4FFB51462D844F75F86A388D9F0A +:80A700003F15F7D1F33B54DABDF2FD5C5E6F6EFF4E1C8F84A8752BCEBAFB2412FFCD4BF221333B239F92F258399F97F732388F87F5383A9F17B732F5FADEAF2AFBDAFA5ED3AF89F93B38BFAEFF7E565F7FFF53D33F1FF77351DF1BFD24742F14FE31E14F65F4F5353F5DFF56D54F7DBDF2BFB2B397F3F4F51F6FF7B6766F3BF2B2A77F67C1 +:80A78000F7B636FE572F7EFFD1D27F69F3E9DA2F26FE45F33F24F5D1D16F4FFF5CFC4F6EFF7C7C8F83ABBB2B8AFED24B723F1B0B2A0121204288E18144E18144E28944820417892C124126282488228802421842514288424929A412A092F02481F02481481C08221A049224482CA2418922091228F01383602812A1281848C02880220252 +:80A800006089460242B6082A84014A410819A424224219290128B0418208256141632401928B86441C292884044198604422A048C0415D7BC0521F4152281F4132481FC1326A1D24AB141D2CAB9619B24A19F54A914B42AF1439242F147B24D852F924488D954FA2E454FA244A16F5244A9E252E4A96C54A9E242E4A1F49C2421F49522833 +:80A880001F4932481F49364A1F48B24AD1C1B66AB911B24A19B54A3934ABB443B242F9344829F92448984FAAF49941C04A1F4156281F4126F4112C8354414AF1812C8F4411F14AB441AF14BB24F44A91412F1469822D912F82949829C5912E881E818C24E98264599CE449C24B17C9ACB49156281B69811F49324A1B28A9D1C1F2429417F1 +:80A9000081AF441AB54A2BB14A79249812478329F9264829E9A8B58304000000200282400428000000002180018800004001008004000000400428200100008121F04CEF0022802102284602288C081B142B84608246327119826A581B421A0449B2235481D018A2241828B6084A3222188492824B41200148882212881008A2122908AEF1 +:80A9800018184AF2E528E024B2848121C2421E221485E181F282114A018219614810C8828E584E11528841682308902A00178449C84220A9182AA821431231222128632AA84352C8811E81882A28216886238E4401FF960E4E22560412482C233248A128C9041F2229BD848242E225BAA8B411FC8146CA9254122B283B288181850115F8D1 +:80AA000081248B69B0282CA2248CC274344E32806348C84B69222A25983182A28A4262822DE24EB81823F7CD4800281828260214112E121389094211403848111C218211012A4484443122282A2405102291929218828844002302A041888488842081A9480000BF360B2400280049410800122182241260820090418044914114A0212055 +:80AA8000C11280242402271220242982324213A89282244301003288AA84290A708E0928186F2291188363228CA63462278A228CC851844B491DAC602919EB1A21B724611887122844688594481F82C424C84E24282E141B8449C1884D128B82432218E419B228944113832CD881AC422A35844A12A44249E4443A245F480424100218242A +:80AB00002E481222238232981C0186140A831141013E44822E411C5214224100222002284092214D1246684A1024C9A819A1928869D88128A642824A9224C2412AC8249E732082B114D282C3282849E184829488002934881AB4A5012AB882A3387814148420C441848B529396149AD442A4424B411BC249C188A082122A88B24332416A3E +:80AB80004821848104184323A8842A216E44F0BDF90060C5843283AA21CA0210011614884422EE242221022180081CC1488B840088912AE581422164A280044A884A913112860400248938844A22018C3222A28BC1FF7E438104421C2304848741282E8884844C882931888444E210B14209224B4289034C691A42161141823C448284A0CC +:80AC0000482A01202328C21412601248205741421282292881F3DCF330120021808924D88204380011901412855181421284480000225289026844A02128111A9835800248A97444028384C8824112841422684304004544A31450482F122196188CF7244284898A021A98981847882F8659689E284A223198488A028094289E614AC28160 +:80AC8000814931882E514217221845818288E82522F1241240088611D48228E344A24178E8A2828B248F13090018841828608162D0184108114212B0216414408104E04472211898544028A1424AB22245A48280A829186822118F168884A941883042128F44082850488023D8D30E60888021C34184122A849448AC8221C9C8C02181224F +:80AD0000263181394291228219460188914E9898822184329C9221348C42248484C26142624448824921220148222098421F3A0A4842808244024210C222B04828042C24444262A400003127814222840048100100301280C31230419084E0228408C84A0942828800886F1508208941081A22120821120020A182812A98891480240A00C2 +:80AD800000184E21402822822106001A04A02100320018838502228A01802684FAAADD00100115085828801233422004800A48800190482220924800144021842A91888042242892829082114498001A18248122828108846FF30248442890281924840281228A010022800416082248828004888188848018810100160142008880888C70 +:80AE00000181812008928001F034490012A0124A01914A81420290848884844E812419EA6428230C8D11230430481B281628860AC22814282E428213521886882482828422842C882222820C1A2A3622F014E5001410012400294181454282111231122224221304178890812D224E8A262281126181460114401101218A2125083C8111AB +:80AE800002C042435428002C0400421F960430828942888801218184888AE224018888004A81088828C24A022860228A25C22222888024042289342882121812280000845A0818130227414E11F0A3DF40085800A219422824024C042816321D201C28A184304A1902908800B082014E1128881518C2485014481119228848C184823812DE +:80AF000000882001B02208EF910E4E4286882183A2E22B63812396433AED24F892425AE981E51BB222A1448AF527282A2CA6E21B8D2E228B542E62A03317381E596E889A14A198526E811C62224F11E286EE1423ACE89A292D0A4AA89CEBC382AA28B68168224B828E21486F9F0CE049311885283B11116AD628D1A8022B284D1829C482C1 +:80AF8000D5E888E6A868B68F1D3D418A1E0819582293E42246A9E383E621A3A62A8EF221738912E818914953A1811A87E11294E3E84AAA48E0CCA34621923A27A9712E11CAF821FF0019B42192319F84E5347148EB818126F2432A2E584A28388A2CFC41812A92AB242F191173C1F92A6B2F1CB4214278C8B888F84A181BA88308271C1734 +:80B0000083508117223B2127C68B188F28B423681239E25231429E561AF11848B01CAB31D842292BA4C4A9F2C3A8001C41480100241E48140040020000000000100211421100004222200243824423612248228A14022584148294220012F0BBC64052571AD119E42EF26323BF34B642A623BF17F3BEB28F23F382822F28F95A184FE4B324 +:80B0800032EB22F273F16FE4B482E51AF621A98FB37C2272617121E122F8715B2F23F3B2318FA1F1A2A21AF359518EA22559B92BDB8B159F8BF189C92D412B541F3EFC83A329E821CD525E182E22AFA1F24242211F28FFC2D24F46A6542BC41F34044E426FC41418E824F35332B7342181AB15AF6DF91A122F42AA98DEB84FE4B332EB2A19 +:80B10000F27BB9E5FE92922F12F669A98FA1F482C21F1AFD61432F26FC715BAFBBF3B2B18FB1F2C2225E511F85F581822F1454B92B888F85F119D89F95E11AA3541F1CEC4CE924F4F2B22CF9D89A2F2CF88A886AAE841F28FCD2D26F46A5DEDAFDB46BE024F417451AF139193AF2797ABF25F75A782B67BF96F2F2D62F26F682A22F21B860 +:80B1800042FC44742FA7DBA2F852DA6FE6FEB2712B6A8F9AFE29D9AE813B861B422CE42DFDD2E22B798F31FF82E21AF7F1F9CEF22B628D2B2BBBEF85F3ED389F9EFFE3E13BBD1F3FFA93A62BFFDABFC2F5C81A2B62CFC5A6662E222BF6EAFDA684BAADD8C6094E42FF517419F939391F1DF5597ABF249462AF87F569293F3DF992926BF52D +:80B200002DD22BD74F5EFF32BA2FAAFA5AF8EFF2FED3912B648F9EFE285A2F2CFC71C235F2E24A8FADFDFAFA2F1DEF25FFC2221BFF1BFF1F2EFE22619FB2B2B3FB78389F8F7FC9FBB3B33F27FB73A22BBF7E722BBD2B918F8DE927F75AFA2BEE4E922BEEEAFE3614BAA9D8CF7C05002A014028C248221A64228608009E4824842813A8244E +:80B280001142A02411288082A824188028044001148C848984A84800A04140088A0448004282FF360B481214E016D181921280311180A414124A38312C82F44A821220885221880048D08125E882044819828822024302223042282F12A14920084B4388A218B2422A8408AF92042CF511248D121F4132481F41324A1D24AB141D64AB9492 +:80B3000019B24A5985AB9443F24A9143F2429147822D914F82C4914FA2D418F8244A16F1244AD6F1214A96C54A9E24ACF4D1242E421F49F228821F49B26CF19124A3F48164AB161D24AB961B68AB9459B44A3924AF44B924B442F9244829FB244889F9244A1FEC0149D581D622F5112483F41124A7241D2446D241F648141D242BB45D289B +:80B38000AF2439248F5439342F1469822D856F82D418F926521CF824DA87114BC2D6F1224896D4B2E449D2B2F5C12C2AF4914CAF227C91B46C789114EA48366A15F42A941F49943859B64829F248944B42984D48B86F82D448D826F595330082000000000080020000009022800100000000008001000000842200000000002501ED982470 +:80B400000026A8218426488864411284002341028CA242871123229C18984A4A28126184A0212892841E8482221028216445428A6212122182181A0C3243A48482B28458AA61828FBF0112B200482B84121A42084AA214890442A28E1130248822480000A021161808682B28260A4416A221235824861128210D1C3248894891C8E01108A8 +:80B480004E1820224AA1487F4E04A02D843246E8882481751884B1242461A6802478B88146398266321888F28182B028C41884221F2946C8AC8908522D288A61443749421AA818245382B82839818988E318246484B8244A49A1C13F21022901224082128802108804122422004C2382888401204281012A01A0282C0143022C01801488C3 +:80B50000621612C048A04142C0148298902822B826F8FDD80000100800000018304800201404800100142200004028011902162404000081000000000000482F3A0220021C0212005220098B84A08122132922490268209221488044219481802204301400601248A04114292882091A049828C200436641F0AF150000191208000098C093 +:80B5800098200C1C09CA4114228621C22142142811421C082842001C034C219421488011118A22014200200890444C011FA30420020012004A010042608122200200000000480000108801410000004820088220011A8882048002422F180F2001001242001800800182000000200222000020220200400122180000008001302C00A0148E +:80B600002200BF590E00288122260318814A482824044181841A264284242204848004204502422220288202002CDA140436A22800008812000082A0824FF40F14004112810012001218000000521888001140840141008004000081830618004812008200421002201AF8382E0012102863824820A1C1202101448280034CA11488482818 +:80B6800081288001430580820400260189E283A4284C012602180088604142248025826A8AAD6C4001224430112112811088242401848148284820024001460400302242228088020040924120A186001220982800008200EFB9010000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000046 +:80B70000000000000000000000000000000000000000000000FFE40F8004000000400428000000002180018800004001400848000000004480020000001002183F5F0B0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F24 +:80B780000000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFDE +:80B80000E40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000069 +:80B8800000FFE40F00002200008800000000000000000088000041000000000000008200000000005EC28001003048000000B04821918840088800000024602240280128484C428208250400002200000082A0840020F83D22400125418202160240081E42101211418498241826080010480840241222040044124031488055141A0889C3 +:80B9000008C24160680021898288046FE70D19410280220400842011A21416918840188408000040082602221848224240A6811002004418228908C24410240829280220F816F400400121842C0100804442081144822812890200400821101418020043020045C148A04114820000002C088014282804BDDC4002212866410810882206A7 +:80B9800081200442844A618228000090288442489014822021024084114121382882462201482089128401444382089FE24401121E23812148D0820181982210889891B044011290411A8A4222041324C821493448661C1434844B811082321246F446121E4612284A880443044C25282C228401889F9E0F801132224248200126280A813C +:80BA000084821321044088220400409848C02143044648941449C8141046223141C8362288048014842921A841904418005B1240021C43CA218424848420250220840847854A8103119A8202292412A14842F01448490A808208A01211412D146D4818222BC14280042E444188223024882CF8B9C10022141A344821282006902826044078 +:80BA80007424B848A112481229068141142283442102342082B12174482402228B42622541981496048227128081028024912281127F5A095082802402840078490822008C010024226112428081A912002814124885212104281024410A4A420412108432122800B0820442DFE94C810100402881410187110029648400408102000020E5 +:80BB000004008C2112040000142304208108200260A4804CC4382281121A14F86DE4002342018952828C2321A2141181244289D44891281A64116823E24482114844A1412608228B122849A12414134184D221223264621825E8428488225912AC84A2B4418B122283A1E18CD128F4B7DF800120210400468192982800004484288001809A +:80BB80000480824501400220A142002044C8121588288101284024112202480042F0814600000014F022484210280400191341080022408184021210512800890141282002000048542161A0242445781262485084848242FF21412244022384018110020000008005002002110000408482050012144AE1110254542141400428144112D0 +:80BC00008800224B182A21F2D9A7A0122301188C022C12110842000014810014001C011021028001271141501410145441814508288303128011544248400444121A8804CF2402C021C0224262009028504842000022202201400184200200C02118180048301112001111214C0211122880A11422222221411F630D236822008C6412A0FB +:80BC800012A0120080014904196682121304844008111B241045C8444088420414448504471400260450144120514821414C4804441CF2341F00110010084262004E11802204892411012072111218E1818808000048411C812102142241C01125C411250340210100425820C222D0710A480012180000480028200228201188611421A031 +:80BD00001420042224468422016012180024382189044818001AC421441248802218147284F2FB17302100206281178620222404114211621942814201120084142814284414458802801101003998188120011431124684146224A04900430DEF4E0FA4C04215024200A1814064441C020000124810021848C810014812541944C4284426 +:80BD80004818440043E4540240A4144A021242492201230121218F18081E42335A222C24C4214682A14426084A0420467128C838264181E11152215081850178144144255844D054B111732444C44549D24E72422152C6283542F242142CD154D62422F1A6544C253C2E813CC8A21F3344722241012B1129B73884F24229AF82B248810475 +:80BE000026011453734131513813A1412A6411118F14F491282A14A1221761CD434D6158859C21B011015352B81B1985F44516321F2461413362115744724E44C52E24D944A5113E944B5843F6B84DA0242C0313723878417828E92204684698194E4419054A86E21244C83846018C4309484E2126011446E843A1271E511247422815A17F +:80BE8000111F430159D198F441214F51C41110E51194111AB142612163A4A34CBA84E24752423F5A4B0114002082E4220118481C011C0138190413011142001142115211121142001440011440C348344826023448800448248A041008F0FC51F023223D2B211F3114D818F219538D6AAF86F258785AB54134615E115A83D34CF528183A2E +:80BF0000F318181E11222A528A85D988E311A3922A52646F61D1CCF11454CFC7F7141447414FC4A2335F53A7132B9B4F43F32D272352252B322AE24151114F2152464D14AFA2BA12F924266D944D144F45E54EFED86CF023223FB656223F31F5685887129F33F53A5AAF87B368F65C5C9F81F1513446A1156AF56C548F92F2292987811F91 +:80BF8000317163F12828BF917148F8A8B81F17E312F331314F71F1471F6FD3F27474CFC7F71C1C57515D6D1B333AF71D1CFFDBFB3534CFE3B713F115462F63F323213B335D454F65F646144D16CFE2FF46D44F2FB292F936344F47F7D6D4AF914BF323221F32561317315AF449619F35F51272AF86F268688FC1F519591B6415A1151AF27E +:80C000005C4C8F96F731318F91E115B572F721318D188D498F92EE12E317F621211E173F71F14C5D8FC3F57C7C157924F431551B115F51F138183F5AF94946BF71F156366F267213F511133B7555F414466F21F45E1AEF8FBB92FD2466EF41983E4B554F64F529A5143F26F62B63357353E387F269219F37F76262AF86F238388F8454997B +:80C080005B441F1121A467CFD7F638399F93F319191F11F173719FB2D399F149491F97FE61717E611F1242F3475F6FC7F66C5CCFC7F7151D5F53F23D355F417155F51D1E7F7AFB4B4AFFF5F577767F76F713133F11B153F745545F77F54616AFA4F5FEFE4F4DFDC432EF49DB4CE226FAC4965FD30900001884228422846081200112400843 +:80C10000120028100880818201184249012290148001181200002041022001822021043F22078A9121008006B0420118484200481C22122881118142482182024012082800140040C12820D112215112101201481890822A941822421CF4519FC0421F41F228131F41326A1F41726AD241F24A111D24AB9419B64A19B54A3925AF143B245B +:80C180002F147924D812FB24481CF9254A1CF8244A16F1244A96E1A26459ACE449C24A1F49C2431F4952281F497248F19124A7241F48F24A131D2CAF249921AF2419B54AB924F44AB243BA42F92448A9F92448984FA2F4ACC450A24C762AF21144A3C624AF26D141B248D141D24AC92CABB449B24A19D1427B25F8428157822F145B861C19 +:80C20000FA275A4AF8259A5E8157A296F1254A871D45FB98252E4A86DCB4F491648D4396744CF1112C4F12E888F42E111D6CAF467911D41A9B45AF448BD44AD984F442142E48AD942F82C4142D582F83028400008400000000000000000018800800000000000000000044000000000000DB818022210118121019984148008C5414118469 +:80C28000188008138492412842109824108C92242B14511A7421C22424424121AC44812B28111125012118868212AC4960826E3DC041237822084551217460112B821331212F316418007A081A02848B8381846924D218014602582384118454424410D4680A1642F4882446D538A24A8502C7244B16668A2A12AC244187588AF44933A015 +:80C3000042569228C01416131461212A7414613272191445B13888218158286222567142249A11C042D084954149F14214C149F5412228644B424522C14459DA41CF88322614F1481443952A8A825A424FA2A48543A841DFB30834800114404358181328043486082004280017898184284881844C023022283041214441D028082484A1C4 +:80C3800060328A543841242246220126084181A6F842F60000122411240080014A8104450813081381028111541312984128844448874180A282440025014116080048904100303481B0482102487FD20B422912322283A541815A92581A28D4825422802D39888CA28129E8C1E41C82048E28482B42C0181A344A892AB4448848A4214932 +:80C400003288C2871140E241EC6B1401101A8D9C4C8243EE4894848E44448CFA682B0022A0218B1423012180A11400A08486088E29983969432E4140C12448C041382C258484644C2841384488111830186B1462314800416084E084088449042AF4EF6CC0422410021C14A861568848C24A4A31421249918800904888890487183CB2286F +:80C48000048181C48E288D1420884A2412B842184904888E1400D08344291C94B44392C45E842A18C48896064260218081C2244C224288925847222C24048A4144F11224102244A9281C83C5144393382A28C2781621A516563A11004110084004B028448C240180880152E02B0624263241226608A43489344411F02844842022648116CC +:80C5000008182912110418A221001412448712118887428AC241C088842D2184164604926128230262822384082223F1D3EA0012848140814428611212139282008A018042A842C014C8424085140356488808000041269422924A01308184C08100A8C3111238484A4138A83FFC0C24249991288346B14C523826D849021E29A51218A290 +:80C58000828A6181364A8886C245CB84CA82E236A11467138B211F83C818AAC11813853334294A3124A283A94240C481811259042288CD1282A99CC84AE18192A84F4202481A42021828244CA214482E11484A882424211444313418801101114441004222874422800C1C4144424C7211182811022C6888858684A342001820042F24082C +:80C600004821100A0000830148708A028014180490128185C1881189548481430811418440241854144450414410848181C254800149818801184308CF49020084242C460416022C0612100483012022250124481C4428E212B42264122B4820311429819411825021588B141A24813885908100490C882426028184F035F30040210222A9 +:80C680000010C88400104184882204205A18138A22E28214C18142450182904C1014014241418C04114211421880080041E0420481CFDE0D1428008C1278424B68246084814B24A8830810342452A0149824D02244012A54C2222F884421241802588281110048001081820C8A0524C0821084F8A15FA0282221222144A021A049A02188A1 +:80C70000C1863814820000B30222481782804388C745498148140448411100466141C121138441C844A64414C412C034418BC28C42F9FACC80042C0442800429042B8429DC220400837488A44800907212192181484251298481182480E4888104930881001112484C91821820014C45A82818007F9F072410184808814200844411584042 +:80C78000480412A0584286028C0114008800C9C4488A210188416015122158D228218A8462241A84242E88088008FF7E058004002210480811828410024428818608136816202208848890884908110015044248441008004A02C02480184404160812F03C4F40488226411148224403400C782800002004218418803852901290128714BF +:80C80000002F8801198588180810C454400528004448C08243821882F8765B002F2812D12262A22285E825521A2C581229B24938582902C9A8224C2B2144C8A1A7859D2115817448B64AF2A9AA257D847CD4F8444267414AEC14C1844F48543144571484446B585CE214B2C443B444B31645A45A8AD186C834A9DA14B188F85587A064626A +:80C88000856A824641344181B0287488AC8D69D6264818684888428E481AE111F818181968888B2585D811C2494511A4948D94818A9814D18288CF84F844481E14653414441B4519159816AAC884124D8467442CA3828664CAF0D9155021302283916ACD2A2CD482E524F452184ADC8845E2C8B589F8141C4A54CCCB424AC1C23B7E1F2E76 +:80C90000E412F26242A6F863212F83F5A1822F45F5E9C2A71148DCC15A23E149F8151115A1481F11D188B458B548F551818A31121DC15ACC44C24BDC522C684BE3E887958884AF180C1304111031221118158811815181188041C834000010682881B01882381800000000002184213022302212211221902292200192F0EBAE141553B3B9 +:80C98000A5F21233EF54D65F724AF232632731BF34B1DBFD7161171BC5F61939124B89CBCE8F47A591DED287837E71FECB2FBEFE4B4B1F17F773432FAEFD2A3BFF33DE4EF594CCCFF9F956D66F45F5551547414F58584CFF75715B7B4EF67664DFFEFFC3D23F32F38BCD4D166F687846F646444F64FDCACA6D966F4CF424344FC8D8A8F83A +:80CA0000A5CAE026F6434BB5F3123BEF54D457523B2FB3F242513F3CF9DFD48F23FEC2F47F71F59A1843B184A9EC8B9D1AA9DDBF82FA6169FEF89F1EFEE9EB1F97F75263AFBDF4E27FFF7EFFCE55CFC9FC989E2F85FD56545F49FD95144758CF44F45F57BF95D1C4F16476FFFEFFC39446F1C8CA6F64F44624CAB9C4FD4442EFA4F4A2A2BC +:80CA80006F265E46CFC8F818989F4C07242B629FB2B212F34D668F24F6494B2F22F34B4ABF29F88ADD6E388F8CF2DC94DD954F48F9CCC88B9B8B461AA9DDAF9FEF1FFF68788F82E6A2FC71212F26B5EAF4BA6EAF67F64251CFC1F1DCDE6FE9F9D2545F51F511915F48F8494E5F55B15AF548585E56AFC4EC44F9E1B19FBDBF46B194FD5446 +:80CB0000844F69B9E2FFD8DA6F62FBDEDC6F8CF59C188D18FFD20A1F36F629638FA2E2A1F36D4E1FB6F6484A6E7ABFA4F49B8AAF5DFC68F2FFBCFC8FCFEF49F88C98CF8CFCBCB88F4EA8D5DAFC28E98F9AFEA9F99FBEFE6AE38F96F76373BFBEF4FB673F7CED4CFD585C8FEDFDC6D62F4DF595941F49F981859FF4FC55543FA5D5CA81F590 +:80CB8000DDCF3F3DF9F3B19F8DFD54562F2FFD56844F2DF97674CFE5F53616CF8FFD565CCFC1F188988FF40E001410C4488004402308008480048A04824A028B2420048384A82400884200880048188C44220140A248A04900200800F048F5601A2042488146417842232854812449C481C084A2852421048901882281807222224818C820 +:80CC0000428218122018082522018A240429080021482D822242806A985F8D0C2CF4112485F2112487261F41324A1D24AB161D24AB9419B24A19B54A3924AF1439242F547B24D812F924488D914FAAD418F8264A87116FA2F498252ECA96C54A9E24ACF491242CF4912485F2912483F49124A3F4812CAB141D24AB9419B24A19B54A39248B +:80CC8000AB9443BA427B2498924F8A84F9A44A8FD201941E64AD414CF26A111E24A716442716CCF26E81282F34DA85B24838242F1458842F547A24F84A935782AD915F2A55185FA29D885D428D255FA26C584D4B9E214D4A1F89D2A4F49164CD431B29C7349E24C7341FC8F244121D288F7669418F347A11F848A6228D944B492F44A24338 +:80CD00002D846B4B25F4A458CF260B84000000000014000000000021800118000040010080040000004004280000000021F07C4F6022004303842881248C621494258201611748468861828318048C942C00138614082124831454218815480122856421876284821048698541428608C8888604F05C8B3044A6214241224324946D828CC0 +:80CD80008821CC8C18282438190219249289102134418186815441863844443C98A422412624430C3D444A7114315813874914A11430141A761A420446D984D4EC084E2413063641828142E882B482924D85239E161269D22498781393288AC4249C785298258A147141C8418314D181483448871819B8424A9821C024812D158B21E5F198 +:80CE0000448811835384941A2494884AF142824D824C18F814484FBA03242042048C1284541484881260880014005018001008422282401422144634265014442A411884344612181A8618A11441301428160820044F5F0326022712306811A3828661888042318181484604852462448032814200224A02824981824404110014E0244106 +:80CE8000D82A21818184A848348244602420348480F41D9430421483712A92158CD46184D168C2613C22492A3411242823288334384A22312886641449B712C4141CB46C8136884BA1581D241A7226F128824C933713A28243B22408254258428698482E12174243884484128CF89BF8A042111D38285F841179212C127C8281A22115924D +:80CF0000411941A224B02C21E4460190A144114582A24313A42D90284B841A44E1129125841431482998221E8410D282388484AB846C02869442412A4888D8190E254202252A229442298533683482818884484429082284683884C8485A22150485B42485A821412644028E221E244CC3318CD2489122184830428601124D214220144439 +:80CF80002474490A482044314251B0467332184811614323012937842E132A1132518D2210C4986D81812171D0A5E811964821818E42421F8162311E421C71A85418293E44441CC218E810182298821886280429F117C51092421E2183830248904143243828471A48128881002844231465144A918830648A0110C8841CC1214446180471 +:80D0000044A6A4412312A1212504482290822822168806887012F227439014288440084902001212814008008118224008284A62411884804124E1C2041218208202001022E2242158C246088A2124022391181E48812FAF082F4491228CC3192D28544C86B238D44864188B1287112321B162C18C3CC2182259A624156414CE287D688D34 +:80D0800016667497084718C3E441781A64124B412941C4124D328E3541AD221C784222A2122B856D88891482A3842B183A24213D1885F272B50040812204241E44250118118848818220C122121884814100800130182B1283A44280088F12912142B0681921E6410219148804869882228902A94828046F5A0A2D22811439C422C0220004 +:80D10000698881E3210824224B82374490185608828D2168484129C1C122282144C144444479082D28414413984246DC82081FA438848C12245862684604C450485FFC064021010046081212888128460400184220E21402002E881848418624894281041518A81200315048CC02484821422C0142C0888429048684F47FE220C422C9120C +:80D180003444517022041114001216288184088880511C4842124241487C146444C0141126242141048CE3421448043481904841301400800828F02BD4C02856049028280048406841902288411218122A61328412218814262222018CC4189E41111215B889E248240910AA24A0240011B0225828200222A0422432CC0D8A011825C8421B +:80D20000846081422944C2880018CC0248B24964188B4220112C14DC14B78431428A22848164181824114C41218845F221488388084821202975248282342844812AF896DE2490111447228016022188218004A542D1222492421C0214E880410270228841A4289C02402A84C462267C221108106244444110012470842838844841F08C8C +:80D28000810000148444478244008424848444D041130110089021001188148811000020814421C1142412121623A18592121602290824478112301285F4214F80C44281101649242361520044844489018283621C00830110B848413828A44287581028012230424424B031041260A18413418D0100294A8C6284F08EBD402212140842FC +:80D3000048812064182748981E24281100118418122B2446D88131212A0824131108D411C48C728184041C11D8214214C18485D14308C912928C41C84E1418228CB822A8C1FF3608246F991153414F86D683344638211DC5A7288A38CA18EB194931C22F41B87881F8282989A336228CD2387434B2C4F511A92F94E44218FA14AC4B44CFB8 +:80D38000486131CF424AE6219419AF58F21C212FC2BA62758CC4122F88E82C7944C4344F686129228AF9F22298CF8AD228A14B9FED043A9641CD27ED28218D218B22E5E42531D616911A4C7118C828A5ED51D6119162414A31321ECA5E61422AE21425E26EB184E214230F165111221E114F11B945F334284F82B122F41451281FA7BDC5CF +:80D40000FC58125D413F2961312B814AFD8664224DCC4E284CE4CCD244BB944632426E221E183C54684746EC648348281D8836E821DA4644B631F22412EAC4819F9FB711F84149D35889CF18F451888D2C2FF1924C1F61F98E485DEC8955C9125D2417AC33CA8425771162E49724D51D529A19548A8D48F78A85584624EFE49618C74A4240 +:80D480004B828784EFB50220024150246022502412A04124126C1241120141301410053901001901188001290125011C010014000000001A5418128112F0D9CA242F24F4131BDFB3F32226FF12D659B24AD44832125F525A3985F23AD88F81B11AB338F15255AAFBC2788E294F5BFF74443E384FC352448FE2F354594FE6B7A6D22AF24409 +:80D500002F2F46F424248FC4F49D941F62F275355F79F11564C763EF7BF96A68FFB7F61317FF61D1AAF11B5BBFF7F447D7EF81D966F146C26F67F9BE964F6BFB6C74CF43F764E44F44FC2DDE241E323F36F23B32211F12F623212B466D342B157F72FE83872729AF41FF1A182F81F132243F15F5E2A13F9FEF9BFABCFDEFD7F77C5D8F9245 +:80D580005319CFE2FA51574FE7F5D61EAFE1F1C5CFEFDEFE7C7CCFC4F4848D4F62F2B5675F79F115278763AF7AFA6E6EFFF3F73F3FFF7BF75AD6AF35F55BFBFFE5F91FBEEFE8F1C6D66F67BBF2BFACFF6C78EFC3F768E8EF86E62F4BF262421F33F4392B3F32F22B691F32F24F4D4F66F716547F76F38B9F2CF95AF88FA5B11AF138136FDD +:80D6000014E73EFBCB794FCEF3F9F93F9EFF75756E5997968FF2FA16595FF7F636B4EF71F88E8FAFD6F468648FC5F5919C1F62F232D51F38B117F32D2E7F7BFB4F4CFFF5F61237BF61FB8B1EBFB9F5DB6B7FB5FD1E9A6D1A6F2DF4E6E66FEFF9C4B6CF47F7EE6C4FCFFF6CBCCF22084E223F32F63F2395FF6D6BBFF6F26F4FEFE6F7565443 +:80D680006F76F78B9BAFA9F95ED2EFA4F11A1AFF33F353732F3FFBFBF95FDFFFF9F94FDFEF13F72849D7D2DFF2F273577FF7F5B79FBFF9F8DF5FEFCFF77C7CCFC5F595955F63F3B7B73F79F11737BFB3F3BFBF5FC7F71F3FFFD1F39DB7BF3DFD92139FBDFD5FDEDFE3D9EEF9D6D66F2EFEF4D27FEBFFFA78CF8CF6FCFACFCEF249A500505A +:80D700001484438224020014000040A448A048288242A024101831488092920080011C0824800124482486488144234102202804003F2C0B8A8502280042A01496049098D04821032289034E15225C0144481E244342C59228A0211021321100898112B81102288B94841812218242A2872422818A84C2482FF3024F22F41124C5F211243D +:80D78000C3F41124A3D641B24EF11124AB961B21AB9453B94A39A4AF543B242F547924D812F934481CF9A44A1CF8244A16F1245A96E1A26459ACE549C2DA1F49C2521F49D228F191248B841F49F24A111F48B24AD9C1B24A9921AB9453B84A3924AB9443B24AF92448A9F93448984FA2F46B65F0224A19965A1B21A7341E28E72617C1AFA7 +:80D8000026B111F26A8617818F64BA95764A32A1AF343B112F147B24D81AB936D41AF8A5528D115F22CC816F8261197FA27588F524138F58D224D9C1D2A4FD8164ED1213F94E9186D83ED941B246D9C1F24A951D242BB457882F447324F84A94322F64A8432D842B434CF8225ABFA30646084818000000000000400800100240040000404D +:80D8800001400800000000400428001008005012F0F4A4C041400C8C344C8CE2414281A8A133C158942B48582352822B48ADA42788264C044C8412B112C2218A94148D5425E244A22112C0144CC27C2C91288B244CC1128E4828601186D822384418206188784148EF7A4C52241B28135384195312165318624912228AD8425128814E81D6 +:80D900004C313114430748483449C4182C34544137222AC8181A3845A243C82814883782C84F18F14822471C20018924A1412AE8463846E384D148F838C185F4FB54244635634D29C9747142ED82D185034D224B1227127E825D1AC81AF423828761197C8BE2AE41344452518E44BCA1614D714C9C11AF44D3A2C1255922E3C478386412F5 +:80D98000CB25A9726238B5C14DD3C3282292188E124E92624F228D344616BA8875946941ADC2008001814834601682889281502884428033244426082034224002244C8208D852880044881381C8486E122024011914084C0844168838244AC2483F250249044100008C0212241E283440241102003014508142415484168465482C25A1C3 +:80DA000082174100004D81402311028503818285321430240089528442F099FC50124531232815B81994844887714EA88F190230118611E8C27598E588743B34944211A286954A122D158F241AA4126962424905572126126C412B164E184C94414B691A82A11423C4484C48B86C18C23E6496843A1C8CF89D6B7041044D2128818D114382 +:80DA8000886681CAC198320044833116824844414905143C441C545A560E9AB22284A2C111182881E018024429818BC11921814092182E882836584227412E888981F891152440071021048155322819124AD112C181C0681D1C89B82B810911833A84421981216A45444721433124495114254294146B4189954146D14224024A31428BEF +:80DB000084861C64446141608A414314F83D9D0010210248235182282E5C2814413125D414021D284100212A6432981912684540041C82216122901A1D1414816B282813C41166486425A0144423216924222422002F81F47DB250414B1410684325491835586038124B424969812C011098221AB28244044A0152252282D2412851842704 +:80DB800012181283042E84688490144845420C8449A214888118C219341489342429F187BF20820290411849020081892609A084560412204848112412263228A014296184284031C12052221216214842188129E22811082628164838234A08001F2C0F4D2149028076421B5C428B1466D4217221A84147314781CE221E4485512C2832FC +:80DC00008968424932E22D253AF41668214E246D11844FA1A2211C73418231247728721E898AC24616F149268E1826E228911C522F812A6324E22D421EC4424912F8413E0012148CD21421A1121528628189A8412C2808530122188088641411809888808221A852009092C0112885C22430118304A041814844B04868818122288480F4D4 +:80DC8000411D10044412812C1464929B211984B2894511083CB82484C4446022146A8881082154268418141204250444114338812C21C414221815683A41860427412CA818442AF188644B1C8A34842F22498206183041814A614542200441432802601880080028681024043A842181C1242C6441184C38424470818412010088B04408BE +:80DD00002843A2A4250210047F29063504C460114244403144184E18003044848C91148081A52114601442241854604528141609841684C3548811521116C4248844981110B4121834148C218281F86F1840288221022D3C818502248490182055122082021488241068431212412C0100482458880028002CE861243452181880C1120073 +:80DD80001288801142F8E76AA038388400902810A42928110044241B421411A0421302428841C119240220A2212244A01226816214432891244A2868541442244B1420012229B22421D228076F8B0B840017420000388100001828C04421496511008814800211281052141604190290112061442400216413113228868222121214624822 +:80DE00003018FFEC02002884222880032041721421810444002641048E4828220044002E4420041C068288802886228822024880024CA28400A0481002DBE320518410C81A14130200841008008422680012156218841348218851142511212491128E21511882281110616141122284590100201101819C02BFE506461881248106211589 +:80DE800094444C816442B0141236461881121442482D188021A2A4832224A4344B8414C8608480162481A421428813846A44822813881494448A8404482998661D7B4034814C8211D88BF52844CCD551C276284871442B2473E8967465D9147644A1121F12FC78181D118D291CD21654D576C5136E111A83A4533C8242F481A13F48D5117B +:80DF0000B581F231451394C146D2176418E13B193D1249ADA282641EC14F8AD484F8B8D1E3F93AA9B04262C287818FC1E283F464224D2195E28334588CF558211A7194781462362594482B131B1A4714421C882E36E54AA3C149B175DC26B446F474244D827FC1B55735151AB134F2D4844E564B244F287FD294947EA41B84174D49E84E28 +:80DF80004436C24F42BDF4F424325E847E24542ECCFF984AB235A5214931211F34032D184F13B244D11438781F8851D8184CC544C9A33846041B612B118E6223AA881664C26229C2241E241D84181F4422E412B8887B2484A8221A8869434F32F313648CE1228749F41C81324D162B21295B42A9A3584E2AB03A47014901452148810412B1 +:80E000002A082A0888801AC184114C2A8112215481D081C12419219811C2188222601240012E81400126018044012840020081A0246F564AB266F62521CFC2E212F268782B777F47F76D649FD4F4587C8F8DFDD91B33C9922BEC6B4CAF1DC5862F497984F5C1416A6594124E49CF8C559CC0954F41F994954F4EF634F44F61FD85664F419D +:80E08000FC85B44F4AF2A5F447445F4CFAE4667F6FFF92925F63A1111F38F89A9C1F68F98ABA67624F6DF9F4F62BBB6F54F48C84C5F48484474BBF5443B272F675758F43F228758F96F7787ABFC7F56D7D9FD5F5F8BC8FCDFFF97B2F4BC3822BFD4F7EF6FA594F74FCD3D1BE311F1EF4E2F18F1CF8A8918F1CFCE4C855F128AD2E811E9201 +:80E100007F7DED5EE645FD54D67FCFF715E45F4DBFB1FA85F41F44F2D5B54F6FF6F7F72F69F9B1B61B37CE42EF8AFA8585CFA8FB26364E124F6FFFB2B26F74F786B4EFC1FB14D46F4EFDBBF3F064645F53F734245F52B269F62172FFC6F37D3DDFD4F6D8FC8FC4F779F3BF91E3A8B142F864A2BF1771CCDF57F824A43AB922F4F1D9CAF569 +:80E1800049814F94F844418F86F665514F587594F526E54F43E728F7D7795EC55F5BFFB4A45F53FA54845F46F271727BFD1F2AF571532F63F18383AF8DFF9196BF8DFD24444F6FE927BFB2FF5652AF83F18EBC4BE8EEF47F9A4BF371515F53F7382C9FD4F169F19FA6F56F3CDFD6F371757E748F8DFF69FBEF81F3941A2BD75F72FA3F1DEA +:80E20000CFFBF153D15F57FF35951F13F3F9B197181F94F84585DF95F5B5711F16F4A1573F7DB522FE3474FE767F5FF771E55F5BFFB1A51F5FF3F1755F57F371277F5BFBF5F75F7EFF71733F3DFDDBF95D85DF9FBD24F7E4B26F2FFDA2F26F66F6B2B4CD7C4F21F7E4EE2FAE0F2220022C0141481486088240482648848422089200004616 +:80E280000442984A3222420029082A081820022420021440820400924A2288027F5D0D222042E822210128188041C81192244881821848188A04A2A04280410490922898D0122501822049A24120D9220829012182A04342100289033F3C032CF4112485F21124C3F41124A7241F41F64A121D24AF149921AB9451AB9443F24A9143F242F1 +:80E300009147832D914F82C4914FA2C4814FA264116FA265592FA2655DACE549C25A1F49C2421F4952281F49724AF29124AB841F48B24AD141B24AD981B24A19F54A9443B24A39242B94478229F92448984FA2F44B1750A61D64CD431E24141E68211FC116B881D458B181F4483453B8483195A714578A4E15178925D487D418F927128D7A +:80E38000915BC28D811945F125DA144D9B1CD2A47D11DCA4FD9144CD111B29C57391F44E811D24ED9115D45AF9812CA97395784A6581AF4438A44E1426D84AF926484CF986183D9D4028080000000000280000008A04000000000014000041000000004480024800000014F0DF2B243845331884554A48115C68822CE48144E2884102870B +:80E40000428A6182508280C381478281481AE28116E284D14241644243B242D82408A62681B8227C31C4A7D38395824012FC12C4281AAC164C384441C024ADEA90458A8252216046499322224D1196886889901C42112D2496B541E849A21C4820D843E4C25142714394212CBA483312001C6292188A74127C1411222128E2121571928D78 +:80E4800041225168452824FA2811B6C548BF8A0743239C229552942FC2C4374C42988743B15A688212161852694CF38518C6F21C8242621B81874A86BC243524578227441D4217414D6850288AF444212D284F29A248A748CE142D149E278DB52CE2137821D45271164224B34CB12EA5842E828D151EA116F47571D012D4419218000084E7 +:80E500004322B148082C6988444828822811289218003914D82221058B212E82126B124C028214802171229121004A81048618A849218210644422442E487FE80B2D4100128B141014612216A41280015C082C2882311481A214400110227422082EC2282AA8218812490110B144C14C221E48102184F44281D04231243024100448DDB734 +:80E5800080921663D34A1211C42949118A42312B3CF818811AD41AD9C183DDC23E82B6816182E24628E4D2C142CCFB148121004E1449941614114F28F228148D241119F3188543A221423016418CC54882C38664424AD384CA24FF2A042D6116C414496395302819C1282D244098118C4897191FC3B8123C424C91312A6882288C04164F93 +:80E600007288F2249121C68232A443A11890156C981422A016899B7C38002488124E1C2A188C84826282F034A140422252824054414121121F223121882D114A2908228F6A21388812148A448184823474812002524A123611806282853555855541001324B416C445831412843624414B4149B82474780E224B439125284204288429B1FB +:80E680001212322441183018412788A7422829136C88455828D2848845885114C48219826184108412225858148764442889E484820580AA4241C9D5424224F5F43C002CA4211E23702A9148D4292212312943421192212728462901912112809944812121124126AB1A1094232F8471322122E455C2222094821504211C0A2A28E2E4C17A +:80E7000088838292C2221E228F340141211084819412601190884200514C0C40048634482214481444422024022489222114C4828184A485E4212228220816134452244800008981044F41054127221E221CC32297621E489D249C22929931506149F14422AC188C392ACCE8846241844D881D4218AC243848444D224D128B2836F6116236 +:80E78000F01322C183F45C234D821636812A2848C21A8F14C8522686B43CA4A42638285E284CC242FF3F0322165418C4298104D0222131228C064031811819544A411C2291281328D4847848140249A121848B281001168488622230281D2846C24C2581621441208822181AE444318442221FCD0900213011258292211800244021742215 +:80E800009A2426A584A02143122424B82C142424618283414164884290824921E44A143814450848400881A0212800304800F038FBC0221817410060811200A8221890820030142644143818158844820800202589820212818504186200121244142003610010C444221AF49AC71041613149634119130133C42881002061417424100895 +:80E8800021282C629282418C5292A048A4800220D22401504889A24211118111415124442AC824846B422913086CF2979200228C14018128004581419184414183A89281203187822DC6001112888882008415426184001CD14862288814C04646646189A4212180842104C5823324F0378630A23440424882456224824A6921A4004503DA +:80E90000864206890420531210D2843322901125C284290421822188A1274444118B42604A1304C98491246928C48430428504845F5E0960832E4214004068425652418694818D122A088111888221178112884AC1C80040024B82128800122A983C8812814C8111445848002298004220218401D77DC01842404801812810815249124C7E +:80E980000A8008144180748A110110188191410048181A66124021E41441621110847152012714281420C4242812004249F65515901225240241895121811A8208885018812870880480982424C18A0298704198182849148801228D21003022482A051C022847A83C21082CC112CB21628023049FAF0A008CE4A18652414014943481C489 +:80EA000014A843919113012219B818C49123A2848951141B86132C62188A84C86100460B9B42204111012506144604683C0420046781221062212F7B081F23B2B25317C1241C711A61526B4223912483B21251436D144597AE4D822D21A1814F81D134FAF4638F9C52E14E244F343212841E928B28CED28B582CD221622BD5F18A5A5F28F7 +:80EA800095223F929211C5F4544455588119CC1A194B2488A2527E1289A6446A84F7AA9C3421918FA383B63161A11F8621E141F345B1BF8578817181F18C9A8B488E381D112F88E241C4267F41FEA824CC958313F284616B11AE889F94D118AB687C1DBE21621490A136EC51F23884CF842134143F245331ABA18F34513E9F5424F61692A6 +:80EB00002F2237544F44D8466241AF81913443F6924E806174F0331BE57529C4228D2A1374A8A41AAC998C143E829B83B654594B885B98CE183DC1835B8829BC4848B919A4A21F28744831441E2C1AB832E416D482A13843E484F21186CF49E5D606384E5568463C1427312AF244842E54AD2A8CF466184F4202167E3B0D400140582440E0 +:80EB8000420840628174164846481241264114111842941390121001214288501200601280A84100200148200112810012F01971343F31F1161CCF23F335211B33FF12F241417D159F94F448CABF9DFE91B33F13F11C923FD1B3264AD44CF28CAD9FBBF3FB3D8F84D858F16CEEBB889FB2712AFD65673B766E2A2F96EEE6B6E226F6B1B134 +:80EC00001F3AFAE3B9DFDAFAB56D1F14F49DA49F9CFCCDD7AFAEBE43F493913E322FCFDDFFF5C3E14F4CEC2BF826364F4AFA24262D564D344D24CFE3F2E4AB342F21F11556CF22F33D3B1F13F323319F14D54EF1486ABFBCFFEFFDBE333F13AB111F11FB22212EA26F48D2DDFAB93D9F97776AFC79D1CFEFBDA2FCE1C727125F77F76BF9FA +:80EC80008FA6FAE36B2FD2F65CDC8FAFF8B29B2F1AFAA1E9DFEAFA1FFF3F1CFC7D6E9FC7F4C9C7AFEAFE27753F1AEB32F2CEE8FFE4F5D3E14B446F28F826264F4EFA7C662F63D34682F23C6EA7A61417316F42F52C3E7F53F33B1DF772BF84D6F7F113111F3CFCF367BF33F39BB99F39F99B19AF2AFA8A38CF72F2A6A51EB3EF95FBDA89E9 +:80ED00004F1CF5C4D6BF3CFC2BABFFB3F32F6F3F3FF5D22BAF95FEE8EF2F86E6A7F5333B3D233BE8DFEAFABE2EAF44F759619F84F54C5EEFA3F34743BFFCF86B2BAFACFE4F1F7F58F9C4D42F2BFD26168F8FFD2C1E2E546D744F43F32C1E1F71457331F32516DFE2F33517DFD3712FFF6B797D1FBFB5F7FBFFBFFFFF3B33BFB8F89F1BBF22 +:80ED8000DAF8AF2BBFF8FAAFAF3F72F216B3AF1C7ED5F1F9D1CFECFDABC3EFB6FE3B3BFFF3F7F3F33FBDFADB6BAFEAFADEDEAFAFF833333D63BF2AFA2F2AFFF5FBEBFDDFFFFEDBDD9FF1F57A7E7F77F7F3BBBFB3F3DADAFFF4F1B7954BDD6F2BFD76724F8FF96C5E6F42F5167C4F41F36C7ADFC20C146012C011E0124108484008402541B8 +:80EE0000041041245148009028114A8218A81281001490145014200222204248A14174822C8204484A0200DFE104822849416822282412E0489212D02221C812C083431268822D112A844AC2A14D42811887112B42C22722A012C22501A3624125012991613011902142512148002143C1244F82041C74D7092CF41124A5F3112487241FFB +:80EE800041724AD241B24AD141F24A921B21AF243915AF74B924F44A9743F342934F83D452F924488D954FA2C4816FA264516FA265192FA265594D4A9E242D4A1F49C2421F49522A1F4932481F49324E1F48B24AD141B24AB911B24A19B54A3924AF4439242B94478229F92448984FA2F44AB7D022E441D63AF41124E3F4112CA11D642F21 +:80EF000014D141F22A951B618F547214D81AD884F44A91578327144F83541A7B428D916F82D118B9A5044F8261181FA265594D4B1E25A41FC8C2DA1E6485F3112460C165F3112C4F24F1812CAD961F48B2427A85B84A3134AF4429FB4A96478229F9364829E922F5AF184008000000008002280000000000008800004001008848000000AC +:80EF80000044800200000000F0B731244843416433441CD1220289C118BCC1A113F8884124844728628717B0489148C04A8C1234162269548226343242860221248621C828D081C48489B834B4121602484B842D84812186D88218E8C1022CE46F0F411348113C21637614E182016DA200842D148634D41864449F42B824C8258DC48286CF +:80F0000034498C9411801102882D1444D6852852268E1274499B38277240897248518421428E2443C224442B48484561429FA50B4456157414C8215C16B512C218C93217A82E89DBC14358C243986267924C78C47A2CA1485A78827884F244182E122485722412416248A5B645E824C822862259629F48E46338A543E62402268CE424C8D9 +:80F08000844C1274A49A8C2C3C187054E24C07290414195226122B1284249285124102A04918414A712188835448844CD28104114684012A218C0118C081448312A112848522D11A816214455842488D822200A14B424422DF3209002501105112A014281CB1114201180000409441442200D021344848A04282E041120298130100442023 +:80F1000081282124E1247814080012890220A23214611D2441818D122E188B1C1117A2C44221A44D424E84412E81C9E4A158488F1894248B49A0A487444D58C09285E226418261244AA8282483B28A028D11337699022FC294428C2411086084AD512C6A4CF014488148CF214502401418B822A148118522622413532146C2D44100981057 +:80F18000982412A0482005248C1462241A88748422082A38133019421E89D02A81C8581860244C4188C4A249014E148428AFE34E41C42525011215381BC071C11301814400197A444858C2C69541C32C82924C85D421B45808762202B0122602A9C1A8409221412143260442898148C8428D11203C288480F434361419C34A1312120C4017 +:80F200001112011245C218234282668820117442A124722C024881CC4202469238D41C04422B212B2124124890422C78884482028416C444244B388668CD2931144CF8CCE35042688351142C622287216217A3228E415042142A412448413C4831A5443114C48126E84601478185B412022D1116B483668413084D184A62286282381448E0 +:80F280008E24402424A1180021403812BD5600108403912200432151181886048641040016081009411480810644488002105824403126830142188C4A4888712202222005A800AF634972246122CF2132356C6232183B241E2827429E4116185249184532C419486C24165C85229B4243024698248D148B4345EA21F648124CD11436433A +:80F3000060224CD268E131C2448B342B48CE228CA8C2254868C15AE244C1128AB2487116A828164C76820F1840018184830225311110C112922113884208164881641441816D881CC258284502412884122A08AD911221482E8200121C418808244121A24C21A8841220F8B1660000280000400884405218164668A12A0400488C110410EB +:80F380001862822064448C74220800448722268232421E228C018D428B1C428100622062214816085F5A0512449413011E242972128432818072143888429142A216484962128486216A1924112214851244180141182442402804422813845341A11B1422400A12288420F29FFB208102100800130123012100000054A11440814289719E +:80F40000828141C1148582011824410040482A24724212011574110223440A00220048AFF10A2113818104209121A5C424840014122001222091482D88AA14C242A012C0C284004C81C481A0412A81C8141661422548948C00484C48A21481124004005FEC054440094781C04E158266428002608481424508844840028447288904488497 +:80F4800040F824482608224440240248260A2E122830588448200212100824F0D15A0080145822A4225028840024491241542840088014014821109421484E22002D41108212A2242428008884B0484142110888528828A0121870F44301460214100100A0128CA812816982092CC11120285842604842888314982445111402224724B0F8 +:80F50000240441F084281810240440028118208281012D2870780586348118C9C114124C0100280010A442800422484144E3344A608488424421003044004440081028018426010022AC8681424208148CF2ECB640684148205848405414245041841C220180025081833892221941180184184AA294142A18C218C0D98114241812851183 +:80F58000214304282C41584226425481C0182D2470DD42021F3E911846F48814224A333127444B2A22818343BA28F11144E083F41A28F44ADC122AF4C821418D9114DF18E216447B685884E544E9448281B11CE8867488742A72D89242142D281B1E8CF619128FB4749222B22AB238A7321A7122A81185A5264F23091E1486549189618151 +:80F600003D168743744F92529A382E821867182FC1F42C128CD4226312132211F58C9D57A22F72FE814AAB448C982899D27294584E628F6348E24856262865C42945F823544F86D3223764A57D19C24519C1592F84C21A27A427412E214953821649D8450441432171311B741C58266193417612D881421C7945C18883358C588185F9C834 +:80F680004824297DC83844ACB112D482F1E45449F342868CB141F6225855C2245C816322388C721872B8F81916686A71C418324C85E2450C88848331682E3224AFAB4D0234402148021C014D9280087C081C083C0888114411443110211121192119329821131C3281308124174824443412140041244110441104418187291416D6A2118F +:80F70000721D57539731EF85A6216F85C4A62BB91F19EB49F91496AF4DFDE5E49F8CFC44D63F9BA9AA1B445F88FC5CDCCFACFCC7C4C7641B154FD6A6BAAE925F4BEDA9F472FC5ED27F5DEC26F762A51CF889C1D7627F7AF8CFC51B669E91CD258F81D498E684F415145F55F73414EBDD2D442F48F82C3EA72226F4181C45FE8CDC3467410E +:80F780001E4816721F55DD1711CFE7E633F2524889FA9C949F13F3183C8F81B9D8FD756C9F85F464F41F9BB9A89A48AF88FCD8D88F8FADCECFECF41A58EFCBE582F1283EABDD2FD9E4C6FE48C19F9DFE81953EE54F53FA8DC59F2A781AF23A48DFCFFF7859EF46D6CAF218388FC6F711129F11F33416EF8DFD72742F4AF82C3EEFE271229A +:80F80000E443F314364FA9457316D45555884D167D15DD17EFC6F62437AF86E42BD1C2F81119284F69F14AC4CF52D74CF5E5772F81E993F3D9D9FF9CFC9CDDCFBEFFCFE5CF747C4BF17C7D9F92E237F2B76D4DDB6FC6E6ACF4564C5F3EFF36741F49F13934CFFBFB3636AF85F76168EFDDFF4979BFC7D591F651789F11F5111169F2DAF4A9 +:80F88000AB746BB98FA2F12E1CAF82518C2E1A8FB6457114F41D17BFA1F11E1CDFF1F91F1FEFC7F62437EFA6F6BA36AFC2FAB9B9C5FA9F16EF44FCBCFDCF61F5EF6F2F81F839399F9DFDCDCDDF59F5ED7FFFFCFE4FCFBF91F52D6D1F96F2F9AFFFDBC6DE2FE2F6FB7A3FBFFE42162F63B2B3F2FDB48FB3F3182AFFDFFEE9F8CFD4F75B79A7 +:80F90000BF97F71939DF94F74D45DF73F12E22AFEFFF6A786B9BDFE2F32A38AF82F13C38CFE2939A9014C011844D118443022284228400148C048C94280082819028009028418121831404223024844028628122482216081A44A341281E482890288002FF940F000024122411254204128502002C0118601415081588D82254182944B1D8 +:80F980002124144214026190128426222104255281508185821428011002188001DF9A082E421F417228F3112487361F41324A1F41F24E131F49F24A931B28AF243985AF3439A4AF3439A42F34F9A4482D954F82C4B14FA2C4816FA264114FA265192FA26D59ACFD98242DDA1F49D222FD9124AD821F49F24E821F49F24E821F48F24E9278 +:80FA00001F48F24A921B28AB9453F84A9243B24A39242B9447822B944F82A4944FA2F47ABAF0224B1E44EF2224316A1741A7141E6C811F41764A95218F54B314F24A14128F5433242D114F8384F336484EB46FA2C5942EC8442E58442E58442E5B8D242E5315ECA2F1116489F111248B141B218B1419B248A129CD828E24ABB45B28AF44FB +:80FA800031A48F4431A4AF447924E844F926488F44F9265ABFBD0F86280800000000000000002400001880080000140000580000000044800200000040015FB90D21411678215422CD111E21284482850140594A60421221814211414880042598421F64A3242904A82888F084128169D8A492A42C8232224A4238124844A88A028E2C8901 +:80FB0000D4C2058B4889F257D1144571A2F181248CC121227014D881622222279114983CD8840220A241C05C814181A34284431418C4382AB41614941126342843D229012CF114881E8140A1258115068CD12A55581880624616016F550B4433FE15A81829625328102DD28612236289F398224902214846721418944484AE18248992447A +:80FB80002E496F229429622E94C3621843B698D226629822AA31A6130813C22A8F424155422AE88D42F414A883F4245A6664941E289F5A042541041D2C34841CE1C122224861811411508420816281904181002944C412901480052904181044D824411C66812F228122A44180041658221508100298245FCB0E2081012211424822110082 +:80FC00004A8824042304428001284870264204008004248241000044818A5222008298480088220088268818F494E9144815062D2142A762502B91266628848411303412495412418631448241628418431322544222850426A741889031181862C041F08A428129C48687481A9248246265024810F8B8EC20440129229222608425216269 +:80FC8000288442004CA114481441924904442C342416440424442281C027180013216141680025E228C488884C4C040028104208449FA6078156861121544927241126181512C488662124121234421011A282481A62A8E0210248804444628843A448200240A8283304844123072D88384E88222D424488232648FAB1CF107512C126845A +:80FD00002824424513C4220081233144904821278C80480400001028C2828189020021453228804AD82A2128480A30128483B858322A2D2841A3C1444428EFD10230241130141605122218502240021022248291118C048002818301C02442006905280028004484C502808484842108008280C7442F720900701402284303209491819850 +:80FD80000012001841812842812400282E860020194802160224122112200500128141008240888401F06B1350411826C11436F4152243D114C12426A281A4832191442C1128B4921424C16842842240B818D2840A263248AE18815820018982A1281867818E4884108235588564882A94A821A416C81436B424F443E440D2415224842144 +:80FE00002006211A44032C082160249028128D8141001002002362480024442582522670220281901286140A242024D128098912A4844842F0F25D000000001120098221504250280000004128004528342410228128114214044384020000008240C882C01249941800242F81091141211694111F21024034428250288331188821C028E0 +:80FE800042842280044144188E247042284A6223100410823182232238422C480283088091188129080048F0791F00008021010023040029911200212014382220240244414141800A2D12400424002221822188212184880092841280110224FBCC50988F44B442345414260311448A7184D444B82EE28262C28642088902242512E2410D +:80FF0000A1114B898A38982A8CD22A1481817A185A88CB444E44424E16822220044554444B2A2A226281A49082274485522223A411EFD20B000021104202800481814210020082001004100422000000800100212C0A800424248100000000F022B910D882A414480000244014C62422280020012012D24221A1928A8208001C14416188CD +:80FF8000818C24A44182441800506241CC228202212001002129F1197B4008482941428421021042042800004842242421800188104488021400848084088200004004890280442824842812025FC44702581001000040042C0225282404001002188008244002140084A04100000000448002200400002180D18D040010014042020010B8 +:020000040001F9 +:800000000800218100000080020028180000000000002C08404208460821000000418B662485B848A41442001012014556446B222222180080440245A2111AE349282808001111118558888B44424AC1A20000504445B424322822428488002450241A9148405288A04420014002004544A82242408404002121411A018A080040511200DE +:800080008528A84420C118218840125844422B22000000212121C7C3001245224102840010020048109888000010046082492204000080014188801822080000001810084800001F930B12003022901200008180548280040000000000442002000012180000100200000010040000F064BC40224154132532122F2121120100217048A84C +:8001000044428CA8454800104404004C2402420020018A81887882022938822424A124850858295484480000F0E6F6248001122845025022259242A1854208904281200428004122261814022B2300800812208822216128888004A13042420012208802411F31022311E221C11200812502400284872429C4128141008210442492242873 +:80018000261494280024008061411A219884A92142020084465288248189084A041004E764F026222F21E222B11221B112012C512329F812131F31B189E989F848888F18F44848421F941481548985F844488F44F424444B244F4222E24202284556442E246F22F212222AA1191AB89229E828592229F812131F31B188E999F848888B48EF +:800200008F8424E48404488558884F84F43632F0262265A2123A211102142512D232F1111119F8918887818F18A44C42141501848588F44844C5B444A226220050424584F2262265E222A1131AB88228082512D232B11191819E8887818B48CA240400848588F4851800000000000000000000000000000000000000000000000000000097 +:80028000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000000000000000A0 +:800300000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000000000001F +:8003800000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000000000009F +:80040000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000001E +:800480000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000009E +:8005000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000001D +:80058000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000009D +:800600000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000001C +:8006800000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000009C +:80070000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000001B +:800780000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000009B +:8008000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000001A +:80088000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE009A +:800900000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04F17 +:80098000FE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000D8 +:800A0000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000000000000000000000000000018 +:800A80000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000098 +:800B000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000000000000000017 +:800B8000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000000000000000097 +:800C00000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000016 +:800C800000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000096 +:800D0000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000015 +:800D80000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000095 +:800E000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000014 +:800E8000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000094 +:800F00000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000013 +:800F800000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000093 +:80100000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000012 +:801080000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0092 +:8011000000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE420 +:801180000F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000000000000000000000000074 +:80120000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000000000000000000000000010 +:801280000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE142044C9481CD484042A1434142302440000F018261287248282842748822981D14811862132488364446084188041088C143414221222822C424442C4249A02128331161F980B2D419D1240110C4786AD162CB6C1721421E2123830 +:80130000845F246A4269D26A032EC22A297118C294482B436C62288283E982FC14C8882E8283A24210D828C4CE46346C1E262CA686442241C4412E4A49C2321225223B8A8AE484F832391032480044850444214B841820084621624284818246280888445200472141186E18822E8249829648004304498211329200418222438242042853 +:801380006089888CF464C814201162848190482B124C321335041482A82100322944225128CC21A48226241812A824490846C84800128D428A1102E0442246840181608400328E122821469A844F71024214001C044C02422822100441408213A2211200100220C18882841008000040684410044400004002231112820112F09AD3400196 +:80140000911120048C04002822411014421404290A8A01882582110218822004001008106884660880222242542440244204820012AFA20F000000000000000000000000000000200800000000000000000000000000B739D0214412282301A12D21169128A3C4A84224644D482B42416230824A82E19842024941E3818A21F51842001A8D +:801480004AA48183684919F48822422AC81418428A81114882283134822C8838442A1564E92410245362818B211744242810011440C82130328A6141260C9044814C04844562C42A388224C448A200265868449382254C988124882CE844312C21299C1662842841A47E6870430227221A321A38412D21292222A48200A5D4823422226A6C +:8015000049B2888286F1812885222451388F49D2846525830184CA12A418828BA1C3F48A249B245AE24431184E818229318823B52698124391822AD482A8424C43F227C8004489410484A714C01184A5416814005362244301434104904410440410A2282C0C61122A0881441410228808208108448424AAC41482102454849F9E022302C0 +:8015800060412144204102A0412C082111008148141518588544001008122210022200122C28081AB24C0822122724304284103442800181229DC1144532112F525112172119E2118256413C511825C9119486E149E288222BD268A1144CC6E490288561851CC4246F86C828161CB854B841C8112E94544C621366CB46C0228981A44817CB +:80160000818C81487418B2884118DA84922C4281AF1902211CD1124201221152443951288384412188031038141324624851843048195428A63418CC426A4990212210A428254984E1821808822724A488448143582881406484F094A4146C026C6141273145218312012531113C481863588B822A89628423D11CB44812C8249112302469 +:801680008984220148C681319454321CE128C6422846941262589C812144C81287214270343828C0285FA70C1C02902250481116C23842801284C51411A8424D42841421441C1604218D248613880283F3281122452125012883814161814014087144436144444187424008219F18434164411342140E2922622434114243185182901A52 +:80170000BC611147229821608182D42C81A521222503494841263A4245592343E142388224502480C61C228721850288812444284C3612DFCC0529C1224361918011545214811213115882100622288044581820024022048339681042A114282B822210D248528413A229190321822082723882088C01A0488FF50A7961431F4192362171 +:80178000C391226D218D613518E112417851921465B228D138371449B28244486C924C4A692136F48352223D982E48322943B32515328E39A2124F88938E154EE94268138B428CD1146881AD122A7488D6846842AD14898264241F7B0722105281C150141229819412482C48181881084E23841C011448184D82888C84428812728844C8D3 +:8018000024881AE2120165022A012A2111022502444342240384004C22F8CA6A80A421246CC12424221816682122248240084A08422241118B34004302A249014D68C941280112232121B188D32231185048883618E8814434142488A400AB2189D22818F8CE511014069112830181282882830181414311125C1480888DE8A20C14A81407 +:801880002088612882821A021C048C088B48803182280014A160838031441248004B242F4B02494203281C13012002609244551814488122183C29008013217248220A800500122817214548E24412544810644E81008C440400280081245F5B0100142446C4248092421608884601398802422110E2C2488101A487144511612711A21EF2 +:801900002D8400828382220C222902186012211682988A836142824C8168441E44F09F744001C038428C2524014444488004004D814068241E281012E888122108845284442244004149221188C134841784002DA48608490680A12CD0420885F169178004811124174281C344223868448602A430428126624841142F8881229842002056 +:801980001819C3B1124E11C81284302AD0820800400149422411848312B2182C1112D28B05244412003022108816D24102182113CAA11246C54292491484080070416814100489882812044842884882C886E4817C52E42124345280B188C4C445129448A0243F48021932112501850120262508428304821481682A280440112A84810410 +:801A000022200860164280021A0838448D41188C02294C082C08AB484129C288A01A4186F4E96C1484281A14024818008C244814E158124188C2818130485042903BC08846E8883111216214206282B0241403112220220536041E21814843820C00B092047FA70C46E14252282F916112763B284E785E184E4CA968B414C61CB528C86154 +:801A80005D1C1D2468C5A44B8D218FA463921D492D488D2C1A45F142384F8313F838A81741484C49F8242C5AF56CD244BF83026AE1A1F3D2118189F95E4876F494184F8929F212946B654A7488BB46B426064B627133D125D24DD6478261638932224B2C1BC3DB843553422D25A3E6129E88A3F42312496B452AF84222832266143F4AAAA8 +:801B0000E8CD43974C2D38584A87E311F429122F21F9A88833F16E184F28B544F1194C8F4CD888366675CA962D1AAB848F44B2C26DA8ACE8CAA314874A1BED1415E631C11183B25291582B24812AF498B22289A248C9F1888917A11B88872C4F1ED4E4E88C7C49FD859A2398888E349D211BC885F9511A1389FCB48486212ABB22F21424AB +:801B800093CC228E289A42F4A8884BA82A7421E2B16D4582C9CE242E424D244B268B18CB814F41CC2ADE9A006D118425415834840024841C41C817822C41C814C016001130828041140131202204C011100222488812224001444082442241048110681C24694408A14B649D273D41CD5418CF61B282B198AACDCF2CF49294172133F1489D +:801C0000A19EB54FEBFB26642E38C2DE8A3F14E482E593F13CBD5FCA7A91F383818D64FAAEA85F5DAEC95F5CFAA9A33F5B26FD81A18F8AFE21358AF84125CB241F14F9818955D188F5A4A42BBA4D122D82AFA2B26AA6B28F82F32C2CBF5543D222F4465A259242421D611D414F46D788F1ECF44F49AF21FAAE5D8F89FB99881B8DDEB5DE99 +:801C8000F14FCFFB2C6CBF8AFF51197E381F96E68AFD3159DFD7FFB5BD9F9DFC81518F9AF774EC8D38DFD5A6A84FC8FEACA85F537258F83161EF6BFE2B23AF8CFCD1B5CFC5F361B11F9FFF9D9FAFCCFDACAEABBB4F64F842C2AFABBB72BFEEF2A8B8CFC3D3D1091E161D4185BA2AF268688F22D39BD44CF458684F6DF28A1C9F1AFB88A8BE +:801D00009F2DBD8AD828F1CB888BBDCF98FEA4EEEFCBFF6229FE518FACF7CBC11F82EC14F4292D1FDFFFA1833F8FF93865BEB88F88FAD5EDBAFE34748F63719BF5C828BF9DFB82B23F7AFF1E38DFD4FAF8B44E899F99FB4545CFC9BDFEF9A2B26F2CF51692AFA4FF62F82B728D18CF42F7BF4C141E12BD76AD1ABF87726CFA2A3EBD69CF68 +:801D8000C6F7787A6F66FB3AFC9F8AFBC8EAFFBCFCBA9E3F22F1EBE8DF8CFEF9FB6FECF81A5CDF86F6F9D98FACFFCBCB3F83FC29498FDCF6D1FC9FBEFCF35BEFCBF634BC8F8AFB557DAAFB2D359FF1F11B1FABBEBF1FFFAEBEFFFBBFDEF74DB58FEEEF96FAD9F9DFDCFCDEDEE726EFEBFBB6F66F67FDCEECFAFFF468CF89F96C7C5B9A9003 +:801E00001460122082E412A1412220A24880446488008524B8480289028B24A024118D243048412022840100C0484D1284411260881484448AC4268022F948249244826F6E068683E22211C112152404E0881402341308F042A1821CA248253495422442118180D22189A29281988280E23269C82E12808832288266A24818922542886365 +:801E80008864C024228344D1FF074D421F41D23EF11124E7341F41724AD341F24A121D24AF249921AF343985AF743924AF7439242F747925D852F925481CF9244A1CF8264A16F5274A96F5274A96F5224A9E242D4A1F49C2421F49D23AF19124E3F69124A3F48124AB161D24AB9419F24A9151AF643924AF2439242B944782AD944F82940F +:801F0000984FA2F47CDDD082C464581E2C421E2C23D4C1B248D141F242948CE244FB8428AB1443F2429147824E91178229F92748987FA2C5814F826D111F82641D57A296E592645D4D4A9E2C9C94618DD39E24C71696744AE149762AC144AF549921ADB519F64A9343F24A924B4329A84229F92648986F22B5680A8480040010010000283C +:801F8000000000000000000000004008480000008281000000000000F0ED71403412257328021901802152821A0290516E845E8249B2146A8218284E14828502411D2C50216C4344C8188222206A58935941548984B48426220850484D828249A486CF220841004FF34791221B282E1411484644849125511A421158C182100884601C93D2 +:802000001471410428460832478489E482C8444AE21224F4811481A4688394421D2481842B48BB34831186941881A800E08864984CF21525C0265E22119722485C1484912145129C112255B811E8446AAC4CB21C18C8434E281E41D641229A442062142FE27581CC448B21992834C183988C1B49745483048F42986699BE2811944C8919CD +:8020800068468A92282592C8E021F2281F1012F124120012004991212A81120842800128229811444181107825285184201288A42422162412312A8C24D4413248482C28410210948282424308418918F4329E2002201118C11210A44981802808C026C081A084114E2530488428E044C21880311841822C4894929092004C8448186281B8 +:8021000040A814498482144A882A0241AB2614D052E22241C67164193214267A2428E91148C857C6644490988163C424488668C4863442E1393219284F82084B86837942942488C992281726882E9289A8424B162A24662198359C1812882E449A120C4C4CF8A2EC1424442E1249D18155412301C9B24AA98119091D142B844024892824D2 +:80218000028D814688984884222E1936684A124F8886A1484968488B81601923E823688CCA92444278241E82CB144528A284C386210A4344F8FF1F8032214022023CC214C02481C088C841436422849542B44498416644744C022D2425C144100812CD8241264262428332620041B0183222811884141A844102A6182C2218F4A84C30143C +:8022000022118042C1A42A5142111314B18441CC6840223212285124D41240140594286021488F117264B14251826400121074440826D818C8142442AF420132224890824078BF0511415A72220427814039284225281244815384230A11A012ACA2141D5440282124082A41184403303883C1624C938389128962224C8804221608C1A7C4 +:80228000648426C4184C012B298F3204105286301441824440C43284002428304822101204A0242621723412042004211810049110C814285084111821614180094B81122283944C485F380D5311E6C17222E421120185544A43B4587222085416D28432228D42141011D4149544685413B114728788A212484D42F01661182D2483712AF4 +:8023000051422D918991298147828718872912244F8174129418AF645284762421C54CE6F868440028250141163C241B212211251181493848C0822238222D342618180126C8244800C01AE08201292411042A413824444306239241244160824C28810B89728408F0AA5D00434224020084488D24004354A2A021190440F1A8114211408B +:80238000140400412342143644121A1211F1211411E044684A282022C218482939448E684100182082F26B24E045C2111009834424846224488140C444858431482C363410E46812082121006648A2412A5421482082064A2201818218C6C21282511488A094622088231CF435F55024244511E4228484042684042420840827222041082E +:8024000081414228621C04282148498834224C4612149848204C1CC888422024C488444A0242824A2254484644F8C86C00000032812654820022818C02002228242002430281442E489460694001111A14480220128221C5141012044224182222004A01428F5303CA820200115604184148800649C411424981A4921C44014041444804D1 +:802480008342818101A5420280123812804A8822088A14A248E0846888424182618225F1A31F24182301D1466881224242805248A028222598194608248C8A12411804904A421122424C4224C24C49C228124C032F1842614484120043041A18A4121A28212212026FA10F00120024241648DA28422454282888424140324144C1E68AC415 +:80250000422C8202214443811202141D2810460200481288811E84181C110118008890882382F8BDA61042622100282844212521A2422142800428914CB4440184262404282218B042880A6218004094422B86998144642C48135C822F8178220840088B69848A4424FC27DA4048944822244416AA21008125048E268722176241189088FE +:80258000904123042981F4448A8024048114A164D4D042142A51414A32145048C0248032144313040032901243F255B2E0426558355298812E4C4F81F1184E6CD422E42442784A4CEC6CF8562A2AF4384883344C2F57F6286CC8C7444B448D4233964E42C7E26B817E54242E211E211D41702824F12A4286F2CAC5DB53CF85A8418BD229D6 +:80260000F8488A1D564929A8299A810589A8854EE168ED1E244B2165A21119C262B9F322626B12239224228722226994269D11A71169023D1A495814CFD85282222D24CD6CA436EA14E45AD624D242F4424E3F46F53626455632AF2662514E84414644F4483C211F259516C71D914F25D684F548A44A6A852E628D5C4742C11D857042A2D5 +:8026800033C5742424247548A4248F8473699C4E4AC6428F2CB828E442F445144AE133E65BFE8918137461E222463764246A9241284E122F88B87412542C4AF12A214D284D1D4AB333F721388EA8AAB584682CAAA2492D882F5DE642F948842E48A24BFA9AB1A4E228E14EF872E600671284434248024100840044844048022840044421FD +:802700000010820200400100004018042041424803002001504812F0D78CD024F2213DFF3252422CFC1D15CF67F42E142D4815B128A266A3B648FC8AE42B444E42EF64F42321BF16BE922CE248A8631D452B322B224FC4E423538A9AFD984C3E52CD4ED5F5514327222E225F53F37D6F6F7BFAAF299FDEEA4FE76AF94ACA3F38FA1A9C9F80 +:802780009CFD491943B6D4A834CAF8CC9C8FAEF5CCE84E548E815F210C281F94F7313329E426F66767EF45F46C74CF65F54D674F42A266AD22AF4CAC882B442F27D766F323319F1CFFA2F8AF82B4E4B872F72161AEF42F46F26CAE2F27F34A281F1DF7B8BD7E56E5FF5D1F1F36F26242A15F71F51B5B6F59FC48899F9EFA28E88F6ADCCE36 +:80280000F481F1AFC2F3C9D99D394BDE4F49A964AAFAECFC8FA6F58AA86AA6D9BB242429F621719F32F22A289F96FE3F37EF65F426542F84D475F228648F86D428B2C2BC8EF87B7B8F85F57C141F13F7C3F12F89FDEB8D1F18AE721D412B8645FC444E2B516AA4D98FD1FD32568D4C1FD1F155455F42F421225F43F37D7E6F7BF2BBF99FFD +:802880001EF3E8FC8F6AF97A7E3F3ADA8AF6CDC9FFD5F8E4344F4EAB345AF9CC8C8F82B39AABD44F4CBB8844D224F22874EFA3F36A2C9FB656FFEFE5F424588F85D5FDF2282C8F8656A86F8CFC8888FFB6F76A7BEFE6F323331F3CFFA6F9DF9EEC3AEE82D711F472E4E7C4EFEEF21A5AAFA6F651F58FCBFB7256FD2C7E3D1F56F2254495E1 +:80290000F27B16BF83F516C5CF9DFF79BD8FCBFFB8D6AFC3F7B3F1EF81F3CCD7FFD3F1E4744FCAAB7DBAFBFCEC8F87B7DEEF47F7C4D56F470F43026302226022844502260224864822818254289285044C0242801212180129082302185012F0261190844888004022412188220812460142F0581700110046014148C14C06004188510063 +:802980002843C821481CD88484024426082A4404401201204208448322018C2202A9010018842082528420F2984EF024421F41F22E131F4132481F41B24ED141B24AD141B24A9921AB9451AF443924AF1439242F147924D812FB24485CF9244A8D855FA264155FA264192E4ADE252E4ADE24ACF4D1242E431F4952281F4932481F49364EAA +:802A00001FC8B24AD141F64A9219F64A9255F84A934B42AB944B422F44FB2448A9F924488DB44FA2F44B2950A24CC65217C1421D2CAF14B111B24AD141D252D981D64A9B4529FB24482F147935D812D984D412F926481CF923588D915FA2EC1578256A182E5AC6F5241383DCB4F1D12847321F89D42CB49152289E6C2B141F48D23EB19198 +:802A800056421B685CB381D658E182D448B91494A24B4A29B19684F2A25ABDA9608882480000008200100200000010021880080000000080040020020000280000000014A02C4046410324411453A241001B821281144962212A34814031287028528528253744212830162C12342212212240682262288C648830884608484942341488D3 +:802B0000248120E41478EE07429E227014828402401111921860652C4401805162384880044624122826146484818984192252A143A2244481887041825412241516AC818C3C68B04C0143C68183F2853B7044B2C151234381942680021512D4182AC25619D4528291228E1125C21289021A12E2480246B82224445441848D428F216221C9 +:802B80002889D2426686288B2428488861392854244E28AAB188B43C2468A1A42E441CA883FEFB002800214051414E1100121884008004411C82048C54582CC4256120022D58286182001400442182811D484284851241144404904400428CB4450E430241195222151408241142400100211188114A0210110844204418488202402201B1 +:802C000060221618420828805412704A4108001068824A02DF3E0F112607614712421C331C30443601D018A4184819461CE422114818584826C225814964421C322481842A141207167988014681416221C28502A400C82D882F385184D68A8201F0B89120524110121201CC41324452406114802412C8841F2261828484C100412002286D +:802C800084A9A242212524416818608112809162A448A13043C22D881C41A8C1842200AF7F01512C42D441C2274674310810611200819224191405200440C12A4D218143C44499120C001011C211812833144218820840038484308261A4228CA124F066E980648245186442115481480050C29128E12361440060613014C4141800406820 +:802D000052616D28255442814782002189166C11842121868C08A1811006418301219EC43016654901421800544604661184946250489179D28664128552818B21224146D248618289522185C12840C112812D112E411E281C218851822186082524324882104848088881A9D2BE0F00218D321400432212F111288100C9A1120000000069 +:802D800000512C4442044800200450241024C1214842C01118A14160228A2189B1188C0244BF634F62413742B01CF22244194135244C54411E288D238074520C83411BC5441008890254196585A722CC42638426185A5256062119D282D314B198763CE191C44A84312F881148CC8822AB818648688D8C0245F84BDF8004E5011400842686 +:802E00008144811458812447832594442C42C821435118418D244014061078244234241002CF1241440200250288122482460281D0422141241928E2E101200234114962211400A484220048001048914419C52814918086342A906A0041441825C1114E2813F1482210C8124A0883042024223444844100F01D7E1422C02222121024223E +:802E8000243646228502142830242CC7212A24C226C048281A44C824186811801491410042208421044220243A4282908800428289948848AEC75021C44008124844811414A14820060028E08441887444022D124651141E484242A021150480020068800640C668211C9C42439E424282C8100412BFA50942111116242404212004002C6F +:802F00001251422B41123414212100844C44022603160B00125021910024504342818119018100908A182443840826D87906464402214E2480011220011A4408304414531444410427274800421321144181044944450100212D44454121848CC2C380542248D08412120282282F8E0222442210E24122C42C2814892244041254124904DE +:802F80002C8442C821144F12F12441100494008181288422100100602410683844240020028486022582F83D75141200001425440144C026A44E21A041143012001314440440014112208262228422813260122E113224200A001111222800412848A324B4A90E43691A2011144861841422100143A44228444844680000280000144018D1 +:803000007844014240228204445081242018018288442CB848A1280044F0116B5081C041412220022306624644C12A2081C23100841312128101A81C528210229442221C64A249A1524001A01222825042818A1211928844006882239488EF450612473826C2116E11223E16A126C8212E2289D23A51843B722E161E2426741231269F8165 +:8030800026443422651894312A52BCAD21BCF443488D182E258D24157511F63321484813F4241A75742298A8A3B82251319F3878820144E14B424B844B2281C48D48CFDE0C1754A215712A56421F857146D141F24261172446485884B5423144414E315F22E13422D498D611F21C6599F42844501517421D581B34344AC4481B542E42853E +:8031000081D11152812926413141426CD828DA8A12622426A284222785A9E424AC888E422E32BE37144B72BD24284391644D24484F9284E142D449B563A4644A24F412614E515B414E649974227127F4744217246E231F15F242438F64A47556028B222A724552144B242A438AE116E233F142647AD618F492424E481F1CB4C4AC4419FC30 +:80318000C2E4AF8AA6CC8F4861AA27484E448B84CAF83E97004302C1302C4003404843480300441224400428504800298112120830249016200218D02441A81284188418008464128D250010F8D1981455D377F22E2F6F63D284F8352E7FF3F32C251F15F34444DF93F329488FA3F14F463F25F367173F55F544762F655576BD495D4D5F70 +:8032000056E432F46A68D7F6777627148F95F712288D688D6A2B664E6A2F46A4641B321F2132224AF271332F23F635629F83F428D83E72BFBBFF98DAAFA5B512F7E462C7A2AFA4F47A36AFA4B2A2F484C4CD8C8FAAFCEEB9145F71F14667E7F2EFE3F466CC5FE5F53F3D4FD2F251315D25DFF1F129288FA5F74F4E2B154F47F151555F71C9 +:80328000F147576F66F46A48F5FC45452E1267E66FFEF867472F16F878699F91F34161AFA2B262F6486A7FD6F465611B773F21B322E422F273732B725F63F63B482E52AFEBFF2B6BBFBAFE13D22B116F26F62E284AFC18988FACFEA2866F4CF44C8C8FAEE59543F144477D677F72F23B2A7F45F53D363FF3D77CB252F345259FF7F56B4B32 +:80330000AFA1D3EFF453127F71F1535147757F77F72647BF92F62F6D5F54D631F162223F167A656524BF95F52A7B3F32F622632B26EC7222FC24277F73F7123223E226F273236B517F12F522422F23FE22763F34FC82E23F38AC884F6EFEA6E66F6DFDFABEEFE4F2A6846B88CDC88FAAFF5BF6145F57D755F62D2F3F27F27774DF65F53BC3 +:803380007F2D2F2B375F56F2515F9FB6F25A5AF5FE51126F65F553554F77F377677F72F669699FD2F24565267262FA62AA77763F7EF26B7BAFB3F36361AFA2B222F22C2E7F56F225237F52F733232B261F22F263736F41F56577BFB2F4F2E2AFAAFF13D3AFB8DE33BC82F864E6EFCAFAD4D6EFE9F96F6E2F4EBE46D484FC286A8785C01148 +:803400003026D01281F4241248268144C24880440220810281114C024431442189921210020000290114A0124022280214402208922882205848F0D55DF02441404238681604C422702801403842C0354924342121002285014C1204224088424844C124001428214489011896182A81188442485684802444F88332F024421F41522C1FE5 +:8034800041326C1F41324A1D24AF34D1C1B24AD981F24A9255B84A3924AF143934AF747934F842914F83D458F9244A8DA14FA27418F5245A96E1A2F5D825ACE549D2A4F591242CF591248D121FC9B248F1916CEF14F1812CAB141D2CAB941D28AB9455B84A3924AB944783AB944F82949A4F8294984FA2F4B9A3C04A1AD638B411324813C2 +:803500007148F21124E3F4112C4E961E282F547A14F848A543F24A9113F3489147834E9527838F14D8A6F148912E828F14F8251AD6F1231A875C2D11CE254F8271D1D8A4F19164AF1275819C189E6CED131F88E612D1C1D442D9C1D622DB84D618B92494924F83D4429844ADB46F8284F926523F5F0D2088040000000048000000000000A7 +:8035800080080000140000480000000000280000000014F0EE990010080040110881200500185110054240112194291722148C2241420442421181002014354880088211820018430860841283F4ABE64032812424B025812288021110582120120949446811001014044400142002002250523C6251250460323021403648308841812C0A +:8036000002281428750A204C4A0249232298285084B0281411229219144354143448301111C66482542120114144314842134298435012695414466832493821A264830C8849D184C822248CC6111E28F7F440120100111001400118000041408801004440214261821424280000406412160400000011008100000048AEB1001604100625 +:803680005041222824110000100541004243428484022820842804001942214841081D48211100000024102211084241BF9F044032216B21197224A12821244028638145420291218C14D181145184904225C4443D448054812122811304003C91442C441D92414B242C24841808428484495448181588C928CF64054012512217424C82E8 +:803700001284121278123118412110581284418904CC94244842412504423C84280419041411114489449C48424AC24242002044189242164C08C845F8ECB2004C8162431021180322200200211141421414140025544268132402812012088002982D412415421153410088840040180418158821F216B550A42642712384042800210003 +:8037800015442201236824A641488802839482C0884A410865521820924410082592284400282608C8648200809821480010F294220080048434142884443129120428225082410024458801A082450828141400112C9428814C24048110018041EC12012522138404841281AD127735004480010010922832244051182012042334840033 +:803800004410180400220030224004405412282004860180040084112841824C046FC803442312D252C248142822A4441D22282551211361228A427A81028128402408C1CC4488722201C022114810584247861422204238818A054E11002B1287484862804144F27E4100441412002501218C92120010082449C4248CC4845048AC048481 +:80388000281800442508E04442C2240025421408468102502882240080028524384884DFF6090000903200212400101202200215022014120800101201000089C11244812100000010848404000000E0A94B01408141C141218024081611A42800A2C8822292C812228632A42215044D1245280242584343848401000026724502482414FF +:803900002124A02486820482D0220C8002282004289024800200222242002A24021C6412486248422A044848400800484220041002110000008888200448A788105118241118004414100415021282103212121480048100288188001444448C0C00190828888B844440228804A02422218B42868202E0B70600004042010000000000286F +:80398000220081220060182410020048000048000042002460820042000000CFE707288082C122C0221428C02800143B426120582141305122240081282851222905230255022400454283048024549440C44281C0420080045FAA021688211194812E1512188021842804121112281A6C1811301120FC2281881642014D48005843219161 +:803A0000142D312C219252C2868262222844D021623820982226C8292BA48302289B9814824B28C0212200282428C021002012128202222200134212092052218044050040020046044281144246C444002C04004214485D8D6096112A0518E032053342224244814221294C4622B1122C912A1CA4144C8484E48294414AC28285C188C06E +:803A80004824C8004818F061822068463582022004852284022304FF640A1AF688241A8323F241233E313D322E218E2289824216111324FAC2222C027AA8476A632497A222484E4487126E41BFC676221228051F21D524C1824D12861A32828AF862A36D42AB644E619552277908A304CE421FA4AEA62AE41884F41AC71422862112E21971 +:803B000062423724412C8431221E81428642E118922222BA98A21901141CE614FC42A1666122464A42218484E841210E23314239061B54A048405421C2428D4223E422AC428C121A426814F0B6DD501113437131D521B112052231436244135211217AB132E82499C42F14F135132F18E618F3184833A2284F68D488F29121687F48532455 +:803B80001A6C244D6D4F845444169C3112425E44282F4444A8263C086D414C645648F04222A322AA482B2460266F52060084A048001C019880091C081448340000825082448412352859849A42A828411B28611B28B081429221100120025440020085010028EF75081F16F6353D9F93F23C3C1F25F357173F17B623F23131BAF3FE782A38 +:803C0000F3C1D22F29F1C2415F79F382924F45F9E3C17F72F2A3D11F17F729316AD628F2ED676FC1F558D88F1BFD7C622FB3FB7A9AAF2AFC96581F5BFBF4944F6AF891133F3AEA2BFF36243F3DF9C7873F28FE21228FBC7C4153BB7724EFECBE42F4AAEA2AF2686AAFAEB2A2FC48486AA666AE6B141F16F6757D9F93F33C7C1F3B7327F7DD +:803C800063612B333AA32AEFCEF6A1B11F3EFF92132F3CF6B6B63F18F994B41F1EFE37351F3BFB73317E38AB378CF4AD5FFF5264982F9BFDB8AAFF32FE62C98F2BF9E2291F97F775155F5EEC2BF323633F15F5D5857E327F5EFA81C21F24F48CCF15F36B2B7764FFCCAE668FA8BC62D6A8F6AAAA2F2A5C8A6AE625F5AC56B061F4155516B6 +:803D0000F135151F11F716572F17B413513129F84A4C9AF851633B913F15FDB4B62BFE5F59ADDF5F53B331F553F19F11E92ECF2B1F32DA4EE4A6F6134B1F7CDD1AE4B8F6824AABF317915F75F386463EB23F31F1531367452F2BFF26A72F38FE23228FFCFC6223AD6B7774CFE83842AFAAFE2222AFA6F6CB8A2BC8AF86A62218AF4B4AF159 +:803D80005151DF51E511F155151F37F677572F1555333F33B112F96A4C17111F3DFE13933F37FDB7B72F2CFDD5F52BFF5F53F391913F15E9A5F9E8B38F36F679E37D4D1F33F3BBE39D333D4F9AE7A9B54FEC47F7D4B66F29F413932F27F3F2B26F6DF853536F5CE83AFE6362AFFAFE2323AFB47647F7AF8F2F22F28ACA2F26F62A6A8F2A88 +:803E0000BAA2FE2A282AE2267317061440011C012412000014400228130812281301138812011828188021941280011420022682840824408104C022800200008DCF0000122011022480210110021C082D82C08100201484024062442210845214289021904110011902004100006082212200AEAAC0421F4152281F41326A1F41324E1D0E +:803E800024EB141F48B64AB981B24A3985AB9443F24A9343F242B147822F14F924484E914FA2C4814FA264554FA2645D4FA26C59ACEC49D2A4FCD1244DC21F49D22CF891248B841FC9B24AF88124EB141D6CAB941B68AB9451AF443924AB944B4AAB944F82B442F9A448984FA2F474F47024D2C1B4287411382C4C742ED141F42E111F41EC +:803F00007422B411D44AB215561A3AD41AB814C4A54F82F4429565F848B16B128D912A7C583125874535F218253C7418C5421FC54298418915F148121D2CAB141F48D22AF181488D141F88F44A3686D838F3A448A9F1A44829B184B44231862B144FA8F1C4E6402808000000000028000000000018800800001400004800000000002800F8 +:803F80000000002501EFD404400400282128400200002400C2282100280080024A1204000021008092420000804411084082440244002C012008820000008002140000400822001100000024401802008044012004420020044200004814B0810C30C40080022800412810814202A084AC4222021A4221082820425421401A480280249404 +:804000002121003044A0421008400224244C4421F1E19800008200210010020000000000000000800400000000004220040010210442200400004F9901504100008002002800000010044004400284004002240000002004000000424100002002F043CB002A0114001001248420010040040000812146040000832402450121212821007F +:8040800000000000400890281008F0D5F50016051400601200A12218000041400400A4D024048400C0482902354402201202420000002014040026088C02D0840120020000000000000000004004000000000000100200000000000081000000F0D821800200400114210000820050140000100410880100000000002800404888088182B0 +:804100000080040000F05CA1002614080000484242810000001002000011410000001004004901184228000000400400002218F0C5E3000020020000140080110410040084000000000020040000000000001008000000008F41022244818042011121420000400415441402400840112401000080040043210248228484824008814420DA +:8041800004002200AFE3098002000020044641088218000000004100810000004004000012000000200800000080017F9D0B000000400800400100000000000000000000000000228840082800000080010012F0E1FC00000000000000001004000000000000000000000000000000000000000070AC01140000000000000000000082007D +:80420000000000000000000000000000000000000070F303110000000000000040040000000000000000000000000000000000000000F0184D000000000000000000000082000000000000000000000000000000000000A043000000000000000000000000000000000000000000000000000000380000E0EB0F0010084088044100000092 +:804280004400240000000020010000800100840000000000000000006FC60B0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000002400008840020000000000000000000000007B9C001001AB +:80430000000000000000000000400400000000000000000000000000000000009F7F070000000000000000000000000000000000000000000000000000000000F04FFE0040410800421004000010040000000000200188002180010084000000000000280000F0A8C500000040080000000000002100440010020000000000000000000091 +:804380000000180000B06C0E0000000000000000000000000000000000000000000000000000000000F04FFE0040010080045400004840040021004400100218808802218001884008000028840000800200009FD2010014000048405588281082044480022100448002214818808802214818448828842148408481421882041E14800244 +:80440000211A01445C0300000000000014000000000000000000000028000080080000002884000000001B72004001008004540000484084041002400400218001882810021880088400008042080000280000F0E2D1000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000D2 +:8044800000000000000000000000000000000000F04FFE0010020000000000281002008002000080028004000080044480022148400400214840040021EFA20A0000000000000000000000000000000000000000000000000000000000F04FFE000000000000400100000000000000000028000000008800000080420800000070820E0053 +:8045000000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000008002000000000000000000000000F07F4D00000000000040010000000000000000000000000080080000002884000000002FDBFBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF63 +:11458000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3B +:00000001FF diff --git a/kernel/xpp/firmwares/FPGA_1151.hex b/kernel/xpp/firmwares/FPGA_1151.hex new file mode 100644 index 0000000..5ecab69 --- /dev/null +++ b/kernel/xpp/firmwares/FPGA_1151.hex @@ -0,0 +1,664 @@ +# +# $Id: FPGA_1151.hex 5128 2007-12-13 14:30:31Z dima $ +# +:020000040000FA +:80000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6AD6FF400038460A006AD6FF400038460A006AD6FF400038460A0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4455544455557475577775577675577775577765566665563625523235D2E37C2B511115511115511115511136 +:80008000155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111000000000000000000000000000000000000002552222552222552220025522225522200000000001AA1111AA1110025522200001AA1111AA111001AA11100001AA1111AA11100001AA1111AA1111AA113 +:80010000110000002552222552222F21F112122F21F112122552222552222552222552220000001AA111255222255222255222255222255222255222255222255222255222255222000000002F21F112122F21F1121200002552222552221AA1111AA1112552222F21F1121200001AA1112F21F112121AA111002F21F112122F21F11212EF +:800180001AA11100255222255222000000000025522200000000255222255222000000000025522200001F1BFBB1B1755777000000000000000000000000001AA1111AA11100000000000000000000000000002552220000000025522225522200002552222552222552222552222552222552222552222552222552220025522200000066 +:8002000000004F44F444444F44F44444000000004554444F41F114141AA1114F44F4444400004F44F444444F44F444440000004F44F444446F64F446466F64F44646000000004F48F884846F69F996962F21F112120000004AA4442F25F552522F21F112124F48F884846F61F116164554444AA4446F65F556566F61F116164F41F1141411 +:800280004554446F65F556566F65F556566F65F55656000000008AA8882F29F992922F21F112120000004F44F444446F65F556562F21F112128AA8882F21F11212004F4CFCC4C46F6DFDD6D62F21F112122F21F11212006F6DFDD6D68AA888255222006F6DFDD6D66F6DFDD6D6000000008F8CFCC8C8AFACFCCACA255222000000455444CE +:80030000455444008F8CFCC8C8255222004F44F444444F44F444440000004F44F444444F44F444444F44F4444400000000CFCCFCCCCCCFCCFCCCCC000000008F88F88888AFA8F88A8A255222CFCCFCCCCCC55CCCC55CCCCAACCCEFECFCCECEE55EEEC55CCCC55CCCEFECFCCECEEFECFCCECEEFECFCCECE00000000CFC8F88C8CCFC8F88CB8 +:800380008C000000008F84F44848AFA4F44A4A255222CFC8F88C8CC55CCCC55CCCCAACCCEFECFCCECEE55EEEC55CCCC55CCCEFECFCCECEEFECFCCECEEFECFCCECE00000000CFC8F88C8CCFC8F88C8C000000008F84F44848AFA4F44A4A255222CFC8F88C8CC55CCCC55CCCCAACCCEFECFCCECEE55EEEC55CCCC55CCCEFECFCCECEEFECFCE8 +:80040000CECEEFECFCCECE00000000CFC8F88C8CCFCBFBBCBC3AA3330000008F84F44848AFA5F55A5A2F21F11212CFC8F88C8CCFC3F33C3CC55CCCCAACCCEFEDFDDEDEEFE1F11E1ECFC1F11C1CC55CCC4F4CFCC4C48F8BFBB8B800EFEDFDDEDEEFEDFDDEDEEFEDFDDEDE000000008AA8889AA9991AA111000000CFC4F44C4CEFE6F66E6E1A +:800480002F22F222228AA8883AA33300CFCCFCCCCCEFECFCCECE2552220000EFECFCCECEEFECFCCECEEFECFCCECE000000004AA4441F14F44141155111000000CFC8F88C8CFFFBFBBFBF3F33F333334AA44415511100CFCCFCCCCCFFFFFFFFFF3F33F3333315511100FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000008F84F448489F95F51A +:8005000059591F11F11111000000CFC8F88C8CFFFAFAAFAF3F32F223238F84F448489F91F119198558884F4CFCC4C4FFFEFEEFEFBFB2F22B2B955999855888FFFEFEEFEFFFFEFEEFEFFFFEFEEFEF00000000CFC4F44C4CFFF4F44F4F3553330000008F88F88888BFBBFBBBBB3F33F33333CFC4F44C4CF55FFFC55CCCCAACCCFFFFFFFFFF9E +:80058000FFF3F33F3FD55DDDC55CCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004554444F42F224242AA2220000008F8CFCC8C8BFBFFFFBFB3F33F333334554444F42F224244554448F8CFCC8C8FFFFFFFFFF7F73F337374F42F224244AA4446F6CFCC6C600455444FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004AA4446AA6662AB6 +:80060000A222000000CFC8F88C8CFFFBFBBFBF3F33F333334AA4442AA22200CFCCFCCCCCFFFFFFFFFF3F33F333332AA22200FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000CFC4F44C4CCFC6F66C6C2AA2220000008F88F88888BFBBFBBBBB3F33F33333CFC4F44C4CCFC2F22C2CC55CCCCAACCCFFFFFFFFFFFFF3F33F3FCFC2F22C2CC571 +:800680005CCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F48F884846F68F886862552220000008F84F44848BFB7F77B7B3F33F333334F48F88484255222008F8CFCC8C8BFBFFFFBFB3F33F333330000BFBFFFFBFBBFBFFFFBFBBFBFFFFBFB000000004F48F884846F68F88686255222000000CFC4F44C4CFFF7F77F7F3F33F33333C3 +:800700004F48F8848425522200CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F48F884846F68F88686255222000000CFC4F44C4CFFF7F77F7F3F33F333334F48F884846556664554448F8CFCC8C8FFFFFFFFFF7F73F337375F59F9959585588800655666455444FFFFFFFFFFFFFFFFFFFFFFC6 +:80078000FFFFFFFF000000004F44F444447F75F557573F31F11313000000CFC8F88C8CCFCBFBBCBC3AA3334F44F444443F31F1131300CFC8F88C8CCFCBFBBCBC3AA3330000CFCBFBBCBCCFCBFBBCBCCFCBFBBCBC000000004F44F444445F54F445451551110000008F8CFCC8C88F8FFFF8F83AA3334F44F444441F15F551514AA4448F88ED +:80080000F888888F8EFEE8E86AA6664AA4444AA4448F8EFEE8E88F8EFEE8E88F8EFEE8E8000000004F44F444444F47F774743AA333000000CFCCFCCCCCDFDEFEEDED1F12F221214F44F444441F17F771714AA444CFC8F88C8CCFCEFEECEC6AA6664AA4444AA444CFCEFEECECCFCEFEECECCFCEFEECEC000000004F44F444444F47F774740C +:800880003AA3330000008F8CFCC8C89F9FFFF9F91F13F331314F44F444441F17F771714AA4448F88F888888F8FFFF8F87AA7774AA4444AA4448F8FFFF8F88F8FFFF8F88F8FFFF8F80000000000000000000000000000000000008F8FFFF8F88F8DFDD8D800008001000000000000000000000000004001000000000000000000000000DF75 +:800900008D07480000000000000000000000140000000000000000000000000000000000F07472000000000000000000000000000000000000000000000000000000000000FFE40F48008001000000000000000040010000000014000000000000000000000000F0E6F40000000000000000000000000000000000000000000000000000D7 +:8009800000000000FFE40F2800001400004840012800484001280000002800480000108204140000484001002148000010F26B52000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE80840180020000001002000010024082 +:800A000001002100140000000028000080880200008828002800FF9C030080840100002001000000000000402101000014000000140000001400000000007028034818148002800414182810820416012810A21140012810A2414001002B11484001280048408188022148008828108204F05C65808401800200000010020000100240016A +:800A80000021001400000000280000808802000088280000F04EFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000210000002100180000000000000000000000280000F0994D000020020000002400000000000000180000000000200200008228000080080000D0C10C00000A +:800B0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000008001800100000000000000000000000000F0A149000080020000002400000024000000000000000000000000200800000000000078 +:800B8000EF8A0C000000000000000000000000002400000000000000000020020000000000D015020000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000002200000000000088280000F09AEA00000000000000000000000000240000000000000000000000009C +:800C000000000000F06646000000000000480000000000002002000025220200220000000000002008200200002F940C000000000000000000000000000000002100000000000000000000220000F0855400000000000048000000000000C022000010220200280000000000008008000000F0D59C0018000000002001009800000000405E +:800C80000118001100000080010000000000000000820067E5000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00400100240000180024000020011200002002000000000000000000004002000000CFE10500000000005F +:800D000080010000002001120000000000000000000000000000000000007DE10040010024000000400200000000000028000000000000000000000024000000F0CAFE000020820420824402002400000020040010210410020000008004000000000080024200F0823100200200184002200100400200000048A0240080040010020034F9 +:800D8000000000C20000280042004A22F8D8D9000000481800000040020000000000000042004002004003000000000000800400F03C270020022800C0224230120000240000800442204681042400000000200400008A040080022220046282EF214881040000200223011032220000006022008001420040010048004800002162200427 +:800E00000028280040410248CF2F0800A01248004041011301482880022200241120018002001C024001284212002800002602000000002480F8D4F5000014002224001248004082046022002004400100184800400200000048000000100280128104D06703420013022082427112814102480068800221281148002002000010012200EC +:800E8000002220A42460240020820280024220F8813700001242001002B011440200210022000000144800122A04002C04200100100280020010020000C0431FB80912800228A024112842288082040000201202182382210622264202C022808202201481229442138802800882008800A22A94828F8D0C10011902001224002B61250159 +:800F00004812222006004222482C04808484840490411118581122484A018012232408244227244A0242C800481F87041838002222002346021420042A1422020042200412800620026014222A140162208222022094218028A4822A0842288084C281CF3D05481021212481A3248022041304004818122A0540022002180010228203000D +:800F80002A01A0141002800800291802212182002C28F258BDA04211121842424828482C22324300000020020080A24226022248904100281CA424C0212800102232C100484A082304238402292A28F21AEF00222222000025022002210021480062484268482121482904290446818404C04160140020860842420042A084200430424804 +:80100000CF2C0C00001800005840021800622828000024004800222002002001001218428024220800202822026200F03D44001800806221420048C0427062220400425840022400220000000090214021020019042800200280082240017FAF0E001C05121A0400000028800252520010021880180218282AC1614081118104002D422863 +:801080002800828868002282228888422114F7C620041B3212621AA7567E622AA2622F22063521A444802681A232282344B24281A6216A662668222D4220A2262D61384A11F12121112E111E622B22F041A319AAA4A0888A784222B242282AA444486E218AE6CC021AE71341E11282244242219412F032632C8454226E420032A056484A45 +:80110000E42266242E429062422C26B423A7441B4113F261411681036A86226424428AE41C641860244E42AAA8A42CA4C42AAA82AAE818AC86AFA502902112181A23A421D02264244213A4242981A22123A6764AA544000023B242512212224AA122422820041B22362144A1452B12482B6222222AA48C4880F68242AA92228AE428A2242C +:8011800024217FDE0F4001000018C012C0138001180000122001211022011221122041011440010024400100002440020000D07E01821F1283A2324AA2231E222B232B212AB252F33123567242B2522327A3137AA1223AA1151AA1272B46423E526E622B562E125A25A1115AB15184B111F111311996413E1223C5222B441386A446A0844B +:801200004AE824B422E8247482E116A4C248C814DDDA80B47127A1525AA4534E422B472B457E122B552B433B272F25B11221A3477AA117284AB452A1554E224E429EB22B731EB22B542E127E525E216AA6261B671CB57137112E21687E722B552986B261C8A14AAEEE4A88BA62A48A6ABEA2BC6186BC22A6C46AFAF617A0551F11A4213A38 +:80128000A3246AE224F262322D622B732B241F36C3622F21B142C432583AA5117A273242E026F36242882E427E722B463E225AF6223120F471612AA3731E111119E621B37261262B441F1EA288EA8C2224E82CB622EC249EA3CA24B8A2A66AAAF24A2FA06F1B6317117A21A5175E522F22B14264262F25F163133B6427242B556E726AA5A0 +:80130000275AA7755A25A4444E224E421EA22F23F782222B4476E22794326AA6351F15C6311B711B331F1292615E722B372F2692221F1EE21AAAE6CAAE84AAF8E2622F2AB862BE22A8EEEAAACEEA6C1EAF160E1880011848184880044880044820818204000000008002200222A012601220822422280220088228821182288228823D2F67 +:801380000011008048022502244001250229820400000021100200230200144001002C01001482002400D012028004F02FC980B41162121B2166B11132621B212F36B111F262921B212F1439112B94322F1429F24291222F14AB424E912E421CFA22425E212F22E519E22265192D52DAC2521B292D531B29341B2946B1917642B381724267 +:8014000092612F1498212F3418F14282222F2428B2422892822AA4842E42CFCD0F2AA4412AB41122B6113262282B1619B26299214A9B214A29F24291222F1429F342A12B434E812AE514AAC25EA12E42DE212E42D6C143DE2148DAC2439AC6431B2946B19166141B282384E61498612DA119B642A8422B842AA4842A94822B424AE8226407 +:8014800012008248000000000028800400000090128008000000008004488001000080020000004001DF4B07820020042400004003A01242108304128004002200282C0200800200294102488200002426022848008048F28CBA20A42980012E1220C2422AD4222432428682542111284822132202226842001110832402271242290121A2 +:8015000060124E11264122A28426C18224C2003081282044A1245F7B4921A43C80012A01298224964222394482E6211281C241282C8203322A240828113023172422702221A4219042242E111A74228194228A64122A08239C2221E0188442021C88F2D1670000200421400224402208114210824401800448000020020024000040012013 +:80158000084002002002004880F4F3730020020000424821134102210082000000100121100100003C0814004800000034000000800842F09A76200220E2240228002130C2200C8002308128800242A0428022482282020028181642021180223C8100004A022800424228F0DCFD200228282C062200219093308221000011000042E0224F +:80160000048048222202708182321118101201803481100120040080042A046FA80300000000484821488004808208822820021001801201000000400242002888001002282002802804C0DB002212280028122C04C0420012488004224002184280A48486014081A821C01218822601A02100225021004888820024422420724C03008022 +:801680000480041448181420022280010046022C0110820800268104800411C84200501200E2224800428008884E22A0842F8C0500400100210024002100880020080082000012000000000000800400004002000082007FEF022002110022230129C412172400182A24880422884240824C8284C481180048001A94121C98A142200248BA +:80170000226014004888290882304282A0486E2F008081022004460100240000120000000000002022A81200000080012501A028214800420080A84260129F250B1222102121B21222922222002131882901282246118232812C44C123C0224821582800181419811201198922C46110011C84084222004248422229F4EEAE10010011137C +:8017800044210446024211422096229081008004800888110020A82920042B41002011024840011082084A2882188108F0566200140024000020B8120212002200182004222014218585021118421001001C02282440210421482024220442006234DF840D1100281142204422041314211422C48142214A120100B88048A12848800412C4 +:801800000030114248305125118108881188428842884288248880F84CB8A0343220A121321F25A212683248000000282A04258122B31244B112225222004A28A224268122828282022880862224A6244A0823282204A2222A2C263822AF15040038140040028880022908290288002A0821A82901802228220220280400110082000000E8 +:801880002100800200004817B80000000000242810422208210014001304581400E0281481044814000021C84200000020040042000024CF4A04228212226215021120880848886814424A2988C2421CC42288A2121CC6410028000022002012011448192ACA818004200800286014886F5D0400682008002420420128001111112128100D +:801900004281D5228408132208C0D1214229849141208435812400800428000000002114CF480A1F12242801171E15A2142D42422CADA41B1235C1428AD821A6248E82822C9421421F1CB6C2D823E421D912B2413222212A2502181344C1113F1243011F11F8211333A442114846812C988280268A0288C04142FFAF44A111968162111893 +:801980002F11342211232228DA32042D112B242333A11381DA11E11408181F23A4863714172426A3E44E82C6A1244AB6518EB663A42112286AA46C1AC4631C62146EA11D22461182A44E62A042EAA424A22E21229F6F03282AA2121B221AA2261F11A2362CB26212A22446A28C244225A16617366A7222B2216622288E212A26A2C11F1888 +:801A0000A16A281CA499238A81027041922118CA0A33A4E8A0C8114EC24288884AAC84882AB442EC24F882C2EDDE144218C011481C8184818481C411482CA1482C8184818401180000008840022E926022E0220122A092603220226812822088228822C821822882286FA2032A220319A7221D112AF211113A23E829F912322B11A0911E0D +:801A80002137111F18BB31FB31323F1DED14F43171EAFE21811F18E416E637FFE341281F3C5C22272B1E42171235723222712113F23181121B461B4415D11124E224744292624A8604424AA64428482CF253DA142E21CA84C2612E233D422F22F223432B229AED2BD933F622231ED22F21EF31F231211F18BDB1DB31F4E3C12F14F43171F3 +:801B00008E921F3AC8E32F37F742432F1EA4A21F3C5C322F28E128F4414135F3534315D313A444171D17384E433D411F12F481411F1CE412622C29A24C48CA84E21CA444238824FC8885A0671AA5121B317AF671132B6717342B66FAA9EC1F24B243B6D2B1C2F841712F14F4D1811F1EFF63213F18F853111F12E63EEF1EF841833F16F672 +:801B80003173EE43CE223F1ECC612BAF2BA51F32B641B633B613E22292221F1FBE91B662B662B681CAE11BA21F2CFE42822B886AAECA2AAA8A6AAECE2BA2AAEC22BEA14FF171719AA5331F15F371711F25F573711F35B562A6CC2F2FFF53732F34E624FC72D23F34F762611F1DFCE1F13F17F7A3811F15F321618E83EEC11F24F473711D64 +:801C0000431F3EE42AFAE3C12AB2F2B7F2F621631F16B633F723323F16F261611F1FF3A1326E633F12B6A1EE1AFEE1E18EA32F2CB8A2A8EEAAAEEEAAAAEEEAAEAEAAEE2EFE89AE00004002240082000010011348022800114231423110022004005012400114004001000000000000CE42400122400186210112211A5212122928511212A2 +:801C800030114212148210219451C0822820D1221881244102141B412C180140114102210000002004FF740E1CB41142B11162141B21271419B24291212B9419F2429313F84293A22F342BF24291222D91AAE414E922C4A12E4216E122E419E2226D192CA5292CBD91C2521B292CB19122B491F242921B28271419F6428219F6428119B4B9 +:801D00004228B242A8422B842229A842882E428F6A0A2A91415819A212482B1219B4229141298986AB68981B482DB1482DB1AAD412B182E414CB121CCAC21EA11D424AF2218256E13268192EC213E922B481E422349162112F12A84826B18134228AC4211B68218A94228A94228AB4423282288E422FC90E20880400000000800200000011 +:801D800000000028000000008004000024001480022800000014F08AD5200A1200282902000042000000130300221C984100822400222119022B288021858234414240021C04000048002860222BCF00822A08141414282234964181410230532CA6212416A1251A8414021C0118281965241842208401148819082C02828A34A129486220 +:801E0000242C048A04A814421C08EF324201C218001C32228042032044824222C52232267311021A249783C2190198283B1413D422210446A238E011846512A0424880C4212B8630422420842452214A4221B2C90C22A08240011428001C19810100144820013A04001100000028902100008882421121822C28480124482008820088F0D2 +:801E8000E8220000281420924124124612613400001A04120020021100000080082A08804281C48200008288102288082008A024F034AE200232124868112AC141004A018AA1844A93411488424882488842486810C12214224821484A211242011429828284480121404202482220C44100AF910E228001116819A2143C840118158221DB +:801F00008841A114881848884282408104142C0222482328A41400115021A22100C082002488002288481448F02F9500808223049021004239242428A42442142004002242422200100100A08228212811422022244801821042828804004222F0C8F6A0142218680013023021200388800240014022818B028008001400228210828C02A3 +:801F80002848004031424820081081022C0A48FF6701008024042001290420A8420023880422602480A584A041888228141C3242002422C22024012448A20082200462000046022CF2EDDD0000000028001210021061140000000000000042A02818001100008200880000240014200822D0D30912281222426012222419260188C85021E9 +:802000001B480022208481AAC2A04120881241820438249083884A82014A3842A8881582842404220020888642F24545800400002001001A120220024814000048000000A042A08280880200200200008800822304200282A042EF9D0F48721081C1110050121220582200922192211A2201E0280218808991916898B0410A4A83820C98BB +:802080002882281CA4821002828E2222282280226232F0546F8002282280024A82A4288002282002702201A0824022240A2200622004400200422011018821484800200482C0C28084B8540740218184044248008248482004424220922229046219924214001906222848006022284021822286220440032088280480C42123F49C2800F1 +:8021000000120012003042002002208202C8800800208404000048480011602242240080820800222022068288281F330800209121322822281B8228A2258224A8212A9C8324005E212AA9851CC461222822C22848628A8662188230218223C141213042468106212018024888802484BA83051800284290410042130800200818E0280398 +:802180008246D112A2182C41A194882246011C88818812218138211C0400110080B44218828814010000571C20228112014200240000102224011220094002A0148001181118148084018024828982E8280288800842483081800420F44F8120041240110120042120880410B2212488081410020000000028C02100800225D1226C28805A +:80220000084A088002A8808428CA81F0A829808182042242322022A44242422842C228241100906280014A0A288820410114208204B0820480042048A268200448601A0021F0436520A2511AA125A0412A05F042426A88082D42A0842B48211CCAB2281BC8682F21D2222A9441A0381CACA422A213671A623B6A22271A2212E6E222BE62C8 +:80228000AC62398C2A88384290A28AE21CEA12A4442BAA469322AFF6094A47A1222E11261121056E4213B88204272CA086C0224ED38632A28ADC12612C6AF4814125A3245A848422228488841A0190C14AE4249C418240226422482420A6466A044AA28848AEE162AF240A122A02111B746E3119A266282EA11B216A862C9442AAA7971B7A +:80230000223B13B032A1272E911C28A6E33E11AAA283EAF1115119A7758AB241E418A6111A82F281223F1AF3123125E128F2C381A2CAE424F8C2418AF882E282882AA4882842A0C8F501004021080040220840022048124122089210020088000040010000344002248200240000402108002F450B5AA2261219A62717161F16A2462A2217 +:80238000B4E24A12028AE821B162AE7726A1B34A64111F1BAAAA3F1A6A2C3F16A691AAAA5417131AA1CADAADE88AF8A1813AD311A6CC4AB433B382A2CC1712371AAA8EA8842F247822B262A4C66E41A0486A8444F1C53B20A5531AB121B2F1D611A1374AA42217342BE68E822BEE2F24B4C2EA2DB972F3D3B23B992F23B3D2FF53E11F137D +:80240000F6E1F31F36F441F33F17A751EAF641711F17E613A3FF7AF5E1E1CEA11F1FAF331F1AFAA1813F1BF8B3B1AEA22BAE3F16BA62ACEEAA6A242B2CEEC22BA82AA4CE4A2CB862A8EE4AA835A0642A26F311313E3115F13131E02626B2E2EA26F4C2A246A2CC4E422F26EE22E23AE822AAEE2F14F4F1B11F1EFB83811F34F86361A0BBFC +:802480001F11F131417E61AAA88C1BC81B881F1A0E1F18FAC1E3FEF23B112F2CFAE2E217323F1EA2EECEE229F8428227222BCE6AACA819A2C82BCC482AF27758A0553A21B331B371F751511F17A3446E62CEC22BE6242BEC25B2E2EC29BBF2FB13333F19F932322BFD1F15FDB1F11F3EFEA3C33F34F473711AA37F1F1DFF31617AA6FFFAC9 +:80250000FF6161CE811F1BAF331F1AFA81A12F1BFE3231EEA22BEE3F1AFAE3E1EAAEEC4EC22F2EF862C22928B2C18CAE886AAAEE6EA1FF4F0318800118C011480014004880044820A824132824A82411004220044200000000184888482248A048208802A0482800826F4102009021421180243481232408102228B4811402210015820837 +:8025800000804881A428C88AC28128B0814282E232084682E214082C080021800A208208EF8F032AB41142B11162141B212394212F24B191B24299212F2419B14229FA429313F242B3A22D91AAC4912E421CF8224216E12264192EC29E212CAC292CB4D1C2431B2925B2917242B2917242B3817242B381F2428219F24282112F1428B2426C +:8026000028F24281A22B842AA4842E427F6A092AA441481B2162122316B16231912316A1B41B282B94924EB113F142B1B22D112B491CAA521C89EC15CA521E212CED11C2D39E212CA52D3CB491C6D11B29421B6927148A62141B282394214A8AD212A8424AA84A2B84A22334224A6822AF4A012008000000000028180000000000000000FC +:8026800000000048000000000028004800004001AFCD0A20020038241C8154215AE81823084223C291208804422A2182080086A12400284248C02182210098A08410220200240048200240F2F7DB20611820098044220200482038812344826422260182108214022810A141107223E2340880A8482E82142C02804881D4214481022008D1 +:80270000821414A0E21412130C00184662212815A2142E8188A028E01C41A248241D2248823229A848214081061180744222240229AC48222B1822C224822222002C028004244001FF540480029280021142802821044632A121002A04800300008A021458282119C283118800821410021021944125010088804A01B0A509A021222002DE +:802780002240A2412001100210810828C021209441008024842144A2212428002901260200228200200848888008005F390E4A02185021D0212482A28214C224821C8C88A28121581420641C28282B244A8392212890822A01230E8800211908D0121C312270C2612C488A04228848428A84F4A4F42022A32180024200290DD8001488409F +:80280000031001281442222984031422208882622C00101292812110122108212400422A28082004EF3D06480040031D2222282814402238C2202289A8412260148A2492412248282A24C41248162231222882800122001B482C82028E414AA8844A0800C8428848DFAD0118002811002800C2285280C51242420040220192002C083240A5 +:80288000C11280210C12260218002022641286218C04210080C82240F23777000048420042245200880068801121244202A021808128880414201241021448428800002842000000A2002442229FAB0F001001001200121A1402000012002A2824148202280018428A2408128082810228242C04002100A048884082A2480067EA2001606F +:80290000121C04A02410A2816AA141A0412A95424A31118022AA14468282828132824A2281A41CA2111A08112AA1249228242C8422225612C80048204A22A86842249F2C0700000020011A24042908000080040080080080010021122C042A01210000201481084290828200280026F18926800211800142281021140124924A082492A000 +:802980001430813021E024421221A281806824428008003A0434482008800C284282000010F2986D00118002602311221023921280C4122C01002248482221240020082C248502428004222400280029840C0088422004800A5F250A4A02C011281C8102001800182021042280B212222104A043001200222D11A81128342248200620A27E +:802A000024222119042480024A62284A022E412F384D01280012200129810688C800A88820841202002C8142A18492820000188212200100828215024240220C209CC20000704C061A841221324119C64222258231412001487041A24227214229248812A24222162281862404422C02298242823212304100821082988311C28822242A9B +:802A800028084622F89E4500802201123100802284C881D022A2838A81A8121228C8348088C821860118111C018A0280820418218A868292432C2A04828012210262884072AA04004001002012011200200400008001142400122022028025810180820450221C0400002800000022E055011182280000A0412823A2384218002242421266 +:802B000088482C028004582023C41280011220A1181914022384388214404232414A082182292824C68188EF820F4081041382044A014800802A1902822C02201962162C2181180180226612429062800412222800200880028046B2214403822924F6C3F114621F18621213837111E1245312281B22327E82881622B122ADC12D128E521B +:802B80002B235AA1582225E22282B4533761BE51A21A8381AD11EE726A2382E124A2645AA7428E428ADC319A824A2AACC8422220AA2826014886E126322DE011221A8132314A32122223C2121F14A638181989E12DE212A28E294AB22238729E924A12A212242B1111582A94212B242C8218825B21A23623F24222464132E24E4125C2C29D +:802C000035E21888EE28A4241D42282BCC826E21887B3C8004281CE11482B521E421A6152F141442A14D82CEC2F0C21248724A8186BA41F621411D412F2822E21894821AAA846E4236B26134121B4912282B11182411A82B22F081222A14621439642C6ACAC22B862BCC222BA62CBC82F42A4B0014408104400214001220490124822400EE +:802C8000821001211001000021111811100100400124400200100100007F444C8194212AB221267A61F363212AA2445E132B55EAACCC1F14C4923F19B8E2A8932B574AA6AC6AA14426F24243CE425E324AE818A8884AC4622D222F24F1B1E18AA82315F18183317E321F15A5EC2BCCEEE11F16E22EAECC4823A4AE8AA8C4211B662BEA2A41 +:802D0000A8CE4AF4DD7D144AB461B621B231B631FB11232F2531222B241F25B113A1CEEAFF41D12CFB83832F2EBC52E72FBF72B7D2BB42AEEC6E132F36B422B972A3261F1CAD886AC4432F2632421F3FFF53111F15A4221F1BBF11F751735AA5C82BCE1F2CB661B2E2BE62C6422B64EAA8CA4AFE23E21F26BEA2BE62EA14A4CCDF3A4CB162 +:802D800041D61146F121116E511F36F163316E622B541F15B151A7E4CA7E81E129F922A23F1CACD72B574E622BEF2BDF4AF421723F34F442C25E521F15E119A8814A4513E226F491F11F1AAA732AE219487142F25353CEE223A822112F28F882E2299482E024E824BC62AAEE2BC829AC88AEE26E1A141B661B62111B151B771F35F75333E0 +:802E00002B662F24F343223B66EAAEFD1F11E927FDE2A23F3EFEC2E22F2BBB72B7F2AFE6EAEE36F6626327212F27A2271F1DAD8B6AE526F662622F24F4D2F22B9F3AF72121FEB13E713F36F65252CEC22BCC3F2CB663B6C2BCC2DE21B4A2A8AAEEE26EE22F26EE2EBEA2AEE6EEE18EC22B41A01240012E11E0128144A2411448A0410028CA +:802E80008022A1241228A024800242884218422220020029012A81A48240A248240048248E4128A02420045F6D0E1C0422004021512228228218A094122DA18A3442304280C8424641021B521280E22224453291204183523219C21240B2810428421188224E82602482208208B71980B41142B11162141B21272419F2421119F242931B31 +:802F0000212F3439912B94222F3429FA4293222D911B4A1CF921421CF8214216F1234296F1224296C1C29AC2C21B2D2D421B292CB99122B49136421B28271419F2428319F24282112F2428B24228B2422892822A84E822F4E58780B41186B411021A3642284A81B242B911A2B41B294A29F24291B22714A21CB1A384F921521CF921C21A00 +:802F8000B82164192E4216C1C39E212CBCD142B211C6D21B29881B6923A428271419F2428119A2A419B24228A284222B842229B82284E822E48F0D208804000000008002000000008004000000000080040000000021280000000014E06B0400108114011A22E1312821011220012142142A8921024262200222C022202222228321284852 +:8030000042014211C08288802C024282002028F4B963A014A68101322B8148002820AA41002C0618212C324122124A18032A418289B521218521C44146022816C142184A811422B8220C460221904180A4828691411CA2823E6820651E005E22118003199212226200282112C023CE122832123924A821282B184AB221B1411122C66122F2 +:803080001A22E1198494122B412442112B48822B82244A288284A4482AC8821344A1C29F13040018112029041892208921011A440223041C22018A042A040018202201C042200288408104822260240040010011800A8E8800002822112503292188A94820010050128242002014022200C22C04002440011428241002230424824240022D +:8031000088800880F4469E002222142412321848212962218286028AA3D298A04122424A2214314111B041888222A2812CA4848A81A18226823A1286A1244E813B8228E2420024288A8284024242F01DE20020C22124302212482988A385E02801824A8148218C86043041218042014A82062C04181041022333812133DC32A824824221BA +:8031800042242823880C824200E78C0028002813D1210129418208290880836A212001A04248904111A0482882248A018AC482122A88B28102800628A0248008002220028024F4B4C580250248502180417112023812A025304221268102821C8112229442C822424041A2424A212422042880021180262422044A08682024442284F26976 +:803200001F1001A05242804403111C02A08428220080044248482818923290321B521C0288283012528821188220C88282200A0000221042826824AF810322804201000042000020081A02A08180028A0414000042003188001480082024021400002120088282006F7105262102114234400233912118128A24612AA02114481282182473 +:803280002A28B413A412B05212A124242A7C2281A4211819089288806422E8148248C08280A228304220C4422E918005221A02203411144821280042602480228288E414A24242004828A0250020C58200302220021C280848008004488084288828F272BB8083A221C012281824242C6224244225420240426222402122149222212221D4 +:80330000282511E222E81812328221803162008A04001308860248290888482142A2485FB50900001904214A230480A281D88005408121212121021118E0120118005213A44122114200120040012123048A02000000F09DEE002081024001001814A01448000000280011001A041A280221192288A8411001114800C042202428A48422EC +:80338000822924040070D6030020011148122004420088222D41A0522B41141A34210048140000480000112400400142118280028820140200230AF0525E80011420D42184633446224192A12124822C244102260200207412120123848214238AD8220812299142A0422014C14100821502004800422240F14F83C06100421821102221A5 +:8034000088021239A8212301271218A041A04148406122828280A1121C01182C0411160229210100113413344228280080084820F2988C00186800000000188002224A223141804201C0118081044001208124232222C221200222228882806224000028A8C082887F1C02200200624A3222A0A423088E4120045012004828111D2280045E +:80348000A8B08124840248400140011C0428A0841062120021233C2288200480F494FB0080A41280010020220128002212002830428085E222084824225214601222342A0448A042113302A042008220E2248804281002C778B02104A03442230123C212E23AE82132122B448AB122312123A34236A26116218432433642A2C84A22D21224 +:8035000011A18923F89241DE621B12282D121976529141198C52113C54124A7482622C8A6E22C8290C2A0486A3846F5B0F38121A22031D431F269751808F7441E114BC81A8462C0218159112621943D121C44119E61132421994E11B254229B241E2244AC141121122192425044A042C84B8412C6226CA6A24424EC24A9822A0424F9F0DC8 +:80358000122AB221011E536A32125E222B4425D222B222E928E121D122A8452F2457312F25A1243921B63127467242B123E123B28261292E422B73223ED3112B922F217223E3153642282A83F223418AB281B881FA232390C2212934A28222286A8C0A2F9203111811001800120000200112100100000011000080092A091400B02201239B +:8036000002146032820024C022000080F23668501117142AB211C6413F32322237322B722F2C3CA23F39F9D3D2173429FB22222B662F23F352412F21B172A7666AE626F66362CE132F21E323B1D2E529FD33224E22DE624E422F31C8223F27E322F232521AE521F262423F1EEE1EAAA61BE64E436AFC4141288AF862E2EEE2EAAECC4AA623 +:8036800066AAAACC47F8145AF441411F12B311E635F53333373135F372722F2CFC82823F39F9F3B23F3CF492B22F22F372722F33F372732F25F5327229A4462F27F763622F24FD13132F23B9D2ED2DFF73322F34E225EF24FC32932F2AF633723F22F232323F31F532723F34F4E3E11F1EFC61E16ABE43B463F44141C82CF8E2E22BEE2B15 +:80370000EE4A24B4A2AAAAEEE2FF85031AF211711F1212E136F6333337373D132F26F7F2F22F2BF113133F3DFFC3932F28DD22F372723F27F753532F25B552B762E612C6133F36F642C33F31F172722F2FF792D33F33F252632F29F272623F39F873623F32F622233F33F142623F31B252F661632F16F6616119FCA1631BAC1F1444A28AB7 +:803780002BE26AA644CAAC642BEEEAACEEDF760B1F15A6113AB351E237F733333F35F413132F27F7E2E22F2EFCD3D33F3DFAD3932F2BF922322F27F772732F37F752522B673F16E632C7533F36F652423F31F1E2622F2EFEC2C33F37F652622F2BFBF2F23F3BFBF3723F23F323223F33F363611F17F771311F36F663411F16C6C23F2ABE69 +:80380000C3FE41412F24E42AFAE2E22B6E29A44442EAAACEEAFEBDB70000808164124822004814004810011200002811002800220040011480018024021440810482288200282024F82D2CC0411922122182542220249812282D928A6424220029219322C0112E4214260258922722168124D82234C1262201197242024613418162240051 +:80388000822724C08220248AAA424214571280B411021B21421B212394212B1419B24299212B94112B9413F2429113F2429113D212A9421CE922C4811F2264111F2264192E4296C1429AC2C21B292CBC9142B39122B49132421B282394212F3698212F1418F14282222F2428F242822229A842882E423F1F05481B61181B21421B212384B2 +:80390000724291212B941B282BB4112F1428D21228D2122BF2429129D412E922C5812E82122E42922E8296C1438AE222BC81C2C21B69241B29421B28230621282726824A12F14282222D82F042A222882B4A29E822F4DCD4008004000000008002000000100218000000000000480000000000280000000000AF8B032002224216214503A7 +:8039800086A221000030510048008A0220041810A28124201202142028222A04424001820000422088222424F6FB42145811005022190215822248611C824819268898C11B8313242681786291221904115A188102C88842404181CC114081388229248244C1422400C6C242822814F08DA380E4140222481721194211D3228801AA0448C2 +:803A0000221384B881A4841D422832123D22C213245121B081D1210268884213048681641840012C8884A2C214482400822C682A2A84E424F256BC80010024A01400282A18412108198409303180842828240200D800C0820040012AA82142E0240814004002806424480000AF5A030080220200A0212008B042010042824200002210019A +:803A800000482830110000182800800482421124602410020020F2248D144A2102111819018091816800230C8A81E419841131B1D28286A12800781981A986AA01A0822AA88234C0813C0C272A2C0814218058122CA48288202CAC8428B0B208001081C21100122E812888002182421448A034000022A02119210138001B1288101142915C +:803B000021218A1282042928348125714222160248800824AF8F0D1A8402281800001242002B484A21015A8831811CA81C8813A882001C0488AA848C028222A8001AA84824C08240010000822C08884A282482F283A6A0240048002002298124842884828288222E94112868808C311188208444014001003A84840824244602268302802A +:803B80000880C422402288F8EEEC14001A82A624182200A01820C18268200400001391A280011A2A0811142C2C22A22128422480818812212208822A08280082002C02E0F20D00800124004842100180C1122024012A0880042002804102005888212880024880044882304140020020082A045F56432106281A22C412200229A1494292CD +:803C00002C8881A1844AA24BB0A18102E288C01132824A9141808892711A22022C028A8144C242222B48152298C1A02800482C0200887FD90882800122200242481001484222210048004E312004280000214221C0822022210688281448A028000021800888224A0AEF350B90116014102102280000122002481308001302134281A2216F +:803C80001442D800228004A21A28442102248E22A0243041004221200C48AA04AFD507122022011200800828A8002711C023A08414146018825021146012209C82252105293811008A34911C962100822188118A04AA14120221008FFA078A0100001158A04200008014210C8028023200008282262102A042001C12212224044A0830420C +:803D000080C44188282304282A0428488A041480248804242890114A98118081024218E024018888002A1422250300141E621110E1212C22019A828802C811808A480288801C0221243FE90928802284C321180020860800222200220000221A4821220413042888181200132408400182000022682128422302001CF2D8EF140018304138 +:803D800000801621C841C82182001502864211813211181188133812112928C8811121882160211440011420822844210800400288005FC70120810424426800211C0119011820082A01184800D829B412944224405221142124208104423A08482024C422800221882400808288F8C61B202428110100005A0200200480091200200200D3 +:803E0000C0610000200800E81C0280222832228008002880088008884F6F0982224832A041142800242A052880C44128134CA184223981B44121A284001A24A12416212D92D219881432821442824248822122A024200400A2482129F4D4F2141A6519E014944114112A21F482114AF9219118181813A1448E5319A1991F14C1C113E81100 +:803E800031611F1126E511A48286E11EA4A816A2C2DA9182171116B162B911EA11B691E2149421CEC28ABC82021113F822422ABA8254228EA2298CE81282E81C08118A22A231423B356A324228621D421A223812246A021BA78AA844821982B28184043D633B3C1E51194222B48238D12F32A44523582186A246C24E1113E814A822226E0C +:803F00004180AC668A68242C22A4442223A6842726FEA38082A131111A82641128221B618AA2441BA4A086481F1208271617222928E212A1228EA3E60226F241224E521B911F2284D23283E22881A8BA1F11768291812AACA2AE42F042222CB862681C1C2894426A883822288A24A8482F6E0142222022581248211A142211A241211A1406 +:803F800022019A842209924282421901190819089800A012C081A092C0810040A24814482882248A04822880F27FC320A836181D611F36F6C342213E322F21F382822BCD2F2CFC72422F24B4927A13F1B2A33F1AFAF1E32B446E311B4415F191811F38BEE2F7227329E824B472E723BB72A7E44AE42FBFF2FF21B33F28F883422B111F1834 +:80400000B9812AA88827282F22F42242C81BC8CAEC24B482A8222B842B8829A2CCCAAC447FC646F141411A051F11A5E61F17EF25F512122B751F1EF8E1E13F3CFCC3E14AA4CC3F17F2B2A32F1AFEA1A32B4CEEA33F1656113F39FA83E16EE23F36F643623F36F673723F3BFB72716AEE2DE42ABDF2F7A1E32F2AFAB3D21B111F1CF841A135 +:804080001F1CEC1CFC4242212BA229B881F861E2272429B822FA42C227222B222BC4CAEC24FC8EAB147AA6512AF231111F17B751F541632B224AF641B1DED21F1EBF92AB54DED21F34F1A1F33F3AFF33F32F21BC52F963411F11E11EFD81633F32FA52732F15E435F472716EE32F1FA7A86E62BEF22F2DFD93D33F2BFAB3332F11FBF131B3 +:804100001F19BA81F8E12227282B4C2B628ABEC1EC3CFCE2E22F2EEC24B4C2E82CBA82BA22AA8A6EA2FF2844A15D1A011F15F131733F17A7441E122F25F763B1FEB21F1EFF92922B54DED21F34F1A1F33F38FDF3F32F2DB4D2F9E3C11F39F9E1F33F18E626F653733F25F4D3C33F29FD83C32F2FA7ABFE628EC22F2DF593933F3BF2D392A8 +:804180003BB31F1FFBD1C11F1CEC3EFCC2422B4C2BAA2B881BCC1F1EEC26BE62BAC2FCC2C22F26BE22AAE6AAEA26FA97FA0080012E13C01340023440834412818204114211102114221402184A021002001C082901226022822400828044022880222804BF6C0D14008081B62201228246B18104480014221C081C280A24A8C02122468122 +:8042000068182A2188A428481122114A38811081082210120110022C022148C041FF2C01581B21141B21421B21271419B24291212B9419B24219B14229F34291A22F1429DA12A94A1CE92AE414F8214216F1214296F121C296C1C29AC2C21B293CB49142B291E216B891B242B881F2428119F2428219F24281112F14A8422F242AB242285E +:8042800092822A84EA22F4E9E120A26126B11122B49152121912B211B26239912F24BB91C212A24623EB34218BBBA2D412E12A41E122E811A852122B82922DC31A82AC292BC21B492D121B214AB8119292282998212D82199222112F24A84224222522022B4229E822F4EFBD0082480000000000280000004410021800000000000000000A +:80430000000000800200000000B07E0B5424005222111361238C282481054428003061442884C2800418822826A842224C988123A32120B821A1280088800C0080016880022A812AF27A3D24129A0228471AA02822808113889819005D8219E1C823E811A2851986328100504121138441828484440593A2482C81816B24871B2426A84823 +:8043800024C0A2002824444081F48DEF3015CA1122E2418C32A11962211628C318EA911844221D841621C92115A668147A388182805141D0819621288E44172C3A745401141BA4221232423E894883A28610E2210A28404202224AF278131082026012001222824200110024D048A24838128B2400480082230258100280028E281892218B +:80440000822C082C080000808422422483089F25010080C21219468102200260880088800838A2004420642280288828850880021024A882008222821486880820812A0100824FF10F211681C2125B427012C4482E124A38813BA4271930149CA414888F41A2485324A428AE418E422C5641424B4B4E2156DA24046D223EC147341E812988 +:8044800089088713238488082328245C12468109E8D02212A8148B24F0F5242420218272728432128C26318219E82498818818871498881624082A883221462416E422A4184AA248006B282B184384A281824189212E08A028C813448808A0852210229568D0E90C1001183413541480228432231884448004898AE4542384888C18D21231 +:80450000046634818C91C62B41B0411271921102F0812200888221C0821C68149820C2822A410820F8B8F7001212190749011682D424842265483E448022C8121148612C82E124211C88C294801444B1820282002AB1ADA425924148A31814688444882822CA024932146024284CFA39149018200400182128129215A441228C0441448106 +:80458000322224CC84819221484A8891242114301A99218401488502002A3418602144800A800A28882CB21844E21C0D2C1414045A22024342018428800812320020284501450215428208A0412008000010648222008822200420210410624144421FC40A184C118482A512126722281E422E98001A0412B664611426B28422D71C843438 +:8046000062A115C254296924415288251821042A31848B2149712468228C1288E884034882284AAA2CC014604689C246BE31C042803111224420611444B011A6944338482200811A0480014C38214A023024408282290912D08162248280A48416140821820018C024222928E14421FAFD2F244A02A11428150824244826026C08001C52C0 +:80468000144225621446211864844E114631424678427441B4422888B8411287088E24835C185C84C44468C848811031842A9448884D8245688290246F510114952481818801C1441288424282461884312A124321CA28C0930018821B81002C81B22101E86B149012008CD24211082123024227A228A931244D284A22828408BFF90180F8 +:80470000224248281628C1423A64348C6A214C2422B28824B48862826800281964428954424827828C9412480029018A914820048384698C8D1216A252962838C8824212128D948021F5ACFC5021124829224474531411988484604212822480581200881446E86841886882202838882CC148C8442884A018A694222C0A440000522901E9 +:804780008248200250221F320BC612518140482214B1420184000029318231141D88A119D418840215088C34124508851208124E81864248129C1186D942322A27412342B81814E19102811285C4441A28816D585F82021A92241AA4211D2689022243C2222828828270286443436144524122328B4881AAE41288328822224814428A0229 +:80480000002044C8444004824C88084280446C15820021484FFE0A440041121184A11184A0142901A90D81830228884110220200803112112899092810042820812101412841004426042A382A484E8822F06A57144180C249416B14644604458194884241244246A418CCF241845CC19862A0284116180452228044022411212351424468 +:8048800012A02499B158C2129018882C0338D022218423042F5D0416A84148008021C12888196841A0254008422B8140082D8845D21441A282008282E098011184228A34E42AA1288288A0825048800A0000002398228B82AF5F0A3F72768495138F8143EC123654CD42CFC2B258A668814E8458216D4413D6187488F649E1EF98F2A82109 +:804900008F8484E9886A189B1322848F61B1248A59882E596A7265921486BA74D1C4BD8C62A32D328E246FA1F1442287834E988E5819FCA2B46394884B711AD262E783E518E822F461F430442B268F82D212F43922FFE1D121D5113241374A83B2F2BB863616ACE522728834436EE1A664421B44AE819B6A97525F2646734472C8B2246E84 +:80498000AD85A26A9345C24519D842F88A842364834F1CB82CB464F5A184BAC8F22B4119E81631182AF4343C66FAA4C88789421E424B24AFBF47A1111F81217121944442A5FC121C2D5249F9438B8CE421E14CB8E8D888F116FA4FEBFB17184FA1B141FD14881D3247E46F24D4C8E184D6CABE117DC298413F8DF452928E821F19BC92FA82 +:804A0000A26283C1628B2B1F74D849E74D781AB848D68A15922C87218FA97244F298284AF488842F64B164B888AA368E9C4FFE4D0100002400402249022412200882309120098210032908290922702201002A084D1190841004000024C02450282004F09A7F1447246F65F1141C9F93F39D17FF7B53CCDFF6F244141F37F63D218F2AAB4A +:804A8000D54F6DF884C4CF62F2286CF5BB39F1A697ED9C9F96F6ADCDDFBAFA838323F81E154F469E424F46F626646E72AF89F118383B91FEB41F58A222AA0A5B3BFE724F2DFBD2D27FB3DA8AF49A8A2BDE1F81F4D1614F46BE424EB458F132A4AAFF78E88DA86E644F924DF16563EFEBF71D2D8F81F15D15FF555ADFDFF6D357F1ED6C1FE4 +:804B0000DEBAF8EB4DFF8484CFC8FC3C348FE2F6BFEF3FD1F9AABAFF9CFD4348DFD2FCFFCFBFFEFC6BF85FC7F76C6C8F8DFD7CFC4F4EF6E8EBAFADF1DA788F99FDA4E55FDBF73EBC6F4AF6181C9FCEF4F87F2F6FFFDADEBF56FD18D4AF88F85A789F19F4891B6F4FFDD8D8CF8EBC5CF16E646FC7F7E2D88F81E165FEE67E344F21F51777FB +:804B80006F41F131311F1AF63B7157D41F16F24D3D1F74FD2BBD8FA5BFD2FFC4562BDDCF67F1F2FC5F73F3B3976F73F9FFBDBF97F7ADDDCFF8D97BF866866F55F17476EF4AF2E4426BBB8FB7F6FA3AAFA7FFB3F84F6FFFB7F58F81F1A4A62F42F2B53D8F87F7A4A22F2DFC87C18FE6F68A882BFD1B559F9DADF62BD44D4CCF8FFB26A6CF0A +:804C00008FFD6AE88D884DF44A4EF23577FF7BF317351F13F37979BF55F65F1FBF76F34F3FFFEFF7B3BBAFAFFBD6D26F6DFDDADAEF67F3EEEEFF7FFF5B9FAFEAFBDFDD9F9FFF25DFCFFEFEA3EDDFF7F67F7FEFE7F7F6FEEFE7FEF676AFAFFFE2388FAFFFB3FB7F7AF6BFB7AFA1F9F626AFCFFFD9C5CFF7FF6674EFEDFDDFDFAFAFFD8A8A9C +:804C8000AF85F5D9D99FBCFD66F6EFC4BDECFDECB8EFE6FEF6FCFEF88F8DDD44FFA6260030228440583448268144410840E68904135128401401110085048D24410000B0240129016981542490841608926081A048608144124C22A124F0BCEC4031111081E1411402E08864148028480430842324480188136844654811048844884A929B +:804D0000921B242A08888E24D081E2220888282D82282B841114439212803224A98804471A4FC1063CF4112485F21124A7241F41324A1D24AB141F48B24AB911B24A19B54A79A5F84A9143FA4291578A2D914F8AE414F9A44A1CF8254A16F1254A96F121CA96E5A2EC49E2A2F491243CF4912487221F49F24C821F49724EF18124EB941D8A +:804D800024AB9419F24A9251AF243924AB9443F242B64F82F442914F8284F9244AC7F3E0B2F41164CD421B21A7261F413262157C4AF2812487661B218DB259A684478A2D334F8AF44231478AAD212B4AAD254F2AC5214F828CFA2648F022C88D242DC38F4992C29E2C2D4A1F49C2C217C1CF24F8812443F41128EB84282D961D6CAF243BF2 +:804E0000854E324782AB9443F84216224E94678AA9F1A452BFE704848248000000004400000084000048180000002100401884040000000000A011000000008E39108452C12014342400866818AB42884491281B21B024B81876C1C43114444C24022D7811C02429081634812304212A884446784412881202C810084028088F446148891A +:804E800008DF930B2722922884CC48325868AB8645334840682892184634214224B04428811663445C02888B86888CD142A2426B166C021143116488C8892A741431482F1A0170C211E884A118386888583641F2177A24608D4D29B08444B61C2632489D847F8438222E8845C218326E1126E148C232741F4132117279A46811278313C894 +:804F0000282E861338224B25BB432E44211149CE444728B068384A4D2343E4122106390C12818AA1244D4A411648F2924B7024820284810048230AC04820C8814004428CA4848A044110C42448800C8C4104861402211240B84848041285228808818483248902989A840A6FA107100180C1242A41581C682A28814188081C6A8810111873 +:804F800001480016D52604488304B02408410028A02826E281044821908A1984419882484A2202412848BFE1064B24A0121882256324124812123B82244A41240130B498BAA4161F88342128212F8214B12DB4242122E98368252EC24A82CA3295B2942265882CA8A486A925214260141902891884E841221528F27FB1C06411208198243F +:805000002E42124588C1221818838508190A4B8219E98124C2884824E033642489C4242E48189E284B782F288426AA2199E24AA13484A31D32C82B24212D48008501424B42822818009FBE03002A011231294198412A84B92148024412308812A0821395411C8202A554414D21522008801204502220A882A086111880C8411C85328289D6 +:80508000082849C1448C22F6F76B50484883011A04282422951494180041A21219C428181A44428C49021AA283A9850316218DA2292F8A91128AD1812E81311447222A048052428E181E68981302422D44822E428E34A85F840A8015020089941140222862412F42A14131491A48A124E02128C1122A04807881024043628145410881486B +:80510000246024301416A2818344C44128A041200828EC08581FF7094A0140485848D04A222124118108109848418A01002024184431484443342468228200400446644A8A022006200800144301100200AFEE0758128C018C15A4428D15324681C128C0144391298B4987549B186858C0144E828E424416C158CE192A8582B52264884D08 +:8051800083127018448894844F28D6242261239828219CB51824A834162468442AF844A84B38888FED0C430821844058282821C42938112C094622C8248022019281800228264214462422B922A1212E8212881B284D121A82014386048C8428081200460221002E417F2C020020C24185D218028489CE881129524212250C101105178116 +:8052000044002D1E83820820951450848072282158410084188921AA21118152804396440084004E282FCB09800117443041245142C012200822002240CA448848888E411148A1C88121811A5412E81298A021884668431B248846084288848C22648CC0884324082E1412DF1B0E8280821134C428221256081018812848081A021741D0EA +:8052800041014420512200205142256241604422824B214C030011281E220010846122202223A242145F150544288014391219012524180270121218D81289149682C84B428A94442CA4421C88D485A448A4482E41488C84044820242CE444A88446344846A43428528B84304A4628548400F08661001614248111449218224440B84201BA +:8053000064004140146A43E0410884431604124A0912842100841840644118301C19044B81898402E2284C48088481C0F1A0422812284210C2224A81A21811E0441A410413B38931111911312315D28179A1D481B911348124E082441D41944281188382286188906C22407548014245022002109282482DC1200124442187194548041077 +:80538000880181882C314C840088882400008418430411862101B8888200A840088288CC0228A0218011621218226483F258CEA012824C41220149154804608115981143218121B124341880A4384004404114486422A01418823880684320449414C01418008C888812A4422012C449F0DC7A400C8C46918C2180C128004422CA120286C5 +:8054000014113842101292418921948410388485028712205A82A061424280C888101168C854284098188638112088311288EF1C032A61491AF221121F41D81358854B11C14C582895F2621A211B18448A911415D112F1474C9EE557451B4447741B4C2D6B7F91F45188DE469E5A6F21F578224B44EAA2154F183938824741EAF61848AED2 +:80548000C49AEC828EF5A9724B844A94C88BDA2E44A76E1CEC9296A82E284731E09A0949A21A641E4467844F45F52A2285F8627846A8111E11E015B814CA12EFC17818E362F314848E91C3C64147719DC845355C812D41854894288CD511D122BD82FC182882CBE22A66814B92CF15F148344E155F832AD5590226A824A781688146B43489 +:805500001164D2623ED5E04184B22CF144218D5385EA55F1222716F4A8728E88848F18F28D5625FE1E8813B461F25C889D4A169211AEB28A28F82A381F42A184C74849384A17866748A7A147C12AA242B81E11CAD944694C8445388D8344E9897518A82547C1CEB24D186F8E03862AB148FF8878AFAF0A100465C14845012410240848444C +:8055800084248A44144124480485140111441110040023022A088884002A08419214001200241028514890289F1A0C4AA61485FA15729FE5F14D1EBB641AA1158ABA8CD833F15B4E3F74F58AA88F88F8DAD885A8CE5F5CF88F89DFDFFE9D99CFC4542EEF2EE421F518D817985E5A4FC8FD145CCF6BF96C766F48A8CE9AA8888AED84EF8B33 +:80560000FB74544F4BF96CFC4F83F34161AAFAE8885E188BFD4763EF4CF8DE146F5FFF35344F43F13434BADD18F869D6B054A673CFE2F215768FA5F15E4F5E622B336B37DAF38C84B5F323447F71F53F1F8FA8F898989F92F2E8C5DFDCF88BC8FFCFFCB999DFF5FD888BFFB6FC7677AF917588FCC84ACFCDFD1C5DCFCBF97C7C6FE9B8F254 +:80568000AFEABAFAA8884F86EF87F37C5C4FCBF978F85FD3F379FD1F8AFAC9B95E588F8DFD84AEEFECFEDE3E9BEE4F43F33C346F43F3B8F88F87FD83F6E044C65487E15F61F35B4CDFE4B143E621F1525CCEE48D8E3D13BFB5F657D7FF91F99888AF8DFD1C185FBFFCD78DFF98F8FFFD5F19FDC4D4FD4B6F26FC53536F85F58541CF25FD22 +:80570000C4C6AF75F788FA6E726F83AFCE9AACABBABB78BFA8B3FCF7FCB48F85FD7D399F57FFE9218F8CFE5848DEC86E8A2FC4F8D6946FCFFFF4BC4FC2F2363CAEFC8F82FB9658F054644F43F33C2E7F75F35E5FFF75F553722F43F36E7C4F4DFF989EB5FB4F6BFFF9FD979F6FA8B852F57D7DCF5EFDDF8D7F55F4E5C55F5FF545D7CFFCD0 +:80578000FC6F4BEFB7F7464D5F5CF4CCC64F6DFD7876AFAFFF7A786BEFFAADA3BAF8B8888B7F8BFFCFCFFFF4FC8F8FFF75759F97FFE1789F9CAD45DEC86EEA2FC6FEF6F4CFCEFEF9F88F82F23C3CCFCAFF68D9B7FB0080012C810412204142482349012011180113080021812911881818044100A0828443028884001486080086C82416AB +:8058000048240880028D9B200841503415981E10A24818D02811D42A3884181508D04A094C61285451009601F02212E02221091A0280684149E841A2821741902120018021123234209118226F65082E521F41722CF21124C7141FC1766AD341F26A131F48B24AB981B24A19F54A96578AAF3439252F147BA4D852F924485CFB254A5CF868 +:80588000254A1E215FA264192FA26459ACE449E2A2F491246F22F49124CD831F49F248811F49326A1F48F24E911F41F24A9219F24A9153B14A3924AF2439242B94478329F924488B944FA2F41776F0244A1B4143E2C154141FC1722AD341F46C131788AF44F18124A9B385F24296478AAD138AE444F3A4482F5451862F54FBA41A4E844DB3 +:80590000825AEAA2645D2FA26814BCED4582F8D12C65F21144CDC21F4192881F49968A1D4469E941566A1AB642B395D42AB224D428B92494184B43A9B8A2B44AF1A41A1F5B0C00000000000080028008000028800100440000008480042200000000000084000014E04301402602678295942230184C81812401818148802252482AA5A4B7 +:805980004142604283245284AB242001520012182A91411221C82F81041C22045086424944481828B448918CEF9A05F0A211842D18242A95141F2249041324423A146042843088427651148092284C120280C6148B284686A42826E212018D84C014E0822831A42482196988C042A02138116A7134C821286F54072453C7222C017B123295 +:805A0000139A1849914522163816282281A0824247B34F12A5424B212AB484322242288F44B22211C116428B522413048741325601232ABD2C11C421B601244394424E341618C17249C251CBA16DBB00104A382C8C14261106184800814528048122428008814044087048E482280482221A822108441884248A442228648840088042184E +:805A8000E881942870FE05410000110081901880118428C181414C214251844A08812AC4240040C412004218448860241E244A082364812098981028110200448444F0C8E2E022815226842783A5522583028223B821018CD92C512426BA38388149618232494208904348848CBB2221A4254C2402222684484868422946A4242266018A08 +:805B000005808181C851481A2485B67F082E12226542C2329502210089292181D82408318D241C99349126EC461808221448C0124961211A044A02908482421E248A06290440C18812001212821B4144844422AFF905410081815041831228183221701864814CC1A8294904281800842CC46410688A2242224604124C2202854248A624AF +:805B8000418B5222CA22A148812C010080A4141A24F4EA661088448AE281562A3418218439D1A1014F82012088A4412840E28304235182278826A221449D1483212888C4416082481662428E4800241A444A0C2883222814684A44666281F0138400298501008C14883114001634A2521002001256028B1420A44820688440D241E2812270 +:805C000041A8521682C84400188A02A0141604A82021031236C116882E145F12080015441122822112994122001018480820441808800612001888801442821A82280180015628042282002D12812001134808B0A80810C2182CC2782CF218411A12F11148C019124CE9811458820040A814424824899442228AB244C18D167AA4021A7423 +:805C8000E2A1122E982928C5248B41188B2980C43200A012824068483634448C28F288D30012451341424842981A442F12012542088088A4142A84419838A44A02834122412801422E9840022051248008424829C14889092C48981A3A842183688318415F560945021042081504442228184098488141814C44A84142224A013044221879 +:805D000042442084018823054241810048008A01441982144C08402401F0625400001110C13A84108805482C0424199C11008413C3182C48021518F824489487388B848688284A41A4418E1C8890688122A24068948718908812828488180012E90B20226222A01222228C0122262201A0428B2122182828008C82820280848202120000E7 +:805D80001648428C02184004202101420018201442A2846FFE0B28480012101208118425289219120098198811124808194832182C0416C2189230C81218C04222821838488C018F14131892288C51A6002141001A04F6048284B04141311180814281C1125022C0120029226214184E2100814A224801420016A884481A02C80048006870 +:805E00002422230111244118004480015F8A054604414141CF2442344243512C11204164C12D841644DCE1014D18426381189441694864C12259014E186214842185128C7428042849C498444C0888421A88D22A48881898188C023EB900E08104843011002981842424A442158884847441487221082D49142110084424200228283444CF +:805E80002832104198284028514911008420010082F022A1006022224C110218800210184224042210420441262228482204648800E08401C0441281000056C412004418411225240481428984D492098CC1244C042842816CC4282341C1448002989B824826D82405412914951443B211086081428186210216682448E012214188D114F5 +:805F0000418842043884124280428C06218CF8EB8280A1484415D244714851962F87E1412112A1161E1229B41EF41A71CF4831514B422B5666F428684E461B783D812C9451891264C3AF6E4DA8818B43D81C1CD188E14648147848384885A58E13D122F917114B81526FC978429C82C084850C4A25F42CC440B428F22C223625F231348F10 +:805F80004313782CF8192C4E39872129764443B844E8173A2C19D338F216421711CB116E8947682F8272449C4429B7484218A27C8C1288B214034F81E697429C41184B73CD288D1A89528886DD98E324751CD224E18121B854F612482E88C89FDF0A495642122B2497A12C54214CD422D212B132944283D488E14661A83D488C7FDA7F1411 +:80600000D898B144E192522C224718A713278C87D55D1257118B8D85A89C1B2F1E122F247416F68A12CB983AA3231E2846E841B524668948991111A8128788AB2445081887218E183F3E045241B024014714844184454108400444402458681185145148214450481181718902400122151854811815287211988415A88284888488222C1E +:80608000289388228B8432818FD90E4AB524F2383A3D318FA1F63373AF95D2AE56AAB5AA644AE664744AB212F561832F86FC51122B143FD7F711595F92F629789D4D1D839FF6D633F433791F13F3313D9FB9F99818AAEE8AE21BA15D3E329FF3F383C11F4EF63D351F91F331111B355F56FA81A1273A33CA818F88FAAC284F8EF634B43B33 +:80610000DFDF48A22C2AA2D88BE8DB77A0327AF72C2A3D333F75F22362AD6BAD7AEFA3F12B2B6F44E624F752742F25F512363F3CFDD3DD1FA5F5725E3FB7B772F62B318F82F3F9F31F3AFA68EA3F32F27BF99F53F72977DFBBDF99B4F8FF78218F9BE7299452BF73F38781DFC6F634348B319F17F55D544B919EB4373AADA11F11F9D9F9CE +:80618000C7ECABC4EF43BBF2FD84248BE42B22BEF178AF2B065E444D448FE3D373711FFB77338FC7F22E7EAFE153EB1F76F662722B75EF25F55C1A7FB6F3FFF95F3FFFDFF1FFD7F714587FD2F7687DDFDCF5A7A2CFE4FC5F517F95B714F3313CAFFDFDE8E99AED8BFAB1B95E523F31F53A3C1F4AFAE8CDCF43E385B731E115F7E4744EE4E0 +:806200007EC33B754F4CC58AED8EEFE4F5BC162F84DE987864F8C2982E388F88FDAE61E047F63474CFE2F21737EFE1F177361E7EED7E6FE3F32F3FAFC1F7487A6B556F65F556567F7EFFFFFDDFF7F7777F5FF7F65549DFD2D3D9F3EDFF7F3AFA6C6EFF13F35F7DCFC5F7797EEFF9ED9AFED8D89F8FFAB1F92E623F33F33A36FFEBFAEEED2E +:806280004F43F369699F87E717B6A4F3F17B3F36FE42415F5CF5F9598FA4B96AF7BE142F9DD7CCF86C488F8FEF95D588FC18A600A01210023440224162812448241B4180044800100100218B240022812200C0113026400100200100484412000000EFAB05822012413311A1405281805428008481122C48A81426088450224028141518E0 +:8063000022A142C092502A4C0216180818CC1208A1604416D82262821084228221F22E92C0421F41722AF2112483F49124A7141D2CAB141D2CAF14D981B24A19F54A9143F24A9143FA4A934782AF14F924488D914FA2C4816FA27418F1244A87197FA27498D5A2E44DC24A1F49D224F49124C5F2912C83F4912CAB141FC9B24ED1C1B24A57 +:80638000D981B24A5985AB944782AF2439342B94478329F93448984FA2F4FA48F024481B6167221EC84F12D1817226F111286B161D282F56D9C1B24AAB21AF5428FA4AB713FA4A3613D24A3B33AD94AAF148B53F22DC48BA217188B427F588242D939E25ACE8C952B413DD2664C94E911FC8B622E1C9521616F86217CCE614F314482F141C +:806400007324F84A124B41A7444B41A33436A3D424F5F79C008004000024004400000000000000000000000080040000002001280000000014F0339130142514044661422210048C85C4181844002444844413444442141445012826448264424216815812901A0024E08481C528192425210484E9F21228CB2541C044BBE71420E8A24186 +:80648000415882D12C41C82110081062924A218269226280C2491D282212222741811849243148444ABA12D284311828295182308445322860210028001A48061AC411F08DA614444364A21415D848422151C21C325483B4282111362158222959282446019B4137824B28441163116843158295688364337A781289F5281212254862483C +:80650000857444C8283E41422004818F2158A42E1E181C2175FF062C0149014602C30200810000840044224E24C02440041621022290441044840C41842100001AB4220124121822002D2432424904418BFE8081022002241D448110889288844088016C1284028184001A12D14812012011044100840081C42112188221000020242934A9 +:80658000844A82F49CC62441642284D11624420AA32266111C51424A8142346488144964122826344484004881C562644344D2140151163422C042113B41B0240C4628A4811CA1B484988C08AD1410044BCD10868242C82900178481B02844E19118AA148118222225E142C42181C1460422148C44586880012711108111022C443848A057 +:80660000871288481A28A18284888288C18842F0565C805124004449612245423228200341801294448644042082028418302411C0442D44444441444183021071121542048C1402114A011846283152412684F46E86201444988A1828001412C844C8122419082116C814282CE44164121A06CE182191804194212140B822083C0C2C06BA +:806680004182244AA2248748811A02808403922480F5C3F47028B1220480180623721698485048E02288218234418240C81211AC28018200529490451813618810A44110384880954881857112D416C42425424808608285A228F01D922001A08282B48481002828A5C144810010210240280428C016100C52000024182081080049218111 +:8067000001C048890800100444F0DFEDB031144658821265092C6291124A4232486C4138A346621486C1142688D158F4488228404816B1144429E1421412012D824C1121D1288A04124D528382338267144B418358824628022E84848684F4E85F2088022880522A84418C84C8281CA848180090182280843121422252291148289144802F +:806780002181880292214881444A48A8141D4889415828008001890128B0850E002180028400100444488100200120044891888034234200D0429442C01140190600425180544110648888508400428443B57F4E111741140100D084210880A22818802128322C1B188282132828440C122244266111113024400A10450420810D21842A8D +:806800005122452231124282121E84F083682482224140841244110412004044488842840428281244800500324240941848001820914213045825284804218001894C2201006FD50484442321154A24C11490118119810180011011123284182312189D81B648820845C2411215C4A33034468A081E2890242012B188718C318890214CB8 +:806880000940042884AEFBB02424044413018444604840088228004D48002002490412418042040014460284202282120800208601A08118004608424814CF1A0580028096283048201489044C123845312222852402611382023021A0424042440244484810082144881032120061452818187482A4411086F4A976004148213014001017 +:80690000818128018088414128988E15A484881C58481C08234418448811982180110115041348381130819081303100488A8181388283788AF44AFF14308889C1118D848818810014882210844808242828841068424602868424084180044883220226126412E02264481FA2244102408244C64212004282AFF1078C9112400281442054 +:8069800001400428004058584254397443041813810D242082E414084048D41C7C4244810183529422186C18B8816288188480622868451802BF854981671D4146F6F4248241D4121F48D8D90132C826681425187418E424F482222E41472351937849F211458693134E242AF22448003447422B154CD882F684263C328A447447292FB161 +:806A0000FCC2321D828576A2548C8243656927AD25024D858AF823FB503247EA1E121E1115783CB418115C8446014E8128434814088426FA22A44B815FC842E41CE1125AD4CB14CB244E624840E74DF1454A5F84A36C8D2197828724371247411F92C6295B6646B521A28185C8884F21E82198886C989449A4B85AF4A8428D1CEBB52445A9 +:806A800084524A11A18C42AC144C8121B188C114301C4B988F11F1E8215D21C57821AD84CEC12EE845ACD1A083222F8AD8442194422751291441FC14235C1188311483B48881B3C8C1416F597181D189A3182F679118AF8486B954D48468854F24F4CDDA2084016186A8148442124F1428A184124E84844A28E14408642004441088012148 +:806B0000004A92148A1234814B1217886332812A7181281221321126628160812003328526422403EBC3341F28D16451E81F11F551514F48F34C444F44E44131811B5D4AA49DC2CF8CF644463F197981F1E541AEC2225F5CBC81F869C95F18F8C5437F11F524C6828F887824F46C4A2F23F188CA2BAA1F14F215951D883F68782EFF9597FB +:806B80007F887825F4989B3F1BB9D3BD93F992936F28F88D81AF6BFBD6D46D266F84F6E6A42BCACF8AAEEACF62D8FA4CD343E16652A81F31E54EC624CFC454444AE41CF44CCC8AA88EC28F86FC8D8F2BCC1F1EF6A1412BAE2B88FF9EFEA5E19F9AFDA1A8DFF4DC13F424462EE2CFC67624F4684B2722CFACFCA7EB2B8C5CFC288B5F78F8CA +:806C0000898A346F94F4CDC59FE5F5D2D52F7FF9D3939FE9FB8E86DF58FAB2B6EFCFFF46666D24AAB2A2F9CECC8EC8CFEE7D7245F341533E7687E17F51F111115EF48F45544C1E145F44FC595C8F88A8B14DC4CF84F48C8EBF11F945C55F16FCA2C23F1EFCE7E11B88DFCAF9CDC1DF34FC171957F2371CEFCCF864448FF4F6D6D6EFE25643 +:806C8000F76F4CFE34758E2D8F62F2ADAE6F71F34E694F46F6D9FA2F3BFB5AFD3BFF2F39F38F8FFF79F99A966F6FFF86866FC6F4EE8C2BE8ED584BD84F62F978EF341F5EE761F5181E7F75F13B355E74CFC1F15C5C1E145F51F9191C8F85A5394DC4C5F85D5FAB19DF52BA24FCE6A83F1CFCEDE95F1CF4EDCD5F9EFE4D4B3F85F5745E2E23 +:806D0000E2CFC6F66444CFE4F6D6D6EFE3F786C63F56E643F3BD3EDF6AFA282F2F23F3FFF8DF4EFE787F6F6FFF7BA83F1FFB9D8AEF68F8BF1F2FEBFBDE4E6F6CFCE6DECFEEBD82FB4C5C4FC2F7ECCE6FAB03230221808114C4488004488004190448904130814411100100410042214221008424108444820482249264400620088281F0DB +:806D80002618001E2410110C1816041301160810280184708418A2424282144D48422C61142004901420022E122843022B128422122128A901A19242802119228841F34485C0421F4152381F4132681FC1324A1FC1F24A111FC1F24A911B21AF143915AB944783AF1439342F347B34F842B54F83C4914FA2D418FA244A16F1245A9E212FAE +:806E0000A2E55DC25A9E244D5A1F49C2531F49D23AF1912CAF14F19124AF14F1812CAF14F19124AF34B911F24A915781AB944783AB9443F3429247822B944F83A4944FA2F4169940DA41561C1FC13668153C4A1D2CEF14D1C1F24A1528AF149325276426F84811512F6442C8A163D21AD8A4D558FA24D816D122DC18D2A2F48825B48F1968 +:806E8000D2A4F4812C3CB491543A1F88744A71917C4A7191FC4A1117812F74B111F448B14781AF147B34B84229F34A122E484A39322B944FA2714901208804000000008002000000000080480100400100001800000000800200000000F0FB32002841248744E094C242412E1883820387148128A02C4140142816C4444C229444424A4A65 +:806F0000853414222C642120028944A582A0872C31C81483088A219484430929018281874C6F48092753137832884A4294141E2826231411581A881694184F21028B2429A42428862CC428211C332128618B61274146D88281422598128424484181F42E482041024664812C914887458C28C4484E15F08E962430E144A8464CE415E22264 +:806F800045E48451842C11D881882303624D4A482483A2C212C3644A19B44422A22C4D43428361918364214A880383148512F888248D32C94CB12808C2A0184D182C4148B24898185AB8DD0A4F1201AB125022104C68322826C12814488544C8368228E0440285944428211A122114B61892144634222865012184244849084E1348204157 +:80700000024CE18144A64887449242604445F8AE7C00000020024228189018000080418802809428A0211852480040022400402141018304220000802802410042F0A898200122382843021662411088018081311C2142202117880248C063D028022481899424728AC182186888284826022B418081840C524082A241418A21F21FA100A6 +:807080008082824224622112001800800100842268844280842281D4280610D82844A4248200288228904825820118480098401284158425F234549018001280029044228D1430182212D068015880311280E28102124E2312002440C128182B148223C14112144822C06400A06820240222102208BF7E0F212A0140044112222A618212CF +:807100001E421E881818701209811168CC4288442184C22883A642852494224F24011A028138A024401118220414C0288C06102C048442AFCA0918008440440221232411518241100360882692288812422822000084902800008D218210110422422220416CA42001248022A1244197FC144501442800001400000026481C1404400444B3 +:807180000089022001100231B611524228252C0114841001841880110220084800BF230B65A121448441444562212C8266831458AB81164258A44D1983382815E84492148D4422148B2490282AB42854842722D0342533226561AA166C1144149187242242836181837412B83804C0884858626CF4A9CE800180020040210112A14130315C +:8072000000449022828902422220028C01304826021C28312820026220021400512012022441281008BF260F260120810100180040010014800128122822001248003024004424001180024001100148421018040048A0425FFC041228213C02382587312489013012401482222222113844002262264C2162422248833412001C31142494 +:8072800049914412190211850283141288140424369848414C069F150C1810823212001841180020420414A012106841222023922848222022263412004243010012141411008D42A0244844443018202424F6E431D089B2480213012E12150638844554447B232826022228806122272425A2131AA148164401430215559111855CA88FE7 +:8073000015A4441469B144022200455C474B222A1608810029724852622D261AF1C815240000000000168101110000800242800444221004230100000080020040010010080020022242F0759910C848422C044302802141144424820200120025825242386A29880800461141411868824848100422004441441C82420284005022D042C3 +:80738000716708A4800440010000442A810224180000108292148028028100264102AC22A44410220280041C4424A222000000484221485F720B80060000181041042A0280010000218001881100282814008C02480000000044902800000000218071380526022228000040210120110140040000420042000000002121220022000040D2 +:807400004118180140040000F026BF90228324240400005044C5B424022220011240D222642243019282824C86825111151153A887818344220400001145544443826482000060242542B614F196DF404888C44280022200107114E411B2210300008052242981A11288A8008026D2110250884CC4410000110050442868008412004012F6 +:80748000F287A8001014020018141214002100000000404104844400280024280022282110280200842494140000002084F4A7CB2001280000800180010000008004422240040000000000000000001400001008008004F099B9242821260460122021414111082581412201180022484F5202437241082E4489A2114A02A0222311420461 +:807500008002224811481184A71484105884004200445FB4092723222C022128001112181B111A11410100808204414A84A224B024028082840225622280823222228100501181508100001880044849F4AB1800002C0241808391111301A0111112184112004AA422504444281024322260222C02206222150241801241011008971424D5 +:80758000100828A0644324F4B4B4F0362225C2122B111221C0122592832F31F119111B98179987818F18F44848D09154111C548985F844688F44D444B444F22424224C02284554642E246F23D222E222B132A1812B88C0922592832F31F111119B98179987848B488F84244408488558884F84F423B4F0262265A2321A21210118259282DC +:80760000BCF1111319E989588889242444511148155889488F44D44CB444A226220028444584F326226D222AA1111A282988512229C8131F3191C19E888598484A24240448848588F67E1A000000848100000000000000000000000000000000000000000000000000009F820F0000401808000000000000000000000000000000000000F8 +:8076800000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F00004018080000000000000000000000003E +:8077000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F0000401808000000000000BD +:8077800000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F00004018083D +:8078000000000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F822B +:807880000F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F80000008481000000000000000000000000000000000000000000005D +:80790000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000BB +:80798000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F80000008481000000000000000000003B +:807A0000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000BA +:807A8000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F80000003F +:807B0000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000CA +:807B8000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F00004018080000000000000000000000000000000000000039 +:807C0000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000B8 +:807C8000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F00004018080000000000000038 +:807D0000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800B7 +:807D8000000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F97 +:807E0000000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F800000084810000000000000000000000000000000000000000000000E6 +:807E80000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F80000008481000000000000000000000000000000000036 +:807F00000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F800000084810000000000000000000000B5 +:807F80000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F80000008481000000000035 +:808000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F80000008435 +:808080008100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F0D9 +:8081000029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F00004018080000000000000000000000000000000000000000A3 +:808180000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F0000401808000000000000000000000000000033 +:808200000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F00004018080000000000000000B2 +:808280000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F0000401808000032 +:808300000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F0011 +:80838000000081848400000000000000000000000000000000000000000000000000BF46070000008100000000000000000000000000000000000000000000000000003F5A07000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000051 +:8084000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F80000008481000000000000000000000000000000000000B0 +:8084800000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F80000005088848400000000000000000000000000000000000000000000000000EF9805000040180800000000000000000000000000000000000000000000000000F029F800000084810000000000000000000000F9 +:808500000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000000854808000000000000000000000000000000000000000000000000005F530700004018080000000037 +:80858000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F800000010480800000000000000000000000000000000000000000000000000DE5800000050DE +:80860000884008000000000000000000000000000000000000000000000000F0FD74000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000001E +:808680009F820F000040180800000000000000000000000000000000000000000000000000F029F800000084001008000000000000000000000000000000000000000000000000AF8A08000040180800000000000000000000000000000000000000000000000000F029F80000008481000000000000000000000000000000000000000086 +:808700000000000000009F824F0184001445C8184538242200005440442461218B2412100213820218B18B245951488144204441C94384438204200240642484409628282C0210F641A9902114154859C2C0262602174161284D38417026C2221B212D2E1362318189E124117452D221611125C91413E18422D4213649195481814845C879 +:80878000448D4247826F2492645132D912D81472249224A342662484818344F8FB4310014008C032261C92114410048002188391112E4840A2142446D1221101112822411B420089048064446CD224C226408131288016081008216024842FDB09280024448100442C02C01810114246012125C118844024322190184C2165448485C244AB +:8088000000141014020020224211181502AD22904226184818B4990300840041450800002241402202282212200100001421141901404801848C14111808486604404404302280022400F0A7121450181411150800284120021014046C120424002480011602848181481081440111848094480041000049424414840200F087BB00002094 +:808880000200008400000000000000000000200800800100140000000000001800001F180700443524022280E14182421801211A741398A5282825488C81820221B0428202A041813A840110C8114D121049518523342813642440020098491104F05F34B0149215188C12F4542924841052221800A4459824301247944C25142118A22432 +:808900004A518243013B254C31281E421144512AC11348298204AE4829484B01434892A4584B2426D8489242281E48287FFF09411D14188752281F440140323428161801A14994181F22A8126C02C344C12222222B41842367223611A412A43A0415A42187213C654248818DC2D4A523324188212D2423C46490BC29848281B2740B2A0147 +:808980004502418C622284185022004062812D2541D081F4481480210848104204421883841591140011201112611282421508490482189028C0144183049F8F0A00902100230223022240A34129810416088002448C942800230200482820A1122800242841B04208818224488140068D24002084F495AC9026282F1182712A22D281E477 +:808A00008225018CD18204844643785439824B25444791836C83502183A212483829D2A242EC8411C62523B48191163645C819842951843AA84832488CA8844AC8489E28245AF284488385A2821F3C0749829221135282213D284638328082041819041781122E444413022A21042032221A028D22488B416114529A12521470181124D1EF +:808A800042A418200184C248E4B281214B481248C83FC349023012122822421A0260A1811127842D1283D424948812901C4E88851468B28C2281042722504828604329426141388582121832882883AC2842231C28881438246A11C84828222FFC47D281D24205A02149D2A211D442424268C481830211469824885021181A025682184289 +:808B000088382429447422042227814A018A0113CA821210220200388812288319383689A812211FCF0416C841009011C02124114308122A2821420400410021128C08282C2101221384C844608436081244108838285301C048285042004124008CE2B904007024D11C148804141816012145C24882212503360885048924229248100304 +:808B80001812D0828201100141D08402214088218448B644215424200146C444484E3224126160124D4845D1A2742154341D1298106A481A34A18D441D22C02814443884422D288344EA113836214722228A32442981B111A281415B828E2EAC8198229C82210416F244924944B688D168C114CCC41446F8A94460121301442E111E281844 +:808C0000302250188C8441180A2512842841648180844202220052184654821A0210081800008418008E48448021028022A8242217D600C0212D428C1408004601284800C08800E0820100A889420412CC944420346C4B5844417062084B123024124322028C110285044A480442400C1FD30D902100111C044118601882819902682227EC +:808C80008849318242151814724218044180A881220000812E888841D01608220026021082811104481212002F4E04409423223183D282C42284901121106E818091266388024932148C420100651A0484CC1104412E5240428E188411042812104A885148000046C814F02219C042C018119042113024CA024229A1242191304830C8A327 +:808D000012918210081282190860494800AC04281A041C148808249698C880A8144AA824884A21014B814AC2483EE2104441C628004904400491846042E01204222220C2212E12430227C28410981C1082C4252A840290289021442C12110288182B86812325B14241A814488C08CF270DA4221001418CA21490282384214891816E1280B6 +:808D800012C818130800188D1412004200208161218816180A006081430824001240084148844420F1ACD380028149E4410421200181A2408404490186024186C8C8C188211CE841240414E04801426011448888194AC821A021160240450C824810440418F0C8BB004444848514611241C41150281B4224831204645024002810A421000D +:808E0000254442480C84005042004522024140223218124352423016004508005F94024E3C9042002144226882824C2481541484C4489B24481644548280012A08AC08824009404884D414D22208A0C182C88296058B682048048A2291228229C448DFDD056E1655343A2D28AFA1F4694227524E223A23044AD8187C41588D6E612F6E72F8 +:808E8000E8A8876E884A7829E588782898AB442E3147898D488C74147CAC46984859847684544A9BB44F887884C5814CC1144722ACD82268819BC14F24E4C1E824B9D4684446D88294D48F4468857E15002F12D2E1F2214515444108F021659B8C26EA8441E2130A4D1945F28C262972168CD254847244383440B485B94EF848811249041F +:808F00004A682419C1228421293A27492A92F1281B258869313AC3D44CC4444B514B118B2483A543F019A8906424457148724451C2DB644F42714CBC887812B18B3732ED452744CD1883D1425692CF28F528314D888B236721A6D6A87314CC422546A618848F4D7174EC417314F4326A4F83F8A2468D261F26D1C8B2B1B41C7A82B4B2B165 +:808F8000A8D12A61A8CCAB18278318298AF4141486D48491483FB305122011441844081A14C4486089C048441F810448441A149841448A1488058880A82418422A011800200442124220240882200AA2200AA2811F540D5AB412F11818CB228F85754DD98AF248488F81F1C98A2F28FC2322BFF7F5CBCA21AE82EF8BFD8CA85DC92B8A7FFA +:809000003DB96412E44CFCC88887A435F14CCA2F88E8ACFC93D12E42AFCFFD48481F1DADCC1F1D79A87AA1F548481F5AFA8BC95F1BF7D8F817546AF671738F8DD1D9F5C8624F2FF71A182F61FB1A38BEB6AFABF93C784F8BE383F21A12F054625F6256B93F33579A97B4FD288F82D28CF2A9AA7FE8B823FA49CFFFFCFC22251F38FC8A8ADA +:80908000EF8AF823892672C3F167288F8CFCEAF88FACF8EEAAFD29CFA5ED8CFCC4CEFFD9FDADCBAFCA68D41FDCEC6CFCA3EFE7285778CFA6F6E5E7BFDAFEB175CFEDFE7335CFE2F22B3BAFC5D3FDD4AEF2747EAFC3F31636AF85F7F4F6EF2BF91A448F81F57278FF52036E527F7254A87D249FA7F3676DAF94F464648F87F5ED8FAF7CFCC7 +:809100006BA2BFBDFFC78E31DF36F65F59CFEEFAE3C1CF8CF8B5F17F5AF8C1C14FEAF92A688FA2F87755C5FE828CECF8C3858F3CFADEFCCFC4F6757D4F66F297D58FAA72A3F52A2CBFDEF68BACDFDDFBD8B85F72FEAAACBFB3FBDABABFF1FCCACA4FADFD7EB8AFE5FCFE987E56AB65EB914F8DF9E898DFBC0B4E725F62F23D3F5F75F36CB2 +:809180002DDFF6F64F4D4F47F75C7C5F66FECBCEBFA7FFDFDBFFCCBC61F4347E7FF7F7EECCBFBEFC7E7E7F5BF7A4859F3AFAECCEEFE2F626AEFFD5F79C1E8E82AD8AFFDDF9DCB3EFC9FB19385F57E723F3BDB7CF2951FD8FC6F6AB2DBFD8FAD9BD8FADFBA7E7AFE8FADBDBEF8DF98FC5EFAEFCE4FAEF8DFDDEDEEF8FF97456EF84F6DEDCDF +:80920000CFABFFE8D88FB60C417022415832484184404801248C44454842480628C0248002287048141618141804430221844F22084150241220416281241E484440243148124482EF1E0F220084406812844A812224110A42A034224284892118489288604120081288128C2484214182020080A1212C889288860812881A94881E48603D +:80928000818B8486F16921C0421F4152281F4132481FC1724AF2112CAB141F41B26AB911B24A7915B84A7934F84A9147832F147934D81AF934481CF9A54A8D814FA264115FA265192EDA96C5CADE24ACF591242CF591248D121F49B248F19124AB141F49B24AD141B24A9921AB9451AB9443B24A39242B9447822D914F8294984FA2F4991A +:8093000015E0A2F41164C5F211644376117C22D2C1F22E121D24AF4258C12F14D385522257824C732598225782AD14778229F8251A85F4259A83F1278AF02148442D4B1E252D4A16CC4B1E64C5A36814C4A561C9A5C12C2D15CCD21A03AF743324AF247124F8421226C8946F82B44AF124525FFF0500492408000000002800200800008041 +:809380000484000000000000002002004480020000001022F4CCA31460428144400149624219220281830425486C82C91208874A9904C0248C142C42A2418F240121521243522485C48828001621028181442184844D4840D84864814628F222E57024424204C189628184844288110025A82430842361424F120970644842C21425C2C148 +:8094000084262C4AC48444222002224136C81488F08228189293281824012F881224B98466188974FF45016B248441849C4228C22C28490281C02821456882C183C2234F827848B13804276A8D4224A6416AC51F284146D44824B144421442684281601130AC83618ACC2818247148224878D4B234E888E485F226BD302410064180410C74 +:80948000198418018C14E28204439832414C0910046041452804282E488028210222C42A082A6141882821801111421818942841818C04F0B1178001418C52241638428C1604204801004400104888210A254881042A64440000002120420890881281114200602412284F8B04228921F2E653204601218302533A14896381232122114881 +:80950000341C8C91A836B68CF182444CC42446B825A4244F85322887644D18282D44C1421CB546E118120517C162DE222C4523B691727288984C83B422919443944450485842428F3A0C2A4401A14592181183D448C218A082191108439118895A2483388A842E14425125D8184458482D2426C244813011441414609326289E1282294111 +:80958000D183A148814238182985D648091A9218425F9D021810846282246E841E241224120010144804324C61444604A688A6422E142A24E481C4441084C4424A612A4140842461241528B6A8A142304481214B8441442A54484248226EB4344D184944140945522462214658942829860423A249241781C0214241CF24818A084049D866 +:809600008201842532512661841132A3328B424542D126611882A3914869024002150A248904BFC50E8C82150200141200418012181854824F1562422484890820918AC0688084C44921960884429811425082184AE284CA28160459A82440B81442354240C81423F44397001008419B42008B212504160821188904008302100140742CFC +:809680000292800888201222411C0428C0211608904900D022344410418102308CEFB5094C821152184122E021C22825088C21344A10FA82484E147782850284444C245A4A47228C16C942894942D828914126015D981B1221882D4819F122412F26C1888531124DC1630446284374422A1288918C1758B08241140CD0C1543648184C54D9 +:8097000018282190184B4218138221D218B2825412A40081204928C4488229A8212112407468D281024C9218866C129A1448488254424121007048C442AF45032084022002141181242218448608604840C428434AC284824827914110024282621220041284832842E2881648088460950000180080F4342300150422260450842083C8F7 +:809780001111902282830B212B8224142D282881458106A13CB4412802107832128112210B100A1348112B32892289028241005240F82FB73081004160484548A82447A822188800290228408202002121800126012100100225D2848804A1880014460290221218421884004A41F2BE2F402882240448421008182C18A428501423422194 +:809800007888819148271A9C84712188D41824480820440A19044840011304130843041304008336344290128440E4AB0124100813022400180000134208212450284846232224721851424314621628182F840268198812A1288C841284D2838411011111A9042D28CC14820484145FB646419C21152442040013048C18494804105484C4 +:8098800036889145844781431C0441848C38A884C088200970882411C8862489951A002142810081414018F2284422F0ECFD00C042800884148D16C0124091218388288868188922681888811568A400188089082441001486244401114241212E8200803812202149882108BE4CC02147881014082314D26242042622012147821421C0FE +:8099000012100400124482410086420A4882411C2804800400808441024100C044121038185F970845084D411C1491844144201C6248828972114211CE21A354144C012D44342ED425C4823C31418A64228CD4140414150C4C4418A1149388183142814485E1443258290527A4812181307242DF5C0E15F4814C87624AC22443784846D581 +:8099800029D468A4113B834F18D984E882AA829E8189A89C8E88C9D38B38AC446D2815F64D428D18476513AA8E26887842E22111E418E442F896598F145481211B88A961D825D132D411D1141493285088218CB91A041E21841ECE50144358142A34A9442D486127D26B8B2CE2180315B281F1842BCF42E23A32284F51D1E2F4C4654E67CA +:809A00006F9AF2C84665C92D4F1588EC14C6492F2CF648428C76C3B4611BB18992818CF348C41B664E181F82B24BC4461D886897887A7742E883B562D28C341EB07CC1886CD4314F61222E2111555414624195B844C318AB8885321B44A5534B255A4725FB2B223E81D081F949C21CB868B7125163A798AD883F218268C98342D812546263 +:809A80004551481B8A96D2B8586ACEC3D089A124A7842485BB145D2A4F48E565C1428CC1488B5683D58D05302450141044480240088414841001114413480446146144401421044229A82414288828804681C2811AC682288880A8412C28C18213918890A812F08644E02AF226288D2A6D6187E82B4C8FA4F449495E34DAB796A999AF4B9B +:809B00005974EFC9FB28289FA2F886865F49E9C6F43B188FD4A4998FCFFE81884E68CF81D5E8FC11522E431E528F82F41436224F5AF9D4744B2687C28F42B558F73CBFAF8AF8A68D8F84F6AC2E8F8B5328AFCDFD9C1EAF8DF374368F8FFBF83ADE12EFD5F19298CF4BAB511CF41CE7F024267F42D2EDD246F64C6E6DA48F84F449485E345D +:809B80008B64AFC2B3A2FB8BA44F68F89EBEA7A22B8A45F4B434CFCEF68E1CEF56F4349D6FEEFB8E8EFFFCFB155DCFA1FC14D28FAAFA1A5ABF92F87C5C8796EFC8FBD6767F2276ABFC893C9F89FF3CBEAF8EFCCEEC2F81F7AD2CDFCFB7C9FCDBF85FE9F19B18CF4FBBF8FBFC3CCF6DF1DE9EAFADFDDEDC3AF342529F320D2E267D6495FFDC +:809C0000272587EA6F46F4484AB5B853F5D4D49E963E31AF39533BEFC1F128893F32F8A2A1DFFBFB664FFF9BD9CEB294FB645757124FD6FE3E1AAD1D9FB9F5284B2F33F72A496F69DB8AF685CF7F6BD526F68AA98F41F1785BFFF9FBCBE8DFD8F86948DDAEBFD5F1EBA8BFB5F34686AF95F1D48EAF81F138BA2FB7F79F8EAF81F17E7CBAE9 +:809C8000AD54AF5842F1A5277D24D5FE6725DFF6F626248FA454E37F47F7E4F6AFAAFB3BB9FF39F88B83FFFBF9A6893F1AE81AFAB5B5EFDEFEDFFDDFD6F6BDFFCFF6F4AD47EFF7FE7E5FEFFDF597DF1FBEFE3BFBAFB6FCF6DE3F84F687CF7F6B7527F38FAD9FD9F9F9DBFFFFF9CBEAFFF9F1FB5AFFE6F85B1CBF86F2DB9A7F74F85B5BEF44 +:809D0000E7F3FAFAEFE6FE7E7AEFE1F1D2D8EF47E52BEAB4F43F58100414000084148A2422412348424846C82490281358488210131812181308800849012541C811C08284002484141648410816482221241108DF7E08224440444204C4C522412208504A0040668144604440D484041844482829048C0C290841808114220848145028ED +:809D8000A0148033248190128C24042F39096F22F41124C5F21124C3F41124A3D4C1B64AD141B24A9921AB9451AB944783AF1439242F147924D852F924484E954FA2E454F8244A16F5244AD6E5A2645DACE44DC2CA1F49C2421F4952281F49324A1F49364A1F48B24AD941B64A9921AB9453B14AB934B44A3934AB944782A9F93448984F21 +:809E0000A27497066D491B41E3F21168E7361F81522A1FC1A2161D2C2F44D9C1B2427B15F84AB15781AB145393121F82F4421436F842B51FA2E544EBA2EC55F2258AD6E4A26D554D594E216DDADE28B41F41D628F41124E3E489D61EA1616F34F81168AD941F4196BA1B41AF64AB43AD964B43A9A942AD942F81D442EB82F5F52520228824 +:809E80000400840000000000000000000000008814008400180000000080020000200825018FE80D22260194A149422231142283180AA4709468811391C3D34124C484C14CC24590212248482116E882014D8118244110A142221F42042342111228C11242100C304840F84BA300436882308184158CC6884728144078815485269245500F +:809F0000842632C18D24288A12C2228C11D4861894888B42212412482F483214884140388A102C2D1208484972141288210D41144847DF80625E2658A19C184488411C542481264858818D161E4514AB48BCF384438F423424369C244F18548247128CC84446D22916B8183218112F468951424041D882B84552244B3C26638281184C2261 +:809F800001168C41C248148B413F43010000C028458386A928AD8100535842A281125441008886022212244C028308122490C41024180462284008002024714246088A044100CFF607008280080088000000000000000000000000000000000000000010010011400170E705211E221D1885148442218652A243C24119016D82C44A05BE56 +:80A000008218A5E58188A24C144554212E29811A1431C2C016C9B4620A118F4151848A4A230625F82421198441F44E8A4818E02B88514A1E8828828FD10723628411859414A834622952814712488E128C28B41A9414E01A58212584F8183843C8454217221E298911A1882914C8184E242F220C11E042BD4C6218506684183E619F284874 +:80A0800028B412148421026C2981D284F44ECE00200880088008000000000000000000000000000000000000000011001001140097725024002863020014122A41082084C4124041180A00004484424001800D48001224200487243048804988891462888843220400CDB13043264544D481D42861D4118F4134C129A8419601DC98A325C6 +:80A1000078D8A4483245D194936883E4444288213129493168A82E1A41291814223385141064C314E0286282231451228931581098428448562CF668FF244642014932228C314A1149E538A118848830C9394CAA811C0C31431188946400811D2849410916684C90448091840046648224608C84D8842999488C1118784284044E14226FFF +:80A18000F60B54491204D3041504158824A2411C01412229914C6083C493A2428410C814184220A68228272182248032111502301499042C8212424122914282882284428448EF1A0C85225486441A042046280215423C220000821883028E142A21C88148128420420948880058411021C8161426440228E1C1F04214428460888028F46D +:80A200007AE780F24428101212085422248426E841D214048651842C84043F2108221C01883220381413E15114A218A5A2482C924C21A0184021081948E34122883122004C120481502A4F5805232401003410821424210120A11248182C614280088D421054214825010018100480A8121628624100804348981100809142244860424463 +:80A28000EFBB0C23362285148655389023891684E1A211784681C1A120A1C14C739A019AE2849282511B25482368411E218391125849384222CC381683C111406418E0284218FA118885642256E42441487482088E24C5F2848E0016140221004C0428A11118001287444825022882251401002951180049042C0888901228A02849391135 +:80A30000214CC21115C412412C01004E242044188274A30D4111405418110010010000A81244228C02894498848D814C4101608242488302001564811901508260448116044D128481A91248288404819042BF610D221280428204444D222094421840082A24020070220120824422222C01008604008212314242230800311002238832D3 +:80A3800082844E198848F06F7B0041141C35818902204124021004880016416481008313628481840043444814082200C14828100847888CD8491208001002002121817307248004604421902682232916420245022460241410081810A24812212541424112512212103288003088190100290249080000888812BFD70B8E241528721101 +:80A40000A4121D14001A048422184141418688A821B08442942121452884860610A12483548122308110A12481006548848112448601224508C088405812ADE3800141218504444901108131A4283A8811A412811B12902944112D42100425381120418105204109162165A6200214441C1848021280B848028042F4CFA400288C042032D0 +:80A48000282184200480130229145442400240082C82088A642480E8110200242428842302221220020082834208480068004FDD080080240643810214190200288001478411C511011564324185041A1489810228002814811440C288901145D11808206228A6A28200001881DF460C42444C2442042800414044AA28450245222C582CF9 +:80A500002A219482224941885882242288279827181440084812214CB4121204228342148A42084082014058821A72BC054F42E21851415C52E18F511444F418144D848F2AA2628723246F22F384862F217C24B222582865794888F88C3E43586AE3F6CA421AD1283243A722CD2812345035855A9BA7814AD2A851284849C224854A12DEF6 +:80A58000A261422BA8C1C2811E888894C3D1780D1A144EB224B57832644C92224726A04580D944C18C284B344CB21563921D141CD4B542D11B92541D4CA0284E414B59482A54188828281981F2C122346829F28C381E1155E818D2874818D82252A827A88846283422622D18FFF20AD041922C1355141D228B124D12281553114E1241823E +:80A600008051488A7D48FC45348F233A25833221ECE4860226F8424A3F8348F1D1A823F9214869022B19144B911CF53A4423E6C8D442D8C9F8B8111372184582FA88882AA12229A542818F88F4881262EFCA073024108414042112671282211220C12492A049441381124134810028989091400224A0120000A082601282144002002800A3 +:80A68000B048028B243FFA056E641F1252B96D448FA2F61D1DAFA1F22222AFC5F58787EFB848F2989C6F21F992B26D26AFA9F722622F25FFAA82EFA5F52C2CCFC8F8A8A4AFAAFA6A6AAF82D68AF83818AEE38FB9F1CAEAAF8CFE587A2F2252465F78781AF13B63BF97F67C3E8785E5FC9C1C5D1C9D32BF389A8AE5E68969A23AE12AFA5C61 +:80A700009C8F8A4A88AC95EF47F24A1EF064645FD2F62D2B7D45CFA4F61D3DAF83A222CFC4F682A7BFFCE824F4A8AC6D862F28D866F28A6E2F22D6A2F2AFAEFF7454CF1F98F8A7B45FDEEEAEFE4A48AFA4FC2848AEE285FB6A6BAF8DBF18F328284F62F2C7CD9791BF3BFEFBE94F65F17A2AE5FE3E345F4AFB98BEBF28D8AA5A6EAFA97BAA +:80A780002ABA1AF3A8AACFC5F9E8E885D88AFC78B8E7C41FDD036E645F5256E875F5787F5F57F71B292AF25C7A5D25B7C62B66AFA9FB1692EF89F92E2EEFAFB722FA5AD2EF5AFA5C59EFD6F68C854F52FB6CCBAFA6FE2A62AF86F4BA188FBEFEBA3B2F1AFEE8EAAF85E782021F397D1BF3ABA33F1EFE3636AF85F2CE6CCFC9F9A5BC9F6848 +:80A80000FB9BB18FA15BEE2F89E922F238388F8AFAFCFCBAEB81F52A685E58CFC6F7583FF064445F52F22D2F7F57F35C7FDFD1F33B2B2F43F35C7E5BA8BF9EBA72F79EBA6D86EFC9F9BEBEEFEFBF36FB7AFAFFCBFB5D5DFFC6F4A98B5FC2FA65CDCFA6FE6A6AAFAEB4F2F5F1F2BFBFB7B2EF2FBF1AE3A2F22222BF1B7F19FBFBBBBF8EFEC0 +:80A880007476AFA7F2CC668FCBF3A5BD8FB8FA9BB89F9159EE8FABB92AB218F9A8AACFCFAFBB8F81F5A8E88FAFFF6C6CAB4C00400100410000000000000000828F4412E2440281B04802420000144001C0484048220800844008008281F0F1B2308410044712601290141188C01240245162438271115842154854814C028125229411F0A9 +:80A9000022188304001224842CC1488D12009644414803242224A02484811048B16A0C4D421F41D22EF11124C7241FC1724AF21124EF24F19124AF34B911B24A19B54A3934AF543B352F147935D852F925481CF9A54A5CF8254A16F1244A96F1255A96D5A4E549D2A6F491242DC31F49D22EF1912483F49124A7141F48B24AF18164AF1451 +:80A980009921AF3419B54A3924AF4439242BB44782A9F924488B944FA2F4FAC4508419B62CF111484D121D288D121D2CC72217C98F6251C18B245789AB3484ADA5478A2968882F447286D842E3AA45F424DA16D1A4CC212E4A86C14B9AF222DA16D8A2B481F42AC21B218B8413394A13B14AD141F46A141B212BB41789ABB443F34A1212B5 +:80AA00004A71B4983A6B418B944D1257BC400800000000008002000000100200000000004008000000220000000000121008F02473144941941736C8244114871241830884488B94524126184BC48421424C1845AD4255D84A0415084124184492221A085C2144311481B66811521C185448AD26124A414408905826F8B3E7244AB28101ED +:80AA80002112154824F441222287286283110589511428B611BA54B2242881944220856221229746255884C1C04618C44CB12874311492C1184661821C8204214A318888298292148C4C9144FF6B4CC244472416F112281E24454114796164824D88266881479D4AD384712D8232112CE823644412635116E247348D2416722871215A85FC +:80AB000045D84811C8C26A514818CF11747411739411E896D985E111B2A144562CCB1623A114418942061E4847214F9D0A2A311141008414682482244842000015C8A6454824CA841934483018480046041042941480492402808401224800008928982280E188042E484F91092D1250228001221224B0689121188410411211021822288A +:80AB800000415022408852249249012A010081842440425C2811424042086064122840044FF50F193214448F41D242D2C211158531242D812542019CC13283C1782E482FBAC4415C416C162F486212E9942889312483B412C22A2C861E96224D23C952272E124923823111221A688833718441D248C22C284E2516A4A5124F82F88F291036 +:80AC0000711206AF21A2218911116121228A5312404848417852A1426213742441C4214414848400E0616283412D229022144154A31232222C51580083D812C18125423C284F24924141F26048DB2C3032401414544249C21410744368221901168193128C52A21788232191282CA4286C62442D228371247868022CA8168AB4140247225C +:80AC8000872281181E24001889D21229044484284160432A014961828B3C7048245541444C188814141204524C924858A121850224131454488D12248C9491160410C245A4005084425048418324022602422829012C6881362C01484149057FE34F422814482203008354221B18312F41F616829011C01482C012488031241188106485F1 +:80AD00004361122B42CC91914C64828314248401202884D218E2429884902A8830A4001210F26F57A0214124118E4222278129118101400881D08404452305842222484044622300C0848223542112182810E8421152124400108134144C5422814D2ACCC228A0824FC441C2544464344F2432282F8114141334813B1425DAA4C158918950 +:80AD8000544882421481818125C2491671146243561826944425BC43685412838122D448A14322232814A242D0168194ACE42E1A83CA2E26982C122A78D201221285418401241287241229014AA148241225245172122B1449D44222E244024400211247228B289812244C0244C1502C40C12422158C284822B14219C4146044122744F09A +:80AE00006D33243081B02291298012010042483042204483024028141A831111D1480222100840B228019E21C220133881278241244447249681088800008691D26F2D065883B1184475144274461882614810029238618423485982AC0644C0262081424242A4412E8446094902240088884E242F82119148A984094485C428428002280F +:80AE80001648586800C20042271211804431538121008412002001140012217012C5181884214004104A04188504502C2A4804122619484424481444C445F07F6A241602418100284914068162804608250430842318849E8483946C904CC0840016898262845988048420969144429013891441829AD2008042782842F4D3BD4042084AE7 +:80AF00000228841420030024220020110C00178114134431448C214221048582128422924C2140189822244490442143C422488A0200238221F8752F4028217115321414418412518480018C44844429044121842118218344012012465141922210081448426011614004001800008812D084F56F21604641A120868484922124482AD882 +:80AF800024C424412DA2506241214813448464482816D4228812424CC98182801484042A34A8824288004283E18C928230A883E48C11394881003F8C0B4486022502C21420120210241424810111484415189881502141A1110045229222400230492D211840112CA23426026908444100824C424401AF7E0884224C149888643044150442 +:80B000001941042800C140440244271144294184280247A4812948B5441844C88268295284C314941400C014D081522818124518992481426322F2179FB044A54985F274324AF142A1F7449F14E221B684724A0843A444874785F648189127444D488F4114E83224D91262249CE19E321887224CD1E1B186A28A4C121444D8D2CAA84CF86D +:80B0800028788F52D8A8F84E284E287082D6F8F878828D92CBC24B828F18685A4DA8784515B861022F41F28A2A4C51816F187621E2324276218561318F248A3582453212672125D32D82F88222D4D354C84DC82F4237162119F312486F121208ED44414E662F32D2283264F3B6C8D344E885942626552227B5CD48CA54C16F819232448CE8 +:80B1000011C444C5E89BE687F952BA24245C7116585A87E34D448C944449517119A5424447212D684B824C34841C516A4394478E1C7DC315761DD161D46D74267F8454A86BC48FC2F9412BB2228E9C23D229C5411E48C25D121F5B41F2A454785A91176718A664CD8F8C24C428872226D428F186442FC50A100421008426022A48C882C0F1 +:80B1800084842C68826C382124A242132234821002318A820141200221D0120822501448806422400180440485214124A1247E2C2456F27331F7D16F63F7781BFFB6F24A4A37247F53F124A51F38FC82822BDF4AE928FB8696CFEEFF62E22F27F9A2822BA8CF46F21C5CC7FAFFF8F24F4F7F75F56A692F2FFF8E8E77F96F27FEE6E66F6C4E +:80B20000F69EB42E22EEAAAD2AAFAAFEAE8CFE844F6DF6C6A48FEBF92A288F83F32A2A2B117FA1F95BD8C59C94CF42F214954F4FFF1C98CFC6A413CF55F437652447643F75F51F1FEFE2F37A7FFFF2D233F262226F41F114959ED6AFA4F412344F44F984B2CD1E6F66F764E37F77F9A6866BA8EF52F23D3DDFFAF1C7657F54FC5757EFF6E3 +:80B28000FE6762A5FA932FEFF7FEE6E26F6CFE96BC2AF2A2EAAF82F2ABEB7F4EE84FF8BCAEBFDFFBB5B64FE2F2181E8FA1F1323A65FFCAE84FC8F85ED8CF4EFA159C8F9FFF1C9CE5EC86B6CEFD29D9244F65F13276AF23F332322F67F16B2CAFA4F671335F77F5E765AFE34FE225F7D616EFA5FD2626EFE5F58723EFED53E463F26F6CDFC3 +:80B30000C3F7A5D77F54F647C65F77F736376F97F72E2E7FDFF55ADD6F6AFAC6E26FC9E926F6A2E68FAAFAA62FE75E8F4FFBACAEEF6EF2AB3DCFCAEAEFFBA2A8AF2CDBA7F84FCCCF82F36CD88B664FC1F9ECEC49FAE2ECBADBCCE392437256F61256EF43F33A365E549FC2D2ABF2783E7E523F5EF63AFA8FACBC14F1D416EFA7FDAAAEEFB8 +:80B38000E5F58E2BFFFDF3868E6BCECF94F45D5D9F7AFCCFEFFF94F43D3FEFFBF35F7BAFABFBF77FEFC5FDAAA66F6CFE96B46E66AF4AB8AAFAE527DFCAF2F8BC8FEAFAEFBFFFEEFFE6EE2FADFBE2BA8FAC5FF7FF4EFCB6B4EFC7BFE8FA149CCFCEDECCF8B49C4FAFFDAC8D9DD190129016844B125014501400400280C4244881828D24C046 +:80B40000241189125148118D244901224261422290848440B8246881434248628124845416C8244820180889021EBB002002A503244418D0120121A0141229312121482111004614223122D022014B527022485424702C024F1468414244A503830442800121490414444180F4BB8FC0421F4152281F41324A1F41764AD2C1B64AD141F2C6 +:80B480004A921D68AB9459F44A924782AF347925F84293478B2D915F8AC4914FA2C4816FA264117FA264192FA264594D5A9E242E5A1F49C2421F49D23AF19124AF14F99124E3F48124AF14D141F24A9319F64A9153F84A9143BA4AB9A4F44294478229F934484E944FAAD4A30A26BA11D62CF41124811F4116DA41B44CF18144AF42B9815E +:80B50000D648BA81B44A3BA48F1429EA1478A44871A658184B1A144F82ED117A2428C9CA8F49C2CB4CE2A25CC1ACFC8164811D648B841F49324A1992988E24AF4429B84A3B84A933A4A9618A2933342B842F8A8479B4FA36E360888248000000004400000080040000000000001840080000000000000048000040018F7407441341711A39 +:80B5800005124CA242478189E211568224194184522111150C3217828C8124468441381A63314248701422522424C503316E86862752382800884260C426881142744254844C39442FEC4D22748422011508C88448218C58214890422531422044481904A441244D4A00844B1283A24188152624024B12281110054B18312283145482243F +:80B60000CA2142984119018D41287FEA022564F816C15D1130248445085B213538621721463422195412DC1478217228417818A24286F644188485C21846B44182D52498292D444E22158E92212EC127483952812DA645018B82431442B84289116824455248C71962FF5F0B4812241028218CE624C1288B844002101102008911848144FF +:80B680000450221245A22184804144026041214414442001284210984489221252141B142014D4FA0500800228100110020000002184100400002440024004000000860400008008000021411004484F63098002250415022481C018C0189018285681822C6219481241D0A48621820118A01221121243012902112120018A0481808182C3 +:80B70000442451286084437824F88F330040C224C021211121100A00001981B2424818210444209612301220014B2100184C418202172800004A080020224482518450844CC8486FC20820020000400812608160812848002292441200C18002100210220100004100180030888001400424800426F49E46000044418CC24144800400135E +:80B780000800118810210400212820810141818200000080088800004004200112108402CFA8021460313012000000424002C44121008100800446422882022012642460222864441200000080088C08E0883448A0818481CF880300100825811108001800309200200110080084004821382112200244818002000088000000414449063F +:80B8000042F0D6551001508627419C6215850448800186012F480111821885810400214608324A134222822904205268800180088008884184004DC887444C1404E0E50C001C01240000004800218464000010084280528200B02411180423821206412888000000008220011228928B24841FFC0D0000000000000000000000000000006C +:80B880000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F8004000000400428000000002180018800004001400848000000004480020000001002183F5F0B0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000058 +:80B900000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000069 +:80B9800000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000E9 +:80BA0000000000000000000000000000000000000000000000000000000000FFE40F00800100000000000000000000000000000000400181000000000000008200F0B5C800004004100880024008890100C0481243042284002001402282043011000080020000004412204408001FE30F290280024216043082800C82100282268E150422 +:80BA8000403144118410048C220200230244221881111800348904000084450800847024020080420441812480820884301A00008C24314460420040040024222C840212201118812102304800004412414008009F6D0D230200808401200848200800828D261A44041021548181001889220200004581020000400300004018880410089D +:80BB00002F670B108141180200002160140011290880541884106144A490412002008002444014088D1113112208110000201202008304DF340665C224A51204284184411A8831D881834864C8514E2985D42838145199111448911C4146187C41C8228332844C48C5217494302141C0898715608B181D1A49CC16B04451488146242152FA +:80BB800048AF170141105824804244088602828008131821048297414481444100C0484C22241262484C12C521514548186151136118142001348664214012044418818574E704213D2423110A00408481315887148141E449D881123C4821941C41C1489467815C04818501260888400431804208A18B58F08128188C8114044B52818486 +:80BC000042A042E0CC0A125234006415260114404A548416881268411440382420684949288283514818460150411845C84812282A010041121D92648904281A24018824429289F8D4C3406A444009000041426062861184240800649018A04188318002244581C288100848602482004641084024B24801008A011042046783341906F01E +:80BC80002412A411811424800181008081229118404814048424434408116044209662804801417024020020880816181208384048081FA70933D64201354A1A143A1350144A5128A4591828C418360400265C4849684C44146B1281811C3142288147344A41840824430341001234608C83A4215283818908818668A87FE7051840E141CF +:80BD000002114501240000844C2182081C618185041800A428481A12044146848822028113212608282714C420C98228188421003280C414F05C9DC04628242880028C010084008362822046280A26044DC880111134181004896182008C1148941CE02401220014A5A44818800142188B818C149848BFBF0C2200142246981C549C7198F6 +:80BD8000A5812B21C02114128018446A185843011528021EA82829C2524A18D412D441895442207443C22141367442221818E22412482804968A614C424120F8EC35144004100480C2244008400441408419440400304820141C8814088014040060242608188142003823861882282204181244CF2B0A148041447818C412002A09854491 +:80BE0000186812149C424201001B24288A96149892002541511244008032332841444038212120082034C841821822828A22F815133082154414084C1488052D44A04228497488D484449141414840488448841204E0210422100180022A881802212829451802218C082181189084407A1471CA0648904A0090242200841088025048827C +:80BE800085220846841851181D484820618815C88C8118111C08180017828531484A18A114A01400102804104804F013C44084C4212412271150941518281301190900830130129812418221893A2222413E82F09241212C894501AC7118044800289088888A42420829110421800C1F3F0624A451A354820080018848888120048188CC2E +:80BF0000C48480C44841D0C1248428488444C4484C44441448048744201E8801CA01184A51844945044490181821AEBEC01180444404804484064445C26245421354343C026882211C825314888514D4144218C4414911D28199122A14A342181352484018410C2820284AE248046C210884DF9845E14475C43417253E1E71897223953470 +:80BF800067118E2A2E28248D418F42C241E5DDCCF1128BCB488A78449481815D814B2746B298FB1C182EC27F76D4266CC14F24A1C44F25B4122252186F24F7594583249B68BE292CF498C28AC1486A9D464ED887482B11484B8C47498F3858C25F870B43722142B32C44E483D144C11895F928C88B819B41811125C92411195A482C9A350B +:80C000009EA86E541F54E2E8D291E41265442E2445DC8861542F28544847311D1184843E1287CB67A21D45AD66C6B243714858824E482D1284878C2368844A6C49188F84A94283EC5845523125D8484261828F446481CB6516E44C8321E4C2F8449C5D82D78522CE435B2827C427445843F1A4C88B428D14D5FC244882BB29928F88B24CEA +:80C08000F133491F48E148D845F118227F484681F2243A47843658281C41C1A69A38182CF818246F2179A4B444713A0E1E184B81CF7C031A021A12843246304630463042E04421E84421EA44312118222008244654218008882880428102800829012190823022102218220222A042A042812F560C7E431AE3E1F128288F23F53F572F4540 +:80C10000F4652FBFB1D4EEBD5E7D53F18AD6CF68FC52536FDFFA82D32B42DFA5F338FA8F82A81D7AF32163FF16563867312FA1B228F26A64AF61F5226AABBBAF41F3B9B63B2315D722F225671F32F231239F14F2E6BEAF28FB31B39F97FF7AF2AFEBF8C89A8B144F26FAEAC2AFAFBFE6EB27FBD6148F8EFAB4BC4F6EE65A45F17146AFE4BC +:80C18000F6272E6FC3736EF83D5DCF25F56F2FF794CFCAEF477F53F1EAB6CF61F55A56EFCFFAE3BFEFDBF51C7F8FABFF288A2BBF5AF127377FA6F64EDC5F46F264EE4FC3F3EAEEAFE3D7F6F89E962F65F3BEBF2BFB1FB4F42A2AFFF3F7DBB93F73F26B22CF8EBB2AF37BEBFFF7BFF8FFBAACAFACF94A32EF8EFAE8CAEFE9B9C6ED23FBF67D +:80C2000038CE88CFEDFDFAEAAE65F044734D462E2EDFD2F2193DDF55F3541E3FD1F539355F56FAD99F1FB3E628FBDC9E6FADD9D7F52F236F6DF9FF9A8EEA8F89BFD2A57BDFDCFBA9ABEFD2FA14414F63F6A828AFEFF73BF2AFB1FD9AC62F47F451FE7F65FD3777EFE3F3A7A75FC6F667699FB3F6A4BCABFE3F1BF3D156DAB9DABECAF91885 +:80C2800092EF8EF898BAAFA8F886844D166F4AFE86944FCDFDAC9E7F8A47F34772ED467FE1F1171DFD2FFF55F33C7CDFB3F71E1F7F5FFBB9FB9FB3F684B24764EFE8FC2F7DF5FFCF8FFFFAFC8CEAAF89BFF6EE29FD6DAF3F9AFA7C6D5FF7F3F67A4F8BF3FAFEFFEBF7FEFEAF6DFC62463FBDFB5756FF32F63E3EFFFFFAFFFEDFF2F6796D81 +:80C30000EFCEFB68729FBFF6D95CAF8DF9DCE28F2CB9E8FCEC8AAF8DFF9C9E6F4FF77476EF897C8CFCBCAECFEEFDDBBD100425415824E022012623490240081548042008128314A1242144218D24318B246B128163024B929014842941581484881A44E181041A0496C824484CA2494C221128F89BD2202811241144182C1144A882840060 +:80C380005C185158518160444044D84828625584B02141842804421430241584C844A0682A180180490849D4280198102892884712C77CE032F41124C7221F41326E1F41324E1D24EB141D24AB941B21AB9453F14A9443F34AB553F342B557832DB15F82C4B14FA2E414F8254A16F5244A96E1A26459ACE449C24A1F49C2431F4952281FD7 +:80C40000497248F29124A7241F49F24A121D2CAF249921AF3419F54A9243B24A39242B9447822B944F82B448F9244A7502BCD541941C48ED1112E5F11124E582D278E949D23833118D36128D97126C7114989869D412F1245A1CE1A268514FA26C152E4A16E5B244E4827D91FC22489E44A5F2116487261748AF24F19124A724CCF24A16F7 +:80C480004CF24AB251AF241BB44A1BF442B245885B86ADB44D125F7D0F8480040000000080020000001002188008000041008488000000004004280000000021F03CD224400495041E4441644CB592469848188A4424A14158150440094784190800448303484E8C8426022081A8818E12621220981823318810181814A841288152C12CBB +:80C50000F855BA20318341901E911FA28133291480014483E4C8441424C81C62C0240021224531481164446041202588E24144088C41A2C2122998481AB48821E441A4349A242201856412F07DD7142D1257844485361856C43469D141F28221450830444F84B28481B544C181496124949048248A2142849418443354488130524628A2D3 +:80C5800081830926C8128AC682C97112E84A351842C14483A521403814478229D85A0B00101154818581B24AA141E0818421088C4404448428C024411C08105148130241C249810282184420B94201208188142818A8414A232824038C04F0A14100100C411100419082848840844414411101004146342444137248850824824084081407 +:80C60000281811102102A0412001400229A148201208BF130F25042A31111C042D458B128F3144091391422398C11419E424C1688D14174226B4C9611284D018049011578489C1485248296112B8541942C8318344E212F488221415588625A248848B3483321428414449FAF1F4100281204422049F644109184622B84568145364344230 +:80C680005D182611C488224528D28494218114942CB1482805181922922438113213041982181158C22442F0224A818E1410446C485F660941E0423111454151413608248815988200001217824084E2141125444401174492431408D02424081E8114148414812C82942823456121201828A11242282220E2DA042D4810880422007042FB +:80C70000140244A51284D884F442228A1162A2415D58814914E42802241046014249244408481612A868416022D084118818882182C1841216BA484848F464BE148444D012840418411D28141608C42A15D8828201198443230400308543223A4414762112D881D2421212A442460418004A28189422121228C4238401864604F04B54204F +:80C7800062221514941241156881005081C084190100818100E04402814242400800410032811181184126D81A0400120088524480082004CD2600282415A614C018811153144201CE1643B182C24CF081582B21178243B419D44806441B2443224A428502CC7441842252842671484448846214248812A321C118A262189890884E8C4024 +:80C80000B6CA0F2B4244E501C0241416742802894158288C5218842CA142218400446044844429046D48808502286D4212002C21A196C4A18A0684A02820D168914444924C0183043FDC094140551424104224113211A4181427414312981247111831202844AA422C116C8490494A1168212001004E112551288054181414C18C8C840288 +:80C880002A946840988882D0240B0084A121001C413181C3228812041110044142848484148400905C40285185682A141184312820010018E026181128248CA18142183828F025243014100400404228112257488912081B8181852241827C5851620014181816824112281481810180210186129814200881281800C0288400814FC70EA7 +:80C90000315B14A024B1280060441009822810420113081681024845628222142A4848012248880000422744518018420440148801004C2825C1228FD7028A62431100902843E4451225040023B14881081410041C081018044904521248244012488211410148830152148400880080080025F1452D4008324004411200110012008129A7 +:80C98000420415084114114870440340811412182102114078125221844D429304302148822212622881908828389F7D0B40C24A816042800280B3223812284E8411411200D80084C1008908135422850411125411282018AC122012143122A028460226028B4816022281F09459800100002744006A112211981240884114425486C38408 +:80CA00007141C244472249B1213814008021440212004248942C444402821EC10081C880012A0998248E3D4019A141439221009024502815045912B8641805982880181284032E8818110029488108178490511C0881431444222C6844803218822604442024544A84BFA74B039E239D182362222E22238451249E432F4462A96D128D1208 +:80CA8000848F2452A1816B11242D51F088484D424D242F64F62B14B967144F24D49AF45218811D482F16541385011A1159C84E722D462CC4195AA148CCA4489052DA092A812EDC8851D82AF2DDBB30154D442C72445CC30045C32D574415FA222189721474427481D854F82611116B83C3F4C6414B82D484835284AE87C11E111285E5818D +:80CB0000D51C3911AE329011822CC45215394CCD38BF485813F0A9A18F84A8D48F8AA2422B655ECC85B814A86DB662213F87095C931147518D231444CD245E247A81F338119B9416D811B83CF924558B1916C48D5CD1C1D888F9111393F44B4145A82147811F41B588F241122C1CE224025E441B114D2311FE193715E7411C7842F444429D +:80CB8000883DA14E1214C782884C22B28882D18AA382B885B87D4A02400800702481B42488446288448A04840081A24222441146044411861462482186641244144C82C824800228349A0210328429B214143294A1413014F0A8E1242B221F36F22B23BD4E55F42626AF84F4212117523DC37D922F22FA2B9D75F747414F44DC88F8A7A384 +:80CC0000A5F82C2A7FB5F4A5ADCF4A7A2EFE462BA67A32EA24BC9BF88CC27FB8E8ACF416866D8AFD52AE826F51F224227BEA8B24FF52F663276F46F2121E5FEAF2327237189FBF59EC8BFD8F62FA92966F68FCD6C8CFE2F23674CF47FFB498E7422FCF064F63B352F41C12BFF252136F62F24A4C5F55F531117F73D9EAF97A7A3F12F3972D +:80CC800093FFD1D38CF814923F7ADB73F1A2B63F91F5C78D9F1DFD34172D27CD9A67E3CFF5FD1A15CF25F5979B6FFDF416866FA6FEB7BA5F65F6776C55D217D598F73775FFF5714CFC7E3E7FE6F222651F38F8FBFFC7E4CF65F5AAA62F4CF8E4E4CF8FEEAAFAB2F8EF4EFEBCA8AF83F3B8F9143E244F63F63A33FFF2D277D266F24E485B0E +:80CD0000331F6676C7F7DA7E9F32FA1BBB65F6DBDD8BF78F88F8B7A33F315126EF8FFE179D5D85DFA6D577F226862F23F16E6BF7958FE1F58212EDD58F25F5AA363FA2F7E6C73F11F611163B994F47F45161E57D44F47C7E7FE4FC93D63F1ABAD99BC2CF6DB9E2BA94BD24F7F896AF8EA846EF8FFFB8BC8FA2F16241243F63F316444F23E4 +:80CD8000F32F2F3D236D26AFC4F465741F26F7E766AFADF5EBE3BFB9FB8A9EFFDEFD7CB4CFF9F9BFAFFFF1F18F9FFF1BFB55D51F1FFF685FED2FEFA3F23616EFFEF65A1D9FFDFDD35BAF81FC5C5EAFEEF7B3B23F35F63F641F63F3D391CFFFFC5B69FFD2F64C4CCFE5F5B7BE3F19FDA1A3FF9DFF46C48F85E9AFFBD6F26B768FEFBB7AF1D2 +:80CE0000F4DCCF8EEFEBFB2832D7F810041C012302A041204122011648210812441351489242001098114C123148188314021C0114C01150144800204801400812801408005FE70E47181054812641140445112146D818588489389585518130819044145538484189028384411102182848122068341618082344FC421148428442A034D9 +:80CE800012892A8309382679EF072CF4112485F2112C83F4112CE7241D24EF14D1C1F24A9219B24A5985AF643924AF147924F8429147822F14F924481CF9254A4E855FA264515FA264592E4A9E252D4A9E242FA2F491243CF4912485F3912483F49124A3F48124AF34F91124AF149921AB9451AF143934ABB44B4BAB94478229F9344898F5 +:80CF00004FA2F45439F0224A1F417422F2114CC7241F81726E42F86C131D4CAF64D941E2245385AF6411E4347B84F84A3343F242112F82D452F9245A4E956FA268456F827C98D486E459D296E449D2A67491DC86E449964E1F41324E1F49324A1F41F24E929AF248861F41F24AB243F94A2643D16AB8B4F44A8643F242946F8BD442F8248F +:80CF80005AAFAD0A000028000000180000000000001800000000002608001004000044008400000000F07616604100702244FA1528209481A962811CC4486B48A22A041C1188222464246044CD220050626292638423855128100A11842301A8421588148104B0280836044901FEA18072A45148004B429058224382018CC19483D184B1C9 +:80D000008C61C14312C45447912295C4418332414662428984C694301820581243E111A238808562828E421A94884A389160291AA821E028812C6E14CCF2C8F56041461548C22483F211241848471A6781837168D128945C4CB86818D814117864D21C05876514478ED12C048C34621D44301A8B121E4246417812628230418CE28142323E +:80D080007489F468811311813482188C4AE262A824128F41F26CBB20821204C044A18C2402228031948836C81443811284014A1221044A12C22440B422299944802891141982091810A2488882A04820892102924A216844F05946200218901C4422151414411261140012888028D118130400240044200144221004207124410820E481A6 +:80D10000021B41814003242AD44822039246046F8B0716062555A480324422562825233118C9C184895449D15B4294A024481C72440A1E4916C41276714188518216A812882352C28A82D126624963062B481314223483E08184921C82428B92488648F86FEE400431818564424916654142221C31484182811C18DD144C391828601245D0 +:80D1800058224649440484188082022125845861830200C81934128C3482305A7012B8288895284882F091A8A0122143512412002883C4112C011C9118411A54488082611246840442808121F132414E112485C41818498842282343E641D842867432081C04141480B2444224822969C484EBAA40A8124084443452413A44C198246483C6 +:80D200008244814431824E2C1224388A81C48890248480084C0120250148008C4822248466846CA41284484B8400448F41C8682A14F81A2450822195A443818414A30281118D214CB124096112840045C248414A4192842A05A2463C228311A11A1C2362E2F022489014103189448C014CB88884F42482106118D0220412281D93E01211E4 +:80D280000430121C1228416841281894141228E041220222400989824234481230144362824442008420052880023011001216889211A50100C444CF7B0D382F4211C83423C4252795C98344A9388D31A571162184A2418B2182842E147024098722812A352C26688423DA84F224182A91213A841228024391A8113B2C4CA46184B08AB12C +:80D3000048A1D22BC22C414874DAA4242E58C1EF6F0A25014501894148028B121654188061882C11055129B224048C84A14842434284241964411890845260412542A814001008811B414A8A044548048800844422AF980E4114459848C1224931285B123218001004C541F81441841C110180064219644140041840440291830444241693 +:80D380002442042315C8481044B81804412004445F83074A02114022440185328185A124184C3428150A2830254542286282418C2441088484448D444200114054222C041018B122010023140822412418845882FFE50EC024494104448118448420240432C1444461101424150410244828218181420800A04318388181A02881225012E3 +:80D400008CB2C2216181420018006FFB0100C0214C72182131442846144414288424A21200800421488C7122C4C84C021DC4842842448981288114E344084664221E448128215210D1282214961290448012F842F4A02800001422841004200241415084C048218534241E488081021088048C01000084222848233418181068C3000048BF +:80D480004082288814B8C14F429428D0480212001041490812800128811038622125841185C8480018C0211800134199148C542A1838302131184219032064488501120049F43415C04900141301109211202192D2288034121C214B8408A1B044418888010000811812C0521082B1880228004C0489220100E0830481C082BF13094041C8 +:80D5000008897224C82813022800C180A1128230482800183902A2181A084644B42815464424813214224C416442466C644C042A4822189854412258491484A481F09756C019442A041400100842C410944A4826882122E48201E90C8C21E54298228C3122C081141929C268801C81021210024E1885042C22022D180080241102AFCE0BFD +:80D580006E355F185288C13E232E598782D3C21C8F4FD2D11138584B14521F6221D248F2346C4416782BFC386845D488E6877554D488487428B918F4342A8F42D288A1311AD512C2893E46BAA251FE282E622FA164123377A278149A419D182DAA2B442FE28AE182A4118CA455483F1D429241874254174230184B2121261304484C0DA9F9 +:80D6000031142D94479189D881524649D424B158624487482AB4D121F152444D1419B414E44558C4A21B111A519CAF44F12E24AD5446EC44D165C12A8189C51223F214448D18C3C448474449A81522826F96064130349C56CD5D241CE184B31D521183E5867222C8444FC2F64868DF81E222B141B16CD4290F4E843F8254244D218CF32299 +:80D68000648D18434888E984511400502D3B344D422445B21EB12C92E889A17562A798688B1416A45156C4122F44948888CD8E3F4844214121013042704201698894820084001412540040416214241460181882200C821882188224100488482C08888028C18211880022B0EE0E7E651FD3F119151F52F459728F23B714F22C223F24F655 +:80D70000E173DB186E22AFCDFD585A2FA5F76F7EAF9A59151F1CF97837EFBE3C218F9AFC24273F16F4697D2B47AFF7FEE9EDF5FD25A98FC6FEB8FEEFD9F5B4B4DAEF8E7B88EC4AFA8686EFE5F1EEEC2F63F37E5A6D648F86B2A2F3FADC2DC2AFA5FFDED4CFACF96E32EFA5F5E7E4CD4CEAFEA8B84F4AEE4245F272641FD656591F53F56936 +:80D7800067CF62F7746AEF27F73632DFFEF781156E62AF8BFD585EAFE7F76F7EAF1B0B4F4DF97C7FEFDEFC6D44CFF8FE647B7F36F466E8FF97F67A2F9FDFFF9E94CFC7FF79EDFEB667CD8FC3A3751BFB8FC9F1387CE7A16F6DFB662E6F66F17E5EFFDBFF8CAC8F8FF3F8FCADCABFB4FC5E5EEFADF9BEB26F2DF9FABCCFE4B442F5C8D96F9D +:80D800004FFB6445343B764B6285F9212D5F93B777F32927BF56F6787D3F56FE59572F8FFB58784F65F54E4AFF82F7A8BBEFA2B1CAFD7D76FFCF7F2FF8BC991F86F7296AEFC6FE7C7ADFE7F65D5CEFCCFC343C8F9FF7FC3EEFC5F9343C5E722F2BB71AF811154F45F17E2EEFEBFA3636EFE5F5CDED9F77E327FBD8789F1CF45852EF65F53D +:80D88000D6944F4FFB787B7F62F2D6D4AF8DAC98CFEAEDAB4DF36335CF42F61C19DFD7F3296DFF46F3292D9F72F23F39FFD6FE595BAF8FFF58784F65F57E5AFF87F7BCBFFFF3F3FEFC9FE7F7FFF8DFC6F498B95FE6F6676C5F96F67C7ADFE7F7DDDCFFD4F47D7D8F9FF6D43E6FC5F9243CDEF23F3BF31A999FD5F1DE8E6F6FFB5E5E6F652B +:80D90000F75E5EDFD7F75836AF25FBDE7ABF3CD4BBF49EDEEFE5F53E762F27F33E3E6F4DFD7A78EEF3CFEE79EA01411004418C84C1480000E0814406401828112841048504449028202422048001225032008420486188A048148E48248608822001825FAE038211C0284304460189419418901812811A441484216144124E214548814466 +:80D98000D18525817418051644480419C212C42A6141C064C38694928A622484984198AA44944429098849F47E59C0421F4152381F417248F21124A7241D24EF24D141F26A9219B24A19B54A7925F84A9153F3429157822D954F82C4914FA2E414F8264A16F1264A96F1224A96C55ADE24ACF491242CF491248D121F49F248121F49324EB0 +:80DA00001F48B24AD141B24A9921AB9451AB9443F34AB243B242792498924F8284F9244A8FD40B3CC44C87324C76487111344C44CF14018F52D941F648B251ABB45788AF2431B52D2217882D14678A1CD184E514D88469112EC896E5A2E458C259DE252E4A1FCD42FA8164AD121F48C2121FC9724CB28132481D24AD9619F648A6518F24C2 +:80DA80003B348F243B248B844782B95B86A9D984F5BF19302280040000000080020000008821008008000014008400000080020000000000001470CB4A0241181504837112088524384A8E311602457A1438E8502443C824684392444A023041E3E18128B128212506C8182A89D8481994C8814E8892802421E188E4219244839A28842235 +:80DB0000281A82F4CECD4021487118C229637244514A56128452228D415B481448544B412283B21824688584304247228D242C6214222304832118312484161A2102494482C24212602824402A1124BC4841D418449CF62460441285D582B22471441866C44D8245825A82614912E85618447482D42484B218321C2C240C993636871C16AB +:80DB8000E28384D418928846E145321889311C2284904828430422888A8433481A08812E4226649187459F15021440214143D81241C812306813E114B18154384B41811A84628289A348468484024C121698122820810588A082822D81444AC84C2C2849A2411812A5022566828D248A9418A024F0E52920C2246144008002482642088453 +:80DC000040882282082061441008818C01414A9212420000000049C1444260221A044002884138304800D09604154421127A3E32482E844412218DC10018812F55D21484742C314887544E2483C2242B864222441F4522412182229742228023A921CE222CE221883298C082888E18111E66478129C448A2A29E48844CD8CB0E4992212964 +:80DC800042342C81430880E48442088C4132751524E6820899A4436822298284921446256114328027840200322216E44439228C09822100412D18486880E28108B0370B144444A5622148224C2211621821008184685041461814548441830C8181384122216824008083094E82282148C02258888B18142B2549584283A128838C14C817 +:80DD000084BFFB0E46C8112D2A8C449414003862100248848229041F81882121449812225C88044448848160C119850919818401801408848444B048811C048C88840144A9DADF0B4781444148D0180218100422442B12A021B024014A02211981118828013608108121046081812A3448138286A1610013C224290523E288C4242A81C2CE +:80DD8000848242219FB407280080455284914082410841141548583244448482414A022932212B2424004B2542002A4484981290188A0120C111420000201564812200F0492E40D425C124A1481655821C21F34422122942224468AB422697812812428D142810A64168C3314284C924D44824A12C3088290328F84AB11826419929A041EA +:80DE00004E1AA8C24B34478889238A18C4A8EEE5A052100849C12841840040084341115128128D144B41818214488932211C128202A0121218138461411C018B1417810000184824288054488083C4142044D18903244904428428400C00008442122816C9453024004B122881411256140123011268182820049A848104800419011B144C +:80DE80001A12042AA1828BA445483A24BFAE0B1A2411286124184CA2142C6448806421431448614410B841031485914124148111008181818922C129D01855420046C9281908DCC1A8601C00842E1883041882AA21F8FCBCC014140010442C3118263118228418302115381C90442422404911B5411141120880241441011681012612010C +:80DF00008B142200812884C0142410082904945F550425083048498224820280044880D148048A64819C41B1888401582B4222CB49803C1129240180ED418424A2940012A0141988210E114921048C981126881182B13A0A8200401845384849E2448114413848498882094C09884888422A0812211242992225010044844341280883082D +:80DF800080223844880032A80042A820746F0F420044161228C12112004E141021018144429064442C6442A0424908491481444891248426C86828460842892614420246222914C22200622A180226A8821FD90540A24100124221482618148A1A4442444583824A4801402888880281402342E8140121242642010019048483121101843B +:80E000008489010000B0D10C498281022A11C81290281281321818000022442984230148442242222218001084042A440281229018A04812858401842282828440C841818F410584269C589B124C840241414218444882C332888002811210228881A18425042180488198228412C88413850222A034184C04288B1C414890111981C9547E +:80E080002B18247F764EC2544FF94328F1283643E48481D48476A4F1144883A14185E8C1B247524866ECC4C51D5F44928D11874C288F5CF1454417416485C818258A65621F42B621E246E312F814481B182A2C24E21128B2D9AC332F4C28B953912CE5A4A8DE711BA8A351848F9B926A6A033248811B6412BB111E267D288F67715834487A +:80E100001993884749896C1219FB1C81ABA1DBE12F82A8638BC11CB221BC2782F2CC5149B342C442899128988F15A14DCB41997262A2458291CE688C21D45261841B711DC1C83E18621608814EF82BCA1CC91ACB793044213AD1C8F144482E2CC3F278148087B162E4A6B141951487C94D49193125625827142CB12565A4488F2331225ADD +:80E1800074A17139B1512CF14828C013E0A1D148531A4E3A2E7989B14BA4718CB2885C9C428549E481F728128F82E88321FA581442AE843FCC4E02002018861402690829485842822117882182149214864861A814A414A48220282208823081100111881110010092002011088141F025CF342B67AC52AAFFF3F45A665F57763A5CFFAFDA +:80E20000C6F726A2AFA8F8C3C32D5C7F74FC1E3AFFE1FA5E51DF34B743F47D7BF7845F53B379F75DC775F66D7BDF11F27E332F38FAB8BB8F1DFDEA6AAF81F818B22BE93E632BA54F41D811F6D9C99F1EFFC9D99D6BBF9FF7D193FF9DF969ABBFD1D821F942513E32EF8717E895F4981B2F21F13C349AFDF6CF8BB3147E662F457318FA2FD6 +:80E2800057EFC6F663776FE6F26D2FCFC5F72EAEEFC8F8D9D98F87F54FD3EFC4F75CECCFC5F5E5F3BF16F6ADEB7716DFDFFB7973FD85F5FDBFFBEF33B77CF74264AFB7F7FAF39FBAF35AC88F25FF9EEDBEE22F11FF2C8D9B8A9F94B4E9FFC9D99FA3F3FB791F29F9C3DD9FA4F96BF94E522B744F23F37E588F8AB9D9FD383B2F81F1BE140C +:80E30000BE58EEDA8FB54EF174644D66AFA1713FBF3EF27F6D4FE5D4FDF16C3ECFCBF37AFC9F94E5ACFF45D5AFC8F93CACCF6BDB5BF2C1CCDFB7F7FAC87F53E38DFC45D5AF88F867C14D4B5F52F61B792F33F7D851AF34FC3A389E3A2F81F291C26F517788D94DF2D9C99B9D1F97F7D1F2BF99F1591ABFDDF969BBBF95F3C89AAF8DF53CF2 +:80E380003AEF87F7A8388F87E6A3B172F7FAF84FC9EDA4F58D51342F23F6167487A1FFF7F17EEE5F17F7766CFFD7F7787ECF8AF26ABEBF95F5D8FA9FD4FDEEDE7FC7FEFCFF7FDEFFEDEDDFBFBEF7FCFDFD1FADFC65C51F2CFC3DCB2E486F52F6183FFEF3BFBFF748CBAF87E7ADF5E7AC7E627F51F3A92BCF4AFA59498BDD9F95F5F8F2BF5E +:80E400009DF5181ABF1FFF69FABF94DFA9F97AD14F23F37E688F8AFBD8F88F22F172788F83F5B4CC6E6BA72CA012008441001241844008404448844404002880024440941100B02421E412012200A08248E08824C248E081440140982812288228F03EA6904412242889A1418144A041421242168828E8546288188648A44198438A8204A3 +:80E480004B1214581AC21812841014C11284188C344812881288821882701488628120081E488148B7A8D022F41124A5F31124C7241F41724AD241F24E121D24AF349921AF245985AF64B925F44A9357822F147935D81AF925488D915FA2D418F8274A8F15F2264A87192FA264592D4ADE24ACF491242CF4912485F2912487241F49324A6C +:80E500001F48B24AD141B24A9921AB9453B14AB924F44A924B43AB944F82949A4F82C4944FA2F417F5D092F41164E5B311764C3311A543D43E01AF7441F4423384AF74BB35F44A9255D8227915988839F44A941F22D548D9273C186F227818F1224256F522491E2525F8112C2D481F45D22EF41124872617498F24F18124AF265141AF6452 +:80E58000D941F248B25B218D1243D22A3134A53224A9B122D442E982F5AFF3008248000000000028000000002180011908000000188480040000004004280000000014E0D401421443411408832361D21A689816381844C3318400448A024664428A022992246442284D7800244870117411164492288F242A2114381870828281B854E22D +:80E600002A04C0188118438274310216652A222474413028C024382D22344A681883711884321841C3A61220648446843118498101AD424E2C8B2119218502AC121811025FA10A2D822E5842821C0499A1348B49112A3941871187224D599044133A244D42814128831245F4358A8C322A4CB41C981C4981C21C4CEA22B45482A285842793 +:80E680004A43D2680118833649A992383B144A713458248B42257822A88429615A81AB1887222E44888A94241F85A852CE18182E925661115E2A6F5D0D1C0129014503892131289A02123C21482118080085044422424812604522161462440010C1114410312AF0481240A2412C2841A1412C024019088D24F02DAC80014100A012008007 +:80E7000001290818924C08AD2260442200004E2141802194148308282A082215084001221281820083044C088D84124018088F88044C522716D18642046489F426526A8182211548944428A149C42C224909854444C41412CC289228826AF128125694541812C0781E69389C541884822E49189C24A141A3B31C8C834888A14283E623069C +:80E78000641118A1001E24A0251A04121A18C814444948A842C9A224445084004C2521084212E81869B4A424214118E88184021598183048109818C02884CC8A08184A6282FF1D06324465C12444002D4A642238304200D82225526840A49200444126115448388932848991281A820128117819C2111D48223088132A6114425269E94178 +:80E800002C2141484888F4C771248418608260425012182602467888A48249048B18118228822CD441412302800A28302270848181E1C1928848E028A23425419C1415542138813088A021800292904EAF4B018444803448402182C2448042F4261220022D2424248C921822A11887483608B018242281442164448490494221863848002F +:80E880004400A2E022242984018951848C13F218FD000010025A1208218C010018251824011200420010043548848144180823021B2118164414A412008328014694184008200520047F7F082141C02A42282A94211A726432188322D824B14421F284182752822A91224A11458352841250815E242229C248862C6447223698195282ECC7 +:80E900009A58C11634881429E1C864812E48278128A0128971189438C3B4490B20011048C41384240048852248420812249088844A4308D048622240288105201162411C0845C2242B1419024021010082881A8481048242F034270043024322840246225484422824122B142678C294144285648428188584528421381222291102A01A79 +:80E9800020890100168C018841320010A8120012A08440F839FDC0421824808294280010AC414E1820D24105224538415B8316140182224824A414281008448246A448008902481885911A304282203182800888817084F2C6FD00000081424942182801221284831104222A1484012800200581820084801998982884843034844B12628D +:80EA0000184B21C048228182E08221913620F44A5E008484902844001E241A0212414C8A081681E891480148811001195118111E4115B228240311141148990113E113948900110014118094480022B04281F3759D2008248B24844285641410040085C114828100304840A421A280E44204624548116884260816840242418110020040A5 +:80EA80008261880029018C0418481F310521280044642C02A14221287044122822284584014D2842828F4401003200184681216484288044A8414448C048488C8289B12884A38122484A82490488BFC3073880050080018091484280140445C8116012601241406CC18100008880088820A8212848C024A88308421B8482808401002E88A3 +:80EB0000C352482B5C24108152814C0441C41A94211009844C085884C8CC014832895C484E228188288C0118411C034410B8240500008041081240048F410820845424F0AA93E0849214584100421AC2244A114824A124002262288001AF4804190549081544B289E182C471804428C421811E214223C2246E154714E0540868201C888407 +:80EB800038482508278A22F942A1248E341E123982342C2F44F642442F81F614742D481D485AB614F182EC5119B714B4919E5417484B3319A5A94F92DC84C4148C32281F83F18A81218E482AE4123D144D853E188F54314846F91E444D8546F1C81D8B358F2A32144AB142B834D2889918C28538928E1889CC586B44242B41318446F42899 +:80EC00002C30241D22CD149558488B14ACF141868B148DDE4F4198A845E141725CE944E4957A28BCC1C226B9B47C7811A4641D1C97868B26144B248ABC58B4888AC6118F4337611AE683D124CE4C1AA5B41126D8A82CE8860C3A85B92AA811CB82972A20323C22C78243E44454884F832126A6113A12D48834143A32C86E1C8FC67149A916 +:80EC80007284C742495448837254C8512D31A5E321A2711E148F813188118A43618B3E28C0388B166D241392811588E4199C598AA1654399924AF268484F44F6242C2F4CB2C50D00008400004008120014400181000000002128290100100115081150810020090082400882002029E417094F41D5D5F13C34DF7276427444764AFC6D3535 +:80ED00008D5CDF72941E1D118F467159F5DAE8D7C19F89BD88F8859187924FB3F4696D1F9FFE656DDF16F66C7E6F42F674223FF3F37B4B77713B444F4EEF96F779717AE7D5F138115F53B7C9FC4D5FFF96F6E5C22F5FADCEC7841F95C5D41D13AF8DF16C6C8B56CF64F57AB8FEF22F25F5ECEC85F832A8EFE6024F43F55575CFC3F32D6FF8 +:80ED8000EFC4F24C2EE5FE4F27EFC7F76D4FAF45F559598F847719FDD2C8DFC1F14958CFCBFBE1D95F97F37D7BFFD6F7B5F17F55F7296DCFEEBE36F73CCA27E3AFB77416FD71694F4BEF86F731791F17E751D118F23D6D9F8DFC4C2EAF86F4E5C22F1FFDF5358FC7F359591AE929F9DA38CFC7F668D84F65F5FAF8FEF22B77AF87FD141895 +:80EE00004E5C5E51A0515D558FA3D3FF7266742C5ECEDFF4D2CEF43D3FAF46F359118FA4F3DD9BEF8D7958F93C489F12F6B4988FD3F23469FF96B7C4FFE5F9CFCEF66DEB7F31F5266297F39FB7F4A4A64E414F4FAD77CE681F1EFE94D49F8BFB25248F9CFC5C5EEFC7F765662F56F7F5F59FDCFC79795AFB4153AF8DFD6C748B76CF6CBD8F +:80EE8000F2FBF8EA2BFF6FCFFFE8C88F82BB6C0C2AF635658FA3F34F2FEFC6F26C2EE5FC7D3FEFC5F52D2FAB379F95F1485ADFF4F5DE9CC7D5CF86F5EDED4FCFFD757DCF87F76F794F2AFFC175CFC8F66DEB7F31F5A74B9FF3F2784B4F5BEA96F4B4D48F86F791F1FAFF94149B89DFC7F3D8D9CFE5F13B79DFE7F762795FDFF3F8F89F97BF +:80EF0000A7D51F3DFDFBD9CFCFFFA8F84FEDBDF2FFF8FAAF8BFF74FCCF8FFD4CCCD50C00228461001A14C44820019E486089444844400485249828400489820118A01210042A014098141A2462816089006088288A049228D04822F88CBE3086282A413422C4C128611A2246881194824889228378310816E81402444342D48245712302EE +:80EF80008C088492412888841828C028C1408122341100389608148148189CF4EAD8C0531F41522A1F4132481FC1324A1D24AB141D24AB941F81B24A19F54A9253F24A9153F24A91478A2F14F924481CF9244A1CF8244A16F1244AD6F1224ADE252FA2E549D2A4F491243CF4912485F3912C87141F49726AF1812CAF34F11124AF249921E5 +:80F00000AB9451AF243924AB94478A2BB4478229F934484AF9244A1F350A4D5B1A563E1B6187321FC1724AD241F24A131D242F54E9C1F24AA349F24A9353B24A3925A939242F147926F842915FA2E514F925CA1E215F826C5D65E85CF2261BDE254D4ADE282E4BD6D43CE489724CA3698736CCF248931F41F64A171D64AF349B25AF34B17B +:80F0800024E4646982AF64F3244829F9364823F424182F88040000004400004400000010010000000000400100800400000000800200000000704F0B444D222244AF11342441948711813C51A119440840A84372330296688C4628C224478113C22C8C119426124906416C514918276143682250841AC8C922A36421C860E14D728E222EE9 +:80F100008243241494443743142C2668318C41C418114B242C721481288331128D118618160A4483644222228242901C1A3C64996281448911A2142212A042188F41A84986420C89E12178487418C22400438105856497F0CFBDF02442472438E14CB528117424D18153875961A2663112160884A12CD514C24A1EAC4E881A26684A89C14E +:80F180003DCB294E3417C2CC22D1B414684443D25AC1424B616B18C9B25248F41884578C2E127E884C414814DC22E74893E26724C9B4347454D2120A804221511A44148C04122C38111884148658423A84020028842848442044082941A412802101120098D028084048C2482F2429821104120081F0F5DB50244C921A0048458114241124 +:80F200000234501840213948A2288042684448812A54484112254224022A4C94169018488042028B1480080042848B243048438811E4C34102C0A54D1816F4221232C1831204C018814512042A248244C8189984A428444D7280658C4E2846A824238815021C1218012E14214C76889522C8422358248F219C286349B2842182B16818F860 +:80F28000B731106242DC5248809214CC54846C014048480D80232608C04889241AF4481222414DC88C7642682482302270261138114210C242152E064A3882418B418B244098168CA2188BE1F011FB5024909218433152271280020013110261148A142836288C61126044424982648520012D24221AA484441840083684C224888C810CB1 +:80F3000040C282D0C2292628140445F842B6400C282C14C1238481222D128A11514862A04843C1228301602445E814D1868812CC182AC81884848C0480C4281AD284A52518412E8423014C22261408E722112041B328C18890226F754342287319D412D64884A14200830228444712842230452002458A8303A02124817016E14235228E23 +:80F380002138172284512A0C81842170A40845AA211442882E88802461282281F0D824404204180047117B1248460489011258244810019B4A00444A4229C42420440224842112000022004E28480088218C011E4144C025A01482487F324E027035B82261C416D1927716A1242FA1068C0244182A98422604229368844C41A442224B2125 +:80F400002CE18832585CE1253228A123E116819224C442288514F21248C82828D21484E9F27288A0416CE388E38463884AE2F50D45E2410211258112C42840843911811B418384C41419D41A014A1294281F22D448D881B84878240824816528A4822824C0119AA21216088E2422CC028C5422844A21084100200870C3022442160210C44E +:80F4800029204391114A811484054E142A811414AC148424104464453C0120033244C04481448741444481C02422A2D0A444412401108452841441DF8602221001411B21414440840889011392218800107224B111341322930A268854818A44440D1200144A2204208C32422118839482842B8420244222844108DF41034015080040683F +:80F50000A21826284196111054413011844C6181846E8441488C4182A242902A18464841220112182913C82448706841081C68414228256481811A021425F8CFE52064821A942C8110A22180120210188E912844216A012121841306531401241F41244148031C440100008F142101181418211424450862408285A9947DB1200441224921 +:80F58000212212048DE24C18A91424422448801192688021024D42A0811218212412481858C41042044961284F18D2480A172490111018E2442184016088E0940E2C1141022064D11485141168428082C1848249C4248421468C440E8302A415C8483AA848C28CC244450828852412386830482183843148B048216984869114C9D8821966 +:80F600002412F45A4B24404241021C0148124180041041088941091011048501144260120060410011446220061504128018411C120281C041419044842F6B032F18215886137412298461221008854249440884284666422200108848D814081211811084F41422624F828441F8148236823214866121891281111448C41A4581450E25E7 +:80F6800015F231444008484482450842415A284124E211128429012112522271484C054A09002882460181842C810568480013480A4C84810243A112880060882B12244BEA3052C71A658412F661198351414D144B44298B8655452995191D14247F64352CCF44B124D2119199489D2A484B6911BFA1B424F228421A34551447411E64CD74 +:80F70000213283F56624521F8EF24565AF8898213A784A798C7246C49A8F461238214661442B1D87D2AD824FED4A62323F28D431D127645945F624284A518A8FDA7B88F8191825091755453414323659223E28AF15558845F64E25C6F45C198D922F82C131188CA31C2E14EF45A1127941F44C144D748371269E8C2F2B981427A6997211DD +:80F78000E251E52171DCE481F192986FC1F11CDECF8151C44F397644F437538005878187428D181AD651B12CA6233721471142C3F71A13CD289AFAEAC8CF44035E3C2954C14F45F4626817824BC21574416D15623F3DBC94588C8D68481F247448F1221A6826A85889C35589F121668B51CE59583D88959942614F44A464F022A281988C0B +:80F80000F18444A02520012044384420042200408144010044008200801108284128182840088418200288806881888028832882A842A04B814F2A4CF333122FB6F13A3A2F32F71CD8CF17E751F55557AFA5F546ECCF99FD797BBFE7F54643AF84F545C6EFDAEB63F31311186D52CFD3F714117FD456FD7F2AF757514FE5FD544727263F5D +:80F880003FFCE6266FCBFF3435DF17D471F4711F7F63F336644AF6D4E2AD68BF6CBCB2FFE9E1EF8BFBA2A2ABCD5BDD3B49EEF2AAFEFCFE3F2FFB36354FE7F34C243EA44F2576BD45F333123F33F53F3AEFB3F35E5CDF57F76D79DFF7F77A3EAFECFCDACD9FB4F47B68DFB5F54B58DFEFFE9E9D8FE7F77B794B76CF82F36F69DFD1F4755594 +:80F90000DFF6F42F66FFD5F574F6DFF7765AF8D1D37F7EFE96F4CFD7F7746C5E461F73F51F3EEFC3F2485AEFEDFF6A68FF6FFFBBD78F6FFF7EFCBFBEFF7BFF5FADFDD6F4AFEEFD72FEAFAFFC72B27F47F5FCBCEFC6F374FDCFEEFFF41B343F25C763AFE1F12E3FAF83F37C794F41F1797FAFA5F1CBEB3FD9FD797BBFA557BAEFC5D5FCF1E7 +:80F980006E7EFFB2B276E642D386F436751F53F7657EF7B23FF2FE73715FF6F6787B6E52BFBFFCE2B72FC8FF24245FD5F561531F72F7393F6F43F3484C4F2DBE36F7F3F76BFFDF5FFF72B4BF2EFB5BA85F4DFD1B58CF2EBD28FEFCDAEFB7FB3616AFCBFF8E9CCF47DE6CF13593343F25D733F31B1EEFF3F3BA78DFD7F71C7CDFB5F72E2E30 +:80FA0000FFFEFEFBF99FB7F75B7AF5FF5F5CCFF2F34E5AFFF7F77E7CCFC2F126187E75DFD3F7EDDEFFFEFC2B6FBF97F7EC3E9FB7F7787ABFADFDE2F7AFC9FD7D7C4F47F574525F72F33D3FEFC3D3E8F5DEFE6B77FFF7FFFEF2CF6FFF7274BF3AF95E3A5FFDFDFA59EF6DFD7A7EEFEDFD76366F6DFCB6FCCF48FB34BDCFECFE1739002042A6 +:80FA80006812804108841484341648A541A041850485044A0228902811811890168118901400901440021C486832841412348424128112200882AF320F145014107811044CA2128614024A0181418D823A24241232141445581861144B5210C2218C2801C04228148C62241E284342D824A12142288D124130148141819082168869887FE6 +:80FB00007B034F22F4112485F3112487241F41324E1D2CAB141D24AB9419B24A19F54A9153F24AB15B422F147924F842914F82C4954FAAE414F8244A16F1244A87194FA265594D4ADE24ACF491242D531F4952281FC932481FC9B26AF18124AF24D141B24AB911F24A9255F84A9243B34A39242B944F82B442F9B4488B944FAAF4CCAFF065 +:80FB800026481E44AD411F41724AF21124C7241D288B141F41F26A961D24ABB449D63A9945ABB45B4229F934482D916F82D452F9A45A1CF124CA1E816FA274C8F1241AD655949E216DCA8E282D5B1F4D925C1F8932421FC8B22AF98144AD121D648F44F911242DA25D688D924B4389B824B44269822F64698BAF44E12AB18C0B828200000D +:80FC0000000000800200000000008008001240010080040000000048000000005012F062D314164146098022C22425318C80384841486B6127222602854434181A1824021818444598162C0898A021166119D021C22CC3A28184A04823F2528889814904107818A28486A84A22EE5F2032B3384799671116151BE344F22251232182D818B8 +:80FC80007491041B49128B122AF5211826618281114C024B2413212422C214C44D312150C245420856D214A2428F68444849E228D4A4048B828F223481448052584978BD0F126F2CE381321525E412511A4427522D8D612850143C6F461BC32D3212467C31FE2811863818136248121E645361E42038128E19CF3221019B18491451421EA4 +:80FD0000644D814864CF28C4232A88715A04A8A48609248CC8C12721CD47601211148CC81144269221421A8621B848C848441221902832003841200200E0412242140422131106A3C22885A22183E28804848F24E188C48241812A0447812B84228D2443FA34DB001A0284224003426014A084008488222100004800812001802408860445 +:80FD80000082881504400200850214840010844808F0EB1D104511085863010000911522D4120C1144818AD24822020042274289E12228941883024812204288F12458988C128204A72880212414F218C241861218242208B778102402A0212110220410612424C28414248160C22800008400218480280400849018128421406228400828 +:80FE0000422186022484448100B7DA103111818924341414006054811B824814803824200A002905C8274283A12948121D6800478980029AB46438852820144218E422814441E8844184188488823812BD453023100A4461D022C23285212A0421840046C61580E844C841644582420820C488212B42001100C0282301200162A0412D886C +:80FE80008122C062B08841B8448142F276710080410414004042088214302112182229912200C0481012C42844271260814115C2124151214142126130481824000021A0249062821E44888FF90A80011502811214150811172294814825081481628418000024226400121028228242381980088125080084444C4408848122184008DF00 +:80FF0000E24A312318A34105411217221611BA8862162D8885815483D0617418C1328B284A8154244D4A103224C7224217A21889514826C1216952848711A0C11245628146A834701258428D442210E884E2A8C278437C2488F81C4C00005026154802831251124003812218126C820443480120121802452248A22400290134702C02244E +:80FF800084000042860884212A142201124A01BF3E0D004008440000140000000012200200000010082888000012244022180840185281002400840040F2E1B110D1520123111111011D2810185181450820684824001021627410084924112422082B1843D1124861288830122860212411244001883014304888C122EFEA0C3011241807 +:020000040001F9 +:80000000100510011400008018040022141849844808204104222C081282400220811A28512285111213010018848140582257EE5089AF44A444831401143028504C55B42DF228242200882412242552221AC3139AA888C04440D811D211187198588CAF14B441A49482254202004554444B228B2222801842042C348265A213CF210B3053 +:800080001200214C0100004001141012080000000040040000000000000010010000000000008F2705818C2484041021024014E448722881224808005022102291142AC88400181413486188818C2484041220024016C424378228008112002490122F1F0E84E02144018011518114924480220800002012129414828E810081284041029E +:80010000A48004214112002450418052810000001002EF770380040000004044810281000020180218800A280021140084804422013410120244800221100800100218BF1D062100180020011113080084000080080000000000001002002410082400145021424008000000F75B10B8482424041100004555444F822A26060000242542EB +:8001800026019604430822501111118558888B4452420010420245544C4B222A362100004002241AF1CC95008D184C8404000082805844112A0281840000242981A1112A88080040521121508848C8240010020045042A4202442002212512F29876241800000014004019111A01C084120000112828000022200140024C1882C2120011C7 +:8002000011114018080000004044F474F8002001238261110012000000000000401404812244000040020024000040022121102801810000002FD50F21001012412143482119718111234402410000004742441382022229031200106249822D2223816122100381214008814112220000DF5A49228121711203410014118881401128584B +:80028000888C08A0880045014B226042100840022121405222C012A11003213181467B4A012508000010F448610023C11480A2111B1115019815C18189784878810910880180124404C028414504228048C2822400185014242124241543411219810185080010042FEC0A6F22F212222E122B11122B11C0132592822F31F111119B888E32 +:80030000898F84F888418F8424F4414915C1419558884F84F448444F42B444F22424222E2480524445E642F326222D222E122B191AB88229C8122592831E111F11B189F991898F84B888F44848424E4880548885F844484FF6046F2252262AA1131200182592823CF1111319EC89D988B888A44C4214158154819588F44844C5B444A22291 +:800380002200405444286F22D226A8123AA1812B8882822592823CF1131119EC897818B888A4444200405888483F810B48420000008024040000000000000000000000000000000000000000000000F09359802484240420240400000000000000000000002024042084A4444200202424040000000000002FB80B484A04484200420020A4 +:800400000400000000000000008004428024240400A044004200000080088200004DB1800480040000424242000000000000000000A04400800442004A040000000000A088820000330948420000008024040000000000000000000000000000000000000000000000F09359802404000000484200000000000000000000000000000000CC +:8004800000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F093590000004200000000000000000000004848000042000080842404484800000088820000E0A40648420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000006D +:800500000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F09359808C +:80058000240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000B6 +:80060000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B484200000080240400000000000000D9 +:8006800000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B484200000001 +:800700008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F0935980240442000080040000000000000000000000000020240400000000000022 +:80078000000000B50B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F093598024044200008004000000000000000000000000A0 +:8008000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F0935980240442000080040000D7 +:800880000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F09359C5 +:80090000802404420000800400000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F9905484200000080240400000000000000000000000000000000B2 +:8009800000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F9905484200000080240400000000000056 +:800A00000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F9905484200007D +:800A8000008024040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F093598024040000004842000000000000000000000000000000000000000000BC +:800B00000000003F990548420000008024040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000D4 +:800B8000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420054 +:800C000000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F0935980044A0420040000000000000000000000000042422084840400420000000000000000FFBF07484200000080240400000000000000000000000000000000000000000000AA +:800C800000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B484200000080240400000000000000000000000053 +:800D00000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F0935900000000002004000000000000000048480020040000A0444800004200008008200800BFAE0548420000008024E4 +:800D8000040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B200448420020240442000000000000000000004A0420240400A04400420000000088820000EF5B074800480000004242000000000000000000A04400800442004A0442 +:800E00000000000000A0888200001FBE0548420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548422004200442480000000000000000000000000000424200002004000000000000FFFB0C80048004000042420033 +:800E800000000000000000008084A444004A04004A8404484800000000008200F03D2980240400000048420000000000000000000000000000000000000000000000003F9905484220040000480000000000000000000000000000424200000000000000000050BB00428024042024044242000000000000000000004A0420240400A044BA +:800F0000004200000000888200001FEE014800480000004242000000000000000000A04400800442004A040000000000A0888200001FBE0548420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548000000004820B2 +:800F8000040000000000000000424200002004000042420000000020080082828FDA0720048004000042420000000000000000000048480048002084840400000000008800009FAC0E4242004200004820040000000000000080840442002004000020044200000080280800009FA904480048420000000000000000000000000080248418 +:801000000400008024040000000000820000DFC506004248420000484200000000000000000000A0440042000048428084240400000088820020F8912C0000200442424242424200000000000000002024A444000020042084044A24A444420000008A280800F03C62802404000000484200000000000000000000000000000000000000CD +:8010800000000000003F99054A848404200400004200000000000000000048428084A444484848002004424A040000008A0888888888EFF7070042004200004800000000000000000000A044424A84A4440080A4444A2484A44442000000008200F05A1800008004000000000000000000000020044A8484044800004248428024240400C8 +:801100000020882808001F4807484220040000480000000000000000000000000000424200000000000000000050BB004A044800000048420000000000000000004800800400008024040000000088000080B8590148428024048004000000000000000000000048428084240400484280040000000088820000BFA20142A0444A0400009C +:8011800000000000000000000000004248008004A04400008024040000000000E0AF0A48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F9905484248004200002004000000000000000000420020044848002004202D +:8012000004000000820000B0B50148000000004248420000000000000000000020042024042084048004000000000000B0750E48420000008024040000000000000000000000000000000000000000000000F093598004200400004842420000000000000000202404000000004200200442000000820000D0530820042004008024240470 +:80128000000000000000000000A044004242000042004200000000888200007FAA0C4800480000202404000000000000000000A04400800442004A040000420000008A280800F0CEE580240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000013 +:8013000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F9905484220040000480000000000000000000000000000424200000000000000000050BB80240400000048420000000000000000000000000000000000000000000000003F9905480042000080242404000000000098 +:801380000000004242000000002004004220040000200800003D85004200420000484200000000000000000000A04400424200004200422004000080280800F0FA2F8004800400004220040000000000000000004A0400482004A0440000000000008A280800F0D49B802404000000484200000000000000000000000000000000000000B7 +:8014000000000000003F990548420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548000000004842000000000000000000424200000000200400000000002008008282AFDF0F4842000000802404000000000000FD +:801480000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F9905A044000000802404000000000000000000000000480000000000000080080000F04BB2802404420000800400000000000000000000000000202404000000000000000000B50B480000FA +:801500000000480000000000000000000000422024040000422004000000000000002F57044800000000484200000000000000000000200442424A0400200420240400008008800880F8F4F78004004842008004000000000000000000004842800400004820044800000000802808008B7A0080240400004A0442000000000000000000C1 +:80158000A04442488004000020044820040000200800009F9D4D0184008CC1484149E422247824214861484C0A282C22E121120820083121883121889881882042490184484548B82638A41400C4C0224C420624122051828FB20D1416D381D129D4411464862648F424418092348415D22542341E57A2881B1AAB1896F8421249A81A1E13 +:801600002533F118849F48B129C12986446BD2113632189DC25C1CAC4A4B5242296443325C2378615684248B121E2E6AF12842894128F56AB80000800148842C2268128A3221601841C01854239111848341022822147D8282119312480A80820121806821464284020028E4008D24304A218981F193A14061211941924800483041448085 +:80168000D14808112C2212082528082B41411004124321A28144112685C211218998880049C484821C819111896814284489122207890189D4AB084001994411C42826440400000061641A826A221282408249B11248581882004048011142C04C8924022841C0244110024418200124E0E60E4018084483140448260440044D222200009F +:8017000082008882152201008C018288008484111744302481224880021004268201212200247B6F000000000000000000000000000000000000280000400800000000000000005F2B0F19414261C2114E2114154421C48129224102302820220216042C728428022E18872286D842C412224CD421210418162C94192495145484261852F7 +:8017800028701802296224248C0849A4812CF82A38108441522148831178421A9828121421256814441381721258225C059241482443562298E082482821812212022642189241AA219261923C117114938420118601182284412FB44111612115C22D13F42148248754A18394812229119243411782D022211263418828274C28418D1224 +:80180000872287288B48802321C14200ECC242181394A74145E88211538363D1864982624429110A43B61888D86D044901002112850114282C11018400182289024E1480111448A2242322094CC21A90441932228021115881608122198628011124C01200821800412FAE0900003411181004188424009260888112101108608242211E7E +:80188000242144222888122B8211002D12160448002412872480015084420010088F840A1B423D1218B014C2187C72249A58AE581C24C2898351141558C12981D84178212883C2814732001E24821E2127832741848903186C7821988C194A6844C3F1D4222E188C240A1221A3E122C832433248424982064E49805612002289D125119418 +:801900001CC6A814C08812411E89159882833894841484824483024C32942F31922C412688092B1A74118522628148813E828C2104462A512200209648404408EFA604141223014D131422AC22A421118C42434801448C01111C828342C121212C242102122B129028188068824CF8811241411E44468412B8820380C1188E2247832504F4 +:80198000422268F0BB1FC0287C02482424182100122244E3561A1C8228216121111008278E284184222002184311B122E4846282144C5424B04463924C616919C12200002722D04A41CC648185F2688A508212111B41008416044C948142CE1422580046582B2082A4122901458191661D86100100002784001221C421902244C68A429836 +:801A00001290428008288448221F34064830182841CC9141911C4288844141012444612012D884080084141212168251825082414711241D84120028944B4124284008812FC11204C921128201883FA34E0336158201C57241C219114628A8218E52142D48308487443D1828931214088C42751463C19E27B02351822C3114644B412259C0 +:801A80008AB1145426415C34251AE22A21181A7A1298364CC42216BC1662423889648ABEAAA042D0189121452291184422444E1148144D481C31212522412211E2888443A2842E88882A04180040186132101A017028E281F2481244211F8104008425028884A14D48005FAD0B200100205248448068883088151824382886F411882D81D2 +:801B0000448215144818413811824012088064229C324485C238D0826324264851821800448C43C81881282280F2F1DF0011E045420481001E84130110C584880028224119140218439812240016011A88243311A124152892818308178848C111000024009012458811F46D1600615012501428135281182119A3818814211CD124618180 +:801B80004400181001005018C04800111AA81813B18802102118411102402101801288014048F899FD80829248504812449042148B242426044941022531218249712851213E42411C01A6C182428C084A1218484881021B2410D22101B0414996480028C01821288004242FFB0F118140C831005C220211149441282484824D831181C6B1 +:801C00006889458118C81200200250821414248142208121341800272184111442002250188041E1D90E16A8242C2704288523018078822C8221212A31241212211833A28242400122184364A180A338221800244D212B822D21282C238184C12820E12221120212898122F2C9B400904800212180C12A49241412938815E8180200008062 +:801C800011082061184A88111288784222042C4882880482883D888280820528820022224810F8A88B209313288436681148184225412AC281122C02601824818B81232892481C8618B2188C52188B481A223A32412221001528981143942212281316648114128120215182286021CFE60A94441AE4111241140584C4184C84042194283F +:801D0000409824112A5122244447144B84671243A12125A1481CA1484098A1C82E814A088304488289C414484AA21448001028283122708B0E266247167241117112E4C2525683D44871C458A19E816D886DA1B7421DA18C7838FE87283B9128AC3B144F44F21C81124D611AD131E8F461A3ACB15AB421062E331F22028F36F6A284841EC7 +:801D8000E2242AF331883914F818511B1128A8278236C8322DA8878236E922F2D373141E21B12AB216E1129325F021222CA4211DD1299A27174199C1831823B285C994B48C651B2D383924D813F19A981F6AF838488B4BA0A82E2896F1311112AF18B84EB281F851393F397221F84B299D43A7484E3A3E181784E041F1381281A1853838F8 +:801E0000527018F82D3890114D318D188F82761CCC11F7141E185D3857B8AF21F2E85183E61861EB8638BA5F78C3218733C7489F5F18F161C78D891D4E4636212D21CA91818BD4AB438E92ECE12CF6838816F8A1CB84248B942F5CA1DA2F89E83465112F440446A146842C832183C17438447F69040000008441200200440000102808400C +:801E80000400000000420000C048C048220084200148208102002021F4FCD4143E123F97F3193B2F12F62C2FBFB3F17B5197128F63F241C14F1EFF6121BFF6F48A118F18EA13F33A19BE989E963F92F347D9BABBB1F9E1E33F18FA81135F15F561A15F17F451415F76F36AE22F2AB36AF6BCA62F3AE8925A11288F2CD46EB8DBFC5DD73FF4 +:801F000083F72361FF33F12B23BF57F441111D612AF7A882A1242F22B392E986A7667E62AD17143E323F13F7393B2F13F23C2FBF93F37977EF62F1121E4EC98FFEFF696BBFB4D47FF1173B1FB3F33A3B2FABFBBEBF3FA2F2D7DE3BBB9F8BFBF5E77D299FB1FC55433F37FA77733F36F6773F3FB7FE3232AFB1F2564F2F3FEF22F61A181F26 +:801F800012F62923EF63F31B81DF53F21179AB62AF67F129339F1757911F11A1328FABFB22222F21F13A32AF29BB4AA7772F26F52151F034362F22F73B3B3F33F22F2F2722BF77F52F2FEF67F65343AFD7FE4941BFB4F68E95CF18E812F23A9B2FEBF1B297BFB2D357F1FBF81B775F7AFBAFA3BD82DFD4F46122FFBBB253F47537AF37E225 +:80200000A1331A4FE9F8E2E21F1256198FA2F24A6AEF6FBFEAFA9D9FBF97FF21318FF7F56A72BF91F2415146A176AEA2212E222B329AF922382AA232AF71074F63F33232BFB3F3332BAFF3B223F27977FFF2F37E7EBFB7F77AFB8FB7F75BDBFF78F1BE9B8FB2FABABB6FEAFABEBF3FA2F21F9DBF8FF779685F7AFB272ABD4BDFF5F5F333FF +:80208000FFB3F36363FFF7F77A6B2FA1F31B2A67612F2FEF23F31A12BFB6F22A2BEF63FB69E1DFD7F67B798B33AFA3FD6872BF95F711191F15A5778FABFB3A382F23F32A388F89F93A383E328FA2F235AE4001186012844D13843492266189248214960817816C224834818113A8245048118129384823123822422D81C0118414C093600C +:80210000221E4826031416080012002800F04D82A0181F4152221638241082B244C128241A52184026C123860845581892206254354A84644413A225A025214280D222086AC848218CE214891288828144013826186281A3A4432894BF78072D421F41522C1F4132481F41324E1D2CAB141D24AF249921AB9453F14A9643F24A9543F24A16 +:8021800091478B2DB14F82C4954FA2C4854FA264116FA264192E5A96C54ADE24ACF491242CF59124E5F2912483F4916CA3F6812CAB141D24AB941F81B24A19B54A3934AF4439242BB4478229F934484CF9244A7F34056D4A1F41762CB21134481F41324E1D2CAB1615D44AD941B668B915F24A84228F543924AF147994D812D282C4B56F12 +:80220000A2C5954F8AC481ACE558F2245A96C14BDE2545FA81288CF59164C7221B29411FC9362E17C8AB141F48F242141FC1B24A9A25A93934AF4419B4427B2498922F83F442844FA2F564E1008004000000008002000000100218000000400100000000000000000000001002BF7B07114712111213110385D4254321289111B0826161B6 +:80228000461884E8C88241284C18214204AB61CC22011A48F812222071221808861148C3482C011542181592428A054981048190284F9E08288A012641584815022192601881E511814243122811014D18412442811F42412554A12E882C021442142486025223A183982718001A0412248125022D2A26486411242FB30D136246C031993A +:802300001101213D2411411C9111141ACA341518C688264442881942B18213E441723CE144D281B181221B1A297441421A083C011B2929C19161342A051821A94492148F24C22284128721CFA60330111440424C41CC12928882855284250123042196C81170485484801458214284508240A22121122282218A9418F04882001018158259 +:80238000C4924002814120F2CFB7200265032C01182814111C01A048141002850130144251104304814528044241422C8802440063B28114283848923440264104899244188022F2D3FC244411165885D411508116A2858988D1127112711438124498641AEA9885244978840810924429493C3223B3E211B44462112A817283081427430B +:802400002E8622241314FA188213688427A24F261174A262424901F0EA97D04212811143066012B0833511183C21512424A08184B8481A8415348C140049341C89C4122AB5B4C44448222264871890234E148D2680244421514152442B144CB2A224818122F233F100505AC1934181113811C08810C2C19921410454218F1118845818242F +:80248000101452288844230221604A3381210240B48322A828843F2811388A23582A89C224A164264404F0B247401812591484101C08890121168418F8188190128229140148188128A112118440D4410128222518594200C25410C8828C824231421882C0141622E288445428DF720746C9142D2421502813246882B048114834241682A2 +:8025000024C82412282168382D121024C1442C4852181211002146AC281C6244430222132224018B24444024952C882824288A81F29F47301200364254141A62482714618213012111104203832182488C34248C04303248224058484100002B212901304221110048122312E22408818904005F6947B3414154C25C431CB13754481782BD +:8025800087418C5C1A124181C8803382AD321382FE1844469224837412E8413493AC6492439118854404448C127642342670258224244918D814D422141492AC2978280283C49489B29A01241A643210421C08272480214122C81317812D82511848002810B824880828210044807222021C98212A21A1846032843428428021A394484C92 +:8026000021B148220AD0F40C401442744801118C0480114201141CC1128460138A0142484B2C4B4812211820482882028AA11231430C9048884C34441BE142009741006301804118B42871C80B1312814423025034184400223881441482D08244911421008429886284244CE4444368848A2614E181321A44411222890190A2C88F440844 +:802680001863012AC428422218823FA90A25C212D02244012D4918000040840144C48905001961428002188B82178A89018F4438811684418461821EC816CA24008184008448CC914C28274100418516F456C720A424911A021902A952481952492D634414222E4189722212543280D2284488052C9844804421488101001124444A024422 +:8027000041131202AB1200228001450248C0423EDB60284840088C119441F0831840081C08241214A082418122BC082A28E412384244321014A82110081111141115B4832188E4115821883902188400438182E112F8F579409418121524015230114582111121911584141218421418211849C9428470144188642118228AF44428118C1E +:80278000A421288A02004682A924841A046C2892E270428A62412342B67E0348444C0200222002E02208218008421344982288203221212800224CD88242114482281484088085C3284951218008104218342812002914F8C3561012512818490485865118100812816161C114C48031221F8861148001142C381515082CF844138445A2C2 +:80280000290011C11902118F19029011111281304829A1282C0281216BC660C1504181846C04442D4481D0481198648100168612C488412532841880D88448240848262118441884542246682564982C06C01646826284230660C463150421F01D44244F243492474149B1126421DB614D514511F411141592225C6C3143741A6A141E4566 +:802880004AB692A182167A12ED1AC2442B1245E544588A5AB14CA1A2EF15B448F8C4721AD368B124F219245E427F25C2843F81227282F1A1A21DC22F4C5C432BD287C3C5D2E885E7269224C752497B674261428557A2177485595884521FC5D35341E81498117B119FC2711881F119142B14C7324F22F814181F12B18DC4868B2A481B2E1C +:802900004F1B7541B526E8A832842E12824034333B9165F925142E4D4B1B4F72C4861E4821A791197118D92452242F423236E7872B112E141E4A86FCDA84D012B165D519723A38652A7442772B1EFA2888A5F23A28C54118D6417A25F5862ACD2A3F8158194CB248EC26BA44E42449FA128A85B8A4FB894F3AF4184C1FC8FA34761E84D7E3 +:802980001E948FA8A44C8F888291218B1CDF9DF761925AA53C85E82675189C525ED84A626845344818A7266DCB8092142849810228803244284A084A48A8842288118120241808104194118110088100228426416812404108122641486181A88488908848A81A043FCF4AF243213E3BAFB2F23B7E8FE8F22F6F3FD7F77374BFA4F4AAA6B3 +:802A0000FF96F6CBD8BFEDFD53185F4DFFE7F6ABBAFF869DBABB143F9CFD6D6D1F1CF971A14F7EFAC3133F11E121F9CB829FBDF88B97A5F6DEE68F8EF4A8A62F29F8B2AA8FB1E2B9E9A1F1A6BB6F62F2E2F32E263F5ED233F35293AF8B7984F845EA4FE6B6C6E827B192EDE8F2A2444F4EFEC4C44FF774814CF241255F7652B9F7E4BD2F9B +:802A8000FFE3F753541F71F17A7C9FF3F3BBBD9D1BAFA7F7C39BEFC8D8EEF14A58CFA2B912FBA8B27FFCFD4F4D17149F3CFBE7A73F36F2595B4F6DFDE6E25F7FFE5347AF77F6F6F6EEF32FEEFFD2C62F6DDD75F216145E5A6F2CFD22262F2EEFEAFF73757F78E72CED69BF16FDD6DA4F6DFDC68C6BBF2F8BFFA62C6F6AB4D6FD9C94CF6A62 +:802B0000E13E45F273566F7157EABF61F12A4C5F64F653543F45F12B3AEFECFC1A1CBF82F35B3A3F89FD191C65F61A18BFDEF58A3DBF98F8B3B9FFD3F3D4D41F1AEB7EDE22B862F66467FF3DFDF9E9DFDAFFECCFEF6FFECCE84FA1FE56427F7ADEFDF2B5BF9FCCF8F9EF7F67F6A7B71F4FFA23B43F74F33333BF81FF951DDDCCCFCAFB9409 +:802B8000D44F6AFF56748FE4BB72F326644F41F1A41E3FF84AF273565F71F73C3EFFE1F1B3555F65F773345FF1F11E1CDFF6F69B999F3EFF5A3A3D4BEFC8F8CECEEF87F7AD1F7F58F3E9AB7FDBFB3F3D4F4BFBC9CB7F7AF862628FA7F7F577FF37FFF9EB7F69FDFEFEEF6BFBEDFE6F6BFFF6627F7BFF1D3F7FDBFBBDFD5F7BFB73773F7A84 +:802C0000F9F9FD6F43F543F71F33FF1FDB7FD1F99FDF4F62F37E3C6F47F3AEFCEFC3BB72F33674CFC7F7AC8F3B96C0119016D022014D111E4824400134400744122008112048143248902861422B92816B823026302250249014124522098260890044128584440444F09E9610169118D01CE1414422511CD0280189018D1412348485971D +:802C8000448DB1128F5432A146048B216B4214D88D21411A02A0D211472296681215088A521A1966221B41421125E688D428234A220B823886F85FC4F024421F41F22C121F41F268111F41726AD241F26E111F48F66A921B68AF14B985F44A914F8AF44AB34B4AAF347B24D812F924488D914FA2D418F8244A16F5264A87592E5A8759ACF0 +:802D0000F49824ACF491242E421F497228F2912CA3F6912CA3F4812CAB141FC1B26AD981B24A7915B84A7924F84AB24782AF247924B84AF934484AFB244A6F5D044FA2B411F42C5212CB1613316A44CB121F49F42A848E4489BB84969A5F8994AA4B488BB447838D8563DA58F1265A8D914BC28D852E5A87482E528759BCF49824341FC91A +:802D8000E2A2F411642AE9C932281E2C29E8C8B24AF1112C2F46C82C2BB44F81B24A5984A97B24B8487924B8487916A8A46FA2B1CC048282480000000000280000000021008008002840010080040000004004000000005012E01F0BC0221508531601804181112128840112A48D838110C4644014880600243024844436C29288174100D1 +:802E0000C022002022880183622143180200D01CF2EB5190411B18242A014C91442501248420411FE8485381208192818922113481415991281911D84139282B81D0123142405C8230361608C06927888044064F2814382818C542286411F063AF10B1E141A8211D6419C144141814C34101C7348B21281651281E81A95221C9B224751289 +:802E80003485C3B825C12813011B8199B23648D82F21B54258862D15F012248428218B246388A24A4D12D02422318A18A4244216311A972D800425034044020021800930948110088800002004404814020022128884001800118100008E488143121214083024EF97082011021C11011A62141B411812A51104122D144838120042220045 +:802F0000444021B2D86282CA3222C01200108A1608216822122484004222188221A24624F2AF196051436213188934244F9162644002230685D1147444885C182094458A5284948B4822A3B428D148391460418484211B28248885A521008D4130128823162244E2C568822D882F22C428CBC36082E0490B15043B21301844DCA314141BCF +:802F800014244A111A1121A48183044A1124C244268144022A7195086668418C1E0A1902502D8C23041304422AA81440088B94A48F22A8122D882A8DA842222F9404184C0312469121D0248204298112514849341C6914810319841848C88822C914082E148A312860228059228800228481212B1270224282046162206422C122C1F0C99D +:8030000044D084016C028C426244921C021042B429218101478400800498200248460248118341943311453811280040048B12AA146849147048146C248420618840F65B7D248914417934210400524C9431484443465412440089611289189C18844328A5211148231392210012AC51482C2921018531118091224C02C126022280512262 +:80308000482604AFFE0F1922016041254598A400400888E088C24212124410248612444804188341C8448044A2420025010028210048212504008514040081C88F8145925119C1221D14464C57842E141661441A52827094011C42B21C2441044314B4284854484AA1211C51288B1225E48182342133741452283C2321014D2111181A969E +:803100006A2349558426144A5248182331488CC286CF74024382541C282E122004624081048CC4169668440016C82186B8480281224C8824945242485024122A81D4142108008429C128884002C048444F820400824448D7F16044492222149438291298122835481142312281211016180210086458647048022C42448201182642448864 +:803180001478120200A02180A1184784188A1188E882210AED7200218C84020028708104008A024346280A13122402130232882688342412004906004430448429044518621410588485440420024248E0A2F47C730018128345112101448C850E88800A491894814188844AA841008034882088A25893214821085024C42284528D42206B +:8032000024C441001092482A2411742408BF360613035014A1859428464508181E24422893149961100410942480014902121A0815482152144A08108808541684021400504180C112414184182C81F874BF2420C322868491121042982210022110022184A9110810084082C142403A1C246024004B212C2404255822420080D1844108F5 +:8032800041801898222240F8FF32008004C12C022C42512440A6242C864402C73440021008409C42882311983211A585147264280125C42842109488244244212081B422448401449012F04CDD50244C544811001001002A1888018885012008548200190811224C14051444841845880400C2421614020000812024C2141A2818C244DFAB +:803300005C0C828601408244024582F4441240924124D02464818512048181008091829012812112A1702304814227224449422832848504C430428422424CA452816141F085331484D041B4183221450130318C814214C528901140912190283046483890844A410880C8491B81534548810C14004091481A7262C5412F1112112651222A +:803380008129684286D82A28E23644A221A285D6617228F322282C127615F3B24416B222C24237842439D279F4162D24291BC82446B44882C2356E46AF48E226B4426221AB2256F622388512E641B1244AF6AA24AF84246E211E536CD41581E6C45544434464A427218F820D5E168F8D989466E2A94811F5C11449F2344115F41955256803 +:8034000086A554946F1C8639AA8E113B6E87D1633C49778815FC822CC14B8A8C0524414ED38B81CFE18459A1CD984E825DC517188885126C9441D1C9F12E2C212904149F11519B526F43A454474547C5ADA84F42A12229761F0146B61662938F8471145824321D232E188F24E3824163542C44C8C22668288D25C502948D48117084B8120F +:8034800021D182A118A7D21E8529F41D452B157E649116B442D42444D6E276422C7CC878683241AF2162841E16C78838412F28B2A837A42887E9CD886F990A8001004A0142800888800998224C299298228D952285214AA51214228691148B28A028A028499121B081021F8802199284288816088C44244A04801488048F5F4E53131F31C0 +:80350000512B39F6C86EBF75F3434B35EA25F383677F3DF55372BF6EFCDA5A3F39F166337F3FFFBA22373BBD2E2F99FBA1A115F198A91F18FAAD3B1F31F56222BFBAFF4B4B2F22FA2AAAAFAFFFE862EF4AFEE6E457DACFE27A26F36A677F5EFAEAEE6F72F3A2B1AE219F8DF7C383BB8875F74A786F26BF72AFAE2BEE6F74B122FF54544F19 +:803580004D4DF2BCE6342B331FF6762BF23B3BAFF5F74B2F3FB4F6436B2FB5F7C33F3F7EF7C3E2BF297BCA7A8AF2CF93DFB9F9BE2677BBBFC9FB9ABBEFCABA6CF6CAF91F18FAACAA6F27F643C33F3DFCB7E7AB91AFA2FACAEAFFAEF6577F3B771F1FF72CAEEFFAFEEEA55F54F6696DCEFB6F56F7C361EFDDF7C3C3BF8EFE4F4FEFC1F12E28 +:80360000962F67EF2AFCE2A46FF6F722FAEFC5F4D4D44F61F1E82F346F64F437773D22BF817348FE3B7FAFA6F67B7AAFA5F12BE23F61F1F3F1BF14F64BCBB734BF3DFC4353EFF6DD3EF29F9E2792EFC1F1F4B89D5826D1ECF872723F34B44AF1CECE3FF3F3BA3B6F6DF762E27FF5F767654F49F53DBD6F68F8E7E66D64FFD6F64A64BF4F1F +:80368000DB5CFE797C3F34B65B771FFA4B5C2FA6B472A267EFCFFF2E4A2F8FFB3EE84F49E92EFFD829346F61F13F773F21F31B3FA7FCFFD3F71A1ABFB3F35A5BBF67FB11123F36F6DB93BFB57D4BF35F437F3EFF2D9FFD2BF5FEBA99FFD3F3DC9A9D4826F12DAF6F61F4D2123F3FFF7636BFF1F1AA2A2F2CF562B27F75F5E3E44F4BF52DFF +:80370000AFE7E6FF62F64745EFCEFED8DCBF47D355FC7A7D3F34F65B78F7B1FF9555EA2F63F66446AFCAFE7E5E2F8FFB3E7C4F4BF9647E97F8C011C011842941E81241186481144081041D4844848504441287440060443048004181180000108454244880442248A14120011A44A448852448046B8120E241322216F44E111A7242128128 +:80378000813622482D1219D422014A11D1220118844200241210182251A2812C3441581285022542180889012B84288B14112544584210628229219838223F8D052CF411248D121F417248F11124EB141D24AF14F18124AB941F88B24A3985AB9443FA4AB143FA4AB5478AADB14F8AD458FB244A1CFA244A8F51F2245A9E252ECA8F59C214 +:80380000DA9E24ACFC91242CFC91248D931F497248F19124A7141FC8F24A111D24AF14B911B24A5985AB944782AF647924B8427924B84AF924484AF9244A8F3C05A41D648F22E14136481D24EB144CB24AF181242F46F9812C2BB45F88B24A3984AF142BF84AB54788A9BB82D44AFB845289D324DC48C2529E24ACFD88243CED49C2CB1F18 +:80388000C8C2DA1F48D624F9916C83F4912423F4812CEB141F41F24A841F81F24AB45D28A96982AF447124A8144782AB9463A2946FA2F12EE30082480000000000280000000021008008800140010080040000000000000000002501BF7B0E1001502818803242822C0134207428041800100400000023049024604A1822281489C1242021 +:8039000022018C21B2480142A622043028208C21F281281033A23016485D2881805114111B8184130480918410047270484432441285240216282411C811424068212C049C0446C8434820082144001A449684875214641F7706312F1C026331484D288032425938141B818511A124898291140024723054244328918C28231438412281BC +:8039800097425262264891482992412218116D4828AA05424C82044A61E245F22844167112F61C3A0000403211818001344082044120084110048480040020011604920020911244813048481810082182210080388120F2DF6A10421406005041004A286814004188C0838A44212804100410080040021844A0282C088144250200400809 +:803A00008421848100828564885F510B4E25331151121042B14211718201462378C2D11418528323184CA2181068C88618420241216D288800A8C082822C21643188A18C2881A482C014216381C8828281B04481082E532424572134004072544141A1848288884C584284884C187212014884240021A4248400200880282A341323186CEA +:803A80002812480064504280988200988398882F75021D641014012111408208137443C24111241D8210A9848882844C9888410044302482408222C186809182400AA1002A088C018D1282848181C04444F0E5BA60C4501484688042820220C48480820200248881800844491544C228200100401802448A321821100824861C02B0416286 +:803B0000C1809142493484F098B68002283504001110A868C04442288F2138882008A08238298108002212006082124827848144123084850110014449210841214604A428C01AAFB6051164842444141218142001212C084224852182024444904400840085128411120400001440140238200118813100880048F0A5B9144E25644D2837 +:803B8000B542440116C1218468B08244028B2186581A0082C3E241024B84A014C42682421884D1829214482512084CC1A1C5521410B811022F88311610B824544A496429E04402D0830880C4414462A01210029848A048A04821802A12220882908444008C01290100004004804918020000981022013048E04448F8E2BF00460C4088146B +:803C000048042F110C0048E06884048024422852862942024140489288240000829088182140081018088018082484301820F8E23114006125240210080021481CB28204208846220400428022A82441211230848384215424002001822181250200001082280440F8ED5440010000000041100400000024002100248120091002248810F9 +:803C8000480280289882000024004440040024F0225A1012134211626422104386C242001121D024028C02490220A22860220028002418460220044810022D82D042140444C82129082D82448841F0247400004110146211244184882480020000811008400841001008830824008048C81800000084004008008301F05A676044508448DC +:803D00005110694469848844020080022C021008C18088481214182A180A4810E8280484008608004C482808400884100821126F86010028144001208204211480880862A1A228A2290686022A8422224262441012E2410448100441004508E4002100424011022924D88C0563388100860214001400460213042120141808812221502207 +:803D800010281808814022280424408A484808444042480460888440065C01AFCD0F22274448A35487400441241454881C022100812502100249818228110422400118848004200148E0A814C88441E8002504448481708202D54E9242231CF2474147284191463842344634422DC23561222514A222842BA283E4427228722282A2882D13 +:803E000022418147A2A7828954288829B4C20D8E8827244C4898828486221804C0484442214608144696185489F8A7DB1415F68145C506444E424D29645D24535418114344222408648F2406212D8848457842C42822235246822427482538844216324224100A44AD8288894CAA84A542022C18B88258C8AC58861AD8143D12FF310C43F6 +:803E800052A428E4B79215149215242F49DC22C28211481F18CCC22A243C228D4A2E28818C52482E822682D468AB268B8128AC0925EAA14194484160888F25B198A1488558E2A1A7A845BC88182658C4855224A318484822F87D4DA024C028412843848281969468880000800888488848A848802481E449822408860486048604862444A8 +:803F00002444A484844A084A18A484418841884994884B41F0E21234777A7776243FA2766A7A61E194F471732B333BFA7F18F18B891D471F28D82134826EE22F2E74AAD88AB4EAF8C8888F8AB848E66CFA6A282B336F67FEF6BCFE943E864F6CFD888ACF88B81EFDD2D26FC8B88438862FACFC96944F49FC84C4CAFC4E84ABCC2B4CAFAC77 +:803F8000FC488E6F4CF4C446E7888FC4FC888CF7C8236C444F48F8C442CF2D0E4762FFF2F422267FF2F66A4F5F52E482F2616335F5C7D43F5AFBEAEA3F38FE838329B622EA2CFCE242AF8AE2AAFEEAAAAF86F268688FA5F7C2A6AF8EB352F7D4666FCEE26EF8BA8E9FBC7D84FE8C8B6FADFDD6D6674C4B886B8C4F6CFC56D49ED2AF28B4E1 +:80400000C27CCCDECAD8A8F86AEAC7AC2BA84D86EFAC7C8EDACAD8EDF8C68EEF8CA854DEC4EF444DF347673D47BFF2526FAD2E7D47EFB6F64B432F44F497C43F47F62B291F14B6C1F8C1C2272C2F22BA227868F8CAC8AD48A5F848488F8A8BF628AA2F27F62636AFEAB6A6F874624F787988FA888C2F84F5D4D62F28F4828625F2868EAF68 +:804080002DFD929227246F4CB882D4CAD882F84AA88E4A25D22658E2AFACD48ED886D8C6F48A885AF584127FEF44F1C567F557DBFF76F24A2F7774E5FA7B733F56F6D7C63B4DAFACFC43433F3CB8E2BC62FAC2C22BC687868FA6F6AAE8AF8AFA28288FACDF22F63AAA2B234F66F72E6E6F2BF97EC28FB859E69FE8B852ED2DD966F4828688 +:8041000023E82CFC16966F69794AF2C6842C5C8A8FACF44A288DCA676A2F6CF4CA4EAD8AE57888FE8248A5F89494CED6BF8D0326011440022623412161124002244800240000002128299128291108810021100225424842088200248224822482200882003FF90A24442415044C1444484244128128482142024018088141001004002DA2 +:8041800012400858000012008D821008A908008110082184009F780D2CF41124C5F21124C7141FC1324A1D24EB141D24AF249921AB9451AF1439A4AF5439A42F7479A4F842914F8AE454F9A44A4EA14FA27458F1244AD6E1A2645D2D4A9E24ACF491242CF4912485F2912C83F49164A3F48164AF24D141F64A921D68AB9459B44AB924B4A1 +:804200004AB924F442924782A9F9244889F9244A7F480FA41F45F22C421E28C3F61128A3F41124E3B211D642D8C1B6489B64AB9443FA4A154B4A2F54F3A4481C73A6C8356FA8D118F3248A8D814F2261182E189E25B49E21ACF49128ACB49146F29128811B29A11B28A991214CD981D2489B25A93924A939242B9447828B946B438B846F3B +:80428000AAF55C724028880400000000A028000000002180018800004001008004000000400428000000002501BFB70D82001110114201248810082502218008005048211002009800804806000000000000000000888440F29FC5008200000082190211004A08002141000000C02600210010028810028200880000200494200118402140 +:80430000D1984C01C608144003144012142102290A2124104402301A218230244082180124812442240000200841200200850112C0928114216FFD0D00000000821982088160240080080010042440022001008241820020080000002004000000007F6B01000000421048840121000010020014000000000000400444290840240429018E +:80438000210000100200007F6107100114001004002880241884089840048281400222144218008441120000800100200242211022020000844FA60410011100424481410021801824082B1800908184002122114812004084410464880044002110C242002110020040F81339000000000020810248000000410000000000008400000011 +:804400008001482021020000220000002F650700000000000000293188002100000000000000000000000000C048000000424800005FA307201208218121250800811011218454422A2408280080020040544221000028404481D84202200200008018140880013F3D060000000010E222040000001008008A0200400100000000000000B8 +:804480000010080000000000EFE206008110121812480268214031138608412A94888002A8000011000000002200118228009048840000884914088001476E002800002400008400806424100200002002004054260000001004244400220000000048000027DE00000014008400000000000000000000000080080000009028200200C092 +:804500002800180000F063DF000000000000000000000000000000000000000000000000000000000000FFE40F000000002400000000000000000000000000400200000000000000000010081F4406000000000000000000000000000000000000100200000000000000000000CFDC09000000002400000000000000000000000000000006 +:8045800000000000000000000081F063C50000840000000000000040020041000000000000000000000000000080020000DBC40000001008000000484004000000000000000000120040080000000000800100004F54030000000000000000000000000000000000000000000000000000000000F04FFE0000000000440000000000000054 +:804600000000000000000000000000000000000000F0634900000000000000000000000000400220018200000000000000000000000000F0EF63000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000210000000000000000000000004759000000400840040080B8 +:804680000441001002400400218001820000120000000000000000280000E0280E00400800000000000000000000000000001002000084000000000000180000F09536000000000000000000000000000000000000000000000000000000000000FFE40F000000004005008004440010024004002180018828100218800884000080420853 +:804700000000280000B014010014000048405588281082044480022100448002214818808802214818448828842148408481421882041E148002211A01445C03000040010080041400000000000000000000002800008008000000288400000000BF7405000000004005008004440010024004002180018828908280018840080000288492 +:804780000000800200003F6A0C0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0021001400004800800221000028000000280048000000484004281082044400108204440010F2448D0000000000000000000000000060 +:804800000000000000000000000000000000000000FFE40F00000000000014000000000000000000800200000080080080020084000000002F3A0A0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000008002000000000000280000000000004F7D0200000000000014E6 +:494880000000000000000000000000000000880000000084000000009FA3F7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD8 +:00000001FF diff --git a/kernel/xpp/firmwares/FPGA_FXS.hex b/kernel/xpp/firmwares/FPGA_FXS.hex new file mode 100644 index 0000000..1321a53 --- /dev/null +++ b/kernel/xpp/firmwares/FPGA_FXS.hex @@ -0,0 +1,648 @@ +# +# $Id: FPGA_1131.hex 5122 2007-12-12 10:07:59Z dima $ +# +:020000040000FA +:80000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6AD6FF4000F8030A006AD6FF4000F8030A006AD6FF4000F8030A0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4455544455557475577775577675577775577765566665563625523235D2E37C2B5111155111155111155111BF +:80008000155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111000000000000000000000000000000000000002552222552222552220025522225522200000000001AA1111AA1110025522200000000001AA1110000000000000000000000002552222552222F21F11211 +:80010000122F21F112122552222552222552222552220000001AA111255222255222255222255222255222255222255222255222255222255222000000002F21F112122F21F1121200002552222552221AA1111AA1112552222F21F1121200001AA1112F21F112121AA111002F21F112122F21F112121AA111002552222552220000000087 +:800180000025522200001AA1111AA111255222255222000000000025522200005F51F115151F1AFAA1A1000000000000000000000000001AA1111AA11100000000000000000000000000002552220000000025522225522200002552222552222552222552222552222552222552222552222552220025522200000000004AA4444AA44402 +:80020000000000004F44F444445F55F555551F11F111114F44F4444400004AA4444AA4440000004AA4442F24F442422F24F44242000000004554446F61F116162F21F11212000000CAACCC2F2DFDD2D22F21F112124F48F884846F61F116164554444AA4446F65F556566F61F116166F61F116164554446F65F556566F65F556566F65F559 +:80028000565600000000002F21F112122F21F112120000004F4CFCC4C46F6DFDD6D62F21F112128AA8882F21F11212004F44F444446F65F556562F21F112122F21F11212006F65F556563553336F6DFDD6D6006F65F556566F65F5565600000000CAACCC2F2CFCC2C2255222000000CFCCFCCCCCCFCCFCCCCC008F8CFCC8C8255222004FD0 +:800300004CFCC4C44F4CFCC4C40000004F4CFCC4C44F4CFCC4C44F4CFCC4C400000000CFC4F44C4CCFC4F44C4C000000008F8CFCC8C8AFACFCCACA255222CFCCFCCCCCC55CCCC55CCC4AA444EFE4F44E4EE55EEEC55CCCC55CCCEFE4F44E4EEFE4F44E4EEFE4F44E4E00000000CFC8F88C8CCFC8F88C8C000000008F8CFCC8C8AFACFCCAE0 +:80038000CA255222CFC8F88C8CC55CCCC55CCCCAACCCEFECFCCECEE55EEEC55CCCC55CCCEFECFCCECEEFECFCCECEEFECFCCECE00000000CFC8F88C8CCFC8F88C8C000000008F8CFCC8C8AFACFCCACA255222CFC8F88C8CC55CCCC55CCCCAACCCEFECFCCECEE55EEEC55CCCC55CCCEFECFCCECEEFECFCCECEEFECFCCECE00000000CFC8F85E +:800400008C8CCFCBFBBCBC3AA3330000008F8CFCC8C8AFADFDDADA2F21F11212CFC8F88C8CCFC3F33C3CC55CCCCAACCCEFEDFDDEDEEFE1F11E1ECFC1F11C1CC55CCC455444BFB7F77B7B00EFEDFDDEDEEFEDFDDEDEEFEDFDDEDE000000008AA8889AA9991AA111000000CFCCFCCCCCEFEEFEEEEE2F22F222228AA8883AA33300CFCCFCCC28 +:80048000CCEFECFCCECE2552220000EFECFCCECEEFECFCCECEEFECFCCECE000000004AA4441F14F44141155111000000CFCCFCCCCCFFFFFFFFFF3F33F333334AA44415511100CFCCFCCCCCFFFFFFFFFF3F33F3333315511100FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000008F84F448489F95F559591F11F11111000000CFCCFCCCCCFF9B +:80050000FEFEEFEF3F32F223238F84F448489F91F119198558884F4CFCC4C4FFFEFEEFEFBFB2F22B2B955999855888FFFEFEEFEFFFFEFEEFEFFFFEFEEFEF00000000CFC4F44C4CFFF4F44F4F3553330000008F8CFCC8C8BFBFFFFBFB3F33F33333CFC4F44C4CF55FFFC55CCCCAACCCFFFFFFFFFFFFF3F33F3FF55FFFC55CCCFFFFFFFFFF03 +:80058000FFFFFFFFFFFFFFFFFFFF000000004554444F42F224242AA2220000008F8CFCC8C8BFBFFFFBFB3F33F333334554444F42F224244554448F8CFCC8C8FFFFFFFFFF7F73F337374554444AA44435533300455444FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004AA4446AA6662AA222000000CFCCFCCCCCFFFFFFFFFF3F33F33333ED +:800600004AA4442AA22200CFCCFCCCCCFFFFFFFFFF3F33F333332AA22200FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000CFC4F44C4CCFC6F66C6C2AA2220000008F8CFCC8C8BFBFFFFBFB3F33F33333CFC4F44C4CCFC2F22C2CC55CCCCAACCCFFFFFFFFFFFFF3F33F3FCFC2F22C2CC55CCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000F1 +:80068000004F48F884846F68F886862552220000008F8CFCC8C8BFBFFFFBFB3F33F333334F48F88484255222008F8CFCC8C8BFBFFFFBFB3F33F333330000BFBFFFFBFBBFBFFFFBFBBFBFFFFBFB000000008AA8882F28F88282255222000000CFCCFCCCCCDFDFFFFDFD1F13F331314F48F88484255222008F8CFCC8C89F9FFFF9F91F13F35E +:80070000313100009F9FFFF9F99F9FFFF9F99F9FFFF9F9000000004F48F884846F68F88686255222000000CFCCFCCCCCFFFFFFFFFF3F33F333334F48F884846556664554448F8CFCC8C8FFFFFFFFFF7F73F337374F4FFFF4F4BFB2F22B2B00455444455444FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F44F444447F74F4474735530B +:8007800033000000CFC8F88C8CDFDBFBBDBD1F13F331314F44F444447F71F117174554448F88F88888DFDAFAADAD5F52F22525455444455444DFDAFAADADDFDAFAADADDFDAFAADAD000000004F44F444445F54F44545155111000000CFCCFCCCCCEFEFFFFEFE2F23F332324F44F444441F11F1111100CFCCFCCCCCCFCEFEECEC2AA222002A +:8008000000CFCEFEECECCFCEFEECECCFCEFEECEC000000004F44F444445F57F775751F13F33131000000CFCCFCCCCCFFFCFCCFCF3553334F44F444441F17F771714AA444CFC8F88C8CDFDCFCCDCD1F14F441414AA4444AA444DFDCFCCDCDDFDCFCCDCDDFDCFCCDCD000000004F44F444445F57F775751F13F33131000000CFCCFCCCCCDFF0 +:80088000DDFDDDDD1F11F111114F44F444441F17F771714AA444CFC8F88C8CDFDDFDDDDD1F15F551515AA5554AA444DFDDFDDDDDDFDDFDDDDDDFDDFDDDDD0000000000000000000000000000000000001F19F99191DFDBFBBDBD00008001000000000000000000000000004001000000000000000000000000DF8D0748000000000000000E +:8009000000000000000000000000000000000080020000000000F01B24000000000000000000000000000000000000000000000000000000000000FFE40F48008001000000000000000000000000004001000000000080020000000000F089A2000000000000000000000000000000000000000000000000000000000000FFE40F28000013 +:8009800014000048400128004840012800000028004800001082040000800400002148000010F2BA5E000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE80840180020000001002000010024001002100140000001480028E +:800A00000040818802000088280000F04CBE0000481800000012000000000000002001000014000000000000008002000000003F84054818148002800414182810820416012810A21140012810A2414001002B11484001280048408188022148008828108204F05C65808401800200000010020000100240010021001400000014800200F6 +:800A800040818802000088280000F04CBE000000000000000000000000000000000000000000000000000000000000FFE40F0000280000000021000000000000100280010000400100004081080000000000002F6D020000000000000000004002001100800100000000002200000000000082280000F0293D000000000000000000000095 +:800B000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000110000000000000000000000000000000000F0726D0000000000000000000000000000000000000011000000110000008088020000AFED030000000000009B +:800B80000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000230120010000008002000088000000000000F036AD00002002000000100200001002000000000000000000000000000000000000F0DB150000000040020000000000000000000000000000002002000014000000800842F03E +:800C00003C89000012000040020020C41212000000000000000000000000100100000000000000F07CB2000018000000210000901200000000000000000000000040010040010000008880045F960900000000100200208401000000000000000000000000280000000000000000E03A0F8001000000000000000000000000000000000034 +:800C8000000000280000400100002008F0C63F000000000000000000000000000000000000000000000000000000000000FFE40F000000000000200800000000000000000000000000000020040000000000B0440A001800000000000000820042000000001200008002290100002200000000008800008FF30A0000000000000000000062 +:800D00004200000000120000800200000000000000000000009F3901001800000000008200200800000000000000000029010000220048000000200800E0980D000000002240020030110020080020040000100200002100000000000000000000E0DA0B00188001002C0800000000000000000000000048A2000080022004480000000033 +:800D80004200F09C7F0020010000880000001800000000420000400200800A000022000042000000004800F09B5200002001002C02240000110080080000000000002004240000002004000000000000F06BB7800380220100001122230280081282249082C0110080140200800800200180082824002800008004005022EFA80E800200CB +:800E0000000080013A0812308200002180018001882011012002488880040000002848000000240070A40A0000001828000000800110A1280018480048808401A021004800880022000028000000000020F4653A80830200000010C1221A0812988218822221202104206524C21812802188220488884280024002220000004200002CF42B +:800E8000FE550000281880810280010000214021088210018888000080020000120088200200800400000000F0A33220822102000000000000280000214200880038220022003440A21200002268800400220000004248FF110B000000281C02291882188288031880111222082722242C8128822428250C82200882460128240000008043 +:800F0000020024808404F04D86000028002800A8000028222082288204100212180048000022800220080000800648224200808204007FD60C800212000010828182810218003082188821118E528028010012000012122001000000800200220000009FFF0FA021282001000016021200201201008004114213042A8484A428284081420E +:800F8000828A82220442800414000022002022041CD45D0F00000000800118800200002C020080210882110000001002000000280080020000002004AF420822112002001114001988C22182800114400121121800428098114820081B841B1211002286C28182002082022840022200002F520D0018800180021825820100180088884278 +:80100000001002A0810020030022303220238488060000004228008002006FFF0B00481C01001001400228802A8808800839188109982800001420018084018200210024E01412420200100221147FCD079011181382010024A21AA1883A21888201E031288A1462342C02211AA123484AAA113A2A82081BCA211BAB2B42B22830418262BF +:801080000020848284022180021442F7E4000038002A12011E92242B1110A182128814C0A223A48830122D415848988044A1140011303129418121A4888A02001B462111A0268002224A04006FAA062AA2232A222101E0125211212117222120A12A3AA32882211E81805C118E829A58128AE41623A8448A842228C3232C031A83A24A242A +:801100002934226800224823022302242823A2444A84F4E6DF0022A012000080082C08888022011180048A0419041828208821088214822B128218A08660246024601420042800C0220020E4A8012817111AF311218880F2212115B312B892F191119AD9112828AA8A171815F122A23F14A4CC1F14EC2CF842428215A1C61F1EACC41F1594 +:80118000AC6EAA8AE811F9C1411F19A22ABAAAC84AA4C43F1EEE2AFE42622B441F347443F141432B444E422124212382A44448F08DC580F251611AD11187012AF2212115F392122B993F31B912DB1128A8299A798141F222A23F1C9C421F14E42CFD42432BC41F11A1921F1C24FCC1D11F16AF2A86A1991F36FCE2D22AAB72EAADE64AF813 +:801200006161EEE22F2436421F34F443611F3494426E6229421292224E622B444829F4459980F231511AF31121002AF2212115F292122F21F111831A7B8181A81AAAF981811D832F22FA63612BC81F14EC28F98383297811A147171A8217116EE1A2821B111F14FC13612B82BAAAA8CAE62CF8E1E32BAA6A26E424D413F241432B446E42B2 +:801280002342522226B242B4428424F4F52D80F231713AF171311A092AF2212115F312922B193F39B112718181A82BBAA9881D832F22FAE3E18AF8C1C1CE823F3C1CF21111AAD31182F81191BE712A92811F11F9E1632F2BA73B7AA3DBEAEE28F863632BEA6A064E4237141F3494426E62294252222E222B662B442CA444860D0000002215 +:80130000402201922008000000002004422084282402888008260100000000000000004200D0AE0522122A0118004022480200208102248002001002182800980060221288A01200A08228000000280080024214EF14042AB41122B211A2141B212394212B1619F2629219B24239112B94322F142BF342B1322D912AC4912E421CEA2264A2 +:80138000112F22E519E222E519C2529AE222B4D1E222B491D222B191F262111B2923B481324219B26298212B84112B84222BA4222BA42229AA424AE822F4D42580B411C4411361141B212394212F1491212B9419F242B1112F1429FA428113B84238A129B8A384F1A152881B4A881D42821F2224C9439E212C244DB39186A4294631112F9C +:8014000024A828273419E224082F340A2F34082F24082F242892822B42296822BF6C0D2088040000240000000000000000800800000000800400000000000000000021F05EA100008082522248002400003200822800000021112001246A0828008002002200004200000028A04240F1A17E009200000020040024000040A22122824A0214 +:80148000422081A1241901202428840180A428488820880400004280040014F0E43F00D200C02280044210224202180082266223228272602C00186A11512120842824054848A848888088042A040042808442A224002BAF00002002240000000022000000000090110012A02C8002002800800200000000000000F0EC580000A01200123E +:80150000000000003081000000000028190818008008001800008A0240010000002820049FD608288002001800881200820022002100000018160200006A0138A012800228200820220400000000008FEC042880021A021200880000002814000000000022142001002880031A020082009041000000200248F0DBF8000000001200180082 +:8015800082008048020000001816028800A043800900002200A280020000000000D0710522002081082800002280018001002180010062409221200100001200820024282228140000002200F088A88001A02180010000A0820022822800212928C1130012240010012391218024080000000028002200001002F0D7FC000000824002009E +:8016000020010000922872000000008001000020012008280000000000000000AF67031A028001002221002001208208822223031824001268001B1200121902001880280800292202142002000000F078ED000028181200000088800120830142821001884002240012210080090080020000000000800200BF310CA0210000802202000A +:801680002430228880582200000023010029088800822225F1228100118828220028000020020000F0E21D8002148082C211180000181218111800004002423031824A081A08208482A1A40080080040410111004848200200F09EA900002004001828122C0121221022012522818101248260292C0100880040028288001012021002217A +:8017000021002110120270E20F00122820218101820080022A01221200822D8224822602001081A92428E01C028002484081C86300480024002A0400004FC10D1100800400281882882812002280810100122001009211008800A03823884142022824404202404202400200224E148002002001002001800A0000001002182813240214A8 +:8017800000000025011C0200248082621248281100000000E03107A012001902001440011CC1221120410114234491428813082A193182004282484248A2000012111411114228482280242434420000BF9A0920880120020088200100000018120000001800000082880000140000004021020028004001573B00800488000022800828E2 +:80180000802202204222911282291181081941A181E01421AA2414800486810848002C8444C16211002C02190410022FDF0928BA2221A2282AA2113A2122182121422251211286021400A0811C9821122C3812868181A8844AA64CAE61489AA882863181401331221D216E42141512512260222B262D431042013FB9062282002AA4111419 +:801880003011B8E02889B112B8232208141AF1321258988A04272C2A9132B234121F1908BAA48A224AD832C823821A481112A228172427241C3222230410B2428684120214F0DE5D1081C1113041008022A291701182012AA3323824701262111E122728B012F821411CA19C39089A0480DA21B1A1322219024AA8811B4223C22110A144CE +:801900001CF42221A04400420020F2443110A1121130812A110111221130112C081C0A1C083C8844A141142984820529044800122212271212141223044A088004000080020000F0DCA41415D1111151111F14F45161111F11F111111F13A99117181D9129F183911B821B998217183F1AFAD3D14AD411F1C1C3CE821326E126EE25F151B2 +:801980009115A144A0391E11172917321F3BFBB2B1CA54312F21DD22F423233F16F66163212F34F442423512E224F46242251202002E22CFCD06281F173611486AF45171111AA1311F11F39191988AFB81912B981B821B9B17181718BEB29AF983811F1DFDC1D3CAB8E1A8657E621F15F951111F11F151D1C29E911F1FE71DFED3F11F38EC +:801A0000FAB2B1DAFD515329FC81C33F1EDE11F261632B222F14E62414024AE426F462422F24542221A0223FB904221B531601881B671E111AA1312AFA1191921ABB82F88381AE21A81D81B022B312F113114AC5121DC31F12FA51512E321E5217181B55145AA5EC6E311D321F22E63AF2B3311E122BC41F197941F323232F36F663613F9E +:801A800012F643611D433553222B446E6229820421A022CF1A031D211B6316217421B1714781D111F311319A89F981931F31B112E11BA1931A59113F32B352051F11E124F483C13F12FA11217E623F19F512111F156518DABDC1FC61714E733F28E63BFBA3A14E422B911F187841F363633F32F263613F12F243411F34543325B242E42203 +:801B0000F462422F241412022AF2E348004001144001144021492149210982308142121001208401192884099880092A08001C0926814401800400480000002F5F0A26210120A24120212288012011228122812191120082108292111229410120022A082D11122C0800008002000022000040F1B17EA0421B212AB11122B611B262912115 +:801B80002B1619F242921B212F2419F14292222F342BF242B3222D913AC4912E421CF822421E212F2265192F2264192E429AE222B491E222B49152321B29421B2923B681324219B24298212B84112B84222B84222BA42229AA42882E4247B4809461481B2142133142112B14112B8419A2B4114A39212B94112B84222D913B424AA1124E99 +:801C0000811D82122A6C1C2662193C641D24D2349AC4419A42B191562219662419C282684EA3E03428E22428C2822A84B82294822CF48A29008248008001000000000000000000880000000000480000000000000000001002AF1B0A0000002001822081018800002882280000000018800100322822A0282002000000000000426012AF49 +:801C8000950960188082C1A2182822225A088214001260212412200129181211022C91A1800A820010120280280228008642822402142C880214F0BD6300C6012280022A81A28292204A2108128061221E82221212248211009083111A08882007230228800A8002222424422810C182244200BF7A0800001888290100421218000040023A +:801D0000004082081002181A022800002210220820020020080000800220F239E740010000206122820088008081041A040000001502210080010025011400000000820000002800481C012800808204421200182088888102822C0A2028021122800928802A82080082239822804802482100200888208804005F1A082800800220C43228 +:801D800082000082181820A8580000002214160200802108241182133822800880042008000088280048CFFB051100004280010012888200224280120288224001248220028A22020040020040021002008880088004008FFF0F000000002583A11200821800281824108282810280222891211142212200804202000048000022888840E9 +:801E0000821802F0AE48A0140020040000602200200220089082C01288200100108141022820018001100100000000001002245D5900000000200488004800140020040000110020012200980000000000220000000000002B9680040042008094123A682280842112810224800824882021820819022E429022382081422201400142226C +:801E80000000880024820024BFED0E1848000000250100200800800942800228881400181220018008000000000000200282000000CF9D0B402162140080220400004800202228110225020040020024001800202124021001008008002C0200007D33009041000000CA02282008222148250220880180918124001126621824288092A1B6 +:801F00001A1222938128A082190A11881120220282A800288F4203002004008001182110018005D02222083022E029022112241200005021502348141001002240012200002400F0DE1900001218122480022800101162225AA218003083D0210112008824E01102182121000014808848118108000088220021F079F50011281100281823 +:801F8000422B16200200180020A212821818222222860212221212282128002800800280028088082260224002009FD2071240010020022001400120018800100129010020021C421101120080210224288028C88240810888C0820021B08C040020410200008008004682248A8281681121141824001002108289012122601A004001009F +:8020000011240000002A0800EBF700002820012021010040222182311200000033088011A11280222802228001000028A0280020022820024021F21B4E200148800100288002C02213240600001123289211902100502388863111001429042601001C0A0090228088888848011012F265C92051112214009032128AA51128002D42187A40 +:80208000E1212ABA82A1911D111F2119029022D0223112381F2132122531223022222429E2128468121C42312182118200A82824142440015FCF0A00B051032901226A27A1222908171815B17284249412260220885231A6420212221622A2129E822C61212429F812118E51181100AA88E8122A48E118A8A8008828824081F28ADF8001AA +:802100001D21481A218102B062022200422C92222B521EA228A22B88143633223BB11F1261287081722391828A9A311A82D311C2212A3231282681B2A388E218023C9882312222AAA82A2B8A2BA2213022CF8F0D0000001002290829082908240012000010020020180200200813883181308110011110010000822400008F6F0912D01177 +:80218000F211611E822B11E023F352722BF79AEB2AFA82823D8119E822A3574AA49888F081811F18F821213551213593829AF9B1B317181E922B88AAA2AA8A98812EA33F3B38431B8C86F181233BA21B2226F121211592832F18A8228240F2A281AA0820F2C911A0114E4115F13171821E1225F212122B777EF22F2BFB22222F22D213F85E +:8022000041A12B332F27F7C2922B982BB3213F19F981811D131573A1523327282B111F3371A1E332BA82EA2BFAA2A22BAA1BE62EA39EC3FEA11F1C38818EA32F18D21192811CE212F283813BA8828AAAA28EA223AA8A002B222DA5A01119D411D21152312B111E122F23B372A77E3EB22F229222173837182F23B372632529A1AA3ADB13BC +:80228000F811111F3253221F223823241AF1212333F82283AE82AE2221E01276817212F3C2F16A9E8186D312AA22112E213CB283F882812A22A82270A231822120F269D9A0111D4115F171311F11E121B132A3223E722B7F3AABAA281738371A2B332B373E122B98BAAB911F19B911F921231F32F221823552221AF1B193172A2EA2BEB266 +:80230000BE222B232E222E611F2AF2F2A23B751BE61CE828B883B221EA18A82219FA83813B8AAAA2882AE2227A22B2A20220F22EF100601240022E120000400224122492200913091128212800213022B022012B82A082A092A0820020220800822880220800F03C62801121224121A112C012682E12000048382AC42290328009282410B1 +:802380002221021882888001250280048280820800880082200200F0868D80B411021B21421B212394212B141B282B941B282B9413F84293222F1429F34291222D912AC4912E421CF8224216E12265192EC296D122AC292CB491C2421B29341B294E111B292F14B181724291212F1498212F1418F14281222B84A22B842229A842882E420A +:80240000FF2E07481B61B01126B411324219B242B181B242B181B242A3282F1421E21429F24291222D912B421CA9521CB8218CE82264111F222CC1C39E212CB491C2421B693CB49162141B2827341B284691212F1498212F349A212F1428B2422872422282B82294822E422FCA078282000000000080020000000000800800001400004838 +:802480000000000000280000000025012F240C182800423342012448420000002001004002009042001888120080213912186024280000000000200420B2490D228A8111814882A14280C23142400210018224A0242042C22280029032888058121214882712196C120024242248402198212C02828882194201BFFB0612CA03A0482C2297 +:8025000021022B24284222240011204942A2242011A2282128002B211282142521611460191CC5116024220042221488190200E024C82114226FAA032280114112418104E01401000000000020022140220480089800C092282988024002230200002C0288820000BFF10700000022200400000088482880020010010000218088028001CF +:802580000024200210810800002C020000DFA80E48808202301218C082822118253281422022080080280821809622380022184022225212122322080021240023082008682022F241D68004282240A22112428288212C411221044A220222000011218012220120A821002828212C012928021041028008801A8202006F560D0000000015 +:802600000021008008888008002088080048282602200200230114200200242008240000200422223EE500002800000082200321888642221802292881188212018001008214002100004880042008000000212422F0F928800100800200001C2202200240012121002A0182320010010000482094120000000024280080042602F04685AC +:8026800000000000000010928200001200000000000042100224001002008800000000002800003D6980012002000020D8214202A08282256228100212882042810118003082110021202401428848000020020022212200EFC70A8084048002000080211802001C0120082428802802004800400200250200000088400200800480025FE7 +:80270000870B20044280B21104008221822008820000004022038008882488248880081C0829088830422410120200000000F0E6FC0000001821182110012A219812880029011812002188282240820420021840022A110120042A8404008004290400003F4C0E20812405002200212C02204202000022122902C0822400808202800218A6 +:802780002800808202820000220020221202F0D8B60028000000122811002800220010221102402204A082100218284E822800A82848002280820400302200200222FFBB021822208312322128200A2100004221122188A092242C28B222012382020040021128241002001002100200000000227F9C01A04158206112806421200112308F +:80280000120020025A0221000080040028281302288002288082A868102204212228282002C022F071DA0000001223850116012C0929031218128011A228230448002290122280040000001AA41A4248A0A44820044200280010023FC9041282003821800400000010412214022022080023281212020024220021002180020000000000D6 +:80288000424021E4BF0F228004002280022112802202200112101212820188000098144A182204C800802604002290614880042A44012221F0221D00B2A0352821722A26E2221131122124A0184A512246129282882E12282CD422B222C4222AC2222128E022C6226811A82722A228F2222A02A823842424242214A246146240011FC20187 +:8029000032CA24812412D113A2111063282C29A918234B22AA11212C6123184890822AC122882DC2126A8881AC81882B1A29488248F2328129A6842C84F422422A62242914022A840200296212F0E61A808103E021E1238365241A81DA12218213820314A01312583AA2A127288028312230A224882B223023422A22C12138428026ACA671 +:80298000C22C0411A0246022282A0222242AF6BC740000002603228028C18280088822204A8284A248B0828482A42148924892201922099220C81282002400400200001448800497DCA0225A032A062E113160212D232B998AB892C9822B999AF1F1732F2BBAD24DA2FF7AA5994AB4C2E42CF532126E422F2DED2DBD92AD495AED21FBF18C +:802A0000F1121F11E921F9928229F1E2E2AAA846EABEC25E222D2223F44343A0442E222F2616A2662AA6666A9622DFC40E3AA2711AA1231AD21293633A62213F38BA82B812B112E321B992A92A1F3DF5B2B22BFF2B332B992B137AE5256528AEB22F25F562C227222F22B292FDB1616AEE36FEF1F3BAF841C12CF892C22BDC2D222AA2EE1C +:802A80004AB4427622F222222B663F34A4646AE622F26262216E612E622B666AA622AFEB012AA273A0231E323E233B23183AE3385A222C91329AA1911AF951D32B337AD722B1A2BB32A3FD2CF982822EA22F26F432322D2221D24E916A66283F17B6E2FF2161863212AAF97272624AA4AC2F24D622D222B242F64343A0444AA4464AA444A5 +:802B00006A3242A0663F14082AA233A0331AF313313F11A3333E323F31B392B982D922F192122B91881F37FF12122B552B322BDC32BAE924ED2CEC235A222F2FF562422F2979D2F262B16AF6F1521F3FAE741D61BE322F2DF862522F23B3D2AFEC4AF642622B2429F242623F34B462A4664E422F26B642A6666A32422AA266BDB900008081 +:802B800001184002240000402201A024200442214229219412422200A01220022A8124022248800448002800800242D0CF07AAA121182002211A220221009012122812292311A24218002220022E12282A012E128001183042000000280020420228202402F0EC4980B411021B2166B211726292212B141B282F26B981B24239812F242989 +:802C0000FA4291222F3429D212A9421CEB22C4A12F22E411E222E419E2226C192CAC292DC21B292DC21B292D821B294E811B292F14B881B24298212B8419B24218B14228B24228B2422892822A84E822F4994D80B4118634114212259161421B282B8413B8423A812B8413AA84AAF44211AAC4812B4A1C89C5812C6D112EC2D6E122681CAB +:802C80001CE81CC282DAC2838AC6C39AE234A8281CB881F642821B284692212F248AC2812A94822A94822A94822B42882E4237D2008004000000002008000000008001880000000000480000000000280000000025017F5D09820018800116420112120088A08480250800001002004262000000292808808408000024240000280070C247 +:802D000008202A014082016012A04288122124221D22199831302190212128800224801102232212222A52212218200225222208002200288661141C64268FDC01200418C012002113022222248224A22C82854982021A12E22802A8002314110221304210022220240821222200242800C082144681F26F8D0028180080214101181A8443 +:802D800028012014C18113021110010000002A058022022AA8283C08182002248008240000221C82042CF4F89920028042021C813222122001200428121C32312100002400A092901200402209008008200800400100002800F059FA00262101A0522839016602483011C011C0A2004820023121301200322830724818F0128125E21108E9 +:802E00001E21888A02400200004268284800482F1D0C2828124082671139818217A241601142192182691218210050210018A02926A221301242182123113292601B88A20000400100228006006FD40D4001280028282100000000222113820428244002210012002A0420C9814001002008100200208484020042DFAE4A011480020024B8 +:802E800013018021228421020028191982C142183011248800803642C042200142000020840280048008882100F08613200142200500108201220088008E110021208801802202282008221200219012400242400129022200001002428EC5000014000048000040010000800400001280810140028001182008800C000000480028000029 +:802F0000AFEF064001281A040027212001200422001B18281C01184A084081818A81032446228294121229819492002304200220848284082E820080E4D906188014010060140012001C2108008088042480A881260200A02C0018484800008088241441020000000040F2D19B141130211860221890113021181200140027112601C8C074 +:802F800082281382B221844221210420052008341E212230832115021431140021A0240000DF6B0D120028001418408101288228001308201442E11481288108881A8888810811208C048810410114C02200000021002280F489126011141400400100271822805122101101183192882214C0111414100100884812909100188219288828 +:803000000224482088240400422228CF650DA02520041601199242284200281824122A0120011288C082882412484082438252212882282E8286022880D2239841422420823822420000F0DF2D0013011418338803286602008012110226110314601421141C014601484A6224D02182E22184811701131281122108111114202A02800212 +:8030800040D14B09228082218201128081821102202101182001122220282229220100180000000028000000000080222412022F1704001A840210124122288868212880080024C280148282218482288868288228428880021226020024402244023042200A2908001F8944218224012A1102C052200124181012414202111C04601800C6 +:803100008A810519042C82C212112C8A82841221018002142004222024022842005F2A01808204800228C011A0828032521230222001122F34082C81820880042A68114A918222211A94811818488222C82228822880880242C0421022F22988F01121F011113228371311321C353135A11229011AC311211F12B212C111984AE814B5425E +:80318000B82108211F1428088A85C1623AF2921213E428A22A19C4811AB212417181C2211B223CD23214022224422A2A82246212428DD320C251B04122031C92214E22292888C822232816D2310117322135F181111B881D4186B1B2C941BAB2128558112EC2AA081F166C3A2B921A21A22915D211F281822E811F226C184288171421A86F +:803200008A8606482B824A0424CB1814181B272A82C1122CB312C113124E333AAF29121E1225F21182128E12F011225AB4126421AE3229D211B23183F161A11B5D4AA82C2B112D522829A24529E81DFB21122F1229A62228822D823332412C5411822B8627224A84E22482022AF2CAFD140020023440214101228088C4828008880080027F +:803280002880028001214229012100C0122004460224400200240000004E2814387AA2111F11A1223B333B323E217AF733332BCCCE422B8127282B1929B191B9A3B2A2D222F1939119AD991F29FA82832F18A111988AFD91D11F18E92EEB27E72FEE28EC33E72EAA2A8E819E923D222F14B6A1EA1AFE21E2AEA11F14A6CC2C54122EA22B5E +:80330000EE4AA2AA2E222BEA4A0424BFC2041B221F16B231F131712AF33133E012E221F1B3B23BCE6EF22F297B8232822B993F19B9B27382F212123BD92BD9DAED38FBA2832B225AB7F1AFF51F1DFD81511F3CA911BEB3CAEC2DADDCAAABD9BEB23F21B251B681BA81FCA1C21BEE1D212BEE2B4429E228B8C2BE42B4A2EA22F2E2C22B44D9 +:8033800040B24748A1321F12F611311F11A3313B333B321F13F231323F3ABA82EA28F312B22D822B452F29A9112EA33F33F392923B512F1DFD91D1EEF32F38B821F871511F17F521511F19BD91E93FEF2FEF2FFFF1D31F2FEF2BAFAB1BA81F31F1A3B23B881BEE1BAA3F2EBAA3B841E61CFE4143312E222F26E624A4AA6E222BCC2B66E02C +:8034000022F24677141F13F321611B131F17A3323F33F333311F12F221323F3BFAA3812EB22F29D922B842F412122B991F33FB33332F29F913511F1DFD91D1EEE3273A1F12F25171FE711F14F3D1D11BD9FED32B993F2FFFD3D13F3DBDB2BDB27AD1F191133F2BBB93BA41BE81F8C3823BCC1D21CEE23F34742341F242422F24B4A2EA26E4 +:80348000B2E2BC42042E22AF1A0A2A01001800402109400230112412241242822008214218421880088842888008002A0124000048002448004A0228B04C0F14111428A021271212628A5212281880012521521240216914A64231213021821928C582C012823C0198121C8852128214C08128250314800842000014DF470D1CB41122B2F3 +:803500001162241B2127341B212F1491212F16B981B24239812F24A94A2F1429FA4291A22DB12AC4912E421CEA22E411F222429E212F2264192CA5292D421B292D521B2925B29162241B292F24B181724292212F2498212F2418B14228F24282222B842229A8424AE822F4767EC0411986A14146A12127145012282D9113A8B413B842A987 +:803580004A4E91A22F1429DA12B922C4912E521CC8D21E812C64192E4286E11264192213A9421369221B4946B211E224B881662619E42498614E2219E224084EA2E02422022B4229A8423F2E090048000000000000000000000080080000140000481800000000800200000000F0D8284011014001143682410228140028002128802164D5 +:80360000241021110320AC1421B08181021C01483A08400134282C44815422008A020022F0881B14200218481200000020810112230223C181481211150211122D912329011848A04111221C8102212121140011100220284482021422BF6A4D11A124004218111821100222802162212221235221521AE4311461181971123192181ABC3B +:80368000119412C091484621C211622A0925021430221B4235622400A0C224240028AD5300112041018082018042210100001288000021001429080048A012C0110010021440010000218200288002F7F500000000004826020088400200200800000011B0222809200218C091702201290821501240022008202428044F7C0C111432140B +:8037000032182E112312B22128180140012248221B42230128142D6220042988A18618301212190140012D112C08109221008211208284922222808278C30C1120438183C11228C0A1A2140000282022048840A22421006011CA222821012601001123D112088225120111101182A28426820200828F950B4001009021242004210019088F +:803780009042D02182012211004824824022632820210112111A4821121202281022080000208628064F5F0E188001241221200130221A04282200255122122002AE12200425A241200490514002240040821402130429829442284822006602F0FC4500480000008002002A0400280022211888182A44018230211C02242818128A0480ED +:803800006123400120322200228250223022212848BF64081400000028000000C012901200001100502262000048280000120080228808000000000000E01A0A1C011840821122020021424860230031211A021C818832622581220811288092421800002021724281083C42024823224A420223822602FF1C0982000000808102281800D9 +:80388000402203100228808828D4220429858224041B2120918212211226022C08800400488084020080F4383B40011212800520041448001848138224041811C8488012118102228084140100141602200A2280CA228E42282B2822002728248A0426F21ECB00141420110162601A29322248CA0210A22123813262C8141A0224C84E2244 +:80390000001C2424422286062410131113A1484A9842462204424821208C0400C29F890DAA2101282A2132231227226023240080021419021962122290215A08112822000012241A0222113819084021120142002006002004B7B8202402004248200120A4121422A0120000008001126011880012001021C21220880200828282148028CE +:803980006428800810024FA84F8104004021C121800228460280D2120415224231C24228422826612E1110A124421811233411211200C021E824C82414141C04A22868008042E17508001128000040030010314224720000214800880021800848200200800A0010014886821882142208824A0848BF530F002A01245022482924C4119889 +:803A00003041C01188806414482A414181C1414218E012A12C181222481D12821B8119E22221011093C290422400420021422A240282CFA904288A03122C2641032084842141C252182411236124808101421829824112018822382302222B8221223428601228C0210060228088228202A622F21F782019A14200281A26E121820124900D +:803A800022118001222001290A2E111CC8922081812143011602800500928224C02220881201904240029042F0AE34141AA32A1B232063126A86A724924AA2211AF242411B112B212B3425E11231623A21E21645A146CE411B112662131921A9B24AA51316029683FB113160281F18092622484291411F2C8C4282FA62C2248229081CBCCF +:803B0000827C930C1CB48141A1322CA25416335126F2224225F142C22F24348127326A64231B641B25482F24F64161A02419F221326E613F15D423E113E214A6451246A2562B472A718222F212313B8229B221B241F662413BCE3F26F4C282141BC4CA7E62A228EAE4268CB2A2AC244E22CF220562168121A1143F21921327222B511F143E +:803B8000F231122A8101423CD111E82391423C52119AB981AA52141A18A23828233821822A82D613D221922313532217221E31228E812F18C8A2288A8A125232238204290A2A242422E2FE0200004800001C88C482C0811A8488040012000000100200001880010000002440022482200840220882F0CC9C14AAF6212111782AFA61B317FE +:803C0000141F32A235CE222F28F162322F28FC93111B286E32AAFB611317362B334AF421A11F14A1471F12F421731F36F762A327313F1BF8D1D19A81A4652F247442F28282921F3161213F38F993311F3252333F36FC43211F16E624F842433D222F24BE42F462422B866E4282A8482CF68C95141AF551712A82A7B31F3AF3715137322B1E +:803C800026172C2F2AF1A2822F2EBE9331832F22F3B3B13D133F26F212323F347623F161414AA5628E626E623F18F292B33F13F2D1711F1AA3115E733F3515F2E3619E221F33E721F283B33F197921F323232F268CFAC1412F267A8242F242622B222B4A2B826E422AB262A6462CFA81D6B021F631611B112AA3462F2431421F3287E72140 +:803D0000FB52522F2FFA12723F15B951A5AE1F167761F131513AF751513984F16151226EE37E631F337313F3A3811F1FED1DA3665AF473712B333F182EAB1213F3B1B11F19FB21233F34F862C22B286AE62CFA43833F18ACE42B8C27262B882F26BCC29CA28AEC28F6EE8CB0B1F711611F11A1367AF741531B571F33A5772F25F972522B52 +:803D8000472F2DFF53913F35F5E2F23F37F553533F37F752723F15F723211F12A6442AE622FE71631F31F393B327131F1FE518A3371F27F673732B333F19E729F2613313F2B2B33F197921F323222F26BC82FAC141CEA22F2CB882B8C2FEE2A22F2EB282FAE2C22BEEEAAECE8EA28BB920022A01220040A241241280041210418204132814 +:803E00000442808201188021240222A09220021C0988820014480024480000002FE30500144002244818121450221301D02213C112122122184041421123312282A02124120025321121000011252208501200222C080060385F7E09581B21B091A2141B212B1619B262B181F262931B282B9413F94291A22F1429F242B1322DB12AC49138 +:803E80002E421CEA2264112E429E212F226C192CA4292CB491C2521B292CB19122B49132621B28272619F2628219F24282112B84222BA4222F242892822AA4842E421F410F581B61481B21181B612F1681F262118AF222131B684AA32825B1A194122AF442B113B2423B222D912E521CEA22ED1528E211F223C2D2349E212CA42D348AC612 +:803F0000431B2946B2917262A2282693612E8219E624BA8142A24A2B24222D828AA42423B842E222F4155E00824800000000148002000000000080080000140000480040080000800200000080022F520F80021480128586818111421188110A2123921111428052831190322901922D42A44211184094112941212402C0229200002228F7 +:803F80002031224A1224FA8DADD01261491681612182B01A1892C87038014249242792218A41A234A2C5010030411432114132203741281A0811708282C1228B82A04270C1C8912C064668242084E11488F4A1592413B1E42181218118F5528A9098200246C8266E187022A3821D1224C8441E22852148A21200135843A322641356218411 +:80400000C11240B182A421228B82222B8320B49102232222642126222588FA18A80040114182022818482C711148014A012880014E3122850110011D4216A1121248122142809284111C0124400280041788A042C0482420246244481FAD08480000402241C248250114001228112001A0244828002011012A0148005012002042081225A4 +:804080001201110020010000481FD406002713858251224194422A812225DC822148098041118801601C28B012442115282482239425200136D228C6191662228A043214863844482880C672A0144A82D8330C48F022118450221043E2821182A484A1881C214201148112008E41400219410162007021443211002994118C41221142410F +:80410000318149242402484A12822124F4A3B300003012103418424213221121018400121800624822222005588118223A240400A0218722830229A248B022018100208182014222825F650A1D2222382065211140312149D2810289A5242F4221A4212228412148804631338880266314842D182A24344444214C66222C02222741511189 +:80418000844842251882012448288CB448D23905804468822184408112489812442625082225229112812334184A0121482978120861411190116084402AC11448301188C301A0282022042828304222F0CDC100142112431201182031112001848440480122100141400800B480240441002200123C0242A0124221A0148C28242101C096 +:8042000014F0F16B4051128B213828161B011C12B9185292184E148E4826847212AA21293128428C014125915B24838152C14914B8429151414144244E244C923239826144182E1146280C322328A1121E22A02443B148F2556620821242B846013011A021141A021548628142221422446014484A022821C0421A122244888204248C8296 +:8042800021210427329285012460248C3448480042B048029F72440112188148842814008C24011692184088040018260128484818224A4204208421445112111001423228181C011502002A84A3421A028249F2691B200110418134188904C6092C048699412E122882188120048481803248001C42858E121145044341A8844EA4168C74 +:80430000044C14324938488222100420324848DFE90718118051189A12021C0240981400141048082B1226D12841118882611100304448112664211820284442C1282244118C1222A1122250262061221810F8F9B80028810020A42489141251438140314A1605130200A01214408148018042048888A8124E222682426234241502214C98 +:804380000110A481002D8288A012F0E9BF3084A021608214123400492624848421628442C041212100101102290114000022434192141CC1424400929886822C48612128C24968848008C6F1F1F11012042021028190486051002A2401100280133248108803240000492211010042848C021424260811810048812260418001EDF9201228 +:80440000414129D482A4422848004C08A7112188281C018A2224B482041B4260842B24229044708401148038A300824A6841421984E4110490428AA4816C8101C8428C4CF2BFE58024C121122812A130216082844588241221A12189041902931101589111C04400239244284828C06128D480024A6212A881948A2112FCA2182043840261 +:804480004CA2AD7021288284622140038427227022662128818C5423942E118324459142284A9121888413942242681421421E28314BC270112A1251211D121A08CC04295A214C052034842038228CF8D922141E451F48D11111A85684129344EB88D42484D4A861252B421F12F163119C91124AE81504581D1117122E225E421519A1425A +:80450000112CD244BA64A4815B48182F1832548B4487648A528466F164811F11FAC2D217248D82114A6D288F41BA12F382A23EB4A28F1AB564FC88DB242A42E183C238289B342B522E488B62F021281FB13B543B588F91714852847A74117928F822221F16F511A180764151118F2CE42112D454E4522448F424112CF387A72CD8716392FB +:804580003DE1375637272C94512F4625B314F811112F15DC44D242DA22A5824B414388A1A185D24E04183A02171197B12F23F4482B1C3243AF14324AA3544285B941F212E88F2132898B263C84A12187A48F827648C8588F82A31366B142A22443A44639B24162173253A3C21F21638AC9DC58B713F3922285D299D29A64882E12B28B1787 +:80460000478E47446E1848296E848E2C3D82200460128008246032E012888428C1A4482C8AC4A412880010180221280061800800210084450224860882200848448A44020083F4678614BE315F5363111D51173E3F35711A5112357381D199F883833F38C9822BE85FF8F89E952B922F28F986867F58EC11B5D8FF494946E936B452744154 +:80468000E135F5214157144F26F6A48246F4E1C51F7CF8D4B24F49F134752CF286A63F28F23A322F24F633723F35F57B13BF11F14A4A3F24F572A68F83F9382E2723EFA2F276546AE483D3EC74C54BF336355FD67638F929799FB57D8BF35A493F16D41BF6A1619FF4FA6323BF3187F8C8AAB7B4A7922F86F8B393EFE2F626462F15F5D977 +:80470000F89F9541E112EA14F459B95E531F1254155F72E268F82424DFDFED5DF995F85F59F934759D286F58FA81A67F65F153633F2DF5733737368F9AF2CA5B3F247752F6F8D267A56F2F754EFEF6D62B888F8BFF9C7E6784342B775F537739F92939B43F91F17863BF12F24B613F3EF243E7AF27F643311F2CF442C23F34F14B53BF1E16 +:80478000F64AC3AF86F231513F1CFD58589F967541F968EBBB6717343F35F5222457546E638E826F48F8754D5F57F697D76F48E87152BA6FECFE8FABFF33F342723F37FFDBDFBF3FF85BE3AF24FCD3936F67F27C488FCFFA72C2EFAEFBE6C42B448F8AFA4CDE4F3F4CF3F674DF5264931F96F3595BBF14F47A2BBF96F24B632F2EF24AEAD6 +:80480000AF2BFA5B519F3CF4629A6F7DF97E77BF1FF372F3AF8EAE533F1DFD59588F9663948FB6F67B798FBDE735E5427245F564678E866F4AFAF5DD5F5EFEBFB67F7BFB5227BFB3F1A6E7BFD8FA1D163F35B7D3FCFBFABF3FF9DBFB2FBDFDF3D36F6DB9FCFDD69C6F4FFD4C9C4F47BD12F978F8CFECBD730E410084264128C24800C0481E +:8048800014404208118113011183044A1211888112250442490898D012011C41D814A841141220011A442341648164924492008FA107239221100148211146518110D128011CA1421816480221124A42082A2404B02444914400B02444044C4282065022482410082058480000484294DE17C0421F41D228F111248F14F11124AB141D24B4 +:80490000AB141D24AF149921AF143915AB9443F24AB143F2429147832D914F82C4914FA2C4814FA264114FA264192E4A9E254D4A9E242E4A1F49C2C21F4952281F49B248F89124E7261F48F26E121D24AB9619B24A19B54A3924ABB443F242B6478229FB24488B944FA2D4580EBCC1648D53448F14C124AF14D141B2486148AF5429D81A4D +:80498000BB85B44A289ABA4B481CE988D412F8A6481CF9245A89F824C21E814FA224E8A2E459F2244996E4A27411DCB4BC11D628F81124CB841B29672617C8CF2661486E1417C8AF34B385B24811D42A2BD8685384B86D48ABB44F88D5520D8482480082200100008100000000210000000040016084800400000000800200000000F06BC0 +:804A0000B5902213638115841141D64866225028110014208384C22419912484304D001C22012F8104924210466241112180088311825222189C81A128482B82C9C9328184B246F275B1207182225282A01C89089564A26082185C119888428D22122422521228222211D043A414114324C222471212222241124D51A01468494438384A32 +:804A8000C844C820829442444A815A1443B2E34D22F3C2138B21A584C1418938225C421A7C28217314118188D628226162244A21215381A2112652414217851D44AA61268712446692244523C111884A91686149322A2B4816848AAA24222F88F414221E4289BA94B214724E0F800211A08141CC54282824001048888184021C332481E047 +:804B000044021021C512000044290118004C048081142881D181A41440A2484C0181002CF47B231002251251181118200481101A111A01113412208132212800134285211104221B2141111C41C8821222602400001D481484449022222800249F3B0E1C82E342012952828289613289912282205941367A219C2222872881A21100342221 +:804B8000188CC225812F222184058E2324283B8129217212A816884E812B82271129084823882246B44221A1484902CF520339822201118031181352A28482841958C122430214218003222810221148C51825067219D16142A21282243602002581D22201842484412A042B43122042D2510C60214722159228A581084818221082119245 +:804C000019353823228F211888C82111108132211D243820230422821414B72192C038788A243C8211821CC4418222244302228A1404AF560F1C248182A221354852857088A221E71112230329828142C824216911A412C288524283724802214D421008560434188460821AD22211C428844E389E48606C466242211261899118CF45075D +:804C8000D014241113420212154441382481848B2100A180042932288909CB828502008343039028414260414E2218122113441424214B04842082CC82896228442CB334014C111228014484D02A02004014911442642A8191288344018414264114221141481838112A21824208448CA44120A44111006024402881812804F06D4540D139 +:804D000014C13A1722188504455A2D868283124864214158CD22838195288745853488835849BC1414E28471315882E1A1122A912470146827C381E484E313248474183118CC814D9AC48B242F28662820941C2CF2A138F0845200122612512A13215281857211C812165818322480322421221C222224A221488942022004191224211271 +:804D800011028D1240624129818288148844024C2191B84308849734802211082818442F148222844601141014C42820223118439AA2211946922129C14214122CC24123C24149022D26844D221683022A48C122196228426512C41241282781228843F45D510024162242E2842202118B1A812C44A8182414B44A91684D825140117484C5 +:804E0000819923C0282052228484441211002880C28220A4281C48140388814B82184928841184F8C4771423182203188504810018121818A012436944100841108844018022822204411244400488408821113514181810A4A418902440C8444289F23712402802974189048344765892484481648041014081B1448254221CC412008461 +:804E8000141E8812114418111012B14111120154888314423441618E12200400488CE12201DFFC41012800A12041130140A142144880048844881E41114C04121480D1421204859428122302221621424204682064289216022CC12C252A882102848CF164FEC01E508200608212204182046818482CC218896482818C2A8C0290A8867977 +:804F0000421841810221219C4108411991428722485116041148202822A848200800E2DFF80122002D113C248C9442004888251858828881A228272C002584C8944A8A0811811622015094901400009611012D82190290841100801112848818E4960A1A7498010024121A6281241682522146084E22A2240050140021800410068C8681CA +:804F800003499822472128182B24484E34351828912280C1241AA416A302123AA82426013F1407254CA442872213280185C442004C818122329414C0131E4193032B14124611B2182827344121881CA284682D6811E84219341190883E821B12824C011CE61144044CC462535242867812086F7449C14282A3D212312369947887466A24BF +:805000007C72DE1161164E588B344F4DA8248F41D282F15448557D41BDC57F24A4442B493668A815BA15F421234E618FE2E262E13431114CC2922B64237111E169E111782BF1285E16A281255444CAB154F434D4EB814F62F112811AE2C4FF18198BC1DD11242E24AE3616381D8E418B9127811E519721AB51184E82EFA1719831121F1287 +:80508000F2268B2AF549412F42BA12B324042D635F78B841334919B638716A4C2411C4A93E242EB717111F42A2111563229CF2A7185E16271C1714172A16F2138259CC26A1EC82E262722434B8AE814FC4D2E4066B1137812CE3A272586A8647267D2A2D192688B41A0631245897492F84E822FA89128BC28B91748B8D212E812D21AF122A +:80510000F142618E232B112F823912AB45F16B44E3127425E78EB346366B4E668ABA15FAA2B41CF341F18E512F71B2A2E9A4A24E2B854B18AF840D6C662A1FE80F424008602284002C48888884884486442211088524010090283088208821088241826182184880041A049A44240182A04914828112812FEB45F134267FF363812F33D763 +:805180002882F3541C15F4682AAFABB3B67331F2AA841F19F18B1B1B89DB8B422465F6475549E21AFA25A14F4CEC2AE627F731E93F99FB727F6F57FE3888CFCEFEA81ABF37FD73B51FFDF8B3352F48BCC2FA61619F9CFEE8689F88DF4FD723FB33B33F11F555D15F14A7368F8EF518785AE544C6283AA7B14F23F2989A1427627F7666A1C1 +:805200009F3397698CF74C3C3F61F27B228FAAE36FF3F382AF8BFA9153BFB9F1B5D1DF3BF9AAA2AD2A6FAEF4DFDD6F8CEE5AFAA7A75F58EC2BF7787B1F1BF6B1F3EF6DFF57C59FA3F8E6EEB79A5FF7FD73A11F79FEB3312E462B753F38D89BF2DCDC9F88798FDC62DB33F133716F25FDD6544D24E7C5EF6DF376745F4DF656782F8BE78DF0 +:80528000FF8E3E2F444AF375675F737738FA2223AF16F66A326D5CDD458D6A2FA1FF7276FED2AB745E98BF95FDD397FFBDEDA6F37373EFF5F14655FFD8ABBB5F5AFBA5A52CFA72722FA3F6333A2FDAFA342587BA8FAFF57CCE4FF7E76FF792463F735B622F14F27372EFE9FEAFE5AF89FD69721F6CFF23B31F1DFF46D27B914F42FBE8D862 +:80530000EFE5BF92B844FFE4F8AF41FF18B4CF22FB4A3C341F74F42767A7A1AF37F37A73AFA6F34E7EFF75F44B6B8FA5FF7A7AAFA3F1DAF85EDABF95FDF757EF2FFDFAF2BFB777C6FFDCDD5FD9FBB1B75F7AFEA7A72F23F27B7BAFB3F6B3BBEFE1F115158FBAF1FA7ABFA7FD75575F2F7797F737B147642BFC3F39F95A7BFF7CFCBFBDFFE9 +:80538000FFF6D2F33F39B9D1FF53D33F59B986FBDED8EFADBFB6BAD6FED6F88FC2EFE1FB8CAAEFCE0314004001418C64121A64221E48141230812813883291448032814C028001714269111802185012D012811404471240012482141244844412004604EF3E0E27284425C228218C064CB22821012850811812852412A842A1484625A8DE +:805400008422832432582A0480924442408441642410688960C82911B1423114422004184885A44A89018F3C042CF51124CD121FC1326C1F41324A1D2CAB141F48B24AF98128AB9453B84A3924AF543934AF547924D81AF934488D954FA2C4814FA27418F1244A8F19F221CA96C5CA9E24ACFC91244DC21F49D22CF89124EB861FC9B26A3D +:80548000F98124AB141F41B26AB911B24AB915F44A9443B24A3B342BB44782A9F9344889F9244ADF4A094D181F41D636D5C1B26E7111A4141D2C8B141D244E141D2CA99345182E488D952E488F543924AD912B4A8D954F82C5815F823C185D4A8B211FA27418C4435CE282E4C1F2244B1B61C7221B21E3E6C17262F3912C89F11124AF427E +:80550000F89124A9B215F24A8643FA483243EB2472A498386B43A9F8A45ADFF20F00481E1200000000000000000000188008000014000000200800901800280000000025015FBB0212142123410A2D3816284211480112A4444588B282024228A028442190620041814981012D6290211119F221140000E01241984413B414822132122041 +:8055800009422AF4E3F210A1283628180270216495181C21E28401B028C1611644F11224004D584419248442848382336222C14444228921018149654329F1284425198804849062471119741814B24C6318815F990E111F24A2212D1250228362421D6819911C222A01242A511C441CD2424382C25C1EA44631C2604432224B21B364427F +:80560000165128482B24818092384426267168561C838224B441C2241249C31160298B341483F5227780018188818071118801141183241158844A2293822004004480322200202251844443022E11134151414A2101001311181428B142123142478121414A28F2ECCD108202901212801402B0119498164841C814415410CA48422004E7 +:8056800000890212650200241024612280410800864822F14814C01222187048348442223F5E477131542154D01852281D1C16081B4189322200414B81142E588CA2241601228461812D4C1144CB2481D048E1423184430218301436CA4C23631329E928A452488C8498D22B248D1248ABA52A081E2870960D262452528042781285116223 +:805700001580248141151CE4C4529442848904A44C048C0426B848C21224124361484C12820136D48213B82881830829048C0523A8213668244A6888882A81F2E6961439110170132811C848008D22139388812099111828263211A0240085124411144418442C020041124062651031128AB4188A14B2CCA1412D4224188B12434694480D +:80578000F09F69108401851274281104482941D1246111C3428421220218B22C6112C71321825662418CA114611281C512081860834220275283244C68848169132282C122411A0224B044F141C2A012488992224240480284845508228140981800602481124C8418A442412052124C2613084B841200A4814130684CA412233341582135 +:80580000828904648648C214188F7E0E48400100182962C2481240882441221484332C81C44142008400C088841880E221024120C11410AA25000000A490121210C44884842F8E072A811138284226911830662F84518140C844C1246289A1124483D24851849902D0A4E145C2145827C884844302324B1843A12148A42C15E8138482E42E +:805880008453822CC1128123D822024C42C448C9D148F4F8DB90446032104658242881807111D812418821113824608398481CD22464442004818092125E24AC8142024088614183C224A18C9482C01259242482E181C41412A908009E15244096154932498F440270482126028442A02142C03842A90118412C0240828153828420062690 +:80590000044146CA1C2921117A28246162818D82C954848B242288418849212414F4268C200124811210B14201B041414814382100220020522832218AC24200401204C03680138102441116848412C124130111301C212A08228A212AF43976242031191820054A8101842015288211C84423B4280146088141901A205218830144322038 +:80598000121491121820012A61812A810884444422842B214C428AA214284FD545D1A11401111414997121421111E15214413159C0128901003021901119342142801491455A424AD812048C120427228D41294212744A6341250223DD2221C424422FA128481C42D88A47217824312424811290285880128882048C2264428143A21283B1 +:805A0000018F22840442244168004144124C21410811226604130400904418224B94588E44B0440888F0BEA1F05428502841434329022819042E14B01192484222A014488914114204882006202381420180C8148C722204904869A148A12449844211082544482882312418FF530B004008200424A44D4AD02241420227812012480218B7 +:805A80001126011418480048149044100820E444111814084284119290C4800842200888AFE80B17628428181014082002469148189881282512842122220244896181820028121816248661422241228022022218328E142C28880118A3D14212B848D224A1A4CFEF0C84124828274480434818084C41820248C0580042131403581386DE +:805B0000321C411113446814482146082C85410125A484144324C8C422388C3482C04880044121F0374B1437668E256F41E1D1734D79647D39E21134411F92F63B2146D1815418BF82A8161E2A2CD648E6A4E1852512D8AAD251B221726179328AB121D1887312A8211B2529B214D344D294D148D6427326E6127682DC1AF31A361F11F2BE +:805B800012BA37B1A5F68483AFA2AA83CD248F81F326264CF422E89AB872E2BA051E617B111D28A7222F41B4194191281E68A14AD48BD422D182A5352D286AB5463112497428C2281C81B524F482D12B7149B422A46417178F14B46455484F25B54234988F43F2221A47314A7243B45C62444AF8424A484F4CE88CC9544B1947642F8DFD5F +:805C000064848F8C6D824B144F42C4442FF34B92148487324138484E386E1A8D114245A833874713C5418B41A187C36E188B23289F14B531722435424618A894455418214D14444F2265C217422A5121437161A811CFA1A1425F83B424F4289483AA124B41B7854E448C47F28242B09C7A98A4348F28F8A5790018844018844442480324C0 +:805C80001648022412201128011246041002181002001811981118111815C882130115081B414008802211281108702F49F215325FC3721CD667F41B189FC1B131B73BF27B389F9652149D132F465111DEE86AA672C57614F424348F82F339391F13731C5A37BFBCF5415B4FC4EC62F222231FB7F278284B234F62F21F451F56F6958D8F69 +:805D0000AAF83A5B2F17F735176F63F31415BEB51F3AB82A43F34B4DDFA4F4C3716D846F64F462762B76ED256B668E88BA73B4F22554245F63F36575C5D7D7F45D599FC5F539383F12F37B7B3F92D2D8D211F25822B5E9A9F82222AF87774EF4561CCFC6E2A2F33B391F13D3F95133BFBCF41143CFC3F224263F32F2792B9FD7E246E746F1 +:805D8000C74E4F47F7D5C5DFFBF83F762F16F77577BFF3F33B148FFBFB8787BF5AFBA3982F8BFB5249AF8CBD2EBFFAFF6EE66F8B7A86FCEE6C6F44F4B4346F28B93247F154766F43761A761FF65B1C1FD5F1787ABF27B31BF1282BA5FD4933BD7939B5CBFD7872AF84F34616EB45CF42F72838BF93F331395FB45535BFB4FC435B6FE4F43C +:805E000072663F37F66B7BAFD67214F424266FC3E442F295C49FB2F33E2E7B777B337FF6F3D4DE9F83F6DDDEBFD6E621F5CAE8DFA4F5C7DF6FE3F87E4EAFEEF7E232ED876BEE6F84B724E228F17D5A245F67F73775F771DFE4F27D7C9FC3F3796A3F27F57B7ABFB6D69AD231F35A52BF95F59A9AAFA2F67A386F44F17658CFC3F61838BF12 +:805E800093F521285FF4F42543BFA4FE1353EFE3F736263F37F65B7BAFD7E245E523F717571F57F7B4C58FE3F37A3C7F45F77477AFA7F7DED6BF87F6D4D7AF8FCFDABF91FF5C5FEFCCFD6EF4AF6DFD4EB6EF89FB1E9CEF8FFF4C5C3AF3C4824FC90B6130260048008004008C0448241A14A84189220100002142311002184218104408483D +:805F0000400882E0880484448E48208922089246043F9101828041188C921828294148C1681880418841C8242242130355887221321841282C018CA5240021E022012A01181A0216081281924432812A344284188420F85B71C0421F41D228F1112CC3F4912CA7241D24AB141FC1F24A911B21AB9455B84A3934AF143934AF347934D812CC +:805F8000F934481CF9244A5CF8244A16F1264A87192E5A96D5A2F49824ACF491242CF591248D121F49B248F1912CAB141FC9B24AD941B24AF91128AB9451AB944782AB9443F34AB44783A9F9244889F9244ACFE30FBCD541C4511FC1F246111F81521A1D6C2F16E1C1F24A851FC1F242A15788AF147914F84A8143F34A8547835CF836489D +:806000001CF8261A8D954B8216E1A271888565594D4B8F49F2244B8E284FA2C5648D128E244F24E1C8D22EE181722CC2242F66E9C1D22ABA14F24A9236F84A9443F14AA643D34A7A2698BA4F22759607108204000000008002000000000080080000140000480000000044000000000014F0C56F0000415028151844F814288341214581B7 +:8060800084D42821A125214C3361542490418B212E110049114818025A92921425012C9121004321612300122694162E541A522428434334442FF1025A32A2C011896557181B122B1411A0128150482C420481C902494188E212446424C0488F111268434A11E84611C32490244F8992848C911812A29C38481A286158141028189888420C +:806100008641D83B0E7622041C81E42221F1142189551C4568138B431181684D12128C962A64471295A4213374C491482E1146D81843943989018D262E416BB424411E8C643628012E849999682F4289919528211E4CA2D022E24166581E4CFFF10F80024489D1C1541810A22118006044100A1841381A0480021A12023018414225288506 +:8061800001141922224941882101120050144C21825184890800CFD20C2001442631112400682C318114400140C8224342742428148102508228481A82410410022B12280000811A6424128B14123441242200A90888ACF4F438244A032D232810028312D8B48122721238181A142FF14294218925278822C24A142D154224FC427264225A +:8062000022EC4231251B820027512963534212A1382214463894A021124C341462D28B42F0CE1CB0120613322213024008D3B122417113C818184581E16C81321E1A82822682462211022528B1125242484313E318022CC21123128184F142184218871190942128184C8491C29810F815F71480114204330129128846220AC04384508203 +:80628000803644478840115812548C24D24136224C24820843022B124024C13410081E222242894541C41222406482488B2C428FF20930248C52232444C02284441A0227412644C88141E4105A9424942E18A0284146D24821D12441A114108162252849425848481242811524542A48188200436483404218F8D34BC057485048121410C6 +:8063000092214220446C32512C02604124E024818251841748BC141421144241449818274146041C08AAC1144008874821824F184102182C8109C14622C2525F620D2051412885512844CC0189028400102851121C32640012822A4402830328839228A122412420C118122180A2214400401848048C0A428A419444608AD0147412D4210E +:8063800052498551A64436DC828282532818454371894256851F22714854964AD18121D248C2262CF4542A8751788C51281883D261C114274130351628CA54286E1884954242DA1CC4184C8861AA4A298211C42485F27C72A01828C1282911410214CC044881504822185042220028862814515800244C322287440022B022618824160C09 +:8064000012408488842849022041E481D448883448486DC4601413029142304213840428D04141181901111001112810011230431111001854111646213122452142011CB29154124829C8810022230846021A58282FAA0126444231128139811282714118261532426024B04612344410845138106824894152248744496264285024C058 +:8064800014B594142225582641582588084361C449D8427282A4248860486688F48BF96018400924C012182549D8281851188941E584C113182541110214142210438171421158A22825221111110A2842112253911415827411429111800718A88128442D24CF440D2C4184021248224C02222885041C921228002A816112602620242261 +:80650000A28462200512E0882284026848126223944886082C02822138200443250148828F1F0521241210322810083502469188482C1E41914143CC6819115114100515021144491234541C7228110414A9521E14411C41C821C0816011442CC884C0246382288442F17DBF00190284005428481816A1122124502400160280331280517A +:806580001220014A811849415424422136388156220826C222A04B44008E42C042418240848191446F124BA1421844E0146221421914280620912400401408441028118895584602108116820480011880028448426081442C0446082A08A0148C08B03C0A20285221165C8155481C82D181548248148C91284B582C6132444E22490410A1 +:80660000140313888303218220982214284011624412282568422C216844182306122305632242C2285F9D08AC014D4A4392818E4412100140041A624212282281244410D62C82512888890285026012640044484240548344166148842E441B412884410041128149318282CF570317134F28721BD1D9D2945A316C2236418D138628717E +:806680004956189BB267152F21F116214E8B4D14344D51AC1259D295429A58562173A24192122E241D9622411B128E424E3115F2222A93736AF881828C9C1B29FC17818CF548722F22F884A23AC4A41E34A81E918F64F64FB1803282AC8231422F84F937511D2CA3F163481D31AF9482E9857146A4321D254E16737342BB2421B225653119 +:806700004F2284B451F4E2832E421774CB449FC2F614221572AE78417111D78C721EF12A422F4AF141416CD151F4726C1B315EE21B156C7583B226A841212F443312CF84BC86E424B6A278364BF344521713474225F219528F413648ED539CA421A7661D5227915D4216D9A9A4841B428D341B423F44524116752418F112292F127111985C +:80678000336D581D1E61EE4469C5216D462B1227311F867315F44421C5F446214F21D31C71EC631A4523FC5C8586F4442476B484B8E411E2C331AC45F845550000430288200280248244A441A041A041890228A024A02480028120044288001044080000008200200800828304F0E145141F18F4212395F319735F7FF321269F86F2393FF3 +:806800003F17B721F3111A3F35F3BA915714AF193B445F59F96412DF7AFB7A1A2F1424F65D596F1454FC8FACF45B5BAF967D1AB922F2A5A38CB4D6FC52511F2CFC41463FB5B132E31BFF585EBFACFE43649D2EDD2EF5FEABBA9FA3DB23F54546CFA1F92AAA6F247426D622F826A26B2285D888FD2A6A6FC14FF171533F96F41937FF71F7B9 +:8068800077F71F69F5572CFFF3F37B711B335FA1F13A3BAFD95B54AF985B347F78F936377F7BFA3F1F6F17F576355F51F12537E5DFABF85B5BBFB7793AF967327F3858366BCD2F61F1CBC67F74F41757BFA3F3B9FBFD3FFFE8FA6F6DFFE7F75B1BBD1ABFFAFB31321F72F75556FFF1FB3E1E6F67F5E4666F68F826244F427686FCDCDCCF0F +:80690000EFF7B3EF243F41F42167644F73F377373F67F31F6E9FE3F77B3239F1597C1F35F2DAF3D734EF3D7D6FF3D7D57F76F1E7DFFFF7F347457F57F135154F32F34F4FBD8BBFB5F572733731AFB3F2EFE7A7B46F6DFD56527FFCFC87A65F71F73D337F3BFB5F5F7F7EFE4F4C9FF7F655767F74FE7B3E9FB7FBC3E27F7CF59B1BEFE3FBF2 +:80698000F6F66F66FC62D66F26FEDEE8AF85DCC4FD2C9E6FA641E169D56BF43B3E7F76F36F371F75F1776EFFF6F66A223F35F57B78BF97F7DFDBDFF5F5EFDDCFB7F5C7D76F76F7EFEFDFF7F777754F57F335355F725277BF92F27B7BBFBFF77361FFF7F38F87ED2E6F4DFD56127FFCFE87A77F51F32D1ADFBFFB3F3D7F7EFE6F6DFFF7F68B +:806A00005F59FF55FDFB9BBFBBFB93F35F7CFDF795EFEBFBF6F66F66FE66F66F4AEA89FF74CC4FC5FD6CFE2FC30243021884418449E18164221A048424844048044C2201128504004A122204002022A48220422882041245E289242201820020C122800200EFB2072905181321C42422848100122001322001433142414018281288012A9A +:806A800001262811044828496181008302412822844212E08304802801124CCA493F8B0A2CF4112485F2112483F41124A3D641B24AF18124AB9419B24A3915AB9443F34A9143F3429147822D914F82C4914FA2C4854FA2E411F2244A87192E4A96C55A9E24ACF491242CFD9124C5F2912483F49124AF24F18124AB141D24AB9419B24A1909 +:806B0000B54A3924AB9443B242792498924F8284F9244ABB23C04B1E64AD4313714AF2112487364CF24A111F48D27AA1488DB19AD43AB8B5D42AB8B5948A5994927D482B945D5A4E947FA2EC11D28538987F22644D6DD99E252D8A1E2C6D599E64E5B391F246839E2CED938E24AF14C124AD978E248F3493248F7439B4A536242D94478A24 +:806B80002F44312629F924583F6E04848248820000004014020000000021000000004001400848000000000028800400001002EF4C4B121403288418361CD88182023018161428112C25044601C02C8C0425012691141C52244D281622C28217421292411E252088912C18119812CA8126844284824804C3E21646A1524B18A32181613856 +:806C000082961172927122E811223888174815883281A52425722194C8241C5241421821D04AE182211564512E11824D216D2A6E11244F11E2817264C9421CE2814891441445AA218D422021061685F88B2A9042274D811284922F81D21898211B1269C2212249C1891843822524E4320460C12088441261611353418321B12B21B866888D +:806C8000624363741423A2288F41C42E43C381AA11044AB242512844282A48042769DFF60A4B121129818211918412A52218289198864854818113584A1230258B8426F24821554281810285E4A2E1441244E41211D13461882E11284D1116681248141648A1414E914588A2422021044C61822FCA0C1001001123423448008200000000A0 +:806D0000000042A41001118048448242013450182881442C0100AD9112002901880041C0424F36062440021054819013404271130818911A142342611414414712111B2442898218584184226041308484416021430450249122001C08484848832281664828F76200400210548241A301C0821C014009212214421440052E4821944049B0 +:806D8000348844B016126148154214C8224C142441548128990182200442838231248624F244FC00350800111C021C0464118C0212A0411400142444225661184228821041810284004608141284400221708224430123212408C0426024DF820E002485042250164562228418160250422E1827628015A484004622C4141820442415120B +:806E000004202182084218250110A248508170220818899128844241E05A4691141445081341038512C1D110028111001820220813122C481902121240280439E2480350282AC4184412150484218C41628144480030142042FCCE765021241902604100848140111101008C880183321820128C62A6493229C09222104212712222D81415 +:806E800001288224000025120440181824058400E792002563C2C1F02112502E45EBA2082711195183116132872818522E84831421F248821B24A3C7342A81B414888744641226D522233A152846C814172144508227282C51688351424688D148812141684285724C014D1140031C410411B0111408000085323420122889528444844482 +:806F000021858101250A25022909608823A4212C081400488111608240082E48858404412F3B091440014008110018008481410014221C02400220B1220422444828002415148802400221100A240000220060824224AF22091002122C8152420016D18308212C48C181215C48024411814601150C184912058846B48241C281C0121D1829 +:806F80001F2822F28118452812E8140125213111454808A41E48484840E817070011407228020020490288944D81D01448231244424802822C814404C041200888154468128601131802904300211144200248F0482240727507953A482021014114D02151D445B424E2A222420200C0232513B251A1118F59A88838284712441D814D61CB +:80700000395188B5BA48A4542F846122228951842942D84C51644F12A23232848410981A46522229B418F1A5BD0018100341120025022100200884121100400480420226028008000000241100800440210400120000441F1E0A818C2484041002214014E4E862828A12110800190821292181818808812810414118E881A414482400284F +:80708000212444618D24222842400800282129F12A7E50828004200122810044C0224002141140D22112024931248800001116014008481901411211842140042C1208230480041002BF52058004000000C084800200140000218041810800001D41008480040000211114441428400100001002185F620300121602180000408248020058 +:8071000000000014140044410000000000000000211424840000000010F4E7C5301883246424221002205844C5B42C2222021144114002241A3114921482005011105388818B5442422840020045544C6B222662860020042440A2114FC30B50884848000031200845042A12010000146121284B912E8888442200141501128588A85424D0 +:8071800011401102004514A92240480800216121CF570C211249010018210024008420116A88008800412002224200200800604188C012184002145018000044800400D08F06004001210000200810084001110011000000800200000000100110410280045622040000009F2E0321124414212150222180881858A8A18295518550118002 +:8072000012147424240210322823224402001816A41828E03151232558310084152244B24804A0440041F09F1C2400121270140250A18882D0A208823C518285210113180111114039244904000020018A61112455024012D223145228948D49008112000044CF380B121818358282B11221022424A18200118058118048414144D144A2A5 +:8072800022408482028A090012003012312641015019318314A25421452804800241CF6B016F22F212222E122B11122B11C0123592822F31F111139B989E888D888F18F44848D0915411488558884F84F448444F42B444F22424222E2480526445E442F226222F21A2129AA1812B99823C512229F812131F31B189699987848B488F8424CF +:80730000E48404488558884F84F47C3BF0262265A2123A211102142592822D131F1191811F89F818888F18242C44511150918588F44844C5B444A226220050424584F226226D822E123AA1812B8882822592822D131F1191819E88878189A444420040588848FFAA0A00000000000000000000000000000000000000000000000000000068 +:807380000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000000000000000000002F +:8074000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000AE +:80748000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000002E +:807500000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000000000000AD +:8075800000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000000002D +:80760000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000AC +:807680000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000002C +:8077000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000AB +:80778000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000002B +:807800000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000AA +:8078800000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000002A +:80790000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000A9 +:807980000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0029 +:807A000000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE4B7 +:807A80000F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000000000000000000000000000000B +:807B0000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000000000000000000000A7 +:807B80000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000027 +:807C000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000A6 +:807C8000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000000000000026 +:807D00000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000000000A5 +:807D800000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000025 +:807E0000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000A4 +:807E80000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000024 +:807F000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000A3 +:807F8000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000023 +:808000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000A2 +:8080800000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000022 +:80810000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000A1 +:808180000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000021 +:8082000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFEA0 +:80828000000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F06D +:808300004FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000000000000000000000000008F +:8083800000F04FFE000000000000000000000000000000000000000000000000000000000000FFE44F4181C21880412802301441E042210844D021A22186824228092398521111818188008D8246242241C1418C0547821E4848430212890180420280C222162825F13F7E242816495129D14485942E6362221AA221178845D824322163B0 +:8084000072124C37311F89B48241B8560817281626F912812B811F84B149E98428742198419C16988851468C65426D22422D24282655484E2745D842B234F42612522901842D4C5FA207211601301A4445481284810286880861403137142884810000881282828840021138C088874160C52C210422104128D4420267242052229018525D +:80848000EEB720C22818910010022C2281C115C1902126742804D08394828692C429B88164412131811218807424281641014242808452422132C30111842604452204812C44ECFB0A110000008422440022000000381200002311C211008501C8890840182804415048446800004C42022A81012812001FC30700150815148832240044F8 +:808500002800434202230129882881810110018C3812428D41816014800411118128280044204204002022810140F21E4800000000000000000000000000000000000000000014000000808101000000F0AA3820C122C3011881442A11821288921885238111E14132112C428994484188004428004C1462821D341211828664414826815B +:80858000621481A3C43810088110141408C024418D5234221601871187125C7212C84122257182C219103488E4008285A45811822A149248874527228C6D85212628084A58142830384044D8488882024287144644592400123604C11248EFCB4A21E13172144891188D214D1826031483681389511829111CE241E2183128278C4883DCAF +:8086000024028416022BA18C04469C8226F83184160482A816C444938238418C324A6AC14849141908444100452813F4243730220016681244211A642228254208418928410110C411118084887448342483C41220022044912160C100C02C2200841484101402184783004448FF48072228000000250140080012241114320060824211E8 +:808680004231109128003081241AC21160121121153828100214004100008800F0FAC6001695140042AB1290188D1127925260B18958349C02844D439CC2218D14148220614483C318882B1283A3212014942811211694184902104182886194AC14C48862A4184901F0D4F7001F4211044082033195020024824551831414163121148460 +:80870000850114481C8441312860811211468291191001215528023110011C4418122812B8824104F03BC120021800488190181817828B1470184128612240686684221624820C2C1134281628B81282822208262412912217418C814208402228416844418848001200FF88029584911148481440614410243518891154488814B3127AD4 +:8087800021088145091B18C02819211168138303288C018C048418102481014D11128084110C848183C1128C11F88BAD24814C0229051049042441002E4150124480018244430223A2181724008421110031848014229484B81C0240314484C02A80220162C042A042BFE64BA11200818C311A20018C92192800208121044B12C0881150CC +:808800008484201408131118B22821210290310081231149088C028C880148210000008F3848D14322C312818C651181433144892221C1181E41442196C4431781897321388855582C22942C841499183D182E18A93218312A01C0318143E883B82731188C41414938884E121883241118188825C168CF1606184414122484141100A58153 +:808880000684701508C02241884128118504142628010012221A0250282024014001A0611810086C02A0421810083F110312282232104208182884230600C0311C218192311C4109406B851CA4211412811088311119D21802D0818202221140010081200200202272CB0B428141811608008482004D488E4848850182004188188841181E +:8089000045210A40088430218A02008A022021281A28010043618449141804309C825FA601121008A0242142208401001098481C94411200C08A002400811118200440C4222A014484B0188828015270180212A041208102414F8F0E1400421044111414446164490187422290182240C48822D04109104981084001B0910220348810B1A5 +:8089800084020081840000208242240882CF41072022922822008021A2122884202182220283922980082184812A883249848B42848122482294238A44882232482211008908100280021A2282F2E98640088C24010018004004400184508400361835417042018114180000008810381222402802001100108808200221F01B2CC0644211 +:808A000048901C50488428128CC48C13A424481B8400904182144098881004818001482200208181823818001880488441888834580096081212DFE703000060220028302424008180C1482E4114890122148440018301141818193281102111491861158410418918810888C088002602006FC30A8C021C04263144414954144905C48026 +:808A8000024C6514C01C58002D14C01324884820012A68164A8841888104121841490800D4CCC4284004224C0230842728F0D3A1006A82C2281E284D2444811CF394245992289741207631A143121CF171383E948F89C9949718FF7848724C3D288B1289D518014A1498111BBA13117952A29D1922B198A88413484151518C18084AB428FA +:808B00009128A0A249A18A96F4DA1AA04640B83871282556874B1445A4548F84A18661CE481889F649281F96F44564484942F11D212C44984119F1C1811F117211018B33808A621126E1B33281267834716C18F488282E9115A889CB448260C825E84C6A424CD2A481D24883F2AEE4F0113484C712422CC142814C64832236C24A4E48D0AA +:808B80008DF444881CB18871384851991322C288D09A51228C46688817818CFC18286E49B681B48482F12838897288D811E3C2228332189568818961816B8183C1481A2422A18A122B825F9F0D1504150411421142118819841881088841A84188412843084100008220084288008008000098808984092C9944984588490884F0EAAF14E3 +:808C00001F1454D5D14711CFD5F44B2B6D444F51E554F28545CB4DBF34F4CBC5C2DF5DB768F5B5D54F4C71C5E846F4A594457D94F158444D846F2454476AB4B1E815A4819F84AE794EE88BA11B441BAD85F23B8B2B441F1BFA4C44474B8F84F79818CB1919F1D8DCDAEDA9D146F1D8D84BFD8F49514C4F6BD9C8B8B8F9B8A26D11F04464A7 +:808C80005F5616FD3C39CFD4F64F2FF7D4CFD1F514555F5AF78915AF2ABAEAFEC5458B7D8F1CFFDCDDCFCAF3E559CF94F68893EF42F23511FF2CF5838AAFF45D232F14EE99F8D8C91E895ED18F8FE716FE19381B441F899F389FB3B44AF799B9CFC4F7B4848F847F89D948F889918F4FBF48C4A84F48F9D8D84F86F62884818FABF98AAC06 +:808D00008B8A8BBB8EC6246F4796418FD2E2427265F62E6EF5FD5414DFC5D3CCFC796FAFAEBE4AF648C8DF55F5FCD48F83F524F11FC7A4CF13F326B8BE8C8FB4F58B8B6F24DC77F422489783CEC11B118F9CA67D4EE8BEA95F4EF794C495F3BBBBEFCCF495848F44F4B4AC4AF529A895F591888DB98F8454A8AB89CFC4BD287424F8B4B436 +:808D8000C5FCA284BE984F48F952FA343F15F225648D2D1E345F61D7FF56CE4B15DFC3F73DFD5E72AFA4F2CBE1DFD4AC53DF57F7F9D18F56FF715D9F9FFF3D1DBFDAFBB19F8FB4F4878DAFF5D4BBF4AB691F9BF948591F91F1C8488F8FF769E81F9BFBE5F4DF5BDB39F3F3B1CF4EFFBDBC9FD4F7B4AC6AF739B8957119F98C398F8D7D2814 +:808E00007A1AF2CE5C8F8F7D24A8BB2AF2BABCBE984F6AFB3A7B800122001004200100486081F01148209128128182813100899211811881002A012641A812844712842A081484C04840088C840228824C027FBB0A8002844D1228811241288302A100198402421508C081C081219043000042221308008221008604840014001002000011 +:808E80001886F19F93C0421F4152281F4932481F41324A1D24AB141D24AB941B21AB9451AB9443F24A9143F2429147822D914F82C4914FA2C4814FA264114FA265192E4A96C54ADE24ACF491242CF4912485F2912483F49124A3F49124AB141F41B24AB911B24AB915B44A3934AF44B934F442944F83D442F92448984FA2F4F343D0A2E4B5 +:808F00004156281E64811E2CA1CC921ACCF24A941AF24AB44781AB9413F24A91F04A9117822D913D482F14F1215A4E912E8A87115F226D1D2E4AD6E5B2645DACF5512C45DA41D628E541521C1D64AB141F49364A1F41764AF41124AF14B215364A32A7443A54423E4825F43648986F82F54B7B40084904001800004480024002000021005A +:808F80009088000040014008000000004004280000000021429F770919812221512490749028152821818164148C041D18442D184611C11184C21584814129D421840252143824848C8191412826414AC32889E11801482884002E144432C3A2284F2B0F22502422420084182B124E2860281628082C028C01211A021B4260821417A41ADB +:809000005C488C91482C0838418A514121CC829218200842130212811210240212421C24F4D4BB90114E28122B2144211A140822CB43209B1813240483C1182137241C32111A843C8419C1528DC14D4817211D4888428D212A6124554A782834418361128652212AC4211743124228814122124D126A118CFA9643200241200443028F22AA +:8090800071110812244888842C12416481200117827021081528018324022921112409121828221008811688088112003024004A82E4720A6302004722484110C2488302810084283289A8424A0800461402224614042622086022822144201934110020088414001220491484012F820318903281A9C1168AD18441218348C81216082DAF +:8091000016C5011594141D141411418242668B648212CC2631342B42460412A8296B129038268881082C315188614E9CC488224B2426889428445FA74D6243303230244212816087A880C11840564140849554004445021C1242644180839142008A81E8429121128362811288A081428958424C488C084A8A0210F4C8AA00008562A116A3 +:80918000968416160184818121248361822A918943C2811411A0484883243668F0244830A628492452222C8208821694210040C2111031582081C214C44CB418026E5560214112214840842802C11018E441329883822682D181984244469828821285342128425C0221442A588480C51483618441413014142C122C04811002803C888466 +:809200001F6E012604C0681608C02483111C051880228204002821802164C8800246186291200181A0422142800122831424288113888141242124420418BF1B0F13C4122216342449628183880412224848008061412823816191005049488444002281181A14826182C02480611120A24220840188185048108821F85852E011D642A128 +:8092800021A3E2C16442C1228150812289954443A11A83A625411819A11416C9486240EC423421CC82941822A1122A19A6212781524C02411741421A621A80B5180483C816188744284A1888F855993084106241228041AC16C418000084003822A90A44105884164118C842302480418404801264818B1412228480C41245081218000070 +:80930000458849F8E33D80042081018504404428538200890144404408006022220040184118010000484410280181821A14A1412004802807001F290118418D241008504230883A044282430441AA24044486041748004192484210088C2101208182B8491118C4614E34D081024214B02831282847821028A8429F54462208616280024A +:80938000100244842245084C1252128423082200254444384425C92211003024644111E484848009811800890143018083014C3818C4FF6D0E122922422631840083210400301E118C24341162134808008400121968212485048014414401501411000040448102C480B884829424F0517D00411850845828282228122116885422303887 +:8094000020023AC88416F82D822211182A24122422921400112A0118139A44302486118483010000800490284814AFF90E800241008041C4188418212921C11C41168C81012D18290224484CA28113018416081E282081E4A304121412812A8418C82C46A1284C812882D148080020F8A3E33024803428A28F48820100624A2804422AC85E +:809480004122536442D1284421142819148864871D144400192902206244801241B411541411C4460100004189240589F4884C008A41981221901850844830281048082485419C820089082A584184608211802402282251144788842A31288A2111081828C901A0144381014C61493844FEE970644A8245982484E04491324941624424E7 +:80950000380029829122839122123D249014214A18041686A283144C4864E1244946A21260514088E2144264112820422812A4128308A74C22AF220F6892A5F828262F89013845C61483D848C1324E6A2443F52C122CF22B545F94F2F2181D298B122C7884F42281226F8434142F86F431413D35442D28CB118A322525F533158E2A9F4305 +:8095800084322113684389BF3172887914F1494453212262424FC1E342B9E4E945F45C31CF86F41EA930348E242CF114184D244F82781488B63AA2243AA68621274C4CC128AB444D28A5843A8A478926752141521689E2C2991847A485CA41819C2863255384524421871484CD999D1145589C1B3113D48489C4A4124D1820D148D4844954 +:809600004CF41E97244E1667224F432234288F4552281A51844FC165A4AF8194188F81D18AF412854FD2611D3E5245F424964CDA8CC38A4D249D6436A54C1F11E24823F338B84741285D144CA321C57238E18CFB155CCF51E341A26C17474A21B22865111C81F148788B216AB88CE28132A8AA8CBAE70DA012A012A094200488C082122C21 +:8096800008A813810A89228122093388921181B08802822A0114A01284490922204288088884888088840854E04402424D5D70847626F41E2E6FA1F452C88F86744CFC6E2E2B644F48E68CE624A7CC8F2CB482F264563F5CFCEE473719BF3E15F2249455EDB2BA66545557528B615F5AFB29476F749CA24748CF43FAE4E41F74546216FA89 +:8097000023279F9D56D5515F58F885DC5F53F148681B18CE9857545D149AEB8CBC24B294A9E4CF88FD8C888F88F82868BFC2084F61F2466EE5FC366E6FC5DE88F26C3CEFE7D28A76CCFCDC4E2F2CBCE2BED4748EFAEECE6F6CFEAF4F7F3CF66747AD28E7C25D25CFE3B344B424DB4484FED5955F7EF85FF55D954748CD8CCFCFFF61476F16 +:80978000F4D475D233D2DFD4DDF42D1C5FD8F884E55F4BFAD8E49B2A1BBE5F48F885841AF1D8D8C742CFCBF97DFCCFEAF8CAD84F4DFBBEDCFB28246D266F43F7142665F652744F436261EFE2F652781EF48FC4F4E8F24E788D8A2F25F5EED6FF56F56EC72F17FDEFDF7F5AF92E945FDAF925BF7BCE5D855757DFD5F625259FFAFC7757EFBC +:80980000D8F2B4244BA3BEBC5D372F61761AFABAA6CFCDF63C3CCD2D5F59FB59185F5CF848441B919F8DB3D1F915143AA3DD4BCFCFC1F1484849B5B6F9A8488F82C5BA242F2DF61876EFC3F26E2EAD2CCFCDE763F33E7E2F81F75C9C8FE3B772F798BAAF81F9525AEFE7F5FFFFFFF7FD7FFFFFB7FDB7B18FCBF9B5B5CFFAFBC4C36F53F2BE +:809880003D7DDFD9F7DDDDDFF7F57F7FEFD8F2BC3CCF83FBB1BD5F72F23F77FFF1F19FB7FFD9FB3D3DDFC3F3B5B4CFCDFE7D7C8B759BA29F8DF71D5C5741BAFB7878CF4F7C2CF878FC8F4FFDEEFC4FEFFFA4DCEF3C072B123026844184221E484302800448248CC42419C42413D848024411286044A02419912849111804182002618440B7 +:80990000E81228286288A0494482289E488922812228045FE30A65022542A4165028C4428CF2281210082D141088D422011C28C284864834221041110421204204446182811B416041411A041118008081444458481A5448F03E26E022F4112487221F41B248F11124A3D441B24AD141F24A9219F24A9251AB9443F24AB143F242B147820F +:809980002DB14F82C4B14FA2D418F8264A1E216FA264192FA2E459C24A9E242D4A1F49C2421F49522C1F4932481F49324A1F48B24AD141B24A9921AB9451AB944B42AF44B924B4427924F842944F82E444F9244ACFE30747A21B418F22D141B448F11124AB141D24AB141D24AF64F91124AF249A258B9443F34AA143D21A7B34D812FA17DF +:809A00004829F224588F1491C68D216FA27D98F5224ADE252E4B8E242D5B5E2C4FB2A468CD53CCF268111F49326A1F48B24AC12CAD951D64ABB45D28A9A943AD842AF442944F82F44A1463F242B44FA2F56527402888040000004004400100000000188008000014202182080000000000000000005012F06BEB10022B1218244C022220E4 +:809A800041284201852521628119C22480926811405832428CB22401232104224A4145C821189014424115484838488C2484842168424014C824829EFC20A5285028812C24A1818314848441C88C21264C2882085218802204408D7842C82124004200100288A0218A2219C1111854144CC2A8541844424031449FB30852E6A22184212805 +:809B0000122A1118D4842462128728512E148183C281C0521A324832488728D0439488C426321121102874444128021024C6249445012E5884193464823034444D428426E54974940621001285C2442188421220111814488822813224002811001484282B521420044A820124111882181288928117819045008933850000004F440D00D0 +:809B80008280080088000000000000000000000000000000000000000010010011400170E705502219214114CC21624115BC22C161128E822518B85415E322486148841A9B4947586AC122129493C44823584C18284A2C92178FC184A82E145044250A2AC611859AA24AB42411E2210887481E18A8CAF42D2A90226638114C312C28544214 +:809C00004125AA1148268178821A98144827238A48A5114E289BC814444542B818031F943482812E1649928252196148499828146614648129A342348A184298148AA4832425A4112845F8AC72002008880080080000000000000000000000000000000000000000110010011400775E0012100111421781604122111001004814800398A3 +:809C800015081181209114404A342400822D111098411830421280144218A8494058484181924A48F8D5893426042642FC18248584212211A841A3E581745C021218169C888B161D48196114444110C24D91284364422A3112184616443428294112881B91818011691113152891922229A221428441DBDB34260428414902122270188424 +:809D00009212701102187048748831488B24A094851114110A9CA1124289024C026068118123612480098E11205581939159898481C1264942A8584E8844FF510D204112C9189524941912A01493B448C14C00181880C31119411104009744101444343629217144024C2142189118282D41001002A081D08218082A0110F8CE5F002394D2 +:809D800028806441301830481C17CD12001810044418CE12125681464168848C4428C141460228AF4423043880220118848481440028209414451218528483F1B8F120A225001828842200302400168822842202294872245128242A69210024404984028148812014082441447024820248108801006112127F960B4840C128103914E05B +:809E00008412428811CA4480186484122A114108000041200580024400401108002AA41418588004122002424880A484EF330C2229238282741954482A61862D481D488D21833146892109CB241828314E18112C0425911861608412812221446906841B128122002B614684A1142180840178431114028D548C78B7094850188418281842 +:809E800084002A21110220624480321498824C53814A22028C34482C0148462482820100428418106481818C02482012088034484180E46D08411100811412405841840091CC014061415E218489023445D8288142028522014508120015247411480224118148241005901444634288223148F0613D20011011C418488922025844410010 +:809F00004782C018284400240040A24A8D16408A215281242800329018008324911400200423C88820311A8140F25B5A0000498204701891162850811008100820818194148941280684A042404CC84260448415082810482441182A082480688400448694441282DFFB061128932214D14852818624021128CC8501814931284260844199 +:809F800023E252841184420480226411602484444846841482049012005821984400C81842308242FF21038A03109C34411A2202890228180022482621A2242A614248C302A2248F216222368224A44100224441188984C4386012428442444A8194442094748384B31684E414F182A74038244412004441811480854404462443041508CB +:80A000001429014342D48408001829018F1104800210A12144893248288281004C8121240222803816A3F273CF14411448260113270400284008468401101404120042421248C18420C2210084B0284488013304002120241801418AC18810082D88D021084A2234288168802204A0248C0112008024049052538224428224210342001230 +:80A08000425884400414184A210252884014A438184304410024889F4B0A84003018400C0083614480C21848C30214C021859142E01411D88448048032244D41241284112A3421289025D120048744821D228230881281203C882504CB31145B42821538115B368D389742148185F161288B34421CE145D188353885F82445283CB211D15D +:80A100001412C8255845F81A6229325223B142D644F211415823D2896242DD14683B341FD1D149A2442B312181D02371C3A4829A782488E1A271146A898FBD28F2BAA8C0241F561218C44C625AF7247284418B1136694143116C464D184F12A4247E158F82E59266434B2226686487244F8268E2848F24F3281487868B1427245845D484B0 +:80A18000A24442163A4A4D4A9558A88F81E888A881444935C44CC592C7488183C8844D54DEC8FFF5091A012E248FD6321857514558C83E241B224848CD58854898244E241B21125D4812C7444AF5435DEB44CF8AF232244E14CB118F22A24243A151A4124E2450193AF23919B02426E113A2444E544E424B444F14A8811E16C784DE446E7E +:80A20000E847456ABF4C0525F27938144245011C41480100140040840484441110011110012181290829010021422601146032601260221A4421488204800228009028DFE84F21D451D2CCD2DDE7C4F44165C7424F4254881F12F25C583A31184AB41CF164244FC6B654F138184F43F1341C4FC3B114312441CFE2D2ECF148228EAAAA3A57 +:80A280004AE3D54454288B5558474245F41444817E526F95F56C5C89F1482AEB8917141551357F11A3888F43FB1C344CF19CBC9AF95CD48E182CF2EC49E044E244D2CCD2CC66424F44564CCD6445F42424CF45B718F73834CB45CF81E243F374745B35CF837135F4545C77834B351B568782CFCAFE161487279E9AAFAAFA5852AF15C4489A +:80A300008FB4F45258588C54DCCF817418A1554F84F544544E19428F4CFCC9491F1EFEC5C14BECCAFDF8F4CF45ECCDFDC4CC4FC9F9DEDC4F88ED89F5DCD5147AF425658D28DFD1F35C4CDF56F66C2C4F4656CC5F53F3585C8F83F158784AF45C1C4FC6F65C7CC75797934F53F131116FD7F53551CFD2D111E2E2DEECF5686A2E228F83738B +:80A3800048F84C494544E285B512F72161D5FC111519F1717BBF95F579399F83E5A6F39A9C8F88A86455F393914B88CBFA4F43E346F528284F4AF94EC4CFC4E426FF74D7145F55D65556555FD7F3794DDFD7764DFD5C78CFC1F31D3D9F57B738F35C78CFC5F57C1C4F42F65C5CDFD7727DFD35359F15F77D5D5F57F76D4D9F92F224CEEF2C +:80A40000E3F57C481AF13A1A8FA7F55A58CFC4F7494A2B552B319F1252DD1F15F371733FB7F77B78DFD7F37153AF27F3DAD88F88EC2CFE17173F5BF9C4D4CF4EFFF4A4CFCFFD2C2C4FCAFC9CDCCFC1F9E8FA2FC60E221044382484436281002216081A0412281A84028922E1440289028744D048028324022014042280C148181E4820010F +:80A480004820482449A44885042049048F9A0C86112112011781202152C1183048109844C0481C2141954181411448286D12A0121225385820110214150C48251181E181941A001A54122A041290444A01C0417F330A3CF4112485F3112487141FC1764AD341F24A111D24AF149921AF1419F54A9143F24A9147822F147924D812F9244828 +:80A500001CF9244A1CF8264A87116FA2641D2FA264592D5A9E24ACF4D1242D421F4952281F497248F29124A7241F48F24A121F41F24A921B61AF2419F54A924B42AF2439242F2479A4989A4F8284F9244A6FAB0CACB11156281D64181FC1522A4C92181D24AF44A921AF448BB24A39242F14698229392429F9364829F9245A986F827C183F +:80A58000F126C85671226A586D5B9E24BCF4D12C2F22E44954289E64836649EB1686B4687191544A1F41B2489325AB944B424A19A4B4848D346F8284D926D5A60200480000008240042800000000000088008100140000000000004004280000000020F4B49C30240020449A1C19642324C0488CC1144283A4411243883815C04C44002850 +:80A60000228129641149042B424602248061CA2220F1211418304280A4484D5A87414B41A997488D249018F0A5AE003F28624181841F42018516189C1822406A211C01158885260622C028A0144508851412A2414D182D14523287424D234A11F4122487428984288521A418148022084301411483F4FA8D40661623113848851344C32AAC +:80A68000C12062C2CD124A31484883614C2ADC340566244128A843818146581253846482A394426A21E24162CC261462C35B25984725582A2431418CD1C2C1928B164E1847A2448483F513AB200241001E2489C14C18901A8C840124138111810128101884023024102611229156168401E1112B12B024018100008A84984428490441006C +:80A7000018F0824B4092214054224062C12244002C01188414843021142688C24842111261460581604D8052241A0240020080048008814B491812892368441A44048F984BD1526141828962838D41C4D05AD118D48272623A481D164631138C6E64C0444781B0C101112674227138223248636561224E122440C1324331242E4244242403 +:80A780001F22F1881118B9D121C145248F42044974422CD384C81850EFD04131228849F21A2248106692E42846784252241215F84128460A4E214D11284E218314012B21E3E1443248482C812474224282211242C22241004E111818881C1188D98482F1483489BC14E241484CF2747F10D241018110496C81693141812992181CC14129D9 +:80A8000021180441818198809425112C1241321C41432B01412681C1144C2204502228A718249C01671446B412042441428924015FA745E244622516182C4424012041A824124698141C0148243265682241818051218C1822A21216810448200438AC4104886A28024D1860844887241014082658824C81F1E79B004A027022048324612E +:80A880009128008243410147818484204A42C81226C88822128441501818D081A2215211812324C1644611284118844284018842182814294828E14A05400412103A24240040180A818448121A0420844144C44418481A024140240121C0140028882C62112011210820911C8C81041C0820F4AC8624441E2421C9D142524A8F41C41212EA +:80A90000328428A971541868818CE481C44232678268C445CA24C9D42123C138224181411866A1211853D128735802AE44823F83A4210082C3A4417012D448351822848200EFE20E2A0489014220028501C04888C015114C0189018880018100AC04411A822105100200E0410219860889711108001E48890842804AD84881749C0D5964F9 +:80A98000181844895494114FB21414141108644485851424140520044A026241480022004604412243241402290C2112884261182D426A88942280120A4D1A1F290C004008184418281800521321110226518129010068414D42200916021628C12220031210088305AB244C28049858001288800418009FF3042048342800421842148C1F +:80AA00006812811008111200A0410028002290522004004240041842210080881C6224C01441A086450243A4814AF8E798203124813143219618484C8282618121002633184601AC4261C210042688C842004604C064202182044C02162482239822400442302800A0921A28027FCA024C240112100441608480324252100AC1111304B040 +:80AA8000442A22448494142314843818288006C028188C94248448483880820C4CE142042A44B4289814228423F2AFF400282AC1226850840049828204604416148222D682612210924A4448002242268452144004800110012C213144184C11180420881188812C8424F4977E1429021032881A826482481961A500C018F0182400224914 +:80AB0000840400242848800200408282024400232242040040028284808D04818885F49BD4A0128222200222200100844180024822B011826241418092142818801301802184013024181004402401202C1104848E1180E81281F8E85E5082444D486412C681018148E041248102122E411818437442941C290218818821412410424102C8 +:80AB800025084C8422812406442CA12444182840A2414901418504A502FF554DB15434A42A3212AB91493134C741429B54848F86F21848407634341287128572116A142E444AE4C6E246242684013E528E448B15442E224E641A0318682E284CE282A5444E685AA371388B1145064B462B234E424786176896F4224C3EA14F82F4DB47249A +:80AC000027428E2147E11CA2264EC1CC85D348F534254A42A1144751CD18A5BB4C7345B42195385F623348451694248D4C1AF676C43A64443AD28202424311A221C321714C64258F4562624F43D16438A2DE82C24AB45489F84C5C188A949458DAE998D522F9E1F2C031169418C7E2CCF4312C87146E4B4B22F098112F2115E22421953181 +:80AC80001F92A4714E216F5694424F81A3B248D0247222C4222764103621384425A24643E24252441E52195422B825223844D0242CD122E461A188439BB87E48CBA2818572C8F483C714800118400120410100002400122412200100184218800122A0124218B024012E124002472212224082C4224828C024800228EF35470122CB212EAF +:80AD0000628414C5DC44D2CCF224258B4424AF84E444F44444A5B1220247448FA441F42C4CAAFA386844CFA4F126266F211C62236F68F81928454453461A64848F8112A44495FB1C4CC5BE145164008F84F48496684D528F8CFD54146E889788A285F81898CFC4F42AF314126E44CB22CF62F6645C6E414FC4F44434C784CFD2F26C248F7A +:80AD8000A6F26A6C4F44F44C6C2AF26F6D9F93F26464ED2C3F54F26E48FAFA7818F02CBA6F66D226BC62F664666F685A99457424764E9E428C54C84CE44651FD8558EC6AF414866EC48AF868A84F68D94446F29CEC188F84FD9C5C4BDCAF84A4FD4F8DFDACE41419A543CFA1F232288F85D419F22D48CF83F75C7C5F16F6494C2AF24868EF +:80AE000085FC4C4CA712BF96F664455FD7F3611B9D5DEFC1A5AA8F82D7C8F46CCE6F43B272A6414F63F49E8CAF91D244D264F2162C2B451AF418284B338F84F61B2BEFC57446B616F3C2762F49A3748F8DF786966F41F52652AF86F5FC1CEE888F9EF8B4942F8EAC924D36EF1A41B313A773CF21F37A32EFC7F17D255FC6E486F36C38DFCE +:80AE800092F2693E2F26F24E788FC4F4685E4762FFD6F374155FF7F3723BAFD1F73C7CFAFF6C5CCFC6F67C4E6F47F3F2722F23F37676EFCDFF7A794F42F224266FE7A3558B31CFC1F374348FC7F37F7FAF85F556762B772F6FBFF2AFFF8F8DFBC6D66F47F5E6B6EFCFFFE8388F8EFBFC3C4BFE7E78EEF84F2EFF3DBE10022210C44843C2F7 +:80AF000048221E4826A241C0484416C8248CC4261904A0246044A0242014221402201402004110A441800482A041449A041A442439489220D8F20A824C1248342213010015344828001811215150848B2441205248411086722402004014820244418C148612A64929818401215042862854844248C04A96083CF4112485F3112487141F04 +:80AF800041724AD341F24A111F48F24A9119F24A9351AF343924AF1439242F347924D812F924481CF9244A1CF8244A56F1244A96E1A26459ACE44DC25A1F4DD224F49124C5F2912487241F49724AF28124EF24F9112CAF249921AF2419F54A924B42AF24B924F4429247822D944F82C4944FA2F4D3E4C05A4CD628C5248B141F41724AE2A0 +:80B000004132481FC8F24A144CF24AB24D28AF24B925B4483935AF2438342D816F8B541A4F22C5914FA2EC14F8245A86E1A255586F326D5D2E1817CC6D5A1F48F6245217886A7181FC42111FC8B2667911F86A8415A4B45F88921A4994BA49A4B445C8B42D484CDBA6D52F0D004800001200400428000000000000000000140000000000CE +:80B08000002002280000008240017F2F028234128CF22B144C81D184124C92180050525E28841D5882124152899C44426042428991144B242089848211141638744C92424D411B121A2C52821221430C44C8A24482C04841AFDB43832208234112C9A8002014384889C142148052842E44844998111C024224180084428CC228200422266F +:80B1000004840040A41C428883084A0844838121012661848FD209297241226181275327518B21261C0C4945287618524137868193918478A44B414E915B43A048B0121448346819A4288C96281A644428C44A7328844434114E944F222464238938448841436482412C099CF21844FFC50B00242881848200100A812024012A141844240D +:80B18000180842C0242081410483010010861204211924029884888088048298120042246F4E0718000044000018000020041400000000840000001180020012000000800400000047828074170600004211A1112508A348480840460110C4114116140810028014C242430223813114A45912481102944121000080442244084282C4BF5D +:80B20000AF04000048340081241E888181004413041441131144440824100846020024111812814942981121501844008004008004C06860445F390E18000041841502000000240000001200000000486902183024241100004002000080440281402418D84B04112200212004805228001002840018804208424840081800000000002869 +:80B2800042121A28122808840044001008007F1A08001A0240080000001800120020230481840000490418208104A0210018184028A44842004888202102121A02229F290B0000004028012001104401400A002288008441002228000000804208842889010000204108002006CB9E4081020084480022800112448001241832628486187F +:80B30000284448084C0412208104A021208281048AC278C20080044183810289812284F22B8400A01210024088018502002111811008002820041004182822000000008C8261818901818A0484208801002081022FFA0B0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000015 +:80B380000000000000000000000000000000000000FFE40F8004000000400428000000002180018800004001400848000000004480020000001002183F5F0B0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000A8 +:80B4000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00006E +:80B48000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40FEE +:80B5000000000000000000000000000000000000000000008400002001000010084200F0D12E604100221290248904180011811210048111480080028041E618810400E041020011420044882800004A218841880940086E3F24284100100880120A8180150128830542260822800428A04260222200241084011082335822188001892825 +:80B5800041088820840200DF140C164404221230248C2402101841C811001038412A0428A0240018641CA92400001E244400118033484922212201838821212808422200F0DFCF302200008400241608001A04C0241E480081000080024A0230220010021840820412200800008C041281920081D09808408461412211411B410021124099 +:80B600008801211281820046618210840228002904418081824128628140282629A2410018480089084C51848141AF18022816424828018913C82C1AD428420211814C3121872449D6245594188460C4211C341219A4218B242E1284812223220800424C818421048890441C5848281E4C2A91588C26BC4401BFA606222031180084004662 +:80B68000022901141210622489A24815880183724802241828282A241448042282188480112424A2488004448884224A913848362888019EC2006C41488413E142F111484D281289022184814391211698444311069C0444414E21304118842B2121842829810280924818841A248122094819C144108C38184C7444D84844D4E54501428A +:80B7000083A112D08162812A018071248223041846081820C1421184221CF14812188924048394648430282367212A91448998882846382C28412A018341A2144A61881018C218129766202444044844405228260841891238141004840047281242B0A285028280422101288961448484102202224212C12200228D24C0342210021AF46A +:80B78000844FA012184012042A04284126480851001004493322840000400683212102211800004004000080C48448200820248802846E58A0251841244C1469842692286D288371281268941604CC44248121D1849811602266C122418183A4218B422A15222102D0820249E88822B22824A42181428624C122C924B184A3248C0840F8AF +:80B80000E2590090181A024CA21212002280110412008143922248C0480083C512C218004484282CE14192181247248400C02C00183048808B14082092182CF46DE680014C323149C12811441AA22100411142B01C9218818441212843048B42128302160884281E68208122A22162001B1431D0480C27448081041288188302003F1F0B85 +:80B88000242C1228044845181832420000182E182032144100841411000000200100901800444285C4584081216991260890844820014622F61BB4001810D2C1B2111411C8284127A1181884130221412440C8282280846182A024421842005E28480010881238420012A34608481008100C4141F0675900804208002004C08C6B8418A12E +:80B9000084402802290124154808112C840113044200301814000012C021400400824A2982210381008DC32018042001201164838036182021A11244896411328C02C4003048400820A12120850228004210018C018C024816280286584881806114AF17072E189012122143C14A402284022EC228B02114044400C048008004814818221A +:80B98000001A02A04112324840A842846218E084122892884AE14482C4248248F0528A0023433422422648249442244244210044811901C3524240011110C121111C11C118284840210184118D211041881681621486014858268401824120F25A4F80061851A9022449854188A11490118084240218005242801208220042000000814022 +:80BA00000810022210828408207428240600F06E2750848004111120421C042D8424282304003248841002CC35482A081618011A42410884428C048B414885118263D4704225A128608822008091882388F1A118C0328E226D188F32743AC4448794C7A5484AD222B2486B4814488B4447C1CD2449E39271380C265AD187848B42814E4802 +:80BA80007049E91191581A95283618A121818C13098558281782848FD16422921691288CB5C8A97543088B2343C891127FB30C2212F012145B348B1715D242A336AF21C518122F21F51A123F81E1A2A2221679282491162AA24490411E282E682E212D381A112181E28785A251833231221AB548A6446F95A4558B641B14BB648CE5842474 +:80BB000034282E2847424CF35C288885A4442B2225014B412F42E1639221941D294584741E7E242CF58242CB8611624F11B148A11256D86E04A5D818B34C4425D41111F8384148486E28228025A4148C31186E2857823419D11A7221E52AA211B7469B881EC8CAA841828F87EC42D584C188414AD4C702B0220161481C8144224122019E9B +:80BB80004824125C22410114128501000042208401222032411001842200122220022009C02480022098283F790F4F25F674141E221F13F355195F55F51913EF66F74C4C4E546B262F24F87ADC3F14B458F349551F57F528249FD6F5692B3F13E382F231191F9114D49155881F16041F14F419198F81F238288F827239A1661F97D299A212 +:80BC0000221F14B22152313F34D513F37D349FA5F76B7BB7168F81F1511126F8B8F8CF82FB6CDCCFCEEE8151888F89F96A68AF440C4F26F67476C7A29FB3F73D3DDF53F31D14EF47F37E5C6F47F77A7CAFA3FA52F41F35F453116E645E541F53F24175CFA7F21E14AB221F97F34959C9F4A1F98B229F92F829398D199F95F459598F82F382 +:80BC800068791D391F12A37789F2392187859B2697B437243F11F57D3D9FF5F5697BAB771AFD59112E288F8EFE2CA8CF84F9ECEC1E3A65FC1818AF83F3DC92F074626F43F73E2AFF91F257115F56F655596B76CF61D76CF77A3CAF84F95A783D13BF11D14CF1785CD7528F47B768A3333F92E287F3455D46F469E995F969691AF159411FF8 +:80BD000011F148798F87A6663E281F16A6418F83F338381F15F729689714B7B4BF95F37D351D66BFB6F65B719DD91D9926A8F78F86F3E8DC8F8EEF82D1C6F894D42AF781F2F054724F63F53C3E9FF7F15C3DDFD4F65919EF47F33E1C6F47F77A7AAFA3FB5ED89FB1F15B59DFD7F77C7C8FC1F27177FFF7F31E1C9F92E287F345458D459F64 +:80BD800093FC69419F9EF659599F15D411F178798F83B371F771717AA7519F12F239318F86B2697249734BFB7B79DFD7F361633F36B65AD799FD4991FEB87AFF3C38CF8AFBACE44FC3D3C6E825AD76AFA60F4110423822844D12844302400812701108118113D148028304830483048912210483A412C01140011C81048C44A14114160824 +:80BE00001A048A0484200100E0DB094B1A122A711104174120C1121E48229A76422241A1428921C1349032C02141812200285881182826282422018C22C24824B0280124684038484889B314A4A4412841464471CA072E521F41D22AF11124A3F41124AF34F11124AF24F11124AB941B29AF24B915F44A9243F34AB143F242914783AD91C3 +:80BE80004F82C4914FA2C4814FA264154FA2651D2FA264592E5A9E242E4A1F4DC2421F4952281F49326C1FC9324E1F49B26AF18124AB961B28AB9453B14A3924AB9443F242B4478229FB2448984FA2D4EF022E1A1F41D62AB11116CA24A7321F41724AF21124AF6638918F64F215688F2428D318BA24F442911F8194AA7F8394825FA285AF +:80BF0000F925CA4AF8255AD227A287592E539E25AC74D14CFA91648D421F4932649E28E7141F49326E1B28AF46E148F24A3143794A3124AB9422AF443BA429BB3684F1A65ACFCB0F000000000040040000000000000000004001000000000000000000000000F0456B800189418181815114182628B38804874484836188841D18280081E9 +:80BF800020025311889312588B522842424850422826C8186266180C13440A444528317848412A190CCA82F434773024B228459A48158822833214208205458122A341418C9114832AC1212006430228214112268C32262A61821240420852C198584A2189014149CA38462CA1831629F245CF9014522A51148904324C23923C4B218B86D3 +:80C000006A415C4189B288C1184391384D128483A12122AA044CA2122F21827171A412418934644A1126932812A984B64C11F414C116B82241741408833764CCF118C4A42AB198A4255F4E0422288184297111081118000048811228488501200A11001645082044082E48282128830240284208848024240912448228224C2188029F6615 +:80C080000A244400230218442110A82180144808845C22081242260855088042082228220011C1122268810012A0412150228002288648648142A41F13063624B21412CC148C7441BA69E11364A12800160B36C3C512421A24B6446213C027222B523899B4448195184626252664432826B11C14B454D224D585828406819A14282591640A +:80C1000098522B4144124AF2BC6F902425841254426085336414831182018D11211911143824808201283C62C218182847816083284268484C22024A11B44C92442D2CA02412252808482262AA8114548418F098B11418284911889348118F4231326082222044782832C1181CA41C484E246E118444112B4228998424054D423800135149 +:80C18000841E21262C268141810548E0244198121841C09A4A8121B428F4BE6AC02442455241C01B2880012227823885C318141221422260441223C4288951824D482842181E4920018B34623860814488804802492202422C4328248121428821F118F940E144018B12424048818231184981A2184128C3224521C188281461498431118F +:80C20000881A0870240122103844004412224142809E442A81C814212290684A129842481A669C80051D28402422A112800424844410086081422282490200204108460826044A02004042985860814160188004202C038180322483F81514C0214487427528E492911A8081C4282D18214D938901260E1324648A4B244711496442843741 +:80C280008149A592423058438202122228701C32182E58448845821C01C845028B42781E288944B84842C4A85EA9905412141A1204221B212212184C921884441782181A941832208802830488848130584302184AA2424418004488B04801228A86014A219382202483022B34486FDB0D00122004321004812A8121114818732418410146 +:80C30000004A020080024800482A818302920000444244484812418AA11600444781283622F2C5FF00C9024E28401488D228E1288265242C623818C0488651282602704A02485668148601911A28C4D11C984225810100004CC4414429018241144342C884412880280CEFCE0D0085124488810200000020A12100004898004C22711421C9 +:80C380008204114228812280026A182402008022012A0120220444C04242FE5700120090284C2481240148811A0259021100301211121812800622001C02424291481D28B021611422189C224C1104C200849260284618027F7B069222A415081048C82C8D84412284201112440890218005422C3844218062112282902120014982240115 +:80C40000423624051A0619614148A012281822258863127FD7068C06182C82162541842182220100C10041222B4100408224C24889042812C042608180A418124852192154221A021A8202824392444321E4814404F033A100604241840048808494821A04A08219819441218628241293138584014146882C8C6118A48400000028206817 +:80C4800014008E244004824820281802BFF30C32302420420822C0181200844130640080221324021CD21482420180038001484420422482C12200003048C0441A04432124041AF4B14240888104212A21C458683028449024892615CA4418424851332884012C38148D4420826812008C6412484896C168188470B4C1815C41A12888686F +:80C500009880386822282308DF2A011847898FE1E34214B814A2362E182AE22891244E32844D124285CB319D2D8511919243E127D132E424F448181AC2212811AE4142881F24B418E512E61182E212A15B47152A95441C644498121A61411CB8E4E48386AC831E188F2AB224E81813B2AC0F2828D08B92222E141E448D64ECA4278D482A23 +:80C58000A83496D988D242735E24941426628619914942145F697465F243D4475485A8111ED16AA2883D281218A0E1468132512E385E16CF3377D1C1314F1A14B4FC014E8443A6184D444F81D488E623A467ED2EA0432A312445E28654898528B55CD1C8A8172B418721E041B134FC21484B48172429C6612B468E852A032AC25547838F13 +:80C6000082A4664AAA2A9AC52166B2423169418748A82E5C2813B524B283D842B661041B984CE4419A148F49F344446AE24439C24A086F5E01800122482A012200B02228918248A81288848815089628048001809211802144012A113128199418488501458204408584A24900850428A0242F27064F41F114148D24AD4CDF74F65777EF78 +:80C68000C47264FC5C768F4AF212B2AFAAF9FAD82D88EF89FBD8EAAF8AD889F8D1DAAFBCF85A5A8F99F9B1AC25F82828477A7D178F917C49A1661B8A1B5BAAEE3FF712532B551F17F33838CF99FD984983F511195E192AF32FBB3F16374113E259F8D8DC7AF2D8D8C784CF8EEF4FDA88F43C7C1AA5ADCFB6034F41F15454CD36CF62F44D7F +:80C700004F7F77B522F36C3C4FE6F72CBC6F4AFB38388FC4D782F98E9A6FA6F62F299DC81FBDFDCA8B2F25F5F2F11FCAEFA4F52B294F7CFC7737FF91FD69696AB4F1EA1FACCEBEF3AF16B762F539713AF3B4B18F9FFD79617E187E298FE4F3E1E73F5EBA71B721F21491CFC4B434F65C788FC3F678E84BDDC5F87E345AA7DF8E9DA0333AAD +:80C78000F714262D2E9F34F6173F6F47F2743C4F67E74FF77ABC8F87F6587A8FA9F15C9ABFB6F6272557589F35FD422B3F1BBF12F1F9B58B368F86F62DCB7F31F5387957526E611F18EE1AAEAEEEE23FB7B753A7621F13B3B4FBDDF44E681F11F749311F22F3AFB83F5EEF13B711F391819F8DF974F4CFCFF9ECE84BFE8FCFFDA8C8EFCB23 +:80C80000AFCEEAFF6D1FA0313AF71C36CF66F2496B7FF3B352F37C1C4FE7F73CBCAFEDFFFAD8CFA5F4981ACFA5F9DFEF77525FDCF45DD52FB6F2FBF92B779F5BFF6862BF96F62DEB7F76F7BF695F56E414F6B1E1BAAEEE1F2EFA636B3B772AF23131CF8BFBBDD41F97A2579F16F26D7E7F7EFFA1E17E611B215F18F88DCC4F47AFF34F47B7 +:80C88000BF74FFFCFCCF4AFE7CF4AAAEBEAF2D042A010045024184800484400811448444A02480122114C224902800002A28840149014B124800A0482001001A8462894482890228F0BE3DB084819218CC726A6241A021E0C1021A12281128431141024E2119A4B490282084E144F221485222422C9121A0212280082AB1112466412382BF +:80C9000044015C014CA242B014048C84C341CBC7C0521F41F228121F4132681F41B66AD141F24A121D24AF26B911F24A9251AF143934AF143B24AF147B24D81AF9B4488F14F9244A1CF8244A16F1245A96E1A2E459C25ADE24ACF591242E421F49F228131FC97248F1916CEF14F1816CEF24D1C1B24AB981B64A9945AF44B934B44ABB249E +:80C98000B4427924D842F924484AFB244ABFFC04241F41F628121F4136281E64AB1215F44A121D248F62D941D2288BD2483924ADB143D212BB2594922B484E256D121CFA25CA125F222CF9214A4CD2A1EC5CC24A9E2C2E431F48C6421749421F4836468AF6461128AD951D64AB3449F442154B42A9BA24B44A69832D946F82E444F3845A1D +:80CA00007F190B0000000000400400000000100200000000140084002002000011000000000000C0270044384B128C41C933A012D081321812A0142A5C2848842823348480422882812282276142CCA8B48022210280A3821B21478218B042081348728428C9284028A1124149F2AD6F6042860240821102C42829E12812D8485141259919 +:80CA8000818117484C34852A44C8441B48A9A4241014A486482290242924029021172400584DE129A1128485B441A12444241AE64A84344C871346F83575106424B0140225E13102C1F0261189322A43C1438332814817884D621F4894A4846B2193E888222592241E64884C1668178582A6162830214E22282A91644B3443A1A126C88CFC +:80CB0000248B824B1885A216CE2424CB14225E24EF9E0A22442A0189618121A01228819218844CB181542884440048802494422800A025E04882C824000030118811893181258204114E1149042240A814228D1484FFB20B40D42201008901209198193448D048014A31258542482162144578481182021E2121005024C05240421408222B +:80CB80004800A028002C48C8A448008B84A084246FC246C2241280F2324215021F2224F1228630224014D22864822D4A4B42646694141A823222481E4841A9C42CA381324422488AA212260C3F4483D642E188922486DD22661483DC5818EC486181928E6C4A92244DE816C8242F2A0C6116446222722583218621F81882488124490166BB +:80CC0000581AC1211426C451C49C32428C048F13342284224228482A24618241278490164A0894B041C2C859586885F414885A984848882AACC126B241062224180010185122361432214241818934122E442946FC224418222682041A5224402E014164602928450253A3422889C224433862290884881A28022E8428665C848141EF1906 +:80CC8000021C012C028416119129846C52C1A38152624528144401284309847B842118809518008561848C028922748128415861281884C42A11240AA741828344469164849014843BED40384216658149D22202605100B042538124222301A99812B04403A9028CE1882402128CD414524288004AC122A02481163424203288CB61C098D3 +:80CD0000281622A1142A8101290644150120011C02002C011220220820C1481822642200902C004430482081391222604241890288008041816884210088C041004088E4CC083C81F111243D18C12F314271211823137232E22154784582654511212CE349B2444118342E80946416B84811D82CD148318822303449C2388B2415381436C6 +:80CD800014F824188CBA183AC8A9588298ABC14721124E34844AD28441E459090080220220911C44854588088122A1128DA24120021F8A0484898801202422BC224128028D830086342200C0114820C11400484A0200218CD41B0D502424201292122D12812784282308236484AF28042D12682911021002002C84215124502240022422F6 +:80CE0000482280A62180614A488941A481984227414A93141280085FD6030084812117818B24913081C0242302211D2483182C9141128C2258218400820000442250A444400C81402482828158221821B0222194828244102AF4A54C800440688283222122642222D01824044280322C8C2602100881009088A182228428442A8402814535 +:80CE80000823C14444202288188481088028188464484F3B41522114141C4211440110C841110022A0420082828821228800281002848424448890481AC2822C02822B81D82324080028A012242C022A2442F2FD76A02C100A183028182901244004C8888091128180A11824812100902480024100141088C22441410088581008222098E4 +:80CF00001838448021F495D400446021000028004410181808448001A121230980242201424C4431214058840081202284128602C11604822E988026248A0921CED4000010880148C044428004008894422812261182228809808281423824508400004420A828004A3122986021000060812100E30A450200482880A2422800440010288C +:80CF8000120421821008A98282342845486412501422C02881184440049AA442006088401404100418A2416FA84B4389C2422800484001412645C12841004028280A218240820C4042184499884008C82240622446522486024480C2840022822C24A22423048D646014675885420185B81867242F14E6283441D091A244C81F64BCA8186C +:80D00000E841A252BEA222A0218318A82420A11165986844518942F42A44883AE1487228F68262414F64E942AB518A0B4D884B882B988A84ACBC4D962F42A284EAA8448F144F93622C12117A536A1317A42E3126FA28254F227223734456A8265288A44F127362F289A8218A6128218812482AB8227384861442F82AA4274223588525D8B7 +:80D080008C44588266F4C2923AF654422B8226D28C7188C6143E228F21EB62A14123DDA4E841D72846F4B28E502550823E2A8B224D322216886184488A820487C48A8264E1CD585682D1988AF9A98A257AA20A4A56288782874257CAEB22944141288B2228C39224413E64233882CE242B449E821A211164421A62822AA61922184D825FD8 +:80D10000620A000040124132112C48C882C08240023482344001140020048221822182232238268220080030244840584210022184148440087F2E045F4656559FB2F219119F15371AAF84F43839AD41EF48F68F298F84EC5EB886F84A643BE62F1AFAB5B57F9DE911F9B3919D899F9BFBB8A92F9AEAAA9122688F8958A84FCEFE81828E6E +:80D18000AA86E62AEA2AFAE5A78AE288AEB94F22F28286AEA4CAF566246E722B268FA3516CE06BFB9ADA2CF788DAA5EC25FC68788BFA8B44AFE94CF345475FF6F62B2BAF81F548683F12F34B598F92F24A41FF5C768EFC6BE93F18BE867842FCC388AF18B8BCFBD6D88F9BFFB391AF89F9B8B88F9AEA9AEAAB99622EC2AFABF9AAAEF06CDF +:80D200006F4FEA7AA8FA2C2E2E221F7AFEA8288F82F2383EAFEA7A42F2E6B26F6EFDF6E22F4CE924F62AA2CD1A9EB22F6BFB3ADA2E52EE926F24FA4EEAAF86B4F8F95E56FF4748F222267D4595FB393BBF35F53B23B5F3183A3F23D266FC4367EE628F24DE2EF4CAC63F2EFEAAAB4FE37156F2F9BAAF99F9AAA89AF929BA3F28F828822B15 +:80D28000244E62AFA1F1828A6FC656BA6F6AD2EAFA262E2F22F2874729A83185F22E222F4CEC4DADFC4F46EE67BFA2F698386FC9E829F8B2B48F8FBB42F342427F6CF19E982B764E588CE5774AE374F42C66A5FA7B399F34F43A32AF27F7586ABFA7F26FEF2F64F4E363BFA47C4EFACACEBFAAFAAAAB57F36F67F2F9BAAF99F8B9B99AF9E3 +:80D30000A9AA3FA8F83A8A29E62AF6BABA2FE25246AFEEFEA226AFA2FA262E6F6A7A83D78AB838F3ACAE6F6AFA42446F6AF9E2F24F27B6B2ED2FF792B8ED984F43E96AFBFA982BBEAFAFFB76B26BB1AF8EECADFDC49E4FE10D00250126012AC148228C2422088A048C0416882281221908810090284908881004222002418443A2412A2807 +:80D3800029A2482009924C228122099228828FAE0247180084A9012110022B84501A10229822412B14269892126022004224C01250A48B2826A22826624840A88282250266C2242001450880084E824128489044BFAF012CF4112485F21124C7241F41724AF31124AF34D141F24A9319F24A9251AF243924AF74B924F4429347822D914FEE +:80D4000082C4914FA2C4814FA264154FA264192E4A96D5A2E449F2224A1F49F226421F49522E1F4932481F49324A1F48B26ED141F24A9219F64A9255F84A9643F24A9243F24294478229F924484CF9244A8FEA0B2E4A1F41F628421F4112FC116487141F41724EF181244E151F88F24A341B288B14418DB54B422F147924D81AF926481CF1 +:80D48000FB86581CF324CA5E214FA268112ECA5E259CEC41E292FC112C4BC21AD43CFC11248B941F41B24AF88124EB1619D26AD941E6249B218F6439244E924B424E9443B24239262D944F22758D0E84000000000000280000000000188008002044410400000000002002000000200825014F4103512D324181001C61211E211811848AD1 +:80D5000041028372A28C219482200426084902A0288444418830228092122C62822E843C0581C018814241122C4F8421A1C284C028A8BFE202484718831162218D112422902C2110A814811112C18434482A3848C04881E344412A13A1166481800228904100225B824981A882208918A881224141484B125C08C7AD504146532881701204 +:80D580006111382D314D1245416882588489B28E41C8422C48220E324668E848E088125A411F4116542A898222B62241E21482CA434085919C8328C214188B4286A41243B1444A2AD31438B25FE90A2CE441921480414802C0280098101281321481114230488420524811A012008200008012488481B22848042842828892290100424187 +:80D6000089023F4F0A80120481842140028044412814D1123821508444501820944610020040240218001150412C912149080020014026089088008AF46A7D903534847042C6116C0144472116D18241824169C1C4E979119451111800441038444C991620831474143147226189D24285F2C124128B2465C23160A18662148E5262148937 +:80D6800032944C93188B21227F51011524124A4298122901412D1412895421166814908427C253B14801181430444954284964492120818462214C81128422C124EE1423811242018100D24A120386C42C8C412874960A32114430449141210025230140D8C151921909454105840021009014201244544146012115D842141131214F8822 +:80D7000044B422011823D9120461828322A18120A3822FC208222A44140A0041680043224391142004430249412451C2824342A8128082611480448B24D541D218624282B02204450A88C28842257824280246A8412084F485C9109244A30200874216612124863814839A8484412608D048418829125282CA21034C21018333B125142C16 +:80D7800022542240081A02800725418414942418478800210024DF21094A11024116452415180628008100252491112260844842488448101B1808848C223211250418D01C41143C61B08801814100244AC1180060C1F0638FA04243D2C21266414489D2B4D12445628A20D148381C44C322816183C14D58188536C84E24841A721E618186 +:80D800001638288728C3722431717023668126184116942145FA188290884C84544289F1422818463812A0412CF46E21D022014048014B142002A0218918013042C0254118824A8204845A022002581A820425624190214196AC128C26A461308142824426C8244319084221A5045FA6084246044914084A1108182304C094433488141DD1 +:80D880008819C48824928E2840028C223422230C4C3218192928181198220092400CA82412442D1480048428412200FF8F07320020644220A252448001101281018C18810411848C1525418804221CC42400002E148524A124E0140380410142424A02522816A4845022F0267340024502181018842268418458C01849D1E21494126460F0 +:80D900004C48883448151C821134118210484484051B81884CC1448AE1488482040000182842848121812678860F0048186021801402812E82A0182221281820E81318A121248824281860284110C242112C6C489220348186C8442048242244411184089880419882415FE8018E1424244582528252161804248091446094183C44529462 +:80D9800042001C21628400201421C2281604172290238D421F4146841628420419A2411848414924921880432482F81AD9400200441100124F2481016512C1181008841880012364141B18884430124C12224102201288010000802221C8844422224341648110429422D77D10022041F82452902424302800104424684818424C01C4C0BB +:80DA0000844414842E542410C48600804134248035111111280014488084A1849024448148C1DF8804481441A03423446424424A0A60464246A21424524E824221418886180210124284C1920070221414122208851584A88188180082182684880822601A886FE34B421C840444108811042662CA002190428022A1281374131295242402 +:80DA8000881024011150C24115081C4C521428282238301244E0116211100210012821F0493D9016330869745C7E43324A4F8715F28414AD682B895823782E58814B552F249C118F48B58168418BA19FA8C4A53745C78283F4222456D626E122BB12731892842D841EE19EA86F16F214B44953418D31CCAA298A41120145246748BAF28C01 +:80DB000068124E2E8147B28D249F464FE226C442C0122AB32C0189F264442F21EA630127461F64285528BD888E1816F855885A96D417321A38498E4A3C11A41548157485648ACC41F5C4222D14C18FC1F8C2412E44CF97E5463C814CB812C4314AF845D41B944C36544A84D1D892142AC2E188AF2501165444456641481E644F8145A631F9 +:80DB80004A048FA232144B516CF5D655267215F5CAE225B32671C3F1845865F1A64245912327A14D426B983E2146516C6F1418722151243F72C112115E818A3A154B52222EA413A35116E31114B42297941AB824215B8682678A1FEB074A02008A044880D4240888482C88C4812A44A542142242A22022240222C221008230813081B08179 +:80DC0000048E48002008488004482048810448F0AB44C0263F7452622F61F41E2C7F13761A546C2B124F4ABF9CA1988E841F78BD8AF93EF7BF93F325241F8BF9A46F26F1A5451D311F3E762EF66E4E2D22CFC2B2B4E92FFD17B59EB22F437B18D256F8A6A53F15FA89A6AFB9EF5FBF21FAECEDDFDBFB9DBD8FE8923238CEC625F242514FD3 +:80DC800022B166F5B4144F42712CA842CFC6F66444CF8EF69848F044267D6D2465F4AC2CFFD7D64A7414F632726F4BFF98948E98C85F59FD38F27F61FD1E5D6F72F2B399DFC4FE45647F56F7ED5C9FA5DE7BF6EDFE6F63F11E3E4F6DB2F2FEB1911F2BFB36B49FE1F18B8D7F4AFAB5EC8E83FFF9F3F3F45F5BFFCDFCDFDDF399AD8FE8F25B +:80DD000086141AE12FFF96C66F44D764F746544F4EF1B818CFC3F22868EFC67428F8BE3CDE172427223F524432123AF63177CF61F12E362F42F1F4F6AFC1A199A81F7CDC6AF9DFD66FF17924F594FC7FE1F7D7347F54FC351D8FA4F7CE26FFF47C27DECEB294F7E1C73F51FBA4B5BEBE8F6159E27F6ADA23E67AFAAA3A3BCC1B37CED59FB7 +:80DD8000DBFF9595BEA62F41A122CA2EA45566B276F594D44FC37324784CFCAEECC7C2CF88FB5572E026742F55646741CFC6F67F7FEFE4F4363E2F27F7F6F6AF89E189FB42427F7CFC7E5E6FFCFD76FE7F62F8C7FE6FF4F466D55F57F55DFD8FA4F56AC6FFF7FC1F3FEFE1F176567F7EFEB7972F3AFBB6BE8FE1D9F2F8A2A7EF63FAB7A680 +:80DE0000EFF3F3F6F55F57FFC1D45F5FE74BEA6BFAB2B43AF3D1F1DEC44F47E526F676544F4DFDB8B8DFC27248F8ACEC8FA6F6ACBCFF250729010018842A4108122642081A44E28104160892301110111803219012A01290143026A012B022014B1212148422402149052812002880028F130A244465024582448294121E4421C01241208E +:80DE8000582849D422C8484282D084A484844028140463022D8A4426421446084C04CC049E2400184829B814048A9438C0148028F87556E022F4112485F2112483F41164A3D441F64E121D64AB9419F64A9259B44AB925F44AB15B422F54FB25482F14FBA4481CFB244A4EA14FA2E415F2245ADE212E4ADE252D4ADE24ACF4D1243CFC91A4 +:80DF0000248D831F49F248811F49F64A811FC8B64AF98164AF249961AB9459B44AB9A4B44AB9A4B442F9A4482B944F82A4944FAAD4350926EA41D638F4112483E641744ED141B62A91418D9419D64A9B658D915B42AF44BB2194B25F82E4447BA6E854F3265A4EB14FA2E854FA241ADE251F82E45D42EB5D42EAC5C28B1E648DC31E248F24 +:80DF800014E841D612D8C1F64A921FC8F648961F48F648B25B68AF24B9A49418AAF442944F8AB44AE18AF44A944FAAF56D1A4028081400000000800200000000800100000014000000000000402484020000220014F08173802413181229F34C226081421648029042244641028934843014106122144CE14861210030428E112308354201 +:80E00000B442820A482002818921981842C3E88411A82828488644F8DE3FD0426128444D9241D012D12401C52288815442478141854294141E244A514826410E2073428212F624122A7132C41426B445B222280285C6156822521288222C98194C981CC021CA42C8844116C1242F250B43210E4959182E121D7869618143949C162256423A +:80E0800044448110326C4F211494148502AA31121E424B82165442222B212751CD116E83CE22222127441E84286812324181328D9143795488F848112E88A66828449631149F260E2924512E1006411042180200AB14704213C4141288841C1244011C122611A221294184A4286140417428922142200488288D821008852422044C8244A1 +:80E1000064823FC70D2200284110C26C27221A0400001280C4A241442004422682024E242A84F2244812187024020000904122408212420848444825A448308428825FEA0841181E24A5D218C11C5606844581A212149662244B8441641364241304111059821374221A59823721B08692242614032D242C2A8232141252C68C2D29552440 +:80E180004328D8283A182A0528904C26F8AB27400426145A5A44584B248446242241819142183044299444230442904822682632482722122684E14122824242240210A4144249A4418A3142812148CC22E44204806884A23FCC0122181228181658422578229211200282244B4841E012184205144051A214A126354826C34A4B28405639 +:80E2000061808238222812142A918886228211C484828827A1184A2812942481BD2924222C44810215A8421214A0826110471418182288619810344A2F8952421200F08222854524518446A124CC12CE24B04402400211244849612143A1144034124C06222FFB0448690484A33426441421444A81D442830819E24214044149220421B02E +:80E280008901181C04441C22822292184E148062848C86114188248883044028048A345830125624F96485002218290110518256A814111E2842818C7412028991188C82C1AC121C42048322128611A81418821E4224204102448247812A911832841A3818208A3824006800847E8DE022942416F1221246382E5C54A38981611F252255BA +:80E30000C2481D186F8214BC1868821F8AD18492148D2343525289013112A5922828821A26B1143218A146986C5E2459C13818237938A1581698141A98422E4482442B21433544A6D89D082110420811221246C144E081061358682224123014448A0448894888A21246048E244965412A41D4320443C22463028884C0482240820426C89E +:80E380009412421E48422218F02EE42460412146A221444A524821428422C04284207228343226023024C0224C8804237142924426C22C44442D448C01224800C04812002011222128618230442A04841F810815240410284424A1412B181B81C09812B02411028554858E42163898151844186888821628EA812418222A3282874182A56C +:80E40000A448A14084024820082149228211820245083FF24B211402122D42361A982A7022E3244281044218C9164802382245A2242522143224001214124D3825024D2860444004262481812D2298141845820250688C1CE481C824A7381001AD4244004C22C128121110223D8481186044009A2402410048800A123041848840468888CB +:80E4800042014187481400A04829E24411E4449822184084F1B5486028C01A8418C01800481200C042418C8182014C1404430210B42424014384542860446844004220022844214A0120A885920043A121812845F8924714400180944430441826058041848102232512044AA21400002988624224444881006229062210A441818001805C +:80E500004C41028634282C0210025B4F001241302C1842404402268848C88842481420C98814002518A1841181902181298104100228258424081842488A12111484022840082B38004F8E0900181C41561824200228182D4410944241210049018004502410022480240220414224C2144442284A8A88D8822C84948480C8840049888A93 +:80E58000F1FFDD00C044412032124A924640584A848B282181214614229222822F28041845820840064C48B51198228490E21440A82436CC41814084814284040012803412286FFA0A426B488D1C2B414724550A4D184FA6B68191128F3282B1CCF18C824F22F424222FC47428B428A2738B14CE22A144CF549844CD4416382A4D24E5B504 +:80E6000042B51502242B126F8268424F8C624686BC24C2411AB34324B4C1B11489B824DC42A3214B631AF2E2324D884FC8D2A8F13ED414357111024D162F4272487438722AF212142F31F4212116D842C8884C754AB858F4283149D145F8C4882B228BD32CD22202E01E3A224D2423E48164E28FF4FC262A6B4C4B24281B2422121962C5A6 +:80E680004F43B18C2CA15A814666612F28B2943CA485526A1E44EAA1114CF2FACF5024186721918F81B532F7467C5E64E046F2984A218F8DE4217442E841D3C251242B612D1225F494C145B465548425724A562298CE122ED36E92CB812B124CAC228FE1C816ED822D444DCA4386F5482866AC98A829A8485B4C5E14224CE8C8F8241884E6 +:80E700004CB6283834DF2804000040020049082C08002C022484148446454841484168142568182528981282200882A11B48811110011B483081002008820020084FBD4651475F75F11E1EFFD1F51A38DFD1B236F21E14CF81F11D9B7F1AABBA29F18494CF8DFD3818EF43D3D9526EF5B293F998DC9F19F91F263B22C55E5D9F12F22737AC +:80E780008FAAF8C9C9EE663AFB1C8EEF4EEE24F4C21AEDAE4F48FE252D5FD3B3C8CE2945F531372B951F32F25BD94B111F31F136166F417934F4148623F25E18CFC7F73CBCAFA2D22D4651575F71751CFE1F1FEFC5F16D3F6FC2F22434CF87F77FF8FFD9FB82B8AF46F79494CF4DEF61F3465C8FE4547FFF6BFBBBF8BFDBFFB9B5DF21F33C +:80E800002D2A9FF8D939B46AF6AEBE87E2FFDDEE3FF674F64F64FC848EEEE22F2AD7AEF88C8E5F9EFEF5BD975447D2141F31F857D52E22AFCEFA81918AFB36B62F41F934248FA9FA3A3AEFA5F176348FCBF9382A2B47141F71F113576F61711FFF1A1EBFD1F112346F61B356F39735BFF9E122B292FB8496EFADF51A1CEFE7F23B3D6FE323 +:80E88000F196B18FC9F9F7D54F89FD247785DA75D8C6F46464CFE37337F3E412AFF4FF12389E7E4FE4E66CFC32722729BF9AAAEC8B35DF5EEE82F315341E3E3F5FEB26FA5AF84B111F31F932122BB84B934FA3792AFA5A28AF86FE38B88F22F3EF51141F71F111171E167F71F17E3EFF72F342266F61F356547F5FF79B1FAFA2B2D6FB94F4 +:80E9000096EFEFFD7A3EEFE4F46A6E3FF3F3B6972F4FFF6CDC5FD9F9247345F21C8E7D4F7F54F43436BFFBF8F676EFE5FF5E7EEFEFF7E4E64E642F21F3BA2A3F32B262F6F9B187444FC3F17D3C9FFAFBF2F4EEE2FF9CFA9591FE922F2ABB82BBB4F9B89AAFA3F25A682BEE8F8AFA283ABFFC0969012901418CB424412802221648E2880432 +:80E980001244846C0244924A0228200444A02422200243022A0122482248229628A248A041249220D9480285248802DFC20886016041214C724262414E1213412201478181482F240218C0B44800442542642290145269052D58442D42442C41044C024449810480118498442850284128488D1445E1FA0C2CF4112485F2112C87241F41CF +:80EA0000324A1D24AB141FC8F24A921B68AF1419F54A9243F24AB343F24A914F82F44A914F82D418F9244A8F14F8244A87154FA274D8F122CA87592DCA9E242DDA1F49C2C21F49D228F8912CAF24F8916CAB841FC8B24AF18124AB941B68AF2419B54A39B4AB944B4A2B944F8B94924F8A84F9A44A7FCC0FACE441C6431E2C87341E2487EA +:80EA8000141D242B141D28AD16688F549325AF2419F448B343F248914B42AF1439268D956F22F548914F227C58B1247858B1227418D512C4242D5B1FC1C24A1F4186E4C152221E6C4AE1C8F24A128E248D968E648F24D384B24839B4AB844B4A2B144F8B94826F8A94124FAAF51ADA40081800000000440000002200001400880000400139 +:80EB00004008000000004004280000000081F084DA403211144C4111C27322445602A11C91924889128202214C82022440544A4244295142472422984840828181514219628224222C1428714428F12488884508004608F0331A146714A2AC022AE442115E14871425A4412242C14D18133518C3C1441335525311384485822632141242DB +:80EB80002C0124839212644D11702612B418C2524D1216188828821CD22444C2442224C9A718436299F04F3424423B249121190433372347A446F61442281F22B48491188B2427812248486727446041212D66458879142285714502A98A15F4421923E16142963C1A64828C113284A3A21AC3C4548C9A4285042E4C8E1287428A61215D0E +:80EC000024501412221664221E24C14414124088416844130147816413011313881408284904244421282C014044021860321614C2284260244012C484222412801408EFBF064D114429014088110184181062810029030060824284408A420A8444244C02000040012011240160148200400884288444F048F740028816D12254241485A8 +:80EC8000321445022215882401845624A1411242C024230487244446A22483242211D442C414284C93864332141722E082E4489281188C3914DD124344E849A4822A5484131C48F45BB750618068314825381215C2144421109A1800844E14008022441442C22264304241221224444381C21282114111184C4614011B8188191144C8444E +:80ED0000822226048544F4D8282041941200441484102821128184012B1280A114184608262844C84884488C628424491284049024444C22612240A892881883C414458A049628C24884178C007F8B02859654858412082E1418212524B224289249488A01181048384A8442260C4160821284421E448B24412084912448441E444302E024 +:80ED8000481128D18601441E48B0824408231404BFAC45B228C442901A2210688816082D18A48743188423A242421044152215084D992100831441512A822E1385E424423218818110188142040018AA4134442052122184845F2B48212102901245028644810140512200C47014888301205822608258214469342800A02400602100E059 +:80EE00008104484A02118184881281421144181049E146F11422C1A7231A12D48471146A81298171A80216CA482AC9440045D84911288158C23598265829B218D41234284721839A254384622149522885241144081281183D1C8CA182D86C21E88412125484F0D4F9502200100823021444A3028D1319440289A2418D14328034488C84A5 +:80EE8000121408814185C44283842431221062814A0143C4284E11284A88060047818584344800481884CB1B400400421E284130182001008146043448800441480018481846945681382A9458903880054A0320012A044841E042C8248022218202286FB3083A448C822401223684421488218481C11141901C87122AD11815480150181A +:80EF0000140026828414081914814234414048140811288484818100004E821832F0E2FF00401882014082042324042400210000152441082C028100000000482420022180040012003068442384088882F071F5408884961C84C1A304282022321A4442141A020010024B2141C4C034608228002C414442C454280046841342C4940020CB +:80EF800004298882B82C21131812FC175660241048C128484800148C0489014249042119044C0400002A14018034220068008042212424384882482810C4148288A018203814A2F0A12460C14100481116140400009112301843C1142021840400800441444220024A022820042A2102908242214048981C82200600385F470400444362DD +:80F0000048430128448041084C9124504111845D188147821D2619C228261424D24826048183C4484001142001810081141044882484346866184898288C14E84E018286018480041444001400002400100142102121020000C424112C9221414160424141400130182441430200141840015B2D40084984912428120041C04C80420400E3 +:80F080002902002B2180031D84441F44C212A0121C524164CC4186142102228041084E14800248C0488143182E781A42F23E9C50448A3428718CF835484C25F3244815C4281386D441C1184C545845D112C4394F9417E234E454312426A4628B444658286A34224E4C2CA2441D12701504724E444D648A81011B44205148E1A6CC184C0827 +:80F100009BA8CAB128E8193328AFDB082A75811CC43C49C33647861D265024895128857814C24447144B1121C304E044F42C2481104CD554E212C224E08425A24115A4441F4282F22664196222224D268CD48DE84928421844C4C2C74885BAE87C6438288E188D4127C1EF81085612C42C8B418F47344812411E24A0451E481A11387417C7 +:80F180002126D221E1C1132D713DA9111B229C82931F13D344B544D566932889736CD986F326216D592392111C8473582832587022A165E945E884B54CA2E66AC6381E142FC1BA16E282C822EFF602280022480018A012482200001302112811281144150884121528452801121412204121010040010080044800A048A048F09E7E145E5B +:80F20000623F9452441D45474E57515AF625351E141F11A1269F1282F115155E544B26CF827326F746648F82F265664B448B616FC2762DFC2D2D4FC5F578F88F83F11C4E6D568D18CFC5F124266F66F546776B3575F534545AD544F41414CFC808346B8856F21A14C5F21E18AABAD8038F85F54D56EDDECFC6E486FD5A4A6F9345F15466AC +:80F280007D65C7C25D15CF867355AD655F52A3135F53F164649F12D2C8D355D14453418D1A2F63F1567CCFC3F37474BF84F41C444FC3F724245F1AFA646C9F96FE34344F65D466F52B39CFC7F7747FEFE4F746767F11F7171547421F16F6747445F49CBC8548FA424416F23A3885B25AB768E285E78AFA7878CFE4F486CCEFC6F6B8A88FEC +:80F30000A2F13E49146E423F12F42C2CDFD2F26C4CDFD3A1665F57E642F325258FC57151A131DFD1F144544F55F41D1F67727F55F768495F57F56E799F17E596F721215F52FA2D255F96E613D664D7EEF21221CFC2F23C3E3FC2F457477F72F617115F12B241F664648FC3F3E8EC8B119F3CFCC3E47E32AB31C5B652B5C4B8DCA9AE8F87C7 +:80F38000F548EEEFC5FB2ECC8D988FA8F9FC2B144F667423D54CF23D35CFCEF7757D7AF77165385D258FC7F77969CF81F11D1D4F427111F5393B37727F55F76D4D5F57F16D7DDF53F7257DDFD2F22585DF56F4F579CFD7F66476EFA6F21221CFC3F32D2E3FD4F677677F73535717121B754F475788CFCDFF18181FB4F443613E32AB31C5B5 +:80F40000F67E5CCF86F258788F8EFE78788FF9FBFEBCCFCAFFF8F88FA858AB800140884128024120420884804404008D246044400442002004202214062302002216080012004088628828124C0228F03C5C00002084828104202401A014C011112B14844E11C01111202214042E424422C0484CE2121401446220C44483A44846811218EF +:80F4800024348442A08480288128F89C35D022F4112485F21124A7241F41764AF2112CAF24F1116CAF269961AF249945AF247924F84A9143F2429147822DB14F82D418F9244A8D854FA27418F1265A871D2E5A8759ACE549C25A1F49C2521F49D228F19124AF24F19124AF24F18124EB141F41B24A9921AB9459F44A924B42AF24B924F4E2 +:80F500004294478A29F9A448984FA2F4871D7026F91164EF1224714EB3117644E3C17662F3114CAF72D841F44AB3688F747924B8427B24D842DB8494B26D48A9CB528DB4C88DA46D528B2C2E1287584D538E24BCE5C8C25A1F4896588E24EF34B181F248121D64CD921AF64A961D248F24BB15F648924B43AD924B43AF6438A48B146B4A2D +:80F58000AF44F1A4521F18018A240800000000000000000000800188000040011884000000000000280000000014F0E34C002220814121341448AB411440111C98821211221884130415121401372214C28503E04443C4214014449A2860424894CE19123911081812C08216088061424772E012B486511284E71285541421260121233150 +:80F600008223645184281246084E2410848442048B144C9214254424041A6441274238224A81742422D46881483248248864C9F288268161282246C42546F8A1ADC042D60481AD14809414502A51213B82CCD4A58188C1112812458A14C441218E15F0124135245D1C15044CA1145D224E281A92248314C2244E24C494D97918E21201605D +:80F6800083CB8270822461224364131AB61B0F26815212122651C1450366A14120410240880283044A1201C02400268852241022A4424418444180C16824E0242168244824864816C412842426084054847301002D1150124042180A2440031800400140084800D02324010000000028C50200201148081124C082C014008048F85491C024 +:80F700004212812D1140914143614121501881441001263442490143044048098111241223C6142081220245812682B426F81242248223C212004F81C248448E48288481122CF6F4CD806421191113413141A11221405181001120121204488004403241211022C614002800224C122224288591822782120027818C18B284048181888DAB +:80F7800042D50B248C442811029014E14042C826411800411C84415284008C51814068118051120089014A021594482870220621450824130226841464812210222172ED0A2820425182221280031142D094115812122C2292182034214CC2420000622508298412148401101282420385044E119088814321C2428218404848FA94ED24F2 +:80F8000049411441042501121185122802001241891109A9041830288419048301100216880200A302811004000018502281848420014901DF5208110084108814481822611131211018484114441414180828644400414A22012D420060410048781321044048A44120014884498801E0E145231194215508A7121A3418AC0183B1411297 +:80F88000521E81A711818D125D28814D4860838CC22289924444844E2290621289B3444204244783408874646111C1204458488C2531188182E041C81812F0124970240100A1006012842521412101C0141302431192441441830414211250482442241022015022202211820413019224412982344A16085048845FC10510110414001247 +:80F90000008502000018008418110000008100210000104A04204208009012100200000081229FE30B11001721106111100111C011259119210084440048100460C14181C024000012142443135612272130922100210084109C124412007787100140022081015029C0112111211800841021044400814048C22500001214242A5142507C +:80F980008221291802702202000023111442084F8C0F85B849E444E4144141410111504445B424E212B2280100844116522225A2111A210943518400154111518885F848424E4843440427121820514445B436A2220084504840921225A2139FEF0E00240000000000814002000000000000000000000070120414A124008485020000006B +:80FA000000F0AB6A10C848424800000054514C22820200005022901216949482880000111484818C24841402182210411644848202812001400229F196512484804411420410084044C821110020010021800188104408111C424242888144014011021041458202008420021002BF9603904200001001114480028400810010024901883D +:80FA800000004001C028242A44024002004004280000000021C014DFD7032001001001110040010000000010044411440000000060230018002400000000000000B02B04A18B4420041400004554444B2226712801400C40522225A2111A2129280800112811851AB84824A51410020050444534244822128141002440A2114FB60F5088B6 +:80FB00004C8414021100100155B44882020000002421111A818818021240D111021285984448002C014002D0C4828202100800212512F2C66A801102000014400110080081000040044922420800004022021200282400001481001C042100200841446FFC0300100200000091240018000000000000410028240024001002801212434291 +:80FB8000028542080020020070C906230144140040011100157848589924818100000000004420012228234282C11427212C42427122512200101A384140588812800840F417AE00124002411511414801911435010045280100414554544059241008282C0224233122260230140040513214401A02A141800200418F614E42124212129D +:80FC000012014001154111088001000000207224041004004082021212142129F112122C42582311A1A442811800200210048FCE0C6F22F212222E122B111221C0132592822F31F111119B98D659888F18F44848421F945411488558884F84F448444F42B444F22424222E2480524445E642F226222F21E222B112A1812B99C0932592828D +:80FC80001E111F11B189E999F848888B488F8424E48404488558884F84F4F1CFF0262265A2121A212101502229C8131F3191C19E8887818D414A2444511148155988688F44544C4B242A220280425444286F22D226A2123AA1812328082592823CF1131119EC897818B888A444420048848588F6C5B400000000004842282200000080228D +:80FD000002000000000000000000000000000000000000EF6E09000000008024842202002222220000000000000042422084A4444A2404004242000000000000E0F70400002002004842282A82220200220020020000480048208424240400004A0442000000000000006F220B0000282200802484022800000022222200000042004A0462 +:80FD800080044200A0440000000000000000F09854000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000002097 +:80FE0000024842000022000000000000484A840400000000808424848404000000000000AF910F0000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E0900000000802484220200000028220000000000000000B9 +:80FE800000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248467 +:80FF000022020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE960000000000484228220000008022020000000000000000000000000006 +:80FF80000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000801C +:020000040001F9 +:800000002202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F04F +:80008000EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F9309000000008024842202000000282200000000E7 +:800100000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000C +:800180000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE9600000000004842282200000080020000000000000000424242F1 +:800200000000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE9600000000004842282200BD +:800280000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000003D +:800300000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E0900000000802484220200000028220074 +:800380000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E098A +:800400000000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000D9 +:80048000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE9600000000004823 +:80050000422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F930900000000802484220200000028220000000000000000000000002E +:80058000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE960000000022802484022220020000000000000000200442484848002004000000000000005F2901000000008024842202D8 +:800600000000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE9600000000004842282200000080020000000000000000424242000000000000B8 +:800680000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE960000002002802404000000002002000021 +:800700008084840400420000004A840400420000000000001F65080000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F9309000028220080240422282200002222200200000000A04420240400004A044200006A +:8007800000000000006FEA030000282200802484022800000020220200002004A04400482004004A040000000000000000BE44000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822003D +:8008000000222082020000000000000000424242000042000000000000F0533E000000A022004842800228000000222200000000808424044A0400A04448484800000000000000BE7F000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002800000000000000002024E6 +:8008800024040000000000000000F0359900008022020048422082220200222220220200000000A04420240400004A0442000000000000009F41030000282200802484022800000020220200002004A04400482004004A040000000000000000BE44000000000048422822000000802202000000000000000000000000000000000000EFEC +:800900006E090000000080248422020000002822000000000000000000000000000000000000F0EE9600000000002A248602002002002820020000202424040020040000200400000000000000CF420B000080820280240422808202000022220000000000480048000042480000000000000000DF1A01000000008024242202220000802C +:800980000222000080A4444820042004000000424200000000000000AFCF010000200200484228802202000000000000000080A44400000080240400000000000000DF4A020000282200802406A02222000080220200000000004A04420000802484842404000000000000ADB800008022020048420020022222222222222200000042421E +:800A0000424A0400200400424848424A24040000000000F0784A000000000048422822000000802202000000000000000000000000000000000000EF6E0900002880828282A6242A820220020000200200002004484280A44448484848002024A444000000000000F0594600000020220248420022A022220000280000000000A0444A8423 +:800A8000A4440000484A2484A44442000000000000BF6C02000080A2220048420080020000000000002024044A8404480000208424842424040000000000F05B8A000000000048422822000000800200000000000000004242420000000000000000005F93090000000080A424A022280000008022020000480048004800000080240400F1 +:800B0000000000000000FFF70C00002822008024842282220200280000000000008024848424040080248404000000000000008FAE0200000000802424022A020000000000000000208404808424044A04008024040000000000F0AEC2000000000048422822000000802202000000000000000000000000000000000000EF6E09000000D4 +:800B80008084044228220000008022020000000000000000000000000000000000005FA70A0000000000422822002200000022000000420042004280848404004220040000000000003E98000000000048422800000000222822000000000020044242002084044800000000000000CF2F08000000008024842202000000282200000000FD +:800C00000000000000000000000000000000F0EE96000000000048422800000000282222000000424242000000420042004220040000000000F0D521000080220200484220022200008022220200000000A0442024040000422004000000000000F091F90000802202004842288002000020220200000042004A0480044200A04400004270 +:800C80000000000000006B8E000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000004848A0442822000000802202000000000000000000000000000000000000FFCA0600000000802484220200000096 +:800D0000280000000000000000202424040000000000000000F03599000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248402000000802222020000202424040000200420042004420000000000005F1D020000282200802404222002000028220000000000A04420240400004220AD +:800D80000442000000000000FFDE02000028228004A044288002000020022200000042004A0480044200A0440000000000000000F09DF4000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE9600000000004843 +:800E0000422822000000802202000000000000000000000000000000000000EF6E0900000080042262280000000028220000002024240400000000420000000000000000F0C1530000000080044A8422020000002822000000000000000000000000000000000000F03447000000000048422822000000802202000000000000000000000D +:800E80000000000000000000EF6E09000000008024042A02000000282200000048000000800400000000000000000000F03547000000000048422822000000800200000000000000004242420000000000000000005F930900000020024842280000220080020000000000200442000000420000000000000000FF9A0E000000A022A044B2 +:800F000028280000000028220000004800004220A444000020044242000000000000B02C04000080220280248402802202008002000000000048424800000048208404000000000000C0220000008002802404000000002A022200000042004A24044880240400208404420000000000006F4F044001482D5900849044610000112CE24135 +:800F80006241304812200110835143A1990181850225C12184808124628148484712804144C22424448761288902009F860A118C51839144C9D468E444D142341214D05811D441D24A5242153A282F25E22211C81243147232C1121483C1153019411C5281401AD118944DC48D546F22D4249224122297428143467822F41862282C612157 +:80100000122C7154F21D4A40811148E28164448440224104851144412142638221812D18D042042001418001C4223125912184111A044E3428295242110060446144504818250800BF3F051011924841002721441003181014082648A4142A04006033301111C480018501400281002418412023D218110885024628220212D024643D00D6 +:801080008414003044898494440044002952248001001212100224204111014008811140598450484862410000282449022122211682F17663000014118110040000804206160422290100215021C01A1181810000004844488442000026442402281823011200304900001400000000000000280000000000000000100400000000000027 +:8011000000000000F0F6F200400900D05242519484848B148185142C05126902440000241D181018022CC412200444812502002816688848004004416648028450844FE5084D42205212843D241605842A9151501250122114672294850220014115120113021A422813C411866412701201265184343024466112D02441E828022812CC2B +:80118000229124A2288773101462A240C225416511C93D8F140129445248411B144C7212792204440044002D18109832846662411691C41424160B2651481428366C846601109A2490248C819212C92282F23F498004141181C011280040D81841484348024018021800154211C12100204102801204240010021C0830142018024A52840E +:80120000008845F88E410040012552412184216012121C013014400816480100400821444522054441282111414082020000A01412250225026400128902CF760B11121818458951411A92248905508250A58CD48222D12C0281528B434042D24111044226781804184381C23218A5521485C4148B428CBA1202883082491168CA844618EC +:8012800018049E4487444F9D03141811505225122532244E1814183110816482188C124808360810C8154014648444444432213410522683321448100220D4223814212D8C21422141D04862448B5700202111D84101161802289018107C1E0284412311A1144840022512042CA4128C0118442838494148410489B2888203881812108800 +:801300004258848120A1C1816F4F02512B2415361448402882812212AC21128120123118418148521421841688B248224242019022B3922400122D242C41011884848331221608C41882008909125FD20D200484810000C4114B422800114A2141145834C122001D144348421198121CA121290181482021C241842850281923042644D651 +:8013800028A118402801618412AFE1470244205242A505100118000025028722002051489024904185044883028100001110180800414022C8918002414C01926044848D555025494254A44954522002411B218B42124052214AC2392781C484414914815218C37424382189342220321222114420E181D21442982290141352281612C574 +:8014000014AB12CC48A41820215148811FD9092140A321818481C0118C0200128180014440E5819438244441164132482283911283410223824201248C84110184A9819488928190121285248178842804DFC80F412C0224998212B2124481098865B2183842005C28C144408118C484548114288410094022493218901420496841818BBA +:8014800012001688424802890158C048F0337F14172214C041448591488551481C82521881548A121141229423222032110090140081320088400810C8148CC282400285826838118E1640022F28011AB81448F4E5137024011121284C8442865424872A28886081828B81C0848975820840482C68428C013084406811101212425424AC17 +:80150000281A1444041028418808C1440000846F550D8444584A8204800600448002C7222222006C214222022302222043180250861444100240111808148091262A013800874830442842FFD30510141216184812CC428D82818D9184A30812242E14882712401464528844C08481884100888019088C029E228082C82829C1281200187C +:801580008A4101184A412844F1D987241038242400C9013041402488322400C02881803112000040442462415022004436042244446C2842242614024311044100C1446144BF99088480041624822441240120B2146288137481440343884A91A2001188114098818249186448008490128001000019E85842111824481888886981F09CE8 +:801600001614200228603400812518041814586245588285043028102812088342A41200D058018420028425182461811284128460485084124B18418004481F840B8C51824880140426024942C2242128256468188025D8E28111028C819284218CD84284C28C94218184215C14DE120281C02100448002101288026C022918F8DF1314E8 +:801680005D11E7121E246E252B419F56744AFC3C1763F45C2D2F8A722B417C1AE983B2A47828FE21242E4CCFB8F48C8259A3321CD248D251025B2341BA66428F9A78883496A410922445D226D282B8187118DE1262211D2887A51B188E163E28AC5162160ACD1EC49AC4114D4C2FAE0A4CC22A10D2C4D284022D2885ED2848E288FB281250 +:801700005D862DD41F444361984F24B823D3423222004B882A5844869128A9D12C92145041A32818ECA351C21E1DC3F925884147CBC11A012391821D11C3B1148858EC124F24AE148F8F24E4EF4362224435C2428716241E624AC4423B12C1242B888A31CC8D437B996D12AB194E843E1816F98482DFC2415A8483D2CA61C845EC986841EF +:80178000A4BCD144F81392E4A5952883C2362F48A2A889C12CA386D2887815D944E848B828514C1AAB881AD1C4D84458285F6D0E1220011241800118800100608120412141011424142416416211241A0212301188132112612211221321329122122009A22003A220027F2A4691344FC1F324245F43F37958DF72F25E1CDF67F33B389FB3 +:801800001FFF9CB8BD21AFEAF89B93EF8DEF36F62321DF52F26467DD44D7C8C5F48D9DDFCAFAA9A4CD1C7FD3F337373FA3F3F8FE3FF8F31A3AEFE1F398988B994F69F982998FB9DB7BF51134FF51F19B99DF78B893FA89833F1DFE8882B791D79995F1A832EFCBF32E282B8B6D3C6F49A3334B118FA1F269A990155F91F731335F62F66934 +:80188000289FF3F34E4C9FA5F52F3EBFF7D7CAF1193BAFA8FA9B1BEF85FD7DBF75F33E367FE6F21D9ECFF8F83D2D9FBBFBB9BEAFFAFAAFAD7FD3F23632EFFBFA7C7CDFDBFB18BB8F49FA1A1A37795F71F9DAD98FB9F91F5FBF81F19812EFCBF98D8FF7C18F68F89E8C9F38F81A2EF5DF9BF29C1A6FC9F1AAA86F4BF81A386F25F7FE7C7E1D +:80190000784E721FFF457316D457F615177F72F24B6BFFF2F23F3DDFD3D799F1BDBDBFDAFB3B39BFB8FA1D1FBFB5F5EB6BFFD3535D6F37DF5EFC9C9CFF58D8DCF1A4B7E762FFD2FA342B4FE3733CFCFBF9C7C88FBB713EFE9C9A77B17F71D164F41D3EBFE2F31235EF43FB9ABEBFE2F31233EF62F35276AF2AFB9BBB77B8FFF8F89A1EEF3D +:80198000E9F92E1AAFA9FB961E6F4BF996944BBBCD1E4F814BF11527FF51F321237F56F25D5FBFF3F36F2FDFF7F74D4FBFFF778BFB3BBBBFB9F19F1FFFF5FCFFFFFFB3F33E327FA7FF3ADFEFC9F99E8C9F81F3A4B5C7C2CF82FA252A5FB3F3AC8CBF97F7A8BAAFABF9A884EFA17186F61496ED56BFA3F37F3EEFD3B3A8FBB9BBBFAAFB3E52 +:801A00003FAF62F33B3FBF3AFB9E9A6FF8F8AB8BEFE9F9B6BEEFEAF996B6EFE9B176F9FEFC9EC8CFE4F4B6AA302200302620C248438224022440A2492049269928128D24828504850410044918081004411006492891841220098444402449048324714804CB9F602815041564241187224414865832118931818911414228048D241200CB +:801A8000814128504880028140948210C228241AC2828AC2121A42A2682C29C8135028C092E044084234DDABC0421F4152281F41324C1F41324A1D24AB141D24AB9419B24A19B54A3934AF147934F84A9147832D914F82C4914FA2C4816FA264116FA264192FA264592D4A9E242D4A1F49C2421F4952281F497248F2912CA3F49124AB1454 +:801B00001FC1B24AF91128AB9453B14A3924AB9443B342792498924F8284F9244AFF6D0B2CF4116C85F21144411B21A3D441B24AD141F242941D24AB3451AF443B14AF547834F8428147832D816F82C4116D581CF924C816D1846415267898C5411E24BCF49824ACE441D62864498724962464C9AB1416F44A9416B44A3B152B244782A3C5 +:801B80003434AB944782216F8294124FA2752B090048008400000080020000001002428008000014008480040018000044800200000000F099480031151255144440CC11C22114188604257812342481261C26B241028998244144004412248480084410684181214C09200818002449D1229148D28A8124F4FB972446258A01A1224868BD +:801C0000290491281D48218631649944D24101824328C9882542022982D148C2A8A39292C0813012842120124114112C0118672880644110C4142688D41819F4D11F304513265141C5818244CA514E8241282E494C082786BD546440666826641D8379822A4A44247124E822D881F31282C0818246582C108812594243588441882A318464 +:801C80002120D142C1128B142CA1858C39543BF5502240032144C064008511C112C0814120D25861822088025024302200850440082412006041001C011840220148445042418BA42004FF1F0D004901008521411121224182142288118182D4180A0050228180D2227118C418800929084D131114B0421851220013581882244800441241 +:801D00004A212844F87ACF702112C521141351268A5322B0521A011216C9421415CABA24D44CC11142341548841122358817268E244885041594242598343E8C12B06A21153C12A911D24A11B18831184A31382662C2422828E79BD021428142211162191890A11100B4241C58218D1123D29434A81621042144A911A2431889948C48475D +:801D8000885016809121892A2138111210B212581829117112981842841283852804FFAA0340D4140114648C1252231A848221B142810489814A0216054051A10040C28A2E1523031880C82475CA1417413042A72648E11295028748200C124B12282D2442228CF23FA810241411C24A3011D01261846034B821C0149250848C11B14891FF +:801E00004447248C2872D8024200144682028934560010A82130122280624A6311D8427184E8460128800683F154EF80F1214400400481412417814382122C6122844C03442D16C011812692112348642828701A118441921842D3C8812224501242844189A143881820041212E1A420F53DE92415424234212002610040081058120019B2 +:801E8000018400800490482588C149000000122B2150168984818201008D413048212484800180F274C550412D24501248274211E5624184189922584216E8527192C8344062818CB14561442558122D488534C21290184582438251429391132815CA68241A64821088E81588F148148E4864160823A124A0242F980829115116288180F9 +:801F0000011448A5C14429414802008D154781544840A8A42212291438228714214200481249A82824442C31112212A0214E1245582850423A0432854408847D1A8002208432382281421305C02442230226521C138484A1421811302800482724A2800A40C2246903800390242024884422042E42A012F2208444F2ECA12420116481811B +:801F80001054224144816C81A421C88AC4484830822A84C18145F24182D0210231A251444324A124118814433A41860124200A12124B2C442C084349144212DC42A148FFD60410439823104188028C82824238142223E221425824C312023022101292242284E024088800C024212100881A02D0A2421442CA24121602000028AFDA4D225F +:802000002602814008548118491882C821154816A14229014841004904806C8811002C04144800141034412A614449812124228412181828542212222C24F8A75420582884240010123C84002841401A04C012202292442902442D5410064180312488858209C048234546810218008012040000841CF26B4F001A82A2612054481F84D249 +:8020800021444184928A28901440D183A6420021A2188521048812282C0100CC115221465141412C88044E884B42441289384888182988C3488021016F5647C11C002092162081A242309846B4826484CA324841800841331C41C1441C02481022061F42247422118124A842214413C2C2004C084C118484124424E9C4732834A4F0E13F00 +:802100004012512214A122214012B88204908100411828C11182442339842248181922012911641229A8124324984443488168841014024384817244422C04490220027F920F460848004601583302842D8C809281211929AA18C092422903181188861378649181282E812185412C0A24A04B4591821C0822660428122120924270428472 +:8021800054A287441FA846A3219718841CD288F2592465A2259FA2747218D2222AE21428B884E9527414B55176A8F212234B2B2C647A1D448CF645624F4448F123C21CF826764A84F621224AF28A2216B144DC11364D1EC16E7E6B482B9843F5D2724D14AD822AB3C82CA2C34AB6D2A8524E481E312B8CAF8B05212723701B02266142D5AF +:802200007144D15CFD88A88AF188887D428F94DE28B25998622F92F84214C846E441988665722431221B793F24D85831A250662F42E15C64494D843F6273A117D65274C212E2167A6CA4422A28E449D1A844F61C186C91124D6823F52234ACCC48FF7D086E4638ED226E5823D28255882FA2D5429221476487836F44E6497121F262446D93 +:802280003A97AE4D124DE84A81F4A1311B61EE81B11425F2A8684B255922ADAA1739815F3231614B88214E84BA5B451B881741282912A8614B4447446B222D66E37834E62251C4C1C7464F22F22A5400400C862404188001188001200912819220016044200112881288522041018190185018D01828918880688188800A888008817B2761 +:80230000347F76F63333CFA2F22D6B2F21D557F67D39DF83F77A6E1FDFFFB5B17AFF72C2AFB4FD4EFC1F1CF2C2427F5EFE61F3FFFEA26A4DE41D914F42FA6AAAEFC4B351F154754FE9FBD4FB7F19B972E767F33636AF3ABB13E1C6FB11361F38F2EB6A3F5E7684E9A3F3F95B3F51FBD9998F88A91FCD8C4F4DFDE466CFCBF336844F4CFC52 +:8023800088882F4CF57C58CFC9F9548A6F524DF341637FF1F72E2ADFB2E627F12767BFF3F73B7DAFF7F7FBFFFFBAEB27F75676BFB4FC4FCE9FB6B676F5E3E96EF37F7EF2B2326F44DC11F975F7BFB6DA9B38536F77FFB6A6FEF32F1BF8F6F55E264F5FFBF4FE7F7FEF47EB49F9C545DFBEF6DF1F7FDCF4B6FEFFF7FF1B9F7F7FF97232AF21 +:80240000A7F956866F4F7EEEBE36F922862F6E5CCEEFE5FD7E584F5AFCD4D21EDC346F64F43373BFF3F319137FF1F15B39CFC7F31D7CAFE6F6793D8F4AABD5AF84FEDC5DCFC5FDD5F17DC37F7FFF23B3FFF3BD22FE37515F1AFB8496AFA6F667C53AA2334FEBFA14FF67517E732F67F636763FAAFC13523F6AF73B3F9FBAF263E3BFD2F26C +:80248000D5D19F22F68183AFCAE264F852122F25F7CE4EEFC5FD74F6CF87F3E6244F44F82828AFC7F7FAF8CFC1F1C49A9F4C43E325F51F37BFF3F3793B7F73F97B3BEFE3F71F75AFF7F6FFDFAFEAEA2FFF1E4AFFFCF5CF5E5F3FFFF7D17F5DFF6BFBFFF7B9F2FF77715F1AFB6473FFBEFE27651F16E22FF7AEAECFF77F26F574766E665F14 +:8025000047F5A5D77F7BFDB376AFFBFBED2FFFB6FEB7F77F55F5BFF7FFF5FDF2762F6FF3FABAAFA5F7D256EFCFF57EDEEF85F1EE2E2F6EF6AEACEFC5F5FEB8CFD3F7C4DA2FF2062D11004042C811844722864861882484441F810480A2414213891201114A02426110024322A4822002254388A1412CA841008004124448004E2412008F9B +:80258000950B2C9421850214121870464148028314C11212467114D832688120C1858E4244A410912820C8828E2430812722442E81C44384929416B84AC124266281C048A514D44A032504213244F0ACB9C0421F4152281FC132681F41724AD241F24A111D24AF249921AB9451AF343934AF143B34AF147934D852F934481CF9244A1CF824 +:80260000244A16F1244A96F1224ADE254DCA9E24ACFC91244D421F49522C1F49324C1F49F26A121F48B24EF11124AB9419B24A19F54A924782AF2439242F24792498924F82A4944FA2F4C459C0421FC17622F2114C83F41124E3068B141D24AF4299418B9649B24A29734825F34A8513D142F236481CD8A685EBA26C512E4887592E4A56D4 +:80268000C48B1AC2CB1FC9C24A9A56281B6983A428AF1661488B1419F24A9419F24AB4512BB447828B9447828B944393986F8294986F22F56544A02882480000000044800200000010020000000014000048000000004480020010080025015FB40F5023441A1221045522C121100113112A836241251204164C042143341A004904214475 +:80270000238421921484004508850449230142200442181034C82840F1AB3214205881418113122302441A088711805128248D21126229812201A22312D4245128368232486810A41829382423116A22182881908221248504450221A1846044167144A8711424C2256C43201632252341211961411189C32A282C6221267412A212412399 +:8027800071A2624A4941022B14221904239418F01284EC82150823110C4CB316186264442830422C41484CCA44167156F8511C00111450181114004C0250181221122457818004458801C04281491178240225E84402442A090021CC02288100008442412400A0842200AF960826011450144001145012102A58128002A942E8440185041B +:8028000040088042082BC20020021812248429488C212122088444C03284448242861828D2584F228151846522014B216C6141C9011800814E28C4181AA44128442844416CC2241871182A68C1C01416921414442D218249C11418C188F012482498841E8CA149BC38941A8982C26481FDDC200285554251E01112341487410025881842BF +:8028800068821829B548A142414C4204444124264528D8860941D04212217122214862488C41848892C8C088414938224B84498248888826F262D124192101241240C4121124141200914A120489024C018440648229220112222A04121818408441D2488141C41812241830128189D12811C85A838166828544F8D3F9001A8401842412D1 +:80290000C03121822138AD14840047241810948818850449E32224022244812A042312686600423228004412608345018041028421894828F16E3924186CC4241321044009416014A81420E284084144130249022AC85840240818100C902A4282A1009011122484622A9448482302218006244C61217F3A0528111022514110029011817F +:802980000021120000C24484244200104224A821820012004912184218420813420821188582684200820048CF5B4221D361819212565825501A1E21415092182D11A1128C4C6641444F12DC48481498C2CC26042388A28189E2820C283826044D28843284394108948962818904288A6162C04A82814C21D4820A21901411001840021C8D +:802A000089845884200248000089138402286302414418442410022D826024200218442B12484612E52441582200222018081F21052912C522A444484481404C089081003840142401B8810016C82418C382088881408418043022201224012221842120B22818042392124C021F9706460200000011001C1811A441430481188140180496 +:802A800081444112000045082008008008928A41C42880822292184082A1818A018C01AF540780014355121586C2221C41028622C84288242648022E121004222112A110829126882170820CE141216441844425040010042247238604A22001A49DFA80221268128741234218173822182392282D883022486D1828218CA2A400862242E0 +:802B000002261AD4280124C22CA2281E222AC4262810028A82321230188932288546288138447064786832841FDF09440000844110844421010000100416044181402402800244C42018840448804224283114001004490240041A0240F832950081E484810083E481C21816482811210281411200200118901440040010341418801404F1 +:802B8000809914488218988048C6128280C11244C118F0E369248C5414484C21E2410211400140014122484881C4484C048889080018400448482284800490884042024E28000020042B8244881096245F840543698960123C01172126443224246028C016C012282C8292248C82A81228290121412528D1C222388A106282212A54424466 +:802C00000000209222284130144C82847244884422F5EABE4082C24420528129026110F34134214932A2412148A118238418622818A488876460212A6828664106A44CE9280681161A24022821449022212110222204904286F271D8246F44F19E3C85FA621815D881F4243117148D181F82D198018A7BCCB524D144E68412A41226A4420C +:802C80008D24188B82E0816281284F42019EBC2E8C8F885488444F41B8A88808C147A316E8487912A4222B2624241064E22FC10A4F4DE82229B148F5744483F37F171468134A7418F31C374743648782155348248BB1A4118626F228422A65611A33444F8438948AA2882961426D48122D1C10E644B2C638A4214D3429F2246425B28258E6 +:802D00004643B184DA62A8112A3B12C554428983E16282F3D424E74863C11845DAB602264231245D2423D23A52826D266F41F2462233F1A34335D122B8125E222B11A7E4ED28E5FA123CAAC4A416DAAA5264ED126C51A2CF23722662286D826CF412AA8E2227A5476227244CD24822E822A2144B1185082E28ACE8A2321647266F8839225A +:802D8000486ACB2C8D222F48FC2AD1000000422004422004800400000000100881001008000000840000888008888008800400004FD444F2576375FB2F2FFFE1F6EB6A8FA3771AFF3B1BFFB6F64F49A794AFA6FAE3D27F74FC96366D26EF67F762622D2AAD2A29F13C9C4F4AFA188AAF28DA2251226FE7F63636E5FE1212AFE8F2A6EEEF79 +:802E00008CF4B2B26F6BF3F63E65D66654666FE9F912162F2BFBF6726F42F358789E92AF2B594CC9F2ACA24B554F49F9D614EEB3AF89F97C3CCFC6F7ACE47F6548F25763FFB6F4272FFD7FEFEEF73E7EAF77F67B72FFA6F63B3BE7E4BFBFDBEBF9CFCF6F49DB66F25E7EAFE6F63A3EAFA2F22A3AEF8BB924FA8A9A2F28FAA2A22FA2B272DC +:802E8000FE3A3AEFE2F1B2127D27EFEEFECECFAF2BF3A6A66FCB57664F6252464F6BFB82822F2BF3F2F22F2BFBDEDC2E22AFE8FA8C8CCFC8F88EBA6F25F7B4B66F4BE92BF9BA9AEFC6F26C7CCF4F7E3446F157654D66FFF3F33F2EBFA2F67B33B7F1BFB7F7767AFFB2F23A3FAFAAF6C3F23F7DFDD1932F26F27E768F23D7AAF23E2EE7C17A +:802F0000EFCBF3B4B48FAAF9A2AAAD8E2FA1F1544EE7E1EFA2F212B2AFB9EBAEFECACA2FABFB36B26F6BFF26A66D26EFC2F2BAB4EFE9F9AEBC4BF74F48F9487EAFA1F19ABAEFE858CECD1ACF4DFD9C942F6EFED2932BDD6FC7F7686CCF6AFFCD15347F15F22C66BF93F37B3FAFA3F77B1FBFF3F23B3ECFA3F37F7B2F63F3BBFBFFA8F15FE4 +:802F8000DF3F3FF16222EFE7F77E7EAFC3F33E3EAFC3F3BEF8BE328FAAF8AAA8ED8E2FA1F1F66EAFE3F22E3E8FA9FB1ABBAFA6FECBCA2FA3FB8686EF6BFB26A66D22EFC2F2BCBCAFA8F83AB84F2FFF3636AFE7F7BABAEFA151EEE5FC2E3AEF2FFFB8B62F6FFDB6B66BF76FC6F46C4CCFEEFFFA93100661846D1148458114C448148E48149D +:8030000082544084442441240800400444189084800888B02408229084C0828226628924822008C02682850442826FC20122128501811A56221E68141E4823A24125024A01A5042D1200434124885822120023624125825224C012864442041E24252201860482184308922D26802101411826FAA132C0421F4152281F417248F11124A348 +:80308000D441B24AD141B24A9921AF145985AB944B43AF1439242F147924D812F924488D914FA2C4A14FA264114FA264192E4A96C54A8F49E2A2F491242CF491248D121F4932481F49326A1F48B24AD141B24A9921AB9451AF243924AF2439242B94478229FB2448984FA274DD032CF4116C85E24136481F41324A1F41B24AF11124AF4452 +:80310000E941B24A5B85ABB44B41AF1438342F1419F4429163D312D924D518D924FC18814D5A96E1227498C543DE252417C92E521FC8D628F19164421FC9B24A7181BC6AD141F24A841D242B9659B24239248B944782184D4829792688F3265A8D2B4028080000000044800200000010021880084200400140084800000000448002000015 +:80318000005012E017042417221014C81146049045248180441802C0124160C200002002401492346041002011C1329024200810084012B8148261820040F8834A1420887812012504110082152218B2810100482008184110044188221A088880088890A4C1880090240040145841440044D0484211F457AF0017AE2C68418444480046C1 +:80320000358491230A1002A0142186428C11048A01268428C282112A0888E08408491989084902491A0484412815044418264462C21425F2924A400210413211411100244082D418090010042200100400604160416041008012A421210000001008A52403840050841F59034054122002250224100288165818122903200222208202005B +:8032800010021810840290142800100190180000400400888281F0E491108501141118163911901812233111000012964228B1443114002542A241C0422C42041818602180711294122C0324821002C0164C5228A8208104A8F01A75101144112102351802242C01191108122B1200250844440010124222441204180010042C212151125C +:80330000244008001861818800C83028F04178406421001418181C01A9011888129100189822186A8121C222005200298201411A021229E121120422008218210044286422800182883092004284100210820190411001237242082A054168400218002400002410021022017022928412008931228051142C145828400424EF750528427E +:80338000110022485C2122C419284C02000045022480014F22882149180812400460110016040018101404E042092C2891284180612420C17E0000144043089445022400000000230200004230224002C240044400100200248648022410121184040000DFFC0A0015084083C4119C512413C1610020C248801422A22418C0822041782250 +:803400000A0041401441042301002B12446C3188508229082918F2482240820140D2890C220011212885422482140821112410024C03250440C2242004001221C224901200442C010029080018431122C114418744849044009FD20D8002121414110029011612281122110840C4140000000000124400C0240021004400214014020041C1 +:80348000210040043B73001410010000130894118E216082216728412880120220080044242200122812302280024034344004004400000021F0C7B5000010110821000040180850820000241800200112240000006021442100442001412428100400125024F0D13E0090114A02008F21022480010081800218241838800120084C1802A5 +:8035000000211A0812A08145021002400200803212121042845224AF170E002200000040010000001848180000224002000000008001002400004084012100000044AF94430100201122011100001C42212184810444000090820040240144124004000044005042800221400212801402EFDC04318004400210721202888716182888841C +:8035800000200840028008002100182828008012240850421220820343810840C41480019F9B0B8286011880011140080024840000008001B08201180000800121220020020040060000416100212114E0D7099C039994218211182903115041212814222124284428502280012E82408201885488448412495C422606210021401482427D +:80360000242821A12131684C5122F0A86A341882124213581334181113092417141E113302242C23C4144C8903001820012C51422241444412414B8144B6522482414512562420C21226B482D1425942244D1121C015F09D7960128215B131021229B133022D1B211D89853881811E18878421902449023A5122602A280012242901982B91 +:80368000212B2A2A434252462F42124244642212242512845144414981015E224974245124DFEF0411171289C21116112851282502111A31228542F928A22187482D3442122124189082F082127086041A4824810116042B1328002421168411524400602216B21242921416445242AD5F2001100889018901890998800998224CA9424C9C +:8037000028031200001220099A028A82218821882108000000122001322002222003BFF944D21393218F81A1519FA151AAA7913F117112FA921ABF19E1A1F1DBCA2B199F99F11812AF8FFFA624674A284F490B2A6221212B322B131E122F29F914161E961AFBA4B44F4BF386842B884F487884F694928EA4442F2858662546A6112B111E20 +:80378000124F2151444F2AB2B6FB34342F23D154F214744B67412CF2926B243D311F9557981F11B51141529A9FB1F1131B3FB9F18F151FB9F9F3F62B199F88F1989A2BFE4F6AF2B6144F44F684A62B221AC112212B2A23E329F192829E962F41F811B14F4BEB1BF31E1C23F2D4DC476869C4226F4A5A2265562265F616142F21F13232452F +:80380000526467682B884F436323284F61F776642AF21436DB4BA0231B621AF1181815F213133F13F21B1925F21A92AD162FA9F94B6A3F31D9BBF1BABAAF84B526B816A3884B132B113AC312212BA223E3217112F2949616F6B4154F48F314966FE3F316344F4BF714964F214144F486866544C4144C11C22265F216144F29B186F83414D0 +:803880006F6153666F42B446B53483B11B4EF233219F13E712F259191B119FB1F13B391F317113F31B9395F7131BFFADFE1B9AB5FA3A3AAF8CFC3C9A6B754BDD4B132B221A4112B2223A221E122F28E86151424F5BF194341F21F9363E6F4AFABC744D866B15BEB26F4A5A666544D266D14251222D226F21F116166F69B1B2FB34146F6187 +:80390000F312136F43F566741AD164F1157330226012843C416812841484348424404308001220010021282110064110046B1280012E121004241224400264001244124200F0111A60180000122400101211080085024C1184210100000024000012808261416128002144000000441012140244F052DAC0421F4152381F417248F11124C2 +:80398000A7241D24AB141F48B24AB981F24A9153B84A39A4AF343BA42F547BB4D852FB34481CFB244A1CF8244A16F1244A96E1A26C592DCA9E24ACFC91242CFD91248F22F99124EF24F99124AB841F48B26ED141F24A9219B24A19B54A3924AF4439242B94478229F924484CF9244AFF9706ACC464241E6C421FC132421D2C4AD1C1F24A8F +:803A0000144CB24A9365AB1441AF1483C43516D852F316481CFA265A1CF924CA16F1244A16E1826451BC6451AC54C1ACD54196581F41B248B11132481F48B24A9121AF44B911F248A453B14A2AB94A18B442598429F91248886D5A1EFA4008480000000000280000000021008008000014008480040000004004000000005012F0E9176002 +:803A80002822000084140018001121008001000000400200000000000021222141001200004C020000418FBB0E30818948011400181110010080010000000000002741800100188008180000000040023011440014F0192F00133688111001140043110114290218004002301220081042624111008120058220110221414160430010C25B +:803B000024131144021423F11D7E400200008180110100000080010000000000001200000000800200000000000000413FFA053011000081000000000022108401000000004002000000005041002100008028020000F0EC7C400200120015024140010000000000000041000043428801181012188421020018400418002122182841F03F +:803B800053684002001840082141100100002240840100001004009026840012240044121742002118400418882200122244E0BC0BC011000040010000000000000000000000008001001008000000000000212800007F760E00000000000000401802520000000010084100000000000000002C01008180088100F0A4551001004011027D +:803C00000080040021000021000000218004212100800100221004800800000040048218F0D636200200001100200200000041100484000000810000002100818400000000001200001800CF5B0411000010020028480050280049040084000000890421004002008428100480080000008840888101EFBD06220000111400000040020030 +:803C8000185042000000218140440200200100840000002C01008901100482007F5A0C0010040081000014000044100400001004000000200200008800A0120000840018004008BFE70F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000000000000000000000D4 +:803D000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000210000002180010000000040080000000000800100006FB70E00000000000000000000000000000000002100000041 +:803D80000000000000000000004759000084008400000000000000000000000000000000000000000000000000001A0E0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000200100000000000000200200006F8C0800000000000000000000000000000000000070 +:803E00000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0040080000000000000000000000218001001002180040080000000000000000F05C4B00000040080000000000002100000000000000000000000000000000380000F05672000000000000000000000000C7 +:803E8000000000000000000000000000000000000000FFE40F000000004005000040040021004400100218808802218001884008000028840000800200004FB1070014000048405588281082044480022100448002214818808802214818448828842148408481421882041E148002211A01445C03000040010080045400004840040000D9 +:803F000040040000008002000088000000804208000000F0469900000000005400000044001002400400218001882810021880088400008042080000280000F0147B000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0044 +:803F80001002400100800400281082040028000000280048000000484004281082044400108204440010F28F41000000000000000000000000000000000000000000000000000000000000FFE40F0000000000005400400400000000440000800200000080080000002884000000002FDD0E000000000000000000000000000000000000BC +:804000000000000000000000000000F04FFE00000000000000004004000000000000002800000000000000000000000000BFF20A00000000000054000000000000400400000000000080080000002884000000006FCBFBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08 +:01408000FF40 +:00000001FF diff --git a/kernel/xpp/firmwares/LICENSE.firmware b/kernel/xpp/firmwares/LICENSE.firmware new file mode 100644 index 0000000..b9bb89f --- /dev/null +++ b/kernel/xpp/firmwares/LICENSE.firmware @@ -0,0 +1,37 @@ +The firmware files (*.hex) in this directory are software for the +Astribank itself and not intended to run on the Linux system itself. +They are generally freely distriributable (see exact terms below). + +/****************************************************************************/ +/* Copyright (c) 2004-2006 Xorcom Inc. All Rights Reserved. */ +/* Redistribution and use of the microcode software ( Firmware ) is */ +/* permitted provided that the following conditions are met: */ +/* */ +/* 1. Firmware is redistributed verbatim without any modification; */ +/* 2. Any reproduction of Firmware must contain the above */ +/* copyright notice, this list of conditions and the below */ +/* disclaimer in the documentation and/or other materials */ +/* provided with the distribution; and */ +/* 3. The name of Xorcom may not be used to endorse or promote */ +/* products derived from this Firmware without specific prior */ +/* written consent. */ +/* */ +/* Disclaimer: Xorcom provides this firmware "as is" with no warranties */ +/* or indemnities whatsoever. Xorcom expressly disclaims any express, */ +/* statutory or implied warranties, including, but not limited to, the */ +/* implied warranties of merchantability, fitness for a particular */ +/* purpose and non-infringement. In no event shall Xorcom be liable for */ +/* any direct, indirect, incidental, special, exemplary, or consequential */ +/* damages (including, but not limited to, procurement of substitute */ +/* goods or services; loss of use, data, or profits; or business */ +/* interruption) however caused and on any theory of liability, whether */ +/* in contract, strict liability, or tort (including negligence or */ +/* otherwise) arising in any way out of the use of this firmware, even */ +/* if advised of the possibility of such damage. User acknowledges and */ +/* agrees that the purchase or use of the firmware will not create or */ +/* give grounds for a license by implication, estoppel, or otherwise in */ +/* any intellectual property rights (patent, copyright, trade secret, */ +/* mask work, or other proprietary right) embodied in any other Xorcom */ +/* hardware or firmware either solely or in combination with the firmware. */ +/****************************************************************************/ + diff --git a/kernel/xpp/firmwares/README b/kernel/xpp/firmwares/README new file mode 100644 index 0000000..e423aa6 --- /dev/null +++ b/kernel/xpp/firmwares/README @@ -0,0 +1,19 @@ +This distribution includes the firmware files required by the Xorcom[tm] +Astribank[tm]. + +This distribution inlcudes just the firmware files. Be sure to use a +zaptel distribution/package of a matching version. + +INSTALLATION +"""""""""""" +run "make install" as root. (which will simply copy all the *.hex files +to /usr/share/zaptel ) + +USAGE +""""" +When the firmware files are in place everything should work +automagically. Consult the xpp documentation included in the package +zaptel (or the debian package zaptel) that you use for further information. + + +For further information contact support@xorcom.com http://xorcom.com diff --git a/kernel/xpp/firmwares/USB_FW.hex b/kernel/xpp/firmwares/USB_FW.hex new file mode 100644 index 0000000..01f7ce9 --- /dev/null +++ b/kernel/xpp/firmwares/USB_FW.hex @@ -0,0 +1,223 @@ +# +# $Id:$ +# +:100600001201000200000040E4E451110000010268 +:1006100003010A0600020000004001000902370041 +:1006200002010080320904000002FF0000040705F7 +:100630000202000200070586020002000904010010 +:1006400002FF0000050705040200020007058802FA +:100650000002000902370002010080320904000094 +:1006600002FF0000040705020240000007058602A1 +:100670004000000904010002FF0000050705040214 +:100680004000000705880240000004030904160327 +:1006900058006F00720063006F006D0020004C0076 +:1006A0005400440014034100730074007200690098 +:1006B000620061006E006B001203490053004E009F +:1006C00075006D006200650072000A03460050006C +:1006D000470041002A034D0061006E006100670081 +:1006E00065006D0065006E0074002000500072000F +:1006F0006F0063006500730073006F0072000000FC +:0B0B6C00C2B675B5C4120B18D2B62239 +:100A6300E4901010F07A107B107D017F50120A9FE2 +:100A73007F501208567A107B007D107F50020A8344 +:1008F8007F031209EBEF2402FFE43EFEE516C394E2 +:1009080008501F74082516F582E43410F583E0FDBD +:100918008F828E8375F002E5161205E8EDF0051654 +:0209280080DA73 +:01092A0022AA +:10092B00E50B240AFDE4350AFC901003E02FFF0DC4 +:10093B00EDAA0470010C14F5828A83EFF090100479 +:10094B00E08D828C83F0D20512099090E680E05402 +:02095B00F7F0B3 +:01095D002277 +:1007000090E600E054E74410F090E60174C0F090E9 +:10071000E6107420F000000090E611F00000009058 +:10072000E6047480F0000000740FF0000000E4F0B4 +:1007300000000090E6187410F0000000E490E61944 +:10074000F000000090E61A7408F0000000E490E663 +:100750001BF000000090E6497482F0000000F000F9 +:10076000000090E6247402F0000000E490E625F01A +:1007700000000090E6957480F0000000F00000009A +:0407800043AF012260 +:040B18007F327E00AA +:100B1C007C007D181205D6EF1FAC0670011E4C70C0 +:020B2C00F622AF +:0A0784008E188F198B1A8A1B891C2E +:10078E00E4F51DF51EC3E51E9519E51D95185033AC +:10079E00AB1AAA1BA91C851E82851D83120587FF15 +:1007AE00E4FEC2B2EF1392B7EFC313FFD2B20EBE86 +:1007BE0008F0C2B220B002C322051EE51E70C605A7 +:0407CE001D80C2D3F5 +:0107D2002204 +:10029200E4901010F0F516F517C204E5AA54846034 +:1002A200030203F990F400E024FE700302036524C4 +:1002B200FA700302038724F870030203B324F07078 +:1002C200030203BD24E070030203D824C0700302BA +:1002D20003D8247F60030203CC75160075170490BF +:1002E200FC007401F090F401E090FC01F090F40243 +:1002F200E090FC02F090F401E07017A3E07013307C +:10030200B01090E60174C0F0C2B6120B18D2B61249 +:100312000B1820B00330B44390E694E0FE90E695CB +:10032200E07C002400FFEC3ECF24FCCF34FFFE7BB8 +:10033200017AF47904120784501990FC0330B40D49 +:100342007408F07FE87E03120B1C0203D87404F0D9 +:100352000203D890FC037402F0807B90FC037401CA +:10036200F0807375160075170490FC007402F0E4B7 +:10037200A3F0A3F030B406A37410F0805990FC03EC +:100382007420F0805175160075171190FC007408E6 +:10039200F0E4FF74002FF582E43410F583E0FE747C +:1003A200012FF582E434FCF583EEF00FBF10E480F8 +:1003B2002590E6017403F07F02800A90E60174C082 +:1003C200F0C2B6E4FF12092B800C751600751701F6 +:1003D20090FC0074AAF0E51745166012E51690E647 +:1003E2009CF0000000E51790E69DF000000090E60A +:0703F200957480F00000008B +:0103F90022E1 +:020AFD00D32202 +:080B8C0090E6BAE0F528D3223F +:100AEB0090E740E528F0E490E68AF090E68B04F07E +:020AFB00D32204 +:080B940090E6BAE0F527D32238 +:100B5A0090E740E527F0E490E68AF090E68B04F00F +:020B6A00D32294 +:100A160090E6B9E0242F600D04701990E604E0FF1B +:100A2600430780800890E604E0FF53077F0000003C +:070A3600EFF08002D322C3A0 +:010A3D002296 +:100ABB00C0E0C083C082D2015391EF90E65D740118 +:080ACB00F0D082D083D0E032AC +:100B2E00C0E0C083C0825391EF90E65D7404F0D0B4 +:060B3E0082D083D0E032FA +:100B4400C0E0C083C0825391EF90E65D7402F0D0A0 +:060B540082D083D0E032E4 +:10088E00C0E0C083C08285100C85110D850D828558 +:10089E000C83A37402F085080E85090F850F8285DF +:1008AE000E83A37407F05391EF90E65D7410F0D0B1 +:0608BE0082D083D0E0327D +:100AD300C0E0C083C082D2035391EF90E65D7408F7 +:080AE300F0D082D083D0E03294 +:10081900C0E0C083C08290E680E030E72085080C04 +:1008290085090D850D82850C83A37402F085100E50 +:1008390085110F850F82850E83A37407F05391EFFD +:0D08490090E65D7420F0D082D083D0E032C4 +:0A0B8200000102020303040405054C +:10050200C203C200C202C201120B6C120700120B1C +:100512009C120A63750A06750B0075120675131292 +:1005220075080675091C7510067511537514067544 +:10053200158AD2E843D82090E668E04409F090E6B4 +:100542005CE0443DF0D2AF1208F87F0112092B5350 +:100552008EF8C203120292300105120070C20130FD +:1005620003F2C203120A3E20001690E682E030E750 +:1005720004E020E1EF90E682E030E604E020E0E4EF +:050582001209BF80CF4B +:0B0B770090E50DE030E402C322D32221 +:1000700090E6B9E0700302012F1470030201A4247A +:10008000FE700302021F24FB700302012914700397 +:1000900002012314700302011714700302011D24CE +:1000A00005600302027E120AFD400302028A90E606 +:1000B000BBE024FE602714603824FD601114602723 +:1000C00024067050E50A90E6B3F0E50B803C120B75 +:1000D00077503EE51290E6B3F0E513802DE50C90E5 +:1000E000E6B3F0E50D8023E50E90E6B3F0E50F8072 +:1000F0001990E6BAE0FF1209EBAA06A9077B01EA0C +:10010000494B600DEE90E6B3F0EF90E6B4F00202DA +:100110008A020279020279120B5A02028A120B94A5 +:1001200002028A120B8C02028A120AEB02028A90E5 +:10013000E6B8E0247F601514601924027063A20001 +:10014000E43325E0FFA202E4334F8041E490E7402E +:10015000F0803F90E6BCE0547EFF7E00E0D39480C8 +:100160007C0040047D0180027D00EC4EFEED4F24BA +:1001700082F582740B3EF583E493FF3395E0FEEF46 +:1001800024A1FFEE34E68F82F583E0540190E7402E +:10019000F0E4A3F090E68AF090E68B7402F002029D +:1001A0008A02027990E6B8E024FE60162402600319 +:1001B00002028A90E6BAE0B40105C20002028A0295 +:1001C000027990E6BAE0705590E6BCE0547EFF7E7E +:1001D00000E0D394807C0040047D0180027D00EC2F +:1001E0004EFEED4F2482F582740B3EF583E493FFBF +:1001F0003395E0FEEF24A1FFEE34E68F82F583E035 +:1002000054FEF090E6BCE05480131313541FFFE03B +:10021000540F2F90E683F0E04420F0806D805A90D8 +:10022000E6B8E024FE60192402704E90E6BAE0B40D +:100230000104D200805490E6BAE06402604C803938 +:1002400090E6BCE0547EFF7E00E0D394807C0040CA +:10025000047D0180027D00EC4EFEED4F2482F5828C +:10026000740B3EF583E493FF3395E0FEEF24A1FF8A +:10027000EE34E68F82F583800D90E6A08008120AA6 +:1002800016500790E6A0E04401F090E6A0E044801C +:01029000F07D +:01029100224A +:03003300020BA419 +:040BA40053D8EF3201 +:03004300020B00AD +:03005300020B009D +:100B0000020ABB00020B4400020B2E00020AD300B3 +:080B100002088E000208190022 +:1009BF0090E682E030E004E020E60B90E682E03043 +:1009CF00E119E030E71590E680E04401F07F147EF6 +:0C09DF00001207D390E680E054FEF022E6 +:1009900030050990E680E0440AF0800790E680E0A8 +:1009A0004408F07FDC7E051207D390E65D74FFF00B +:0F09B00090E65FF05391EF90E680E054F7F0226D +:080B9C00E4F526D2E9D2AF22F4 +:10085600AD0790E678E020E6F9C2E990E678E04454 +:1008660080F0ED25E090E679F090E678E030E0F96A +:1008760090E678E04440F090E678E020E6F990E6ED +:0808860078E030E1D6D2E9224E +:10095E00AC0790E678E020E6F9E526702390E6787D +:10096E00E04480F0EC25E090E679F08D21AF03A90C +:10097E00077522018A238924E4F525752601D322E1 +:02098E00C32282 +:1008C400AC0790E678E020E6F9E526702590E67816 +:1008D400E04480F0EC25E0440190E679F08D21AF0E +:1008E40003A9077522018A238924E4F525752603C3 +:0408F400D322C32226 +:03004B000203FAB3 +:1003FA00C0E0C083C082C085C084C086758600C044 +:10040A00D075D000C000C001C002C003C006C0073A +:10041A0090E678E030E2067526060204E490E67873 +:10042A00E020E10CE526640260067526070204E472 +:10043A00E52624FE605F14603624FE70030204D5AC +:10044A0024FC70030204E1240860030204E4AB22E2 +:10045A00AA23A924AF2505258F8275830012058753 +:10046A0090E679F0E52565217070752605806B9018 +:10047A00E679E0AB22AA23A924AE258E82758300F1 +:10048A001205B4752602E5216401704E90E678E003 +:10049A004420F08045E52124FEB5250790E678E062 +:1004AA004420F0E52114B5250A90E678E04440F0AE +:1004BA0075260090E679E0AB22AA23A924AE258E00 +:1004CA00827583001205B40525800F90E678E04412 +:1004DA0040F075260080037526005391DFD007D0BF +:1004EA0006D003D002D001D000D0D0D086D084D09C +:0804FA0085D082D083D0E032EE +:0209EB00A9075A +:1009ED00AE14AF158F828E83A3E064037017AD0133 +:1009FD0019ED7001228F828E83E07C002FFDEC3E7D +:080A0D00FEAF0580DFE4FEFFEF +:010A150022BE +:100A83001208C4E52624FA600E146006240770F3E6 +:0C0A9300D322E4F526D322E4F526D3227A +:100A9F0012095EE52624FA600E146006240770F32F +:0C0AAF00D322E4F526D322E4F526D3225E +:100A3E0090E682E044C0F090E681F043870100002A +:040A4E000000002282 +:1007D3008E188F1990E600E054187012E519240161 +:1007E300FFE43518C313F518EF13F519801590E6D8 +:1007F30000E05418FFBF100BE51925E0F519E518C3 +:1008030033F518E5191519AE18700215184E600561 +:06081300120A5280EE22E1 +:100A52007400F58690FDA57C05A3E582458370F9B7 +:010A62002271 +:030000000205F402 +:0C05F400787FE4F6D8FD7581280205022E +:10058700BB010CE58229F582E5833AF583E0225029 +:1005970006E92582F8E622BBFE06E92582F8E22273 +:0D05A700E58229F582E5833AF583E493228D +:1005B400F8BB010DE58229F582E5833AF583E8F07D +:1005C400225006E92582C8F622BBFE05E92582C829 +:0205D400F22211 +:1005D600EF8DF0A4A8F0CF8CF0A428CE8DF0A42E39 +:0205E600FE22F3 +:0C05E800A42582F582E5F03583F583221E +:00000001FF + \ No newline at end of file diff --git a/kernel/xpp/init_card_3_29 b/kernel/xpp/init_card_3_29 new file mode 100755 index 0000000..43dbb54 --- /dev/null +++ b/kernel/xpp/init_card_3_29 @@ -0,0 +1,189 @@ +#! /bin/sh +# +# Written by Oron Peled +# Copyright (C) 2006, Xorcom +# +# All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# See the file LICENSE in the top level of this tarball. +# + +# +# $Id$ +# +# Data format: +# - A comment start with ';' or '#' until the end of line +# - Blank lines are ignored +# - Fields are whitespace separated (spaces or tabs) +# +# The fields are (in command line order): +# 1. SLIC select in decimal (range 0-7). +# 31 is a special value which means ALL SLICS (only some registers +# accept settings for ALL SLICS). +# 2. Command word: +# - RD Read Direct register. +# - RI Read Indirect register. +# - WD Write Direct register. +# - WI Write Indirect register. +# 3. Register number in hexadecimal. +# 4. Low data byte in hexadecimal. (for WD and WI commands). +# 5. High data byte in hexadecimal. (for WI command only). +# +# + +# ----------------------------------==== 8-channel FXS unit initialization ===----------------------------------------- + +set -e + +me=`basename $0` +INIT_DIR=`dirname $0` +XPP_BASE=/proc/xpp +export XPP_BASE +LOGGER="logger -s -t $me" + +ZAPTEL_BOOT_DEBIAN=${ZAPTEL_BOOT_DEBIAN:-/etc/default/zaptel} +ZAPTEL_BOOT_FEDORA=${ZAPTEL_BOOT_FEDORA:-/etc/sysconfig/zaptel} + +# read default configuration from /etc/default/zaptel +if [ -r $ZAPTEL_BOOT_DEBIAN ]; then . $ZAPTEL_BOOT_DEBIAN; fi +if [ -r $ZAPTEL_BOOT_FEDORA ]; then . $ZAPTEL_BOOT_FEDORA; fi + +if [ "$DEBUG_CALIBRATION"=1 ]; then + LOGGER=":" +fi + +# Always redirect stderr somewhere, otherwise the shell script will die +# when it tries to do I/O related stuff on closed file descriptor. +# Our default is to throw it down the bit-bucket. +exec 2> /dev/console +## If you wish to trace this script: +#exec 2> /tmp/xpp_init_$XPD_NAME +## Altenativly, if you have multiple XBUS'es: +#exec 2> /tmp/xpp_init_$XBUS_NAME_$XPD_NAME +#set -x + +# redirect script output to the "slics" (registers command) file: +exec 1> "$XPP_BASE/$XPD_BUS/$XPD_NAME/slics" + +$LOGGER -p kern.info "$XPD_BUS/$XPD_NAME: Calibrating '$0'" + +"$INIT_DIR/calibrate_slics" + +$LOGGER -p kern.info "$XPD_BUS/$XPD_NAME: Continue '$0'" + +echo " +# Change SLICs states to "Open state"s (Off,all transfers tristated to avoid data collision), Voltage sense +31 WD 40 00 + +# Flush out energy accumulators +31 WI 58 00 00 +31 WI 59 00 00 +31 WI 5A 00 00 +31 WI 5B 00 00 +31 WI 5C 00 00 +31 WI 5D 00 00 +31 WI 5E 00 00 +31 WI 5F 00 00 +31 WI 61 00 00 +31 WI 58 00 00 +31 WI C1 00 00 +31 WI C2 00 00 +31 WI C3 00 00 +31 WI C4 00 00 +31 WI C5 00 00 +31 WI C6 00 00 +31 WI C7 00 00 +31 WI C8 00 00 +31 WI C9 00 00 +31 WI CA 00 00 +31 WI CB 00 00 +31 WI CC 00 00 +31 WI CD 00 00 +31 WI CE 00 00 +31 WI CF 00 00 +31 WI D0 00 00 +31 WI D1 00 00 +31 WI D2 00 00 +31 WI D3 00 00 + +# Setting of SLICs offsets +# New card initialization +0 WD 02 00 +0 WD 04 00 +1 WD 02 08 +1 WD 04 08 +2 WD 02 10 +2 WD 04 10 +3 WD 02 18 +3 WD 04 18 +4 WD 02 20 +4 WD 04 20 +5 WD 02 28 +5 WD 04 28 +6 WD 02 30 +6 WD 04 30 +7 WD 02 38 +7 WD 04 38 +31 WD 03 00 +31 WD 05 00 + +# Audio path. (also initialize 0A and 0B here if necessary) +31 WD 08 00 +31 WD 09 00 + +# Automatic/Manual Control: defaults - Cancel Power Alarm +31 WD 43 1E + +# Loop Closure Debounce Interval +31 WD 45 0A + +# Ring Detect Debounce Interval +31 WD 46 47 + +# Battery Feed Control: Battery low (DCSW low) +31 WD 42 00 + +# Loop Current Limit +31 WD 47 00 + +31 WD 6C 01 + +31 WI 23 00 80 +31 WI 24 20 03 +31 WI 25 8C 08 +31 WI 26 00 01 +31 WI 27 10 00 + +#------ Metering tone +31 WI 17 61 15 # Amplitue Ramp-up +31 WI 18 61 15 # Max Amplitude +31 WI 19 FB 30 # Frequency +31 WD 2C 00 # Timer dL +31 WD 2D 03 # Timer dH + +# ------------------------------------- Initialization of direct registers -------------------------------------------- + +# Mode(8-bit,u-Law,1 PCLK ) setting, Loopbacks and Interrupts clear + +31 WD 01 29 +#31 WD 0E 00 + +#31 WD 15 00 +#31 WD 16 03 + +# Clear pending interrupts +31 WD 12 FF +31 WD 13 FF +31 WD 14 FF + +#31 WD 4A 34 +#31 WD 4B 10 +" | sed -e 's/[;#].*$//' -e '/^[ ]*$/d' + +$LOGGER -p kern.info "$XPD_BUS/$XPD_NAME: Ending '$0'" +exit 0 diff --git a/kernel/xpp/init_card_4_29 b/kernel/xpp/init_card_4_29 new file mode 100755 index 0000000..5dda0b2 --- /dev/null +++ b/kernel/xpp/init_card_4_29 @@ -0,0 +1,165 @@ +#! /bin/sh +# +# Written by Oron Peled +# Copyright (C) 2006, Xorcom +# +# All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# See the file LICENSE in the top level of this tarball. +# + +# +# $Id$ +# +# Data format: +# - A comment start with ';' or '#' until the end of line +# - Blank lines are ignored +# - Fields are whitespace separated (spaces or tabs) +# +# The fields are (in command line order): +# 1. DAA select in decimal (range 0-7). +# 31 is a special value which means ALL DAAs (only some registers +# accept settings for ALL DAAs). +# 2. Command word: +# - RD Read Direct register. +# - WD Write Direct register. +# 3. Register number in hexadecimal. +# 4. Data byte in hexadecimal. (for WD command). +# + +# ----------------------------------==== 8-channel FXO unit initialization ===----------------------------------------- + +set -e + +opermode='FCC' + +me=`basename $0` +INIT_DIR=`dirname $0` +XPP_BASE=/proc/xpp +export XPP_BASE +LOGGER="logger -s -t $me" + +ZAPTEL_BOOT_DEBIAN=${ZAPTEL_BOOT_DEBIAN:-/etc/default/zaptel} +ZAPTEL_BOOT_FEDORA=${ZAPTEL_BOOT_FEDORA:-/etc/sysconfig/zaptel} + +# read default configuration from /etc/default/zaptel +if [ -r $ZAPTEL_BOOT_DEBIAN ]; then . $ZAPTEL_BOOT_DEBIAN; fi +if [ -r $ZAPTEL_BOOT_FEDORA ]; then . $ZAPTEL_BOOT_FEDORA; fi + +if [ "$DEBUG_CALIBRATION"=1 ]; then + LOGGER=":" +fi + +# Always redirect stderr somewhere, otherwise the shell script will die +# when it tries to do I/O related stuff on closed file descriptor. +# Our default is to throw it down the bit-bucket. +exec 2> /dev/console +## If you wish to trace this script: +#exec 2> /tmp/xpp_init_$XPD_NAME +## Altenativly, if you have multiple XBUS'es: +#exec 2> /tmp/xpp_init_$XBUS_NAME_$XPD_NAME +#set -x + +# redirect script output to the "slics" (registers command) file: +exec 1> "$XPP_BASE/$XPD_BUS/$XPD_NAME/slics" + +$LOGGER -p kern.info "$XPD_BUS/$XPD_NAME: Initializing '$0'" + +# Several countries (South Africa, UAE, anybody else) +# require a shorter delay: +case "$opermode" in +SOUTHAFRICA|UAE) echo 31 WD 17 2B;; +esac + +# Remove empty lines and commets. Not strictly necessary +# but works around some limitations of the proc interface: +echo " + + +31 WD 21 28 +31 WD 18 99 +31 WD 06 00 + +# ----------- DAA PCM start offset ---------- + +0 WD 22 00 +0 WD 23 00 +0 WD 24 00 +0 WD 25 00 + +1 WD 22 08 +1 WD 23 00 +1 WD 24 08 +1 WD 25 00 + +2 WD 22 10 +2 WD 23 00 +2 WD 24 10 +2 WD 25 00 + +3 WD 22 18 +3 WD 23 00 +3 WD 24 18 +3 WD 25 00 + +4 WD 22 20 +4 WD 23 00 +4 WD 24 20 +4 WD 25 00 + +5 WD 22 28 +5 WD 23 00 +5 WD 24 28 +5 WD 25 00 + +6 WD 22 30 +6 WD 23 00 +6 WD 24 30 +6 WD 25 00 + +7 WD 22 38 +7 WD 23 00 +7 WD 24 38 +7 WD 25 00 + +# ----------- DAA ONHOOK -------------------- +31 WD 05 00 + +# Set tip to ring voltage to 3.5 volts while off-hook +# instead of default of 3.1 +31 WD 1A C0 +" | sed -e 's/[;#].*$//' -e '/^[ ]*$/d' + +# Turning off red LEDs +# Warning: do not send WD 31 20 A0 ! +for i in `seq 0 7`; do + echo "$i WD 20 A0" +done + +# based on fxo_modes from wctdm.c . +reg16=00; reg26=00; reg30=00; reg31=20; ring_osc=; ring_x=; +mode="$opermode" +if [ -r $INIT_DIR/init_fxo_modes ]; then + . $INIT_DIR/init_fxo_modes +fi +# Our register numbers are HEXADECIMAL! +echo " +31 WD 10 $reg16 +31 WD 1A $reg26 +31 WD 1E $reg30 +31 WD 1F $reg31 +" +# for the FXS: +#if [ "$ring_osc" != '' ]; then +# /bin/echo "31 WI __ $ring_osc" +#fi +#if [ "$ring_x" != '' ]; then +# /bin/echo "31 WI __ $ring_x" +#fi +$LOGGER -p kern.info "$XPD_BUS/$XPD_NAME: Ending '$0'" +exit 0 diff --git a/kernel/xpp/init_card_6_29 b/kernel/xpp/init_card_6_29 new file mode 100755 index 0000000..0da1f61 --- /dev/null +++ b/kernel/xpp/init_card_6_29 @@ -0,0 +1,434 @@ +#! /usr/bin/perl -w +use strict; + +# +# $Id$ +# + +# +# Written by Oron Peled +# Copyright (C) 2006, Xorcom +# +# All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# See the file LICENSE in the top level of this tarball. +# + +# This script is run from the xpp kernel module upon detection +# of a new XPD. +# +# Expects the following environment variables to be set: +# XPD_BUS - bus name +# XPD_NAME - xpd name +# XPD_UNIT - xpd unit number +# XPD_SUBUNIT - xpd subunit number +# XPD_TYPE - xpd type number (from protocol reply): +# 3 - FXS +# 4 - FXO +# 6 - BRI_TE +# 7 - BRI_NT +# XPD_REVISION - xpd revision number +# +# Output data format: +# - An optional comment start with ';' or '#' until the end of line +# - Optional Blank lines are ignored +# - Fields are whitespace separated (spaces or tabs) +# +# The fields are (in command line order): +# 1. CHIP select in decimal (ignored, taken from 3 LSB's of subunit number) +# 2. Command word: +# - RD Read Direct register. +# - RS Read Sub-register. +# - WD Write Direct register. +# - WS Write Sub-register. +# 3. Register number in hexadecimal. +# 4. Subregister number in hexadecimal. (for RS and WS commands). +# 5. Data byte in hexadecimal. (for WD and WS commands only). +# + +package main; +use File::Basename; + +my $program = basename("$0"); +my $init_dir = dirname("$0"); +my $unit_id; + +sub logit { + print STDERR "$unit_id: @_\n"; +} + +# Arrange for error logging +if (-t STDERR) { + $unit_id = 'Interactive'; + logit "Interactive startup\n"; +} else { + $unit_id = "$ENV{XPD_BUS}/$ENV{XPD_NAME}"; + open (STDERR, "| logger -t $program -p kern.info") || die; + logit "Non Interactive startup\n"; +} + +package BRI; + +sub gen { + my $fmt = shift; + $| = 1; + printf "$fmt\n", @_; +} + +package BRI::Port; + +sub new { + my $pack = shift; + my $port = { @_ }; + bless $port, $pack; +} + +# zap_xhfc_su.c:995 +sub init_su { + my $port = shift; + my $portnum = $port->{PORT_NUM}; + my $port_mode_up = $port->{PORT_MODE_UP}; + my $port_mode_exch = $port->{PORT_MODE_EXCH}; + my $bri_nt = $port->{BRI_NT}; + #logit "init_su(portnum=$portnum, port_mode_up=$port_mode_up, bri_nt=$bri_nt)"; + + # Setting PLL + # R_PLL_CTRL = 0 (V_PLL_M = 0, Reset PLL, Disable PLL_ + # R_CLK_CFG = 05 (PLL clock as system clock, output it to CLK_OUT pin) + # R_PLL_P = 1 + # R_PLL_N = 6 + # R_PLL_S = 1 + # R_PLL_CTRL = 1 (V_PLL_M) + + BRI::gen "#--------------------------- init_su($portnum, $bri_nt, $port_mode_up, $port_mode_exch)"; + BRI::gen "0 WD 02 04"; + BRI::gen "0 WD 50 00"; # disable PLL + BRI::gen "0 WD 51 02"; + BRI::gen "0 WD 52 06"; + BRI::gen "0 WD 53 04"; + BRI::gen "0 WD 50 01"; # Enable PLL + BRI::gen "0 WD 02 05"; # Enable PLL + + su_sel($portnum); # select port + if ("$port_mode_up" == 1) { + $port->{CTRL3} = 0x01; # A_ST_CTRL3: V_ST_SEL = 1 + $port->{CTRL0} = 0x10; # A_SU_CTRL0: V_ST_SQ_EN = 1 + BRI::gen "0 WD 34 0F"; # A_MS_TX: + # (multiframe/superframe transmit register) + } else { + $port->{CTRL3} = 0x00; # A_ST_CTRL3: V_ST_SEL = 0 + $port->{CTRL0} = 0x00; # A_SU_CTRL0: V_ST_SQ_EN = 0 + } + if ("$bri_nt" == 1) { + $port->{CTRL0} |= 0x04; # V_SU_MD + } + # ((V_SU_EXCH)?0x80:00) (change polarity) + if($port_mode_exch) { + $port->{CTRL2} = 0x80; + } else { + $port->{CTRL2} = 0x00; + } + BRI::gen "0 WD 35 %02X", $port->{CTRL3}; # A_ST_CTRL3 + BRI::gen "0 WD 31 %02X", $port->{CTRL0}; # A_SU_CTRL0 + BRI::gen "0 WD 35 F8"; # A_ST_CTRL3 = set end of pulse control to 0xF8 + BRI::gen "0 WD 32 08"; # A_SU_CTRL1 = Ignore E-channel data + BRI::gen "0 WD 33 %02X", $port->{CTRL2}; # A_SU_CTRL2 + + # zap_xhfc_su.c:1030 in init_su() + # A_SU_CLK_DLY + my $clk_dly; + if ("$bri_nt" == 1) { + $clk_dly = 0x6C; + } else { + $clk_dly = 0x0E; + } + #logit "clk_dly=$clk_dly"; + BRI::gen "0 WD 37 %02X", "$clk_dly"; +} + +sub su_sel { + if (@_ != 1 ) { + main::logit "ERROR: su_sel() called with " . scalar(@_) . " parameters"; + exit 1; + } + my $portnum = shift; + BRI::gen "0 WD 16 %02X", $portnum; # R_SU_SEL +} + +# zap_xhfc_su.c:281 +sub xhfc_selfifo { + if (@_ != 1 ) { + main::logit "ERROR: xhfc_selfifo() called with " . scalar(@_) . " parameters"; + exit 1; + } + my $fifonum = shift; + #logit "xhfc_selfifo($fifonum)"; + BRI::gen "0 WD 0F %02X", $fifonum; + # --> WAIT UNTIL (R_STATUS & M_BUSY) == 0 +} + +# zap_xhfc_su.c:295 +sub xhfc_resetfifo() { + #logit "xhfc_resetfifo()"; + # A_INC_RES_FIFO = M_RES_FIFO | M_RES_FIFO_ERR + BRI::gen "0 WD 0E 0A"; + # --> WAIT UNTIL (R_STATUS & M_BUSY) == 0 +} + +# zap_xhfc_su.c:1040 +# Initialize fifo (called for each portnum, channel, direction) +sub setup_fifo { + my $port = shift; + my $chan = shift; + my $direction = shift; + my $conhdlc = shift; + my $subcfg = shift; + my $fifoctrl = shift; + + my $portnum = $port->{PORT_NUM}; + my $port_mode_up = $port->{PORT_MODE_UP}; + my $port_mode_exch = $port->{PORT_MODE_EXCH}; + my $bri_nt = $port->{BRI_NT}; + + BRI::gen "#--------------------------- setup_fifo($portnum, $chan, $direction)"; + # my $fifonum = 0x80 | ($portnum << 3) | ($chan << 1) | ($direction); # # MSB first + my $fifonum = ($portnum << 3) | ($chan << 1) | ($direction); # # MSB first + my $r_slot = ($portnum << 3) | ($chan << 1) | ($direction); + + # channel order workaround, swap odd and even portnums in $r_slot for PCM (chan 0, 1) only + if ("$chan" == 0 || "$chan" == 1) { + $r_slot = $r_slot ^ 0x08; + } + + my $short_portnum = $portnum & 0x03; + my $a_sl_cfg = (0x80 | ($short_portnum << 3) | ($chan << 1) | ($direction)); # receive data from STIO2, transmit to STIO1 + + #logit "setup_fifo($fifonum)"; + xhfc_selfifo $fifonum; + # A_CON_HDLC: transparent mode selection + BRI::gen "0 WD FA %02X", $conhdlc; + # A_SUBCH_CFG: subchnl params + BRI::gen "0 WD FB %02X", $subcfg; + # A_FIFO_CTRL: FIFO Control Register + BRI::gen "0 WD FF %02X", $fifoctrl; + xhfc_resetfifo; + xhfc_selfifo $fifonum; # wait for busy is builtin in this command + BRI::gen "0 WD 10 %02X", $r_slot; # R_SLOT + BRI::gen "0 WD D0 %02X", $a_sl_cfg; # A_SL_CFG + + #system("/bin/echo \"----=====TE\" \"short_portnum=\"$short_portnum \"portnum=\" $portnum \"chan=\" $chan\"======----\n\" >>/root/xortel/test_init"); +} + +# zap_xhfc_su.c:1071 +sub setup_su { + my $port = shift; + my $bchan = shift; + my $portnum = $port->{PORT_NUM}; + my $port_mode_exch = $port->{PORT_MODE_EXCH}; + my $bri_nt = $port->{BRI_NT}; + + BRI::gen "#--------------------------- setup_su($portnum, $bchan)"; + #logit "setup_su(portnum=$portnum, bchan=$bchan, port_mode_exch=$port_mode_exch, bri_nt=$bri_nt)"; + $port->{CTRL0} |= (1 << $bchan) | $bri_nt; + $port->{CTRL2} |= ($port_mode_exch << 7) | (1 << $bchan); + su_sel($portnum); # Select port + BRI::gen "0 WD 31 %02X", $port->{CTRL0}; # A_SU_CTRL0: V_B1_TX_EN | V_SU_MD | (NT/TE) + BRI::gen "0 WD 33 %02X", $port->{CTRL2}; # A_SU_CTRL2: V_B1_RX_EN +} + +sub xhfc_ph_command { + my $port = shift; + my $cmd = shift; + my $portnum = $port->{PORT_NUM}; + #logit "xhfc_ph_command(portnum=$portnum)"; + if ("$cmd" eq "HFC_L1_ACTIVATE_TE") { + su_sel($portnum); # Select port + BRI::gen "0 WD 30 60"; # A_SU_WR_STA = (M_SU_ACT & 0x03) + # (set activation) + } elsif ("$cmd" eq "HFC_L1_FORCE_DEACTIVATE_TE") { + su_sel($portnum); # Select port + BRI::gen "0 WD 30 40"; # A_SU_WR_STA = (M_SU_ACT & 0x02) + # (set deactivation) + } elsif ("$cmd" eq "HFC_L1_ACTIVATE_NT") { + su_sel($portnum); # Select port + BRI::gen "0 WD 30 E0"; # A_SU_WR_STA = (M_SU_ACT & 0x03) | 0x80 + # (set activation + NT) + } elsif ("$cmd" eq "HFC_L1_DEACTIVATE_NT") { + su_sel($portnum); # Select port + BRI::gen "0 WD 30 40"; # A_SU_WR_STA = (M_SU_ACT & 0x02) + # (set deactivation) + } +} + + +sub zthfc_startup { + my $port = shift; + my $portnum = $port->{PORT_NUM}; + my $port_mode_exch = $port->{PORT_MODE_EXCH}; + my $bri_nt = $port->{BRI_NT}; + #logit "zthfc_startup(portnum=$portnum, port_mode_exch=$port_mode_exch, bri_nt=$bri_nt)"; + + # PCM <-> ST/Up Configuration + foreach my $chan ( 0, 1 ) { + $port->setup_fifo($chan, 0, 0xFE, 0, 0);# Transparent mode, FIFO EN, ST->PCM + $port->setup_fifo($chan, 1, 0xFE, 0, 0);# Transparent mode, FIFO EN, ST->PCM + $port->setup_su($chan); # zap_xhfc_su.c:194 + } + + # Zaptel chan 2 used as HDLC D-Channel + $port->setup_fifo(2, 0, 0x05, 2, 0); # D-TX: zap_xhfc_su.c:205 + $port->setup_fifo(2, 1, 0x05, 2, 0); # D-RX: zap_xhfc_su.c:206 + # E-chan, Echo channel is ignored + + + # enable this port's state machine + su_sel($portnum); # Select port + # A_SU_WR_STA: reset port state machine + BRI::gen "0 WD 30 00"; + if ("$bri_nt" == 0) { + $port->xhfc_ph_command("HFC_L1_ACTIVATE_TE"); + } else { + $port->xhfc_ph_command("HFC_L1_ACTIVATE_NT"); + } +} + + +package main; +use Getopt::Std; + +my %opts; +getopts('o:', \%opts); + +$ENV{XPP_BASE} = '/proc/xpp'; +my $cmd = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/command"; +my $output; +if ($opts{o}) { + $output = $opts{o}; +} else { + $ENV{XPD_BUS} || die "Missing XPD_BUS environment variable\n"; + $ENV{XPD_NAME} || die "Missing XPD_NAME environment variable\n"; + $ENV{XPD_TYPE} || die "Missing XPD_TYPE environment variable\n"; + $ENV{XPD_REVISION} || die "Missing XPD_REVISION environment variable\n"; + $output = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/$ENV{XPD_NAME}/slics"; +} + +open(REG, ">$output") || die "Failed to open '$output': $!\n"; +select REG; + +logit "Starting '$0'"; + +#------------------------------------------- Instance detection + +# zap_xhfc_su.c:895 +sub init_xhfc() { + #logit "init_xhfc()"; + BRI::gen "#--------------------------- init_xhfc"; + BRI::gen "0 WD 0D 00"; # r_FIFO_MD: 16 fifos, + # 64 bytes for TX and RX each (FIFO mode config) + + # software reset to enable R_FIFO_MD setting + BRI::gen "0 WD 00 08"; # R_CIRM = M_SRES (soft reset) + # --> WAIT 5u + BRI::gen "0 WD 00 00"; # R_CIRM = 0 (zero it to deactivate reset) + + # amplitude + BRI::gen "0 WD 46 80"; # R_PWM_MD: (PWM output mode register) + # PWM push to zero only + BRI::gen "0 WD 39 18"; # R_PWM1: (modulator register for PWM1) + # set duty cycle + + BRI::gen "0 WD 0C 11"; # R_FIFO_THRES: (FIFO fill lvl control register) + # RX/TX threshold = 16 bytes + + # --> Wait until (R_STATUS & (M_BUSY | M_PCM_INIT)) + # M_BUSY status will be checked after fifo selection + BRI::gen "0 WD 0F 80"; + # set PCM !master mode + BRI::gen "0 WD 14 08"; # R_PCM_MD0 = PCM slave mode, F0IO duration is 2 HFC_PCLK's + + # (C4IO, F0IO are inputs) + + # set pll adjust + # WD 14 90 # R_PCM_MD0: Index value to select + # the register at address 15 + # WD 15 2C # R_PCM_MD1: V_PLL_ADJ (DPLL adjust speed), C4IO is 16.384MHz(128 time slots) + # in the last slot of PCM frame + BRI::gen "0 WS 14 98 20"; # R_PCM_MD1: V_PLL_ADJ + # (DPLL adjust speed) in the + # last slot of PCM frame + + BRI::gen "0 WD 4C 03"; # GPIOGPIO function (not PWM) on GPIO0 and GPIO1 pins + BRI::gen "0 WD 4A 03"; # Output enable for GPIO0 and GPIO1 pins +} + +my %port_type = ( + 6 => { 'BRI_NT' => 0 }, + 7 => { 'BRI_NT' => 1 } + ); + +# zap_xhfc_su.c:175 +sub main() { + #logit "main(): XPD_TYPE=$ENV{XPD_TYPE}"; + + $ENV{XPD_TYPE} || die "Missing XPD_TYPE environment variable\n"; + my $type = $port_type{$ENV{XPD_TYPE}}; + die "Bad XPD_TYPE=$ENV{XPD_TYPE}\n" unless $type; + die "Missing XPD_SUBUNIT information\n" unless defined($ENV{XPD_SUBUNIT}); + + # We must first turn off packet reception. + # + # Otherwise we mess with registers while the FPGA firmware tries to + # send us packets. + BRI::gen "0 Wm"; + + # Common initialization + if(($ENV{XPD_SUBUNIT} % 4) eq '0') { + # Turn off multi-byte packet reception before initialization started + my $chipnum = ($ENV{XPD_SUBUNIT} & 0x04) << 3; # Max 2 XHFC chips + for my $subunit (0 .. 3) { # 4 subunits per XHFC chip + my $addr = $chipnum | ($subunit << 3); + my $str = sprintf("0A 00 0F %02X C0 00 00 00 00 00\n", $addr); + open(CMD, ">$cmd") || die "Failed to open '$cmd': $!\n"; + print CMD $str; + close CMD; + } + init_xhfc; # zap_xhfc_su.c:1173 in setup_instance() + } + + # Port initialization + my $p = BRI::Port->new( + 'PORT_NUM' => $ENV{XPD_SUBUNIT}, + 'BRI_NT' => $type->{BRI_NT}, + 'PORT_MODE_UP' => 0, + 'PORT_MODE_EXCH' => 0 + ); + # zap_XHfc_su.c:1186 in setup_instance() + $p->init_su; + + $p->zthfc_startup; + + if(($ENV{XPD_SUBUNIT} % 4) eq 3) { + # Turn on multi-byte packet reception when ports initialization finished + my $chipnum = ($ENV{XPD_SUBUNIT} & 0x04) << 3; # Max 2 XHFC chips + for my $subunit (0 .. 3) { # 4 subunits per XHFC chip + my $addr = $chipnum | ($subunit << 3); + my $str = sprintf("0A 00 0F %02X 80 00 00 00 00 00\n", $addr); + open(CMD, ">$cmd") || die "Failed to open '$cmd': $!\n"; + print CMD $str; + close CMD; + } + } +} + +main; + +logit "Ending '$0'"; + +close REG; +close STDERR; +exit 0; diff --git a/kernel/xpp/init_card_7_29 b/kernel/xpp/init_card_7_29 new file mode 100755 index 0000000..255d50e --- /dev/null +++ b/kernel/xpp/init_card_7_29 @@ -0,0 +1,434 @@ +#! /usr/bin/perl -w +use strict; + +# +# $Id$ +# + +# +# Written by Oron Peled +# Copyright (C) 2006, Xorcom +# +# All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# See the file LICENSE in the top level of this tarball. +# + +# This script is run from the xpp kernel module upon detection +# of a new XPD. +# +# Expects the following environment variables to be set: +# XPD_BUS - bus name +# XPD_NAME - xpd name +# XPD_UNIT - xpd unit number +# XPD_SUBUNIT - xpd subunit number +# XPD_TYPE - xpd type number (from protocol reply): +# 3 - FXS +# 4 - FXO +# 6 - BRI_TE +# 7 - BRI_NT +# XPD_REVISION - xpd revision number +# +# Output data format: +# - An optional comment start with ';' or '#' until the end of line +# - Optional Blank lines are ignored +# - Fields are whitespace separated (spaces or tabs) +# +# The fields are (in command line order): +# 1. CHIP select in decimal (ignored, taken from 3 LSB's of subunit number) +# 2. Command word: +# - RD Read Direct register. +# - RS Read Sub-register. +# - WD Write Direct register. +# - WS Write Sub-register. +# 3. Register number in hexadecimal. +# 4. Subregister number in hexadecimal. (for RS and WS commands). +# 5. Data byte in hexadecimal. (for WD and WS commands only). +# + +package main; +use File::Basename; + +my $program = basename("$0"); +my $init_dir = dirname("$0"); +my $unit_id; + +sub logit { + print STDERR "$unit_id: @_\n"; +} + +# Arrange for error logging +if (-t STDERR) { + $unit_id = 'Interactive'; + logit "Interactive startup\n"; +} else { + $unit_id = "$ENV{XPD_BUS}/$ENV{XPD_NAME}"; + open (STDERR, "| logger -t $program -p kern.info") || die; + logit "Non Interactive startup\n"; +} + +package BRI; + +sub gen { + my $fmt = shift; + $| = 1; + printf "$fmt\n", @_; +} + +package BRI::Port; + +sub new { + my $pack = shift; + my $port = { @_ }; + bless $port, $pack; +} + +# zap_xhfc_su.c:995 +sub init_su { + my $port = shift; + my $portnum = $port->{PORT_NUM}; + my $port_mode_up = $port->{PORT_MODE_UP}; + my $port_mode_exch = $port->{PORT_MODE_EXCH}; + my $bri_nt = $port->{BRI_NT}; + #logit "init_su(portnum=$portnum, port_mode_up=$port_mode_up, bri_nt=$bri_nt)"; + + # Setting PLL + # R_PLL_CTRL = 0 (V_PLL_M = 0, Reset PLL, Disable PLL_ + # R_CLK_CFG = 05 (PLL clock as system clock, output it to CLK_OUT pin) + # R_PLL_P = 1 + # R_PLL_N = 6 + # R_PLL_S = 1 + # R_PLL_CTRL = 1 (V_PLL_M) + + BRI::gen "#--------------------------- init_su($portnum, $bri_nt, $port_mode_up, $port_mode_exch)"; + BRI::gen "0 WD 02 04"; + BRI::gen "0 WD 50 00"; # disable PLL + BRI::gen "0 WD 51 02"; + BRI::gen "0 WD 52 06"; + BRI::gen "0 WD 53 04"; + BRI::gen "0 WD 50 01"; # Enable PLL + BRI::gen "0 WD 02 05"; # Enable PLL + + su_sel($portnum); # select port + if ("$port_mode_up" == 1) { + $port->{CTRL3} = 0x01; # A_ST_CTRL3: V_ST_SEL = 1 + $port->{CTRL0} = 0x10; # A_SU_CTRL0: V_ST_SQ_EN = 1 + BRI::gen "0 WD 34 0F"; # A_MS_TX: + # (multiframe/superframe transmit register) + } else { + $port->{CTRL3} = 0x00; # A_ST_CTRL3: V_ST_SEL = 0 + $port->{CTRL0} = 0x00; # A_SU_CTRL0: V_ST_SQ_EN = 0 + } + if ("$bri_nt" == 1) { + $port->{CTRL0} |= 0x04; # V_SU_MD + } + # ((V_SU_EXCH)?0x80:00) (change polarity) + if($port_mode_exch) { + $port->{CTRL2} = 0x80; + } else { + $port->{CTRL2} = 0x00; + } + BRI::gen "0 WD 35 %02X", $port->{CTRL3}; # A_ST_CTRL3 + BRI::gen "0 WD 31 %02X", $port->{CTRL0}; # A_SU_CTRL0 + BRI::gen "0 WD 35 F8"; # A_ST_CTRL3 = set end of pulse control to 0xF8 + BRI::gen "0 WD 32 08"; # A_SU_CTRL1 = Ignore E-channel data + BRI::gen "0 WD 33 %02X", $port->{CTRL2}; # A_SU_CTRL2 + + # zap_xhfc_su.c:1030 in init_su() + # A_SU_CLK_DLY + my $clk_dly; + if ("$bri_nt" == 1) { + $clk_dly = 0x6C; + } else { + $clk_dly = 0x0E; + } + #logit "clk_dly=$clk_dly"; + BRI::gen "0 WD 37 %02X", "$clk_dly"; +} + +sub su_sel { + if (@_ != 1 ) { + main::logit "ERROR: su_sel() called with " . scalar(@_) . " parameters"; + exit 1; + } + my $portnum = shift; + BRI::gen "0 WD 16 %02X", $portnum; # R_SU_SEL +} + +# zap_xhfc_su.c:281 +sub xhfc_selfifo { + if (@_ != 1 ) { + main::logit "ERROR: xhfc_selfifo() called with " . scalar(@_) . " parameters"; + exit 1; + } + my $fifonum = shift; + #logit "xhfc_selfifo($fifonum)"; + BRI::gen "0 WD 0F %02X", $fifonum; + # --> WAIT UNTIL (R_STATUS & M_BUSY) == 0 +} + +# zap_xhfc_su.c:295 +sub xhfc_resetfifo() { + #logit "xhfc_resetfifo()"; + # A_INC_RES_FIFO = M_RES_FIFO | M_RES_FIFO_ERR + BRI::gen "0 WD 0E 0A"; + # --> WAIT UNTIL (R_STATUS & M_BUSY) == 0 +} + +# zap_xhfc_su.c:1040 +# Initialize fifo (called for each portnum, channel, direction) +sub setup_fifo { + my $port = shift; + my $chan = shift; + my $direction = shift; + my $conhdlc = shift; + my $subcfg = shift; + my $fifoctrl = shift; + + my $portnum = $port->{PORT_NUM}; + my $port_mode_up = $port->{PORT_MODE_UP}; + my $port_mode_exch = $port->{PORT_MODE_EXCH}; + my $bri_nt = $port->{BRI_NT}; + + BRI::gen "#--------------------------- setup_fifo($portnum, $chan, $direction)"; + # my $fifonum = 0x80 | ($portnum << 3) | ($chan << 1) | ($direction); # # MSB first + my $fifonum = ($portnum << 3) | ($chan << 1) | ($direction); # # MSB first + my $r_slot = ($portnum << 3) | ($chan << 1) | ($direction); + + # channel order workaround, swap odd and even portnums in $r_slot for PCM (chan 0, 1) only + if ("$chan" == 0 || "$chan" == 1) { + $r_slot = $r_slot ^ 0x08; + } + + my $short_portnum = $portnum & 0x03; + my $a_sl_cfg = (0x80 | ($short_portnum << 3) | ($chan << 1) | ($direction)); # receive data from STIO2, transmit to STIO1 + + #logit "setup_fifo($fifonum)"; + xhfc_selfifo $fifonum; + # A_CON_HDLC: transparent mode selection + BRI::gen "0 WD FA %02X", $conhdlc; + # A_SUBCH_CFG: subchnl params + BRI::gen "0 WD FB %02X", $subcfg; + # A_FIFO_CTRL: FIFO Control Register + BRI::gen "0 WD FF %02X", $fifoctrl; + xhfc_resetfifo; + xhfc_selfifo $fifonum; # wait for busy is builtin in this command + BRI::gen "0 WD 10 %02X", $r_slot; # R_SLOT + BRI::gen "0 WD D0 %02X", $a_sl_cfg; # A_SL_CFG + + #system("/bin/echo \"----=====NT\" \"short_portnum=\"$short_portnum \"portnum=\" $portnum \"chan=\" $chan\"======----\n\" >>/root/xortel/test_init"); +} + +# zap_xhfc_su.c:1071 +sub setup_su { + my $port = shift; + my $bchan = shift; + my $portnum = $port->{PORT_NUM}; + my $port_mode_exch = $port->{PORT_MODE_EXCH}; + my $bri_nt = $port->{BRI_NT}; + + BRI::gen "#--------------------------- setup_su($portnum, $bchan)"; + #logit "setup_su(portnum=$portnum, bchan=$bchan, port_mode_exch=$port_mode_exch, bri_nt=$bri_nt)"; + $port->{CTRL0} |= (1 << $bchan) | $bri_nt; + $port->{CTRL2} |= ($port_mode_exch << 7) | (1 << $bchan); + su_sel($portnum); # Select port + BRI::gen "0 WD 31 %02X", $port->{CTRL0}; # A_SU_CTRL0: V_B1_TX_EN | V_SU_MD | (NT/TE) + BRI::gen "0 WD 33 %02X", $port->{CTRL2}; # A_SU_CTRL2: V_B1_RX_EN +} + +sub xhfc_ph_command { + my $port = shift; + my $cmd = shift; + my $portnum = $port->{PORT_NUM}; + #logit "xhfc_ph_command(portnum=$portnum)"; + if ("$cmd" eq "HFC_L1_ACTIVATE_TE") { + su_sel($portnum); # Select port + BRI::gen "0 WD 30 60"; # A_SU_WR_STA = (M_SU_ACT & 0x03) + # (set activation) + } elsif ("$cmd" eq "HFC_L1_FORCE_DEACTIVATE_TE") { + su_sel($portnum); # Select port + BRI::gen "0 WD 30 40"; # A_SU_WR_STA = (M_SU_ACT & 0x02) + # (set deactivation) + } elsif ("$cmd" eq "HFC_L1_ACTIVATE_NT") { + su_sel($portnum); # Select port + BRI::gen "0 WD 30 E0"; # A_SU_WR_STA = (M_SU_ACT & 0x03) | 0x80 + # (set activation + NT) + } elsif ("$cmd" eq "HFC_L1_DEACTIVATE_NT") { + su_sel($portnum); # Select port + BRI::gen "0 WD 30 40"; # A_SU_WR_STA = (M_SU_ACT & 0x02) + # (set deactivation) + } +} + + +sub zthfc_startup { + my $port = shift; + my $portnum = $port->{PORT_NUM}; + my $port_mode_exch = $port->{PORT_MODE_EXCH}; + my $bri_nt = $port->{BRI_NT}; + #logit "zthfc_startup(portnum=$portnum, port_mode_exch=$port_mode_exch, bri_nt=$bri_nt)"; + + # PCM <-> ST/Up Configuration + foreach my $chan ( 0, 1 ) { + $port->setup_fifo($chan, 0, 0xFE, 0, 0);# Transparent mode, FIFO EN, ST->PCM + $port->setup_fifo($chan, 1, 0xFE, 0, 0);# Transparent mode, FIFO EN, ST->PCM + $port->setup_su($chan); # zap_xhfc_su.c:194 + } + + # Zaptel chan 2 used as HDLC D-Channel + $port->setup_fifo(2, 0, 0x05, 2, 0); # D-TX: zap_xhfc_su.c:205 + $port->setup_fifo(2, 1, 0x05, 2, 0); # D-RX: zap_xhfc_su.c:206 + # E-chan, Echo channel is ignored + + + # enable this port's state machine + su_sel($portnum); # Select port + # A_SU_WR_STA: reset port state machine + BRI::gen "0 WD 30 00"; + if ("$bri_nt" == 0) { + $port->xhfc_ph_command("HFC_L1_ACTIVATE_TE"); + } else { + $port->xhfc_ph_command("HFC_L1_ACTIVATE_NT"); + } +} + + +package main; +use Getopt::Std; + +my %opts; +getopts('o:', \%opts); + +$ENV{XPP_BASE} = '/proc/xpp'; +my $cmd = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/command"; +my $output; +if ($opts{o}) { + $output = $opts{o}; +} else { + $ENV{XPD_BUS} || die "Missing XPD_BUS environment variable\n"; + $ENV{XPD_NAME} || die "Missing XPD_NAME environment variable\n"; + $ENV{XPD_TYPE} || die "Missing XPD_TYPE environment variable\n"; + $ENV{XPD_REVISION} || die "Missing XPD_REVISION environment variable\n"; + $output = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/$ENV{XPD_NAME}/slics"; +} + +open(REG, ">$output") || die "Failed to open '$output': $!\n"; +select REG; + +logit "Starting '$0'"; + +#------------------------------------------- Instance detection + +# zap_xhfc_su.c:895 +sub init_xhfc() { + #logit "init_xhfc()"; + BRI::gen "#--------------------------- init_xhfc"; + BRI::gen "0 WD 0D 00"; # r_FIFO_MD: 16 fifos, + # 64 bytes for TX and RX each (FIFO mode config) + + # software reset to enable R_FIFO_MD setting + BRI::gen "0 WD 00 08"; # R_CIRM = M_SRES (soft reset) + # --> WAIT 5u + BRI::gen "0 WD 00 00"; # R_CIRM = 0 (zero it to deactivate reset) + + # amplitude + BRI::gen "0 WD 46 80"; # R_PWM_MD: (PWM output mode register) + # PWM push to zero only + BRI::gen "0 WD 39 18"; # R_PWM1: (modulator register for PWM1) + # set duty cycle + + BRI::gen "0 WD 0C 11"; # R_FIFO_THRES: (FIFO fill lvl control register) + # RX/TX threshold = 16 bytes + + # --> Wait until (R_STATUS & (M_BUSY | M_PCM_INIT)) + # M_BUSY status will be checked after fifo selection + BRI::gen "0 WD 0F 80"; + # set PCM !master mode + BRI::gen "0 WD 14 08"; # R_PCM_MD0 = PCM slave mode, F0IO duration is 2 HFC_PCLK's + + # (C4IO, F0IO are inputs) + + # set pll adjust + # WD 14 90 # R_PCM_MD0: Index value to select + # the register at address 15 + # WD 15 2C # R_PCM_MD1: V_PLL_ADJ (DPLL adjust speed), C4IO is 16.384MHz(128 time slots) + # in the last slot of PCM frame + BRI::gen "0 WS 14 98 20"; # R_PCM_MD1: V_PLL_ADJ + # (DPLL adjust speed) in the + # last slot of PCM frame + + BRI::gen "0 WD 4C 03"; # GPIOGPIO function (not PWM) on GPIO0 and GPIO1 pins + BRI::gen "0 WD 4A 03"; # Output enable for GPIO0 and GPIO1 pins +} + +my %port_type = ( + 6 => { 'BRI_NT' => 0 }, + 7 => { 'BRI_NT' => 1 } + ); + +# zap_xhfc_su.c:175 +sub main() { + #logit "main(): XPD_TYPE=$ENV{XPD_TYPE}"; + + $ENV{XPD_TYPE} || die "Missing XPD_TYPE environment variable\n"; + my $type = $port_type{$ENV{XPD_TYPE}}; + die "Bad XPD_TYPE=$ENV{XPD_TYPE}\n" unless $type; + die "Missing XPD_SUBUNIT information\n" unless defined($ENV{XPD_SUBUNIT}); + + # We must first turn off packet reception. + # + # Otherwise we mess with registers while the FPGA firmware tries to + # send us packets. + BRI::gen "0 Wm"; + + # Common initialization + if(($ENV{XPD_SUBUNIT} % 4) eq '0') { + # Turn off multi-byte packet reception before initialization started + my $chipnum = ($ENV{XPD_SUBUNIT} & 0x04) << 3; # Max 2 XHFC chips + for my $subunit (0 .. 3) { # 4 subunits per XHFC chip + my $addr = $chipnum | ($subunit << 3); + my $str = sprintf("0A 00 0F %02X C0 00 00 00 00 00\n", $addr); + open(CMD, ">$cmd") || die "Failed to open '$cmd': $!\n"; + print CMD $str; + close CMD; + } + init_xhfc; # zap_xhfc_su.c:1173 in setup_instance() + } + + # Port initialization + my $p = BRI::Port->new( + 'PORT_NUM' => $ENV{XPD_SUBUNIT}, + 'BRI_NT' => $type->{BRI_NT}, + 'PORT_MODE_UP' => 0, + 'PORT_MODE_EXCH' => 0 + ); + # zap_XHfc_su.c:1186 in setup_instance() + $p->init_su; + + $p->zthfc_startup; + + if(($ENV{XPD_SUBUNIT} % 4) eq 3) { + # Turn on multi-byte packet reception when ports initialization finished + my $chipnum = ($ENV{XPD_SUBUNIT} & 0x04) << 3; # Max 2 XHFC chips + for my $subunit (0 .. 3) { # 4 subunits per XHFC chip + my $addr = $chipnum | ($subunit << 3); + my $str = sprintf("0A 00 0F %02X 80 00 00 00 00 00\n", $addr); + open(CMD, ">$cmd") || die "Failed to open '$cmd': $!\n"; + print CMD $str; + close CMD; + } + } +} + +main; + +logit "Ending '$0'"; + +close REG; +close STDERR; +exit 0; diff --git a/kernel/xpp/init_card_9_29 b/kernel/xpp/init_card_9_29 new file mode 100755 index 0000000..dd3b0a5 --- /dev/null +++ b/kernel/xpp/init_card_9_29 @@ -0,0 +1,358 @@ +#! /usr/bin/perl -w +use strict; + +# +# $Id$ +# + +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# +# All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# See the file LICENSE in the top level of this tarball. +# + +# This script is run from the xpp kernel module upon detection +# of a new XPD. +# +# Expects the following environment variables to be set: +# XPD_BUS - bus name +# XBUS_CONNECTOR - bus connector id string +# XPD_NAME - xpd name +# XPD_UNIT - xpd unit number +# XPD_TYPE - xpd type number (from protocol reply): +# 3 - FXS +# 4 - FXO +# 6 - BRI_TE +# 7 - BRI_NT +# 8 - PRI_TE +# 9 - PRI_NT +# XPD_REVISION - xpd revision number +# +# Output data format: +# - An optional comment start with ';' or '#' until the end of line +# - Optional Blank lines are ignored +# - Fields are whitespace separated (spaces or tabs) +# +# The fields are (in command line order): +# 1. CHIP select in decimal (ignored, taken from 3 LSB's of subunit number) +# 2. Command word: +# - RD Read Direct register. +# - WD Write Direct register. +# 3. Register number in hexadecimal. +# 4. Subregister number in hexadecimal. (for RS and WS commands). +# 5. Data byte in hexadecimal. (for WD and WS commands only). +# + +package main; +use File::Basename; + +my $program = basename("$0"); +my $init_dir = dirname("$0"); +my $unit_id; + +sub logit { + print STDERR "$unit_id: @_\n"; +} + +# Arrange for error logging +if (-t STDERR) { + $unit_id = 'Interactive'; + logit "Interactive startup\n"; +} else { + $unit_id = "$ENV{XPD_BUS}/$ENV{XPD_NAME}"; + open (STDERR, "| logger -t $program -p kern.info") || die; + logit "Non Interactive startup\n"; +} + +package PRI; + +sub gen { + my $fmt = shift; + $| = 1; + printf "$fmt\n", @_; +} + +package PRI::Port; + +sub new { + my $pack = shift; + my $port = { @_ }; + bless $port, $pack; +} + +package main; +use Getopt::Std; +BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/zconf"); } +use Zaptel::Config::Defaults; + +my %opts; +getopts('o:', \%opts); + +$ENV{XPP_BASE} = '/proc/xpp'; +#my $cmd = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/command"; +my $output; +if ($opts{o}) { + $output = $opts{o}; +} else { + $ENV{XPD_BUS} || die "Missing XPD_BUS environment variable\n"; + $ENV{XPD_NAME} || die "Missing XPD_NAME environment variable\n"; + $ENV{XPD_TYPE} || die "Missing XPD_TYPE environment variable\n"; + $ENV{XPD_REVISION} || die "Missing XPD_REVISION environment variable\n"; + $ENV{XBUS_CONNECTOR} || die "Missing XBUS_CONNECTOR environment variable\n"; + $output = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/$ENV{XPD_NAME}/slics"; +} + +sub write_pri_info { + my $pri_type = shift || die "Missing pri_type parameter"; + my $pri_proto = shift || die "Missing pri_proto parameter"; + my $info = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/$ENV{XPD_NAME}/pri_info"; + + open(INFO, ">$info") || die "Failed to open '$info': $!\n"; + print INFO "$pri_type $pri_proto\n" || die "Failed writing to '$info': $!\n"; + close INFO || die "Failed during close of '$info': $!\n"; +} + +my @PRI_SETUP; + +sub set_defaults { + my @pri_specs; + my $match; + my $setup; + # For lab tests + my $labfile = "${0}.setup"; + + # Source default files + $ENV{ZAPTEL_DEFAULTS} = "$labfile" if -r "$labfile"; + my $setup_var = 'XPP_PRI_SETUP'; + my $setup_string; + my ($default_file, %source_defaults) = + Zaptel::Config::Defaults::source_vars($setup_var); + $setup_string = $source_defaults{$setup_var}; + $setup_string =~ s/^\s+//; # trim + $setup_string =~ s/\s+$//; # trim + $setup_string =~ s/\s+/\n/g; # cannonical spaces + logit "From $default_file: $setup_var=\n$setup_string\n"; + @pri_specs = split(/\s+/, $setup_string); + push(@pri_specs, 'NUM/*=TE,E1'); # Fall back default (last) + logit "pri_specs: @pri_specs"; +SPEC: + for(my $i = 0; $i < @pri_specs; $i++) { + my $spec = $pri_specs[$i]; + ($match, $setup) = split(/=/, $spec); + next unless defined $match and defined $setup; + # Convert "globs" to regex + $match =~ s/\*/.*/g; + $match =~ s/\?/./g; + #logit "match: $match"; + my @patlist = ( + "CONNECTOR/$ENV{XBUS_CONNECTOR}/$ENV{XPD_NAME}", + "NUM/$ENV{XPD_BUS}/$ENV{XPD_NAME}" + ); + foreach my $pattern (@patlist) { + #logit "testmatch: $pattern =~ $match"; + if($pattern =~ $match) { + logit "MATCH($i): '$match' setup=$setup"; + last SPEC; + } + } + } + die "No setup matching $ENV{XPD_BUS}/$ENV{XPD_NAME}\n" unless defined $setup; + @PRI_SETUP = split(/,/, $setup); + die "Bad setup string '$setup'\n" unless @PRI_SETUP; +} + +set_defaults; + +open(REG, ">$output") || die "Failed to open '$output': $!\n"; +select REG; + +logit "Starting '$0'"; + +PRI::gen "#--------------------------- start"; + +# only one of the following loopbacks can be activated in the same time +my $LIM1_RL = 0 << 1; # RL (Remote Loopback) +my $lim1 = 0xB0 | $LIM1_RL; + +my $subunits_num = 4; +my $subunit = $ENV{XPD_SUBUNIT}; + +if($subunit eq 0) { + # Tuning of clocking unit to the 16.384 MHz reference frequence + # by setting Global Clock Mode registers (GCM[1:8]), same for E1 and T1/J1 + PRI::gen "0 WD 92 00"; # GCM1 + PRI::gen "0 WD 93 18"; # GCM2 + PRI::gen "0 WD 94 FB"; # GCM3 + PRI::gen "0 WD 95 0B"; # GCM4 + PRI::gen "0 WD 96 01"; # GCM5 + PRI::gen "0 WD 97 0B"; # GCM6 + PRI::gen "0 WD 98 DB"; # GCM7 + PRI::gen "0 WD 99 DF"; # GCM8 + + for(my $i = 0; $i < $subunits_num; $i++) { + PRI::gen "0 WS 26 $i BD"; # XPM0: Pulse Shape Programming for R1=18Ohms (0x54) + PRI::gen "0 WS 27 $i 03"; # XPM1: ...3V Pulse Level at the line (0x02) + PRI::gen "0 WS 28 $i 00"; # XPM2: ~XLT (transmit line is not in the high impedance state) + + # if (unchannelized) + #PRI::gen "0 WS 1F $i 22"; # LOOP (Channel Looback): + # ECLB (Enable Channel Loop-Back) + # CLA (Channel Address) + PRI::gen "0 WS 2B $i EF"; # IDL (Idle): + # If channel loopback is enabled than transmit this code on the outgoing + PRI::gen "0 WS 1F $i 00"; # LOOP (Channel Looback): + #if($i eq 0){ + # PRI::gen "0 WS 1F $i 00"; # LOOP (Channel Looback): + # # channels (XL1/XL2) + #}else { + # PRI::gen "0 WS 1F $i 20"; # LOOP (Channel Looback): + #} + + PRI::gen "0 WS 37 $i %02X", $lim1; + # LIM1: ~RL (Remote Loop bit 0x02), + # ~DRS (Dual Rail Select, latch receive data while trasmit), + # RIL1, RIL0 (Receive Input Treshold 0.62 V), + # CLOS (Clear data in case of LOS) + PRI::gen "0 WS 3A $i 20"; # LIM2: SLT1, SLT0 = 01 + # (Receiver Slicer Threshold, the receive slicer + # generates a mark (digital one) if the voltage at + # RL1/2 exceeds 50% of the peak amplitude, + # default, recommended in E1 mode). + + PRI::gen "0 WS 38 $i 0A"; # PCD: (Pulse Count Detection, LOS Detection after 176 consecutive 0s) + PRI::gen "0 WS 39 $i 15"; # PCR: (Pulse Count Recovery, LOS Recovery after 22 ones in PCD interval) + + # Configure system interface + PRI::gen "0 WS 3E $i C2"; # SIC1: SSC1 (System clock ) is 8.192 Mhz, + # SSD1 (System Data rate) is 8.192 Mbit/s, + # ~BIM (Byte interleaved mode), + # XBS (Transmit Buffer Size) is 2 frames + PRI::gen "0 WS 40 $i 04"; # SIC3: Edges for capture, Synchronous Pulse Receive @Rising Edge + PRI::gen "0 WS 41 $i 04"; # CMR4: RCLK is 8.192 MHz + PRI::gen "0 WS 43 $i 04"; # CMR5: TCLK is 8.192 MHz + PRI::gen "0 WS 44 $i 34"; # CMR6: Receive reference clock generated by channel 1, + # RCLK is at 8.192 Mhz dejittered, Clock recovered from the line + # TCLK is at 8.192 MHz is de-jittered by DCO-R to drive a6.176 MHz + # clock on RCLK.*/ + + PRI::gen "0 WS 20 $i 9F"; # XSW: XSIS (Spare Bit For International Use fixed to 1), + # XY0, XY1, XY2, XY3, XY4 (Y0, Y1 and Y3-Bits fixed to 1) + + # cas = 0x1c; + # if (!(lineconfig & ZT_CONFIG_CCS)) + # cas |= 0x40; + + PRI::gen "0 WS 22 $i 00"; # XC0: (Transmit Counter Offset = 497/T=2) + PRI::gen "0 WS 23 $i 04"; # XC1: + + PRI::gen "0 WS 24 $i 00"; # RC0: (Receive Counter Offset = 497/T=2) + PRI::gen "0 WS 25 $i 05"; # RC1: + + my $sic2 = sprintf("%x", 0x00 | ($i << 1)); + + PRI::gen "0 WS 3F $i $sic2"; # SIC2: No FFS, no center receive elastic buffer, data active at phase ($sic >> 1) + + # enable the following interrupt sources + PRI::gen "0 WS 16 $i 00"; # IMR2 (Interrupt Mask Register2): Enable ALL + + PRI::gen "0 WS 17 $i 3F"; # IMR3 ~ES, ~SEC (Enable ES and SEC interrupts) + PRI::gen "0 WS 18 $i 00"; # IMR4: Enable ALL + + PRI::gen "0 WS 08 $i 04"; # IPC: SYNC is 8 Khz + + PRI::gen "0 WS 02 $i 51"; # CMDR (Command Register): RRES, XRES, SRES (Receiver/Transmitter reset) + PRI::gen "0 WS 02 $i 00"; # CMDR + + + # Configure interrupts + PRI::gen "0 WS 46 $i 40"; # GCR: Interrupt on Activation/Deactivation of AIX, LOS + + PRI::gen "0 WS 45 $i 00"; # CMR2: External sources for SYPR, SCLKR, SYPX, SCLKX for TX and RX. + #PRI::gen "0 WS 22 $i 00"; # XC0: Normal operation of Sa-bits + #PRI::gen "0 WS 23 $i 04"; # XC1: X=4 => T=4-X=0 offset + #PRI::gen "0 WS 24 $i 00"; # RC0: 0 offset + #PRI::gen "0 WS 25 $i 00"; # RC1: Remaining part of RC0 + + # Configure ports + PRI::gen "0 WD 85 80"; # GPC1 (Global Port Configuration 1): + #PRI::gen "0 WD 85 00"; # GPC1 (Global Port Configuration 1): + # SMM (System Interface Multiplex Mode) + PRI::gen "0 WS 80 $i 00"; # PC1: SYPR/SYPX provided to RPA/XPA inputs + + PRI::gen "0 WS 84 $i 31"; # PC5: XMFS active low, SCLKR is input, RCLK is output (unused) + PRI::gen "0 WS 86 $i 03"; # PC6: CLK1 is Tx Clock output, CLK2 is 8.192 Mhz from DCO-R + PRI::gen "0 WS 3B $i 00"; # Clear LCR1 - Loop Code Register 1 + + # printk("TE110P: Successfully initialized serial bus for card\n"); + + # Initialize PCM and SIG regs + PRI::gen "0 WS A0 $i 00"; # TSEO (Time Slot Even/Odd Select) + PRI::gen "0 WS A1 $i FF"; # TSBS (Time Slot Bit Select)- only selected bits are used for HDLC channel 1 + # in selected time slots + PRI::gen "0 WS 03 $i 89"; # Mode Register: + # MDS (Mode Select) = 100 (No address comparison) + # HRAC (Receiver Active - HDLC channel 1) + # RFT2 (HDLC Receive FIFO is 64 byte deep) + PRI::gen "0 WS 09 $i 18"; # CCR1 (Common Configuration Register1) + # EITS (Enable Internal Time Slot 0 to 31 Signalling) + # ITF (Interframe Time Fill) + PRI::gen "0 WS 0A $i 04"; # CCR2 (Common Configuration Register2) + # RCRC (enable CRC - HDLC channel 1enable CRC - HDLC channel 1) + PRI::gen "0 WS 0C $i 00"; # RTR1 (Receive Time Slot register 1) + PRI::gen "0 WS 0D $i 00"; # RTR2 (Receive Time Slot register 2) + PRI::gen "0 WS 0E $i 00"; # RTR3 (Receive Time Slot register 3), TS16 (Enable time slot 16) + PRI::gen "0 WS 0F $i 00"; # RTR4 (Receive Time Slot register 4) + + PRI::gen "0 WS 10 $i 00"; # TTR1 (Transmit Time Slot register 1) + PRI::gen "0 WS 11 $i 00"; # TTR2 (Transmit Time Slot register 2) + PRI::gen "0 WS 12 $i 00"; # TTR3 (Transmit Time Slot register 3), TS16 (Enable time slot 16) + PRI::gen "0 WS 13 $i 00"; # TTR4 (Transmit Time Slot register 4) + + # configure the best performance of the Bipolar Violation detection for all four channels + PRI::gen "0 WS BD $i 00"; # BFR (Bugfix Register): ~BVP (Bipolar Violations), + # use Improved Bipolar Violation Detection instead + } + PRI::gen "0 WD BB FF"; # REGFP + PRI::gen "0 WD BC AC"; # REGFD + PRI::gen "0 WD BB 2B"; # REGFP + PRI::gen "0 WD BC 00"; # REGFD + PRI::gen "0 WD BB AB"; # REGFP + PRI::gen "0 WD BC 2A"; # REGFD + PRI::gen "0 WD BB FF"; # REGFP + PRI::gen "0 WD BC AA"; # REGFD + PRI::gen "0 WD BB 29"; # REGFP + PRI::gen "0 WD BC FF"; # REGFD + PRI::gen "0 WD BB A9"; # REGFP + PRI::gen "0 WD BC 28"; # REGFD + PRI::gen "0 WD BB 00"; # REGFP + PRI::gen "0 WD BC A8"; # REGFD + PRI::gen "0 WD BB 27"; # REGFP + PRI::gen "0 WD BC FF"; # REGFD + PRI::gen "0 WD BB A7"; # REGFP + PRI::gen "0 WD BC 00"; # REGFD + +# PRI::gen "0 WS 80 00 00"; # PC1 (Port configuration 1): RPB_1.SYPR , XPB_1.SYPX + PRI::gen "0 WS 81 00 0B"; # PC2 (Port configuration 2): RPB_1.GPOH (ResetID ), XPB_1.GPOL (MUX_SEL0) + PRI::gen "0 WS 82 00 9B"; # PC3 (Port configuration 3): RPC_1.GPI (nConfig0), XPC_1.GPOL (MUX_SEL1) + PRI::gen "0 WS 83 00 9B"; # PC4 (Port configuration 4): RPD_1.GPI (nConfig1), XPD_1.GPOL (MUX_SEL2) +} + + +#------------------------------------------- Instance detection + +logit "Ending '$0'"; + +close REG; + +write_pri_info @PRI_SETUP; + +close STDERR; +exit 0; diff --git a/kernel/xpp/param_doc b/kernel/xpp/param_doc new file mode 100755 index 0000000..5848728 --- /dev/null +++ b/kernel/xpp/param_doc @@ -0,0 +1,40 @@ +#! /usr/bin/perl -w +use strict; +# +# Extract parameter documentation from *.ko files. +# Assumes that parameter description include the default +# value in the format we use in our DEF_PARM() macro +# + +@ARGV || die "Usage: $0 module.ko....\n"; + +my $modinfo = '/sbin/modinfo'; +my @mod_params; + +foreach my $file (glob "@ARGV") { + undef @mod_params; + print "$file:\n"; + open(F, "$modinfo '$file' |") || die; + while() { + chomp; + next unless s/^parm:\s*//; + my ($name, $description) = split(/:/, $_, 2); + # Extract type + $description =~ s/\s*\(([^)]+)\)$//; + my $type = $1; + # Extract default value + $description =~ s/\s*\[default\s+([^]]+)\]$//; + my $default = $1; + push(@mod_params, { + NAME => $name, + TYPE => $type, + DEFVAL => $default, + DESC => $description, + }); + } + # Print sorted list + foreach my $p (sort { $a->{NAME} cmp $b->{NAME} } @mod_params) { + printf "\t%-8s %-22s = %-20s %s\n", $p->{TYPE}, $p->{NAME}, $p->{DEFVAL}, $p->{DESC}; + } + close F || die; +} diff --git a/kernel/xpp/parport_debug.c b/kernel/xpp/parport_debug.c new file mode 100644 index 0000000..93049ef --- /dev/null +++ b/kernel/xpp/parport_debug.c @@ -0,0 +1,113 @@ +/* + * Written by Oron Peled + * Copyright (C) 2007, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +# warning "This module is tested only with 2.6 kernels" +#endif + +#include +#include +#include +#include "parport_debug.h" + +static struct parport *debug_sync_parport = NULL; +static int parport_toggles[8]; /* 8 bit flip-flop */ + +void flip_parport_bit(unsigned char bitnum) +{ + static unsigned char last_value; + spinlock_t lock = SPIN_LOCK_UNLOCKED; + unsigned long flags; + unsigned char mask; + unsigned char value; + + if(!debug_sync_parport) { + if(printk_ratelimit()) { + printk(KERN_NOTICE "%s: no debug parallel port\n", + THIS_MODULE->name); + } + return; + } + BUG_ON(bitnum > 7); + mask = 1 << bitnum; + spin_lock_irqsave(&lock, flags); + value = last_value & ~mask; + if(parport_toggles[bitnum] % 2) /* square wave */ + value |= mask; + last_value = value; + parport_toggles[bitnum]++; + spin_unlock_irqrestore(&lock, flags); + parport_write_data(debug_sync_parport, value); +} +EXPORT_SYMBOL(flip_parport_bit); + +static void parport_attach(struct parport *port) +{ + printk(KERN_INFO "%s: Using %s for debugging\n", THIS_MODULE->name, port->name); + if(debug_sync_parport) { + printk(KERN_ERR "%s: Using %s, ignore new attachment %s\n", + THIS_MODULE->name, debug_sync_parport->name, port->name); + return; + } + parport_get_port(port); + debug_sync_parport = port; +} + +static void parport_detach(struct parport *port) +{ + printk(KERN_INFO "%s: Releasing %s\n", THIS_MODULE->name, port->name); + if(debug_sync_parport != port) { + printk(KERN_ERR "%s: Using %s, ignore new detachment %s\n", + THIS_MODULE->name, debug_sync_parport->name, port->name); + return; + } + parport_put_port(debug_sync_parport); + debug_sync_parport = NULL; +} + +static struct parport_driver debug_parport_driver = { + .name = "parport_debug", + .attach = parport_attach, + .detach = parport_detach, +}; + +int __init parallel_dbg_init(void) +{ + int ret; + + ret = parport_register_driver(&debug_parport_driver); + return ret; +} + +void __exit parallel_dbg_cleanup(void) +{ + parport_unregister_driver(&debug_parport_driver); +} + +MODULE_DESCRIPTION("Use parallel port to debug drivers"); +MODULE_AUTHOR("Oron Peled "); +MODULE_LICENSE("GPL"); +MODULE_VERSION("$Id:"); + +module_init(parallel_dbg_init); +module_exit(parallel_dbg_cleanup); diff --git a/kernel/xpp/parport_debug.h b/kernel/xpp/parport_debug.h new file mode 100644 index 0000000..138af99 --- /dev/null +++ b/kernel/xpp/parport_debug.h @@ -0,0 +1,31 @@ +#ifndef PARPORT_DEBUG_H +#define PARPORT_DEBUG_H +/* + * Written by Oron Peled + * Copyright (C) 2007, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifdef DEBUG_SYNC_PARPORT +void flip_parport_bit(unsigned char bitnum); +#else +#define flip_parport_bit(bitnum) +#endif + +#endif /* PARPORT_DEBUG_H */ diff --git a/kernel/xpp/utils/Makefile b/kernel/xpp/utils/Makefile new file mode 100644 index 0000000..437b359 --- /dev/null +++ b/kernel/xpp/utils/Makefile @@ -0,0 +1,136 @@ +PEDANTIC = -ansi -pedantic -std=c99 + +RANLIB = ranlib +INSTALL = install +INSTALL_DATA = install -m 644 + +ZAPTEL_DIR ?= ../.. + +-include $(ZAPTEL_DIR)/makeopts + +INSTALL_DATA = $(INSTALL) -m 644 + +# In 1.4 those are provided by autoconf through makeopts +prefix ?= /usr +datadir ?= $(prefix)/share +mandir ?= $(datadir)/man +INSTALL ?= install + +INSTALL_DATA = $(INSTALL) -m 644 + +SBINDIR = $(prefix)/sbin +DATADIR = $(datadir)/zaptel +MANDIR = $(mandir)/man8 +HOTPLUG_USB_DIR = /etc/hotplug/usb +UDEV_RULES_DIR = /etc/udev/rules.d +PERLLIBDIR := $(shell eval `perl -V:sitelib`; echo "$$sitelib") +PERL_DIRS := $(shell cd zconf; find * -name '[A-Z]*' -type d| xargs) +PERL_MODS_PAT := *.pm $(PERL_DIRS:%=%/*.pm) +PERL_MODS := $(shell cd zconf; echo $(PERL_MODS_PAT)) + +XPD_FIRMWARE = $(wildcard ../firmwares/*.hex) +XPD_INIT_DATA = $(XPD_FIRMWARE) init_fxo_modes +XPD_INIT = $(wildcard ../init_card_?_*) ../calibrate_slics xpp_fxloader + +# Variables that should be defined above, but need sane defaults: +# FIXME: Are those values really sane? +HOSTCC ?= $(CC) + +ifeq (,$(PBX_LIBUSB)) +# No PBX_LIBUSB? Maybe we compile against zaptel-1.2 +# Let's make a poor man detection of libusb +PBX_LIBUSB = $(shell if [ -r /usr/include/usb.h ]; then echo 1; else echo 0; fi) +endif + +WCTDM=$(ZAPTEL_DIR)/wctdm.c + +CFLAGS = -g -Wall $(EXTRA_CFLAGS) + +%.8: % + pod2man --section 8 $^ > $@ || $(RM) $@ +PERL_SCRIPTS = \ + zt_registration \ + xpp_sync \ + lszaptel \ + xpp_blink \ + zapconf \ + zaptel_hardware \ + # + +PERL_MANS = $(PERL_SCRIPTS:%=%.8) + +TARGETS = init_fxo_modes print_modes perlcheck +PROG_INSTALL = genzaptelconf +MAN_INSTALL = $(PROG_INSTALL:%=%.8) +ifeq (1,$(PBX_LIBUSB)) +TARGETS += libhexfile.a fpga_load test_parse +PROG_INSTALL += fpga_load +endif +ifneq (,$(PERLLIBDIR)) +PROG_INSTALL += $(PERL_SCRIPTS) +TARGETS += $(PERL_MANS) +endif + +all: $(TARGETS) + +docs: $(PERL_MANS) + +install: all + $(INSTALL) -d $(DESTDIR)$(SBINDIR) + $(INSTALL) $(PROG_INSTALL) $(DESTDIR)$(SBINDIR)/ + $(INSTALL) -d $(DESTDIR)$(DATADIR) + $(INSTALL_DATA) $(XPD_INIT_DATA) $(DESTDIR)$(DATADIR)/ + $(INSTALL) $(XPD_INIT) $(DESTDIR)$(DATADIR)/ + $(INSTALL) -d $(DESTDIR)$(MANDIR) + $(INSTALL_DATA) $(MAN_INSTALL) $(DESTDIR)$(MANDIR)/ + $(INSTALL) -d $(DESTDIR)$(HOTPLUG_USB_DIR) + $(INSTALL_DATA) xpp_fxloader.usermap $(DESTDIR)$(HOTPLUG_USB_DIR)/ + # for backward compatibility and for hotplug users: + ln -sf $(DATADIR)/xpp_fxloader $(DESTDIR)$(HOTPLUG_USB_DIR)/ + $(INSTALL) -d $(DESTDIR)$(UDEV_RULES_DIR) + $(INSTALL_DATA) xpp.rules $(DESTDIR)$(UDEV_RULES_DIR)/ +ifneq (,$(PERLLIBDIR)) + $(INSTALL) -d $(DESTDIR)$(PERLLIBDIR) + for i in $(PERL_DIRS); \ + do \ + $(INSTALL) -d "$(DESTDIR)$(PERLLIBDIR)/$$i"; \ + done + for i in $(PERL_MODS); \ + do \ + $(INSTALL_DATA) "zconf/$$i" "$(DESTDIR)$(PERLLIBDIR)/$$i"; \ + done +endif + +libhexfile.a: hexfile.o + $(AR) cru $@ $^ + $(RANLIB) $@ + +fpga_load: fpga_load.o libhexfile.a + $(CC) -L. -o $@ $@.o $(EXTRA_LIBS) -lhexfile -lusb + +fpga_load.o: CFLAGS+=-D_GNU_SOURCE # We use memrchr() + +hexfile.o: hexfile.c hexfile.h + $(CC) $(CFLAGS) $(PEDANTIC) -c $< + +test_parse.o: test_parse.c hexfile.h + $(CC) $(CFLAGS) $(PEDANTIC) -c $< + +test_parse: test_parse.o libhexfile.a + $(CC) -L. -o $@ $@.o $(EXTRA_LIBS) -lhexfile -lusb + +print_modes: print_modes.c wctdm_fxomodes.h + $(HOSTCC) -o $@ $(CFLAGS) $< + +wctdm_fxomodes.h: $(WCTDM) + perl -n -e 'print if (/^static struct fxo_mode {$$/ .. /};$$/)' $(WCTDM) >$@ + +init_fxo_modes: print_modes + ./$< >$@ + +perlcheck: $(PERL_SCRIPTS) + for i in $^; do perl -I./zconf -c $$i || exit 1; done + touch $@ + +clean: + $(RM) *.o $(TARGETS) diff --git a/kernel/xpp/utils/astribank_hook b/kernel/xpp/utils/astribank_hook new file mode 100755 index 0000000..351cd93 --- /dev/null +++ b/kernel/xpp/utils/astribank_hook @@ -0,0 +1,53 @@ +#! /bin/sh + +# This is an example of an Astribank device hook. The xpp.rules file +# calls /usr/share/zaptel/astribank_hook after a new Astribank is ready +# and after and old Astribank device has been destroyed. +# +# This example script sets the sync source, and thus makes the call to +# xpp_sync in the init.d script unnecessary. + +set -e + +xpp_sync="/usr/sbin/xpp_sync" + +me=`basename $0` +INIT_DIR=`dirname $0` +XPP_BASE=/proc/xpp +export XPP_BASE +LOGGER="logger -s -t $me" +XPP_SYNC='auto' + +ZAPTEL_BOOT_DEBIAN=${ZAPTEL_BOOT_DEBIAN:-/etc/default/zaptel} +ZAPTEL_BOOT_FEDORA=${ZAPTEL_BOOT_FEDORA:-/etc/sysconfig/zaptel} + +# read default configuration from /etc/default/zaptel +if [ -r $ZAPTEL_BOOT_DEBIAN ]; then . $ZAPTEL_BOOT_DEBIAN; fi +if [ -r $ZAPTEL_BOOT_FEDORA ]; then . $ZAPTEL_BOOT_FEDORA; fi + +if [ "$ASTRIBANK_HOOK_DISABLED" != '' ]; then + $LOGGER -p kern.info "Exiting... ASTRIBANK_HOOK_DISABLED" + exit 0 +fi + +# Always redirect stderr somewhere, otherwise the shell script will die +# when it tries to do I/O related stuff on closed file descriptor. +# Our default is to throw it down the bit-bucket. +#exec 2> /dev/console +## If you wish to trace this script: +#exec 2> "/tmp/astribank_hook_$XBUS_NAME" + +$LOGGER -p kern.info "$ACTION: $*. Setting sync to $XPP_SYNC." + +case "$ACTION" in +add) + "$xpp_sync" $XPP_SYNC + ;; +remove) + "$xpp_sync" $XPP_SYNC + ;; +*) + ;; +esac + +"$xpp_sync" | $LOGGER -p kern.info diff --git a/kernel/xpp/utils/example_default_zaptel b/kernel/xpp/utils/example_default_zaptel new file mode 100644 index 0000000..f60b651 --- /dev/null +++ b/kernel/xpp/utils/example_default_zaptel @@ -0,0 +1,31 @@ +# Disables hotplug firmware loading +#XPP_HOTPLUG_DISABLED=yes +# +# Disables udev hook called when an astribank is added and ready +# or removed. +#ASTRIBANK_HOOK_DISABLED=yes + +# Setup for XPP PRI. This allows to have fixed settings: +# 1. The variable XPP_PRI_SETUP contains a whitespace separated list of +# port specifications. +# 2. Each port specification contains a match expression, a '=' and +# a setting string. +# 2. Match expressions may be: +# - CONNECTOR/usb..../XPD-nn To identify by physical connector +# - NUM/XBUS-mm/XPD-nn To identify by bus number +# 4. Match expressions may contain "wildcards" (which are translated +# internally to regular expressions): +# * matches zero or more characters. +# ? matches one charater +# 5. The list of matches is scanned from beginning to end. First match wins. +# 6. The list implicitly contains an 'NUM/*=TE,E1' catch all default, appended +# to its end. +# 7. The setting string is composed of comma separated settings. Valid +# settings are: +# - NT or TE +# - E1 or T1 or J1 +# +XPP_PRI_SETUP=' + CONNECTOR/usb-0000:00:1d.7-1/XPD-01=NT,E1 + NUM/*/XPD-03=NT,E1 + ' diff --git a/kernel/xpp/utils/fpga_load.8 b/kernel/xpp/utils/fpga_load.8 new file mode 100644 index 0000000..412a839 --- /dev/null +++ b/kernel/xpp/utils/fpga_load.8 @@ -0,0 +1,86 @@ +.TH "FPGA_LOAD" "8" "16 April 2006" "" "" + +.SH NAME +ztcfg \- reads and loads zaptel.conf +.SH SYNOPSIS + +.B fpga_load +[\fB-g\fR] [\fB-r\fR] [\fB-v\fR] \fB-D \fR{/proc/bus/usb|/dev/bus/usb}/\fIBUS/DEV\fR + +.B fpga_load +[\fB-g\fR] [\fB-v\fR] \fB-D \fR{/proc/bus/usb|/dev/bus/usb}/\fIBUS/DEV\fR \fB-I \fIfirmware.hex\fR [\fB-b \fIdump.bin\fR] [\fB-i\fR] + +.B fpga_load -h + +.SH DESCRIPTION +.B fpga_load +loads the FPGA firmware to the Xorcom Astribank device. +The syntax resembles that of fxload(8). + +.SH OPTIONS +.B -b +.I dump.bin +.RS +Before writing firmware, bump the processed binary file to +.I dump.bin\fR. +.RE + +.B -D +.I DEVICE +.RS +Required. The device to read from/write to. On modern UDEV-based system +this is usually /dev/bus/usb/\fIbus_num\fR/\fIdevice_num\fR, +where \fIbus_num\fR and \fIdevice_num\fR are the first two numbers in the +output of lsusb(8). +On older systems that use usbfs, it is usually +/proc/bus/usb/\fIbus_num\fR/\fIdevice_num\fR. +.RE + +.B -r +.RS +Reset the Astribank and renumerate its USB connection to power on product ID. +.RE + +.B -g +.RS +Dump all eeprom data to standard output. +.RE + +.B -I +.I fireware_file +.RS +The firmware file to write to the device. +.RE + +.B -i +.RS +Show information about the firmware file (valid only with \fB-I\fR option). +Example: +.PP + ./FPGA_1151.hex: Version=3297 Checksum=58270 + +In particular, the calculated checksum should match the output of \fIsum(1)\fR +on the binary firmware file generated by the \fB-b\fR option. +.RE + +.B -v +.RS +Increase verbosity. May be used multiple times. +.RE + +.B -h +.RS +Displays usage message. +.RE + +.SH SEE ALSO +fxload(8), lsusb(8) + +.SH AUTHOR +This manual page was written by Tzafrir Cohen . +Permission is granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. + +On Debian systems, the complete text of the GNU General Public +License can be found in /usr/share/common-licenses/GPL. diff --git a/kernel/xpp/utils/fpga_load.c b/kernel/xpp/utils/fpga_load.c new file mode 100644 index 0000000..3d6bdbe --- /dev/null +++ b/kernel/xpp/utils/fpga_load.c @@ -0,0 +1,1003 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "hexfile.h" + +static const char rcsid[] = "$Id$"; + +#define ERR(fmt, arg...) do { \ + if(verbose >= LOG_ERR) \ + fprintf(stderr, "%s: ERROR (%d): " fmt, \ + progname, __LINE__, ## arg); \ + } while(0); +#define INFO(fmt, arg...) do { \ + if(verbose >= LOG_INFO) \ + fprintf(stderr, "%s: " fmt, \ + progname, ## arg); \ + } while(0); +#define DBG(fmt, arg...) do { \ + if(verbose >= LOG_DEBUG) \ + fprintf(stderr, "%s: DBG: " fmt, \ + progname, ## arg); \ + } while(0); + +static int verbose = LOG_WARNING; +static char *progname; +static int disconnected = 0; + +#define MAX_HEX_LINES 10000 +#define PACKET_SIZE 512 +#define EEPROM_SIZE 16 +#define LABEL_SIZE 8 +#define TIMEOUT 5000 + + +/* My device parameters */ +#define MY_EP_OUT 0x04 +#define MY_EP_IN 0x88 + +#define FPGA_EP_OUT 0x02 +#define FPGA_EP_IN 0x86 + +/* USB firmware types */ +#define USB_11xx 0 +#define USB_FIRMWARE_II 1 + +#define TYPE_ENTRY(t,ni,n,ne,out,in,...) \ + [t] = { \ + .type_code = (t), \ + .num_interfaces = (ni), \ + .my_interface_num = (n), \ + .num_endpoints = (ne), \ + .my_ep_in = (in), \ + .my_ep_out = (out), \ + .name = #t, \ + .endpoints = { __VA_ARGS__ }, \ + } + +static const struct astribank_type { + int type_code; + int num_interfaces; + int my_interface_num; + int num_endpoints; + int my_ep_out; + int my_ep_in; + char *name; + int endpoints[4]; /* for matching */ +} astribank_types[] = { + TYPE_ENTRY(USB_11xx, 1, 0, 4, MY_EP_OUT, MY_EP_IN, + FPGA_EP_OUT, + MY_EP_OUT, + FPGA_EP_IN, + MY_EP_IN), + TYPE_ENTRY(USB_FIRMWARE_II, 2, 1, 2, MY_EP_OUT, MY_EP_IN, + MY_EP_OUT, + MY_EP_IN), +}; +#undef TYPE_ENTRY + +enum fpga_load_packet_types { + PT_STATUS_REPLY = 0x01, + PT_DATA_PACKET = 0x01, +#ifdef XORCOM_INTERNAL + PT_EEPROM_SET = 0x04, +#endif + PT_EEPROM_GET = 0x08, + PT_RENUMERATE = 0x10, + PT_RESET = 0x20, + PT_BAD_COMMAND = 0xAA +}; + +struct myeeprom { + uint8_t source; + uint16_t vendor; + uint16_t product; + uint8_t release_major; + uint8_t release_minor; + uint8_t reserved; + uint8_t label[LABEL_SIZE]; +} PACKED; + +struct fpga_packet_header { + struct { + uint8_t op; + } PACKED header; + union { + struct { + uint16_t seq; + uint8_t status; + } PACKED status_reply; + struct { + uint16_t seq; + uint8_t reserved; + uint8_t data[ZERO_SIZE]; + } PACKED data_packet; + struct { + struct myeeprom data; + } PACKED eeprom_set; + struct { + struct myeeprom data; + } PACKED eeprom_get; + } d; +} PACKED; + +enum fpga_load_status { + FW_FAIL_RESET = 1, + FW_FAIL_TRANS = 2, + FW_TRANS_OK = 4, + FW_CONFIG_DONE = 8 +}; + +struct my_usb_device { + struct usb_device *dev; + usb_dev_handle *handle; + int my_interface_num; + int my_ep_out; + int my_ep_in; + char iManufacturer[BUFSIZ]; + char iProduct[BUFSIZ]; + char iSerialNumber[BUFSIZ]; + char iInterface[BUFSIZ]; + int is_usb2; + struct myeeprom eeprom; + const struct astribank_type *abtype; +}; + +const char *load_status2str(enum fpga_load_status s) +{ + switch(s) { + case FW_FAIL_RESET: return "FW_FAIL_RESET"; + case FW_FAIL_TRANS: return "FW_FAIL_TRANS"; + case FW_TRANS_OK: return "FW_TRANS_OK"; + case FW_CONFIG_DONE: return "FW_CONFIG_DONE"; + default: return "UNKNOWN"; + } +} + +/* return 1 if: + * - str has a number + * - It is larger than 0 + * - It equals num + */ +int num_matches(int num, const char* str) { + int str_val = atoi(str); + if (str_val <= 0) + return 0; + return (str_val == num); +} + +struct usb_device *dev_of_path(const char *path) +{ + struct usb_bus *bus; + struct usb_device *dev; + char dirname[PATH_MAX]; + char filename[PATH_MAX]; + const char *p; + int bnum; + int dnum; + int ret; + + assert(path != NULL); + if(access(path, F_OK) < 0) { + perror(path); + return NULL; + } + /* Find last '/' */ + if((p = memrchr(path, '/', strlen(path))) == NULL) { + ERR("Missing a '/' in %s\n", path); + return NULL; + } + /* Get the device number */ + ret = sscanf(p + 1, "%d", &dnum); + if(ret != 1) { + ERR("Path tail is not a device number: '%s'\n", p); + return NULL; + } + /* Search for a '/' before that */ + p = memrchr(path, '/', p - path); + if(p == NULL) + p = path; /* Relative path */ + else + p++; /* skip '/' */ + /* Get the bus number */ + ret = sscanf(p, "%d", &bnum); + if(ret != 1) { + ERR("Path tail is not a bus number: '%s'\n", p); + return NULL; + } + sprintf(dirname, "%03d", bnum); + sprintf(filename, "%03d", dnum); + for (bus = usb_busses; bus; bus = bus->next) { + if (! num_matches(bnum, bus->dirname)) + //if(strcmp(bus->dirname, dirname) != 0) + continue; + for (dev = bus->devices; dev; dev = dev->next) { + //if(strcmp(dev->filename, filename) == 0) + if (num_matches(dnum, dev->filename)) + return dev; + } + } + ERR("no usb device match '%s'\n", path); + return NULL; +} + +int get_usb_string(char *buf, unsigned int len, uint16_t item, usb_dev_handle *handle) +{ + char tmp[BUFSIZ]; + int ret; + + if (!item) + return 0; + ret = usb_get_string_simple(handle, item, tmp, BUFSIZ); + if (ret <= 0) + return ret; + return snprintf(buf, len, "%s", tmp); +} + +void my_usb_device_cleanup(struct my_usb_device *mydev) +{ + assert(mydev != NULL); + if(!mydev->handle) { + return; /* Nothing to do */ + } + if(!disconnected) { + if(usb_release_interface(mydev->handle, mydev->abtype->my_interface_num) != 0) { + ERR("Releasing interface: usb: %s\n", usb_strerror()); + } + } + if(usb_close(mydev->handle) != 0) { + ERR("Closing device: usb: %s\n", usb_strerror()); + } + disconnected = 1; + mydev->handle = NULL; +} + +static void show_device_info(const struct my_usb_device *mydev) +{ + const struct myeeprom *eeprom; + uint8_t data[LABEL_SIZE + 1]; + + assert(mydev != NULL); + eeprom = &mydev->eeprom; + memset(data, 0, LABEL_SIZE + 1); + memcpy(data, eeprom->label, LABEL_SIZE); + printf("USB Firmware Type: [%s]\n", mydev->abtype->name); + printf("USB iManufacturer: [%s]\n", mydev->iManufacturer); + printf("USB iProduct: [%s]\n", mydev->iProduct); + printf("USB iSerialNumber: [%s]\n", mydev->iSerialNumber); + printf("EEPROM Source: 0x%02X\n", eeprom->source); + printf("EEPROM Vendor: 0x%04X\n", eeprom->vendor); + printf("EEPROM Product: 0x%04X\n", eeprom->product); + printf("EEPROM Release: %d.%03d\n", eeprom->release_major, eeprom->release_minor); + printf("EEPROM Label: HEX(%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X) [%s]\n", + data[0], data[1], data[2], data[3], + data[4], data[5], data[6], data[7], data); +} + +void dump_packet(const char *msg, const char *buf, int len) +{ + int i; + + for(i = 0; i < len; i++) + INFO("%s: %2d> 0x%02X\n", msg, i, (uint8_t)buf[i]); +} + +int send_usb(const char *msg, struct my_usb_device *mydev, struct fpga_packet_header *phead, int len, int timeout) +{ + char *p = (char *)phead; + int ret; + + if(verbose >= LOG_DEBUG) + dump_packet(msg, p, len); + if(mydev->my_ep_out & USB_ENDPOINT_IN) { + ERR("send_usb called with an input endpoint 0x%x\n", mydev->my_ep_out); + return -EINVAL; + } + ret = usb_bulk_write(mydev->handle, mydev->my_ep_out, p, len, timeout); + if(ret < 0) { + /* + * If the device was gone, it may be the + * result of renumeration. Ignore it. + */ + if(ret != -ENODEV) { + ERR("bulk_write to endpoint 0x%x failed: %s\n", mydev->my_ep_out, usb_strerror()); + dump_packet("send_usb[ERR]", p, len); + } else { + disconnected = 1; + my_usb_device_cleanup(mydev); + } + return ret; + } else if(ret != len) { + ERR("bulk_write to endpoint 0x%x short write: %s\n", mydev->my_ep_out, usb_strerror()); + dump_packet("send_usb[ERR]", p, len); + return -EFAULT; + } + return ret; +} + +int recv_usb(const char *msg, struct my_usb_device *mydev, char *buf, size_t len, int timeout) +{ + int ret; + + if(mydev->my_ep_in & USB_ENDPOINT_OUT) { + ERR("recv_usb called with an output endpoint 0x%x\n", mydev->my_ep_in); + return -EINVAL; + } + ret = usb_bulk_read(mydev->handle, mydev->my_ep_in, buf, len, timeout); + if(ret < 0) { + ERR("bulk_read from endpoint 0x%x failed: %s\n", mydev->my_ep_in, usb_strerror()); + return ret; + } + if(verbose >= LOG_DEBUG) + dump_packet(msg, buf, ret); + return ret; +} + +#ifdef XORCOM_INTERNAL +int eeprom_set(struct my_usb_device *mydev, const struct myeeprom *eeprom) +{ + int ret; + int len; + char buf[PACKET_SIZE]; + struct fpga_packet_header *phead = (struct fpga_packet_header *)buf; + + DBG("%s Start...\n", __FUNCTION__); + assert(mydev != NULL); + phead->header.op = PT_EEPROM_SET; + memcpy(&phead->d.eeprom_set.data, eeprom, EEPROM_SIZE); + len = sizeof(phead->d.eeprom_set) + sizeof(phead->header.op); + ret = send_usb("eeprom_set[W]", mydev, phead, len, TIMEOUT); + if(ret < 0) + return ret; + ret = recv_usb("eeprom_set[R]", mydev, buf, sizeof(buf), TIMEOUT); + if(ret <= 0) + return ret; + phead = (struct fpga_packet_header *)buf; + if(phead->header.op == PT_BAD_COMMAND) { + ERR("Firmware rejected PT_EEPROM_SET command\n"); + return -EINVAL; + } else if(phead->header.op != PT_EEPROM_SET) { + ERR("Got unexpected reply op=%d\n", phead->header.op); + return -EINVAL; + } + return 0; +} +#endif + +int eeprom_get(struct my_usb_device *mydev) +{ + int ret; + int len; + char buf[PACKET_SIZE]; + struct fpga_packet_header *phead = (struct fpga_packet_header *)buf; + struct myeeprom *eeprom; + + assert(mydev != NULL); + eeprom = &mydev->eeprom; + DBG("%s Start...\n", __FUNCTION__); + phead->header.op = PT_EEPROM_GET; + len = sizeof(phead->header.op); /* warning: sending small packet */ + ret = send_usb("eeprom_get[W]", mydev, phead, len, TIMEOUT); + if(ret < 0) + return ret; + ret = recv_usb("eeprom_get[R]", mydev, buf, sizeof(buf), TIMEOUT); + if(ret <= 0) + return ret; + phead = (struct fpga_packet_header *)buf; + if(phead->header.op == PT_BAD_COMMAND) { + ERR("PT_BAD_COMMAND\n"); + return -EINVAL; + } else if(phead->header.op != PT_EEPROM_GET) { + ERR("Got unexpected reply op=%d\n", phead->header.op); + return -EINVAL; + } + memcpy(eeprom, &phead->d.eeprom_get.data, EEPROM_SIZE); + return 0; +} + +int send_hexline(struct my_usb_device *mydev, struct hexline *hexline, int seq) +{ + int ret; + int len; + uint8_t *data; + char buf[PACKET_SIZE]; + struct fpga_packet_header *phead = (struct fpga_packet_header *)buf; + enum fpga_load_status status; + + assert(mydev != NULL); + assert(hexline != NULL); + if(hexline->d.content.header.tt != TT_DATA) { + DBG("Non data record %d type = %d\n", seq, hexline->d.content.header.tt); + return 0; + } + len = hexline->d.content.header.ll; /* don't send checksum */ + data = hexline->d.content.tt_data.data; + phead->header.op = PT_DATA_PACKET; + phead->d.data_packet.seq = seq; + phead->d.data_packet.reserved = 0x00; + memcpy(phead->d.data_packet.data, data, len); + len += sizeof(hexline->d.content.header); + DBG("%04d+\r", seq); + ret = send_usb("hexline[W]", mydev, phead, len, TIMEOUT); + if(ret < 0) + return ret; + ret = recv_usb("hexline[R]", mydev, buf, sizeof(buf), TIMEOUT); + if(ret <= 0) + return ret; + DBG("%04d-\r", seq); + phead = (struct fpga_packet_header *)buf; + if(phead->header.op != PT_STATUS_REPLY) { + ERR("Got unexpected reply op=%d\n", phead->header.op); + dump_packet("hexline[ERR]", buf, ret); + return -EINVAL; + } + status = (enum fpga_load_status)phead->d.status_reply.status; + switch(status) { + case FW_TRANS_OK: + case FW_CONFIG_DONE: + break; + case FW_FAIL_RESET: + case FW_FAIL_TRANS: + ERR("status reply %s (%d)\n", load_status2str(status), status); + dump_packet("hexline[ERR]", buf, ret); + return -EPROTO; + default: + ERR("Unknown status reply %d\n", status); + dump_packet("hexline[ERR]", buf, ret); + return -EPROTO; + } + return 0; +} + +//. returns > 0 - ok, the number of lines sent +//. returns < 0 - error number +int send_splited_hexline(struct my_usb_device *mydev, struct hexline *hexline, int seq, uint8_t maxwidth) +{ + struct hexline *extraline; + int linessent = 0; + int allocsize; + int extra_offset = 0; + unsigned int this_line = 0; + uint8_t bytesleft = 0; + + assert(mydev != NULL); + if(!hexline) { + ERR("Bad record %d type = %d\n", seq, hexline->d.content.header.tt); + return -EINVAL; + } + bytesleft = hexline->d.content.header.ll; + // split the line into several lines + while (bytesleft > 0) { + int status; + this_line = (bytesleft >= maxwidth) ? maxwidth : bytesleft; + allocsize = sizeof(struct hexline) + this_line + 1; + // generate the new line + if((extraline = (struct hexline *)malloc(allocsize)) == NULL) { + ERR("Not enough memory for spliting the lines\n" ); + return -EINVAL; + } + memset(extraline, 0, allocsize); + extraline->d.content.header.ll = this_line; + extraline->d.content.header.offset = hexline->d.content.header.offset + extra_offset; + extraline->d.content.header.tt = hexline->d.content.header.tt; + memcpy( extraline->d.content.tt_data.data, hexline->d.content.tt_data.data+extra_offset, this_line); + status = send_hexline(mydev, extraline, seq+linessent ); + // cleanups + free(extraline); + extra_offset += this_line; + bytesleft -= this_line; + if (status) + return status; + linessent++; + } + return linessent; +} + +int match_usb_device_identity(const struct usb_config_descriptor *config_desc, + const struct astribank_type *ab) +{ + struct usb_interface *interface; + struct usb_interface_descriptor *iface_desc; + + if(config_desc->bNumInterfaces <= ab->my_interface_num) + return 0; + interface = &config_desc->interface[ab->my_interface_num]; + iface_desc = interface->altsetting; + + return iface_desc->bInterfaceClass == 0xFF && + iface_desc->bInterfaceNumber == ab->my_interface_num && + iface_desc->bNumEndpoints == ab->num_endpoints; +} + +const struct astribank_type *my_usb_device_identify(const char devpath[], struct my_usb_device *mydev) +{ + struct usb_device_descriptor *dev_desc; + struct usb_config_descriptor *config_desc; + int i; + + assert(mydev != NULL); + usb_init(); + usb_find_busses(); + usb_find_devices(); + mydev->dev = dev_of_path(devpath); + if(!mydev->dev) { + ERR("Bailing out\n"); + return 0; + } + dev_desc = &mydev->dev->descriptor; + config_desc = mydev->dev->config; + for(i = 0; i < sizeof(astribank_types)/sizeof(astribank_types[0]); i++) { + if(match_usb_device_identity(config_desc, &astribank_types[i])) { + DBG("Identified[%d]: interfaces=%d endpoints=%d: \"%s\"\n", + i, + astribank_types[i].num_interfaces, + astribank_types[i].num_endpoints, + astribank_types[i].name); + return &astribank_types[i]; + } + } + return NULL; +} + +int my_usb_device_init(const char devpath[], struct my_usb_device *mydev, const struct astribank_type *abtype) +{ + struct usb_device_descriptor *dev_desc; + struct usb_config_descriptor *config_desc; + struct usb_interface *interface; + struct usb_interface_descriptor *iface_desc; + struct usb_endpoint_descriptor *endpoint; + int ret; + int i; + + assert(mydev != NULL); + usb_init(); + usb_find_busses(); + usb_find_devices(); + mydev->dev = dev_of_path(devpath); + if(!mydev->dev) { + ERR("Bailing out\n"); + return 0; + } + mydev->handle = usb_open(mydev->dev); + if(!mydev->handle) { + ERR("Failed to open usb device '%s/%s': %s\n", mydev->dev->bus->dirname, mydev->dev->filename, usb_strerror()); + return 0; + } + if(usb_claim_interface(mydev->handle, abtype->my_interface_num) != 0) { + ERR("usb_claim_interface: %s\n", usb_strerror()); + return 0; + } + dev_desc = &mydev->dev->descriptor; + config_desc = mydev->dev->config; + interface = &config_desc->interface[abtype->my_interface_num]; + iface_desc = interface->altsetting; + endpoint = iface_desc->endpoint; + mydev->is_usb2 = (endpoint->wMaxPacketSize == 512); + for(i = 0; i < iface_desc->bNumEndpoints; i++, endpoint++) { + if(endpoint->bEndpointAddress != abtype->endpoints[i]) { + ERR("Wrong endpoint 0x%X (at index %d)\n", endpoint->bEndpointAddress, i); + return 0; + } + if(endpoint->bEndpointAddress == MY_EP_OUT || endpoint->bEndpointAddress == MY_EP_IN) { + if(endpoint->wMaxPacketSize > PACKET_SIZE) { + ERR("Endpoint #%d wMaxPacketSize too large (%d)\n", i, endpoint->wMaxPacketSize); + return 0; + } + } + } + mydev->abtype = abtype; + mydev->my_ep_in = abtype->my_ep_in; + mydev->my_ep_out = abtype->my_ep_out; + ret = get_usb_string(mydev->iManufacturer, BUFSIZ, dev_desc->iManufacturer, mydev->handle); + ret = get_usb_string(mydev->iProduct, BUFSIZ, dev_desc->iProduct, mydev->handle); + ret = get_usb_string(mydev->iSerialNumber, BUFSIZ, dev_desc->iSerialNumber, mydev->handle); + ret = get_usb_string(mydev->iInterface, BUFSIZ, iface_desc->iInterface, mydev->handle); + INFO("ID=%04X:%04X Manufacturer=[%s] Product=[%s] SerialNumber=[%s] Interface=[%s]\n", + dev_desc->idVendor, + dev_desc->idProduct, + mydev->iManufacturer, + mydev->iProduct, + mydev->iSerialNumber, + mydev->iInterface); + if(usb_clear_halt(mydev->handle, mydev->my_ep_out) != 0) { + ERR("Clearing output endpoint: %s\n", usb_strerror()); + return 0; + } + if(usb_clear_halt(mydev->handle, mydev->my_ep_in) != 0) { + ERR("Clearing input endpoint: %s\n", usb_strerror()); + return 0; + } + return 1; +} + +int renumerate_device(struct my_usb_device *mydev, enum fpga_load_packet_types pt) +{ + char buf[PACKET_SIZE]; + struct fpga_packet_header *phead = (struct fpga_packet_header *)buf; + int ret; + + assert(mydev != NULL); + DBG("Renumerating with 0x%X\n", pt); + phead->header.op = pt; + ret = send_usb("renumerate[W]", mydev, phead, 1, TIMEOUT); + if(ret < 0 && ret != -ENODEV) + return ret; +#if 0 + /* + * FIXME: we count on our USB firmware to reset the device... should we? + */ + ret = usb_reset(mydev->handle); + if(ret < 0) { + ERR("usb_reset: %s\n", usb_strerror()); + return -ENODEV; + } +#endif + return 0; +} + +/* + * Returns: true on success, false on failure + */ +int fpga_load(struct my_usb_device *mydev, const struct hexdata *hexdata) +{ + unsigned int i; + unsigned int j = 0; + int ret; + int finished = 0; + const char *v = hexdata->version_info; + + v = (v[0]) ? v : "Unknown"; + assert(mydev != NULL); + INFO("FPGA_LOAD (version %s)\n", v); + /* + * i - is the line number + * j - is the sequence number, on USB 2, i=j, but on + * USB 1 send_splited_hexline may increase the sequence + * number, as it needs + */ + for(i = 0; i < hexdata->maxlines; i++) { + struct hexline *hexline = hexdata->lines[i]; + + if(!hexline) + break; + if(finished) { + ERR("Extra data after End Of Data Record (line %d)\n", i); + return 0; + } + if(hexline->d.content.header.tt == TT_EOF) { + DBG("End of data\n"); + finished = 1; + continue; + } + if(mydev->is_usb2) { + if((ret = send_hexline(mydev, hexline, i)) != 0) { + perror("Failed sending hexline"); + return 0; + } + } else { + if((ret = send_splited_hexline(mydev, hexline, j, 60)) < 0) { + perror("Failed sending hexline (splitting did not help)"); + return 0; + } + j += ret; + } + } + DBG("Finished...\n"); + return 1; +} + +#include + +void usage() +{ + fprintf(stderr, "Usage: %s -D {/proc/bus/usb|/dev/bus/usb}// [options...]\n", progname); + fprintf(stderr, "\tOptions:\n"); + fprintf(stderr, "\t\t[-r] # Reset the device\n"); + fprintf(stderr, "\t\t[-b ] # Output to \n"); + fprintf(stderr, "\t\t[-I ] # Input from \n"); + fprintf(stderr, "\t\t[-H ] # Output to ('-' is stdout)\n"); + fprintf(stderr, "\t\t[-i] # Show hexfile information\n"); + fprintf(stderr, "\t\t[-g] # Get eeprom from device\n"); + fprintf(stderr, "\t\t[-v] # Increase verbosity\n"); +#ifdef XORCOM_INTERNAL + fprintf(stderr, "\t\t[-C srC byte] # Set Address sourCe (default: C0)\n"); + fprintf(stderr, "\t\t[-V vendorid] # Set Vendor id on device\n"); + fprintf(stderr, "\t\t[-P productid] # Set Product id on device\n"); + fprintf(stderr, "\t\t[-R release] # Set Release. 2 dot separated decimals\n"); + fprintf(stderr, "\t\t[-L label] # Set label.\n"); +#endif + exit(1); +} + +static void parse_report_func(int level, const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + if(level <= verbose) + vfprintf(stderr, msg, ap); + va_end(ap); +} + +#ifdef XORCOM_INTERNAL +static void eeprom_fill(struct myeeprom *myeeprom, + const char vendor[], + const char product[], + const char release[], + const char label[], + const char source[]) +{ + // FF: address source is from device. C0: from eeprom + if (source) + myeeprom->source = strtoul(source, NULL, 0); + else + myeeprom->source = 0xC0; + if(vendor) + myeeprom->vendor = strtoul(vendor, NULL, 0); + if(product) + myeeprom->product = strtoul(product, NULL, 0); + if(release) { + int release_major = 0; + int release_minor = 0; + + sscanf(release, "%d.%d", &release_major, &release_minor); + myeeprom->release_major = release_major; + myeeprom->release_minor = release_minor; + } + if(label) { + /* padding */ + memset(myeeprom->label, 0, LABEL_SIZE); + memcpy(myeeprom->label, label, strlen(label)); + } +} +#endif + +int main(int argc, char *argv[]) +{ + const struct astribank_type *abtype; + struct my_usb_device mydev; + const char *devpath = NULL; + const char *binfile = NULL; + const char *inhexfile = NULL; + const char *outhexfile = NULL; + struct hexdata *hexdata = NULL; + int opt_reset = 0; + int opt_info = 0; + int opt_read_eeprom = 0; + int opt_output_width = 0; + int output_is_set = 0; +#ifdef XORCOM_INTERNAL + int opt_write_eeprom = 0; + char *vendor = NULL; + char *source = NULL; + char *product = NULL; + char *release = NULL; + char *label = NULL; + const char options[] = "rib:D:ghH:I:vw:C:V:P:R:S:"; +#else + const char options[] = "rib:D:ghH:I:vw:"; +#endif + int ret = 0; + + progname = argv[0]; + assert(sizeof(struct fpga_packet_header) <= PACKET_SIZE); + assert(sizeof(struct myeeprom) == EEPROM_SIZE); + while (1) { + int c; + + c = getopt (argc, argv, options); + if (c == -1) + break; + + switch (c) { + case 'D': + devpath = optarg; + if(output_is_set++) { + ERR("Cannot set -D. Another output option is already selected\n"); + return 1; + } + break; + case 'r': + opt_reset = 1; + break; + case 'i': + opt_info = 1; + break; + case 'b': + binfile = optarg; + if(output_is_set++) { + ERR("Cannot set -b. Another output option is already selected\n"); + return 1; + } + break; + case 'g': + opt_read_eeprom = 1; + break; + case 'H': + outhexfile = optarg; + if(output_is_set++) { + ERR("Cannot set -H. Another output option is already selected\n"); + return 1; + } + break; + case 'I': + inhexfile = optarg; + break; +#ifdef XORCOM_INTERNAL + case 'V': + vendor = optarg; + break; + case 'C': + source = optarg; + break; + case 'P': + product = optarg; + break; + case 'R': + release = optarg; + break; + case 'S': + label = optarg; + { + const char GOOD_CHARS[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "-_."; + int len = strlen(label); + int goodlen = strspn(label, GOOD_CHARS); + + if(len > LABEL_SIZE) { + ERR("Label too long (%d > %d)\n", len, LABEL_SIZE); + usage(); + } + if(goodlen != len) { + ERR("Bad character in label number (pos=%d)\n", goodlen); + usage(); + } + } + break; +#endif + case 'w': + opt_output_width = strtoul(optarg, NULL, 0); + break; + case 'v': + verbose++; + break; + case 'h': + default: + ERR("Unknown option '%c'\n", c); + usage(); + } + } + + if (optind != argc) { + usage(); + } + if(inhexfile) { +#ifdef XORCOM_INTERNAL + if(vendor || product || release || label || source ) { + ERR("The -I option is exclusive of -[VPRSC]\n"); + return 1; + } +#endif + parse_hexfile_set_reporting(parse_report_func); + hexdata = parse_hexfile(inhexfile, MAX_HEX_LINES); + if(!hexdata) { + ERR("Bailing out\n"); + exit(1); + } + if(opt_info) { + printf("%s: Version=%s Checksum=%d\n", + inhexfile, hexdata->version_info, + bsd_checksum(hexdata)); + } + if(binfile) { + dump_binary(hexdata, binfile); + return 0; + } + if(outhexfile) { + if(opt_output_width) + dump_hexfile2(hexdata, outhexfile, opt_output_width); + else + dump_hexfile(hexdata, outhexfile); + return 0; + } + } +#ifdef XORCOM_INTERNAL + else if(vendor || product || release || label || source ) { + if(outhexfile) { + FILE *fp; + + if(strcmp(outhexfile, "-") == 0) + fp = stdout; + else if((fp = fopen(outhexfile, "w")) == NULL) { + perror(outhexfile); + return 1; + } + memset(&mydev.eeprom, 0, sizeof(struct myeeprom)); + eeprom_fill(&mydev.eeprom, vendor, product, release, label, source); + gen_hexline((uint8_t *)&mydev.eeprom, 0, sizeof(mydev.eeprom), fp); + gen_hexline(NULL, 0, 0, fp); /* EOF */ + return 0; + } + } +#endif + if(!devpath) { + ERR("Missing device path\n"); + usage(); + } + DBG("Startup %s\n", devpath); + if((abtype = my_usb_device_identify(devpath, &mydev)) == NULL) { + ERR("Bad device. Does not match our types.\n"); + usage(); + } + INFO("FIRMWARE: %s (type=%d)\n", abtype->name, abtype->type_code); + if(!my_usb_device_init(devpath, &mydev, abtype)) { + ERR("Failed to initialize USB device '%s'\n", devpath); + ret = -ENODEV; + goto dev_err; + } + ret = eeprom_get(&mydev); + if(ret < 0) { + ERR("Failed reading eeprom\n"); + goto dev_err; + } +#ifdef XORCOM_INTERNAL + if(vendor || product || release || label || source ) { + eeprom_fill(&mydev.eeprom, vendor, product, release, label, source); + opt_write_eeprom = 1; + opt_read_eeprom = 1; + } +#endif + if(opt_read_eeprom) { + show_device_info(&mydev); + } + if(hexdata) { + if (!mydev.is_usb2) + INFO("Warning: working on a low end USB1 backend\n"); + if(!fpga_load(&mydev, hexdata)) { + ERR("FPGA loading failed\n"); + ret = -ENODEV; + goto dev_err; + } + ret = renumerate_device(&mydev, PT_RENUMERATE); + if(ret < 0) { + ERR("Renumeration failed: errno=%d\n", ret); + goto dev_err; + } + } +#ifdef XORCOM_INTERNAL + else if(opt_write_eeprom) { + if(abtype->type_code == USB_FIRMWARE_II) { + ERR("No EEPROM burning command in %s. Use fxload for that\n", + abtype->name); + goto dev_err; + } + ret = eeprom_set(&mydev, &mydev.eeprom); + if(ret < 0) { + ERR("Failed writing eeprom: %s\n", strerror(-ret)); + goto dev_err; + } + printf("------- RESULTS -------\n"); + show_device_info(&mydev); + } +#endif + if(opt_reset) { + DBG("Reseting to default\n"); + ret = renumerate_device(&mydev, PT_RESET); + if(ret < 0) { + ERR("Renumeration to default failed: errno=%d\n", ret); + goto dev_err; + } + } + DBG("Exiting\n"); +dev_err: + my_usb_device_cleanup(&mydev); + return ret; +} diff --git a/kernel/xpp/utils/genzaptelconf b/kernel/xpp/utils/genzaptelconf new file mode 100755 index 0000000..1435e9f --- /dev/null +++ b/kernel/xpp/utils/genzaptelconf @@ -0,0 +1,1195 @@ +#! /bin/bash + +# genzaptelconf: generate as smartly as you can: +# /etc/zaptel.conf +# /etc/asterisk/zapata-channels.conf (to be #include-d into zapata.conf) +# update: +# With '-M' /etc/modules (list of modules to load) +# +# Copyright (C) 2005 by Xorcom +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# +# If you have any technical questions, contact +# Tzafrir Cohen +# + +# The script uses a number of bash-specific features +# TODO: either ditch them or convert to perl +# Don't override variables here. +# Override them in /etc/default/zaptel (debian) or /etc/sysconfig/zaptel +# (redhat/centos) + +# /etc/default/zaptel may override the following variables +VERSION=0.5.10 +rcsid='$Id$' +lc_country=us +# set to: ls, ks or gs for (Loopstart, Kewlstart and GroundStart) +# on FXS channels (FXO signalling). +fxs_default_start=ks +base_exten=6000 +# If set: no context changes are made in zapata-channels.conf +#context_manual=yes +context_lines=from-pstn # context into which PSTN calls go +context_phones=from-internal # context for internal phones calls. +# The two below apply to input and output ports of the Xorcom Astribank: +context_input=astbank-input +context_output=astbank-output # useless, but helps marking the channels :-) +# TODO: what about PRI/BRI? +# If set: no group changes are made in zapata-channels.conf +#group_manual=yes +group_phones=5 # group for phones +group_lines=0 # group for lines +# Set fxs_immediate to 'yes' to make all FXS lines answer immediately. +fxs_immediate=no + +ZAPCONF_FILE=${ZAPCONF_FILE:-/etc/zaptel.conf} +ZAPCONF_FILE_SYSTEM=$ZAPCONF_FILE +ZAPATA_FILE=${ZAPATA_FILE:-/etc/asterisk/zapata-channels.conf} +ZAPSCAN_FILE=${ZAPSCAN_FILE:-/etc/asterisk/zapscan.conf} +ZAPTEL_BOOT_DEBIAN=${ZAPTEL_BOOT_DEBIAN:-/etc/default/zaptel} +ZAPTEL_BOOT_FEDORA=${ZAPTEL_BOOT_FEDORA:-/etc/sysconfig/zaptel} +MODLIST_FILE=/etc/modules +MODLIST_FILE_FEDORA=/etc/sysconfig/zaptel +exten_base_dir=/etc/asterisk/extensions-phones.d +exten_defs_file=/etc/asterisk/extensions-defs.conf +# perl utilities: +xpp_sync=/usr/sbin/xpp_sync +zt_registration=/usr/sbin/zt_registration +# how long to wait for /dev/zap/ctl to appear? (seconds) +DEVZAP_TIMEOUT=${DEVZAP_TIMEOUT:-20} +ZTCFG=${ZTCFG:-/sbin/ztcfg} +# BRI/PRI spans will be in an additional per-span group whose number +# is SPAN_GROUP_BASE + span-number +SPAN_GROUP_BASE=10 +# set to "yes" to make BRI NT spans set overlapdial (handy for ISDN phones +# and other devices). +brint_overlap=no + +# a temporary directory to store whatever we need to remember. +# +# The main loop of genconf is run in a sub-process. +tmp_dir= + +# A list of all modules: +# - the list of modules which will be probed (in this order) if -d is used +# - The module that will be deleted from /etc/modules , if -d -M is used +ALL_MODULES="wct4xxp wcte12xp wcte11xp wct1xxp wanpipe tor2 torisa qozap vzaphfc zaphfc ztgsm wctdm24xxp wctdm opvxa1200 wcfxo pciradio wcusb xpp_usb" + +# The name of the variable in /etc/sysconfig/zaptel into which to set +# the list of detected modules. +modules_var=MODULES +# On SuSE with the rpm package: +#modules_var=ZAPTEL_MODULES + +# What signalling to give to ZapBRI channels? +# bri: bri_net; bri_cpe (Bristuffed Asterisk. No multi- support) +# bri_ptmpi: bri_net_ptmp; bri_cpe_ptmp (Bristuffed Asterisk, multi- support) +# pri: pri_net; pri_cpe (Recent Asterisk. Experimental) +#ZAPBRI_SIGNALLING=bri +ZAPBRI_SIGNALLING=bri_ptmp +#ZAPBRI_SIGNALLING=pri +zapconf_def_termtype=te + +# A command to stop / start asterisk. Must support parameters "start" +# and "stop" . This is the executable: +ZAPCONF_ASTERISK_SCRIPT=/etc/init.d/asterisk +# +# Should you need to pass extra arguments: +ZAPCONF_ASTERISK_CMD=$ZAPCONF_ASTERISK_SCRIPT + +# read default configuration from /etc/default/zaptel +if [ -r $ZAPTEL_BOOT_DEBIAN ]; then . $ZAPTEL_BOOT_DEBIAN; fi +if [ -r $ZAPTEL_BOOT_FEDORA ]; then . $ZAPTEL_BOOT_FEDORA; fi + +if [ ! -x "$ZTCFG" ]; then + # Work around a bug in the rpm package: ztcfg should be in + # /sbin as it may be required for starting a network interface + if [ -x /usr/sbin/ztcfg ]; then + ZTCFG=/usr/sbin/ztcfg + else + echo >&2 "ztcfg is not on found, do you have zaptel properly installed?" + exit_cleanup 1 + fi +fi + +XPP_SYNC=auto # sync mode. can be set to '0' or '1' or HOST explicitly. + +# it is safe to use -c twice: the last one will be used. +ztcfg_cmd="$ZTCFG -c $ZAPCONF_FILE" + +# work around a bug (that was already fixed) in the installer: +if [ "$lc_country" = '' ]; then lc_country=us; fi + +force_stop_ast=no +do_detect=no +do_unload=no +do_module_list=no +verbose=no +do_restart=yes +fxsdisable=no +do_gen_zapscan=no + +span_te_timing_counter=1 + +case "$ZAPBRI_SIGNALLING" in +bri) ZAPBRI_NET=bri_net; ZAPBRI_CPE=bri_cpe ;; +pri) ZAPBRI_NET=pri_net; ZAPBRI_CPE=pri_cpe ;; +bri_ptmp) ZAPBRI_NET=bri_net_ptmp; ZAPBRI_CPE=bri_cpe_ptmp ;; +*) + die "Incorrect value for ZAPBRI_SIGNALLING ($ZAPBRI_SIGNALLING). Abortring" + ;; +esac + +die() { + echo "$@" >&2 + exit_cleanup 1 +} + +say() { + if [ "$verbose" = no ]; then + return + fi + echo "$@" >&2 +} + +# exit (exit value is the optional $1), and clean up after us +exit_cleanup() { + if [ -d "$tmp_dir" ]; then + # don't fail but don't hide error if directory is not + # empty + rmdir "$tmp_dir" || : + fi + exit $1 +} + +# Wait for udev to generate /dev/zap/ctl, if needed: +wait_for_zapctl() { + # if device file already exists, or if zaptel has failed to load: + # no point waiting. + if [ -c /dev/zap/ctl ] || ! grep -q zaptel /proc/modules ; then + return + fi + say "Waiting for /dev/zap/ctl to be generated" + devzap_found=0 + for i in `seq $DEVZAP_TIMEOUT`; do + sleep 1 + if [ -c /dev/zap/ctl ]; then + devzap_found=1 + break + fi + done + if [ "$devzap_found" != 1 ]; then + say "Still no /dev/zap/ctl after $devzap_timeout seconds." + echo >&2 "No /dev/zap/ctl: cannot run ztcfg. Aborting." + fi +} + +run_ztcfg() { + # Run ztcfg itself + if [ "$verbose" = no ]; then + $ztcfg_cmd "$@" + else + say "Reconfiguring identified channels" + $ztcfg_cmd -vv "$@" + fi +} + +update_module_list_debian() { + say "Updating Debian modules list $MODLIST_FILE." + del_args=`for i in $ALL_MODULES ztdummy + do + echo "$i" | sed s:.\*:-e\ '/^&/d': + done` + add_args=`for i in $* + do + echo "$i" | sed s:.\*:-e\ '\$a&': + done` + + sed -i.bak $del_args "$MODLIST_FILE" + for i in $* + do + echo "$i" + done >> "$MODLIST_FILE" +} + +update_module_list_fedora() { + say "Updating modules list in zaptel init config $MODLIST_FILE_FEDORA." + sed -i.bak -e "/^$modules_var=/d" "$MODLIST_FILE_FEDORA" + echo "$modules_var=\"$*\"" >> "$MODLIST_FILE_FEDORA" +} + +update_module_list() { + if [ -f "$MODLIST_FILE" ]; then + update_module_list_debian "$@" + elif [ -f "$MODLIST_FILE_FEDORA" ]; then + update_module_list_fedora "$@" + else + die "Can't find a modules list to update. Tried: $MODLIST_FILE, $MODLIST_FILE_FEDORA. Aborting" + fi +} + + + +zap_reg_xpp() { + if [ ! -d /proc/xpp ]; then return; fi + + # Get a list of connected Astribank devices, sorted by the name of + # the USB connector. That order is rather arbitrary, but will not + # change without changes to the cabling. + xbusses=`sed -e '/STATUS=connected/!d' -e 's/ *STATUS=.*//' -e 's/ *CONNECTOR=//' /proc/xpp/xbuses | sort -t: -k 2 | cut -d: -f1` + say "Zaptel registration order:" + say "$xbusses" + + # get a list of XPDs that were not yet registered as zaptel spans. + # this will be the case if you set the parameter zap_autoreg=0 to + # the module xpp + # Append /dev/null to provide a valid file name in case of an empty pattern. + xbusses_pattern=`echo $xbusses| sed -e 's|XBUS-[0-9]*|/proc/xpp/&/XPD-*/zt_registration|g'`' /dev/null' + xpds_to_register=`grep -l 0 $xbusses_pattern` + for file in $xpds_to_register; do + echo 1 >$file + done +} + +# Initialize the Xorcom Astribank (xpp/) +xpp_startup() { + # do nothing if the module xpp was not loaded, or if no + # Astribanks connected: + if [ ! -d /proc/xpp ]; then return 0; fi + if ! grep -q 'STATUS=connected' /proc/xpp/xbuses; then return 0; fi + + echo "Waiting for Astribank devices to initialize:" + cat /proc/xpp/XBUS-[0-9]*/waitfor_xpds 2>/dev/null || true + + # overriding locales for the above two, as perl can be noisy + # when locales are missing. + # No register all the devices if they didn't auto-register: + LC_ALL=C $zt_registration on + + # this one could actually be run after ztcfg: + LC_ALL=C $xpp_sync "$XPP_SYNC" +} + + + +usage() { + program=`basename $0` + + echo >&2 "$program: generate zaptel.conf and zapata.conf" + echo >&2 "(version $VERSION, $rcsid)" + echo >&2 "usage:" + echo >&2 " $program [-sRdv] [-m k|l|g] [-c ] [-e ] [-F]" + echo >&2 " $program [-sRdv] -l" + echo >&2 " $program -su" + echo >&2 " $program -h (this screen)" + echo >&2 "" + echo >&2 "Options:" + echo >&2 " -c CODE: set the country code (default: $lc_country)" + echo >&2 " -e NUM: set the base extension number (default: $base_exten)" + echo >&2 " -F: Don't print FXSs in zapata.conf" + echo >&2 " -l: output a list of detected channels instead of zaptel.conf" + echo >&2 " -d: Perform hardware detection" + echo >&2 " -u: Unload zaptel modules (will not restart Asterisk)." + echo >&2 " -v: verbose" + echo >&2 " -s: Stop Asterisk before running, and start it at the end." + echo >&2 " -R: Don't restart asterisk in the end." + echo >&2 " -z: also generate zapscan.conf for the asterisk GUI." +} + +# print /etc/asterisk/zapscan.conf for the Asterisk-GUI +# $1: port type. Currently only fxs/fxo . Note that this is the type, and +# not the signalling (which would be the fxo fir an fxs port. +# $2: port number. Probably a range of ports is also allowed. +print_zapscan_port () { + if [ "$do_gen_zapscan" != 'yes' ]; then return 0; fi + + echo " +[$2] +port=$1 +" >>$zapscan_file +} + +# $1: channel number +print_pattern() { + local astbank_type='' + local reset_values="" + OPTIND=1 + while getopts 'a:' arg + do + case "$arg" in + a) case "$OPTARG" in input|output) astbank_type=$OPTARG;;esac ;; + esac + done + shift $(( $OPTIND-1 )) + + + local chan=$1 + local sig=$2 #fxs/fxo + local mode=$3 + local method + + if [ "$sig" = 'fxs' ]; then + # Coutries in which we need to use busydetect: + # United Arab Emirats, Israel, Slovenia + case "$lc_country" in + ae|il|si) + method=ls + ;; + *) + method=ks + ;; + esac + else + method="$fxs_default_start" + fi + case "$sig" in + fxs) sig_name=FXO;; + fxo) sig_name=FXS;; + esac + case "$mode" in + list) + echo $chan $sig_name $astbank_type;; + files) + # sadly, both input ports and output ports go into the same span as + # the FXS ports. Thus we need to separate between them. See also + # the zapata.conf section: + + echo ";;; line=\"$line\"" >> $zapata_file + + if [ "$astbank_type" != '' ]; + then echo "# astbanktype: $astbank_type" >>$zaptel_file; + fi + echo "${sig}$method=$chan" >>$zaptel_file + # zap2amp will rewrite those from zaptel.conf and hints there + if [ "$fxsdisable" = 'yes' ] && [ "$sig" = 'fxo' ]; then return; fi + + echo "signalling=${sig}_$method" >>$zapata_file + if [ "$sig" = 'fxo' ] + then + # to preconfigure channel 1's extension to 550, set + # chan_1_exten=550 + # in, e.g, /etc/default/zaptel + var_name=`echo chan_${chan}_exten` + cfg_exten=`echo ${!var_name} | tr -d -c 0-9` + var_name=`echo chan_${chan}_vmbox` + cfg_vmbox=`echo ${!var_name} | tr -d -c 0-9` + var_name=`echo chan_${chan}_cntxt` + cfg_cntxt=`echo ${!var_name} | tr -d -c 0-9` + + if [ "$cfg_exten" = '' ] + then # No extension number set for this channel + exten=$(($chan+$base_exten)) + else # use the pre-configured extension number + exten=$cfg_exten + fi + # is there any real need to set 'mailbox=' ? + if [ "x$cfg_vmbox" = x ] + then # No extension number set for this channel + vmbox=$exten + else # use the pre-configured extension number + vmbox=$cfg_vmbox + fi + echo "callerid=\"Channel $chan\" <$exten>" >> $zapata_file + reset_values="$reset_values callerid" + echo "mailbox=$exten" >> $zapata_file + reset_values="$reset_values mailbox" + if [ "$group_manual" != "yes" ] + then + echo "group=$group_phones" >> $zapata_file + reset_values="$reset_values group" + fi + if [ "$context_manual" != "yes" ] + then + if [ "$astbank_type" != '' ]; + then + context_var_name=context_$astbank_type + echo context=${!context_var_name} >> $zapata_file + else + echo "context=$context_phones" >> $zapata_file + fi + reset_values="$reset_values context" + fi + else # this is an FXO (trunk/phone: FXO signalling) + # we have may have set it. So reset it: + echo "callerid=asreceived" >> $zapata_file + if [ "$group_manual" != "yes" ] + then + echo "group=$group_lines" >> $zapata_file + fi + if [ "$context_manual" != "yes" ] + then + echo "context=$context_lines" >> $zapata_file + reset_values="$reset_values context" + fi + if [ "$lc_country" = 'uk' ] + then + echo "cidsignalling=v23" >> $zapata_file + case $line in + *WCFXO*) echo "cidstart=history" >> $zapata_file;; + *) echo "cidstart=polarity" >> $zapata_file;; + esac + reset_values="$reset_values cidsignalling cidstart" + fi + case "$line" in + *XPP_FXO*) + if [ "$xpp_fxo_rxgain" != '' ]; then + echo "rxgain=$xpp_fxo_rxgain" >> $zapata_file + reset_values="$reset_values rxgain" + fi + ;; + esac + # if kewlstart is not used, busydetect has to be employed: + if [ "$method" = 'ls' ] + then + echo 'busydetect=yes' >> $zapata_file + reset_values="$reset_values busydetect" + fi + fi + + if [ "$astbank_type" = 'input' ] || \ + ( [ "$fxs_immediate" = 'yes' ] && [ "$sig" = "fxo" ] ) + then + echo 'immediate=yes' >> $zapata_file + reset_values="$reset_values immediate" + fi + echo "channel => $chan" >> $zapata_file + reset_zapata_entry $zapata_file $reset_values + echo "" >> $zapata_file + + print_zapscan_port "$sig" "$chan" + ;; + esac + +} + +# the number of channels from /proc/zaptel +# must always print a number as its output. +count_proc_zap_lines() { + # if zaptel is not loaded there are 0 channels: + if [ ! -d /proc/zaptel ]; then echo '0'; return; fi + + ( + for file in `echo /proc/zaptel/* |grep -v '\*'` + do sed -e 1,2d $file # remove the two header lines + done + ) | wc -l # the total number of lines +} + +load_modules() { + say "Test Loading modules:" + for i in $ALL_MODULES + do + lines_before=`count_proc_zap_lines` + args="${i}_args" + eval "args=\$$args" + # a module is worth listing if it: + # a. loaded successfully, and + # b. added channels lines under /proc/zaptel/* + if /sbin/modprobe $i $args 2> /dev/null + then + check=0 + case "$i" in + xpp_usb) check=`grep 'STATUS=connected' 2>/dev/null /proc/xpp/xbuses | wc -l` ;; + *) if [ $lines_before -lt `count_proc_zap_lines` ]; then check=1; fi ;; + esac + if [ "$check" != 0 ] + then + probed_modules="$probed_modules $i" + say " ok $i $args" + else + say " - $i $args" + rmmod $i + fi + else + say " - $i $args" + fi + done +} + +# recursively unload a module and its dependencies, if possible. +# where's modprobe -r when you need it? +# inputs: module to unload. +# returns: the result from +unload_module() { + module="$1" + line=`lsmod 2>/dev/null | grep "^$1 "` + if [ "$line" = '' ]; then return; fi # module was not loaded + + set -- $line + # $1: the original module, $2: size, $3: refcount, $4: deps list + mods=`echo $4 | tr , ' '` + # xpp_usb keeps the xpds below busy, and hence must be removed + # before them: + case "$module" in xpd_*) mods="xpp_usb $mods";; esac + for mod in $mods; do + # run in a subshell, so it won't step over our vars: + (unload_module $mod) + # TODO: the following is probably the error handling we want: + # if [ $? != 0 ]; then return 1; fi + done + rmmod $module +} + +unload_modules() { + say "Unloading zaptel modules:" + unload_module zaptel + say '' +} + +# sleep a while until the xpp modules fully register +wait_for_xpp() { + if [ -d /proc/xpp ] + then + # wait for the XPDs to register: + # TODO: improve error reporting and produce a messagee here + cat /proc/xpp/XBUS-*/waitfor_xpds 2>/dev/null >/dev/null || true + fi +} + +detect() { + unload_modules + temporary_zapconf save + load_modules + temporary_zapconf restore + modlist="$probed_modules" + modlist="$(echo $modlist)" # clean spaces + if [ "$do_module_list" = yes ] + then + update_module_list "$modlist" + fi + if echo $modlist | grep -q xpp_usb; then wait_for_xpp; fi +} + +# The module configuration generated by zaptel includes a totally useless +# automatic run of ztcfg after modules loading. As a workaround for that, +# we provide an empty zaptel.conf temporarily. +# +# At hardware detection time we shouldn't really touch zaptel.conf . So we +# must keep a copy of it somewhere. +# +# I use ZAPCONF_FILE_SYSTEM rather than ZAPCONF_FILE, as the bogus modprobe +# entries will not be initiated by us. +# +# ZAPCONF_FILE_TMP is a "global", as it needs to be preserved between the +# call to 'save' and to 'restore' +ZAPCONF_FILE_TMP= +temporary_zapconf() { + case "$1" in + save) + say "Temporarily moving zaptel.conf aside to work around broken modprobe.conf" + ZAPCONF_FILE_TMP=`mktemp /tmp/genzaptelconf-zaptel.conf-XXXXXX` || die "Error creating temporary zaptel.conf" + if [ -f $ZAPCONF_FILE_SYSTEM ]; then + cp -a $ZAPCONF_FILE_SYSTEM $ZAPCONF_FILE_TMP + fi + echo -n >$ZAPCONF_FILE_SYSTEM + ;; + restore) + # restore original zaptel.conf: + if [ "$ZAPCONF_FILE_TMP" = '' ]; then return; fi + mv $ZAPCONF_FILE_TMP $ZAPCONF_FILE_SYSTEM + ZAPCONF_FILE_TMP='' + ;; + esac +} + +# run after the channel's entry. Used to reset all the values +reset_zapata_entry() { + conf_file="$1"; shift + + for arg in "$@"; do + case "$arg" in + busydetect) echo "$arg=no" >>$conf_file;; + context) echo "$arg=default" >>$conf_file;; + immediate) echo "$arg=no" >>$conf_file;; + overlapdial) echo "$arg=no" >>$conf_file;; + rxgain) echo "$arg=0" >>$conf_file;; + txgain) echo "$arg=0" >>$conf_file;; + *) echo "$arg=" >>$conf_file;; + esac + done +} + + +# we need to preserve the permissions of existing configurations files. +# However we also don't want to be left with incomplete configurations in +# case we are stopped in the middle. Thus we create a temporary file and +# mv it to the original file only when done. +# +# This function gives the temporary file the permissions of the original, +# or some sane defaults. +# +# The temporary file is generated here, and ths its name is passed through +# a variable whose name is passed as a parameter (new_var). +# +# $1: orig_cfg_file +# $2: new_var +gen_tmp_conf() { + orig_cfg_file=$1 + new_var=$2 + + # assign to new_var by reference: + eval $new_var=`mktemp /tmp/genzaptelconf-conf-XXXXXX` \ + || die "Unable to create temporary config file for $orig_cfg_file" + if [ -r "$orig_cfg_file" ]; then + chown --reference="$orig_cfg_file" ${!new_var} 2>/dev/null + chmod --reference="$orig_cfg_file" ${!new_var} 2>/dev/null + else + chmod 644 ${!new_var} + fi +} + +# Extract information from one digital channel (one line in a /proc/zaptel +# file). Information is saved to $tmp_dir/span_foo variables. +# FIXME: detection should move to when we know the number of channels +# and hence can tell between an E1 and a T1. +detect_digital_channel() { + line="$1" + chan_num="$2" + span_num="$3" + + # PRI/BRI channel + # Rather than identifying cards by the header line, we identify + # them by the channel names. This is shorter. + # This also allows us to count the channel numbers and check if + # we have a E1 span, a T1 span or a BRI span. + + # span_lastd is always the one before last + # channel. span_bchan is the last: + echo $chan_num >$tmp_dir/span_end + + if [ "`cat $tmp_dir/span_begin`" != "-1" ] + then + return #we already configured this span. + fi + + # Now we need to give initial configuration to the span + echo $chan_num >$tmp_dir/span_begin + echo $span_num >$tmp_dir/span_num + + case "$line" in + *ZTHFC*/* | *ztqoz*/* | *XPP_BRI_*/*) + # BRI channel + echo 'ccs' >$tmp_dir/span_framing + echo 'euroisdn' >$tmp_dir/span_switchtype + if [ "`cat $tmp_dir/span_termtype`" = 'nt' 2>/dev/null ] + then + echo $ZAPBRI_NET >$tmp_dir/span_signalling + else + echo $ZAPBRI_CPE >$tmp_dir/span_signalling + fi + ;; + *ztgsm*/*) + # Junghanns's GSM cards. + echo 'ccs' >$tmp_dir/span_framing + #Does this mean anything? + echo 'gsm' >$tmp_dir/span_signalling + ;; + *TE[24]/* | *WCT1/* | *Tor2/* | *TorISA/* | *WP[TE]1/* | \ + *R[124]T1/* | *XPP_[TEJ]1_*) + # FIXME: handle cwain around here. + # name: *cwain[12]/* . Always E1. + + # PRI span (E1/T1) + echo 'esf' >$tmp_dir/span_framing + echo 'b8zs' >$tmp_dir/span_coding + echo 'national' >$tmp_dir/span_switchtype + if [ "`cat $tmp_dir/span_termtype`" = 'nt' 2>/dev/null ] + then + echo pri_net >$tmp_dir/span_signalling + else + echo pri_cpe >$tmp_dir/span_signalling + fi + # an example of country-specific setup. This is probably not accurate + # Contributions are welcome + case "$lc_country" in + nl) + # (Just an example for per-country info) + echo 'ccs' >$tmp_dir/span_framing + echo 'ami' >$tmp_dir/span_coding + #echo 'crc4' >$tmp_dir/span_yellow + #echo 'euroisdn' >$tmp_dir/span_switchtype + #echo 'pri_cpe' >$tmp_dir/span_signalling + ;; + il|de|au) + echo 'ccs' >$tmp_dir/span_framing + echo 'hdb3' >$tmp_dir/span_coding + echo 'crc4' >$tmp_dir/span_yellow + echo 'euroisdn' >$tmp_dir/span_switchtype + ;; + cl) + echo 'ccs' >$tmp_dir/span_framing + echo 'hdb3' >$tmp_dir/span_coding + #echo 'crc4' >$tmp_dir/span_yellow + echo 'national' >$tmp_dir/span_switchtype + ;; + esac + ;; + esac +} + +# read information from the $tmp_dir/span_foo files and generate +# configuration for the span and its channels. +write_digital_config() { + # if the current file we checked was not of a digital span, we have + # nothing to do: + if [ "`cat $tmp_dir/span_begin`" = -1 ]; then return; fi + + # read files to variables: + for suffix in num begin end timing lbo framing \ + coding switchtype signalling yellow termtype + do + eval span_$suffix=`cat $tmp_dir/span_$suffix 2>/dev/null` + done + + # exactly the same logic is used in asterisk's chan_zap.c. + # also not that $(( )) is bash-specific + case "$((1+ $span_end - $span_begin))" in + 2|3|24) #ztgsm, BRI or T1 + dchan=$span_end + bchans="$span_begin-$(($span_end-1))" + ;; + 31) #E1 + dchan="$(($span_begin+15))" + bchans="$span_begin-$(($span_begin+14)),$(($span_begin+16))-$span_end" + if [ "$span_framing" = 'esf' ]; then + # don't leave an E1 span with defective defaults: + span_framing=ccs + span_coding=hdb3 + span_switchtype=euroisdn + span_yellow=crc4 + fi + ;; + esac + if [ "$span_yellow" != '' ]; then span_yellow=",$span_yellow"; fi + # Let's assume that a TE span should get the clock from the remote unit, + # and NT spans should provide timing. Just as a sane default. + # If we have several TE spans, the first will have priority 1, + # second: 2, etc. + case "$span_signalling" in *_cpe*) + span_timing=$span_te_timing_counter + span_te_timing_counter=$(($span_te_timing_counter + 1)) + ;; + esac + case "$mode" in + files) + echo span=$span_num,$span_timing,$span_lbo,$span_framing,$span_coding$span_yellow >> $zaptel_file + # leave a comment in zaptel.conf that allows to tell if + # this span is TE or NT: + if [ "$span_termtype" != '' ] + then echo "# termtype: $span_termtype" >>$zaptel_file + fi + + echo bchan=$bchans >>$zaptel_file + echo dchan=$dchan >>$zaptel_file + if [ "$fxsdisable" = 'yes' ] && [ "$span_termtype" = 'nt' ]; then return; fi + # You should not send content to zapata.conf below this line + + span_group=$(($SPAN_GROUP_BASE + $span_num)) + + if [ "$span_termtype" != '' ] + then + # an ISDN card's span that we know if it is in NT mode or TE mode. + # NT is the same as FXS for us and TE is the same as FXO + if [ "$span_termtype" = 'nt' ] + then + echo "callerid=\"Channels $span_begin - $span_end\" <$span_begin>" >> $zapata_file + reset_values="$reset_values callerid" + #echo "mailbox=$exten" + if [ "$brint_overlap" = 'yes' ] + then + echo "overlapdial=yes" >> $zapata_file + reset_values="$reset_values overlapdial" + fi + if [ "$group_manual" != "yes" ] + then + echo "group=$group_phones,$span_group" >> $zapata_file + reset_values="$reset_values group" + fi + if [ "$context_manual" != "yes" ] + then + echo "context=$context_phones" >> $zapata_file + fi + else + #echo "mailbox=" + if [ "$group_manual" != "yes" ] + then + echo "group=$group_lines,$span_group" >> $zapata_file + reset_values="$reset_values group" + fi + if [ "$context_manual" != "yes" ] + then + echo "context=$context_lines" >> $zapata_file + reset_values="$reset_values context" + fi + fi + fi + echo "switchtype = $span_switchtype" >> $zapata_file + echo "signalling = $span_signalling" >> $zapata_file + echo "channel => $bchans" >> $zapata_file + reset_zapata_entry $zapata_file $reset_values + reset_values= + ;; + list) + echo "### BRI/PRI: $span_termtype" + echo "$bchans Data" + echo "$dchan Control" + #echo BRI/PRI: chans: $bchans, control: $dchan + ;; + esac +} + +# This is where the actual detection configuration detection work happens. +genconf() { + local mode=$1 + local reset_values="" + +# spanlist=`echo /proc/zaptel/* | grep -v '\*'` +# spanlist=$(for i in `for i in /proc/zaptel/*; do if [ -f $i ]; then echo $i | cut -f 4 -d / ; fi; done | sort -n`; do echo -n "/proc/zaptel/$i "; done) +# spanlist=(cd /proc/zaptel; ls | sort -n | sed 's|^|/proc/zaptel/|') + spanlist=`ls /proc/zaptel/ 2>/dev/null | sort -n | sed 's|^|/proc/zaptel/|'` + + #if [ "$spanlist" == "" ]; then + # die "No zapata interfaces in /proc/zaptel" + #fi + + + case "$mode" in + files) + if [ "$do_gen_zapscan" = 'yes' ]; then + gen_tmp_conf "$ZAPSCAN_FILE" zapscan_file + cat <$zapscan_file +; zapscan.conf: information about detected zaptel channels +; (currently: analog only) +; +; Automatically generated by $0 -- Please do not edit. + +EOF + fi + gen_tmp_conf "$ZAPTEL_FILE" zaptel_file + gen_tmp_conf "$ZAPATA_FILE" zapata_file + cat <$zaptel_file +# Autogenerated by $0 -- do not hand edit +# Zaptel Configuration File +# +# This file is parsed by the Zaptel Configurator, ztcfg +# + +# It must be in the module loading order + +EOF + cat <$zapata_file +; Autogenerated by $0 -- do not hand edit +; Zaptel Channels Configurations (zapata.conf) +; +; This is not intended to be a complete zapata.conf. Rather, it is intended +; to be #include-d by /etc/zapata.conf that will include the global settings +; +EOF + ;; + esac + + # For each line in the spanlist: see if it represents a channel. + # if it does, test that the channel is usable. + # we do that by configuring it (using ztcfg with a 1-line config file) + # and then trying to read 1 byte from the device file. + # + # The '<(command)' syntax creates a temporary file whose content is is the + # output of 'command'. + # + # Another problem with such an approach is how to include an existing + # configuration file. For instance: how to include some default settings. + # + # Maybe an 'include' directive should be added to zaptel.conf ? + #cat $spanlist | + for procfile in $spanlist + do + span_num=`basename $procfile` + # the first line is the title line. It states the model name + # the second line is empty + title=`head -n 1 $procfile` + # stuff that needs to be remembered accross lines (for PRI/BRI support) + case "$mode" in + list) echo "### $title";; + files) + echo "" >>$zaptel_file + echo "# $title" >>$zaptel_file + echo "" >>$zapata_file + echo "; $title" >>$zapata_file + ;; + esac + echo '-1' >$tmp_dir/span_begin + echo '-1' >$tmp_dir/span_end + echo '0' >$tmp_dir/span_timing + echo '0' >$tmp_dir/span_lbo + echo '' >$tmp_dir/span_framing + echo 'ami' >$tmp_dir/span_coding + echo '' >$tmp_dir/span_switchtype + echo '' >$tmp_dir/span_signalling + if [ "$zapconf_def_termtype" != '' ] + then + echo "$zapconf_def_termtype" >$tmp_dir/span_termtype + fi + + # Check if ZapBRI cards are in TE or NT mode + if echo $title | egrep -q '((quad|octo)BRI PCI ISDN Card.* \[NT\]\ |octoBRI \[NT\] |HFC-S PCI A ISDN.* \[NT\] |Xorcom .* (BRI|T1|E1)_NT)' + then + echo 'nt' >$tmp_dir/span_termtype + elif echo $title | egrep -q '((quad|octo)BRI PCI ISDN Card.* \[TE\]\ |octoBRI \[TE\] |HFC-S PCI A ISDN.* \[TE\] |Xorcom .* (BRI|T1|E1)_TE)' + then + echo 'te' >$tmp_dir/span_termtype + fi + + # The rest of the lines are per-channel lines + sed -e 1,2d $procfile | \ + while read line + do + # in case this is a real channel. + chan_num=`echo $line |awk '{print $1}'` + case "$line" in + *WCTDM/* | *\ WRTDM/* | *OPVXA1200/*) + # TDM400P/2400P and similar cards (Sangoma A200, OpenVox A1200) + # this can be either FXS or FXO + maybe_fxs=0 + maybe_fxo=0 + $ztcfg_cmd -c <(echo fxoks=$chan_num) &>/dev/null && maybe_fxs=1 + $ztcfg_cmd -c <(echo fxsks=$chan_num) &>/dev/null && maybe_fxo=1 + if [ $maybe_fxs = 1 ] && [ $maybe_fxo = 1 ] + then + # An installed module won't accept both FXS and FXO signalling types: + # this is an empty slot. + # TODO: I believe that the Sangoma A20x will reject both and thus + # print nothing here. + echo "# channel $chan_num, WCTDM, no module." >> $zaptel_file + continue + fi + + if [ $maybe_fxs = 1 ]; then print_pattern $chan_num fxo $mode; fi + if [ $maybe_fxo = 1 ]; then print_pattern $chan_num fxs $mode; fi + ;; + *WCFXO/*) + # X100P + print_pattern $chan_num fxs $mode || \ + echo "# channel $chan_num, WCFXO, inactive." >>$zaptel_file + ;; + *WCUSB/*) + print_pattern $chan_num fxo $mode + ;; + *XPP_FXO/*) + # Astribank FXO span + print_pattern $chan_num fxs $mode + ;; + *XPP_FXS/*) + # Astribank FXS span (regular port) + print_pattern $chan_num fxo $mode + ;; + *' FXO'/*) + # FXO module (probably Rhino) + print_pattern $chan_num fxs $mode + ;; + *' FXS'/*) + # FXS module (probably Rhino) + print_pattern $chan_num fxo $mode + ;; + *' ---'/*) + # no module (probably Rhino) + continue + ;; + *XPP_OUT/*) + # Astribank FXS span (output port) + print_pattern -a output $chan_num fxo $mode + ;; + *XPP_IN/*) + # Astribank FXS span (input port) + print_pattern -a input $chan_num fxo $mode + ;; + *ZTHFC*/* | *ztqoz*/* |*ztgsm/* |*TE[24]/* | \ + *WCT1/*|*Tor2/* | *TorISA/* | \ + *XPP_BRI_*/* | *WP[TE]1/* | *R[124]T1/* | \ + *XPP_[TE]1*/* ) + detect_digital_channel "$line" "$chan_num" "$span_num" + ;; + '') ;; # Empty line (after span header) + *) + case "$mode" in + list) echo "# ??: $line";; + files) + echo "# ??: $line" >>$zaptel_file + echo "; ??: $line" >>$zapata_file + esac + ;; + esac + done + # end of part in sub-process. + + write_digital_config + done + + if [ "$mode" = 'files' ] + then + cat <> ${zaptel_file} + +# Global data + +loadzone = $loadzone +defaultzone = $defaultzone +EOF + fi + + if [ "$mode" = 'files' ]; then + mv ${ZAPCONF_FILE} ${ZAPCONF_FILE}.bak 2>/dev/null + mv $zaptel_file ${ZAPCONF_FILE} + mv ${ZAPATA_FILE} ${ZAPATA_FILE}.bak 2>/dev/nullk + mv $zapata_file ${ZAPATA_FILE} + if [ "$do_gen_zapscan" = 'yes' ]; then + mv $ZAPSCAN_FILE $ZAPSCAN_FILE.bak 2>/dev/null + mv $zapscan_file $ZAPSCAN_FILE + fi + + zapata_file_name=`basename $ZAPATA_FILE` + if ! grep -q "^#include.*$zapata_file_name" \ + /etc/asterisk/zapata.conf + then + say "Note: generated $ZAPATA_FILE not included in zapata.conf" + say "To fix: echo '#include $zapata_file_name' >>/etc/asterisk/zapata.conf" + fi + fi +} + +while getopts 'c:de:Fhlm:MRsuvz' arg +do + case "$arg" in + e) # guarantee that it is a number: + new_base_exten=`echo $OPTARG | tr -d -c 0-9` + if [ "x$new_base_exten" != x ]; then base_exten=$new_base_exten; fi + ;; + c) lc_country=`echo $OPTARG | tr -d -c a-z` ;; + d) do_detect=yes ;; + F) fxsdisable=yes;; + u) do_unload=yes ; force_stop_ast=yes ;; + v) verbose=yes ;; + l) mode='list' ;; + M) do_module_list=yes; do_detect=yes ;; + s) force_stop_ast=yes ;; + R) do_restart=no ;; + z) do_gen_zapscan=yes ;; + h) usage; exit 0;; + *) echo >&2 "unknown parameter -$arg, Aborting"; usage; exit 1;; + esac +done +shift $(( $OPTIND-1 )) +if [ $# != 0 ]; then + echo >&2 "$0: too many parameters" + usage + exit 1 +fi + +tmp_dir=`mktemp -d /tmp/genzaptelconf-dir-XXXXXX` || \ + die "$0: failed to create temporary directory. Aborting" + + +case "$lc_country" in + # the list was generated from the source of zaptel: + #grep '{.*[0-9]\+,.*"[a-z][a-z]"' zonedata.c | cut -d'"' -f 2 | xargs |tr ' ' '|' + us|au|fr|nl|uk|fi|es|jp|no|at|nz|it|gr|tw|cl|se|be|sg|il|br|hu|lt|pl|za|pt|ee|mx|in|de|ch|dk|cz|cn):;; + *) + lc_country=us + echo >&2 "unknown country-code $lc_country, defaulting to \"us\"" + ;; +esac +# any reason for loadzone and defaultzone to be different? If so, this is +# the place to make that difference +loadzone=$lc_country +defaultzone=$loadzone + +# make sure asterisk is not in our way +if [ "$force_stop_ast" = 'yes' ] +then + $ZAPCONF_ASTERISK_CMD stop 1>&2 +else + # if asterisk is running and we wanted to detect modules + # or simply to unload modules, asterisk needs to go away. + if ( [ "$do_unload" = yes ] || [ "$do_detect" = yes ] ) && \ + pidof asterisk >/dev/null + then + echo >&2 "Asterisk is already running. Configuration left untouched" + echo >&2 "You can use the option -s to shut down Asterisk for the" + echo >&2 "duration of the detection." + exit_cleanup 1 + fi +fi + +if [ "$do_unload" = yes ] +then + unload_modules + exit_cleanup $? +fi + +if [ "$do_detect" = yes ] +then + detect +fi + +if [ "$zapconf_use_perl" = yes ]; then + #redefine genconf to use perl utilities: + genconf() { + case "$1" in + list) zaptel_hardware ;; + files) zapconf ;; + esac + } +fi + +if [ "$mode" = list ]; then + genconf list +else + #zap_reg_xpp + xpp_startup + wait_for_zapctl + say "Generating '${ZAPCONF_FILE} and ${ZAPATA_FILE}'" + genconf files + run_ztcfg +fi + +if [ "$tmp_dir" != '' ] +then + rm -rf "$tmp_dir" +fi + +if [ "$force_stop_ast" != 'yes' ] || [ "$do_restart" != 'yes' ] +then + exit_cleanup 0 +fi + +if [ -x "$ZAPCONF_ASTERISK_SCRIPT" ] +then + $ZAPCONF_ASTERISK_CMD start 1>&2 +fi + +# if in verbose mode: verify that asterisk is running +if [ "$verbose" != 'no' ] + then + say "Checking channels configured in Asterisk:" + sleep 1 # give it some time. This is enough on our simple test server + if [ -x ast-cmd ] + then + ast-cmd cmd "zap show channels" + else + asterisk -rx "zap show channels" + fi +fi + +# vim:ts=8: diff --git a/kernel/xpp/utils/genzaptelconf.8 b/kernel/xpp/utils/genzaptelconf.8 new file mode 100644 index 0000000..c3f6f73 --- /dev/null +++ b/kernel/xpp/utils/genzaptelconf.8 @@ -0,0 +1,326 @@ +.TH GENZAPTELCONF 8 "July 18th, 2005" "Xorcom Rapid Asterisk" "Linux Programmer's Manual" +.SH "NAME" +.B genzaptelconf +-- generates zaptel configuration (TDM adaptors) +.SH SYNOPSIS +.PP +.B genzaptelconf +[-sRdvzF] [-c ] [-e ] + +.B genzaptelconf +[-sRdv] -l -- only list to standard output + +.B genzaptelconf +-su -- only unload zaptel modules + +.B genzaptelconf +-h -- Help screen + +.SH DESCRIPTION +.B genzaptelconf +is a script to detect zaptel devices (currently mostly TDM cards are +supported). It generates both +.I /etc/zaptel.conf +and +.I /etc/asterisk/zapata-channels.conf + +.I PRI +and +.I BRI +(with ZapBRI) cards are basically identified as well. However the span +configiration is a default that I only hope is sane. Looking for feedback + +.SH OPTIONS +.B -c +.I country_code +.RS +A two-letter country code. Sets the country-code for the zonezone +entries in +.I zaptel.conf +, The default is the value of +.I lc_country +from +.I /etc/default/zaptel +and failing that, "us". +.RE + +.B -d +.RS +Also try to detect modules. Unloads all zaptel modules and loads them +one by one. Considers a module useful if it loaded successfully and if +loading it has generated at least one zapata channel. + +The list of detected modules is written as the value of +.I ZAPTEL_MODS +in +.I /etc/default/zaptel +.RE + +.B -e +.I base_exten_num +.RS +Configure channel +.I i +as extension +.I exten_num ++ +.I i + . This is mostly for the caller-id values. Crude, but may be good enough. +See also +.I -r +.RE + +.B -F +.RS +Disable writing FXS extensions in zapata.conf +.RE + +.B -l +.RS +Only list deceted channels and their signalling. Don't write +configuration files. Note, however that +.I -ld +will still rewrite the modules line in +.I /etc/default/zaptel +(see +.I -d +above). +.RE + +.B -M +.RS +Update +.I /etc/modules +with a list of our modules, thereby +triggers their loading via modprobe on the next boot. + +This triggers the +.I -d +option as well. +.RE + +.B -R +.RS +Don't restart asterisk even if it was stopped using +.I -s + . +.RE + +.B -s +.RS +Stop asterisk for the duration of the test. The detection will only +work if nobody uses the zaptel channels: + +* To allow unloading of modules + +* to allow reading configuration files. + +This option tells the script to stop asterisk (if it was running) and to +try to start it after the end of the test. +.RE + +.B -v +.RS +Be verbose. lists the detected modules if +.I -d +is used. Lists detected channls. In the end tries to connect to asterisk +to get a list of configured zaptel channels. +.RE + +.B -z +.RS +emulate the operation of zapscan.bin: generate +.I /etc/asterisk/zapscan.conf +with the results of the scan. +.RE + +.SH CONFIGURATION +Look at the beginning of the script for a number of variables that can +be overriden through the configuraion file. Some variables can also be +overriden through the environment. The configuration file is sourced by +bash but for compatibility expected to have only 'var=VALUE' lines and +comments or empty lines. + +The configuration will first be read from +.I /etc/default/zaptel +if it exists, and +.I /etc/sysconfig/zaptel +otherwise (But those file names may be overriden, see +.I ZAPTEL_BOOT_DEBIAN +and +.I ZAPTEL_BOOT_FEDORA +below). Variables set in those files will override the default settings +and setting rom the environment. + +The following variables may be set from the environment: +ZAPCONF_FILE, ZAPATA_FILE, ZAPTEL_BOOT_DEBIAN, ZAPTEL_BOOT_FEDORA, +DEVZAP_TIMEOUT, ZTCFG + +.RS +.I lc_country +.RS +The default country. Can be also overriden by the option -c +.RE + +.I base_exten +.RS +The base number used for automatic numbering +.RE + +.I context_manual +.RS +If set to 'yes', no context changes are made in zapata-channels.conf +.RE + +.I context_lines +.RS +The context into which calls will go from zaptel trunks. +.RE + +.I context_phones +.RS +The context into which calls will go from zaptel phones. +.RE + +.I context_manual +.RS +If set to 'yes', no group settings are made in zapata-channels.conf +.RE + +.I group_lines +.RS +The group number for zaptel trunks. +.RE + +.I group_phones +.RS +The group number for zaptel phones. +.RE + +.I ALL_MODULES +.RS +modules list. Used for unloading and modules detection. The order of modules +is the same for both. +.RE + +.I ZAPCONF_FILE +.RS +ztcfg's configuration file. The sane default is /etc/zaptel.conf . +.RE + +.I ZAPATA_FILE +.RS +The generated partial zapata.conf snippet. Default: +/etc/asterisk/zapata-channels.conf . +.RE + +.I ZAPTEL_BOOT_DEBIAN +.RS +The Debian Zaptel defaults file. Normally +.I /etc/default/zaptel +. +.RE + + +.I ZAPTEL_BOOT_FEDORA +.RS +The Zaptel defaults file on various other distributions. Normally +.I /etc/sysconfig/zaptel + . +.RE + +.I DEVZAP_TIMEOUT +.RS +Maximal number of seconds to wait for /dev/zap to be initializaed by +udev. +.RE + +.I ZTCFG +.RS +The full path to the ztcfg tool. Default: +.I /sbin/ztcfg +genzaptelconf will also explicitly test for +.I /usr/sbin/ztcfg +as a last resort. +.RE +.RE + +.SH FILES +.I /etc/zaptel.conf +.RS +The configuration file used by +.I ztcfg +to configure zaptel devices. re-written by +.I genzaptelconf + . A backup copy is saved to +.I /etc/zaptel.conf.bak + . +.RE + +.I /etc/asterisk/zapata.conf +.RS +The configuration file of Asterisk's +.I chan_zap. +Not modified directly by +.I genzaptelconf. +If you want genzaptelconf's setting to take effect, add the following +line at the end of +.I zapata.conf: +.RS +#include "zapata-channels.conf" +.RE +.RE + +.I /etc/asterisk/zapata-channels.conf +.RS +This is the snippet of +.I chan_zap +configuration file that +.I genzaptelconf generates. + . A backup copy is saved to +.I /etc/asterisk/zapata-channels.conf.bak + . +.RE + +.I /etc/default/zaptel +.RS +This file holds configuration for both +.I genzaptelconf +and +.I /etc/init.d/zaptel . +It is sourced by both scripts and can thus be used to override settings +of variables from those scripts. +.RE + +.I /etc/modules +.RS +A debian-specific list of kernel modules to be loaded by modprobe at +boot time. When the option +.I -d +(detect) is used, genzaptelconf will write in this file zaptel modules +to be loaded. If you want to use a different file, set +.I MOD_FILELIST + . If it is rewritten, a backup copy is saved to +.I /etc/modules.bak + . +.RS +The backup copy of +.I /etc/modules +.RE + +.SH "SEE ALSO" +ztcfg(8) asterisk(8). + +.SH BUGS +If you override a configuration variable both through the environment +and through the configuration file, the value from the configuration +file wins. + +.SH "AUTHOR" +This manual page was written by Tzafrir Cohen +Permission is granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. + +On Debian systems, the complete text of the GNU General Public +License can be found in /usr/share/common-licenses/GPL. diff --git a/kernel/xpp/utils/hexfile.c b/kernel/xpp/utils/hexfile.c new file mode 100644 index 0000000..2a01b3f --- /dev/null +++ b/kernel/xpp/utils/hexfile.c @@ -0,0 +1,567 @@ +/* + * Written by Oron Peled + * Copyright (C) 2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include "hexfile.h" + +static const char rcsid[] = "$Id$"; + +static parse_hexfile_report_func_t report_func = NULL; + +parse_hexfile_report_func_t parse_hexfile_set_reporting(parse_hexfile_report_func_t rf) +{ + parse_hexfile_report_func_t old_rf = report_func; + report_func = rf; + return old_rf; +} + +static void chomp(char buf[]) +{ + size_t last = strlen(buf) - 1; + while(last >= 0 && isspace(buf[last])) + buf[last--] = '\0'; +} + +static int hexline_checksum(struct hexline *hexline) +{ + unsigned int i; + unsigned int chksm = 0; + int ll = hexline->d.content.header.ll; + + for(i = 0; i <= sizeof(hexline->d.content.header) + ll; i++) { + chksm += hexline->d.raw[i]; + } + return chksm & 0xFF; +} + +int dump_hexline(int recordno, struct hexline *line, FILE *fp) +{ + uint8_t ll; + uint16_t offset; + uint8_t tt; + uint8_t old_chksum; + uint8_t new_chksum; + uint8_t *data; + unsigned int i; + + ll = line->d.content.header.ll; + offset = line->d.content.header.offset; + tt = line->d.content.header.tt; + fprintf(fp, ":%02X%04X%02X", ll, offset, tt); + data = line->d.content.tt_data.data; + for(i = 0; i < ll; i++) { + fprintf(fp, "%02X", data[i]); + } + old_chksum = data[ll]; + data[ll] = 0; + new_chksum = 0xFF - hexline_checksum(line) + 1; + data[ll] = old_chksum; + fprintf(fp, "%02X\n", new_chksum); + if(new_chksum != old_chksum) { + if(report_func) + report_func(LOG_ERR, "record #%d: new_chksum(%02X) != old_chksum(%02X)\n", + recordno, new_chksum, old_chksum); + return 0; + } + return 1; +} + +struct hexline *new_hexline(uint8_t datalen, uint16_t offset, uint8_t tt) +{ + struct hexline *hexline; + size_t allocsize; + + allocsize = sizeof(struct hexline) + datalen + 1; /* checksum byte */ + if((hexline = malloc(allocsize)) == NULL) { + if(report_func) + report_func(LOG_ERR, "No more memory\n"); + return NULL; + } + memset(hexline, 0, allocsize); + hexline->d.content.header.ll = datalen; + hexline->d.content.header.offset = offset; + hexline->d.content.header.tt = tt; + return hexline; +} + +static int append_hexline(struct hexdata *hexdata, char *buf) +{ + int ret; + unsigned int ll, offset, tt; + char *p; + struct hexline *hexline; + unsigned int i; + + if(hexdata->got_eof) { + if(report_func) + report_func(LOG_ERR, "Extranous data after EOF record\n"); + return -EINVAL; + } + if(hexdata->last_line >= hexdata->maxlines) { + if(report_func) + report_func(LOG_ERR, "Hexfile too large (maxline %d)\n", hexdata->maxlines); + return -ENOMEM; + } + ret = sscanf(buf, "%02X%04X%02X", &ll, &offset, &tt); + if(ret != 3) { + if(report_func) + report_func(LOG_ERR, "Bad line header (only %d items out of 3 parsed)\n", ret); + return -EINVAL; + } + switch(tt) { + case TT_DATA: + break; + case TT_EOF: + if(ll != 0) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(EOF): Bad len = %d\n", + hexdata->last_line, tt, ll); + return -EINVAL; + } + if(offset != 0) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(EOF): Bad offset = %d\n", + hexdata->last_line, tt, offset); + return -EINVAL; + } + hexdata->got_eof = 1; + break; + case TT_EXT_SEG: + if(ll != 2) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(EXT_SEG): Bad len = %d\n", + hexdata->last_line, tt, ll); + return -EINVAL; + } + if(offset != 0) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(EXT_SEG): Bad offset = %d\n", + hexdata->last_line, tt, offset); + return -EINVAL; + } + break; + case TT_START_SEG: + if(ll != 4) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(START_SEG): Bad len = %d\n", + hexdata->last_line, tt, ll); + return -EINVAL; + } + if(offset != 0) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(START_SEG): Bad offset = %d\n", + hexdata->last_line, tt, offset); + return -EINVAL; + } + break; + case TT_EXT_LIN: + if(ll != 2) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(EXT_LIN): Bad len = %d\n", + hexdata->last_line, tt, ll); + return -EINVAL; + } + if(offset != 0) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(EXT_LIN): Bad offset = %d\n", + hexdata->last_line, tt, ll); + return -EINVAL; + } + break; + case TT_START_LIN: /* Unimplemented */ + if(ll != 4) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(EXT_LIN): Bad len = %d\n", + hexdata->last_line, tt, ll); + return -EINVAL; + } + if(offset != 0) { + if(report_func) + report_func(LOG_ERR, + "%d: Record %d(EXT_LIN): Bad offset = %d\n", + hexdata->last_line, tt, ll); + return -EINVAL; + } + break; + default: + if(report_func) + report_func(LOG_ERR, "%d: Unimplemented record type %d: %s\n", + hexdata->last_line, tt, buf); + return -EINVAL; + } + buf += 8; /* Skip header */ + if((hexline = new_hexline(ll, offset, tt)) == NULL) { + if(report_func) + report_func(LOG_ERR, "No more memory for hexfile lines\n"); + return -EINVAL; + } + p = buf; + for(i = 0; i < ll + 1; i++) { /* include checksum */ + unsigned int val; + + if((*p == '\0') || (*(p+1) == '\0')) { + if(report_func) + report_func(LOG_ERR, "Short data string '%s'\n", buf); + return -EINVAL; + } + ret = sscanf(p, "%02X", &val); + if(ret != 1) { + if(report_func) + report_func(LOG_ERR, "Bad data byte #%d\n", i); + return -EINVAL; + } + hexline->d.content.tt_data.data[i] = val; + p += 2; + } + if(hexline_checksum(hexline) != 0) { + if(report_func) { + report_func(LOG_ERR, "Bad checksum (%d instead of 0)\n", + hexline_checksum(hexline)); + dump_hexline(hexdata->last_line, hexline, stderr); + } + return -EINVAL; + } + hexdata->lines[hexdata->last_line] = hexline; + if(hexdata->got_eof) + return 0; + hexdata->last_line++; + return 1; +} + +void free_hexdata(struct hexdata *hexdata) +{ + if(hexdata) { + unsigned int i; + + for(i = 0; i < hexdata->maxlines; i++) + if(hexdata->lines[i] != NULL) + free(hexdata->lines[i]); + free(hexdata); + } +} + +int dump_hexfile(struct hexdata *hexdata, const char *outfile) +{ + FILE *fp; + unsigned int i; + + if(report_func) + report_func(LOG_INFO, "Dumping hex data into '%s'\n", outfile); + if(!outfile || strcmp(outfile, "-") == 0) + fp = stdout; + else if((fp = fopen(outfile, "w")) == NULL) { + perror(outfile); + exit(1); + } + for(i = 0; i <= hexdata->last_line; i++) { + struct hexline *line = hexdata->lines[i]; + if(!line) { + if(report_func) + report_func(LOG_ERR, "Missing line at #%d\n", i); + return -EINVAL; + } + if(!dump_hexline(i, line, fp)) + return -EINVAL; + } + return 0; +} + +int dump_hexfile2(struct hexdata *hexdata, const char *outfile, uint8_t maxwidth) +{ + FILE *fp; + uint8_t tt; + unsigned int i; + struct hexline *line; + + if(report_func) + report_func(LOG_INFO, + "Dumping hex data into '%s' (maxwidth=%d)\n", + outfile, maxwidth); + if(!outfile || strcmp(outfile, "-") == 0) + fp = stdout; + else if((fp = fopen(outfile, "w")) == NULL) { + perror(outfile); + exit(1); + } + if(maxwidth == 0) + maxwidth = UINT8_MAX; + for(i = 0; i <= hexdata->last_line; i++) { + int bytesleft = 0; + int extra_offset = 0; + int base_offset; + uint8_t *base_data; + + line = hexdata->lines[i]; + if(!line) { + if(report_func) + report_func(LOG_ERR, "Missing line at #%d\n", i); + return -EINVAL; + } + bytesleft = line->d.content.header.ll; + /* split the line into several lines */ + tt = line->d.content.header.tt; + base_offset = line->d.content.header.offset; + base_data = line->d.content.tt_data.data; + while (bytesleft > 0) { + struct hexline *extraline; + uint8_t new_chksum; + unsigned int curr_bytes = (bytesleft >= maxwidth) ? maxwidth : bytesleft; + + /* generate the new line */ + if((extraline = new_hexline(curr_bytes, base_offset + extra_offset, tt)) == NULL) { + if(report_func) + report_func(LOG_ERR, "No more memory for hexfile lines\n"); + return -EINVAL; + } + memcpy(extraline->d.content.tt_data.data, base_data + extra_offset, curr_bytes); + new_chksum = 0xFF - hexline_checksum(extraline) + 1; + extraline->d.content.tt_data.data[curr_bytes] = new_chksum; + /* print it */ + dump_hexline(i, extraline, fp); + /* cleanups */ + free(extraline); + extra_offset += curr_bytes; + bytesleft -= curr_bytes; + } + } + if(tt != TT_EOF) { + if(report_func) + report_func(LOG_ERR, "Missing EOF record\n"); + return -EINVAL; + } + dump_hexline(i, line, fp); + return 0; +} + +void process_comment(struct hexdata *hexdata, char buf[]) +{ + char *dollar_start; + char *dollar_end; + const char id_prefix[] = "Id: "; + char tmp[BUFSIZ]; + char *p; + int len; + + if(report_func) + report_func(LOG_INFO, "Comment: %s\n", buf + 1); + /* Search for RCS keywords */ + if((dollar_start = strchr(buf, '$')) == NULL) + return; + if((dollar_end = strchr(dollar_start + 1, '$')) == NULL) + return; + /* Crop the '$' signs */ + len = dollar_end - dollar_start; + len -= 2; + memcpy(tmp, dollar_start + 1, len); + tmp[len] = '\0'; + p = tmp; + if(strstr(tmp, id_prefix) == NULL) + return; + p += strlen(id_prefix); + if((p = strchr(p, ' ')) == NULL) + return; + p++; + snprintf(hexdata->version_info, BUFSIZ, "%s", p); + if((p = strchr(hexdata->version_info, ' ')) != NULL) + *p = '\0'; +} + +struct hexdata *parse_hexfile(const char *fname, unsigned int maxlines) +{ + FILE *fp; + struct hexdata *hexdata = NULL; + int datasize; + char buf[BUFSIZ]; + int line; + int dos_eof = 0; + int ret; + + assert(fname != NULL); + if(report_func) + report_func(LOG_INFO, "Parsing %s\n", fname); + datasize = sizeof(struct hexdata) + maxlines * sizeof(char *); + hexdata = (struct hexdata *)malloc(datasize); + if(!hexdata) { + if(report_func) + report_func(LOG_ERR, "Failed to allocate %d bytes for hexfile contents\n", datasize); + goto err; + } + memset(hexdata, 0, datasize); + hexdata->maxlines = maxlines; + if((fp = fopen(fname, "r")) == NULL) { + if(report_func) + report_func(LOG_ERR, "Failed to open hexfile '%s'\n", fname); + goto err; + } + for(line = 1; fgets(buf, BUFSIZ, fp); line++) { + if(dos_eof) { + if(report_func) + report_func(LOG_ERR, "%s:%d - Got DOS EOF character before true EOF\n", fname, line); + goto err; + } + if(buf[0] == 0x1A && buf[1] == '\0') { /* DOS EOF char */ + dos_eof = 1; + continue; + } + chomp(buf); + if(buf[0] == '\0') { + if(report_func) + report_func(LOG_ERR, "%s:%d - Short line\n", fname, line); + goto err; + } + if(buf[0] == '#') { + process_comment(hexdata, buf); + continue; + } + if(buf[0] != ':') { + if(report_func) + report_func(LOG_ERR, "%s:%d - Line begins with 0x%X\n", fname, line, buf[0]); + goto err; + } + if((ret = append_hexline(hexdata, buf + 1)) < 0) { + if(report_func) + report_func(LOG_ERR, "%s:%d - Failed parsing.\n", fname, line); + goto err; + } + } + fclose(fp); + if(report_func) + report_func(LOG_INFO, "%s parsed OK\n", fname); + return hexdata; +err: + free_hexdata(hexdata); + return NULL; +} + +void dump_binary(struct hexdata *hexdata, const char *outfile) +{ + FILE *fp; + unsigned int i; + size_t len; + + if(report_func) + report_func(LOG_INFO, "Dumping binary data into '%s'\n", outfile); + if((fp = fopen(outfile, "w")) == NULL) { + perror(outfile); + exit(1); + } + for(i = 0; i < hexdata->maxlines; i++) { + struct hexline *hexline = hexdata->lines[i]; + + if(!hexline) + break; + switch(hexline->d.content.header.tt) { + case TT_EOF: + if(report_func) + report_func(LOG_INFO, "\ndump: good EOF record"); + break; + case TT_DATA: + if(report_func) + report_func(LOG_INFO, "dump: %6d\r", i); + len = hexline->d.content.header.ll; + if(fwrite(hexline->d.content.tt_data.data, 1, len, fp) != len) { + perror("write"); + exit(1); + } + break; + case TT_EXT_SEG: + case TT_START_SEG: + case TT_EXT_LIN: + case TT_START_LIN: + if(report_func) + report_func(LOG_INFO, + "\ndump(%d): ignored record type %d", + i, hexline->d.content.header.tt); + break; + default: + if(report_func) + report_func(LOG_ERR, "dump: Unknown record type %d\n", + hexline->d.content.header.tt); + exit(1); + } + } + if(report_func) + report_func(LOG_INFO, "\nDump finished\n"); + fclose(fp); +} + +void gen_hexline(const uint8_t *data, uint16_t addr, size_t len, FILE *output) +{ + struct hexline *hexline; + + if(!data) { + fprintf(output, ":%02X%04X%02XFF\n", 0, 0, TT_EOF); + return; + } + if((hexline = new_hexline(len, addr, (!data) ? TT_EOF : TT_DATA)) == NULL) { + if(report_func) + report_func(LOG_ERR, "No more memory\n"); + return; + } + if(data) + memcpy(&hexline->d.content.tt_data, data, len); + dump_hexline(0, hexline, output); + free(hexline); +} + +/* + * Algorithm lifted of sum(1) implementation from coreutils. + * We chose the default algorithm (BSD style). + */ +int bsd_checksum(struct hexdata *hexdata) +{ + unsigned int i; + size_t len; + int ck = 0; + + for(i = 0; i < hexdata->maxlines; i++) { + struct hexline *hexline = hexdata->lines[i]; + unsigned char *p; + + if(!hexline) + break; + if(hexline->d.content.header.tt == TT_EOF) + continue; + len = hexline->d.content.header.ll; + p = hexline->d.content.tt_data.data; + for(; len; p++, len--) { + ck = (ck >> 1) + ((ck & 1) << 15); + ck += *p; + ck &= 0xffff; /* Keep it within bounds. */ + } + } + return ck; +} diff --git a/kernel/xpp/utils/hexfile.h b/kernel/xpp/utils/hexfile.h new file mode 100644 index 0000000..f8bf6a9 --- /dev/null +++ b/kernel/xpp/utils/hexfile.h @@ -0,0 +1,123 @@ +/* + * Written by Oron Peled + * Copyright (C) 2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef PARSE_HEXFILE_H +#define PARSE_HEXFILE_H + +#include + +/* + * Some portability workarounds + */ +#ifdef _WINDOWS + +#include /* for UCHAR USHORT */ +typedef UCHAR uint8_t; +typedef USHORT uint16_t; +#define PACKED +#define sscanf sscanf_s +#define ZERO_SIZE 1 + +/* From /usr/include/syslog.h */ +#define LOG_EMERG 0 /* system is unusable */ +#define LOG_ALERT 1 /* action must be taken immediately */ +#define LOG_CRIT 2 /* critical conditions */ +#define LOG_ERR 3 /* error conditions */ +#define LOG_WARNING 4 /* warning conditions */ +#define LOG_NOTICE 5 /* normal but significant condition */ +#define LOG_INFO 6 /* informational */ +#define LOG_DEBUG 7 /* debug-level messages */ + +#ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS } +#else +# define __BEGIN_DECLS +# define __END_DECLS +#endif + +#elif __GNUC__ + +#include +#include +#define PACKED __attribute__((packed)) +#define ZERO_SIZE 1 + +#else + +#error "Cannot compile on this platform" + +#endif + +/* Record types in hexfile */ +enum { + TT_DATA = 0, + TT_EOF = 1, + TT_EXT_SEG = 2, + TT_START_SEG = 3, + TT_EXT_LIN = 4, + TT_START_LIN = 5, + TT_NO_SUCH_TT +}; + +#pragma pack(1) +struct hexline { + union { + uint8_t raw[ZERO_SIZE]; + struct content { + struct header { + uint8_t ll; /* len */ + uint16_t offset; /* offset */ + uint8_t tt; /* type */ + } PACKED header; + struct tt_data { + uint8_t data[ZERO_SIZE]; + } tt_data; + } PACKED content; + } d; +} PACKED; +#pragma pack() + +struct hexdata { + unsigned int maxlines; + unsigned int last_line; + int got_eof; + char version_info[BUFSIZ]; + struct hexline *lines[ZERO_SIZE]; +}; + + +__BEGIN_DECLS + +typedef void (*parse_hexfile_report_func_t)(int level, const char *msg, ...); + +parse_hexfile_report_func_t parse_hexfile_set_reporting(parse_hexfile_report_func_t rf); +void free_hexdata(struct hexdata *hexdata); +struct hexdata *parse_hexfile(const char *fname, unsigned int maxlines); +int dump_hexfile(struct hexdata *hexdata, const char *outfile); +int dump_hexfile2(struct hexdata *hexdata, const char *outfile, uint8_t maxwidth); +void dump_binary(struct hexdata *hexdata, const char *outfile); +void gen_hexline(const uint8_t *data, uint16_t addr, size_t len, FILE *output); +int bsd_checksum(struct hexdata *hexdata); +__END_DECLS + +#endif diff --git a/kernel/xpp/utils/lszaptel b/kernel/xpp/utils/lszaptel new file mode 100755 index 0000000..a836d98 --- /dev/null +++ b/kernel/xpp/utils/lszaptel @@ -0,0 +1,108 @@ +#! /usr/bin/perl -w +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use File::Basename; +BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/zconf"); } + +use Zaptel; +use Zaptel::Span; +use Zaptel::Xpp; +use Zaptel::Xpp::Xbus; +use Zaptel::Xpp::Xpd; + +my @xbuses = Zaptel::Xpp::xbuses("SORT_CONNECTOR"); +my @xpds = map { $_->xpds } @xbuses; + +foreach my $span (Zaptel::spans()) { + my $spanno = $span->num; + my $xpd = $span->xpd; + my @lines; + my $index = 0; + + @lines = @{$xpd->lines} if defined $xpd; + printf "### Span %2d: %s %s\n", $span->num, $span->name, $span->description; + foreach my $chan ($span->chans()) { + my %type_map = ( + OUT => 'Output', + IN => 'Input' + ); + my ($type) = map { $type_map{$_} or $_ } $chan->type || ("unknown"); + my $batt = ""; + $batt = "(battery)" if $chan->battery; + printf "%3d %-10s %-10s %s %s\n", + $chan->num, $type, $chan->signalling, $chan->info, $batt; + $index++; + } +} + +__END__ + +=head1 NAME + +lszaptel - List all zaptel channels with their types and spans. + +=head1 SYNOPSIS + +lszaptel + +=head1 DESCRIPTION + +Example output: + + ### Span 1: WCTDM/0 "Wildcard TDM400P REV E/F Board 1" + 1 FXO FXOLS (In use) + 2 FXS FXSKS + 3 FXS FXSKS + 4 FXS FXSKS + ### Span 2: XBUS-00/XPD-00 "Xorcom XPD #00/00: FXO" + 5 FXO FXSKS (In use) + 6 FXO FXSKS (In use) (no pcm) + 7 FXO FXSKS (In use) (no pcm) + 8 FXO FXSKS (In use) (no pcm) + 9 FXO FXSKS (In use) (no pcm) + 10 FXO FXSKS (In use) (no pcm) + 11 FXO FXSKS (In use) (no pcm) + 12 FXO FXSKS (In use) (no pcm) + ### Span 3: XBUS-00/XPD-10 "Xorcom XPD #00/10: FXO" + 13 FXO FXSKS (In use) (no pcm) + 14 FXO FXSKS (In use) (no pcm) + 15 FXO FXSKS (In use) (no pcm) + 16 FXO FXSKS (In use) (no pcm) + 17 FXO FXSKS (In use) (no pcm) + 18 FXO FXSKS (In use) (no pcm) + 19 FXO FXSKS (In use) (no pcm) + 20 FXO FXSKS (In use) (no pcm) + + ... + + ### Span 6: XBUS-01/XPD-00 "Xorcom XPD #01/00: FXS" + 37 FXS FXOLS (In use) + 38 FXS FXOLS (In use) (no pcm) + 39 FXS FXOLS (In use) (no pcm) + 40 FXS FXOLS (In use) (no pcm) + 41 FXS FXOLS (In use) (no pcm) + 42 FXS FXOLS (In use) (no pcm) + 43 FXS FXOLS (In use) (no pcm) + 44 FXS FXOLS (In use) (no pcm) + 45 Output FXOLS (In use) (no pcm) + 46 Output FXOLS (In use) (no pcm) + 47 Input FXOLS (In use) (no pcm) + 48 Input FXOLS (In use) (no pcm) + 49 Input FXOLS (In use) (no pcm) + 50 Input FXOLS (In use) (no pcm) + +The first column is the type of the channel (port, for an analog device) +and the second one is the signalling (if set). + +=head1 FILES + +lszaptel is a somewhat glorified 'cat /proc/zaptel/*' . Unlike that +command, it sorts the spans with the proper order. It also formats the +output slightly differently. diff --git a/kernel/xpp/utils/print_modes.c b/kernel/xpp/utils/print_modes.c new file mode 100644 index 0000000..6312bd1 --- /dev/null +++ b/kernel/xpp/utils/print_modes.c @@ -0,0 +1,44 @@ +#include + +#include "wctdm_fxomodes.h" + +int main() { + size_t i; + + printf("case \"$mode\" in\n"); + for (i=0; i<(sizeof(fxo_modes)/sizeof(struct fxo_mode)); i++) { + if (fxo_modes[i].name == NULL) break; + int reg16=0, reg26=0, reg30=0, reg31=0x20; + char ring_osc[BUFSIZ]="", ring_x[BUFSIZ] = ""; + + reg16 |= (fxo_modes[i].ohs << 6); + reg16 |= (fxo_modes[i].rz << 1); + reg16 |= (fxo_modes[i].rt); + + reg26 |= (fxo_modes[i].dcv << 6); + reg26 |= (fxo_modes[i].mini << 4); + reg26 |= (fxo_modes[i].ilim << 1); + + reg30 = (fxo_modes[i].acim); + + reg31 |= (fxo_modes[i].ohs2 << 3); + + if (fxo_modes[i].ring_osc !=0 ) { + snprintf(ring_osc, BUFSIZ, "; ring_osc=\"%02X %02X\"", + (fxo_modes[i].ring_osc)>>8, + (fxo_modes[i].ring_osc)&&0xFF + ); + } + if (fxo_modes[i].ring_x !=0 ) { + snprintf(ring_x, BUFSIZ, "; ring_x=\"%02X %02X\"", + (fxo_modes[i].ring_x)>>8, + (fxo_modes[i].ring_x)&&0xFF + ); + } + + printf("%s)\treg16=%02X; reg26=%02X; reg30=%02X; reg31=%02X%s%s;;\n", + fxo_modes[i].name, reg16, reg26, reg30, reg31, ring_osc, ring_x); + } + printf("esac\n"); + return 0; +} diff --git a/kernel/xpp/utils/test_parse.c b/kernel/xpp/utils/test_parse.c new file mode 100644 index 0000000..8ac2023 --- /dev/null +++ b/kernel/xpp/utils/test_parse.c @@ -0,0 +1,35 @@ +#include +#include +#include "hexfile.h" + +static void default_report_func(int level, const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + vfprintf(stderr, msg, ap); + va_end(ap); +} + +int main(int argc, char *argv[]) +{ + struct hexdata *hd; + int i; + + if(argc < 2) { + fprintf(stderr, "Usage: program hexfile...\n"); + return 1; + } + parse_hexfile_set_reporting(default_report_func); + for(i = 1; i < argc; i++) { + hd = parse_hexfile(argv[i], 2000); + if(!hd) { + fprintf(stderr, "Parsing failed\n"); + return 1; + } + fprintf(stderr, "=== %s === (version: %s)\n", argv[i], hd->version_info); + dump_hexfile2(hd, "-", 60 ); + free_hexdata(hd); + } + return 0; +} diff --git a/kernel/xpp/utils/xpp.rules b/kernel/xpp/utils/xpp.rules new file mode 100644 index 0000000..794a9f0 --- /dev/null +++ b/kernel/xpp/utils/xpp.rules @@ -0,0 +1,13 @@ +BUS!="usb", ACTION!="add", GOTO="xpp_usb_add_end" +KERNEL=="*_ep*", GOTO="xpp_usb_add_end" +KERNEL=="[0-9]*", GOTO="xpp_usb_add_end" + +# Load firmware into the Xorcom Astribank device: +SYSFS{idVendor}=="e4e4", SYSFS{idProduct}=="11[345][01]", \ + RUN+="/usr/share/zaptel/xpp_fxloader udev $sysfs{idVendor}/$sysfs{idProduct}/$sysfs{bcdDevice}" + +LABEL="xpp_usb_add_end" + +# Hotplug hook for Astribank up/down +KERNEL=="xbus*" RUN+="/usr/share/zaptel/astribank_hook udev $kernel $sysfs{status} $sysfs{connector}" + diff --git a/kernel/xpp/utils/xpp_blink b/kernel/xpp/utils/xpp_blink new file mode 100755 index 0000000..8a96502 --- /dev/null +++ b/kernel/xpp/utils/xpp_blink @@ -0,0 +1,130 @@ +#! /usr/bin/perl -w +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use File::Basename; +BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/zconf"); } + +use Zaptel; +use Zaptel::Span; +use Zaptel::Xpp; +use Zaptel::Xpp::Xbus; + +sub usage { + die "Usage: $0 {on|off|bzzt} {span | xpd [] | label /dev/null 2>&1 &)& +} + +init_astribank() { + wait_for_xpp + zap_reg_xpp + fix_asterisbank_sync + run_adj_clock +} + +xpp_do_blink() { + val="$1" + shift + for xbus in $* + do + for xpd in /proc/xpp/XBUS-"$xbus"/XPD-* + do + echo "$val" > "$xpd/blink" + done + done +} + +xpp_blink() { + xbuses=`grep STATUS=connected /proc/xpp/xbuses | sed -e 's/^XBUS-//' -e 's/:.*$//'` + num=`echo $1 | tr -c -d 0-9` + case "$num" in + [0-9]*) + shift + xpp_do_blink 1 $xbuses + sleep 2 + xpp_do_blink 0 $xbuses + ;; + *) + shift + echo 1>&2 Enumerating $xbuses + xpp_do_blink 0 $xbuses + for i in $xbuses + do + echo "BLINKING: $i" + xpp_do_blink 1 "$i" + sleep 2 + xpp_do_blink 0 "$i" + done + ;; + esac +} + +# The current Debian start function. +# The function is not responsible for loading the zaptel modules: +# they will be loaded beforehand. +debian_start() { + wait_for_xpp + zap_reg_xpp + fix_asterisbank_sync + wait_for_zapctl + + if [ -r /etc/fxotune.conf ] && [ -x $FXOTUNE ]; then + $FXOTUNE -s + fi + + # configure existing modules: + $ZTCFG +} + + +# run_fxotune: destroy all FXO channels and run fxotune. +# This allows running fxotune without completly shutting down Asterisk. +# +# A simplistic assumption: every zaptel channel in the context from-pstn +# is a FXO ones. +# or rather: all tunable FXO channels are in the context from-pstn are +# not defined by zaptel. +run_fxotune() { + zap_fxo_chans=`asterisk -rx "zap show channels" | awk "/$FXO_CONTEXT/{print \$1}"` + xpp_fxo_chans=`cat /proc/zaptel/* | awk '/XPP_FXO/{print $1}'` + for chan in $xpp_fxo_chans $zap_fxo_chans; do + asterisk -rx "zap destroy channel $chan" + done + $FXOTUNE -i + asterisk -rx "zap restart" +} + + +# recursively unload a module and its dependencies, if possible. +# where's modprobe -r when you need it? +# inputs: module to unload. +unload_module() { + set +e + module="$1" + line=`lsmod 2>/dev/null | grep "^$module "` + if [ "$line" = '' ]; then return; fi # module was not loaded + + set -- $line + # $1: the original module, $2: size, $3: refcount, $4: deps list + mods=`echo $4 | tr , ' '` + # xpd_fxs actually sort of depends on xpp: + case "$module" in xpd_*) mods="xpp_usb $mods";; esac + for mod in $mods; do + # run in a subshell, so it won't step over our vars: + (unload_module $mod) + done + rmmod $module || true + set -e +} + +unload() { + unload_module zaptel +} + +# sleep a while until the xpp modules fully register +wait_for_xpp() { + if [ -d /proc/xpp ] && \ + [ "`cat /sys/module/xpp/parameters/zap_autoreg`" = 'Y' ] + then + # wait for the XPDs to register: + # TODO: improve error reporting and produce a messagee here + cat /proc/xpp/XBUS-*/waitfor_xpds 2>/dev/null >/dev/null || true + fi +} + +############################################################################# +##### +##### Hardware detection functions +##### + +load_modules() { + say "Test Loading modules:" + for i in $ALL_MODULES + do + lines_before=`count_proc_zap_lines` + args="${i}_args" + eval "args=\$$args" + # a module is worth listing if it: + # a. loaded successfully, and + # b. added channels lines under /proc/zaptel/* + if /sbin/modprobe $i $args 2> /dev/null + then + check=0 + case "$i" in + xpp_usb) check=`grep 'STATUS=connected' 2>/dev/null /proc/xpp/xbuses | wc -l` ;; + # FIXME: zttranscode will always load, and will never + # add a span. Maybe try to read from /dev/zap/transcode . + zttranscode) : ;; + *) if [ $lines_before -lt `count_proc_zap_lines` ]; then check=1; fi ;; + esac + if [ "$check" != 0 ] + then + probed_modules="$probed_modules $i" + say " ok $i $args" + else + say " - $i $args" + rmmod $i + fi + else + say " - $i $args" + fi + done +} + +update_module_list_debian() { + say "Updating Debian modules list $MODLIST_FILE_DEBIAN." + del_args=`for i in $ALL_MODULES ztdummy + do + echo "$i" | sed s:.\*:-e\ '/^&/d': + done` + add_args=`for i in $* + do + echo "$i" | sed s:.\*:-e\ '\$a&': + done` + + sed -i.bak $del_args "$MODLIST_FILE_DEBIAN" + for i in $* + do + echo "$i" + done >> "$MODLIST_FILE_DEBIAN" +} + +update_module_list_redhat() { + say "Updating modules list in zaptel init config $MODLIST_FILE_REDHAT." + sed -i.bak -e '/^MODULES=/d' "$MODLIST_FILE_REDHAT" + echo "MODULES=\"$*\"" >> "$MODLIST_FILE_REDHAT" +} + +update_module_list() { + if [ -f "$MODLIST_FILE_DEBIAN" ]; then + update_module_list_debian "$@" + elif [ -f "$MODLIST_FILE_REDHAT" ]; then + update_module_list_redhat "$@" + else + die "Can't find a modules list to update. Tried: $MODLIST_FILE_DEBIAN, $MODLIST_FILE_REDHAT. Aborting" + fi +} + + + + + + +# unless we wanted to use this as a set of functions, run +# the given function with its parameters: +if [ "$ZAPHELPER_ONLY_INCLUDE" = '' ]; then + "$@" +fi diff --git a/kernel/xpp/utils/zaptel_drivers b/kernel/xpp/utils/zaptel_drivers new file mode 100755 index 0000000..d7904c0 --- /dev/null +++ b/kernel/xpp/utils/zaptel_drivers @@ -0,0 +1,9 @@ +#! /usr/bin/perl -w +use strict; +use File::Basename; +BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/zconf"); } + +use Zaptel::Hardware; + +my $hardware = Zaptel::Hardware->scan; +print join("\n", $hardware->drivers),"\n"; diff --git a/kernel/xpp/utils/zaptel_hardware b/kernel/xpp/utils/zaptel_hardware new file mode 100755 index 0000000..004a44b --- /dev/null +++ b/kernel/xpp/utils/zaptel_hardware @@ -0,0 +1,164 @@ +#! /usr/bin/perl -w +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use File::Basename; +use Getopt::Std; +BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/zconf"); } + +use Zaptel; +use Zaptel::Span; +use Zaptel::Xpp; +use Zaptel::Xpp::Xbus; +use Zaptel::Hardware; + +sub usage { + die "Usage: $0 [-v][-x]\n"; +} + +our ($opt_v, $opt_x); +getopts('vx') || usage; +@ARGV == 0 or usage; + +my $hardware = Zaptel::Hardware->scan; +my @spans = Zaptel::spans; + +sub show_xbus($) { + my $xbus = shift or die; + my @xpds = $xbus->xpds; + my $label = '[' . $xbus->label() . ']'; + my $connector = ($xbus->status eq 'CONNECTED') ? $xbus->connector : "MISSING"; + printf " LABEL=%-20s CONNECTOR=%-20s\n", $label, $connector; + foreach my $xpd (@xpds) { + my $reg = $xpd->zt_registration; + my $span; + my $spanstr; + if($reg && @spans) { + ($span) = grep { $_->name eq $xpd->fqn } @spans; + $spanstr = ($span) ? ("Span " . $span->num) : ""; + } else { + $spanstr = "Unregistered"; + } + my $master = ''; + #$master = "XPP-SYNC" if $xpd->is_sync_master; + $master .= " ZAPTEL-SYNC" if defined($span) && $span->is_zaptel_sync_master; + printf "\t%-10s: %-8s %s %s\n", $xpd->fqn, $xpd->type, $spanstr, $master; + } +} + +my %seen; +my $format = "%-20s %-12s %4s:%4s %s\n"; + +sub show_disconnected(%) { + my %seen = @_; + + my $notified_lost = 0; + foreach my $xbus (Zaptel::Xpp::xbuses('SORT_CONNECTOR')) { + if(!$seen{$xbus->name}) { + print "----------- XPP Spans with disconnected hardware -----------\n" + unless $notified_lost++; + printf($format, $xbus->name, '', '', '', "NO HARDWARE"); + show_xbus($xbus) if $opt_v; + } + } +} + +foreach my $dev ($hardware->device_list) { + my $driver = $dev->driver || ""; + my $xbus; + my $loaded; + if($dev->is_astribank) { + $xbus = $dev->xbus; + } + $loaded = $dev->loaded; + warn "driver should be '$driver' but is actually '$loaded'\n" + if defined($loaded) && $driver ne $loaded; + $driver = "$driver" . (($loaded) ? "+" : "-"); + my $description = $dev->description || ""; + printf $format, $dev->hardware_name, $driver, $dev->vendor, $dev->product, $description; + if(!defined $xbus || !$xbus) { + next; + } + $seen{$xbus->name} = 1; + show_xbus($xbus) if $opt_v; +} + +show_disconnected(%seen) if $opt_x; + +__END__ + +=head1 NAME + +zaptel_hardware - Shows Zaptel hardware devices. + +=head1 SYNOPSIS + +zaptel_hardware [-v][-x] + +=head1 OPTIONS + +=over + +=item -v + +Verbose ouput - show spans used by each device etc. Currently only +implemented for the Xorcom Astribank. + +=item -x + +Show disconnected Astribank unit, if any. + +=back + +=head1 DESCRIPTION + +Show all zaptel hardware devices. Devices are recognized according to +lists of PCI and USB IDs in Zaptel::Hardware::PCI.pm and +Zaptel::Hardware::USB.pm . For PCI it is possible to detect by +sub-vendor and sub-product ID as well. + +The first output column is the connector: a bus specific field that +shows where this device is. + +The second field shows which driver should handle the device. a "-" sign +marks that the device is not yet handled by this driver. A "+" sign +means that the device is handled by the driver. + +For the Xorcom Astribank (and in the future: for other Zaptel devices) +some further information is provided from the driver. Those extra lines +always begin with spaces. + +Example output: + +Without drivers loaded: + + usb:001/002 xpp_usb- e4e4:1152 Astribank-multi FPGA-firmware + usb:001/003 xpp_usb- e4e4:1152 Astribank-multi FPGA-firmware + pci:0000:01:0b.0 wctdm- e159:0001 Wildcard TDM400P REV H + +With drivers loaded, without -v: + usb:001/002 xpp_usb+ e4e4:1152 Astribank-multi FPGA-firmware + usb:001/003 xpp_usb+ e4e4:1152 Astribank-multi FPGA-firmware + pci:0000:01:0b.0 wctdm+ e159:0001 Wildcard TDM400P REV E/F + +With drivers loaded, with -v: + usb:001/002 xpp_usb+ e4e4:1152 Astribank-multi FPGA-firmware + LABEL=[usb:123] CONNECTOR=usb-0000:00:1d.7-1 + XBUS-00/XPD-00: FXS Span 2 + XBUS-00/XPD-10: FXS Span 3 + XBUS-00/XPD-20: FXS Span 4 + XBUS-00/XPD-30: FXS Span 5 + usb:001/003 xpp_usb+ e4e4:1152 Astribank-multi FPGA-firmware + LABEL=[usb:4567] CONNECTOR=usb-0000:00:1d.7-4 + XBUS-01/XPD-00: FXS Span 6 XPP-SYNC + XBUS-01/XPD-10: FXO Span 7 + XBUS-01/XPD-20: FXO Span 8 + XBUS-01/XPD-30: FXO Span 9 + pci:0000:01:0b.0 wctdm+ e159:0001 Wildcard TDM400P REV E/F + diff --git a/kernel/xpp/utils/zconf/Zaptel.pm b/kernel/xpp/utils/zconf/Zaptel.pm new file mode 100644 index 0000000..a7e7d6c --- /dev/null +++ b/kernel/xpp/utils/zconf/Zaptel.pm @@ -0,0 +1,68 @@ +package Zaptel; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Zaptel::Span; + +=head1 NAME + +Zaptel - Perl interface to Zaptel information + +This package allows access from Perl to information about Zaptel +hardware and loaded Zaptel devices. + +=head1 SYNOPSIS + + # Listing channels in analog spans: + use Zaptel; + # scans system: + my @xbuses = Zaptel::spans(); + for my $span (@spans) { + next if ($span->is_digital); + $span->num. " - [". $span->type ."] ". $span->name. "\n"; + for my $chan ($span->chans) { + print " - ".$chan->num . " - [". $chan->type. "] ". $chan->fqn". \n"; + } + } +=cut + +my $proc_base = "/proc/zaptel"; + +=head1 spans() + +Returns a list of span objects, ordered by span number. + +=cut + +sub spans() { + my @spans; + + -d $proc_base or return (); + foreach my $zfile (glob "$proc_base/*") { + $zfile =~ s:$proc_base/::; + my $span = Zaptel::Span->new($zfile); + push(@spans, $span); + } + @spans = sort { $a->num <=> $b->num } @spans; + return @spans; +} + +=head1 SEE ALSO + +Span objects: L. + +Zaptel channels objects: L. + +Zaptel hardware devices information: L. + +Xorcom Astribank -specific information: L. + +=cut + +1; diff --git a/kernel/xpp/utils/zconf/Zaptel/Chans.pm b/kernel/xpp/utils/zconf/Zaptel/Chans.pm new file mode 100644 index 0000000..b02bf24 --- /dev/null +++ b/kernel/xpp/utils/zconf/Zaptel/Chans.pm @@ -0,0 +1,187 @@ +package Zaptel::Chans; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Zaptel::Utils; + +=head1 NAME + +Zaptel::Chans - Perl interface to a Zaptel channel information + +This package allows access from perl to information about a Zaptel +channel. It is part of the Zaptel Perl package. + +=head1 battery() + +Returns 1 if channel reports to have battery (A remote PBX connected to +an FXO port), 0 if channel reports to not have battery and C +otherwise. + +Currently only wcfxo and Astribank FXO modules report battery. For the +rest of the channels + +=head1 fqn() + +(Fully Qualified Name) Returns the full "name" of the channel. + +=head1 index() + +Returns the number of this channel (in the span). + +=head1 num() + +Returns the number of this channel as a Zaptel channel. + +=head signalling() + +Returns the signalling set for this channel through /etc/zaptel.conf . +This is always empty before ztcfg was run. And shows the "other" type +for FXS and for FXO. + +=head1 span() + +Returns a reference to the span to which this channel belongs. + +=head1 type() + +Returns the type of the channel: 'FXS', 'FXO', 'EMPTY', etc. + +=cut + +sub new($$$$$$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $span = shift or die "Missing a span parameter\n"; + my $index = shift; + my $line = shift or die "Missing an input line\n"; + defined $index or die "Missing an index parameter\n"; + my $self = { + 'SPAN' => $span, + 'INDEX' => $index, + }; + bless $self, $pack; + my ($num, $fqn, $rest) = split(/\s+/, $line, 3); + $num or die "Missing a channel number parameter\n"; + $fqn or die "Missing a channel fqn parameter\n"; + my $signalling = ''; + my $info = ''; + if(defined $rest) { + if($rest =~ s/^\s*(\w+)\s*//) { + $signalling = $1; + } + if($rest =~ s/(.*)//) { + $info = $1; + } + } + $self->{NUM} = $num; + $self->{FQN} = $fqn; + $self->{SIGNALLING} = $signalling; + $self->{INFO} = $info; + my $type; + if($fqn =~ m|\bXPP_(\w+)/.*$|) { + $type = $1; # An Astribank + } elsif ($fqn =~ m{\bWCFXO/.*}) { + $type = "FXO"; # wcfxo - x100p and relatives. + # A single port card. The driver issue RED alarm when + # There's no better + $self->{BATTERY} = !($span->description =~ /\bRED\b/); + } elsif ($fqn =~ m{\bFXS/.*}) { + $type = "FXS"; # likely Rhino + } elsif ($fqn =~ m{\bFXO/.*}) { + $type = "FXO"; # likely Rhino + } elsif ($fqn =~ m{\b---/.*}) { + $type = "EMPTY"; # likely Rhino, empty slot. + } elsif ($fqn =~ m{\b(TE[24]|WCT1|Tor2|TorISA|WP[TE]1|cwain[12])/.*}) { + # TE[24]: Digium wct4xxp + # WCT1: Digium single span card drivers? + # Tor2: Tor PCI cards + # TorISA: ISA ones (still used?) + # WP[TE]1: Sangoma. TODO: this one tells us if it is TE or NT. + # cwain: Junghanns E1 card. + $type = "PRI"; + } elsif ($fqn =~ m{\b(ZTHFC%d*|ztqoz\d*)/.*}) { + # ZTHFC: HFC-s single-port card (zaphfc/vzaphfc) + # ztqoz: qozap (Junghanns) multi-port HFC card + $type = "BRI"; + } elsif ($fqn =~ m{\bztgsm/.*}) { + # Junghanns GSM card + $type = "GSM"; + } elsif(defined $signalling) { + $type = 'FXS' if $signalling =~ /^FXS/; + $type = 'FXO' if $signalling =~ /^FXO/; + } else { + $type = undef; + } + $self->type($type); + $self->span()->type($type) + if ! defined($self->span()->type()) || + $self->span()->type() eq 'UNKNOWN'; + return $self; +} + +=head1 probe_type() + +In the case of some cards, the information in /proc/zaptel is not good +enough to tell the type of each channel. In this case an extra explicit +probe is needed. + +Currently this is implemented by using some invocations of ztcfg(8). + +It may later be replaced by ztscan(8). + +=cut + +my $ztcfg = $ENV{ZTCFG} || '/sbin/ztcfg'; +sub probe_type($) { + my $self = shift; + my $fqn = $self->fqn; + my $num = $self->num; + my $type; + + if($fqn =~ m:WCTDM/| WRTDM/|OPVXA1200/:) { + my %maybe; + + undef %maybe; + foreach my $sig (qw(fxo fxs)) { + my $cmd = "echo ${sig}ks=$num | $ztcfg -c /dev/fd/0"; + + $maybe{$sig} = system("$cmd >/dev/null 2>&1") == 0; + } + if($maybe{fxo} and $maybe{fxs}) { + $type = 'EMPTY'; + } elsif($maybe{fxo}) { + $type = 'FXS'; + } elsif($maybe{fxs}) { + $type = 'FXO'; + } else { + $type = 'EMPTY'; + } + } else { + $type = $self->type; + } + return $type; +} + +sub battery($) { + my $self = shift or die; + my $span = $self->span or die; + + return undef unless $self->type eq 'FXO'; + return $self->{BATTERY} if defined $self->{BATTERY}; + + my $xpd = $span->xpd; + my $index = $self->index; + return undef if !$xpd; + + # It's an XPD (FXO) + my @lines = @{$xpd->lines}; + my $line = $lines[$index]; + return $line->battery; +} + +1; diff --git a/kernel/xpp/utils/zconf/Zaptel/Config/Defaults.pm b/kernel/xpp/utils/zconf/Zaptel/Config/Defaults.pm new file mode 100644 index 0000000..1d11403 --- /dev/null +++ b/kernel/xpp/utils/zconf/Zaptel/Config/Defaults.pm @@ -0,0 +1,54 @@ +package Zaptel::Config::Defaults; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; + +# Use the shell to source a file and expand a given list +# of variables. +sub do_source($@) { + my $file = shift; + my @vars = @_; + my @output = `env -i sh -ec '. $file; export @vars; for i in @vars; do eval echo \$i=\\\$\$i; done'`; + die "$0: Sourcing '$file' exited with $?" if $?; + my %vars; + + foreach my $line (@output) { + chomp $line; + my ($k, $v) = split(/=/, $line, 2); + $vars{$k} = $v if grep /^$k$/, @vars; + } + return %vars; +} + +sub source_vars { + my @vars = @_; + my $default_file; + my %system_files = ( + "/etc/default/zaptel" => 'Debian and friends', + "/etc/sysconfig/zaptel" => 'Red Hat and friends', + ); + + if(defined $ENV{ZAPTEL_DEFAULTS}) { + $default_file = $ENV{ZAPTEL_DEFAULTS}; + } else { + foreach my $f (keys %system_files) { + if(-r $f) { + if(defined $default_file) { + die "An '$f' collides with '$default_file'"; + } + $default_file = $f; + } + } + } + die "No default_file" unless $default_file; + my %vars = Zaptel::Config::Defaults::do_source($default_file, @vars); + return ($default_file, %vars); +} + +1; diff --git a/kernel/xpp/utils/zconf/Zaptel/Hardware.pm b/kernel/xpp/utils/zconf/Zaptel/Hardware.pm new file mode 100644 index 0000000..5af22f7 --- /dev/null +++ b/kernel/xpp/utils/zconf/Zaptel/Hardware.pm @@ -0,0 +1,60 @@ +package Zaptel::Hardware; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Zaptel::Hardware::USB; +use Zaptel::Hardware::PCI; + +sub device_detected($$) { + my $dev = shift || die; + my $name = shift || die; + die unless defined $dev->{'BUS_TYPE'}; + $dev->{IS_ASTRIBANK} = 0 unless defined $dev->{'IS_ASTRIBANK'}; + $dev->{'HARDWARE_NAME'} = $name; +} + +sub device_removed($) { + my $dev = shift || die; + my $name = $dev->hardware_name; + die "Missing zaptel device hardware name" unless $name; +} + +sub device_list($) { + my $self = shift || die; + my @types = @_; + my @list; + + @types = qw(USB PCI) unless @types; + foreach my $t (@types) { + @list = ( @list, @{$self->{$t}} ); + } + return @list; +} + +sub drivers($) { + my $self = shift || die; + my @devs = $self->device_list; + my @drvs = map { $_->{DRIVER} } @devs; + # Make unique + my %drivers; + @drivers{@drvs} = 1; + return sort keys %drivers; +} + +sub scan($) { + my $pack = shift || die; + my $self = {}; + bless $self, $pack; + + $self->{USB} = [ Zaptel::Hardware::USB->devices ]; + $self->{PCI} = [ Zaptel::Hardware::PCI->scan_devices ]; + return $self; +} + +1; diff --git a/kernel/xpp/utils/zconf/Zaptel/Hardware/PCI.pm b/kernel/xpp/utils/zconf/Zaptel/Hardware/PCI.pm new file mode 100644 index 0000000..45173d4 --- /dev/null +++ b/kernel/xpp/utils/zconf/Zaptel/Hardware/PCI.pm @@ -0,0 +1,204 @@ +package Zaptel::Hardware::PCI; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Zaptel::Utils; +use Zaptel::Hardware; + +our @ISA = qw(Zaptel::Hardware); + +# Lookup algorithm: +# First match 'vendor:product/subvendor:subproduct' key +# Else match 'vendor:product/subvendor' key +# Else match 'vendor:product' key +# Else not a zaptel hardware. +my %pci_ids = ( + # from wct4xxp + '10ee:0314' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE410P/TE405P (1st Gen)' }, + 'd161:0420/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE420 (4th Gen)' }, + 'd161:0410/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE410P (4th Gen)' }, + 'd161:0405/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE405P (4th Gen)' }, + 'd161:0410/0003' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE410P (3rd Gen)' }, + 'd161:0405/0003' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE405P (3rd Gen)' }, + 'd161:0410' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE410P (2nd Gen)' }, + 'd161:0405' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE405P (2nd Gen)' }, + 'd161:0220/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE220 (4th Gen)' }, + 'd161:0205/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE205P (4th Gen)' }, + 'd161:0210/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE210P (4th Gen)' }, + 'd161:0205/0003' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE205P (3rd Gen)' }, + 'd161:0210/0003' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE210P (3rd Gen)' }, + 'd161:0205' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE205P ' }, + 'd161:0210' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE210P ' }, + + # from wctdm24xxp + 'd161:2400' => { DRIVER => 'wctdm24xxp', DESCRIPTION => 'Wildcard TDM2400P' }, + 'd161:0800' => { DRIVER => 'wctdm24xxp', DESCRIPTION => 'Wildcard TDM800P' }, + 'd161:8002' => { DRIVER => 'wctdm24xxp', DESCRIPTION => 'Wildcard AEX800' }, + 'd161:8003' => { DRIVER => 'wctdm24xxp', DESCRIPTION => 'Wildcard AEX2400' }, + + # from pciradio + 'e159:0001/e16b' => { DRIVER => 'pciradio', DESCRIPTION => 'PCIRADIO' }, + + # from wcfxo + 'e159:0001/8084' => { DRIVER => 'wcfxo', DESCRIPTION => 'Wildcard X101P clone' }, + 'e159:0001/8085' => { DRIVER => 'wcfxo', DESCRIPTION => 'Wildcard X101P' }, + 'e159:0001/8086' => { DRIVER => 'wcfxo', DESCRIPTION => 'Wildcard X101P clone' }, + 'e159:0001/8087' => { DRIVER => 'wcfxo', DESCRIPTION => 'Wildcard X101P clone' }, + '1057:5608' => { DRIVER => 'wcfxo', DESCRIPTION => 'Wildcard X100P' }, + + # from wct1xxp + 'e159:0001/6159' => { DRIVER => 'wct1xxp', DESCRIPTION => 'Digium Wildcard T100P T1/PRI or E100P E1/PRA Board' }, + + # from wctdm + 'e159:0001/a159' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard S400P Prototype' }, + 'e159:0001/e159' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard S400P Prototype' }, + 'e159:0001/b100' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV E/F' }, + 'e159:0001/b1d9' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV I' }, + 'e159:0001/b118' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV I' }, + 'e159:0001/b119' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV I' }, + 'e159:0001/a9fd' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, + 'e159:0001/a8fd' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, + 'e159:0001/a800' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, + 'e159:0001/a801' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, + 'e159:0001/a908' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, + 'e159:0001/a901' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, + #'e159:0001' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, + + # from wcte11xp + 'e159:0001/71fe' => { DRIVER => 'wcte11xp', DESCRIPTION => 'Digium Wildcard TE110P T1/E1 Board' }, + 'e159:0001/79fe' => { DRIVER => 'wcte11xp', DESCRIPTION => 'Digium Wildcard TE110P T1/E1 Board' }, + 'e159:0001/795e' => { DRIVER => 'wcte11xp', DESCRIPTION => 'Digium Wildcard TE110P T1/E1 Board' }, + 'e159:0001/79de' => { DRIVER => 'wcte11xp', DESCRIPTION => 'Digium Wildcard TE110P T1/E1 Board' }, + 'e159:0001/797e' => { DRIVER => 'wcte11xp', DESCRIPTION => 'Digium Wildcard TE110P T1/E1 Board' }, + + # from wcte12xp + 'd161:0120' => { DRIVER => 'wcte12xp', DESCRIPTION => 'Wildcard TE12xP' }, + + # from tor2 + '10b5:9030' => { DRIVER => 'tor2', DESCRIPTION => 'PLX 9030' }, + '10b5:3001' => { DRIVER => 'tor2', DESCRIPTION => 'PLX Development Board' }, + '10b5:D00D' => { DRIVER => 'tor2', DESCRIPTION => 'Tormenta 2 Quad T1/PRI or E1/PRA' }, + '10b5:4000' => { DRIVER => 'tor2', DESCRIPTION => 'Tormenta 2 Quad T1/E1 (non-Digium clone)' }, + + # Cologne Chips: + # (Still a partial list) + '1397:08b4/b556' => { DRIVER => 'qozap', DESCRIPTION => 'Junghanns DuoBRI ISDN card' }, + '1397:08b4' => { DRIVER => 'qozap', DESCRIPTION => 'Junghanns QuadBRI ISDN card' }, + '1397:16b8' => { DRIVER => 'qozap', DESCRIPTION => 'Junghanns OctoBRI ISDN card' }, + '1397:30b1' => { DRIVER => 'cwain', DESCRIPTION => 'HFC-E1 ISDN E1 card' }, + '1397:2bd0' => { DRIVER => 'zaphfc', DESCRIPTION => 'HFC-S ISDN BRI card' }, + '1397:f001' => { DRIVER => 'ztgsm', DESCRIPTION => 'HFC-GSM Cologne Chips GSM' }, + + # Rhino cards (based on pci.ids) + '0b0b:0105' => { DRIVER => 'r1t1', DESCRIPTION => 'Rhino R1T1' }, + '0b0b:0205' => { DRIVER => 'r4fxo', DESCRIPTION => 'Rhino R14FXO' }, + '0b0b:0206' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB4FXO 4-channel FXO analog telphony card' }, + '0b0b:0305' => { DRIVER => 'r1t1', DESCRIPTION => 'Rhino R1T1' }, + '0b0b:0405' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino R8FXX' }, + '0b0b:0406' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB8FXX 8-channel modular analog telphony card' }, + '0b0b:0505' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino R24FXX' }, + '0b0b:0506' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB24FXS 24-Channel FXS analog telphony card' }, + '0b0b:0605' => { DRIVER => 'rxt1', DESCRIPTION => 'Rhino R2T1' }, + '0b0b:0705' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino R24FXS' }, + '0b0b:0706' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB24FXO 24-Channel FXO analog telphony card' }, + '0b0b:0906' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB24FXX 24-channel modular analog telphony card' }, + + # Sangoma cards (based on pci.ids) + '1923:0040' => { DRIVER => 'wanpipe', DESCRIPTION => 'Sangoma Technologies Corp. A200/Remora FXO/FXS Analog AFT card' }, + '1923:0100' => { DRIVER => 'wanpipe', DESCRIPTION => 'Sangoma Technologies Corp. A104d QUAD T1/E1 AFT card' }, + '1923:0300' => { DRIVER => 'wanpipe', DESCRIPTION => 'Sangoma Technologies Corp. A101 single-port T1/E1' }, + '1923:0400' => { DRIVER => 'wanpipe', DESCRIPTION => 'Sangoma Technologies Corp. A104u Quad T1/E1 AFT' }, + ); + +$ENV{PATH} .= ":/usr/sbin:/sbin:/usr/bin:/bin"; + +sub pci_sorter { + return $a->priv_device_name() cmp $b->priv_device_name(); +} + +sub new($$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $self = { @_ }; + bless $self, $pack; + Zaptel::Hardware::device_detected($self, + sprintf("pci:%s", $self->{PRIV_DEVICE_NAME})); + return $self; +} + +my %pci_devs; + +sub readfile($) { + my $name = shift || die; + open(F, $name) || die "Failed to open '$name': $!"; + my $str = ; + close F; + chomp($str); + return $str; +} + +sub scan_devices($) { + my @devices; + + while() { + m,([^/]+)$,,; + my $name = $1; + my $l = readlink $_ || die; + $pci_devs{$name}{PRIV_DEVICE_NAME} = $name; + $pci_devs{$name}{DEVICE} = $l; + $pci_devs{$name}{VENDOR} = readfile "$_/vendor"; + $pci_devs{$name}{PRODUCT} = readfile "$_/device"; + $pci_devs{$name}{SUBVENDOR} = readfile "$_/subsystem_vendor"; + $pci_devs{$name}{SUBPRODUCT} = readfile "$_/subsystem_device"; + my $dev = $pci_devs{$name}; + grep(s/0x//, $dev->{VENDOR}, $dev->{PRODUCT}, $dev->{SUBVENDOR}, $dev->{SUBPRODUCT}); + $pci_devs{$name}{DRIVER} = ''; + } + + while() { + m,^(.*?)/([^/]+)/([^/]+)$,; + my $prefix = $1; + my $drvname = $2; + my $id = $3; + my $l = readlink "$prefix/$drvname/module"; + # Find the real module name (if we can). + if(defined $l) { + my $moduledir = "$prefix/$drvname/$l"; + my $modname = $moduledir; + $modname =~ s:^.*/::; + $drvname = $modname; + } + $pci_devs{$id}{LOADED} = $drvname; + } + foreach (sort keys %pci_devs) { + my $dev = $pci_devs{$_}; + my $key; + # Try to match + $key = "$dev->{VENDOR}:$dev->{PRODUCT}/$dev->{SUBVENDOR}:$dev->{SUBPRODUCT}"; + $key = "$dev->{VENDOR}:$dev->{PRODUCT}/$dev->{SUBVENDOR}" if !defined($pci_ids{$key}); + $key = "$dev->{VENDOR}:$dev->{PRODUCT}" if !defined($pci_ids{$key}); + next unless defined $pci_ids{$key}; + + my $d = Zaptel::Hardware::PCI->new( + BUS_TYPE => 'PCI', + PRIV_DEVICE_NAME => $dev->{PRIV_DEVICE_NAME}, + VENDOR => $dev->{VENDOR}, + PRODUCT => $dev->{PRODUCT}, + SUBVENDOR => $dev->{SUBVENDOR}, + SUBPRODUCT => $dev->{SUBPRODUCT}, + LOADED => $dev->{LOADED}, + DRIVER => $pci_ids{$key}{DRIVER}, + DESCRIPTION => $pci_ids{$key}{DESCRIPTION}, + ); + push(@devices, $d); + } + @devices = sort pci_sorter @devices; + return @devices; +} + +1; diff --git a/kernel/xpp/utils/zconf/Zaptel/Hardware/USB.pm b/kernel/xpp/utils/zconf/Zaptel/Hardware/USB.pm new file mode 100644 index 0000000..a2dc08f --- /dev/null +++ b/kernel/xpp/utils/zconf/Zaptel/Hardware/USB.pm @@ -0,0 +1,116 @@ +package Zaptel::Hardware::USB; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Zaptel::Utils; +use Zaptel::Hardware; +use Zaptel::Xpp; +use Zaptel::Xpp::Xbus; + +our @ISA = qw(Zaptel::Hardware); + +my %usb_ids = ( + # from wcusb + '06e6:831c' => { DRIVER => 'wcusb', DESCRIPTION => 'Wildcard S100U USB FXS Interface' }, + '06e6:831e' => { DRIVER => 'wcusb2', DESCRIPTION => 'Wildcard S110U USB FXS Interface' }, + '06e6:b210' => { DRIVER => 'wc_usb_phone', DESCRIPTION => 'Wildcard Phone Test driver' }, + + # from xpp_usb + 'e4e4:1130' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-8/16 no-firmware' }, + 'e4e4:1131' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-8/16 USB-firmware' }, + 'e4e4:1132' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-8/16 FPGA-firmware' }, + 'e4e4:1140' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-BRI no-firmware' }, + 'e4e4:1141' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-BRI USB-firmware' }, + 'e4e4:1142' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-BRI FPGA-firmware' }, + 'e4e4:1150' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-multi no-firmware' }, + 'e4e4:1151' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-multi USB-firmware' }, + 'e4e4:1152' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-multi FPGA-firmware' }, + 'e4e4:1160' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-modular no-firmware' }, + 'e4e4:1161' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-modular USB-firmware' }, + 'e4e4:1162' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-modular FPGA-firmware' }, + ); + + +$ENV{PATH} .= ":/usr/sbin:/sbin:/usr/bin:/bin"; + +my @xbuses = Zaptel::Xpp::xbuses('SORT_CONNECTOR'); + +sub usb_sorter() { + return $a->hardware_name cmp $b->hardware_name; +} + +sub xbus_of_usb($) { + my $priv_device_name = shift; + my $dev = shift; + + my ($wanted) = grep { + defined($_->usb_devname) && + $priv_device_name eq $_->usb_devname + } @xbuses; + return $wanted; +} + +sub new($$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $self = { @_ }; + bless $self, $pack; + my $xbus = xbus_of_usb($self->priv_device_name); + if(defined $xbus) { + $self->{XBUS} = $xbus; + $self->{LOADED} = 'xpp_usb'; + } else { + $self->{XBUS} = undef; + $self->{LOADED} = undef; + } + Zaptel::Hardware::device_detected($self, + sprintf("usb:%s", $self->{PRIV_DEVICE_NAME})); + return $self; +} + +sub devices($) { + my $pack = shift || die; + my $usb_device_list = "/proc/bus/usb/devices"; + return unless (-r $usb_device_list); + + my @devices; + open(F, $usb_device_list) || die "Failed to open $usb_device_list: $!"; + local $/ = ''; + while() { + my @lines = split(/\n/); + my ($tline) = grep(/^T/, @lines); + my ($pline) = grep(/^P/, @lines); + my ($sline) = grep(/^S:.*SerialNumber=/, @lines); + my ($busnum,$devnum) = ($tline =~ /Bus=(\w+)\W.*Dev#=\s*(\w+)\W/); + my $devname = sprintf("%03d/%03d", $busnum, $devnum); + my ($vendor,$product) = ($pline =~ /Vendor=(\w+)\W.*ProdID=(\w+)\W/); + my $serial; + if(defined $sline) { + $sline =~ /SerialNumber=(.*)/; + $serial = $1; + #$serial =~ s/[[:^print:]]/_/g; + } + my $model = $usb_ids{"$vendor:$product"}; + next unless defined $model; + my $d = Zaptel::Hardware::USB->new( + IS_ASTRIBANK => ($model->{DRIVER} eq 'xpp_usb')?1:0, + BUS_TYPE => 'USB', + PRIV_DEVICE_NAME => $devname, + VENDOR => $vendor, + PRODUCT => $product, + SERIAL => $serial, + DESCRIPTION => $model->{DESCRIPTION}, + DRIVER => $model->{DRIVER}, + ); + push(@devices, $d); + } + close F; + @devices = sort usb_sorter @devices; +} + +1; diff --git a/kernel/xpp/utils/zconf/Zaptel/Span.pm b/kernel/xpp/utils/zconf/Zaptel/Span.pm new file mode 100644 index 0000000..380dc7f --- /dev/null +++ b/kernel/xpp/utils/zconf/Zaptel/Span.pm @@ -0,0 +1,160 @@ +package Zaptel::Span; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Zaptel::Utils; +use Zaptel::Chans; +use Zaptel::Xpp::Xpd; + +my $proc_base = "/proc/zaptel"; + +sub chans($) { + my $span = shift; + return @{$span->{CHANS}}; +} + +sub by_number($) { + my $span_number = shift; + die "Missing span number" unless defined $span_number; + my @spans = Zaptel::spans(); + + my ($span) = grep { $_->num == $span_number } @spans; + return $span; +} + +my @bri_strings = ( + 'BRI_(NT|TE)', + '(?:quad|octo)BRI PCI ISDN Card.* \[(NT|TE)\]\ ', + 'octoBRI \[(NT|TE)\] ', + 'HFC-S PCI A ISDN.* \[(NT|TE)\] ' + ); + +my @pri_strings = ( + '(E1|T1|J1)_(NT|TE)' + ); + +our $ZAPBRI_NET = 'bri_net'; +our $ZAPBRI_CPE = 'bri_cpe'; + +our $ZAPPRI_NET = 'pri_net'; +our $ZAPPRI_CPE = 'pri_cpe'; + +sub new($$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $num = shift or die "Missing a span number parameter\n"; + my $self = { NUM => $num }; + bless $self, $pack; + $self->{TYPE} = "UNKNOWN"; + my @xpds = Zaptel::Xpp::Xpd::xpds_by_spanno; + my $xpd = $xpds[$num]; + if(defined $xpd) { + die "Spanno mismatch: $xpd->spanno, $num" unless $xpd->spanno == $num; + $self->{XPD} = $xpd; + } + open(F, "$proc_base/$num") or die "Failed to open '$proc_base/$num\n"; + my $head = ; + chomp $head; + $self->{IS_DIGITAL} = 0; + $self->{IS_BRI} = 0; + $self->{IS_PRI} = 0; + foreach my $cardtype (@bri_strings) { + if($head =~ m/$cardtype/) { + $self->{IS_DIGITAL} = 1; + $self->{IS_BRI} = 1; + $self->{TERMTYPE} = $1; + $self->{TYPE} = "BRI_$1"; + $self->{DCHAN_IDX} = 2; + $self->{BCHAN_LIST} = [ 0, 1 ]; + last; + } + } + foreach my $cardtype (@pri_strings) { + if($head =~ m/$cardtype/) { + $self->{IS_DIGITAL} = 1; + $self->{IS_PRI} = 1; + $self->{PROTO} = "$1"; + $self->{TERMTYPE} = $2; + $self->{TYPE} = "$1_$2"; + if($self->{PROTO} eq 'E1') { + $self->{DCHAN_IDX} = 15; + $self->{BCHAN_LIST} = [ 0 .. 14, 16 .. 30 ]; + } elsif($self->{PROTO} eq 'T1') { + $self->{DCHAN_IDX} = 23; + $self->{BCHAN_LIST} = [ 0 .. 22 ]; + } else { + die "'$self->{PROTO}' unsupported yet"; + } + last; + } + } + die "$0: Unkown TERMTYPE [NT/TE]\n" + if $self->is_digital and !defined $self->{TERMTYPE}; + ($self->{NAME}, $self->{DESCRIPTION}) = (split(/\s+/, $head, 4))[2, 3]; + $self->{IS_ZAPTEL_SYNC_MASTER} = + ($self->{DESCRIPTION} =~ /\(MASTER\)/) ? 1 : 0; + $self->{CHANS} = []; + my @channels; + my $index = 0; + while() { + chomp; + s/^\s*//; + s/\s*$//; + next unless /\S/; + my $c = Zaptel::Chans->new($self, $index, $_); + push(@channels, $c); + $index++; + } + close F; + @channels = sort { $a->num <=> $b->num } @channels; + $self->{CHANS} = \@channels; + $self->{YELLOW} = undef; + $self->{CRC4} = undef; + if($self->is_bri()) { + $self->{CODING} = 'ami'; + $self->{DCHAN} = ($self->chans())[$self->{DCHAN_IDX}]; + $self->{BCHANS} = [ ($self->chans())[@{$self->{BCHAN_LIST}}] ]; + # Infer some info from channel name: + my $first_chan = ($self->chans())[0] || die "$0: No channels in span #$num\n"; + my $chan_fqn = $first_chan->fqn(); + if($chan_fqn =~ m(ZTHFC.*/|ztqoz.*/|XPP_BRI_.*/)) { # BRI + $self->{FRAMING} = 'ccs'; + $self->{SWITCHTYPE} = 'euroisdn'; + $self->{SIGNALLING} = ($self->{TERMTYPE} eq 'NT') ? $ZAPBRI_NET : $ZAPBRI_CPE ; + } elsif($chan_fqn =~ m(ztgsm.*/)) { # Junghanns's GSM cards. + $self->{FRAMING} = 'ccs'; + $self->{SIGNALLING} = 'gsm'; + } + } + if($self->is_pri()) { + $self->{DCHAN} = ($self->chans())[$self->{DCHAN_IDX}]; + $self->{BCHANS} = [ ($self->chans())[@{$self->{BCHAN_LIST}}] ]; + if($self->{PROTO} eq 'E1') { + $self->{CODING} = 'hdb3'; + $self->{FRAMING} = 'ccs'; + $self->{SWITCHTYPE} = 'euroisdn'; + $self->{CRC4} = 'crc4'; + } elsif($self->{PROTO} eq 'T1') { + $self->{CODING} = 'b8zs'; + $self->{FRAMING} = 'esf'; + $self->{SWITCHTYPE} = 'national'; + } else { + die "'$self->{PROTO}' unsupported yet"; + } + $self->{SIGNALLING} = ($self->{TERMTYPE} eq 'NT') ? $ZAPPRI_NET : $ZAPPRI_CPE ; + } + return $self; +} + +sub bchans($) { + my $self = shift || die; + + return @{$self->{BCHANS}}; +} + +1; diff --git a/kernel/xpp/utils/zconf/Zaptel/Utils.pm b/kernel/xpp/utils/zconf/Zaptel/Utils.pm new file mode 100644 index 0000000..8d13ad7 --- /dev/null +++ b/kernel/xpp/utils/zconf/Zaptel/Utils.pm @@ -0,0 +1,52 @@ +package Zaptel::Utils; + +# Accessors (miniperl does not have Class:Accessor) +our $AUTOLOAD; +sub AUTOLOAD { + my $self = shift; + my $name = $AUTOLOAD; + $name =~ s/.*://; # strip fully-qualified portion + return if $name =~ /^[A-Z_]+$/; # ignore special methods (DESTROY) + my $key = uc($name); + my $val = shift; + if (defined $val) { + #print STDERR "set: $key = $val\n"; + return $self->{$key} = $val; + } else { + if(!exists $self->{$key}) { + #$self->xpp_dump; + #die "Trying to get uninitialized '$key'"; + } + my $val = $self->{$key}; + #print STDERR "get: $key ($val)\n"; + return $val; + } +} + +sub xpp_dump($) { + my $self = shift || die; + printf STDERR "Dump a %s\n", ref($self); + foreach my $k (sort keys %{$self}) { + my $val = $self->{$k}; + $val = '**UNDEF**' if !defined $val; + printf STDERR " %-20s %s\n", $k, $val; + } +} + +# Based on Autoloader + +sub import { + my $pkg = shift; + my $callpkg = caller; + + #print STDERR "import: $pkg, $callpkg\n"; + # + # Export symbols, but not by accident of inheritance. + # + die "Sombody inherited Zaptel::Utils" if $pkg ne 'Zaptel::Utils'; + no strict 'refs'; + *{ $callpkg . '::AUTOLOAD' } = \&AUTOLOAD; + *{ $callpkg . '::xpp_dump' } = \&xpp_dump; +} + +1; diff --git a/kernel/xpp/utils/zconf/Zaptel/Xpp.pm b/kernel/xpp/utils/zconf/Zaptel/Xpp.pm new file mode 100644 index 0000000..8a2a6eb --- /dev/null +++ b/kernel/xpp/utils/zconf/Zaptel/Xpp.pm @@ -0,0 +1,183 @@ +package Zaptel::Xpp; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Zaptel::Xpp::Xbus; + +=head1 NAME + +Zaptel::Xpp - Perl interface to the Xorcom Astribank drivers. + +=head1 SYNOPSIS + + # Listing all Astribanks: + use Zaptel::Xpp; + # scans hardware: + my @xbuses = Zaptel::Xpp::xbuses("SORT_CONNECTOR"); + for my $xbus (@xbuses) { + print $xbus->name." (".$xbus->label .", ". $xbus->connector .")\n"; + for my $xpd ($xbus->xpds) { + print " - ".$xpd->fqn,"\n"; + } + } +=cut + + +my $proc_base = "/proc/xpp"; + +# Nominal sorters for xbuses +sub by_name { + return $a->name cmp $b->name; +} + +sub by_connector { + return $a->connector cmp $b->connector; +} + +sub by_label { + my $cmp = $a->label cmp $b->label; + return $cmp if $cmp != 0; + return $a->connector cmp $b->connector; +} + +=head1 xbuses([sort_order]) + +Scans system (/proc and /sys) and returns a list of Astribank (Xbus) +objects. The optional parameter sort_order is the order in which +the Astribanks will be returns: + +=over + +=item SORT_CONNECTOR + +Sort by the connector string. For USB this defines the "path" to get to +the device through controllers, hubs etc. + +=item SORT_LABEL + +Sorts by the label of the Astribank. The label field is unique to the +Astribank. It can also be viewed through 'lsusb -v' without the drivers +loaded (the iSerial field in the Device Descriptor). + +=item SORT_NAME + +Sort by the "name". e.g: "XBUS-00". The order of Astribank names depends +on the load order, and hence may change between different runs. + +=item custom function + +Instead of using a predefined sorter, you can pass your own sorting +function. See the example sorters in the code of this module. + +=back + +=cut + +sub xbuses { + my $optsort = shift || 'SORT_CONNECTOR'; + my @xbuses; + + -d "$proc_base" or return (); + my @lines; + local $/ = "\n"; + open(F, "$proc_base/xbuses") || + die "$0: Failed to open $proc_base/xbuses: $!\n"; + @lines = ; + close F; + foreach my $line (@lines) { + chomp $line; + my ($name, @attr) = split(/\s+/, $line); + $name =~ s/://; + $name =~ /XBUS-(\d\d)/ or die "Bad XBUS number: $name"; + my $num = $1; + @attr = map { split(/=/); } @attr; + my $xbus = Zaptel::Xpp::Xbus->new(NAME => $name, NUM => $num, @attr); + push(@xbuses, $xbus); + } + my $sorter; + if($optsort eq "SORT_CONNECTOR") { + $sorter = \&by_connector; + } elsif($optsort eq "SORT_NAME") { + $sorter = \&by_name; + } elsif($optsort eq "SORT_LABEL") { + $sorter = \&by_label; + } elsif(ref($optsort) eq 'CODE') { + $sorter = $optsort; + } else { + die "Unknown optional sorter '$optsort'"; + } + @xbuses = sort $sorter @xbuses; + return @xbuses; +} + +sub xpd_of_span($) { + my $span = shift or die "Missing span parameter"; + return undef unless defined $span; + foreach my $xbus (Zaptel::Xpp::xbuses('SORT_CONNECTOR')) { + foreach my $xpd ($xbus->xpds()) { + return $xpd if $xpd->fqn eq $span->name; + } + } + return undef; +} + +=head1 sync([new_sync_source]) + +Gets (and optionally sets) the internal Astribanks synchronization +source. When used to set sync source, returns the original sync source. + +A synchronization source is a value valid writing into /proc/xpp/sync . +For more information read that file and see README.Astribank . + +=cut + +sub sync { + my $newsync = shift; + my $result; + my $newapi = 0; + + my $file = "$proc_base/sync"; + return '' unless -f $file; + # First query + open(F, "$file") or die "Failed to open $file for reading: $!"; + while() { + chomp; + /SYNC=/ and $newapi = 1; + s/#.*//; + if(/\S/) { # First non-comment line + s/^SYNC=\D*// if $newapi; + $result = $_; + last; + } + } + close F; + if(defined($newsync)) { # Now change + $newsync =~ s/.*/\U$&/; + if($newsync =~ /^(\d+)$/) { + $newsync = ($newapi)? "SYNC=$1" : "$1 0"; + } elsif($newsync ne 'ZAPTEL') { + die "Bad sync parameter '$newsync'"; + } + open(F, ">$file") or die "Failed to open $file for writing: $!"; + print F $newsync; + close(F) or die "Failed in closing $file: $!"; + } + return $result; +} + +=head1 SEE ALSO + +For the documentation of xbus objects, see L. For +information about XPD objects, see L. + +General documentation can be found in the master package L. + +=cut + +1; diff --git a/kernel/xpp/utils/zconf/Zaptel/Xpp/Line.pm b/kernel/xpp/utils/zconf/Zaptel/Xpp/Line.pm new file mode 100644 index 0000000..e3e04f0 --- /dev/null +++ b/kernel/xpp/utils/zconf/Zaptel/Xpp/Line.pm @@ -0,0 +1,59 @@ +package Zaptel::Xpp::Line; +# +# Written by Oron Peled +# Copyright (C) 2008, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Zaptel::Utils; + +my $proc_base = "/proc/xpp"; + +sub new($$$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $xpd = shift or die; + my $index = shift; + defined $index or die; + my $self = {}; + bless $self, ref($xpd); + $self->{XPD} = $xpd; + $self->{INDEX} = $index; + return $self; +} + +sub create_all($$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $xpd = shift || die; + my $procdir = shift || die; + local $/ = "\n"; + my @lines; + for(my $i = 0; $i < $xpd->{CHANNELS}; $i++) { + my $line = Zaptel::Xpp::Line->new($xpd, $i); + push(@lines, $line); + } + $xpd->{LINES} = \@lines; + my ($infofile) = glob "$procdir/*_info"; + die "Failed globbing '$procdir/*_info'" unless defined $infofile; + my $type = $xpd->type; + open(F, "$infofile") || die "Failed opening '$infofile': $!"; + while () { + chomp; + if($type eq 'FXO') { + if(s/^\s*battery\s*:\s*//) { + my @batt = split; + foreach my $l (@lines) { + die unless @batt; + $l->{BATTERY} = shift @batt; + } + die if @batt; + } + } + } + close F; +} + + +1; diff --git a/kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm b/kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm new file mode 100644 index 0000000..a5fcf1e --- /dev/null +++ b/kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm @@ -0,0 +1,117 @@ +package Zaptel::Xpp::Xbus; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Zaptel::Utils; +use Zaptel::Xpp::Xpd; + +my $proc_base = "/proc/xpp"; + +sub xpds($) { + my $xbus = shift; + return @{$xbus->{XPDS}}; +} + +sub by_number($) { + my $busnumber = shift; + die "Missing xbus number parameter" unless defined $busnumber; + my @xbuses = Zaptel::Xpp::xbuses(); + + my ($xbus) = grep { $_->num == $busnumber } @xbuses; + return $xbus; +} + +sub by_label($) { + my $label = shift; + die "Missing xbus label parameter" unless defined $label; + my @xbuses = Zaptel::Xpp::xbuses(); + + my ($xbus) = grep { $_->label eq $label } @xbuses; + return $xbus; +} + +sub get_xpd_by_number($$) { + my $xbus = shift; + my $xpdid = shift; + die "Missing XPD id parameter" unless defined $xpdid; + my @xpds = $xbus->xpds; + return $xpds[$xpdid]; +} + +sub new($$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $self = {}; + bless $self, $pack; + while(@_) { + my ($k, $v) = @_; + shift; shift; + # Keys in all caps + $k = uc($k); + # Some values are in all caps as well + if($k =~ /^(STATUS)$/) { + $v = uc($v); + } + $self->{$k} = $v; + } + # backward compat for drivers without labels. + if(!defined $self->{LABEL}) { + $self->{LABEL} = '[]'; + } + $self->{LABEL} =~ s/^\[(.*)\]$/$1/ or die "$self->{NAME}: Bad label"; + # Fix badly burned labels. + $self->{LABEL} =~ s/[[:^print:]]/_/g; + $self->{NAME} or die "Missing xbus name"; + my $prefix = "$proc_base/" . $self->{NAME}; + my $usbfile = "$prefix/xpp_usb"; + if(open(F, "$usbfile")) { + my $head = ; + chomp $head; + close F; + $head =~ s/^device: +([^, ]+)/$1/i or die; + $self->{USB_DEVNAME} = $head; + } + @{$self->{XPDS}} = (); + foreach my $dir (glob "$prefix/XPD-??") { + my $xpd = Zaptel::Xpp::Xpd->new($self, $dir); + push(@{$self->{XPDS}}, $xpd); + } + @{$self->{XPDS}} = sort { $a->id <=> $b->id } @{$self->{XPDS}}; + return $self; +} + +sub pretty_xpds($) { + my $xbus = shift; + my @xpds = sort { $a->id <=> $b->id } $xbus->xpds(); + my @xpd_types = map { $_->type } @xpds; + my $last_type = ''; + my $mult = 0; + my $xpdstr = ''; + foreach my $curr (@xpd_types) { + if(!$last_type || ($curr eq $last_type)) { + $mult++; + } else { + if($mult == 1) { + $xpdstr .= "$last_type "; + } elsif($mult) { + $xpdstr .= "$last_type*$mult "; + } + $mult = 1; + } + $last_type = $curr; + } + if($mult == 1) { + $xpdstr .= "$last_type "; + } elsif($mult) { + $xpdstr .= "$last_type*$mult "; + } + $xpdstr =~ s/\s*$//; # trim trailing space + return $xpdstr; +} + +1; diff --git a/kernel/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm b/kernel/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm new file mode 100644 index 0000000..326aafd --- /dev/null +++ b/kernel/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm @@ -0,0 +1,123 @@ +package Zaptel::Xpp::Xpd; +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use Zaptel::Utils; +use Zaptel::Xpp; +use Zaptel::Xpp::Line; + +my $proc_base = "/proc/xpp"; + +sub blink($$) { + my $self = shift; + my $on = shift; + my $result; + + my $file = "$proc_base/" . $self->fqn . "/blink"; + die "$file is missing" unless -f $file; + # First query + open(F, "$file") or die "Failed to open $file for reading: $!"; + $result = ; + chomp $result; + close F; + if(defined($on) and $on ne $result) { # Now change + open(F, ">$file") or die "Failed to open $file for writing: $!"; + print F ($on)?"1":"0"; + if(!close(F)) { + if($! == 17) { # EEXISTS + # good + } else { + undef $result; + } + } + } + return $result; +} + +sub zt_registration($$) { + my $self = shift; + my $on = shift; + my $result; + + my $file = "$proc_base/" . $self->fqn . "/zt_registration"; + die "$file is missing" unless -f $file; + # First query + open(F, "$file") or die "Failed to open $file for reading: $!"; + $result = ; + chomp $result; + close F; + if(defined($on) and $on ne $result) { # Now change + open(F, ">$file") or die "Failed to open $file for writing: $!"; + print F ($on)?"1":"0"; + if(!close(F)) { + if($! == 17) { # EEXISTS + # good + } else { + undef $result; + } + } + } + return $result; +} + +sub xpds_by_spanno() { + my @xbuses = Zaptel::Xpp::xbuses("SORT_CONNECTOR"); + my @xpds = map { $_->xpds } @xbuses; + @xpds = grep { $_->spanno } @xpds; + @xpds = sort { $a->spanno <=> $b->spanno } @xpds; + my @spanno = map { $_->spanno } @xpds; + my @idx; + @idx[@spanno] = @xpds; # The spanno is the index now + return @idx; +} + +sub new($$) { + my $pack = shift or die "Wasn't called as a class method\n"; + my $xbus = shift || die; + my $procdir = shift || die; + my $self = {}; + bless $self, $pack; + $self->{XBUS} = $xbus; + $self->{DIR} = $procdir; + local $/ = "\n"; + open(F, "$procdir/summary") || die "Missing summary file in $procdir"; + my $head = ; + chomp $head; # "XPD-00 (BRI_TE ,card present, span 3)" + # The driver does not export the number of channels... + # Let's find it indirectly + while() { + chomp; + if(s/^\s*offhook\s*:\s*//) { + my @offhook = split; + @offhook || die "No channels in '$procdir/summary'"; + $self->{CHANNELS} = @offhook; + last; + } + } + close F; + $head =~ s/^(XPD-(\d\d))\s+// || die; + $self->{ID} = $2; + $self->{FQN} = $xbus->name . "/" . $1; + $head =~ s/^.*\(// || die; + $head =~ s/\) */, / || die; + $head =~ s/\s*,\s*/,/g || die; + my ($type,$present,$span,$rest) = split(/,/, $head); + #warn "Garbage in '$procdir/summary': rest='$rest'\n" if $rest; + if($span =~ s/span\s+(\d+)//) { # since changeset:5119 + $self->{SPANNO} = $1; + } + $self->{TYPE} = $type; + $self->{IS_BRI} = ($type =~ /BRI_(NT|TE)/); + $self->{IS_PRI} = ($type =~ /[ETJ]1_(NT|TE)/); + $self->{IS_DIGITAL} = ( $self->{IS_BRI} || $self->{IS_PRI} ); + Zaptel::Xpp::Line->create_all($self, $procdir); + return $self; +} + +1; diff --git a/kernel/xpp/utils/zt_registration b/kernel/xpp/utils/zt_registration new file mode 100755 index 0000000..3bdc642 --- /dev/null +++ b/kernel/xpp/utils/zt_registration @@ -0,0 +1,125 @@ +#! /usr/bin/perl -w +# +# Written by Oron Peled +# Copyright (C) 2007, Xorcom +# This program is free software; you can redistribute and/or +# modify it under the same terms as Perl itself. +# +# $Id$ +# +use strict; +use File::Basename; +BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/zconf"); } + +use Zaptel; +use Zaptel::Span; +use Zaptel::Xpp; +use Zaptel::Xpp::Xbus; + +sub usage { + die "Usage: $0 [on|off|1|0]\n"; +} + +@ARGV == 0 or @ARGV == 1 or usage; +my $on = shift; +my $verbose = 0; +my $should_output = 1; + +if(defined($on)) { # Translate to booleans + $on = uc($on); + $on =~ /^(ON|OFF|1|0)$/ or usage; + $on = ($on eq 'ON') ? 1 : 0; + $should_output = 0 unless $verbose; +} + +sub state2str($) { + return (shift)?"on":"off"; +} + +sub myprintf { + printf @_ if $should_output; +} + +my @spans = Zaptel::spans; + +foreach my $xbus (Zaptel::Xpp::xbuses('SORT_CONNECTOR')) { + myprintf "%-10s\t%s\t%s\n", $xbus->name, $xbus->label, $xbus->connector; + next unless $xbus->status eq 'CONNECTED'; + foreach my $xpd ($xbus->xpds()) { + my $prev = $xpd->zt_registration($on); + if(!defined($prev)) { # Failure + printf "%s: Failed %s\n", $xpd->fqn, $!; + next; + } + myprintf "\t%-10s: ", $xpd->fqn; + if(!defined($on)) { # Query only + my ($span) = grep { $_->name eq $xpd->fqn } @spans; + my $spanstr = ($span) ? ("Span " . $span->num) : ""; + myprintf "%s %s\n", state2str($prev), $spanstr ; + next; + } + myprintf "%3s ==> %3s\n", state2str($prev), state2str($on); + } +} + +__END__ + +=head1 NAME + +zt_registration - Handle registration of Xorcom XPD modules in zaptel. + +=head1 SYNOPSIS + +zt_registration [on|off] + +=head1 DESCRIPTION + +Without parameters, show all connected XPDs sorted by physical connector order. +Each one is show to be unregistered (off), or registered to a specific zaptel +span (the span number is shown). + +All registerations/deregisterations are sorted by physical connector string. + +Span registration should generally always succeed. Span unregistration may +fail if channels from the span are in use by e.g. asterisk. In such a case +you'll also see those channels as '(In use)' in the output of lszaptel(8). + +=head2 Parameters + +off -- deregisters all XPD's from zaptel. + +on -- registers all XPD's to zaptel. + +=head2 Sample Output + +An example of the output of zt_registration for some registered +Astribanks: + + $ zt_registration + XBUS-02 [] usb-0000:00:1d.7-4 + XBUS-00/XPD-00: on Span 1 + XBUS-00/XPD-10: on Span 2 + XBUS-00 [usb:00000126] usb-0000:00:1d.7-2 + XBUS-02/XPD-00: on Span 3 + XBUS-02/XPD-10: on Span 4 + XBUS-02/XPD-20: on Span 5 + XBUS-02/XPD-30: on Span 6 + XBUS-01 [usb:00000128] usb-0000:00:1d.7-1 + XBUS-01/XPD-00: on Span 7 + XBUS-01/XPD-10: on Span 8 + XBUS-01/XPD-20: on Span 9 + XBUS-01/XPD-30: on Span 10 + +=head1 FILES + +=over + +=item /proc/xpp/XBUS-nn/XPD-mm/zt_registration + +Reading from this file shows if if the if the specific XPD is +registered. Writing to it 0 or 1 registers / unregisters the device. + +This should allow you to register / unregister a specific XPD rather +than all of them. + +=back diff --git a/kernel/xpp/xbus-core.c b/kernel/xpp/xbus-core.c new file mode 100644 index 0000000..790c12a --- /dev/null +++ b/kernel/xpp/xbus-core.c @@ -0,0 +1,1798 @@ +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +# warning "This module is tested only with 2.6 kernels" +#endif + +#include +#include +#include +#include +#ifdef PROTOCOL_DEBUG +#include +#endif +#include +#include +#include /* for msleep() to debug */ +#include "xpd.h" +#include "xpp_zap.h" +#include "xbus-core.h" +#ifdef XPP_DEBUGFS +#include "xpp_log.h" +#endif +#include "zap_debug.h" + +static const char rcsid[] = "$Id$"; + +/* Defines */ +#define INITIALIZATION_TIMEOUT (60*HZ) /* in jiffies */ +#define PROC_XBUSES "xbuses" +#define PROC_XBUS_SUMMARY "summary" +#define PROC_XBUS_WAITFOR_XPDS "waitfor_xpds" + +#ifdef PROTOCOL_DEBUG +#define PROC_XBUS_COMMAND "command" +static int proc_xbus_command_write(struct file *file, const char __user *buffer, unsigned long count, void *data); +#endif + +/* Command line parameters */ +extern int print_dbg; +DEF_PARM(uint, poll_timeout, 1000, 0644, "Timeout (in jiffies) waiting for units to reply"); +DEF_PARM_BOOL(rx_tasklet, 0, 0644, "Use receive tasklets"); + +static int xbus_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data); +static int xbus_read_waitfor_xpds(char *page, char **start, off_t off, int count, int *eof, void *data); +static void transport_init(xbus_t *xbus, struct xbus_ops *ops, ushort max_send_size, void *priv); +static void transport_destroy(xbus_t *xbus); + +/* + * Encapsulate all poll related data of a single xbus. + */ +struct xbus_poller { + /* + * Bus scanning + */ + uint xbus_num; + struct workqueue_struct *wq; + bool is_polling; + atomic_t count_poll_answers; + struct list_head poll_results; + wait_queue_head_t wait_for_polls; + + struct work_struct xpds_init_work; + + atomic_t count_xpds_to_initialize; + atomic_t count_xpds_initialized; + wait_queue_head_t wait_for_xpd_initialization; + struct proc_dir_entry *proc_xbus_waitfor_xpds; +}; + +/* Data structures */ +static spinlock_t xbuses_lock = SPIN_LOCK_UNLOCKED; +static int bus_count = 0; +static struct proc_dir_entry *proc_xbuses = NULL; + +static struct xbus_desc { + xbus_t *xbus; + atomic_t xbus_refcount; + wait_queue_head_t can_release_xbus; +} xbuses_array[MAX_BUSES]; + +static void init_xbus(uint num, xbus_t *xbus) +{ + struct xbus_desc *desc; + + BUG_ON(num >= ARRAY_SIZE(xbuses_array)); + desc = &xbuses_array[num]; + desc->xbus = xbus; + atomic_set(&desc->xbus_refcount, 0); + init_waitqueue_head(&desc->can_release_xbus); +} + +int refcount_xbus(uint num) +{ + BUG_ON(num >= ARRAY_SIZE(xbuses_array)); + return atomic_read(&xbuses_array[num].xbus_refcount); +} + +xbus_t *get_xbus(uint num) +{ + struct xbus_desc *desc; + + if(num >= ARRAY_SIZE(xbuses_array)) + return NULL; + desc = &xbuses_array[num]; + atomic_inc(&desc->xbus_refcount); + if(!desc->xbus) + atomic_dec(&desc->xbus_refcount); + return desc->xbus; +} + +void put_xbus(xbus_t *xbus) +{ + struct xbus_desc *desc; + int num; + + BUG_ON(!xbus); + num = xbus->num; + BUG_ON(num >= ARRAY_SIZE(xbuses_array)); + desc = &xbuses_array[num]; + BUG_ON(desc->xbus != xbus); + if(atomic_dec_and_test(&desc->xbus_refcount)) { + static int rate_limit; + + if((rate_limit++ % 1003) == 0) + XBUS_DBG(DEVICES, xbus, + "wake_up(can_release_xbus) (%d)\n", rate_limit); + wake_up(&desc->can_release_xbus); + } +} + +bool __must_check wait_for_xbus_release(uint xbus_num) +{ + xbus_t *xbus; + int ret; + + xbus = get_xbus(xbus_num); + if(!xbus) { + ERR("%s: xbus #%d is already removed. Skip.\n", + __FUNCTION__, xbus_num); + return 0; + } + put_xbus(xbus); + DBG(DEVICES, "Waiting... refcount_xbus=%d\n", refcount_xbus(xbus_num)); + ret = wait_event_interruptible(xbuses_array[xbus_num].can_release_xbus, + refcount_xbus(xbus_num) == 0); + if(ret) { + ERR("%s: waiting for xbus #%d interrupted!!!\n", + __FUNCTION__, xbus_num); + } else + DBG(DEVICES, "Waiting for refcount_xbus done.\n"); + return 1; +} + +static void initialize_xbuses_array(void) +{ + int i; + + for(i = 0; i < ARRAY_SIZE(xbuses_array); i++) + init_xbus(i, NULL); +} + +static void finalize_xbuses_array(void) +{ + int i; + + for(i = 0; i < ARRAY_SIZE(xbuses_array); i++) { + if(xbuses_array[i].xbus != NULL) { + ERR("%s: xbus #%d is not NULL\n", __FUNCTION__, i); + BUG(); + } + } +} + +/*------------------------- Debugfs Handling -----------------------*/ +#ifdef XPP_DEBUGFS + +#define DEBUGFS_BUFSIZ 4096 /* must be power of two, otherwise POS_IN_BUF will have to use '%' instead of '&' */ +#define POS_IN_BUF(x) ((x) & (DEBUGFS_BUFSIZ-1)) + +struct debugfs_data { + spinlock_t lock; + xbus_t *xbus; + char buffer[DEBUGFS_BUFSIZ]; + unsigned long head, tail; /* reading and writing are performed at position (head % BUF_SIZ) and (tail % BUF_SIZ) */ + wait_queue_head_t queue; +}; + +static unsigned long add_to_buf(struct debugfs_data *d, unsigned long tail, const void *buf, unsigned long len) +{ + unsigned long count = min(len, (unsigned long)(DEBUGFS_BUFSIZ - POS_IN_BUF(tail))); + memcpy(d->buffer + POS_IN_BUF(tail), buf, count); /* fill starting at position tail */ + memcpy(d->buffer, (u_char *)buf + count, len - count); /* fill leftover */ + return len; +} + +int xbus_log(xbus_t *xbus, xpd_t *xpd, int direction, const void *buf, unsigned long len) +{ + unsigned long tail; + unsigned long flags; + struct debugfs_data *d; + struct log_header header; + int ret = 0; + + BUG_ON(!xbus); + BUG_ON(!xpd); + BUG_ON(sizeof(struct log_header) + len > DEBUGFS_BUFSIZ); + d = xbus->debugfs_data; + if (!d) /* no consumer process */ + return ret; + spin_lock_irqsave(&d->lock, flags); + if (sizeof(struct log_header) + len > DEBUGFS_BUFSIZ - (d->tail - d->head)) { + ret = -ENOSPC; + XPD_DBG(GENERAL, xpd, "Dropping debugfs data of len %lu, free space is %lu\n", sizeof(struct log_header) + len, + DEBUGFS_BUFSIZ - (d->tail - d->head)); + goto out; + } + header.len = sizeof(struct log_header) + len; + header.time = jiffies_to_msecs(jiffies); + header.xpd_num = xpd->xbus_idx; + header.direction = (char)direction; + tail = d->tail; + tail += add_to_buf(d, tail, &header, sizeof(header)); + tail += add_to_buf(d, tail, buf, len); + d->tail = tail; + wake_up_interruptible(&d->queue); +out: + spin_unlock_irqrestore(&d->lock, flags); + return ret; +} + +static struct dentry *debugfs_root = NULL; +static int debugfs_open(struct inode *inode, struct file *file); +static ssize_t debugfs_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos); +static int debugfs_release(struct inode *inode, struct file *file); + +static struct file_operations debugfs_operations = { + .open = debugfs_open, + .read = debugfs_read, + .release = debugfs_release, +}; + +/* + * As part of the "inode diet" the private data member of struct inode + * has changed in 2.6.19. However, Fedore Core 6 adopted this change + * a bit earlier (2.6.18). If you use such a kernel, Change the + * following test from 2,6,19 to 2,6,18. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) +#define I_PRIVATE(inode) ((inode)->u.generic_ip) +#else +#define I_PRIVATE(inode) ((inode)->i_private) +#endif + +static int debugfs_open(struct inode *inode, struct file *file) +{ + xbus_t *xbus = I_PRIVATE(inode); + struct debugfs_data *d; + struct log_global_header gheader; + + BUG_ON(!xbus); + XBUS_DBG(GENERAL, xbus, "\n"); + if (xbus->debugfs_data) + return -EBUSY; + d = KZALLOC(sizeof(struct debugfs_data), GFP_KERNEL); + if (!d) + return -ENOMEM; + try_module_get(THIS_MODULE); + spin_lock_init(&d->lock); + d->xbus = xbus; + d->head = d->tail = 0; + init_waitqueue_head(&d->queue); + file->private_data = d; + + gheader.magic = XPP_LOG_MAGIC; + gheader.version = 1; + d->tail += add_to_buf(d, d->tail, &gheader, sizeof(gheader)); + + xbus->debugfs_data = d; + return 0; +} + +static ssize_t debugfs_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) +{ + struct debugfs_data *d = file->private_data; + size_t len; + + BUG_ON(!d); + BUG_ON(!d->xbus); + XBUS_DBG(GENERAL, d->xbus, "\n"); + while (d->head == d->tail) { + if (wait_event_interruptible(d->queue, d->head != d->tail)) + return -EAGAIN; + } + len = min(nbytes, (size_t)(d->tail - d->head)); + if (copy_to_user(buf, d->buffer + POS_IN_BUF(d->head), len)) + return -EFAULT; + d->head += len; + /* optimization to avoid future buffer wraparound */ + if (d->head == d->tail) { + unsigned long flags; + spin_lock_irqsave(&d->lock, flags); + if (d->head == d->tail) + d->head = d->tail = 0; + spin_unlock_irqrestore(&d->lock, flags); + } + return len; +} + +static int debugfs_release(struct inode *inode, struct file *file) +{ + struct debugfs_data *d = file->private_data; + + BUG_ON(!d); + BUG_ON(!d->xbus); + XBUS_DBG(GENERAL, d->xbus, "\n"); + d->xbus->debugfs_data = NULL; + kfree(d); + module_put(THIS_MODULE); + return 0; +} +#endif + +/*------------------------- Frame Handling ------------------------*/ + +void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize, void *priv) +{ + memset(xframe, 0, sizeof(*xframe)); + INIT_LIST_HEAD(&xframe->frame_list); + xframe->priv = priv; + xframe->xbus = xbus; + xframe->packets = xframe->first_free = buf; + xframe->frame_maxlen = maxsize; + atomic_set(&xframe->frame_len, 0); + do_gettimeofday(&xframe->tv_created); + xframe->xframe_magic = XFRAME_MAGIC; +} + +/* + * Return pointer to next packet slot in the frame + * or NULL if the frame is full. + * + * FIXME: we do not use atomic_add_return() because kernel-2.6.8 + * does not have it. This make this code a little racy, + * but we currently call xframe_next_packet() only in the + * PCM loop (xbus_tick() etc.) + */ +xpacket_t *xframe_next_packet(xframe_t *frm, int len) +{ + int newlen = XFRAME_LEN(frm); + + newlen += len; +// DBG(GENERAL, "len=%d, newlen=%d, frm->frame_len=%d\n", len, newlen, XFRAME_LEN(frm)); + if (newlen > XFRAME_DATASIZE) { + return NULL; + } + atomic_add(len, &frm->frame_len); + return (xpacket_t *)(frm->packets + newlen - len); +} + +static spinlock_t serialize_dump_xframe = SPIN_LOCK_UNLOCKED; + +static void do_hexdump(const char msg[], byte *data, uint16_t len) +{ + int i; + int print_dbg = DBG_ANY; /* mask global print_dbg */ + + for(i = 0; i < len; i++) + DBG(ANY, "%s: %3d> %02X\n", msg, i, data[i]); +} + +void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe) +{ + const uint16_t frm_len = XFRAME_LEN(xframe); + xpacket_t *pack; + uint16_t pos = 0; + uint16_t nextpos; + int num = 1; + bool do_print; + unsigned long flags; + + if(xframe->xframe_magic != XFRAME_MAGIC) { + XBUS_ERR(xbus, "%s: bad xframe_magic %lX\n", + __FUNCTION__, xframe->xframe_magic); + return; + } + spin_lock_irqsave(&serialize_dump_xframe, flags); + do { + if(pos >= xbus->transport.max_send_size) { + if(printk_ratelimit()) { + XBUS_NOTICE(xbus, "%s: xframe overflow (%d bytes)\n", + msg, frm_len); + do_hexdump(msg, xframe->packets, frm_len); + } + break; + } + if(pos > frm_len) { + if(printk_ratelimit()) { + XBUS_NOTICE(xbus, "%s: packet overflow pos=%d frame_len=%d\n", + msg, pos, frm_len); + do_hexdump(msg, xframe->packets, frm_len); + } + break; + } + pack = (xpacket_t *)&xframe->packets[pos]; + if(XPACKET_LEN(pack) <= 0) { + if(printk_ratelimit()) { + XBUS_NOTICE(xbus, "%s: xframe -- bad packet_len=%d pos=%d frame_len=%d\n", + msg, XPACKET_LEN(pack), pos, frm_len); + do_hexdump(msg, xframe->packets, frm_len); + } + break; + } + nextpos = pos + XPACKET_LEN(pack); + if(nextpos > frm_len) { + if(printk_ratelimit()) { + XBUS_NOTICE(xbus, "%s: packet overflow nextpos=%d frame_len=%d\n", + msg, nextpos, frm_len); + do_hexdump(msg, xframe->packets, frm_len); + } + break; + } + do_print = 0; + if(XPACKET_OP(pack) != XPROTO_NAME(GLOBAL,PCM_READ) && + XPACKET_OP(pack) != XPROTO_NAME(GLOBAL,PCM_WRITE)) + do_print = 1; + else if(print_dbg & DBG_PCM) { + static int rate_limit; + + if((rate_limit++ % 1003) == 0) + do_print = 1; + } + if(do_print) { + if(num == 1) { + XBUS_DBG(ANY, xbus, "%s: frame_len=%d. %s\n", + msg, frm_len, + (XPACKET_IS_PCM(pack)) + ? "(IS_PCM)" + : ""); + } + XBUS_DBG(ANY, xbus, " %3d. DATALEN=%d pcm=%d slot=%d OP=0x%02X XPD-%d%d (pos=%d)\n", + num, XPACKET_LEN(pack), + XPACKET_IS_PCM(pack), XPACKET_PCMSLOT(pack), + XPACKET_OP(pack), + XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack), + pos); + dump_packet(" ", pack, print_dbg); + } + num++; + pos = nextpos; + if(pos >= frm_len) + break; + } while(1); + spin_unlock_irqrestore(&serialize_dump_xframe, flags); +} + +bool xbus_ready(const xbus_t *xbus, const char msg[]) +{ + if(!xbus) { + ERR("null xbus: %s\n", msg); + return 0; + } + if (!TRANSPORT_RUNNING(xbus)) { + XBUS_ERR(xbus, "%s -- hardware is not ready.", msg); + return 0; + } + if(!xbus->transport.ops) { + XBUS_ERR(xbus, "%s -- hardware is gone.", msg); + return 0; + } + return 1; +} + +/** + * + * Frame is freed: + * - In case of error, by this function. + * - Otherwise, by the underlying sending mechanism + */ +int send_pcm_frame(xbus_t *xbus, xframe_t *xframe) +{ + struct xbus_ops *ops; + int ret = -ENODEV; + + BUG_ON(!xframe); + if(!xbus_ready(xbus, "Dropped a pcm frame")) { + ret = -ENODEV; + goto error; + } + ops = transportops_get(xbus); + BUG_ON(!ops); + ret = ops->xframe_send_pcm(xbus, xframe); + transportops_put(xbus); + if(ret) + XBUS_COUNTER(xbus, TX_BYTES) += XFRAME_LEN(xframe); + return ret; + +error: + FREE_SEND_XFRAME(xbus, xframe); + return ret; +} + +static int really_send_cmd_frame(xbus_t *xbus, xframe_t *xframe) +{ + struct xbus_ops *ops; + int ret; + + BUG_ON(!xbus); + BUG_ON(!xframe); + BUG_ON(xframe->xframe_magic != XFRAME_MAGIC); + if(!xbus_ready(xbus, "Dropped command before sending")) { + FREE_SEND_XFRAME(xbus, xframe); + return -ENODEV; + } + ops = transportops_get(xbus); + BUG_ON(!ops); + ret = ops->xframe_send_cmd(xbus, xframe); + transportops_put(xbus); + if(ret == 0) { + XBUS_COUNTER(xbus, TX_CMD)++; + XBUS_COUNTER(xbus, TX_BYTES) += XFRAME_LEN(xframe); + } + return ret; +} + +int xbus_command_queue_tick(xbus_t *xbus) +{ + xframe_t *frm; + int ret = 0; + + frm = xframe_dequeue(&xbus->command_queue); + if(frm) { + BUG_ON(frm->xframe_magic != XFRAME_MAGIC); + ret = really_send_cmd_frame(xbus, frm); + if(ret < 0) + XBUS_ERR(xbus, + "Failed to send from command_queue (ret=%d)\n", + ret); + XBUS_PUT(xbus); + } else + wake_up(&xbus->command_queue_empty); + return ret; +} + +static void xbus_command_queue_clean(xbus_t *xbus) +{ + xframe_t *frm; + + XBUS_DBG(DEVICES, xbus, "count=%d\n", xbus->command_queue.count); + xframe_queue_disable(&xbus->command_queue); + while((frm = xframe_dequeue(&xbus->command_queue)) != NULL) { + FREE_SEND_XFRAME(xbus, frm); + XBUS_PUT(xbus); + } +} + +static int xbus_command_queue_waitempty(xbus_t *xbus) +{ + int ret; + + XBUS_DBG(DEVICES, xbus, "Waiting for command_queue to empty\n"); + ret = wait_event_interruptible(xbus->command_queue_empty, + xframe_queue_count(&xbus->command_queue) == 0); + if(ret) { + XBUS_ERR(xbus, "waiting for command_queue interrupted!!!\n"); + } + return ret; +} + +int send_cmd_frame(xbus_t *xbus, xframe_t *xframe) +{ + static int rate_limit; + const char *msg = ""; + int ret = 0; + + + BUG_ON(xframe->xframe_magic != XFRAME_MAGIC); + if(!xbus_ready(xbus, "Dropped command before queueing")) { + ret = -ENODEV; + goto err; + } + if(!XBUS_GET(xbus)) { + msg = "Dropped command xframe. Is shutting down."; + ret = -ENODEV; + goto err; + } + if(!xframe_enqueue(&xbus->command_queue, xframe)) { + XBUS_PUT(xbus); + msg = "Dropped command xframe. Cannot enqueue."; + ret = -E2BIG; + goto err; + } + return 0; +err: + if((rate_limit++ % 1003) == 0) { + XBUS_ERR(xbus, "%s\n", msg); + dump_xframe("send_cmd_frame", xbus, xframe); + } + FREE_SEND_XFRAME(xbus, xframe); + return ret; +} + +/*------------------------- Receive Tasklet Handling ---------------*/ + +static void xframe_enqueue_recv(xbus_t *xbus, xframe_t *xframe) +{ + int cpu = smp_processor_id(); + + BUG_ON(!xbus); + xbus->cpu_rcv_intr[cpu]++; + if(!xframe_enqueue(&xbus->receive_queue, xframe)) { + static int rate_limit; + + if((rate_limit++ % 1003) == 0) + XBUS_ERR(xbus, "Failed to enqueue for receive_tasklet (%d)\n", rate_limit); + FREE_RECV_XFRAME(xbus, xframe); /* return to receive_pool */ + return; + } + tasklet_schedule(&xbus->receive_tasklet); +} + +/* + * process frames in the receive_queue in a tasklet + */ +static void receive_tasklet_func(unsigned long data) +{ + xbus_t *xbus = (xbus_t *)data; + xframe_t *xframe = NULL; + int cpu = smp_processor_id(); + + BUG_ON(!xbus); + xbus->cpu_rcv_tasklet[cpu]++; + while((xframe = xframe_dequeue(&xbus->receive_queue)) != NULL) { + xframe_receive(xbus, xframe); + } +} + +void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe) +{ + BUG_ON(!xbus); + if(rx_tasklet) { + xframe_enqueue_recv(xbus, xframe); + } else { + if (likely(TRANSPORT_RUNNING(xbus))) + xframe_receive(xbus, xframe); + else + FREE_RECV_XFRAME(xbus, xframe); /* return to receive_pool */ + } +} + +/*------------------------- Bus Management -------------------------*/ +xpd_t *xpd_of(const xbus_t *xbus, int xpd_num) +{ + if(!VALID_XPD_NUM(xpd_num)) + return NULL; + return xbus->xpds[xpd_num]; +} + +xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit) +{ + if(unit > MAX_UNIT || subunit > MAX_SUBUNIT) + return NULL; + return xbus->xpds[XPD_IDX(unit,subunit)]; +} + +int xbus_register_xpd(xbus_t *xbus, xpd_t *xpd) +{ + unsigned int xpd_num = xpd->xbus_idx; + unsigned long flags; + int ret = 0; + + xbus = get_xbus(xbus->num); /* until unregister */ + BUG_ON(!xbus); + XBUS_DBG(DEVICES, xbus, "XPD #%d (xbus_refcount=%d)\n", + xpd_num, refcount_xbus(xbus->num)); + spin_lock_irqsave(&xbus->lock, flags); + if(!VALID_XPD_NUM(xpd_num)) { + XBUS_ERR(xbus, "Bad xpd_num = %d\n", xpd_num); + ret = -EINVAL; + goto out; + } + if(xbus->xpds[xpd_num] != NULL) { + xpd_t *other = xbus->xpds[xpd_num]; + + XBUS_ERR(xbus, "xpd_num=%d is occupied by %p (%s)\n", + xpd_num, other, other->xpdname); + ret = -EINVAL; + goto out; + } + xbus->xpds[xpd_num] = xpd; + xpd->xbus = xbus; + xbus->num_xpds++; +out: + spin_unlock_irqrestore(&xbus->lock, flags); + return ret; +} + +int xbus_unregister_xpd(xbus_t *xbus, xpd_t *xpd) +{ + unsigned int xpd_num = xpd->xbus_idx; + unsigned long flags; + int ret = -EINVAL; + + spin_lock_irqsave(&xbus->lock, flags); + XBUS_DBG(DEVICES, xbus, "XPD #%d (xbus_refcount=%d)\n", + xpd_num, refcount_xbus(xbus->num)); + if(!VALID_XPD_NUM(xpd_num)) { + XBUS_ERR(xbus, "%s: Bad xpd_num = %d\n", __FUNCTION__, xpd_num); + goto out; + } + if(xbus->xpds[xpd_num] == NULL) { + XBUS_ERR(xbus, "%s: slot xpd_num=%d is empty\n", __FUNCTION__, xpd_num); + goto out; + } + if(xbus->xpds[xpd_num] != xpd) { + xpd_t *other = xbus->xpds[xpd_num]; + + XBUS_ERR(xbus, "%s: slot xpd_num=%d is occupied by %p (%s)\n", + __FUNCTION__, xpd_num, other, other->xpdname); + goto out; + } + xbus->xpds[xpd_num] = NULL; + xbus->num_xpds--; + xpd->xbus = NULL; + put_xbus(xbus); /* we got it in xbus_register_xpd() */ + ret = 0; +out: + spin_unlock_irqrestore(&xbus->lock, flags); + return ret; +} + +/* + * This must be called from synchronous (non-interrupt) context + * it returns only when all XPD's on the bus are detected and + * initialized. + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) +static void xbus_poll(struct work_struct *work) +{ + struct xbus_poller *poller = container_of(work, struct xbus_poller, xpds_init_work); +#else +static void xbus_poll(void *data) +{ + struct xbus_poller *poller = data; +#endif + int id; + int ret = 0; + unsigned long flags; + struct list_head *card; + struct list_head *next_card; + struct list_head removal_list; + struct list_head additions_list; + int count_removed; + int count_added; + xbus_t *xbus; + + BUG_ON(!poller); + xbus = get_xbus(poller->xbus_num); + if(!xbus) { + XBUS_ERR(xbus, "Aborting poll. XBUS #%d disappeared.\n", + poller->xbus_num); + return; + } + msleep(2); /* roundtrip for older polls */ + spin_lock_irqsave(&xbus->lock, flags); + XBUS_DBG(DEVICES, xbus, "\n"); + poller->is_polling = 1; + if(!XBUS_GET(xbus)) { + XBUS_ERR(xbus, "Aborting poll. Is shutting down.\n"); + goto out; + } + /* + * Send out the polls + */ + for(id = 0; id < MAX_XPDS; id++) { + if(!TRANSPORT_RUNNING(xbus)) + break; + XBUS_DBG(DEVICES, xbus, "Polling slot %d\n", id); + spin_unlock_irqrestore(&xbus->lock, flags); + ret = CALL_PROTO(GLOBAL, DESC_REQ, xbus, NULL, id); + spin_lock_irqsave(&xbus->lock, flags); + if(ret < 0) { + XBUS_ERR(xbus, "Failed sending DESC_REQ to XPD #%d\n", id); + goto out; + } + } + spin_unlock_irqrestore(&xbus->lock, flags); + /* + * Wait for replies + */ + XBUS_DBG(DEVICES, xbus, "Polled %d XPD's. Waiting for replies max %d jiffies\n", MAX_XPDS, poll_timeout); + ret = wait_event_interruptible_timeout(poller->wait_for_polls, atomic_read(&poller->count_poll_answers) >= MAX_XPDS, poll_timeout); + if(ret == 0) { + XBUS_ERR(xbus, "Poll timeout. Continuing anyway.\n"); + /* + * Continue processing. Maybe some units did reply. + */ + } else if(ret < 0) { + XBUS_ERR(xbus, "Poll interrupted %d\n", ret); + goto out; + } else + XBUS_DBG(DEVICES, xbus, "Poll finished in %d jiffies.\n", poll_timeout - ret); + /* + * Build removals/additions lists + */ + spin_lock_irqsave(&xbus->lock, flags); + INIT_LIST_HEAD(&removal_list); + INIT_LIST_HEAD(&additions_list); + count_removed = 0; + count_added = 0; + list_for_each_safe(card, next_card, &poller->poll_results) { + struct card_desc_struct *card_desc = list_entry(card, struct card_desc_struct, card_list); + byte type = card_desc->type; + xpd_t *xpd; + + BUG_ON(card_desc->magic != CARD_DESC_MAGIC); + /* + * Return the refcount we got in xbus_poller_notify() + * We are still protected by the refcount taken in + * the beginning of xbus_poll(). + */ + put_xbus(xbus); + xpd = xpd_byaddr(xbus, card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit); + + if(xpd && type == XPD_TYPE_NOMODULE) { /* card removal */ + list_move_tail(card, &removal_list); + count_removed++; + } else if(!xpd && type != XPD_TYPE_NOMODULE) { /* card detection */ + if(card_desc->rev != XPP_PROTOCOL_VERSION) { + XBUS_NOTICE(xbus, "XPD at %d%d: type=%d.%d has bad firmware revision %d.%d\n", + card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit, + card_desc->type, card_desc->subtype, + card_desc->rev / 10, card_desc->rev % 10); + list_del(card); + kfree(card_desc); + continue; + } + XBUS_INFO(xbus, "Detected XPD at %d%d type=%d.%d Revision %d.%d\n", + card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit, + card_desc->type, card_desc->subtype, + card_desc->rev / 10, card_desc->rev % 10); + list_move_tail(card, &additions_list); + count_added++; + } else { /* same same */ + list_del(card); + kfree(card_desc); + } + } + poller->is_polling = 0; + /* + * We set this *after* poll is finished, so wait_for_xpd_initialization can + * tell we already know how many units we have. + */ + atomic_set(&poller->count_xpds_to_initialize, count_added); + spin_unlock_irqrestore(&xbus->lock, flags); + XBUS_INFO(xbus, "Poll results: removals=%d additions=%d\n", count_removed, count_added); + /* + * Process removals first + */ + list_for_each_safe(card, next_card, &removal_list) { + struct card_desc_struct *card_desc = list_entry(card, struct card_desc_struct, card_list); + xpd_t *xpd; + + list_del(card); + xpd = xpd_byaddr(xbus, card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit); + if(xpd) + xpd_disconnect(xpd); + kfree(card); + } + /* + * Now process additions + */ + list_for_each_safe(card, next_card, &additions_list) { + struct card_desc_struct *card_desc = list_entry(card, struct card_desc_struct, card_list); + + list_del(card); + /* FIXME: card_detected() should have a return value for count_xpds_initialized */ + card_detected(card_desc); + atomic_inc(&poller->count_xpds_initialized); + } + /* Device-Model */ + if((ret = xbus_sysfs_create(xbus)) < 0) { + XBUS_ERR(xbus, "%s: xbus_sysfs_create() failed: %d\n", __FUNCTION__, ret); + goto out; + } + /* + * Now request Astribank to start self_ticking. + * This is the last initialization command. So + * all others will reach the device before it. + */ + xbus_request_sync(xbus, SYNC_MODE_PLL); + elect_syncer("xbus_poll(end)"); /* FIXME: try to do it later */ +out: + poller->is_polling = 0; /* just for safety */ + XBUS_PUT(xbus); + wake_up(&poller->wait_for_xpd_initialization); + put_xbus(xbus); + return; +} + +void xbus_poller_notify(xbus_t *xbus, struct card_desc_struct *card_desc) +{ + struct xbus_poller *poller; + unsigned long flags; + + BUG_ON(!xbus); + poller = xbus->poller; + BUG_ON(!poller); + if(!poller->is_polling) { + XBUS_NOTICE(xbus, "%d%d replied not during poll. Ignore\n", + card_desc->xpd_addr.unit, + card_desc->xpd_addr.subunit); + kfree(card_desc); + return; + } + spin_lock_irqsave(&xbus->lock, flags); + if(card_desc->type == XPD_TYPE_NOMODULE) + XBUS_COUNTER(xbus, DEV_DESC_EMPTY)++; + else + XBUS_COUNTER(xbus, DEV_DESC_FULL)++; + atomic_inc(&poller->count_poll_answers); + list_add_tail(&card_desc->card_list, &poller->poll_results); + spin_unlock_irqrestore(&xbus->lock, flags); + /* + * Reference counting for the xbus. + * Would be returned in xbus_poll() + */ + xbus = get_xbus(xbus->num); + BUG_ON(!xbus); + /* + * wake_up only after exiting our critical section. + * We suspect that otherwise a spinlock nesting may occur + * and cause a panic (if spinlock debugging is compiled in). + */ + wake_up(&poller->wait_for_polls); + return; +} + +static void poller_destroy(struct xbus_poller *poller) +{ + xbus_t *xbus; + + if(!poller) + return; + xbus = get_xbus(poller->xbus_num); + if(xbus) { +#ifdef CONFIG_PROC_FS + if(xbus->proc_xbus_dir && poller->proc_xbus_waitfor_xpds) { + XBUS_DBG(PROC, xbus, "Removing proc '%s'\n", PROC_XBUS_WAITFOR_XPDS); + remove_proc_entry(PROC_XBUS_WAITFOR_XPDS, xbus->proc_xbus_dir); + poller->proc_xbus_waitfor_xpds = NULL; + } +#endif + XBUS_DBG(DEVICES, xbus, "detach poller\n"); + xbus->poller = NULL; + } + if (poller->wq) { + DBG(DEVICES, "XBUS #%d: destroy workqueue\n", poller->xbus_num); + flush_workqueue(poller->wq); + destroy_workqueue(poller->wq); + poller->wq = NULL; + } + put_xbus(xbus); + KZFREE(poller); +} + +/* + * Allocate a poller for the xbus including the nessessary workqueue. + * May call blocking operations, but only briefly (as we are called + * from xbus_new() which is called from khubd. + */ +static struct xbus_poller *poller_new(xbus_t *xbus) +{ + struct xbus_poller *poller; + + BUG_ON(xbus->busname[0] == '\0'); /* No name? */ + BUG_ON(xbus->poller); /* Hmmm... overrun pollers? */ + XBUS_DBG(DEVICES, xbus, "\n"); + poller = KZALLOC(sizeof(*poller), GFP_KERNEL); + if(!poller) + goto err; + poller->xbus_num = xbus->num; + xbus->poller = poller; + /* poll related variables */ + atomic_set(&poller->count_poll_answers, 0); + atomic_set(&poller->count_xpds_to_initialize, 0); + atomic_set(&poller->count_xpds_initialized, 0); + INIT_LIST_HEAD(&poller->poll_results); + init_waitqueue_head(&poller->wait_for_polls); + init_waitqueue_head(&poller->wait_for_xpd_initialization); + poller->wq = create_singlethread_workqueue(xbus->busname); + if(!poller->wq) { + XBUS_ERR(xbus, "Failed to create poller workqueue.\n"); + goto err; + } +#ifdef CONFIG_PROC_FS + if(xbus->proc_xbus_dir) { + poller->proc_xbus_waitfor_xpds = create_proc_read_entry( + PROC_XBUS_WAITFOR_XPDS, 0444, + xbus->proc_xbus_dir, + xbus_read_waitfor_xpds, + xbus); + if (!poller->proc_xbus_waitfor_xpds) { + XBUS_ERR(xbus, "Failed to create proc file '%s'\n", PROC_XBUS_WAITFOR_XPDS); + goto err; + } + poller->proc_xbus_waitfor_xpds->owner = THIS_MODULE; + } +#endif + return poller; +err: + poller_destroy(poller); + return NULL; +} + +/* + * Sends an xbus_poll() work to the poller workqueue of the given xbus. + */ +static int poller_dispatch(xbus_t *xbus) +{ + struct xbus_poller *poller = xbus->poller; + + if(!poller) { + XBUS_ERR(xbus, "missing poller\n"); + return 0; + } + /* Initialize the work. (adapt to kernel API changes). */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) + INIT_WORK(&poller->xpds_init_work, xbus_poll); +#else + INIT_WORK(&poller->xpds_init_work, xbus_poll, poller); +#endif + /* Now send it */ + if(!queue_work(poller->wq, &poller->xpds_init_work)) { + XBUS_ERR(xbus, "Failed to queue xpd initialization work\n"); + return 0; + } + return 1; +} + +int xbus_activate(xbus_t *xbus) +{ + struct xbus_ops *ops; + struct xbus_poller *poller; + + BUG_ON(!xbus); + ops = transportops_get(xbus); + BUG_ON(!ops); + poller = xbus->poller; + BUG_ON(!poller); + /* Sanity checks */ + BUG_ON(!ops->xframe_send_pcm); + BUG_ON(!ops->xframe_send_cmd); + BUG_ON(!ops->alloc_xframe); + BUG_ON(!ops->free_xframe); + xpp_timing_init(&xbus->timing, xbus->busname); + /* + * We start with timer based ticking + */ + xbus_set_command_timer(xbus, 1); + xbus->transport.transport_running = 1; /* must be done after transport is valid */ + XBUS_INFO(xbus, "[%s] Activating\n", xbus->label); + /* + * Make sure Astribank knows not to send us ticks. + */ + xbus_request_sync(xbus, SYNC_MODE_NONE); + /* Poll it */ + poller_dispatch(xbus); + return 0; +} + +void xbus_disconnect(xbus_t *xbus) +{ + int i; + + BUG_ON(!xbus); + XBUS_INFO(xbus, "[%s] Disconnecting\n", xbus->label); + xbus_set_command_timer(xbus, 1); + xbus_request_sync(xbus, SYNC_MODE_PLL); /* no more ticks */ + for(i = 0; i < MAX_XPDS; i++) { + xpd_t *xpd = xpd_of(xbus, i); + if(!xpd) + continue; + if(xpd->xbus_idx != i) { + XBUS_ERR(xbus, "BUG: xpd->xbus_idx=%d != i=%d\n", xpd->xbus_idx, i); + continue; + } + xpd_disconnect(xpd); + } + XBUS_DBG(DEVICES, xbus, "Deactivating\n"); + tasklet_kill(&xbus->receive_tasklet); + xframe_queue_clear(&xbus->receive_queue); + xbus_command_queue_clean(xbus); + xbus_command_queue_waitempty(xbus); + del_timer_sync(&xbus->command_timer); + xframe_queue_clear(&xbus->send_pool); + xframe_queue_clear(&xbus->receive_pool); + xframe_queue_clear(&xbus->pcm_tospan[0]); + xframe_queue_clear(&xbus->pcm_tospan[1]); + transportops_put(xbus); + transport_destroy(xbus); + elect_syncer("disconnect"); + XBUS_DBG(DEVICES, xbus, "Deactivated (refcount_xbus=%d)\n", refcount_xbus(xbus->num)); + if(atomic_dec_and_test(&xbus->xbus_ref_count)) { + XBUS_DBG(DEVICES, xbus, "Going to remove XBUS\n"); + xbus_remove(xbus); + } +} + +static xbus_t *xbus_alloc(void) +{ + unsigned long flags; + xbus_t *xbus; + int i; + + xbus = KZALLOC(sizeof(xbus_t), GFP_KERNEL); + if(!xbus) { + ERR("%s: out of memory\n", __FUNCTION__); + return NULL; + } + spin_lock_irqsave(&xbuses_lock, flags); + for(i = 0; i < MAX_BUSES; i++) + if(xbuses_array[i].xbus == NULL) + break; + if(i >= MAX_BUSES) { + ERR("%s: No free slot for new bus. i=%d\n", __FUNCTION__, i); + kfree(xbus); + return NULL; + } + /* Found empty slot */ + xbus->num = i; + init_xbus(i, xbus); + xbus = get_xbus(i); + bus_count++; + spin_unlock_irqrestore(&xbuses_lock, flags); + return xbus; +} + + +static void xbus_free(xbus_t *xbus) +{ + unsigned long flags; + uint num; + + if(!xbus) + return; + spin_lock_irqsave(&xbuses_lock, flags); + num = xbus->num; + BUG_ON(!xbuses_array[num].xbus); + BUG_ON(xbus != xbuses_array[num].xbus); + spin_unlock_irqrestore(&xbuses_lock, flags); +#ifdef XPP_DEBUGFS + if(xbus->debugfs_dir) { + if(xbus->debugfs_file) { + XBUS_DBG(GENERAL, xbus, "Removing debugfs file\n"); + debugfs_remove(xbus->debugfs_file); + } + XBUS_DBG(GENERAL, xbus, "Removing debugfs directory\n"); + debugfs_remove(xbus->debugfs_dir); + } +#endif + poller_destroy(xbus->poller); +#ifdef CONFIG_PROC_FS + if(xbus->proc_xbus_dir) { + if(xbus->proc_xbus_summary) { + XBUS_DBG(PROC, xbus, "Removing proc '%s'\n", PROC_XBUS_SUMMARY); + remove_proc_entry(PROC_XBUS_SUMMARY, xbus->proc_xbus_dir); + xbus->proc_xbus_summary = NULL; + } +#ifdef PROTOCOL_DEBUG + if(xbus->proc_xbus_command) { + XBUS_DBG(PROC, xbus, "Removing proc '%s'\n", PROC_XBUS_COMMAND); + remove_proc_entry(PROC_XBUS_COMMAND, xbus->proc_xbus_dir); + xbus->proc_xbus_command = NULL; + } +#endif + XBUS_DBG(PROC, xbus, "Removing proc directory\n"); + remove_proc_entry(xbus->busname, xpp_proc_toplevel); + xbus->proc_xbus_dir = NULL; + } +#endif + spin_lock_irqsave(&xbuses_lock, flags); + /* + * Return to xbus reference counts: + * - One from our caller: transport disconnect or xpp_close() + * - One from xbus_alloc() + */ + put_xbus(xbus); + put_xbus(xbus); + if(!wait_for_xbus_release(xbus->num)) + BUG(); /* Let's see what happens next... */ + bus_count--; + XBUS_DBG(DEVICES, xbus, "Going to free... refcount_xbus=%d\n", refcount_xbus(num)); + BUG_ON(refcount_xbus(num) != 0); + init_xbus(num, NULL); + spin_unlock_irqrestore(&xbuses_lock, flags); + KZFREE(xbus); +} + +xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, void *priv) +{ + int err; + xbus_t *xbus = NULL; + struct xbus_poller *poller; + + BUG_ON(!ops); + XBUS_DBG(GENERAL, xbus, "allocate new xbus\n"); + xbus = xbus_alloc(); + if(!xbus) + return NULL; + transport_init(xbus, ops, max_send_size, priv); + spin_lock_init(&xbus->lock); + atomic_set(&xbus->xbus_ref_count, 1); /* a single ref */ + snprintf(xbus->busname, XBUS_NAMELEN, "XBUS-%02d", xbus->num); + init_waitqueue_head(&xbus->command_queue_empty); + init_timer(&xbus->command_timer); + atomic_set(&xbus->pcm_rx_counter, 0); + xbus->min_tx_sync = INT_MAX; + xbus->min_rx_sync = INT_MAX; + + xbus->num_xpds = 0; + xbus->sync_mode = SYNC_MODE_NONE; + init_rwsem(&xbus->in_use); + xbus_reset_counters(xbus); +#ifdef CONFIG_PROC_FS + XBUS_DBG(PROC, xbus, "Creating xbus proc directory\n"); + xbus->proc_xbus_dir = proc_mkdir(xbus->busname, xpp_proc_toplevel); + if(!xbus->proc_xbus_dir) { + XBUS_ERR(xbus, "Failed to create proc directory\n"); + err = -EIO; + goto nobus; + } + xbus->proc_xbus_summary = create_proc_read_entry(PROC_XBUS_SUMMARY, 0444, xbus->proc_xbus_dir, + xbus_read_proc, (void *)(xbus->num)); + if (!xbus->proc_xbus_summary) { + XBUS_ERR(xbus, "Failed to create proc file '%s'\n", PROC_XBUS_SUMMARY); + err = -EIO; + goto nobus; + } + xbus->proc_xbus_summary->owner = THIS_MODULE; +#ifdef PROTOCOL_DEBUG + xbus->proc_xbus_command = create_proc_entry(PROC_XBUS_COMMAND, 0200, xbus->proc_xbus_dir); + if (!xbus->proc_xbus_command) { + XBUS_ERR(xbus, "Failed to create proc file '%s'\n", PROC_XBUS_COMMAND); + err = -EIO; + goto nobus; + } + xbus->proc_xbus_command->write_proc = proc_xbus_command_write; + xbus->proc_xbus_command->data = xbus; + xbus->proc_xbus_command->owner = THIS_MODULE; +#endif +#endif +#ifdef XPP_DEBUGFS + xbus->debugfs_dir = debugfs_create_dir(xbus->busname, debugfs_root); + if(!xbus->debugfs_dir) { + XBUS_ERR(xbus, "Failed to create debugfs directory\n"); + goto nobus; + } + xbus->debugfs_file = debugfs_create_file("dchannel", S_IFREG|S_IRUGO|S_IWUSR, xbus->debugfs_dir, xbus, &debugfs_operations); + if(!xbus->debugfs_file) { + XBUS_ERR(xbus, "Failed to create dchannel file\n"); + goto nobus; + } +#endif + xframe_queue_init(&xbus->command_queue, 10, 200, "command_queue", xbus); + xframe_queue_init(&xbus->receive_queue, 10, 50, "receive_queue", xbus); + xframe_queue_init(&xbus->send_pool, 10, 200, "send_pool", xbus); + xframe_queue_init(&xbus->receive_pool, 10, 50, "receive_pool", xbus); + xframe_queue_init(&xbus->pcm_tospan[0], 5, 10, "pcm_tospan[0]", xbus); + xframe_queue_init(&xbus->pcm_tospan[1], 5, 10, "pcm_tospan[1]", xbus); + tasklet_init(&xbus->receive_tasklet, receive_tasklet_func, (unsigned long)xbus); + /* + * Create poller after /proc/XBUS-?? so the directory exists + * before /proc/XBUS-??/waitfor_xpds tries to get created. + */ + poller = poller_new(xbus); + if(!poller) { + ERR("Failed to allocate poller\n"); + xbus_free(xbus); + return NULL; + } + return xbus; +nobus: + xbus_free(xbus); + return NULL; +} + +void xbus_remove(xbus_t *xbus) +{ + int i; + + BUG_ON(TRANSPORT_RUNNING(xbus)); + down_write(&xbus->in_use); + + XBUS_INFO(xbus, "[%s] Removing\n", xbus->label); + xbus_sysfs_remove(xbus); /* Device-Model */ + for(i = 0; i < MAX_XPDS; i++) { + xpd_t *xpd = xpd_of(xbus, i); + + if(xpd) { + if(xpd->xbus_idx != i) { + XBUS_ERR(xbus, "BUG: xpd->xbus_idx=%d != i=%d\n", xpd->xbus_idx, i); + continue; + } + XBUS_DBG(DEVICES, xbus, " Removing xpd #%d\n", i); + xpd_remove(xpd); + } + xbus->xpds[i] = NULL; + } + xbus_free(xbus); +} + +/*------------------------- Proc handling --------------------------*/ + +void xbus_reset_counters(xbus_t *xbus) +{ + int i; + + XBUS_DBG(GENERAL, xbus, "Reseting counters\n"); + for(i = 0; i < XBUS_COUNTER_MAX; i++) { + xbus->counters[i] = 0; + } +} + +#if CONFIG_PROC_FS + +static int xbus_fill_proc_queue(char *p, struct xframe_queue *q) +{ + int len; + + len = sprintf(p, + "%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02ld.%ld ms\n", + q->name, + q->steady_state_count, + q->count, + q->max_count, + q->worst_count, + q->overflows, + q->worst_lag_usec / 1000, + q->worst_lag_usec % 1000); + xframe_queue_clearstats(q); + return len; +} + +static int xbus_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + xbus_t *xbus; + struct xbus_poller *poller; + unsigned long flags; + int len = 0; + int i = (int)data; + struct timeval now; + + + xbus = get_xbus(i); + if(!xbus) + goto out; + spin_lock_irqsave(&xbus->lock, flags); + do_gettimeofday(&now); + poller = xbus->poller; + + len += sprintf(page + len, "%s: CONNECTOR=%s LABEL=[%s] STATUS=%s\n", + xbus->busname, + xbus->busdesc, + xbus->label, + (TRANSPORT_RUNNING(xbus)) ? "connected" : "missing" + ); + len += sprintf(page + len, "POLLS: %d/%d\n", + atomic_read(&poller->count_poll_answers), MAX_XPDS); + len += sprintf(page + len, "XPDS_READY: %d/%d\n", + atomic_read(&poller->count_xpds_initialized), + atomic_read(&poller->count_xpds_to_initialize)); + len += sprintf(page + len, "\nxbus_ref_count=%d\n", + atomic_read(&xbus->xbus_ref_count) + ); + len += xbus_fill_proc_queue(page + len, &xbus->send_pool); + len += xbus_fill_proc_queue(page + len, &xbus->receive_pool); + len += xbus_fill_proc_queue(page + len, &xbus->command_queue); + len += xbus_fill_proc_queue(page + len, &xbus->receive_queue); + len += xbus_fill_proc_queue(page + len, &xbus->pcm_tospan[0]); + len += xbus_fill_proc_queue(page + len, &xbus->pcm_tospan[1]); + if(rx_tasklet) { + len += sprintf(page + len, "\ncpu_rcv_intr: "); + for_each_online_cpu(i) + len += sprintf(page + len, "%5d ", xbus->cpu_rcv_intr[i]); + len += sprintf(page + len, "\ncpu_rcv_tasklet: "); + for_each_online_cpu(i) + len += sprintf(page + len, "%5d ", xbus->cpu_rcv_tasklet[i]); + len += sprintf(page + len, "\n"); + } + len += sprintf(page + len, "self_ticking: %d\n", xbus->self_ticking); + len += sprintf(page + len, "xbus: pcm_rx_counter = %d, frag = %d\n", + atomic_read(&xbus->pcm_rx_counter), xbus->xbus_frag_count); + len += sprintf(page + len, "max_rx_process = %2ld.%ld ms\n", + xbus->max_rx_process / 1000, + xbus->max_rx_process % 1000); + xbus->max_rx_process = 0; + len += sprintf(page + len, "\nTRANSPORT: max_send_size=%d refcount=%d\n", + MAX_SEND_SIZE(xbus), + atomic_read(&xbus->transport.transport_refcount) + ); + len += sprintf(page + len, "\nSYNC: [%d] %-14s: DRIFT=%d %3ld sec ago\n", + xbus->sync_mode, sync_mode_name(xbus->sync_mode), xbus->sync_adjustment, + (xbus->pll_updated_at == 0) ? 0 : now.tv_sec - xbus->pll_updated_at); + len += sprintf(page + len, + "tick timing: avg = %3d usec stddev = %4d usec (count=%ld)\n", + xbus->timing.tick_avg, xbus->timing.tick_stddev, xbus->timing.timing_count); + len += sprintf(page + len, + "sync_offset_usec=%ld\n", xbus->sync_offset_usec); + len += sprintf(page + len, "PCM Metrices:\n"); + len += sprintf(page + len, "\tPCM TX: min=%ld max=%ld\n", + xbus->min_tx_sync, xbus->max_tx_sync); + len += sprintf(page + len, "\tPCM RX: min=%ld max=%ld\n", + xbus->min_rx_sync, xbus->max_rx_sync); + len += sprintf(page + len, "COUNTERS:\n"); + for(i = 0; i < XBUS_COUNTER_MAX; i++) { + len += sprintf(page + len, "\t%-15s = %d\n", + xbus_counters[i].name, xbus->counters[i]); + } + len += sprintf(page + len, "<-- len=%d\n", len); + /* reset statistics */ + xbus->min_tx_sync = INT_MAX; + xbus->max_tx_sync = 0; + xbus->min_rx_sync = INT_MAX; + xbus->max_rx_sync = 0; + spin_unlock_irqrestore(&xbus->lock, flags); + put_xbus(xbus); +out: + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; + +} + +static int xbus_read_waitfor_xpds(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + unsigned long flags; + xbus_t *xbus = data; + struct xbus_poller *poller; + int ret; + + if(!xbus) + goto out; + /* first handle special cases */ + if(!count || off) + goto out; + /* + * poller is created before /proc/XBUS-?? + * So by now it exists and initialized. + */ + poller = xbus->poller; + BUG_ON(!poller); + XBUS_DBG(DEVICES, xbus, + "Waiting for card initialization of %d XPD's max %d seconds\n", + atomic_read(&poller->count_xpds_to_initialize), INITIALIZATION_TIMEOUT/HZ); + /* + * when polling is finished xbus_poll(): + * - Unset poller->is_polling + * - Sets poller->count_xpds_to_initialize. + * So we wait until polling is finished (is_polling == 0) and: + * - No poll answers from Astribank (e.g: defective firmware). + * - Or no units to initialize (e.g: mini-AB with only main card). + * - Or we finished initializing all existing units. + * - Or A timeout passed. + */ + ret = wait_event_interruptible_timeout(poller->wait_for_xpd_initialization, + !poller->is_polling && ( + atomic_read(&poller->count_poll_answers) == 0 || + atomic_read(&poller->count_xpds_to_initialize) == 0 || + atomic_read(&poller->count_xpds_initialized) >= + atomic_read(&poller->count_xpds_to_initialize)), + INITIALIZATION_TIMEOUT); + if(ret == 0) { + XBUS_ERR(xbus, "Card Initialization Timeout\n"); + return ret; + } else if(ret < 0) { + XBUS_ERR(xbus, "Card Initialization Interrupted %d\n", ret); + return ret; + } else + XBUS_DBG(DEVICES, xbus, + "Finished initialization of %d XPD's in %d seconds.\n", + atomic_read(&poller->count_xpds_initialized), + (INITIALIZATION_TIMEOUT - ret)/HZ); + spin_lock_irqsave(&xbus->lock, flags); + len += sprintf(page + len, "XPDS_READY: %s: %d/%d\n", + xbus->busname, + atomic_read(&poller->count_xpds_initialized), + atomic_read(&poller->count_xpds_to_initialize)); + spin_unlock_irqrestore(&xbus->lock, flags); +out: + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; + +} + +#ifdef PROTOCOL_DEBUG +static int proc_xbus_command_write(struct file *file, const char __user *buffer, unsigned long count, void *data) +{ + char *buf; + xbus_t *xbus = data; + char *p; + byte *pack_start; + byte *q; + xframe_t *xframe; + size_t len; + const size_t max_len = xbus->transport.max_send_size; + const size_t max_text = max_len * 3 + 10; + + if(count > max_text) { + XBUS_ERR(xbus, "%s: line too long (%ld > %d)\n", __FUNCTION__, count, max_len); + return -EFBIG; + } + /* 3 bytes per hex-digit and space */ + buf = kmalloc(max_text, GFP_KERNEL); + if(!buf) + return -ENOMEM; + if(copy_from_user(buf, buffer, count)) { + count = -EINVAL; + goto out; + } + buf[count] = '\0'; + XBUS_DBG(GENERAL, xbus, "count=%ld\n", count); + /* + * We replace the content of buf[] from + * ascii representation to packet content + * as the binary representation is shorter + */ + q = pack_start = buf; + for(p = buf; *p;) { + int val; + char hexdigit[3]; + + while(*p && isspace(*p)) // skip whitespace + p++; + if(!(*p)) + break; + if(!isxdigit(*p)) { + XBUS_ERR(xbus, "%s: bad hex value ASCII='0x%X' at position %ld\n", + __FUNCTION__, *p, (long)(p - buf)); + count = -EINVAL; + goto out; + } + hexdigit[0] = *p++; + hexdigit[1] = '\0'; + hexdigit[2] = '\0'; + if(isxdigit(*p)) + hexdigit[1] = *p++; + if(sscanf(hexdigit, "%2X", &val) != 1) { + XBUS_ERR(xbus, "%s: bad hex value '%s' at position %ld\n", + __FUNCTION__, hexdigit, (long)(p - buf)); + count = -EINVAL; + goto out; + } + *q++ = val; + XBUS_DBG(GENERAL, xbus, "%3d> '%s' val=%d\n", q - pack_start, hexdigit, val); + } + len = q - pack_start; + xframe = ALLOC_SEND_XFRAME(xbus); + if(!xframe) { + count = -ENOMEM; + goto out; + } + if(len > max_len) + len = max_len; + atomic_set(&xframe->frame_len, len); + memcpy(xframe->packets, pack_start, len); /* FIXME: checksum? */ + dump_xframe("COMMAND", xbus, xframe); + send_cmd_frame(xbus, xframe); +out: + kfree(buf); + return count; +} +#endif + + +static int read_proc_xbuses(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + unsigned long flags; + int i; + + spin_lock_irqsave(&xbuses_lock, flags); + for(i = 0; i < MAX_BUSES; i++) { + xbus_t *xbus = get_xbus(i); + + if(xbus) { + len += sprintf(page + len, "%s: CONNECTOR=%s LABEL=[%s] STATUS=%s REFCOUNT=%d\n", + xbus->busname, + xbus->busdesc, + xbus->label, + (TRANSPORT_RUNNING(xbus)) ? "connected" : "missing", + refcount_xbus(i) - 1 + ); + put_xbus(xbus); + } + } +#if 0 + len += sprintf(page + len, "<-- len=%d\n", len); +#endif + spin_unlock_irqrestore(&xbuses_lock, flags); + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; + +} +#endif + +static void transport_init(xbus_t *xbus, struct xbus_ops *ops, ushort max_send_size, void *priv) +{ + BUG_ON(!xbus); + BUG_ON(!ops); + BUG_ON(!ops->xframe_send_pcm); + BUG_ON(!ops->xframe_send_cmd); + BUG_ON(!ops->alloc_xframe); + BUG_ON(!ops->free_xframe); + xbus->transport.ops = ops; + xbus->transport.max_send_size = max_send_size; + xbus->transport.priv = priv; + spin_lock_init(&xbus->transport.lock); + atomic_set(&xbus->transport.transport_refcount, 0); + init_waitqueue_head(&xbus->transport.transport_unused); +} + +void transport_destroy(xbus_t *xbus) +{ + int ret; + + BUG_ON(!xbus); + xbus->transport.transport_running = 0; + XBUS_INFO(xbus, "Waiting... (transport_refcount=%d)\n", + atomic_read(&xbus->transport.transport_refcount)); + ret = wait_event_interruptible(xbus->transport.transport_unused, + atomic_read(&xbus->transport.transport_refcount) == 0); + if(ret) + XBUS_ERR(xbus, "Waiting for transport_refcount interrupted!!!\n"); + xbus->transport.ops = NULL; + xbus->transport.priv = NULL; +} + +struct xbus_ops *transportops_get(xbus_t *xbus) +{ + struct xbus_ops *ops; + + BUG_ON(!xbus); + atomic_inc(&xbus->transport.transport_refcount); + ops = xbus->transport.ops; + if(!ops) + atomic_dec(&xbus->transport.transport_refcount); + /* fall through */ + return ops; +} + +void transportops_put(xbus_t *xbus) +{ + struct xbus_ops *ops; + + BUG_ON(!xbus); + ops = xbus->transport.ops; + BUG_ON(!ops); + if(atomic_dec_and_test(&xbus->transport.transport_refcount)) + wake_up(&xbus->transport.transport_unused); +} + +/*------------------------- Initialization -------------------------*/ +static void xbus_core_cleanup(void) +{ + finalize_xbuses_array(); +#ifdef XPP_DEBUGFS + if(debugfs_root) { + DBG(GENERAL, "Removing xpp from debugfs\n"); + debugfs_remove(debugfs_root); + } +#endif +#ifdef CONFIG_PROC_FS + if(proc_xbuses) { + DBG(PROC, "Removing " PROC_XBUSES " from proc\n"); + remove_proc_entry(PROC_XBUSES, xpp_proc_toplevel); + proc_xbuses = NULL; + } +#endif +} + +int __init xbus_core_init(void) +{ + int ret = 0; + + initialize_xbuses_array(); +#ifdef PROTOCOL_DEBUG + INFO("FEATURE: with PROTOCOL_DEBUG\n"); +#endif +#ifdef XPP_DEBUGFS + INFO("FEATURE: with XPP_DEBUGFS support\n"); +#endif +#ifdef CONFIG_PROC_FS + proc_xbuses = create_proc_read_entry(PROC_XBUSES, 0444, xpp_proc_toplevel, read_proc_xbuses, NULL); + if (!proc_xbuses) { + ERR("Failed to create proc file %s\n", PROC_XBUSES); + ret = -EFAULT; + goto err; + } + proc_xbuses->owner = THIS_MODULE; +#endif +#ifdef XPP_DEBUGFS + DBG(GENERAL, "Creating debugfs xpp root\n"); + debugfs_root = debugfs_create_dir("xpp", NULL); + if(!debugfs_root) { + ERR("Failed to create debugfs root\n"); + ret = -EFAULT; + goto err; + } +#endif + if((ret = register_xpp_bus()) < 0) + goto err; + return 0; +err: + xbus_core_cleanup(); + return ret; +} + + +void __exit xbus_core_shutdown(void) +{ + int i; + + for(i = 0; i < MAX_BUSES; i++) { + xbus_t *xbus = get_xbus(i); + + if(xbus) { + xbus_remove(xbus); + } + } + BUG_ON(bus_count); + unregister_xpp_bus(); + xbus_core_cleanup(); +} + +EXPORT_SYMBOL(xpd_of); +EXPORT_SYMBOL(xpd_byaddr); +EXPORT_SYMBOL(get_xbus); +EXPORT_SYMBOL(put_xbus); +EXPORT_SYMBOL(xbus_new); +EXPORT_SYMBOL(xbus_remove); +EXPORT_SYMBOL(xbus_activate); +EXPORT_SYMBOL(xbus_disconnect); +EXPORT_SYMBOL(xbus_receive_xframe); +EXPORT_SYMBOL(xbus_reset_counters); +EXPORT_SYMBOL(xframe_next_packet); +EXPORT_SYMBOL(dump_xframe); +EXPORT_SYMBOL(send_pcm_frame); +EXPORT_SYMBOL(send_cmd_frame); +EXPORT_SYMBOL(xframe_init); +EXPORT_SYMBOL(transportops_get); +EXPORT_SYMBOL(transportops_put); +EXPORT_SYMBOL(xbus_poller_notify); +EXPORT_SYMBOL(xbus_command_queue_tick); +#ifdef XPP_DEBUGFS +EXPORT_SYMBOL(xbus_log); +#endif diff --git a/kernel/xpp/xbus-core.h b/kernel/xpp/xbus-core.h new file mode 100644 index 0000000..de6e859 --- /dev/null +++ b/kernel/xpp/xbus-core.h @@ -0,0 +1,278 @@ +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#ifndef XBUS_CORE_H +#define XBUS_CORE_H + +#include +#include /* for tasklets */ +#include "xpd.h" +#include "xframe_queue.h" +#include "xbus-pcm.h" + +#define MAX_BUSES 32 +#define XFRAME_DATASIZE 512 + +/* forward declarations */ +struct xbus_poller; +#ifdef XPP_DEBUGFS +struct debugfs_data; +#endif + +#ifdef __KERNEL__ + +struct xbus_ops { + int (*xframe_send_pcm)(xbus_t *xbus, xframe_t *xframe); + int (*xframe_send_cmd)(xbus_t *xbus, xframe_t *xframe); + xframe_t *(*alloc_xframe)(xbus_t *xbus, gfp_t gfp_flags); + void (*free_xframe)(xbus_t *xbus, xframe_t *xframe); +}; + +/* + * XBUS statistics counters + */ +enum { + XBUS_N_DESC_REQ, + XBUS_N_DEV_DESC_FULL, + XBUS_N_DEV_DESC_EMPTY, + XBUS_N_TX_XFRAME_PCM, + XBUS_N_RX_XFRAME_PCM, + XBUS_N_TX_PACK_PCM, + XBUS_N_RX_PACK_PCM, + XBUS_N_TX_BYTES, + XBUS_N_RX_BYTES, + XBUS_N_TX_PCM_FRAG, + XBUS_N_TX_CMD, +}; + +#define XBUS_COUNTER(xbus, counter) ((xbus)->counters[XBUS_N_ ## counter]) + +#define C_(x) [ XBUS_N_ ## x ] = { #x } + +/* yucky, make an instance so we can size it... */ +static struct xbus_counters { + char *name; +} xbus_counters[] = { + C_(DESC_REQ), + C_(DEV_DESC_FULL), + C_(DEV_DESC_EMPTY), + C_(TX_XFRAME_PCM), + C_(RX_XFRAME_PCM), + C_(TX_PACK_PCM), + C_(RX_PACK_PCM), + C_(TX_BYTES), + C_(RX_BYTES), + C_(TX_PCM_FRAG), + C_(TX_CMD), +}; + +#undef C_ + +#define XBUS_COUNTER_MAX ARRAY_SIZE(xbus_counters) + +struct xbus_transport { + struct xbus_ops *ops; + void *priv; + ushort max_send_size; + bool transport_running; /* Hardware is functional */ + atomic_t transport_refcount; + wait_queue_head_t transport_unused; + spinlock_t lock; +}; + +#define MAX_SEND_SIZE(xbus) ((xbus)->transport.max_send_size) +#define TRANSPORT_RUNNING(xbus) ((xbus)->transport.transport_running) +#define TRANSPORT_EXIST(xbus) ((xbus)->transport.ops != NULL) + +struct xbus_ops *transportops_get(xbus_t *xbus); +void transportops_put(xbus_t *xbus); + +/* + * Allocate/Free an xframe from pools of empty xframes. + * Calls to {get,put}_xframe are wrapped in + * the macros bellow, so we take/return it + * to the correct pool. + */ +xframe_t *get_xframe(struct xframe_queue *q); +void put_xframe(struct xframe_queue *q, xframe_t *xframe); + +#define ALLOC_SEND_XFRAME(xbus) get_xframe(&(xbus)->send_pool) +#define ALLOC_RECV_XFRAME(xbus) get_xframe(&(xbus)->receive_pool) +#define FREE_SEND_XFRAME(xbus, xframe) put_xframe(&(xbus)->send_pool, (xframe)) +#define FREE_RECV_XFRAME(xbus, xframe) put_xframe(&(xbus)->receive_pool, (xframe)) + +xbus_t *get_xbus(uint num); +void put_xbus(xbus_t *xbus); + +/* + * An xbus is a transport layer for Xorcom Protocol commands + */ +struct xbus { + char busname[XBUS_NAMELEN]; /* set by xbus_new() */ + + /* low-level bus drivers set these 2 fields */ + char busdesc[XBUS_DESCLEN]; + char label[LABEL_SIZE]; + struct xbus_transport transport; + + int num; + struct xpd *xpds[MAX_XPDS]; + + struct xframe_queue command_queue; + wait_queue_head_t command_queue_empty; + + struct xframe_queue send_pool; /* empty xframes for send */ + struct xframe_queue receive_pool; /* empty xframes for receive */ + + /* tasklet processing */ + struct xframe_queue receive_queue; + struct tasklet_struct receive_tasklet; + int cpu_rcv_intr[NR_CPUS]; + int cpu_rcv_tasklet[NR_CPUS]; + + bool self_ticking; + enum sync_mode sync_mode; + struct timer_list command_timer; + unsigned int xbus_frag_count; + struct xframe_queue pcm_tospan[2]; /* double buffer */ + struct xpp_timing timing; + atomic_t pcm_rx_counter; + unsigned int global_counter; + long sync_offset_usec; + + /* Device-Model */ + struct device astribank; +#define dev_to_xbus(dev) container_of(dev, struct xbus, astribank) + + spinlock_t lock; + atomic_t xbus_ref_count; /* How many need this struct? */ + + /* PCM metrics */ + struct timeval last_tx_sync; + struct timeval last_rx_sync; + unsigned long max_tx_sync; + unsigned long min_tx_sync; + unsigned long max_rx_sync; + unsigned long min_rx_sync; + unsigned long max_rx_process; /* packet processing time (usec) */ + + struct xbus_poller *poller; + + /* + * Sync adjustment + */ + int sync_adjustment; + int sync_adjustment_offset; + long pll_updated_at; + + struct rw_semaphore in_use; +#define XBUS_GET(xbus) down_read_trylock(&(xbus)->in_use) +#define XBUS_PUT(xbus) up_read(&(xbus)->in_use) + + int num_xpds; + +#ifdef XPP_DEBUGFS + struct dentry *debugfs_dir; + struct dentry *debugfs_file; + struct debugfs_data *debugfs_data; +#endif +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *proc_xbus_dir; + struct proc_dir_entry *proc_xbus_summary; +#ifdef PROTOCOL_DEBUG + struct proc_dir_entry *proc_xbus_command; +#endif +#endif + + /* statistics */ + int counters[XBUS_COUNTER_MAX]; +}; +#endif + +#define XFRAME_MAGIC 123456L + +struct xframe { + unsigned long xframe_magic; + struct list_head frame_list; + atomic_t frame_len; + xbus_t *xbus; + struct timeval tv_created; + struct timeval tv_queued; + struct timeval tv_submitted; + struct timeval tv_received; + /* filled by transport layer */ + size_t frame_maxlen; + byte *packets; /* max XFRAME_DATASIZE */ + byte *first_free; + void *priv; +}; + +void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize, void *priv); + +#define XFRAME_LEN(frame) atomic_read(&(frame)->frame_len) + +int xbus_core_init(void); /* Initializer */ +void xbus_core_shutdown(void); /* Terminator */ + +#ifdef XPP_DEBUGFS +/* Debugfs handling */ +int xbus_log(xbus_t *xbus, xpd_t *xpd, int direction, const void *buf, unsigned long len); +#endif + +/* Frame handling */ +void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe); +int send_cmd_frame(xbus_t *xbus, xframe_t *xframe); + +/* + * Return pointer to next packet slot in the frame + * or NULL if the frame is full. + */ +xpacket_t *xframe_next_packet(xframe_t *xframe, int len); + +/* XBUS handling */ + +/* + * Map: unit+subunit <--> index in xbus->xpds[] + */ +#define XPD_IDX(unit,subunit) ((unit) * MAX_SUBUNIT + (subunit)) +#define XBUS_UNIT(idx) ((idx) / MAX_SUBUNIT) +#define XBUS_SUBUNIT(idx) ((idx) % MAX_SUBUNIT) + +xpd_t *xpd_of(const xbus_t *xbus, int xpd_num); +xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit); +xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, void *priv); +void xbus_remove(xbus_t *xbus); +int xbus_activate(xbus_t *xbus); +void xbus_disconnect(xbus_t *xbus); +void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe); + +void xbus_poller_notify(xbus_t *xbus, struct card_desc_struct *card_desc); +int xbus_register_xpd(xbus_t *xbus, xpd_t *xpd); +int xbus_unregister_xpd(xbus_t *xbus, xpd_t *xpd); + +/* sysfs */ +int register_xpp_bus(void); +void unregister_xpp_bus(void); +int xbus_sysfs_create(xbus_t *xbus); +void xbus_sysfs_remove(xbus_t *xbus); + +#endif /* XBUS_CORE_H */ + diff --git a/kernel/xpp/xbus-pcm.c b/kernel/xpp/xbus-pcm.c new file mode 100644 index 0000000..0b1e5d1 --- /dev/null +++ b/kernel/xpp/xbus-pcm.c @@ -0,0 +1,1168 @@ +/* + * Written by Oron Peled + * Copyright (C) 2004-2007, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +# warning "This module is tested only with 2.6 kernels" +#endif + +#include +#include +#include "xbus-pcm.h" +#include "xbus-core.h" +#include "xpp_zap.h" +#include "zap_debug.h" +#include "parport_debug.h" + +static const char rcsid[] = "$Id$"; + +extern int print_dbg; +#ifdef XPP_EC_CHUNK +#include "supress/ec_xpp.h" +DEF_PARM_BOOL(xpp_ec, 0, 0444, "Do we use our own (1) or Zaptel's (0) echo canceller"); +#endif +#ifdef OPTIMIZE_CHANMUTE +DEF_PARM_BOOL(optimize_chanmute, 1, 0644, "Optimize by muting inactive channels"); +#endif + +DEF_PARM(int, disable_pcm, 0, 0644, "Disable all PCM transmissions"); +#ifdef DEBUG_PCMTX +DEF_PARM(int, pcmtx, -1, 0644, "Forced PCM value to transmit (negative to disable)"); +DEF_PARM(int, pcmtx_chan, 0, 0644, "channel to force PCM value"); +#endif +DEF_PARM_BOOL(pcm_tasklet, 0, 0644, "Handle PCM in a tasklet (lower interrupt load)"); +#define PCM_TASKLET_DEPRECATION "\n" \ + "====================================================================\n" \ + "CONFIGURATION ERROR: 'pcm_tasklet' module parameter is deprecated!!!\n" \ + "====================================================================\n" + +static xbus_t *syncer; /* current syncer */ +static struct xpp_timing ref_sync; +static atomic_t xpp_tick_counter; +static const struct xpp_timing *global_ticker; /* increment xpp_tick_counter */ +static bool zaptel_syncer = 0; + +#define PROC_SYNC "sync" +#define BIG_TICK_INTERVAL 1000 +#define SYNC_ADJ_MIN (-30) /* minimal firmware drift unit */ +#define SYNC_ADJ_MAX 30 /* maximal firmware drift unit */ +#define SYNC_ADJ_FACTOR(x) ((x) / 30) /* average usec/drift_unit */ + +#ifdef ZAPTEL_SYNC_TICK +static unsigned int zaptel_tick_count = 0; +#endif + +/*------------------------- SYNC Handling --------------------------*/ + + +const char *sync_mode_name(enum sync_mode mode) +{ + static const char *sync_mode_names[] = { + [SYNC_MODE_AB] "SYNC_MODE_AB", + [SYNC_MODE_NONE] "SYNC_MODE_NONE", + [SYNC_MODE_PLL] "SYNC_MODE_PLL", + [SYNC_MODE_QUERY] "SYNC_MODE_QUERY", + }; + if(mode >= ARRAY_SIZE(sync_mode_names)) + return NULL; + return sync_mode_names[mode]; +} + +static void xpp_set_syncer(xbus_t *xbus, bool on) +{ + if(syncer != xbus && on) { + XBUS_DBG(SYNC, xbus, "New syncer\n"); + syncer = xbus; + } else if(syncer == xbus && !on) { + XBUS_DBG(SYNC, xbus, "Lost syncer\n"); + syncer = NULL; + } else + XBUS_DBG(SYNC, xbus, "ignore %s (current syncer: %s)\n", + (on)?"ON":"OFF", + (syncer) ? syncer->busname : "NO-SYNC"); +} + +void xpp_timing_init(struct xpp_timing *timing, const char *name) +{ + memset(timing, 0, sizeof(*timing)); + do_gettimeofday(&timing->timing_val); + spin_lock_init(&timing->lock); + timing->name = name; +} + +#define XPP_TIMING_SAMPLES 50 +#define XPP_TIMING_TICKS 100 +#define XPP_TIMING_MAX_STDDEV 500 + +static void xpp_timing_tick(struct xpp_timing *timing, const struct timeval *val) +{ + long usec; + int diff_sec; + int diff_usec; + unsigned long flags; + + spin_lock_irqsave(&timing->lock, flags); + if((timing->timing_count % XPP_TIMING_TICKS) != 0) + goto out; + diff_sec = val->tv_sec - timing->timing_val.tv_sec; + diff_usec = val->tv_usec - timing->timing_val.tv_usec; + timing->timing_val = *val; + /* ignore first batch of samples */ + if(timing->timing_count < (XPP_TIMING_TICKS * XPP_TIMING_SAMPLES)) + goto out; + if(abs(diff_sec) > 2) { + static int rate_limit; + + if((rate_limit++ % 1003) == 0) + NOTICE("TIMING(%s): bad timing: diff_sec=%d\n", + timing->name, diff_sec); + goto out; + } + usec = diff_sec * 1000000 + diff_usec; + if(usec) + timing->tick_rate = XPP_TIMING_TICKS * 1000000 / usec; + usec -= 1000 * XPP_TIMING_TICKS; /* normalize */ + + timing->accumulated_usec += usec; + timing->accumulated_usec_sqr += usec * usec; + if((timing->timing_count % (XPP_TIMING_TICKS * XPP_TIMING_SAMPLES)) == 0) { + int avg; + int stddev; + + avg = timing->accumulated_usec / XPP_TIMING_SAMPLES; + stddev = (timing->accumulated_usec_sqr / XPP_TIMING_SAMPLES); + stddev = int_sqrt(stddev); + timing->accumulated_usec = 0; + timing->accumulated_usec_sqr = 0; + if(stddev > XPP_TIMING_MAX_STDDEV) { + static int rate_limit; + + if((rate_limit++ % 1003) == 0) + NOTICE("TIMING(%s): bad timing: stddev=%d avg=%d\n", + timing->name, stddev, avg); + goto out; + } + timing->tick_avg = avg; + timing->tick_stddev = stddev; + } +out: + timing->timing_count++; + if(timing == global_ticker) + atomic_inc(&xpp_tick_counter); + spin_unlock_irqrestore(&timing->lock, flags); +} + +void xbus_command_timer(unsigned long param) +{ + xbus_t *xbus = (xbus_t *)param; + struct timeval now; + + BUG_ON(!xbus); + do_gettimeofday(&now); + xbus_command_queue_tick(xbus); + if(!xbus->self_ticking) + mod_timer(&xbus->command_timer, jiffies + 1); /* Must be 1KHz rate */ +} + +void xbus_set_command_timer(xbus_t *xbus, bool on) +{ + XBUS_DBG(SYNC, xbus, "%s\n", (on)?"ON":"OFF"); + if(on) { + if(!timer_pending(&xbus->command_timer)) { + XBUS_DBG(SYNC, xbus, "add_timer\n"); + xbus->command_timer.function = xbus_command_timer; + xbus->command_timer.data = (unsigned long)xbus; + xbus->command_timer.expires = jiffies + 1; + add_timer(&xbus->command_timer); + xbus->self_ticking = 0; + } + } else if(timer_pending(&xbus->command_timer)) { + xbus->self_ticking = 1; + XBUS_DBG(SYNC, xbus, "del_timer\n"); + del_timer(&xbus->command_timer); + } +} + +/* + * Called when the Astribank replies to a sync change request + */ +void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift) +{ + unsigned long flags; + + XBUS_DBG(SYNC, xbus, "%s (%d), drift=%d (pcm_rx_counter=%d)\n", + sync_mode_name(mode), mode, drift, atomic_read(&xbus->pcm_rx_counter)); + spin_lock_irqsave(&xbus->lock, flags); + xbus->sync_adjustment = (signed char)drift; + if(xbus->sync_mode == mode) { + XBUS_DBG(SYNC, xbus, "Already in %s. Ignored\n", sync_mode_name(mode)); + goto out; + } + switch(mode) { + case SYNC_MODE_AB: + xbus->sync_mode = mode; + xbus_set_command_timer(xbus, 0); + xpp_set_syncer(xbus, 1); + break; + case SYNC_MODE_PLL: + xbus->sync_mode = mode; + xbus_set_command_timer(xbus, 0); + xpp_set_syncer(xbus, 0); + break; + case SYNC_MODE_NONE: /* lost sync source */ + xbus->sync_mode = mode; + xbus_set_command_timer(xbus, 1); + xpp_set_syncer(xbus, 0); + break; + case SYNC_MODE_QUERY: /* ignore */ + break; + default: + XBUS_ERR(xbus, "%s: unknown mode=0x%X\n", __FUNCTION__, mode); + } +out: + spin_unlock_irqrestore(&xbus->lock, flags); +} + +void xbus_request_sync(xbus_t *xbus, enum sync_mode mode) +{ + BUG_ON(!xbus); + XBUS_DBG(SYNC, xbus, "sent request (mode=%d)\n", mode); + CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, mode, 0); +} + +static void reset_sync_counters(void) +{ + int i; + + //DBG(SYNC, "%d\n", atomic_read(&xpp_tick_counter)); + for(i = 0; i < MAX_BUSES; i++) { + xbus_t *xbus = get_xbus(i); + + if(!xbus) + continue; + if (TRANSPORT_RUNNING(xbus)) { + if(XBUS_GET(xbus)) { + /* Reset sync LEDs once in a while */ + CALL_PROTO(GLOBAL, RESET_SYNC_COUNTERS, xbus, NULL); + XBUS_PUT(xbus); + } else { + static int rate_limit; + + if((rate_limit++ % 1003) == 0) + XBUS_DBG(GENERAL, xbus, + "Dropped packet. Is shutting down. (%d)\n", rate_limit); + } + } + put_xbus(xbus); + } +} + +static void send_drift(xbus_t *xbus, int drift) +{ + struct timeval now; + const char *msg; + + BUG_ON(drift < SYNC_ADJ_MIN || drift > SYNC_ADJ_MAX); + do_gettimeofday(&now); + if(drift > xbus->sync_adjustment) + msg = "up"; + else + msg = "down"; + XBUS_DBG(SYNC, xbus, "DRIFT adjust %s (%d) (last update %ld seconds ago)\n", + msg, drift, now.tv_sec - xbus->pll_updated_at); + CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_PLL, drift); + xbus->pll_updated_at = now.tv_sec; +} + +#ifdef ZAPTEL_SYNC_TICK +int zaptel_sync_tick(struct zt_span *span, int is_master) +{ + xpd_t *xpd = span->pvt; + struct timeval now; + static int redundant_ticks; /* for extra spans */ + + if(!zaptel_syncer) + goto noop; + BUG_ON(!xpd); + /* + * Detect if any of our spans is zaptel sync master + */ + if(is_master) { + static int rate_limit; + + if(xpd->xbus != syncer && ((rate_limit % 1003) == 0)) { + XPD_ERR(xpd, + "Zaptel master, but syncer=%s\n", + xpd->xbus->busname); + } + if((rate_limit % 5003) == 0) + XPD_NOTICE(xpd, "Zaptel master: ignore ZAPTEL sync\n"); + rate_limit++; + goto noop; + } + /* Now we know for sure someone else is zaptel sync master */ + if(syncer) { + static int rate_limit; + + if((rate_limit++ % 5003) == 0) + XBUS_DBG(SYNC, syncer, + "Already a syncer, ignore ZAPTEL sync\n"); + goto noop; + } + /* ignore duplicate calls from all our registered spans */ + if((redundant_ticks++ % total_registered_spans()) != 0) { +#if 0 + static int rate_limit; + + if((rate_limit++ % 1003) < 16) + XPD_NOTICE(xpd, "boop (%d)\n", zaptel_tick_count); +#endif + goto noop; + } + do_gettimeofday(&now); + xpp_timing_tick(&ref_sync, &now); + zaptel_tick_count++; + flip_parport_bit(1); + return 0; +noop: + return 0; /* No auto sync from zaptel */ +} +#endif + + +static void sync_rate_adjust(xbus_t *xbus) +{ + int offset; + + xbus->sync_offset_usec = xbus->timing.tick_avg - ref_sync.tick_avg; + /* Calculate required PLL fix */ + offset = SYNC_ADJ_FACTOR(xbus->sync_offset_usec); + if(offset < SYNC_ADJ_MIN) + offset = SYNC_ADJ_MIN; + if(offset > SYNC_ADJ_MAX) + offset = SYNC_ADJ_MAX; + xbus->sync_adjustment_offset = offset; + if(xbus != syncer && xbus->sync_adjustment != offset) + send_drift(xbus, offset); +} + +/* + * called from elect_syncer() + * if new_syncer is NULL, than we move all to SYNC_MODE_PLL + * for ZAPTEL sync. + */ +static void update_sync_master(xbus_t *new_syncer) +{ + const char *msg = (zaptel_syncer) ? "ZAPTEL" : "NO-SYNC"; + int i; + + DBG(SYNC, "%s => %s\n", + (syncer) ? syncer->busname : msg, + (new_syncer) ? new_syncer->busname : msg); + if(new_syncer) { + XBUS_DBG(SYNC, new_syncer, "pcm_rx_counter=%d\n", + atomic_read(&new_syncer->pcm_rx_counter)); + zaptel_syncer = 0; + global_ticker = &new_syncer->timing; + xbus_request_sync(new_syncer, SYNC_MODE_AB); + } else + global_ticker = &ref_sync; + DBG(SYNC, "stop unwanted syncers\n"); + /* Shut all down except the wanted sync master */ + for(i = 0; i < MAX_BUSES; i++) { + xbus_t *xbus = get_xbus(i); + if(!xbus) + continue; + if(TRANSPORT_RUNNING(xbus) && xbus != new_syncer) { + if(xbus->self_ticking) + xbus_request_sync(xbus, SYNC_MODE_PLL); + else + XBUS_DBG(SYNC, xbus, "Not self_ticking yet. Ignore\n"); + } + put_xbus(xbus); + } +} + +void elect_syncer(const char *msg) +{ + int i; + int j; + uint timing_priority = 0; + xpd_t *best_xpd = NULL; + xbus_t *the_xbus = NULL; + + for(i = 0; i < MAX_BUSES; i++) { + xbus_t *xbus = get_xbus(i); + if(!xbus) + continue; + if(!the_xbus) + the_xbus = xbus; + if (TRANSPORT_RUNNING(xbus)) { + for(j = 0; j < MAX_XPDS; j++) { + xpd_t *xpd = xpd_of(xbus, j); + + if(!xpd) + continue; + if(xpd->timing_priority > timing_priority) { + timing_priority = xpd->timing_priority; + best_xpd = xpd; + } + } + } + put_xbus(xbus); + } + if(best_xpd) { + the_xbus = best_xpd->xbus; + XPD_DBG(SYNC, best_xpd, "%s: elected with priority %d\n", msg, timing_priority); + } else if(the_xbus) { + XBUS_DBG(SYNC, the_xbus, "%s: elected\n", msg); + } else + DBG(SYNC, "%s: No more syncers\n", msg); + if(the_xbus != syncer) + update_sync_master(the_xbus); +} + +/* + * This function is used by FXS/FXO. The pcm_mask argument signifies + * channels which should be *added* to the automatic calculation. + * Normally, this argument is 0. + * + * The caller should spinlock the XPD before calling it. + */ +void __pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask) +{ + int i; + int line_count = 0; + + /* Add/remove all the trivial cases */ + pcm_mask |= xpd->offhook; + pcm_mask |= xpd->cid_on; + pcm_mask &= ~xpd->digital_signalling; /* No PCM in D-Channels */ + pcm_mask &= ~xpd->digital_inputs; + pcm_mask &= ~xpd->digital_outputs; + for_each_line(xpd, i) + if(IS_SET(pcm_mask, i)) + line_count++; + /* + * FIXME: Workaround a bug in sync code of the Astribank. + * Send dummy PCM for sync. + */ + if(xpd->addr.unit == 0 && pcm_mask == 0) { + pcm_mask = BIT(0); + line_count = 1; + } + xpd->pcm_len = (line_count) + ? RPACKET_HEADERSIZE + sizeof(xpp_line_t) + line_count * ZT_CHUNKSIZE + : 0L; + xpd->wanted_pcm_mask = pcm_mask; +} + +/* + * A spinlocked version of __pcm_recompute() + */ +void pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask) +{ + unsigned long flags; + + spin_lock_irqsave(&xpd->lock, flags); + __pcm_recompute(xpd, pcm_mask); + spin_unlock_irqrestore(&xpd->lock, flags); +} + +void fill_beep(u_char *buf, int num, int duration) +{ + bool alternate = (duration) ? (jiffies/(duration*1000)) & 0x1 : 0; + int which; + u_char *snd; + + /* + * debug tones + */ + static u_char beep[] = { + 0x7F, 0xBE, 0xD8, 0xBE, 0x80, 0x41, 0x24, 0x41, /* Dima */ + 0x67, 0x90, 0x89, 0x90, 0xFF, 0x10, 0x09, 0x10, /* Izzy */ + }; + static u_char beep_alt[] = { + 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, /* silence */ + }; + if(alternate) { + which = num % ARRAY_SIZE(beep_alt); + snd = &beep_alt[which]; + } else { + which = num % ARRAY_SIZE(beep); + snd = &beep[which]; + } + memcpy(buf, snd, ZT_CHUNKSIZE); +} + +#ifdef XPP_EC_CHUNK +/* + * Taken from zaptel.c + */ +static inline void xpp_ec_chunk(struct zt_chan *chan, unsigned char *rxchunk, const unsigned char *txchunk) +{ + int16_t rxlin; + int x; + unsigned long flags; + + /* Perform echo cancellation on a chunk if necessary */ + if (!chan->ec) + return; + spin_lock_irqsave(&chan->lock, flags); + for (x=0;xec, ZT_XLAW(txchunk[x], chan), rxlin); + rxchunk[x] = ZT_LIN2X((int)rxlin, chan); + } + spin_unlock_irqrestore(&chan->lock, flags); +} +#endif + +static void do_ec(xpd_t *xpd) +{ + struct zt_chan *chans = xpd->span.chans; + int i; + +#ifdef WITH_ECHO_SUPPRESSION + /* FIXME: need to Echo cancel double buffered data */ + for (i = 0;i < xpd->span.channels; i++) { + if(unlikely(IS_SET(xpd->digital_signalling, i))) /* Don't echo cancel BRI D-chans */ + continue; +#ifdef XPP_EC_CHUNK + /* even if defined, parameterr xpp_ec can override at run-time */ + if (xpp_ec) + xpp_ec_chunk(&chans[i], chans[i].readchunk, xpd->ec_chunk2[i]); + else +#endif + zt_ec_chunk(&chans[i], chans[i].readchunk, xpd->ec_chunk2[i]); + memcpy(xpd->ec_chunk2[i], xpd->ec_chunk1[i], ZT_CHUNKSIZE); + memcpy(xpd->ec_chunk1[i], chans[i].writechunk, ZT_CHUNKSIZE); + } +#endif +} + +#if 0 +/* Okay, now we get to the signalling. You have several options: */ + +/* Option 1: If you're a T1 like interface, you can just provide a + rbsbits function and we'll assert robbed bits for you. Be sure to + set the ZT_FLAG_RBS in this case. */ + +/* Opt: If the span uses A/B bits, set them here */ +int (*rbsbits)(struct zt_chan *chan, int bits); + +/* Option 2: If you don't know about sig bits, but do have their + equivalents (i.e. you can disconnect battery, detect off hook, + generate ring, etc directly) then you can just specify a + sethook function, and we'll call you with appropriate hook states + to set. Still set the ZT_FLAG_RBS in this case as well */ +int (*hooksig)(struct zt_chan *chan, zt_txsig_t hookstate); + +/* Option 3: If you can't use sig bits, you can write a function + which handles the individual hook states */ +int (*sethook)(struct zt_chan *chan, int hookstate); +#endif + +int xpp_echocan(struct zt_chan *chan, int len) +{ +#ifdef XPP_EC_CHUNK + if(len == 0) { /* shut down */ + /* zaptel calls this also during channel initialization */ + if(chan->ec) { + xpp_echo_can_free(chan->ec); + } + return 0; + } + if(chan->ec) { + ERR("%s: Trying to override an existing EC (%p)\n", __FUNCTION__, chan->ec); + return -EINVAL; + } + chan->ec = xpp_echo_can_create(len, 0); + if(!chan->ec) { + ERR("%s: Failed creating xpp EC (len=%d)\n", __FUNCTION__, len); + return -EINVAL; + } +#endif + return 0; +} + +static bool pcm_valid(xpd_t *xpd, xpacket_t *pack) +{ + xpp_line_t lines = RPACKET_FIELD(pack, GLOBAL, PCM_READ, lines); + int i; + int count = 0; + uint16_t good_len; + + BUG_ON(!pack); + BUG_ON(XPACKET_OP(pack) != XPROTO_NAME(GLOBAL, PCM_READ)); + /* + * Don't use for_each_line(xpd, i) here because for BRI it will + * ignore the channels of the other xpd's in the same unit. + */ + for (i = 0; i < CHANNELS_PERXPD; i++) + if(IS_SET(lines, i)) + count++; + /* FRAMES: include opcode in calculation */ + good_len = RPACKET_HEADERSIZE + sizeof(xpp_line_t) + count * 8; + if(XPACKET_LEN(pack) != good_len) { + static int rate_limit = 0; + + XPD_COUNTER(xpd, RECV_ERRORS)++; + if((rate_limit++ % 1000) <= 10) { + XPD_ERR(xpd, "BAD PCM REPLY: packet_len=%d (should be %d), count=%d\n", + XPACKET_LEN(pack), good_len, count); + dump_packet("BAD PCM REPLY", pack, 1); + } + return 0; + } + return 1; +} + + + +static inline void pcm_frame_out(xbus_t *xbus, xframe_t *xframe) +{ + unsigned long flags; + struct timeval now; + unsigned long usec; + + spin_lock_irqsave(&xbus->lock, flags); + do_gettimeofday(&now); + if(unlikely(disable_pcm || !TRANSPORT_RUNNING(xbus))) + goto dropit; + if(XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) { + usec = usec_diff(&now, &xbus->last_tx_sync); + xbus->last_tx_sync = now; + /* ignore startup statistics */ + if(likely(atomic_read(&xbus->pcm_rx_counter) > BIG_TICK_INTERVAL)) { + if(abs(usec - 1000) > TICK_TOLERANCE) { + static int rate_limit; + + if((rate_limit++ % 5003) == 0) + XBUS_DBG(SYNC, xbus, "Bad PCM TX timing(%d): usec=%ld.\n", + rate_limit, usec); + } + if(usec > xbus->max_tx_sync) + xbus->max_tx_sync = usec; + if(usec < xbus->min_tx_sync) + xbus->min_tx_sync = usec; + } + } + spin_unlock_irqrestore(&xbus->lock, flags); + /* OK, really send it */ + if(print_dbg & DBG_PCM ) + dump_xframe("TX_XFRAME_PCM", xbus, xframe); + send_pcm_frame(xbus, xframe); + XBUS_COUNTER(xbus, TX_XFRAME_PCM)++; + return; +dropit: + spin_unlock_irqrestore(&xbus->lock, flags); + FREE_SEND_XFRAME(xbus, xframe); +} + +/* + * Generic implementations of card_pcmfromspan()/card_pcmtospan() + * For FXS/FXO + */ +void generic_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, xpacket_t *pack) +{ + byte *pcm; + struct zt_chan *chans; + unsigned long flags; + int i; + + BUG_ON(!xbus); + BUG_ON(!xpd); + BUG_ON(!pack); + RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = lines; + pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm); + spin_lock_irqsave(&xpd->lock, flags); + chans = xpd->span.chans; + for (i = 0; i < xpd->channels; i++) { + if(IS_SET(lines, i)) { + if(SPAN_REGISTERED(xpd)) { +#ifdef DEBUG_PCMTX + if(pcmtx >= 0 && pcmtx_chan == i) + memset((u_char *)pcm, pcmtx, ZT_CHUNKSIZE); + else +#endif + memcpy((u_char *)pcm, chans[i].writechunk, ZT_CHUNKSIZE); + // fill_beep((u_char *)pcm, xpd->addr.subunit, 2); + } else + memset((u_char *)pcm, 0x7F, ZT_CHUNKSIZE); + pcm += ZT_CHUNKSIZE; + } + } + XPD_COUNTER(xpd, PCM_WRITE)++; + spin_unlock_irqrestore(&xpd->lock, flags); +} + +void generic_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack) +{ + byte *pcm; + xpp_line_t pcm_mask; + unsigned long flags; + int i; + + pcm = RPACKET_FIELD(pack, GLOBAL, PCM_READ, pcm); + pcm_mask = RPACKET_FIELD(pack, GLOBAL, PCM_READ, lines); + spin_lock_irqsave(&xpd->lock, flags); + if(!SPAN_REGISTERED(xpd)) + goto out; + for (i = 0; i < xpd->channels; i++) { + volatile u_char *r = xpd->span.chans[i].readchunk; + + if(!IS_SET(xpd->wanted_pcm_mask, i)) { + if(IS_SET(xpd->silence_pcm, i)) + memset((u_char *)r, 0x7F, ZT_CHUNKSIZE); // SILENCE + continue; + } + pcm_mask &= ~xpd->mute_dtmf; + if(IS_SET(pcm_mask, i)) { + // memset((u_char *)r, 0x5A, ZT_CHUNKSIZE); // DEBUG + // fill_beep((u_char *)r, 1, 1); // DEBUG: BEEP + memcpy((u_char *)r, pcm, ZT_CHUNKSIZE); + pcm += ZT_CHUNKSIZE; + } else { + memset((u_char *)r, 0x7F, ZT_CHUNKSIZE); // SILENCE + } + } +out: + XPD_COUNTER(xpd, PCM_READ)++; + spin_unlock_irqrestore(&xpd->lock, flags); +} + +static int copy_pcm_tospan(xbus_t *xbus, xframe_t *xframe) +{ + byte *xframe_end; + xpacket_t *pack; + byte *p; + int ret = -EPROTO; /* Assume error */ + + if(print_dbg & DBG_PCM) + dump_xframe("RX_XFRAME_PCM", xbus, xframe); + /* handle content */ + + p = xframe->packets; + xframe_end = p + XFRAME_LEN(xframe); + do { + int len; + xpd_t *xpd; + + pack = (xpacket_t *)p; + len = XPACKET_LEN(pack); + /* Sanity checks */ + if(unlikely(XPACKET_OP(pack) != XPROTO_NAME(GLOBAL,PCM_READ))) { + static int rate_limit; + + if((rate_limit++ % 1003) == 0) { + XBUS_NOTICE(xbus, + "%s: Non-PCM packet within a PCM xframe. (%d)\n", + __FUNCTION__, rate_limit); + dump_xframe("In PCM xframe", xbus, xframe); + } + goto out; + } + p += len; + if(p > xframe_end || len < RPACKET_HEADERSIZE) { + static int rate_limit; + + if((rate_limit++ % 1003) == 0) { + XBUS_NOTICE(xbus, + "%s: Invalid packet length %d. (%d)\n", + __FUNCTION__, len, rate_limit); + dump_xframe("BAD LENGTH", xbus, xframe); + } + goto out; + } + xpd = xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack)); + if(unlikely(!xpd)) { + static int rate_limit; + + if((rate_limit++ % 1003) == 0) { + notify_bad_xpd(__FUNCTION__, xbus, XPACKET_ADDR(pack), "RECEIVE PCM"); + dump_xframe("Unknown XPD addr", xbus, xframe); + } + goto out; + } + if(!pcm_valid(xpd, pack)) + goto out; + if(SPAN_REGISTERED(xpd)) { + XBUS_COUNTER(xbus, RX_PACK_PCM)++; + CALL_XMETHOD(card_pcm_tospan, xbus, xpd, pack); + } + } while(p < xframe_end); + ret = 0; /* all good */ + XBUS_COUNTER(xbus, RX_XFRAME_PCM)++; +out: + FREE_RECV_XFRAME(xbus, xframe); + return ret; +} + +static void xbus_tick(xbus_t *xbus) +{ + int i; + xpd_t *xpd; + xframe_t *xframe = NULL; + xpacket_t *pack = NULL; + size_t pcm_len; + bool sent_sync_bit = 0; + + /* + * Update zaptel + */ + for(i = 0; i < MAX_XPDS; i++) { + xpd = xpd_of(xbus, i); + if(xpd && SPAN_REGISTERED(xpd)) { +#ifdef OPTIMIZE_CHANMUTE + int j; + xpp_line_t xmit_mask = xpd->wanted_pcm_mask; + + xmit_mask |= xpd->silence_pcm; + xmit_mask |= xpd->digital_signalling; + for_each_line(xpd, j) { + xpd->chans[j].chanmute = (optimize_chanmute) + ? !IS_SET(xmit_mask, j) + : 0; + } +#endif + /* + * calls to zt_transmit should be out of spinlocks, as it may call back + * our hook setting methods. + */ + zt_transmit(&xpd->span); + } + } + /* + * Fill xframes + */ + for(i = 0; i < MAX_XPDS; i++) { + if((xpd = xpd_of(xbus, i)) == NULL) + continue; + pcm_len = xpd->pcm_len; + if(SPAN_REGISTERED(xpd)) { + if(pcm_len && xpd->card_present) { + do { + // pack = NULL; /* FORCE single packet frames */ + if(xframe && !pack) { /* FULL frame */ + pcm_frame_out(xbus, xframe); + xframe = NULL; + XBUS_COUNTER(xbus, TX_PCM_FRAG)++; + } + if(!xframe) { /* Alloc frame */ + xframe = ALLOC_SEND_XFRAME(xbus); + if (!xframe) { + static int rate_limit; + + if((rate_limit++ % 3001) == 0) + XBUS_ERR(xbus, + "%s: failed to allocate new xframe\n", + __FUNCTION__); + return; + } + } + pack = xframe_next_packet(xframe, pcm_len); + } while(!pack); + XPACKET_INIT(pack, GLOBAL, PCM_WRITE, xpd->xbus_idx, 1, 0); + XPACKET_LEN(pack) = pcm_len; + if(!sent_sync_bit) { + XPACKET_ADDR_SYNC(pack) = 1; + sent_sync_bit = 1; + } + CALL_XMETHOD(card_pcm_fromspan, xbus, xpd, xpd->wanted_pcm_mask, pack); + XBUS_COUNTER(xbus, TX_PACK_PCM)++; + } + } + } + if(xframe) /* clean any leftovers */ + pcm_frame_out(xbus, xframe); + /* + * Receive PCM + */ + i = atomic_read(&xbus->pcm_rx_counter) & 1; + while((xframe = xframe_dequeue(&xbus->pcm_tospan[i])) != NULL) { + copy_pcm_tospan(xbus, xframe); + if(XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) { + struct timeval now; + unsigned long usec; + + do_gettimeofday(&now); + usec = usec_diff(&now, &xbus->last_rx_sync); + xbus->last_rx_sync = now; + /* ignore startup statistics */ + if(likely(atomic_read(&xbus->pcm_rx_counter) > BIG_TICK_INTERVAL)) { + if(abs(usec - 1000) > TICK_TOLERANCE) { + static int rate_limit; + + if((rate_limit++ % 5003) == 0) + XBUS_DBG(SYNC, xbus, "Bad PCM RX timing(%d): usec=%ld.\n", + rate_limit, usec); + } + if(usec > xbus->max_rx_sync) + xbus->max_rx_sync = usec; + if(usec < xbus->min_rx_sync) + xbus->min_rx_sync = usec; + } + } + } + for(i = 0; i < MAX_XPDS; i++) { + xpd = xpd_of(xbus, i); + if(!xpd || !xpd->card_present) + continue; + if(SPAN_REGISTERED(xpd)) { + do_ec(xpd); + zt_receive(&xpd->span); + } + xpd->silence_pcm = 0; /* silence was injected */ + xpd->timer_count = xbus->global_counter; + /* + * Must be called *after* tx/rx so + * D-Chan counters may be cleared + */ + CALL_XMETHOD(card_tick, xbus, xpd); + } +} + +void do_tick(xbus_t *xbus, struct timeval tv_received) +{ + int counter = atomic_read(&xpp_tick_counter); + + xbus_command_queue_tick(xbus); + xpp_timing_tick(&xbus->timing, &tv_received); + if(syncer == xbus) { + xpp_timing_tick(&ref_sync, &tv_received); + if((counter % BIG_TICK_INTERVAL) == 0) + reset_sync_counters(); + } + if((atomic_read(&xbus->pcm_rx_counter) % BIG_TICK_INTERVAL) == 0) { + if(xbus->sync_mode == SYNC_MODE_PLL) + sync_rate_adjust(xbus); + } + if(likely(xbus->self_ticking)) + xbus_tick(xbus); + xbus->global_counter = counter; +} + +void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe) +{ + int which = atomic_read(&xbus->pcm_rx_counter) & 1; + + if(!xframe_enqueue(&xbus->pcm_tospan[which], xframe)) { + static int rate_limit; + + if((rate_limit++ % 1003) == 0) + XBUS_DBG(SYNC, xbus, + "Failed to enqueue received pcm frame. (%d)\n", + rate_limit); + FREE_RECV_XFRAME(xbus, xframe); + } + /* + * The sync_master bit is marked at the first packet + * of the frame, regardless of the XPD that is sync master. + * FIXME: what about PRI split? + */ + if(XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) { + do_tick(xbus, xframe->tv_received); + atomic_inc(&xbus->pcm_rx_counter); + } else + xbus->xbus_frag_count++; +} + +#ifdef CONFIG_PROC_FS +int proc_sync_read(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + struct timeval now; + unsigned int counter = atomic_read(&xpp_tick_counter); + unsigned long usec; + + do_gettimeofday(&now); + len += sprintf(page + len, "# To modify sync source write into this file:\n"); + len += sprintf(page + len, "# ZAPTEL - Another zaptel device provide sync\n"); + len += sprintf(page + len, "# SYNC=nn - XBUS-nn provide sync\n"); + len += sprintf(page + len, "# QUERY=nn - Query XBUS-nn for sync information (DEBUG)\n"); + if(!syncer) { + if(zaptel_syncer) + len += sprintf(page + len, "ZAPTEL\n"); + else + len += sprintf(page + len, "NO-SYNC\n"); + } else + len += sprintf(page + len, "SYNC=%02d\n", syncer->num); +#ifdef ZAPTEL_SYNC_TICK + if(zaptel_syncer) { + len += sprintf(page + len, + "Zaptel Reference Sync (%d registered spans):\n", + total_registered_spans()); + len += sprintf(page + len, "\tzaptel_tick: #%d\n", zaptel_tick_count); + len += sprintf(page + len, "\ttick - zaptel_tick = %d\n", + counter - zaptel_tick_count); + } else { + len += sprintf(page + len, + "Zaptel Reference Sync Not activated\n"); + } +#endif + usec = usec_diff(&now, &ref_sync.timing_val); + len += sprintf(page + len, "\ntick: #%d\n", counter); + len += sprintf(page + len, + "tick rate: %4d/second (measured %ld.%ld msec ago)\n", + ref_sync.tick_rate, + usec / 1000, usec % 1000); + if(pcm_tasklet) + len += sprintf(page + len, PCM_TASKLET_DEPRECATION); + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; +} + +static int proc_sync_write(struct file *file, const char __user *buffer, unsigned long count, void *data) +{ + char buf[MAX_PROC_WRITE]; + int xbus_num; + int xpd_num; + xbus_t *xbus; + xpd_t *xpd; + + // DBG(SYNC, "%s: count=%ld\n", __FUNCTION__, count); + if(count >= MAX_PROC_WRITE) + return -EINVAL; + if(copy_from_user(buf, buffer, count)) + return -EFAULT; + buf[count] = '\0'; + if(strncmp("ZAPTEL", buf, 6) == 0) { + DBG(SYNC, "ZAPTEL\n"); + zaptel_syncer=1; + update_sync_master(NULL); + } else if(sscanf(buf, "SYNC=%d", &xbus_num) == 1) { + DBG(SYNC, "SYNC=%d\n", xbus_num); + if((xbus = get_xbus(xbus_num)) == NULL) { + ERR("No bus %d exists\n", xbus_num); + return -ENXIO; + } + update_sync_master(xbus); + put_xbus(xbus); + } else if(sscanf(buf, "QUERY=%d", &xbus_num) == 1) { + DBG(SYNC, "QUERY=%d\n", xbus_num); + if((xbus = get_xbus(xbus_num)) == NULL) { + ERR("No bus %d exists\n", xbus_num); + return -ENXIO; + } + CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_QUERY, 0); + put_xbus(xbus); + } else if(sscanf(buf, "%d %d", &xbus_num, &xpd_num) == 2) { + NOTICE("Using deprecated syntax to update %s file\n", + PROC_SYNC); + if(xpd_num != 0) { + ERR("Currently can only set sync for XPD #0\n"); + return -EINVAL; + } + if((xbus = get_xbus(xbus_num)) == NULL) { + ERR("No bus %d exists\n", xbus_num); + return -ENXIO; + } + if((xpd = xpd_of(xbus, xpd_num)) == NULL) { + XBUS_ERR(xbus, "No xpd %d exists\n", xpd_num); + put_xbus(xbus); + return -ENXIO; + } + update_sync_master(xbus); + put_xbus(xbus); + } else { + ERR("%s: cannot parse '%s'\n", __FUNCTION__, buf); + count = -EINVAL; + } + return count; +} + +static struct proc_dir_entry *top; + +#endif + +int xbus_pcm_init(struct proc_dir_entry *toplevel) +{ + int ret = 0; +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *ent; +#endif + +#ifdef OPTIMIZE_CHANMUTE + INFO("FEATURE: with CHANMUTE optimization (%sactivated)\n", + (optimize_chanmute)?"":"de"); +#endif +#ifdef WITH_ECHO_SUPPRESSION + INFO("FEATURE: with ECHO_SUPPRESSION\n"); +#else + INFO("FEATURE: without ECHO_SUPPRESSION\n"); +#endif + if(xpp_ec) + INFO("FEATURE: with XPP_EC_CHUNK\n"); + else + INFO("FEATURE: without XPP_EC_CHUNK\n"); +#ifdef ZAPTEL_SYNC_TICK + INFO("FEATURE: with sync_tick() from ZAPTEL\n"); +#else + INFO("FEATURE: without sync_tick() from ZAPTEL\n"); +#endif +#ifdef CONFIG_PROC_FS + top = toplevel; + ent = create_proc_entry(PROC_SYNC, 0644, top); + if(!ent) { + ret = -EFAULT; + goto err; + } + ent->read_proc = proc_sync_read; + ent->write_proc = proc_sync_write; + ent->data = NULL; +#endif + if(pcm_tasklet) + ERR(PCM_TASKLET_DEPRECATION); + xpp_timing_init(&ref_sync, "REF-SYNC"); +err: + return ret; +} + +void xbus_pcm_shutdown(void) +{ +#ifdef CONFIG_PROC_FS + DBG(GENERAL, "Removing '%s' from proc\n", PROC_SYNC); + remove_proc_entry(PROC_SYNC, top); +#endif +} + + +EXPORT_SYMBOL(xbus_request_sync); +EXPORT_SYMBOL(got_new_syncer); +EXPORT_SYMBOL(elect_syncer); +EXPORT_SYMBOL(xpp_echocan); +#ifdef ZAPTEL_SYNC_TICK +EXPORT_SYMBOL(zaptel_sync_tick); +#endif +EXPORT_SYMBOL(__pcm_recompute); +EXPORT_SYMBOL(pcm_recompute); +EXPORT_SYMBOL(generic_card_pcm_tospan); +EXPORT_SYMBOL(generic_card_pcm_fromspan); + diff --git a/kernel/xpp/xbus-pcm.h b/kernel/xpp/xbus-pcm.h new file mode 100644 index 0000000..79d0078 --- /dev/null +++ b/kernel/xpp/xbus-pcm.h @@ -0,0 +1,106 @@ +/* + * Written by Oron Peled + * Copyright (C) 2004-2007, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * This source module contains all the PCM and SYNC handling code. + */ +#ifndef XBUS_PCM_H +#define XBUS_PCM_H + +#include "xdefs.h" +#include +#include + +#ifdef __KERNEL__ + +enum sync_mode { + SYNC_MODE_NONE = 0x00, + SYNC_MODE_AB = 0x01, /* Astribank sync */ + SYNC_MODE_PLL = 0x03, /* Adjust XPD's PLL according to HOST */ + SYNC_MODE_QUERY = 0x80, +}; + +/* + * A generic timing source. Encapsulates all sampling + * logic, average and standard deviation computation, + * tick_rate computation. + * + * Each xbus has embedded instance. + * Also there is a global instance for external reference + * syncing (e.g: from zaptel) + */ +struct xpp_timing { + const char *name; + struct timeval timing_val; + unsigned long timing_count; + long accumulated_usec; + long accumulated_usec_sqr; + int tick_avg; + int tick_stddev; + spinlock_t lock; + unsigned int tick_rate; +}; + +void xpp_timing_init(struct xpp_timing *timing, const char *name); + +static inline long usec_diff(const struct timeval *tv1, const struct timeval *tv2) +{ + long diff_sec; + long diff_usec; + + diff_sec = tv1->tv_sec - tv2->tv_sec; + diff_usec = tv1->tv_usec - tv2->tv_usec; + return diff_sec * 1000000 + diff_usec; +} + + +int xbus_pcm_init(struct proc_dir_entry *top); +void xbus_pcm_shutdown(void); +int send_pcm_frame(xbus_t *xbus, xframe_t *xframe); +void pcm_recompute(xpd_t *xpd, xpp_line_t tmp_pcm_mask); +void __pcm_recompute(xpd_t *xpd, xpp_line_t tmp_pcm_mask); /* non locking */ +void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe); +void generic_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, xpacket_t *pack); +void generic_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack); +void fill_beep(u_char *buf, int num, int duration); +const char *sync_mode_name(enum sync_mode mode); +void xbus_set_command_timer(xbus_t *xbus, bool on); +void xbus_request_sync(xbus_t *xbus, enum sync_mode mode); +void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift); +int xbus_command_queue_tick(xbus_t *xbus); +void xbus_reset_counters(xbus_t *xbus); +void elect_syncer(const char *msg); +int xpp_echocan(struct zt_chan *chan, int len); +#ifdef ZAPTEL_SYNC_TICK +int zaptel_sync_tick(struct zt_span *span, int is_master); +#endif + +#ifdef XPP_EC_CHUNK +extern int xpp_ec; +#else +#define xpp_ec 0 +#endif + +#endif /* __KERNEL__ */ + +#endif /* XBUS_PCM_H */ + diff --git a/kernel/xpp/xbus-sysfs.c b/kernel/xpp/xbus-sysfs.c new file mode 100644 index 0000000..d45058e --- /dev/null +++ b/kernel/xpp/xbus-sysfs.c @@ -0,0 +1,273 @@ +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +# warning "This module is tested only with 2.6 kernels" +#endif + +#include +#include +#include +#include +#ifdef PROTOCOL_DEBUG +#include +#endif +#include +#include +#include /* for msleep() to debug */ +#include "xpd.h" +#include "xpp_zap.h" +#include "xbus-core.h" +#ifdef XPP_DEBUGFS +#include "xpp_log.h" +#endif +#include "zap_debug.h" + +static const char rcsid[] = "$Id$"; + +/* Command line parameters */ +extern int print_dbg; + + +/* Kernel versions... */ +/* + * Hotplug replaced with uevent in 2.6.16 + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) +#define OLD_HOPLUG_SUPPORT // for older kernels +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) +#define DEVICE_ATTR_FUNC(name,dev,buf) \ + ssize_t name(struct device *dev, struct device_attribute *attr, char *buf) +#else +#define DEVICE_ATTR_FUNC(name,dev,buf) \ + ssize_t name(struct device *dev, char *buf) +#endif + +/*--------- Sysfs Bus handling ----*/ +static int xpp_bus_match(struct device *dev, struct device_driver *driver) +{ + DBG(GENERAL, "dev->bus_id = %s, driver->name = %s\n", dev->bus_id, driver->name); + return 1; +} + +#ifdef OLD_HOPLUG_SUPPORT +static int xpp_bus_hotplug(struct device *dev, char **envp, int envnum, char *buff, int bufsize) +{ + xbus_t *xbus; + + if(!dev) + return -ENODEV; + xbus = dev_to_xbus(dev); + envp[0] = buff; + if(snprintf(buff, bufsize, "XBUS_NAME=%s", xbus->busname) >= bufsize) + return -ENOMEM; + envp[1] = NULL; + return 0; +} +#else + +#define XBUS_ADD_UEVENT_VAR(fmt, val...) \ + do { \ + int err = add_uevent_var(envp, num_envp, &i, \ + buffer, buffer_size, &len, \ + fmt, val); \ + if (err) \ + return err; \ + } while (0) + +static int xpp_bus_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) +{ + xbus_t *xbus; + int i = 0; + int len = 0; + + if(!dev) + return -ENODEV; + xbus = dev_to_xbus(dev); + DBG(GENERAL, "bus_id=%s xbus=%s\n", dev->bus_id, xbus->busname); + XBUS_ADD_UEVENT_VAR("XBUS_NUM=%02d", xbus->num); + XBUS_ADD_UEVENT_VAR("XBUS_NAME=%s", xbus->busname); + envp[i] = NULL; + return 0; +} +#endif + +static void xpp_bus_release(struct device *dev) +{ + DBG(GENERAL, "\n"); +} + +static void xpp_dev_release(struct device *dev) +{ + xbus_t *xbus; + + BUG_ON(!dev); + xbus = dev_to_xbus(dev); + XBUS_DBG(GENERAL, xbus, "\n"); +} + +static struct bus_type xpp_bus_type = { + .name = "astribanks", + .match = xpp_bus_match, +#ifdef OLD_HOPLUG_SUPPORT + .hotplug = xpp_bus_hotplug, +#else + .uevent = xpp_bus_uevent, +#endif +}; + +static struct device xpp_bus = { + .bus_id = "xppbus", + .release = xpp_bus_release +}; + +static struct device_driver xpp_driver = { + .name = "xppdrv", + .bus = &xpp_bus_type, +#ifndef OLD_HOPLUG_SUPPORT + .owner = THIS_MODULE +#endif +}; + +int register_xpp_bus(void) +{ + int ret; + + if((ret = bus_register(&xpp_bus_type)) < 0) { + ERR("%s: bus_register failed. Error number %d", __FUNCTION__, ret); + goto failed_bus; + } + if((ret = device_register(&xpp_bus)) < 0) { + ERR("%s: registration of xpp_bus failed. Error number %d", + __FUNCTION__, ret); + goto failed_busdevice; + } + if((ret = driver_register(&xpp_driver)) < 0) { + ERR("%s: driver_register failed. Error number %d", __FUNCTION__, ret); + goto failed_driver; + } + return 0; +failed_driver: + device_unregister(&xpp_bus); +failed_busdevice: + bus_unregister(&xpp_bus_type); +failed_bus: + return ret; +} + +void unregister_xpp_bus(void) +{ + driver_unregister(&xpp_driver); + device_unregister(&xpp_bus); + bus_unregister(&xpp_bus_type); +} + +/*--------- Sysfs Device handling ----*/ +static DEVICE_ATTR_FUNC(connector_show, dev, buf) +{ + xbus_t *xbus; + int ret; + + xbus = dev_to_xbus(dev); + ret = snprintf(buf, PAGE_SIZE, "%s\n", xbus->busdesc); + return ret; +} + +static DEVICE_ATTR_FUNC(label_show, dev, buf) +{ + xbus_t *xbus; + int ret; + + xbus = dev_to_xbus(dev); + ret = snprintf(buf, PAGE_SIZE, "%s\n", xbus->label); + return ret; +} + +static DEVICE_ATTR_FUNC(status_show, dev, buf) +{ + xbus_t *xbus; + int ret; + + xbus = dev_to_xbus(dev); + ret = snprintf(buf, PAGE_SIZE, "%s\n", (TRANSPORT_RUNNING(xbus))?"connected":"missing"); + return ret; +} + +static DEVICE_ATTR(connector, S_IRUGO, connector_show, NULL); +static DEVICE_ATTR(label, S_IRUGO, label_show, NULL); +static DEVICE_ATTR(status, S_IRUGO, status_show, NULL); + +void xbus_sysfs_remove(xbus_t *xbus) +{ + struct device *astribank; + + BUG_ON(!xbus); + XBUS_DBG(GENERAL, xbus, "\n"); + astribank = &xbus->astribank; + BUG_ON(!astribank); + device_remove_file(&xbus->astribank, &dev_attr_status); + device_remove_file(&xbus->astribank, &dev_attr_label); + device_remove_file(&xbus->astribank, &dev_attr_connector); + device_unregister(&xbus->astribank); +} + +int xbus_sysfs_create(xbus_t *xbus) +{ + struct device *astribank; + int ret = 0; + + BUG_ON(!xbus); + astribank = &xbus->astribank; + BUG_ON(!astribank); + XBUS_DBG(GENERAL, xbus, "\n"); + device_initialize(astribank); + astribank->bus = &xpp_bus_type; + astribank->parent = &xpp_bus; + snprintf(astribank->bus_id, BUS_ID_SIZE, "xbus-%02d", xbus->num); + astribank->driver_data = NULL; /* FIXME: add some usefull data */ + astribank->release = xpp_dev_release; + ret = device_register(astribank); + if(ret) { + XBUS_ERR(xbus, "%s: device_add failed: %d\n", __FUNCTION__, ret); + goto out; + } + ret = device_create_file(astribank, &dev_attr_connector); + if(ret) { + XBUS_ERR(xbus, "%s: device_create_file failed: %d\n", __FUNCTION__, ret); + goto out; + } + ret = device_create_file(astribank, &dev_attr_label); + if(ret) { + XBUS_ERR(xbus, "%s: device_create_file failed: %d\n", __FUNCTION__, ret); + goto out; + } + ret = device_create_file(astribank, &dev_attr_status); + if(ret) { + XBUS_ERR(xbus, "%s: device_create_file failed: %d\n", __FUNCTION__, ret); + goto out; + } +out: + return ret; +} diff --git a/kernel/xpp/xdefs.h b/kernel/xpp/xdefs.h new file mode 100644 index 0000000..2aec497 --- /dev/null +++ b/kernel/xpp/xdefs.h @@ -0,0 +1,131 @@ +#ifndef XDEFS_H +#define XDEFS_H +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "xpp_version.h" + +#ifdef __KERNEL__ + +#include +#include + +#else + +/* This is to enable user-space programs to include this. */ + +#include +typedef uint8_t __u8; +typedef uint32_t __u32; + +#include + +#define DBG(fmt, ...) printf("DBG: %s: " fmt, __FUNCTION__, ## __VA_ARGS__) +#define INFO(fmt, ...) printf("INFO: " fmt, ## __VA_ARGS__) +#define NOTICE(fmt, ...) printf("NOTICE: " fmt, ## __VA_ARGS__) +#define ERR(fmt, ...) printf("ERR: " fmt, ## __VA_ARGS__) +#define __user + +struct list_head { struct list_head *next; struct list_head *prev; }; + +#endif + +#define PACKED __attribute__((packed)) + +#define ALL_LINES ((lineno_t)-1) + +#define BIT(i) (1 << (i)) +#define BIT_SET(x,i) ((x) |= BIT(i)) +#define BIT_CLR(x,i) ((x) &= ~BIT(i)) +#define IS_SET(x,i) (((x) & BIT(i)) != 0) +#define BITMASK(i) (((u64)1 << (i)) - 1) + +#define MAX_PROC_WRITE 100 /* Largest buffer we allow writing our /proc files */ +#define CHANNELS_PERXPD 32 /* Depends on xpp_line_t and protocol fields */ + +#define MAX_SPANNAME 20 /* From zaptel.h */ +#define MAX_SPANDESC 40 /* From zaptel.h */ +#define MAX_CHANNAME 40 /* From zaptel.h */ + +#define XPD_NAMELEN 10 /* must be <= from maximal workqueue name */ +#define XPD_DESCLEN 20 +#define XBUS_NAMELEN 20 /* must be <= from maximal workqueue name */ +#define XBUS_DESCLEN 40 +#define LABEL_SIZE 20 + +#define UNIT_BITS 3 /* Bit for Astribank unit number */ +#define SUBUNIT_BITS 3 /* Bit for Astribank subunit number */ + +#define MAX_UNIT BIT(UNIT_BITS) /* 1 FXS + 3 FXS/FXO | 1 BRI + 3 FXS/FXO */ +#define MAX_SUBUNIT BIT(SUBUNIT_BITS) /* 8 port BRI */ + +/* + * Compile time sanity checks + */ +#if MAX_UNIT > BIT(UNIT_BITS) +#error "MAX_UNIT too large" +#endif + +#if MAX_SUBUNIT > BIT(SUBUNIT_BITS) +#error "MAX_SUBUNIT too large" +#endif + +#define MAX_XPDS (MAX_UNIT*MAX_SUBUNIT) + +#define VALID_XPD_NUM(x) ((x) < MAX_XPDS && (x) >= 0) + +#define CHAN_BITS 5 /* 0-30 for E1, 31 = ALL_CHANS */ +#define ALL_CHANS BITMASK(CHAN_BITS) +#define MAX_CHAN (ALL_CHANS - 1) +#define VALID_CHAN_NUM(x) ((x) < MAX_CHAN) + +typedef char *charp; +typedef unsigned char byte; +#ifdef __KERNEL__ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) +#define KMEM_CACHE_T kmem_cache_t +#else +#define KMEM_CACHE_T struct kmem_cache +#endif + +#define KZALLOC(size, gfp) my_kzalloc(size, gfp) +#define KZFREE(p) do { \ + memset((p), 0, sizeof(*(p))); \ + kfree(p); \ + } while(0); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) +typedef int bool; +#endif +#else +typedef int bool; +#endif +typedef struct xbus xbus_t; +typedef struct xpd xpd_t; +typedef struct xframe xframe_t; +typedef struct xpacket xpacket_t; +typedef struct xops xops_t; +typedef __u32 xpp_line_t; /* at most 31 lines for E1 */ +typedef byte lineno_t; + +#endif /* XDEFS_H */ diff --git a/kernel/xpp/xframe_queue.c b/kernel/xpp/xframe_queue.c new file mode 100644 index 0000000..23dee0e --- /dev/null +++ b/kernel/xpp/xframe_queue.c @@ -0,0 +1,258 @@ +#include "xframe_queue.h" +#include "xbus-core.h" +#include "zap_debug.h" + +static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags); +static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe); + +void xframe_queue_init(struct xframe_queue *q, unsigned int steady_state_count, unsigned int max_count, const char *name, void *priv) +{ + memset(q, 0, sizeof(*q)); + spin_lock_init(&q->lock); + INIT_LIST_HEAD(&q->head); + q->max_count = XFRAME_QUEUE_MARGIN + max_count; + q->steady_state_count = XFRAME_QUEUE_MARGIN + steady_state_count; + q->name = name; + q->priv = priv; +} + +void xframe_queue_clearstats(struct xframe_queue *q) +{ + q->worst_count = 0; + //q->overflows = 0; /* Never clear overflows */ + q->worst_lag_usec = 0L; +} + +static bool __xframe_enqueue(struct xframe_queue *q, xframe_t *xframe) +{ + int ret = 1; + + if(q->count >= q->max_count) { + q->overflows++; + ret = 0; + goto out; + } + if(++q->count > q->worst_count) + q->worst_count = q->count; + list_add_tail(&xframe->frame_list, &q->head); + do_gettimeofday(&xframe->tv_queued); +out: + return ret; +} + +bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&q->lock, flags); + ret = __xframe_enqueue(q, xframe); + spin_unlock_irqrestore(&q->lock, flags); + return ret; +} + +xframe_t *__xframe_dequeue(struct xframe_queue *q) +{ + xframe_t *frm = NULL; + struct list_head *h; + struct timeval now; + unsigned long usec_lag; + + if(list_empty(&q->head)) + goto out; + h = q->head.next; + list_del_init(h); + --q->count; + frm = list_entry(h, xframe_t, frame_list); + do_gettimeofday(&now); + usec_lag = + (now.tv_sec - frm->tv_queued.tv_sec)*1000*1000 + + (now.tv_usec - frm->tv_queued.tv_usec); + if(q->worst_lag_usec < usec_lag) + q->worst_lag_usec = usec_lag; +out: + return frm; +} + +xframe_t *xframe_dequeue(struct xframe_queue *q) +{ + unsigned long flags; + xframe_t *frm; + + spin_lock_irqsave(&q->lock, flags); + frm = __xframe_dequeue(q); + spin_unlock_irqrestore(&q->lock, flags); + return frm; +} +void xframe_queue_disable(struct xframe_queue *q) +{ + q->max_count = 0; +} + +void xframe_queue_clear(struct xframe_queue *q) +{ + xframe_t *xframe; + xbus_t *xbus = q->priv; + int i = 0; + + xframe_queue_disable(q); + while((xframe = xframe_dequeue(q)) != NULL) { + transport_free_xframe(xbus, xframe); + i++; + } + XBUS_INFO(xbus, "%s: finished queue clear (%d items)\n", q->name, i); +} + +uint xframe_queue_count(struct xframe_queue *q) +{ + return q->count; +} + +/*------------------------- Frame Alloc/Dealloc --------------------*/ + +static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags) +{ + struct xbus_ops *ops; + xframe_t *xframe; + unsigned long flags; + + BUG_ON(!xbus); + ops = transportops_get(xbus); + if(unlikely(!ops)) { + XBUS_ERR(xbus, "Missing transport\n"); + return NULL; + } + spin_lock_irqsave(&xbus->transport.lock, flags); + //XBUS_INFO(xbus, "%s (transport_refcount=%d)\n", __FUNCTION__, atomic_read(&xbus->transport.transport_refcount)); + xframe = ops->alloc_xframe(xbus, gfp_flags); + if(!xframe) { + static int rate_limit; + + if((rate_limit++ % 3001) == 0) + XBUS_ERR(xbus, + "Failed xframe allocation from transport (%d)\n", + rate_limit); + transportops_put(xbus); + /* fall through */ + } + spin_unlock_irqrestore(&xbus->transport.lock, flags); + return xframe; +} + +static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe) +{ + struct xbus_ops *ops; + unsigned long flags; + + BUG_ON(!xbus); + ops = xbus->transport.ops; + BUG_ON(!ops); + spin_lock_irqsave(&xbus->transport.lock, flags); + //XBUS_INFO(xbus, "%s (transport_refcount=%d)\n", __FUNCTION__, atomic_read(&xbus->transport.transport_refcount)); + ops->free_xframe(xbus, xframe); + transportops_put(xbus); + spin_unlock_irqrestore(&xbus->transport.lock, flags); +} + +static bool xframe_queue_adjust(struct xframe_queue *q) +{ + xbus_t *xbus; + xframe_t *xframe; + int delta; + unsigned long flags; + int ret = 0; + + BUG_ON(!q); + xbus = q->priv; + BUG_ON(!xbus); + spin_lock_irqsave(&q->lock, flags); + delta = q->count - q->steady_state_count; + if(delta < -XFRAME_QUEUE_MARGIN) { + /* Increase pool by one frame */ + //XBUS_INFO(xbus, "%s(%d): Allocate one\n", q->name, delta); + xframe = transport_alloc_xframe(xbus, GFP_ATOMIC); + if(!xframe) { + XBUS_ERR(xbus, "%s: failed frame allocation\n", q->name); + goto out; + } + if(!__xframe_enqueue(q, xframe)) { + XBUS_ERR(xbus, "%s: failed enqueueing frame\n", q->name); + transport_free_xframe(xbus, xframe); + goto out; + } + } else if(delta > XFRAME_QUEUE_MARGIN) { + /* Decrease pool by one frame */ + //XBUS_INFO(xbus, "%s(%d): Free one\n", q->name, delta); + xframe = __xframe_dequeue(q); + if(!xframe) { + XBUS_ERR(xbus, "%s: failed dequeueing frame\n", q->name); + goto out; + } + transport_free_xframe(xbus, xframe); + } + ret = 1; +out: + spin_unlock_irqrestore(&q->lock, flags); + return ret; +} + +xframe_t *get_xframe(struct xframe_queue *q) +{ + xframe_t *xframe; + xbus_t *xbus; + + BUG_ON(!q); + xbus = (xbus_t *)q->priv; + BUG_ON(!xbus); + xframe_queue_adjust(q); + xframe = xframe_dequeue(q); + if(!xframe) { + static int rate_limit; + + if((rate_limit++ % 3001) == 0) + XBUS_ERR(xbus, "%s STILL EMPTY (%d)\n", q->name, rate_limit); + return NULL; + } + BUG_ON(xframe->xframe_magic != XFRAME_MAGIC); + atomic_set(&xframe->frame_len, 0); + xframe->first_free = xframe->packets; + do_gettimeofday(&xframe->tv_created); + /* + * If later parts bother to correctly initialize their + * headers, there is no need to memset() the whole data. + * + * ticket:403 + * + * memset(xframe->packets, 0, xframe->frame_maxlen); + */ + //XBUS_INFO(xbus, "%s\n", __FUNCTION__); + return xframe; +} + +void put_xframe(struct xframe_queue *q, xframe_t *xframe) +{ + xbus_t *xbus; + + BUG_ON(!q); + xbus = (xbus_t *)q->priv; + BUG_ON(!xbus); + //XBUS_INFO(xbus, "%s\n", __FUNCTION__); + BUG_ON(!TRANSPORT_EXIST(xbus)); + if(unlikely(!xframe_enqueue(q, xframe))) { + XBUS_ERR(xbus, "Failed returning xframe to %s\n", q->name); + transport_free_xframe(xbus, xframe); + return; + } + xframe_queue_adjust(q); +} + + +EXPORT_SYMBOL(xframe_queue_init); +EXPORT_SYMBOL(xframe_queue_clearstats); +EXPORT_SYMBOL(xframe_enqueue); +EXPORT_SYMBOL(xframe_dequeue); +EXPORT_SYMBOL(xframe_queue_disable); +EXPORT_SYMBOL(xframe_queue_clear); +EXPORT_SYMBOL(xframe_queue_count); +EXPORT_SYMBOL(get_xframe); +EXPORT_SYMBOL(put_xframe); diff --git a/kernel/xpp/xframe_queue.h b/kernel/xpp/xframe_queue.h new file mode 100644 index 0000000..5612d65 --- /dev/null +++ b/kernel/xpp/xframe_queue.h @@ -0,0 +1,34 @@ +#ifndef XFRAME_QUEUE_H +#define XFRAME_QUEUE_H + +#include +#include +#include "xdefs.h" + +#define XFRAME_QUEUE_MARGIN 10 + +struct xframe_queue { + struct list_head head; + unsigned int count; + unsigned int max_count; + unsigned int steady_state_count; + spinlock_t lock; + const char *name; + void *priv; + /* statistics */ + unsigned int worst_count; + unsigned int overflows; + unsigned long worst_lag_usec; /* since xframe creation */ +}; + +void xframe_queue_init(struct xframe_queue *q, + unsigned int steady_state_count, unsigned int max_count, + const char *name, void *priv); +__must_check bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe); +__must_check xframe_t *xframe_dequeue(struct xframe_queue *q); +void xframe_queue_clearstats(struct xframe_queue *q); +void xframe_queue_disable(struct xframe_queue *q); +void xframe_queue_clear(struct xframe_queue *q); +uint xframe_queue_count(struct xframe_queue *q); + +#endif /* XFRAME_QUEUE_ */ diff --git a/kernel/xpp/xpd.h b/kernel/xpp/xpd.h new file mode 100644 index 0000000..3187227 --- /dev/null +++ b/kernel/xpp/xpd.h @@ -0,0 +1,223 @@ +#ifndef XPD_H +#define XPD_H + +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "xdefs.h" +#include "xproto.h" + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#ifdef XPP_DEBUGFS +#ifndef CONFIG_DEBUG_FS +#warning kernel does not include CONFIG_DEBUG_FS, canceling XPP_DEBUGFS support +#undef XPP_DEBUGFS +#else +#include +#endif +#endif +#endif /* __KERNEL__ */ + +#include + +#ifdef __KERNEL__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) +/* also added in RHEL kernels with the OpenInfiniband backport: */ +#if LINUX_VERSION_CODE != KERNEL_VERSION(2,6,9) || !defined(DEFINE_SPINLOCK) +typedef unsigned gfp_t; /* Added in 2.6.14 */ +#endif +#endif + +/* + * FIXME: Kludge for 2.6.19 + * bool is now defined as a proper boolean type (gcc _Bool) + * but the command line parsing framework handles it as int. + */ +#define DEF_PARM_BOOL(name,init,perm,desc) \ + int name = init; \ + module_param(name, bool, perm); \ + MODULE_PARM_DESC(name, desc " [default " #init "]") + +#define DEF_PARM(type,name,init,perm,desc) \ + type name = init; \ + module_param(name, type, perm); \ + MODULE_PARM_DESC(name, desc " [default " #init "]") + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) +/* + * Old 2.6 kernels had module_param_array() macro that receive the counter + * by value. + */ +#define DEF_ARRAY(type,name,count,init,desc) \ + unsigned int name ## _num_values; \ + type name[count] = { [0 ... ((count)-1)] = (init) }; \ + module_param_array(name, type, name ## _num_values, 0644); \ + MODULE_PARM_DESC(name, desc " ( 1-" __MODULE_STRING(count) ")") +#else +#define DEF_ARRAY(type,name,count,init,desc) \ + unsigned int name ## _num_values; \ + type name[count] = {[0 ... ((count)-1)] = init}; \ + module_param_array(name, type, &name ## _num_values, 0644); \ + MODULE_PARM_DESC(name, desc " ( 1-" __MODULE_STRING(count) ")") +#endif +#endif // __KERNEL__ + +#define CARD_DESC_MAGIC 0xca9dde5c + +struct card_desc_struct { + struct list_head card_list; + u32 magic; + xbus_t *xbus; + byte rev; /* Revision number */ + byte type; /* LSB: 1 - to_phone, 0 - to_line */ + byte subtype; + struct xpd_addr xpd_addr; + xpp_line_t line_status; /* Initial line status (offhook) */ +}; + +typedef enum xpd_direction { + TO_PSTN = 0, + TO_PHONE = 1, +} xpd_direction_t; + +#ifdef __KERNEL__ + +/* + * XPD statistics counters + */ +enum { + XPD_N_PCM_READ, + XPD_N_PCM_WRITE, + XPD_N_RECV_ERRORS, +}; + +#define XPD_COUNTER(xpd, counter) ((xpd)->counters[XPD_N_ ## counter]) + +#define C_(x) [ XPD_N_ ## x ] = { #x } + +/* yucky, make an instance so we can size it... */ +static struct xpd_counters { + char *name; +} xpd_counters[] = { + C_(PCM_READ), + C_(PCM_WRITE), + C_(RECV_ERRORS), +}; + +#undef C_ + +#define XPD_COUNTER_MAX (sizeof(xpd_counters)/sizeof(xpd_counters[0])) + +/* + * An XPD is a single Xorcom Protocol Device + */ +struct xpd { + char xpdname[XPD_NAMELEN]; + struct zt_span span; + struct zt_chan *chans; + int channels; + xpd_type_t type; + const char *type_name; + byte subtype; + byte revision; /* Card revision */ + xpd_direction_t direction; /* TO_PHONE, TO_PSTN */ + xpp_line_t no_pcm; /* Temporary: disable PCM (for USB-1) */ + xpp_line_t offhook; /* Actual chip state: 0 - ONHOOK, 1 - OFHOOK */ + xpp_line_t cid_on; + xpp_line_t msg_waiting; /* Voice Mail Waiting Indication */ + xpp_line_t digital_outputs; /* 0 - no, 1 - yes */ + xpp_line_t digital_inputs; /* 0 - no, 1 - yes */ + xpp_line_t digital_signalling; /* BRI signalling channels */ + uint timing_priority; /* from 'span' directives in zapata.conf */ + + /* maintained by card drivers */ + uint pcm_len; /* allocation length of PCM packet (dynamic) */ + xpp_line_t wanted_pcm_mask; + xpp_line_t silence_pcm; /* inject silence during next tick */ + xpp_line_t mute_dtmf; + + bool ringing[CHANNELS_PERXPD]; + + xbus_t *xbus; /* The XBUS we are connected to */ + + spinlock_t lock; + atomic_t zt_registered; /* Am I fully registered with zaptel */ + atomic_t open_counter; /* Number of open channels */ + + int flags; + bool blink_mode; /* for visual identification */ +#define DEFAULT_LED_PERIOD (1000/8) /* in tick */ + +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *proc_xpd_dir; + struct proc_dir_entry *proc_xpd_summary; + struct proc_dir_entry *proc_xpd_ztregister; + struct proc_dir_entry *proc_xpd_blink; +#endif + + int counters[XPD_COUNTER_MAX]; + + const xproto_table_t *xproto; /* Card level protocol table */ + const xops_t *xops; /* Card level operations */ + void *priv; /* Card level private data */ + bool card_present; + reg_cmd_t requested_reply; + reg_cmd_t last_reply; + + unsigned long last_response; /* in jiffies */ + unsigned xbus_idx; /* index in xbus->xpds[] */ + struct xpd_addr addr; + struct list_head xpd_list; + unsigned int timer_count; + /* Echo cancelation */ + u_char ec_chunk1[CHANNELS_PERXPD][ZT_CHUNKSIZE]; + u_char ec_chunk2[CHANNELS_PERXPD][ZT_CHUNKSIZE]; +}; + +#define for_each_line(xpd,i) for((i) = 0; (i) < (xpd)->channels; (i)++) +#define IS_BRI(xpd) ((xpd)->type == XPD_TYPE_BRI_NT || (xpd)->type == XPD_TYPE_BRI_TE) +#define TICK_TOLERANCE 500 /* usec */ + +#ifdef DEBUG_SYNC_PARPORT +void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1); +#else +#define xbus_flip_bit(xbus, bitnum0, bitnum1) +#endif + +static inline void *my_kzalloc(size_t size, gfp_t flags) +{ + void *p; + + p = kmalloc(size, flags); + if(p) + memset(p, 0, size); + return p; +} + +#endif + +#endif /* XPD_H */ diff --git a/kernel/xpp/xpp_log.h b/kernel/xpp/xpp_log.h new file mode 100644 index 0000000..322b7f0 --- /dev/null +++ b/kernel/xpp/xpp_log.h @@ -0,0 +1,52 @@ +#ifndef XPP_LOG_H +#define XPP_LOG_H +/* + * Written by Alexander Landau + * Copyright (C) 2004-2007, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifdef __KERNEL__ + +#include +#include + +#else + +/* This is to enable user-space programs to include this. */ + +#include "xdefs.h" + +#endif + +#define XPP_LOG_MAGIC 0x10583ADE + +struct log_global_header { + __u32 magic; + __u32 version; +} __attribute__((packed)); + +struct log_header { + __u32 len; + __u32 time; + __u8 xpd_num; + __u8 direction; +} __attribute__((packed)); + +#endif diff --git a/kernel/xpp/xpp_usb.c b/kernel/xpp/xpp_usb.c new file mode 100644 index 0000000..785e713 --- /dev/null +++ b/kernel/xpp/xpp_usb.c @@ -0,0 +1,1085 @@ +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include /* for udelay */ +#include +#include +#include +#include +#include +#include +#include "xpd.h" +#include "xproto.h" +#include "xbus-core.h" +#include "xframe_queue.h" +#ifdef DEBUG +#include "card_fxs.h" +#include "card_fxo.h" +#endif +#include "parport_debug.h" + +static const char rcsid[] = "$Id$"; + +DEF_PARM(int, print_dbg, 0, 0644, "Print DBG statements"); /* must be before zap_debug.h */ +DEF_PARM(int, usb1, 0, 0644, "Allow using USB 1.1 interfaces"); +DEF_PARM(uint, tx_sluggish, 2000, 0644, "A sluggish transmit (usec)"); +DEF_PARM(uint, drop_pcm_after, 6, 0644, "Number of consecutive tx_sluggish to drop a PCM frame"); + +#include "zap_debug.h" + + +#define XUSB_PRINTK(level, xusb, fmt, ...) \ + printk(KERN_ ## level "%s-%s: xusb-%d (%s) [%s]: " fmt, #level, \ + THIS_MODULE->name, (xusb)->index, xusb->path, xusb->serial, ## __VA_ARGS__) + +#define XUSB_DBG(bits, xusb, fmt, ...) \ + ((void)((print_dbg & (DBG_ ## bits)) && XUSB_PRINTK(DEBUG, xusb, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))) +#define XUSB_ERR(xusb, fmt, ...) XUSB_PRINTK(ERR, xusb, fmt, ## __VA_ARGS__) +#define XUSB_NOTICE(xusb, fmt, ...) XUSB_PRINTK(NOTICE, xusb, fmt, ## __VA_ARGS__) +#define XUSB_INFO(xusb, fmt, ...) XUSB_PRINTK(INFO, xusb, fmt, ## __VA_ARGS__) + +/* FIXME: A flag that was deprecated at some point, and rather useless */ +/* anyway. Only used in the code or-ed to other flags */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) +# define URB_ASYNC_UNLINK 0 +#endif +/* Get a minor range for your devices from the usb maintainer */ +#define USB_SKEL_MINOR_BASE 192 + +#ifdef CONFIG_PROC_FS +#define PROC_USBXPP_SUMMARY "xpp_usb" +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +# warning "This module is tested only with 2.6 kernels" +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) +# undef USB_FIELDS_MISSING +#else +# define USB_FIELDS_MISSING + +# define USB_MAX_STRING 128 +# define USB_GET_STRING(udev,field,buf) \ + do { \ + if((udev)->descriptor.field) { \ + char tmp[USB_MAX_STRING]; \ + if(usb_string((udev), (udev)->descriptor.field, tmp, sizeof(tmp)) > 0) \ + snprintf((buf), USB_MAX_STRING, "%s", tmp); \ + } \ + } while(0); +# define USB_GET_IFACE_NAME(udev,iface,buf) \ + do { \ + if((iface)->desc.iInterface) { \ + char tmp[USB_MAX_STRING]; \ + if(usb_string((udev), (iface)->desc.iInterface, tmp, sizeof(tmp)) > 0) \ + snprintf((buf), USB_MAX_STRING, "%s", tmp); \ + } \ + } while(0); +#endif + +#ifdef DEBUG_PCM_TIMING +static cycles_t stamp_last_pcm_read; +static cycles_t accumulate_diff; +#endif + +struct xusb_model_info; + +struct xusb_endpoint { + int ep_addr; + int max_size; + usb_complete_t callback; +}; + +enum xusb_dir { + XUSB_RECV = 0, + XUSB_SEND = 1, +}; + +static int xframe_send_pcm(xbus_t *xbus, xframe_t *xframe); +static int xframe_send_cmd(xbus_t *xbus, xframe_t *xframe); +static xframe_t *alloc_xframe(xbus_t *xbus, gfp_t flags); +static void free_xframe(xbus_t *xbus, xframe_t *frm); + +static struct xbus_ops xusb_ops = { + .xframe_send_pcm = xframe_send_pcm, + .xframe_send_cmd = xframe_send_cmd, + .alloc_xframe = alloc_xframe, + .free_xframe = free_xframe, +}; + +enum { + XUSB_N_RX_FRAMES, + XUSB_N_TX_FRAMES, + XUSB_N_RX_ERRORS, + XUSB_N_TX_ERRORS, + XUSB_N_RCV_ZERO_LEN, +}; + +#define XUSB_COUNTER(xusb, counter) ((xusb)->counters[XUSB_N_ ## counter]) + +#define C_(x) [ XUSB_N_ ## x ] = { #x } + +static struct xusb_counters { + char *name; +} xusb_counters[] = { + C_(RX_FRAMES), + C_(TX_FRAMES), + C_(RX_ERRORS), + C_(TX_ERRORS), + C_(RCV_ZERO_LEN), +}; + +#undef C_ + +#define XUSB_COUNTER_MAX ARRAY_SIZE(xusb_counters) + +#define MAX_PENDING_WRITES 100 + +static KMEM_CACHE_T *xusb_cache = NULL; + +typedef struct xusb xusb_t; + +/* + * A uframe is our low level representation of a frame. + * + * It contains the metadata for the usb stack (a urb) + * and the metadata for the xbus-core (an xframe) + * as well as pointing to the data (transfer_buffer, transfer_buffer_length) + * directionality (send/receive) and ownership (xusb). + */ +struct uframe { + unsigned long uframe_magic; +#define UFRAME_MAGIC 654321L + struct urb urb; + xframe_t xframe; + size_t transfer_buffer_length; + void *transfer_buffer; /* max XFRAME_DATASIZE */ + xusb_t *xusb; +}; + +#define urb_to_uframe(urb) container_of(urb, struct uframe, urb) +#define xframe_to_uframe(xframe) container_of(xframe, struct uframe, xframe) +#define xusb_of(xbus) ((xusb_t *)((xbus)->transport.priv)) + +#define USEC_BUCKET 100 /* usec */ +#define NUM_BUCKETS 15 +#define BUCKET_START (500/USEC_BUCKET) /* skip uninteresting */ + +/* + * USB XPP Bus (a USB Device) + */ +struct xusb { + uint xbus_num; + struct usb_device *udev; /* save off the usb device pointer */ + struct usb_interface *interface; /* the interface for this device */ + unsigned char minor; /* the starting minor number for this device */ + uint index; + char path[XBUS_DESCLEN]; /* a unique path */ + + struct xusb_model_info *model_info; + struct xusb_endpoint endpoints[2]; /* RECV/SEND endpoints */ + + int present; /* if the device is not disconnected */ + atomic_t pending_writes; /* submited but not out yet */ + struct semaphore sem; /* locks this structure */ + int counters[XUSB_COUNTER_MAX]; + + /* metrics */ + struct timeval last_tx; + unsigned int max_tx_delay; + uint usb_tx_delay[NUM_BUCKETS]; + uint sluggish_debounce; + bool drop_next_pcm; /* due to sluggishness */ + atomic_t pcm_tx_drops; + atomic_t usb_sluggish_count; + +#ifdef USB_FIELDS_MISSING + /* storage for missing strings in old kernels */ + char manufacturer[USB_MAX_STRING]; + char product[USB_MAX_STRING]; + char serial[USB_MAX_STRING]; + char interface_name[USB_MAX_STRING]; +#else + const char *manufacturer; + const char *product; + const char *serial; + const char *interface_name; +#endif + +}; + +static spinlock_t xusb_lock = SPIN_LOCK_UNLOCKED; +static xusb_t *xusb_array[MAX_BUSES] = {}; +static unsigned bus_count = 0; + + +/* prevent races between open() and disconnect() */ +static DECLARE_MUTEX (disconnect_sem); + +/* + * AsteriskNow kernel has backported the "lean" callback from 2.6.20 + * to 2.6.19 without any macro to notify of this fact -- how lovely. + * Debian-Etch and Centos5 are using 2.6.18 for now (lucky for us). + * Fedora6 jumped from 2.6.18 to 2.6.20. So far luck is on our side ;-) + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) +#define USB_PASS_CB(u) struct urb *u, struct pt_regs *regs +#else +#define USB_PASS_CB(u) struct urb *u +#endif + +static void xpp_send_callback(USB_PASS_CB(urb)); +static void xpp_receive_callback(USB_PASS_CB(urb)); +static int xusb_probe (struct usb_interface *interface, const struct usb_device_id *id); +static void xusb_disconnect (struct usb_interface *interface); +static int xusb_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data); + +/*------------------------------------------------------------------*/ + +/* + * Updates the urb+xframe metadata from the uframe information. + */ +static void uframe_recompute(struct uframe *uframe, enum xusb_dir dir) +{ + struct urb *urb = &uframe->urb; + xusb_t *xusb = uframe->xusb; + struct usb_device *udev = xusb->udev; + struct xusb_endpoint *xusb_ep = &xusb->endpoints[dir]; + unsigned int ep_addr = xusb_ep->ep_addr; + usb_complete_t urb_cb = xusb_ep->callback; + unsigned int epnum = ep_addr & USB_ENDPOINT_NUMBER_MASK; + int pipe = usb_pipein(ep_addr) + ? usb_rcvbulkpipe(udev, epnum) + : usb_sndbulkpipe(udev, epnum); + + BUG_ON(uframe->uframe_magic != UFRAME_MAGIC); + usb_fill_bulk_urb(urb, udev, pipe, uframe->transfer_buffer, uframe->transfer_buffer_length, urb_cb, uframe); + urb->transfer_flags = (URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK); +} + +static xframe_t *alloc_xframe(xbus_t *xbus, gfp_t gfp_flags) +{ + struct uframe *uframe; + xusb_t *xusb; + void *p; + int size; + static int rate_limit; + + BUG_ON(!xbus); + xusb = xusb_of(xbus); + BUG_ON(!xusb); + if(!xusb->present) { + if((rate_limit++ % 1003) == 0) + XUSB_ERR(xusb, + "abort allocations during device disconnect (%d)\n", rate_limit); + return NULL; + } + size = min(xusb->endpoints[XUSB_SEND].max_size, xusb->endpoints[XUSB_RECV].max_size); + uframe = kmem_cache_alloc(xusb_cache, gfp_flags); + if(!uframe) { + if((rate_limit++ % 1003) == 0) + XUSB_ERR(xusb, "frame allocation failed (%d)\n", rate_limit); + return NULL; + } + usb_init_urb(&uframe->urb); + p = usb_buffer_alloc(xusb->udev, size, gfp_flags, &uframe->urb.transfer_dma); + if(!p) { + if((rate_limit++ % 1003) == 0) + XUSB_ERR(xusb, "buffer allocation failed (%d)\n", rate_limit); + kfree(uframe); + return NULL; + } + uframe->uframe_magic = UFRAME_MAGIC; + uframe->transfer_buffer_length = size; + uframe->transfer_buffer = p; + uframe->xusb = xusb; + xframe_init(xbus, &uframe->xframe, uframe->transfer_buffer, uframe->transfer_buffer_length, uframe); + return &uframe->xframe; +} + +void free_xframe(xbus_t *xbus, xframe_t *xframe) +{ + struct uframe *uframe = xframe_to_uframe(xframe); + struct urb *urb = &uframe->urb; + + BUG_ON(xbus->transport.priv != uframe->xusb); + //XUSB_INFO(uframe->xusb, "frame_free\n"); + usb_buffer_free(urb->dev, uframe->transfer_buffer_length, + urb->transfer_buffer, + urb->transfer_dma); + memset(uframe, 0, sizeof(*uframe)); + kmem_cache_free(xusb_cache, uframe); +} + +/*------------------------------------------------------------------*/ + +/* + * Actuall frame sending -- both PCM and commands. + */ +static int do_send_xframe(xbus_t *xbus, xframe_t *xframe) +{ + struct urb *urb; + xusb_t *xusb; + int ret = 0; + struct uframe *uframe; + static int rate_limit; + + BUG_ON(!xframe); + BUG_ON(xframe->xframe_magic != XFRAME_MAGIC); + xusb = xusb_of(xbus); + BUG_ON(!xusb); + if(!xusb->present) { + if((rate_limit++ % 1003) == 0) + XUSB_ERR(xusb, + "abort do_send_xframe during device disconnect (%d)\n", rate_limit); + ret = -ENODEV; + goto failure; + } + /* + * If something really bad happend, do not overflow the USB stack + */ + if(atomic_read(&xusb->pending_writes) > MAX_PENDING_WRITES) { + static int rate_limit; + + if((rate_limit++ % 5000) == 0) + XUSB_ERR(xusb, + "USB device is totaly stuck. Dropping packets (#%d).\n", + rate_limit); + ret = -ENODEV; + goto failure; + } + uframe = xframe->priv; + BUG_ON(!uframe); + BUG_ON(uframe->uframe_magic != UFRAME_MAGIC); + uframe_recompute(uframe, XUSB_SEND); + urb = &uframe->urb; + BUG_ON(!urb); + /* update urb length */ + urb->transfer_buffer_length = XFRAME_LEN(xframe); + do_gettimeofday(&xframe->tv_submitted); + ret = usb_submit_urb(urb, GFP_ATOMIC); + if(ret < 0) { + static int rate_limit; + + if((rate_limit++ % 1000) < 5) + XUSB_ERR(xusb, "failed submit_urb: %d\n", ret); + ret = -EBADF; + goto failure; + } +// if (print_dbg) +// dump_xframe("USB_FRAME_SEND", xbus, xframe); + atomic_inc(&xusb->pending_writes); + return 0; +failure: + XUSB_COUNTER(xusb, TX_ERRORS)++; + FREE_SEND_XFRAME(xbus, xframe); /* return to pool */ + return ret; +} + +/* + * PCM wrapper + */ +static int xframe_send_pcm(xbus_t *xbus, xframe_t *xframe) +{ + xusb_t *xusb; + + BUG_ON(!xbus); + BUG_ON(!xframe); + xusb = xusb_of(xbus); + BUG_ON(!xusb); + if(xusb->drop_next_pcm) { + FREE_SEND_XFRAME(xbus, xframe); /* return to pool */ + xusb->drop_next_pcm = 0; + return -EIO; + } + return do_send_xframe(xbus, xframe); +} + +/* + * commands wrapper + */ +static int xframe_send_cmd(xbus_t *xbus, xframe_t *xframe) +{ + BUG_ON(!xbus); + BUG_ON(!xframe); + //XBUS_INFO(xbus, "%s:\n", __FUNCTION__); + return do_send_xframe(xbus, xframe); +} + +/* + * get a urb from the receive_pool and submit it on the read endpoint. + */ +static bool xusb_listen(xusb_t *xusb) +{ + xbus_t *xbus = get_xbus(xusb->xbus_num); + xframe_t *xframe; + struct uframe *uframe; + int ret = 0; + + BUG_ON(!xbus); + xframe = ALLOC_RECV_XFRAME(xbus); + if(!xframe) { + XBUS_ERR(xbus, "Empty receive_pool\n"); + goto out; + } + uframe = xframe_to_uframe(xframe); + uframe_recompute(uframe, XUSB_RECV); + ret = usb_submit_urb(&uframe->urb, GFP_ATOMIC); + if(ret < 0) { + XBUS_ERR(xbus, "Failed to submit a receive urb\n"); + FREE_RECV_XFRAME(xbus, xframe); + goto out; + } + ret = 1; +out: + put_xbus(xbus); + return ret; +} + +/*------------------------- XPP USB Bus Handling -------------------*/ + +enum XUSB_MODELS { + MODEL_FPGA_XPD +}; + +static const struct xusb_model_info { + const char *desc; + int iface_num; + struct xusb_endpoint in; + struct xusb_endpoint out; +} model_table[] = { + [MODEL_FPGA_XPD] { + .iface_num = 0, + .in = { .ep_addr = 0x86 }, + .out = { .ep_addr = 0x02 }, + .desc = "FPGA_XPD" + }, +}; + +/* table of devices that work with this driver */ +static const struct usb_device_id xusb_table [] = { + { USB_DEVICE(0xE4E4, 0x1132), .driver_info=(kernel_ulong_t)&model_table[MODEL_FPGA_XPD] }, // FPGA_FXS + { USB_DEVICE(0xE4E4, 0x1142), .driver_info=(kernel_ulong_t)&model_table[MODEL_FPGA_XPD] }, // FPGA_1141 + { USB_DEVICE(0xE4E4, 0x1152), .driver_info=(kernel_ulong_t)&model_table[MODEL_FPGA_XPD] }, // FPGA_1151 + { USB_DEVICE(0xE4E4, 0x1162), .driver_info=(kernel_ulong_t)&model_table[MODEL_FPGA_XPD] }, // FPGA_1161 + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, xusb_table); + + +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver xusb_driver = { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) + .owner = THIS_MODULE, +#endif + .name = "xpp_usb", + .probe = xusb_probe, + .disconnect = xusb_disconnect, + .id_table = xusb_table, +}; + +/* + * File operations needed when we register this driver. + * This assumes that this driver NEEDS file operations, + * of course, which means that the driver is expected + * to have a node in the /dev directory. If the USB + * device were for a network interface then the driver + * would use "struct net_driver" instead, and a serial + * device would use "struct tty_driver". + */ +static struct file_operations xusb_fops = { + /* + * The owner field is part of the module-locking + * mechanism. The idea is that the kernel knows + * which module to increment the use-counter of + * BEFORE it calls the device's open() function. + * This also means that the kernel can decrement + * the use-counter again before calling release() + * or should the open() function fail. + */ + .owner = THIS_MODULE, +}; + +/* + * usb class driver info in order to get a minor number from the usb core, + * and to have the device registered with devfs and the driver core + */ +static struct usb_class_driver xusb_class = { + .name = "usb/xpp_usb%d", + .fops = &xusb_fops, +/* FIXME: The sysfs class interfase seems to have chaged around here */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) + .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, +#endif + .minor_base = USB_SKEL_MINOR_BASE, +}; + +/* + * Check that an endpoint's wMaxPacketSize attribute is 512. This + * indicates that it is a USB2's high speed end point. + * + * If it is 64, it means we have a USB1 controller. By default we do not + * support it and just fail the probe of the device. However if the user + * has set usb1=1, we continue and just put a notice. + * + * Returns true if all OK, false otherwise. + */ +static int check_usb1(struct usb_endpoint_descriptor *endpoint) +{ + const char *msg = (usb_pipein(endpoint->bEndpointAddress))?"input":"output"; + + if(endpoint->wMaxPacketSize >= sizeof(xpacket_t)) + return 1; + + if(usb1) { + NOTICE("USB1 endpoint detected: USB %s endpoint 0x%X support only wMaxPacketSize=%d.\n", + msg, endpoint->bEndpointAddress, endpoint->wMaxPacketSize); + return 1; + } + NOTICE("USB1 endpoint detected. Device disabled. To enable: usb1=1, and read docs. (%s, endpoint %d, size %d).\n", + msg, endpoint->bEndpointAddress, endpoint->wMaxPacketSize); + return 0; +} + +/* + * set up the endpoint information + * check out the endpoints + * FIXME: Should be simplified (above 2.6.10) to use usb_dev->ep_in[0..16] and usb_dev->ep_out[0..16] + */ +static int set_endpoints(xusb_t *xusb, struct usb_host_interface *iface_desc, struct xusb_model_info *model_info) +{ + struct usb_endpoint_descriptor *endpoint; + struct xusb_endpoint *xusb_ep; + int ep_addr; + int i; + +#define BULK_ENDPOINT(ep) (((ep)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) + + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + ep_addr = endpoint->bEndpointAddress; + + if(!BULK_ENDPOINT(endpoint)) { + DBG(DEVICES, "endpoint 0x%x is not bulk: mbAttributes=0x%X\n", + ep_addr, endpoint->bmAttributes); + continue; + } + if(usb_pipein(ep_addr)) { // Input + if(ep_addr == model_info->in.ep_addr) { + if (!check_usb1(endpoint)) + return 0; + xusb_ep = &xusb->endpoints[XUSB_RECV]; + xusb_ep->ep_addr = ep_addr; + xusb_ep->max_size = endpoint->wMaxPacketSize; + xusb_ep->callback = xpp_receive_callback; + } + } else { // Output + if(ep_addr == model_info->out.ep_addr) { + if (!check_usb1(endpoint)) + return 0; + xusb_ep = &xusb->endpoints[XUSB_SEND]; + xusb_ep->ep_addr = ep_addr; + xusb_ep->max_size = endpoint->wMaxPacketSize; + xusb_ep->callback = xpp_send_callback; + } + } + } + if (!xusb->endpoints[XUSB_RECV].ep_addr || !xusb->endpoints[XUSB_SEND].ep_addr) { + XUSB_ERR(xusb, "Couldn't find bulk-in or bulk-out endpoints\n"); + return 0; + } + DBG(DEVICES, "in=0x%02X out=0x%02X\n", xusb->endpoints[XUSB_RECV].ep_addr, xusb->endpoints[XUSB_SEND].ep_addr); + return 1; +} + +/** + * xusb_probe + * + * Called by the usb core when a new device is connected that it thinks + * this driver might be interested in. + */ +static int xusb_probe(struct usb_interface *interface, const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(interface); + struct usb_host_interface *iface_desc = usb_altnum_to_altsetting(interface, 0); + xusb_t *xusb = NULL; + struct xusb_model_info *model_info = (struct xusb_model_info*)id->driver_info; + struct proc_dir_entry *procsummary = NULL; + xbus_t *xbus = NULL; + unsigned long flags; + int retval = -ENOMEM; + int i; + + DBG(DEVICES, "New XUSB device MODEL=%s\n", model_info->desc); + if(iface_desc->desc.bInterfaceNumber != model_info->iface_num) { + DBG(DEVICES, "Skip interface #%d != #%d\n", + iface_desc->desc.bInterfaceNumber, model_info->iface_num); + return -ENODEV; + } + + /* The USB stack before 2.6.10 seems to be a bit shoddy. It seems that when being called + * from the probe we may already have the lock to udev (the Usb DEVice). Thus we call + * the internal __usb_reset_device instead. */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) + if((retval = __usb_reset_device(udev)) < 0) { +#else + if((retval = usb_reset_device(udev)) < 0) { +#endif + ERR("usb_reset_device failed: %d\n", retval); + goto probe_failed; + } + if (!model_info) { + ERR("Missing endpoint setup for this device %d:%d\n", + udev->descriptor.idVendor,udev->descriptor.idProduct); + retval = -ENODEV; + goto probe_failed; + } + + /* allocate memory for our device state and initialize it */ + xusb = KZALLOC(sizeof(xusb_t), GFP_KERNEL); + if (xusb == NULL) { + ERR("xpp_usb: Unable to allocate new xpp usb bus\n"); + retval = -ENOMEM; + goto probe_failed; + } + init_MUTEX (&xusb->sem); + atomic_set(&xusb->pending_writes, 0); + atomic_set(&xusb->pcm_tx_drops, 0); + atomic_set(&xusb->usb_sluggish_count, 0); + xusb->udev = udev; + xusb->interface = interface; + xusb->model_info = model_info; + + if(!set_endpoints(xusb, iface_desc, model_info)) { + retval = -ENODEV; + goto probe_failed; + } +#ifndef USB_FIELDS_MISSING + xusb->serial = udev->serial; + xusb->manufacturer = udev->manufacturer; + xusb->product = udev->product; + xusb->interface_name = iface_desc->string; +#else + USB_GET_STRING(udev, iSerialNumber, xusb->serial); + USB_GET_STRING(udev, iManufacturer, xusb->manufacturer); + USB_GET_STRING(udev, iProduct, xusb->product); + USB_GET_IFACE_NAME(udev, iface_desc, xusb->interface_name); +#endif + INFO("XUSB: %s -- %s -- %s\n", + xusb->manufacturer, xusb->product, xusb->interface_name); + + /* allow device read, write and ioctl */ + xusb->present = 1; + + /* we can register the device now, as it is ready */ + usb_set_intfdata (interface, xusb); + retval = usb_register_dev (interface, &xusb_class); + if (retval) { + /* something prevented us from registering this driver */ + ERR ("Not able to get a minor for this device.\n"); + goto probe_failed; + } + + xusb->minor = interface->minor; + + /* let the user know what node this device is now attached to */ + DBG(DEVICES, "USB XPP device now attached to minor %d\n", xusb->minor); + xbus = xbus_new(&xusb_ops, min(xusb->endpoints[XUSB_SEND].max_size, xusb->endpoints[XUSB_RECV].max_size), xusb); + if(!xbus) { + retval = -ENOMEM; + goto probe_failed; + } + spin_lock_irqsave(&xusb_lock, flags); + for(i = 0; i < MAX_BUSES; i++) { + if(xusb_array[i] == NULL) + break; + } + spin_unlock_irqrestore(&xusb_lock, flags); + if(i >= MAX_BUSES) { + ERR("xpp_usb: Too many XPP USB buses\n"); + retval = -ENOMEM; + goto probe_failed; + } + usb_make_path(udev, xusb->path, XBUS_DESCLEN); // May trunacte... ignore + snprintf(xbus->busdesc, XBUS_DESCLEN, "%s", xusb->path); + if(xusb->serial && xusb->serial[0]) + snprintf(xbus->label, LABEL_SIZE, "usb:%s", xusb->serial); + xusb->index = i; + xusb_array[i] = xusb; + XUSB_DBG(DEVICES, xusb, "GOT XPP USB BUS: %s\n", xbus->busdesc); + +#ifdef CONFIG_PROC_FS + DBG(PROC, "Creating proc entry " PROC_USBXPP_SUMMARY " in bus proc dir.\n"); + procsummary = create_proc_read_entry(PROC_USBXPP_SUMMARY, 0444, xbus->proc_xbus_dir, + xusb_read_proc, xusb); + if (!procsummary) { + XBUS_ERR(xbus, "Failed to create proc file '%s'\n", PROC_USBXPP_SUMMARY); + // FIXME: better error handling + retval = -EIO; + goto probe_failed; + } + procsummary->owner = THIS_MODULE; +#endif + bus_count++; + xusb->xbus_num = xbus->num; + xusb_listen(xusb); + xbus_activate(xbus); + return retval; +probe_failed: + ERR("Failed to initialize xpp usb bus: %d\n", retval); + usb_set_intfdata (interface, NULL); + if(xusb) { + if(xusb->minor) // passed registration phase + usb_deregister_dev(interface, &xusb_class); + kfree(xusb); + } + if(xbus) { + if(procsummary) { + XBUS_DBG(PROC, xbus, "Remove proc_entry: " PROC_USBXPP_SUMMARY "\n"); + remove_proc_entry(PROC_USBXPP_SUMMARY, xbus->proc_xbus_dir); + procsummary = NULL; + } + xbus_disconnect(xbus); // Blocking until fully deactivated! + } + return retval; +} + +/** + * xusb_disconnect + * + * Called by the usb core when the device is removed from the system. + * + * This routine guarantees that the driver will not submit any more urbs + * by clearing dev->udev. It is also supposed to terminate any currently + * active urbs. Unfortunately, usb_bulk_msg(), used in xusb_read(), does + * not provide any way to do this. But at least we can cancel an active + * write. + */ +static void xusb_disconnect(struct usb_interface *interface) +{ + xusb_t *xusb; + xbus_t *xbus; + int minor; + int i; + + DBG(DEVICES, "CALLED\n"); + /* prevent races with open() */ + down (&disconnect_sem); + + xusb = usb_get_intfdata (interface); + xbus = get_xbus(xusb->xbus_num); + + /* find our xusb */ + for(i = 0; i < MAX_BUSES; i++) { + if(xusb_array[i] == xusb) + break; + } + BUG_ON(i >= MAX_BUSES); + xusb_array[i] = NULL; + +#ifdef CONFIG_PROC_FS + if(xbus->proc_xbus_dir) { + XBUS_DBG(PROC, xbus, "Remove proc_entry: " PROC_USBXPP_SUMMARY "\n"); + remove_proc_entry(PROC_USBXPP_SUMMARY, xbus->proc_xbus_dir); + } +#endif + /* + * put_xbus() would be called during xbus_disconnect() + */ + xbus_disconnect(xbus); // Blocking until fully deactivated! + xusb->present = 0; + usb_set_intfdata (interface, NULL); + + down (&xusb->sem); + minor = xusb->minor; + + /* give back our minor */ + usb_deregister_dev (interface, &xusb_class); + + up (&xusb->sem); + DBG(DEVICES, "Semaphore released\n"); + kfree(xusb); + + up (&disconnect_sem); + XUSB_INFO(xusb, "now disconnected\n"); +} + +static void xpp_send_callback(USB_PASS_CB(urb)) +{ + struct uframe *uframe = urb_to_uframe(urb); + xframe_t *xframe = &uframe->xframe; + xusb_t *xusb = uframe->xusb; + xbus_t *xbus = get_xbus(xusb->xbus_num); + struct timeval now; + long usec; + int writes = atomic_read(&xusb->pending_writes); + int i; + + if(!xbus) { + XUSB_ERR(xusb, "Sent URB does not belong to a valid xbus anymore...\n"); + return; + } + //flip_parport_bit(6); + atomic_dec(&xusb->pending_writes); + do_gettimeofday(&now); + xusb->last_tx = xframe->tv_submitted; + usec = usec_diff(&now, &xframe->tv_submitted); + if(usec > xusb->max_tx_delay) + xusb->max_tx_delay = usec; + i = usec / USEC_BUCKET; + if(i >= NUM_BUCKETS) + i = NUM_BUCKETS - 1; + xusb->usb_tx_delay[i]++; + if(unlikely(usec > tx_sluggish)) { + atomic_inc(&xusb->usb_sluggish_count); + if(xusb->sluggish_debounce++ > drop_pcm_after) { + static int rate_limit; + + if((rate_limit++ % 1003) == 500) /* skip first messages */ + XUSB_NOTICE(xusb, + "Sluggish USB. Dropping next PCM frame (pending_writes=%d)\n", + writes); + atomic_inc(&xusb->pcm_tx_drops); + xusb->drop_next_pcm = 1; + xusb->sluggish_debounce = 0; + } + } else + xusb->sluggish_debounce = 0; + /* sync/async unlink faults aren't errors */ + if (urb->status && !(urb->status == -ENOENT || urb->status == -ECONNRESET)) { + static int rate_limit; + if((rate_limit++ % 1000) < 10) + XUSB_ERR(xusb, + "nonzero write bulk status received: %d (pending_writes=%d)\n", + urb->status, writes); + XUSB_COUNTER(xusb, TX_ERRORS)++; + } else + XUSB_COUNTER(xusb, TX_FRAMES)++; + FREE_SEND_XFRAME(xbus, xframe); + if(!xusb->present) + XUSB_ERR(xusb, "A urb from non-connected device?\n"); + put_xbus(xbus); +} + +static void xpp_receive_callback(USB_PASS_CB(urb)) +{ + struct uframe *uframe = urb_to_uframe(urb); + xframe_t *xframe = &uframe->xframe; + xusb_t *xusb = uframe->xusb; + xbus_t *xbus = get_xbus(xusb->xbus_num); + size_t size; + bool do_resubmit = 1; + bool is_inuse = 0; + + //flip_parport_bit(7); + if(!xbus) { + XUSB_ERR(xusb, "Received URB does not belong to a valid xbus anymore...\n"); + return; + } + if (urb->status) { + DBG(GENERAL, "nonzero read bulk status received: %d\n", urb->status); + XUSB_COUNTER(xusb, RX_ERRORS)++; + goto err; + } + if(!XBUS_GET(xbus)) { + XUSB_ERR(xusb, "Dropping urb. Is shutting down.\n"); + do_resubmit = 0; + goto err; + } + is_inuse = 1; + if(!xusb->present) { + XUSB_ERR(xusb, "A packet from non-connected device?\n"); + do_resubmit = 0; + goto err; + } + size = urb->actual_length; + if(size == 0) { + static int rate_limit; + + if((rate_limit++ % 5003) == 0) + XUSB_NOTICE(xusb, "Received a zero length URBs (%d)\n", rate_limit); + XUSB_COUNTER(xusb, RCV_ZERO_LEN)++; + goto err; + } + atomic_set(&xframe->frame_len, size); + do_gettimeofday(&xframe->tv_received); + +// if (print_dbg) +// dump_xframe("USB_FRAME_RECEIVE", xbus, xframe); + XUSB_COUNTER(xusb, RX_FRAMES)++; + /* Send UP */ + xbus_receive_xframe(xbus, xframe); +end: + if(is_inuse) + XBUS_PUT(xbus); + if(do_resubmit) + xusb_listen(xusb); + put_xbus(xbus); + return; +err: + FREE_RECV_XFRAME(xbus, xframe); + goto end; +} + + +/*------------------------- Initialization -------------------------*/ + +static void xpp_usb_cleanup(void) +{ + if(xusb_cache) { + kmem_cache_destroy(xusb_cache); + xusb_cache = NULL; + } +} + +int __init xpp_usb_init(void) +{ + int ret; + //xusb_t *xusb; + + INFO("revision %s [sizeof(uframe)=%d]\n", XPP_VERSION, sizeof(struct uframe)); + xusb_cache = kmem_cache_create("xusb_cache", + sizeof(xframe_t) + XFRAME_DATASIZE, + 0, 0, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) + NULL, +#endif + NULL); + if(!xusb_cache) { + ret = -ENOMEM; + goto failure; + } + + /* register this driver with the USB subsystem */ + ret = usb_register(&xusb_driver); + if (ret) { + ERR("usb_register failed. Error number %d\n", ret); + goto failure; + } + return 0; +failure: + xpp_usb_cleanup(); + return ret; +} + + +void __exit xpp_usb_shutdown(void) +{ + DBG(GENERAL, "\n"); + /* deregister this driver with the USB subsystem */ + usb_deregister(&xusb_driver); + xpp_usb_cleanup(); +} + + + +#ifdef CONFIG_PROC_FS + +static int xusb_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + unsigned long flags; + int i; + //unsigned long stamp = jiffies; + xusb_t *xusb = data; + uint usb_tx_delay[NUM_BUCKETS]; + const int mark_limit = tx_sluggish/USEC_BUCKET; + + if(!xusb) + goto out; + // TODO: probably needs a per-xusb lock: + spin_lock_irqsave(&xusb_lock, flags); + len += sprintf(page + len, "Device: %03d/%03d\n", + xusb->udev->bus->busnum, + xusb->udev->devnum + ); + len += sprintf(page + len, "USB: manufacturer=%s\n", xusb->manufacturer); + len += sprintf(page + len, "USB: product=%s\n", xusb->product); + len += sprintf(page + len, "USB: serial=%s\n", xusb->serial); + len += sprintf(page + len, "Minor: %d\nModel Info: %s\n", + xusb->minor, xusb->model_info->desc); + len += sprintf(page + len, "Endpoints:\n" + "\tIn: 0x%02X - Size: %d)\n" + "\tOut: 0x%02X - Size: %d)\n", + xusb->endpoints[XUSB_RECV].ep_addr, + xusb->endpoints[XUSB_RECV].max_size, + xusb->endpoints[XUSB_SEND].ep_addr, + xusb->endpoints[XUSB_SEND].max_size + ); + len += sprintf(page + len, "\npending_writes=%d\n", atomic_read(&xusb->pending_writes)); + len += sprintf(page + len, "max_tx_delay=%d\n", xusb->max_tx_delay); + xusb->max_tx_delay = 0; +#ifdef DEBUG_PCM_TIMING + len += sprintf(page + len, "\nstamp_last_pcm_read=%lld accumulate_diff=%lld\n", stamp_last_pcm_read, accumulate_diff); +#endif + memcpy(usb_tx_delay, xusb->usb_tx_delay, sizeof(usb_tx_delay)); + len += sprintf(page + len, "usb_tx_delay[%d,%d,%d]: ", + USEC_BUCKET, BUCKET_START, NUM_BUCKETS); + for(i = BUCKET_START; i < NUM_BUCKETS; i++) { + len += sprintf(page + len, "%6d ", + usb_tx_delay[i]); + if(i == mark_limit) + len += sprintf(page + len, "| "); + } + len += sprintf(page + len, "\nPCM_TX_DROPS: %5d (sluggish: %d)\n", + atomic_read(&xusb->pcm_tx_drops), + atomic_read(&xusb->usb_sluggish_count) + ); + len += sprintf(page + len, "\nCOUNTERS:\n"); + for(i = 0; i < XUSB_COUNTER_MAX; i++) { + len += sprintf(page + len, "\t%-15s = %d\n", xusb_counters[i].name, xusb->counters[i]); + } +#if 0 + len += sprintf(page + len, "<-- len=%d\n", len); +#endif + spin_unlock_irqrestore(&xusb_lock, flags); +out: + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; + +} + +#endif + + + +MODULE_DESCRIPTION("XPP USB Transport Driver"); +MODULE_AUTHOR("Oron Peled "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(XPP_VERSION); + +module_init(xpp_usb_init); +module_exit(xpp_usb_shutdown); diff --git a/kernel/xpp/xpp_zap.c b/kernel/xpp/xpp_zap.c new file mode 100644 index 0000000..edaedf9 --- /dev/null +++ b/kernel/xpp/xpp_zap.c @@ -0,0 +1,1049 @@ +/* + * Written by Oron Peled + * Copyright (C) 2004, Xorcom + * + * Derived from ztdummy + * + * Copyright (C) 2002, Hermes Softlab + * Copyright (C) 2004, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +# warning "This module is tested only with 2.6 kernels" +#endif + +#include +#include +#include +#include +#include +#include /* for udelay */ +#include +#include +#include +#include "xbus-core.h" +#include "xproto.h" +#include "xpp_zap.h" +#include "parport_debug.h" + +static const char rcsid[] = "$Id$"; + +#ifdef CONFIG_PROC_FS +struct proc_dir_entry *xpp_proc_toplevel = NULL; +#define PROC_DIR "xpp" +#define PROC_XPD_ZTREGISTER "zt_registration" +#define PROC_XPD_BLINK "blink" +#define PROC_XPD_SUMMARY "summary" +#endif + +#define MAX_QUEUE_LEN 10000 +#define DELAY_UNTIL_DIALTONE 3000 + +DEF_PARM(int, print_dbg, 0, 0644, "Print DBG statements"); +DEF_PARM_BOOL(zap_autoreg, 0, 0644, "Register spans automatically (1) or not (0)"); +DEF_PARM_BOOL(prefmaster, 0, 0644, "Do we want to be zaptel preferred sync master"); +// DEF_ARRAY(int, pcmtx, 4, 0, "Forced PCM values to transmit"); + +#include "zap_debug.h" + +#ifdef DEBUG_SYNC_PARPORT +/* + * Use parallel port to sample our PCM sync and diagnose quality and + * potential problems. A logic analizer or a scope should be connected + * to the data bits of the parallel port. + * + * Array parameter: Choose the two xbuses Id's to sample. + * This can be changed on runtime as well. Example: + * echo "3,5" > /sys/module/xpp/parameters/parport_xbuses + */ +static int parport_xbuses[2] = { 0, 1 }; +unsigned int parport_xbuses_num_values; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) +module_param_array(parport_xbuses, int, &parport_xbuses_num_values, 0577); +#else +module_param_array(parport_xbuses, int, parport_xbuses_num_values, 0577); +#endif +MODULE_PARM_DESC(parport_xbuses, "Id's of xbuses to sample (1-2)"); + +/* + * Flip a single bit in the parallel port: + * - The bit number is either bitnum0 or bitnum1 + * - Bit is selected by xbus number from parport_xbuses[] + */ +void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1) +{ + int num = xbus->num; + + if(num == parport_xbuses[0]) + flip_parport_bit(bitnum0); + if(num == parport_xbuses[1]) + flip_parport_bit(bitnum1); +} +EXPORT_SYMBOL(xbus_flip_bit); +#endif + +static atomic_t num_registered_spans = ATOMIC_INIT(0); + +int total_registered_spans(void) +{ + return atomic_read(&num_registered_spans); +} + +static int zaptel_register_xpd(xpd_t *xpd); +static int zaptel_unregister_xpd(xpd_t *xpd); +static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data); +static int proc_xpd_ztregister_read(char *page, char **start, off_t off, int count, int *eof, void *data); +static int proc_xpd_ztregister_write(struct file *file, const char __user *buffer, unsigned long count, void *data); +static int proc_xpd_blink_read(char *page, char **start, off_t off, int count, int *eof, void *data); +static int proc_xpd_blink_write(struct file *file, const char __user *buffer, unsigned long count, void *data); +static void xpd_free(xpd_t *xpd); + +static void xpd_free(xpd_t *xpd) +{ + xbus_t *xbus = NULL; + + if(!xpd) + return; + xbus = xpd->xbus; + if(!xbus) + return; + XPD_DBG(DEVICES, xpd, "\n"); +#ifdef CONFIG_PROC_FS + if(xpd->proc_xpd_dir) { + if(xpd->proc_xpd_summary) { + XPD_DBG(PROC, xpd, "Removing proc '%s'\n", PROC_XPD_SUMMARY); + remove_proc_entry(PROC_XPD_SUMMARY, xpd->proc_xpd_dir); + xpd->proc_xpd_summary = NULL; + } + if(xpd->proc_xpd_ztregister) { + XPD_DBG(PROC, xpd, "Removing proc '%s'\n", PROC_XPD_ZTREGISTER); + remove_proc_entry(PROC_XPD_ZTREGISTER, xpd->proc_xpd_dir); + xpd->proc_xpd_ztregister = NULL; + } + if(xpd->proc_xpd_blink) { + XPD_DBG(PROC, xpd, "Removing proc '%s'\n", PROC_XPD_BLINK); + remove_proc_entry(PROC_XPD_BLINK, xpd->proc_xpd_dir); + xpd->proc_xpd_blink = NULL; + } + XPD_DBG(PROC, xpd, "Removing proc directory\n"); + remove_proc_entry(xpd->xpdname, xbus->proc_xbus_dir); + xpd->proc_xpd_dir = NULL; + } +#endif + xbus_unregister_xpd(xbus, xpd); + if(xpd->xproto) + xproto_put(xpd->xproto); + xpd->xproto = NULL; + KZFREE(xpd); +} + + +/*------------------------- XPD Management -------------------------*/ + +/* + * Synchronous part of XPD detection. + * Called from xbus_poll() + */ +void card_detected(struct card_desc_struct *card_desc) +{ + xbus_t *xbus; + xpd_t *xpd = NULL; + byte type; + byte subtype; + int unit; + int subunit; + byte rev; + const xops_t *xops; + const xproto_table_t *proto_table; + + + BUG_ON(!card_desc); + BUG_ON(card_desc->magic != CARD_DESC_MAGIC); + xbus = card_desc->xbus; /* refcount held by xbus_poll() */ + type = card_desc->type; + subtype = card_desc->subtype; + unit = card_desc->xpd_addr.unit; + subunit = card_desc->xpd_addr.subunit; + rev = card_desc->rev; + BUG_ON(!xbus); + xpd = xpd_byaddr(xbus, unit, subunit); + if(xpd) { + if(type == XPD_TYPE_NOMODULE) { + XBUS_NOTICE(xbus, "XPD at %d%d removed\n", + unit, subunit); + BUG(); + goto out; + } + XPD_NOTICE(xpd, "XPD at %d%d already exists\n", + unit, subunit); + goto out; + } + if(type == XPD_TYPE_NOMODULE) { + XBUS_NOTICE(xbus, "XPD at %d%d Missing\n", + unit, subunit); + goto out; + } + proto_table = xproto_get(type); + if(!proto_table) { + XBUS_NOTICE(xbus, "XPD at %d%d: missing protocol table for type=%d. Ignored.\n", + unit, subunit, + type); + goto out; + } + xops = &proto_table->xops; + BUG_ON(!xops); + xpd = xops->card_new(xbus, unit, subunit, proto_table, subtype, rev); + if(!xpd) { + XBUS_NOTICE(xbus, "card_new(%d,%d,%d,%d,%d) failed. Ignored.\n", + unit, subunit, proto_table->type, subtype, rev); + xproto_put(proto_table); + goto err; + } + xpd->addr = card_desc->xpd_addr; + xpd->xbus_idx = XPD_IDX(unit,subunit); + snprintf(xpd->xpdname, XPD_NAMELEN, "XPD-%1d%1d", unit, subunit); + xpd->subtype = card_desc->subtype; + xpd->offhook = card_desc->line_status; + + /* For USB-1 disable some channels */ + if(MAX_SEND_SIZE(xbus) < RPACKET_SIZE(GLOBAL, PCM_WRITE)) { + xpp_line_t no_pcm; + + no_pcm = 0x7F | xpd->digital_outputs | xpd->digital_inputs; + xpd->no_pcm = no_pcm; + XBUS_NOTICE(xbus, "max xframe size = %d, disabling some PCM channels. no_pcm=0x%04X\n", + MAX_SEND_SIZE(xbus), xpd->no_pcm); + } + xbus_register_xpd(xbus, xpd); +#ifdef CONFIG_PROC_FS + XPD_DBG(PROC, xpd, "Creating proc directory\n"); + xpd->proc_xpd_dir = proc_mkdir(xpd->xpdname, xbus->proc_xbus_dir); + if(!xpd->proc_xpd_dir) { + XPD_ERR(xpd, "Failed to create proc directory\n"); + goto err; + } + xpd->proc_xpd_summary = create_proc_read_entry(PROC_XPD_SUMMARY, 0444, xpd->proc_xpd_dir, + xpd_read_proc, xpd); + if(!xpd->proc_xpd_summary) { + XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_XPD_SUMMARY); + goto err; + } + xpd->proc_xpd_summary->owner = THIS_MODULE; + xpd->proc_xpd_ztregister = create_proc_entry(PROC_XPD_ZTREGISTER, 0644, xpd->proc_xpd_dir); + if (!xpd->proc_xpd_ztregister) { + XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_XPD_ZTREGISTER); + goto err; + } + xpd->proc_xpd_ztregister->owner = THIS_MODULE; + xpd->proc_xpd_ztregister->data = xpd; + xpd->proc_xpd_ztregister->read_proc = proc_xpd_ztregister_read; + xpd->proc_xpd_ztregister->write_proc = proc_xpd_ztregister_write; + xpd->proc_xpd_blink = create_proc_entry(PROC_XPD_BLINK, 0644, xpd->proc_xpd_dir); + if (!xpd->proc_xpd_blink) { + XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_XPD_BLINK); + goto err; + } + xpd->proc_xpd_blink->owner = THIS_MODULE; + xpd->proc_xpd_blink->data = xpd; + xpd->proc_xpd_blink->read_proc = proc_xpd_blink_read; + xpd->proc_xpd_blink->write_proc = proc_xpd_blink_write; +#endif + if(CALL_XMETHOD(card_init, xbus, xpd) < 0) + goto err; + //CALL_XMETHOD(XPD_STATE, xbus, xpd, 0); /* Turn off all channels */ + xpd->card_present = 1; + CALL_XMETHOD(XPD_STATE, xbus, xpd, 1); /* Turn on all channels */ + XPD_INFO(xpd, "Initialized: %s\n", xpd->type_name); + + if(zap_autoreg) + zaptel_register_xpd(xpd); +out: + KZFREE(card_desc); + return; +err: + xpd_free(xpd); + goto out; +} + + +#ifdef CONFIG_PROC_FS + +/** + * Prints a general procfs entry for the bus, under xpp/BUSNAME/summary + * @page TODO: figure out procfs + * @start TODO: figure out procfs + * @off TODO: figure out procfs + * @count TODO: figure out procfs + * @eof TODO: figure out procfs + * @data an xbus_t pointer with the bus data. + */ +static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + xpd_t *xpd = data; + xbus_t *xbus; + int i; + + if(!xpd) + goto out; + + xbus = xpd->xbus; + len += sprintf(page + len, "%s (%s ,card %s, span %d)\n" + "timing_priority: %d\n" + "timer_count: %d span->mainttimer=%d\n" + , + xpd->xpdname, xpd->type_name, + (xpd->card_present) ? "present" : "missing", + (SPAN_REGISTERED(xpd)) ? xpd->span.spanno : 0, + xpd->timing_priority, + xpd->timer_count, xpd->span.mainttimer + ); + len += sprintf(page + len, "Address: U=%d S=%d\n", xpd->addr.unit, xpd->addr.subunit); + len += sprintf(page + len, "Type: %d.%d\n\n", xpd->type, xpd->subtype); + len += sprintf(page + len, "pcm_len=%d\n\n", xpd->pcm_len); + len += sprintf(page + len, "wanted_pcm_mask=0x%04X\n\n", xpd->wanted_pcm_mask); + len += sprintf(page + len, "mute_dtmf=0x%04X\n\n", xpd->mute_dtmf); + len += sprintf(page + len, "STATES:"); + len += sprintf(page + len, "\n\t%-17s: ", "output_relays"); + for_each_line(xpd, i) { + len += sprintf(page + len, "%d ", IS_SET(xpd->digital_outputs, i)); + } + len += sprintf(page + len, "\n\t%-17s: ", "input_relays"); + for_each_line(xpd, i) { + len += sprintf(page + len, "%d ", IS_SET(xpd->digital_inputs, i)); + } + len += sprintf(page + len, "\n\t%-17s: ", "offhook"); + for_each_line(xpd, i) { + len += sprintf(page + len, "%d ", IS_SET(xpd->offhook, i)); + } + len += sprintf(page + len, "\n\t%-17s: ", "cid_on"); + for_each_line(xpd, i) { + len += sprintf(page + len, "%d ", IS_SET(xpd->cid_on, i)); + } + len += sprintf(page + len, "\n\t%-17s: ", "msg_waiting"); + for_each_line(xpd, i) { + len += sprintf(page + len, "%d ", IS_SET(xpd->msg_waiting, i)); + } + len += sprintf(page + len, "\n\t%-17s: ", "ringing"); + for_each_line(xpd, i) { + len += sprintf(page + len, "%d ", xpd->ringing[i]); + } + len += sprintf(page + len, "\n\t%-17s: ", "no_pcm"); + for_each_line(xpd, i) { + len += sprintf(page + len, "%d ", IS_SET(xpd->no_pcm, i)); + } +#if 1 + if(SPAN_REGISTERED(xpd)) { + len += sprintf(page + len, "\nPCM:\n | [readchunk] | [writechunk] | W D"); + for_each_line(xpd, i) { + struct zt_chan *chans = xpd->span.chans; + byte rchunk[ZT_CHUNKSIZE]; + byte wchunk[ZT_CHUNKSIZE]; + byte *rp; + byte *wp; + int j; + + if(IS_SET(xpd->digital_outputs, i)) + continue; + if(IS_SET(xpd->digital_inputs, i)) + continue; + if(IS_SET(xpd->digital_signalling, i)) + continue; + rp = chans[i].readchunk; + wp = chans[i].writechunk; + memcpy(rchunk, rp, ZT_CHUNKSIZE); + memcpy(wchunk, wp, ZT_CHUNKSIZE); + len += sprintf(page + len, "\n port %2d> | ", i); + for(j = 0; j < ZT_CHUNKSIZE; j++) { + len += sprintf(page + len, "%02X ", rchunk[j]); + } + len += sprintf(page + len, " | "); + for(j = 0; j < ZT_CHUNKSIZE; j++) { + len += sprintf(page + len, "%02X ", wchunk[j]); + } + len += sprintf(page + len, " | %c", + (IS_SET(xpd->wanted_pcm_mask, i))?'+':' '); + len += sprintf(page + len, " %c", + (IS_SET(xpd->mute_dtmf, i))?'-':' '); + } + } +#endif +#if 0 + if(SPAN_REGISTERED(xpd)) { + len += sprintf(page + len, "\nSignalling:\n"); + for_each_line(xpd, i) { + struct zt_chan *chan = &xpd->span.chans[i]; + len += sprintf(page + len, "\t%2d> sigcap=0x%04X sig=0x%04X\n", i, chan->sigcap, chan->sig); + } + } +#endif + len += sprintf(page + len, "\nCOUNTERS:\n"); + for(i = 0; i < XPD_COUNTER_MAX; i++) { + len += sprintf(page + len, "\t\t%-20s = %d\n", + xpd_counters[i].name, xpd->counters[i]); + } + len += sprintf(page + len, "<-- len=%d\n", len); +out: + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; + +} + +#endif + +/* + * xpd_alloc - Allocator for new XPD's + * + */ +xpd_t *xpd_alloc(size_t privsize, const xproto_table_t *proto_table, int channels) +{ + xpd_t *xpd = NULL; + size_t alloc_size = sizeof(xpd_t) + privsize; + int type = proto_table->type; + + DBG(DEVICES, "type=%d channels=%d (alloc_size=%d)\n", + type, channels, alloc_size); + if(channels > CHANNELS_PERXPD) { + ERR("%s: type=%d: too many channels %d\n", + __FUNCTION__, type, channels); + goto err; + } + + if((xpd = KZALLOC(alloc_size, GFP_KERNEL)) == NULL) { + ERR("%s: type=%d: Unable to allocate memory\n", + __FUNCTION__, type); + goto err; + } + xpd->priv = (byte *)xpd + sizeof(xpd_t); + spin_lock_init(&xpd->lock); + xpd->xbus = NULL; + xpd->xbus_idx = -1; + xpd->channels = channels; + xpd->chans = NULL; + xpd->card_present = 0; + xpd->offhook = 0x0; /* ONHOOK */ + xpd->type = proto_table->type; + xpd->xproto = proto_table; + xpd->xops = &proto_table->xops; + xpd->digital_outputs = 0; + xpd->digital_inputs = 0; + + atomic_set(&xpd->zt_registered, 0); + atomic_set(&xpd->open_counter, 0); + + xpd->chans = kmalloc(sizeof(struct zt_chan)*xpd->channels, GFP_KERNEL); + if (xpd->chans == NULL) { + ERR("%s: Unable to allocate channels\n", __FUNCTION__); + goto err; + } + return xpd; +err: + if(xpd) { + if(xpd->chans) + kfree((void *)xpd->chans); + kfree(xpd); + } + return NULL; +} + +/* FIXME: this should be removed once digium patch their zaptel.h + * I simply wish to avoid changing zaptel.h in the xpp patches. + */ +#ifndef ZT_EVENT_REMOVED +#define ZT_EVENT_REMOVED (20) +#endif + +void xpd_disconnect(xpd_t *xpd) +{ + unsigned long flags; + + BUG_ON(!xpd); + + spin_lock_irqsave(&xpd->lock, flags); + XPD_DBG(DEVICES, xpd, "(%p)\n", xpd->xproto); + if(!xpd->card_present) /* Multiple reports */ + goto out; + xpd->card_present = 0; + if(SPAN_REGISTERED(xpd)) { + int i; + + update_xpd_status(xpd, ZT_ALARM_NOTOPEN); + /* TODO: Should this be done before releasing the spinlock? */ + XPD_DBG(DEVICES, xpd, "Queuing ZT_EVENT_REMOVED on all channels to ask user to release them\n"); + for (i=0; ispan.channels; i++) + zt_qevent_lock(&xpd->chans[i],ZT_EVENT_REMOVED); + } +out: + spin_unlock_irqrestore(&xpd->lock, flags); +} + +void xpd_remove(xpd_t *xpd) +{ + xbus_t *xbus; + + BUG_ON(!xpd); + xbus = xpd->xbus; + XPD_INFO(xpd, "Remove\n"); + zaptel_unregister_xpd(xpd); + CALL_XMETHOD(card_remove, xbus, xpd); + xpd_free(xpd); +} + +void update_xpd_status(xpd_t *xpd, int alarm_flag) +{ + struct zt_span *span = &xpd->span; + + if(!SPAN_REGISTERED(xpd)) { + // XPD_NOTICE(xpd, "%s: XPD is not registered. Skipping.\n", __FUNCTION__); + return; + } + switch (alarm_flag) { + case ZT_ALARM_NONE: + xpd->last_response = jiffies; + break; + default: + // Nothing + break; + } + if(span->alarms == alarm_flag) + return; + span->alarms = alarm_flag; + zt_alarm_notify(span); + XPD_DBG(GENERAL, xpd, "Update XPD alarms: %s -> %02X\n", xpd->span.name, alarm_flag); +} + +void update_line_status(xpd_t *xpd, int pos, bool to_offhook) +{ + zt_rxsig_t rxsig; + + BUG_ON(!xpd); + if(to_offhook) { + BIT_SET(xpd->offhook, pos); + rxsig = ZT_RXSIG_OFFHOOK; + } else { + BIT_CLR(xpd->offhook, pos); + BIT_CLR(xpd->cid_on, pos); + rxsig = ZT_RXSIG_ONHOOK; + /* + * To prevent latest PCM to stay in buffers + * indefinitely, mark this channel for a + * single silence transmittion. + * + * This bit will be cleared on the next tick. + */ + BIT_SET(xpd->silence_pcm, pos); + } + /* + * We should not spinlock before calling zt_hooksig() as + * it may call back into our xpp_hooksig() and cause + * a nested spinlock scenario + */ + LINE_DBG(SIGNAL, xpd, pos, "rxsig=%s\n", (rxsig == ZT_RXSIG_ONHOOK) ? "ONHOOK" : "OFFHOOK"); + if(SPAN_REGISTERED(xpd)) + zt_hooksig(&xpd->chans[pos], rxsig); +} + +#ifdef CONFIG_PROC_FS +int proc_xpd_ztregister_read(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + unsigned long flags; + xpd_t *xpd = data; + + BUG_ON(!xpd); + spin_lock_irqsave(&xpd->lock, flags); + + len += sprintf(page + len, "%d\n", SPAN_REGISTERED(xpd) ? xpd->span.spanno : 0); + spin_unlock_irqrestore(&xpd->lock, flags); + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; +} + +static int proc_xpd_ztregister_write(struct file *file, const char __user *buffer, unsigned long count, void *data) +{ + xpd_t *xpd = data; + char buf[MAX_PROC_WRITE]; + int zt_reg; + int ret; + + BUG_ON(!xpd); + if(count >= MAX_PROC_WRITE) + return -EINVAL; + if(copy_from_user(buf, buffer, count)) + return -EFAULT; + buf[count] = '\0'; + ret = sscanf(buf, "%d", &zt_reg); + if(ret != 1) + return -EINVAL; + XPD_DBG(GENERAL, xpd, "%s\n", (zt_reg) ? "register" : "unregister"); + if(zt_reg) + ret = zaptel_register_xpd(xpd); + else + ret = zaptel_unregister_xpd(xpd); + return (ret < 0) ? ret : count; +} + +int proc_xpd_blink_read(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = 0; + unsigned long flags; + xpd_t *xpd = data; + + BUG_ON(!xpd); + spin_lock_irqsave(&xpd->lock, flags); + + len += sprintf(page + len, "%d\n", xpd->blink_mode); + spin_unlock_irqrestore(&xpd->lock, flags); + if (len <= off+count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; +} + +static int proc_xpd_blink_write(struct file *file, const char __user *buffer, unsigned long count, void *data) +{ + xpd_t *xpd = data; + char buf[MAX_PROC_WRITE]; + int blink; + int ret; + + BUG_ON(!xpd); + if(count >= MAX_PROC_WRITE) + return -EINVAL; + if(copy_from_user(buf, buffer, count)) + return -EFAULT; + buf[count] = '\0'; + ret = sscanf(buf, "%d", &blink); + if(ret != 1) + return -EINVAL; + XPD_DBG(GENERAL, xpd, "%s\n", (blink) ? "blink" : "unblink"); + xpd->blink_mode = blink; + return count; +} + +#endif + + +#define XPP_MAX_LEN 512 + +/*------------------------- Zaptel Interfaces ----------------------*/ + + +/* + * Called from zaptel with spinlock held on chan. Must not call back + * zaptel functions. + */ +int xpp_open(struct zt_chan *chan) +{ +#if 0 + xpd_t *xpd = chan->pvt; + xbus_t *xbus = xpd->xbus; + int pos = chan->chanpos - 1; + unsigned long flags; +#else + xpd_t *xpd; + xbus_t *xbus; + int pos; + unsigned long flags; + + if (!chan) { + NOTICE("open called on a null chan\n"); + return -EINVAL; + } + xpd = chan->pvt; + if (!xpd) { + NOTICE("open called on a chan with no pvt (xpd)\n"); + return -EINVAL; + } + xbus = xpd->xbus; + if (!xbus) { + NOTICE("open called on a chan with no xbus\n"); + return -EINVAL; + } + pos = chan->chanpos - 1; +#endif + + spin_lock_irqsave(&xbus->lock, flags); + atomic_inc(&xbus->xbus_ref_count); + atomic_inc(&xpd->open_counter); + if(IS_SET(xpd->digital_signalling, pos)) /* D-chan offhook */ + BIT_SET(xpd->offhook, pos); + DBG(DEVICES, "chan=%d (xbus_ref_count=%d)\n", + pos, atomic_read(&xbus->xbus_ref_count)); + spin_unlock_irqrestore(&xbus->lock, flags); + if(xpd->xops->card_open) + xpd->xops->card_open(xpd, pos); + return 0; +} + +int xpp_close(struct zt_chan *chan) +{ + xpd_t *xpd = chan->pvt; + xbus_t *xbus = xpd->xbus; + int pos = chan->chanpos - 1; + unsigned long flags; + + spin_lock_irqsave(&xbus->lock, flags); + atomic_dec(&xpd->open_counter); + if(IS_SET(xpd->digital_signalling, pos)) /* D-chan onhook */ + BIT_CLR(xpd->offhook, pos); + spin_unlock_irqrestore(&xbus->lock, flags); + if(xpd->xops->card_close) + xpd->xops->card_close(xpd, pos); + XPD_DBG(GENERAL, xpd, "pid=%d: chan=%d (xbus_ref_count=%d)\n", + current->pid, pos, atomic_read(&xbus->xbus_ref_count)); + if(atomic_dec_and_test(&xbus->xbus_ref_count)) + xbus_remove(xbus); + return 0; +} + +void report_bad_ioctl(const char *msg, xpd_t *xpd, int pos, unsigned int cmd) +{ + XPD_NOTICE(xpd, "%s: Bad ioctl\n", msg); + XPD_NOTICE(xpd, "ENOTTY: chan=%d cmd=0x%x\n", pos, cmd); + XPD_NOTICE(xpd, " IOC_TYPE=0x%02X\n", _IOC_TYPE(cmd)); + XPD_NOTICE(xpd, " IOC_DIR=0x%02X\n", _IOC_DIR(cmd)); + XPD_NOTICE(xpd, " IOC_NR=%d\n", _IOC_NR(cmd)); + XPD_NOTICE(xpd, " IOC_SIZE=0x%02X\n", _IOC_SIZE(cmd)); +} + +int xpp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long arg) +{ + xpd_t *xpd = chan->pvt; + int pos = chan->chanpos - 1; + + if(!xpd) { + ERR("%s: channel in pos %d, was already closed. Ignore.\n", + __FUNCTION__, pos); + return -ENODEV; + } + switch (cmd) { + default: + /* Some span-specific commands before we give up: */ + if (xpd->xops->card_ioctl != NULL) { + return xpd->xops->card_ioctl(xpd, pos, cmd, arg); + } + report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd); + return -ENOTTY; + } + return 0; +} + +static int xpp_hooksig(struct zt_chan *chan, zt_txsig_t txsig) +{ + xpd_t *xpd = chan->pvt; + xbus_t *xbus; + int pos = chan->chanpos - 1; + + if(!xpd) { + ERR("%s: channel in pos %d, was already closed. Ignore.\n", + __FUNCTION__, pos); + return -ENODEV; + } + xbus = xpd->xbus; + BUG_ON(!xbus); + DBG(SIGNAL, "Setting %s to %s (%d)\n", chan->name, txsig2str(txsig), txsig); + return CALL_XMETHOD(card_hooksig, xbus, xpd, pos, txsig); +} + +/* Req: Set the requested chunk size. This is the unit in which you must + report results for conferencing, etc */ +int xpp_setchunksize(struct zt_span *span, int chunksize); + +/* Enable maintenance modes */ +int xpp_maint(struct zt_span *span, int cmd) +{ + xpd_t *xpd = span->pvt; + int ret = 0; +#if 0 + char loopback_data[] = "THE-QUICK-BROWN-FOX-JUMPED-OVER-THE-LAZY-DOG"; +#endif + + DBG(GENERAL, "span->mainttimer=%d\n", span->mainttimer); + switch(cmd) { + case ZT_MAINT_NONE: + printk("XXX Turn off local and remote loops XXX\n"); + break; + case ZT_MAINT_LOCALLOOP: + printk("XXX Turn on local loopback XXX\n"); + break; + case ZT_MAINT_REMOTELOOP: + printk("XXX Turn on remote loopback XXX\n"); + break; + case ZT_MAINT_LOOPUP: + printk("XXX Send loopup code XXX\n"); + // CALL_XMETHOD(LOOPBACK_AX, xpd->xbus, xpd, loopback_data, ARRAY_SIZE(loopback_data)); + break; + case ZT_MAINT_LOOPDOWN: + printk("XXX Send loopdown code XXX\n"); + break; + case ZT_MAINT_LOOPSTOP: + printk("XXX Stop sending loop codes XXX\n"); + break; + default: + ERR("XPP: Unknown maint command: %d\n", cmd); + ret = -EINVAL; + break; + } + if (span->mainttimer || span->maintstat) + update_xpd_status(xpd, ZT_ALARM_LOOPBACK); + return ret; +} + +#ifdef CONFIG_ZAPTEL_WATCHDOG +/* + * If the watchdog detects no received data, it will call the + * watchdog routine + */ +static int xpp_watchdog(struct zt_span *span, int cause) +{ + static int rate_limit = 0; + + if((rate_limit++ % 1000) == 0) + DBG(GENERAL, "\n"); + return 0; +} +#endif + +/** + * Unregister an xpd from zaptel and release related resources + * @xpd The xpd to be unregistered + * @returns 0 on success, errno otherwise + * + * Checks that nobody holds an open channel. + * + * Called by: + * - User action through /proc + * - During xpd_remove() + */ +static int zaptel_unregister_xpd(xpd_t *xpd) +{ + unsigned long flags; + + BUG_ON(!xpd); + spin_lock_irqsave(&xpd->lock, flags); + + if(!SPAN_REGISTERED(xpd)) { + XPD_NOTICE(xpd, "Already unregistered\n"); + spin_unlock_irqrestore(&xpd->lock, flags); + return -EIDRM; + } + update_xpd_status(xpd, ZT_ALARM_NOTOPEN); + if(atomic_read(&xpd->open_counter)) { + XPD_NOTICE(xpd, "Busy (open_counter=%d). Skipping.\n", atomic_read(&xpd->open_counter)); + spin_unlock_irqrestore(&xpd->lock, flags); + return -EBUSY; + } + mdelay(2); // FIXME: This is to give chance for transmit/receiveprep to finish. + spin_unlock_irqrestore(&xpd->lock, flags); + if(xpd->card_present) + xpd->xops->card_zaptel_preregistration(xpd, 0); + atomic_dec(&xpd->zt_registered); + atomic_dec(&num_registered_spans); + zt_unregister(&xpd->span); + if(xpd->card_present) + xpd->xops->card_zaptel_postregistration(xpd, 0); + return 0; +} + +static int zaptel_register_xpd(xpd_t *xpd) +{ + struct zt_span *span; + xbus_t *xbus; + int cn; + const xops_t *xops; + + BUG_ON(!xpd); + xops = xpd->xops; + xbus = xpd->xbus; + + if (SPAN_REGISTERED(xpd)) { + XPD_ERR(xpd, "Already registered\n"); + return -EEXIST; + } + cn = xpd->channels; + XPD_DBG(DEVICES, xpd, "Initializing span: %d channels.\n", cn); + memset(xpd->chans, 0, sizeof(struct zt_chan)*cn); + memset(&xpd->span, 0, sizeof(struct zt_span)); + + span = &xpd->span; + snprintf(span->name, MAX_SPANNAME, "%s/%s", xbus->busname, xpd->xpdname); + span->deflaw = ZT_LAW_MULAW; /* default, may be overriden by card_* drivers */ + init_waitqueue_head(&span->maintq); + span->pvt = xpd; + span->channels = cn; + span->chans = xpd->chans; + + span->open = xpp_open; + span->close = xpp_close; + span->flags = ZT_FLAG_RBS; + span->hooksig = xpp_hooksig; /* Only with RBS bits */ + span->ioctl = xpp_ioctl; + span->maint = xpp_maint; +#ifdef ZAPTEL_SYNC_TICK + span->sync_tick = zaptel_sync_tick; +#endif + if (xpp_ec) + span->echocan = xpp_echocan; +#ifdef CONFIG_ZAPTEL_WATCHDOG + span->watchdog = xpp_watchdog; +#endif + + snprintf(xpd->span.desc, MAX_SPANDESC, "Xorcom XPD #%02d/%1d%1d: %s", + xbus->num, xpd->addr.unit, xpd->addr.subunit, xpd->type_name); + XPD_DBG(GENERAL, xpd, "Registering span '%s'\n", xpd->span.desc); + xpd->xops->card_zaptel_preregistration(xpd, 1); + if(zt_register(&xpd->span, prefmaster)) { + XPD_ERR(xpd, "Failed to zt_register span\n"); + return -ENODEV; + } + atomic_inc(&num_registered_spans); + atomic_inc(&xpd->zt_registered); + xpd->xops->card_zaptel_postregistration(xpd, 1); + /* + * Update zaptel about our state + */ +#if 0 + /* + * FIXME: since asterisk didn't open the channel yet, the report + * is discarded anyway. OTOH, we cannot report in xpp_open or + * xpp_chanconfig since zaptel call them with a spinlock on the channel + * and zt_hooksig tries to acquire the same spinlock, resulting in + * double spinlock deadlock (we are lucky that RH/Fedora kernel are + * compiled with spinlock debugging).... tough. + */ + for_each_line(xpd, cn) { + struct zt_chan *chans = xpd->span.chans; + + if(IS_SET(xpd->offhook, cn)) { + LINE_NOTICE(xpd, cn, "Report OFFHOOK to zaptel\n"); + zt_hooksig(&chans[cn], ZT_RXSIG_OFFHOOK); + } + } +#endif + return 0; +} + +/*------------------------- Proc debugging interface ---------------*/ + +#ifdef CONFIG_PROC_FS + +#if 0 +static int xpp_zap_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data) +{ +} +#endif + +#endif + +/*------------------------- Initialization -------------------------*/ + +static void do_cleanup(void) +{ +#ifdef CONFIG_PROC_FS + if(xpp_proc_toplevel) { + DBG(GENERAL, "Removing '%s' from proc\n", PROC_DIR); + remove_proc_entry(PROC_DIR, NULL); + xpp_proc_toplevel = NULL; + } +#endif +} + +int __init xpp_zap_init(void) +{ + int ret = 0; + + INFO("revision %s MAX_XPDS=%d (%d*%d)\n", XPP_VERSION, + MAX_XPDS, MAX_UNIT, MAX_SUBUNIT); +#ifdef CONFIG_ZAPATA_BRI_DCHANS + INFO("FEATURE: with BRISTUFF support\n"); +#else + INFO("FEATURE: without BRISTUFF support\n"); +#endif +#ifdef CONFIG_PROC_FS + xpp_proc_toplevel = proc_mkdir(PROC_DIR, NULL); + if(!xpp_proc_toplevel) { + ret = -EIO; + goto err; + } +#endif + ret = xbus_core_init(); + if(ret) { + ERR("xbus_core_init failed (%d)\n", ret); + goto err; + } + ret = xbus_pcm_init(xpp_proc_toplevel); + if(ret) { + ERR("xbus_pcm_init failed (%d)\n", ret); + xbus_core_shutdown(); + goto err; + } + return 0; +err: + do_cleanup(); + return ret; +} + +void __exit xpp_zap_cleanup(void) +{ + xbus_pcm_shutdown(); + xbus_core_shutdown(); + do_cleanup(); +} + +EXPORT_SYMBOL(print_dbg); +EXPORT_SYMBOL(card_detected); +EXPORT_SYMBOL(xpd_alloc); +EXPORT_SYMBOL(xpd_disconnect); +EXPORT_SYMBOL(update_xpd_status); +EXPORT_SYMBOL(update_line_status); +EXPORT_SYMBOL(xpp_open); +EXPORT_SYMBOL(xpp_close); +EXPORT_SYMBOL(xpp_ioctl); +EXPORT_SYMBOL(xpp_maint); +EXPORT_SYMBOL(report_bad_ioctl); + +MODULE_DESCRIPTION("XPP Zaptel Driver"); +MODULE_AUTHOR("Oron Peled "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(XPP_VERSION); + +module_init(xpp_zap_init); +module_exit(xpp_zap_cleanup); diff --git a/kernel/xpp/xpp_zap.h b/kernel/xpp/xpp_zap.h new file mode 100644 index 0000000..fee20c5 --- /dev/null +++ b/kernel/xpp/xpp_zap.h @@ -0,0 +1,49 @@ +#ifndef XPP_ZAP_H +#define XPP_ZAP_H +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "xpd.h" +#include "xproto.h" + +void xpd_disconnect(xpd_t *xpd); +void card_detected(struct card_desc_struct *card_desc); +xpd_t *xpd_alloc(size_t privsize, const xproto_table_t *proto_table, int channels); +void xpd_remove(xpd_t *xpd); +void update_xpd_status(xpd_t *xpd, int alarm_flag); +void update_line_status(xpd_t *xpd, int pos, bool good); +int xpp_open(struct zt_chan *chan); +int xpp_close(struct zt_chan *chan); +int xpp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long arg); +int xpp_maint(struct zt_span *span, int cmd); +void report_bad_ioctl(const char *msg, xpd_t *xpd, int pos, unsigned int cmd); +int total_registered_spans(void); + +#ifdef CONFIG_PROC_FS +#include + +extern struct proc_dir_entry *xpp_proc_toplevel; +#endif + +#define SPAN_REGISTERED(xpd) atomic_read(&(xpd)->zt_registered) + +#endif /* XPP_ZAP_H */ diff --git a/kernel/xpp/xproto.c b/kernel/xpp/xproto.c new file mode 100644 index 0000000..d55949e --- /dev/null +++ b/kernel/xpp/xproto.c @@ -0,0 +1,446 @@ +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "xpd.h" +#include "xproto.h" +#include "xpp_zap.h" +#include "xbus-core.h" +#include "zap_debug.h" +#include +#include + +static const char rcsid[] = "$Id$"; + +extern int print_dbg; + +static const xproto_table_t *xprotocol_tables[XPD_TYPE_NOMODULE]; + +#if MAX_UNIT*MAX_SUBUNIT > MAX_XPDS +#error MAX_XPDS is too small +#endif + +bool valid_xpd_addr(const struct xpd_addr *addr) +{ + return ((addr->subunit & ~BITMASK(SUBUNIT_BITS)) == 0) && ((addr->unit & ~BITMASK(UNIT_BITS)) == 0); +} + +/*---------------- General Protocol Management ----------------------------*/ + +const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, byte opcode) +{ + const xproto_entry_t *xe; + + //DBG(GENERAL, "\n"); + xe = &table->entries[opcode]; + return (xe->handler != NULL) ? xe : NULL; +} + +const xproto_entry_t *xproto_global_entry(byte opcode) +{ + const xproto_entry_t *xe; + + xe = xproto_card_entry(&PROTO_TABLE(GLOBAL), opcode); + //DBG(GENERAL, "opcode=0x%X xe=%p\n", opcode, xe); + return xe; +} + +xproto_handler_t xproto_global_handler(byte opcode) +{ + return xproto_card_handler(&PROTO_TABLE(GLOBAL), opcode); +} + +const xproto_table_t *xproto_table(xpd_type_t cardtype) +{ + if(cardtype >= XPD_TYPE_NOMODULE) + return NULL; + return xprotocol_tables[cardtype]; +} + +const xproto_table_t *xproto_get(xpd_type_t cardtype) +{ + const xproto_table_t *xtable; + + if(cardtype >= XPD_TYPE_NOMODULE) + return NULL; + xtable = xprotocol_tables[cardtype]; + if(!xtable) { /* Try to load the relevant module */ + int ret = request_module(XPD_TYPE_PREFIX "%d", cardtype); + if(ret != 0) { + NOTICE("%s: Failed to load module for type=%d. exit status=%d.\n", + __FUNCTION__, cardtype, ret); + /* Drop through: we may be lucky... */ + } + xtable = xprotocol_tables[cardtype]; + } + if(xtable) { + BUG_ON(!xtable->owner); + DBG(GENERAL, "%s refcount was %d\n", xtable->name, module_refcount(xtable->owner)); + if(!try_module_get(xtable->owner)) { + ERR("%s: try_module_get for %s failed.\n", __FUNCTION__, xtable->name); + return NULL; + } + } + return xtable; +} + +void xproto_put(const xproto_table_t *xtable) +{ + BUG_ON(!xtable); + DBG(GENERAL, "%s refcount was %d\n", xtable->name, module_refcount(xtable->owner)); + BUG_ON(module_refcount(xtable->owner) <= 0); + module_put(xtable->owner); +} + +xproto_handler_t xproto_card_handler(const xproto_table_t *table, byte opcode) +{ + const xproto_entry_t *xe; + + //DBG(GENERAL, "\n"); + xe = xproto_card_entry(table, opcode); + return xe->handler; +} + +void notify_bad_xpd(const char *funcname, xbus_t *xbus, const struct xpd_addr addr, const char *msg) +{ + XBUS_NOTICE(xbus, "%s: non-existing address (%1d%1d): %s\n", + funcname, addr.unit, addr.subunit, msg); +} + +int packet_process(xbus_t *xbus, xpacket_t *pack) +{ + byte op; + const xproto_entry_t *xe; + xproto_handler_t handler; + xproto_table_t *table; + xpd_t *xpd; + int ret = -EPROTO; + + BUG_ON(!pack); + if(!valid_xpd_addr(&XPACKET_ADDR(pack))) { + if(printk_ratelimit()) { + XBUS_NOTICE(xbus, "%s: from %d%d: bad address.\n", + __FUNCTION__, + XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack)); + dump_packet("packet_process -- bad address", pack, print_dbg); + } + goto out; + } + op = XPACKET_OP(pack); + xpd = xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack)); + /* XPD may be NULL (e.g: during bus polling */ + xe = xproto_global_entry(op); + /*-------- Validations -----------*/ + if(!xe) { + const xproto_table_t *xtable; + + if(!xpd) { + if(printk_ratelimit()) { + XBUS_NOTICE(xbus, "%s: from %d%d opcode=0x%02X: no such global command.\n", + __FUNCTION__, + XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack), op); + dump_packet("packet_process -- no such global command", pack, 1); + } + goto out; + } + xtable = xproto_table(xpd->type); + if(!xtable) { + if(printk_ratelimit()) + XPD_ERR(xpd, "%s: no protocol table (type=%d)\n", + __FUNCTION__, + xpd->type); + goto out; + } + xe = xproto_card_entry(xtable, op); + if(!xe) { + if(printk_ratelimit()) { + XPD_NOTICE(xpd, "%s: bad command (type=%d,opcode=0x%x)\n", + __FUNCTION__, + xpd->type, op); + dump_packet("packet_process -- bad command", pack, 1); + } + goto out; + } + } + table = xe->table; + BUG_ON(!table); + if(!table->packet_is_valid(pack)) { + if(printk_ratelimit()) { + ERR("xpp: %s: wrong size %d for opcode=0x%02X\n", + __FUNCTION__, XPACKET_LEN(pack), op); + dump_packet("packet_process -- wrong size", pack, print_dbg); + } + goto out; + } + ret = 0; /* All well */ + handler = xe->handler; + BUG_ON(!handler); + XBUS_COUNTER(xbus, RX_BYTES) += XPACKET_LEN(pack); + handler(xbus, xpd, xe, pack); +out: + return ret; +} + +static int xframe_receive_cmd(xbus_t *xbus, xframe_t *xframe) +{ + byte *xframe_end; + xpacket_t *pack; + byte *p; + int len; + int ret; + + p = xframe->packets; + xframe_end = p + XFRAME_LEN(xframe); + do { + pack = (xpacket_t *)p; + len = XPACKET_LEN(pack); + /* Sanity checks */ + if(unlikely(XPACKET_OP(pack) == XPROTO_NAME(GLOBAL,PCM_READ))) { + static int rate_limit; + + if((rate_limit++ % 1003) == 0) { + XBUS_DBG(GENERAL, xbus, "A PCM packet within a Non-PCM xframe\n"); + dump_xframe("In Non-PCM xframe", xbus, xframe); + } + ret = -EPROTO; + goto out; + } + p += len; + if(p > xframe_end || len < RPACKET_HEADERSIZE) { + static int rate_limit; + + if((rate_limit++ % 1003) == 0) { + XBUS_NOTICE(xbus, "Invalid packet length %d\n", len); + dump_xframe("BAD LENGTH", xbus, xframe); + } + ret = -EPROTO; + goto out; + } + ret = packet_process(xbus, pack); + if(unlikely(ret < 0)) + break; + } while(p < xframe_end); +out: + FREE_RECV_XFRAME(xbus, xframe); + return ret; +} + +int xframe_receive(xbus_t *xbus, xframe_t *xframe) +{ + int ret = 0; + struct timeval now; + struct timeval tv_received; + int usec; + + if(XFRAME_LEN(xframe) < RPACKET_HEADERSIZE) { + static int rate_limit; + + if((rate_limit++ % 1003) == 0) { + XBUS_NOTICE(xbus, "short xframe\n"); + dump_xframe("short xframe", xbus, xframe); + } + FREE_RECV_XFRAME(xbus, xframe); + return -EPROTO; + } + if(!XBUS_GET(xbus)) { + XBUS_DBG(GENERAL, xbus, "Dropped xframe. Is shutting down.\n"); + return -ENODEV; + } + tv_received = xframe->tv_received; + /* + * We want to check that xframes do not mix PCM and other commands + */ + if(XPACKET_IS_PCM((xpacket_t *)xframe->packets)) + xframe_receive_pcm(xbus, xframe); + else + ret = xframe_receive_cmd(xbus, xframe); + /* Calculate total processing time */ + do_gettimeofday(&now); + usec = (now.tv_sec - tv_received.tv_sec) * 1000000 + + now.tv_usec - tv_received.tv_usec; + if(usec > xbus->max_rx_process) + xbus->max_rx_process = usec; + XBUS_PUT(xbus); + return ret; +} + +#define VERBOSE_DEBUG 1 +#define ERR_REPORT_LIMIT 20 + +void dump_packet(const char *msg, const xpacket_t *packet, bool print_dbg) +{ + byte op = XPACKET_OP(packet); + byte *addr = (byte *)&XPACKET_ADDR(packet); + + if(!print_dbg) + return; + printk(KERN_DEBUG "%s: XPD=%1X-%1X%c (0x%X) OP=0x%02X LEN=%d", + msg, + XPACKET_ADDR_UNIT(packet), + XPACKET_ADDR_SUBUNIT(packet), + (XPACKET_ADDR_SYNC(packet))?'+':' ', + *addr, + op, + XPACKET_LEN(packet)); +#if VERBOSE_DEBUG + { + int i; + byte *p = (byte *)packet; + + printk(" BYTES: "); + for(i = 0; i < XPACKET_LEN(packet); i++) { + static int limiter = 0; + + if(i >= sizeof(xpacket_t)) { + if(limiter < ERR_REPORT_LIMIT) { + ERR("%s: length overflow i=%d > sizeof(xpacket_t)=%lu\n", + __FUNCTION__, i+1, (long)sizeof(xpacket_t)); + } else if(limiter == ERR_REPORT_LIMIT) { + ERR("%s: error packet #%d... squelsh reports.\n", + __FUNCTION__, limiter); + } + limiter++; + break; + } + if (print_dbg) + printk("%02X ", p[i]); + } + } +#endif + printk("\n"); +} + +void dump_reg_cmd(const char msg[], const reg_cmd_t *regcmd, bool writing) +{ + char action; + byte chipsel; + + if(regcmd->bytes != sizeof(*regcmd) - 1) { /* The size byte is not included */ + NOTICE("%s: Wrong size: regcmd->bytes = %d\n", __FUNCTION__, regcmd->bytes); + return; + } + if(writing && (REG_FIELD(regcmd, chipsel) & 0x80)) + ERR("Sending register command with reading bit ON\n"); + action = (writing) ? 'W' : 'R'; + chipsel = REG_FIELD(regcmd, chipsel) & ~0x80; + if(REG_FIELD(regcmd, do_subreg)) { + DBG(GENERAL, "%s: %d %cS %02X %02X [%02X] # data_high=%X m=%d eof=%d\n", msg, chipsel, action, + REG_FIELD(regcmd, regnum), + REG_FIELD(regcmd, subreg), + REG_FIELD(regcmd, data_low), + REG_FIELD(regcmd, data_high), + regcmd->multibyte, regcmd->eoframe); + } else if(REG_FIELD(regcmd, regnum) == 0x1E) { + DBG(GENERAL, "%s: %d %cI %02X [%02X %02X] # m=%d eof=%d\n", msg, chipsel, action, + REG_FIELD(regcmd, subreg), + REG_FIELD(regcmd, data_low), + REG_FIELD(regcmd, data_high), + regcmd->multibyte, regcmd->eoframe); + } else { + DBG(GENERAL, "%s: %d %cD %02X [%02X] # data_high=%X m=%d eof=%d\n", msg, chipsel, action, + REG_FIELD(regcmd, regnum), + REG_FIELD(regcmd, data_low), + REG_FIELD(regcmd, data_high), + regcmd->multibyte, regcmd->eoframe); + } +} + +const char *xproto_name(xpd_type_t xpd_type) +{ + const xproto_table_t *proto_table; + + BUG_ON(xpd_type >= XPD_TYPE_NOMODULE); + proto_table = xprotocol_tables[xpd_type]; + if(!proto_table) + return NULL; + return proto_table->name; +} + +#define CHECK_XOP(f) \ + if(!(xops)->f) { \ + ERR("%s: missing xmethod %s [%s (%d)]\n", __FUNCTION__, #f, name, type); \ + return -EINVAL; \ + } + +int xproto_register(const xproto_table_t *proto_table) +{ + int type; + const char *name; + const xops_t *xops; + + BUG_ON(!proto_table); + type = proto_table->type; + name = proto_table->name; + if(type >= XPD_TYPE_NOMODULE) { + NOTICE("%s: Bad xproto type %d\n", __FUNCTION__, type); + return -EINVAL; + } + DBG(GENERAL, "%s (%d)\n", name, type); + if(xprotocol_tables[type]) + NOTICE("%s: overriding registration of %s (%d)\n", __FUNCTION__, name, type); + xops = &proto_table->xops; + CHECK_XOP(card_new); + CHECK_XOP(card_init); + CHECK_XOP(card_remove); + CHECK_XOP(card_tick); + CHECK_XOP(card_pcm_fromspan); + CHECK_XOP(card_pcm_tospan); + CHECK_XOP(card_zaptel_preregistration); + CHECK_XOP(card_zaptel_postregistration); + CHECK_XOP(card_hooksig); + // CHECK_XOP(card_ioctl); // optional method -- call after testing + CHECK_XOP(card_register_reply); + CHECK_XOP(XPD_STATE); + CHECK_XOP(RING); + CHECK_XOP(RELAY_OUT); + + xprotocol_tables[type] = proto_table; + return 0; +} + +void xproto_unregister(const xproto_table_t *proto_table) +{ + int type; + const char *name; + + BUG_ON(!proto_table); + type = proto_table->type; + name = proto_table->name; + DBG(GENERAL, "%s (%d)\n", name, type); + if(type >= XPD_TYPE_NOMODULE) { + NOTICE("%s: Bad xproto type %s (%d)\n", __FUNCTION__, name, type); + return; + } + if(!xprotocol_tables[type]) + NOTICE("%s: xproto type %s (%d) is already unregistered\n", __FUNCTION__, name, type); + xprotocol_tables[type] = NULL; +} + +EXPORT_SYMBOL(dump_packet); +EXPORT_SYMBOL(dump_reg_cmd); +EXPORT_SYMBOL(xframe_receive); +EXPORT_SYMBOL(notify_bad_xpd); +EXPORT_SYMBOL(valid_xpd_addr); +EXPORT_SYMBOL(xproto_global_entry); +EXPORT_SYMBOL(xproto_card_entry); +EXPORT_SYMBOL(xproto_name); +EXPORT_SYMBOL(xproto_register); +EXPORT_SYMBOL(xproto_unregister); diff --git a/kernel/xpp/xproto.h b/kernel/xpp/xproto.h new file mode 100644 index 0000000..f68fedf --- /dev/null +++ b/kernel/xpp/xproto.h @@ -0,0 +1,306 @@ +#ifndef XPROTO_H +#define XPROTO_H +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "xdefs.h" + +#ifdef __KERNEL__ +#include +#include +#include + +/* + * This must match the firmware protocol version + */ +#define XPP_PROTOCOL_VERSION 29 + +struct xpd_addr { + uint8_t unit:UNIT_BITS; + uint8_t subunit:SUBUNIT_BITS; + uint8_t reserved:1; + uint8_t sync_master:1; +} PACKED; + +struct xpacket_header { + uint16_t packet_len:10; + uint16_t reserved:1; + uint16_t is_pcm:1; + uint16_t pcmslot:4; + uint8_t opcode; + struct xpd_addr addr; +} PACKED; + +#define XPACKET_OP(p) ((p)->head.opcode) +#define XPACKET_LEN(p) ((p)->head.packet_len) +#define XPACKET_IS_PCM(p) ((p)->head.is_pcm) +#define XPACKET_PCMSLOT(p) ((p)->head.pcmslot) +#define XPACKET_RESERVED(p) ((p)->head.reserved) +#define XPACKET_ADDR(p) ((p)->head.addr) +#define XPACKET_ADDR_UNIT(p) (XPACKET_ADDR(p).unit) +#define XPACKET_ADDR_SUBUNIT(p) (XPACKET_ADDR(p).subunit) +#define XPACKET_ADDR_SYNC(p) (XPACKET_ADDR(p).sync_master) +#define XPACKET_ADDR_RESERVED(p) (XPACKET_ADDR(p).reserved) + +#define PROTO_TABLE(n) n ## _protocol_table + +/* + * The LSB of the type number signifies: + * 0 - TO_PSTN + * 1 - TO_PHONE + */ +#define XPD_TYPE_FXS 3 // TO_PHONE +#define XPD_TYPE_FXO 4 // TO_PSTN +#define XPD_TYPE_BRI_TE 6 // TO_PSTN +#define XPD_TYPE_BRI_NT 7 // TO_PHONE +#define XPD_TYPE_PRI 9 // TO_PSTN/TO_PHONE (runtime) +#define XPD_TYPE_NOMODULE 15 + +typedef byte xpd_type_t; + +#define XPD_TYPE_PREFIX "xpd-type-" + +#define MODULE_ALIAS_XPD(type) \ + MODULE_ALIAS(XPD_TYPE_PREFIX __stringify(type)) + +#define PCM_CHUNKSIZE (CHANNELS_PERXPD * 8) /* samples of 8 bytes */ + +bool valid_xpd_addr(const struct xpd_addr *addr); + +#define XPROTO_NAME(card,op) card ## _ ## op +#define XPROTO_HANDLER(card,op) XPROTO_NAME(card,op ## _handler) +#define XPROTO_CALLER(card,op) XPROTO_NAME(card,op ## _send) + +#define HANDLER_DEF(card,op) \ + static int XPROTO_HANDLER(card,op) ( \ + xbus_t *xbus, \ + xpd_t *xpd, \ + const xproto_entry_t *cmd, \ + xpacket_t *pack) + +#define CALL_PROTO(card,op, ...) XPROTO_CALLER(card,op)( __VA_ARGS__ ) + +#define DECLARE_CMD(card,op, ...) \ + int CALL_PROTO(card, op, xbus_t *xbus, xpd_t *xpd, ## __VA_ARGS__ ) + +#define HOSTCMD(card, op, ...) \ + DECLARE_CMD(card, op, ## __VA_ARGS__ ) + +#define RPACKET_NAME(card,op) XPROTO_NAME(RPACKET_ ## card, op) +#define RPACKET_TYPE(card,op) struct RPACKET_NAME(card, op) + +#define DEF_RPACKET_DATA(card,op, ...) \ + RPACKET_TYPE(card,op) { \ + struct xpacket_header head; \ + __VA_ARGS__ \ + } PACKED +#define RPACKET_HEADERSIZE sizeof(struct xpacket_header) +#define RPACKET_FIELD(p,card,op,field) (((RPACKET_TYPE(card,op) *)(p))->field) +#define RPACKET_SIZE(card,op) sizeof(RPACKET_TYPE(card,op)) + +#define XENTRY(prototab,module,op) \ + [ XPROTO_NAME(module,op) ] = { \ + .handler = XPROTO_HANDLER(module,op), \ + .datalen = RPACKET_SIZE(module,op), \ + .name = #op, \ + .table = &PROTO_TABLE(prototab) \ + } + +#define XPACKET_INIT(p, card, op, to, pcm, pcmslot) \ + do { \ + XPACKET_OP(p) = XPROTO_NAME(card,op); \ + XPACKET_LEN(p) = RPACKET_SIZE(card,op); \ + XPACKET_IS_PCM(p) = (pcm); \ + XPACKET_PCMSLOT(p) = (pcmslot); \ + XPACKET_RESERVED(p) = 0; \ + XPACKET_ADDR_UNIT(p) = XBUS_UNIT(to); \ + XPACKET_ADDR_SUBUNIT(p) = XBUS_SUBUNIT(to); \ + XPACKET_ADDR_SYNC(p) = 0; \ + XPACKET_ADDR_RESERVED(p) = 0; \ + } while(0) + +#define XFRAME_NEW_CMD(frm, p, xbus, card, op, to) \ + do { \ + int len = RPACKET_SIZE(card,op); \ + \ + if(!TRANSPORT_RUNNING(xbus)) \ + return -ENODEV; \ + frm = ALLOC_SEND_XFRAME(xbus); \ + if(!frm) \ + return -ENOMEM; \ + (p) = xframe_next_packet(frm, len); \ + if(!(p)) \ + return -ENOMEM; \ + XPACKET_INIT(p, card, op, to, 0, 0); \ + } while(0) + +#endif + +/*--------------------------- register handling --------------------------------*/ +/* + * After the opcode, there are always: + * * A size (in bytes) of the rest. Only 6 bits are counted: + * - The MSB signifies a multibyte write (to BRI fifo) + * - The MSB-1 signifies end of frame to multibyte writes in BRI. + * A normal register command (not multibyte) than contains: + * * A channel selector byte: + * - ALL_CHANS (currently 31) is a broadcast request to set a + * register for all channels. + * - Smaller numbers (0-30) represent the addressed channel number. + * - The MSB signifies: + * 1 - register [R]ead request + * 0 - register [W]rite request + * * Register number + * * Subregister number -- 0 when there is no subregister + * * Data low + * * Data high -- 0 for single byte registers (direct registers) + * A multibyte register command than contains a sequence of bytes. + */ + +#define MULTIBYTE_MAX_LEN 5 /* FPGA firmware limitation */ + +typedef struct reg_cmd { + byte bytes:6; + byte eoframe:1; /* For BRI -- end of frame */ + byte multibyte:1; /* For BRI -- fifo data */ + union { + struct { + byte chipsel:CHAN_BITS; /* chip select */ + byte reserved:1; + byte do_subreg:1; + byte read_request:1; + byte regnum; + byte subreg; + byte data_low; + byte data_high; + } PACKED r; + /* For Write-Multibyte commands in BRI */ + struct { + byte xdata[MULTIBYTE_MAX_LEN]; + } PACKED d; + } PACKED alt; +} PACKED reg_cmd_t; + +/* Shortcut access macros */ +#define REG_FIELD(regptr,member) ((regptr)->alt.r.member) +#define REG_XDATA(regptr) ((regptr)->alt.d.xdata) + +#ifdef __KERNEL__ +/*--------------------------- protocol tables ----------------------------------*/ + +typedef struct xproto_entry xproto_entry_t; +typedef struct xproto_table xproto_table_t; + +typedef int (*xproto_handler_t)( + xbus_t *xbus, + xpd_t *xpd, + const xproto_entry_t *cmd, + xpacket_t *pack); + +const xproto_table_t *xproto_get(xpd_type_t cardtype); +void xproto_put(const xproto_table_t *xtable); +const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, byte opcode); +xproto_handler_t xproto_card_handler(const xproto_table_t *table, byte opcode); + +const xproto_entry_t *xproto_global_entry(byte opcode); +xproto_handler_t xproto_global_handler(byte opcode); + +#define CALL_XMETHOD(name, xbus, xpd, ...) \ + (xpd)->xops->name(xbus, xpd, ## __VA_ARGS__ ) + +struct xops { + xpd_t *(*card_new)(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table, byte subtype, byte revision); + int (*card_init)(xbus_t *xbus, xpd_t *xpd); + int (*card_remove)(xbus_t *xbus, xpd_t *xpd); + int (*card_tick)(xbus_t *xbus, xpd_t *xpd); + void (*card_pcm_fromspan)(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, xpacket_t *pack); + void (*card_pcm_tospan)(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack); + int (*card_zaptel_preregistration)(xpd_t *xpd, bool on); + int (*card_zaptel_postregistration)(xpd_t *xpd, bool on); + int (*card_hooksig)(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig); + int (*card_ioctl)(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg); + int (*card_open)(xpd_t *xpd, lineno_t pos); + int (*card_close)(xpd_t *xpd, lineno_t pos); + int (*card_register_reply)(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *reg); + + int (*XPD_STATE)(xbus_t *xbus, xpd_t *xpd, bool on); + int (*RING)(xbus_t *xbus, xpd_t *xpd, lineno_t chan, bool on); + int (*RELAY_OUT)(xbus_t *xbus, xpd_t *xpd, byte which, bool on); +}; + +struct xproto_entry { + xproto_handler_t handler; + int datalen; + const char *name; + xproto_table_t *table; +}; + +struct xproto_table { + struct module *owner; + xproto_entry_t entries[256]; /* Indexed by opcode */ + xops_t xops; + xpd_type_t type; + const char *name; + bool (*packet_is_valid)(xpacket_t *pack); + void (*packet_dump)(const char *msg, xpacket_t *pack); +}; + +#include "card_global.h" +#include "card_fxs.h" +#include "card_fxo.h" +#include "card_bri.h" +#include "card_pri.h" + + +#define MEMBER(card,op) RPACKET_TYPE(card,op) RPACKET_NAME(card,op) + +struct xpacket { + struct xpacket_header head; + union { + MEMBER(GLOBAL, NULL_REPLY); + MEMBER(GLOBAL, DESC_REQ); + MEMBER(GLOBAL, DEV_DESC); + MEMBER(GLOBAL, PCM_WRITE); + MEMBER(GLOBAL, PCM_READ); + MEMBER(GLOBAL, SYNC_REPLY); + MEMBER(GLOBAL, ERROR_CODE); + + MEMBER(FXS, SIG_CHANGED); + MEMBER(FXO, SIG_CHANGED); + + byte data[0]; + }; + /* Last byte is chksum */ +} PACKED; + +void dump_packet(const char *msg, const xpacket_t *packet, bool print_dbg); +void dump_reg_cmd(const char msg[], const reg_cmd_t *regcmd, bool writing); +int xframe_receive(xbus_t *xbus, xframe_t *xframe); +void notify_bad_xpd(const char *funcname, xbus_t *xbus, const struct xpd_addr addr, const char *msg); +int xproto_register(const xproto_table_t *proto_table); +void xproto_unregister(const xproto_table_t *proto_table); +const xproto_entry_t *xproto_global_entry(byte opcode); +const char *xproto_name(xpd_type_t xpd_type); + +#endif /* __KERNEL__ */ + +#endif /* XPROTO_H */ diff --git a/kernel/xpp/zap_debug.c b/kernel/xpp/zap_debug.c new file mode 100644 index 0000000..bf54e62 --- /dev/null +++ b/kernel/xpp/zap_debug.c @@ -0,0 +1,91 @@ +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +# warning "This module is tested only with 2.6 kernels" +#endif + +#include +#include +#include +#include +#include "zap_debug.h" +#include "xdefs.h" + +static const char rcsid[] = "$Id$"; + +#define P_(x) [ x ] = { .value = x, .name = #x, } +static struct { + int value; + char *name; +} poll_names[] = { + P_(POLLIN), + P_(POLLPRI), + P_(POLLOUT), + P_(POLLERR), + P_(POLLHUP), + P_(POLLNVAL), + P_(POLLRDNORM), + P_(POLLRDBAND), + P_(POLLWRNORM), + P_(POLLWRBAND), + P_(POLLMSG), + P_(POLLREMOVE) +}; +#undef P_ + +void dump_poll(int print_dbg, const char *msg, int poll) +{ + int i; + + for(i = 0; i < ARRAY_SIZE(poll_names); i++) { + if(poll & poll_names[i].value) + DBG(GENERAL, "%s: %s\n", msg, poll_names[i].name); + } +} + +void alarm2str(int alarm, char *buf, int buflen) +{ + char *p = buf; + int left = buflen; + int i; + int n; + + if(!alarm) { + snprintf(buf, buflen, "NONE"); + return; + } + memset(buf, 0, buflen); + for(i = 0; i < 8; i++) { + if(left && (alarm & BIT(i))) { + n = snprintf(p, left, "%s,", alarmbit2str(i)); + p += n; + left -= n; + } + } + if(p > buf) /* kill last comma */ + *(p - 1) = '\0'; +} + +EXPORT_SYMBOL(dump_poll); +EXPORT_SYMBOL(alarm2str); diff --git a/kernel/xpp/zap_debug.h b/kernel/xpp/zap_debug.h new file mode 100644 index 0000000..fb1ecc3 --- /dev/null +++ b/kernel/xpp/zap_debug.h @@ -0,0 +1,190 @@ +#ifndef ZAP_DEBUG_H +#define ZAP_DEBUG_H +/* + * Written by Oron Peled + * Copyright (C) 2004-2006, Xorcom + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include /* for zt_* defs */ + +/* Debugging Macros */ + +#define PRINTK(level, category, fmt, ...) \ + printk(KERN_ ## level "%s%s-%s: " fmt, #level, category, THIS_MODULE->name, ## __VA_ARGS__) + +#define XBUS_PRINTK(level, category, xbus, fmt, ...) \ + printk(KERN_ ## level "%s%s-%s: %s: " fmt, #level, \ + category, THIS_MODULE->name, (xbus)->busname, ## __VA_ARGS__) + +#define XPD_PRINTK(level, category, xpd, fmt, ...) \ + printk(KERN_ ## level "%s%s-%s: %s/%s: " fmt, #level, \ + category, THIS_MODULE->name, (xpd)->xbus->busname, (xpd)->xpdname, ## __VA_ARGS__) + +#define LINE_PRINTK(level, category, xpd, pos, fmt, ...) \ + printk(KERN_ ## level "%s%s-%s: %s/%s/%d: " fmt, #level, \ + category, THIS_MODULE->name, (xpd)->xbus->busname, (xpd)->xpdname, (pos), ## __VA_ARGS__) + +#define DBG(bits, fmt, ...) \ + ((void)((print_dbg & (DBG_ ## bits)) && PRINTK(DEBUG, "-" #bits, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))) +#define INFO(fmt, ...) PRINTK(INFO, "", fmt, ## __VA_ARGS__) +#define NOTICE(fmt, ...) PRINTK(NOTICE, "", fmt, ## __VA_ARGS__) +#define WARNING(fmt, ...) PRINTK(WARNING, "", fmt, ## __VA_ARGS__) +#define ERR(fmt, ...) PRINTK(ERR, "", fmt, ## __VA_ARGS__) + +#define XBUS_DBG(bits, xbus, fmt, ...) \ + ((void)((print_dbg & (DBG_ ## bits)) && XBUS_PRINTK(DEBUG, "-" #bits, xbus, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))) +#define XBUS_INFO(xbus, fmt, ...) XBUS_PRINTK(INFO, "", xbus, fmt, ## __VA_ARGS__) +#define XBUS_NOTICE(xbus, fmt, ...) XBUS_PRINTK(NOTICE, "", xbus, fmt, ## __VA_ARGS__) +#define XBUS_ERR(xbus, fmt, ...) XBUS_PRINTK(ERR, "", xbus, fmt, ## __VA_ARGS__) + +#define XPD_DBG(bits, xpd, fmt, ...) \ + ((void)((print_dbg & (DBG_ ## bits)) && XPD_PRINTK(DEBUG, "-" #bits, xpd, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))) +#define XPD_INFO(xpd, fmt, ...) XPD_PRINTK(INFO, "", xpd, fmt, ## __VA_ARGS__) +#define XPD_NOTICE(xpd, fmt, ...) XPD_PRINTK(NOTICE, "", xpd, fmt, ## __VA_ARGS__) +#define XPD_WARNING(xpd, fmt, ...) XPD_PRINTK(WARNING, "", xpd, fmt, ## __VA_ARGS__) +#define XPD_ERR(xpd, fmt, ...) XPD_PRINTK(ERR, "", xpd, fmt, ## __VA_ARGS__) + +#define LINE_DBG(bits, xpd, pos, fmt, ...) \ + ((void)((print_dbg & (DBG_ ## bits)) && LINE_PRINTK(DEBUG, "-" #bits, xpd, pos, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))) +#define LINE_NOTICE(xpd, pos, fmt, ...) LINE_PRINTK(NOTICE, "", xpd, pos, fmt, ## __VA_ARGS__) +#define LINE_ERR(xpd, pos, fmt, ...) LINE_PRINTK(ERR, "", xpd, pos, fmt, ## __VA_ARGS__) + +/* + * Bits for print_dbg + */ +#define DBG_GENERAL BIT(0) +#define DBG_PCM BIT(1) +#define DBG_LEDS BIT(2) +#define DBG_SYNC BIT(3) +#define DBG_SIGNAL BIT(4) +#define DBG_PROC BIT(5) +#define DBG_REGS BIT(6) +#define DBG_DEVICES BIT(7) /* instanciation/destruction etc. */ +#define DBG_ANY (~0) + +void dump_poll(int print_dbg, const char *msg, int poll); + +static inline char *rxsig2str(zt_rxsig_t sig) +{ + switch(sig) { + case ZT_RXSIG_ONHOOK: return "ONHOOK"; + case ZT_RXSIG_OFFHOOK: return "OFFHOOK"; + case ZT_RXSIG_START: return "START"; + case ZT_RXSIG_RING: return "RING"; + case ZT_RXSIG_INITIAL: return "INITIAL"; + } + return "Unknown rxsig"; +} + +static inline char *txsig2str(zt_txsig_t sig) +{ + switch(sig) { + case ZT_TXSIG_ONHOOK: return "TXSIG_ONHOOK"; + case ZT_TXSIG_OFFHOOK: return "TXSIG_OFFHOOK"; + case ZT_TXSIG_START: return "TXSIG_START"; + case ZT_TXSIG_KEWL: return "TXSIG_KEWL"; /* Drop battery if possible */ + } + return "Unknown txsig"; +} + +static inline char *event2str(int event) +{ + switch(event) { + case ZT_EVENT_NONE: return "NONE"; + case ZT_EVENT_ONHOOK: return "ONHOOK"; + case ZT_EVENT_RINGOFFHOOK: return "RINGOFFHOOK"; + case ZT_EVENT_WINKFLASH: return "WINKFLASH"; + case ZT_EVENT_ALARM: return "ALARM"; + case ZT_EVENT_NOALARM: return "NOALARM"; + case ZT_EVENT_ABORT: return "ABORT"; + case ZT_EVENT_OVERRUN: return "OVERRUN"; + case ZT_EVENT_BADFCS: return "BADFCS"; + case ZT_EVENT_DIALCOMPLETE: return "DIALCOMPLETE"; + case ZT_EVENT_RINGERON: return "RINGERON"; + case ZT_EVENT_RINGEROFF: return "RINGEROFF"; + case ZT_EVENT_HOOKCOMPLETE: return "HOOKCOMPLETE"; + case ZT_EVENT_BITSCHANGED: return "BITSCHANGED"; + case ZT_EVENT_PULSE_START: return "PULSE_START"; + case ZT_EVENT_TIMER_EXPIRED: return "TIMER_EXPIRED"; + case ZT_EVENT_TIMER_PING: return "TIMER_PING"; + case ZT_EVENT_POLARITY: return "POLARITY"; + } + return "Unknown event"; +} + +static inline char *hookstate2str(int hookstate) +{ + switch(hookstate) { + case ZT_ONHOOK: return "ZT_ONHOOK"; + case ZT_START: return "ZT_START"; + case ZT_OFFHOOK: return "ZT_OFFHOOK"; + case ZT_WINK: return "ZT_WINK"; + case ZT_FLASH: return "ZT_FLASH"; + case ZT_RING: return "ZT_RING"; + case ZT_RINGOFF: return "ZT_RINGOFF"; + } + return "Unknown hookstate"; +} + +/* From zaptel.c */ +static inline char *sig2str(int sig) +{ + switch (sig) { + case ZT_SIG_FXSLS: return "FXSLS"; + case ZT_SIG_FXSKS: return "FXSKS"; + case ZT_SIG_FXSGS: return "FXSGS"; + case ZT_SIG_FXOLS: return "FXOLS"; + case ZT_SIG_FXOKS: return "FXOKS"; + case ZT_SIG_FXOGS: return "FXOGS"; + case ZT_SIG_EM: return "E&M"; + case ZT_SIG_EM_E1: return "E&M-E1"; + case ZT_SIG_CLEAR: return "Clear"; + case ZT_SIG_HDLCRAW: return "HDLCRAW"; + case ZT_SIG_HDLCFCS: return "HDLCFCS"; + case ZT_SIG_HDLCNET: return "HDLCNET"; + case ZT_SIG_SLAVE: return "Slave"; + case ZT_SIG_CAS: return "CAS"; + case ZT_SIG_DACS: return "DACS"; + case ZT_SIG_DACS_RBS: return "DACS+RBS"; + case ZT_SIG_SF: return "SF (ToneOnly)"; + case ZT_SIG_NONE: + break; + } + return "Unconfigured"; +} + +static inline char *alarmbit2str(int alarmbit) +{ + /* from zaptel.h */ + switch(1 << alarmbit) { + case ZT_ALARM_NONE: return "NONE"; + case ZT_ALARM_RECOVER: return "RECOVER"; + case ZT_ALARM_LOOPBACK: return "LOOPBACK"; + case ZT_ALARM_YELLOW: return "YELLOW"; + case ZT_ALARM_RED: return "RED"; + case ZT_ALARM_BLUE: return "BLUE"; + case ZT_ALARM_NOTOPEN: return "NOTOPEN"; + } + return "UNKNOWN"; +} + +void alarm2str(int alarm, char *buf, int buflen); + +#endif /* ZAP_DEBUG_H */ diff --git a/kernel/zaptel-base.c b/kernel/zaptel-base.c new file mode 100644 index 0000000..7203645 --- /dev/null +++ b/kernel/zaptel-base.c @@ -0,0 +1,7443 @@ +/* + * Zapata Telephony Interface Driver + * + * Written by Mark Spencer + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon . + * + * Special thanks to Steve Underwood + * for substantial contributions to signal processing functions + * in zaptel and the zapata library. + * + * Yury Bokhoncovich + * Adaptation for 2.4.20+ kernels (HDLC API was changed) + * The work has been performed as a part of our move + * from Cisco 3620 to IBM x305 here in F1 Group + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001 -2006 Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "zconfig.h" +#include "../version.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_DEVFS_FS +#include +#endif /* CONFIG_DEVFS_FS */ +#ifdef CONFIG_ZAPATA_NET +#include +#endif /* CONFIG_ZAPATA_NET */ +#include +#ifdef CONFIG_ZAPATA_PPP +#include +#include +#include +#endif +#include + +#ifndef CONFIG_OLD_HDLC_API +#define NEW_HDLC_INTERFACE +#endif + +#define __ECHO_STATE_MUTE (1 << 8) +#define ECHO_STATE_IDLE (0) +#define ECHO_STATE_PRETRAINING (1 | (__ECHO_STATE_MUTE)) +#define ECHO_STATE_STARTTRAINING (2 | (__ECHO_STATE_MUTE)) +#define ECHO_STATE_AWAITINGECHO (3 | (__ECHO_STATE_MUTE)) +#define ECHO_STATE_TRAINING (4 | (__ECHO_STATE_MUTE)) +#define ECHO_STATE_ACTIVE (5) + +/* #define BUF_MUNGE */ + +/* Grab fasthdlc with tables */ +#define FAST_HDLC_NEED_TABLES +#include "fasthdlc.h" + +#include "zaptel.h" + +#ifdef LINUX26 +#include +#endif + +/* Get helper arithmetic */ +#include "arith.h" +#if defined(CONFIG_ZAPTEL_MMX) || defined(ECHO_CAN_FP) +#include +#endif + +#define hdlc_to_ztchan(h) (((struct zt_hdlc *)(h))->chan) +#define dev_to_ztchan(h) (((struct zt_hdlc *)(dev_to_hdlc(h)->priv))->chan) +#ifdef LINUX26 +#define ztchan_to_dev(h) ((h)->hdlcnetdev->netdev) +#else +#define ztchan_to_dev(h) (&((h)->hdlcnetdev->netdev.netdev)) +#endif + +/* macro-oni for determining a unit (channel) number */ +#define UNIT(file) MINOR(file->f_dentry->d_inode->i_rdev) + +/* names of tx level settings */ +static char *zt_txlevelnames[] = { +"0 db (CSU)/0-133 feet (DSX-1)", +"133-266 feet (DSX-1)", +"266-399 feet (DSX-1)", +"399-533 feet (DSX-1)", +"533-655 feet (DSX-1)", +"-7.5db (CSU)", +"-15db (CSU)", +"-22.5db (CSU)" +} ; + +EXPORT_SYMBOL(zt_transcode_fops); +EXPORT_SYMBOL(zt_init_tone_state); +EXPORT_SYMBOL(zt_dtmf_tone); +EXPORT_SYMBOL(zt_register); +EXPORT_SYMBOL(zt_unregister); +EXPORT_SYMBOL(__zt_mulaw); +EXPORT_SYMBOL(__zt_alaw); +#ifdef CONFIG_CALC_XLAW +EXPORT_SYMBOL(__zt_lineartoulaw); +EXPORT_SYMBOL(__zt_lineartoalaw); +#else +EXPORT_SYMBOL(__zt_lin2mu); +EXPORT_SYMBOL(__zt_lin2a); +#endif +EXPORT_SYMBOL(zt_lboname); +EXPORT_SYMBOL(zt_transmit); +EXPORT_SYMBOL(zt_receive); +EXPORT_SYMBOL(zt_rbsbits); +EXPORT_SYMBOL(zt_qevent_nolock); +EXPORT_SYMBOL(zt_qevent_lock); +EXPORT_SYMBOL(zt_hooksig); +EXPORT_SYMBOL(zt_alarm_notify); +EXPORT_SYMBOL(zt_set_dynamic_ioctl); +EXPORT_SYMBOL(zt_ec_chunk); +EXPORT_SYMBOL(zt_ec_span); +EXPORT_SYMBOL(zt_hdlc_abort); +EXPORT_SYMBOL(zt_hdlc_finish); +EXPORT_SYMBOL(zt_hdlc_getbuf); +EXPORT_SYMBOL(zt_hdlc_putbuf); +EXPORT_SYMBOL(zt_alarm_channel); +EXPORT_SYMBOL(zt_register_chardev); +EXPORT_SYMBOL(zt_unregister_chardev); + +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry *proc_entries[ZT_MAX_SPANS]; +#endif + +/* Here are a couple important little additions for devfs */ +#ifdef CONFIG_DEVFS_FS +static devfs_handle_t zaptel_devfs_dir; +static devfs_handle_t channel; +static devfs_handle_t pseudo; +static devfs_handle_t ctl; +static devfs_handle_t timer; +#endif + +/* udev necessary data structures. Yeah! */ +#ifdef CONFIG_ZAP_UDEV + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) +#define CLASS_DEV_CREATE(class, devt, device, name) \ + class_device_create(class, NULL, devt, device, name) +#else +#define CLASS_DEV_CREATE(class, devt, device, name) \ + class_device_create(class, devt, device, name) +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) +static struct class *zap_class = NULL; +#else +static struct class_simple *zap_class = NULL; +#define class_create class_simple_create +#define class_destroy class_simple_destroy +#define class_device_create class_simple_device_add +#define class_device_destroy(a, b) class_simple_device_remove(b) +#endif + +#endif /* CONFIG_ZAP_UDEV */ + + +/* There is a table like this in the PPP driver, too */ + +static int deftaps = 64; + +#if !defined(LINUX26) +static +__u16 fcstab[256] = +{ + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; +#endif + +static int debug; + +/* states for transmit signalling */ +typedef enum {ZT_TXSTATE_ONHOOK,ZT_TXSTATE_OFFHOOK,ZT_TXSTATE_START, + ZT_TXSTATE_PREWINK,ZT_TXSTATE_WINK,ZT_TXSTATE_PREFLASH, + ZT_TXSTATE_FLASH,ZT_TXSTATE_DEBOUNCE,ZT_TXSTATE_AFTERSTART, + ZT_TXSTATE_RINGON,ZT_TXSTATE_RINGOFF,ZT_TXSTATE_KEWL, + ZT_TXSTATE_AFTERKEWL,ZT_TXSTATE_PULSEBREAK,ZT_TXSTATE_PULSEMAKE, + ZT_TXSTATE_PULSEAFTER + } ZT_TXSTATE_t; + +typedef short sumtype[ZT_MAX_CHUNKSIZE]; + +static sumtype sums[(ZT_MAX_CONF + 1) * 3]; + +/* Translate conference aliases into actual conferences + and vice-versa */ +static short confalias[ZT_MAX_CONF + 1]; +static short confrev[ZT_MAX_CONF + 1]; + +static sumtype *conf_sums_next; +static sumtype *conf_sums; +static sumtype *conf_sums_prev; + +static struct zt_span *master; +static struct file_operations zt_fops; +struct file_operations *zt_transcode_fops = NULL; + +static struct +{ + int src; /* source conf number */ + int dst; /* dst conf number */ +} conf_links[ZT_MAX_CONF + 1]; + + +/* There are three sets of conference sum accumulators. One for the current +sample chunk (conf_sums), one for the next sample chunk (conf_sums_next), and +one for the previous sample chunk (conf_sums_prev). The following routine +(rotate_sums) "rotates" the pointers to these accululator arrays as part +of the events of sample chink processing as follows: + +The following sequence is designed to be looked at from the reference point +of the receive routine of the master span. + +1. All (real span) receive chunks are processed (with putbuf). The last one +to be processed is the master span. The data received is loaded into the +accumulators for the next chunk (conf_sums_next), to be in alignment with +current data after rotate_sums() is called (which immediately follows). +Keep in mind that putbuf is *also* a transmit routine for the pseudo parts +of channels that are in the REALANDPSEUDO conference mode. These channels +are processed from data in the current sample chunk (conf_sums), being +that this is a "transmit" function (for the pseudo part). + +2. rotate_sums() is called. + +3. All pseudo channel receive chunks are processed. This data is loaded into +the current sample chunk accumulators (conf_sums). + +4. All conference links are processed (being that all receive data for this +chunk has already been processed by now). + +5. All pseudo channel transmit chunks are processed. This data is loaded from +the current sample chunk accumulators (conf_sums). + +6. All (real span) transmit chunks are processed (with getbuf). This data is +loaded from the current sample chunk accumulators (conf_sums). Keep in mind +that getbuf is *also* a receive routine for the pseudo part of channels that +are in the REALANDPSEUDO conference mode. These samples are loaded into +the next sample chunk accumulators (conf_sums_next) to be processed as part +of the next sample chunk's data (next time around the world). + +*/ + +#define DIGIT_MODE_DTMF 0 +#define DIGIT_MODE_MFV1 1 +#define DIGIT_MODE_PULSE 2 + +#include "digits.h" + +static struct zt_dialparams global_dialparams = { + .dtmf_tonelen = DEFAULT_DTMF_LENGTH, + .mfv1_tonelen = DEFAULT_MFV1_LENGTH, +}; + +static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit); + +#if defined(CONFIG_ZAPTEL_MMX) || defined(ECHO_CAN_FP) +/* XXX kernel_fpu_begin() is NOT exported properly (in 2.4), so we have to make + a local version. Somebody fix this! XXX */ + +#ifndef LINUX26 +static inline void __save_init_fpu( struct task_struct *tsk ) +{ + if ( cpu_has_fxsr ) { + asm volatile( "fxsave %0 ; fnclex" + : "=m" (tsk->thread.i387.fxsave) ); + } else { + asm volatile( "fnsave %0 ; fwait" + : "=m" (tsk->thread.i387.fsave) ); + } + tsk->flags &= ~PF_USEDFPU; +} + +static inline void zt_kernel_fpu_begin(void) +{ + struct task_struct *tsk = current; + if (tsk->flags & PF_USEDFPU) { + __save_init_fpu(tsk); + return; + } + clts(); +} +#else +#define zt_kernel_fpu_begin kernel_fpu_begin +#endif /* LINUX26 */ +#endif + +static struct zt_timer { + int ms; /* Countdown */ + int pos; /* Position */ + int ping; /* Whether we've been ping'd */ + int tripped; /* Whether we're tripped */ + struct zt_timer *next; /* Linked list */ + wait_queue_head_t sel; +} *zaptimers = NULL; + +#ifdef DEFINE_SPINLOCK +static DEFINE_SPINLOCK(zaptimerlock); +static DEFINE_SPINLOCK(bigzaplock); +#else +static spinlock_t zaptimerlock = SPIN_LOCK_UNLOCKED; +static spinlock_t bigzaplock = SPIN_LOCK_UNLOCKED; +#endif + +struct zt_zone { + atomic_t refcount; + char name[40]; /* Informational, only */ + int ringcadence[ZT_MAX_CADENCE]; + struct zt_tone *tones[ZT_TONE_MAX]; + /* Each of these is a circular list + of zt_tones to generate what we + want. Use NULL if the tone is + unavailable */ + struct zt_tone dtmf[16]; /* DTMF tones for this zone, with desired length */ + struct zt_tone dtmf_continuous[16]; /* DTMF tones for this zone, continuous play */ + struct zt_tone mf[15]; /* MF tones for this zone, with desired length */ + struct zt_tone mf_continuous[15]; /* MF tones for this zone, continuous play */ +}; + +static struct zt_span *spans[ZT_MAX_SPANS]; +static struct zt_chan *chans[ZT_MAX_CHANNELS]; + +static int maxspans = 0; +static int maxchans = 0; +static int maxconfs = 0; +static int maxlinks = 0; + +static int default_zone = -1; + +short __zt_mulaw[256]; +short __zt_alaw[256]; + +#ifndef CONFIG_CALC_XLAW +u_char __zt_lin2mu[16384]; + +u_char __zt_lin2a[16384]; +#endif + +static u_char defgain[256]; + +#ifdef DEFINE_RWLOCK +static DEFINE_RWLOCK(zone_lock); +static DEFINE_RWLOCK(chan_lock); +#else +static rwlock_t zone_lock = RW_LOCK_UNLOCKED; +static rwlock_t chan_lock = RW_LOCK_UNLOCKED; +#endif + +static struct zt_zone *tone_zones[ZT_TONE_ZONE_MAX]; + +#define NUM_SIGS 10 + + +/* Echo cancellation */ +#if defined(ECHO_CAN_HPEC) +#include "hpec/hpec_zaptel.h" +#elif defined(ECHO_CAN_STEVE) +#include "sec.h" +#elif defined(ECHO_CAN_STEVE2) +#include "sec-2.h" +#elif defined(ECHO_CAN_KB1) +#include "kb1ec.h" +#elif defined(ECHO_CAN_MG2) +#include "mg2ec.h" +#elif defined(ECHO_CAN_JP1) +#include "jpah.h" +#endif + +static inline void rotate_sums(void) +{ + /* Rotate where we sum and so forth */ + static int pos = 0; + conf_sums_prev = sums + (ZT_MAX_CONF + 1) * pos; + conf_sums = sums + (ZT_MAX_CONF + 1) * ((pos + 1) % 3); + conf_sums_next = sums + (ZT_MAX_CONF + 1) * ((pos + 2) % 3); + pos = (pos + 1) % 3; + memset(conf_sums_next, 0, maxconfs * sizeof(sumtype)); +} + + /* return quiescent (idle) signalling states, for the various signalling types */ +static int zt_q_sig(struct zt_chan *chan) +{ +int x; + +static unsigned int in_sig[NUM_SIGS][2] = { + { ZT_SIG_NONE, 0}, + { ZT_SIG_EM, 0 | (ZT_ABIT << 8)}, + { ZT_SIG_FXSLS,ZT_BBIT | (ZT_BBIT << 8)}, + { ZT_SIG_FXSGS,ZT_ABIT | ZT_BBIT | ((ZT_ABIT | ZT_BBIT) << 8)}, + { ZT_SIG_FXSKS,ZT_BBIT | ZT_BBIT | ((ZT_ABIT | ZT_BBIT) << 8)}, + { ZT_SIG_FXOLS,0 | (ZT_ABIT << 8)}, + { ZT_SIG_FXOGS,ZT_BBIT | ((ZT_ABIT | ZT_BBIT) << 8)}, + { ZT_SIG_FXOKS,0 | (ZT_ABIT << 8)}, + { ZT_SIG_SF, 0}, + { ZT_SIG_EM_E1, ZT_DBIT | ((ZT_ABIT | ZT_DBIT) << 8) }, + } ; + + /* must have span to begin with */ + if (!chan->span) return(-1); + /* if RBS does not apply, return error */ + if (!(chan->span->flags & ZT_FLAG_RBS) || + !chan->span->rbsbits) return(-1); + if (chan->sig == ZT_SIG_CAS) + return chan->idlebits; + for (x=0;xsig) return(in_sig[x][1]); + } return(-1); /* not found -- error */ +} + +#ifdef CONFIG_PROC_FS +static char *sigstr(int sig) +{ + switch (sig) { + case ZT_SIG_FXSLS: + return "FXSLS"; + case ZT_SIG_FXSKS: + return "FXSKS"; + case ZT_SIG_FXSGS: + return "FXSGS"; + case ZT_SIG_FXOLS: + return "FXOLS"; + case ZT_SIG_FXOKS: + return "FXOKS"; + case ZT_SIG_FXOGS: + return "FXOGS"; + case ZT_SIG_EM: + return "E&M"; + case ZT_SIG_EM_E1: + return "E&M-E1"; + case ZT_SIG_CLEAR: + return "Clear"; + case ZT_SIG_HDLCRAW: + return "HDLCRAW"; + case ZT_SIG_HDLCFCS: + return "HDLCFCS"; + case ZT_SIG_HDLCNET: + return "HDLCNET"; + case ZT_SIG_HARDHDLC: + return "Hardware-assisted HDLC"; + case ZT_SIG_SLAVE: + return "Slave"; + case ZT_SIG_CAS: + return "CAS"; + case ZT_SIG_DACS: + return "DACS"; + case ZT_SIG_DACS_RBS: + return "DACS+RBS"; + case ZT_SIG_SF: + return "SF (ToneOnly)"; + case ZT_SIG_NONE: + default: + return "Unconfigured"; + } + +} + +static int zaptel_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int x, len = 0; + long span; + + /* In Linux 2.6, this MUST NOT EXECEED 1024 bytes in one read! */ + + span = (long)data; + + if (!span) + return 0; + + if (spans[span]->name) + len += sprintf(page + len, "Span %ld: %s ", span, spans[span]->name); + if (spans[span]->desc) + len += sprintf(page + len, "\"%s\"", spans[span]->desc); + else + len += sprintf(page + len, "\"\""); + + if(spans[span] == master) + len += sprintf(page + len, " (MASTER)"); + + if (spans[span]->lineconfig) { + /* framing first */ + if (spans[span]->lineconfig & ZT_CONFIG_B8ZS) + len += sprintf(page + len, " B8ZS/"); + else if (spans[span]->lineconfig & ZT_CONFIG_AMI) + len += sprintf(page + len, " AMI/"); + else if (spans[span]->lineconfig & ZT_CONFIG_HDB3) + len += sprintf(page + len, " HDB3/"); + /* then coding */ + if (spans[span]->lineconfig & ZT_CONFIG_ESF) + len += sprintf(page + len, "ESF"); + else if (spans[span]->lineconfig & ZT_CONFIG_D4) + len += sprintf(page + len, "D4"); + else if (spans[span]->lineconfig & ZT_CONFIG_CCS) + len += sprintf(page + len, "CCS"); + /* E1's can enable CRC checking */ + if (spans[span]->lineconfig & ZT_CONFIG_CRC4) + len += sprintf(page + len, "/CRC4"); + } + + len += sprintf(page + len, " "); + + /* list alarms */ + if (spans[span]->alarms && (spans[span]->alarms > 0)) { + if (spans[span]->alarms & ZT_ALARM_BLUE) + len += sprintf(page + len, "BLUE "); + if (spans[span]->alarms & ZT_ALARM_YELLOW) + len += sprintf(page + len, "YELLOW "); + if (spans[span]->alarms & ZT_ALARM_RED) + len += sprintf(page + len, "RED "); + if (spans[span]->alarms & ZT_ALARM_LOOPBACK) + len += sprintf(page + len, "LOOP "); + if (spans[span]->alarms & ZT_ALARM_RECOVER) + len += sprintf(page + len, "RECOVERING "); + if (spans[span]->alarms & ZT_ALARM_NOTOPEN) + len += sprintf(page + len, "NOTOPEN "); + + } + if (spans[span]->syncsrc && (spans[span]->syncsrc == spans[span]->spanno)) + len += sprintf(page + len, "ClockSource "); + len += sprintf(page + len, "\n"); + if (spans[span]->bpvcount) + len += sprintf(page + len, "\tBPV count: %d\n", spans[span]->bpvcount); + if (spans[span]->crc4count) + len += sprintf(page + len, "\tCRC4 error count: %d\n", spans[span]->crc4count); + if (spans[span]->ebitcount) + len += sprintf(page + len, "\tE-bit error count: %d\n", spans[span]->ebitcount); + if (spans[span]->fascount) + len += sprintf(page + len, "\tFAS error count: %d\n", spans[span]->fascount); + if (spans[span]->irqmisses) + len += sprintf(page + len, "\tIRQ misses: %d\n", spans[span]->irqmisses); + if (spans[span]->timingslips) + len += sprintf(page + len, "\tTiming slips: %d\n", spans[span]->timingslips); + len += sprintf(page + len, "\n"); + + + for (x=1;xspan && (chans[x]->span->spanno == span)) { + if (chans[x]->name) + len += sprintf(page + len, "\t%4d %s ", x, chans[x]->name); + if (chans[x]->sig) { + if (chans[x]->sig == ZT_SIG_SLAVE) + len += sprintf(page + len, "%s ", sigstr(chans[x]->master->sig)); + else { + len += sprintf(page + len, "%s ", sigstr(chans[x]->sig)); + if (chans[x]->nextslave && chans[x]->master->channo == x) + len += sprintf(page + len, "Master "); + } + } + if ((chans[x]->flags & ZT_FLAG_OPEN)) { + len += sprintf(page + len, "(In use) "); + } +#ifdef OPTIMIZE_CHANMUTE + if ((chans[x]->chanmute)) { + len += sprintf(page + len, "(no pcm) "); + } +#endif + len += sprintf(page + len, "\n"); + } + if (len <= off) { /* If everything printed so far is before beginning of request */ + off -= len; + len = 0; + } + if (len > off+count) /* stop if we've already generated enough */ + break; + } + } + if (len <= off) { /* If everything printed so far is before beginning of request */ + off -= len; + len = 0; + } + *start = page + off; + len -= off; /* un-count any remaining offset */ + if (len > count) len = count; /* don't return bytes not asked for */ + return len; +} +#endif + +static int zt_first_empty_alias(void) +{ + /* Find the first conference which has no alias pointing to it */ + int x; + for (x=1;x0;x--) { + if (confrev[x]) { + maxconfs = x+1; + return; + } + } + maxconfs = 0; +} + +static void recalc_maxlinks(void) +{ + int x; + for (x=ZT_MAX_CONF-1;x>0;x--) { + if (conf_links[x].src || conf_links[x].dst) { + maxlinks = x+1; + return; + } + } + maxlinks = 0; +} + +static int zt_first_empty_conference(void) +{ + /* Find the first conference which has no alias */ + int x; + for (x=ZT_MAX_CONF-1;x>0;x--) { + if (!confalias[x]) + return x; + } + return -1; +} + +static int zt_get_conf_alias(int x) +{ + int a; + if (confalias[x]) { + return confalias[x]; + } + + /* Allocate an alias */ + a = zt_first_empty_alias(); + confalias[x] = a; + confrev[a] = x; + + /* Highest conference may have changed */ + recalc_maxconfs(); + return a; +} + +static void zt_check_conf(int x) +{ + int y; + + /* return if no valid conf number */ + if (x <= 0) return; + /* Return if there is no alias */ + if (!confalias[x]) + return; + for (y=0;yconfna == x) && + ((chans[y]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_CONF || + (chans[y]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_CONFANN || + (chans[y]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_CONFMON || + (chans[y]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_CONFANNMON || + (chans[y]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_REALANDPSEUDO)) + return; + } + /* If we get here, nobody is in the conference anymore. Clear it out + both forward and reverse */ + confrev[confalias[x]] = 0; + confalias[x] = 0; + + /* Highest conference may have changed */ + recalc_maxconfs(); +} + +/* enqueue an event on a channel */ +static void __qevent(struct zt_chan *chan, int event) +{ + + /* if full, ignore */ + if ((chan->eventoutidx == 0) && (chan->eventinidx == (ZT_MAX_EVENTSIZE - 1))) + return; + /* if full, ignore */ + if (chan->eventinidx == (chan->eventoutidx - 1)) return; + /* save the event */ + chan->eventbuf[chan->eventinidx++] = event; + /* wrap the index, if necessary */ + if (chan->eventinidx >= ZT_MAX_EVENTSIZE) chan->eventinidx = 0; + /* wake em all up */ + if (chan->iomask & ZT_IOMUX_SIGEVENT) wake_up_interruptible(&chan->eventbufq); + wake_up_interruptible(&chan->readbufq); + wake_up_interruptible(&chan->writebufq); + wake_up_interruptible(&chan->sel); + return; +} + +void zt_qevent_nolock(struct zt_chan *chan, int event) +{ + __qevent(chan, event); +} + +void zt_qevent_lock(struct zt_chan *chan, int event) +{ + unsigned long flags; + spin_lock_irqsave(&chan->lock, flags); + __qevent(chan, event); + spin_unlock_irqrestore(&chan->lock, flags); +} + +/* sleep in user space until woken up. Equivilant of tsleep() in BSD */ +static int schluffen(wait_queue_head_t *q) +{ + DECLARE_WAITQUEUE(wait, current); + add_wait_queue(q, &wait); + current->state = TASK_INTERRUPTIBLE; + if (!signal_pending(current)) schedule(); + current->state = TASK_RUNNING; + remove_wait_queue(q, &wait); + if (signal_pending(current)) { + return -ERESTARTSYS; + } + return(0); +} + +static inline void calc_fcs(struct zt_chan *ss, int inwritebuf) +{ + int x; + unsigned int fcs=PPP_INITFCS; + unsigned char *data = ss->writebuf[inwritebuf]; + int len = ss->writen[inwritebuf]; + /* Not enough space to do FCS calculation */ + if (len < 2) + return; + for (x=0;x> 8) & 0xff; +} + +static int zt_reallocbufs(struct zt_chan *ss, int j, int numbufs) +{ + unsigned char *newbuf, *oldbuf; + unsigned long flags; + int x; + /* Check numbufs */ + if (numbufs < 2) + numbufs = 2; + if (numbufs > ZT_MAX_NUM_BUFS) + numbufs = ZT_MAX_NUM_BUFS; + /* We need to allocate our buffers now */ + if (j) { + newbuf = kmalloc(j * 2 * numbufs, GFP_KERNEL); + if (!newbuf) + return (-ENOMEM); + } else + newbuf = NULL; + /* Now that we've allocated our new buffer, we can safely + move things around... */ + spin_lock_irqsave(&ss->lock, flags); + ss->blocksize = j; /* set the blocksize */ + oldbuf = ss->readbuf[0]; /* Keep track of the old buffer */ + ss->readbuf[0] = NULL; + if (newbuf) { + for (x=0;xreadbuf[x] = newbuf + x * j; + ss->writebuf[x] = newbuf + (numbufs + x) * j; + } + } else { + for (x=0;xreadbuf[x] = NULL; + ss->writebuf[x] = NULL; + } + } + /* Mark all buffers as empty */ + for (x=0;xwriten[x] = + ss->writeidx[x]= + ss->readn[x]= + ss->readidx[x] = 0; + + /* Keep track of where our data goes (if it goes + anywhere at all) */ + if (newbuf) { + ss->inreadbuf = 0; + ss->inwritebuf = 0; + } else { + ss->inreadbuf = -1; + ss->inwritebuf = -1; + } + ss->outreadbuf = -1; + ss->outwritebuf = -1; + ss->numbufs = numbufs; + if (ss->txbufpolicy == ZT_POLICY_WHEN_FULL) + ss->txdisable = 1; + else + ss->txdisable = 0; + + if (ss->rxbufpolicy == ZT_POLICY_WHEN_FULL) + ss->rxdisable = 1; + else + ss->rxdisable = 0; + + spin_unlock_irqrestore(&ss->lock, flags); + if (oldbuf) + kfree(oldbuf); + return 0; +} + +static int zt_hangup(struct zt_chan *chan); +static void zt_set_law(struct zt_chan *chan, int law); + +/* Pull a ZT_CHUNKSIZE piece off the queue. Returns + 0 on success or -1 on failure. If failed, provides + silence */ +static int __buf_pull(struct confq *q, u_char *data, struct zt_chan *c, char *label) +{ + int oldoutbuf = q->outbuf; + /* Ain't nuffin to read */ + if (q->outbuf < 0) { + if (data) + memset(data, ZT_LIN2X(0,c), ZT_CHUNKSIZE); + return -1; + } + if (data) + memcpy(data, q->buf[q->outbuf], ZT_CHUNKSIZE); + q->outbuf = (q->outbuf + 1) % ZT_CB_SIZE; + + /* Won't be nuffin next time */ + if (q->outbuf == q->inbuf) { + q->outbuf = -1; + } + + /* If they thought there was no space then + there is now where we just read */ + if (q->inbuf < 0) + q->inbuf = oldoutbuf; + return 0; +} + +/* Returns a place to put stuff, or NULL if there is + no room */ + +static u_char *__buf_pushpeek(struct confq *q) +{ + if (q->inbuf < 0) + return NULL; + return q->buf[q->inbuf]; +} + +static u_char *__buf_peek(struct confq *q) +{ + if (q->outbuf < 0) + return NULL; + return q->buf[q->outbuf]; +} + +#ifdef BUF_MUNGE +static u_char *__buf_cpush(struct confq *q) +{ + int pos; + /* If we have no space, return where the + last space that we *did* have was */ + if (q->inbuf > -1) + return NULL; + pos = q->outbuf - 1; + if (pos < 0) + pos += ZT_CB_SIZE; + return q->buf[pos]; +} + +static void __buf_munge(struct zt_chan *chan, u_char *old, u_char *new) +{ + /* Run a weighted average of the old and new, in order to + mask a missing sample */ + int x; + int val; + for (x=0;xinbuf; + if (q->inbuf < 0) { + return -1; + } + if (data) + /* Copy in the data */ + memcpy(q->buf[q->inbuf], data, ZT_CHUNKSIZE); + + /* Advance the inbuf pointer */ + q->inbuf = (q->inbuf + 1) % ZT_CB_SIZE; + + if (q->inbuf == q->outbuf) { + /* No space anymore... */ + q->inbuf = -1; + } + /* If they don't think data is ready, let + them know it is now */ + if (q->outbuf < 0) { + q->outbuf = oldinbuf; + } + return 0; +} + +static void reset_conf(struct zt_chan *chan) +{ + int x; + /* Empty out buffers and reset to initialization */ + for (x=0;xconfin.buf[x] = chan->confin.buffer + ZT_CHUNKSIZE * x; + chan->confin.inbuf = 0; + chan->confin.outbuf = -1; + + for (x=0;xconfout.buf[x] = chan->confout.buffer + ZT_CHUNKSIZE * x; + chan->confout.inbuf = 0; + chan->confout.outbuf = -1; +} + + +static void close_channel(struct zt_chan *chan) +{ + unsigned long flags; + void *rxgain = NULL; + struct echo_can_state *ec = NULL; + int oldconf; + short *readchunkpreec; +#ifdef CONFIG_ZAPATA_PPP + struct ppp_channel *ppp; +#endif + + /* XXX Buffers should be send out before reallocation!!! XXX */ + if (!(chan->flags & ZT_FLAG_NOSTDTXRX)) + zt_reallocbufs(chan, 0, 0); + spin_lock_irqsave(&chan->lock, flags); +#ifdef CONFIG_ZAPATA_PPP + ppp = chan->ppp; + chan->ppp = NULL; +#endif + ec = chan->ec; + chan->ec = NULL; + readchunkpreec = chan->readchunkpreec; + chan->readchunkpreec = NULL; + chan->curtone = NULL; + if (chan->curzone) + atomic_dec(&chan->curzone->refcount); + chan->curzone = NULL; + chan->cadencepos = 0; + chan->pdialcount = 0; + zt_hangup(chan); + chan->itimerset = chan->itimer = 0; + chan->pulsecount = 0; + chan->pulsetimer = 0; + chan->ringdebtimer = 0; + init_waitqueue_head(&chan->sel); + init_waitqueue_head(&chan->readbufq); + init_waitqueue_head(&chan->writebufq); + init_waitqueue_head(&chan->eventbufq); + init_waitqueue_head(&chan->txstateq); + chan->txdialbuf[0] = '\0'; + chan->digitmode = DIGIT_MODE_DTMF; + chan->dialing = 0; + chan->afterdialingtimer = 0; + /* initialize IO MUX mask */ + chan->iomask = 0; + /* save old conf number, if any */ + oldconf = chan->confna; + /* initialize conference variables */ + chan->_confn = 0; + if ((chan->sig & __ZT_SIG_DACS) != __ZT_SIG_DACS) { + chan->confna = 0; + chan->confmode = 0; + } + chan->confmute = 0; + /* release conference resource, if any to release */ + if (oldconf) zt_check_conf(oldconf); + chan->gotgs = 0; + reset_conf(chan); + + if (chan->gainalloc && chan->rxgain) + rxgain = chan->rxgain; + + chan->rxgain = defgain; + chan->txgain = defgain; + chan->gainalloc = 0; + chan->eventinidx = chan->eventoutidx = 0; + chan->flags &= ~(ZT_FLAG_LOOPED | ZT_FLAG_LINEAR | ZT_FLAG_PPP | ZT_FLAG_SIGFREEZE); + + zt_set_law(chan,0); + + memset(chan->conflast, 0, sizeof(chan->conflast)); + memset(chan->conflast1, 0, sizeof(chan->conflast1)); + memset(chan->conflast2, 0, sizeof(chan->conflast2)); + + if (chan->span && chan->span->dacs && oldconf) + chan->span->dacs(chan, NULL); + + spin_unlock_irqrestore(&chan->lock, flags); + + if (chan->span && chan->span->echocan) + chan->span->echocan(chan, 0); + + if (rxgain) + kfree(rxgain); + if (ec) + echo_can_free(ec); + if (readchunkpreec) + kfree(readchunkpreec); + +#ifdef CONFIG_ZAPATA_PPP + if (ppp) { + tasklet_kill(&chan->ppp_calls); + skb_queue_purge(&chan->ppp_rq); + ppp_unregister_channel(ppp); + kfree(ppp); + } +#endif + +} + +static int free_tone_zone(int num) +{ + struct zt_zone *z; + + if ((num >= ZT_TONE_ZONE_MAX) || (num < 0)) + return -EINVAL; + + write_lock(&zone_lock); + z = tone_zones[num]; + tone_zones[num] = NULL; + write_unlock(&zone_lock); + if (!z) + return 0; + + if (atomic_read(&z->refcount)) { + /* channels are still using this zone so put it back */ + write_lock(&zone_lock); + tone_zones[num] = z; + write_unlock(&zone_lock); + + return -EBUSY; + } else { + kfree(z); + + return 0; + } +} + +static int zt_register_tone_zone(int num, struct zt_zone *zone) +{ + int res = 0; + + if ((num >= ZT_TONE_ZONE_MAX) || (num < 0)) + return -EINVAL; + + write_lock(&zone_lock); + if (tone_zones[num]) { + res = -EINVAL; + } else { + res = 0; + tone_zones[num] = zone; + } + write_unlock(&zone_lock); + + if (!res) + printk(KERN_INFO "Registered tone zone %d (%s)\n", num, zone->name); + + return res; +} + +static int start_tone(struct zt_chan *chan, int tone) +{ + int res = -EINVAL; + + /* Stop the current tone, no matter what */ + chan->tonep = 0; + chan->curtone = NULL; + chan->pdialcount = 0; + chan->txdialbuf[0] = '\0'; + chan->dialing = 0; + + if (tone == -1) { + /* Just stop the current tone */ + res = 0; + } else if ((tone >= 0 && tone <= ZT_TONE_MAX)) { + if (chan->curzone) { + /* Have a tone zone */ + if (chan->curzone->tones[tone]) { + chan->curtone = chan->curzone->tones[tone]; + res = 0; + } else /* Indicate that zone is loaded but no such tone exists */ + res = -ENOSYS; + } else /* Note that no tone zone exists at the moment */ + res = -ENODATA; + } else if (tone >= ZT_TONE_DTMF_BASE && tone <= ZT_TONE_DTMF_MAX) { + /* ZT_SENDTONE should never be used on a channel configured for pulse dialing */ + chan->dialing = 1; + res = 0; + if ((chan->digitmode == DIGIT_MODE_DTMF) && + (tone >= ZT_TONE_DTMF_BASE) && + (tone <= ZT_TONE_DTMF_MAX)) + chan->curtone = &chan->curzone->dtmf_continuous[tone - ZT_TONE_DTMF_BASE]; + else if ((chan->digitmode == DIGIT_MODE_MFV1) && + (tone >= ZT_TONE_MF_BASE) && + (tone <= ZT_TONE_MF_MAX)) + chan->curtone = &chan->curzone->mf_continuous[tone - ZT_TONE_MF_BASE]; + else { + chan->dialing = 0; + res = -EINVAL; + } + } + + if (chan->curtone) + zt_init_tone_state(&chan->ts, chan->curtone); + + return res; +} + +static int set_tone_zone(struct zt_chan *chan, int zone) +{ + int res = 0; + struct zt_zone *z; + unsigned long flags; + + /* Do not call with the channel locked. */ + + if (zone == -1) + zone = default_zone; + + if ((zone >= ZT_TONE_ZONE_MAX) || (zone < 0)) + return -EINVAL; + + read_lock(&zone_lock); + + if ((z = tone_zones[zone])) { + spin_lock_irqsave(&chan->lock, flags); + if (chan->curzone) + atomic_dec(&chan->curzone->refcount); + + atomic_inc(&z->refcount); + chan->curzone = z; + chan->tonezone = zone; + memcpy(chan->ringcadence, z->ringcadence, sizeof(chan->ringcadence)); + spin_unlock_irqrestore(&chan->lock, flags); + } else { + res = -ENODATA; + } + + read_unlock(&zone_lock); + + return res; +} + +static void zt_set_law(struct zt_chan *chan, int law) +{ + if (!law) { + if (chan->deflaw) + law = chan->deflaw; + else + if (chan->span) law = chan->span->deflaw; + else law = ZT_LAW_MULAW; + } + if (law == ZT_LAW_ALAW) { + chan->xlaw = __zt_alaw; +#ifdef CONFIG_CALC_XLAW + chan->lineartoxlaw = __zt_lineartoalaw; +#else + chan->lin2x = __zt_lin2a; +#endif + } else { + chan->xlaw = __zt_mulaw; +#ifdef CONFIG_CALC_XLAW + chan->lineartoxlaw = __zt_lineartoulaw; +#else + chan->lin2x = __zt_lin2mu; +#endif + } +} + +#ifdef CONFIG_DEVFS_FS +static devfs_handle_t register_devfs_channel(struct zt_chan *chan, devfs_handle_t dir) +{ + char path[100]; + char link[100]; + char buf[50]; + char tmp[100]; + int link_offset = 0; + int tmp_offset = 0; + int path_offset = 0; + int err = 0; + devfs_handle_t chan_dev; + umode_t mode = S_IFCHR|S_IRUGO|S_IWUGO; + unsigned int flags = DEVFS_FL_AUTO_OWNER; + + sprintf(path, "%d", chan->chanpos); + chan_dev = devfs_register(dir, path, flags, ZT_MAJOR, chan->channo, mode, &zt_fops, NULL); + if (!chan_dev) { + printk("zaptel: Something really bad happened. Unable to register devfs entry\n"); + return NULL; + } + + /* Set up the path of the destination of the link */ + link_offset = devfs_generate_path(chan_dev, link, sizeof(link) - 1); + /* Now we need to strip off the leading "zap/". If we don't, then we build a broken symlink */ + path_offset = devfs_generate_path(zaptel_devfs_dir, path, sizeof(path) - 1); /* We'll just "borrow" path for a second */ + path_offset = strlen(path+path_offset); + link_offset += path_offset; /* Taking out the "zap" */ + link_offset++; /* Add one more place for the '/'. The path generated does not contain the '/' we need to strip */ + + /* Set up the path of the file/link itself */ + tmp_offset = devfs_generate_path(zaptel_devfs_dir, tmp, sizeof(tmp) - 1); + sprintf(buf, "/%d", chan->channo); + strncpy(path, tmp+tmp_offset, sizeof(path) - 1); + strncat(path, buf, sizeof(path) - 1); + + err = devfs_mk_symlink(NULL, path, DEVFS_FL_DEFAULT, link+link_offset, &chan->fhandle_symlink, NULL); + if (err != 0) { + printk("Problem with making devfs symlink: %d\n", err); + } + + return chan_dev; +} +#endif /* CONFIG_DEVFS_FS */ + +static int zt_chan_reg(struct zt_chan *chan) +{ + int x; + int res=0; + unsigned long flags; + + write_lock_irqsave(&chan_lock, flags); + for (x=1;xlock); + chans[x] = chan; + if (maxchans < x + 1) + maxchans = x + 1; + chan->channo = x; + if (!chan->master) + chan->master = chan; + if (!chan->readchunk) + chan->readchunk = chan->sreadchunk; + if (!chan->writechunk) + chan->writechunk = chan->swritechunk; + zt_set_law(chan, 0); + close_channel(chan); + /* set this AFTER running close_channel() so that + HDLC channels wont cause hangage */ + chan->flags |= ZT_FLAG_REGISTERED; + res = 0; + break; + } + } + write_unlock_irqrestore(&chan_lock, flags); + if (x >= ZT_MAX_CHANNELS) + printk(KERN_ERR "No more channels available\n"); + return res; +} + +char *zt_lboname(int x) +{ + if ((x < 0) || ( x > 7)) + return "Unknown"; + return zt_txlevelnames[x]; +} + +#if defined(CONFIG_ZAPATA_NET) || defined(CONFIG_ZAPATA_PPP) +#endif + +#ifdef CONFIG_ZAPATA_NET +#ifdef NEW_HDLC_INTERFACE +static int zt_net_open(struct net_device *dev) +{ +#ifdef LINUX26 + int res = hdlc_open(dev); + struct zt_chan *ms = dev_to_ztchan(dev); +#else + hdlc_device *hdlc = dev_to_hdlc(dev); + struct zt_chan *ms = hdlc_to_ztchan(hdlc); + int res = hdlc_open(hdlc); +#endif + +/* if (!dev->hard_start_xmit) return res; is this really necessary? --byg */ + if (res) /* this is necessary to avoid kernel panic when UNSPEC link encap, proven --byg */ + return res; +#else +static int zt_net_open(hdlc_device *hdlc) +{ + struct zt_chan *ms = hdlc_to_ztchan(hdlc); + int res; +#endif + if (!ms) { + printk("zt_net_open: nothing??\n"); + return -EINVAL; + } + if (ms->flags & ZT_FLAG_OPEN) { + printk("%s is already open!\n", ms->name); + return -EBUSY; + } + if (!(ms->flags & ZT_FLAG_NETDEV)) { + printk("%s is not a net device!\n", ms->name); + return -EINVAL; + } + ms->txbufpolicy = ZT_POLICY_IMMEDIATE; + ms->rxbufpolicy = ZT_POLICY_IMMEDIATE; + + res = zt_reallocbufs(ms, ZT_DEFAULT_MTU_MRU, ZT_DEFAULT_NUM_BUFS); + if (res) + return res; + + fasthdlc_init(&ms->rxhdlc); + fasthdlc_init(&ms->txhdlc); + ms->infcs = PPP_INITFCS; + + netif_start_queue(ztchan_to_dev(ms)); + +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#endif +#ifdef CONFIG_ZAPATA_DEBUG + printk("ZAPNET: Opened channel %d name %s\n", ms->channo, ms->name); +#endif + return 0; +} + +#ifdef LINUX26 +static int zt_register_hdlc_device(struct net_device *dev, const char *dev_name) +{ + int result; + + if (dev_name && *dev_name) { + if ((result = dev_alloc_name(dev, dev_name)) < 0) + return result; + } + result = register_netdev(dev); + if (result != 0) + return -EIO; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,14) + if (netif_carrier_ok(dev)) + netif_carrier_off(dev); /* no carrier until DCD goes up */ +#endif + return 0; +} +#endif + +#ifdef NEW_HDLC_INTERFACE +static int zt_net_stop(struct net_device *dev) +{ +#ifdef LINUX26 + hdlc_device *h = dev_to_hdlc(dev); + struct zt_hdlc *hdlc = h->priv; +#else + hdlc_device *hdlc = dev_to_hdlc(dev); +#endif + +#else +static void zt_net_close(hdlc_device *hdlc) +{ +#endif + struct zt_chan *ms = hdlc_to_ztchan(hdlc); + if (!ms) { +#ifdef NEW_HDLC_INTERFACE + printk("zt_net_stop: nothing??\n"); + return 0; +#else + printk("zt_net_close: nothing??\n"); + return; +#endif + } + if (!(ms->flags & ZT_FLAG_NETDEV)) { +#ifdef NEW_HDLC_INTERFACE + printk("zt_net_stop: %s is not a net device!\n", ms->name); + return 0; +#else + printk("zt_net_close: %s is not a net device!\n", ms->name); + return; +#endif + } + /* Not much to do here. Just deallocate the buffers */ + netif_stop_queue(ztchan_to_dev(ms)); + zt_reallocbufs(ms, 0, 0); +#ifdef LINUX26 + hdlc_close(dev); +#else +#ifndef CONFIG_OLD_HDLC_API + hdlc_close(hdlc); +#endif +#endif +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#endif +#ifdef NEW_HDLC_INTERFACE + return 0; +#else + return; +#endif +} + +#ifdef NEW_HDLC_INTERFACE +/* kernel 2.4.20+ has introduced attach function, dunno what to do, + just copy sources from dscc4 to be sure and ready for further mastering, + NOOP right now (i.e. really a stub) --byg */ +#ifdef LINUX26 +static int zt_net_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity) +#else +static int zt_net_attach(hdlc_device *hdlc, unsigned short encoding, + unsigned short parity) +#endif +{ +/* struct net_device *dev = hdlc_to_dev(hdlc); + struct dscc4_dev_priv *dpriv = dscc4_priv(dev); + + if (encoding != ENCODING_NRZ && + encoding != ENCODING_NRZI && + encoding != ENCODING_FM_MARK && + encoding != ENCODING_FM_SPACE && + encoding != ENCODING_MANCHESTER) + return -EINVAL; + + if (parity != PARITY_NONE && + parity != PARITY_CRC16_PR0_CCITT && + parity != PARITY_CRC16_PR1_CCITT && + parity != PARITY_CRC32_PR0_CCITT && + parity != PARITY_CRC32_PR1_CCITT) + return -EINVAL; + + dpriv->encoding = encoding; + dpriv->parity = parity;*/ + return 0; +} +#endif + +static struct zt_hdlc *zt_hdlc_alloc(void) +{ + struct zt_hdlc *tmp; + tmp = kmalloc(sizeof(struct zt_hdlc), GFP_KERNEL); + if (tmp) { + memset(tmp, 0, sizeof(struct zt_hdlc)); + } + return tmp; +} + +#ifdef NEW_HDLC_INTERFACE +static int zt_xmit(struct sk_buff *skb, struct net_device *dev) +{ + /* FIXME: this construction seems to be not very optimal for me but I could find nothing better at the moment (Friday, 10PM :( ) --byg */ +/* struct zt_chan *ss = hdlc_to_ztchan(list_entry(dev, struct zt_hdlc, netdev.netdev));*/ +#ifdef LINUX26 + struct zt_chan *ss = dev_to_ztchan(dev); + struct net_device_stats *stats = hdlc_stats(dev); +#else + struct zt_chan *ss = (list_entry(dev, struct zt_hdlc, netdev.netdev)->chan); + struct net_device_stats *stats = &ss->hdlcnetdev->netdev.stats; +#endif + +#else +static int zt_xmit(hdlc_device *hdlc, struct sk_buff *skb) +{ + struct zt_chan *ss = hdlc_to_ztchan(hdlc); + struct net_device *dev = &ss->hdlcnetdev->netdev.netdev; + struct net_device_stats *stats = &ss->hdlcnetdev->netdev.stats; +#endif + int retval = 1; + int x,oldbuf; + unsigned int fcs; + unsigned char *data; + unsigned long flags; + /* See if we have any buffers */ + spin_lock_irqsave(&ss->lock, flags); + if (skb->len > ss->blocksize - 2) { + printk(KERN_ERR "zt_xmit(%s): skb is too large (%d > %d)\n", dev->name, skb->len, ss->blocksize -2); + stats->tx_dropped++; + retval = 0; + } else if (ss->inwritebuf >= 0) { + /* We have a place to put this packet */ + /* XXX We should keep the SKB and avoid the memcpy XXX */ + data = ss->writebuf[ss->inwritebuf]; + memcpy(data, skb->data, skb->len); + ss->writen[ss->inwritebuf] = skb->len; + ss->writeidx[ss->inwritebuf] = 0; + /* Calculate the FCS */ + fcs = PPP_INITFCS; + for (x=0;xlen;x++) + fcs = PPP_FCS(fcs, data[x]); + /* Invert it */ + fcs ^= 0xffff; + /* Send it out LSB first */ + data[ss->writen[ss->inwritebuf]++] = (fcs & 0xff); + data[ss->writen[ss->inwritebuf]++] = (fcs >> 8) & 0xff; + /* Advance to next window */ + oldbuf = ss->inwritebuf; + ss->inwritebuf = (ss->inwritebuf + 1) % ss->numbufs; + + if (ss->inwritebuf == ss->outwritebuf) { + /* Whoops, no more space. */ + ss->inwritebuf = -1; + + netif_stop_queue(ztchan_to_dev(ss)); + } + if (ss->outwritebuf < 0) { + /* Let the interrupt handler know there's + some space for us */ + ss->outwritebuf = oldbuf; + } + dev->trans_start = jiffies; + stats->tx_packets++; + stats->tx_bytes += ss->writen[oldbuf]; +#ifdef CONFIG_ZAPATA_DEBUG + printk("Buffered %d bytes to go out in buffer %d\n", ss->writen[oldbuf], oldbuf); + for (x=0;xwriten[oldbuf];x++) + printk("%02x ", ss->writebuf[oldbuf][x]); + printk("\n"); +#endif + retval = 0; + /* Free the SKB */ + dev_kfree_skb_any(skb); + } + spin_unlock_irqrestore(&ss->lock, flags); + return retval; +} + +#ifdef NEW_HDLC_INTERFACE +static int zt_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + return hdlc_ioctl(dev, ifr, cmd); +} +#else +static int zt_net_ioctl(hdlc_device *hdlc, struct ifreq *ifr, int cmd) +{ + return -EIO; +} +#endif + +#endif + +#ifdef CONFIG_ZAPATA_PPP + +static int zt_ppp_xmit(struct ppp_channel *ppp, struct sk_buff *skb) +{ + + /* + * If we can't handle the packet right now, return 0. If we + * we handle or drop it, return 1. Always free if we return + * 1 and never if we return 0 + */ + struct zt_chan *ss = ppp->private; + int x,oldbuf; + unsigned int fcs; + unsigned char *data; + long flags; + int retval = 0; + + /* See if we have any buffers */ + spin_lock_irqsave(&ss->lock, flags); + if (!(ss->flags & ZT_FLAG_OPEN)) { + printk("Can't transmit on closed channel\n"); + retval = 1; + } else if (skb->len > ss->blocksize - 4) { + printk(KERN_ERR "zt_ppp_xmit(%s): skb is too large (%d > %d)\n", ss->name, skb->len, ss->blocksize -2); + retval = 1; + } else if (ss->inwritebuf >= 0) { + /* We have a place to put this packet */ + /* XXX We should keep the SKB and avoid the memcpy XXX */ + data = ss->writebuf[ss->inwritebuf]; + /* Start with header of two bytes */ + /* Add "ALL STATIONS" and "UNNUMBERED" */ + data[0] = 0xff; + data[1] = 0x03; + ss->writen[ss->inwritebuf] = 2; + + /* Copy real data and increment amount written */ + memcpy(data + 2, skb->data, skb->len); + + ss->writen[ss->inwritebuf] += skb->len; + + /* Re-set index back to zero */ + ss->writeidx[ss->inwritebuf] = 0; + + /* Calculate the FCS */ + fcs = PPP_INITFCS; + for (x=0;xlen + 2;x++) + fcs = PPP_FCS(fcs, data[x]); + /* Invert it */ + fcs ^= 0xffff; + + /* Point past the real data now */ + data += (skb->len + 2); + + /* Send FCS out LSB first */ + data[0] = (fcs & 0xff); + data[1] = (fcs >> 8) & 0xff; + + /* Account for FCS length */ + ss->writen[ss->inwritebuf]+=2; + + /* Advance to next window */ + oldbuf = ss->inwritebuf; + ss->inwritebuf = (ss->inwritebuf + 1) % ss->numbufs; + + if (ss->inwritebuf == ss->outwritebuf) { + /* Whoops, no more space. */ + ss->inwritebuf = -1; + } + if (ss->outwritebuf < 0) { + /* Let the interrupt handler know there's + some space for us */ + ss->outwritebuf = oldbuf; + } +#ifdef CONFIG_ZAPATA_DEBUG + printk("Buffered %d bytes (skblen = %d) to go out in buffer %d\n", ss->writen[oldbuf], skb->len, oldbuf); + for (x=0;xwriten[oldbuf];x++) + printk("%02x ", ss->writebuf[oldbuf][x]); + printk("\n"); +#endif + retval = 1; + } + spin_unlock_irqrestore(&ss->lock, flags); + if (retval) { + /* Get rid of the SKB if we're returning non-zero */ + /* N.B. this is called in process or BH context so + dev_kfree_skb is OK. */ + dev_kfree_skb(skb); + } + return retval; +} + +static int zt_ppp_ioctl(struct ppp_channel *ppp, unsigned int cmd, unsigned long flags) +{ + return -EIO; +} + +static struct ppp_channel_ops ztppp_ops = +{ + start_xmit: zt_ppp_xmit, + ioctl: zt_ppp_ioctl, +}; + +#endif + +static void zt_chan_unreg(struct zt_chan *chan) +{ + int x; + unsigned long flags; +#ifdef CONFIG_ZAPATA_NET + if (chan->flags & ZT_FLAG_NETDEV) { +#ifdef LINUX26 + unregister_hdlc_device(chan->hdlcnetdev->netdev); + free_netdev(chan->hdlcnetdev->netdev); +#else + unregister_hdlc_device(&chan->hdlcnetdev->netdev); +#endif + kfree(chan->hdlcnetdev); + chan->hdlcnetdev = NULL; + } +#endif + write_lock_irqsave(&chan_lock, flags); + if (chan->flags & ZT_FLAG_REGISTERED) { + chans[chan->channo] = NULL; + chan->flags &= ~ZT_FLAG_REGISTERED; + } +#ifdef CONFIG_ZAPATA_PPP + if (chan->ppp) { + printk("HUH??? PPP still attached??\n"); + } +#endif + maxchans = 0; + for (x=1;xmaster == chan) { + chans[x]->master = chans[x]; + } + if ((chans[x]->confna == chan->channo) && + ((chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR || + (chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORTX || + (chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORBOTH || + (chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_RX_PREECHO || + (chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_TX_PREECHO || + (chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORBOTH_PREECHO || + (chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_DIGITALMON)) { + /* Take them out of conference with us */ + /* release conference resource if any */ + if (chans[x]->confna) { + zt_check_conf(chans[x]->confna); + if (chans[x]->span && chans[x]->span->dacs) + chans[x]->span->dacs(chans[x], NULL); + } + chans[x]->confna = 0; + chans[x]->_confn = 0; + chans[x]->confmode = 0; + } + } + chan->channo = -1; + write_unlock_irqrestore(&chan_lock, flags); +} + +static ssize_t zt_chan_read(struct file *file, char *usrbuf, size_t count, int unit) +{ + struct zt_chan *chan = chans[unit]; + int amnt; + int res, rv; + int oldbuf,x; + unsigned long flags; + /* Make sure count never exceeds 65k, and make sure it's unsigned */ + count &= 0xffff; + if (!chan) + return -EINVAL; + if (count < 1) + return -EINVAL; + for(;;) { + spin_lock_irqsave(&chan->lock, flags); + if (chan->eventinidx != chan->eventoutidx) { + spin_unlock_irqrestore(&chan->lock, flags); + return -ELAST /* - chan->eventbuf[chan->eventoutidx]*/; + } + res = chan->outreadbuf; + if (chan->rxdisable) + res = -1; + spin_unlock_irqrestore(&chan->lock, flags); + if (res >= 0) break; + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + rv = schluffen(&chan->readbufq); + if (rv) return (rv); + } + amnt = count; +/* added */ +#if 0 + if ((unit == 24) || (unit == 48) || (unit == 16) || (unit == 47)) { + int myamnt = amnt; + int x; + if (amnt > chan->readn[res]) + myamnt = chan->readn[res]; + printk("zt_chan_read(unit: %d, inwritebuf: %d, outwritebuf: %d amnt: %d\n", + unit, chan->inwritebuf, chan->outwritebuf, myamnt); + printk("\t("); for (x = 0; x < myamnt; x++) printk((x ? " %02x" : "%02x"), (unsigned char)usrbuf[x]); + printk(")\n"); + } +#endif +/* end addition */ + if (chan->flags & ZT_FLAG_LINEAR) { + if (amnt > (chan->readn[res] << 1)) + amnt = chan->readn[res] << 1; + if (amnt) { + /* There seems to be a max stack size, so we have + to do this in smaller pieces */ + short lindata[128]; + int left = amnt >> 1; /* amnt is in bytes */ + int pos = 0; + int pass; + while(left) { + pass = left; + if (pass > 128) + pass = 128; + for (x=0;xreadbuf[res][x + pos], chan); + if (copy_to_user(usrbuf + (pos << 1), lindata, pass << 1)) + return -EFAULT; + left -= pass; + pos += pass; + } + } + } else { + if (amnt > chan->readn[res]) + amnt = chan->readn[res]; + if (amnt) { + if (copy_to_user(usrbuf, chan->readbuf[res], amnt)) + return -EFAULT; + } + } + spin_lock_irqsave(&chan->lock, flags); + chan->readidx[res] = 0; + chan->readn[res] = 0; + oldbuf = res; + chan->outreadbuf = (res + 1) % chan->numbufs; + if (chan->outreadbuf == chan->inreadbuf) { + /* Out of stuff */ + chan->outreadbuf = -1; + if (chan->rxbufpolicy == ZT_POLICY_WHEN_FULL) + chan->rxdisable = 1; + } + if (chan->inreadbuf < 0) { + /* Notify interrupt handler that we have some space now */ + chan->inreadbuf = oldbuf; + } + spin_unlock_irqrestore(&chan->lock, flags); + + return amnt; +} + +static ssize_t zt_chan_write(struct file *file, const char *usrbuf, size_t count, int unit) +{ + unsigned long flags; + struct zt_chan *chan = chans[unit]; + int res, amnt, oldbuf, rv,x; + /* Make sure count never exceeds 65k, and make sure it's unsigned */ + count &= 0xffff; + if (!chan) + return -EINVAL; + if (count < 1) + return -EINVAL; + for(;;) { + spin_lock_irqsave(&chan->lock, flags); + if ((chan->curtone || chan->pdialcount) && !(chan->flags & ZT_FLAG_PSEUDO)) { + chan->curtone = NULL; + chan->tonep = 0; + chan->dialing = 0; + chan->txdialbuf[0] = '\0'; + chan->pdialcount = 0; + } + if (chan->eventinidx != chan->eventoutidx) { + spin_unlock_irqrestore(&chan->lock, flags); + return -ELAST; + } + res = chan->inwritebuf; + spin_unlock_irqrestore(&chan->lock, flags); + if (res >= 0) + break; + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + /* Wait for something to be available */ + rv = schluffen(&chan->writebufq); + if (rv) + return rv; + } + + amnt = count; + if (chan->flags & ZT_FLAG_LINEAR) { + if (amnt > (chan->blocksize << 1)) + amnt = chan->blocksize << 1; + } else { + if (amnt > chan->blocksize) + amnt = chan->blocksize; + } + +#ifdef CONFIG_ZAPATA_DEBUG + printk("zt_chan_write(unit: %d, res: %d, outwritebuf: %d amnt: %d\n", + unit, chan->res, chan->outwritebuf, amnt); +#endif +#if 0 + if ((unit == 24) || (unit == 48) || (unit == 16) || (unit == 47)) { + int x; + printk("zt_chan_write/in(unit: %d, res: %d, outwritebuf: %d amnt: %d, txdisable: %d)\n", + unit, res, chan->outwritebuf, amnt, chan->txdisable); + printk("\t("); for (x = 0; x < amnt; x++) printk((x ? " %02x" : "%02x"), (unsigned char)usrbuf[x]); + printk(")\n"); + } +#endif + + if (amnt) { + if (chan->flags & ZT_FLAG_LINEAR) { + /* There seems to be a max stack size, so we have + to do this in smaller pieces */ + short lindata[128]; + int left = amnt >> 1; /* amnt is in bytes */ + int pos = 0; + int pass; + while(left) { + pass = left; + if (pass > 128) + pass = 128; + if (copy_from_user(lindata, usrbuf + (pos << 1), pass << 1)) + return -EFAULT; + left -= pass; + for (x=0;xwritebuf[res][x + pos] = ZT_LIN2X(lindata[x], chan); + pos += pass; + } + chan->writen[res] = amnt >> 1; + } else { + if (copy_from_user(chan->writebuf[res], usrbuf, amnt)) + return -EFAULT; + chan->writen[res] = amnt; + } + chan->writeidx[res] = 0; + if (chan->flags & ZT_FLAG_FCS) + calc_fcs(chan, res); + oldbuf = res; + spin_lock_irqsave(&chan->lock, flags); + chan->inwritebuf = (res + 1) % chan->numbufs; + if (chan->inwritebuf == chan->outwritebuf) { + /* Don't stomp on the transmitter, just wait for them to + wake us up */ + chan->inwritebuf = -1; + /* Make sure the transmitter is transmitting in case of POLICY_WHEN_FULL */ + chan->txdisable = 0; + } + if (chan->outwritebuf < 0) { + /* Okay, the interrupt handler has been waiting for us. Give them a buffer */ + chan->outwritebuf = oldbuf; + } + spin_unlock_irqrestore(&chan->lock, flags); + + if (chan->flags & ZT_FLAG_NOSTDTXRX && chan->span->hdlc_hard_xmit) + chan->span->hdlc_hard_xmit(chan); + } + return amnt; +} + +static int zt_ctl_open(struct inode *inode, struct file *file) +{ + /* Nothing to do, really */ +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#endif + return 0; +} + +static int zt_chan_open(struct inode *inode, struct file *file) +{ + /* Nothing to do here for now either */ +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#endif + return 0; +} + +static int zt_ctl_release(struct inode *inode, struct file *file) +{ + /* Nothing to do */ +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#endif + return 0; +} + +static int zt_chan_release(struct inode *inode, struct file *file) +{ + /* Nothing to do for now */ +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#endif + return 0; +} + +static void set_txtone(struct zt_chan *ss,int fac, int init_v2, int init_v3) +{ + if (fac == 0) + { + ss->v2_1 = 0; + ss->v3_1 = 0; + return; + } + ss->txtone = fac; + ss->v1_1 = 0; + ss->v2_1 = init_v2; + ss->v3_1 = init_v3; + return; +} + +static void zt_rbs_sethook(struct zt_chan *chan, int txsig, int txstate, int timeout) +{ +static int outs[NUM_SIGS][5] = { +/* We set the idle case of the ZT_SIG_NONE to this pattern to make idle E1 CAS +channels happy. Should not matter with T1, since on an un-configured channel, +who cares what the sig bits are as long as they are stable */ + { ZT_SIG_NONE, ZT_ABIT | ZT_CBIT | ZT_DBIT, 0, 0, 0 }, /* no signalling */ + { ZT_SIG_EM, 0, ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, + ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, 0 }, /* E and M */ + { ZT_SIG_FXSLS, ZT_BBIT | ZT_DBIT, + ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, + ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, 0 }, /* FXS Loopstart */ + { ZT_SIG_FXSGS, ZT_BBIT | ZT_DBIT, +#ifdef CONFIG_CAC_GROUNDSTART + ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, 0, 0 }, /* FXS Groundstart (CAC-style) */ +#else + ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, ZT_ABIT | ZT_CBIT, 0 }, /* FXS Groundstart (normal) */ +#endif + { ZT_SIG_FXSKS, ZT_BBIT | ZT_DBIT, + ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, + ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, 0 }, /* FXS Kewlstart */ + { ZT_SIG_FXOLS, ZT_BBIT | ZT_DBIT, ZT_BBIT | ZT_DBIT, 0, 0 }, /* FXO Loopstart */ + { ZT_SIG_FXOGS, ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, + ZT_BBIT | ZT_DBIT, 0, 0 }, /* FXO Groundstart */ + { ZT_SIG_FXOKS, ZT_BBIT | ZT_DBIT, ZT_BBIT | ZT_DBIT, 0, + ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT }, /* FXO Kewlstart */ + { ZT_SIG_SF, ZT_BBIT | ZT_CBIT | ZT_DBIT, + ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, + ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, + ZT_BBIT | ZT_CBIT | ZT_DBIT }, /* no signalling */ + { ZT_SIG_EM_E1, ZT_DBIT, ZT_ABIT | ZT_BBIT | ZT_DBIT, + ZT_ABIT | ZT_BBIT | ZT_DBIT, ZT_DBIT }, /* E and M E1 */ + } ; + int x; + + /* if no span, return doing nothing */ + if (!chan->span) return; + if (!chan->span->flags & ZT_FLAG_RBS) { + printk("zt_rbs: Tried to set RBS hook state on non-RBS channel %s\n", chan->name); + return; + } + if ((txsig > 3) || (txsig < 0)) { + printk("zt_rbs: Tried to set RBS hook state %d (> 3) on channel %s\n", txsig, chan->name); + return; + } + if (!chan->span->rbsbits && !chan->span->hooksig) { + printk("zt_rbs: Tried to set RBS hook state %d on channel %s while span %s lacks rbsbits or hooksig function\n", + txsig, chan->name, chan->span->name); + return; + } + /* Don't do anything for RBS */ + if (chan->sig == ZT_SIG_DACS_RBS) + return; + chan->txstate = txstate; + + /* if tone signalling */ + if (chan->sig == ZT_SIG_SF) + { + chan->txhooksig = txsig; + if (chan->txtone) /* if set to make tone for tx */ + { + if ((txsig && !(chan->toneflags & ZT_REVERSE_TXTONE)) || + ((!txsig) && (chan->toneflags & ZT_REVERSE_TXTONE))) + { + set_txtone(chan,chan->txtone,chan->tx_v2,chan->tx_v3); + } + else + { + set_txtone(chan,0,0,0); + } + } + chan->otimer = timeout * ZT_CHUNKSIZE; /* Otimer is timer in samples */ + return; + } + if (chan->span->hooksig) { + if (chan->txhooksig != txsig) { + chan->txhooksig = txsig; + chan->span->hooksig(chan, txsig); + } + chan->otimer = timeout * ZT_CHUNKSIZE; /* Otimer is timer in samples */ + return; + } else { + for (x=0;xsig) { +#ifdef CONFIG_ZAPATA_DEBUG + printk("Setting bits to %d for channel %s state %d in %d signalling\n", outs[x][txsig + 1], chan->name, txsig, chan->sig); +#endif + chan->txhooksig = txsig; + chan->txsig = outs[x][txsig+1]; + chan->span->rbsbits(chan, chan->txsig); + chan->otimer = timeout * ZT_CHUNKSIZE; /* Otimer is timer in samples */ + return; + } + } + } + printk("zt_rbs: Don't know RBS signalling type %d on channel %s\n", chan->sig, chan->name); +} + +static int zt_cas_setbits(struct zt_chan *chan, int bits) +{ + /* if no span, return as error */ + if (!chan->span) return -1; + if (chan->span->rbsbits) { + chan->txsig = bits; + chan->span->rbsbits(chan, bits); + } else { + printk("Huh? CAS setbits, but no RBS bits function\n"); + } + return 0; +} + +static int zt_hangup(struct zt_chan *chan) +{ + int x,res=0; + + /* Can't hangup pseudo channels */ + if (!chan->span) + return 0; + /* Can't hang up a clear channel */ + if (chan->flags & (ZT_FLAG_CLEAR | ZT_FLAG_NOSTDTXRX)) + return -EINVAL; + + chan->kewlonhook = 0; + + + if ((chan->sig == ZT_SIG_FXSLS) || (chan->sig == ZT_SIG_FXSKS) || + (chan->sig == ZT_SIG_FXSGS)) chan->ringdebtimer = RING_DEBOUNCE_TIME; + + if (chan->span->flags & ZT_FLAG_RBS) { + if (chan->sig == ZT_SIG_CAS) { + zt_cas_setbits(chan, chan->idlebits); + } else if ((chan->sig == ZT_SIG_FXOKS) && (chan->txstate != ZT_TXSTATE_ONHOOK)) { + /* Do RBS signalling on the channel's behalf */ + zt_rbs_sethook(chan, ZT_TXSIG_KEWL, ZT_TXSTATE_KEWL, ZT_KEWLTIME); + } else + zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_ONHOOK, 0); + } else { + /* Let the driver hang up the line if it wants to */ + if (chan->span->sethook) { + if (chan->txhooksig != ZT_ONHOOK) { + chan->txhooksig = ZT_ONHOOK; + res = chan->span->sethook(chan, ZT_ONHOOK); + } else + res = 0; + } + } + /* if not registered yet, just return here */ + if (!(chan->flags & ZT_FLAG_REGISTERED)) return res; + /* Mark all buffers as empty */ + for (x = 0;x < chan->numbufs;x++) { + chan->writen[x] = + chan->writeidx[x]= + chan->readn[x]= + chan->readidx[x] = 0; + } + if (chan->readbuf[0]) { + chan->inreadbuf = 0; + chan->inwritebuf = 0; + } else { + chan->inreadbuf = -1; + chan->inwritebuf = -1; + } + chan->outreadbuf = -1; + chan->outwritebuf = -1; + chan->dialing = 0; + chan->afterdialingtimer = 0; + chan->curtone = NULL; + chan->pdialcount = 0; + chan->cadencepos = 0; + chan->txdialbuf[0] = 0; + return res; +} + +static int initialize_channel(struct zt_chan *chan) +{ + int res; + unsigned long flags; + void *rxgain=NULL; + struct echo_can_state *ec=NULL; + if ((res = zt_reallocbufs(chan, ZT_DEFAULT_BLOCKSIZE, ZT_DEFAULT_NUM_BUFS))) + return res; + + spin_lock_irqsave(&chan->lock, flags); + + chan->rxbufpolicy = ZT_POLICY_IMMEDIATE; + chan->txbufpolicy = ZT_POLICY_IMMEDIATE; + + /* Free up the echo canceller if there is one */ + ec = chan->ec; + chan->ec = NULL; + chan->echocancel = 0; + chan->echostate = ECHO_STATE_IDLE; + chan->echolastupdate = 0; + chan->echotimer = 0; + + chan->txdisable = 0; + chan->rxdisable = 0; + + chan->digitmode = DIGIT_MODE_DTMF; + chan->dialing = 0; + chan->afterdialingtimer = 0; + + chan->cadencepos = 0; + chan->firstcadencepos = 0; /* By default loop back to first cadence position */ + + /* HDLC & FCS stuff */ + fasthdlc_init(&chan->rxhdlc); + fasthdlc_init(&chan->txhdlc); + chan->infcs = PPP_INITFCS; + + /* Timings for RBS */ + chan->prewinktime = ZT_DEFAULT_PREWINKTIME; + chan->preflashtime = ZT_DEFAULT_PREFLASHTIME; + chan->winktime = ZT_DEFAULT_WINKTIME; + chan->flashtime = ZT_DEFAULT_FLASHTIME; + + if (chan->sig & __ZT_SIG_FXO) + chan->starttime = ZT_DEFAULT_RINGTIME; + else + chan->starttime = ZT_DEFAULT_STARTTIME; + chan->rxwinktime = ZT_DEFAULT_RXWINKTIME; + chan->rxflashtime = ZT_DEFAULT_RXFLASHTIME; + chan->debouncetime = ZT_DEFAULT_DEBOUNCETIME; + chan->pulsemaketime = ZT_DEFAULT_PULSEMAKETIME; + chan->pulsebreaktime = ZT_DEFAULT_PULSEBREAKTIME; + chan->pulseaftertime = ZT_DEFAULT_PULSEAFTERTIME; + + /* Initialize RBS timers */ + chan->itimerset = chan->itimer = chan->otimer = 0; + chan->ringdebtimer = 0; + + init_waitqueue_head(&chan->sel); + init_waitqueue_head(&chan->readbufq); + init_waitqueue_head(&chan->writebufq); + init_waitqueue_head(&chan->eventbufq); + init_waitqueue_head(&chan->txstateq); + + /* Reset conferences */ + reset_conf(chan); + + /* I/O Mask, etc */ + chan->iomask = 0; + /* release conference resource if any */ + if (chan->confna) zt_check_conf(chan->confna); + if ((chan->sig & __ZT_SIG_DACS) != __ZT_SIG_DACS) { + chan->confna = 0; + chan->confmode = 0; + if (chan->span && chan->span->dacs) + chan->span->dacs(chan, NULL); + } + chan->_confn = 0; + memset(chan->conflast, 0, sizeof(chan->conflast)); + memset(chan->conflast1, 0, sizeof(chan->conflast1)); + memset(chan->conflast2, 0, sizeof(chan->conflast2)); + chan->confmute = 0; + chan->gotgs = 0; + chan->curtone = NULL; + chan->tonep = 0; + chan->pdialcount = 0; + if (chan->gainalloc && chan->rxgain) + rxgain = chan->rxgain; + chan->rxgain = defgain; + chan->txgain = defgain; + chan->gainalloc = 0; + chan->eventinidx = chan->eventoutidx = 0; + zt_set_law(chan,0); + zt_hangup(chan); + + /* Make sure that the audio flag is cleared on a clear channel */ + if ((chan->sig & ZT_SIG_CLEAR) || (chan->sig & ZT_SIG_HARDHDLC)) + chan->flags &= ~ZT_FLAG_AUDIO; + + if ((chan->sig == ZT_SIG_CLEAR) || (chan->sig == ZT_SIG_HARDHDLC)) + chan->flags &= ~(ZT_FLAG_PPP | ZT_FLAG_FCS | ZT_FLAG_HDLC); + + chan->flags &= ~ZT_FLAG_LINEAR; + if (chan->curzone) { + /* Take cadence from tone zone */ + memcpy(chan->ringcadence, chan->curzone->ringcadence, sizeof(chan->ringcadence)); + } else { + /* Do a default */ + memset(chan->ringcadence, 0, sizeof(chan->ringcadence)); + chan->ringcadence[0] = chan->starttime; + chan->ringcadence[1] = ZT_RINGOFFTIME; + } + + spin_unlock_irqrestore(&chan->lock, flags); + set_tone_zone(chan, -1); + + if (chan->span && chan->span->echocan) + chan->span->echocan(chan, 0); + + if (rxgain) + kfree(rxgain); + if (ec) + echo_can_free(ec); + return 0; +} + +static int zt_timing_open(struct inode *inode, struct file *file) +{ + struct zt_timer *t; + unsigned long flags; + t = kmalloc(sizeof(struct zt_timer), GFP_KERNEL); + if (!t) + return -ENOMEM; + /* Allocate a new timer */ + memset(t, 0, sizeof(struct zt_timer)); + init_waitqueue_head(&t->sel); + file->private_data = t; +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#endif + spin_lock_irqsave(&zaptimerlock, flags); + t->next = zaptimers; + zaptimers = t; + spin_unlock_irqrestore(&zaptimerlock, flags); + return 0; +} + +static int zt_timer_release(struct inode *inode, struct file *file) +{ + struct zt_timer *t, *cur, *prev; + unsigned long flags; + t = file->private_data; + if (t) { + spin_lock_irqsave(&zaptimerlock, flags); + prev = NULL; + cur = zaptimers; + while(cur) { + if (t == cur) + break; + prev = cur; + cur = cur->next; + } + if (cur) { + if (prev) + prev->next = cur->next; + else + zaptimers = cur->next; + } + spin_unlock_irqrestore(&zaptimerlock, flags); + if (!cur) { + printk("Zap Timer: Not on list??\n"); + return 0; + } + kfree(t); +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#endif + } + return 0; +} + +static int zt_specchan_open(struct inode *inode, struct file *file, int unit, int inc) +{ + int res = 0; + + if (chans[unit] && chans[unit]->sig) { + /* Make sure we're not already open, a net device, or a slave device */ + if (chans[unit]->flags & ZT_FLAG_OPEN) + res = -EBUSY; + else if (chans[unit]->flags & ZT_FLAG_NETDEV) + res = -EBUSY; + else if (chans[unit]->master != chans[unit]) + res = -EBUSY; + else if ((chans[unit]->sig & __ZT_SIG_DACS) == __ZT_SIG_DACS) + res = -EBUSY; + else { + unsigned long flags; + /* Assume everything is going to be okay */ + res = initialize_channel(chans[unit]); + spin_lock_irqsave(&chans[unit]->lock, flags); + if (chans[unit]->flags & ZT_FLAG_PSEUDO) + chans[unit]->flags |= ZT_FLAG_AUDIO; + if (chans[unit]->span && chans[unit]->span->open) { + res = chans[unit]->span->open(chans[unit]); + } + if (!res) { + chans[unit]->file = file; +#ifndef LINUX26 + if (inc) + MOD_INC_USE_COUNT; +#endif + chans[unit]->flags |= ZT_FLAG_OPEN; + spin_unlock_irqrestore(&chans[unit]->lock, flags); + } else { + spin_unlock_irqrestore(&chans[unit]->lock, flags); + close_channel(chans[unit]); + } + } + } else + res = -ENXIO; + return res; +} + +static int zt_specchan_release(struct inode *node, struct file *file, int unit) +{ + int res=0; + if (chans[unit]) { + unsigned long flags; + spin_lock_irqsave(&chans[unit]->lock, flags); + chans[unit]->flags &= ~ZT_FLAG_OPEN; + spin_unlock_irqrestore(&chans[unit]->lock, flags); + chans[unit]->file = NULL; + close_channel(chans[unit]); + if (chans[unit]->span && chans[unit]->span->close) + res = chans[unit]->span->close(chans[unit]); + } else + res = -ENXIO; +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#endif + return res; +} + +static struct zt_chan *zt_alloc_pseudo(void) +{ + struct zt_chan *pseudo; + unsigned long flags; + /* Don't allow /dev/zap/pseudo to open if there are no spans */ + if (maxspans < 1) + return NULL; + pseudo = kmalloc(sizeof(struct zt_chan), GFP_KERNEL); + if (!pseudo) + return NULL; + memset(pseudo, 0, sizeof(struct zt_chan)); + pseudo->sig = ZT_SIG_CLEAR; + pseudo->sigcap = ZT_SIG_CLEAR; + pseudo->flags = ZT_FLAG_PSEUDO | ZT_FLAG_AUDIO; + spin_lock_irqsave(&bigzaplock, flags); + if (zt_chan_reg(pseudo)) { + kfree(pseudo); + pseudo = NULL; + } else + sprintf(pseudo->name, "Pseudo/%d", pseudo->channo); + spin_unlock_irqrestore(&bigzaplock, flags); + return pseudo; +} + +static void zt_free_pseudo(struct zt_chan *pseudo) +{ + unsigned long flags; + if (pseudo) { + spin_lock_irqsave(&bigzaplock, flags); + zt_chan_unreg(pseudo); + spin_unlock_irqrestore(&bigzaplock, flags); + kfree(pseudo); + } +} + +static int zt_open(struct inode *inode, struct file *file) +{ + int unit = UNIT(file); + int ret = -ENXIO; + struct zt_chan *chan; + /* Minor 0: Special "control" descriptor */ + if (!unit) + return zt_ctl_open(inode, file); + if (unit == 250) { + if (!zt_transcode_fops) + request_module("zttranscode"); + if (zt_transcode_fops && zt_transcode_fops->open) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + if (zt_transcode_fops->owner) { + __MOD_INC_USE_COUNT (zt_transcode_fops->owner); +#else + if (try_module_get(zt_transcode_fops->owner)) { +#endif + ret = zt_transcode_fops->open(inode, file); + if (ret) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + __MOD_DEC_USE_COUNT (zt_transcode_fops->owner); +#else + module_put(zt_transcode_fops->owner); +#endif + } + return ret; + } + return -ENXIO; + } + if (unit == 253) { + if (maxspans) { + return zt_timing_open(inode, file); + } else { + return -ENXIO; + } + } + if (unit == 254) + return zt_chan_open(inode, file); + if (unit == 255) { + if (maxspans) { + chan = zt_alloc_pseudo(); + if (chan) { + file->private_data = chan; + return zt_specchan_open(inode, file, chan->channo, 1); + } else { + return -ENXIO; + } + } else + return -ENXIO; + } + return zt_specchan_open(inode, file, unit, 1); +} + +#if 0 +static int zt_open(struct inode *inode, struct file *file) +{ + int res; + unsigned long flags; + spin_lock_irqsave(&bigzaplock, flags); + res = __zt_open(inode, file); + spin_unlock_irqrestore(&bigzaplock, flags); + return res; +} +#endif + +static ssize_t zt_read(struct file *file, char *usrbuf, size_t count, loff_t *ppos) +{ + int unit = UNIT(file); + struct zt_chan *chan; + + /* Can't read from control */ + if (!unit) { + return -EINVAL; + } + + if (unit == 253) + return -EINVAL; + + if (unit == 254) { + chan = file->private_data; + if (!chan) + return -EINVAL; + return zt_chan_read(file, usrbuf, count, chan->channo); + } + + if (unit == 255) { + chan = file->private_data; + if (!chan) { + printk("No pseudo channel structure to read?\n"); + return -EINVAL; + } + return zt_chan_read(file, usrbuf, count, chan->channo); + } + if (count < 0) + return -EINVAL; + + return zt_chan_read(file, usrbuf, count, unit); +} + +static ssize_t zt_write(struct file *file, const char *usrbuf, size_t count, loff_t *ppos) +{ + int unit = UNIT(file); + struct zt_chan *chan; + /* Can't read from control */ + if (!unit) + return -EINVAL; + if (count < 0) + return -EINVAL; + if (unit == 253) + return -EINVAL; + if (unit == 254) { + chan = file->private_data; + if (!chan) + return -EINVAL; + return zt_chan_write(file, usrbuf, count, chan->channo); + } + if (unit == 255) { + chan = file->private_data; + if (!chan) { + printk("No pseudo channel structure to read?\n"); + return -EINVAL; + } + return zt_chan_write(file, usrbuf, count, chan->channo); + } + return zt_chan_write(file, usrbuf, count, unit); + +} + +/* No bigger than 32k for everything per tone zone */ +#define MAX_SIZE 32768 +/* No more than 128 subtones */ +#define MAX_TONES 128 + +/* The tones to be loaded can (will) be a mix of regular tones, + DTMF tones and MF tones. We need to load DTMF and MF tones + a bit differently than regular tones because their storage + format is much simpler (an array structure field of the zone + structure, rather an array of pointers). +*/ +static int ioctl_load_zone(unsigned long data) +{ + struct zt_tone *samples[MAX_TONES] = { NULL, }; + short next[MAX_TONES] = { 0, }; + struct zt_tone_def_header th; + struct zt_tone_def td; + struct zt_zone *z; + struct zt_tone *t; + void *slab, *ptr; + int x; + size_t space; + size_t size; + int res; + + if (copy_from_user(&th, (struct zt_tone_def_header *) data, sizeof(th))) + return -EFAULT; + + data += sizeof(th); + + if ((th.count < 0) || (th.count > MAX_TONES)) { + printk("Too many tones included\n"); + return -EINVAL; + } + + space = size = sizeof(*z) + th.count * sizeof(*t); + + if (size > MAX_SIZE) + return -E2BIG; + + if (!(z = ptr = slab = kmalloc(size, GFP_KERNEL))) + return -ENOMEM; + + memset(slab, 0, size); + + ptr += sizeof(*z); + space -= sizeof(*z); + + strncpy(z->name, th.name, sizeof(z->name) - 1); + + for (x = 0; x < ZT_MAX_CADENCE; x++) + z->ringcadence[x] = th.ringcadence[x]; + + atomic_set(&z->refcount, 0); + + for (x = 0; x < th.count; x++) { + enum { + REGULAR_TONE, + DTMF_TONE, + MF_TONE, + } tone_type; + + if (space < sizeof(*t)) { + kfree(slab); + printk("Insufficient tone zone space\n"); + return -EINVAL; + } + + if (copy_from_user(&td, (struct zt_tone_def *) data, sizeof(td))) { + kfree(slab); + return -EFAULT; + } + + data += sizeof(td); + + if ((td.tone >= 0) && (td.tone < ZT_TONE_MAX)) { + tone_type = REGULAR_TONE; + + t = samples[x] = ptr; + + space -= sizeof(*t); + ptr += sizeof(*t); + + /* Remember which sample is next */ + next[x] = td.next; + + /* Make sure the "next" one is sane */ + if ((next[x] >= th.count) || (next[x] < 0)) { + printk("Invalid 'next' pointer: %d\n", next[x]); + kfree(slab); + return -EINVAL; + } + } else if ((td.tone >= ZT_TONE_DTMF_BASE) && + (td.tone <= ZT_TONE_DTMF_MAX)) { + tone_type = DTMF_TONE; + + td.tone -= ZT_TONE_DTMF_BASE; + t = &z->dtmf[td.tone]; + } else if ((td.tone >= ZT_TONE_MF_BASE) && + (td.tone <= ZT_TONE_MF_MAX)) { + tone_type = MF_TONE; + + td.tone -= ZT_TONE_MF_BASE; + t = &z->mf[td.tone]; + } else { + printk("Invalid tone (%d) defined\n", td.tone); + kfree(slab); + return -EINVAL; + } + + t->fac1 = td.fac1; + t->init_v2_1 = td.init_v2_1; + t->init_v3_1 = td.init_v3_1; + t->fac2 = td.fac2; + t->init_v2_2 = td.init_v2_2; + t->init_v3_2 = td.init_v3_2; + t->modulate = td.modulate; + + switch (tone_type) { + case REGULAR_TONE: + t->tonesamples = td.samples; + if (!z->tones[td.tone]) + z->tones[td.tone] = t; + break; + case DTMF_TONE: + t->tonesamples = global_dialparams.dtmf_tonelen; + t->next = &dtmf_silence; + z->dtmf_continuous[td.tone] = *t; + z->dtmf_continuous[td.tone].next = &z->dtmf_continuous[td.tone]; + break; + case MF_TONE: + t->tonesamples = global_dialparams.mfv1_tonelen; + t->next = &mfv1_silence; + /* Special case for K/P tone */ + if (td.tone == 10) + t->tonesamples *= 5 / 3; + z->mf_continuous[td.tone] = *t; + z->mf_continuous[td.tone].next = &z->mf_continuous[td.tone]; + break; + } + } + + for (x = 0; x < th.count; x++) { + if (samples[x]) + samples[x]->next = samples[next[x]]; + } + + if ((res = zt_register_tone_zone(th.zone, z))) + kfree(slab); + + return res; +} + +void zt_init_tone_state(struct zt_tone_state *ts, struct zt_tone *zt) +{ + ts->v1_1 = 0; + ts->v2_1 = zt->init_v2_1; + ts->v3_1 = zt->init_v3_1; + ts->v1_2 = 0; + ts->v2_2 = zt->init_v2_2; + ts->v3_2 = zt->init_v3_2; + ts->modulate = zt->modulate; +} + +struct zt_tone *zt_dtmf_tone(const struct zt_chan *chan, char digit) +{ + struct zt_tone *z; + + switch (chan->digitmode) { + case DIGIT_MODE_DTMF: + z = &chan->curzone->dtmf[0]; + break; + case DIGIT_MODE_MFV1: + z = &chan->curzone->mf[0]; + break; + default: + z = NULL; + } + + switch (digit) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return z + (digit - '0'); + case '*': + return z + 10; + case '#': + return z + 11; + case 'A': + case 'B': + case 'C': + return z + (digit + 12 - 'A'); + case 'D': + if (chan->digitmode == DIGIT_MODE_MFV1) + return NULL; + else + return z + (digit + 12 - 'A'); + case 'W': + return &tone_pause; + } + + return NULL; +} + +static void __do_dtmf(struct zt_chan *chan) +{ + char c; + + /* Called with chan->lock held */ + while ((c = chan->txdialbuf[0])) { + memmove(chan->txdialbuf, chan->txdialbuf + 1, sizeof(chan->txdialbuf) - 1); + switch (c) { + case 'T': + chan->digitmode = DIGIT_MODE_DTMF; + chan->tonep = 0; + break; + case 'M': + chan->digitmode = DIGIT_MODE_MFV1; + chan->tonep = 0; + break; + case 'P': + chan->digitmode = DIGIT_MODE_PULSE; + chan->tonep = 0; + break; + default: + if ((c != 'W') && (chan->digitmode == DIGIT_MODE_PULSE)) { + if ((c >= '0') && (c <= '9') && (chan->txhooksig == ZT_TXSIG_OFFHOOK)) { + chan->pdialcount = (c == '0') ? 10 : c - '0'; + zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_PULSEBREAK, + chan->pulsebreaktime); + return; + } + } else { + chan->curtone = zt_dtmf_tone(chan, c); + chan->tonep = 0; + if (chan->curtone) { + zt_init_tone_state(&chan->ts, chan->curtone); + return; + } + } + } + } + + /* Notify userspace process if there is nothing left */ + chan->dialing = 0; + __qevent(chan, ZT_EVENT_DIALCOMPLETE); +} + +static int zt_release(struct inode *inode, struct file *file) +{ + int unit = UNIT(file); + int res; + struct zt_chan *chan; + + if (!unit) + return zt_ctl_release(inode, file); + if (unit == 253) { + return zt_timer_release(inode, file); + } + if (unit == 250) { + res = zt_transcode_fops->release(inode, file); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + if (zt_transcode_fops->owner) + __MOD_DEC_USE_COUNT (zt_transcode_fops->owner); +#else + module_put(zt_transcode_fops->owner); +#endif + return res; + } + if (unit == 254) { + chan = file->private_data; + if (!chan) + return zt_chan_release(inode, file); + else + return zt_specchan_release(inode, file, chan->channo); + } + if (unit == 255) { + chan = file->private_data; + if (chan) { + res = zt_specchan_release(inode, file, chan->channo); + zt_free_pseudo(chan); + } else { + printk("Pseudo release and no private data??\n"); + res = 0; + } + return res; + } + return zt_specchan_release(inode, file, unit); +} + +#if 0 +static int zt_release(struct inode *inode, struct file *file) +{ + /* Lock the big zap lock when handling a release */ + unsigned long flags; + int res; + spin_lock_irqsave(&bigzaplock, flags); + res = __zt_release(inode, file); + spin_unlock_irqrestore(&bigzaplock, flags); + return res; +} +#endif + + +void zt_alarm_channel(struct zt_chan *chan, int alarms) +{ + unsigned long flags; + + spin_lock_irqsave(&chan->lock, flags); + if (chan->chan_alarms != alarms) { + chan->chan_alarms = alarms; + zt_qevent_nolock(chan, alarms ? ZT_EVENT_ALARM : ZT_EVENT_NOALARM); + } + spin_unlock_irqrestore(&chan->lock, flags); +} + +void zt_alarm_notify(struct zt_span *span) +{ + int x; + + span->alarms &= ~ZT_ALARM_LOOPBACK; + /* Determine maint status */ + if (span->maintstat || span->mainttimer) + span->alarms |= ZT_ALARM_LOOPBACK; + /* DON'T CHANGE THIS AGAIN. THIS WAS DONE FOR A REASON. + The expression (a != b) does *NOT* do the same thing + as ((!a) != (!b)) */ + /* if change in general state */ + if ((!span->alarms) != (!span->lastalarms)) { + span->lastalarms = span->alarms; + for (x = 0; x < span->channels; x++) + zt_alarm_channel(&span->chans[x], span->alarms); + /* Switch to other master if current master in alarm */ + for (x=1; xalarms && (spans[x]->flags & ZT_FLAG_RUNNING)) { + if(master != spans[x]) + printk("Zaptel: Master changed to %s\n", spans[x]->name); + master = spans[x]; + break; + } + } + } +} + +#define VALID_SPAN(j) do { \ + if ((j >= ZT_MAX_SPANS) || (j < 1)) \ + return -EINVAL; \ + if (!spans[j]) \ + return -ENXIO; \ +} while(0) + +#define CHECK_VALID_SPAN(j) do { \ + /* Start a given span */ \ + if (get_user(j, (int *)data)) \ + return -EFAULT; \ + VALID_SPAN(j); \ +} while(0) + +#define VALID_CHANNEL(j) do { \ + if ((j >= ZT_MAX_CHANNELS) || (j < 1)) \ + return -EINVAL; \ + if (!chans[j]) \ + return -ENXIO; \ +} while(0) + +static int zt_timer_ioctl(struct inode *node, struct file *file, unsigned int cmd, unsigned long data, struct zt_timer *timer) +{ + int j; + unsigned long flags; + switch(cmd) { + case ZT_TIMERCONFIG: + get_user(j, (int *)data); + if (j < 0) + j = 0; + spin_lock_irqsave(&zaptimerlock, flags); + timer->ms = timer->pos = j; + spin_unlock_irqrestore(&zaptimerlock, flags); + break; + case ZT_TIMERACK: + get_user(j, (int *)data); + spin_lock_irqsave(&zaptimerlock, flags); + if ((j < 1) || (j > timer->tripped)) + j = timer->tripped; + timer->tripped -= j; + spin_unlock_irqrestore(&zaptimerlock, flags); + break; + case ZT_GETEVENT: /* Get event on queue */ + j = ZT_EVENT_NONE; + spin_lock_irqsave(&zaptimerlock, flags); + /* set up for no event */ + if (timer->tripped) + j = ZT_EVENT_TIMER_EXPIRED; + if (timer->ping) + j = ZT_EVENT_TIMER_PING; + spin_unlock_irqrestore(&zaptimerlock, flags); + put_user(j,(int *)data); + break; + case ZT_TIMERPING: + spin_lock_irqsave(&zaptimerlock, flags); + timer->ping = 1; + wake_up_interruptible(&timer->sel); + spin_unlock_irqrestore(&zaptimerlock, flags); + break; + case ZT_TIMERPONG: + spin_lock_irqsave(&zaptimerlock, flags); + timer->ping = 0; + spin_unlock_irqrestore(&zaptimerlock, flags); + break; + default: + return -ENOTTY; + } + return 0; +} + +static int zt_common_ioctl(struct inode *node, struct file *file, unsigned int cmd, unsigned long data, int unit) +{ + union { + struct zt_gains gain; + struct zt_spaninfo spaninfo; + struct zt_params param; + } stack; + struct zt_chan *chan; + unsigned long flags; + unsigned char *txgain, *rxgain; + struct zt_chan *mychan; + int i,j; + int return_master = 0; + size_t size_to_copy; + + switch(cmd) { + /* get channel parameters */ + case ZT_GET_PARAMS_V1: + case ZT_GET_PARAMS: + size_to_copy = (cmd == ZT_GET_PARAMS_V1) ? sizeof(struct zt_params_v1) : + sizeof(struct zt_params); + if (copy_from_user(&stack.param, (struct zt_params *) data, size_to_copy)) + return -EFAULT; + + /* check to see if the caller wants to receive our master channel number */ + if (stack.param.channo & ZT_GET_PARAMS_RETURN_MASTER) { + return_master = 1; + stack.param.channo &= ~ZT_GET_PARAMS_RETURN_MASTER; + } + + /* Pick the right channo's */ + if (!stack.param.channo || unit) { + stack.param.channo = unit; + } + /* Check validity of channel */ + VALID_CHANNEL(stack.param.channo); + chan = chans[stack.param.channo]; + + /* point to relevant structure */ + stack.param.sigtype = chan->sig; /* get signalling type */ + /* return non-zero if rx not in idle state */ + if (chan->span) { + j = zt_q_sig(chan); + if (j >= 0) { /* if returned with success */ + stack.param.rxisoffhook = ((chan->rxsig & (j >> 8)) != (j & 0xff)); + } else { + stack.param.rxisoffhook = ((chan->rxhooksig != ZT_RXSIG_ONHOOK) && + (chan->rxhooksig != ZT_RXSIG_INITIAL)); + } + } else if ((chan->txstate == ZT_TXSTATE_KEWL) || (chan->txstate == ZT_TXSTATE_AFTERKEWL)) + stack.param.rxisoffhook = 1; + else + stack.param.rxisoffhook = 0; + if (chan->span && chan->span->rbsbits && !(chan->sig & ZT_SIG_CLEAR)) { + stack.param.rxbits = chan->rxsig; + stack.param.txbits = chan->txsig; + stack.param.idlebits = chan->idlebits; + } else { + stack.param.rxbits = -1; + stack.param.txbits = -1; + stack.param.idlebits = 0; + } + if (chan->span && (chan->span->rbsbits || chan->span->hooksig) && + !(chan->sig & ZT_SIG_CLEAR)) { + stack.param.rxhooksig = chan->rxhooksig; + stack.param.txhooksig = chan->txhooksig; + } else { + stack.param.rxhooksig = -1; + stack.param.txhooksig = -1; + } + stack.param.prewinktime = chan->prewinktime; + stack.param.preflashtime = chan->preflashtime; + stack.param.winktime = chan->winktime; + stack.param.flashtime = chan->flashtime; + stack.param.starttime = chan->starttime; + stack.param.rxwinktime = chan->rxwinktime; + stack.param.rxflashtime = chan->rxflashtime; + stack.param.debouncetime = chan->debouncetime; + stack.param.channo = chan->channo; + stack.param.chan_alarms = chan->chan_alarms; + + /* if requested, put the master channel number in the top 16 bits of the result */ + if (return_master) + stack.param.channo |= chan->master->channo << 16; + + stack.param.pulsemaketime = chan->pulsemaketime; + stack.param.pulsebreaktime = chan->pulsebreaktime; + stack.param.pulseaftertime = chan->pulseaftertime; + if (chan->span) stack.param.spanno = chan->span->spanno; + else stack.param.spanno = 0; + strncpy(stack.param.name, chan->name, sizeof(stack.param.name) - 1); + stack.param.chanpos = chan->chanpos; + stack.param.sigcap = chan->sigcap; + /* Return current law */ + if (chan->xlaw == __zt_alaw) + stack.param.curlaw = ZT_LAW_ALAW; + else + stack.param.curlaw = ZT_LAW_MULAW; + + if (copy_to_user((struct zt_params *) data, &stack.param, size_to_copy)) + return -EFAULT; + + break; + /* set channel parameters */ + case ZT_SET_PARAMS_V1: + case ZT_SET_PARAMS: + /* The difference between zt_params and zt_params_v1 is just the + * last field, which is read-only anyway. Thus we just read the + * size of the older struct. + */ + if (copy_from_user(&stack.param, (struct zt_params *) data, sizeof(struct zt_params_v1))) + return -EFAULT; + + stack.param.chan_alarms = 0; /* be explicit about the above */ + + /* Pick the right channo's */ + if (!stack.param.channo || unit) { + stack.param.channo = unit; + } + /* Check validity of channel */ + VALID_CHANNEL(stack.param.channo); + chan = chans[stack.param.channo]; + /* point to relevant structure */ + /* NOTE: sigtype is *not* included in this */ + /* get timing stack.paramters */ + chan->prewinktime = stack.param.prewinktime; + chan->preflashtime = stack.param.preflashtime; + chan->winktime = stack.param.winktime; + chan->flashtime = stack.param.flashtime; + chan->starttime = stack.param.starttime; + /* Update ringtime if not using a tone zone */ + if (!chan->curzone) + chan->ringcadence[0] = chan->starttime; + chan->rxwinktime = stack.param.rxwinktime; + chan->rxflashtime = stack.param.rxflashtime; + chan->debouncetime = stack.param.debouncetime; + chan->pulsemaketime = stack.param.pulsemaketime; + chan->pulsebreaktime = stack.param.pulsebreaktime; + chan->pulseaftertime = stack.param.pulseaftertime; + break; + case ZT_GETGAINS: /* get gain stuff */ + if (copy_from_user(&stack.gain,(struct zt_gains *) data,sizeof(stack.gain))) + return -EFAULT; + i = stack.gain.chan; /* get channel no */ + /* if zero, use current channel no */ + if (!i) i = unit; + /* make sure channel number makes sense */ + if ((i < 0) || (i > ZT_MAX_CHANNELS) || !chans[i]) return(-EINVAL); + + if (!(chans[i]->flags & ZT_FLAG_AUDIO)) return (-EINVAL); + stack.gain.chan = i; /* put the span # in here */ + for (j=0;j<256;j++) { + stack.gain.txgain[j] = chans[i]->txgain[j]; + stack.gain.rxgain[j] = chans[i]->rxgain[j]; + } + if (copy_to_user((struct zt_gains *) data,&stack.gain,sizeof(stack.gain))) + return -EFAULT; + break; + case ZT_SETGAINS: /* set gain stuff */ + if (copy_from_user(&stack.gain,(struct zt_gains *) data,sizeof(stack.gain))) + return -EFAULT; + i = stack.gain.chan; /* get channel no */ + /* if zero, use current channel no */ + if (!i) i = unit; + /* make sure channel number makes sense */ + if ((i < 0) || (i > ZT_MAX_CHANNELS) || !chans[i]) return(-EINVAL); + if (!(chans[i]->flags & ZT_FLAG_AUDIO)) return (-EINVAL); + + rxgain = kmalloc(512, GFP_KERNEL); + if (!rxgain) + return -ENOMEM; + + stack.gain.chan = i; /* put the span # in here */ + txgain = rxgain + 256; + + for (j=0;j<256;j++) { + rxgain[j] = stack.gain.rxgain[j]; + txgain[j] = stack.gain.txgain[j]; + } + + if (!memcmp(rxgain, defgain, 256) && + !memcmp(txgain, defgain, 256)) { + if (rxgain) + kfree(rxgain); + spin_lock_irqsave(&chans[i]->lock, flags); + if (chans[i]->gainalloc) + kfree(chans[i]->rxgain); + chans[i]->gainalloc = 0; + chans[i]->rxgain = defgain; + chans[i]->txgain = defgain; + spin_unlock_irqrestore(&chans[i]->lock, flags); + } else { + /* This is a custom gain setting */ + spin_lock_irqsave(&chans[i]->lock, flags); + if (chans[i]->gainalloc) + kfree(chans[i]->rxgain); + chans[i]->gainalloc = 1; + chans[i]->rxgain = rxgain; + chans[i]->txgain = txgain; + spin_unlock_irqrestore(&chans[i]->lock, flags); + } + if (copy_to_user((struct zt_gains *) data,&stack.gain,sizeof(stack.gain))) + return -EFAULT; + break; + case ZT_SPANSTAT_V1: + case ZT_SPANSTAT_V2: + case ZT_SPANSTAT: + size_to_copy = (cmd == ZT_SPANSTAT_V1) ? sizeof(struct zt_spaninfo_v1) : + (cmd == ZT_SPANSTAT_V2) ? sizeof(struct zt_spaninfo_v2) : + sizeof(struct zt_spaninfo); + if (copy_from_user(&stack.spaninfo, (struct zt_spaninfo *) data, size_to_copy)) + return -EFAULT; + i = stack.spaninfo.spanno; /* get specified span number */ + if ((i < 0) || (i >= maxspans)) return(-EINVAL); /* if bad span no */ + if (i == 0) { + /* if to figure it out for this chan */ + if (!chans[unit]) + return -EINVAL; + i = chans[unit]->span->spanno; + } + if (!spans[i]) + return -EINVAL; + stack.spaninfo.spanno = i; /* put the span # in here */ + stack.spaninfo.totalspans = 0; + if (maxspans) stack.spaninfo.totalspans = maxspans - 1; /* put total number of spans here */ + strncpy(stack.spaninfo.desc, spans[i]->desc, sizeof(stack.spaninfo.desc) - 1); + strncpy(stack.spaninfo.name, spans[i]->name, sizeof(stack.spaninfo.name) - 1); + stack.spaninfo.alarms = spans[i]->alarms; /* get alarm status */ + stack.spaninfo.bpvcount = spans[i]->bpvcount; /* get BPV count */ + stack.spaninfo.rxlevel = spans[i]->rxlevel; /* get rx level */ + stack.spaninfo.txlevel = spans[i]->txlevel; /* get tx level */ + stack.spaninfo.crc4count = spans[i]->crc4count; /* get CRC4 error count */ + stack.spaninfo.ebitcount = spans[i]->ebitcount; /* get E-bit error count */ + stack.spaninfo.fascount = spans[i]->fascount; /* get FAS error count */ + stack.spaninfo.irqmisses = spans[i]->irqmisses; /* get IRQ miss count */ + stack.spaninfo.syncsrc = spans[i]->syncsrc; /* get active sync source */ + stack.spaninfo.totalchans = spans[i]->channels; + stack.spaninfo.numchans = 0; + for (j = 0; j < spans[i]->channels; j++) { + if (spans[i]->chans[j].sig) + stack.spaninfo.numchans++; + } + /* version 2 fields */ + stack.spaninfo.lbo = spans[i]->lbo; + stack.spaninfo.lineconfig = spans[i]->lineconfig; + /* version 3 fields */ + stack.spaninfo.irq = spans[i]->irq; + stack.spaninfo.linecompat = spans[i]->linecompat; + strncpy(stack.spaninfo.lboname, zt_lboname(spans[i]->lbo), sizeof(stack.spaninfo.lboname) - 1); + if (spans[i]->manufacturer) + strncpy(stack.spaninfo.manufacturer, spans[i]->manufacturer, + sizeof(stack.spaninfo.manufacturer) - 1); + if (spans[i]->devicetype) + strncpy(stack.spaninfo.devicetype, spans[i]->devicetype, sizeof(stack.spaninfo.devicetype) - 1); + strncpy(stack.spaninfo.location, spans[i]->location, sizeof(stack.spaninfo.location) - 1); + if (spans[i]->spantype) + strncpy(stack.spaninfo.spantype, spans[i]->spantype, sizeof(stack.spaninfo.spantype) - 1); + + if (copy_to_user((struct zt_spaninfo *) data, &stack.spaninfo, size_to_copy)) + return -EFAULT; + break; + case ZT_CHANDIAG: + get_user(j, (int *)data); /* get channel number from user */ + /* make sure its a valid channel number */ + if ((j < 1) || (j >= maxchans)) + return -EINVAL; + /* if channel not mapped, not there */ + if (!chans[j]) + return -EINVAL; + + if (!(mychan = kmalloc(sizeof(*mychan), GFP_KERNEL))) + return -ENOMEM; + + /* lock channel */ + spin_lock_irqsave(&chans[j]->lock, flags); + /* make static copy of channel */ + memcpy(mychan, chans[j], sizeof(*mychan)); + /* release it. */ + spin_unlock_irqrestore(&chans[j]->lock, flags); + + printk(KERN_INFO "Dump of Zaptel Channel %d (%s,%d,%d):\n\n",j, + mychan->name,mychan->channo,mychan->chanpos); + printk(KERN_INFO "flags: %x hex, writechunk: %08lx, readchunk: %08lx\n", + mychan->flags, (long) mychan->writechunk, (long) mychan->readchunk); + printk(KERN_INFO "rxgain: %08lx, txgain: %08lx, gainalloc: %d\n", + (long) mychan->rxgain, (long)mychan->txgain, mychan->gainalloc); + printk(KERN_INFO "span: %08lx, sig: %x hex, sigcap: %x hex\n", + (long)mychan->span, mychan->sig, mychan->sigcap); + printk(KERN_INFO "inreadbuf: %d, outreadbuf: %d, inwritebuf: %d, outwritebuf: %d\n", + mychan->inreadbuf, mychan->outreadbuf, mychan->inwritebuf, mychan->outwritebuf); + printk(KERN_INFO "blocksize: %d, numbufs: %d, txbufpolicy: %d, txbufpolicy: %d\n", + mychan->blocksize, mychan->numbufs, mychan->txbufpolicy, mychan->rxbufpolicy); + printk(KERN_INFO "txdisable: %d, rxdisable: %d, iomask: %d\n", + mychan->txdisable, mychan->rxdisable, mychan->iomask); + printk(KERN_INFO "curzone: %08lx, tonezone: %d, curtone: %08lx, tonep: %d\n", + (long) mychan->curzone, mychan->tonezone, (long) mychan->curtone, mychan->tonep); + printk(KERN_INFO "digitmode: %d, txdialbuf: %s, dialing: %d, aftdialtimer: %d, cadpos. %d\n", + mychan->digitmode, mychan->txdialbuf, mychan->dialing, + mychan->afterdialingtimer, mychan->cadencepos); + printk(KERN_INFO "confna: %d, confn: %d, confmode: %d, confmute: %d\n", + mychan->confna, mychan->_confn, mychan->confmode, mychan->confmute); + printk(KERN_INFO "ec: %08lx, echocancel: %d, deflaw: %d, xlaw: %08lx\n", + (long) mychan->ec, mychan->echocancel, mychan->deflaw, (long) mychan->xlaw); + printk(KERN_INFO "echostate: %02x, echotimer: %d, echolastupdate: %d\n", + (int) mychan->echostate, mychan->echotimer, mychan->echolastupdate); + printk(KERN_INFO "itimer: %d, otimer: %d, ringdebtimer: %d\n\n", + mychan->itimer, mychan->otimer, mychan->ringdebtimer); +#if 0 + if (mychan->ec) { + int x; + /* Dump the echo canceller parameters */ + for (x=0;xec->taps;x++) { + printk(KERN_INFO "tap %d: %d\n", x, mychan->ec->fir_taps[x]); + } + } +#endif + kfree(mychan); + break; + default: + return -ENOTTY; + } + return 0; +} + +static int (*zt_dynamic_ioctl)(unsigned int cmd, unsigned long data); + +void zt_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data)) +{ + zt_dynamic_ioctl = func; +} + +static void recalc_slaves(struct zt_chan *chan) +{ + int x; + struct zt_chan *last = chan; + + /* Makes no sense if you don't have a span */ + if (!chan->span) + return; + +#ifdef CONFIG_ZAPATA_DEBUG + printk("Recalculating slaves on %s\n", chan->name); +#endif + + /* Link all slaves appropriately */ + for (x=chan->chanpos;xspan->channels;x++) + if (chan->span->chans[x].master == chan) { +#ifdef CONFIG_ZAPATA_DEBUG + printk("Channel %s, slave to %s, last is %s, its next will be %d\n", + chan->span->chans[x].name, chan->name, last->name, x); +#endif + last->nextslave = x; + last = &chan->span->chans[x]; + } + /* Terminate list */ + last->nextslave = 0; +#ifdef CONFIG_ZAPATA_DEBUG + printk("Done Recalculating slaves on %s (last is %s)\n", chan->name, last->name); +#endif +} + +static int zt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data) +{ + /* I/O CTL's for control interface */ + int i,j; + struct zt_lineconfig lc; + struct zt_chanconfig ch; + struct zt_sfconfig sf; + int sigcap; + int res = 0; + int x,y; + struct zt_chan *newmaster; + struct zt_dialparams tdp; + struct zt_maintinfo maint; + struct zt_indirect_data ind; + struct zt_versioninfo vi; + unsigned long flags; + int rv; + switch(cmd) { + case ZT_INDIRECT: + if (copy_from_user(&ind, (struct zt_indirect_data *)data, sizeof(ind))) + return -EFAULT; + VALID_CHANNEL(ind.chan); + return zt_chan_ioctl(inode, file, ind.op, (unsigned long) ind.data, ind.chan); + case ZT_SPANCONFIG: + if (copy_from_user(&lc, (struct zt_lineconfig *)data, sizeof(lc))) + return -EFAULT; + VALID_SPAN(lc.span); + if ((lc.lineconfig & 0x07f0 & spans[lc.span]->linecompat) != (lc.lineconfig & 0x07f0)) + return -EINVAL; + if (spans[lc.span]->spanconfig) { + spans[lc.span]->lineconfig = lc.lineconfig; + spans[lc.span]->lbo = lc.lbo; + spans[lc.span]->txlevel = lc.lbo; + spans[lc.span]->rxlevel = 0; + + return spans[lc.span]->spanconfig(spans[lc.span], &lc); + } + return 0; + case ZT_STARTUP: + CHECK_VALID_SPAN(j); + if (spans[j]->flags & ZT_FLAG_RUNNING) + return 0; + if (spans[j]->startup) + res = spans[j]->startup(spans[j]); + if (!res) { + /* Mark as running and hangup any channels */ + spans[j]->flags |= ZT_FLAG_RUNNING; + for (x=0;xchannels;x++) { + y = zt_q_sig(&spans[j]->chans[x]) & 0xff; + if (y >= 0) spans[j]->chans[x].rxsig = (unsigned char)y; + spin_lock_irqsave(&spans[j]->chans[x].lock, flags); + zt_hangup(&spans[j]->chans[x]); + spin_unlock_irqrestore(&spans[j]->chans[x].lock, flags); + spans[j]->chans[x].rxhooksig = ZT_RXSIG_INITIAL; + } + } + return 0; + case ZT_SHUTDOWN: + CHECK_VALID_SPAN(j); + if (spans[j]->shutdown) + res = spans[j]->shutdown(spans[j]); + spans[j]->flags &= ~ZT_FLAG_RUNNING; + return 0; + case ZT_CHANCONFIG: + if (copy_from_user(&ch, (struct zt_chanconfig *)data, sizeof(ch))) + return -EFAULT; + VALID_CHANNEL(ch.chan); + if (ch.sigtype == ZT_SIG_SLAVE) { + /* We have to use the master's sigtype */ + if ((ch.master < 1) || (ch.master >= ZT_MAX_CHANNELS)) + return -EINVAL; + if (!chans[ch.master]) + return -EINVAL; + ch.sigtype = chans[ch.master]->sig; + newmaster = chans[ch.master]; + } else if ((ch.sigtype & __ZT_SIG_DACS) == __ZT_SIG_DACS) { + newmaster = chans[ch.chan]; + if ((ch.idlebits < 1) || (ch.idlebits >= ZT_MAX_CHANNELS)) + return -EINVAL; + if (!chans[ch.idlebits]) + return -EINVAL; + } else { + newmaster = chans[ch.chan]; + } + spin_lock_irqsave(&chans[ch.chan]->lock, flags); +#ifdef CONFIG_ZAPATA_NET + if (chans[ch.chan]->flags & ZT_FLAG_NETDEV) { + if (ztchan_to_dev(chans[ch.chan])->flags & IFF_UP) { + spin_unlock_irqrestore(&chans[ch.chan]->lock, flags); + printk(KERN_WARNING "Can't switch HDLC net mode on channel %s, since current interface is up\n", chans[ch.chan]->name); + return -EBUSY; + } +#ifdef LINUX26 + spin_unlock_irqrestore(&chans[ch.chan]->lock, flags); + unregister_hdlc_device(chans[ch.chan]->hdlcnetdev->netdev); + spin_lock_irqsave(&chans[ch.chan]->lock, flags); + free_netdev(chans[ch.chan]->hdlcnetdev->netdev); +#else + unregister_hdlc_device(&chans[ch.chan]->hdlcnetdev->netdev); +#endif + kfree(chans[ch.chan]->hdlcnetdev); + chans[ch.chan]->hdlcnetdev = NULL; + chans[ch.chan]->flags &= ~ZT_FLAG_NETDEV; + } +#else + if (ch.sigtype == ZT_SIG_HDLCNET) { + spin_unlock_irqrestore(&chans[ch.chan]->lock, flags); + printk(KERN_WARNING "Zaptel networking not supported by this build.\n"); + return -ENOSYS; + } +#endif + sigcap = chans[ch.chan]->sigcap; + /* If they support clear channel, then they support the HDLC and such through + us. */ + if (sigcap & ZT_SIG_CLEAR) + sigcap |= (ZT_SIG_HDLCRAW | ZT_SIG_HDLCFCS | ZT_SIG_HDLCNET | ZT_SIG_DACS); + + if ((sigcap & ch.sigtype) != ch.sigtype) + res = -EINVAL; + + if (!res && chans[ch.chan]->span->chanconfig) + res = chans[ch.chan]->span->chanconfig(chans[ch.chan], ch.sigtype); + if (chans[ch.chan]->master) { + /* Clear the master channel */ + recalc_slaves(chans[ch.chan]->master); + chans[ch.chan]->nextslave = 0; + } + if (!res) { + chans[ch.chan]->sig = ch.sigtype; + if (chans[ch.chan]->sig == ZT_SIG_CAS) + chans[ch.chan]->idlebits = ch.idlebits; + else + chans[ch.chan]->idlebits = 0; + if ((ch.sigtype & ZT_SIG_CLEAR) == ZT_SIG_CLEAR) { + /* Set clear channel flag if appropriate */ + chans[ch.chan]->flags &= ~ZT_FLAG_AUDIO; + chans[ch.chan]->flags |= ZT_FLAG_CLEAR; + } else { + /* Set audio flag and not clear channel otherwise */ + chans[ch.chan]->flags |= ZT_FLAG_AUDIO; + chans[ch.chan]->flags &= ~ZT_FLAG_CLEAR; + } + if ((ch.sigtype & ZT_SIG_HDLCRAW) == ZT_SIG_HDLCRAW) { + /* Set the HDLC flag */ + chans[ch.chan]->flags |= ZT_FLAG_HDLC; + } else { + /* Clear the HDLC flag */ + chans[ch.chan]->flags &= ~ZT_FLAG_HDLC; + } + if ((ch.sigtype & ZT_SIG_HDLCFCS) == ZT_SIG_HDLCFCS) { + /* Set FCS to be calculated if appropriate */ + chans[ch.chan]->flags |= ZT_FLAG_FCS; + } else { + /* Clear FCS flag */ + chans[ch.chan]->flags &= ~ZT_FLAG_FCS; + } + if ((ch.sigtype & __ZT_SIG_DACS) == __ZT_SIG_DACS) { + /* Setup conference properly */ + chans[ch.chan]->confmode = ZT_CONF_DIGITALMON; + chans[ch.chan]->confna = ch.idlebits; + if (chans[ch.chan]->span && + chans[ch.chan]->span->dacs && + chans[ch.idlebits] && + chans[ch.chan]->span && + (chans[ch.chan]->span->dacs == chans[ch.idlebits]->span->dacs)) + chans[ch.chan]->span->dacs(chans[ch.chan], chans[ch.idlebits]); + } else if (chans[ch.chan]->span && chans[ch.chan]->span->dacs) + chans[ch.chan]->span->dacs(chans[ch.chan], NULL); + chans[ch.chan]->master = newmaster; + /* Note new slave if we are not our own master */ + if (newmaster != chans[ch.chan]) { + recalc_slaves(chans[ch.chan]->master); + } + if ((ch.sigtype & ZT_SIG_HARDHDLC) == ZT_SIG_HARDHDLC) { + chans[ch.chan]->flags &= ~ZT_FLAG_FCS; + chans[ch.chan]->flags &= ~ZT_FLAG_HDLC; + chans[ch.chan]->flags |= ZT_FLAG_NOSTDTXRX; + } else + chans[ch.chan]->flags &= ~ZT_FLAG_NOSTDTXRX; + } +#ifdef CONFIG_ZAPATA_NET + if (!res && + (newmaster == chans[ch.chan]) && + (chans[ch.chan]->sig == ZT_SIG_HDLCNET)) { + chans[ch.chan]->hdlcnetdev = zt_hdlc_alloc(); + if (chans[ch.chan]->hdlcnetdev) { +/* struct hdlc_device *hdlc = chans[ch.chan]->hdlcnetdev; + struct net_device *d = hdlc_to_dev(hdlc); mmm...get it right later --byg */ +#ifdef LINUX26 + chans[ch.chan]->hdlcnetdev->netdev = alloc_hdlcdev(chans[ch.chan]->hdlcnetdev); + if (chans[ch.chan]->hdlcnetdev->netdev) { + chans[ch.chan]->hdlcnetdev->chan = chans[ch.chan]; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23) + SET_MODULE_OWNER(chans[ch.chan]->hdlcnetdev->netdev); +#endif + chans[ch.chan]->hdlcnetdev->netdev->irq = chans[ch.chan]->span->irq; + chans[ch.chan]->hdlcnetdev->netdev->tx_queue_len = 50; + chans[ch.chan]->hdlcnetdev->netdev->do_ioctl = zt_net_ioctl; + chans[ch.chan]->hdlcnetdev->netdev->open = zt_net_open; + chans[ch.chan]->hdlcnetdev->netdev->stop = zt_net_stop; + dev_to_hdlc(chans[ch.chan]->hdlcnetdev->netdev)->attach = zt_net_attach; + dev_to_hdlc(chans[ch.chan]->hdlcnetdev->netdev)->xmit = zt_xmit; + spin_unlock_irqrestore(&chans[ch.chan]->lock, flags); + /* Briefly restore interrupts while we register the device */ + res = zt_register_hdlc_device(chans[ch.chan]->hdlcnetdev->netdev, ch.netdev_name); + spin_lock_irqsave(&chans[ch.chan]->lock, flags); + } else { + printk("Unable to allocate hdlc: *shrug*\n"); + res = -1; + } +#else /* LINUX26 */ + chans[ch.chan]->hdlcnetdev->chan = chans[ch.chan]; +#ifndef HDLC_MAINTAINERS_ARE_MORE_STUPID_THAN_I_THOUGHT + chans[ch.chan]->hdlcnetdev->netdev.ioctl = zt_net_ioctl; +#endif + chans[ch.chan]->hdlcnetdev->netdev.netdev.do_ioctl = zt_net_ioctl; +#ifdef NEW_HDLC_INTERFACE + chans[ch.chan]->hdlcnetdev->netdev.netdev.open = zt_net_open; + chans[ch.chan]->hdlcnetdev->netdev.netdev.stop = zt_net_stop; + chans[ch.chan]->hdlcnetdev->netdev.xmit = zt_xmit; + chans[ch.chan]->hdlcnetdev->netdev.attach = zt_net_attach; +#else + chans[ch.chan]->hdlcnetdev->netdev.open = zt_net_open; + chans[ch.chan]->hdlcnetdev->netdev.close = zt_net_close; + chans[ch.chan]->hdlcnetdev->netdev.set_mode = NULL; + chans[ch.chan]->hdlcnetdev->netdev.xmit = zt_xmit; +#endif /* NEW_HDLC_INTERFACE */ + chans[ch.chan]->hdlcnetdev->netdev.netdev.irq = chans[ch.chan]->span->irq; + chans[ch.chan]->hdlcnetdev->netdev.netdev.tx_queue_len = 50; + res = register_hdlc_device(&chans[ch.chan]->hdlcnetdev->netdev); +#endif /* LINUX26 */ + if (!res) + chans[ch.chan]->flags |= ZT_FLAG_NETDEV; + } else { + printk("Unable to allocate netdev: out of memory\n"); + res = -1; + } + } +#endif + if ((chans[ch.chan]->sig == ZT_SIG_HDLCNET) && + (chans[ch.chan] == newmaster) && + !(chans[ch.chan]->flags & ZT_FLAG_NETDEV)) + printk("Unable to register HDLC device for channel %s\n", chans[ch.chan]->name); + if (!res) { + /* Setup default law */ + chans[ch.chan]->deflaw = ch.deflaw; + /* Copy back any modified settings */ + spin_unlock_irqrestore(&chans[ch.chan]->lock, flags); + if (copy_to_user((struct zt_chanconfig *)data, &ch, sizeof(ch))) + return -EFAULT; + spin_lock_irqsave(&chans[ch.chan]->lock, flags); + /* And hangup */ + zt_hangup(chans[ch.chan]); + y = zt_q_sig(chans[ch.chan]) & 0xff; + if (y >= 0) chans[ch.chan]->rxsig = (unsigned char)y; + chans[ch.chan]->rxhooksig = ZT_RXSIG_INITIAL; + } +#ifdef CONFIG_ZAPATA_DEBUG + printk("Configured channel %s, flags %04x, sig %04x\n", chans[ch.chan]->name, chans[ch.chan]->flags, chans[ch.chan]->sig); +#endif + spin_unlock_irqrestore(&chans[ch.chan]->lock, flags); + return res; + case ZT_SFCONFIG: + if (copy_from_user(&sf, (struct zt_chanconfig *)data, sizeof(sf))) + return -EFAULT; + VALID_CHANNEL(sf.chan); + if (chans[sf.chan]->sig != ZT_SIG_SF) return -EINVAL; + spin_lock_irqsave(&chans[sf.chan]->lock, flags); + chans[sf.chan]->rxp1 = sf.rxp1; + chans[sf.chan]->rxp2 = sf.rxp2; + chans[sf.chan]->rxp3 = sf.rxp3; + chans[sf.chan]->txtone = sf.txtone; + chans[sf.chan]->tx_v2 = sf.tx_v2; + chans[sf.chan]->tx_v3 = sf.tx_v3; + chans[sf.chan]->toneflags = sf.toneflag; + if (sf.txtone) /* if set to make tone for tx */ + { + if ((chans[sf.chan]->txhooksig && !(sf.toneflag & ZT_REVERSE_TXTONE)) || + ((!chans[sf.chan]->txhooksig) && (sf.toneflag & ZT_REVERSE_TXTONE))) + { + set_txtone(chans[sf.chan],sf.txtone,sf.tx_v2,sf.tx_v3); + } + else + { + set_txtone(chans[sf.chan],0,0,0); + } + } + spin_unlock_irqrestore(&chans[sf.chan]->lock, flags); + return res; + case ZT_DEFAULTZONE: + if (get_user(j,(int *)data)) + return -EFAULT; + if ((j < 0) || (j >= ZT_TONE_ZONE_MAX)) + return -EINVAL; + write_lock(&zone_lock); + if (!tone_zones[j]) { + write_unlock(&zone_lock); + return -EINVAL; + } + if ((default_zone != -1) && tone_zones[default_zone]) + atomic_dec(&tone_zones[default_zone]->refcount); + atomic_inc(&tone_zones[j]->refcount); + default_zone = j; + write_unlock(&zone_lock); + break; + case ZT_LOADZONE: + return ioctl_load_zone(data); + case ZT_FREEZONE: + get_user(j, (int *) data); + return free_tone_zone(j); + case ZT_SET_DIALPARAMS: + if (copy_from_user(&tdp, (struct zt_dialparams *) data, sizeof(tdp))) + return -EFAULT; + if ((tdp.dtmf_tonelen > 4000) || (tdp.dtmf_tonelen < 10)) + return -EINVAL; + if ((tdp.mfv1_tonelen > 4000) || (tdp.mfv1_tonelen < 10)) + return -EINVAL; + + global_dialparams = tdp; + + /* update the lengths in all currently loaded zones */ + write_lock(&zone_lock); + for (j = 0; j < sizeof(tone_zones) / sizeof(tone_zones[0]); j++) { + struct zt_zone *z = tone_zones[j]; + + if (!z) + continue; + + for (i = 0; i < sizeof(z->dtmf) / sizeof(z->dtmf[0]); i++) + z->dtmf[i].tonesamples = tdp.dtmf_tonelen * ZT_CHUNKSIZE; + + for (i = 0; i < sizeof(z->mf) / sizeof(z->mf[0]); i++) + z->mf[i].tonesamples = tdp.mfv1_tonelen * ZT_CHUNKSIZE; + + /* Special case for K/P tone */ + z->mf[10].tonesamples *= 5 / 3; + } + write_unlock(&zone_lock); + + dtmf_silence.tonesamples = tdp.dtmf_tonelen * ZT_CHUNKSIZE; + mfv1_silence.tonesamples = tdp.mfv1_tonelen * ZT_CHUNKSIZE; + + break; + case ZT_GET_DIALPARAMS: + tdp = global_dialparams; + if (copy_to_user((struct zt_dialparams *) data, &tdp, sizeof(tdp))) + return -EFAULT; + break; + case ZT_GETVERSION: + memset(&vi, 0, sizeof(vi)); + strncpy(vi.version, ZAPTEL_VERSION, sizeof(vi.version) - 1); + echo_can_identify(vi.echo_canceller, sizeof(vi.echo_canceller) - 1); + if (copy_to_user((struct zt_versioninfo *) data, &vi, sizeof(vi))) + return -EFAULT; + break; + case ZT_MAINT: /* do maintenance stuff */ + /* get struct from user */ + if (copy_from_user(&maint,(struct zt_maintinfo *) data, sizeof(maint))) + return -EFAULT; + /* must be valid span number */ + if ((maint.spanno < 1) || (maint.spanno > ZT_MAX_SPANS) || (!spans[maint.spanno])) + return -EINVAL; + if (!spans[maint.spanno]->maint) + return -ENOSYS; + spin_lock_irqsave(&spans[maint.spanno]->lock, flags); + /* save current maint state */ + i = spans[maint.spanno]->maintstat; + /* set maint mode */ + spans[maint.spanno]->maintstat = maint.command; + switch(maint.command) { + case ZT_MAINT_NONE: + case ZT_MAINT_LOCALLOOP: + case ZT_MAINT_REMOTELOOP: + /* if same, ignore it */ + if (i == maint.command) break; + rv = spans[maint.spanno]->maint(spans[maint.spanno], maint.command); + spin_unlock_irqrestore(&spans[maint.spanno]->lock, flags); + if (rv) return rv; + spin_lock_irqsave(&spans[maint.spanno]->lock, flags); + break; + case ZT_MAINT_LOOPUP: + case ZT_MAINT_LOOPDOWN: + spans[maint.spanno]->mainttimer = ZT_LOOPCODE_TIME * ZT_CHUNKSIZE; + rv = spans[maint.spanno]->maint(spans[maint.spanno], maint.command); + spin_unlock_irqrestore(&spans[maint.spanno]->lock, flags); + if (rv) return rv; + rv = schluffen(&spans[maint.spanno]->maintq); + if (rv) return rv; + spin_lock_irqsave(&spans[maint.spanno]->lock, flags); + break; + default: + printk("zaptel: Unknown maintenance event: %d\n", maint.command); + } + zt_alarm_notify(spans[maint.spanno]); /* process alarm-related events */ + spin_unlock_irqrestore(&spans[maint.spanno]->lock, flags); + break; + case ZT_DYNAMIC_CREATE: + case ZT_DYNAMIC_DESTROY: + if (zt_dynamic_ioctl) + return zt_dynamic_ioctl(cmd, data); + else { + request_module("ztdynamic"); + if (zt_dynamic_ioctl) + return zt_dynamic_ioctl(cmd, data); + } + return -ENOSYS; +#if defined(ECHO_CAN_HPEC) + case ZT_EC_LICENSE_CHALLENGE: + case ZT_EC_LICENSE_RESPONSE: + return hpec_license_ioctl(cmd, data); +#endif /* defined(ECHO_CAN_HPEC) */ + default: + return zt_common_ioctl(inode, file, cmd, data, 0); + } + return 0; +} + +static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit) +{ + struct zt_chan *chan = chans[unit]; + union { + struct zt_dialoperation tdo; + struct zt_bufferinfo bi; + struct zt_confinfo conf; + struct zt_ring_cadence cad; + } stack; + unsigned long flags, flagso; + int i, j, k, rv; + int ret, c; + char *s; + + if (!chan) + return -EINVAL; + switch(cmd) { + case ZT_DIALING: + spin_lock_irqsave(&chan->lock, flags); + j = chan->dialing; + spin_unlock_irqrestore(&chan->lock, flags); + if (copy_to_user((int *)data,&j,sizeof(int))) + return -EFAULT; + return 0; + case ZT_DIAL: + if (copy_from_user(&stack.tdo, (struct zt_dialoperation *)data, sizeof(stack.tdo))) + return -EFAULT; + rv = 0; + /* Force proper NULL termination and uppercase entry */ + stack.tdo.dialstr[ZT_MAX_DTMF_BUF - 1] = '\0'; + for (s = stack.tdo.dialstr; *s; s++) + *s = toupper(*s); + spin_lock_irqsave(&chan->lock, flags); + switch (stack.tdo.op) { + case ZT_DIAL_OP_CANCEL: + chan->curtone = NULL; + chan->dialing = 0; + chan->txdialbuf[0] = '\0'; + chan->tonep = 0; + chan->pdialcount = 0; + break; + case ZT_DIAL_OP_REPLACE: + strcpy(chan->txdialbuf, stack.tdo.dialstr); + chan->dialing = 1; + __do_dtmf(chan); + break; + case ZT_DIAL_OP_APPEND: + if (strlen(stack.tdo.dialstr) + strlen(chan->txdialbuf) >= (ZT_MAX_DTMF_BUF - 1)) { + rv = -EBUSY; + break; + } + strncpy(chan->txdialbuf + strlen(chan->txdialbuf), stack.tdo.dialstr, ZT_MAX_DTMF_BUF - strlen(chan->txdialbuf) - 1); + if (!chan->dialing) { + chan->dialing = 1; + __do_dtmf(chan); + } + break; + default: + rv = -EINVAL; + } + spin_unlock_irqrestore(&chan->lock, flags); + return rv; + case ZT_GET_BUFINFO: + stack.bi.rxbufpolicy = chan->rxbufpolicy; + stack.bi.txbufpolicy = chan->txbufpolicy; + stack.bi.numbufs = chan->numbufs; + stack.bi.bufsize = chan->blocksize; + /* XXX FIXME! XXX */ + stack.bi.readbufs = -1; + stack.bi.writebufs = -1; + if (copy_to_user((struct zt_bufferinfo *)data, &stack.bi, sizeof(stack.bi))) + return -EFAULT; + break; + case ZT_SET_BUFINFO: + if (copy_from_user(&stack.bi, (struct zt_bufferinfo *)data, sizeof(stack.bi))) + return -EFAULT; + if (stack.bi.bufsize > ZT_MAX_BLOCKSIZE) + return -EINVAL; + if (stack.bi.bufsize < 16) + return -EINVAL; + if (stack.bi.bufsize * stack.bi.numbufs > ZT_MAX_BUF_SPACE) + return -EINVAL; + chan->rxbufpolicy = stack.bi.rxbufpolicy & 0x1; + chan->txbufpolicy = stack.bi.txbufpolicy & 0x1; + if ((rv = zt_reallocbufs(chan, stack.bi.bufsize, stack.bi.numbufs))) + return (rv); + break; + case ZT_GET_BLOCKSIZE: /* get blocksize */ + put_user(chan->blocksize,(int *)data); /* return block size */ + break; + case ZT_SET_BLOCKSIZE: /* set blocksize */ + get_user(j,(int *)data); + /* cannot be larger than max amount */ + if (j > ZT_MAX_BLOCKSIZE) return(-EINVAL); + /* cannot be less then 16 */ + if (j < 16) return(-EINVAL); + /* allocate a single kernel buffer which we then + sub divide into four pieces */ + if ((rv = zt_reallocbufs(chan, j, chan->numbufs))) + return (rv); + break; + case ZT_FLUSH: /* flush input buffer, output buffer, and/or event queue */ + get_user(i,(int *)data); /* get param */ + spin_lock_irqsave(&chan->lock, flags); + if (i & ZT_FLUSH_READ) /* if for read (input) */ + { + /* initialize read buffers and pointers */ + chan->inreadbuf = 0; + chan->outreadbuf = -1; + for (j=0;jnumbufs;j++) { + /* Do we need this? */ + chan->readn[j] = 0; + chan->readidx[j] = 0; + } + wake_up_interruptible(&chan->readbufq); /* wake_up_interruptible waiting on read */ + wake_up_interruptible(&chan->sel); /* wake_up_interruptible waiting on select */ + } + if (i & ZT_FLUSH_WRITE) /* if for write (output) */ + { + /* initialize write buffers and pointers */ + chan->outwritebuf = -1; + chan->inwritebuf = 0; + for (j=0;jnumbufs;j++) { + /* Do we need this? */ + chan->writen[j] = 0; + chan->writeidx[j] = 0; + } + wake_up_interruptible(&chan->writebufq); /* wake_up_interruptible waiting on write */ + wake_up_interruptible(&chan->sel); /* wake_up_interruptible waiting on select */ + /* if IO MUX wait on write empty, well, this + certainly *did* empty the write */ + if (chan->iomask & ZT_IOMUX_WRITEEMPTY) + wake_up_interruptible(&chan->eventbufq); /* wake_up_interruptible waiting on IOMUX */ + } + if (i & ZT_FLUSH_EVENT) /* if for events */ + { + /* initialize the event pointers */ + chan->eventinidx = chan->eventoutidx = 0; + } + spin_unlock_irqrestore(&chan->lock, flags); + break; + case ZT_SYNC: /* wait for no tx */ + for(;;) /* loop forever */ + { + spin_lock_irqsave(&chan->lock, flags); + /* Know if there is a write pending */ + i = (chan->outwritebuf > -1); + spin_unlock_irqrestore(&chan->lock, flags); + if (!i) break; /* skip if none */ + rv = schluffen(&chan->writebufq); + if (rv) return(rv); + } + break; + case ZT_IOMUX: /* wait for something to happen */ + get_user(chan->iomask,(int*)data); /* save mask */ + if (!chan->iomask) return(-EINVAL); /* cant wait for nothing */ + for(;;) /* loop forever */ + { + /* has to have SOME mask */ + ret = 0; /* start with empty return value */ + spin_lock_irqsave(&chan->lock, flags); + /* if looking for read */ + if (chan->iomask & ZT_IOMUX_READ) + { + /* if read available */ + if ((chan->outreadbuf > -1) && !chan->rxdisable) + ret |= ZT_IOMUX_READ; + } + /* if looking for write avail */ + if (chan->iomask & ZT_IOMUX_WRITE) + { + if (chan->inwritebuf > -1) + ret |= ZT_IOMUX_WRITE; + } + /* if looking for write empty */ + if (chan->iomask & ZT_IOMUX_WRITEEMPTY) + { + /* if everything empty -- be sure the transmitter is enabled */ + chan->txdisable = 0; + if (chan->outwritebuf < 0) + ret |= ZT_IOMUX_WRITEEMPTY; + } + /* if looking for signalling event */ + if (chan->iomask & ZT_IOMUX_SIGEVENT) + { + /* if event */ + if (chan->eventinidx != chan->eventoutidx) + ret |= ZT_IOMUX_SIGEVENT; + } + spin_unlock_irqrestore(&chan->lock, flags); + /* if something to return, or not to wait */ + if (ret || (chan->iomask & ZT_IOMUX_NOWAIT)) + { + /* set return value */ + put_user(ret,(int *)data); + break; /* get out of loop */ + } + rv = schluffen(&chan->eventbufq); + if (rv) return(rv); + } + /* clear IO MUX mask */ + chan->iomask = 0; + break; + case ZT_GETEVENT: /* Get event on queue */ + /* set up for no event */ + j = ZT_EVENT_NONE; + spin_lock_irqsave(&chan->lock, flags); + /* if some event in queue */ + if (chan->eventinidx != chan->eventoutidx) + { + j = chan->eventbuf[chan->eventoutidx++]; + /* get the data, bump index */ + /* if index overflow, set to beginning */ + if (chan->eventoutidx >= ZT_MAX_EVENTSIZE) + chan->eventoutidx = 0; + } + spin_unlock_irqrestore(&chan->lock, flags); + put_user(j,(int *)data); + break; + case ZT_CONFMUTE: /* set confmute flag */ + get_user(j,(int *)data); /* get conf # */ + if (!(chan->flags & ZT_FLAG_AUDIO)) return (-EINVAL); + spin_lock_irqsave(&bigzaplock, flags); + chan->confmute = j; + spin_unlock_irqrestore(&bigzaplock, flags); + break; + case ZT_GETCONFMUTE: /* get confmute flag */ + if (!(chan->flags & ZT_FLAG_AUDIO)) return (-EINVAL); + j = chan->confmute; + put_user(j,(int *)data); /* get conf # */ + rv = 0; + break; + case ZT_SETTONEZONE: + get_user(j, (int *) data); + rv = set_tone_zone(chan, j); + return rv; + case ZT_GETTONEZONE: + spin_lock_irqsave(&chan->lock, flags); + if (chan->curzone) + j = chan->tonezone; + spin_unlock_irqrestore(&chan->lock, flags); + put_user(j, (int *) data); + break; + case ZT_SENDTONE: + get_user(j,(int *)data); + spin_lock_irqsave(&chan->lock, flags); + rv = start_tone(chan, j); + spin_unlock_irqrestore(&chan->lock, flags); + return rv; + case ZT_GETCONF: /* get conf stuff */ + if (copy_from_user(&stack.conf,(struct zt_confinfo *) data,sizeof(stack.conf))) + return -EFAULT; + i = stack.conf.chan; /* get channel no */ + /* if zero, use current channel no */ + if (!i) i = chan->channo; + /* make sure channel number makes sense */ + if ((i < 0) || (i > ZT_MAX_CONF) || (!chans[i])) return(-EINVAL); + if (!(chans[i]->flags & ZT_FLAG_AUDIO)) return (-EINVAL); + stack.conf.chan = i; /* get channel number */ + stack.conf.confno = chans[i]->confna; /* get conference number */ + stack.conf.confmode = chans[i]->confmode; /* get conference mode */ + if (copy_to_user((struct zt_confinfo *) data,&stack.conf,sizeof(stack.conf))) + return -EFAULT; + break; + case ZT_SETCONF: /* set conf stuff */ + if (copy_from_user(&stack.conf,(struct zt_confinfo *) data,sizeof(stack.conf))) + return -EFAULT; + i = stack.conf.chan; /* get channel no */ + /* if zero, use current channel no */ + if (!i) i = chan->channo; + /* make sure channel number makes sense */ + if ((i < 1) || (i > ZT_MAX_CHANNELS) || (!chans[i])) return(-EINVAL); + if (!(chans[i]->flags & ZT_FLAG_AUDIO)) return (-EINVAL); + if ((stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR || + (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORTX || + (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORBOTH || + (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_RX_PREECHO || + (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_TX_PREECHO || + (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORBOTH_PREECHO) { + /* Monitor mode -- it's a channel */ + if ((stack.conf.confno < 0) || (stack.conf.confno >= ZT_MAX_CHANNELS) || !chans[stack.conf.confno]) return(-EINVAL); + } else { + /* make sure conf number makes sense, too */ + if ((stack.conf.confno < -1) || (stack.conf.confno > ZT_MAX_CONF)) return(-EINVAL); + } + + /* if taking off of any conf, must have 0 mode */ + if ((!stack.conf.confno) && stack.conf.confmode) return(-EINVAL); + /* likewise if 0 mode must have no conf */ + if ((!stack.conf.confmode) && stack.conf.confno) return (-EINVAL); + stack.conf.chan = i; /* return with real channel # */ + spin_lock_irqsave(&bigzaplock, flagso); + spin_lock_irqsave(&chan->lock, flags); + if (stack.conf.confno == -1) + stack.conf.confno = zt_first_empty_conference(); + if ((stack.conf.confno < 1) && (stack.conf.confmode)) { + /* No more empty conferences */ + spin_unlock_irqrestore(&chan->lock, flags); + spin_unlock_irqrestore(&bigzaplock, flagso); + return -EBUSY; + } + /* if changing confs, clear last added info */ + if (stack.conf.confno != chans[i]->confna) { + memset(chans[i]->conflast, 0, ZT_MAX_CHUNKSIZE); + memset(chans[i]->conflast1, 0, ZT_MAX_CHUNKSIZE); + memset(chans[i]->conflast2, 0, ZT_MAX_CHUNKSIZE); + } + j = chans[i]->confna; /* save old conference number */ + chans[i]->confna = stack.conf.confno; /* set conference number */ + chans[i]->confmode = stack.conf.confmode; /* set conference mode */ + chans[i]->_confn = 0; /* Clear confn */ + zt_check_conf(j); + zt_check_conf(stack.conf.confno); + if (chans[i]->span && chans[i]->span->dacs) { + if (((stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_DIGITALMON) && + chans[stack.conf.confno]->span && + chans[stack.conf.confno]->span->dacs == chans[i]->span->dacs && + chans[i]->txgain == defgain && + chans[i]->rxgain == defgain && + chans[stack.conf.confno]->txgain == defgain && + chans[stack.conf.confno]->rxgain == defgain) { + chans[i]->span->dacs(chans[i], chans[stack.conf.confno]); + } else { + chans[i]->span->dacs(chans[i], NULL); + } + } + /* if we are going onto a conf */ + if (stack.conf.confno && + ((stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_CONF || + (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_CONFANN || + (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_CONFMON || + (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_CONFANNMON || + (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_REALANDPSEUDO)) { + /* Get alias */ + chans[i]->_confn = zt_get_conf_alias(stack.conf.confno); + } + + if (chans[stack.conf.confno]) { + if ((stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_RX_PREECHO || + (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_TX_PREECHO || + (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORBOTH_PREECHO) + chans[stack.conf.confno]->readchunkpreec = kmalloc(sizeof(*chans[stack.conf.confno]->readchunkpreec) * ZT_CHUNKSIZE, GFP_ATOMIC); + else { + if (chans[stack.conf.confno]->readchunkpreec) { + kfree(chans[stack.conf.confno]->readchunkpreec); + chans[stack.conf.confno]->readchunkpreec = NULL; + } + } + } + + spin_unlock_irqrestore(&chan->lock, flags); + spin_unlock_irqrestore(&bigzaplock, flagso); + if (copy_to_user((struct zt_confinfo *) data,&stack.conf,sizeof(stack.conf))) + return -EFAULT; + break; + case ZT_CONFLINK: /* do conf link stuff */ + if (!(chan->flags & ZT_FLAG_AUDIO)) return (-EINVAL); + if (copy_from_user(&stack.conf,(struct zt_confinfo *) data,sizeof(stack.conf))) + return -EFAULT; + /* check sanity of arguments */ + if ((stack.conf.chan < 0) || (stack.conf.chan > ZT_MAX_CONF)) return(-EINVAL); + if ((stack.conf.confno < 0) || (stack.conf.confno > ZT_MAX_CONF)) return(-EINVAL); + /* cant listen to self!! */ + if (stack.conf.chan && (stack.conf.chan == stack.conf.confno)) return(-EINVAL); + spin_lock_irqsave(&bigzaplock, flagso); + spin_lock_irqsave(&chan->lock, flags); + /* if to clear all links */ + if ((!stack.conf.chan) && (!stack.conf.confno)) + { + /* clear all the links */ + memset(conf_links,0,sizeof(conf_links)); + recalc_maxlinks(); + spin_unlock_irqrestore(&chan->lock, flags); + spin_unlock_irqrestore(&bigzaplock, flagso); + break; + } + rv = 0; /* clear return value */ + /* look for already existant specified combination */ + for(i = 1; i <= ZT_MAX_CONF; i++) + { + /* if found, exit */ + if ((conf_links[i].src == stack.conf.chan) && + (conf_links[i].dst == stack.conf.confno)) break; + } + if (i <= ZT_MAX_CONF) /* if found */ + { + if (!stack.conf.confmode) /* if to remove link */ + { + conf_links[i].src = conf_links[i].dst = 0; + } + else /* if to add and already there, error */ + { + rv = -EEXIST; + } + } + else /* if not found */ + { + if (stack.conf.confmode) /* if to add link */ + { + /* look for empty location */ + for(i = 1; i <= ZT_MAX_CONF; i++) + { + /* if empty, exit loop */ + if ((!conf_links[i].src) && + (!conf_links[i].dst)) break; + } + /* if empty spot found */ + if (i <= ZT_MAX_CONF) + { + conf_links[i].src = stack.conf.chan; + conf_links[i].dst = stack.conf.confno; + } + else /* if no empties -- error */ + { + rv = -ENOSPC; + } + } + else /* if to remove, and not found -- error */ + { + rv = -ENOENT; + } + } + recalc_maxlinks(); + spin_unlock_irqrestore(&chan->lock, flags); + spin_unlock_irqrestore(&bigzaplock, flagso); + return(rv); + case ZT_CONFDIAG: /* output diagnostic info to console */ + if (!(chan->flags & ZT_FLAG_AUDIO)) return (-EINVAL); + get_user(j,(int *)data); /* get conf # */ + /* loop thru the interesting ones */ + for(i = ((j) ? j : 1); i <= ((j) ? j : ZT_MAX_CONF); i++) + { + c = 0; + for(k = 1; k < ZT_MAX_CHANNELS; k++) + { + /* skip if no pointer */ + if (!chans[k]) continue; + /* skip if not in this conf */ + if (chans[k]->confna != i) continue; + if (!c) printk("Conf #%d:\n",i); + c = 1; + printk("chan %d, mode %x\n", + k,chans[k]->confmode); + } + rv = 0; + for(k = 1; k <= ZT_MAX_CONF; k++) + { + if (conf_links[k].dst == i) + { + if (!c) printk("Conf #%d:\n",i); + c = 1; + if (!rv) printk("Snooping on:\n"); + rv = 1; + printk("conf %d\n",conf_links[k].src); + } + } + if (c) printk("\n"); + } + break; + case ZT_CHANNO: /* get channel number of stream */ + put_user(unit,(int *)data); /* return unit/channel number */ + break; + case ZT_SETLAW: + get_user(j, (int *)data); + if ((j < 0) || (j > ZT_LAW_ALAW)) + return -EINVAL; + zt_set_law(chan, j); + break; + case ZT_SETLINEAR: + get_user(j, (int *)data); + /* Makes no sense on non-audio channels */ + if (!(chan->flags & ZT_FLAG_AUDIO)) + return -EINVAL; + + if (j) + chan->flags |= ZT_FLAG_LINEAR; + else + chan->flags &= ~ZT_FLAG_LINEAR; + break; + case ZT_SETCADENCE: + if (data) { + /* Use specific ring cadence */ + if (copy_from_user(&stack.cad, (struct zt_ring_cadence *)data, sizeof(stack.cad))) + return -EFAULT; + memcpy(chan->ringcadence, &stack.cad, sizeof(chan->ringcadence)); + chan->firstcadencepos = 0; + /* Looking for negative ringing time indicating where to loop back into ringcadence */ + for (i=0; iringcadence[i]<0) { + chan->ringcadence[i] *= -1; + chan->firstcadencepos = i; + break; + } + } + } else { + /* Reset to default */ + chan->firstcadencepos = 0; + if (chan->curzone) { + memcpy(chan->ringcadence, chan->curzone->ringcadence, sizeof(chan->ringcadence)); + /* Looking for negative ringing time indicating where to loop back into ringcadence */ + for (i=0; iringcadence[i]<0) { + chan->ringcadence[i] *= -1; + chan->firstcadencepos = i; + break; + } + } + } else { + memset(chan->ringcadence, 0, sizeof(chan->ringcadence)); + chan->ringcadence[0] = chan->starttime; + chan->ringcadence[1] = ZT_RINGOFFTIME; + } + } + break; + default: + /* Check for common ioctl's and private ones */ + rv = zt_common_ioctl(inode, file, cmd, data, unit); + /* if no span, just return with value */ + if (!chan->span) return rv; + if ((rv == -ENOTTY) && chan->span->ioctl) + rv = chan->span->ioctl(chan, cmd, data); + return rv; + + } + return 0; +} + +#ifdef CONFIG_ZAPATA_PPP +/* + * This is called at softirq (BH) level when there are calls + * we need to make to the ppp_generic layer. We do it this + * way because the ppp_generic layer functions may not be called + * at interrupt level. + */ +static void do_ppp_calls(unsigned long data) +{ + struct zt_chan *chan = (struct zt_chan *) data; + struct sk_buff *skb; + + if (!chan->ppp) + return; + if (chan->do_ppp_wakeup) { + chan->do_ppp_wakeup = 0; + ppp_output_wakeup(chan->ppp); + } + while ((skb = skb_dequeue(&chan->ppp_rq)) != NULL) + ppp_input(chan->ppp, skb); + if (chan->do_ppp_error) { + chan->do_ppp_error = 0; + ppp_input_error(chan->ppp, 0); + } +} +#endif + +static int ioctl_echocancel(struct zt_chan *chan, struct zt_echocanparams *ecp, void *data) +{ + struct echo_can_state *ec = NULL, *tec; + struct zt_echocanparam params[ZT_MAX_ECHOCANPARAMS]; + int ret; + unsigned long flags; + + if (ecp->param_count > ZT_MAX_ECHOCANPARAMS) + return -E2BIG; + + if (ecp->tap_length == 0) { + /* disable mode, don't need to inspect params */ + spin_lock_irqsave(&chan->lock, flags); + tec = chan->ec; + chan->ec = NULL; + chan->echocancel = 0; + chan->echostate = ECHO_STATE_IDLE; + chan->echolastupdate = 0; + chan->echotimer = 0; + spin_unlock_irqrestore(&chan->lock, flags); + if (chan->span && chan->span->echocan) + chan->span->echocan(chan, 0); + if (tec) + echo_can_free(tec); + + return 0; + } + + /* if parameters were supplied and this channel's span provides an echocan, + but not one that takes params, then we must punt here and return an error */ + if (ecp->param_count && chan->span && chan->span->echocan && + !chan->span->echocan_with_params) + return -EINVAL; + + /* enable mode, need the params */ + + if (copy_from_user(params, (struct zt_echocanparam *) data, sizeof(params[0]) * ecp->param_count)) + return -EFAULT; + + spin_lock_irqsave(&chan->lock, flags); + tec = chan->ec; + chan->ec = NULL; + spin_unlock_irqrestore(&chan->lock, flags); + + if (tec) + echo_can_free(tec); + + ret = -ENODEV; + + /* attempt to use the span's echo canceler; fall back to built-in + if it fails (but not if an error occurs) */ + if (chan->span) { + if (ecp->param_count) { + if (chan->span->echocan_with_params) + ret = chan->span->echocan_with_params(chan, ecp, params); + } else if (chan->span->echocan) { + ret = chan->span->echocan(chan, ecp->tap_length); + } else if (chan->span->echocan_with_params) { + ret = chan->span->echocan_with_params(chan, ecp, NULL); + } + } + + if (ret == -ENODEV) { + switch (ecp->tap_length) { + case 32: + case 64: + case 128: + case 256: + case 512: + case 1024: + break; + default: + ecp->tap_length = deftaps; + } + + if ((ret = echo_can_create(ecp, params, &ec))) + return ret; + + spin_lock_irqsave(&chan->lock, flags); + chan->echocancel = ecp->tap_length; + chan->ec = ec; + chan->echostate = ECHO_STATE_IDLE; + chan->echolastupdate = 0; + chan->echotimer = 0; + echo_can_disable_detector_init(&chan->txecdis); + echo_can_disable_detector_init(&chan->rxecdis); + spin_unlock_irqrestore(&chan->lock, flags); + } + + return ret; +} + +static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit) +{ + struct zt_chan *chan = chans[unit]; + unsigned long flags; + int j, rv; + int ret; + int oldconf; + void *rxgain=NULL; + struct echo_can_state *ec; + struct zt_echocanparams ecp; + + if (!chan) + return -ENOSYS; + + switch(cmd) { + case ZT_SIGFREEZE: + get_user(j, (int *)data); + spin_lock_irqsave(&chan->lock, flags); + if (j) { + chan->flags |= ZT_FLAG_SIGFREEZE; + } else { + chan->flags &= ~ZT_FLAG_SIGFREEZE; + } + spin_unlock_irqrestore(&chan->lock, flags); + break; + case ZT_GETSIGFREEZE: + spin_lock_irqsave(&chan->lock, flags); + if (chan->flags & ZT_FLAG_SIGFREEZE) + j = 1; + else + j = 0; + spin_unlock_irqrestore(&chan->lock, flags); + put_user(j, (int *)data); + break; + case ZT_AUDIOMODE: + /* Only literal clear channels can be put in */ + if (chan->sig != ZT_SIG_CLEAR) return (-EINVAL); + get_user(j, (int *)data); + if (j) { + spin_lock_irqsave(&chan->lock, flags); + chan->flags |= ZT_FLAG_AUDIO; + chan->flags &= ~(ZT_FLAG_HDLC | ZT_FLAG_FCS); + spin_unlock_irqrestore(&chan->lock, flags); + } else { + /* Coming out of audio mode, also clear all + conferencing and gain related info as well + as echo canceller */ + spin_lock_irqsave(&chan->lock, flags); + chan->flags &= ~ZT_FLAG_AUDIO; + /* save old conf number, if any */ + oldconf = chan->confna; + /* initialize conference variables */ + chan->_confn = 0; + chan->confna = 0; + if (chan->span && chan->span->dacs) + chan->span->dacs(chan, NULL); + chan->confmode = 0; + chan->confmute = 0; + memset(chan->conflast, 0, sizeof(chan->conflast)); + memset(chan->conflast1, 0, sizeof(chan->conflast1)); + memset(chan->conflast2, 0, sizeof(chan->conflast2)); + ec = chan->ec; + chan->ec = NULL; + /* release conference resource, if any to release */ + reset_conf(chan); + if (chan->gainalloc && chan->rxgain) + rxgain = chan->rxgain; + else + rxgain = NULL; + + chan->rxgain = defgain; + chan->txgain = defgain; + chan->gainalloc = 0; + /* Disable any native echo cancellation as well */ + spin_unlock_irqrestore(&chan->lock, flags); + + if (chan->span && chan->span->echocan) + chan->span->echocan(chan, 0); + + if (rxgain) + kfree(rxgain); + if (ec) + echo_can_free(ec); + if (oldconf) zt_check_conf(oldconf); + } + break; + case ZT_HDLCPPP: +#ifdef CONFIG_ZAPATA_PPP + if (chan->sig != ZT_SIG_CLEAR) return (-EINVAL); + get_user(j, (int *)data); + if (j) { + if (!chan->ppp) { + chan->ppp = kmalloc(sizeof(struct ppp_channel), GFP_KERNEL); + if (chan->ppp) { + struct echo_can_state *tec; + memset(chan->ppp, 0, sizeof(struct ppp_channel)); + chan->ppp->private = chan; + chan->ppp->ops = &ztppp_ops; + chan->ppp->mtu = ZT_DEFAULT_MTU_MRU; + chan->ppp->hdrlen = 0; + skb_queue_head_init(&chan->ppp_rq); + chan->do_ppp_wakeup = 0; + tasklet_init(&chan->ppp_calls, do_ppp_calls, + (unsigned long)chan); + if ((ret = zt_reallocbufs(chan, ZT_DEFAULT_MTU_MRU, ZT_DEFAULT_NUM_BUFS))) { + kfree(chan->ppp); + chan->ppp = NULL; + return ret; + } + + if ((ret = ppp_register_channel(chan->ppp))) { + kfree(chan->ppp); + chan->ppp = NULL; + return ret; + } + tec = chan->ec; + chan->ec = NULL; + chan->echocancel = 0; + chan->echostate = ECHO_STATE_IDLE; + chan->echolastupdate = 0; + chan->echotimer = 0; + /* Make sure there's no gain */ + if (chan->gainalloc) + kfree(chan->rxgain); + chan->rxgain = defgain; + chan->txgain = defgain; + chan->gainalloc = 0; + chan->flags &= ~ZT_FLAG_AUDIO; + chan->flags |= (ZT_FLAG_PPP | ZT_FLAG_HDLC | ZT_FLAG_FCS); + if (chan->span && chan->span->echocan) + chan->span->echocan(chan, 0); + if (tec) + echo_can_free(tec); + } else + return -ENOMEM; + } + } else { + chan->flags &= ~(ZT_FLAG_PPP | ZT_FLAG_HDLC | ZT_FLAG_FCS); + if (chan->ppp) { + struct ppp_channel *ppp = chan->ppp; + chan->ppp = NULL; + tasklet_kill(&chan->ppp_calls); + skb_queue_purge(&chan->ppp_rq); + ppp_unregister_channel(ppp); + kfree(ppp); + } + } +#else + printk("Zaptel: Zaptel PPP support not compiled in\n"); + return -ENOSYS; +#endif + break; + case ZT_HDLCRAWMODE: + if (chan->sig != ZT_SIG_CLEAR) return (-EINVAL); + get_user(j, (int *)data); + chan->flags &= ~(ZT_FLAG_AUDIO | ZT_FLAG_HDLC | ZT_FLAG_FCS); + if (j) { + chan->flags |= ZT_FLAG_HDLC; + fasthdlc_init(&chan->rxhdlc); + fasthdlc_init(&chan->txhdlc); + } + break; + case ZT_HDLCFCSMODE: + if (chan->sig != ZT_SIG_CLEAR) return (-EINVAL); + get_user(j, (int *)data); + chan->flags &= ~(ZT_FLAG_AUDIO | ZT_FLAG_HDLC | ZT_FLAG_FCS); + if (j) { + chan->flags |= ZT_FLAG_HDLC | ZT_FLAG_FCS; + fasthdlc_init(&chan->rxhdlc); + fasthdlc_init(&chan->txhdlc); + } + break; + case ZT_ECHOCANCEL_PARAMS: + if (!(chan->flags & ZT_FLAG_AUDIO)) + return -EINVAL; + if (copy_from_user(&ecp, (struct zt_echocanparams *) data, sizeof(ecp))) + return -EFAULT; + data += sizeof(ecp); + if ((ret = ioctl_echocancel(chan, &ecp, (void *) data))) + return ret; + break; + case ZT_ECHOCANCEL: + if (!(chan->flags & ZT_FLAG_AUDIO)) + return -EINVAL; + get_user(j, (int *) data); + ecp.tap_length = j; + ecp.param_count = 0; + if ((ret = ioctl_echocancel(chan, &ecp, NULL))) + return ret; + break; + case ZT_ECHOTRAIN: + get_user(j, (int *)data); /* get pre-training time from user */ + if ((j < 0) || (j >= ZT_MAX_PRETRAINING)) + return -EINVAL; + j <<= 3; + if (chan->ec) { + /* Start pretraining stage */ + chan->echostate = ECHO_STATE_PRETRAINING; + chan->echotimer = j; + } else + return -EINVAL; + break; + case ZT_SETTXBITS: + if (chan->sig != ZT_SIG_CAS) + return -EINVAL; + get_user(j,(int *)data); + zt_cas_setbits(chan, j); + rv = 0; + break; + case ZT_GETRXBITS: + put_user(chan->rxsig, (int *)data); + rv = 0; + break; + case ZT_LOOPBACK: + get_user(j, (int *)data); + spin_lock_irqsave(&chan->lock, flags); + if (j) + chan->flags |= ZT_FLAG_LOOPED; + else + chan->flags &= ~ZT_FLAG_LOOPED; + spin_unlock_irqrestore(&chan->lock, flags); + rv = 0; + break; + case ZT_HOOK: + get_user(j,(int *)data); + if (chan->flags & ZT_FLAG_CLEAR) + return -EINVAL; + if (chan->sig == ZT_SIG_CAS) + return -EINVAL; + /* if no span, just do nothing */ + if (!chan->span) return(0); + spin_lock_irqsave(&chan->lock, flags); + /* if dialing, stop it */ + chan->curtone = NULL; + chan->dialing = 0; + chan->txdialbuf[0] = '\0'; + chan->tonep = 0; + chan->pdialcount = 0; + spin_unlock_irqrestore(&chan->lock, flags); + if (chan->span->flags & ZT_FLAG_RBS) { + switch (j) { + case ZT_ONHOOK: + spin_lock_irqsave(&chan->lock, flags); + zt_hangup(chan); + spin_unlock_irqrestore(&chan->lock, flags); + break; + case ZT_OFFHOOK: + spin_lock_irqsave(&chan->lock, flags); + if ((chan->txstate == ZT_TXSTATE_KEWL) || + (chan->txstate == ZT_TXSTATE_AFTERKEWL)) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EBUSY; + } + zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_DEBOUNCE, chan->debouncetime); + spin_unlock_irqrestore(&chan->lock, flags); + break; + case ZT_RING: + case ZT_START: + spin_lock_irqsave(&chan->lock, flags); + if (chan->txstate != ZT_TXSTATE_ONHOOK) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EBUSY; + } + if (chan->sig & __ZT_SIG_FXO) { + ret = 0; + chan->cadencepos = 0; + ret = chan->ringcadence[0]; + zt_rbs_sethook(chan, ZT_TXSIG_START, ZT_TXSTATE_RINGON, ret); + } else + zt_rbs_sethook(chan, ZT_TXSIG_START, ZT_TXSTATE_START, chan->starttime); + spin_unlock_irqrestore(&chan->lock, flags); + if (file->f_flags & O_NONBLOCK) + return -EINPROGRESS; +#if 0 + rv = schluffen(&chan->txstateq); + if (rv) return rv; +#endif + rv = 0; + break; + case ZT_WINK: + spin_lock_irqsave(&chan->lock, flags); + if (chan->txstate != ZT_TXSTATE_ONHOOK) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EBUSY; + } + zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_PREWINK, chan->prewinktime); + spin_unlock_irqrestore(&chan->lock, flags); + if (file->f_flags & O_NONBLOCK) + return -EINPROGRESS; + rv = schluffen(&chan->txstateq); + if (rv) return rv; + break; + case ZT_FLASH: + spin_lock_irqsave(&chan->lock, flags); + if (chan->txstate != ZT_TXSTATE_OFFHOOK) { + spin_unlock_irqrestore(&chan->lock, flags); + return -EBUSY; + } + zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_PREFLASH, chan->preflashtime); + spin_unlock_irqrestore(&chan->lock, flags); + if (file->f_flags & O_NONBLOCK) + return -EINPROGRESS; + rv = schluffen(&chan->txstateq); + if (rv) return rv; + break; + case ZT_RINGOFF: + spin_lock_irqsave(&chan->lock, flags); + zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_ONHOOK, 0); + spin_unlock_irqrestore(&chan->lock, flags); + break; + default: + return -EINVAL; + } + } else if (chan->span->sethook) { + if (chan->txhooksig != j) { + chan->txhooksig = j; + chan->span->sethook(chan, j); + } + } else + return -ENOSYS; + break; +#ifdef CONFIG_ZAPATA_PPP + case PPPIOCGCHAN: + if (chan->flags & ZT_FLAG_PPP) + return put_user(ppp_channel_index(chan->ppp), (int *)data) ? -EFAULT : 0; + else + return -EINVAL; + break; + case PPPIOCGUNIT: + if (chan->flags & ZT_FLAG_PPP) + return put_user(ppp_unit_number(chan->ppp), (int *)data) ? -EFAULT : 0; + else + return -EINVAL; + break; +#endif + default: + return zt_chanandpseudo_ioctl(inode, file, cmd, data, unit); + } + return 0; +} + +static int zt_prechan_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit) +{ + struct zt_chan *chan = file->private_data; + int channo; + int res; + + if (chan) { + printk("Huh? Prechan already has private data??\n"); + } + switch(cmd) { + case ZT_SPECIFY: + get_user(channo,(int *)data); + if (channo < 1) + return -EINVAL; + if (channo > ZT_MAX_CHANNELS) + return -EINVAL; + res = zt_specchan_open(inode, file, channo, 0); + if (!res) { + /* Setup the pointer for future stuff */ + chan = chans[channo]; + file->private_data = chan; + /* Return success */ + return 0; + } + return res; + default: + return -ENOSYS; + } + return 0; +} + +static int zt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data) +{ + int unit = UNIT(file); + struct zt_chan *chan; + struct zt_timer *timer; + + if (!unit) + return zt_ctl_ioctl(inode, file, cmd, data); + + if (unit == 250) + return zt_transcode_fops->ioctl(inode, file, cmd, data); + + if (unit == 253) { + timer = file->private_data; + if (timer) + return zt_timer_ioctl(inode, file, cmd, data, timer); + else + return -EINVAL; + } + if (unit == 254) { + chan = file->private_data; + if (chan) + return zt_chan_ioctl(inode, file, cmd, data, chan->channo); + else + return zt_prechan_ioctl(inode, file, cmd, data, unit); + } + if (unit == 255) { + chan = file->private_data; + if (!chan) { + printk("No pseudo channel structure to read?\n"); + return -EINVAL; + } + return zt_chanandpseudo_ioctl(inode, file, cmd, data, chan->channo); + } + return zt_chan_ioctl(inode, file, cmd, data, unit); +} + +int zt_register(struct zt_span *span, int prefmaster) +{ + int x; + +#ifdef CONFIG_PROC_FS + char tempfile[17]; +#endif + if (!span) + return -EINVAL; + if (span->flags & ZT_FLAG_REGISTERED) { + printk(KERN_ERR "Span %s already appears to be registered\n", span->name); + return -EBUSY; + } + for (x=1;xname); + return -EBUSY; + } + for (x=1;xflags |= ZT_FLAG_REGISTERED; + span->spanno = x; + spin_lock_init(&span->lock); + if (!span->deflaw) { + printk("zaptel: Span %s didn't specify default law. Assuming mulaw, please fix driver!\n", span->name); + span->deflaw = ZT_LAW_MULAW; + } + + for (x=0;xchannels;x++) { + span->chans[x].span = span; + zt_chan_reg(&span->chans[x]); + } + +#ifdef CONFIG_PROC_FS + sprintf(tempfile, "zaptel/%d", span->spanno); + proc_entries[span->spanno] = create_proc_read_entry(tempfile, 0444, NULL , zaptel_proc_read, (int *)(long)span->spanno); +#endif + +#ifdef CONFIG_DEVFS_FS + { + char span_name[50]; + sprintf(span_name, "span%d", span->spanno); + span->dhandle = devfs_mk_dir(zaptel_devfs_dir, span_name, NULL); + for (x = 0; x < span->channels; x++) { + struct zt_chan *chan = &span->chans[x]; + chan->fhandle = register_devfs_channel(chan, chan->span->dhandle); /* Register our stuff with devfs */ + } + } +#endif /* CONFIG_DEVFS_FS */ + +#ifdef CONFIG_ZAP_UDEV + for (x = 0; x < span->channels; x++) { + char chan_name[50]; + if (span->chans[x].channo < 250) { + sprintf(chan_name, "zap%d", span->chans[x].channo); + CLASS_DEV_CREATE(zap_class, MKDEV(ZT_MAJOR, span->chans[x].channo), NULL, chan_name); + } + } +#endif /* CONFIG_ZAP_UDEV */ + + if (debug) + printk("Registered Span %d ('%s') with %d channels\n", span->spanno, span->name, span->channels); + if (!master || prefmaster) { + master = span; + if (debug) + printk("Span ('%s') is new master\n", span->name); + } + return 0; +} + +int zt_unregister(struct zt_span *span) +{ + int x; + int new_maxspans; + static struct zt_span *new_master; + +#ifdef CONFIG_PROC_FS + char tempfile[17]; +#endif /* CONFIG_PROC_FS */ + + if (!(span->flags & ZT_FLAG_REGISTERED)) { + printk(KERN_ERR "Span %s does not appear to be registered\n", span->name); + return -1; + } + /* Shutdown the span if it's running */ + if (span->flags & ZT_FLAG_RUNNING) + if (span->shutdown) + span->shutdown(span); + + if (spans[span->spanno] != span) { + printk(KERN_ERR "Span %s has spanno %d which is something else\n", span->name, span->spanno); + return -1; + } + if (debug) + printk("Unregistering Span '%s' with %d channels\n", span->name, span->channels); +#ifdef CONFIG_PROC_FS + sprintf(tempfile, "zaptel/%d", span->spanno); + remove_proc_entry(tempfile, NULL); +#endif /* CONFIG_PROC_FS */ +#ifdef CONFIG_DEVFS_FS + for (x = 0; x < span->channels; x++) { + devfs_unregister(span->chans[x].fhandle); + devfs_unregister(span->chans[x].fhandle_symlink); + } + devfs_unregister(span->dhandle); +#endif /* CONFIG_DEVFS_FS */ + +#ifdef CONFIG_ZAP_UDEV + for (x = 0; x < span->channels; x++) { + if (span->chans[x].channo < 250) + class_device_destroy(zap_class, MKDEV(ZT_MAJOR, span->chans[x].channo)); + } +#endif /* CONFIG_ZAP_UDEV */ + + spans[span->spanno] = NULL; + span->spanno = 0; + span->flags &= ~ZT_FLAG_REGISTERED; + for (x=0;xchannels;x++) + zt_chan_unreg(&span->chans[x]); + new_maxspans = 0; + new_master = master; /* FIXME: locking */ + if (master == span) + new_master = NULL; + for (x=1;xname: "no master"); + master = new_master; + + return 0; +} + +/* +** This routine converts from linear to ulaw +** +** Craig Reese: IDA/Supercomputing Research Center +** Joe Campbell: Department of Defense +** 29 September 1989 +** +** References: +** 1) CCITT Recommendation G.711 (very difficult to follow) +** 2) "A New Digital Technique for Implementation of Any +** Continuous PCM Companding Law," Villeret, Michel, +** et al. 1973 IEEE Int. Conf. on Communications, Vol 1, +** 1973, pg. 11.12-11.17 +** 3) MIL-STD-188-113,"Interoperability and Performance Standards +** for Analog-to_Digital Conversion Techniques," +** 17 February 1987 +** +** Input: Signed 16 bit linear sample +** Output: 8 bit ulaw sample +*/ + +#define ZEROTRAP /* turn on the trap as per the MIL-STD */ +#define BIAS 0x84 /* define the add-in bias for 16 bit samples */ +#define CLIP 32635 + +#ifdef CONFIG_CALC_XLAW +unsigned char +#else +static unsigned char __init +#endif +__zt_lineartoulaw(short sample) +{ + static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7}; + int sign, exponent, mantissa; + unsigned char ulawbyte; + + /* Get the sample into sign-magnitude. */ + sign = (sample >> 8) & 0x80; /* set aside the sign */ + if (sign != 0) sample = -sample; /* get magnitude */ + if (sample > CLIP) sample = CLIP; /* clip the magnitude */ + + /* Convert from 16 bit linear to ulaw. */ + sample = sample + BIAS; + exponent = exp_lut[(sample >> 7) & 0xFF]; + mantissa = (sample >> (exponent + 3)) & 0x0F; + ulawbyte = ~(sign | (exponent << 4) | mantissa); +#ifdef ZEROTRAP + if (ulawbyte == 0) ulawbyte = 0x02; /* optional CCITT trap */ +#endif + if (ulawbyte == 0xff) ulawbyte = 0x7f; /* never return 0xff */ + return(ulawbyte); +} + +#define AMI_MASK 0x55 + +#ifdef CONFIG_CALC_XLAW +unsigned char +#else +static inline unsigned char __init +#endif +__zt_lineartoalaw (short linear) +{ + int mask; + int seg; + int pcm_val; + static int seg_end[8] = + { + 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF + }; + + pcm_val = linear; + if (pcm_val >= 0) + { + /* Sign (7th) bit = 1 */ + mask = AMI_MASK | 0x80; + } + else + { + /* Sign bit = 0 */ + mask = AMI_MASK; + pcm_val = -pcm_val; + } + + /* Convert the scaled magnitude to segment number. */ + for (seg = 0; seg < 8; seg++) + { + if (pcm_val <= seg_end[seg]) + break; + } + /* Combine the sign, segment, and quantization bits. */ + return ((seg << 4) | ((pcm_val >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask; +} +/*- End of function --------------------------------------------------------*/ + +static inline short int __init alaw2linear (uint8_t alaw) +{ + int i; + int seg; + + alaw ^= AMI_MASK; + i = ((alaw & 0x0F) << 4); + seg = (((int) alaw & 0x70) >> 4); + if (seg) + i = (i + 0x100) << (seg - 1); + return (short int) ((alaw & 0x80) ? i : -i); +} +/*- End of function --------------------------------------------------------*/ +static void __init zt_conv_init(void) +{ + int i; + + /* + * Set up mu-law conversion table + */ + for(i = 0;i < 256;i++) + { + short mu,e,f,y; + static short etab[]={0,132,396,924,1980,4092,8316,16764}; + + mu = 255-i; + e = (mu & 0x70)/16; + f = mu & 0x0f; + y = f * (1 << (e + 3)); + y += etab[e]; + if (mu & 0x80) y = -y; + __zt_mulaw[i] = y; + __zt_alaw[i] = alaw2linear(i); + /* Default (0.0 db) gain table */ + defgain[i] = i; + } +#ifndef CONFIG_CALC_XLAW + /* set up the reverse (mu-law) conversion table */ + for(i = -32768; i < 32768; i += 4) + { + __zt_lin2mu[((unsigned short)(short)i) >> 2] = __zt_lineartoulaw(i); + __zt_lin2a[((unsigned short)(short)i) >> 2] = __zt_lineartoalaw(i); + } +#endif +} + +static inline void __zt_process_getaudio_chunk(struct zt_chan *ss, unsigned char *txb) +{ + /* We transmit data from our master channel */ + /* Called with ss->lock held */ + struct zt_chan *ms = ss->master; + /* Linear representation */ + short getlin[ZT_CHUNKSIZE], k[ZT_CHUNKSIZE]; + int x; + + /* Okay, now we've got something to transmit */ + for (x=0;xec) { + for (x=0;xtxecdis, getlin[x])) { + printk("zaptel Disabled echo canceller because of tone (tx) on channel %d\n", ss->channo); + ms->echocancel = 0; + ms->echostate = ECHO_STATE_IDLE; + ms->echolastupdate = 0; + ms->echotimer = 0; + echo_can_free(ms->ec); + ms->ec = NULL; + __qevent(ss, ZT_EVENT_EC_DISABLED); + break; + } + } + } +#endif + if ((!ms->confmute && !ms->dialing) || (ms->flags & ZT_FLAG_PSEUDO)) { + /* Handle conferencing on non-clear channel and non-HDLC channels */ + switch(ms->confmode & ZT_CONF_MODE_MASK) { + case ZT_CONF_NORMAL: + /* Do nuffin */ + break; + case ZT_CONF_MONITOR: /* Monitor a channel's rx mode */ + /* if a pseudo-channel, ignore */ + if (ms->flags & ZT_FLAG_PSEUDO) break; + /* Add monitored channel */ + if (chans[ms->confna]->flags & ZT_FLAG_PSEUDO) { + ACSS(getlin, chans[ms->confna]->getlin); + } else { + ACSS(getlin, chans[ms->confna]->putlin); + } + for (x=0;xflags & ZT_FLAG_PSEUDO) break; + /* Add monitored channel */ + if (chans[ms->confna]->flags & ZT_FLAG_PSEUDO) { + ACSS(getlin, chans[ms->confna]->putlin); + } else { + ACSS(getlin, chans[ms->confna]->getlin); + } + + for (x=0;xflags & ZT_FLAG_PSEUDO) break; + ACSS(getlin, chans[ms->confna]->putlin); + ACSS(getlin, chans[ms->confna]->getlin); + for (x=0;xflags & ZT_FLAG_PSEUDO) + break; + + if (!chans[ms->confna]->readchunkpreec) + break; + + /* Add monitored channel */ + ACSS(getlin, chans[ms->confna]->flags & ZT_FLAG_PSEUDO ? + chans[ms->confna]->readchunkpreec : chans[ms->confna]->putlin); + for (x = 0; x < ZT_CHUNKSIZE; x++) + txb[x] = ZT_LIN2X(getlin[x], ms); + + break; + case ZT_CONF_MONITOR_TX_PREECHO: /* Monitor a channel's tx mode */ + /* if a pseudo-channel, ignore */ + if (ms->flags & ZT_FLAG_PSEUDO) + break; + + if (!chans[ms->confna]->readchunkpreec) + break; + + /* Add monitored channel */ + ACSS(getlin, chans[ms->confna]->flags & ZT_FLAG_PSEUDO ? + chans[ms->confna]->putlin : chans[ms->confna]->readchunkpreec); + for (x = 0; x < ZT_CHUNKSIZE; x++) + txb[x] = ZT_LIN2X(getlin[x], ms); + + break; + case ZT_CONF_MONITORBOTH_PREECHO: /* monitor a channel's rx and tx mode */ + /* if a pseudo-channel, ignore */ + if (ms->flags & ZT_FLAG_PSEUDO) + break; + + if (!chans[ms->confna]->readchunkpreec) + break; + + ACSS(getlin, chans[ms->confna]->putlin); + ACSS(getlin, chans[ms->confna]->readchunkpreec); + + for (x = 0; x < ZT_CHUNKSIZE; x++) + txb[x] = ZT_LIN2X(getlin[x], ms); + + break; + case ZT_CONF_REALANDPSEUDO: + /* This strange mode takes the transmit buffer and + puts it on the conference, minus its last sample, + then outputs from the conference minus the + real channel's last sample. */ + /* if to talk on conf */ + if (ms->confmode & ZT_CONF_PSEUDO_TALKER) { + /* Store temp value */ + memcpy(k, getlin, ZT_CHUNKSIZE * sizeof(short)); + /* Add conf value */ + ACSS(k, conf_sums_next[ms->_confn]); + /* save last one */ + memcpy(ms->conflast2, ms->conflast1, ZT_CHUNKSIZE * sizeof(short)); + memcpy(ms->conflast1, k, ZT_CHUNKSIZE * sizeof(short)); + /* get amount actually added */ + SCSS(ms->conflast1, conf_sums_next[ms->_confn]); + /* Really add in new value */ + ACSS(conf_sums_next[ms->_confn], ms->conflast1); + } else { + memset(ms->conflast1, 0, ZT_CHUNKSIZE * sizeof(short)); + memset(ms->conflast2, 0, ZT_CHUNKSIZE * sizeof(short)); + } + memset(getlin, 0, ZT_CHUNKSIZE * sizeof(short)); + txb[0] = ZT_LIN2X(0, ms); + memset(txb + 1, txb[0], ZT_CHUNKSIZE - 1); + /* fall through to normal conf mode */ + case ZT_CONF_CONF: /* Normal conference mode */ + if (ms->flags & ZT_FLAG_PSEUDO) /* if pseudo-channel */ + { + /* if to talk on conf */ + if (ms->confmode & ZT_CONF_TALKER) { + /* Store temp value */ + memcpy(k, getlin, ZT_CHUNKSIZE * sizeof(short)); + /* Add conf value */ + ACSS(k, conf_sums[ms->_confn]); + /* get amount actually added */ + memcpy(ms->conflast, k, ZT_CHUNKSIZE * sizeof(short)); + SCSS(ms->conflast, conf_sums[ms->_confn]); + /* Really add in new value */ + ACSS(conf_sums[ms->_confn], ms->conflast); + } else memset(ms->conflast, 0, ZT_CHUNKSIZE * sizeof(short)); + memcpy(getlin, ms->getlin, ZT_CHUNKSIZE * sizeof(short)); + txb[0] = ZT_LIN2X(0, ms); + memset(txb + 1, txb[0], ZT_CHUNKSIZE - 1); + break; + } + /* fall through */ + case ZT_CONF_CONFMON: /* Conference monitor mode */ + if (ms->confmode & ZT_CONF_LISTENER) { + /* Subtract out last sample written to conf */ + SCSS(getlin, ms->conflast); + /* Add in conference */ + ACSS(getlin, conf_sums[ms->_confn]); + } + for (x=0;x_confn], getlin); + /* Start with silence */ + memset(getlin, 0, ZT_CHUNKSIZE * sizeof(short)); + /* If a listener on the conf... */ + if (ms->confmode & ZT_CONF_LISTENER) { + /* Subtract last value written */ + SCSS(getlin, ms->conflast); + /* Add in conf */ + ACSS(getlin, conf_sums[ms->_confn]); + } + for (x=0;xconfna]) + break; + if (chans[ms->confna]->flags & ZT_FLAG_PSEUDO) { + if (ms->ec) { + for (x=0;xconfna]->getlin[x], ms); + } else { + memcpy(txb, chans[ms->confna]->getraw, ZT_CHUNKSIZE); + } + } else { + if (ms->ec) { + for (x=0;xconfna]->putlin[x], ms); + } else { + memcpy(txb, chans[ms->confna]->putraw, ZT_CHUNKSIZE); + } + } + for (x=0;xconfmute || (ms->echostate & __ECHO_STATE_MUTE)) { + txb[0] = ZT_LIN2X(0, ms); + memset(txb + 1, txb[0], ZT_CHUNKSIZE - 1); + if (ms->echostate == ECHO_STATE_STARTTRAINING) { + /* Transmit impulse now */ + txb[0] = ZT_LIN2X(16384, ms); + ms->echostate = ECHO_STATE_AWAITINGECHO; + } + } + /* save value from last chunk */ + memcpy(ms->getlin_lastchunk, ms->getlin, ZT_CHUNKSIZE * sizeof(short)); + /* save value from current */ + memcpy(ms->getlin, getlin, ZT_CHUNKSIZE * sizeof(short)); + /* save value from current */ + memcpy(ms->getraw, txb, ZT_CHUNKSIZE); + /* if to make tx tone */ + if (ms->v1_1 || ms->v2_1 || ms->v3_1) + { + for (x=0;xtxgain[txb[x]]; +} + +static inline void __zt_getbuf_chunk(struct zt_chan *ss, unsigned char *txb) +{ + /* Called with ss->lock held */ + /* We transmit data from our master channel */ + struct zt_chan *ms = ss->master; + /* Buffer we're using */ + unsigned char *buf; + /* Old buffer number */ + int oldbuf; + /* Linear representation */ + int getlin; + /* How many bytes we need to process */ + int bytes = ZT_CHUNKSIZE, left; + int x; + + /* Let's pick something to transmit. First source to + try is our write-out buffer. Always check it first because + its our 'fast path' for whatever that's worth. */ + while(bytes) { + if ((ms->outwritebuf > -1) && !ms->txdisable) { + buf= ms->writebuf[ms->outwritebuf]; + left = ms->writen[ms->outwritebuf] - ms->writeidx[ms->outwritebuf]; + if (left > bytes) + left = bytes; + if (ms->flags & ZT_FLAG_HDLC) { + /* If this is an HDLC channel we only send a byte of + HDLC. */ + for(x=0;xtxhdlc.bits < 8) + /* Load a byte of data only if needed */ + fasthdlc_tx_load_nocheck(&ms->txhdlc, buf[ms->writeidx[ms->outwritebuf]++]); + *(txb++) = fasthdlc_tx_run_nocheck(&ms->txhdlc); + } + bytes -= left; + } else { + memcpy(txb, buf + ms->writeidx[ms->outwritebuf], left); + ms->writeidx[ms->outwritebuf]+=left; + txb += left; + bytes -= left; + } + /* Check buffer status */ + if (ms->writeidx[ms->outwritebuf] >= ms->writen[ms->outwritebuf]) { + /* We've reached the end of our buffer. Go to the next. */ + oldbuf = ms->outwritebuf; + /* Clear out write index and such */ + ms->writeidx[oldbuf] = 0; + ms->writen[oldbuf] = 0; + ms->outwritebuf = (ms->outwritebuf + 1) % ms->numbufs; + if (ms->outwritebuf == ms->inwritebuf) { + /* Whoopsies, we're run out of buffers. Mark ours + as -1 and wait for the filler to notify us that + there is something to write */ + ms->outwritebuf = -1; + if (ms->iomask & (ZT_IOMUX_WRITE | ZT_IOMUX_WRITEEMPTY)) + wake_up_interruptible(&ms->eventbufq); + /* If we're only supposed to start when full, disable the transmitter */ + if (ms->txbufpolicy == ZT_POLICY_WHEN_FULL) + ms->txdisable = 1; + } + if (ms->inwritebuf < 0) { + /* The filler doesn't have a place to put data. Now + that we're done with this buffer, notify them. */ + ms->inwritebuf = oldbuf; + } +/* In the very orignal driver, it was quite well known to me (Jim) that there +was a possibility that a channel sleeping on a write block needed to +be potentially woken up EVERY time a buffer was emptied, not just on the first +one, because if only done on the first one there is a slight timing potential +of missing the wakeup (between where it senses the (lack of) active condition +(with interrupts disabled) and where it does the sleep (interrupts enabled) +in the read or iomux call, etc). That is why the write and iomux calls start +with an infinite loop that gets broken out of upon an active condition, +otherwise keeps sleeping and looking. The part in this code got "optimized" +out in the later versions, and is put back now. */ + if (!(ms->flags & (ZT_FLAG_NETDEV | ZT_FLAG_PPP))) { + wake_up_interruptible(&ms->writebufq); + wake_up_interruptible(&ms->sel); + if (ms->iomask & ZT_IOMUX_WRITE) + wake_up_interruptible(&ms->eventbufq); + } + /* Transmit a flag if this is an HDLC channel */ + if (ms->flags & ZT_FLAG_HDLC) + fasthdlc_tx_frame_nocheck(&ms->txhdlc); +#ifdef CONFIG_ZAPATA_NET + if (ms->flags & ZT_FLAG_NETDEV) + netif_wake_queue(ztchan_to_dev(ms)); +#endif +#ifdef CONFIG_ZAPATA_PPP + if (ms->flags & ZT_FLAG_PPP) { + ms->do_ppp_wakeup = 1; + tasklet_schedule(&ms->ppp_calls); + } +#endif + } + } else if (ms->curtone && !(ms->flags & ZT_FLAG_PSEUDO)) { + left = ms->curtone->tonesamples - ms->tonep; + if (left > bytes) + left = bytes; + for (x=0;xts, ms->curtone); + *(txb++) = ZT_LIN2X(getlin, ms); + } + ms->tonep+=left; + bytes -= left; + if (ms->tonep >= ms->curtone->tonesamples) { + struct zt_tone *last; + /* Go to the next sample of the tone */ + ms->tonep = 0; + last = ms->curtone; + ms->curtone = ms->curtone->next; + if (!ms->curtone) { + /* No more tones... Is this dtmf or mf? If so, go to the next digit */ + if (ms->dialing) + __do_dtmf(ms); + } else { + if (last != ms->curtone) + zt_init_tone_state(&ms->ts, ms->curtone); + } + } + } else if (ms->flags & ZT_FLAG_LOOPED) { + for (x = 0; x < bytes; x++) + txb[x] = ms->readchunk[x]; + bytes = 0; + } else if (ms->flags & ZT_FLAG_HDLC) { + for (x=0;xtxhdlc.bits < 8) + fasthdlc_tx_frame_nocheck(&ms->txhdlc); + *(txb++) = fasthdlc_tx_run_nocheck(&ms->txhdlc); + } + bytes = 0; + } else if (ms->flags & ZT_FLAG_CLEAR) { + /* Clear channels that are idle in audio mode need + to send silence; in non-audio mode, always send 0xff + so stupid switches won't consider the channel active + */ + if (ms->flags & ZT_FLAG_AUDIO) { + memset(txb, ZT_LIN2X(0, ms), bytes); + } else { + memset(txb, 0xFF, bytes); + } + bytes = 0; + } else { + memset(txb, ZT_LIN2X(0, ms), bytes); /* Lastly we use silence on telephony channels */ + bytes = 0; + } + } +} + +static inline void rbs_itimer_expire(struct zt_chan *chan) +{ + /* the only way this could have gotten here, is if a channel + went onf hook longer then the wink or flash detect timeout */ + /* Called with chan->lock held */ + switch(chan->sig) + { + case ZT_SIG_FXOLS: /* if FXO, its definitely on hook */ + case ZT_SIG_FXOGS: + case ZT_SIG_FXOKS: + __qevent(chan,ZT_EVENT_ONHOOK); + chan->gotgs = 0; + break; +#if defined(EMFLASH) || defined(EMPULSE) + case ZT_SIG_EM: + case ZT_SIG_EM_E1: + if (chan->rxhooksig == ZT_RXSIG_ONHOOK) { + __qevent(chan,ZT_EVENT_ONHOOK); + break; + } + __qevent(chan,ZT_EVENT_RINGOFFHOOK); + break; +#endif +#ifdef FXSFLASH + case ZT_SIG_FXSKS: + if (chan->rxhooksig == ZT_RXSIG_ONHOOK) { + __qevent(chan, ZT_EVENT_ONHOOK); + break; + } +#endif + /* fall thru intentionally */ + default: /* otherwise, its definitely off hook */ + __qevent(chan,ZT_EVENT_RINGOFFHOOK); + break; + } +} + +static inline void __rbs_otimer_expire(struct zt_chan *chan) +{ + int len = 0; + /* Called with chan->lock held */ + + chan->otimer = 0; + /* Move to the next timer state */ + switch(chan->txstate) { + case ZT_TXSTATE_RINGOFF: + /* Turn on the ringer now that the silent time has passed */ + ++chan->cadencepos; + if (chan->cadencepos >= ZT_MAX_CADENCE) + chan->cadencepos = chan->firstcadencepos; + len = chan->ringcadence[chan->cadencepos]; + + if (!len) { + chan->cadencepos = chan->firstcadencepos; + len = chan->ringcadence[chan->cadencepos]; + } + + zt_rbs_sethook(chan, ZT_TXSIG_START, ZT_TXSTATE_RINGON, len); + __qevent(chan, ZT_EVENT_RINGERON); + break; + + case ZT_TXSTATE_RINGON: + /* Turn off the ringer now that the loud time has passed */ + ++chan->cadencepos; + if (chan->cadencepos >= ZT_MAX_CADENCE) + chan->cadencepos = 0; + len = chan->ringcadence[chan->cadencepos]; + + if (!len) { + chan->cadencepos = 0; + len = chan->curzone->ringcadence[chan->cadencepos]; + } + + zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_RINGOFF, len); + __qevent(chan, ZT_EVENT_RINGEROFF); + break; + + case ZT_TXSTATE_START: + /* If we were starting, go off hook now ready to debounce */ + zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_AFTERSTART, ZT_AFTERSTART_TIME); + wake_up_interruptible(&chan->txstateq); + break; + + case ZT_TXSTATE_PREWINK: + /* Actually wink */ + zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_WINK, chan->winktime); + break; + + case ZT_TXSTATE_WINK: + /* Wink complete, go on hook and stabalize */ + zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_ONHOOK, 0); + if (chan->file && (chan->file->f_flags & O_NONBLOCK)) + __qevent(chan, ZT_EVENT_HOOKCOMPLETE); + wake_up_interruptible(&chan->txstateq); + break; + + case ZT_TXSTATE_PREFLASH: + /* Actually flash */ + zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_FLASH, chan->flashtime); + break; + + case ZT_TXSTATE_FLASH: + zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_OFFHOOK, 0); + if (chan->file && (chan->file->f_flags & O_NONBLOCK)) + __qevent(chan, ZT_EVENT_HOOKCOMPLETE); + wake_up_interruptible(&chan->txstateq); + break; + + case ZT_TXSTATE_DEBOUNCE: + zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_OFFHOOK, 0); + /* See if we've gone back on hook */ + if ((chan->rxhooksig == ZT_RXSIG_ONHOOK) && (chan->rxflashtime > 2)) + chan->itimerset = chan->itimer = chan->rxflashtime * ZT_CHUNKSIZE; + wake_up_interruptible(&chan->txstateq); + break; + + case ZT_TXSTATE_AFTERSTART: + zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_OFFHOOK, 0); + if (chan->file && (chan->file->f_flags & O_NONBLOCK)) + __qevent(chan, ZT_EVENT_HOOKCOMPLETE); + wake_up_interruptible(&chan->txstateq); + break; + + case ZT_TXSTATE_KEWL: + zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_AFTERKEWL, ZT_AFTERKEWLTIME); + if (chan->file && (chan->file->f_flags & O_NONBLOCK)) + __qevent(chan, ZT_EVENT_HOOKCOMPLETE); + wake_up_interruptible(&chan->txstateq); + break; + + case ZT_TXSTATE_AFTERKEWL: + if (chan->kewlonhook) { + __qevent(chan,ZT_EVENT_ONHOOK); + } + chan->txstate = ZT_TXSTATE_ONHOOK; + chan->gotgs = 0; + break; + + case ZT_TXSTATE_PULSEBREAK: + zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_PULSEMAKE, + chan->pulsemaketime); + wake_up_interruptible(&chan->txstateq); + break; + + case ZT_TXSTATE_PULSEMAKE: + if (chan->pdialcount) + chan->pdialcount--; + if (chan->pdialcount) + { + zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, + ZT_TXSTATE_PULSEBREAK, chan->pulsebreaktime); + break; + } + chan->txstate = ZT_TXSTATE_PULSEAFTER; + chan->otimer = chan->pulseaftertime * ZT_CHUNKSIZE; + wake_up_interruptible(&chan->txstateq); + break; + + case ZT_TXSTATE_PULSEAFTER: + chan->txstate = ZT_TXSTATE_OFFHOOK; + __do_dtmf(chan); + wake_up_interruptible(&chan->txstateq); + break; + + default: + break; + } +} + +static void __zt_hooksig_pvt(struct zt_chan *chan, zt_rxsig_t rxsig) +{ + + /* State machines for receive hookstate transitions + called with chan->lock held */ + + if ((chan->rxhooksig) == rxsig) return; + + if ((chan->flags & ZT_FLAG_SIGFREEZE)) return; + + chan->rxhooksig = rxsig; +#ifdef RINGBEGIN + if ((chan->sig & __ZT_SIG_FXS) && (rxsig == ZT_RXSIG_RING) && + (!chan->ringdebtimer)) + __qevent(chan,ZT_EVENT_RINGBEGIN); +#endif + switch(chan->sig) { + case ZT_SIG_EM: /* E and M */ + case ZT_SIG_EM_E1: + switch(rxsig) { + case ZT_RXSIG_OFFHOOK: /* went off hook */ + /* The interface is going off hook */ +#ifdef EMFLASH + if (chan->itimer) + { + __qevent(chan,ZT_EVENT_WINKFLASH); + chan->itimerset = chan->itimer = 0; + break; + } +#endif +#ifdef EMPULSE + if (chan->itimer) /* if timer still running */ + { + int plen = chan->itimerset - chan->itimer; + if (plen <= ZT_MAXPULSETIME) + { + if (plen >= ZT_MINPULSETIME) + { + chan->pulsecount++; + + chan->pulsetimer = ZT_PULSETIMEOUT; + chan->itimerset = chan->itimer = 0; + if (chan->pulsecount == 1) + __qevent(chan,ZT_EVENT_PULSE_START); + } + } + break; + } +#endif + /* set wink timer */ + chan->itimerset = chan->itimer = chan->rxwinktime * ZT_CHUNKSIZE; + break; + case ZT_RXSIG_ONHOOK: /* went on hook */ + /* This interface is now going on hook. + Check for WINK, etc */ + if (chan->itimer) + __qevent(chan,ZT_EVENT_WINKFLASH); +#if defined(EMFLASH) || defined(EMPULSE) + else { +#ifdef EMFLASH + chan->itimerset = chan->itimer = chan->rxflashtime * ZT_CHUNKSIZE; + +#else /* EMFLASH */ + chan->itimerset = chan->itimer = chan->rxwinktime * ZT_CHUNKSIZE; + +#endif /* EMFLASH */ + chan->gotgs = 0; + break; + } +#else /* EMFLASH || EMPULSE */ + else { + __qevent(chan,ZT_EVENT_ONHOOK); + chan->gotgs = 0; + } +#endif + chan->itimerset = chan->itimer = 0; + break; + default: + break; + } + break; + case ZT_SIG_FXSKS: /* FXS Kewlstart */ + /* ignore a bit poopy if loop not closed and stable */ + if (chan->txstate != ZT_TXSTATE_OFFHOOK) break; +#ifdef FXSFLASH + if (rxsig == ZT_RXSIG_ONHOOK) { + chan->itimer = ZT_FXSFLASHMAXTIME * ZT_CHUNKSIZE; + break; + } else if (rxsig == ZT_RXSIG_OFFHOOK) { + if (chan->itimer) { + /* did the offhook occur in the window? if not, ignore both events */ + if (chan->itimer <= ((ZT_FXSFLASHMAXTIME - ZT_FXSFLASHMINTIME) * ZT_CHUNKSIZE)) + __qevent(chan, ZT_EVENT_WINKFLASH); + } + chan->itimer = 0; + break; + } +#endif + /* fall through intentionally */ + case ZT_SIG_FXSGS: /* FXS Groundstart */ + if (rxsig == ZT_RXSIG_ONHOOK) { + chan->ringdebtimer = RING_DEBOUNCE_TIME; + chan->ringtrailer = 0; + if (chan->txstate != ZT_TXSTATE_DEBOUNCE) { + chan->gotgs = 0; + __qevent(chan,ZT_EVENT_ONHOOK); + } + } + break; + case ZT_SIG_FXOGS: /* FXO Groundstart */ + if (rxsig == ZT_RXSIG_START) { + /* if havent got gs, report it */ + if (!chan->gotgs) { + __qevent(chan,ZT_EVENT_RINGOFFHOOK); + chan->gotgs = 1; + } + } + /* fall through intentionally */ + case ZT_SIG_FXOLS: /* FXO Loopstart */ + case ZT_SIG_FXOKS: /* FXO Kewlstart */ + switch(rxsig) { + case ZT_RXSIG_OFFHOOK: /* went off hook */ + /* if asserti ng ring, stop it */ + if (chan->txstate == ZT_TXSTATE_START) { + zt_rbs_sethook(chan,ZT_TXSIG_OFFHOOK, ZT_TXSTATE_AFTERSTART, ZT_AFTERSTART_TIME); + } + chan->kewlonhook = 0; +#ifdef CONFIG_ZAPATA_DEBUG + printk("Off hook on channel %d, itimer = %d, gotgs = %d\n", chan->channo, chan->itimer, chan->gotgs); +#endif + if (chan->itimer) /* if timer still running */ + { + int plen = chan->itimerset - chan->itimer; + if (plen <= ZT_MAXPULSETIME) + { + if (plen >= ZT_MINPULSETIME) + { + chan->pulsecount++; + chan->pulsetimer = ZT_PULSETIMEOUT; + chan->itimer = chan->itimerset; + if (chan->pulsecount == 1) + __qevent(chan,ZT_EVENT_PULSE_START); + } + } else + __qevent(chan,ZT_EVENT_WINKFLASH); + } else { + /* if havent got GS detect */ + if (!chan->gotgs) { + __qevent(chan,ZT_EVENT_RINGOFFHOOK); + chan->gotgs = 1; + chan->itimerset = chan->itimer = 0; + } + } + chan->itimerset = chan->itimer = 0; + break; + case ZT_RXSIG_ONHOOK: /* went on hook */ + /* if not during offhook debounce time */ + if ((chan->txstate != ZT_TXSTATE_DEBOUNCE) && + (chan->txstate != ZT_TXSTATE_KEWL) && + (chan->txstate != ZT_TXSTATE_AFTERKEWL)) { + chan->itimerset = chan->itimer = chan->rxflashtime * ZT_CHUNKSIZE; + } + if (chan->txstate == ZT_TXSTATE_KEWL) + chan->kewlonhook = 1; + break; + default: + break; + } + default: + break; + } +} + +void zt_hooksig(struct zt_chan *chan, zt_rxsig_t rxsig) +{ + /* skip if no change */ + unsigned long flags; + spin_lock_irqsave(&chan->lock, flags); + __zt_hooksig_pvt(chan,rxsig); + spin_unlock_irqrestore(&chan->lock, flags); +} + +void zt_rbsbits(struct zt_chan *chan, int cursig) +{ + unsigned long flags; + if (cursig == chan->rxsig) + return; + + if ((chan->flags & ZT_FLAG_SIGFREEZE)) return; + + spin_lock_irqsave(&chan->lock, flags); + switch(chan->sig) { + case ZT_SIG_FXOGS: /* FXO Groundstart */ + /* B-bit only matters for FXO GS */ + if (!(cursig & ZT_BBIT)) { + __zt_hooksig_pvt(chan, ZT_RXSIG_START); + break; + } + /* Fall through */ + case ZT_SIG_EM: /* E and M */ + case ZT_SIG_EM_E1: + case ZT_SIG_FXOLS: /* FXO Loopstart */ + case ZT_SIG_FXOKS: /* FXO Kewlstart */ + if (cursig & ZT_ABIT) /* off hook */ + __zt_hooksig_pvt(chan,ZT_RXSIG_OFFHOOK); + else /* on hook */ + __zt_hooksig_pvt(chan,ZT_RXSIG_ONHOOK); + break; + + case ZT_SIG_FXSKS: /* FXS Kewlstart */ + case ZT_SIG_FXSGS: /* FXS Groundstart */ + /* Fall through */ + case ZT_SIG_FXSLS: + if (!(cursig & ZT_BBIT)) { + /* Check for ringing first */ + __zt_hooksig_pvt(chan, ZT_RXSIG_RING); + break; + } + if ((chan->sig != ZT_SIG_FXSLS) && (cursig & ZT_ABIT)) { + /* if went on hook */ + __zt_hooksig_pvt(chan, ZT_RXSIG_ONHOOK); + } else { + __zt_hooksig_pvt(chan, ZT_RXSIG_OFFHOOK); + } + break; + case ZT_SIG_CAS: + /* send event that something changed */ + __qevent(chan, ZT_EVENT_BITSCHANGED); + break; + + default: + break; + } + /* Keep track of signalling for next time */ + chan->rxsig = cursig; + spin_unlock_irqrestore(&chan->lock, flags); +} + +static inline void __zt_ec_chunk(struct zt_chan *ss, unsigned char *rxchunk, const unsigned char *txchunk) +{ + short rxlin, txlin; + int x; + unsigned long flags; + + spin_lock_irqsave(&ss->lock, flags); + + if (ss->readchunkpreec) { + /* Save a copy of the audio before the echo can has its way with it */ + for (x = 0; x < ZT_CHUNKSIZE; x++) + /* We only ever really need to deal with signed linear - let's just convert it now */ + ss->readchunkpreec[x] = ZT_XLAW(rxchunk[x], ss); + } + + /* Perform echo cancellation on a chunk if necessary */ + if (ss->ec) { +#if defined(CONFIG_ZAPTEL_MMX) || defined(ECHO_CAN_FP) + zt_kernel_fpu_begin(); +#endif + if (ss->echostate & __ECHO_STATE_MUTE) { + /* Special stuff for training the echo can */ + for (x=0;xechostate == ECHO_STATE_PRETRAINING) { + if (--ss->echotimer <= 0) { + ss->echotimer = 0; + ss->echostate = ECHO_STATE_STARTTRAINING; + } + } + if ((ss->echostate == ECHO_STATE_AWAITINGECHO) && (txlin > 8000)) { + ss->echolastupdate = 0; + ss->echostate = ECHO_STATE_TRAINING; + } + if (ss->echostate == ECHO_STATE_TRAINING) { + if (echo_can_traintap(ss->ec, ss->echolastupdate++, rxlin)) { +#if 0 + printk("Finished training (%d taps trained)!\n", ss->echolastupdate); +#endif + ss->echostate = ECHO_STATE_ACTIVE; + } + } + rxlin = 0; + rxchunk[x] = ZT_LIN2X((int)rxlin, ss); + } + } else { +#if !defined(ZT_EC_ARRAY_UPDATE) + for (x=0;xec, ZT_XLAW(txchunk[x], ss), rxlin); + rxchunk[x] = ZT_LIN2X((int) rxlin, ss); + } +#else /* defined(ZT_EC_ARRAY_UPDATE) */ + short rxlins[ZT_CHUNKSIZE], txlins[ZT_CHUNKSIZE]; + for (x = 0; x < ZT_CHUNKSIZE; x++) { + rxlins[x] = ZT_XLAW(rxchunk[x], ss); + txlins[x] = ZT_XLAW(txchunk[x], ss); + } + echo_can_array_update(ss->ec, rxlins, txlins); + for (x = 0; x < ZT_CHUNKSIZE; x++) + rxchunk[x] = ZT_LIN2X((int) rxlins[x], ss); +#endif /* defined(ZT_EC_ARRAY_UPDATE) */ + } +#if defined(CONFIG_ZAPTEL_MMX) || defined(ECHO_CAN_FP) + kernel_fpu_end(); +#endif + } + spin_unlock_irqrestore(&ss->lock, flags); +} + +void zt_ec_chunk(struct zt_chan *ss, unsigned char *rxchunk, const unsigned char *txchunk) +{ + __zt_ec_chunk(ss, rxchunk, txchunk); +} + +void zt_ec_span(struct zt_span *span) +{ + int x; + for (x = 0; x < span->channels; x++) { + if (span->chans[x].ec) + __zt_ec_chunk(&span->chans[x], span->chans[x].readchunk, span->chans[x].writechunk); + } +} + +/* return 0 if nothing detected, 1 if lack of tone, 2 if presence of tone */ +/* modifies buffer pointed to by 'amp' with notched-out values */ +static inline int sf_detect (sf_detect_state_t *s, + short *amp, + int samples,long p1, long p2, long p3) +{ +int i,rv = 0; +long x,y; + +#define SF_DETECT_SAMPLES (ZT_CHUNKSIZE * 5) +#define SF_DETECT_MIN_ENERGY 500 +#define NB 14 /* number of bits to shift left */ + + /* determine energy level before filtering */ + for(i = 0; i < samples; i++) + { + if (amp[i] < 0) s->e1 -= amp[i]; + else s->e1 += amp[i]; + } + /* do 2nd order IIR notch filter at given freq. and calculate + energy */ + for(i = 0; i < samples; i++) + { + x = amp[i] << NB; + y = s->x2 + (p1 * (s->x1 >> NB)) + x; + y += (p2 * (s->y2 >> NB)) + + (p3 * (s->y1 >> NB)); + s->x2 = s->x1; + s->x1 = x; + s->y2 = s->y1; + s->y1 = y; + amp[i] = y >> NB; + if (amp[i] < 0) s->e2 -= amp[i]; + else s->e2 += amp[i]; + } + s->samps += i; + /* if time to do determination */ + if ((s->samps) >= SF_DETECT_SAMPLES) + { + rv = 1; /* default to no tone */ + /* if enough energy, it is determined to be a tone */ + if (((s->e1 - s->e2) / s->samps) > SF_DETECT_MIN_ENERGY) rv = 2; + /* reset energy processing variables */ + s->samps = 0; + s->e1 = s->e2 = 0; + } + return(rv); +} + +static inline void __zt_process_putaudio_chunk(struct zt_chan *ss, unsigned char *rxb) +{ + /* We transmit data from our master channel */ + /* Called with ss->lock held */ + struct zt_chan *ms = ss->master; + /* Linear version of received data */ + short putlin[ZT_CHUNKSIZE],k[ZT_CHUNKSIZE]; + int x,r; + + if (ms->dialing) ms->afterdialingtimer = 50; + else if (ms->afterdialingtimer) ms->afterdialingtimer--; + if (ms->afterdialingtimer && (!(ms->flags & ZT_FLAG_PSEUDO))) { + /* Be careful since memset is likely a macro */ + rxb[0] = ZT_LIN2X(0, ms); + memset(&rxb[1], rxb[0], ZT_CHUNKSIZE - 1); /* receive as silence if dialing */ + } + for (x=0;xrxgain[rxb[x]]; + putlin[x] = ZT_XLAW(rxb[x], ms); + } + +#ifndef NO_ECHOCAN_DISABLE + if (ms->ec) { + for (x=0;xrxecdis, putlin[x])) { + printk("zaptel Disabled echo canceller because of tone (rx) on channel %d\n", ss->channo); + ms->echocancel = 0; + ms->echostate = ECHO_STATE_IDLE; + ms->echolastupdate = 0; + ms->echotimer = 0; + echo_can_free(ms->ec); + ms->ec = NULL; + break; + } + } + } +#endif + /* if doing rx tone decoding */ + if (ms->rxp1 && ms->rxp2 && ms->rxp3) + { + r = sf_detect(&ms->rd,putlin,ZT_CHUNKSIZE,ms->rxp1, + ms->rxp2,ms->rxp3); + /* Convert back */ + for(x=0;xrd.lastdetect) + { + if (((r == 2) && !(ms->toneflags & ZT_REVERSE_RXTONE)) || + ((r == 1) && (ms->toneflags & ZT_REVERSE_RXTONE))) + { + __qevent(ms,ZT_EVENT_RINGOFFHOOK); + } + else + { + __qevent(ms,ZT_EVENT_ONHOOK); + } + ms->rd.lastdetect = r; + } + } + } + + if (!(ms->flags & ZT_FLAG_PSEUDO)) { + memcpy(ms->putlin, putlin, ZT_CHUNKSIZE * sizeof(short)); + memcpy(ms->putraw, rxb, ZT_CHUNKSIZE); + } + + /* Take the rxc, twiddle it for conferencing if appropriate and put it + back */ + if ((!ms->confmute && !ms->afterdialingtimer) || + (ms->flags & ZT_FLAG_PSEUDO)) { + switch(ms->confmode & ZT_CONF_MODE_MASK) { + case ZT_CONF_NORMAL: /* Normal mode */ + /* Do nothing. rx goes output */ + break; + case ZT_CONF_MONITOR: /* Monitor a channel's rx mode */ + /* if not a pseudo-channel, ignore */ + if (!(ms->flags & ZT_FLAG_PSEUDO)) break; + /* Add monitored channel */ + if (chans[ms->confna]->flags & ZT_FLAG_PSEUDO) { + ACSS(putlin, chans[ms->confna]->getlin); + } else { + ACSS(putlin, chans[ms->confna]->putlin); + } + /* Convert back */ + for(x=0;xflags & ZT_FLAG_PSEUDO)) break; + /* Add monitored channel */ + if (chans[ms->confna]->flags & ZT_FLAG_PSEUDO) { + ACSS(putlin, chans[ms->confna]->putlin); + } else { + ACSS(putlin, chans[ms->confna]->getlin); + } + /* Convert back */ + for(x=0;xflags & ZT_FLAG_PSEUDO)) break; + /* Note: Technically, saturation should be done at + the end of the whole addition, but for performance + reasons, we don't do that. Besides, it only matters + when you're so loud you're clipping anyway */ + ACSS(putlin, chans[ms->confna]->getlin); + ACSS(putlin, chans[ms->confna]->putlin); + /* Convert back */ + for(x=0;xflags & ZT_FLAG_PSEUDO)) + break; + + if (!chans[ms->confna]->readchunkpreec) + break; + + /* Add monitored channel */ + ACSS(putlin, chans[ms->confna]->flags & ZT_FLAG_PSEUDO ? + chans[ms->confna]->getlin : chans[ms->confna]->readchunkpreec); + for (x = 0; x < ZT_CHUNKSIZE; x++) + rxb[x] = ZT_LIN2X(putlin[x], ms); + + break; + case ZT_CONF_MONITOR_TX_PREECHO: /* Monitor a channel's tx mode */ + /* if not a pseudo-channel, ignore */ + if (!(ms->flags & ZT_FLAG_PSEUDO)) + break; + + if (!chans[ms->confna]->readchunkpreec) + break; + + /* Add monitored channel */ + ACSS(putlin, chans[ms->confna]->flags & ZT_FLAG_PSEUDO ? + chans[ms->confna]->readchunkpreec : chans[ms->confna]->getlin); + for (x = 0; x < ZT_CHUNKSIZE; x++) + rxb[x] = ZT_LIN2X(putlin[x], ms); + + break; + case ZT_CONF_MONITORBOTH_PREECHO: /* Monitor a channel's tx and rx mode */ + /* if not a pseudo-channel, ignore */ + if (!(ms->flags & ZT_FLAG_PSEUDO)) + break; + + if (!chans[ms->confna]->readchunkpreec) + break; + + /* Note: Technically, saturation should be done at + the end of the whole addition, but for performance + reasons, we don't do that. Besides, it only matters + when you're so loud you're clipping anyway */ + ACSS(putlin, chans[ms->confna]->getlin); + ACSS(putlin, chans[ms->confna]->readchunkpreec); + for (x = 0; x < ZT_CHUNKSIZE; x++) + rxb[x] = ZT_LIN2X(putlin[x], ms); + + break; + case ZT_CONF_REALANDPSEUDO: + /* do normal conf mode processing */ + if (ms->confmode & ZT_CONF_TALKER) { + /* Store temp value */ + memcpy(k, putlin, ZT_CHUNKSIZE * sizeof(short)); + /* Add conf value */ + ACSS(k, conf_sums_next[ms->_confn]); + /* get amount actually added */ + memcpy(ms->conflast, k, ZT_CHUNKSIZE * sizeof(short)); + SCSS(ms->conflast, conf_sums_next[ms->_confn]); + /* Really add in new value */ + ACSS(conf_sums_next[ms->_confn], ms->conflast); + } else memset(ms->conflast, 0, ZT_CHUNKSIZE * sizeof(short)); + /* do the pseudo-channel part processing */ + memset(putlin, 0, ZT_CHUNKSIZE * sizeof(short)); + if (ms->confmode & ZT_CONF_PSEUDO_LISTENER) { + /* Subtract out previous last sample written to conf */ + SCSS(putlin, ms->conflast2); + /* Add in conference */ + ACSS(putlin, conf_sums[ms->_confn]); + } + /* Convert back */ + for(x=0;xflags & ZT_FLAG_PSEUDO) /* if a pseudo-channel */ + { + if (ms->confmode & ZT_CONF_LISTENER) { + /* Subtract out last sample written to conf */ + SCSS(putlin, ms->conflast); + /* Add in conference */ + ACSS(putlin, conf_sums[ms->_confn]); + } + /* Convert back */ + for(x=0;xgetlin, putlin, ZT_CHUNKSIZE * sizeof(short)); + break; + } + /* fall through */ + case ZT_CONF_CONFANN: /* Conference with announce */ + if (ms->confmode & ZT_CONF_TALKER) { + /* Store temp value */ + memcpy(k, putlin, ZT_CHUNKSIZE * sizeof(short)); + /* Add conf value */ + ACSS(k, conf_sums_next[ms->_confn]); + /* get amount actually added */ + memcpy(ms->conflast, k, ZT_CHUNKSIZE * sizeof(short)); + SCSS(ms->conflast, conf_sums_next[ms->_confn]); + /* Really add in new value */ + ACSS(conf_sums_next[ms->_confn], ms->conflast); + } else + memset(ms->conflast, 0, ZT_CHUNKSIZE * sizeof(short)); + /* rxc unmodified */ + break; + case ZT_CONF_CONFMON: + case ZT_CONF_CONFANNMON: + if (ms->confmode & ZT_CONF_TALKER) { + /* Store temp value */ + memcpy(k, putlin, ZT_CHUNKSIZE * sizeof(short)); + /* Subtract last value */ + SCSS(conf_sums[ms->_confn], ms->conflast); + /* Add conf value */ + ACSS(k, conf_sums[ms->_confn]); + /* get amount actually added */ + memcpy(ms->conflast, k, ZT_CHUNKSIZE * sizeof(short)); + SCSS(ms->conflast, conf_sums[ms->_confn]); + /* Really add in new value */ + ACSS(conf_sums[ms->_confn], ms->conflast); + } else + memset(ms->conflast, 0, ZT_CHUNKSIZE * sizeof(short)); + for (x=0;x_confn][x], ms); + break; + case ZT_CONF_DIGITALMON: + /* if not a pseudo-channel, ignore */ + if (!(ms->flags & ZT_FLAG_PSEUDO)) break; + /* Add monitored channel */ + if (chans[ms->confna]->flags & ZT_FLAG_PSEUDO) { + memcpy(rxb, chans[ms->confna]->getraw, ZT_CHUNKSIZE); + } else { + memcpy(rxb, chans[ms->confna]->putraw, ZT_CHUNKSIZE); + } + break; + } + } +} + +/* HDLC (or other) receiver buffer functions for read side */ +static inline void __putbuf_chunk(struct zt_chan *ss, unsigned char *rxb, int bytes) +{ + /* We transmit data from our master channel */ + /* Called with ss->lock held */ + struct zt_chan *ms = ss->master; + /* Our receive buffer */ + unsigned char *buf; +#if defined(CONFIG_ZAPATA_NET) || defined(CONFIG_ZAPATA_PPP) + /* SKB for receiving network stuff */ + struct sk_buff *skb=NULL; +#endif + int oldbuf; + int eof=0; + int abort=0; + int res; + int left, x; + + while(bytes) { +#if defined(CONFIG_ZAPATA_NET) || defined(CONFIG_ZAPATA_PPP) + skb = NULL; +#endif + abort = 0; + eof = 0; + /* Next, figure out if we've got a buffer to receive into */ + if (ms->inreadbuf > -1) { + /* Read into the current buffer */ + buf = ms->readbuf[ms->inreadbuf]; + left = ms->blocksize - ms->readidx[ms->inreadbuf]; + if (left > bytes) + left = bytes; + if (ms->flags & ZT_FLAG_HDLC) { + for (x=0;xrxhdlc, *(rxb++)); + bytes--; + res = fasthdlc_rx_run(&ms->rxhdlc); + /* If there is nothing there, continue */ + if (res & RETURN_EMPTY_FLAG) + continue; + else if (res & RETURN_COMPLETE_FLAG) { + /* Only count this if it's a non-empty frame */ + if (ms->readidx[ms->inreadbuf]) { + if ((ms->flags & ZT_FLAG_FCS) && (ms->infcs != PPP_GOODFCS)) { + abort = ZT_EVENT_BADFCS; + } else + eof=1; + break; + } + continue; + } else if (res & RETURN_DISCARD_FLAG) { + /* This could be someone idling with + "idle" instead of "flag" */ + if (!ms->readidx[ms->inreadbuf]) + continue; + abort = ZT_EVENT_ABORT; + break; + } else { + unsigned char rxc; + rxc = res; + ms->infcs = PPP_FCS(ms->infcs, rxc); + buf[ms->readidx[ms->inreadbuf]++] = rxc; + /* Pay attention to the possibility of an overrun */ + if (ms->readidx[ms->inreadbuf] >= ms->blocksize) { + if (!ss->span->alarms) + printk(KERN_WARNING "HDLC Receiver overrun on channel %s (master=%s)\n", ss->name, ss->master->name); + abort=ZT_EVENT_OVERRUN; + /* Force the HDLC state back to frame-search mode */ + ms->rxhdlc.state = 0; + ms->rxhdlc.bits = 0; + ms->readidx[ms->inreadbuf]=0; + break; + } + } + } + } else { + /* Not HDLC */ + memcpy(buf + ms->readidx[ms->inreadbuf], rxb, left); + rxb += left; + ms->readidx[ms->inreadbuf] += left; + bytes -= left; + /* End of frame is decided by block size of 'N' */ + eof = (ms->readidx[ms->inreadbuf] >= ms->blocksize); + if (eof && (ss->flags & ZT_FLAG_NOSTDTXRX)) { + eof = 0; + abort = ZT_EVENT_OVERRUN; + } + } + if (eof) { + /* Finished with this buffer, try another. */ + oldbuf = ms->inreadbuf; + ms->infcs = PPP_INITFCS; + ms->readn[ms->inreadbuf] = ms->readidx[ms->inreadbuf]; +#ifdef CONFIG_ZAPATA_DEBUG + printk("EOF, len is %d\n", ms->readn[ms->inreadbuf]); +#endif +#if defined(CONFIG_ZAPATA_NET) || defined(CONFIG_ZAPATA_PPP) + if (ms->flags & (ZT_FLAG_NETDEV | ZT_FLAG_PPP)) { +#ifdef CONFIG_ZAPATA_NET +#endif /* CONFIG_ZAPATA_NET */ + /* Our network receiver logic is MUCH + different. We actually only use a single + buffer */ + if (ms->readn[ms->inreadbuf] > 1) { + /* Drop the FCS */ + ms->readn[ms->inreadbuf] -= 2; + /* Allocate an SKB */ +#ifdef CONFIG_ZAPATA_PPP + if (!ms->do_ppp_error) +#endif + skb = dev_alloc_skb(ms->readn[ms->inreadbuf]); + if (skb) { + /* XXX Get rid of this memcpy XXX */ + memcpy(skb->data, ms->readbuf[ms->inreadbuf], ms->readn[ms->inreadbuf]); + skb_put(skb, ms->readn[ms->inreadbuf]); +#ifdef CONFIG_ZAPATA_NET + if (ms->flags & ZT_FLAG_NETDEV) { +#ifdef LINUX26 + struct net_device_stats *stats = hdlc_stats(ms->hdlcnetdev->netdev); +#else /* LINUX26 */ + struct net_device_stats *stats = &ms->hdlcnetdev->netdev.stats; +#endif /* LINUX26 */ + stats->rx_packets++; + stats->rx_bytes += ms->readn[ms->inreadbuf]; + } +#endif + + } else { +#ifdef CONFIG_ZAPATA_NET + if (ms->flags & ZT_FLAG_NETDEV) { +#ifdef LINUX26 + struct net_device_stats *stats = hdlc_stats(ms->hdlcnetdev->netdev); +#else /* LINUX26 */ + struct net_device_stats *stats = &ms->hdlcnetdev->netdev.stats; +#endif /* LINUX26 */ + stats->rx_dropped++; + } +#endif +#ifdef CONFIG_ZAPATA_PPP + if (ms->flags & ZT_FLAG_PPP) { + abort = ZT_EVENT_OVERRUN; + } +#endif +#if 1 +#ifdef CONFIG_ZAPATA_PPP + if (!ms->do_ppp_error) +#endif + printk("Memory squeeze, dropped one\n"); +#endif + } + } + /* We don't cycle through buffers, just + reuse the same one */ + ms->readn[ms->inreadbuf] = 0; + ms->readidx[ms->inreadbuf] = 0; + } else +#endif + { + ms->inreadbuf = (ms->inreadbuf + 1) % ms->numbufs; + if (ms->inreadbuf == ms->outreadbuf) { + /* Whoops, we're full, and have no where else + to store into at the moment. We'll drop it + until there's a buffer available */ +#ifdef CONFIG_ZAPATA_DEBUG + printk("Out of storage space\n"); +#endif + ms->inreadbuf = -1; + /* Enable the receiver in case they've got POLICY_WHEN_FULL */ + ms->rxdisable = 0; + } + if (ms->outreadbuf < 0) { /* start out buffer if not already */ + ms->outreadbuf = oldbuf; + } +/* In the very orignal driver, it was quite well known to me (Jim) that there +was a possibility that a channel sleeping on a receive block needed to +be potentially woken up EVERY time a buffer was filled, not just on the first +one, because if only done on the first one there is a slight timing potential +of missing the wakeup (between where it senses the (lack of) active condition +(with interrupts disabled) and where it does the sleep (interrupts enabled) +in the read or iomux call, etc). That is why the read and iomux calls start +with an infinite loop that gets broken out of upon an active condition, +otherwise keeps sleeping and looking. The part in this code got "optimized" +out in the later versions, and is put back now. */ + if (!ms->rxdisable) { /* if receiver enabled */ + /* Notify a blocked reader that there is data available + to be read, unless we're waiting for it to be full */ +#ifdef CONFIG_ZAPATA_DEBUG + printk("Notifying reader data in block %d\n", oldbuf); +#endif + wake_up_interruptible(&ms->readbufq); + wake_up_interruptible(&ms->sel); + if (ms->iomask & ZT_IOMUX_READ) + wake_up_interruptible(&ms->eventbufq); + } + } + } + if (abort) { + /* Start over reading frame */ + ms->readidx[ms->inreadbuf] = 0; + ms->infcs = PPP_INITFCS; + +#ifdef CONFIG_ZAPATA_NET + if (ms->flags & ZT_FLAG_NETDEV) { +#ifdef LINUX26 + struct net_device_stats *stats = hdlc_stats(ms->hdlcnetdev->netdev); +#else /* LINUX26 */ + struct net_device_stats *stats = &ms->hdlcnetdev->netdev.stats; +#endif /* LINUX26 */ + stats->rx_errors++; + if (abort == ZT_EVENT_OVERRUN) + stats->rx_over_errors++; + if (abort == ZT_EVENT_BADFCS) + stats->rx_crc_errors++; + if (abort == ZT_EVENT_ABORT) + stats->rx_frame_errors++; + } else +#endif +#ifdef CONFIG_ZAPATA_PPP + if (ms->flags & ZT_FLAG_PPP) { + ms->do_ppp_error = 1; + tasklet_schedule(&ms->ppp_calls); + } else +#endif + + if ((ms->flags & ZT_FLAG_OPEN) && !ss->span->alarms) + /* Notify the receiver... */ + __qevent(ss->master, abort); +#if 0 + printk("torintr_receive: Aborted %d bytes of frame on %d\n", amt, ss->master); +#endif + + } + } else /* No place to receive -- drop on the floor */ + break; +#ifdef CONFIG_ZAPATA_NET + if (skb && (ms->flags & ZT_FLAG_NETDEV)) +#ifdef NEW_HDLC_INTERFACE + { +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22) + skb->mac.raw = skb->data; +#else + skb_reset_mac_header(skb); +#endif + skb->dev = ztchan_to_dev(ms); +#ifdef ZAP_HDLC_TYPE_TRANS + skb->protocol = hdlc_type_trans(skb, ztchan_to_dev(ms)); +#else + skb->protocol = htons (ETH_P_HDLC); +#endif + netif_rx(skb); + } +#else + hdlc_netif_rx(&ms->hdlcnetdev->netdev, skb); +#endif +#endif +#ifdef CONFIG_ZAPATA_PPP + if (skb && (ms->flags & ZT_FLAG_PPP)) { + unsigned char *tmp; + tmp = skb->data; + skb_pull(skb, 2); + /* Make sure that it's addressed to ALL STATIONS and UNNUMBERED */ + if (!tmp || (tmp[0] != 0xff) || (tmp[1] != 0x03)) { + /* Invalid SKB -- drop */ + if (tmp) + printk("Received invalid SKB (%02x, %02x)\n", tmp[0], tmp[1]); + dev_kfree_skb_irq(skb); + } else { + skb_queue_tail(&ms->ppp_rq, skb); + tasklet_schedule(&ms->ppp_calls); + } + } +#endif + } +} + +static inline void __zt_putbuf_chunk(struct zt_chan *ss, unsigned char *rxb) +{ + __putbuf_chunk(ss, rxb, ZT_CHUNKSIZE); +} + +static void __zt_hdlc_abort(struct zt_chan *ss, int event) +{ + if (ss->inreadbuf >= 0) + ss->readidx[ss->inreadbuf] = 0; + if ((ss->flags & ZT_FLAG_OPEN) && !ss->span->alarms) + __qevent(ss->master, event); +} + +extern void zt_hdlc_abort(struct zt_chan *ss, int event) +{ + unsigned long flags; + spin_lock_irqsave(&ss->lock, flags); + __zt_hdlc_abort(ss, event); + spin_unlock_irqrestore(&ss->lock, flags); +} + +extern void zt_hdlc_putbuf(struct zt_chan *ss, unsigned char *rxb, int bytes) +{ + unsigned long flags; + int res; + int left; + + spin_lock_irqsave(&ss->lock, flags); + if (ss->inreadbuf < 0) { +#ifdef CONFIG_ZAPATA_DEBUG + printk("No place to receive HDLC frame\n"); +#endif + spin_unlock_irqrestore(&ss->lock, flags); + return; + } + /* Read into the current buffer */ + left = ss->blocksize - ss->readidx[ss->inreadbuf]; + if (left > bytes) + left = bytes; + if (left > 0) { + memcpy(ss->readbuf[ss->inreadbuf] + ss->readidx[ss->inreadbuf], rxb, left); + rxb += left; + ss->readidx[ss->inreadbuf] += left; + bytes -= left; + } + /* Something isn't fit into buffer */ + if (bytes) { +#ifdef CONFIG_ZAPATA_DEBUG + printk("HDLC frame isn't fit into buffer space\n"); +#endif + __zt_hdlc_abort(ss, ZT_EVENT_OVERRUN); + } + res = left; + spin_unlock_irqrestore(&ss->lock, flags); +} + +extern void zt_hdlc_finish(struct zt_chan *ss) +{ + int oldreadbuf; + unsigned long flags; + + spin_lock_irqsave(&ss->lock, flags); + + if ((oldreadbuf = ss->inreadbuf) < 0) { +#ifdef CONFIG_ZAPATA_DEBUG + printk("No buffers to finish\n"); +#endif + spin_unlock_irqrestore(&ss->lock, flags); + return; + } + + if (!ss->readidx[ss->inreadbuf]) { +#ifdef CONFIG_ZAPATA_DEBUG + printk("Empty HDLC frame received\n"); +#endif + spin_unlock_irqrestore(&ss->lock, flags); + return; + } + + ss->readn[ss->inreadbuf] = ss->readidx[ss->inreadbuf]; + ss->inreadbuf = (ss->inreadbuf + 1) % ss->numbufs; + if (ss->inreadbuf == ss->outreadbuf) { + ss->inreadbuf = -1; +#ifdef CONFIG_ZAPATA_DEBUG + printk("Notifying reader data in block %d\n", oldreadbuf); +#endif + ss->rxdisable = 0; + } + if (ss->outreadbuf < 0) { + ss->outreadbuf = oldreadbuf; + } + + if (!ss->rxdisable) { + wake_up_interruptible(&ss->readbufq); + wake_up_interruptible(&ss->sel); + if (ss->iomask & ZT_IOMUX_READ) + wake_up_interruptible(&ss->eventbufq); + } + spin_unlock_irqrestore(&ss->lock, flags); +} + +/* Returns 1 if EOF, 0 if data is still in frame, -1 if EOF and no buffers left */ +extern int zt_hdlc_getbuf(struct zt_chan *ss, unsigned char *bufptr, unsigned int *size) +{ + unsigned char *buf; + unsigned long flags; + int left = 0; + int res; + int oldbuf; + + spin_lock_irqsave(&ss->lock, flags); + if (ss->outwritebuf > -1) { + buf = ss->writebuf[ss->outwritebuf]; + left = ss->writen[ss->outwritebuf] - ss->writeidx[ss->outwritebuf]; + /* Strip off the empty HDLC CRC end */ + left -= 2; + if (left <= *size) { + *size = left; + res = 1; + } else + res = 0; + + memcpy(bufptr, &buf[ss->writeidx[ss->outwritebuf]], *size); + ss->writeidx[ss->outwritebuf] += *size; + + if (res) { + /* Rotate buffers */ + oldbuf = ss->outwritebuf; + ss->writeidx[oldbuf] = 0; + ss->writen[oldbuf] = 0; + ss->outwritebuf = (ss->outwritebuf + 1) % ss->numbufs; + if (ss->outwritebuf == ss->inwritebuf) { + ss->outwritebuf = -1; + if (ss->iomask & (ZT_IOMUX_WRITE | ZT_IOMUX_WRITEEMPTY)) + wake_up_interruptible(&ss->eventbufq); + /* If we're only supposed to start when full, disable the transmitter */ + if (ss->txbufpolicy == ZT_POLICY_WHEN_FULL) + ss->txdisable = 1; + res = -1; + } + + if (ss->inwritebuf < 0) + ss->inwritebuf = oldbuf; + + if (!(ss->flags & (ZT_FLAG_NETDEV | ZT_FLAG_PPP))) { + wake_up_interruptible(&ss->writebufq); + wake_up_interruptible(&ss->sel); + if ((ss->iomask & ZT_IOMUX_WRITE) && (res >= 0)) + wake_up_interruptible(&ss->eventbufq); + } + } + } else { + res = -1; + *size = 0; + } + spin_unlock_irqrestore(&ss->lock, flags); + + return res; +} + + +static void process_timers(void) +{ + unsigned long flags; + struct zt_timer *cur; + spin_lock_irqsave(&zaptimerlock, flags); + cur = zaptimers; + while(cur) { + if (cur->ms) { + cur->pos -= ZT_CHUNKSIZE; + if (cur->pos <= 0) { + cur->tripped++; + cur->pos = cur->ms; + wake_up_interruptible(&cur->sel); + } + } + cur = cur->next; + } + spin_unlock_irqrestore(&zaptimerlock, flags); +} + +static unsigned int zt_timer_poll(struct file *file, struct poll_table_struct *wait_table) +{ + struct zt_timer *timer = file->private_data; + unsigned long flags; + int ret = 0; + if (timer) { + poll_wait(file, &timer->sel, wait_table); + spin_lock_irqsave(&zaptimerlock, flags); + if (timer->tripped || timer->ping) + ret |= POLLPRI; + spin_unlock_irqrestore(&zaptimerlock, flags); + } else + ret = -EINVAL; + return ret; +} + +/* device poll routine */ +static unsigned int +zt_chan_poll(struct file *file, struct poll_table_struct *wait_table, int unit) +{ + + struct zt_chan *chan = chans[unit]; + int ret; + unsigned long flags; + + /* do the poll wait */ + if (chan) { + poll_wait(file, &chan->sel, wait_table); + ret = 0; /* start with nothing to return */ + spin_lock_irqsave(&chan->lock, flags); + /* if at least 1 write buffer avail */ + if (chan->inwritebuf > -1) { + ret |= POLLOUT | POLLWRNORM; + } + if ((chan->outreadbuf > -1) && !chan->rxdisable) { + ret |= POLLIN | POLLRDNORM; + } + if (chan->eventoutidx != chan->eventinidx) + { + /* Indicate an exception */ + ret |= POLLPRI; + } + spin_unlock_irqrestore(&chan->lock, flags); + } else + ret = -EINVAL; + return(ret); /* return what we found */ +} + +static int zt_mmap(struct file *file, struct vm_area_struct *vm) +{ + int unit = UNIT(file); + if (unit == 250) + return zt_transcode_fops->mmap(file, vm); + return -ENOSYS; +} + +static unsigned int zt_poll(struct file *file, struct poll_table_struct *wait_table) +{ + int unit = UNIT(file); + struct zt_chan *chan; + + if (!unit) + return -EINVAL; + + if (unit == 250) + return zt_transcode_fops->poll(file, wait_table); + + if (unit == 253) + return zt_timer_poll(file, wait_table); + + if (unit == 254) { + chan = file->private_data; + if (!chan) + return -EINVAL; + return zt_chan_poll(file, wait_table,chan->channo); + } + if (unit == 255) { + chan = file->private_data; + if (!chan) { + printk("No pseudo channel structure to read?\n"); + return -EINVAL; + } + return zt_chan_poll(file, wait_table, chan->channo); + } + return zt_chan_poll(file, wait_table, unit); +} + +static void __zt_transmit_chunk(struct zt_chan *chan, unsigned char *buf) +{ + unsigned char silly[ZT_CHUNKSIZE]; + /* Called with chan->lock locked */ +#ifdef OPTIMIZE_CHANMUTE + if(likely(chan->chanmute)) + return; +#endif + if (!buf) + buf = silly; + __zt_getbuf_chunk(chan, buf); + + if ((chan->flags & ZT_FLAG_AUDIO) || (chan->confmode)) { +#ifdef CONFIG_ZAPTEL_MMX + zt_kernel_fpu_begin(); +#endif + __zt_process_getaudio_chunk(chan, buf); +#ifdef CONFIG_ZAPTEL_MMX + kernel_fpu_end(); +#endif + } +} + +static inline void __zt_real_transmit(struct zt_chan *chan) +{ + /* Called with chan->lock held */ +#ifdef OPTIMIZE_CHANMUTE + if(likely(chan->chanmute)) + return; +#endif + if (chan->confmode) { + /* Pull queued data off the conference */ + __buf_pull(&chan->confout, chan->writechunk, chan, "zt_real_transmit"); + } else { + __zt_transmit_chunk(chan, chan->writechunk); + } +} + +static void __zt_getempty(struct zt_chan *ms, unsigned char *buf) +{ + int bytes = ZT_CHUNKSIZE; + int left; + unsigned char *txb = buf; + int x; + short getlin; + /* Called with ms->lock held */ + + while(bytes) { + /* Receive silence, or tone */ + if (ms->curtone) { + left = ms->curtone->tonesamples - ms->tonep; + if (left > bytes) + left = bytes; + for (x=0;xts, ms->curtone); + *(txb++) = ZT_LIN2X(getlin, ms); + } + ms->tonep+=left; + bytes -= left; + if (ms->tonep >= ms->curtone->tonesamples) { + struct zt_tone *last; + /* Go to the next sample of the tone */ + ms->tonep = 0; + last = ms->curtone; + ms->curtone = ms->curtone->next; + if (!ms->curtone) { + /* No more tones... Is this dtmf or mf? If so, go to the next digit */ + if (ms->dialing) + __do_dtmf(ms); + } else { + if (last != ms->curtone) + zt_init_tone_state(&ms->ts, ms->curtone); + } + } + } else { + /* Use silence */ + memset(txb, ZT_LIN2X(0, ms), bytes); + bytes = 0; + } + } + +} + +static void __zt_receive_chunk(struct zt_chan *chan, unsigned char *buf) +{ + /* Receive chunk of audio -- called with chan->lock held */ + unsigned char waste[ZT_CHUNKSIZE]; + +#ifdef OPTIMIZE_CHANMUTE + if(likely(chan->chanmute)) + return; +#endif + if (!buf) { + memset(waste, ZT_LIN2X(0, chan), sizeof(waste)); + buf = waste; + } + if ((chan->flags & ZT_FLAG_AUDIO) || (chan->confmode)) { +#ifdef CONFIG_ZAPTEL_MMX + zt_kernel_fpu_begin(); +#endif + __zt_process_putaudio_chunk(chan, buf); +#ifdef CONFIG_ZAPTEL_MMX + kernel_fpu_end(); +#endif + } + __zt_putbuf_chunk(chan, buf); +} + +static inline void __zt_real_receive(struct zt_chan *chan) +{ + /* Called with chan->lock held */ +#ifdef OPTIMIZE_CHANMUTE + if(likely(chan->chanmute)) + return; +#endif + if (chan->confmode) { + /* Load into queue if we have space */ + __buf_push(&chan->confin, chan->readchunk, "zt_real_receive"); + } else { + __zt_receive_chunk(chan, chan->readchunk); + } +} + +int zt_transmit(struct zt_span *span) +{ + int x,y,z; + unsigned long flags; + +#if 1 + for (x=0;xchannels;x++) { + spin_lock_irqsave(&span->chans[x].lock, flags); + if (span->chans[x].flags & ZT_FLAG_NOSTDTXRX) { + spin_unlock_irqrestore(&span->chans[x].lock, flags); + continue; + } + if (&span->chans[x] == span->chans[x].master) { + if (span->chans[x].otimer) { + span->chans[x].otimer -= ZT_CHUNKSIZE; + if (span->chans[x].otimer <= 0) { + __rbs_otimer_expire(&span->chans[x]); + } + } + if (span->chans[x].flags & ZT_FLAG_AUDIO) { + __zt_real_transmit(&span->chans[x]); + } else { + if (span->chans[x].nextslave) { + u_char data[ZT_CHUNKSIZE]; + int pos=ZT_CHUNKSIZE; + /* Process master/slaves one way */ + for (y=0;ychans[x], data); + pos = 0; + } + span->chans[z].writechunk[y] = data[pos++]; + z = span->chans[z].nextslave; + } while(z); + } + } else { + /* Process independents elsewise */ + __zt_real_transmit(&span->chans[x]); + } + } + if (span->chans[x].sig == ZT_SIG_DACS_RBS) { + if (chans[span->chans[x].confna]) { + /* Just set bits for our destination */ + if (span->chans[x].txsig != chans[span->chans[x].confna]->rxsig) { + span->chans[x].txsig = chans[span->chans[x].confna]->rxsig; + span->rbsbits(&span->chans[x], chans[span->chans[x].confna]->rxsig); + } + } + } + + } + spin_unlock_irqrestore(&span->chans[x].lock, flags); + } + if (span->mainttimer) { + span->mainttimer -= ZT_CHUNKSIZE; + if (span->mainttimer <= 0) { + span->mainttimer = 0; + if (span->maint) + span->maint(span, ZT_MAINT_LOOPSTOP); + span->maintstat = 0; + wake_up_interruptible(&span->maintq); + } + } +#endif + return 0; +} + +int zt_receive(struct zt_span *span) +{ + int x,y,z; + unsigned long flags, flagso; + +#if 1 +#ifdef CONFIG_ZAPTEL_WATCHDOG + span->watchcounter--; +#endif + for (x=0;xchannels;x++) { + if (span->chans[x].master == &span->chans[x]) { + spin_lock_irqsave(&span->chans[x].lock, flags); + if (span->chans[x].nextslave) { + /* Must process each slave at the same time */ + u_char data[ZT_CHUNKSIZE]; + int pos = 0; + for (y=0;ychans[z].readchunk[y]; + if (pos == ZT_CHUNKSIZE) { + if(!(span->chans[x].flags & ZT_FLAG_NOSTDTXRX)) + __zt_receive_chunk(&span->chans[x], data); + pos = 0; + } + z=span->chans[z].nextslave; + } while(z); + } + } else { + /* Process a normal channel */ + if (!(span->chans[x].flags & ZT_FLAG_NOSTDTXRX)) + __zt_real_receive(&span->chans[x]); + } + if (span->chans[x].itimer) { + span->chans[x].itimer -= ZT_CHUNKSIZE; + if (span->chans[x].itimer <= 0) { + rbs_itimer_expire(&span->chans[x]); + } + } + if (span->chans[x].ringdebtimer) + span->chans[x].ringdebtimer--; + if (span->chans[x].sig & __ZT_SIG_FXS) { + if (span->chans[x].rxhooksig == ZT_RXSIG_RING) + span->chans[x].ringtrailer = ZT_RINGTRAILER; + else if (span->chans[x].ringtrailer) { + span->chans[x].ringtrailer-= ZT_CHUNKSIZE; + /* See if RING trailer is expired */ + if (!span->chans[x].ringtrailer && !span->chans[x].ringdebtimer) + __qevent(&span->chans[x],ZT_EVENT_RINGOFFHOOK); + } + } + if (span->chans[x].pulsetimer) + { + span->chans[x].pulsetimer--; + if (span->chans[x].pulsetimer <= 0) + { + if (span->chans[x].pulsecount) + { + if (span->chans[x].pulsecount > 12) { + + printk("Got pulse digit %d on %s???\n", + span->chans[x].pulsecount, + span->chans[x].name); + } else if (span->chans[x].pulsecount > 11) { + __qevent(&span->chans[x], ZT_EVENT_PULSEDIGIT | '#'); + } else if (span->chans[x].pulsecount > 10) { + __qevent(&span->chans[x], ZT_EVENT_PULSEDIGIT | '*'); + } else if (span->chans[x].pulsecount > 9) { + __qevent(&span->chans[x], ZT_EVENT_PULSEDIGIT | '0'); + } else { + __qevent(&span->chans[x], ZT_EVENT_PULSEDIGIT | ('0' + + span->chans[x].pulsecount)); + } + span->chans[x].pulsecount = 0; + } + } + } + spin_unlock_irqrestore(&span->chans[x].lock, flags); + } + } + + if (span == master) { + /* Hold the big zap lock for the duration of major + activities which touch all sorts of channels */ + spin_lock_irqsave(&bigzaplock, flagso); + /* Process any timers */ + process_timers(); + /* If we have dynamic stuff, call the ioctl with 0,0 parameters to + make it run */ + if (zt_dynamic_ioctl) + zt_dynamic_ioctl(0,0); + for (x=1;xconfmode && !(chans[x]->flags & ZT_FLAG_PSEUDO)) { + u_char *data; + spin_lock_irqsave(&chans[x]->lock, flags); + data = __buf_peek(&chans[x]->confin); + __zt_receive_chunk(chans[x], data); + if (data) + __buf_pull(&chans[x]->confin, NULL,chans[x], "confreceive"); + spin_unlock_irqrestore(&chans[x]->lock, flags); + } + } + /* This is the master channel, so make things switch over */ + rotate_sums(); + /* do all the pseudo and/or conferenced channel receives (getbuf's) */ + for (x=1;xflags & ZT_FLAG_PSEUDO)) { + spin_lock_irqsave(&chans[x]->lock, flags); + __zt_transmit_chunk(chans[x], NULL); + spin_unlock_irqrestore(&chans[x]->lock, flags); + } + } + if (maxlinks) { +#ifdef CONFIG_ZAPTEL_MMX + zt_kernel_fpu_begin(); +#endif + /* process all the conf links */ + for(x = 1; x <= maxlinks; x++) { + /* if we have a destination conf */ + if (((z = confalias[conf_links[x].dst]) > 0) && + ((y = confalias[conf_links[x].src]) > 0)) { + ACSS(conf_sums[z], conf_sums[y]); + } + } +#ifdef CONFIG_ZAPTEL_MMX + kernel_fpu_end(); +#endif + } + /* do all the pseudo/conferenced channel transmits (putbuf's) */ + for (x=1;xflags & ZT_FLAG_PSEUDO)) { + unsigned char tmp[ZT_CHUNKSIZE]; + spin_lock_irqsave(&chans[x]->lock, flags); + __zt_getempty(chans[x], tmp); + __zt_receive_chunk(chans[x], tmp); + spin_unlock_irqrestore(&chans[x]->lock, flags); + } + } + for (x=1;xconfmode && !(chans[x]->flags & ZT_FLAG_PSEUDO)) { + u_char *data; + spin_lock_irqsave(&chans[x]->lock, flags); + data = __buf_pushpeek(&chans[x]->confout); + __zt_transmit_chunk(chans[x], data); + if (data) + __buf_push(&chans[x]->confout, NULL, "conftransmit"); + spin_unlock_irqrestore(&chans[x]->lock, flags); + } + } +#ifdef ZAPTEL_SYNC_TICK + for (x=0;xsync_tick) + s->sync_tick(s, s == master); + } +#endif + spin_unlock_irqrestore(&bigzaplock, flagso); + } +#endif + return 0; +} + +MODULE_AUTHOR("Mark Spencer "); +MODULE_DESCRIPTION("Zapata Telephony Interface"); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif +#ifdef MODULE_VERSION +MODULE_VERSION(ZAPTEL_VERSION); +#endif + +#ifdef LINUX26 +module_param(debug, int, 0600); +module_param(deftaps, int, 0600); +#else +MODULE_PARM(debug, "i"); +MODULE_PARM(deftaps, "i"); +#endif + +static struct file_operations zt_fops = { + owner: THIS_MODULE, + llseek: NULL, + open: zt_open, + release: zt_release, + ioctl: zt_ioctl, + read: zt_read, + write: zt_write, + poll: zt_poll, + mmap: zt_mmap, + flush: NULL, + fsync: NULL, + fasync: NULL, +}; + +#ifdef CONFIG_ZAPTEL_WATCHDOG +static struct timer_list watchdogtimer; + +static void watchdog_check(unsigned long ignored) +{ + int x; + unsigned long flags; + static int wdcheck=0; + + local_irq_save(flags); + for (x=0;xflags & ZT_FLAG_RUNNING)) { + if (spans[x]->watchcounter == ZT_WATCHDOG_INIT) { + /* Whoops, dead card */ + if ((spans[x]->watchstate == ZT_WATCHSTATE_OK) || + (spans[x]->watchstate == ZT_WATCHSTATE_UNKNOWN)) { + spans[x]->watchstate = ZT_WATCHSTATE_RECOVERING; + if (spans[x]->watchdog) { + printk("Kicking span %s\n", spans[x]->name); + spans[x]->watchdog(spans[x], ZT_WATCHDOG_NOINTS); + } else { + printk("Span %s is dead with no revival\n", spans[x]->name); + spans[x]->watchstate = ZT_WATCHSTATE_FAILED; + } + } + } else { + if ((spans[x]->watchstate != ZT_WATCHSTATE_OK) && + (spans[x]->watchstate != ZT_WATCHSTATE_UNKNOWN)) + printk("Span %s is alive!\n", spans[x]->name); + spans[x]->watchstate = ZT_WATCHSTATE_OK; + } + spans[x]->watchcounter = ZT_WATCHDOG_INIT; + } + } + local_irq_restore(flags); + if (!wdcheck) { + printk("Zaptel watchdog on duty!\n"); + wdcheck=1; + } + mod_timer(&watchdogtimer, jiffies + 2); +} + +static int __init watchdog_init(void) +{ + init_timer(&watchdogtimer); + watchdogtimer.expires = 0; + watchdogtimer.data =0; + watchdogtimer.function = watchdog_check; + /* Run every couple of jiffy or so */ + mod_timer(&watchdogtimer, jiffies + 2); + return 0; +} + +static void __exit watchdog_cleanup(void) +{ + del_timer(&watchdogtimer); +} + +#endif + +int zt_register_chardev(struct zt_chardev *dev) +{ +#ifdef CONFIG_ZAP_UDEV + char udevname[strlen(dev->name) + 3]; + + strcpy(udevname, "zap"); + strcat(udevname, dev->name); + CLASS_DEV_CREATE(zap_class, MKDEV(ZT_MAJOR, dev->minor), NULL, udevname); +#endif /* CONFIG_ZAP_UDEV */ + +#ifdef CONFIG_DEVFS_FS + dev->devfs_handle = devfs_register(zaptel_devfs_dir, dev->name, DEVFS_FL_DEFAULT, ZT_MAJOR, dev->minor, mode, &zt_fops, NULL); +#endif /* CONFIG_DEVFS_FS */ + + return 0; +} + +int zt_unregister_chardev(struct zt_chardev *dev) +{ +#ifdef CONFIG_ZAP_UDEV + class_device_destroy(zap_class, MKDEV(ZT_MAJOR, dev->minor)); +#endif /* CONFIG_ZAP_UDEV */ + +#ifdef CONFIG_DEVFS_FS + devfs_unregister(dev->devfs_handle); +#endif /* CONFIG_DEVFS_FS */ + + return 0; +} + +static int __init zt_init(void) { + int res = 0; + +#ifdef CONFIG_PROC_FS + proc_entries[0] = proc_mkdir("zaptel", NULL); +#endif + +#ifdef CONFIG_ZAP_UDEV /* udev support functions */ + zap_class = class_create(THIS_MODULE, "zaptel"); + CLASS_DEV_CREATE(zap_class, MKDEV(ZT_MAJOR, 253), NULL, "zaptimer"); + CLASS_DEV_CREATE(zap_class, MKDEV(ZT_MAJOR, 254), NULL, "zapchannel"); + CLASS_DEV_CREATE(zap_class, MKDEV(ZT_MAJOR, 255), NULL, "zappseudo"); + CLASS_DEV_CREATE(zap_class, MKDEV(ZT_MAJOR, 0), NULL, "zapctl"); +#endif /* CONFIG_ZAP_UDEV */ + +#ifdef CONFIG_DEVFS_FS + { + umode_t mode = S_IFCHR|S_IRUGO|S_IWUGO; + + devfs_register_chrdev(ZT_MAJOR, "zaptel", &zt_fops); + if (!(zaptel_devfs_dir = devfs_mk_dir(NULL, "zap", NULL))) + return -EBUSY; /* This would be bad */ + timer = devfs_register(zaptel_devfs_dir, "timer", DEVFS_FL_DEFAULT, ZT_MAJOR, 253, mode, &zt_fops, NULL); + channel = devfs_register(zaptel_devfs_dir, "channel", DEVFS_FL_DEFAULT, ZT_MAJOR, 254, mode, &zt_fops, NULL); + pseudo = devfs_register(zaptel_devfs_dir, "pseudo", DEVFS_FL_DEFAULT, ZT_MAJOR, 255, mode, &zt_fops, NULL); + ctl = devfs_register(zaptel_devfs_dir, "ctl", DEVFS_FL_DEFAULT, ZT_MAJOR, 0, mode, &zt_fops, NULL); + } +#else + if ((res = register_chrdev(ZT_MAJOR, "zaptel", &zt_fops))) { + printk(KERN_ERR "Unable to register Zaptel character device handler on %d\n", ZT_MAJOR); + return res; + } +#endif /* CONFIG_DEVFS_FS */ + + printk(KERN_INFO "Zapata Telephony Interface Registered on major %d\n", ZT_MAJOR); + printk(KERN_INFO "Zaptel Version: %s\n", ZAPTEL_VERSION); + echo_can_init(); + zt_conv_init(); + fasthdlc_precalc(); + rotate_sums(); + rwlock_init(&chan_lock); +#ifdef CONFIG_ZAPTEL_WATCHDOG + watchdog_init(); +#endif + return res; +} + +static void __exit zt_cleanup(void) { + int x; + +#ifdef CONFIG_PROC_FS + remove_proc_entry("zaptel", NULL); +#endif + + printk(KERN_INFO "Zapata Telephony Interface Unloaded\n"); + for (x = 0; x < ZT_TONE_ZONE_MAX; x++) { + if (tone_zones[x]) + kfree(tone_zones[x]); + } + +#ifdef CONFIG_DEVFS_FS + devfs_unregister(timer); + devfs_unregister(channel); + devfs_unregister(pseudo); + devfs_unregister(ctl); + devfs_unregister(zaptel_devfs_dir); + devfs_unregister_chrdev(ZT_MAJOR, "zaptel"); +#else +#ifdef CONFIG_ZAP_UDEV + class_device_destroy(zap_class, MKDEV(ZT_MAJOR, 253)); /* timer */ + class_device_destroy(zap_class, MKDEV(ZT_MAJOR, 254)); /* channel */ + class_device_destroy(zap_class, MKDEV(ZT_MAJOR, 255)); /* pseudo */ + class_device_destroy(zap_class, MKDEV(ZT_MAJOR, 0)); /* ctl */ + class_destroy(zap_class); +#endif /* CONFIG_ZAP_UDEV */ + unregister_chrdev(ZT_MAJOR, "zaptel"); +#endif +#ifdef CONFIG_ZAPTEL_WATCHDOG + watchdog_cleanup(); +#endif + + echo_can_shutdown(); +} + +module_init(zt_init); +module_exit(zt_cleanup); diff --git a/kernel/zaptel.h b/kernel/zaptel.h new file mode 100644 index 0000000..53bebf3 --- /dev/null +++ b/kernel/zaptel.h @@ -0,0 +1,2009 @@ +/* + * Zapata Telephony Interface + * + * Written by Mark Spencer + * Based on previous works, designs, and architectures conceived and + * written by Jim Dixon . + * + * Copyright (C) 2001 Jim Dixon / Zapata Telephony. + * Copyright (C) 2001 - 2006 Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _LINUX_ZAPTEL_H +#define _LINUX_ZAPTEL_H + +#ifdef __KERNEL__ +#include "zconfig.h" +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) +#include +#endif +#include +#include + +#ifdef CONFIG_ZAPATA_NET +#include +#endif + +#ifdef CONFIG_ZAPATA_PPP +#include +#include +#include +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#define LINUX26 +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) +#define zap_pci_module pci_register_driver +#else +#define zap_pci_module pci_module_init +#endif + +#ifdef LINUX26 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) +#define ZAP_IRQ_HANDLER(a) static irqreturn_t a(int irq, void *dev_id) +#else +#define ZAP_IRQ_HANDLER(a) static irqreturn_t a(int irq, void *dev_id, struct pt_regs *regs) +#endif +#else +#define ZAP_IRQ_HANDLER(a) static void a(int irq, void *dev_id, struct pt_regs *regs) +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) +#define ZAP_IRQ_SHARED IRQF_SHARED +#define ZAP_IRQ_DISABLED IRQF_DISABLED +#define ZAP_IRQ_SHARED_DISABLED IRQF_SHARED | IRQF_DISABLED +#else +#define ZAP_IRQ_SHARED SA_SHIRQ +#define ZAP_IRQ_DISABLED SA_INTERRUPT +#define ZAP_IRQ_SHARED_DISABLED SA_SHIRQ | SA_INTERRUPT +#endif + +#include "ecdis.h" +#include "fasthdlc.h" + +#ifdef CONFIG_DEVFS_FS +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#include +#else +#undef CONFIG_DEVFS_FS +//#warning "Zaptel doesn't support DEVFS in post 2.4 kernels. Disabling DEVFS in zaptel" +#endif +#endif /* CONFIG_DEVFS_FS */ +#endif /* __KERNEL__ */ + +#include + +#ifndef ELAST +#define ELAST 500 +#endif + +/* Per-span configuration values */ +#define ZT_CONFIG_TXLEVEL 7 /* bits 0-2 are tx level */ + +/* Line configuration */ +/* These apply to T1 */ +#define ZT_CONFIG_D4 (1 << 4) +#define ZT_CONFIG_ESF (1 << 5) +#define ZT_CONFIG_AMI (1 << 6) +#define ZT_CONFIG_B8ZS (1 << 7) +/* These apply to E1 */ +#define ZT_CONFIG_CCS (1 << 8) /* CCS (ISDN) instead of CAS (Robbed Bit) */ +#define ZT_CONFIG_HDB3 (1 << 9) /* HDB3 instead of AMI (line coding) */ +#define ZT_CONFIG_CRC4 (1 << 10) /* CRC4 framing */ +#define ZT_CONFIG_NOTOPEN (1 << 16) + +/* Signalling types */ +#define ZT_SIG_BROKEN (1 << 31) /* The port is broken and/or failed initialization */ + +#define __ZT_SIG_FXO (1 << 12) /* Never use directly */ +#define __ZT_SIG_FXS (1 << 13) /* Never use directly */ + +#define ZT_SIG_NONE (0) /* Channel not configured */ +#define ZT_SIG_FXSLS ((1 << 0) | __ZT_SIG_FXS) /* FXS, Loopstart */ +#define ZT_SIG_FXSGS ((1 << 1) | __ZT_SIG_FXS) /* FXS, Groundstart */ +#define ZT_SIG_FXSKS ((1 << 2) | __ZT_SIG_FXS) /* FXS, Kewlstart */ + +#define ZT_SIG_FXOLS ((1 << 3) | __ZT_SIG_FXO) /* FXO, Loopstart */ +#define ZT_SIG_FXOGS ((1 << 4) | __ZT_SIG_FXO) /* FXO, Groupstart */ +#define ZT_SIG_FXOKS ((1 << 5) | __ZT_SIG_FXO) /* FXO, Kewlstart */ + +#define ZT_SIG_EM (1 << 6) /* Ear & Mouth (E&M) */ + +/* The following are all variations on clear channel */ + +#define __ZT_SIG_DACS (1 << 16) + +#define ZT_SIG_CLEAR (1 << 7) /* Clear channel */ +#define ZT_SIG_HDLCRAW ((1 << 8) | ZT_SIG_CLEAR) /* Raw unchecked HDLC */ +#define ZT_SIG_HDLCFCS ((1 << 9) | ZT_SIG_HDLCRAW) /* HDLC with FCS calculation */ +#define ZT_SIG_HDLCNET ((1 << 10) | ZT_SIG_HDLCFCS) /* HDLC Network */ +#define ZT_SIG_SLAVE (1 << 11) /* Slave to another channel */ +#define ZT_SIG_SF (1 << 14) /* Single Freq. tone only, no sig bits */ +#define ZT_SIG_CAS (1 << 15) /* Just get bits */ +#define ZT_SIG_DACS (__ZT_SIG_DACS | ZT_SIG_CLEAR) /* Cross connect */ +#define ZT_SIG_EM_E1 (1 << 17) /* E1 E&M Variation */ +#define ZT_SIG_DACS_RBS ((1 << 18) | __ZT_SIG_DACS) /* Cross connect w/ RBS */ +#define ZT_SIG_HARDHDLC ((1 << 19) | ZT_SIG_CLEAR) + +/* tone flag values */ +#define ZT_REVERSE_RXTONE 1 /* reverse polarity rx tone logic */ +#define ZT_REVERSE_TXTONE 2 /* reverse polarity tx tone logic */ + +#define ZT_ABIT 8 +#define ZT_BBIT 4 +#define ZT_CBIT 2 +#define ZT_DBIT 1 + +#define ZT_MAJOR 196 + +#define ZT_CODE 'J' + +/* Default chunk size for conferences and such -- static right now, might make + variable sometime. 8 samples = 1 ms = most frequent service interval possible + for a USB device */ +#define ZT_CHUNKSIZE 8 +#define ZT_MIN_CHUNKSIZE ZT_CHUNKSIZE +#define ZT_DEFAULT_CHUNKSIZE ZT_CHUNKSIZE +#define ZT_MAX_CHUNKSIZE ZT_CHUNKSIZE +#define ZT_CB_SIZE 2 + +#define ZT_MAX_BLOCKSIZE 8192 +#define ZT_DEFAULT_NUM_BUFS 2 +#define ZT_MAX_NUM_BUFS 32 +#define ZT_MAX_BUF_SPACE 32768 + +#define ZT_DEFAULT_BLOCKSIZE 1024 +#define ZT_DEFAULT_MTR_MRU 2048 + +#define ZT_POLICY_IMMEDIATE 0 /* Start play/record immediately */ +#define ZT_POLICY_WHEN_FULL 1 /* Start play/record when buffer is full */ + +#define RING_DEBOUNCE_TIME 2000 /* 2000 ms ring debounce time */ + +#define ZT_GET_PARAMS_RETURN_MASTER 0x40000000 + +/* Extended attributes in lineconfig structure */ +#define ZT_SPANINFO_HAS_LINECONFIG +#define ZT_SPANINFO_HAS_LBONAME + +struct zt_params_v1 +{ + int channo; /* Channel number */ + int spanno; /* Span itself */ + int chanpos; /* Channel number in span */ + int sigtype; /* read-only */ + int sigcap; /* read-only */ + int rxisoffhook; /* read-only */ + int rxbits; /* read-only */ + int txbits; /* read-only */ + int txhooksig; /* read-only */ + int rxhooksig; /* read-only */ + int curlaw; /* read-only -- one of ZT_LAW_MULAW or ZT_LAW_ALAW */ + int idlebits; /* read-only -- What is considered the idle state */ + char name[40]; /* Name of channel */ + int prewinktime; + int preflashtime; + int winktime; + int flashtime; + int starttime; + int rxwinktime; + int rxflashtime; + int debouncetime; + int pulsebreaktime; + int pulsemaketime; + int pulseaftertime; +}; + +typedef struct zt_params +{ + int channo; /* Channel number */ + int spanno; /* Span itself */ + int chanpos; /* Channel number in span */ + int sigtype; /* read-only */ + int sigcap; /* read-only */ + int rxisoffhook; /* read-only */ + int rxbits; /* read-only */ + int txbits; /* read-only */ + int txhooksig; /* read-only */ + int rxhooksig; /* read-only */ + int curlaw; /* read-only -- one of ZT_LAW_MULAW or ZT_LAW_ALAW */ + int idlebits; /* read-only -- What is considered the idle state */ + char name[40]; /* Name of channel */ + int prewinktime; + int preflashtime; + int winktime; + int flashtime; + int starttime; + int rxwinktime; + int rxflashtime; + int debouncetime; + int pulsebreaktime; + int pulsemaketime; + int pulseaftertime; + __u32 chan_alarms; /* alarms on this channel */ +} ZT_PARAMS; + +struct zt_spaninfo_v1 { + int spanno; /* span number */ + char name[20]; /* Name */ + char desc[40]; /* Description */ + int alarms; /* alarms status */ + int txlevel; /* what TX level is set to */ + int rxlevel; /* current RX level */ + int bpvcount; /* current BPV count */ + int crc4count; /* current CRC4 error count */ + int ebitcount; /* current E-bit error count */ + int fascount; /* current FAS error count */ + int irqmisses; /* current IRQ misses */ + int syncsrc; /* span # of current sync source, or 0 for free run */ + int numchans; /* number of configured channels on this span */ + int totalchans; /* total number of channels on the span */ + int totaflspans; /* total number of spans in entire system */ +}; + +struct zt_spaninfo_v2 { + int spanno; /* span number */ + char name[20]; /* Name */ + char desc[40]; /* Description */ + int alarms; /* alarms status */ + int txlevel; /* what TX level is set to */ + int rxlevel; /* current RX level */ + int bpvcount; /* current BPV count */ + int crc4count; /* current CRC4 error count */ + int ebitcount; /* current E-bit error count */ + int fascount; /* current FAS error count */ + int irqmisses; /* current IRQ misses */ + int syncsrc; /* span # of current sync source, or 0 for free run */ + int numchans; /* number of configured channels on this span */ + int totalchans; /* total number of channels on the span */ + int totalspans; /* total number of spans in entire system */ + int lbo; /* line build out */ + int lineconfig; /* framing/coding */ +}; + +typedef struct zt_spaninfo { + int spanno; /* span number */ + char name[20]; /* Name */ + char desc[40]; /* Description */ + int alarms; /* alarms status */ + int txlevel; /* what TX level is set to */ + int rxlevel; /* current RX level */ + int bpvcount; /* current BPV count */ + int crc4count; /* current CRC4 error count */ + int ebitcount; /* current E-bit error count */ + int fascount; /* current FAS error count */ + int irqmisses; /* current IRQ misses */ + int syncsrc; /* span # of current sync source, or 0 for free run */ + int numchans; /* number of configured channels on this span */ + int totalchans; /* total number of channels on the span */ + int totalspans; /* total number of spans in entire system */ + int lbo; /* line build out */ + int lineconfig; /* framing/coding */ + char lboname[40]; /* line build out in text form */ + char location[40]; /* span's device location in system */ + char manufacturer[40]; /* manufacturer of span's device */ + char devicetype[40]; /* span's device type */ + int irq; /* span's device IRQ */ + int linecompat; /* signaling modes possible on this span */ + char spantype[6]; /* type of span in text form */ +} ZT_SPANINFO; + +typedef struct zt_maintinfo +{ +int spanno; /* span number 1-2 */ +int command; /* command */ +} ZT_MAINTINFO; + +typedef struct zt_confinfo +{ +int chan; /* channel number, 0 for current */ +int confno; /* conference number */ +int confmode; /* conferencing mode */ +} ZT_CONFINFO; + +typedef struct zt_gains +{ +int chan; /* channel number, 0 for current */ +unsigned char rxgain[256]; /* Receive gain table */ +unsigned char txgain[256]; /* Transmit gain table */ +} ZT_GAINS; + +typedef struct zt_lineconfig +{ +int span; /* Which span number (0 to use name) */ +char name[20]; /* Name of span to use */ +int lbo; /* line build-outs */ +int lineconfig; /* line config parameters (framing, coding) */ +int sync; /* what level of sync source we are */ +} ZT_LINECONFIG; + +typedef struct zt_chanconfig +{ +int chan; /* Channel we're applying this to (0 to use name) */ +char name[40]; /* Name of channel to use */ +int sigtype; /* Signal type */ +int deflaw; /* Default law (ZT_LAW_DEFAULT, ZT_LAW_MULAW, or ZT_LAW_ALAW */ +int master; /* Master channel if sigtype is ZT_SLAVE */ +int idlebits; /* Idle bits (if this is a CAS channel) or + channel to monitor (if this is DACS channel) */ +char netdev_name[16]; /*name for the hdlc network device*/ +} ZT_CHANCONFIG; + +typedef struct zt_sfconfig +{ +int chan; /* Channel we're applying this to (0 to use name) */ +char name[40]; /* Name of channel to use */ +long rxp1; /* receive tone det. p1 */ +long rxp2; /* receive tone det. p2 */ +long rxp3; /* receive tone det. p3 */ +int txtone; /* Tx tone factor */ +int tx_v2; /* initial v2 value */ +int tx_v3; /* initial v3 value */ +int toneflag; /* Tone flags */ +} ZT_SFCONFIG; + +typedef struct zt_bufferinfo +{ +int txbufpolicy; /* Policy for handling receive buffers */ +int rxbufpolicy; /* Policy for handling receive buffers */ +int numbufs; /* How many buffers to use */ +int bufsize; /* How big each buffer is */ +int readbufs; /* How many read buffers are full (read-only) */ +int writebufs; /* How many write buffers are full (read-only) */ +} ZT_BUFFERINFO; + +typedef struct zt_dialparams +{ +int mfv1_tonelen; /* MF tone length (KP = this * 5/3) */ +int dtmf_tonelen; /* DTMF tone length */ +int reserved[4]; /* Reserved for future expansion -- always set to 0 */ +} ZT_DIAL_PARAMS; + + +typedef struct zt_dynamic_span { + char driver[20]; /* Which low-level driver to use */ + char addr[40]; /* Destination address */ + int numchans; /* Number of channels */ + int timing; /* Timing source preference */ + int spanno; /* Span number (filled in by zaptel) */ +} ZT_DYNAMIC_SPAN; + +/* Define the max # of outgoing DTMF or MFv1 digits to queue in-kernel */ +#define ZT_MAX_DTMF_BUF 256 + +#define ZT_DIAL_OP_APPEND 1 +#define ZT_DIAL_OP_REPLACE 2 +#define ZT_DIAL_OP_CANCEL 3 + +#define ZT_LAW_DEFAULT 0 /* Default law for span */ +#define ZT_LAW_MULAW 1 /* Mu-law */ +#define ZT_LAW_ALAW 2 /* A-law */ + +typedef struct zt_dialoperation +{ +int op; +char dialstr[ZT_MAX_DTMF_BUF]; +} ZT_DIAL_OPERATION; + + +typedef struct zt_indirect_data +{ +int chan; +int op; +void *data; +} ZT_INDIRECT_DATA; + +struct zt_versioninfo { + char version[80]; + char echo_canceller[80]; +}; + +struct zt_hwgain{ + __s32 newgain; /* desired gain in dB but x10. -3.5dB would be -35 */ + __u32 tx:1; /* 0=rx; 1=tx */ +}; + + +/* ioctl definitions */ +#define ZT_CODE 'J' + +/* + * Get Transfer Block Size. + */ +#define ZT_GET_BLOCKSIZE _IOR (ZT_CODE, 1, int) + +/* + * Set Transfer Block Size. + */ +#define ZT_SET_BLOCKSIZE _IOW (ZT_CODE, 2, int) + +/* + * Flush Buffer(s) and stop I/O + */ +#define ZT_FLUSH _IOW (ZT_CODE, 3, int) + +/* + * Wait for Write to Finish + */ +#define ZT_SYNC _IOW (ZT_CODE, 4, int) + +/* + * Get channel parameters + */ +#define ZT_GET_PARAMS_V1 _IOR (ZT_CODE, 5, struct zt_params_v1) +#define ZT_GET_PARAMS _IOR (ZT_CODE, 5, struct zt_params) + +/* + * Get channel parameters + */ +#define ZT_SET_PARAMS_V1 _IOW (ZT_CODE, 6, struct zt_params_v1) +#define ZT_SET_PARAMS _IOW (ZT_CODE, 6, struct zt_params) + +/* + * Set Hookswitch Status + */ +#define ZT_HOOK _IOW (ZT_CODE, 7, int) + +/* + * Get Signalling Event + */ +#define ZT_GETEVENT _IOR (ZT_CODE, 8, int) + +/* + * Wait for something to happen (IO Mux) + */ +#define ZT_IOMUX _IOWR (ZT_CODE, 9, int) + +/* + * Get Span Status + */ +#define ZT_SPANSTAT_V1 _IOWR (ZT_CODE, 10, struct zt_spaninfo_v1) +#define ZT_SPANSTAT_V2 _IOWR (ZT_CODE, 10, struct zt_spaninfo_v2) +#define ZT_SPANSTAT _IOWR (ZT_CODE, 10, struct zt_spaninfo) + +/* + * Set Maintenance Mode + */ +#define ZT_MAINT _IOW (ZT_CODE, 11, struct zt_maintinfo) + +/* + * Get Conference Mode + */ +#define ZT_GETCONF _IOWR (ZT_CODE, 12, struct zt_confinfo) + +/* + * Set Conference Mode + */ +#define ZT_SETCONF _IOWR (ZT_CODE, 13, struct zt_confinfo) + +/* + * Setup or Remove Conference Link + */ +#define ZT_CONFLINK _IOW (ZT_CODE, 14, struct zt_confinfo) + +/* + * Display Conference Diagnostic Information on Console + */ +#define ZT_CONFDIAG _IOR (ZT_CODE, 15, int) + +/* + * Get Channel audio gains + */ +#define ZT_GETGAINS _IOWR (ZT_CODE, 16, struct zt_gains) + +/* + * Set Channel audio gains + */ +#define ZT_SETGAINS _IOWR (ZT_CODE, 17, struct zt_gains) + +/* + * Set Line (T1) Configurations and start system + */ +#define ZT_SPANCONFIG _IOW (ZT_CODE, 18, struct zt_lineconfig) + +/* + * Set Channel Configuration + */ +#define ZT_CHANCONFIG _IOW (ZT_CODE, 19, struct zt_chanconfig) + +/* + * Set Conference to mute mode + */ +#define ZT_CONFMUTE _IOW (ZT_CODE, 20, int) + +/* + * Send a particular tone (see ZT_TONE_*) + */ +#define ZT_SENDTONE _IOW (ZT_CODE, 21, int) + +/* + * Set your region for tones (see ZT_TONE_ZONE_*) + */ +#define ZT_SETTONEZONE _IOW (ZT_CODE, 22, int) + +/* + * Retrieve current region for tones (see ZT_TONE_ZONE_*) + */ +#define ZT_GETTONEZONE _IOR (ZT_CODE, 23, int) + +/* + * Master unit only -- set default zone (see ZT_TONE_ZONE_*) + */ +#define ZT_DEFAULTZONE _IOW (ZT_CODE, 24, int) + +/* + * Load a tone zone from a zt_tone_def_header, see + * below... + */ +#define ZT_LOADZONE _IOW (ZT_CODE, 25, struct zt_tone_def_header) + +/* + * Free a tone zone + */ +#define ZT_FREEZONE _IOW (ZT_CODE, 26, int) + +/* + * Set buffer policy + */ +#define ZT_SET_BUFINFO _IOW (ZT_CODE, 27, struct zt_bufferinfo) + +/* + * Get current buffer info + */ +#define ZT_GET_BUFINFO _IOR (ZT_CODE, 28, struct zt_bufferinfo) + +/* + * Get dialing parameters + */ +#define ZT_GET_DIALPARAMS _IOR (ZT_CODE, 29, struct zt_dialparams) + +/* + * Set dialing parameters + */ +#define ZT_SET_DIALPARAMS _IOW (ZT_CODE, 30, struct zt_dialparams) + +/* + * Append, replace, or cancel a dial string + */ +#define ZT_DIAL _IOW (ZT_CODE, 31, struct zt_dialoperation) + +/* + * Set a clear channel into audio mode + */ +#define ZT_AUDIOMODE _IOW (ZT_CODE, 32, int) + +/* + * Enable or disable echo cancellation on a channel + * + * For ECHOCANCEL: + * The number is zero to disable echo cancellation and non-zero + * to enable echo cancellation. If the number is between 32 + * and 1024, it will also set the number of taps in the echo canceller + * + * For ECHOCANCEL_PARAMS: + * The structure contains parameters that should be passed to the + * echo canceler instance for the selected channel. + */ +#define ZT_ECHOCANCEL _IOW (ZT_CODE, 33, int) +#define ZT_ECHOCANCEL_PARAMS _IOW (ZT_CODE, 33, struct zt_echocanparams) + +/* + * Return a channel's channel number (useful for the /dev/zap/pseudo type interfaces + */ +#define ZT_CHANNO _IOR (ZT_CODE, 34, int) + +/* + * Return a flag indicating whether channel is currently dialing + */ +#define ZT_DIALING _IOR (ZT_CODE, 35, int) + +/* Numbers 60 to 90 are reserved for private use of low level hardware + drivers */ + +/* + * Set a clear channel into HDLC w/out FCS checking/calculation mode + */ +#define ZT_HDLCRAWMODE _IOW (ZT_CODE, 36, int) + +/* + * Set a clear channel into HDLC w/ FCS mode + */ +#define ZT_HDLCFCSMODE _IOW (ZT_CODE, 37, int) + +/* + * Specify a channel on /dev/zap/chan -- must be done before any other ioctl's and is only + * valid on /dev/zap/chan + */ +#define ZT_SPECIFY _IOW (ZT_CODE, 38, int) + +/* + * Temporarily set the law on a channel to + * ZT_LAW_DEFAULT, ZT_LAW_ALAW, or ZT_LAW_MULAW. Is reset on close. + */ +#define ZT_SETLAW _IOW (ZT_CODE, 39, int) + +/* + * Temporarily set the channel to operate in linear mode when non-zero + * or default law if 0 + */ +#define ZT_SETLINEAR _IOW (ZT_CODE, 40, int) + +/* + * Set a clear channel into HDLC w/ PPP interface mode + */ +#define ZT_HDLCPPP _IOW (ZT_CODE, 41, int) + +/* + * Set the ring cadence for FXS interfaces + */ +#define ZT_SETCADENCE _IOW (ZT_CODE, 42, struct zt_ring_cadence) + +/* + * Set the bits going out for CAS interface + */ +#define ZT_SETTXBITS _IOW (ZT_CODE, 43, int) + + +/* + * Display Channel Diagnostic Information on Console + */ +#define ZT_CHANDIAG _IOR (ZT_CODE, 44, int) + +/* + * Obtain received signalling + */ +#define ZT_GETRXBITS _IOR (ZT_CODE, 45, int) + +/* + * Set Channel's SF Tone Configuration + */ +#define ZT_SFCONFIG _IOW (ZT_CODE, 46, struct zt_sfconfig) + +/* + * Set timer expiration (in samples) + */ +#define ZT_TIMERCONFIG _IOW (ZT_CODE, 47, int) + +/* + * Acknowledge timer expiration (number to acknowledge, or -1 for all) + */ +#define ZT_TIMERACK _IOW (ZT_CODE, 48, int) + +/* + * Get Conference to mute mode + */ +#define ZT_GETCONFMUTE _IOR (ZT_CODE, 49, int) + +/* + * Request echo training in some number of ms (with muting in the mean time) + */ +#define ZT_ECHOTRAIN _IOW (ZT_CODE, 50, int) + +/* + * Set on hook transfer for n number of ms -- implemnted by low level driver + */ +#define ZT_ONHOOKTRANSFER _IOW (ZT_CODE, 51, int) + +/* + * Queue Ping + */ +#define ZT_TIMERPING _IOW (ZT_CODE, 42, int) /* Should be 52, but works */ + +/* + * Acknowledge ping + */ +#define ZT_TIMERPONG _IOW (ZT_CODE, 53, int) + +/* + * Set/get signalling freeze + */ +#define ZT_SIGFREEZE _IOW (ZT_CODE, 54, int) +#define ZT_GETSIGFREEZE _IOR (ZT_CODE, 55, int) + +/* + * Do a channel IOCTL from the /dev/zap/ctl interface + */ +#define ZT_INDIRECT _IOWR (ZT_CODE, 56, struct zt_indirect_data) + + +/* + * Get the version of Zaptel that is running, and a description + * of the compiled-in echo canceller (if any) + */ +#define ZT_GETVERSION _IOR(ZT_CODE, 57, struct zt_versioninfo) + +/* + * Put the channel in loopback mode (receive from the channel is + * transmitted back on the interface) + */ +#define ZT_LOOPBACK _IOW(ZT_CODE, 58, int) + + +/* + * 60-80 are reserved for private drivers + * 80-85 are reserved for dynamic span stuff + */ + +/* + * Create a dynamic span + */ +#define ZT_DYNAMIC_CREATE _IOWR (ZT_CODE, 80, struct zt_dynamic_span) + +/* + * Destroy a dynamic span + */ +#define ZT_DYNAMIC_DESTROY _IOW (ZT_CODE, 81, struct zt_dynamic_span) + +/* + * Set the HW gain for a device + */ +#define ZT_SET_HWGAIN _IOW (ZT_CODE, 86, struct zt_hwgain) + +/* + * Enable tone detection -- implemented by low level driver + */ +#define ZT_TONEDETECT _IOW (ZT_CODE, 91, int) + +/* + * Set polarity -- implemented by individual driver. 0 = forward, 1 = reverse + */ +#define ZT_SETPOLARITY _IOW (ZT_CODE, 92, int) + +/* + * Transcoder operations + */ +#define ZT_TRANSCODE_OP _IOWR(ZT_CODE, 93, int) + +/* + * VoiceMail Waiting Indication (WMWI) -- implemented by low-level driver. + * Value: number of waiting messages (hence 0: switch messages off). + */ +#define ZT_VMWI _IOWR(ZT_CODE, 94, int) + +/* + * Startup or Shutdown a span + */ +#define ZT_STARTUP _IOW (ZT_CODE, 99, int) +#define ZT_SHUTDOWN _IOW (ZT_CODE, 100, int) + +#define ZT_TONE_ZONE_MAX 128 + +#define ZT_TONE_ZONE_DEFAULT -1 /* To restore default */ + +#define ZT_TONE_STOP -1 +#define ZT_TONE_DIALTONE 0 +#define ZT_TONE_BUSY 1 +#define ZT_TONE_RINGTONE 2 +#define ZT_TONE_CONGESTION 3 +#define ZT_TONE_CALLWAIT 4 +#define ZT_TONE_DIALRECALL 5 +#define ZT_TONE_RECORDTONE 6 +#define ZT_TONE_INFO 7 +#define ZT_TONE_CUST1 8 +#define ZT_TONE_CUST2 9 +#define ZT_TONE_STUTTER 10 +#define ZT_TONE_MAX 16 + +#define ZT_TONE_DTMF_BASE 64 +#define ZT_TONE_MF_BASE 80 + +enum { + ZT_TONE_DTMF_0 = ZT_TONE_DTMF_BASE, + ZT_TONE_DTMF_1, + ZT_TONE_DTMF_2, + ZT_TONE_DTMF_3, + ZT_TONE_DTMF_4, + ZT_TONE_DTMF_5, + ZT_TONE_DTMF_6, + ZT_TONE_DTMF_7, + ZT_TONE_DTMF_8, + ZT_TONE_DTMF_9, + ZT_TONE_DTMF_s, + ZT_TONE_DTMF_p, + ZT_TONE_DTMF_A, + ZT_TONE_DTMF_B, + ZT_TONE_DTMF_C, + ZT_TONE_DTMF_D +}; + +#define ZT_TONE_DTMF_MAX ZT_TONE_DTMF_D + +enum { + ZT_TONE_MF_0 = ZT_TONE_MF_BASE, + ZT_TONE_MF_1, + ZT_TONE_MF_2, + ZT_TONE_MF_3, + ZT_TONE_MF_4, + ZT_TONE_MF_5, + ZT_TONE_MF_6, + ZT_TONE_MF_7, + ZT_TONE_MF_8, + ZT_TONE_MF_9, + ZT_TONE_MF_s, + ZT_TONE_MF_p, + ZT_TONE_MF_A, + ZT_TONE_MF_B, + ZT_TONE_MF_C, +}; + +#define ZT_TONE_MF_MAX ZT_TONE_MF_C + +#define ZT_MAX_CADENCE 16 + +#define ZT_TONEDETECT_ON (1 << 0) /* Detect tones */ +#define ZT_TONEDETECT_MUTE (1 << 1) /* Mute audio in received channel */ + +#define ZT_TRANSCODE_MAGIC 0x74a9c0de + +/* Operations */ +#define ZT_TCOP_ALLOCATE 1 /* Allocate/reset DTE channel */ +#define ZT_TCOP_TRANSCODE 2 /* Begin transcoding a block */ +#define ZT_TCOP_GETINFO 3 /* Get information (use zt_transcode_info) */ +#define ZT_TCOP_RELEASE 4 /* Release DTE channel */ +#define ZT_TCOP_TEST 5 /* test DTE device */ +typedef struct zt_transcode_info { + unsigned int op; + unsigned int tcnum; + char name[80]; + int numchannels; + unsigned int srcfmts; + unsigned int dstfmts; +} ZT_TRANSCODE_INFO; + +#define ZT_TCCONF_USETS (1 << 0) /* Use/update timestamp field */ +#define ZT_TCCONF_USESEQ (1 << 1) /* Use/update seqno field */ + +#define ZT_TCSTAT_DSTRDY (1 << 0) /* Destination data is ready */ +#define ZT_TCSTAT_DSTBUSY (1 << 1) /* Destination data is outstanding */ + +#define __ZT_TRANSCODE_BUFSIZ 16384 +#define ZT_TRANSCODE_HDRLEN 256 +#define ZT_TRANSCODE_BUFSIZ ((__ZT_TRANSCODE_BUFSIZ) - (ZT_TRANSCODE_HDRLEN)) +#define ZT_TRANSCODE_DSTOFFSET (((ZT_TRANSCODE_BUFSIZ) / 2) + ZT_TRANSCODE_HDRLEN) +#define ZT_TRANSCODE_SRCOFFSET (((ZT_TRANSCODE_BUFSIZ) / 2) + ZT_TRANSCODE_HDRLEN) + +typedef struct zt_transcode_header { + unsigned int srcfmt; /* See formats.h -- use TCOP_RESET when you change */ + unsigned int srcoffset; /* In bytes -- written by user */ + unsigned int srclen; /* In bytes -- written by user */ + unsigned int srctimestamp; /* In samples -- written by user (only used if ZT_TCCONF_USETS is set) */ + unsigned int srcseqno; /* In units -- written by user (only used if ZT_TCCONF_USESEQ is set) */ + + unsigned int dstfmt; /* See formats.h -- use TCOP_RESET when you change */ + unsigned int dstoffset; /* In bytes -- written by user */ + unsigned int dsttimestamp; /* In samples -- read by user */ + unsigned int dstseqno; /* In units -- read by user (only used if ZT_TCCONF_USESEQ is set) */ + unsigned int dstlen; /* In bytes -- read by user */ + unsigned int dstsamples; /* In timestamp units -- read by user */ + + unsigned int magic; /* Magic value -- ZT_TRANSCODE_MAGIC, read by user */ + unsigned int config; /* Read/write by user */ + unsigned int status; /* Read/write by user */ + unsigned char userhdr[ZT_TRANSCODE_HDRLEN - (sizeof(unsigned int) * 14)]; /* Storage for user parameters */ + unsigned char srcdata[ZT_TRANSCODE_BUFSIZ / 2]; /* Storage of source data */ + unsigned char dstdata[ZT_TRANSCODE_BUFSIZ / 2]; /* Storage of destination data */ +} ZT_TRANSCODE_HEADER; + +struct zt_ring_cadence { + int ringcadence[ZT_MAX_CADENCE]; +}; + +#define ZT_MAX_ECHOCANPARAMS 8 + +struct zt_echocanparam { + char name[16]; + __s32 value; +}; + +struct zt_echocanparams { + __u32 tap_length; /* 8 taps per millisecond */ + __u32 param_count; /* number of parameters supplied */ + /* immediately follow this structure with zt_echocanparam structures */ + struct zt_echocanparam params[0]; +}; + +struct zt_tone_def_header { + int count; /* How many samples follow */ + int zone; /* Which zone we are loading */ + int ringcadence[ZT_MAX_CADENCE]; /* Ring cadence in ms (0=on, 1=off, ends with 0 value) */ + char name[40]; /* Informational name of zone */ + /* Immediately follow the zt_tone_def_header by zt_tone_def's */ +}; + +struct zt_tone_def { /* Structure for zone programming */ + int tone; /* See ZT_TONE_* */ + int next; /* What the next position in the cadence is + (They're numbered by the order the appear here) */ + int samples; /* How many samples to play for this cadence */ + /* Now come the constants we need to make tones */ + int shift; /* How much to scale down the volume (2 is nice) */ + + /* + Calculate the next 6 factors using the following equations: + l = , f1 = , f2 = + gain = pow(10.0, (l - 3.14) / 20.0) * 65536.0 / 2.0; + + // Frequency factor 1 + fac_1 = 2.0 * cos(2.0 * M_PI * (f1/8000.0)) * 32768.0; + // Last previous two samples + init_v2_1 = sin(-4.0 * M_PI * (f1/8000.0)) * gain; + init_v3_1 = sin(-2.0 * M_PI * (f1/8000.0)) * gain; + + // Frequency factor 2 + fac_2 = 2.0 * cos(2.0 * M_PI * (f2/8000.0)) * 32768.0; + // Last previous two samples + init_v2_2 = sin(-4.0 * M_PI * (f2/8000.0)) * gain; + init_v3_2 = sin(-2.0 * M_PI * (f2/8000.0)) * gain; + */ + int fac1; + int init_v2_1; + int init_v3_1; + int fac2; + int init_v2_2; + int init_v3_2; + int modulate; + +}; + +#ifdef __KERNEL__ +#endif /* KERNEL */ + +/* Define the maximum block size */ +#define ZT_MAX_BLOCKSIZE 8192 + +/* Define the default network block size */ +#define ZT_DEFAULT_MTU_MRU 2048 + +/* Flush and stop the read (input) process */ +#define ZT_FLUSH_READ 1 + +/* Flush and stop the write (output) process */ +#define ZT_FLUSH_WRITE 2 + +/* Flush and stop both (input and output) processes */ +#define ZT_FLUSH_BOTH (ZT_FLUSH_READ | ZT_FLUSH_WRITE) + +/* Flush the event queue */ +#define ZT_FLUSH_EVENT 4 + +/* Flush everything */ +#define ZT_FLUSH_ALL (ZT_FLUSH_READ | ZT_FLUSH_WRITE | ZT_FLUSH_EVENT) + + +/* Value for ZT_HOOK, set to ON hook */ +#define ZT_ONHOOK 0 + +/* Value for ZT_HOOK, set to OFF hook */ +#define ZT_OFFHOOK 1 + +/* Value for ZT_HOOK, wink (off hook momentarily) */ +#define ZT_WINK 2 + +/* Value for ZT_HOOK, flash (on hook momentarily) */ +#define ZT_FLASH 3 + +/* Value for ZT_HOOK, start line */ +#define ZT_START 4 + +/* Value for ZT_HOOK, ring line (same as start line) */ +#define ZT_RING 5 + +/* Value for ZT_HOOK, turn ringer off */ +#define ZT_RINGOFF 6 + +/* Ret. Value for GET/WAIT Event, no event */ +#define ZT_EVENT_NONE 0 + +/* Ret. Value for GET/WAIT Event, Went Onhook */ +#define ZT_EVENT_ONHOOK 1 + +/* Ret. Value for GET/WAIT Event, Went Offhook or got Ring */ +#define ZT_EVENT_RINGOFFHOOK 2 + +/* Ret. Value for GET/WAIT Event, Got Wink or Flash */ +#define ZT_EVENT_WINKFLASH 3 + +/* Ret. Value for GET/WAIT Event, Got Alarm */ +#define ZT_EVENT_ALARM 4 + +/* Ret. Value for GET/WAIT Event, Got No Alarm (after alarm) */ +#define ZT_EVENT_NOALARM 5 + +/* Ret. Value for GET/WAIT Event, HDLC Abort frame */ +#define ZT_EVENT_ABORT 6 + +/* Ret. Value for GET/WAIT Event, HDLC Frame overrun */ +#define ZT_EVENT_OVERRUN 7 + +/* Ret. Value for GET/WAIT Event, Bad FCS */ +#define ZT_EVENT_BADFCS 8 + +/* Ret. Value for dial complete */ +#define ZT_EVENT_DIALCOMPLETE 9 + +/* Ret Value for ringer going on */ +#define ZT_EVENT_RINGERON 10 + +/* Ret Value for ringer going off */ +#define ZT_EVENT_RINGEROFF 11 + +/* Ret Value for hook change complete */ +#define ZT_EVENT_HOOKCOMPLETE 12 + +/* Ret Value for bits changing on a CAS / User channel */ +#define ZT_EVENT_BITSCHANGED 13 + +/* Ret value for the beginning of a pulse coming on its way */ +#define ZT_EVENT_PULSE_START 14 + +/* Timer event -- timer expired */ +#define ZT_EVENT_TIMER_EXPIRED 15 + +/* Timer event -- ping ready */ +#define ZT_EVENT_TIMER_PING 16 + +/* Polarity reversal event */ +#define ZT_EVENT_POLARITY 17 + +/* Ring Begin event */ +#define ZT_EVENT_RINGBEGIN 18 + +/* Echo can disabled event */ +#define ZT_EVENT_EC_DISABLED 19 + +/* Channel was disconnected. Hint user to close channel */ +#define ZT_EVENT_REMOVED 20 + +#define ZT_EVENT_PULSEDIGIT (1 << 16) /* This is OR'd with the digit received */ +#define ZT_EVENT_DTMFDOWN (1 << 17) /* Ditto for DTMF key down event */ +#define ZT_EVENT_DTMFUP (1 << 18) /* Ditto for DTMF key up event */ + +/* Flag Value for IOMUX, read avail */ +#define ZT_IOMUX_READ 1 + +/* Flag Value for IOMUX, write avail */ +#define ZT_IOMUX_WRITE 2 + +/* Flag Value for IOMUX, write done */ +#define ZT_IOMUX_WRITEEMPTY 4 + +/* Flag Value for IOMUX, signalling event avail */ +#define ZT_IOMUX_SIGEVENT 8 + +/* Flag Value for IOMUX, Do Not Wait if nothing to report */ +#define ZT_IOMUX_NOWAIT 0x100 + +/* Alarm Condition bits */ +#define ZT_ALARM_NONE 0 /* No alarms */ +#define ZT_ALARM_RECOVER 1 /* Recovering from alarm */ +#define ZT_ALARM_LOOPBACK 2 /* In loopback */ +#define ZT_ALARM_YELLOW 4 /* Yellow Alarm */ +#define ZT_ALARM_RED 8 /* Red Alarm */ +#define ZT_ALARM_BLUE 16 /* Blue Alarm */ +#define ZT_ALARM_NOTOPEN 32 +/* Maintenance modes */ +#define ZT_MAINT_NONE 0 /* Normal Mode */ +#define ZT_MAINT_LOCALLOOP 1 /* Local Loopback */ +#define ZT_MAINT_REMOTELOOP 2 /* Remote Loopback */ +#define ZT_MAINT_LOOPUP 3 /* send loopup code */ +#define ZT_MAINT_LOOPDOWN 4 /* send loopdown code */ +#define ZT_MAINT_LOOPSTOP 5 /* stop sending loop codes */ + + +/* Conference modes */ +#define ZT_CONF_MODE_MASK 0xff /* mask for modes */ +#define ZT_CONF_NORMAL 0 /* normal mode */ +#define ZT_CONF_MONITOR 1 /* monitor mode (rx of other chan) */ +#define ZT_CONF_MONITORTX 2 /* monitor mode (tx of other chan) */ +#define ZT_CONF_MONITORBOTH 3 /* monitor mode (rx & tx of other chan) */ +#define ZT_CONF_CONF 4 /* conference mode */ +#define ZT_CONF_CONFANN 5 /* conference announce mode */ +#define ZT_CONF_CONFMON 6 /* conference monitor mode */ +#define ZT_CONF_CONFANNMON 7 /* conference announce/monitor mode */ +#define ZT_CONF_REALANDPSEUDO 8 /* real and pseudo port both on conf */ +#define ZT_CONF_DIGITALMON 9 /* Do not decode or interpret */ +#define ZT_CONF_MONITOR_RX_PREECHO 10 /* monitor mode (rx of other chan) - before echo can is done */ +#define ZT_CONF_MONITOR_TX_PREECHO 11 /* monitor mode (tx of other chan) - before echo can is done */ +#define ZT_CONF_MONITORBOTH_PREECHO 12 /* monitor mode (rx & tx of other chan) - before echo can is done */ +#define ZT_CONF_FLAG_MASK 0xff00 /* mask for flags */ +#define ZT_CONF_LISTENER 0x100 /* is a listener on the conference */ +#define ZT_CONF_TALKER 0x200 /* is a talker on the conference */ +#define ZT_CONF_PSEUDO_LISTENER 0x400 /* pseudo is a listener on the conference */ +#define ZT_CONF_PSEUDO_TALKER 0x800 /* pseudo is a talker on the conference */ + + +#define ZT_DEFAULT_WINKTIME 150 /* 150 ms default wink time */ +#define ZT_DEFAULT_FLASHTIME 750 /* 750 ms default flash time */ + +#define ZT_DEFAULT_PREWINKTIME 50 /* 50 ms before wink */ +#define ZT_DEFAULT_PREFLASHTIME 50 /* 50 ms before flash */ +#define ZT_DEFAULT_STARTTIME 1500 /* 1500 ms of start */ +#define ZT_DEFAULT_RINGTIME 2000 /* 2000 ms of ring on (start, FXO) */ +#if 0 +#define ZT_DEFAULT_RXWINKTIME 250 /* 250ms longest rx wink */ +#endif +#define ZT_DEFAULT_RXWINKTIME 300 /* 300ms longest rx wink (to work with the Atlas) */ +#define ZT_DEFAULT_RXFLASHTIME 1250 /* 1250ms longest rx flash */ +#define ZT_DEFAULT_DEBOUNCETIME 600 /* 600ms of FXS GS signalling debounce */ +#define ZT_DEFAULT_PULSEMAKETIME 50 /* 50 ms of line closed when dial pulsing */ +#define ZT_DEFAULT_PULSEBREAKTIME 50 /* 50 ms of line open when dial pulsing */ +#define ZT_DEFAULT_PULSEAFTERTIME 750 /* 750ms between dial pulse digits */ + +#define ZT_MINPULSETIME (15 * 8) /* 15 ms minimum */ + +#ifdef SHORT_FLASH_TIME +#define ZT_MAXPULSETIME (80 * 8) /* we need 80 ms, not 200ms, as we have a short flash */ +#else +#define ZT_MAXPULSETIME (200 * 8) /* 200 ms maximum */ +#endif + +#define ZT_PULSETIMEOUT ((ZT_MAXPULSETIME / 8) + 50) + +#define ZT_RINGTRAILER (50 * 8) /* Don't consider a ring "over" until it's been gone at least this + much time */ + +#define ZT_LOOPCODE_TIME 10000 /* send loop codes for 10 secs */ +#define ZT_ALARMSETTLE_TIME 5000 /* allow alarms to settle for 5 secs */ +#define ZT_AFTERSTART_TIME 500 /* 500ms after start */ + +#define ZT_RINGOFFTIME 4000 /* Turn off ringer for 4000 ms */ +#define ZT_KEWLTIME 500 /* 500ms for kewl pulse */ +#define ZT_AFTERKEWLTIME 300 /* 300ms after kewl pulse */ + +#define ZT_MAX_PRETRAINING 1000 /* 1000ms max pretraining time */ + +#define ZT_MAX_SPANS 128 /* Max, 128 spans */ +#define ZT_MAX_CHANNELS 1024 /* Max, 1024 channels */ +#define ZT_MAX_CONF 1024 /* Max, 1024 conferences */ + +#ifdef FXSFLASH +#define ZT_FXSFLASHMINTIME 450 /* min 450ms */ +#define ZT_FXSFLASHMAXTIME 550 /* max 550ms */ +#endif + +#ifdef __KERNEL__ + +#include + +#define ZT_MAX_EVENTSIZE 64 /* 64 events max in buffer */ + +struct zt_span; +struct zt_chan; + +struct zt_tone_state { + int v1_1; + int v2_1; + int v3_1; + int v1_2; + int v2_2; + int v3_2; + int modulate; +}; + +struct zt_chardev { + const char *name; + __u8 minor; +#ifdef CONFIG_DEVFS_FS + static devfs_handle_t devfs_handle; +#endif +}; + +int zt_register_chardev(struct zt_chardev *dev); +int zt_unregister_chardev(struct zt_chardev *dev); + +#ifdef CONFIG_ZAPATA_NET +struct zt_hdlc { +#ifdef LINUX26 + struct net_device *netdev; +#else + hdlc_device netdev; +#endif + struct zt_chan *chan; +}; +#endif + +/* Echo cancellation */ +struct echo_can_state; +#if 0 +/* echo can API consists of these functions */ +void echo_can_init(void); +void echo_chan_shutdown(void); +void echo_can_identify(char *buf, size_t len); +int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p, struct echo_can_state **ec); +void echo_can_free(struct echo_can_state *ec); +short echo_can_update(struct echo_can_state *ec, short iref, short isig); +void echo_can_array_update(struct echo_can_state *ec, short *iref, short *isig); +int echo_can_traintap(struct echo_can_state *ec, int pos, short val); +#endif + +/* Conference queue stucture */ +struct confq { + u_char buffer[ZT_CHUNKSIZE * ZT_CB_SIZE]; + u_char *buf[ZT_CB_SIZE]; + int inbuf; + int outbuf; +}; + +typedef struct +{ + long x1; + long x2; + long y1; + long y2; + long e1; + long e2; + int samps; + int lastdetect; +} sf_detect_state_t; + +struct zt_chan { +#ifdef CONFIG_ZAPATA_NET + /* Must be first */ + struct zt_hdlc *hdlcnetdev; +#endif +#ifdef CONFIG_ZAPATA_PPP + struct ppp_channel *ppp; + struct tasklet_struct ppp_calls; + int do_ppp_wakeup; + int do_ppp_error; + struct sk_buff_head ppp_rq; +#endif + spinlock_t lock; + char name[40]; /* Name */ + /* Specified by zaptel */ + int channo; /* Zaptel Channel number */ + int chanpos; + int flags; + long rxp1; + long rxp2; + long rxp3; + int txtone; + int tx_v2; + int tx_v3; + int v1_1; + int v2_1; + int v3_1; + int toneflags; + sf_detect_state_t rd; + + struct zt_chan *master; /* Our Master channel (could be us) */ + /* Next slave (if appropriate) */ + int nextslave; + + u_char *writechunk; /* Actual place to write to */ + u_char swritechunk[ZT_MAX_CHUNKSIZE]; /* Buffer to be written */ + u_char *readchunk; /* Actual place to read from */ + u_char sreadchunk[ZT_MAX_CHUNKSIZE]; /* Preallocated static area */ + short *readchunkpreec; + + /* Pointer to tx and rx gain tables */ + u_char *rxgain; + u_char *txgain; + + /* Whether or not we have allocated gains or are using the default */ + int gainalloc; + + /* Specified by driver, readable by zaptel */ + void *pvt; /* Private channel data */ + struct file *file; /* File structure */ + + + struct zt_span *span; /* Span we're a member of */ + int sig; /* Signalling */ + int sigcap; /* Capability for signalling */ + __u32 chan_alarms; /* alarms status */ + + /* Used only by zaptel -- NO DRIVER SERVICEABLE PARTS BELOW */ + /* Buffer declarations */ + u_char *readbuf[ZT_MAX_NUM_BUFS]; /* read buffer */ + int inreadbuf; + int outreadbuf; + wait_queue_head_t readbufq; /* read wait queue */ + + u_char *writebuf[ZT_MAX_NUM_BUFS]; /* write buffers */ + int inwritebuf; + int outwritebuf; + wait_queue_head_t writebufq; /* write wait queue */ + + int blocksize; /* Block size */ + + int eventinidx; /* out index in event buf (circular) */ + int eventoutidx; /* in index in event buf (circular) */ + unsigned int eventbuf[ZT_MAX_EVENTSIZE]; /* event circ. buffer */ + wait_queue_head_t eventbufq; /* event wait queue */ + + wait_queue_head_t txstateq; /* waiting on the tx state to change */ + + int readn[ZT_MAX_NUM_BUFS]; /* # of bytes ready in read buf */ + int readidx[ZT_MAX_NUM_BUFS]; /* current read pointer */ + int writen[ZT_MAX_NUM_BUFS]; /* # of bytes ready in write buf */ + int writeidx[ZT_MAX_NUM_BUFS]; /* current write pointer */ + + int numbufs; /* How many buffers in channel */ + int txbufpolicy; /* Buffer policy */ + int rxbufpolicy; /* Buffer policy */ + int txdisable; /* Disable transmitter */ + int rxdisable; /* Disable receiver */ + + + /* Tone zone stuff */ + struct zt_zone *curzone; /* Zone for selecting tones */ + int tonezone; /* Tone zone for this channel */ + struct zt_tone *curtone; /* Current tone we're playing (if any) */ + int tonep; /* Current position in tone */ + struct zt_tone_state ts; /* Tone state */ + + /* Pulse dial stuff */ + int pdialcount; /* pulse dial count */ + + /* Ring cadence */ + int ringcadence[ZT_MAX_CADENCE]; + int firstcadencepos; /* Where to restart ring cadence */ + + /* Digit string dialing stuff */ + int digitmode; /* What kind of tones are we sending? */ + char txdialbuf[ZT_MAX_DTMF_BUF]; + int dialing; + int afterdialingtimer; + int cadencepos; /* Where in the cadence we are */ + + /* I/O Mask */ + int iomask; /* I/O Mux signal mask */ + wait_queue_head_t sel; /* thingy for select stuff */ + + /* HDLC state machines */ + struct fasthdlc_state txhdlc; + struct fasthdlc_state rxhdlc; + int infcs; + + /* Conferencing stuff */ + int confna; /* conference number (alias) */ + int _confn; /* Actual conference number */ + int confmode; /* conference mode */ + int confmute; /* conference mute mode */ + + /* Incoming and outgoing conference chunk queues for + communicating between zaptel master time and + other boards */ + struct confq confin; + struct confq confout; + + short getlin[ZT_MAX_CHUNKSIZE]; /* Last transmitted samples */ + unsigned char getraw[ZT_MAX_CHUNKSIZE]; /* Last received raw data */ + short getlin_lastchunk[ZT_MAX_CHUNKSIZE]; /* Last transmitted samples from last chunk */ + short putlin[ZT_MAX_CHUNKSIZE]; /* Last received samples */ + unsigned char putraw[ZT_MAX_CHUNKSIZE]; /* Last received raw data */ + short conflast[ZT_MAX_CHUNKSIZE]; /* Last conference sample -- base part of channel */ + short conflast1[ZT_MAX_CHUNKSIZE]; /* Last conference sample -- pseudo part of channel */ + short conflast2[ZT_MAX_CHUNKSIZE]; /* Previous last conference sample -- pseudo part of channel */ + + + /* Is echo cancellation enabled or disabled */ + int echocancel; + struct echo_can_state *ec; + echo_can_disable_detector_state_t txecdis; + echo_can_disable_detector_state_t rxecdis; + + int echostate; /* State of echo canceller */ + int echolastupdate; /* Last echo can update pos */ + int echotimer; /* Timer for echo update */ + + /* RBS timings */ + int prewinktime; /* pre-wink time (ms) */ + int preflashtime; /* pre-flash time (ms) */ + int winktime; /* wink time (ms) */ + int flashtime; /* flash time (ms) */ + int starttime; /* start time (ms) */ + int rxwinktime; /* rx wink time (ms) */ + int rxflashtime; /* rx flash time (ms) */ + int debouncetime; /* FXS GS sig debounce time (ms) */ + int pulsebreaktime; /* pulse line open time (ms) */ + int pulsemaketime; /* pulse line closed time (ms) */ + int pulseaftertime; /* pulse time between digits (ms) */ + + /* RING debounce timer */ + int ringdebtimer; + + /* RING trailing detector to make sure a RING is really over */ + int ringtrailer; + + /* PULSE digit receiver stuff */ + int pulsecount; + int pulsetimer; + + /* RBS timers */ + int itimerset; /* what the itimer was set to last */ + int itimer; + int otimer; + + /* RBS state */ + int gotgs; + int txstate; + int rxsig; + int txsig; + int rxsigstate; + + /* non-RBS rx state */ + int rxhooksig; + int txhooksig; + int kewlonhook; + + /* Idle signalling if CAS signalling */ + int idlebits; + + int deflaw; /* 1 = mulaw, 2=alaw, 0=undefined */ + short *xlaw; +#ifdef OPTIMIZE_CHANMUTE + int chanmute; /*!< no need for PCM data */ +#endif +#ifdef CONFIG_CALC_XLAW + unsigned char (*lineartoxlaw)(short a); +#else + unsigned char *lin2x; +#endif + +#ifdef CONFIG_DEVFS_FS + devfs_handle_t fhandle; /* File handle in devfs for the channel */ + devfs_handle_t fhandle_symlink; +#endif /* CONFIG_DEVFS_FS */ +}; + +/* defines for transmit signalling */ +typedef enum { + ZT_TXSIG_ONHOOK, /* On hook */ + ZT_TXSIG_OFFHOOK, /* Off hook */ + ZT_TXSIG_START, /* Start / Ring */ + ZT_TXSIG_KEWL /* Drop battery if possible */ +} zt_txsig_t; + +typedef enum { + ZT_RXSIG_ONHOOK, + ZT_RXSIG_OFFHOOK, + ZT_RXSIG_START, + ZT_RXSIG_RING, + ZT_RXSIG_INITIAL +} zt_rxsig_t; + + +/* Span flags */ +#define ZT_FLAG_REGISTERED (1 << 0) +#define ZT_FLAG_RUNNING (1 << 1) +#define ZT_FLAG_RBS (1 << 12) /* Span uses RBS signalling */ + +/* Channel flags */ +#define ZT_FLAG_DTMFDECODE (1 << 2) /* Channel supports native DTMF decode */ +#define ZT_FLAG_MFDECODE (1 << 3) /* Channel supports native MFr2 decode */ +#define ZT_FLAG_ECHOCANCEL (1 << 4) /* Channel supports native echo cancellation */ + +#define ZT_FLAG_HDLC (1 << 5) /* Perform HDLC */ +#define ZT_FLAG_NETDEV (1 << 6) /* Send to network */ +#define ZT_FLAG_PSEUDO (1 << 7) /* Pseudo channel */ +#define ZT_FLAG_CLEAR (1 << 8) /* Clear channel */ +#define ZT_FLAG_AUDIO (1 << 9) /* Audio mode channel */ + +#define ZT_FLAG_OPEN (1 << 10) /* Channel is open */ +#define ZT_FLAG_FCS (1 << 11) /* Calculate FCS */ +/* Reserve 12 for uniqueness with span flags */ +#define ZT_FLAG_LINEAR (1 << 13) /* Talk to user space in linear */ +#define ZT_FLAG_PPP (1 << 14) /* PPP is available */ +#define ZT_FLAG_T1PPP (1 << 15) +#define ZT_FLAG_SIGFREEZE (1 << 16) /* Freeze signalling */ +#define ZT_FLAG_NOSTDTXRX (1 << 17) /* Do NOT do standard transmit and receive on every interrupt */ +#define ZT_FLAG_LOOPED (1 << 18) /* Loopback the receive data from the channel to the transmit */ + +struct zt_span { + spinlock_t lock; + void *pvt; /* Private stuff */ + char name[40]; /* Span name */ + char desc[80]; /* Span description */ + const char *spantype; /* span type in text form */ + const char *manufacturer; /* span's device manufacturer */ + char devicetype[80]; /* span's device type */ + char location[40]; /* span device's location in system */ + int deflaw; /* Default law (ZT_MULAW or ZT_ALAW) */ + int alarms; /* Pending alarms on span */ + int flags; + int irq; /* IRQ for this span's hardware */ + int lbo; /* Span Line-Buildout */ + int lineconfig; /* Span line configuration */ + int linecompat; /* Span line compatibility */ + int channels; /* Number of channels in span */ + int txlevel; /* Tx level */ + int rxlevel; /* Rx level */ + int syncsrc; /* current sync src (gets copied here) */ + unsigned int bpvcount; /* BPV counter */ + unsigned int crc4count; /* CRC4 error counter */ + unsigned int ebitcount; /* current E-bit error count */ + unsigned int fascount; /* current FAS error count */ + + int maintstat; /* Maintenance state */ + wait_queue_head_t maintq; /* Maintenance queue */ + int mainttimer; /* Maintenance timer */ + + int irqmisses; /* Interrupt misses */ + + int timingslips; /* Clock slips */ + + struct zt_chan *chans; /* Member channel structures */ + + /* ==== Span Callback Operations ==== */ + /* Req: Set the requested chunk size. This is the unit in which you must + report results for conferencing, etc */ + int (*setchunksize)(struct zt_span *span, int chunksize); + + /* Opt: Configure the span (if appropriate) */ + int (*spanconfig)(struct zt_span *span, struct zt_lineconfig *lc); + + /* Opt: Start the span */ + int (*startup)(struct zt_span *span); + + /* Opt: Shutdown the span */ + int (*shutdown)(struct zt_span *span); + + /* Opt: Enable maintenance modes */ + int (*maint)(struct zt_span *span, int mode); + +#ifdef ZAPTEL_SYNC_TICK + /* Opt: send sync to spans */ + int (*sync_tick)(struct zt_span *span, int is_master); +#endif + + /* ==== Channel Callback Operations ==== */ + /* Opt: Set signalling type (if appropriate) */ + int (*chanconfig)(struct zt_chan *chan, int sigtype); + + /* Opt: Prepare a channel for I/O */ + int (*open)(struct zt_chan *chan); + + /* Opt: Close channel for I/O */ + int (*close)(struct zt_chan *chan); + + /* Opt: IOCTL */ + int (*ioctl)(struct zt_chan *chan, unsigned int cmd, unsigned long data); + + /* Opt: Native echo cancellation (simple) */ + int (*echocan)(struct zt_chan *chan, int ecval); + + int (*echocan_with_params)(struct zt_chan *chan, struct zt_echocanparams *ecp, struct zt_echocanparam *p); + + /* Okay, now we get to the signalling. You have several options: */ + + /* Option 1: If you're a T1 like interface, you can just provide a + rbsbits function and we'll assert robbed bits for you. Be sure to + set the ZT_FLAG_RBS in this case. */ + + /* Opt: If the span uses A/B bits, set them here */ + int (*rbsbits)(struct zt_chan *chan, int bits); + + /* Option 2: If you don't know about sig bits, but do have their + equivalents (i.e. you can disconnect battery, detect off hook, + generate ring, etc directly) then you can just specify a + sethook function, and we'll call you with appropriate hook states + to set. Still set the ZT_FLAG_RBS in this case as well */ + int (*hooksig)(struct zt_chan *chan, zt_txsig_t hookstate); + + /* Option 3: If you can't use sig bits, you can write a function + which handles the individual hook states */ + int (*sethook)(struct zt_chan *chan, int hookstate); + + /* Opt: Dacs the contents of chan2 into chan1 if possible */ + int (*dacs)(struct zt_chan *chan1, struct zt_chan *chan2); + + /* Opt: Used to tell an onboard HDLC controller that there is data ready to transmit */ + void (*hdlc_hard_xmit)(struct zt_chan *chan); + + /* Used by zaptel only -- no user servicable parts inside */ + int spanno; /* Span number for zaptel */ + int offset; /* Offset within a given card */ + int lastalarms; /* Previous alarms */ + +#ifdef CONFIG_DEVFS_FS + devfs_handle_t dhandle; /* Directory name */ +#endif + /* If the watchdog detects no received data, it will call the + watchdog routine */ + int (*watchdog)(struct zt_span *span, int cause); +#ifdef CONFIG_ZAPTEL_WATCHDOG + int watchcounter; + int watchstate; +#endif +}; + +struct zt_transcoder_channel { + void *pvt; + struct zt_transcoder *parent; + wait_queue_head_t ready; + int errorstatus; + int offset; + unsigned int chan_built; + unsigned int built_fmts; + unsigned int flags; + unsigned int srcfmt; + unsigned int dstfmt; + struct zt_transcode_header *tch; +}; + +#define ZT_TC_FLAG_BUSY (1 << 0) +#define ZT_TC_FLAG_TRANSIENT (1 << 1) + + +struct zt_transcoder { + struct zt_transcoder *next; + char name[80]; + int numchannels; + unsigned int srcfmts; + unsigned int dstfmts; + int (*operation)(struct zt_transcoder_channel *channel, int op); + /* Transcoder channels */ + struct zt_transcoder_channel channels[0]; +}; + +#define ZT_WATCHDOG_NOINTS (1 << 0) + +#define ZT_WATCHDOG_INIT 1000 + +#define ZT_WATCHSTATE_UNKNOWN 0 +#define ZT_WATCHSTATE_OK 1 +#define ZT_WATCHSTATE_RECOVERING 2 +#define ZT_WATCHSTATE_FAILED 3 + + +struct zt_dynamic_driver { + /* Driver name (e.g. Eth) */ + char name[20]; + + /* Driver description */ + char desc[80]; + + /* Create a new transmission pipe */ + void *(*create)(struct zt_span *span, char *address); + + /* Destroy a created transmission pipe */ + void (*destroy)(void *tpipe); + + /* Transmit a given message */ + int (*transmit)(void *tpipe, unsigned char *msg, int msglen); + + /* Flush any pending messages */ + int (*flush)(void); + + struct zt_dynamic_driver *next; +}; + +/* Receive a dynamic span message */ +void zt_dynamic_receive(struct zt_span *span, unsigned char *msg, int msglen); + +/* Register a dynamic driver */ +int zt_dynamic_register(struct zt_dynamic_driver *driver); + +/* Unregister a dynamic driver */ +void zt_dynamic_unregister(struct zt_dynamic_driver *driver); + +/* Receive on a span. The zaptel interface will handle all the calculations for + all member channels of the span, pulling the data from the readchunk buffer */ +int zt_receive(struct zt_span *span); + +/* Prepare writechunk buffers on all channels for this span */ +int zt_transmit(struct zt_span *span); + +/* Abort the buffer currently being receive with event "event" */ +void zt_hdlc_abort(struct zt_chan *ss, int event); + +/* Indicate to zaptel that the end of frame was received and rotate buffers */ +void zt_hdlc_finish(struct zt_chan *ss); + +/* Put a chunk of data into the current receive buffer */ +void zt_hdlc_putbuf(struct zt_chan *ss, unsigned char *rxb, int bytes); + +/* Get a chunk of data from the current transmit buffer. Returns -1 if no data + * is left to send, 0 if there is data remaining in the current message to be sent + * and 1 if the currently transmitted message is now done */ +int zt_hdlc_getbuf(struct zt_chan *ss, unsigned char *bufptr, unsigned int *size); + + +/* Register a span. Returns 0 on success, -1 on failure. Pref-master is non-zero if + we should have preference in being the master device */ +int zt_register(struct zt_span *span, int prefmaster); + +/* Allocate / free memory for a transcoder */ +struct zt_transcoder *zt_transcoder_alloc(int numchans); +void zt_transcoder_free(struct zt_transcoder *ztc); + +/* Register a transcoder */ +int zt_transcoder_register(struct zt_transcoder *tc); + +/* Unregister a transcoder */ +int zt_transcoder_unregister(struct zt_transcoder *tc); + +/* Alert a transcoder */ +int zt_transcoder_alert(struct zt_transcoder_channel *ztc); + +/* Unregister a span */ +int zt_unregister(struct zt_span *span); + +/* Gives a name to an LBO */ +char *zt_lboname(int lbo); + +/* Tell Zaptel about changes in received rbs bits */ +void zt_rbsbits(struct zt_chan *chan, int bits); + +/* Tell Zaptel abou changes in received signalling */ +void zt_hooksig(struct zt_chan *chan, zt_rxsig_t rxsig); + +/* Queue an event on a channel */ +void zt_qevent_nolock(struct zt_chan *chan, int event); + +/* Queue an event on a channel, locking it first */ +void zt_qevent_lock(struct zt_chan *chan, int event); + +/* Notify a change possible change in alarm status on a channel */ +void zt_alarm_channel(struct zt_chan *chan, int alarms); + +/* Notify a change possible change in alarm status on a span */ +void zt_alarm_notify(struct zt_span *span); + +/* Initialize a tone state */ +void zt_init_tone_state(struct zt_tone_state *ts, struct zt_tone *zt); + +/* Get a given DTMF or MF tone struct, suitable for zt_tone_nextsample. */ +struct zt_tone *zt_dtmf_tone(const struct zt_chan *chan, char digit); + +/* Echo cancel a receive and transmit chunk for a given channel. This + should be called by the low-level driver as close to the interface + as possible. ECHO CANCELLATION IS NO LONGER AUTOMATICALLY DONE + AT THE ZAPTEL LEVEL. zt_ec_chunk will not echo cancel if it should + not be doing so. rxchunk is modified in-place */ + +void zt_ec_chunk(struct zt_chan *chan, unsigned char *rxchunk, const unsigned char *txchunk); +void zt_ec_span(struct zt_span *span); + +extern struct file_operations *zt_transcode_fops; + +/* Don't use these directly -- they're not guaranteed to + be there. */ +extern short __zt_mulaw[256]; +extern short __zt_alaw[256]; +#ifdef CONFIG_CALC_XLAW +u_char __zt_lineartoulaw(short a); +u_char __zt_lineartoalaw(short a); +#else +extern u_char __zt_lin2mu[16384]; +extern u_char __zt_lin2a[16384]; +#endif + +/* Used by dynamic zaptel -- don't use directly */ +void zt_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data)); + +/* Used privately by zaptel. Avoid touching directly */ +struct zt_tone { + int fac1; + int init_v2_1; + int init_v3_1; + + int fac2; + int init_v2_2; + int init_v3_2; + + int tonesamples; /* How long to play this tone before + going to the next (in samples) */ + struct zt_tone *next; /* Next tone in this sequence */ + + int modulate; +}; + +static inline short zt_tone_nextsample(struct zt_tone_state *ts, struct zt_tone *zt) +{ + /* follow the curves, return the sum */ + + int p; + + ts->v1_1 = ts->v2_1; + ts->v2_1 = ts->v3_1; + ts->v3_1 = (zt->fac1 * ts->v2_1 >> 15) - ts->v1_1; + + ts->v1_2 = ts->v2_2; + ts->v2_2 = ts->v3_2; + ts->v3_2 = (zt->fac2 * ts->v2_2 >> 15) - ts->v1_2; + + /* Return top 16 bits */ + if (!ts->modulate) return ts->v3_1 + ts->v3_2; + /* we are modulating */ + p = ts->v3_2 - 32768; + if (p < 0) p = -p; + p = ((p * 9) / 10) + 1; + return (ts->v3_1 * p) >> 15; + +} + +static inline short zt_txtone_nextsample(struct zt_chan *ss) +{ + /* follow the curves, return the sum */ + + ss->v1_1 = ss->v2_1; + ss->v2_1 = ss->v3_1; + ss->v3_1 = (ss->txtone * ss->v2_1 >> 15) - ss->v1_1; + return ss->v3_1; +} + +/* These are the right functions to use. */ + +#define ZT_MULAW(a) (__zt_mulaw[(a)]) +#define ZT_ALAW(a) (__zt_alaw[(a)]) +#define ZT_XLAW(a,c) (c->xlaw[(a)]) + +#ifdef CONFIG_CALC_XLAW +#define ZT_LIN2MU(a) (__zt_lineartoulaw((a))) +#define ZT_LIN2A(a) (__zt_lineartoalaw((a))) + +#define ZT_LIN2X(a,c) ((c)->lineartoxlaw((a))) + +#else +/* Use tables */ +#define ZT_LIN2MU(a) (__zt_lin2mu[((unsigned short)(a)) >> 2]) +#define ZT_LIN2A(a) (__zt_lin2a[((unsigned short)(a)) >> 2]) + +/* Manipulate as appropriate for x-law */ +#define ZT_LIN2X(a,c) ((c)->lin2x[((unsigned short)(a)) >> 2]) + +#endif /* CONFIG_CALC_XLAW */ + +#endif /* __KERNEL__ */ + +/* The following is for the PCI RADIO interface only. This is specified in +this file because external processes need to interact with the device. +Some devices have private functions used for test/diagnostic only, but +this is not the case here. */ + +struct zt_radio_stat { + unsigned short ctcode_rx; /* code of currently received CTCSS + or DCS, 0 for none */ + unsigned short ctclass; /* class of currently received CTCSS or + DCS code */ + unsigned short ctcode_tx; /* code of currently encoded CTCSS or + DCS, 0 for none */ + unsigned char radstat; /* status bits of radio */ +}; + +#define RAD_SERIAL_BUFLEN 128 + +struct zt_radio_param { + unsigned short radpar; /* param identifier */ + unsigned short index; /* tone number */ + int data; /* param */ + int data2; /* param 2 */ + unsigned char buf[RAD_SERIAL_BUFLEN]; +}; + + +/* Get current status IOCTL */ +#define ZT_RADIO_GETSTAT _IOR (ZT_CODE, 57, struct zt_radio_stat) +/* Set a channel parameter IOCTL */ +#define ZT_RADIO_SETPARAM _IOW (ZT_CODE, 58, struct zt_radio_param) +/* Get a channel parameter IOCTL */ +#define ZT_RADIO_GETPARAM _IOR (ZT_CODE, 59, struct zt_radio_param) + + +/* Defines for Radio Status (zt_radio_stat.radstat) bits */ + +#define ZT_RADSTAT_RX 1 /* currently "receiving " */ +#define ZT_RADSTAT_TX 2 /* currently "transmitting" */ +#define ZT_RADSTAT_RXCT 4 /* currently receiving continuous tone with + current settings */ +#define ZT_RADSTAT_RXCOR 8 /* currently receiving COR (irrelevant of COR + ignore) */ +#define ZT_RADSTAT_IGNCOR 16 /* currently ignoring COR */ +#define ZT_RADSTAT_IGNCT 32 /* currently ignoring CTCSS/DCS decode */ +#define ZT_RADSTAT_NOENCODE 64 /* currently blocking CTCSS/DCS encode */ + +/* Defines for Radio Parameters (zt_radio_param.radpar) */ + +#define ZT_RADPAR_INVERTCOR 1 /* invert the COR signal (0/1) */ +#define ZT_RADPAR_IGNORECOR 2 /* ignore the COR signal (0/1) */ +#define ZT_RADPAR_IGNORECT 3 /* ignore the CTCSS/DCS decode (0/1) */ +#define ZT_RADPAR_NOENCODE 4 /* block the CTCSS/DCS encode (0/1) */ +#define ZT_RADPAR_CORTHRESH 5 /* COR trigger threshold (0-7) */ + +#define ZT_RADPAR_EXTRXTONE 6 /* 0 means use internal decoder, 1 means UIOA + logic true is CT decode, 2 means UIOA logic + false is CT decode */ +#define ZT_RADPAR_NUMTONES 7 /* returns maximum tone index (curently 15) */ +#define ZT_RADPAR_INITTONE 8 /* init all tone indexes to 0 (no tones) */ +#define ZT_RADPAR_RXTONE 9 /* CTCSS tone, (1-32) or DCS tone (1-777), + or 0 meaning no tone, set index also (1-15) */ +#define ZT_RADPAR_RXTONECLASS 10 /* Tone class (0-65535), set index also (1-15) */ +#define ZT_RADPAR_TXTONE 11 /* CTCSS tone (1-32) or DCS tone (1-777) or 0 + to indicate no tone, to transmit + for this tone index (0-32, 0 disables + transmit CTCSS), set index also (0-15) */ +#define ZT_RADPAR_DEBOUNCETIME 12 /* receive indication debounce time, + milliseconds (1-999) */ +#define ZT_RADPAR_BURSTTIME 13 /* end of transmit with no CT tone in + milliseconds (0-999) */ + + +#define ZT_RADPAR_UIODATA 14 /* read/write UIOA and UIOB data. Bit 0 is + UIOA, bit 1 is UIOB */ +#define ZT_RADPAR_UIOMODE 15 /* 0 means UIOA and UIOB are both outputs, 1 + means UIOA is input, UIOB is output, 2 + means UIOB is input and UIOA is output, + 3 means both UIOA and UIOB are inputs. Note + mode for UIOA is overridden when in + EXTRXTONE mode. */ + +#define ZT_RADPAR_REMMODE 16 /* Remote control data mode */ + #define ZT_RADPAR_REM_NONE 0 /* no remote control data mode */ + #define ZT_RADPAR_REM_RBI1 1 /* Doug Hall RBI-1 data mode */ + #define ZT_RADPAR_REM_SERIAL 2 /* Serial Data, 9600 BPS */ + #define ZT_RADPAR_REM_SERIAL_ASCII 3 /* Serial Ascii Data, 9600 BPS */ + +#define ZT_RADPAR_REMCOMMAND 17 /* Remote conrtol write data block & do cmd */ + +/* Data formats for capabilities and frames alike (from Asterisk) */ +/*! G.723.1 compression */ +#define ZT_FORMAT_G723_1 (1 << 0) +/*! GSM compression */ +#define ZT_FORMAT_GSM (1 << 1) +/*! Raw mu-law data (G.711) */ +#define ZT_FORMAT_ULAW (1 << 2) +/*! Raw A-law data (G.711) */ +#define ZT_FORMAT_ALAW (1 << 3) +/*! ADPCM (G.726, 32kbps) */ +#define ZT_FORMAT_G726 (1 << 4) +/*! ADPCM (IMA) */ +#define ZT_FORMAT_ADPCM (1 << 5) +/*! Raw 16-bit Signed Linear (8000 Hz) PCM */ +#define ZT_FORMAT_SLINEAR (1 << 6) +/*! LPC10, 180 samples/frame */ +#define ZT_FORMAT_LPC10 (1 << 7) +/*! G.729A audio */ +#define ZT_FORMAT_G729A (1 << 8) +/*! SpeeX Free Compression */ +#define ZT_FORMAT_SPEEX (1 << 9) +/*! iLBC Free Compression */ +#define ZT_FORMAT_ILBC (1 << 10) +/*! Maximum audio format */ +#define ZT_FORMAT_MAX_AUDIO (1 << 15) +/*! Maximum audio mask */ +#define ZT_FORMAT_AUDIO_MASK ((1 << 16) - 1) + +#define ZT_RADPAR_DEEMP 18 /* Audio De-empahsis (on or off) */ + +#define ZT_RADPAR_PREEMP 19 /* Audio Pre-empahsis (on or off) */ + +#define ZT_RADPAR_RXGAIN 20 /* Audio (In to system) Rx Gain */ + +#define ZT_RADPAR_TXGAIN 21 /* Audio (Out from system) Tx Gain */ + +struct torisa_debug { + unsigned int txerrors; + unsigned int irqcount; + unsigned int taskletsched; + unsigned int taskletrun; + unsigned int taskletexec; + int span1flags; + int span2flags; +}; + +/* Special torisa ioctl */ +#define TORISA_GETDEBUG _IOW (ZT_CODE, 60, struct torisa_debug) + +#endif /* _LINUX_ZAPTEL_H */ diff --git a/kernel/zconfig.h b/kernel/zconfig.h new file mode 100644 index 0000000..35056e3 --- /dev/null +++ b/kernel/zconfig.h @@ -0,0 +1,197 @@ +/* + * Zaptel configuration options + * + */ +#ifndef _ZCONFIG_H +#define _ZCONFIG_H + +#ifdef __KERNEL__ +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) +#include +#else +#include +#endif +#endif + +/* Zaptel compile time options */ + +/* + * Uncomment if you have a European phone, or any other phone with a + * short flash time. + * This will stop the flash being mis-detected as a pulse dial "1" on + * phones with short flashes + */ +/* #define SHORT_FLASH_TIME */ + +/* + * Uncomment to disable calibration and/or DC/DC converter tests + * (not generally recommended) + */ +/* #define NO_CALIBRATION */ +/* #define NO_DCDC */ + +/* + * Boost ring voltage (Higher ring voltage, takes more power) + * Note: this only affects the wcfxsusb and wcusb drivers; all other + * drivers have a 'boostringer' module parameter. + */ +/* #define BOOST_RINGER */ + +/* + * Define CONFIG_CALC_XLAW if you have a small number of channels and/or + * a small level 2 cache, to optimize for few channels + * + */ +/* #define CONFIG_CALC_XLAW */ + +/* + * Define if you want MMX optimizations in zaptel + * + * Note: CONFIG_ZAPTEL_MMX is generally incompatible with AMD + * processors and can cause system instability! + * + */ +/* #define CONFIG_ZAPTEL_MMX */ + +/** If defined: the user must define exactly one ECHO_CAN_ var: */ +#ifndef ECHO_CAN_FROMENV + +/* + * Pick your echo canceller: MARK2, MARK3, STEVE, or STEVE2 :) + * + */ +/* #define ECHO_CAN_STEVE */ +/* #define ECHO_CAN_STEVE2 */ +/* #define ECHO_CAN_KB1 */ +/* This is the new latest and greatest */ +#define ECHO_CAN_MG2 + +/* + * This is only technically an "echo canceller"... + * It purposely drops 2 out of 3 samples and sounds horrible. + * You really only want this for testing "echo cancelled" audio. + */ +/* #define ECHO_CAN_JP1 */ + +/* + * Uncomment for aggressive residual echo suppression under + * MARK2, KB1, and MG2 echo canceler + */ +/* #define AGGRESSIVE_SUPPRESSOR */ +#endif /* ifndef ECHO_CAN_FROMENV */ +/* + * Define to turn off the echo canceler disable tone detector, + * which will cause zaptel to ignore the 2100 Hz echo cancel disable + * tone. + */ +/* #define NO_ECHOCAN_DISABLE */ + +/* udev support */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,1) +#define CONFIG_ZAP_UDEV +#endif + +/* We now use the linux kernel config to detect which options to use */ +/* You can still override them below */ +#if defined(CONFIG_HDLC) || defined(CONFIG_HDLC_MODULE) +/* #define CONFIG_ZAPATA_NET */ /* NEVER implicitly turn on ZAPATA_NET */ +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,20) +#define CONFIG_OLD_HDLC_API +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,23) +/* Starting with 2.4.23 the kernel hdlc api changed again */ +/* Now we have to use hdlc_type_trans(skb, dev) instead of htons(ETH_P_HDLC) */ +#define ZAP_HDLC_TYPE_TRANS +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3) +#define HDLC_MAINTAINERS_ARE_MORE_STUPID_THAN_I_THOUGHT +#endif +#endif +#endif +#ifdef CONFIG_PPP +#define CONFIG_ZAPATA_PPP +#endif + +/* + * Uncomment CONFIG_ZAPATA_NET to enable SyncPPP, CiscoHDLC, and Frame Relay + * support. + */ +/* #define CONFIG_ZAPATA_NET */ + +/* + * Uncomment CONFIG_OLD_HDLC_API if your are compiling with ZAPATA_NET + * defined and you are using the old kernel HDLC interface (or if you get + * an error about ETH_P_HDLC while compiling). + */ +/* #define CONFIG_OLD_HDLC_API */ + +/* + * Uncomment for Generic PPP support (i.e. ZapRAS) + */ +/* #define CONFIG_ZAPATA_PPP */ +/* + * Uncomment to enable "watchdog" to monitor if interfaces + * stop taking interrupts or otherwise misbehave + */ +/* #define CONFIG_ZAPTEL_WATCHDOG */ + +/* + * Uncomment for Non-standard FXS groundstart start state (A=Low, B=Low) + * particularly for CAC channel bank groundstart FXO ports. + */ +/* #define CONFIG_CAC_GROUNDSTART */ + +/* + * Uncomment if you happen have an early TDM400P Rev H which + * sometimes forgets its PCI ID to have wcfxs match essentially all + * subvendor ID's + */ +/* #define TDM_REVH_MATCHALL */ + +/* + * Uncomment the following if you want to support E&M trunks being + * able to "flash" after going off-hook (dont ask why, just nod :-) ). + * + * NOTE: *DO NOT* Enable "EMFLASH" and "EMPULSE" at the same time!! + * + */ +/* #define EMFLASH */ + +/* + * Uncomment the following if you want to support E&M trunks being + * able to recognize Dial Pulse digits. This can validly be enabled + * so that either Dial Pulse or DTMF/MF tones will be recognized, but + * the drawback is that the ONHOOK will take an extra {rxwinktime} + * to be recognized. + * + * NOTE: *DO NOT* Enable "EMFLASH" and "EMPULSE" at the same time!! + * + */ +/* #define EMPULSE */ + +/* + * Comment out the following if you dont want events to indicate the + * beginning of an incoming ring. Most non-Asterisk applications will + * want this commented out. + */ +#define RINGBEGIN + +/* + * Uncomment the following if you need to support FXS Flash events. + * Most applications will want this commented out. + */ +/* #define FXSFLASH */ + +/* + * Enable sync_tick() calls. Allows low-level drivers to synchronize + * their internal clocks to the zaptel master clock. + */ +#define ZAPTEL_SYNC_TICK + +/* + * Skip processing PCM if low-level driver won't use it anyway + */ +/* #define OPTIMIZE_CHANMUTE */ + +#endif diff --git a/kernel/ztd-eth.c b/kernel/ztd-eth.c new file mode 100644 index 0000000..97d3492 --- /dev/null +++ b/kernel/ztd-eth.c @@ -0,0 +1,451 @@ +/* + * Dynamic Span Interface for Zaptel (Ethernet Interface) + * + * Written by Mark Spencer + * + * Copyright (C) 2001, Linux Support Services, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_DEVFS_FS +#include +#endif +#ifdef STANDALONE_ZAPATA +#include "zaptel.h" +#else +#include +#endif + +#define ETH_P_ZTDETH 0xd00d + +struct ztdeth_header { + unsigned short subaddr; +}; + +/* We take the raw message, put it in an ethernet frame, and add a + two byte addressing header at the top for future use */ +#ifdef DEFINE_SPINLOCK +static DEFINE_SPINLOCK(zlock); +#else +static spinlock_t zlock = SPIN_LOCK_UNLOCKED; +#endif + +static struct sk_buff_head skbs; + +static struct ztdeth { + unsigned char addr[ETH_ALEN]; + unsigned short subaddr; /* Network byte order */ + struct zt_span *span; + char ethdev[IFNAMSIZ]; + struct net_device *dev; + struct ztdeth *next; +} *zdevs = NULL; + +struct zt_span *ztdeth_getspan(unsigned char *addr, unsigned short subaddr) +{ + unsigned long flags; + struct ztdeth *z; + struct zt_span *span = NULL; + spin_lock_irqsave(&zlock, flags); + z = zdevs; + while(z) { + if (!memcmp(addr, z->addr, ETH_ALEN) && + z->subaddr == subaddr) + break; + z = z->next; + } + if (z) + span = z->span; + spin_unlock_irqrestore(&zlock, flags); + return span; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) +static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) +#else +static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) +#endif +{ + struct zt_span *span; + struct ztdeth_header *zh; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + zh = (struct ztdeth_header *)skb_network_header(skb); +#else + zh = (struct ztdeth_header *)skb->nh.raw; +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9) + span = ztdeth_getspan(eth_hdr(skb)->h_source, zh->subaddr); +#else + span = ztdeth_getspan(skb->mac.ethernet->h_source, zh->subaddr); +#endif + if (span) { + skb_pull(skb, sizeof(struct ztdeth_header)); + zt_dynamic_receive(span, (unsigned char *)skb->data, skb->len); + } + kfree_skb(skb); + return 0; +} + +static int ztdeth_notifier(struct notifier_block *block, unsigned long event, void *ptr) +{ + struct net_device *dev = ptr; + struct ztdeth *z; + unsigned long flags; + switch(event) { + case NETDEV_GOING_DOWN: + case NETDEV_DOWN: + spin_lock_irqsave(&zlock, flags); + z = zdevs; + while(z) { + /* Note that the device no longer exists */ + if (z->dev == dev) + z->dev = NULL; + z = z->next; + } + spin_unlock_irqrestore(&zlock, flags); + break; + case NETDEV_UP: + spin_lock_irqsave(&zlock, flags); + z = zdevs; + while(z) { + /* Now that the device exists again, use it */ + if (!strcmp(z->ethdev, dev->name)) + z->dev = dev; + z = z->next; + } + spin_unlock_irqrestore(&zlock, flags); + break; + } + return 0; +} + +static int ztdeth_transmit(void *pvt, unsigned char *msg, int msglen) +{ + struct ztdeth *z; + struct sk_buff *skb; + struct ztdeth_header *zh; + unsigned long flags; + struct net_device *dev; + unsigned char addr[ETH_ALEN]; + unsigned short subaddr; /* Network byte order */ + + spin_lock_irqsave(&zlock, flags); + z = pvt; + if (z->dev) { + /* Copy fields to local variables to remove spinlock ASAP */ + dev = z->dev; + memcpy(addr, z->addr, sizeof(z->addr)); + subaddr = z->subaddr; + spin_unlock_irqrestore(&zlock, flags); + skb = dev_alloc_skb(msglen + dev->hard_header_len + sizeof(struct ztdeth_header) + 32); + if (skb) { + /* Reserve header space */ + skb_reserve(skb, dev->hard_header_len + sizeof(struct ztdeth_header)); + + /* Copy message body */ + memcpy(skb_put(skb, msglen), msg, msglen); + + /* Throw on header */ + zh = (struct ztdeth_header *)skb_push(skb, sizeof(struct ztdeth_header)); + zh->subaddr = subaddr; + + /* Setup protocol and such */ + skb->protocol = __constant_htons(ETH_P_ZTDETH); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + skb_set_network_header(skb, 0); +#else + skb->nh.raw = skb->data; +#endif + skb->dev = dev; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) + dev_hard_header(skb, dev, ETH_P_ZTDETH, addr, dev->dev_addr, skb->len); +#else + if (dev->hard_header) + dev->hard_header(skb, dev, ETH_P_ZTDETH, addr, dev->dev_addr, skb->len); +#endif + skb_queue_tail(&skbs, skb); + } + } + else + spin_unlock_irqrestore(&zlock, flags); + return 0; +} + + +static int ztdeth_flush(void) +{ + struct sk_buff *skb; + + /* Handle all transmissions now */ + while ((skb = skb_dequeue(&skbs))) { + dev_queue_xmit(skb); + } + return 0; +} + +static struct packet_type ztdeth_ptype = { + type: __constant_htons(ETH_P_ZTDETH), /* Protocol */ + dev: NULL, /* Device (NULL = wildcard) */ + func: ztdeth_rcv, /* Receiver */ +}; + +static int digit2int(char d) +{ + switch(d) { + case 'F': + case 'E': + case 'D': + case 'C': + case 'B': + case 'A': + return d - 'A' + 10; + case 'f': + case 'e': + case 'd': + case 'c': + case 'b': + case 'a': + return d - 'a' + 10; + case '9': + case '8': + case '7': + case '6': + case '5': + case '4': + case '3': + case '2': + case '1': + case '0': + return d - '0'; + } + return -1; +} + +static int hex2int(char *s) +{ + int res; + int tmp; + /* Gotta be at least one digit */ + if (strlen(s) < 1) + return -1; + /* Can't be more than two */ + if (strlen(s) > 2) + return -1; + /* Grab the first digit */ + res = digit2int(s[0]); + if (res < 0) + return -1; + tmp = res; + /* Grab the next */ + if (strlen(s) > 1) { + res = digit2int(s[1]); + if (res < 0) + return -1; + tmp = tmp * 16 + res; + } + return tmp; +} + +static void ztdeth_destroy(void *pvt) +{ + struct ztdeth *z = pvt; + unsigned long flags; + struct ztdeth *prev=NULL, *cur; + spin_lock_irqsave(&zlock, flags); + cur = zdevs; + while(cur) { + if (cur == z) { + if (prev) + prev->next = cur->next; + else + zdevs = cur->next; + break; + } + prev = cur; + cur = cur->next; + } + spin_unlock_irqrestore(&zlock, flags); + if (cur == z) { /* Successfully removed */ + printk("TDMoE: Removed interface for %s\n", z->span->name); + kfree(z); +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#else + module_put(THIS_MODULE); +#endif + } +} + +static void *ztdeth_create(struct zt_span *span, char *addr) +{ + struct ztdeth *z; + char src[256]; + char tmp[256], *tmp2, *tmp3, *tmp4 = NULL; + int res,x; + unsigned long flags; + + z = kmalloc(sizeof(struct ztdeth), GFP_KERNEL); + if (z) { + /* Zero it out */ + memset(z, 0, sizeof(struct ztdeth)); + + /* Address should be /[/subaddr] */ + strncpy(tmp, addr, sizeof(tmp) - 1); + tmp2 = strchr(tmp, '/'); + if (tmp2) { + *tmp2 = '\0'; + tmp2++; + strncpy(z->ethdev, tmp, sizeof(z->ethdev) - 1); + } else { + printk("Invalid TDMoE address (no device) '%s'\n", addr); + kfree(z); + return NULL; + } + if (tmp2) { + tmp4 = strchr(tmp2+1, '/'); + if (tmp4) { + *tmp4 = '\0'; + tmp4++; + } + /* We don't have SSCANF :( Gotta do this the hard way */ + tmp3 = strchr(tmp2, ':'); + for (x=0;x<6;x++) { + if (tmp2) { + if (tmp3) { + *tmp3 = '\0'; + tmp3++; + } + res = hex2int(tmp2); + if (res < 0) + break; + z->addr[x] = res & 0xff; + } else + break; + if ((tmp2 = tmp3)) + tmp3 = strchr(tmp2, ':'); + } + if (x != 6) { + printk("TDMoE: Invalid MAC address in: %s\n", addr); + kfree(z); + return NULL; + } + } else { + printk("TDMoE: Missing MAC address\n"); + kfree(z); + return NULL; + } + if (tmp4) { + int sub = 0; + int mul = 1; + + /* We have a subaddr */ + tmp3 = tmp4 + strlen (tmp4) - 1; + while (tmp3 >= tmp4) { + if (*tmp3 >= '0' && *tmp3 <= '9') { + sub += (*tmp3 - '0') * mul; + } else { + printk("TDMoE: Invalid subaddress\n"); + kfree(z); + return NULL; + } + mul *= 10; + tmp3--; + } + z->subaddr = htons(sub); + } + z->dev = dev_get_by_name( +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) + &init_net, +#endif + z->ethdev); + if (!z->dev) { + printk("TDMoE: Invalid device '%s'\n", z->ethdev); + kfree(z); + return NULL; + } + z->span = span; + src[0] ='\0'; + for (x=0;x<5;x++) + sprintf(src + strlen(src), "%02x:", z->dev->dev_addr[x]); + sprintf(src + strlen(src), "%02x", z->dev->dev_addr[5]); + printk("TDMoE: Added new interface for %s at %s (addr=%s, src=%s, subaddr=%d)\n", span->name, z->dev->name, addr, src, ntohs(z->subaddr)); + + spin_lock_irqsave(&zlock, flags); + z->next = zdevs; + zdevs = z; + spin_unlock_irqrestore(&zlock, flags); +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#else + if(!try_module_get(THIS_MODULE)) + printk("TDMoE: Unable to increment module use count\n"); +#endif + } + return z; +} + +static struct zt_dynamic_driver ztd_eth = { + "eth", + "Ethernet", + ztdeth_create, + ztdeth_destroy, + ztdeth_transmit, + ztdeth_flush +}; + +static struct notifier_block ztdeth_nblock = { + notifier_call: ztdeth_notifier, +}; + +static int __init ztdeth_init(void) +{ + dev_add_pack(&ztdeth_ptype); + register_netdevice_notifier(&ztdeth_nblock); + zt_dynamic_register(&ztd_eth); + + skb_queue_head_init(&skbs); + + return 0; +} + +static void __exit ztdeth_exit(void) +{ + dev_remove_pack(&ztdeth_ptype); + unregister_netdevice_notifier(&ztdeth_nblock); + zt_dynamic_unregister(&ztd_eth); +} + +MODULE_DESCRIPTION("Zaptel Dynamic TDMoE Support"); +MODULE_AUTHOR("Mark Spencer "); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +module_init(ztdeth_init); +module_exit(ztdeth_exit); diff --git a/kernel/ztd-loc.c b/kernel/ztd-loc.c new file mode 100644 index 0000000..6486a2a --- /dev/null +++ b/kernel/ztd-loc.c @@ -0,0 +1,282 @@ +/* + * Dynamic Span Interface for Zaptel (Local Interface) + * + * Written by Nicolas Bougues + * + * Copyright (C) 2004, Axialys Interactive + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Note : a zaptel source must exist prior to loading this driver + * + * Address syntax : + * :[:] + * + * As of now, keys and ids are single digit only + * + * One span may have up to one "normal" peer, and one "monitor" peer + * + * Example : + * + * Say you have two spans cross connected, a thrid one monitoring RX on the + * first one, a fourth one monitoring RX on the second one + * + * 1:0 + * 1:1 + * 1:2:0 + * 1:3:1 + * + * Contrary to TDMoE, no frame loss can occur. + * + * See bug #2021 for more details + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_DEVFS_FS +#include +#endif +#ifdef STANDALONE_ZAPATA +#include "zaptel.h" +#else +#include +#endif + +#ifdef DEFINE_SPINLOCK +static DEFINE_SPINLOCK(zlock); +#else +static spinlock_t zlock = SPIN_LOCK_UNLOCKED; +#endif + +static struct ztdlocal { + unsigned short key; + unsigned short id; + struct ztdlocal *monitor_rx_peer; /* Indicates the peer span that monitors this span */ + struct ztdlocal *peer; /* Indicates the rw peer for this span */ + struct zt_span *span; + struct ztdlocal *next; +} *zdevs = NULL; + +/*static*/ int ztdlocal_transmit(void *pvt, unsigned char *msg, int msglen) +{ + struct ztdlocal *z; + unsigned long flags; + + spin_lock_irqsave(&zlock, flags); + z = pvt; + if (z->peer && z->peer->span) { + zt_dynamic_receive(z->peer->span, msg, msglen); + } + if (z->monitor_rx_peer && z->monitor_rx_peer->span) { + zt_dynamic_receive(z->monitor_rx_peer->span, msg, msglen); + } + spin_unlock_irqrestore(&zlock, flags); + return 0; +} + +static int digit2int(char d) +{ + switch(d) { + case 'F': + case 'E': + case 'D': + case 'C': + case 'B': + case 'A': + return d - 'A' + 10; + case 'f': + case 'e': + case 'd': + case 'c': + case 'b': + case 'a': + return d - 'a' + 10; + case '9': + case '8': + case '7': + case '6': + case '5': + case '4': + case '3': + case '2': + case '1': + case '0': + return d - '0'; + } + return -1; +} + +/*static*/ void ztdlocal_destroy(void *pvt) +{ + struct ztdlocal *z = pvt; + unsigned long flags; + struct ztdlocal *prev=NULL, *cur; + + spin_lock_irqsave(&zlock, flags); + cur = zdevs; + while(cur) { + if (cur->peer == z) + cur->peer = NULL; + if (cur->monitor_rx_peer == z) + cur->monitor_rx_peer = NULL; + cur = cur->next; + } + cur = zdevs; + while(cur) { + if (cur == z) { + if (prev) + prev->next = cur->next; + else + zdevs = cur->next; + break; + } + prev = cur; + cur = cur->next; + } + spin_unlock_irqrestore(&zlock, flags); + if (cur == z) { + printk("TDMoL: Removed interface for %s, key %d id %d\n", z->span->name, z->key, z->id); +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#else + module_put(THIS_MODULE); +#endif + kfree(z); + } +} + +/*static*/ void *ztdlocal_create(struct zt_span *span, char *address) +{ + struct ztdlocal *z, *l; + unsigned long flags; + int key = -1, id = -1, monitor = -1; + + if (strlen(address) >= 3) { + if (address[1] != ':') + goto INVALID_ADDRESS; + key = digit2int(address[0]); + id = digit2int(address[2]); + } + if (strlen (address) == 5) { + if (address[3] != ':') + goto INVALID_ADDRESS; + monitor = digit2int(address[4]); + } + + if (key == -1 || id == -1) + goto INVALID_ADDRESS; + + z = kmalloc(sizeof(struct ztdlocal), GFP_KERNEL); + if (z) { + /* Zero it out */ + memset(z, 0, sizeof(struct ztdlocal)); + + z->key = key; + z->id = id; + z->span = span; + + spin_lock_irqsave(&zlock, flags); + /* Add this peer to any existing spans with same key + And add them as peers to this one */ + for (l = zdevs; l; l = l->next) + if (l->key == z->key) { + if (l->id == z->id) { + printk ("TDMoL: Duplicate id (%d) for key %d\n", z->id, z->key); + goto CLEAR_AND_DEL_FROM_PEERS; + } + if (monitor == -1) { + if (l->peer) { + printk ("TDMoL: Span with key %d and id %d already has a R/W peer\n", z->key, z->id); + goto CLEAR_AND_DEL_FROM_PEERS; + } else { + l->peer = z; + z->peer = l; + } + } + if (monitor == l->id) { + if (l->monitor_rx_peer) { + printk ("TDMoL: Span with key %d and id %d already has a monitoring peer\n", z->key, z->id); + goto CLEAR_AND_DEL_FROM_PEERS; + } else { + l->monitor_rx_peer = z; + } + } + } + z->next = zdevs; + zdevs = z; + spin_unlock_irqrestore(&zlock, flags); +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#else + if(!try_module_get(THIS_MODULE)) + printk("TDMoL: Unable to increment module use count\n"); +#endif + + printk("TDMoL: Added new interface for %s, key %d id %d\n", span->name, z->key, z->id); + } + return z; + +CLEAR_AND_DEL_FROM_PEERS: + for (l = zdevs; l; l = l->next) { + if (l->peer == z) + l->peer = NULL; + if (l->monitor_rx_peer == z) + l->monitor_rx_peer = NULL; + } + kfree (z); + return NULL; + +INVALID_ADDRESS: + printk ("TDMoL: Invalid address %s\n", address); + return NULL; +} + +static struct zt_dynamic_driver ztd_local = { + "loc", + "Local", + ztdlocal_create, + ztdlocal_destroy, + ztdlocal_transmit, + NULL /* flush */ +}; + +/*static*/ int __init ztdlocal_init(void) +{ + zt_dynamic_register(&ztd_local); + return 0; +} + +/*static*/ void __exit ztdlocal_exit(void) +{ + zt_dynamic_unregister(&ztd_local); +} + +module_init(ztdlocal_init); +module_exit(ztdlocal_exit); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif diff --git a/kernel/ztdummy.c b/kernel/ztdummy.c new file mode 100644 index 0000000..5cedaa3 --- /dev/null +++ b/kernel/ztdummy.c @@ -0,0 +1,429 @@ +/* + * Dummy Zaptel Driver for Zapata Telephony interface + * + * Required: usb-uhci module and kernel > 2.4.4 OR kernel > 2.6.0 + * + * Written by Robert Pleh + * 2.6 version by Tony Hoyle + * Unified by Mark Spencer + * Converted to use RTC on i386 by Tony Mountifield + * + * Converted to use HighResTimers on i386 by Jeffery Palmer + * + * Copyright (C) 2002, Hermes Softlab + * Copyright (C) 2004, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * To use the high resolution timers, in your kernel CONFIG_HIGH_RES_TIMERS + * needs to be enabled (Processor type and features -> High Resolution + * Timer Support), and optionally HPET (Processor type and features -> + * HPET Timer Support) provides a better clock source. + */ + +#include + +#ifndef VERSION_CODE +# define VERSION_CODE(vers,rel,seq) ( ((vers)<<16) | ((rel)<<8) | (seq) ) +#endif + + +#if LINUX_VERSION_CODE < VERSION_CODE(2,4,5) +# error "This kernel is too old: not supported by this file" +#endif + +/* + * NOTE: (only applies to kernel 2.6) + * If using an i386 architecture without a PC real-time clock, + * the #define USE_RTC should be commented out. + */ +#if defined(__i386__) || defined(__x86_64__) +#if LINUX_VERSION_CODE >= VERSION_CODE(2,6,13) +/* The symbol hrtimer_forward is only exported as of 2.6.22: */ +#if defined(CONFIG_HIGH_RES_TIMERS) && LINUX_VERSION_CODE >= VERSION_CODE(2,6,22) +#define USE_HIGHRESTIMER +#else +#define USE_RTC +#endif +#else +#if 0 +#define USE_RTC +#endif +#endif +#endif + +#include +#include +#include +#include +#include +#include "zaptel.h" +#ifndef LINUX26 +#include +#include +#include +#endif +#ifdef LINUX26 +#ifdef USE_HIGHRESTIMER +#include +#endif +#ifdef USE_RTC +#include +#endif +#include +#endif +#include "ztdummy.h" + + +static struct ztdummy *ztd; + +static int debug = 0; + +#ifdef LINUX26 +#ifdef USE_HIGHRESTIMER +#define CLOCK_SRC "HRtimer" +struct hrtimer zaptimer; +#elif defined(USE_RTC) +#define CLOCK_SRC "RTC" +static int rtc_rate = 0; +static int current_rate = 0; +static int taskletpending = 0; +static struct tasklet_struct ztd_tlet; +static void ztd_tasklet(unsigned long data); +#else /* Linux 2.6, but no RTC or HRTIMER used */ +#define CLOCK_SRC "Linux26" +/* 2.6 kernel timer stuff */ +static struct timer_list timer; +#endif +#else +#if LINUX_VERSION_CODE < VERSION_CODE(2,4,5) +# error "This kernel is too old: not supported by this file" +#endif +#define CLOCK_SRC "UHCI" +/* Old UCHI stuff */ +static uhci_desc_t *td; +static uhci_t *s; +static int monitor = 0; + +/* exported kernel symbols */ +extern int insert_td (uhci_t *s, uhci_desc_t *qh, uhci_desc_t* new, int flags); +extern int alloc_td (uhci_t *s, uhci_desc_t ** new, int flags); +extern int insert_td_horizontal (uhci_t *s, uhci_desc_t *td, uhci_desc_t* new); +extern int unlink_td (uhci_t *s, uhci_desc_t *element, int phys_unlink); +extern void fill_td (uhci_desc_t *td, int status, int info, __u32 buffer); +extern void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs); +extern int delete_desc (uhci_t *s, uhci_desc_t *element); +extern uhci_t **uhci_devices; + +#endif + + +#define ZAPTEL_RATE 1000 /* zaptel ticks per second */ +#define ZAPTEL_TIME (1000000 / ZAPTEL_RATE) /* zaptel tick time in us */ +#define ZAPTEL_TIME_NS (ZAPTEL_TIME * 1000) /* zaptel tick time in ns */ + +/* Different bits of the debug variable: */ +#define DEBUG_GENERAL (1 << 0) +#define DEBUG_TICKS (1 << 1) + + +#ifdef LINUX26 +#ifdef USE_RTC +static void update_rtc_rate(struct ztdummy *ztd) +{ + if (((rtc_rate & (rtc_rate - 1)) != 0) || (rtc_rate > 8192) || (rtc_rate < 2)) { + printk(KERN_NOTICE "Invalid RTC rate %d specified\n", rtc_rate); + rtc_rate = current_rate; /* Set default RTC rate */ + } + if (!rtc_rate || (rtc_rate != current_rate)) { + rtc_control(&ztd->rtc_task, RTC_IRQP_SET, current_rate = (rtc_rate ? rtc_rate : 1024)); /* 1024 Hz */ + printk(KERN_INFO "ztdummy: RTC rate is %d\n", rtc_rate); + ztd->counter = 0; + } +} + +static void ztd_tasklet(unsigned long data) +{ + if (taskletpending) + update_rtc_rate((struct ztdummy *)ztd); + taskletpending = 0; +} + +/* rtc_interrupt - called at 1024Hz from hook in RTC handler */ +static void ztdummy_rtc_interrupt(void *private_data) +{ + struct ztdummy *ztd = private_data; + unsigned long flags; + + /* Is spinlock required here??? */ + spin_lock_irqsave(&ztd->rtclock, flags); + ztd->counter += ZAPTEL_TIME; + while (ztd->counter >= current_rate) { + ztd->counter -= current_rate; + /* Update of RTC IRQ rate isn't possible from interrupt handler :( */ + if (!taskletpending && (current_rate != rtc_rate)) { + taskletpending = 1; + tasklet_hi_schedule(&ztd_tlet); + } + zt_receive(&ztd->span); + zt_transmit(&ztd->span); + } + spin_unlock_irqrestore(&ztd->rtclock, flags); +} +#elif defined(USE_HIGHRESTIMER) +static enum hrtimer_restart ztdummy_hr_int(struct hrtimer *htmr) +{ + unsigned long overrun; + + /* Trigger Zaptel */ + zt_receive(&ztd->span); + zt_transmit(&ztd->span); + + /* Overrun should always return 1, since we are in the timer that + * expired. + * We should worry if overrun is 2 or more; then we really missed + * a tick */ + overrun = hrtimer_forward(&zaptimer, htmr->expires, + ktime_set(0, ZAPTEL_TIME_NS)); + if(overrun > 1) { + if(printk_ratelimit()) + printk(KERN_NOTICE "ztdummy: HRTimer missed %lu ticks\n", + overrun - 1); + } + + if(debug && DEBUG_TICKS) { + static int count = 0; + /* Printk every 5 seconds, good test to see if timer is + * running properly */ + if (count++ % 5000 == 0) + printk(KERN_DEBUG "ztdummy: 5000 ticks from hrtimer\n"); + } + + /* Always restart the timer */ + return HRTIMER_RESTART; +} +#else +/* use kernel system tick timer if PC architecture RTC is not available */ +static void ztdummy_timer(unsigned long param) +{ + timer.expires = jiffies + 1; + add_timer(&timer); + + ztd->counter += ZAPTEL_TIME; + while (ztd->counter >= HZ) { + ztd->counter -= HZ; + zt_receive(&ztd->span); + zt_transmit(&ztd->span); + } +} +#endif +#else +static void ztdummy_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned short status; + unsigned int io_addr = s->io_addr; + + status = inw (io_addr + USBSTS); + if (status != 0) { /* interrupt from our USB port */ + static int check_int = 0; + zt_receive(&ztd->span); + zt_transmit(&ztd->span); + /* TODO: What's the relation between monitor and + * DEBUG_TICKS */ + if (monitor && check_int) { + check_int = 1; + printk(KERN_NOTICE "ztdummy: interrupt triggered \n"); + } + } + return; +} +#endif + +static int ztdummy_initialize(struct ztdummy *ztd) +{ + /* Zapata stuff */ + sprintf(ztd->span.name, "ZTDUMMY/1"); + snprintf(ztd->span.desc, sizeof(ztd->span.desc) - 1, "%s (source: " CLOCK_SRC ") %d", ztd->span.name, 1); + sprintf(ztd->chan.name, "ZTDUMMY/%d/%d", 1, 0); + strncpy(ztd->span.devicetype, "Zaptel Dummy Timing Driver", sizeof(ztd->span.devicetype) - 1); + ztd->chan.chanpos = 1; + ztd->span.chans = &ztd->chan; + ztd->span.channels = 0; /* no channels on our span */ + ztd->span.deflaw = ZT_LAW_MULAW; + init_waitqueue_head(&ztd->span.maintq); + ztd->span.pvt = ztd; + ztd->chan.pvt = ztd; + if (zt_register(&ztd->span, 0)) { + return -1; + } + return 0; +} + +int init_module(void) +{ +#ifdef LINUX26 +#ifdef USE_RTC + int err; +#endif +#else + int irq; +#ifdef DEFINE_SPINLOCK + DEFINE_SPINLOCK(mylock); +#else + spinlock_t mylock = SPIN_LOCK_UNLOCKED; +#endif + + if (uhci_devices==NULL) { + printk (KERN_ERR "ztdummy: Uhci_devices pointer error.\n"); + return -ENODEV; + } + s=*uhci_devices; /* uhci device */ + if (s==NULL) { + printk (KERN_ERR "ztdummy: No uhci_device found.\n"); + return -ENODEV; + } +#endif + + ztd = kmalloc(sizeof(struct ztdummy), GFP_KERNEL); + if (ztd == NULL) { + printk(KERN_ERR "ztdummy: Unable to allocate memory\n"); + return -ENOMEM; + } + + memset(ztd, 0x0, sizeof(struct ztdummy)); + + if (ztdummy_initialize(ztd)) { + printk(KERN_ERR "ztdummy: Unable to intialize zaptel driver\n"); + kfree(ztd); + return -ENODEV; + } + +#ifdef LINUX26 + ztd->counter = 0; +#ifdef USE_RTC + ztd->rtclock = SPIN_LOCK_UNLOCKED; + ztd->rtc_task.func = ztdummy_rtc_interrupt; + ztd->rtc_task.private_data = ztd; + err = rtc_register(&ztd->rtc_task); + if (err < 0) { + printk(KERN_ERR "ztdummy: Unable to register zaptel rtc driver\n"); + zt_unregister(&ztd->span); + kfree(ztd); + return err; + } + /* Set default RTC interrupt rate to 1024Hz */ + if (!rtc_rate) + rtc_rate = 1024; + update_rtc_rate(ztd); + rtc_control(&ztd->rtc_task, RTC_PIE_ON, 0); + tasklet_init(&ztd_tlet, ztd_tasklet, 0); +#elif defined(USE_HIGHRESTIMER) + printk(KERN_DEBUG "ztdummy: Trying to load High Resolution Timer\n"); + hrtimer_init(&zaptimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + printk(KERN_DEBUG "ztdummy: Initialized High Resolution Timer\n"); + + /* Set timer callback function */ + zaptimer.function = ztdummy_hr_int; + + printk(KERN_DEBUG "ztdummy: Starting High Resolution Timer\n"); + hrtimer_start(&zaptimer, ktime_set(0, ZAPTEL_TIME_NS), HRTIMER_MODE_REL); + printk(KERN_INFO "ztdummy: High Resolution Timer started, good to go\n"); +#else + init_timer(&timer); + timer.function = ztdummy_timer; + timer.expires = jiffies + 1; + add_timer(&timer); +#endif +#else + irq=s->irq; + spin_lock_irq(&mylock); + free_irq(s->irq, s); /* remove uhci_interrupt temporaly */ + if (request_irq (irq, ztdummy_interrupt, ZAP_IRQ_SHARED, "ztdummy", ztd)) { + spin_unlock_irq(&mylock); + err("Our request_irq %d failed!",irq); + kfree(ztd); + return -EIO; + } /* we add our handler first, to assure, that our handler gets called first */ + if (request_irq (irq, uhci_interrupt, ZAP_IRQ_SHARED, s->uhci_pci->driver->name, s)) { + spin_unlock_irq(&mylock); + err("Original request_irq %d failed!",irq); + } + spin_unlock_irq(&mylock); + + /* add td to usb host controller interrupt queue */ + alloc_td(s, &td, 0); + fill_td(td, TD_CTRL_IOC, 0, 0); + insert_td_horizontal(s, s->int_chain[0], td); /* use int_chain[0] to get 1ms interrupts */ +#endif + + if (debug) + printk(KERN_DEBUG "ztdummy: init() finished\n"); + return 0; +} + + +void cleanup_module(void) +{ +#ifdef LINUX26 +#ifdef USE_RTC + if (taskletpending) { + tasklet_disable(&ztd_tlet); + tasklet_kill(&ztd_tlet); + } + rtc_control(&ztd->rtc_task, RTC_PIE_OFF, 0); + rtc_unregister(&ztd->rtc_task); +#elif defined(USE_HIGHRESTIMER) + /* Stop high resolution timer */ + hrtimer_cancel(&zaptimer); +#else + del_timer(&timer); +#endif +#else + free_irq(s->irq, ztd); /* disable interrupts */ +#endif + zt_unregister(&ztd->span); + kfree(ztd); +#ifndef LINUX26 + unlink_td(s, td, 1); + delete_desc(s, td); +#endif + if (debug) + printk("ztdummy: cleanup() finished\n"); +} + + + +#ifdef LINUX26 +module_param(debug, int, 0600); +#ifdef USE_RTC +module_param(rtc_rate, int, 0600); +#endif +#else +MODULE_PARM(debug, "i"); +#endif + +#ifndef LINUX26 +MODULE_PARM(monitor, "i"); +#endif +MODULE_DESCRIPTION("Dummy Zaptel Driver"); +MODULE_AUTHOR("Robert Pleh "); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif diff --git a/kernel/ztdummy.h b/kernel/ztdummy.h new file mode 100644 index 0000000..25e37c9 --- /dev/null +++ b/kernel/ztdummy.h @@ -0,0 +1,152 @@ +/* + * Dummy Zaptel Driver for Zapata Telephony interface + * + * Written by Robert Pleh + * + * Copyright (C) 2002, Hermes Softlab + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * +*/ + +#include +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19) +#define USB2420 +#endif + +struct ztdummy { + struct zt_span span; + struct zt_chan chan; +#ifdef LINUX26 + unsigned int counter; +#ifdef USE_RTC + spinlock_t rtclock; + rtc_task_t rtc_task; +#endif +#endif +}; + + +#ifndef LINUX26 +/* Uhci definitions and structures - from file usb-uhci.h */ +#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ +#define USBSTS 2 + +typedef enum { + TD_TYPE, QH_TYPE +} uhci_desc_type_t; + +typedef struct { + __u32 link; + __u32 status; + __u32 info; + __u32 buffer; +} uhci_td_t, *puhci_td_t; + + +typedef struct { + __u32 head; + __u32 element; /* Queue element pointer */ +} uhci_qh_t, *puhci_qh_t; + +typedef struct { + union { + uhci_td_t td; + uhci_qh_t qh; + } hw; + uhci_desc_type_t type; + dma_addr_t dma_addr; + struct list_head horizontal; + struct list_head vertical; + struct list_head desc_list; + int last_used; +} uhci_desc_t, *puhci_desc_t; + +typedef struct { + struct list_head desc_list; // list pointer to all corresponding TDs/QHs associated with this request + dma_addr_t setup_packet_dma; + dma_addr_t transfer_buffer_dma; + unsigned long started; +#ifdef USB2420 + struct urb *next_queued_urb; // next queued urb for this EP + struct urb *prev_queued_urb; +#else + urb_t *next_queued_urb; + urb_t *prev_queued_urb; +#endif + uhci_desc_t *bottom_qh; + uhci_desc_t *next_qh; // next helper QH + char use_loop; + char flags; +} urb_priv_t, *purb_priv_t; + +struct virt_root_hub { + int devnum; /* Address of Root Hub endpoint */ + void *urb; + void *int_addr; + int send; + int interval; + int numports; + int c_p_r[8]; + struct timer_list rh_int_timer; +}; + +typedef struct uhci { + int irq; + unsigned int io_addr; + unsigned int io_size; + unsigned int maxports; + int running; + + int apm_state; + + struct uhci *next; // chain of uhci device contexts + + struct list_head urb_list; // list of all pending urbs + + spinlock_t urb_list_lock; // lock to keep consistency + + int unlink_urb_done; + atomic_t avoid_bulk; + + struct usb_bus *bus; // our bus + + __u32 *framelist; + dma_addr_t framelist_dma; + uhci_desc_t **iso_td; + uhci_desc_t *int_chain[8]; + uhci_desc_t *ls_control_chain; + uhci_desc_t *control_chain; + uhci_desc_t *bulk_chain; + uhci_desc_t *chain_end; + uhci_desc_t *td1ms; + uhci_desc_t *td32ms; + struct list_head free_desc; + spinlock_t qh_lock; + spinlock_t td_lock; + struct virt_root_hub rh; //private data of the virtual root hub + int loop_usage; // URBs using bandwidth reclamation + + struct list_head urb_unlinked; // list of all unlinked urbs + long timeout_check; + int timeout_urbs; + struct pci_dev *uhci_pci; + struct pci_pool *desc_pool; + long last_error_time; // last error output in uhci_interrupt() +} uhci_t, *puhci_t; +#endif diff --git a/kernel/ztdynamic.c b/kernel/ztdynamic.c new file mode 100644 index 0000000..01b22e2 --- /dev/null +++ b/kernel/ztdynamic.c @@ -0,0 +1,870 @@ +/* + * Dynamic Span Interface for Zaptel + * + * Written by Mark Spencer + * + * Copyright (C) 2001, Linux Support Services, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_DEVFS_FS +#include +#endif +#ifdef STANDALONE_ZAPATA +#include "zaptel.h" +#else +#include +#endif +#ifdef LINUX26 +#include +#endif + +/* + * Tasklets provide better system interactive response at the cost of the + * possibility of losing a frame of data at very infrequent intervals. If + * you are more concerned with the performance of your machine, enable the + * tasklets. If you are strict about absolutely no drops, then do not enable + * tasklets. + */ + +#define ENABLE_TASKLETS + +/* + * Dynamic spans implemented using TDM over X with standard message + * types. Message format is as follows: + * + * Byte #: Meaning + * 0 Number of samples per channel + * 1 Current flags on span + * Bit 0: Yellow Alarm + * Bit 1: Sig bits present + * Bits 2-7: reserved for future use + * 2-3 16-bit counter value for detecting drops, network byte order. + * 4-5 Number of channels in the message, network byte order + * 6... 16-bit words, containing sig bits for each + * four channels, least significant 4 bits being + * the least significant channel, network byte order. + * the rest data for each channel, all samples per channel + before moving to the next. + */ + +/* Arbitrary limit to the max # of channels in a span */ +#define ZT_DYNAMIC_MAX_CHANS 256 + +#define ZTD_FLAG_YELLOW_ALARM (1 << 0) +#define ZTD_FLAG_SIGBITS_PRESENT (1 << 1) +#define ZTD_FLAG_LOOPBACK (1 << 2) + +#define ERR_NSAMP (1 << 16) +#define ERR_NCHAN (1 << 17) +#define ERR_LEN (1 << 18) + +EXPORT_SYMBOL(zt_dynamic_register); +EXPORT_SYMBOL(zt_dynamic_unregister); +EXPORT_SYMBOL(zt_dynamic_receive); + +#ifdef ENABLE_TASKLETS +static int taskletrun; +static int taskletsched; +static int taskletpending; +static int taskletexec; +static int txerrors; +static struct tasklet_struct ztd_tlet; + +static void ztd_tasklet(unsigned long data); +#endif + + +static struct zt_dynamic { + char addr[40]; + char dname[20]; + int err; + int usecount; + int dead; + long rxjif; + unsigned short txcnt; + unsigned short rxcnt; + struct zt_span span; + struct zt_chan *chans; + struct zt_dynamic *next; + struct zt_dynamic_driver *driver; + void *pvt; + int timing; + int master; + unsigned char *msgbuf; +} *dspans; + +static struct zt_dynamic_driver *drivers = NULL; + +static int debug = 0; + +static int hasmaster = 0; +#ifdef DEFINE_SPINLOCK +static DEFINE_SPINLOCK(dlock); +#else +static spinlock_t dlock = SPIN_LOCK_UNLOCKED; +#endif + +#ifdef DEFINE_RWLOCK +static DEFINE_RWLOCK(drvlock); +#else +static rwlock_t drvlock = RW_LOCK_UNLOCKED; +#endif + +static void checkmaster(void) +{ + unsigned long flags; + int newhasmaster=0; + int best = 9999999; + struct zt_dynamic *z, *master=NULL; + spin_lock_irqsave(&dlock, flags); + z = dspans; + while(z) { + if (z->timing) { + z->master = 0; + if (!(z->span.alarms & ZT_ALARM_RED) && + (z->timing < best) && !z->dead) { + /* If not in alarm and they're + a better timing source, use them */ + master = z; + best = z->timing; + newhasmaster = 1; + } + } + z = z->next; + } + hasmaster = newhasmaster; + /* Mark the new master if there is one */ + if (master) + master->master = 1; + spin_unlock_irqrestore(&dlock, flags); + if (master) + printk("TDMoX: New master: %s\n", master->span.name); + else + printk("TDMoX: No master.\n"); +} + +static void ztd_sendmessage(struct zt_dynamic *z) +{ + unsigned char *buf = z->msgbuf; + unsigned short bits; + int msglen = 0; + int x; + int offset; + + /* Byte 0: Number of samples per channel */ + *buf = ZT_CHUNKSIZE; + buf++; msglen++; + + /* Byte 1: Flags */ + *buf = 0; + if (z->span.alarms & ZT_ALARM_RED) + *buf |= ZTD_FLAG_YELLOW_ALARM; + *buf |= ZTD_FLAG_SIGBITS_PRESENT; + buf++; msglen++; + + /* Bytes 2-3: Transmit counter */ + *((unsigned short *)buf) = htons((unsigned short)z->txcnt); + z->txcnt++; + buf++; msglen++; + buf++; msglen++; + + /* Bytes 4-5: Number of channels */ + *((unsigned short *)buf) = htons((unsigned short)z->span.channels); + buf++; msglen++; + buf++; msglen++; + bits = 0; + offset = 0; + for (x=0;xspan.channels;x++) { + offset = x % 4; + bits |= (z->chans[x].txsig & 0xf) << (offset << 2); + if (offset == 3) { + /* Write the bits when we have four channels */ + *((unsigned short *)buf) = htons(bits); + buf++; msglen++; + buf++; msglen++; + bits = 0; + } + } + + if (offset != 3) { + /* Finish it off if it's not done already */ + *((unsigned short *)buf) = htons(bits); + buf++; msglen++; + buf++; msglen++; + } + + for (x=0;xspan.channels;x++) { + memcpy(buf, z->chans[x].writechunk, ZT_CHUNKSIZE); + buf += ZT_CHUNKSIZE; + msglen += ZT_CHUNKSIZE; + } + + z->driver->transmit(z->pvt, z->msgbuf, msglen); + +} + +static void __ztdynamic_run(void) +{ + unsigned long flags; + struct zt_dynamic *z; + struct zt_dynamic_driver *drv; + int y; + spin_lock_irqsave(&dlock, flags); + z = dspans; + while(z) { + if (!z->dead) { + /* Ignore dead spans */ + for (y=0;yspan.channels;y++) { + /* Echo cancel double buffered data */ + zt_ec_chunk(&z->span.chans[y], z->span.chans[y].readchunk, z->span.chans[y].writechunk); + } + zt_receive(&z->span); + zt_transmit(&z->span); + /* Handle all transmissions now */ + ztd_sendmessage(z); + } + z = z->next; + } + spin_unlock_irqrestore(&dlock, flags); + + read_lock(&drvlock); + drv = drivers; + while(drv) { + /* Flush any traffic still pending in the driver */ + if (drv->flush) { + drv->flush(); + } + drv = drv->next; + } + read_unlock(&drvlock); +} + +#ifdef ENABLE_TASKLETS +static void ztdynamic_run(void) +{ + if (!taskletpending) { + taskletpending = 1; + taskletsched++; + tasklet_hi_schedule(&ztd_tlet); + } else { + txerrors++; + } +} +#else +#define ztdynamic_run __ztdynamic_run +#endif + +void zt_dynamic_receive(struct zt_span *span, unsigned char *msg, int msglen) +{ + struct zt_dynamic *ztd = span->pvt; + int newerr=0; + unsigned long flags; + int sflags; + int xlen; + int x, bits, sig; + int nchans, master; + int newalarm; + unsigned short rxpos, rxcnt; + + + spin_lock_irqsave(&dlock, flags); + if (msglen < 6) { + spin_unlock_irqrestore(&dlock, flags); + newerr = ERR_LEN; + if (newerr != ztd->err) { + printk("Span %s: Insufficient samples for header (only %d)\n", span->name, msglen); + } + ztd->err = newerr; + return; + } + + /* First, check the chunksize */ + if (*msg != ZT_CHUNKSIZE) { + spin_unlock_irqrestore(&dlock, flags); + newerr = ERR_NSAMP | msg[0]; + if (newerr != ztd->err) { + printk("Span %s: Expected %d samples, but receiving %d\n", span->name, ZT_CHUNKSIZE, msg[0]); + } + ztd->err = newerr; + return; + } + msg++; + sflags = *msg; + msg++; + + rxpos = ntohs(*((unsigned short *)msg)); + msg++; + msg++; + + nchans = ntohs(*((unsigned short *)msg)); + if (nchans != span->channels) { + spin_unlock_irqrestore(&dlock, flags); + newerr = ERR_NCHAN | nchans; + if (newerr != ztd->err) { + printk("Span %s: Expected %d channels, but receiving %d\n", span->name, span->channels, nchans); + } + ztd->err = newerr; + return; + } + msg++; + msg++; + + /* Okay now we've accepted the header, lets check our message + length... */ + + /* Start with header */ + xlen = 6; + /* Add samples of audio */ + xlen += nchans * ZT_CHUNKSIZE; + /* If RBS info is there, add that */ + if (sflags & ZTD_FLAG_SIGBITS_PRESENT) { + /* Account for sigbits -- one short per 4 channels*/ + xlen += ((nchans + 3) / 4) * 2; + } + + if (xlen != msglen) { + spin_unlock_irqrestore(&dlock, flags); + newerr = ERR_LEN | xlen; + if (newerr != ztd->err) { + printk("Span %s: Expected message size %d, but was %d instead\n", span->name, xlen, msglen); + } + ztd->err = newerr; + return; + } + + bits = 0; + + /* Record sigbits if present */ + if (sflags & ZTD_FLAG_SIGBITS_PRESENT) { + for (x=0;x> ((x % 4) << 2)) & 0xff; + + /* Update signalling if appropriate */ + if (sig != span->chans[x].rxsig) + zt_rbsbits(&span->chans[x], sig); + + } + } + + /* Record data for channels */ + for (x=0;xchans[x].readchunk, msg, ZT_CHUNKSIZE); + msg += ZT_CHUNKSIZE; + } + + master = ztd->master; + + rxcnt = ztd->rxcnt; + ztd->rxcnt = rxpos+1; + + spin_unlock_irqrestore(&dlock, flags); + + /* Check for Yellow alarm */ + newalarm = span->alarms & ~(ZT_ALARM_YELLOW | ZT_ALARM_RED); + if (sflags & ZTD_FLAG_YELLOW_ALARM) + newalarm |= ZT_ALARM_YELLOW; + + if (newalarm != span->alarms) { + span->alarms = newalarm; + zt_alarm_notify(span); + checkmaster(); + } + + /* Keep track of last received packet */ + ztd->rxjif = jiffies; + + /* note if we had a missing packet */ + if (rxpos != rxcnt) + printk("Span %s: Expected seq no %d, but received %d instead\n", span->name, rxcnt, rxpos); + + /* If this is our master span, then run everything */ + if (master) + ztdynamic_run(); + +} + +static void dynamic_destroy(struct zt_dynamic *z) +{ + /* Unregister span if appropriate */ + if (z->span.flags & ZT_FLAG_REGISTERED) + zt_unregister(&z->span); + + /* Destroy the pvt stuff if there */ + if (z->pvt) + z->driver->destroy(z->pvt); + + /* Free message buffer if appropriate */ + if (z->msgbuf) + kfree(z->msgbuf); + + /* Free channels */ + if (z->chans); + vfree(z->chans); + /* Free z */ + kfree(z); + + checkmaster(); +} + +static struct zt_dynamic *find_dynamic(ZT_DYNAMIC_SPAN *zds) +{ + struct zt_dynamic *z; + z = dspans; + while(z) { + if (!strcmp(z->dname, zds->driver) && + !strcmp(z->addr, zds->addr)) + break; + z = z->next; + } + return z; +} + +static struct zt_dynamic_driver *find_driver(char *name) +{ + struct zt_dynamic_driver *ztd; + ztd = drivers; + while(ztd) { + /* here's our driver */ + if (!strcmp(name, ztd->name)) + break; + ztd = ztd->next; + } + return ztd; +} + +static int destroy_dynamic(ZT_DYNAMIC_SPAN *zds) +{ + unsigned long flags; + struct zt_dynamic *z, *cur, *prev=NULL; + spin_lock_irqsave(&dlock, flags); + z = find_dynamic(zds); + if (!z) { + spin_unlock_irqrestore(&dlock, flags); + return -EINVAL; + } + /* Don't destroy span until it is in use */ + if (z->usecount) { + spin_unlock_irqrestore(&dlock, flags); + printk("Attempt to destroy dynamic span while it is in use\n"); + return -EBUSY; + } + /* Unlink it */ + cur = dspans; + while(cur) { + if (cur == z) { + if (prev) + prev->next = z->next; + else + dspans = z->next; + break; + } + prev = cur; + cur = cur->next; + } + spin_unlock_irqrestore(&dlock, flags); + + /* Destroy it */ + dynamic_destroy(z); + + return 0; +} + +static int ztd_rbsbits(struct zt_chan *chan, int bits) +{ + /* Don't have to do anything */ + return 0; +} + +static int ztd_open(struct zt_chan *chan) +{ + struct zt_dynamic *z; + z = chan->span->pvt; + if (z) { + if (z->dead) + return -ENODEV; + z->usecount++; + } +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#else + if(!try_module_get(THIS_MODULE)) + printk("TDMoX: Unable to increment module use count\n"); +#endif + return 0; +} + +static int ztd_chanconfig(struct zt_chan *chan, int sigtype) +{ + return 0; +} + +static int ztd_close(struct zt_chan *chan) +{ + struct zt_dynamic *z; + z = chan->span->pvt; + if (z) + z->usecount--; + if (z->dead && !z->usecount) + dynamic_destroy(z); +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#else + module_put(THIS_MODULE); +#endif + return 0; +} + +static int create_dynamic(ZT_DYNAMIC_SPAN *zds) +{ + struct zt_dynamic *z; + struct zt_dynamic_driver *ztd; + unsigned long flags; + int x; + int bufsize; + + if (zds->numchans < 1) { + printk("Can't be less than 1 channel (%d)!\n", zds->numchans); + return -EINVAL; + } + if (zds->numchans >= ZT_DYNAMIC_MAX_CHANS) { + printk("Can't create dynamic span with greater than %d channels. See ztdynamic.c and increase ZT_DYNAMIC_MAX_CHANS\n", zds->numchans); + return -EINVAL; + } + + spin_lock_irqsave(&dlock, flags); + z = find_dynamic(zds); + spin_unlock_irqrestore(&dlock, flags); + if (z) + return -EEXIST; + + /* XXX There is a silly race here. We check it doesn't exist, but + someone could create it between now and then and we'd end up + with two of them. We don't want to hold the spinlock + for *too* long though, especially not if there is a possibility + of kmalloc. XXX */ + + + /* Allocate memory */ + z = (struct zt_dynamic *)kmalloc(sizeof(struct zt_dynamic), GFP_KERNEL); + if (!z) + return -ENOMEM; + + /* Zero it out */ + memset(z, 0, sizeof(struct zt_dynamic)); + + /* Allocate other memories */ + z->chans = vmalloc(sizeof(struct zt_chan) * zds->numchans); + if (!z->chans) { + dynamic_destroy(z); + return -ENOMEM; + } + + /* Zero out channel stuff */ + memset(z->chans, 0, sizeof(struct zt_chan) * zds->numchans); + + /* Allocate message buffer with sample space and header space */ + bufsize = zds->numchans * ZT_CHUNKSIZE + zds->numchans / 4 + 48; + + z->msgbuf = kmalloc(bufsize, GFP_KERNEL); + + if (!z->msgbuf) { + dynamic_destroy(z); + return -ENOMEM; + } + + /* Zero out -- probably not needed but why not */ + memset(z->msgbuf, 0, bufsize); + + /* Setup parameters properly assuming we're going to be okay. */ + strncpy(z->dname, zds->driver, sizeof(z->dname) - 1); + strncpy(z->addr, zds->addr, sizeof(z->addr) - 1); + z->timing = zds->timing; + sprintf(z->span.name, "ZTD/%s/%s", zds->driver, zds->addr); + sprintf(z->span.desc, "Dynamic '%s' span at '%s'", zds->driver, zds->addr); + z->span.channels = zds->numchans; + z->span.pvt = z; + z->span.deflaw = ZT_LAW_MULAW; + z->span.flags |= ZT_FLAG_RBS; + z->span.chans = z->chans; + z->span.rbsbits = ztd_rbsbits; + z->span.open = ztd_open; + z->span.close = ztd_close; + z->span.chanconfig = ztd_chanconfig; + for (x=0;xnumchans;x++) { + sprintf(z->chans[x].name, "ZTD/%s/%s/%d", zds->driver, zds->addr, x+1); + z->chans[x].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | + ZT_SIG_FXSKS | ZT_SIG_FXSGS | ZT_SIG_FXOLS | + ZT_SIG_FXOKS | ZT_SIG_FXOGS | ZT_SIG_SF | + ZT_SIG_DACS_RBS | ZT_SIG_CAS; + z->chans[x].chanpos = x + 1; + z->chans[x].pvt = z; + } + + spin_lock_irqsave(&dlock, flags); + ztd = find_driver(zds->driver); + if (!ztd) { + /* Try loading the right module */ + char fn[80]; + spin_unlock_irqrestore(&dlock, flags); + sprintf(fn, "ztd-%s", zds->driver); + request_module(fn); + spin_lock_irqsave(&dlock, flags); + ztd = find_driver(zds->driver); + } + spin_unlock_irqrestore(&dlock, flags); + + + /* Another race -- should let the module get unloaded while we + have it here */ + if (!ztd) { + printk("No such driver '%s' for dynamic span\n", zds->driver); + dynamic_destroy(z); + return -EINVAL; + } + + /* Create the stuff */ + z->pvt = ztd->create(&z->span, z->addr); + if (!z->pvt) { + printk("Driver '%s' (%s) rejected address '%s'\n", ztd->name, ztd->desc, z->addr); + /* Creation failed */ + return -EINVAL; + } + + /* Remember the driver */ + z->driver = ztd; + + /* Whee! We're created. Now register the span */ + if (zt_register(&z->span, 0)) { + printk("Unable to register span '%s'\n", z->span.name); + dynamic_destroy(z); + return -EINVAL; + } + + /* Okay, created and registered. add it to the list */ + spin_lock_irqsave(&dlock, flags); + z->next = dspans; + dspans = z; + spin_unlock_irqrestore(&dlock, flags); + + checkmaster(); + + /* All done */ + return z->span.spanno; + +} + +#ifdef ENABLE_TASKLETS +static void ztd_tasklet(unsigned long data) +{ + taskletrun++; + if (taskletpending) { + taskletexec++; + __ztdynamic_run(); + } + taskletpending = 0; +} +#endif + +static int ztdynamic_ioctl(unsigned int cmd, unsigned long data) +{ + ZT_DYNAMIC_SPAN zds; + int res; + switch(cmd) { + case 0: + /* This is called just before rotation. If none of our + spans are pulling timing, then now is the time to process + them */ + if (!hasmaster) + ztdynamic_run(); + return 0; + case ZT_DYNAMIC_CREATE: + if (copy_from_user(&zds, (ZT_DYNAMIC_SPAN *)data, sizeof(zds))) + return -EFAULT; + if (debug) + printk("Dynamic Create\n"); + res = create_dynamic(&zds); + if (res < 0) + return res; + zds.spanno = res; + /* Let them know the new span number */ + if (copy_to_user((ZT_DYNAMIC_SPAN *)data, &zds, sizeof(zds))) + return -EFAULT; + return 0; + case ZT_DYNAMIC_DESTROY: + if (copy_from_user(&zds, (ZT_DYNAMIC_SPAN *)data, sizeof(zds))) + return -EFAULT; + if (debug) + printk("Dynamic Destroy\n"); + return destroy_dynamic(&zds); + } + + return -ENOTTY; +} + +int zt_dynamic_register(struct zt_dynamic_driver *dri) +{ + unsigned long flags; + int res = 0; + write_lock_irqsave(&drvlock, flags); + if (find_driver(dri->name)) + res = -1; + else { + dri->next = drivers; + drivers = dri; + } + write_unlock_irqrestore(&drvlock, flags); + return res; +} + +void zt_dynamic_unregister(struct zt_dynamic_driver *dri) +{ + struct zt_dynamic_driver *cur, *prev=NULL; + struct zt_dynamic *z, *zp, *zn; + unsigned long flags; + write_lock_irqsave(&drvlock, flags); + cur = drivers; + while(cur) { + if (cur == dri) { + if (prev) + prev->next = cur->next; + else + drivers = cur->next; + break; + } + prev = cur; + cur = cur->next; + } + write_unlock_irqrestore(&drvlock, flags); + spin_lock_irqsave(&dlock, flags); + z = dspans; + zp = NULL; + while(z) { + zn = z->next; + if (z->driver == dri) { + /* Unlink */ + if (zp) + zp->next = z->next; + else + dspans = z->next; + if (!z->usecount) + dynamic_destroy(z); + else + z->dead = 1; + } else { + zp = z; + } + z = zn; + } + spin_unlock_irqrestore(&dlock, flags); +} + +struct timer_list alarmcheck; + +static void check_for_red_alarm(unsigned long ignored) +{ + unsigned long flags; + int newalarm; + int alarmchanged = 0; + struct zt_dynamic *z; + spin_lock_irqsave(&dlock, flags); + z = dspans; + while(z) { + newalarm = z->span.alarms & ~ZT_ALARM_RED; + /* If nothing received for a second, consider that RED ALARM */ + if ((jiffies - z->rxjif) > 1 * HZ) { + newalarm |= ZT_ALARM_RED; + if (z->span.alarms != newalarm) { + z->span.alarms = newalarm; + zt_alarm_notify(&z->span); + alarmchanged++; + } + } + z = z->next; + } + spin_unlock_irqrestore(&dlock, flags); + if (alarmchanged) + checkmaster(); + + /* Do the next one */ + mod_timer(&alarmcheck, jiffies + 1 * HZ); + +} + +int ztdynamic_init(void) +{ + zt_set_dynamic_ioctl(ztdynamic_ioctl); + /* Start process to check for RED ALARM */ + init_timer(&alarmcheck); + alarmcheck.expires = 0; + alarmcheck.data = 0; + alarmcheck.function = check_for_red_alarm; + /* Check once per second */ + mod_timer(&alarmcheck, jiffies + 1 * HZ); +#ifdef ENABLE_TASKLETS + tasklet_init(&ztd_tlet, ztd_tasklet, 0); +#endif + printk("Zaptel Dynamic Span support LOADED\n"); + return 0; +} + +void ztdynamic_cleanup(void) +{ +#ifdef ENABLE_TASKLETS + if (taskletpending) { + tasklet_disable(&ztd_tlet); + tasklet_kill(&ztd_tlet); + } +#endif + zt_set_dynamic_ioctl(NULL); + del_timer(&alarmcheck); + printk("Zaptel Dynamic Span support unloaded\n"); +} + +#ifdef LINUX26 +module_param(debug, int, 0600); +#else +MODULE_PARM(debug, "i"); +#endif +MODULE_DESCRIPTION("Zaptel Dynamic Span Support"); +MODULE_AUTHOR("Mark Spencer "); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +module_init(ztdynamic_init); +module_exit(ztdynamic_cleanup); diff --git a/kernel/zttranscode.c b/kernel/zttranscode.c new file mode 100644 index 0000000..ca2cdd8 --- /dev/null +++ b/kernel/zttranscode.c @@ -0,0 +1,491 @@ +/* + * Transcoder Interface for Zaptel + * + * Written by Mark Spencer + * + * Copyright (C) 2006-2007, Digium, Inc. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_DEVFS_FS +#include +#endif +#ifdef STANDALONE_ZAPATA +#include "zaptel.h" +#else +#include +#endif +#ifdef LINUX26 +#include +#endif + +static int debug = 0; +static struct zt_transcoder *trans; +static spinlock_t translock = SPIN_LOCK_UNLOCKED; + +EXPORT_SYMBOL(zt_transcoder_register); +EXPORT_SYMBOL(zt_transcoder_unregister); +EXPORT_SYMBOL(zt_transcoder_alert); +EXPORT_SYMBOL(zt_transcoder_alloc); +EXPORT_SYMBOL(zt_transcoder_free); + +struct zt_transcoder *zt_transcoder_alloc(int numchans) +{ + struct zt_transcoder *ztc; + unsigned int x; + size_t size = sizeof(*ztc) + (sizeof(ztc->channels[0]) * numchans); + + if (!(ztc = kmalloc(size, GFP_KERNEL))) + return NULL; + + memset(ztc, 0, size); + strcpy(ztc->name, ""); + ztc->numchannels = numchans; + for (x=0;xnumchannels;x++) { + init_waitqueue_head(&ztc->channels[x].ready); + ztc->channels[x].parent = ztc; + ztc->channels[x].offset = x; + ztc->channels[x].chan_built = 0; + ztc->channels[x].built_fmts = 0; + } + + return ztc; +} + +static int schluffen(wait_queue_head_t *q) +{ + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue(q, &wait); + current->state = TASK_INTERRUPTIBLE; + + if (!signal_pending(current)) + schedule(); + + current->state = TASK_RUNNING; + remove_wait_queue(q, &wait); + + if (signal_pending(current)) + return -ERESTARTSYS; + + return 0; +} + +void zt_transcoder_free(struct zt_transcoder *ztc) +{ + kfree(ztc); +} + +/* Register a transcoder */ +int zt_transcoder_register(struct zt_transcoder *tc) +{ + struct zt_transcoder *cur; + int res = -EBUSY; + + spin_lock(&translock); + for (cur = trans; cur; cur = cur->next) { + if (cur == tc) { + spin_unlock(&translock); + return res; + } + } + + tc->next = trans; + trans = tc; + printk("Registered codec translator '%s' with %d transcoders (srcs=%08x, dsts=%08x)\n", + tc->name, tc->numchannels, tc->srcfmts, tc->dstfmts); + res = 0; + spin_unlock(&translock); + + return res; +} + +/* Unregister a transcoder */ +int zt_transcoder_unregister(struct zt_transcoder *tc) +{ + struct zt_transcoder *cur, *prev; + int res = -EINVAL; + + spin_lock(&translock); + for (cur = trans, prev = NULL; cur; prev = cur, cur = cur->next) { + if (cur == tc) + break; + } + + if (!cur) { + spin_unlock(&translock); + return res; + } + + if (prev) + prev->next = tc->next; + else + trans = tc->next; + tc->next = NULL; + printk("Unregistered codec translator '%s' with %d transcoders (srcs=%08x, dsts=%08x)\n", + tc->name, tc->numchannels, tc->srcfmts, tc->dstfmts); + res = 0; + spin_unlock(&translock); + + return res; +} + +/* Alert a transcoder */ +int zt_transcoder_alert(struct zt_transcoder_channel *ztc) +{ + if (debug) + printk("ZT Transcoder Alert!\n"); + if (ztc->tch) + ztc->tch->status &= ~ZT_TC_FLAG_BUSY; + wake_up_interruptible(&ztc->ready); + + return 0; +} + +static int zt_tc_open(struct inode *inode, struct file *file) +{ + struct zt_transcoder_channel *ztc; + struct zt_transcode_header *zth; + struct page *page; + + if (!(ztc = kmalloc(sizeof(*ztc), GFP_KERNEL))) + return -ENOMEM; + + if (!(zth = kmalloc(sizeof(*zth), GFP_KERNEL | GFP_DMA))) { + kfree(ztc); + return -ENOMEM; + } + + memset(ztc, 0, sizeof(*ztc)); + memset(zth, 0, sizeof(*zth)); + ztc->flags = ZT_TC_FLAG_TRANSIENT | ZT_TC_FLAG_BUSY; + ztc->tch = zth; + if (debug) + printk("Allocated Transcoder Channel, header is at %p!\n", zth); + zth->magic = ZT_TRANSCODE_MAGIC; + file->private_data = ztc; + for (page = virt_to_page(zth); + page < virt_to_page((unsigned long) zth + sizeof(*zth)); + page++) + SetPageReserved(page); + + return 0; +} + +static void ztc_release(struct zt_transcoder_channel *ztc) +{ + struct zt_transcode_header *zth = ztc->tch; + struct page *page; + + if (!ztc) + return; + + ztc->flags &= ~(ZT_TC_FLAG_BUSY); + + if(ztc->tch) { + for (page = virt_to_page(zth); + page < virt_to_page((unsigned long) zth + sizeof(*zth)); + page++) + ClearPageReserved(page); + kfree(ztc->tch); + } + + ztc->tch = NULL; + /* Actually reset the transcoder channel */ + if (ztc->flags & ZT_TC_FLAG_TRANSIENT) + kfree(ztc); + if (debug) + printk("Released Transcoder!\n"); +} + +static int zt_tc_release(struct inode *inode, struct file *file) +{ + ztc_release(file->private_data); + + return 0; +} + +static int do_reset(struct zt_transcoder_channel **ztc) +{ + struct zt_transcoder_channel *newztc = NULL, *origztc = NULL; + struct zt_transcode_header *zth = (*ztc)->tch; + struct zt_transcoder *tc; + unsigned int x; + unsigned int match = 0; + + if (((*ztc)->srcfmt != zth->srcfmt) || + ((*ztc)->dstfmt != zth->dstfmt)) { + /* Find new transcoder */ + spin_lock(&translock); + for (tc = trans; tc && !newztc; tc = tc->next) { + if (!(tc->srcfmts & zth->srcfmt)) + continue; + + if (!(tc->dstfmts & zth->dstfmt)) + continue; + + match = 1; + for (x = 0; x < tc->numchannels; x++) { + if (tc->channels[x].flags & ZT_TC_FLAG_BUSY) + continue; + if ((tc->channels[x].chan_built) && ((zth->srcfmt | zth->dstfmt) != tc->channels[x].built_fmts)) + continue; + + newztc = &tc->channels[x]; + newztc->flags = ZT_TC_FLAG_BUSY; + break; + } + } + spin_unlock(&translock); + + if (!newztc) + return match ? -EBUSY : -ENOSYS; + + /* Move transcoder header over */ + origztc = (*ztc); + (*ztc) = newztc; + (*ztc)->tch = origztc->tch; + origztc->tch = NULL; + (*ztc)->flags |= (origztc->flags & ~(ZT_TC_FLAG_TRANSIENT)); + ztc_release(origztc); + } + + /* Actually reset the transcoder channel */ + if ((*ztc)->parent && ((*ztc)->parent->operation)) + return (*ztc)->parent->operation((*ztc), ZT_TCOP_ALLOCATE); + + return -EINVAL; +} + +static int wait_busy(struct zt_transcoder_channel *ztc) +{ + int ret; + + for (;;) { + if (!(ztc->tch->status & ZT_TC_FLAG_BUSY)) + return 0; + if ((ret = schluffen(&ztc->ready))) + return ret; + } +} + +static int zt_tc_getinfo(unsigned long data) +{ + struct zt_transcode_info info; + unsigned int x; + struct zt_transcoder *tc; + + if (copy_from_user(&info, (struct zt_transcode_info *) data, sizeof(info))) + return -EFAULT; + + spin_lock(&translock); + for (tc = trans, x = info.tcnum; tc && x; tc = tc->next, x--); + spin_unlock(&translock); + + if (!tc) + return -ENOSYS; + + strncpy(info.name, tc->name, sizeof(info.name) - 1); + info.numchannels = tc->numchannels; + info.srcfmts = tc->srcfmts; + info.dstfmts = tc->dstfmts; + + return copy_to_user((struct zt_transcode_info *) data, &info, sizeof(info)) ? -EFAULT : 0; +} + +static int zt_tc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data) +{ + int op; + int ret; + struct zt_transcoder_channel *ztc = file->private_data; + + if (cmd != ZT_TRANSCODE_OP) + return -ENOSYS; + + if (get_user(op, (int *) data)) + return -EFAULT; + + if (debug) + printk("ZT Transcode ioctl op = %d!\n", op); + + switch(op) { + case ZT_TCOP_GETINFO: + ret = zt_tc_getinfo(data); + break; + case ZT_TCOP_ALLOCATE: + /* Reset transcoder, possibly changing who we point to */ + ret = do_reset(&ztc); + file->private_data = ztc; + break; + case ZT_TCOP_RELEASE: + ret = ztc->parent->operation(ztc, ZT_TCOP_RELEASE); + break; + case ZT_TCOP_TEST: + ret = ztc->parent->operation(ztc, ZT_TCOP_TEST); + break; + case ZT_TCOP_TRANSCODE: + if (!ztc->parent->operation) + return -EINVAL; + + ztc->tch->status |= ZT_TC_FLAG_BUSY; + if (!(ret = ztc->parent->operation(ztc, ZT_TCOP_TRANSCODE))) { + /* Wait for busy to go away if we're not non-blocking */ + if (!(file->f_flags & O_NONBLOCK)) { + if (!(ret = wait_busy(ztc))) + ret = ztc->errorstatus; + } + } else + ztc->tch->status &= ~ZT_TC_FLAG_BUSY; + break; + default: + ret = -ENOSYS; + } + + return ret; +} + +static int zt_tc_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct zt_transcoder_channel *ztc = file->private_data; + unsigned long physical; + int res; + + if (!ztc) + return -EINVAL; + + /* Do not allow an offset */ + if (vma->vm_pgoff) { + if (debug) + printk("zttranscode: Attempted to mmap with offset!\n"); + return -EINVAL; + } + + if ((vma->vm_end - vma->vm_start) != sizeof(struct zt_transcode_header)) { + if (debug) + printk("zttranscode: Attempted to mmap with size %d != %zd!\n", (int) (vma->vm_end - vma->vm_start), sizeof(struct zt_transcode_header)); + return -EINVAL; + } + + physical = (unsigned long) virt_to_phys(ztc->tch); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) + res = remap_pfn_range(vma, vma->vm_start, physical >> PAGE_SHIFT, sizeof(struct zt_transcode_header), PAGE_SHARED); +#else + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + res = remap_page_range(vma->vm_start, physical, sizeof(struct zt_transcode_header), PAGE_SHARED); + #else + res = remap_page_range(vma, vma->vm_start, physical, sizeof(struct zt_transcode_header), PAGE_SHARED); + #endif +#endif + if (res) { + if (debug) + printk("zttranscode: remap failed!\n"); + return -EAGAIN; + } + + if (debug) + printk("zttranscode: successfully mapped transcoder!\n"); + + return 0; +} + +static unsigned int zt_tc_poll(struct file *file, struct poll_table_struct *wait_table) +{ + struct zt_transcoder_channel *ztc = file->private_data; + + if (!ztc) + return -EINVAL; + + poll_wait(file, &ztc->ready, wait_table); + return ztc->tch->status & ZT_TC_FLAG_BUSY ? 0 : POLLPRI; +} + +static struct file_operations __zt_transcode_fops = { + owner: THIS_MODULE, + llseek: NULL, + open: zt_tc_open, + release: zt_tc_release, + ioctl: zt_tc_ioctl, + read: NULL, + write: NULL, + poll: zt_tc_poll, + mmap: zt_tc_mmap, + flush: NULL, + fsync: NULL, + fasync: NULL, +}; + +static struct zt_chardev transcode_chardev = { + .name = "transcode", + .minor = 250, +}; + +int zttranscode_init(void) +{ + int res; + + if (zt_transcode_fops) { + printk("Whoa, zt_transcode_fops already set?!\n"); + return -EBUSY; + } + + zt_transcode_fops = &__zt_transcode_fops; + + if ((res = zt_register_chardev(&transcode_chardev))) + return res; + + printk("Zaptel Transcoder support loaded\n"); + + return 0; +} + +void zttranscode_cleanup(void) +{ + zt_unregister_chardev(&transcode_chardev); + + zt_transcode_fops = NULL; + + printk("Zaptel Transcoder support unloaded\n"); +} + +#ifdef LINUX26 +module_param(debug, int, S_IRUGO | S_IWUSR); +#else +MODULE_PARM(debug, "i"); +#endif +MODULE_DESCRIPTION("Zaptel Transcoder Support"); +MODULE_AUTHOR("Mark Spencer "); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + +module_init(zttranscode_init); +module_exit(zttranscode_cleanup); diff --git a/makefw.c b/makefw.c deleted file mode 100644 index 6a5b0d9..0000000 --- a/makefw.c +++ /dev/null @@ -1,88 +0,0 @@ -/* Xilinx firmware convertor program. - * - * - * Written by Jim Dixon . - * - * Copyright (C) 2001 Jim Dixon / Zapata Telephony. - * Copyright (C) 2001 Linux Support Services, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under thet erms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Primary Author: Mark Spencer - * - */ - -#include -#include -#include - -#define SWATH 12 - -int main(int argc, char *argv[]) -{ -FILE *fp; -int i,j,nbytes; -unsigned char c; -char buf[300]; - - if (argc < 3) - { - puts("Usage... makefw filename.rbt array_name"); - exit(1); - } - - fp = fopen(argv[1],"r"); - if (!fp) - { - perror("bit file open"); - exit(1); - } - nbytes = 0; - printf("static unsigned char %s[] = {\n",argv[2]); - i = 0; - while(fgets(buf,sizeof(buf) - 1,fp)) - { - if (!buf[0]) continue; - if (buf[strlen(buf) - 1] < ' ') buf[strlen(buf) - 1] = 0; - if (!buf[0]) continue; - if (buf[strlen(buf) - 1] < ' ') buf[strlen(buf) - 1] = 0; - if (!buf[0]) continue; - if (strlen(buf) < 32) continue; - if ((buf[0] != '0') && (buf[0] != '1')) continue; - c = 0; - for(j = 0; buf[j]; j++) - { - if (buf[j] > '0') c |= 1 << (j & 7); - if ((j & 7) == 7) - { - nbytes++; - if (i) printf(","); - printf("0x%02x",c); - if (i++ == SWATH) { - printf(",\n"); - i = 0; - } - c = 0; - } - } - } - printf("\n};\n\n"); - fprintf(stderr,"Loaded %d bytes from file\n",nbytes); - fclose(fp); - exit(0); -} - diff --git a/mg2ec.h b/mg2ec.h deleted file mode 100644 index 2dc3597..0000000 --- a/mg2ec.h +++ /dev/null @@ -1,725 +0,0 @@ -/* - * ECHO_CAN_MG2 - * - * by Michael Gernoth - * - * Based upon kb1ec.h and mec2.h - * - * Copyright (C) 2002, Digium, Inc. - * - * This program is free software and may be used and - * distributed according to the terms of the GNU - * General Public License, incorporated herein by - * reference. - * - * Additional background on the techniques used in this code can be found in: - * - * Messerschmitt, David; Hedberg, David; Cole, Christopher; Haoui, Amine; - * Winship, Peter; "Digital Voice Echo Canceller with a TMS32020," - * in Digital Signal Processing Applications with the TMS320 Family, - * pp. 415-437, Texas Instruments, Inc., 1986. - * - * A pdf of which is available by searching on the document title at http://www.ti.com/ - * - */ - -#ifndef _MG2_ECHO_H -#define _MG2_ECHO_H - -#include -#include -#include - -#define MALLOC(a) kmalloc((a), GFP_KERNEL) -#define FREE(a) kfree(a) - -#define ABS(a) abs(a!=-32768?a:-32767) - -#define RESTORE_COEFFS {\ - int x;\ - memcpy(ec->a_i, ec->c_i, ec->N_d*sizeof(int));\ - for (x=0;xN_d;x++) {\ - ec->a_s[x] = ec->a_i[x] >> 16;\ - }\ - ec->backup = BACKUP;\ - } - -/* Uncomment to provide summary statistics for overall echo can performance every 4000 samples */ -/* #define MEC2_STATS 4000 */ - -/* Uncomment to generate per-sample statistics - this will severely degrade system performance and audio quality */ -/* #define MEC2_STATS_DETAILED */ - -/* Uncomment to generate per-call DC bias offset messages */ -/* #define MEC2_DCBIAS_MESSAGE */ - -/* Get optimized routines for math */ -#include "arith.h" - -/* Bring in definitions for the various constants and thresholds */ -#include "mg2ec_const.h" - -#define DC_NORMALIZE - -#ifndef NULL -#define NULL 0 -#endif -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE (!FALSE) -#endif - -/* Generic circular buffer definition */ -typedef struct { - /* Pointer to the relative 'start' of the buffer */ - int idx_d; - /* The absolute size of the buffer */ - int size_d; - /* The actual sample - twice as large as we need, however we do store values at idx_d and idx_d+size_d */ - short *buf_d; -} echo_can_cb_s; - -/* Echo canceller definition */ -struct echo_can_state { - /* an arbitrary ID for this echo can - this really should be settable from the calling channel... */ - int id; - - /* absolute time - aka. sample number index - essentially the number of samples since this can was init'ed */ - int i_d; - - /* Pre-computed constants */ - /* ---------------------- */ - /* Number of filter coefficents */ - int N_d; - /* Rate of adaptation of filter */ - int beta2_i; - - /* Accumulators for power computations */ - /* ----------------------------------- */ - /* reference signal power estimate - aka. Average absolute value of y(k) */ - int Ly_i; - /* ... */ - int Lu_i; - - /* Accumulators for signal detectors */ - /* --------------------------------- */ - /* Power estimate of the recent past of the near-end hybrid signal - aka. Short-time average of: 2 x |s(i)| */ - int s_tilde_i; - /* Power estimate of the recent past of the far-end receive signal - aka. Short-time average of: |y(i)| */ - int y_tilde_i; - - /* Near end speech detection counter - stores Hangover counter time remaining, in samples */ - int HCNTR_d; - - /* Circular buffers and coefficients */ - /* --------------------------------- */ - /* ... */ - int *a_i; - /* ... */ - short *a_s; - /* Backups */ - int *b_i; - int *c_i; - /* Reference samples of far-end receive signal */ - echo_can_cb_s y_s; - /* Reference samples of near-end signal */ - echo_can_cb_s s_s; - /* Reference samples of near-end signal minus echo estimate */ - echo_can_cb_s u_s; - /* Reference samples of far-end receive signal used to calculate short-time average */ - echo_can_cb_s y_tilde_s; - - /* Peak far-end receive signal */ - /* --------------------------- */ - /* Highest y_tilde value in the sample buffer */ - short max_y_tilde; - /* Index of the sample containing the max_y_tilde value */ - int max_y_tilde_pos; - -#ifdef MEC2_STATS - /* Storage for performance statistics */ - int cntr_nearend_speech_frames; - int cntr_residualcorrected_frames; - int cntr_residualcorrected_framesskipped; - int cntr_coeff_updates; - int cntr_coeff_missedupdates; - - int avg_Lu_i_toolow; - int avg_Lu_i_ok; -#endif - unsigned int aggressive:1; - short lastsig; - int lastcount; - int backup; -#ifdef DC_NORMALIZE - int dc_estimate; -#endif - -}; - -static void echo_can_init(void) -{ - printk("Zaptel Echo Canceller: MG2\n"); -} - -static void echo_can_identify(char *buf, size_t len) -{ - strncpy(buf, "MG2", len); -} - -static void echo_can_shutdown(void) -{ -} - -static inline void init_cb_s(echo_can_cb_s *cb, int len, void *where) -{ - cb->buf_d = (short *)where; - cb->idx_d = 0; - cb->size_d = len; -} - -static inline void add_cc_s(echo_can_cb_s *cb, short newval) -{ - /* Can't use modulus because N+M isn't a power of two (generally) */ - cb->idx_d--; - if (cb->idx_d < (int)0) - /* Whoops - the pointer to the 'start' wrapped around so reset it to the top of the buffer */ - cb->idx_d += cb->size_d; - - /* Load two copies into memory */ - cb->buf_d[cb->idx_d] = newval; - cb->buf_d[cb->idx_d + cb->size_d] = newval; -} - -static inline short get_cc_s(echo_can_cb_s *cb, int pos) -{ - /* Load two copies into memory */ - return cb->buf_d[cb->idx_d + pos]; -} - -static inline void init_cc(struct echo_can_state *ec, int N, int maxy, int maxu) -{ - - void *ptr = ec; - unsigned long tmp; - /* Double-word align past end of state */ - ptr += sizeof(struct echo_can_state); - tmp = (unsigned long)ptr; - tmp += 3; - tmp &= ~3L; - ptr = (void *)tmp; - - /* Reset parameters */ - ec->N_d = N; - ec->beta2_i = DEFAULT_BETA1_I; - - /* Allocate coefficient memory */ - ec->a_i = ptr; - ptr += (sizeof(int) * ec->N_d); - ec->a_s = ptr; - ptr += (sizeof(short) * ec->N_d); - - /* Allocate backup memory */ - ec->b_i = ptr; - ptr += (sizeof(int) * ec->N_d); - ec->c_i = ptr; - ptr += (sizeof(int) * ec->N_d); - - /* Reset Y circular buffer (short version) */ - init_cb_s(&ec->y_s, maxy, ptr); - ptr += (sizeof(short) * (maxy) * 2); - - /* Reset Sigma circular buffer (short version for FIR filter) */ - init_cb_s(&ec->s_s, (1 << DEFAULT_ALPHA_ST_I), ptr); - ptr += (sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) * 2); - - init_cb_s(&ec->u_s, maxu, ptr); - ptr += (sizeof(short) * maxu * 2); - - /* Allocate a buffer for the reference signal power computation */ - init_cb_s(&ec->y_tilde_s, ec->N_d, ptr); - - /* Reset the absolute time index */ - ec->i_d = (int)0; - - /* Reset the power computations (for y and u) */ - ec->Ly_i = DEFAULT_CUTOFF_I; - ec->Lu_i = DEFAULT_CUTOFF_I; - -#ifdef MEC2_STATS - /* set the identity */ - ec->id = (int)&ptr; - - /* Reset performance stats */ - ec->cntr_nearend_speech_frames = (int)0; - ec->cntr_residualcorrected_frames = (int)0; - ec->cntr_residualcorrected_framesskipped = (int)0; - ec->cntr_coeff_updates = (int)0; - ec->cntr_coeff_missedupdates = (int)0; - - ec->avg_Lu_i_toolow = (int)0; - ec->avg_Lu_i_ok = (int)0; -#endif - - /* Reset the near-end speech detector */ - ec->s_tilde_i = (int)0; - ec->y_tilde_i = (int)0; - ec->HCNTR_d = (int)0; - -} - -static inline void echo_can_free(struct echo_can_state *ec) -{ -#if defined(DC_NORMALIZE) && defined(MEC2_DCBIAS_MESSAGE) - printk("EC: DC bias calculated: %d V\n", ec->dc_estimate >> 15); -#endif - FREE(ec); -} - -#ifdef DC_NORMALIZE -short inline dc_removal(int *dc_estimate, short samp) -{ - *dc_estimate += ((((int)samp << 15) - *dc_estimate) >> 9); - return samp - (*dc_estimate >> 15); -} -#endif - -static inline short echo_can_update(struct echo_can_state *ec, short iref, short isig) -{ - - /* Declare local variables that are used more than once */ - /* ... */ - int k; - /* ... */ - int rs; - /* ... */ - short u; - /* ... */ - int Py_i; - /* ... */ - int two_beta_i; - -#ifdef DC_NORMALIZE - isig = dc_removal(&ec->dc_estimate, isig); -#endif - - /* flow A on pg. 428 */ - /* eq. (16): high-pass filter the input to generate the next value; - * push the current value into the circular buffer - * - * sdc_im1_d = sdc_d; - * sdc_d = sig; - * s_i_d = sdc_d; - * s_d = s_i_d; - * s_i_d = (float)(1.0 - gamma_d) * s_i_d - * + (float)(0.5 * (1.0 - gamma_d)) * (sdc_d - sdc_im1_d); - */ - - /* Update the Far-end receive signal circular buffers and accumulators */ - /* ------------------------------------------------------------------- */ - /* Delete the oldest sample from the power estimate accumulator */ - ec->y_tilde_i -= abs(get_cc_s(&ec->y_s, (1 << DEFAULT_ALPHA_YT_I) - 1 )) >> DEFAULT_ALPHA_YT_I; - /* Add the new sample to the power estimate accumulator */ - ec->y_tilde_i += abs(iref) >> DEFAULT_ALPHA_ST_I; - /* Push a copy of the new sample into its circular buffer */ - add_cc_s(&ec->y_s, iref); - - - /* eq. (2): compute r in fixed-point */ - rs = CONVOLVE2(ec->a_s, - ec->y_s.buf_d + ec->y_s.idx_d, - ec->N_d); - rs >>= 15; - - if (ec->lastsig == isig) { - ec->lastcount++; - } else { - ec->lastcount = 0; - ec->lastsig = isig; - } - - if (isig == 0) { - u = 0; - } else if (ec->lastcount > 255) { - /* We have seen the same input-signal more than 255 times, - * we should pass it through uncancelled, as we are likely on hold */ - u = isig; - } else { - if (rs < -32768) { - rs = -32768; - ec->HCNTR_d = DEFAULT_HANGT; - RESTORE_COEFFS; - } else if (rs > 32767) { - rs = 32767; - ec->HCNTR_d = DEFAULT_HANGT; - RESTORE_COEFFS; - } - - if (ABS(ABS(rs)-ABS(isig)) > MAX_SIGN_ERROR) - { - rs = 0; - RESTORE_COEFFS; - } - - /* eq. (3): compute the output value (see figure 3) and the error - * note: the error is the same as the output signal when near-end - * speech is not present - */ - u = isig - rs; - - if (u / isig < 0) - u = isig - (rs >> 1); - } - - /* Push a copy of the output value sample into its circular buffer */ - add_cc_s(&ec->u_s, u); - - if (!ec->backup) { - /* Backup coefficients periodically */ - ec->backup = BACKUP; - memcpy(ec->c_i,ec->b_i,ec->N_d*sizeof(int)); - memcpy(ec->b_i,ec->a_i,ec->N_d*sizeof(int)); - } else - ec->backup--; - - - /* Update the Near-end hybrid signal circular buffers and accumulators */ - /* ------------------------------------------------------------------- */ - /* Delete the oldest sample from the power estimate accumulator */ - ec->s_tilde_i -= abs(get_cc_s(&ec->s_s, (1 << DEFAULT_ALPHA_ST_I) - 1 )); - /* Add the new sample to the power estimate accumulator */ - ec->s_tilde_i += abs(isig); - /* Push a copy of the new sample into it's circular buffer */ - add_cc_s(&ec->s_s, isig); - - - /* Push a copy of the current short-time average of the far-end receive signal into it's circular buffer */ - add_cc_s(&ec->y_tilde_s, ec->y_tilde_i); - - /* flow B on pg. 428 */ - - /* If the hangover timer isn't running then compute the new convergence factor, otherwise set Py_i to 32768 */ - if (!ec->HCNTR_d) { - Py_i = (ec->Ly_i >> DEFAULT_SIGMA_LY_I) * (ec->Ly_i >> DEFAULT_SIGMA_LY_I); - Py_i >>= 15; - } else { - Py_i = (1 << 15); - } - -#if 0 - /* Vary rate of adaptation depending on position in the file - * Do not do this for the first (DEFAULT_UPDATE_TIME) secs after speech - * has begun of the file to allow the echo cancellor to estimate the - * channel accurately - * Still needs conversion! - */ - - if (ec->start_speech_d != 0 ){ - if ( ec->i_d > (DEFAULT_T0 + ec->start_speech_d)*(SAMPLE_FREQ) ){ - ec->beta2_d = max_cc_float(MIN_BETA, DEFAULT_BETA1 * exp((-1/DEFAULT_TAU)*((ec->i_d/(float)SAMPLE_FREQ) - DEFAULT_T0 - ec->start_speech_d))); - } - } else { - ec->beta2_d = DEFAULT_BETA1; - } -#endif - - /* Fixed point, inverted */ - ec->beta2_i = DEFAULT_BETA1_I; - - /* Fixed point version, inverted */ - two_beta_i = (ec->beta2_i * Py_i) >> 15; - if (!two_beta_i) - two_beta_i++; - - /* Update the Suppressed signal power estimate accumulator */ - /* ------------------------------------------------------- */ - /* Delete the oldest sample from the power estimate accumulator */ - ec->Lu_i -= abs(get_cc_s(&ec->u_s, (1 << DEFAULT_SIGMA_LU_I) - 1 )) ; - /* Add the new sample to the power estimate accumulator */ - ec->Lu_i += abs(u); - - /* Update the Far-end reference signal power estimate accumulator */ - /* -------------------------------------------------------------- */ - /* eq. (10): update power estimate of the reference */ - /* Delete the oldest sample from the power estimate accumulator */ - ec->Ly_i -= abs(get_cc_s(&ec->y_s, (1 << DEFAULT_SIGMA_LY_I) - 1)) ; - /* Add the new sample to the power estimate accumulator */ - ec->Ly_i += abs(iref); - - if (ec->Ly_i < DEFAULT_CUTOFF_I) - ec->Ly_i = DEFAULT_CUTOFF_I; - - - /* Update the Peak far-end receive signal detected */ - /* ----------------------------------------------- */ - if (ec->y_tilde_i > ec->max_y_tilde) { - /* New highest y_tilde with full life */ - ec->max_y_tilde = ec->y_tilde_i; - ec->max_y_tilde_pos = ec->N_d - 1; - } else if (--ec->max_y_tilde_pos < 0) { - /* Time to find new max y tilde... */ - ec->max_y_tilde = MAX16(ec->y_tilde_s.buf_d + ec->y_tilde_s.idx_d, ec->N_d, &ec->max_y_tilde_pos); - } - - /* Determine if near end speech was detected in this sample */ - /* -------------------------------------------------------- */ - if (((ec->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)) > ec->max_y_tilde) - && (ec->max_y_tilde > 0)) { - /* Then start the Hangover counter */ - ec->HCNTR_d = DEFAULT_HANGT; - RESTORE_COEFFS; -#ifdef MEC2_STATS_DETAILED - printk(KERN_INFO "Reset near end speech timer with: s_tilde_i %d, stmnt %d, max_y_tilde %d\n", ec->s_tilde_i, (ec->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)), ec->max_y_tilde); -#endif -#ifdef MEC2_STATS - ++ec->cntr_nearend_speech_frames; -#endif - } else if (ec->HCNTR_d > (int)0) { - /* otherwise, if it's still non-zero, decrement the Hangover counter by one sample */ -#ifdef MEC2_STATS - ++ec->cntr_nearend_speech_frames; -#endif - ec->HCNTR_d--; - } - - /* Update coefficients if no near-end speech in this sample (ie. HCNTR_d = 0) - * and we have enough signal to bother trying to update. - * -------------------------------------------------------------------------- - */ - if (!ec->HCNTR_d && /* no near-end speech present */ - !(ec->i_d % DEFAULT_M)) { /* we only update on every DEFAULM_M'th sample from the stream */ - if (ec->Lu_i > MIN_UPDATE_THRESH_I) { /* there is sufficient energy above the noise floor to contain meaningful data */ - /* so loop over all the filter coefficients */ -#ifdef USED_COEFFS - int max_coeffs[USED_COEFFS]; - int *pos; - - if (ec->N_d > USED_COEFFS) - memset(max_coeffs, 0, USED_COEFFS*sizeof(int)); -#endif -#ifdef MEC2_STATS_DETAILED - printk(KERN_INFO "updating coefficients with: ec->Lu_i %9d\n", ec->Lu_i); -#endif -#ifdef MEC2_STATS - ec->avg_Lu_i_ok = ec->avg_Lu_i_ok + ec->Lu_i; - ++ec->cntr_coeff_updates; -#endif - for (k=0; k < ec->N_d; k++) { - /* eq. (7): compute an expectation over M_d samples */ - int grad2; - grad2 = CONVOLVE2(ec->u_s.buf_d + ec->u_s.idx_d, - ec->y_s.buf_d + ec->y_s.idx_d + k, - DEFAULT_M); - /* eq. (7): update the coefficient */ - ec->a_i[k] += grad2 / two_beta_i; - ec->a_s[k] = ec->a_i[k] >> 16; - -#ifdef USED_COEFFS - if (ec->N_d > USED_COEFFS) { - if (abs(ec->a_i[k]) > max_coeffs[USED_COEFFS-1]) { - /* More or less insertion-sort... */ - pos = max_coeffs; - while (*pos > abs(ec->a_i[k])) - pos++; - - if (*pos > max_coeffs[USED_COEFFS-1]) - memmove(pos+1, pos, (USED_COEFFS-(pos-max_coeffs)-1)*sizeof(int)); - - *pos = abs(ec->a_i[k]); - } - } -#endif - } - -#ifdef USED_COEFFS - /* Filter out irrelevant coefficients */ - if (ec->N_d > USED_COEFFS) - for (k=0; k < ec->N_d; k++) - if (abs(ec->a_i[k]) < max_coeffs[USED_COEFFS-1]) - ec->a_i[k] = ec->a_s[k] = 0; -#endif - } else { -#ifdef MEC2_STATS_DETAILED - printk(KERN_INFO "insufficient signal to update coefficients ec->Lu_i %5d < %5d\n", ec->Lu_i, MIN_UPDATE_THRESH_I); -#endif -#ifdef MEC2_STATS - ec->avg_Lu_i_toolow = ec->avg_Lu_i_toolow + ec->Lu_i; - ++ec->cntr_coeff_missedupdates; -#endif - } - } - - /* paragraph below eq. (15): if no near-end speech in the sample and - * the reference signal power estimate > cutoff threshold - * then perform residual error suppression - */ -#ifdef MEC2_STATS_DETAILED - if (ec->HCNTR_d == 0) - printk(KERN_INFO "possibily correcting frame with ec->Ly_i %9d ec->Lu_i %9d and expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1))); -#endif - -#ifndef NO_ECHO_SUPPRESSOR - if (ec->aggressive) { - if ((ec->HCNTR_d < AGGRESSIVE_HCNTR) && (ec->Ly_i > (ec->Lu_i << 1))) { - for (k=0; k < 2; k++) { - u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I)) + 1); - } -#ifdef MEC2_STATS_DETAILED - printk(KERN_INFO "aggresively correcting frame with ec->Ly_i %9d ec->Lu_i %9d expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1))); -#endif -#ifdef MEC2_STATS - ++ec->cntr_residualcorrected_frames; -#endif - } - } else { - if (ec->HCNTR_d == 0) { - if ((ec->Ly_i/(ec->Lu_i + 1)) > DEFAULT_SUPPR_I) { - for (k=0; k < 1; k++) { - u = u * (ec->Lu_i >> DEFAULT_SIGMA_LU_I) / ((ec->Ly_i >> (DEFAULT_SIGMA_LY_I + 2)) + 1); - } -#ifdef MEC2_STATS_DETAILED - printk(KERN_INFO "correcting frame with ec->Ly_i %9d ec->Lu_i %9d expression %d\n", ec->Ly_i, ec->Lu_i, (ec->Ly_i/(ec->Lu_i + 1))); -#endif -#ifdef MEC2_STATS - ++ec->cntr_residualcorrected_frames; -#endif - } -#ifdef MEC2_STATS - else { - ++ec->cntr_residualcorrected_framesskipped; - } -#endif - } - } -#endif - -#if 0 - /* This will generate a non-linear supression factor, once converted */ - if ((ec->HCNTR_d == 0) && - ((ec->Lu_d/ec->Ly_d) < DEFAULT_SUPPR) && - (ec->Lu_d/ec->Ly_d > EC_MIN_DB_VALUE)) { - suppr_factor = (10 / (float)(SUPPR_FLOOR - SUPPR_CEIL)) * log(ec->Lu_d/ec->Ly_d) - - SUPPR_CEIL / (float)(SUPPR_FLOOR - SUPPR_CEIL); - u_suppr = pow(10.0, (suppr_factor) * RES_SUPR_FACTOR / 10.0) * u_suppr; - } -#endif - -#ifdef MEC2_STATS - /* Periodically dump performance stats */ - if ((ec->i_d % MEC2_STATS) == 0) { - /* make sure to avoid div0's! */ - if (ec->cntr_coeff_missedupdates > 0) - ec->avg_Lu_i_toolow = (int)(ec->avg_Lu_i_toolow / ec->cntr_coeff_missedupdates); - else - ec->avg_Lu_i_toolow = -1; - - if (ec->cntr_coeff_updates > 0) - ec->avg_Lu_i_ok = (ec->avg_Lu_i_ok / ec->cntr_coeff_updates); - else - ec->avg_Lu_i_ok = -1; - - printk(KERN_INFO "%d: Near end speech: %5d Residuals corrected/skipped: %5d/%5d Coefficients updated ok/low sig: %3d/%3d Lu_i avg ok/low sig %6d/%5d\n", - ec->id, - ec->cntr_nearend_speech_frames, - ec->cntr_residualcorrected_frames, ec->cntr_residualcorrected_framesskipped, - ec->cntr_coeff_updates, ec->cntr_coeff_missedupdates, - ec->avg_Lu_i_ok, ec->avg_Lu_i_toolow); - - ec->cntr_nearend_speech_frames = 0; - ec->cntr_residualcorrected_frames = 0; - ec->cntr_residualcorrected_framesskipped = 0; - ec->cntr_coeff_updates = 0; - ec->cntr_coeff_missedupdates = 0; - ec->avg_Lu_i_ok = 0; - ec->avg_Lu_i_toolow = 0; - } -#endif - - /* Increment the sample index and return the corrected sample */ - ec->i_d++; - return u; -} - -static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p, - struct echo_can_state **ec) -{ - int maxy; - int maxu; - size_t size; - unsigned int x; - char *c; - - maxy = ecp->tap_length + DEFAULT_M; - maxu = DEFAULT_M; - if (maxy < (1 << DEFAULT_ALPHA_YT_I)) - maxy = (1 << DEFAULT_ALPHA_YT_I); - if (maxy < (1 << DEFAULT_SIGMA_LY_I)) - maxy = (1 << DEFAULT_SIGMA_LY_I); - if (maxu < (1 << DEFAULT_SIGMA_LU_I)) - maxu = (1 << DEFAULT_SIGMA_LU_I); - size = sizeof(**ec) + - 4 + /* align */ - sizeof(int) * ecp->tap_length + /* a_i */ - sizeof(short) * ecp->tap_length + /* a_s */ - sizeof(int) * ecp->tap_length + /* b_i */ - sizeof(int) * ecp->tap_length + /* c_i */ - 2 * sizeof(short) * (maxy) + /* y_s */ - 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */ - 2 * sizeof(short) * (maxu) + /* u_s */ - 2 * sizeof(short) * ecp->tap_length; /* y_tilde_s */ - - if (!(*ec = MALLOC(size))) - return -ENOMEM; - - memset(*ec, 0, size); - -#ifdef AGGRESSIVE_SUPPRESSOR - (*ec)->aggressive = 1; -#endif - - for (x = 0; x < ecp->param_count; x++) { - for (c = p[x].name; *c; c++) - *c = tolower(*c); - if (!strcmp(p[x].name, "aggressive")) { - (*ec)->aggressive = p[x].value ? 1 : 0; - } else { - printk(KERN_WARNING "Unknown parameter supplied to MG2 echo canceler: '%s'\n", p[x].name); - kfree(*ec); - - return -EINVAL; - } - } - - init_cc(*ec, ecp->tap_length, maxy, maxu); - - return 0; -} - -static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) -{ - /* Set the hangover counter to the length of the can to - * avoid adjustments occuring immediately after initial forced training - */ - ec->HCNTR_d = ec->N_d << 1; - - if (pos >= ec->N_d) { - memcpy(ec->b_i,ec->a_i,ec->N_d*sizeof(int)); - memcpy(ec->c_i,ec->a_i,ec->N_d*sizeof(int)); - return 1; - } - - ec->a_i[pos] = val << 17; - ec->a_s[pos] = val << 1; - - if (++pos >= ec->N_d) { - memcpy(ec->b_i,ec->a_i,ec->N_d*sizeof(int)); - memcpy(ec->c_i,ec->a_i,ec->N_d*sizeof(int)); - return 1; - } - - return 0; -} - -#endif diff --git a/mg2ec_const.h b/mg2ec_const.h deleted file mode 100644 index 08fd897..0000000 --- a/mg2ec_const.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - Important constants for tuning mg2 echo can - */ -#ifndef _MG2_CONST_H -#define _MG2_CONST_H - - -/* Convergence (aka. adaptation) speed -- higher means slower */ -#define DEFAULT_BETA1_I 2048 - -/* Constants for various power computations */ -#define DEFAULT_SIGMA_LY_I 7 -#define DEFAULT_SIGMA_LU_I 7 -#define DEFAULT_ALPHA_ST_I 5 /* near-end speech detection sensitivity factor */ -#define DEFAULT_ALPHA_YT_I 5 - -#define DEFAULT_CUTOFF_I 128 - -/* Define the near-end speech hangover counter: if near-end speech - * is declared, hcntr is set equal to hangt (see pg. 432) - */ -#define DEFAULT_HANGT 600 /* in samples, so 600 samples = 75ms */ - -/* define the residual error suppression threshold */ -#define DEFAULT_SUPPR_I 16 /* 16 = -24db */ - -/* This is the minimum reference signal power estimate level - * that will result in filter adaptation. - * If this is too low then background noise will cause the filter - * coefficients to constantly be updated. - */ -#define MIN_UPDATE_THRESH_I 2048 - -/* The number of samples used to update coefficients using the - * the block update method (M). It should be related back to the - * length of the echo can. - * ie. it only updates coefficients when (sample number MOD default_m) = 0 - * - * Getting this wrong may cause an oops. Consider yourself warned! - */ -#define DEFAULT_M 16 /* every 16th sample */ - -/* If AGGRESSIVE supression is enabled, then we start cancelling residual - * echos again even while there is potentially the very end of a near-side - * signal present. - * This defines how many samples of DEFAULT_HANGT can remain before we - * kick back in - */ -#define AGGRESSIVE_HCNTR 160 /* in samples, so 160 samples = 20ms */ - -/* Treat sample as error if it has a different sign as the - * input signal and is this number larger in ABS() as - * the input-signal */ -#define MAX_SIGN_ERROR 3000 - -/* Number of coefficients really used for calculating the - * simulated echo. The value specifies how many of the - * biggest coefficients are used for calculating rs. - * This helps on long echo-tails by artificially limiting - * the number of coefficients for the calculation and - * preventing overflows. - * Comment this to deactivate the code */ -#define USED_COEFFS 64 - -/* Backup coefficients every this number of samples */ -#define BACKUP 256 - -/***************************************************************/ -/* The following knobs are not implemented in the current code */ - -/* we need a dynamic level of suppression varying with the ratio of the - power of the echo to the power of the reference signal this is - done so that we have a smoother background. - we have a higher suppression when the power ratio is closer to - suppr_ceil and reduces logarithmically as we approach suppr_floor. - */ -#define SUPPR_FLOOR -64 -#define SUPPR_CEIL -24 - -/* in a second departure, we calculate the residual error suppression - * as a percentage of the reference signal energy level. The threshold - * is defined in terms of dB below the reference signal. - */ -#define RES_SUPR_FACTOR -20 - - -#endif /* _MG2_CONST_H */ - diff --git a/patgen.c b/patgen.c index a740f39..34f455a 100644 --- a/patgen.c +++ b/patgen.c @@ -11,7 +11,7 @@ #include "bittest.h" #ifdef STANDALONE_ZAPATA -#include "zaptel.h" +#include "kernel/zaptel.h" #else #include #endif diff --git a/patlooptest.c b/patlooptest.c index d848ccf..738da63 100644 --- a/patlooptest.c +++ b/patlooptest.c @@ -9,7 +9,7 @@ #include #ifdef STANDALONE_ZAPATA -#include "zaptel.h" +#include "kernel/zaptel.h" #else #include #endif diff --git a/pattest.c b/pattest.c index d7b6fca..69c3b6e 100644 --- a/pattest.c +++ b/pattest.c @@ -11,7 +11,7 @@ #include "bittest.h" #ifdef STANDALONE_ZAPATA -#include "zaptel.h" +#include "kernel/zaptel.h" #else #include #endif diff --git a/pciradio.c b/pciradio.c deleted file mode 100644 index 55270c1..0000000 --- a/pciradio.c +++ /dev/null @@ -1,1934 +0,0 @@ -/* - * PCI RADIO Card Zapata Telephony PCI Quad Radio Interface driver - * - * Written by Jim Dixon - * Based on previous work by Mark Spencer - * Based on previous works, designs, and archetectures conceived and - * written by Jim Dixon . - * - * Copyright (C) 2001-2007 Jim Dixon / Zapata Telephony. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* - The PCI Radio Interface card interfaces up to 4 two-way radios (either - a base/mobile radio or repeater system) to Zaptel channels. The driver - may work either independent of an application, or with it, through - the driver;s ioctl() interface. This file gives you access to specify - load-time parameters for Radio channels, so that the driver may run - by itself, and just act like a generic Zaptel radio interface. -*/ - -/* Latency tests: - -Without driver: 308496 -With driver: 303826 (1.5 %) - -*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef STANDALONE_ZAPATA -#include "zaptel.h" -#else -#include -#endif - -#ifdef LINUX26 -#include -#endif - -#define RAD_MAX_IFACES 128 - -#define NUM_CODES 15 - -#define SERIAL_BUFLEN 128 - -#define SRX_TIMEOUT 300 - -#define RAD_CNTL 0x00 -#define RAD_OPER 0x01 -#define RAD_AUXC 0x02 -#define RAD_AUXD 0x03 - #define XPGM 4 - #define XCS 2 - -#define RAD_MASK0 0x04 -#define RAD_MASK1 0x05 -#define RAD_INTSTAT 0x06 -#define RAD_AUXR 0x07 - #define XINIT 8 - #define XDONE 0x10 - -#define RAD_DMAWS 0x08 -#define RAD_DMAWI 0x0c -#define RAD_DMAWE 0x10 -#define RAD_DMARS 0x18 -#define RAD_DMARI 0x1c -#define RAD_DMARE 0x20 - -#define RAD_AUXFUNC 0x2b -#define RAD_SERCTL 0x2d -#define RAD_FSCDELAY 0x2f - -#define RAD_REGBASE 0xc0 - -#define RAD_CTCSSMASK 0xf -#define RAD_CTCSSOTHER 0xf -#define RAD_CTCSSVALID 0x10 - -#define NUM_CHANS 4 - -#define RAD_GOTRX_DEBOUNCE_TIME 75 -#define RAD_CTCSS_ACQUIRE_TIME 10 -#define RAD_CTCSS_TALKOFF_TIME 1000 - -#define ZT_RADPAR_CTCSSACQUIRETIME 18 /* DEBUG only, this belongs in zaptel.h */ -#define ZT_RADPAR_CTCSSTALKOFFTIME 19 /* DEBUG only, this belongs in zaptel.h */ - -/* -* MX828 Commands -*/ - -#define MX828_GEN_RESET 0x01 /* W */ -#define MX828_SAUDIO_CTRL 0x80 /* W */ -#define MX828_SAUDIO_STATUS 0x81 /* R */ -#define MX828_SAUDIO_SETUP 0x82 /* W */ -#define MX828_TX_TONE 0x83 /* W16 */ -#define MX828_RX_TONE 0x84 /* W16 */ -#define MX828_DCS3 0x85 /* W */ -#define MX828_DCS2 0x86 /* W */ -#define MX828_DCS1 0x87 /* W */ -#define MX828_GEN_CTRL 0x88 /* W */ -#define MX828_GPT 0x8B /* W */ -#define MX828_IRQ_MASK 0x8E /* W */ -#define MX828_SELCALL 0x8D /* W16 */ -#define MX828_AUD_CTRL 0x8A /* W16 */ -#define MX828_IRQ_FLAG 0x8F /* R */ - - -struct encdec -{ - unsigned char state; /* 0 = idle */ - int chan; - unsigned char req[NUM_CHANS]; - unsigned char dcsrx[NUM_CHANS]; - unsigned char ctrx[NUM_CHANS]; - unsigned char dcstx[NUM_CHANS]; - unsigned char cttx[NUM_CHANS]; - unsigned char saudio_ctrl[NUM_CHANS]; - unsigned char saudio_setup[NUM_CHANS]; - unsigned char txcode[NUM_CHANS]; - unsigned long lastcmd; - int myindex[NUM_CHANS]; - unsigned long waittime; - unsigned char retstate; -} ; - - -struct pciradio { - struct pci_dev *dev; - struct zt_span span; - unsigned char ios; - int usecount; - unsigned int intcount; - int dead; - int pos; - int freeregion; - int nchans; - spinlock_t lock; - int remote_locked; - unsigned char rxbuf[SERIAL_BUFLEN]; - unsigned short rxindex; - unsigned long srxtimer; - unsigned char txbuf[SERIAL_BUFLEN]; - unsigned short txindex; - unsigned short txlen; - unsigned char pasave; - unsigned char pfsave; - volatile unsigned long ioaddr; - dma_addr_t readdma; - dma_addr_t writedma; - volatile unsigned int *writechunk; /* Double-word aligned write memory */ - volatile unsigned int *readchunk; /* Double-word aligned read memory */ - unsigned char saudio_status[NUM_CHANS]; - char gotcor[NUM_CHANS]; - char gotct[NUM_CHANS]; - char newctcssstate[NUM_CHANS]; - char ctcssstate[NUM_CHANS]; - char gotrx[NUM_CHANS]; - char gotrx1[NUM_CHANS]; - char gottx[NUM_CHANS]; - char lasttx[NUM_CHANS]; - int gotrxtimer[NUM_CHANS]; - int ctcsstimer[NUM_CHANS]; - int debouncetime[NUM_CHANS]; - int ctcssacquiretime[NUM_CHANS]; - int ctcsstalkofftime[NUM_CHANS]; - int bursttime[NUM_CHANS]; - int bursttimer[NUM_CHANS]; - unsigned char remmode[NUM_CHANS]; - unsigned short present_code[NUM_CHANS]; - unsigned short last_code[NUM_CHANS]; - unsigned short rxcode[NUM_CHANS][NUM_CODES + 1]; - unsigned short rxclass[NUM_CHANS][NUM_CODES + 1]; - unsigned short txcode[NUM_CHANS][NUM_CODES + 1];; - unsigned char radmode[NUM_CHANS]; -#define RADMODE_INVERTCOR 1 -#define RADMODE_IGNORECOR 2 -#define RADMODE_EXTTONE 4 -#define RADMODE_EXTINVERT 8 -#define RADMODE_IGNORECT 16 -#define RADMODE_NOENCODE 32 - unsigned char corthresh[NUM_CHANS]; - struct zt_chan chans[NUM_CHANS]; - unsigned char mx828_addr; - struct encdec encdec; - unsigned long lastremcmd; -}; - - -static struct pciradio *ifaces[RAD_MAX_IFACES]; - -static void pciradio_release(struct pciradio *rad); - -static int debug = 0; - -struct tonedef { - int code; - unsigned char b1; - unsigned char b2; -} ; - -#include "radfw.h" - -static struct tonedef cttable_tx [] = { -{0,0,0}, -{670,0xE,0xB1}, -{693,0xE,0x34}, -{719,0xD,0xB1}, -{744,0xD,0x3B}, -{770,0xC,0xC9}, -{797,0xC,0x5A}, -{825,0xB,0xEF}, -{854,0xB,0x87}, -{885,0xB,0x1F}, -{915,0xA,0xC2}, -{948,0xA,0x62}, -{974,0xA,0x1B}, -{1000,0x9,0xD8}, -{1035,0x9,0x83}, -{1072,0x9,0x2F}, -{1109,0x8,0xE0}, -{1148,0x8,0x93}, -{1188,0x8,0x49}, -{1230,0x8,0x1}, -{1273,0x7,0xBC}, -{1318,0x7,0x78}, -{1365,0x7,0x36}, -{1413,0x6,0xF7}, -{1462,0x6,0xBC}, -{1514,0x6,0x80}, -{1567,0x6,0x48}, -{1598,0x6,0x29}, -{1622,0x6,0x12}, -{1679,0x5,0xDD}, -{1738,0x5,0xAA}, -{1799,0x5,0x79}, -{1835,0x5,0x5D}, -{1862,0x5,0x49}, -{1899,0x5,0x2F}, -{1928,0x5,0x1B}, -{1966,0x5,0x2}, -{1995,0x4,0xEF}, -{2035,0x4,0xD6}, -{2065,0x4,0xC4}, -{2107,0x4,0xAC}, -{2181,0x4,0x83}, -{2257,0x4,0x5D}, -{2291,0x4,0x4C}, -{2336,0x4,0x37}, -{2418,0x4,0x12}, -{2503,0x3,0xEF}, -{2541,0x3,0xE0}, -{0,0,0} -} ; - -static struct tonedef cttable_rx [] = { -{0,0,0}, -{670,0x3,0xD8}, -{693,0x4,0x9}, -{719,0x4,0x1B}, -{744,0x4,0x4E}, -{770,0x4,0x83}, -{797,0x4,0x94}, -{825,0x4,0xCB}, -{854,0x5,0x2}, -{885,0x5,0x14}, -{915,0x5,0x4C}, -{948,0x5,0x87}, -{974,0x5,0x94}, -{1000,0x5,0xCB}, -{1035,0x6,0x7}, -{1072,0x6,0x45}, -{1109,0x6,0x82}, -{1148,0x6,0xC0}, -{1188,0x6,0xD1}, -{1230,0x7,0x10}, -{1273,0x7,0x50}, -{1318,0x7,0xC0}, -{1365,0x8,0x2}, -{1413,0x8,0x44}, -{1462,0x8,0x86}, -{1514,0x8,0xC9}, -{1567,0x9,0xC}, -{1598,0x9,0x48}, -{1622,0x9,0x82}, -{1679,0x9,0xC6}, -{1738,0xA,0xB}, -{1799,0xA,0x84}, -{1835,0xA,0xC2}, -{1862,0xA,0xC9}, -{1899,0xB,0x8}, -{1928,0xB,0x44}, -{1966,0xB,0x83}, -{1995,0xB,0x8A}, -{2035,0xB,0xC9}, -{2065,0xC,0x6}, -{2107,0xC,0x46}, -{2181,0xC,0xC3}, -{2257,0xD,0x41}, -{2291,0xD,0x48}, -{2336,0xD,0x89}, -{2418,0xE,0x8}, -{2503,0xE,0x88}, -{2541,0xE,0xC7}, -{0,0,0} -}; - -static struct { - int code; - char b3; - char b2; - char b1; -} dcstable[] = { -{0,0,0,0}, -{23,0x76,0x38,0x13}, -{25,0x6B,0x78,0x15}, -{26,0x65,0xD8,0x16}, -{31,0x51,0xF8,0x19}, -{32,0x5F,0x58,0x1A}, -{43,0x5B,0x68,0x23}, -{47,0x0F,0xD8,0x27}, -{51,0x7C,0xA8,0x29}, -{54,0x6F,0x48,0x2C}, -{65,0x5D,0x18,0x35}, -{71,0x67,0x98,0x39}, -{72,0x69,0x38,0x3A}, -{73,0x2E,0x68,0x3B}, -{74,0x74,0x78,0x3C}, -{114,0x35,0xE8,0x4C}, -{115,0x72,0xB8,0x4D}, -{116,0x7C,0x18,0x4E}, -{125,0x07,0xB8,0x55}, -{131,0x3D,0x38,0x59}, -{132,0x33,0x98,0x5A}, -{134,0x2E,0xD8,0x5C}, -{143,0x37,0xA8,0x63}, -{152,0x1E,0xC8,0x6A}, -{155,0x44,0xD8,0x6D}, -{156,0x4A,0x78,0x6E}, -{162,0x6B,0xC8,0x72}, -{165,0x31,0xD8,0x75}, -{172,0x05,0xF8,0x7A}, -{174,0x18,0xB8,0x7C}, -{205,0x6E,0x98,0x85}, -{223,0x68,0xE8,0x93}, -{226,0x7B,0x08,0x96}, -{243,0x45,0xB8,0xA3}, -{244,0x1F,0xA8,0xA4}, -{245,0x58,0xF8,0xA5}, -{251,0x62,0x78,0xA9}, -{261,0x17,0x78,0xB1}, -{263,0x5E,0x88,0xB3}, -{265,0x43,0xC8,0xB5}, -{271,0x79,0x48,0xB9}, -{306,0x0C,0xF8,0xC6}, -{311,0x38,0xD8,0xC9}, -{315,0x6C,0x68,0xCD}, -{331,0x23,0xE8,0xD9}, -{343,0x29,0x78,0xE3}, -{346,0x3A,0x98,0xE6}, -{351,0x0E,0xB8,0xE9}, -{364,0x68,0x58,0xF4}, -{365,0x2F,0x08,0xF5}, -{371,0x15,0x88,0xF9}, -{411,0x77,0x69,0x09}, -{412,0x79,0xC9,0x0A}, -{413,0x3E,0x99,0x0B}, -{423,0x4B,0x99,0x13}, -{431,0x6C,0x59,0x19}, -{432,0x62,0xF9,0x1A}, -{445,0x7B,0x89,0x25}, -{464,0x27,0xE9,0x34}, -{465,0x60,0xB9,0x35}, -{466,0x6E,0x19,0x36}, -{503,0x3C,0x69,0x43}, -{506,0x2F,0x89,0x46}, -{516,0x41,0xB9,0x4E}, -{532,0x0E,0x39,0x5A}, -{546,0x19,0xE9,0x66}, -{565,0x0C,0x79,0x75}, -{606,0x5D,0x99,0x86}, -{612,0x67,0x19,0x8A}, -{624,0x0F,0x59,0x94}, -{627,0x01,0xF9,0x97}, -{631,0x72,0x89,0x99}, -{632,0x7C,0x29,0x9A}, -{654,0x4C,0x39,0xAC}, -{662,0x24,0x79,0xB2}, -{664,0x39,0x39,0xB4}, -{703,0x22,0xB9,0xC3}, -{712,0x0B,0xD9,0xCA}, -{723,0x39,0x89,0xD3}, -{731,0x1E,0x49,0xD9}, -{732,0x10,0xE9,0xDA}, -{734,0x0D,0xA9,0xDC}, -{743,0x14,0xD9,0xE3}, -{754,0x20,0xF9,0xEC}, -{0,0,0,0} -}; - -static int gettxtone(int code) -{ -int i; - - if (!code) return(0); - for(i = 0; cttable_tx[i].code || (!i); i++) - { - if (cttable_tx[i].code == code) - { - return (i); - } - } - return(-1); -} - -static int getrxtone(int code) -{ -int i; - - if (!code) return(0); - for(i = 0; cttable_rx[i].code || (!i); i++) - { - if (cttable_rx[i].code == code) - { - return (i); - } - } - return(-1); -} - - -static int getdcstone(int code) -{ -int i; - - if (!code) return(0); - for(i = 0; dcstable[i].code || (!i); i++) - { - if (dcstable[i].code == code) - { - return (i); - } - } - return(-1); -} - - -void __pciradio_setcreg(struct pciradio *rad, unsigned char reg, unsigned char val) -{ - outb(val, rad->ioaddr + RAD_REGBASE + ((reg & 0xf) << 2)); -} - -unsigned char __pciradio_getcreg(struct pciradio *rad, unsigned char reg) -{ - return inb(rad->ioaddr + RAD_REGBASE + ((reg & 0xf) << 2)); -} - - -void rbi_out(struct pciradio *rad, int n, unsigned char *rbicmd) -{ -unsigned long flags; -int x; -DECLARE_WAIT_QUEUE_HEAD(mywait); - - - for(;;) - { - spin_lock_irqsave(&rad->lock,flags); - x = rad->remote_locked || (__pciradio_getcreg(rad,0xc) & 2); - if (!x) rad->remote_locked = 1; - spin_unlock_irqrestore(&rad->lock,flags); - if (x) interruptible_sleep_on_timeout(&mywait,2); - else break; - } - spin_lock_irqsave(&rad->lock,flags); - /* enable and address RBI serializer */ - __pciradio_setcreg(rad,0xf,rad->pfsave | (n << 4) | 0x40); - /* output commands */ - for(x = 0; x < 5; x++) __pciradio_setcreg(rad,0xc,rbicmd[x]); - /* output it */ - __pciradio_setcreg(rad,0xb,1); - rad->remote_locked = 0; - spin_unlock_irqrestore(&rad->lock,flags); - return; -} - - -/* -* Output a command to the MX828 over the serial bus -*/ - - -void mx828_command(struct pciradio *rad,int channel, unsigned char command, unsigned char *byte1, unsigned char *byte2) -{ - - if(channel > 3) - return; - - rad->mx828_addr = channel; - __pciradio_setcreg(rad,0,channel); - if (byte1) __pciradio_setcreg(rad,1,*byte1); - if (byte2) __pciradio_setcreg(rad,2,*byte2); - __pciradio_setcreg(rad,3,command); - -} - -void mx828_command_wait(struct pciradio *rad,int channel, unsigned char command, unsigned char *byte1, unsigned char *byte2) -{ -DECLARE_WAIT_QUEUE_HEAD(mywait); -unsigned long flags; - - - spin_lock_irqsave(&rad->lock,flags); - while(rad->encdec.state) - { - spin_unlock_irqrestore(&rad->lock,flags); - interruptible_sleep_on_timeout(&mywait,2); - spin_lock_irqsave(&rad->lock,flags); - } - rad->encdec.lastcmd = jiffies + 1000; - spin_unlock_irqrestore(&rad->lock,flags); - while(__pciradio_getcreg(rad,0xc) & 1); - rad->encdec.lastcmd = jiffies + 1000; - spin_lock_irqsave(&rad->lock,flags); - rad->encdec.lastcmd = jiffies + 1000; - mx828_command(rad,channel,command,byte1,byte2); - spin_unlock_irqrestore(&rad->lock,flags); - rad->encdec.lastcmd = jiffies + 1000; - while(__pciradio_getcreg(rad,0xc) & 1); - rad->encdec.lastcmd = jiffies; -} - -static void _do_encdec(struct pciradio *rad) -{ -int i,n; -unsigned char byte1 = 0,byte2 = 0; - - /* return doing nothing if busy */ - if ((rad->encdec.lastcmd + 2) > jiffies) return; - if (__pciradio_getcreg(rad,0xc) & 1) return; - n = 0; - byte2 = 0; - switch(rad->encdec.state) - { - case 0: - for(i = 0; i < rad->nchans; i++) - { - n = (unsigned)(i - rad->intcount) % rad->nchans; - if (rad->encdec.req[n]) break; - } - if (i >= rad->nchans) return; - rad->encdec.req[n] = 0; - rad->encdec.dcsrx[n] = 0; - rad->encdec.ctrx[n] = 0; - rad->encdec.dcstx[n] = 0; - rad->encdec.cttx[n] = 0; - rad->encdec.myindex[n] = 0; - rad->encdec.req[n] = 0; - rad->encdec.chan = n; - - /* if something in code 0 for rx, is DCS */ - if (rad->rxcode[n][0]) rad->encdec.dcsrx[n] = 1; - else { /* otherwise, if something in other codes, is CT rx */ - for(i = 1; i <= NUM_CODES; i++) - { - if (rad->rxcode[n][1]) rad->encdec.ctrx[n] = 1; - } - } - /* get index for tx code. Will be 0 if not receiving a CT */ - rad->encdec.myindex[n] = 0; - if (rad->gotrx[n] && rad->encdec.ctrx[n] && (rad->present_code[n])) - rad->encdec.myindex[n] = rad->present_code[n]; - /* get actual tx code from array */ - rad->encdec.txcode[n] = rad->txcode[n][rad->encdec.myindex[n]]; - if (rad->encdec.txcode[n] & 0x8000) rad->encdec.dcstx[n] = 1; - else if (rad->encdec.txcode[n]) rad->encdec.cttx[n] = 1; - if (rad->radmode[n] & RADMODE_NOENCODE) - rad->encdec.dcstx[n] = rad->encdec.cttx[n] = 0; - if ((!rad->gottx[n]) || rad->bursttimer[n]) - rad->encdec.dcstx[n] = rad->encdec.cttx[n] = 0; - rad->encdec.saudio_ctrl[n] = 0; - rad->encdec.saudio_setup[n] = 0; - rad->encdec.state = 1; - break; - case 1: - if (rad->encdec.dcstx[rad->encdec.chan] && (!rad->encdec.dcsrx[rad->encdec.chan])) /* if to transmit DCS */ - { - rad->encdec.saudio_setup[rad->encdec.chan] |= 3; - rad->encdec.saudio_ctrl[rad->encdec.chan] |= 0x80; - byte1 = dcstable[rad->encdec.txcode[rad->encdec.chan] & 0x7fff].b1; - mx828_command(rad,rad->encdec.chan, MX828_DCS1, &byte1, &byte2 ); - rad->encdec.state = 2; - break; - } - rad->encdec.state = 4; - break; - case 2: - byte1 = dcstable[rad->encdec.txcode[rad->encdec.chan] & 0x7fff].b2; - mx828_command(rad,rad->encdec.chan, MX828_DCS2, &byte1, &byte2 ); - rad->encdec.state = 3; - break; - case 3: - byte1 = dcstable[rad->encdec.txcode[rad->encdec.chan] & 0x7fff].b3; - mx828_command(rad,rad->encdec.chan, MX828_DCS3, &byte1, &byte2 ); - rad->encdec.state = 4; - break; - case 4: - if (rad->encdec.cttx[rad->encdec.chan]) - { - rad->encdec.saudio_ctrl[rad->encdec.chan] |= 0x80; - byte1 = cttable_tx[rad->encdec.txcode[rad->encdec.chan]].b1; - byte2 = cttable_tx[rad->encdec.txcode[rad->encdec.chan]].b2; - mx828_command(rad,rad->encdec.chan, MX828_TX_TONE, &byte1, &byte2 ); - } - rad->encdec.state = 5; - break; - case 5: - if (rad->encdec.dcsrx[rad->encdec.chan]) - { - rad->encdec.saudio_setup[rad->encdec.chan] |= 1; - rad->encdec.saudio_ctrl[rad->encdec.chan] |= 0x41; - byte1 = dcstable[rad->rxcode[rad->encdec.chan][0]].b1; - mx828_command(rad,rad->encdec.chan, MX828_DCS1, &byte1, &byte2 ); - rad->encdec.state = 6; - break; - } - rad->encdec.state = 8; - break; - case 6: - byte1 = dcstable[rad->rxcode[rad->encdec.chan][0]].b2; - mx828_command(rad,rad->encdec.chan, MX828_DCS2, &byte1, &byte2 ); - rad->encdec.state = 7; - break; - case 7: - byte1 = dcstable[rad->rxcode[rad->encdec.chan][0]].b3; - mx828_command(rad,rad->encdec.chan, MX828_DCS3, &byte1, &byte2 ); - rad->encdec.state = 8; - break; - case 8: - if (rad->encdec.ctrx[rad->encdec.chan]) - { - rad->encdec.saudio_setup[rad->encdec.chan] |= 0x80; - rad->encdec.saudio_ctrl[rad->encdec.chan] |= 0x60; - } - byte1 = rad->encdec.saudio_setup[rad->encdec.chan]; - mx828_command(rad,rad->encdec.chan, MX828_SAUDIO_SETUP, &byte1, &byte2 ); - rad->encdec.state = 9; - break; - case 9: - byte1 = rad->encdec.saudio_ctrl[rad->encdec.chan]; - mx828_command(rad,rad->encdec.chan, MX828_SAUDIO_CTRL, &byte1, &byte2 ); - rad->encdec.state = 10; - break; - case 10: - rad->encdec.chan = 0; - rad->encdec.state = 0; - break; - } -} - -static inline void pciradio_transmitprep(struct pciradio *rad, unsigned char ints) -{ - volatile unsigned int *writechunk; - int x; - if (ints & 0x01) - /* Write is at interrupt address. Start writing from normal offset */ - writechunk = rad->writechunk; - else - writechunk = rad->writechunk + ZT_CHUNKSIZE; - - /* Calculate Transmission */ - zt_transmit(&rad->span); - - for (x=0;xchans[0].writechunk[x] << 24); - writechunk[x] |= (rad->chans[1].writechunk[x] << 16); - writechunk[x] |= (rad->chans[2].writechunk[x] << 8); - writechunk[x] |= (rad->chans[3].writechunk[x]); - } -} - -static inline void pciradio_receiveprep(struct pciradio *rad, unsigned char ints) -{ - volatile unsigned int *readchunk; - int x; - - if (ints & 0x08) - readchunk = rad->readchunk + ZT_CHUNKSIZE; - else - /* Read is at interrupt address. Valid data is available at normal offset */ - readchunk = rad->readchunk; - for (x=0;xchans[0].readchunk[x] = (readchunk[x] >> 24) & 0xff; - rad->chans[1].readchunk[x] = (readchunk[x] >> 16) & 0xff; - rad->chans[2].readchunk[x] = (readchunk[x] >> 8) & 0xff; - rad->chans[3].readchunk[x] = (readchunk[x]) & 0xff; - } - for (x=0;xnchans;x++) { - zt_ec_chunk(&rad->chans[x], rad->chans[x].readchunk, rad->chans[x].writechunk); - } - zt_receive(&rad->span); -} - -static void pciradio_stop_dma(struct pciradio *rad); -static void pciradio_reset_serial(struct pciradio *rad); -static void pciradio_restart_dma(struct pciradio *rad); - -#ifdef LEAVE_THIS_COMMENTED_OUT -#ifdef LINUX26 -static irqreturn_t pciradio_interrupt(int irq, void *dev_id, struct pt_regs *regs) -#else -static void pciradio_interrupt(int irq, void *dev_id, struct pt_regs *regs) -#endif -#endif - -ZAP_IRQ_HANDLER(pciradio_interrupt) -{ - struct pciradio *rad = dev_id; - unsigned char ints,byte1,byte2,gotcor,gotctcss,gotslowctcss,ctcss; - int i,x,gotrx; - - ints = inb(rad->ioaddr + RAD_INTSTAT); - outb(ints, rad->ioaddr + RAD_INTSTAT); - - if (!ints) -#ifdef LINUX26 - return IRQ_NONE; -#else - return; -#endif - - if (ints & 0x10) { - /* Stop DMA, wait for watchdog */ - printk("RADIO PCI Master abort\n"); - pciradio_stop_dma(rad); -#ifdef LINUX26 - return IRQ_RETVAL(1); -#else - return; -#endif - } - - if (ints & 0x20) { - printk("RADIO PCI Target abort\n"); -#ifdef LINUX26 - return IRQ_RETVAL(1); -#else - return; -#endif - } - - if (ints & 0x0f) { - - rad->intcount++; - x = rad->intcount % rad->nchans; - /* freeze */ - __pciradio_setcreg(rad,0,rad->mx828_addr | 4); - /* read SAUDIO_STATUS for the proper channel */ - byte1 = rad->saudio_status[x] = __pciradio_getcreg(rad,x); - /* thaw */ - __pciradio_setcreg(rad,0,rad->mx828_addr); - /* get COR input */ - byte2 = __pciradio_getcreg(rad,9); - /* get bit for this channel */ - gotcor = byte2 & (1 << x); - if (rad->radmode[x] & RADMODE_INVERTCOR) gotcor = !gotcor; - rad->gotcor[x] = gotcor; - if (rad->radmode[x] & RADMODE_IGNORECOR) gotcor = 1; - gotslowctcss = 0; - if ((byte1 & RAD_CTCSSVALID) && - ((byte1 & RAD_CTCSSMASK) != RAD_CTCSSOTHER)) gotslowctcss = 1; - gotctcss = 1; - ctcss = 0; - /* set ctcss to 1 if decoding ctcss */ - if (!rad->rxcode[x][0]) - { - for(i = 1; i <= NUM_CODES; i++) - { - if (rad->rxcode[x][i]) - { - ctcss = 1; - break; - } - } - } - if (ctcss) - { - if ((!(byte1 & 0x40)) || - ((!rad->gotrx[x]) && (!gotslowctcss))) gotctcss = 0; - } - rad->present_code[x] = 0; - if (rad->rxcode[x][0]) - { - if (byte1 & 0x80) gotctcss = gotslowctcss = 1; else gotctcss = 0; - } else if (gotslowctcss) rad->present_code[x] = (byte1 & RAD_CTCSSMASK) + 1; - if (rad->radmode[x] & RADMODE_EXTTONE) - { - unsigned mask = 1 << (x + 4); /* they're on the UIOB's */ - unsigned char byteuio; - - /* set UIOB as input */ - byteuio = __pciradio_getcreg(rad,0xe); - byteuio |= mask; - __pciradio_setcreg(rad,0xe,byteuio); - /* get UIO input */ - byteuio = __pciradio_getcreg(rad,8); - if (rad->radmode[x] & RADMODE_EXTINVERT) - gotctcss = gotslowctcss = ((byteuio & mask) == 0); - else - gotctcss = gotslowctcss = ((byteuio & mask) != 0); - } - rad->gotct[x] = gotslowctcss; - if ((rad->radmode[x] & RADMODE_IGNORECT) || - ((!(rad->radmode[x] & RADMODE_EXTTONE)) && (!ctcss))) - { - gotctcss = 1; - gotslowctcss = 1; - rad->present_code[x] = 0; - } - if(rad->newctcssstate[x] != gotctcss){ - rad->newctcssstate[x] = gotctcss; - if(rad->newctcssstate[x]) - rad->ctcsstimer[x]=rad->ctcssacquiretime[x]; - else - rad->ctcsstimer[x]=rad->ctcsstalkofftime[x]; - } - else{ - if(!rad->ctcsstimer[x]) - rad->ctcssstate[x] = rad->newctcssstate[x]; - else - rad->ctcsstimer[x]--; - } - gotrx = gotcor && rad->ctcssstate[x]; - if (gotrx != rad->gotrx[x]) - { - rad->gotrxtimer[x] = rad->debouncetime[x]; - } - rad->gotrx[x] = gotrx; - if (rad->present_code[x] != rad->last_code[x]) - { - rad->encdec.req[x] = 1; - rad->last_code[x] = rad->present_code[x]; - } - _do_encdec(rad); - for(x = 0; x < rad->nchans; x++) - { - unsigned char mask = 1 << x; - - if (rad->gottx[x] != rad->lasttx[x]) - { - if (rad->gottx[x]) - { - rad->bursttimer[x] = 0; - rad->pasave |= mask; - __pciradio_setcreg(rad, 0xa, rad->pasave); - } - else - { - if (!rad->bursttime[x]) - { - rad->pasave &= ~mask; - __pciradio_setcreg(rad, 0xa, rad->pasave); - } - else - { - rad->bursttimer[x] = rad->bursttime[x]; - } - } - rad->encdec.req[x] = 1; - rad->lasttx[x] = rad->gottx[x]; - } - if (rad->bursttimer[x]) - { - /* if just getting to zero */ - if (!(--rad->bursttimer[x])) - { - unsigned char mask = 1 << x; - - rad->pasave &= ~mask; - __pciradio_setcreg(rad, 0xa, rad->pasave); - } - } - - /* if timer active */ - if (rad->gotrxtimer[x]) - { - /* if just getting to zero */ - if (!(--rad->gotrxtimer[x])) - { - unsigned char mask; - - mask = 1 << (x + 4); - rad->pasave &= ~mask; - if (gotctcss) rad->pasave |= mask; - __pciradio_setcreg(rad, 0xa, rad->pasave); - - if (rad->gotrx[x] != rad->gotrx1[x]) - { - if (rad->gotrx[x]) { - if (debug) - { - if (rad->present_code[x]) - printk("Chan %d got rx (ctcss code %d)\n",x + 1, - cttable_rx[rad->rxcode[x][rad->present_code[x]]].code); - else - printk("Chan %d got rx\n",x + 1); - } - zt_hooksig(&rad->chans[x],ZT_RXSIG_OFFHOOK); - } else { - if (debug) printk("Chan %d lost rx\n",x + 1); - zt_hooksig(&rad->chans[x],ZT_RXSIG_ONHOOK); - } - rad->encdec.req[x] = 1; - } - rad->gotrx1[x] = rad->gotrx[x]; - } - } - } - /* process serial if any */ - /* send byte if there is one in buffer to send */ - if (rad->txlen && (rad->txlen != rad->txindex)) - { - /* if tx not busy */ - if (!(__pciradio_getcreg(rad,9) & 0x80)) - { - __pciradio_setcreg(rad, 4, rad->txbuf[rad->txindex++]); - } - } - rad->srxtimer++; - /* if something in rx to read */ - while(__pciradio_getcreg(rad,9) & 0x10) - { - unsigned char c = __pciradio_getcreg(rad,4); - rad->srxtimer = 0; - if (rad->rxindex < RAD_SERIAL_BUFLEN) - { - rad->rxbuf[rad->rxindex++] = c; - } - udelay(1); - } - pciradio_receiveprep(rad, ints); - pciradio_transmitprep(rad, ints); - i = 0; - for(x = 0; x < 4; x++) - { - if (rad->gottx[x]) i |= (1 << (x * 2)); - if (rad->gotrx[x]) i |= (2 << (x * 2)); - } - /* output LED's */ - __pciradio_setcreg(rad, 9, i); - } -#ifdef LINUX26 - return IRQ_RETVAL(1); -#endif - -} - -static int pciradio_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) -{ - int i,mycode; - unsigned long flags; - unsigned char byte1,byte2,mask; - union { - struct zt_radio_stat s; - struct zt_radio_param p; - } stack; - - struct pciradio *rad = chan->pvt; - DECLARE_WAIT_QUEUE_HEAD(mywait); - - switch (cmd) { - case ZT_RADIO_GETPARAM: - if (copy_from_user(&stack.p,(struct zt_radio_param *)data,sizeof(struct zt_radio_param))) return -EFAULT; - spin_lock_irqsave(&rad->lock,flags); - stack.p.data = 0; /* start with 0 value in output */ - switch(stack.p.radpar) { - case ZT_RADPAR_INVERTCOR: - if (rad->radmode[chan->chanpos - 1] & RADMODE_INVERTCOR) - stack.p.data = 1; - break; - case ZT_RADPAR_IGNORECOR: - if (rad->radmode[chan->chanpos - 1] & RADMODE_IGNORECOR) - stack.p.data = 1; - break; - case ZT_RADPAR_IGNORECT: - if (rad->radmode[chan->chanpos - 1] & RADMODE_IGNORECT) - stack.p.data = 1; - break; - case ZT_RADPAR_NOENCODE: - if (rad->radmode[chan->chanpos - 1] & RADMODE_NOENCODE) - stack.p.data = 1; - break; - case ZT_RADPAR_CORTHRESH: - stack.p.data = rad->corthresh[chan->chanpos - 1] & 7; - break; - case ZT_RADPAR_EXTRXTONE: - if (rad->radmode[chan->chanpos - 1] & RADMODE_EXTTONE) - { - stack.p.data = 1; - if (rad->radmode[chan->chanpos - 1] & RADMODE_EXTINVERT) - { - stack.p.data = 2; - } - } - break; - case ZT_RADPAR_NUMTONES: - stack.p.data = NUM_CODES; - break; - case ZT_RADPAR_RXTONE: - if ((stack.p.index < 1) || (stack.p.index > NUM_CODES)) { - spin_unlock_irqrestore(&rad->lock,flags); - return -EINVAL; - } - stack.p.data = - cttable_rx[rad->rxcode[chan->chanpos - 1][stack.p.index] & 0x7fff].code; - break; - case ZT_RADPAR_RXTONECLASS: - if ((stack.p.index < 1) || (stack.p.index > NUM_CODES)) { - spin_unlock_irqrestore(&rad->lock,flags); - return -EINVAL; - } - stack.p.data = rad->rxclass[chan->chanpos - 1][stack.p.index] & 0xffff; - break; - case ZT_RADPAR_TXTONE: - if (stack.p.index > NUM_CODES) { - spin_unlock_irqrestore(&rad->lock,flags); - return -EINVAL; - } - stack.p.data = cttable_tx[rad->txcode[chan->chanpos - 1][stack.p.index] & 0x7fff].code; - /* if a DCS tone, return as such */ - if (rad->txcode[chan->chanpos - 1][stack.p.index] & 0x8000) - stack.p.data |= 0x8000; - break; - case ZT_RADPAR_DEBOUNCETIME: - stack.p.data = rad->debouncetime[chan->chanpos - 1]; - break; - - case ZT_RADPAR_CTCSSACQUIRETIME: - stack.p.data = rad->ctcssacquiretime[chan->chanpos - 1]; - break; - - case ZT_RADPAR_CTCSSTALKOFFTIME: - stack.p.data = rad->ctcsstalkofftime[chan->chanpos - 1]; - break; - - case ZT_RADPAR_BURSTTIME: - stack.p.data = rad->bursttime[chan->chanpos - 1]; - break; - case ZT_RADPAR_UIODATA: - stack.p.data = 0; - byte1 = __pciradio_getcreg(rad,8); - if (byte1 & (1 << (chan->chanpos - 1))) stack.p.data |= 1; - if (byte1 & (1 << (chan->chanpos + 3))) stack.p.data |= 2; - break; - case ZT_RADPAR_UIOMODE: - stack.p.data = 0; - byte1 = __pciradio_getcreg(rad,0xe); - if (byte1 & (1 << (chan->chanpos - 1))) stack.p.data |= 1; - if (byte1 & (1 << (chan->chanpos + 3))) stack.p.data |= 2; - break; - case ZT_RADPAR_REMMODE: - stack.p.data = rad->remmode[chan->chanpos - 1]; - break; - default: - spin_unlock_irqrestore(&rad->lock,flags); - return -EINVAL; - } - spin_unlock_irqrestore(&rad->lock,flags); - if (copy_to_user((struct zt_radio_param *)data,&stack.p,sizeof(struct zt_radio_param))) return -EFAULT; - break; - case ZT_RADIO_SETPARAM: - if (copy_from_user(&stack.p,(struct zt_radio_param *)data,sizeof(struct zt_radio_param))) return -EFAULT; - spin_lock_irqsave(&rad->lock,flags); - switch(stack.p.radpar) { - case ZT_RADPAR_INVERTCOR: - if (stack.p.data) - rad->radmode[chan->chanpos - 1] |= RADMODE_INVERTCOR; - else - rad->radmode[chan->chanpos - 1] &= ~RADMODE_INVERTCOR; - break; - case ZT_RADPAR_IGNORECOR: - if (stack.p.data) - rad->radmode[chan->chanpos - 1] |= RADMODE_IGNORECOR; - else - rad->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECOR; - break; - case ZT_RADPAR_IGNORECT: - if (stack.p.data) - rad->radmode[chan->chanpos - 1] |= RADMODE_IGNORECT; - else - rad->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECT; - break; - case ZT_RADPAR_NOENCODE: - if (stack.p.data) - rad->radmode[chan->chanpos - 1] |= RADMODE_NOENCODE; - else - rad->radmode[chan->chanpos - 1] &= ~RADMODE_NOENCODE; - break; - case ZT_RADPAR_CORTHRESH: - if ((stack.p.data < 0) || (stack.p.data > 7)) { - spin_unlock_irqrestore(&rad->lock,flags); - return -EINVAL; - } - rad->corthresh[chan->chanpos - 1] = stack.p.data; - byte1 = 0xc0 | (rad->corthresh[chan->chanpos - 1] << 2); - spin_unlock_irqrestore(&rad->lock,flags); - mx828_command_wait(rad,chan->chanpos - 1, MX828_GEN_CTRL, &byte1, &byte2); - spin_lock_irqsave(&rad->lock,flags); - break; - case ZT_RADPAR_EXTRXTONE: - if (stack.p.data) - rad->radmode[chan->chanpos - 1] |= RADMODE_EXTTONE; - else - rad->radmode[chan->chanpos - 1] &= ~RADMODE_EXTTONE; - if (stack.p.data > 1) - rad->radmode[chan->chanpos - 1] |= RADMODE_EXTINVERT; - else - rad->radmode[chan->chanpos - 1] &= ~RADMODE_EXTINVERT; - break; - case ZT_RADPAR_INITTONE: - for(i = 0; i <= NUM_CODES; i++) - { - rad->rxcode[chan->chanpos - 1][i] = 0; - rad->rxclass[chan->chanpos - 1][i] = 0; - rad->txcode[chan->chanpos - 1][i] = 0; - } - spin_unlock_irqrestore(&rad->lock,flags); - for(i = 0; i < NUM_CODES; i++) - { - /* set to no encode/decode */ - byte1 = 0; - mx828_command_wait(rad,chan->chanpos - 1, MX828_SAUDIO_CTRL, &byte1, &byte2 ); - /* set rx tone to none */ - byte1 = i << 4; - byte2 = 0; - mx828_command_wait(rad,chan->chanpos - 1, MX828_RX_TONE, &byte1, &byte2 ); - } - spin_lock_irqsave(&rad->lock,flags); - break; - case ZT_RADPAR_RXTONE: - if (!stack.p.index) /* if RX DCS mode */ - { - if ((stack.p.data < 0) || (stack.p.data > 777)) { - spin_unlock_irqrestore(&rad->lock,flags); - return -EINVAL; - } - mycode = getdcstone(stack.p.data); - if (mycode < 0) { - spin_unlock_irqrestore(&rad->lock,flags); - return -EINVAL; - } - rad->rxcode[chan->chanpos - 1][0] = mycode; - rad->encdec.req[chan->chanpos - 1] = 1; - break; - } - if ((stack.p.index < 1) || (stack.p.index > NUM_CODES)) { - spin_unlock_irqrestore(&rad->lock,flags); - return -EINVAL; - } - mycode = getrxtone(stack.p.data); - if (mycode < 0) { - spin_unlock_irqrestore(&rad->lock,flags); - return -EINVAL; - } - rad->rxcode[chan->chanpos - 1][stack.p.index] = mycode; - byte1 = cttable_rx[mycode].b1 | ((stack.p.index - 1) << 4); - byte2 = cttable_rx[mycode].b2; - spin_unlock_irqrestore(&rad->lock,flags); - mx828_command_wait(rad,chan->chanpos - 1, MX828_RX_TONE, &byte1, &byte2 ); - spin_lock_irqsave(&rad->lock,flags); - /* zot out DCS one if there */ - rad->rxcode[chan->chanpos - 1][0] = 0; - rad->encdec.req[chan->chanpos - 1] = 1; - break; - case ZT_RADPAR_RXTONECLASS: - if ((stack.p.index < 1) || (stack.p.index > NUM_CODES)) { - spin_unlock_irqrestore(&rad->lock,flags); - return -EINVAL; - } - rad->rxclass[chan->chanpos - 1][stack.p.index] = stack.p.data & 0xffff; - break; - case ZT_RADPAR_TXTONE: - if (stack.p.index > NUM_CODES) { - spin_unlock_irqrestore(&rad->lock,flags); - return -EINVAL; - } - if (stack.p.data & 0x8000) /* if dcs */ - mycode = getdcstone(stack.p.data & 0x7fff); - else - mycode = gettxtone(stack.p.data); - if (mycode < 0) { - spin_unlock_irqrestore(&rad->lock,flags); - return -EINVAL; - } - if (stack.p.data & 0x8000) mycode |= 0x8000; - rad->txcode[chan->chanpos - 1][stack.p.index] = mycode; - rad->encdec.req[chan->chanpos - 1] = 1; - break; - case ZT_RADPAR_DEBOUNCETIME: - rad->debouncetime[chan->chanpos - 1] = stack.p.data; - break; - - case ZT_RADPAR_CTCSSACQUIRETIME: - rad->ctcssacquiretime[chan->chanpos - 1] = stack.p.data; - break; - - case ZT_RADPAR_CTCSSTALKOFFTIME: - rad->ctcsstalkofftime[chan->chanpos - 1] = stack.p.data; - break; - - case ZT_RADPAR_BURSTTIME: - rad->bursttime[chan->chanpos - 1] = stack.p.data; - break; - case ZT_RADPAR_UIODATA: - byte1 = __pciradio_getcreg(rad,8); - byte1 &= ~(1 << (chan->chanpos - 1)); - byte1 &= ~(1 << (chan->chanpos + 3)); - if (stack.p.data & 1) byte1 |= (1 << (chan->chanpos - 1)); - if (stack.p.data & 2) byte1 |= (1 << (chan->chanpos + 3)); - __pciradio_setcreg(rad,8,byte1); - break; - case ZT_RADPAR_UIOMODE: - byte1 = __pciradio_getcreg(rad,0xe); - byte1 &= ~(1 << (chan->chanpos - 1)); - byte1 &= ~(1 << (chan->chanpos + 3)); - if (stack.p.data & 1) byte1 |= (1 << (chan->chanpos - 1)); - if (stack.p.data & 2) byte1 |= (1 << (chan->chanpos + 3)); - __pciradio_setcreg(rad,0xe,byte1); - break; - case ZT_RADPAR_REMMODE: - rad->remmode[chan->chanpos - 1] = stack.p.data; - break; - case ZT_RADPAR_REMCOMMAND: - /* if no remote mode, return an error */ - if (rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_NONE) - { - spin_unlock_irqrestore(&rad->lock,flags); - return -EINVAL; - } - i = 0; - if (rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_RBI1) - { - /* set UIOA and UIOB for output */ - byte1 = __pciradio_getcreg(rad,0xe); - mask = (1 << (chan->chanpos - 1)) | - (1 << (chan->chanpos + 3)); - byte2 = byte1 & (~mask); - i = (byte2 != byte1); - __pciradio_setcreg(rad,0xe,byte2); - byte1 = __pciradio_getcreg(rad,8); - mask = 1 << (chan->chanpos - 1); - byte2 = byte1 | mask; - i = (byte2 != byte1); - __pciradio_setcreg(rad,8,byte2); - spin_unlock_irqrestore(&rad->lock,flags); - if (i || (jiffies < rad->lastremcmd + 10)) - interruptible_sleep_on_timeout(&mywait,10); - rad->lastremcmd = jiffies; - rbi_out(rad,chan->chanpos - 1,(unsigned char *)&stack.p.data); - spin_lock_irqsave(&rad->lock,flags); - break; - } - spin_unlock_irqrestore(&rad->lock,flags); - for(;;) - { - int x; - - spin_lock_irqsave(&rad->lock,flags); - x = rad->remote_locked || (__pciradio_getcreg(rad,0xc) & 2); - if (!x) rad->remote_locked = 1; - spin_unlock_irqrestore(&rad->lock,flags); - if (x) interruptible_sleep_on_timeout(&mywait,2); - else break; - } - spin_lock_irqsave(&rad->lock,flags); - /* set UIOA for input and UIOB for output */ - byte1 = __pciradio_getcreg(rad,0xe); - mask = 1 << (chan->chanpos + 3); /* B an output */ - byte2 = byte1 & (~mask); - byte2 |= 1 << (chan->chanpos - 1); /* A in input */ - __pciradio_setcreg(rad,0xe,byte2); - byte1 = __pciradio_getcreg(rad,8); - byte2 = byte1 | mask; - byte2 |= 1 << (chan->chanpos - 1); - byte2 |= 1 << (chan->chanpos + 3); - __pciradio_setcreg(rad,8,byte2); - spin_unlock_irqrestore(&rad->lock,flags); - if (byte1 != byte2) - interruptible_sleep_on_timeout(&mywait,3); - while (jiffies < rad->lastremcmd + 10) - interruptible_sleep_on_timeout(&mywait,10); - rad->lastremcmd = jiffies; - for(;;) - { - if (!(__pciradio_getcreg(rad,0xc) & 2)) break; - interruptible_sleep_on_timeout(&mywait,2); - } - spin_lock_irqsave(&rad->lock,flags); - /* enable and address async serializer */ - __pciradio_setcreg(rad,0xf,rad->pfsave | ((chan->chanpos - 1) << 4) | 0x80); - /* copy tx buffer */ - memcpy(rad->txbuf,stack.p.buf,stack.p.index); - rad->txlen = stack.p.index; - rad->txindex = 0; - rad->rxindex = 0; - rad->srxtimer = 0; - memset(stack.p.buf,0,SERIAL_BUFLEN); - stack.p.index = 0; - if (stack.p.data) for(;;) - { - rad->rxbuf[rad->rxindex] = 0; - if ((rad->rxindex < stack.p.data) && - (rad->srxtimer < SRX_TIMEOUT) && - ((rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_SERIAL) || - (!strchr((char *)rad->rxbuf,'\r')))) - { - spin_unlock_irqrestore(&rad->lock,flags); - interruptible_sleep_on_timeout(&mywait,2); - spin_lock_irqsave(&rad->lock,flags); - continue; - } - memset(stack.p.buf,0,SERIAL_BUFLEN); - if (stack.p.data && (rad->rxindex > stack.p.data)) - rad->rxindex = stack.p.data; - if (rad->rxindex) - memcpy(stack.p.buf,rad->rxbuf,rad->rxindex); - stack.p.index = rad->rxindex; - break; - } - /* wait for done only if in SERIAL_ASCII mode */ - if (rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_SERIAL_ASCII) - { - /* wait for TX to be done if not already */ - while(rad->txlen && (rad->txindex < rad->txlen)) - { - spin_unlock_irqrestore(&rad->lock,flags); - interruptible_sleep_on_timeout(&mywait,2); - spin_lock_irqsave(&rad->lock,flags); - } - /* disable and un-address async serializer */ - __pciradio_setcreg(rad,0xf,rad->pfsave); - } - rad->remote_locked = 0; - spin_unlock_irqrestore(&rad->lock,flags); - if (rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_SERIAL_ASCII) - interruptible_sleep_on_timeout(&mywait,100); - if (copy_to_user((struct zt_radio_stat *)data,&stack.p,sizeof(struct zt_radio_param))) return -EFAULT; - return 0; - default: - spin_unlock_irqrestore(&rad->lock,flags); - return -EINVAL; - } - spin_unlock_irqrestore(&rad->lock,flags); - break; - case ZT_RADIO_GETSTAT: - spin_lock_irqsave(&rad->lock,flags); - /* start with clean object */ - memset(&stack.s,0,sizeof(struct zt_radio_stat)); - /* if we have rx */ - if (rad->gotrx[chan->chanpos - 1]) - { - stack.s.radstat |= ZT_RADSTAT_RX; - if (rad->rxcode[chan->chanpos - 1][0]) - stack.s.ctcode_rx = - dcstable[rad->rxcode[chan->chanpos - 1][0]].code | 0x8000; - else { - stack.s.ctcode_rx = - cttable_rx[rad->rxcode[chan->chanpos - 1][rad->present_code[chan->chanpos - 1]]].code; - stack.s.ctclass = - rad->rxclass[chan->chanpos - 1][rad->present_code[chan->chanpos - 1]]; - } - } - /* if we have tx */ - if (rad->gottx[chan->chanpos - 1]) - { - unsigned short x,myindex; - - stack.s.radstat |= ZT_RADSTAT_TX; - stack.s.radstat |= ZT_RADSTAT_TX; - - myindex = 0; - if ((!rad->rxcode[chan->chanpos - 1][0]) - && (rad->present_code[chan->chanpos - 1])) - myindex = rad->present_code[chan->chanpos - 1]; - x = rad->txcode[chan->chanpos - 1][myindex]; - if (x & 0x8000) - stack.s.ctcode_tx = dcstable[x & 0x7fff].code | 0x8000; - else - stack.s.ctcode_tx = cttable_tx[x].code; - - } - - if (rad->radmode[chan->chanpos - 1] & RADMODE_IGNORECOR) - stack.s.radstat |= ZT_RADSTAT_IGNCOR; - if (rad->radmode[chan->chanpos - 1] & RADMODE_IGNORECT) - stack.s.radstat |= ZT_RADSTAT_IGNCT; - if (rad->radmode[chan->chanpos - 1] & RADMODE_NOENCODE) - stack.s.radstat |= ZT_RADSTAT_NOENCODE; - if (rad->gotcor[chan->chanpos - 1]) - stack.s.radstat |= ZT_RADSTAT_RXCOR; - if (rad->gotct[chan->chanpos - 1]) - stack.s.radstat |= ZT_RADSTAT_RXCT; - spin_unlock_irqrestore(&rad->lock,flags); - if (copy_to_user((struct zt_radio_stat *)data,&stack.s,sizeof(struct zt_radio_stat))) return -EFAULT; - break; - default: - return -ENOTTY; - } - return 0; - -} - -static int pciradio_open(struct zt_chan *chan) -{ - struct pciradio *rad = chan->pvt; - if (rad->dead) - return -ENODEV; - rad->usecount++; -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#endif - return 0; -} - -static int pciradio_watchdog(struct zt_span *span, int event) -{ - printk("PCI RADIO: Restarting DMA\n"); - pciradio_restart_dma(span->pvt); - return 0; -} - -static int pciradio_close(struct zt_chan *chan) -{ - struct pciradio *rad = chan->pvt; - rad->usecount--; -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#endif - /* If we're dead, release us now */ - if (!rad->usecount && rad->dead) - pciradio_release(rad); - return 0; -} - -static int pciradio_hooksig(struct zt_chan *chan, zt_txsig_t txsig) -{ - struct pciradio *rad = chan->pvt; - - switch(txsig) { - case ZT_TXSIG_START: - case ZT_TXSIG_OFFHOOK: - rad->gottx[chan->chanpos - 1] = 1; - break; - case ZT_TXSIG_ONHOOK: - rad->gottx[chan->chanpos - 1] = 0; - break; - default: - printk("pciradio: Can't set tx state to %d\n", txsig); - break; - } - if (debug) - printk("pciradio: Setting Radio hook state to %d on chan %d\n", txsig, chan->chanpos); - return 0; -} - -static int pciradio_initialize(struct pciradio *rad) -{ - int x; - - /* Zapata stuff */ - sprintf(rad->span.name, "PCIRADIO/%d", rad->pos); - sprintf(rad->span.desc, "Board %d", rad->pos + 1); - rad->span.deflaw = ZT_LAW_MULAW; - for (x=0;xnchans;x++) { - sprintf(rad->chans[x].name, "PCIRADIO/%d/%d", rad->pos, x); - rad->chans[x].sigcap = ZT_SIG_SF | ZT_SIG_EM; - rad->chans[x].chanpos = x+1; - rad->chans[x].pvt = rad; - rad->debouncetime[x] = RAD_GOTRX_DEBOUNCE_TIME; - rad->ctcssacquiretime[x] = RAD_CTCSS_ACQUIRE_TIME; - rad->ctcsstalkofftime[x] = RAD_CTCSS_TALKOFF_TIME; - } - rad->span.chans = rad->chans; - rad->span.channels = rad->nchans; - rad->span.hooksig = pciradio_hooksig; - rad->span.open = pciradio_open; - rad->span.close = pciradio_close; - rad->span.flags = ZT_FLAG_RBS; - rad->span.ioctl = pciradio_ioctl; - rad->span.watchdog = pciradio_watchdog; - init_waitqueue_head(&rad->span.maintq); - - rad->span.pvt = rad; - if (zt_register(&rad->span, 0)) { - printk("Unable to register span with zaptel\n"); - return -1; - } - return 0; -} - -static void wait_just_a_bit(int foo) -{ - long newjiffies; - newjiffies = jiffies + foo; - while(jiffies < newjiffies); -} - -static int pciradio_hardware_init(struct pciradio *rad) -{ -unsigned char byte1,byte2; -int x; -unsigned long endjif; - - /* Signal Reset */ - outb(0x01, rad->ioaddr + RAD_CNTL); - - /* Reset PCI Interface chip and registers (and serial) */ - outb(0x06, rad->ioaddr + RAD_CNTL); - /* Setup our proper outputs */ - rad->ios = 0xfe; - outb(rad->ios, rad->ioaddr + RAD_AUXD); - - /* Set all to outputs except AUX 3 & 4, which are inputs */ - outb(0x67, rad->ioaddr + RAD_AUXC); - - /* Select alternate function for AUX0 */ - outb(0x4, rad->ioaddr + RAD_AUXFUNC); - - /* Wait 1/4 of a sec */ - wait_just_a_bit(HZ/4); - - /* attempt to load the Xilinx Chip */ - /* De-assert CS+Write */ - rad->ios |= XCS; - outb(rad->ios, rad->ioaddr + RAD_AUXD); - /* Assert PGM */ - rad->ios &= ~XPGM; - outb(rad->ios, rad->ioaddr + RAD_AUXD); - /* wait for INIT and DONE to go low */ - endjif = jiffies + 10; - while (inb(rad->ioaddr + RAD_AUXR) & (XINIT | XDONE) && (jiffies <= endjif)); - if (endjif < jiffies) { - printk("Timeout waiting for INIT and DONE to go low\n"); - return -1; - } - if (debug) printk("fwload: Init and done gone to low\n"); - /* De-assert PGM */ - rad->ios |= XPGM; - outb(rad->ios, rad->ioaddr + RAD_AUXD); - /* wait for INIT to go high (clearing done */ - endjif = jiffies + 10; - while (!(inb(rad->ioaddr + RAD_AUXR) & XINIT) && (jiffies <= endjif)); - if (endjif < jiffies) { - printk("Timeout waiting for INIT to go high\n"); - return -1; - } - if (debug) printk("fwload: Init went high (clearing done)\nNow loading...\n"); - /* Assert CS+Write */ - rad->ios &= ~XCS; - outb(rad->ios, rad->ioaddr + RAD_AUXD); - for (x = 0; x < sizeof(radfw); x++) - { - /* write the byte */ - outb(radfw[x],rad->ioaddr + RAD_REGBASE); - /* if DONE signal, we're done, exit */ - if (inb(rad->ioaddr + RAD_AUXR) & XDONE) break; - /* if INIT drops, we're screwed, exit */ - if (!(inb(rad->ioaddr + RAD_AUXR) & XINIT)) break; - } - if (debug) printk("fwload: Transferred %d bytes into chip\n",x); - /* Wait for FIFO to clear */ - endjif = jiffies + 2; - while (jiffies < endjif); /* wait */ - printk("Transfered %d bytes into chip\n",x); - /* De-assert CS+Write */ - rad->ios |= XCS; - outb(rad->ios, rad->ioaddr + RAD_AUXD); - if (debug) printk("fwload: Loading done!\n"); - /* Wait for FIFO to clear */ - endjif = jiffies + 2; - while (jiffies < endjif); /* wait */ - if (!(inb(rad->ioaddr + RAD_AUXR) & XINIT)) - { - printk("Drove Init low!! CRC Error!!!\n"); - return -1; - } - if (!(inb(rad->ioaddr + RAD_AUXR) & XDONE)) - { - printk("Did not get DONE signal. Short file maybe??\n"); - return -1; - } - wait_just_a_bit(2); - /* get the thingy started */ - outb(0,rad->ioaddr + RAD_REGBASE); - outb(0,rad->ioaddr + RAD_REGBASE); - printk("Xilinx Chip successfully loaded, configured and started!!\n"); - - wait_just_a_bit(HZ/4); - - - /* Back to normal, with automatic DMA wrap around */ - outb(0x30 | 0x01, rad->ioaddr + RAD_CNTL); - - /* Configure serial port for MSB->LSB operation */ - outb(0xc1, rad->ioaddr + RAD_SERCTL); /* DEBUG set double dlck to 0 SR */ - - rad->pasave = 0; - __pciradio_setcreg(rad,0xa,rad->pasave); - - __pciradio_setcreg(rad,0xf,rad->pfsave); - __pciradio_setcreg(rad,8,0xff); - __pciradio_setcreg(rad,0xe,0xff); - __pciradio_setcreg(rad,9,0); - rad->pfsave = 0; - - /* Delay FSC by 0 so it's properly aligned */ - outb(/* 1 */ 0, rad->ioaddr + RAD_FSCDELAY); - - /* Setup DMA Addresses */ - outl(rad->writedma, rad->ioaddr + RAD_DMAWS); /* Write start */ - outl(rad->writedma + ZT_CHUNKSIZE * 4 - 4, rad->ioaddr + RAD_DMAWI); /* Middle (interrupt) */ - outl(rad->writedma + ZT_CHUNKSIZE * 8 - 4, rad->ioaddr + RAD_DMAWE); /* End */ - - outl(rad->readdma, rad->ioaddr + RAD_DMARS); /* Read start */ - outl(rad->readdma + ZT_CHUNKSIZE * 4 - 4, rad->ioaddr + RAD_DMARI); /* Middle (interrupt) */ - outl(rad->readdma + ZT_CHUNKSIZE * 8 - 4, rad->ioaddr + RAD_DMARE); /* End */ - - /* Clear interrupts */ - outb(0xff, rad->ioaddr + RAD_INTSTAT); - - /* Wait 1/4 of a second more */ - wait_just_a_bit(HZ/4); - - for(x = 0; x < rad->nchans; x++) - { - mx828_command_wait(rad,x, MX828_GEN_RESET, &byte1, &byte2 ); - byte1 = 0x3f; - byte2 = 0x3f; - mx828_command_wait(rad,x, MX828_AUD_CTRL, &byte1, &byte2 ); - byte1 = 0; - mx828_command_wait(rad,x, MX828_SAUDIO_SETUP, &byte1, &byte2 ); - byte1 = 0; - mx828_command_wait(rad,x, MX828_SAUDIO_CTRL, &byte1, &byte2 ); - byte1 = 0xc8; /* default COR thresh is 2 */ - mx828_command_wait(rad,x, MX828_GEN_CTRL, &byte1, &byte2); - rad->corthresh[x] = 2; - } - /* Wait 1/4 of a sec */ - wait_just_a_bit(HZ/4); - - return 0; -} - -static void pciradio_enable_interrupts(struct pciradio *rad) -{ - /* Enable interrupts (we care about all of them) */ - outb(0x3f, rad->ioaddr + RAD_MASK0); - /* No external interrupts */ - outb(0x00, rad->ioaddr + RAD_MASK1); -} - -static void pciradio_restart_dma(struct pciradio *rad) -{ - /* Reset Master and serial */ - outb(0x31, rad->ioaddr + RAD_CNTL); - outb(0x01, rad->ioaddr + RAD_OPER); -} - -static void pciradio_start_dma(struct pciradio *rad) -{ - /* Reset Master and serial */ - outb(0x3f, rad->ioaddr + RAD_CNTL); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - outb(0x31, rad->ioaddr + RAD_CNTL); - outb(0x01, rad->ioaddr + RAD_OPER); -} - -static void pciradio_stop_dma(struct pciradio *rad) -{ - outb(0x00, rad->ioaddr + RAD_OPER); -} - -static void pciradio_reset_serial(struct pciradio *rad) -{ - /* Reset serial */ - outb(0x3f, rad->ioaddr + RAD_CNTL); -} - -static void pciradio_disable_interrupts(struct pciradio *rad) -{ - outb(0x00, rad->ioaddr + RAD_MASK0); - outb(0x00, rad->ioaddr + RAD_MASK1); -} - -static int __devinit pciradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int res; - struct pciradio *rad; - int x; - static int initd_ifaces=0; - - if(initd_ifaces){ - memset((void *)ifaces,0,(sizeof(struct pciradio *))*RAD_MAX_IFACES); - initd_ifaces=1; - } - for (x=0;x= RAD_MAX_IFACES) { - printk("Too many interfaces\n"); - return -EIO; - } - - if (pci_enable_device(pdev)) { - res = -EIO; - } else { - rad = kmalloc(sizeof(struct pciradio), GFP_KERNEL); - if (rad) { - int i; - - ifaces[x] = rad; - memset(rad, 0, sizeof(struct pciradio)); - spin_lock_init(&rad->lock); - rad->nchans = 4; - rad->ioaddr = pci_resource_start(pdev, 0); - rad->dev = pdev; - rad->pos = x; - for(i = 0; i < rad->nchans; i++) rad->lasttx[x] = rad->gotrx1[i] = -1; - /* Keep track of whether we need to free the region */ - if (request_region(rad->ioaddr, 0xff, "pciradio")) - rad->freeregion = 1; - - /* Allocate enough memory for two zt chunks, receive and transmit. Each sample uses - 32 bits. Allocate an extra set just for control too */ - rad->writechunk = pci_alloc_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, &rad->writedma); - if (!rad->writechunk) { - printk("pciradio: Unable to allocate DMA-able memory\n"); - if (rad->freeregion) - release_region(rad->ioaddr, 0xff); - return -ENOMEM; - } - - rad->readchunk = rad->writechunk + ZT_MAX_CHUNKSIZE * 2; /* in doublewords */ - rad->readdma = rad->writedma + ZT_MAX_CHUNKSIZE * 8; /* in bytes */ - - if (pciradio_initialize(rad)) { - printk("pciradio: Unable to intialize\n"); - /* Set Reset Low */ - x=inb(rad->ioaddr + RAD_CNTL); - outb((~0x1)&x, rad->ioaddr + RAD_CNTL); - outb(x, rad->ioaddr + RAD_CNTL); - __pciradio_setcreg(rad,8,0xff); - __pciradio_setcreg(rad,0xe,0xff); - /* Free Resources */ - free_irq(pdev->irq, rad); - if (rad->freeregion) - release_region(rad->ioaddr, 0xff); - pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma); - kfree(rad); - return -EIO; - } - - /* Enable bus mastering */ - pci_set_master(pdev); - - /* Keep track of which device we are */ - pci_set_drvdata(pdev, rad); - - if (pciradio_hardware_init(rad)) { - unsigned char x; - - /* Set Reset Low */ - x=inb(rad->ioaddr + RAD_CNTL); - outb((~0x1)&x, rad->ioaddr + RAD_CNTL); - outb(x, rad->ioaddr + RAD_CNTL); - __pciradio_setcreg(rad,8,0xff); - __pciradio_setcreg(rad,0xe,0xff); - /* Free Resources */ - free_irq(pdev->irq, rad); - if (rad->freeregion) - release_region(rad->ioaddr, 0xff); - pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma); - pci_set_drvdata(pdev, NULL); - zt_unregister(&rad->span); - kfree(rad); - return -EIO; - - } - - if (request_irq(pdev->irq, pciradio_interrupt, ZAP_IRQ_SHARED, "pciradio", rad)) { - printk("pciradio: Unable to request IRQ %d\n", pdev->irq); - if (rad->freeregion) - release_region(rad->ioaddr, 0xff); - pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma); - pci_set_drvdata(pdev, NULL); - kfree(rad); - return -EIO; - } - - /* Enable interrupts */ - pciradio_enable_interrupts(rad); - /* Initialize Write/Buffers to all blank data */ - memset((void *)rad->writechunk,0,ZT_MAX_CHUNKSIZE * 2 * 2 * 4); - - /* Start DMA */ - pciradio_start_dma(rad); - printk("Found a PCI Radio Card\n"); - res = 0; - } else - res = -ENOMEM; - } - return res; -} - -static void pciradio_release(struct pciradio *rad) -{ - zt_unregister(&rad->span); - if (rad->freeregion) - release_region(rad->ioaddr, 0xff); - kfree(rad); - printk("Freed a PCI RADIO card\n"); -} - -static void __devexit pciradio_remove_one(struct pci_dev *pdev) -{ - struct pciradio *rad = pci_get_drvdata(pdev); - if (rad) { - - /* Stop any DMA */ - pciradio_stop_dma(rad); - pciradio_reset_serial(rad); - - /* In case hardware is still there */ - pciradio_disable_interrupts(rad); - - /* Immediately free resources */ - pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma); - free_irq(pdev->irq, rad); - - /* Reset PCI chip and registers */ - outb(0x3e, rad->ioaddr + RAD_CNTL); - - /* Clear Reset Line */ - outb(0x3f, rad->ioaddr + RAD_CNTL); - - __pciradio_setcreg(rad,8,0xff); - __pciradio_setcreg(rad,0xe,0xff); - - /* Release span, possibly delayed */ - if (!rad->usecount) - pciradio_release(rad); - else - rad->dead = 1; - } -} - -static struct pci_device_id pciradio_pci_tbl[] = { - { 0xe159, 0x0001, 0xe16b, PCI_ANY_ID, 0, 0, (unsigned long)"PCIRADIO" }, - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, pciradio_pci_tbl); - -static struct pci_driver pciradio_driver = { - name: "pciradio", - probe: pciradio_init_one, -#ifdef LINUX26 - remove: __devexit_p(pciradio_remove_one), -#else - remove: pciradio_remove_one, -#endif - suspend: NULL, - resume: NULL, - id_table: pciradio_pci_tbl, -}; - -static int __init pciradio_init(void) -{ - int res; - - res = zap_pci_module(&pciradio_driver); - if (res) - return -ENODEV; - return 0; -} - -static void __exit pciradio_cleanup(void) -{ - pci_unregister_driver(&pciradio_driver); -} - -#ifdef LINUX26 -module_param(debug, int, 0600); -#else -MODULE_PARM(debug, "i"); -#endif - -MODULE_DESCRIPTION("Zapata Telephony PCI Radio Card Zaptel Driver"); -MODULE_AUTHOR("Jim Dixon "); - -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif - -module_init(pciradio_init); -module_exit(pciradio_cleanup); diff --git a/pciradio.rbt b/pciradio.rbt deleted file mode 100644 index 3cd2517..0000000 --- a/pciradio.rbt +++ /dev/null @@ -1,10531 +0,0 @@ -Xilinx ASCII Bitstream -Created by Bitstream E.33 -Design name: pciradio_xilinx.ncd -Architecture: spartan2 -Part: 2s30vq100 -Date: Sat Mar 12 18:19:05 2005 -Bits: 336768 -11111111111111111111111111111111 -10101010100110010101010101100110 -00110000000000001000000000000001 -00000000000000000000000000000111 -00110000000000010110000000000001 -00000000000000000000000000001000 -00110000000000010010000000000001 -00000000100000000011111100101101 -00110000000000001100000000000001 -00000000000000000000000000000000 -00110000000000001000000000000001 -00000000000000000000000000001001 -00110000000000000010000000000001 -00000000000000000000000000000000 -00110000000000001000000000000001 -00000000000000000000000000000001 -00110000000000000100000000000000 -01010000000000000010010001100011 -00000000000100100010000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000001000000000010010000000 -00000000000000000000000000000000 -00000000000100100010000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000010010000000 -00000000000000000000000000000000 -00010000000000100000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000010000000 -00000000000000000000000000000000 -00000000000000100000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000010000000 -00000000000000000000000000000000 -00000000000100100000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000010010000000 -00000000000000000000000000000000 -00010000000100100000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000001000000000010010000000 -00000000000000000000000000000000 -00010000000100100000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000010000000000 -00000000000000000000000000000000 -11101111000100100000000000001110 -00000000000000111000000000000001 -11100000000000000111100000000000 -00011110000000000000011110000000 -00000001111000000000000001111000 -00000000000111100000000000000101 -00000000000000010100000000000000 -01010000000111111100010000000000 -00000000000000000000000000000000 -11000000000001011111101000000001 -11101111001110000011011111110000 -00001100111100000101001100111100 -00000000111111011000000000110111 -11000100000011001101000000000011 -00110000010000001100111000000000 -00110011100000000000110101000000 -00000011001100000000000001110000 -00000000000000000000000000000000 -10000000000100001110101000000000 -11101111010000000010001011000000 -01011101111101000000001000111101 -00010000101110011000001000100011 -11010000100010101000000000000010 -00001000000000001000100010000000 -00100010100101000000100010101000 -00000011001000000000010000110000 -00000000000000000000000000000000 -10001000000001011100010000010001 -10100011001000000010011011001000 -00001000001101000000101000001101 -00000000101110010000000000100100 -11011000000010001001000000000010 -00001000000000001000000100000000 -00100010100000000001100100010000 -01000010011000100000000101110000 -00000000000000000000000000000000 -11000000000101011010000000000000 -10101011000000000010001011000100 -00011001101100000000001000101100 -00000000101110011000000000100010 -11000000000010101001000000000010 -00101000001000001000100000001000 -00100010101100000010100010110000 -10000010001100000000010001100000 -00000000000000000000000000000000 -00000000000101011110101110010000 -11101011000000100011010011101000 -00001100101100000000001100101100 -00000000111100110000000000110110 -11000000010011000001100000001011 -00100111000000001100101001000000 -00110010001000000000110110000100 -00000011010000000000010001110000 -00000000000000000000000000000000 -11100000000000011011101100000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111110 -11000000000011111100000100000011 -11111000100000001111101000100000 -00111110110000000010111101000000 -00001011111110000000000001100000 -00000000000000000000000000000000 -01000000000100001010010100000000 -11110011000001010011111011010001 -00001101001100100000001111101100 -00000000110010010001010000110110 -11000000000011001001000100000011 -00101101000000001110000101100000 -00111010000100000000110110101100 -00000011000100000000010000100000 -00000000000000000000000000000000 -11001000000001010010000000000100 -10111111000000000010111011000000 -00001000111101000000001011111101 -01000010100010011000010100101111 -11000001000010001001000000001010 -10101000000000001000101001000000 -00100000110101000000100010100000 -00000010101100100000000001000000 -00000000000000000000000000000000 -11100000000001010100100000000000 -10110011000000000010110011000000 -01001000001111010001001001001100 -00000000100000010100100000101110 -11000000100010000011110010000010 -00101000000000001010001001000001 -00101000100000000000100000000000 -00000010101110000000000001010000 -00000000000000000000000000000000 -00100000000000010001111000000000 -10110111100000000010111110100000 -00101000011110000000001011001110 -00000000100001011000000000101101 -11100000010010000010100100000010 -10011110000010001000010110000010 -00100001111000000000100001101000 -00000010100110000000000001000000 -00000000000000000000000000000000 -01001000000010000000110000000000 -11110011000000000011110011000000 -00001100001100000000001101001100 -11000000110000110000000000110100 -11000000000011000011000000000011 -00001000000100001110001100000000 -10111000100000000010110000010000 -00000011000100100000001000000000 -00000000000000000000000000000000 -01000000010011011011110000000000 -11111111000000000011110111000000 -01001110111101010000001111111100 -01000000111111110000000000110111 -11000010000011111111000000000011 -11111100010000001111110100010000 -00111111110000000000111011110001 -00000011010100000000011001100000 -00000000000000000000000000000000 -10101000000101011110100100000000 -11111011001000000011110011000000 -00011100101101000000101100101100 -10000001111110110010100000111110 -11000000001011001001000000001011 -00101100000000001100101000000001 -00110010100000000000000010010000 -00000011111010100000000001010000 -00000000000000000000000000000000 -01001000000110011001110100100000 -10110111010010010010110101000000 -00101100001101100000001000011100 -00100101101101110100000000101111 -11001100000010000100000000000010 -00001100000010001000001100000000 -10100001100000000000100000010000 -00000010100100100000010001100000 -00000000000000000000000000000000 -11000000000000001001111010000000 -10110111101000000010111111100000 -00001000011110100001001000011110 -01001000100101111010001000100101 -11101000000010000101100001100010 -00011110000000001000011110000000 -00100001101000000000101001111000 -00000010001100000000000000100000 -00000000000000000000000000000000 -01001000000001001100110000010000 -10110011000000000010111011110000 -00001000001100000000001000001100 -00000000101100110000000000101110 -11000000000010000001100000100010 -00001101001000001000001110010000 -00100010101001000010101000110010 -00000010100100100000010000110000 -00000000000000000000000000000000 -11101000000101011110100000000000 -11111010000000000011111110000000 -00011100101000000000011100101000 -00000000101110100000001000111110 -10000000000011001110101000000011 -00111000000000101100111000000001 -10110011100000000000111011100010 -00101011101110100000010001100000 -00000000000000000000000000000000 -01001000000000011010000000000000 -11111000000000010011111000001100 -01011110100000000000011111000000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11000000000000001111100000000000 -00111110001000000000010110000000 -00000011110100100000000000110000 -00000000000000000000000000000000 -00001000000100001010010000000000 -11110001000000000001001001000000 -00000100100100000010001100100101 -00011000110010010010000000111110 -01000000000011001001000000000010 -00100100000000000100100100000000 -00110010010100000000110000010000 -00000011000000100000010000110000 -00000000000000000000000000000000 -10000000000001000110111001000000 -10111001000000000010001001000000 -00001000100100000000001010100101 -00000010100010111100000100101110 -01000001010010000001110110001010 -00100100000001001000000101100000 -10101010011100000000100010010000 -00000010001000000000000000010000 -00000000000000000000000000000000 -00011000000001010010010000100000 -10111001000000000010101001000000 -00101000000100000000001000100101 -00000000100010010000011000101110 -01000001100010001001000000000010 -10100100000000001000100100000000 -00100010010000000010100010011000 -00000010000001100000000001000000 -00000000000000000000000000000000 -00001000000101001000010000000001 -10110001001010001010100001000000 -00001000000100101000001010000100 -10101000000000110000000000101100 -01001010000010001001001000000010 -10000100100000101000000100100000 -00101000110010000000100000010010 -00011000000000100000000100000000 -00000000000000000000000000000000 -10111000000011011110000000000000 -11111000001000000011101000000000 -00001100100001110000001100100001 -11000000010010000000000000011110 -00001000000011000000010100010011 -10100000000000001100100000000001 -00110000000101000000110010000000 -00000011001011100000001101010000 -00000000000000000000000000000000 -10011000000101011110010000000000 -11111001001010000011011101001011 -00101111100100000000001111100100 -00000000111110010000000000111110 -01001010001011111101000100000011 -01110100111000001011110100010000 -00011111010001000000111111010001 -00000011111001100000011001110000 -00000000000000000000000000000000 -00011000000101011110010000000001 -11111001001010000011111001000100 -00001110110100000000001100110100 -11100000110010110000000000111110 -01010000000011111001010000000011 -00100100000000001100100100000001 -00110011010100000000100011010000 -10000001001001100000000001110000 -00000000000000000000000000000000 -00111000000110000110000000000101 -10110000001000000010111000001000 -00001000100001001001001000100001 -00000010110010000000000000101110 -00101000000010111000000000000010 -10100000101010001000101000000000 -00110110000000000000100010000100 -00000010000011100000010000110000 -00000000000000000000000000000000 -00001000000001010100110000001000 -10110001001011000010111001001000 -00001010000100110000101000000100 -10010010100000010000000000101100 -01010001000010111001010000000010 -00000101000000001000000101000000 -00100000010100000011101000010000 -00000110000000100000000101110000 -00000000000000000000000000000000 -00011000010001011010010010000000 -10111001000000000000111001000000 -00000000100100000000001000100100 -00010000100010010000000000101110 -01000000000010111001010000000010 -10100100100000001000100100000000 -00100100010000000100101010010100 -00000010000001100000010001100000 -00000000000000000000000000000000 -10100000000101011110010100100000 -10111001000000010011110001111000 -01000010100100000011001100100100 -00000000110010010000010000111110 -01000000000011110001000000000011 -00100100000000101100000101000000 -00110010010000000000111010011000 -00001010001010000000010001110000 -00000000000000000000000000000000 -00101000000000001010011000100000 -11111001000001000011111001100100 -00001111000100001000011111000100 -00000000111110011100000000111110 -01000000000011111011000000000011 -11000100000010001111101100010010 -00111110010000000000110110010010 -00000011110010100000000001100000 -00000000000000000000000000000000 -00101000000100001010000100000000 -11111000000001010011101000010000 -00001111100000000000001111100000 -00000000111110000000000000110110 -00000000000011111000000000000011 -11100000000000001111100011000000 -10110010000000000000110010000000 -01000011110010100000010000100000 -00000000000000000000000000000000 -00101000000001000010100100001000 -10111010000000000010001010000000 -00001011111001000001001011111000 -00100000100110100101000000101110 -10000001000010111010100000000010 -11101000000000001011101000000000 -00100011101000000000100001100000 -00000010000010100000000001000000 -00000000000000000000000000000000 -00101000000001010100110100000001 -10110011000000001010000011000000 -00001011001111000000001011001100 -00000000101100110000000000100100 -11000000010010110010000001000010 -11001100000000001011001100000100 -00100000111000000010000100010001 -00000010100010100000000001010000 -00000000000000000000000000000000 -00100000000100010001110000000000 -10110111101000100010000111000000 -10001011011100001000001011011000 -00000000100101110000000000101101 -11000000000010110110010000000010 -11011100110000001011001100000000 -00100000110000100000100101010000 -00000010001010000000000001000000 -00000000000000000000000000000000 -00101000000010000001001001000000 -11110111100000010011000111100000 -00011111011110000000001111011110 -00000000111101001000100000110101 -11100000100011110111100000000011 -11011110101000001111011110010010 -00110001011000000000110100011000 -00000011101010100000001000000000 -00000000000000000000000000000000 -00001000000101011010000110010000 -11111011011010000011011011011010 -00011111101100000001001111101000 -00000001110110100110000000111110 -11000000000011111010010000000011 -11101100100000001111101101000000 -00111110000000000110111010010000 -00000011100000100000011001100000 -00000000000000000000000000000000 -01000000010011011111111000000000 -11001111100010000011011111100110 -00000100110110000000000100111110 -01000000110111111000000000111111 -11100000000011001110110000000011 -00111110000000001100111110000000 -00110011111000000000110011011000 -00000011000100000000000001110000 -00000000000000000000000000000000 -10101000000000011001110001000000 -11011111000000000010000111000000 -01001101010100010000001000111000 -00000000110101100000000001101101 -11000000000010000110010000000010 -00011100000010001010011100000000 -00111111110000000000100001010010 -00000010001010100000010001100000 -00000000000000000000000000000000 -00000000000000001011010000000000 -10000111000000000010010111000001 -00001001010100000000001000011100 -00001000100001010000000000101000 -11000000000010000111000000000010 -00011100000000001001011100000000 -00100001110000100000100001010000 -00000010000001100000000000100000 -00000000000000000000000000000000 -01100000000101001100010000000000 -10010011000000000010010011010100 -00001000100100000000101010001000 -00000000100100100000001000101100 -11000000000010000000010000000010 -00001110100000000011001100100000 -00101100101000000010100000011000 -00000010000110000000010000110000 -00000000000000000000000000000000 -10101000000101011010110100000000 -10001111000001000011011111010000 -00001001101000000000001100100100 -00000001110010110000000000111111 -11000000001011001000000100001011 -00111100100010101101101100100000 -00110010111000000010110010011010 -00000010001011100000010001100000 -00000000000000000000000000000000 -10000000000000001110110000100000 -11111011000000000011101011001000 -00101111101000000000001101100000 -00000000111110010000000000111110 -11000000000011111100010001000011 -11001100000000001110101100000000 -00111110110010000000111110010000 -00000011111000000000000000110000 -00000000000000000000000000000000 -00000001000100001111101000000000 -11111111000000000011111111000000 -00001100101000000000001100111110 -01000000110011001000000001111111 -11000000000011111100001000000011 -00101100000000101100111100000000 -00110011010000000000110001011000 -00000011101000000000010000110000 -00000000000000000000000000000000 -10000001010001000110101000011000 -10111011000001000010110011000000 -00001000101011011000001010101111 -10001000101010001000000000101110 -11000000000010010000110000000010 -00101100000000001000001100000000 -00100010000000000010100010011000 -00100011011000000100000000010000 -00000000000000000000000000000000 -10000000000001010010010010000000 -10111011000000000110111011000000 -00001000101000000000001000000100 -00000000100010110001000000101110 -11000000000010111000000000000010 -00101100000010001000101100000000 -00100000110000000000100010010010 -00000010101000000000000001000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110011000000000110011011000000 -00011010000100000000001010000000 -00000100101000000000000000101100 -11000000000010011000000000001010 -00001100000000011000001110000000 -00100000110000000000100000110000 -00000010010000100000000100000000 -00000000000000000000000000000000 -00000000000001010110010000000000 -11111111000000010011110111000000 -00101100101000000000001100100100 -00000000110010010000010000101110 -11000000000011110000000000000011 -00111100000000001100101100000000 -00110010110000000000110010010000 -00000011101000000000001101010000 -00000000000000000000000000000000 -10100000000101011101010000000000 -10111111000001000011111111000000 -01001101110100000000001111110100 -00000000111111000000000000111111 -11000000000011011100000000000011 -11111100000000001111011000000000 -00111111100000000000111101010000 -00000011101010000000011001110000 -00000000000000000000000000000000 -11000000000001011111010000000100 -10101111001100000011001111010000 -10001101110101000000001111111100 -01000000110011110001000000111111 -01100000000011111111000000000011 -00110110000000001111010010000000 -10110011001000000000111011011001 -00000011111100000000000001110000 -00000000000000000000000000000000 -10000000000100001110011000000000 -10001111000100000010001111010000 -00001000101100000000001011011100 -10000000100011110001010000101110 -01100000000010111111010011000010 -00100110000100001011100010000000 -00100000000010001000111000010000 -00000010111000000000010000110000 -00000000000000000000000000000000 -10001000000001011100010000000000 -10100011001000000010000011001101 -00011001000000100000001011001100 -11000000100000110010000100101100 -11000000000110110011001100000010 -10000100000000001011100000000000 -01100000000000100000101000000010 -00000010111000100000000101110000 -00000000000000000000000000000000 -11000000000101011010010000000011 -10100011000000000010001011000000 -00011000101000001000001011101100 -00000000100010110000000000101110 -11000100000010111011000000000010 -10100110000000001011100000000000 -01100010000001000000101010000001 -00000010111100000000010001100000 -00000000000000000000000000000000 -01000000000101011110011000000000 -11101011000001000011001011000000 -00001101100101000001001111101100 -00000000110010110000000000111110 -01100000000011111011000000001011 -10100100000000001111000001100001 -00110010001010000000111010011000 -00000011110100000000010001110000 -00000000000000000000000000000000 -11100000000000011011011001000100 -11011111000000000011111111000000 -00001111111101000100001111111100 -00000000111111110000000000111111 -01000000000011110111000000000011 -01110100000000001111110000000000 -00111111001000000000111111011000 -00000011111110000000000001100000 -00000000000000000000000000000000 -01000000000100001010011000001000 -11011011000000000011001011000000 -00001100100101000000001111001100 -00000000110010110000000000111110 -11000100000011111011000000000011 -11101100000001001111100001000100 -00110010001000000010110010000000 -00001011000100000000010000100000 -00000000000000000000000000000000 -11001000010001010000010000010000 -10001111000000000010001111000000 -10001010101100000010001011111100 -00000000100011110000000000101110 -11100001000010111111000000000010 -11101101000001001011100000000000 -00100010001100000100100010001000 -00000010001100100000000001000000 -00000000000000000000000000000000 -11100000000001010100010000000000 -10010011000000000010001011000000 -00001000001000000000001011001100 -00000000100000110000000000101100 -01101000000010110011000000000010 -11001100001000001011000100000000 -00100100110000100100100000111000 -01000010011110000000000001010000 -00000000000000000000000000000000 -00100000000000010001011000000000 -10010011100000000010000011100100 -00001010011010000010001011011110 -00001000100001111000000001101101 -11100001010010110111100000000010 -11011110000000001011110111000000 -10100101111000000000100001111000 -00000010010010000000000001000000 -00000000000000000000000000000000 -01001000000010000000110000000000 -11010011000000000011000011000000 -00001100000000000100001111001100 -00000000110000110000000000111100 -01000000000001110011000000000011 -11001100000000001111000100000000 -00110100110000000000110000100000 -10000011010100100000001000000000 -00000000000000000000000000000000 -01000000000111011001110001000000 -11101111010000100011111111010001 -10001110111000010000001111111100 -00000000111111110000100000111111 -11010000100011111111000000100011 -11111101000010001111110100000000 -00111011110000000000111111101000 -00000011100100000000011001100000 -00000000000000000000000000000000 -10101000000001011110111000000000 -11001011111000000011001011000100 -00001100101100000000001100101101 -10001000111110110110000000111110 -01010100000011111011110101000111 -00100101000000001111100100000000 -00110010110000000000111110110000 -00000011111010100000000001110000 -00000000000000000000000000000000 -01001000000100011001110000000000 -10001111011000101010001111000000 -10001000111100000000001000011101 -00100000101101110001000100101101 -11001000000010110111001010010110 -00010100100000001011010100000001 -00100001110000000000101101110000 -00000010110100100000010001100000 -00000000000000000000000000000000 -11000000010000001000111000010000 -10000111100000000010000111101001 -00001000010110000100001000011110 -10000000101101111010000000101101 -01100000000010110111100001001010 -00011110010000001011010110000101 -10100001111000010000101101101000 -00000010111100000000000000100000 -00000000000000000000000000000000 -01001000000101000100110000000000 -10000011000000000010000011000000 -00111000001100000000001000001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -00001110000000001011000100000000 -00100000110000000000101110100000 -00000010110100100000010000110000 -00000000000000000000000000000000 -11101000000101011010101010000010 -11001010000000000011001010000000 -00001100111001000000101100101000 -00000000111110100000000000111110 -10000000000011111010000000000011 -00101000000000001111001000000000 -00110010100000000100111110100000 -00000011111110100000010001100000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000100011111000000000 -00001111100000100000001111100000 -00000000111110000000000100111110 -00000000010011111000000001000011 -11100001010000001111100001000000 -00111110000000000000111111000000 -00000011110100100000000000110000 -00000000000000000000000000000000 -00001000000100001110011100000000 -11111001000000000011111001000000 -00000000100100000000101100100100 -00000000111100010000000000111010 -01000000000011111001000000000011 -11100110000000001111100110000000 -00110010010000000000111110011000 -00000011000000100000010000110000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000001010010111001000000 -00001000100100000000001000100100 -00000000101110010000000000100010 -11000000000010111001000000000010 -11101100000000001011100100011000 -00100010010100001000101110011100 -00000010001000000000000000010000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010110001000000 -00001010000100000000001000100100 -00000000101110010000000000100010 -01000000000010111001000000000010 -11100100010000001011100100000000 -10100011010000000100101111010010 -00000010000001100000000001000000 -00000000000000000000000000000000 -00001000000001000000010010100000 -10110001001010100010110001001011 -00101010000100100000101000000100 -10100000101100010010100000100000 -01100000000010110001001010000010 -11000100000000001001100100000000 -00100001011000000000101101011000 -00001010000000100000000100000000 -00000000000000000000000000000000 -10111000000011010110000010000000 -11111000001000000011111000001000 -00001110100000000010001100100000 -10000000111110000010000000111010 -00000000100011110000001000000011 -11101000000000001111100000000000 -00110010000101000000111111000101 -00000011001011100000001101010000 -00000000000000000000000000000000 -10011000000111011111010000010000 -11111001001010000011111001001010 -00001101110100111000001111100100 -10100000111110010010100010111110 -01000000000011111001001010000011 -11100100000000001111010100000000 -00111110010000000000111110010000 -00000011111001100000011001110000 -00000000000000000000000000000000 -00011000010011011111011000010000 -11111001010010000011001001000100 -00001101100100010100001100100100 -00100000110010010100100000110010 -01000000000011111001010010000011 -00100100000000001100010100000000 -00110011010000000000110011010100 -00000011110001100000000001110000 -00000000000000000000000000000000 -00111000000000001110000100000000 -10111000011000000010000000001000 -00001000100000100000101000100001 -10000000100010000110010000100010 -00000000000010111000010001000010 -00100000000000001000100000000000 -00100010000010000000110110000000 -00000010110011100000010000110000 -00000000000000000000000000000000 -00001000000001010100010100000000 -10110001000000000010000001010000 -00011011000101000000001000000100 -00100000100000010010000000100000 -01000000000010110001001000001010 -00101100000001001000000100000000 -01100000110000100000100100010000 -00000010110000100000000101110000 -00000000000000000000000000000000 -00011000000101011010010000001000 -10111001000000000010000001000000 -10000010100101100000001000100100 -00000000100010010000010010100010 -11001000010010111001000000000010 -00100100100000001000100100000000 -00100010010000000000100010010000 -00000010110001100000010001100000 -00000000000000000000000000000000 -10100000000101011110011000000000 -11111001000000000011001001000000 -00001111100100000000001100100100 -00000000110010010000000000110010 -01000000000011111001000000000011 -00000100000000101100100100000000 -00110010010000000010100110010010 -00000011111010000000010001110000 -00000000000000000000000000000000 -00101000000000011010011100000000 -11110001000000011011111001000000 -00001101000100000000001111000100 -00000010111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -10111110010000001000111110010000 -00000011110010100000000001100000 -00000000000000000000000000000000 -00101000000100001010000000001000 -11101000000000000011111000000000 -00001101100001000000001100100000 -00001100110010000000000000111110 -00000000000011110000000000000011 -00100000001000001111100010000000 -00110010001000000000110010000010 -00000011110010100000010000100000 -00000000000000000000000000000000 -00101000010001010010101000100000 -10001010000000100010111010000000 -00000000101000000000101000101000 -00000000100010100000010000101110 -10000000000010111010000000010010 -00101000000010001011011010001000 -00100011100000000110100011100100 -00000010110010100000000001000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10100011000000000010110011000000 -01000010001100000100001000001100 -00000010100010110000000000101100 -11000100000010110011000000000010 -00001100000000001011001000000000 -00100110110000000100100000110000 -00000010110010100000000001010000 -00000000000000000000000000000000 -10100000000000010000111000000000 -10000111000000000010110111000000 -00001010011100100000001000011100 -10000000100001110010010000101101 -01000000000010110111001000000010 -00011100000010001011111100000000 -10100101110000000000100001110000 -00000010111010000000000001000000 -00000000000000000000000000000000 -10101000000000000001111000000000 -11100111101100100011110111101010 -00101110001110110001001100111110 -10000000110001111000000000111101 -10100000010011111111101100000011 -00011110000000001111011010000000 -00110111111000000000110001111000 -00000011111010100000001000000000 -00000000000000000000000000000000 -00001000000101011010110000000000 -11111011011000000011111011110000 -00001100101100110000001111101101 -11010000111110110011110100111110 -01011000000011111011010000011011 -11101001001000001111101100000000 -00111010110000000000111110110000 -00000011110000100000011001100000 -00000000000000000000000000000000 -00000000000011011111111000000000 -11101111100110000011111111100010 -00101100111110000000001111111111 -00010000111111111000000000110111 -11110100000011001111100010000011 -11111010010000001111111110000000 -00111111111000000000111111111000 -00000011000000000000000001110000 -00000000000000000000000000000000 -10101000000000011001110001000000 -11100111000100000010111111000000 -00001000011100000000001011011100 -01000000101101110001000000100001 -11000100001010000111000000000010 -11011000000000001011011100010000 -00101101110000000000101101110000 -00000010001010100000010001100000 -00000000000000000000000000000000 -00000000000000000001110000000000 -10100111000000000110110111100000 -00001000011100000000001011011100 -00000000101101110000000000100011 -10000010000010010111000000000010 -11010100000000001011011100000000 -00101101110000000000101101110000 -00000010000000000000000000100000 -00000000000000000000000000000000 -00100000000101001100110000000001 -10100011000000100010110011000000 -00011000101110010000001011001100 -00000000101100110000000000100000 -11100000000110010011000000000010 -11000000000000001011001100000000 -00101100100000000000101110110100 -00000010000010000000010000110000 -00000000000000000000000000000000 -10101000000101011010110000000000 -11101111000000000011111111000000 -00001100111100000000001111111100 -00001000111111110000000000110110 -11100000000011011111000000000011 -11100100000000001111000100000000 -00101110110000000000111110110000 -00000011001010100000010001100000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11111011000000100011111011000000 -00001111101100000000001111101100 -00000000111100110000000000111110 -00010000000011101011000000000011 -11100100000000001111100101000000 -00111110110000000000111110111100 -00000011111000000000000000110000 -00000000000000000000000000000000 -00000001000100001101011100001000 -11001111000000000011110111000000 -00000100111100000010011100111100 -00000000111111110000000000110011 -10000000000011111111000000000011 -11111110000000001111110010000000 -00111011110000000000110011111000 -10000011000000000100010000110000 -00000000000000000000000000000000 -10000001010000000110111000000010 -10001011000000000010111011000000 -00001010101100000000001101101100 -00000000101110110000010000100010 -00010000000010111011000000000010 -11101010000001001011100111000000 -00111010111001010000100010010010 -00000010001000000100000000010000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10001011000000000010111011000000 -00001010101100000000001000101100 -00000000101110110000000000100010 -01100000000110111011000000000010 -11100000100000001011101100101000 -00101000110000000000100010110010 -00000010001000000000000001000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10000011000000000010110011000000 -00001010001100000100101000001100 -00000100101100110000000100100000 -00000000000010010011000000000010 -11000000000000001011001100000000 -00100000010000010000100000110000 -00000010000000100000000100000000 -00000000000000000000000000000000 -00000000000001010110110000000000 -11001111000000000011111111000000 -00001110111100000000001000111100 -00000000111101110000000000110010 -00000000100011111111000000000011 -11100100000000001111100100000000 -01111010110000010000110000100000 -00000011000000000000001101010000 -00000000000000000000000000000000 -10100000000101011111110000000000 -11111111000000000011111111000001 -01001111111100000000001111111100 -00000000111111110000000000111101 -00000000000011111111000000000011 -11110000000000001111110100000000 -00111011000000000000111111000000 -00000011111010000000011001110000 -00000000000000000000000000000000 -11000000000001011111110001000000 -11001110100000000011011111100000 -10001100111100100000001101111100 -00000000111111110010000000111111 -11000000000011001111000010000011 -00110000000000001100110110000000 -00110011000000000000111111000000 -00001011001100000000000001110000 -00000000000000000000000000000000 -10000000000100001111110100000000 -10001010100000000010001011001010 -00001000101111000000001000111110 -00000000101111110001000100101111 -11000110000011011111011001000010 -00100000000000001000100000000000 -00100010101000010000101110001100 -00000010001000000000010000110000 -00000000000000000000000000000000 -10001000000001011100110001000000 -10101001000000000010011011000000 -00101000001100010000001001001100 -00000000101100110000000000101100 -11000000000010000011000010001010 -00000100000000001000000000000000 -00100000010000000000101100100100 -00000010001000100000000101110000 -00000000000000000000000000000000 -11000000000101011010110000000000 -10101001001000000010001011000000 -00011000101100000100001000101100 -00000000101110110000000000101110 -11000000000010010011000000000010 -00101000000100001000000010000000 -00100010110000000000101110100000 -00000010001100000000010001100000 -00000000000000000000000000000000 -01000000000100011110110000000000 -11101001100000000011010011000110 -00001100001100000100001101101100 -00000000111110110000000000111110 -11000000000011001011000000000011 -00100101000000101100101011000000 -00110010110000000000111110010000 -00000011000100000000010001110000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11011101000001000011111111000001 -10001111101100000000001111101100 -00010000111110110000000000111111 -11000000000011111111000000000011 -11110000000000101111111000000000 -00111111110000000000111111010010 -00000011111110000000000001100000 -00000000000000000000000000000000 -01000000000100001000110000000000 -11101001000100000111101011000000 -00001101101100000000001101101100 -01100010110010110000000000110010 -11000000000011001011000000000011 -11001101100000101100101001000000 -10110010110000000000111101111010 -00000011000100000000010000100000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10000001010100000110001011000000 -00001000111101110100001101111110 -00000000100011110000000000100011 -11000000001010001111000000000011 -10101011100000001000101000000000 -10110010110101000000101110110100 -00000010001100100000000001000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10100010100000000010100011000000 -00001001001110000000001000001101 -00000000100000110000000000100010 -11000000000010000011000000000010 -01000001000000001000000010000000 -00100100000000000000101100000000 -00100010001110000000000001010000 -00000000000000000000000000000000 -00100000000000010001111000001001 -10000110100000000010001111100000 -01001001011110000000001001011110 -00000001100001111000000001100001 -11100100000110000111100100000010 -10000010000000001000010011100000 -00100001101000000000101100001000 -00000010000010000000000001000000 -00000000000000000000000000000000 -01001000000010000010110000000000 -11100001000000100010100011000000 -00001101001100000000001000001100 -00000000110000110000000010110010 -11000000000011000011000000000011 -11000101000000001100100001001000 -00110100010000000000111100100000 -00001011000100100000001000000000 -00000000000000000000000000000000 -01000000000111011011111000100000 -11110101000000000011110111000000 -00001110111100001000001111111100 -00000000111111110000000000111111 -11000000000011111111000011000011 -11111100000000001111110000100000 -00111111110000000000111111100000 -00000011110100000000011001100000 -00000000000000000000000000000000 -10101000000001011110111000000000 -11000011100000000011011010000000 -00101100101100000000001111101100 -10000000111110110100000000110010 -11001010000011001011101000001011 -00100100000000001100100000000000 -00110010110000000010110010010100 -10000011111010100000000001110000 -00000000000000000000000000000000 -01001000000100011011110010001000 -10000111000000001010001111000000 -00001000011100100001001011011100 -11000000101100110000100000110101 -11000000000010000111001010000010 -00010100010000101000011000000000 -00100001110000000000100001110000 -00000010110100100000010001100000 -00000000000000000000000000000000 -11000000000000001001111000001001 -10000101100000000010000111100000 -00001000011110000000001011011110 -11000000101101111001000000100001 -11100100000010010011101000000010 -00011110000000001000011010000000 -00100000111000000000101001011000 -00000010111100000000000000100000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10000001111000000010000001110000 -00011000001100000000001011001100 -00001000101100110000000000100100 -11000000001010010011000000000010 -00001100000000001000001011100000 -10100000110100000000101000110101 -00000010110100100000010000110000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11001110110000000011001110000000 -00001100101000000000001111001000 -00000000111110100000000000110010 -10000000000011011010000000000011 -00101001000000001100111011001000 -00110011101000000000111000101000 -00000011111110100000010001100000 -00000000000000000000000000000000 -01001000000000001110000000000010 -11111000000100000011101000001100 -00001111100000000000001111100001 -00000000111110000000001000111100 -00000000000011101000000000000011 -11100000100000001111100001000000 -00111110000011000000010110000000 -10010011110100100000000000110000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000100000011111001000000 -00101100000100000000001100100110 -00000000110010010000000000110010 -01000000000011001001000000000011 -11101111000000001110100100000100 -00110000010000000000110010110000 -00000011000000100000010000110000 -00000000000000000000000000000000 -10000000000001000111010000000000 -10111001010000000010111001000000 -00001000100100000000101000100101 -00000000110110010000000000101010 -01000000010010101001000000000010 -11000101000010001000000100100100 -00110110010000000110100010010000 -00000010001000000000000000010000 -00000000000000000000000000000000 -00011000000000010010010000000000 -10111001000010000010110001000000 -00001000100100001000001000100100 -01000000100000010000000000100010 -01000000010010001001000001000010 -11100101000000001010100110000000 -00100010010000000010100010010000 -00000010000001100000000001000000 -00000000000000000000000000000000 -00001000000001000000010010000000 -10110001000000000110110001000000 -01001000000100100000001000000100 -10000100100100010010100000101000 -01001010000110100001001011000010 -11000100100000001000100100000000 -00100100010010000000100000010010 -00010010000000100000000100000000 -00000000000000000000000000000000 -10111000000011010110000101000000 -11111000000000000011111000010100 -00001100100000000000001000101000 -00000000110010000111000100110000 -00001001000011001000001000010011 -11100001010000001110000001010000 -00110010000000000000110010000000 -00001011001011100000001101010000 -00000000000000000000000000000000 -10011000000111011110010100000000 -11111101000000000011111101000000 -00001111100100010000001111100100 -01000000111110010000000000111110 -01001010000011111001001010000011 -11000100010000001111111100000000 -00111111010001000000111110010001 -00000011111001100000011001110000 -00000000000000000000000000000000 -00011000000001011110010100100000 -11110101000000000011101001010000 -00001100110100101000001111110100 -00100000111110010000000000110010 -01000010000011001001000000000011 -00001101001000001100010100000000 -00110010010000100000110010010000 -10000011110001100000000001110000 -00000000000000000000000000000000 -00111000000100001110000110000000 -10111000000000000010001000000001 -00101000100001000000001110100001 -00000000101110000101000000100010 -00111010000011011000000000001010 -00100001000000101000100000100000 -00100010000100010010100011000100 -00000010110011100000010000110000 -00000000000000000000000000000000 -00001000000001011100010000000000 -10110001000000000010101001001000 -00001000000100000000001011000100 -00000000101100010010100010100000 -01000000000010000001011010100110 -00000100000001001000000100001000 -01100001011000000000100001010000 -00000010110000100000000101110000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10111011000000000010001001000010 -00001000100100000100001011100100 -00000000101110010000000000100000 -01000000000110011001000000000110 -00000101000000001000000100000101 -00100010010000000010100011010000 -00000010110001100000010001100000 -00000000000000000000000000000000 -10100000000101011110010000001000 -11110001010010000011100001110000 -00001100100100000000001111100100 -00000000111110010000000000110010 -01000000000011001001000000000011 -00100110000000001100100110000000 -00110010010100000000110010010000 -00000011111010000000010001110000 -00000000000000000000000000000000 -00101000000000011010010000000000 -11111001110010000011111001101000 -01001111100100000000001110100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11101100100000101111100111000000 -10111110010000000000111110011010 -10000011110010100000000001100000 -00000000000000000000000000000000 -00101000000100001010000000010000 -11111000010000100011001000010000 -00001101100000000000011111100000 -01010000110010000000010000111110 -00000001010011001000000000010011 -11100001000000001110100010000000 -00110000000000000000110011000000 -01000011000010100000010000100000 -00000000000000000000000000000000 -00101000000001010010100000000000 -10111110010000000010001010000001 -00001000111011000100001011111001 -00000000100010100000000000101110 -10000000001010001010000000010010 -11101000000000001000111010100000 -00111010100000010000100010100000 -00000010000010100000000001000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110011000100000010000011000000 -00001001000111011001001011001101 -00101000101010110000000001101100 -11000000000010011011000000100010 -11001101100000001010001110000000 -00100100111000000000100000100000 -00000010000010100000000001010000 -00000000000000000000000000000000 -10100000000000010001110011000000 -10111111000000000010001111001000 -01101000010100000100001011011110 -00000000101001110010000000101101 -11000100101110010111000000000010 -11010000000000001000111100000000 -00101001100100000000100001101000 -00000010001010000000000001000000 -00000000000000000000000000000000 -10101000000010000001111010000000 -11110111100000001011000111110000 -00001101010010000000001011001110 -00000010111001111110000000111111 -11101000000011010111110010100001 -11011010000000001110011110000000 -00110100111000000010110000101000 -00001011001010100000001000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111011000000100011110011000010 -00001111100000000000001111101100 -00000000110110110100001000111110 -11010000010011101011011000000011 -11101000001000001111101100000000 -00111110100000000000111110100000 -00000011110000100000011001100000 -00000000000000000000000000000000 -00000000000001011111111000000000 -11111111100000000011001111100000 -00001100110110000000001111111110 -00000100111111111100000000111111 -11110000000011101111100100011011 -00111110000000001100110010100000 -00110011011000000000110011111000 -00000011110000000000000001110000 -00000000000000000000000000000000 -10101000000100011001110001000000 -11110111001000000011010111001000 -00001000010100010000001111011100 -00000000111101110000000000111101 -11001000000010000111000000000010 -00010000001000101000011100100000 -00100001000000000000100001110000 -00000010111010100000010001100000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110111000001000010000111000000 -00001000010100000000001011011100 -01000000101101110000000000101101 -11000000010010000011000000000110 -00011100010000001000011100110100 -00100001010000000000101001111000 -10000010110000000000000000100000 -00000000000000000000000000000000 -00100000000101001100110000000000 -10100011000000000010011011010100 -00000000000100000000001010001000 -00000000101000110000000000101000 -11000000001110000011000000000010 -00001011001000001000101110000000 -00100000000000000000101000111000 -00000010110010000000010000110000 -00000000000000000000000000000000 -10101000000101011011110000000000 -10111010000000000011001111010000 -00101100001100000000001011100100 -00000000101111110000000000101111 -11000000000010001111000000000011 -00101111000000101000101101100000 -00110010111000000100111010001000 -00000011111010100000010001100000 -00000000000000000000000000000000 -10000000000000001110110000010000 -11111011000000000011111011001000 -00001111100001000001001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11100100000001001111101100100000 -00111100101000000100100110000000 -00000001111000000000000000110000 -00000000000000000000000000000000 -00000001000100001111110000000000 -11111111100000000011001111000000 -00001100111010100000101100011100 -00000000110011110000000000111101 -11000000000011001111000000000011 -11111000000000101100111100000101 -00010010110000000100110011000000 -00000011110000000100010000110000 -00000000000000000000000000000000 -10000001000001000110110000010000 -10110011000000000010001011000000 -00101000100000100000001000101111 -00000000100010110000000100101110 -11000000000010001011000000010010 -11101001001000001000101100000000 -00100010100000000110100010001001 -00000010111000000100000000010000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000100000010001011000000 -10001000101100000000001000101111 -00000000100010110000000000101110 -11000000000010001011000000000010 -11001100000000001000100010000000 -00101010010000000000100010010000 -00000010111000000000000001000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10110011000000000010000011000001 -00001000001000000000001000001100 -00000000100000110000000000101100 -11000000000010000011000000000010 -11000100000000001000000110000000 -00101000000000000000100000010000 -00000010110000100000000100000000 -00000000000000000000000000000000 -00000000000011010110110000000000 -11111001000000000011000111000000 -00001100101100000000001100101100 -00000010110011110000000000111101 -11000000000111001111000000000011 -11001100000011011100001000000100 -00111010010000000000110010010000 -00000011110000000000001101010000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11110111000000001011111111000000 -00001111111000000000001111111100 -00000100111111110000000100111111 -11000000000011111111000000000011 -11111100000000011111111100000000 -00110111000000000000111111010000 -00000011111010000000011001110000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11101101100000000011111100000100 -00001110111100000000001101110110 -00000100111111110110000000110011 -11001100100011001110000100100011 -10110000010100001100110000000000 -10110011000001000100110011010001 -01000011001100000000000001110000 -00000000000000000000000000000000 -10000000000100001100110000000000 -10001001100001000010110011001000 -00001100101111000000001000100110 -00010000101111110001000000100011 -11001100000010000010000000000111 -10100000100000001000100000000000 -00110010100010000000100010010010 -00000010001000000000010000110000 -00000000000000000000000000000000 -10001000000001011110111000000010 -10100011000000000010110011001001 -00001010001100010000001000000100 -00000000101100110010000000100000 -11000000000010010011001000100010 -10000000100000001000000000000000 -00100100000010010000100000010010 -00000010011000100000000101110000 -00000000000000000000000000000000 -11000000000101011010111000000000 -10101011000000000010111000100000 -00001001101000000000000000100100 -00000000101110110000000000000000 -11000000000010011011000000000010 -10100000000000001000100000000000 -00100010100000000000100010010000 -00000010011100000000010001100000 -00000000000000000000000000000000 -01000000000101011100110000000000 -11101001000000000011111001100000 -00001110100101000000101101101110 -00000000111110110000000010110010 -11000000000011011010000000000011 -10100011000000001100100100010000 -10110110010000000010110010100000 -00001011010100000000010001110000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11011111000010000011110111000000 -00001110111101000100001111111110 -10000000111101110000000100111111 -11000000001011101110000000000011 -11010010010001101111100110000000 -10111111110000000000111101100000 -00000011101110000000000001100000 -00000000000000000000000000000000 -01000000000100001010111000000000 -11101001000000010011111011000000 -01001110001000001000101101101100 -00000000111110110001000010110010 -11000000000011001011000000000011 -00100001000000101100000100001000 -00110000010000000000110010101010 -00000011000100000000010000100000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10001011000000010000111001000000 -00001000101000000000001000101100 -00000000101111110101000000100011 -11000000000010001011000000000010 -00100000000000001000100101100010 -00100010110000010000100010100100 -00000010001100100000000001000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10000001000000000010110011000000 -00001010000110000000001010000111 -10010000101100110000010000101000 -11000000000010000010000000100010 -00001100000000001000001000000000 -10100000000000000000100000010000 -01000010001110000000000001010000 -00000000000000000000000000000000 -00100000000000010001111000000000 -10000101100000000010110111100100 -00001000001010000100101010010110 -00100000101100111000000000101001 -11100000101010000110100000000010 -00001110000000001000011010000000 -00100000101000000010100001011000 -00000010000010000000000001000000 -00000000000000000000000000000000 -01001000000010000000110000000000 -11100011000001000011110011010000 -01001110001100101000101110001100 -10000000111100110010000000111010 -11000000010001000011000100000111 -00001101100001001100001000100000 -01110000000000000000110010010010 -00001011000100100000001000000000 -00000000000000000000000000000000 -01000000000111011011110000000000 -11111111000000000011111111000000 -10001111111000000000001100111100 -00000000111111110000000000110111 -11000000000011111111000000000011 -11111100000000001111111000000000 -10111111100000000000111111011000 -00000011110100000000011001100000 -00000000000000000000000000000000 -10101000000001011100010000000000 -11001001011000000011111010000000 -00001101000000100000001101100110 -11100000110010110010100010111010 -11100000000011001010000000000011 -11101100000000001100101100000000 -00110110010000000100110010100000 -01000011001010100000000001110000 -00000000000000000000000000000000 -01001000000100011001110000000000 -11010111001010010010111111000000 -00000101011000010000101000010100 -00000000100011110000000010100000 -11011100000010000110000000000010 -11011100000001001010011100000000 -10100001110000000100100001100000 -00000010000100100000010001100000 -00000000000000000000000000000000 -11000000000000001011101000000000 -10000101110100000010110111100000 -00001001011010000000001001111110 -10000010100001111001000000101001 -11101001100010000111100000000010 -10001110000000001010001110000000 -00100001011000000000100001101000 -00000010001100000000000000100000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10010011000000010010110010000000 -00001001001011000000001000001110 -00000000100010110000001010100000 -11000000001010000011000001100010 -11001100000000001010001100000100 -00100000110000000110100000100111 -00001010000100100000010000110000 -00000000000000000000000000000000 -11101000000101011011100000000000 -11001010000000000011111110010000 -00001101101000011000001101101010 -00000000110010100000000010111010 -10000000000011001010000000100011 -10101000000000101110101001000000 -00110010100100000000110011101100 -00001011001110100000010001100000 -00000000000000000000000000000000 -01001000000000001110001100000000 -11111000000000000011111000000010 -00001111000000000000001111100001 -01010000111110000000000000111110 -00000000000011110000000001000011 -11100000000000001011000000001000 -00111110000000100000111101000000 -00000011110100100000000000110000 -00000000000000000000000000000000 -00001000000100001110010000000010 -11101001001000000011000001000000 -00001100101100000000001100100100 -00000100111110010000000010110010 -01000000000011111001000000000011 -00100100000000001000100100000100 -00110010010000000010110010010000 -00001011000000100000010000110000 -00000000000000000000000000000000 -10000000000001000110010100100000 -10000011111000000010001001000000 -00001000100100110000001000101100 -00000000101110010000000010100010 -01000000000010111001000000000010 -00100100000000001000100100000000 -00100010010100000000100010010100 -00000010001000000000000000010000 -00000000000000000000000000000000 -00011000000001010000011000000000 -10101001000000000010001001000000 -01101000101100000100101000100100 -00000000101110010100000000100010 -01000000100010111001000000000010 -00010100000000001010110100000000 -00100001010000100100100011010000 -11000010000001100000000001000000 -00000000000000000000000000000000 -00001000000001000000010000000010 -10001001000000000010000001001000 -00001000000100100000001000000100 -00000000101100010010100010100000 -01001011000010110001001000001010 -00010100100000101010010100100000 -00100001010010000000100001010010 -00000010000000100000000100000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11101000000000000011001000000000 -00001100100000000000001100101000 -00000000111110000111000010110010 -00001000000011111000100000000011 -00100010000000001110100011010000 -00110000001101000000110001001101 -00001011001011100000001101010000 -00000000000000000000000000000000 -10011000000111011111010010100000 -11111001000000001011111101001110 -01001111100100010000001111000100 -00000000111110010000000010011110 -01001010000011111001001110000011 -11100100111000001101100100010000 -10111110010001000100111110010001 -00000011111001100000011001110000 -00000000000000000000000000000000 -00011000000000011110110100000000 -11001001000000000011111001010000 -00001110110100000000001110100100 -00000000111111010001001010110010 -01001010100010111001000000000011 -00100101000000101100110101000100 -00110010010000000000110010010010 -00001011000001100000000001110000 -00000000000000000000000000000000 -00111000000100001100001000000100 -10001000000000010010111000010100 -00001000100001000000001000100000 -00000100101110000100000010101010 -00011000000010111000010000000010 -00100001010000001000000001000001 -00100010000100000000100011000110 -10000010000011100000010000110000 -00000000000000000000000000000000 -00001000000001011100010010000000 -10000001000000010010110001001000 -00001010000101000000001010000100 -00000000101100010110000010100000 -01000011000010110001011010000010 -00000100100001001010000101100100 -00100001010110100000100101010001 -00000010000000100000000101110000 -00000000000000000000000000000000 -00011000000101011000010101000010 -10001001000000100010111001001000 -01001000100100001000001000100100 -00000100101100010000000010001010 -01000001010010111001010000001010 -00100100000000001010100100000001 -00100010010000000000100111010000 -00000010000001100000010001100000 -00000000000000000000000000000000 -10100000000101011110011000000000 -11001001000000000011111001101000 -00001110100110000000001110100110 -00000100111110010000000010010010 -01000000000001111001000000000010 -00100100000000001110100100000000 -10110010010000000000100110010000 -00000011001010000000010001110000 -00000000000000000000000000000000 -00101000000000011010111000000000 -11111001100101000011110001100000 -00001111100101000000001111100100 -10010100111110010000000000111110 -01000000000011111001000000000011 -11100100000000101101100100001000 -00111100010000000010111000010000 -00000011110010100000000001100000 -00000000000000000000000000000000 -00101000000100001010000000000010 -11001000100000000011111000000000 -10001100000001001000101110100010 -00000000111110000000000010110010 -00000000000011110000000000000011 -00000000000100001100100000000000 -10110010000000000000110011000000 -00000011000010100000010000100000 -00000000000000000000000000000000 -00101000000001010010100001000000 -10001010101000000010111010000000 -00001000111000000000001000101000 -00100000101111101100000010110110 -10000000000010111010000000001010 -00101000000000000000111001001000 -00100010100000010000100011100000 -00000010100010100000000001000000 -00000000000000000000000000000000 -00101000000001010100100100000010 -10000011100000000010110011000000 -10011000001100010000001010001100 -00000000101100010110000000101000 -11000001000010110011000000000010 -00001100000000101000101110000000 -10100000111000000010100000101000 -00000010000010100000000001010000 -00000000000000000000000000000000 -10100000000000010001100100000000 -10000111000000000010110011000000 -00111000011100000000001000011100 -00000000101101000000100010101101 -11000000000010110111000000000010 -00001100000000001000010100000000 -00100001110100000000100001100100 -00000010001010000000000001000000 -00000000000000000000000000000000 -10101000000010000001111000000010 -11000111100010000011110111100100 -00001100011010000000001110011110 -00000100111111011000000010111001 -11100100010011111111101010000111 -00011110001000001100011110000010 -00110011101000000010110011111000 -00001011001010100000001000000000 -00000000000000000000000000000000 -00001000000111011010110110110000 -11111010010000000011111011100100 -10001011001100000000001111101000 -10100000111110000000000000110110 -11000100000011111011010100100011 -11101101110000001111100100000100 -10111110100000000000111110110000 -00000011110000100000011001100000 -00000000000000000000000000000000 -00000000000001011111001000000000 -11001110100000000011111111100001 -00001111111110000000101110111010 -00000000111111111000000000111011 -11100000000011111111100000000111 -00111110010000001100111010000000 -00110011011000000100110011001000 -01000011000000000000000001110000 -00000000000000000000000000000000 -10101000000100011001000001000010 -10000110000100000010110111000000 -00001011011100101000001000010100 -01000000101101100000000000100001 -11000000010011100111000000000010 -00111100110000001000111100010000 -00100001010001000100100001000001 -10001010001010100000010001100000 -00000000000000000000000000000000 -00000000000000001001010000100010 -10000101000000000010110111100010 -00001011001100000000001011011000 -00000000101101110000000000101101 -11000000000010110011000000001010 -00011100000000001000011000000000 -00100000000000000010100000011000 -00001010000000000000000000100000 -00000000000000000000000000000000 -00100000000101001100110000000000 -10000000000001000010110011110010 -00001011001101000000001001000000 -00000100101100110000001010100100 -11000000000010100011000000000010 -00001100000000011000101100000000 -00100000001001000000100000010100 -00000010000010000000010000110000 -00000000000000000000000000000000 -10101000000101011000110000000000 -11001001000000000011111111100000 -00001111101100000000001111100100 -00000000111110000000000000111111 -11000000010011111111000000100011 -00111100000000001100101100000000 -00110010110000000000110010101101 -00000011001010100000010001100000 -00000000000000000000000000000000 -10000000000000001110110100000000 -11111001100000000011111011000001 -00001111101101000000001110101100 -00010000111110110100000000111010 -11000000000111111011000000000011 -11101100000000001111100000000000 -00111110110000000000111110100000 -00000011111000000000000000110000 -00000000000000000000000000000000 -00000001000100001111111000100000 -11011111010000000011111111000000 -00011111111100011000001101110100 -00000000111111000001000010110001 -11000000000001001111000000100011 -11011100000000001000111100000000 -00110001100000000010110001110000 -00001011000000000100010000110000 -00000000000000000000000000000000 -10000001000001000110111101100000 -10001010100000000010111011000000 -10001011001101000000001000101000 -00000100101110110100000010110110 -11000001000010101011000000000010 -11101100000100001101100011001010 -00100010100000010000101010110000 -00000010001000000100000000010000 -00000000000000000000000000000000 -10000000000001010010100000000000 -10011000000000000010111011000000 -00011011101100001000001001100010 -00001000101100100000100010100010 -11000000010010101011000001000010 -11101100000000001010100000100000 -00100010010000000000100010000000 -00000010001000000000000001000000 -00000000000000000000000000000000 -00001000000001000010100000000000 -10000000000000000010110011000000 -00001011001100000000011000000100 -00000000101100110000000001100100 -11000000000010100011000000000010 -11001100000000001011000000000000 -00000000010000000010100000000000 -00000010000000100000000100000000 -00000000000000000000000000000000 -00000000000011010100100000000000 -11011001000000000011111111000001 -00001011101100000000101101100000 -00000100111100110000000010110011 -11000000000011101111000000000011 -11111100000010001110100000000000 -10110010000000000100110010010000 -00000011000000000000001101010000 -00000000000000000000000000000000 -10100000000110011111100000000000 -11111100000000000011111111000000 -00001111110100000000101111110000 -00000000111111110000000000111111 -11000000000011011111000000000011 -11111100000000001101110000000000 -00111111000000000000111111010000 -00000011111010000000011001110000 -00000000000000000000000000000000 -11000000000001011111110001000000 -11011111000000000011001111000000 -00011110111100100000001100111100 -00000000110011110010000000110011 -00001010000011111101100000000011 -11110100000000001101111000000010 -00110011110000000000111101101000 -00000011011100000000000001110000 -00000000000000000000000000000000 -10000000000110001110110010000000 -10001011001100000011001111011010 -00001101111101000010001000111101 -11101000100011110110100000100010 -00011011000010111001000000000010 -11110110000000001000100010000100 -00110010111000000000100110110000 -00000010001100000000010000110000 -00000000000000000000000000000000 -10001000010001011000110000000100 -10010011000010000010000011010000 -00001000001100010001001010001100 -00000010100000110001000000100000 -00000000000010110001000000000110 -11001100000000001011000000000000 -00101000111000000000101100010000 -00000010001100100000000101110000 -00000000000000000000000000000000 -11000000000001011100110000000000 -10000011000000000010001011000000 -00001001101100000000001010001100 -00000000100010110000000000100010 -00100000000010111010100000000010 -11100110000000001010100010000001 -00101010100000000000100100011000 -00000010001100000000010001100000 -00000000000000000000000000000000 -01000000000101011110110000000000 -11011011000000011011001011000000 -00001100101100000000101110101100 -00000001110010110000000010010010 -00110000000010111001100000010111 -11100110100000001111101010000000 -00101010110000001000111110111000 -00001011010100000000010001110000 -00000000000000000000000000000000 -11100000000000011010110000000000 -11111011000000000011101011000000 -00001111111100000000001101111100 -00000100111111110000000000111110 -11000000000011111101000000000011 -11110100000000001101101100000000 -00110011110000100000111111110000 -00000011111110000000000001100000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11101011000000010011010011000000 -01001100001100000001001111101100 -00010000110010110000000000110110 -01000000000011011011000010000011 -10001100000000001101100011000000 -00110010110000001000110010010010 -00000011000101010000010000100000 -00000000000000000000000000000000 -11001000000001010011110000001000 -10001111000000000010001111000000 -01001010111101000000001011111100 -00000011101011110000000010100010 -11000000000010001011110011000010 -10101100000000000000000100000000 -00010110111100000010110010010100 -00000010001100100000000001000000 -00000000000000000000000000000000 -11000000000001000100110000000000 -10100011000000000010010011000000 -01001001001110011000000011001100 -00000000100010110000000001101100 -00000000000110010011100000000010 -01001100000000010001001000000001 -01100000111101000000100100000100 -00010010001110000000000001010000 -00000000000000000000000000000000 -00100000000100000101111000000000 -10000111100000000010000111100000 -01001010011110000000001011011110 -01000000101000111001000001101001 -01100100010110000111100000000010 -11010110000000101000010010010000 -00100100111000000000100001011000 -00010110001011000000000001000000 -00000000000000000000000000000000 -01001000000010000100110000000000 -11100011000000000011010011000000 -00001101001100100000001011101100 -00000000100000110000000000111100 -11010000000011011011000000000011 -11001000000000001101001001000000 -00110000110001000000110100010000 -00001011000100100000001000000000 -00000000000000000000000000000000 -01000000000101011011110000000000 -11111111000000000011111111010100 -00001111111100000000001111111101 -00100010111111110000000000110111 -11000000010011111110000000000010 -10010100000000001111110000000100 -00111011110001000000111111010001 -00000011110100000000011001100000 -00000000000000000000000000000000 -00001000000001011110110001000000 -11111011000000000011111011010100 -00001110101111001000001100101101 -00000000110010110111001000111010 -00000000000011101011100000000011 -00101100000000001101101000000000 -10110010110010100000111100111000 -00100011001010100000000001110000 -00000000000000000000000000000000 -01001000000110010001110010000100 -10110111001000000010110111000000 -00000011011101000100001010001100 -10000000110101110011000000100001 -11000000000010001111000000010010 -00011100010000001010011000000000 -00100001110000001000101101110000 -00000010001100100000010001100000 -00000000000000000000000000000000 -00100000000000000001111000000000 -10110111100100000010110111101000 -00001010001110100000001000011110 -00000000100000111000000000101001 -01100000000110100111100000000010 -00001110000000001000001010000000 -01100001111000000000101111011000 -00000010001000000000000000100000 -00000000000000000000000000000000 -01101000000001001100110000000000 -10111011000000000010111011000000 -00001011001100000000001010001100 -00000000100100110000000000101000 -11000000000010000011001100001010 -00001110000000001010001110100000 -00100000110000101000101100010101 -10000010000100100000010000110000 -00000000000000000000000000000000 -11101000000101011110100000000000 -11111010000000000011111010000000 -00001110101000000000101100101000 -00000000110010100000000000111011 -10001000000011101110000000000011 -00111011100000001100111010100000 -00110010100100001000111111101100 -00001011001110100000010001100000 -00000000000000000000000000000000 -01001000000000011010000000000000 -11111000000000000011111000000000 -01001111100000000000001111100000 -00000000111100000000000000010110 -00100000100011111000000000000011 -11100000001000001110100000000001 -00111110000000000100111110000000 -00000011110100100000000000110000 -00000000000000000000000000000000 -00001000000100001000010000000010 -11001001000000000001001001000000 -01000110100110000000001111100100 -00000000110010010000000000110100 -01000000000011001001000000000011 -11000100000000001000000100000000 -00100010110000001000111110010000 -00000011110000100000010000110000 -00000000000000000000000000000000 -10000000000001000110010000000100 -10001001000000000010001001000000 -00101000100110010000001011100100 -00000010100010010000000010100010 -01000000000010101001010000000010 -11100100000000001000100100000000 -00100010010000000000101110010100 -00000010111000000000000000010000 -00000000000000000000000000000000 -00111000000001010010010000000000 -10001001000000001010101001000000 -00001000100100000000001011000100 -00000000100010010000000000100110 -01000000000010001001000010000010 -11100100000000001010100100000000 -00101010010000000000101110010100 -00000010110001100000000001000000 -00000000000000000000000000000000 -00101000000101000000010010000000 -10000001001010000010100001001001 -00001000000100100000001011000100 -10110000100000010010100000100000 -01001000010010100001000000000010 -11000100100000011010000110100000 -00101000010010010000101100010000 -00000010110000100000000100000000 -00000000000000000000000000000000 -10111000000011000110000000000000 -11001000011100100011101000010100 -00001100100001010000001111100000 -10000000110010000010000000110100 -00000000100011001000010100000011 -11100000000000101110100000000000 -10111010000000000000111110000101 -00000011111011100000001101010000 -00000000000000000000000000000000 -10011000000001011010010011110000 -01111001000000000011011001000100 -00001101100100010000001111100100 -10110000111110010010100000111111 -01001110000011111101000000000011 -11110100010000001101110100010001 -00110110010001001000111111010000 -00000011111001100000011001110000 -00000000000000000000000000000000 -00011000000001011110010100001000 -11111001010000000011111001000000 -00001100110101000000001100100100 -00100000110010011000000000110010 -01001000000011111101010000000011 -00010100000000101100000100000000 -00110010010000101000111100010000 -00100011110001100000000101100000 -00000000000000000000000000000000 -00111000000110001110000100001000 -10111000010000000010111000011110 -00001000100001000000001010000011 -10001000110110001111100000100010 -10011001000010110000001000010011 -01100001000000001000100001000000 -00100011100100000000101110000000 -00000010110011100000010000110000 -00000000000000000000000000000000 -01001000010001011000010110000100 -10110001011001000010110001000000 -00101000000101100000001000000100 -00100000100000010000000000100000 -01010010100010110001000000000110 -00000101000000001000010111000010 -10100001010000000000101100011010 -10000010110100100000000100110000 -00000000000000000000000000000000 -00011000000001001010010000001000 -10111001000000000000110001000000 -00000000100100000000001010100100 -00000000100100010000000000100010 -01000000000010110001011000000110 -01100110001000101000110100000000 -00100111010000000000101110010010 -00000010110001100000010001100000 -00000000000000000000000000000000 -10100000000101011110010000000000 -11111001000000010011111001000000 -01000000100100000001001100100100 -00000000110010010000000010110010 -01010000000011111001010000100011 -00100100000000001100100100000010 -00110010010000000000111110011000 -00000011111010000000010001110000 -00000000000000000000000000000000 -01001000000000010010010000000100 -11111001000000000011111001000000 -00001111100100000010001111000100 -00001000111110010000000100111110 -01100100000011111001000000000011 -11000100000000001111000101000100 -00111010010000010000111110110000 -10000011110110100000000001100000 -00000000000000000000000000000000 -00001000000100001010000000000000 -11101000000001000011001000000000 -00001101000000010000001111100000 -00010000110010000000000000110110 -00010000001011001000000000000011 -00100000000000001100100000000000 -00110011000100000100111110000000 -01000011000010100000010000100000 -00000000000000000000000000000000 -00101000000001010010100000000001 -10001010000000000010001010000000 -00001001111000000000001011101000 -00000010100010100000010010100010 -10000000000011011110000000000010 -10101000000000101000101000000000 -00100010100000000100101110100000 -00000010000010100000000001000000 -00000000000000000000000000000000 -00101000000001010100110000000100 -10100011000000100010100011000000 -00001001001110001000001011001100 -00000000100000110000000010100100 -11000000000010000011000000000010 -01000100000000011000001100000000 -10100000100000000000101100110000 -00000010000010100000000001010000 -00000000000000000000000000000000 -10000000000100010001111000000000 -10000111101000000010100111001000 -00011001011000000000001011011100 -10000000100000110001000000100001 -11100100000010000101000000010010 -11010100000000001000010100000000 -00100001100000010000101111111000 -00100010001010000000000001000000 -00000000000000000000000000000000 -10001000000010001011111001000000 -10101111110000000011100111110001 -00001101011110000000001111011111 -00100000110001111010100000110111 -11101000000010000110100000000011 -01010110000000001100011010000000 -00110001101000000000111101111000 -00000011001010100000001000000000 -00000000000000000000000000000000 -00001000000101011010110000000000 -10111011001000001011011011011000 -00001111101000000000001111101100 -00000100111110110000000000111110 -11010000010011111101000000000011 -10100100000000001111100000000000 -00111110100000000000111110110110 -00001011110000100000011001100000 -00000000000000000000000000000000 -00000000000001001111111000100000 -11111111110000000011001111110000 -00001100110110000000001100111110 -00000010110011111000000010110011 -11110000000011111111100100000011 -11110110000000001110111110000000 -00110101101000000000110011111100 -00000011000000000000000001110000 -00000000000000000000000000000000 -10101000000110001001110000000000 -10110111000000000010000111000100 -00001000010001000000001101111100 -00000000100001110010000000100001 -11000000000010110101001100010010 -11010100010000001000010100000000 -00100001100001000000100001110000 -00000010001010100000010001100000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110111000000000010000111000000 -00001000011100000000001000011100 -00000000100001110000000001100001 -11000000000010110110000000100010 -11010101000000001010011000000000 -00100001101000000000100001110100 -00000010000000000000000000100000 -00000000000000000000000000000000 -00100000000001001100110000001001 -10110011000000000010000011000000 -00001000100000000000001001101100 -00000000100010110000000010100000 -11110100000010110001010100000010 -11000100010000001000000010000000 -10100000100100100000100000110000 -00000010000010000000010000110000 -00000000000000000000000000000000 -10101000000101010011110000000000 -10111111000000001110001111000000 -00101000101100000000001100111100 -00000000110011110000000000110011 -11110000000010111001010000000011 -11100000000000001110101101001000 -00110010010100000000110010110000 -00000011001010100000010001100000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11111011000000000011111011000000 -00001111101000000110001111101100 -00000000111110110000000000111110 -11000000000011111001000000000011 -11000000000000001111100100000000 -00111110010000000000111110110100 -00000011111000000000000000110000 -00000000000000000000000000000000 -00100001000100001111110000000000 -11111111000000000001111111000000 -00001111111100000000001100111100 -00000000110011110000000000110011 -11000010000011111100000010000011 -00100000000000001100101000001000 -00111111010000001000111111110000 -00000010000000000100010000110000 -00000000000000000000000000000000 -10100001000001000110110000000000 -10111011000000000010111011000001 -00001011101000000000001010101100 -00000010100010110000000010100010 -11000000000010110001100000000010 -00100001100000001000100000000000 -00101110011000000000101100110000 -00001010001000000000000000010000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000000000010111011000000 -00001011100100000000001000101100 -00000000100010110000000000100010 -11000000000010111001000100100010 -00100000000010001000101100000010 -00101110010001000000101110110100 -00000010101000000000000001000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10110011000000000010110011000000 -01001001000100000000001010001100 -00000000100000110000000000100000 -11000000000010111001000000000010 -00000000000000001000000100000000 -00101100011000000000101110110000 -00000010100000100000000100000000 -00000000000000000000000000000000 -00000000000011010111110000000000 -11110111000000000011110111000000 -00001111001100000000001100111100 -00000000110001110000000000110011 -11000000000011111000000000001011 -00100000000000001100101000000000 -00111110010000000000111110110000 -00000011100000000000001101010000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11111111000000000011111111000000 -00001111110100000010001111111100 -00000000111111110000001000111111 -11000000000011111101000000000011 -11110000000000101111110000000000 -00111111010000000000111101100000 -00000011011010000000011001110000 -00000000000000000000000000000000 -11000000000001011111100000000000 -11001101100000000011111111001000 -00001111111100110000001000110110 -00000000110011110001000000110011 -00001100001010001101100000000011 -11111100000000001100111110000000 -00110111010000000000110011000000 -00110011111100000000000001110000 -00000000000000000000000000000000 -10000000000100001010010000000100 -10001001100000010010111111001110 -00001011111101100000101000100110 -00000100100000110010000000100010 -00001100100010001011100000000010 -11111101100010001000100110000001 -00100010011000000000110110001000 -00000010111000000000010000110000 -00000000000000000000000000000000 -10001000000001001100000000000001 -10000011000001000010110011000000 -00001011001100110000001010101100 -00000000100000110010000000100000 -10001000000010000001000000000010 -11001100011000001010001100000000 -00101110110000000011100000100000 -00000010111000100000000101110000 -00000000000000000000000000000000 -11000000000101011000010000100011 -10001011001000000010111011000000 -00011011101100000000001010100110 -00000000100010110000000001101010 -00000000000010001011000000010010 -11101100000000001010101111000110 -00101010110000000000100110100000 -10000010111100000000010001100000 -00000000000000000000000000000000 -00000000000101011110000101000000 -11001001000000010011111011000000 -00001111101100000100001110000100 -00000000110010110000000001110010 -01001000000011001001100000000011 -11101100000000000110100110000000 -00111100010100100000110010000100 -00000011110000000000010001110000 -00000000000000000000000000000000 -11100000000000011011011000000000 -11111101000011000011111011000000 -00001111111100000000001101110100 -00010000111101110000000011110111 -00000100010011111111100100000011 -11111100000001101101110100000001 -00110111010001000000111110000100 -00100011111110000000000001100000 -00000000000000000000000000000000 -01000000000100001010000100000000 -11101011000000100011111011000000 -00101100001100010000001110101100 -00000000111110110000000000110000 -11000100000011111001000000000011 -11101100000000101110101101001000 -00111110110000100010110010110100 -00001011000100000000010000100000 -00000000000000000000000000000000 -11001000000001010010010111010000 -10001011000000000010111111000000 -00001000111101010000001000100100 -10000000101111110000010000100010 -00100000000010111011100000000010 -11111110000000001000001101100000 -00001110110110000000100010111000 -01000000001100100000000001000000 -00000000000000000000000000000000 -11100000000001010100011100000010 -10100001110000000010110011000000 -00011001001110000000001010000100 -00000100101100110000000000000100 -00011000010010110001100000000010 -11101100010000000010000100000000 -00001100000100010000100100010000 -00000010001110000000000001010000 -00000000000000000000000000000000 -01100000000000010000111000000000 -10010101100010110010110111100000 -11001001011110000000011000011110 -00000000101101111000001000100101 -11100000000010110101100010000010 -11011110000000001010010110000010 -00101100001000010100100101011010 -10010010000110000000000001000000 -00000000000000000000000000000000 -01001000000010000000110010001001 -11100001000001000011110011001000 -10011101101100100000001110001100 -00000000111100110000000010110100 -10001000100011110001000000000011 -11101100000000001110001100110000 -00111100110000000000110100000000 -00001001000100100000001000000000 -00000000000000000000000000000000 -01000000000111011011110100000001 -11101101000000000011111111000000 -00011110111101000001001111111101 -00000000111111110001000000111011 -11000000000011111101000100000011 -11111101001000001101111100010000 -00111111110000000000111011000010 -01000011110100000000011001100000 -00000000000000000000000000000000 -10101000000001011110110000000000 -11001011000000000011111011001001 -00001111101100010000001111100100 -10000000111110110001000000111110 -01000000010011111011001100000011 -11101100100000101100100000000000 -00111100010000000010110010110000 -00010011001010100000000001110000 -00000000000000000000000000000000 -01001000000100010000110000000000 -10000111001100000010110111010010 -00001011011100000101001011011100 -00010000101101110000001000101101 -11000000000010110111000010000010 -11011100000000001000010000000010 -00101101010000000000100001110000 -00000010000100100000010001100000 -00000000000000000000000000000000 -11000000010000000001111000000100 -10000111100101000010110111101000 -00001011011110100000001011011110 -01000001101101111000000000101101 -11100000000010110111101000000010 -11001110100000001011011010001000 -00101101011000000000100000111000 -00000010001100000000000000100000 -00000000000000000000000000000000 -01001000000101001100111000000000 -10000011000000000010110011000000 -00001011001100000000001011001100 -00011000101100110000001000101100 -11000000000010110011000100000010 -11101100000000001011001010000010 -00101100111000010000100000111111 -00000010000100100000010000110000 -00000000000000000000000000000000 -11101000000101011010100000100010 -11001010101000000011111010000000 -10001111101000000100001111101000 -00000000111110100000011001101111 -10010001000011111010100000000011 -11101000000010001111111000000100 -00111111101000000000110011100100 -00001011001110100000010001100000 -00000000000000000000000000000000 -01001000000000001110000000000010 -11111000000000000011111000000000 -00000011100001000000001111100000 -00000000111110000000000001111110 -00000010010011111000000000000011 -11100000000000000000100000100000 -00111100000001000000111100000000 -00000011110100100000000000110000 -00000000000000000000000000000000 -00001000000100001110110001000010 -11001001000000000001001001000000 -10000011000100000010001100100100 -00000000111110010000001001111100 -01000001100011001001100100000011 -11100100000000001100100110000010 -00111110010001100000110010011000 -00000011000000100000010000110000 -00000000000000000000000000000000 -10000000000001000110010100000000 -00000011000000000010001001000000 -00001011100100000000001000101101 -00000100101110010000000000101110 -01000000000010001011100000000010 -11100110000010001000100111000000 -00101110010110000000101010011000 -01000011001000000000000000010000 -00000000000000000000000000000000 -00011000000001010000010100000000 -10001001010000100010101001000000 -01011011100100000000001000100101 -00000000101110010000000000101110 -01000000000010001001000000000010 -11100100010000101000100100101000 -00101110010000000010100010010001 -00000010000001100000000001000000 -00000000000000000000000000000000 -00001000000001000000010010100010 -10001001000000000010100001001010 -00001011000100101000001000000100 -00000000101100010010001100101100 -01001000100010000001000000000010 -11000100101000011000000100000000 -00101100010010000000101000010010 -00000010000000100000000100000000 -00000000000000000000000000000000 -10111000000011000110000010010000 -11001000000001000011101000001000 -10001111101001110000001100100000 -00000000111110000000000100101110 -00010100001011001010000000000011 -11100001110000001100100000000100 -00111110000000000000110010000000 -00001011001011100000001101010000 -00000000000000000000000000000000 -10011000000111011010010010100010 -11111001000000011011011001001010 -00001111100100000000101111100100 -00000000111110010011100000111111 -01000100100011111001000000000011 -11100100000000001111110100000000 -00111111010001010010111111010001 -00000011101001100000011001110000 -00000000000000000000000000000000 -10011000000001011010011000000000 -11001001000000000011111001000100 -00001111110100100000001111100100 -00010000111110010110000000111111 -01001011000011000001000000000011 -11110101000000101100110100000100 -00111111010010000100110011010000 -00000011001001100000000001110000 -00000000000000000000000000000000 -00111000000100001110001010000010 -10001000000000000010110000010100 -00001011100000100000001011100000 -00000000101110000101000000101100 -00011001000010001000000000000010 -11100001000010001000100000000010 -00101110000100000100110110000100 -00001010000011100000010000110000 -00000000000000000000000000000000 -00001000000001001100010100100001 -10000001000001000010110001001000 -00011011000101001000001011000100 -00010001101100010010000000101100 -01000010000010000001000000000010 -11000101100001001000000100000100 -00101100011001000010100000010100 -01000010100000100000000101110000 -00000000000000000000000000000000 -00011000000101011000110010010000 -10001001000000000010111001000001 -00011011100100000000001011100100 -10000000101110010000000000101110 -01000001000010001001000000000010 -11100100000000001000100100000110 -00101110010000000000100110010100 -01000010100001100000010001100000 -00000000000000000000000000000000 -10100000000101011110010000000000 -11001001000100000011111001000000 -01001011100100000100001111100100 -00001000111110010000000000111110 -01000000001011001001000000000011 -11100100000000001100100100010000 -00111110011100000000110000010000 -00000011101010000000010001110000 -00000000000000000000000000000000 -00101000000000011010110000111000 -11111001100000000011111001000000 -00001111100100001000001111100100 -00000000111110010000000000111110 -01000100000011111001000000000011 -11100100000010001111100110000010 -00111110011001000100111110010010 -00000011010010100000000001100000 -00000000000000000000000000000000 -00101000000100001010000000000100 -11001000000000010011111000000000 -10001101100000000000001110100000 -00000000111110000000000011110010 -00000000000011001000000010000011 -00100000000000001101100010000000 -00111110000010000010110010000000 -00000011000010100000010000100000 -00000000000000000000000000000000 -00101000000001010010101000001010 -10001010000000100010111010000000 -00101000111000000000001000101011 -00000000101110100000000100000011 -10000000000010001010010000100010 -00101000000100001000111000000000 -00101101100100001000101011100000 -00000011100010100000000001000000 -00000000000000000000000000000000 -00101000000001010100111000000000 -10010011000100000010110011000000 -00011000001110000000001010001100 -10000000101100110000000000100010 -11100000000010000011010000000010 -00100100000000001001001100000000 -00101100010000000100100000011000 -00000000010010100000000001010000 -00000000000000000000000000000000 -10100000000000010001110000110000 -10010111000000000010110111101000 -00011000010110001000001000010101 -00000100101101111010001000100001 -11010000000010001111100000000010 -00010100000000011000011100000000 -00101101010000001000101001110100 -00010110101010000000000001000000 -00000000000000000000000000000000 -10101000000010000000101001000000 -11010111100010010011110111101000 -00001100111110000000001110011010 -00000000111111111100001000100001 -11100000001011000111100000001011 -00111110000000001101011110000000 -00111100011000000010110000111000 -00001011011010100000001000000000 -00000000000000000000000000000000 -00001000000011011010100010000000 -11101010001000000011111011000100 -00001110100000000000001111100000 -10000000111110110110100000111110 -11000000000011111001011000010011 -11100100000000001111101100000000 -00111110010000000000111110110000 -00000011110000100000011001100000 -00000000000000000000000000000000 -01000000000001011111011001011000 -11101111100100000011111111110000 -00101100111010000000001111111111 -00000000111111111000000000110011 -01100000010011111111110000000011 -11110110000000001100111110000000 -00110001011001000010110011111000 -01000011000100000000000001110000 -00000000000000000000000000000000 -10101000000100011001010011000000 -10000101000000000010110111000000 -00001000010000000000001011010100 -00000000101101110000000000101001 -11000000000010110111000000000010 -11110100100000101101011100000000 -00111101010011000000100001110010 -00100010001010100000010001100000 -00000000000000000000000000000000 -00010000010000001001110000010000 -10000111000000000110110011000000 -00001000011100000000001011011100 -00000000101101110000000000100001 -01000010000010110110000000000010 -11011100000010001000111100000000 -00100001010000000100100001110000 -00000110100000000000000000100000 -00000000000000000000000000000000 -01100000000101001100000100001001 -10000000000000000010111011000001 -00001000000000000000001011000100 -00000001101100110000000000101000 -11100000000010110000000000010000 -11000100000000001000001100000010 -00101000010000000000100000110000 -01100110100110000000010000110000 -00000000000000000000000000000000 -10111000000101011010100100000010 -11001000000000100011111111000000 -10001100101100000000001111101110 -00000000111111110000000000110010 -11110100000011111000100000000001 -11100100000000001000101100000000 -00100010111000000000110000110000 -00000011101011100000010001100000 -00000000000000000000000000000000 -10000000000000001100101100000000 -11111011000000000011111011000000 -00001111101100000000001111101101 -01000000111110110000000000111110 -00010000000011111010000100010011 -11000100000000001111101100010000 -00111110011000000000111110110000 -00000001011000000000000000110000 -00000000000000000000000000000000 -10000000000100001111110000100000 -11011100100000000011111111000000 -00001100111100100000000110111010 -00010000111100110000010000110011 -11000000000011111101000000000011 -11111100000000001100111100000000 -00111111010000000000110011111010 -00000011001000000000010000110000 -00000000000000000000000000000000 -10000101000001000110110000000000 -10001010110000000010111011000000 -00001000101000000010101000101001 -10000000101110110000000000100010 -00101000000010111001100001000010 -11100100000000001000100110000010 -00101100011000000010100010110000 -00000010001001000100000000010000 -00000000000000000000000000000000 -10000000000001010010010000010010 -10001000011000000010111011000000 -00001000000000000000011000100000 -01000000101110110000000000100010 -01001001000010111000000100000010 -11100100000000001000101110000000 -00101110101000100100100010110000 -00000010001000000000000001000000 -00000000000000000000000000000000 -00001000010001000000010000000000 -10000001000000100010110011000000 -00101000000000000000001010000000 -00000000101100110000010100100000 -00000000000010110010100000000010 -11000100000000001000001110000000 -00101110010000000000100000110000 -00001010000000100000000100000000 -00000000000000000000000000000000 -10000000000011010100110000000000 -11001000000000000011111111000000 -00001100100100000000001100100000 -00000100111111110000001000110010 -01000000000011111000000000000011 -11101100000000101100101100000000 -00111110010000000100110010110000 -01000011001000000000001101010000 -00000000000000000000000000000000 -10100000000111011111000000000000 -11111100000000000011111111000000 -00001101110000000010001101110000 -00000000111111110000000010111111 -00000000000011111100000000000011 -11110100000000001111010000000000 -00111111010000000000111101110000 -00000011111010000000011001110000 -00000000000000000000000000000000 -11000000000000011111011000000000 -11011111000010000011001111000110 -00001101110110010000001111110000 -00000000111111011000001100001111 -01100000100011001100001100100001 -11110110000000001100110000000010 -00110011110000000100110011110000 -00000000001100000000000001110000 -00000000000000000000000000000000 -10000000000100001110010000000000 -10001011100000010011011111011000 -00001101100100100000001011100001 -00100100101110011000000000101110 -01100000000010001000011100000010 -11100100000010001000100010000100 -00101010111000000000100010010111 -00010010001000000000010000110000 -00000000000000000000000000000000 -10001000000001011110110000000000 -10010011000000000010000011000000 -00001000000100100000001011000000 -11000000101100010000010000100100 -01000000000010000000000000000010 -11000100000000001000000000000000 -00100000101000000000100000010000 -10000010001000100000000101110000 -00000000000000000000000000000000 -11000000000101011010111000100000 -10001011000000000010010011000000 -00001001100100000000001011100110 -00010000101110111000000000101110 -10100000001010001011100000000010 -11100100100100000000100100000000 -00101010100000010010100000011000 -00100010001100000000010001100000 -00000000000000000000000000000000 -01000000000101010100011100000000 -11011011000000000001001011000000 -00001100100100000000001111100010 -00000000111110011010000000110110 -01100000000011001000110010000011 -11100111000000000100101001010000 -00110010110000000000100010010000 -00000011000100000000010001110000 -00000000000000000000000000000000 -11100000000000011011010000000000 -11111111000000000011111011000001 -00001111110101000000001111111000 -00101000111111010000000000111111 -01000001000011111101000000000011 -11110100000011001111111000000010 -00111110110100001000111111010000 -00000011111110000000000001100000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11101011000000000011111011000000 -00001101100100000000001111100101 -00000000111110110100000000111110 -11001001010011111000010001000011 -00100100001010001100001101001000 -00110010010000000000110010010000 -00000011000100000000010000100000 -00000000000000000000000000000000 -11001000000000010010110000000000 -10110111101000000010111111000000 -00101100100100000000001011101101 -00011000101110110000000001111100 -11100000000010111011110010000010 -10000100000000001000101111100000 -00100000000111000000100010010111 -00000011001100100000000001000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10100011000000010010110011000001 -00001000000100000000001011000011 -00000000101100111000010000101100 -11010100000010110000100010000010 -00000101000100001010000010000000 -00100000110000000010100000010000 -00000010011110000000000001010000 -00000000000000000000000000000000 -00100000000000010001111000000000 -10110111100001000010110111100000 -00011000011110000000011011010110 -01000000101101101100010000101001 -11100000000010110100100001000010 -10110110000010001010011110000001 -00100001111010000000100001011001 -01000010000010000000000001000000 -00000000000000000000000000000000 -01001000000010000000110000000000 -11100011000000000011110011000100 -00001100000100000100001111001001 -00100000111100110001100000101100 -11001000000011111001000000000011 -00000101000001001110001000000000 -10110000110000000000110010010000 -00000001010100100000001000000000 -00000000000000000000000000000000 -01000000000111011011110000000000 -11111111000000100011111111000000 -00001111111100000010001111110100 -00010000111111100000000100111111 -10000000000001111111000000000011 -11010100010010001101011100010000 -00111111110010010000111111010000 -00000011110100000000011001100000 -00000000000000000000000000000000 -10101000000001011110110000000000 -11111011000000000011111011000110 -01000011100100000000001111100100 -00000000111010110000000000111110 -11100001000011001011000000010011 -00100110000000000000001100000000 -00100010110000000000110010010000 -00010011001010100000000001110000 -00000000000000000000000000000000 -01001000000100011001110000000000 -10110111000000000010110111001000 -00001011011100000010000011111100 -00000000100001110000000100111101 -11000000000010000101000001000011 -01010000000000001000011100000001 -00101000110000000000100011010000 -00010010000100100000010001100000 -00000000000000000000000000000000 -11000000010000001001111000010100 -10110111100001000010110111100000 -00011011010110000100001011011111 -00010000101001111100010000101111 -11110000000010010011100000000010 -00011111000000101000011110000100 -00100001111000001010100001011000 -00001010001100000000000000100000 -00000000000000000000000000000000 -01001000000101001100100000000100 -10110011000000000010110011000000 -00011011001100000000001011001110 -00100000100000111000000000101100 -11001000000010011011110000000010 -01000101001000001000001110000000 -00101000010000000000100000010000 -00001010000100100000010000110000 -00000000000000000000000000000000 -11101000000101011011100000000000 -11111010000000000011111010000000 -00001111101000000000001111111001 -00000100111011101000001000111111 -10000000000011011110101100000011 -00111010000000001100111011000000 -10110011100110000010110010100000 -00000011001110100000010001100000 -00000000000000000000000000000000 -01001000000000001110000000100100 -11111000000000000011111000000000 -00001111100000000000001111100001 -00000000111110001000000001111010 -00010000011011101000010000000011 -11100000000000101111000001010000 -00111110000000100000111110000001 -00000011110100100000000000110000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11101001000000000011111001000000 -00001111100100000000011100000100 -00000000110010010000000000111110 -01110000100011111001000100000011 -00100100000001001111100110101000 -00110000011000000000111000010001 -00001011000000100000010000110000 -00000000000000000000000000000000 -10000000000001000100010000000000 -10001001000000000010111001000000 -00001011000100000000001000100100 -00010000101010011000010000101110 -01001000000010111001101000000010 -00100111000000001011100111000010 -10110110010100000000100010011000 -00001010001000000000000000010000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10101001000000000010111001000000 -00011011100100000000101000100100 -10000000100010010010000000101110 -01000000000110111001000000000010 -10100100010000001011101101000000 -00100010010001100000101010010000 -00000010000001100000000001000000 -00000000000000000000000000000000 -00001000000001000010010000000000 -10000001001000000010110001001001 -00011011100100000000001000000100 -10000000101000011000000000101100 -01000000000010110001001000001010 -00001100000000001011000100100100 -00100100010010000010100000010010 -00000010000000100000000100000000 -00000000000000000000000000000000 -10111000000011000110000101000000 -11101000000010000011111000010100 -00001111100000000000001000101001 -01000000110010000000000000111110 -00000000000011111000010100000011 -10000001010000001111100000000000 -00110010000000010000111010000101 -00000011001011100000001101010000 -00000000000000000000000000000000 -10011000000111011011010000000000 -11111001000000000011111001000100 -00001111110100101000001111110100 -01000000111111010000000000111101 -01000000000011111101000100100011 -11110100000000001111110100010000 -00111111010001000000111111010001 -00000011111001100000011001110000 -00000000000000000000000000000000 -00011000000001011110010001000000 -11111101100000000011111001010000 -00001111100101000000001111110101 -00000000010001010000000000111111 -01000000000011110101001000000011 -00110101000000001100110100000110 -00110011010000000010110011010110 -00001011010001100000000001110000 -00000000000000000000000000000000 -00111000000100001110000000000100 -10111000010100000010111000011100 -00001011100000100000000011101001 -00000100110110000000000000101110 -10000000000010111000001011000011 -01100000000000101000100001000000 -00101010000100010000100000000110 -00000010000011100000010000110000 -00000000000000000000000000000000 -00001000010001011100010010010000 -10110001000001000110110001001000 -00011011000100100000001011000101 -10000001100000010000000000101100 -01000000000010110001010000000010 -00000100100001101000000101000000 -01100000010100000100100000010011 -00100010010000100000000101110000 -00000000000000000000000000000000 -00011000000101011010010000010000 -10111001000000000010111001000000 -00011011100100000001001011100110 -00000100100110010000000000101110 -01000001000010111011001000010010 -01000101100000001000100100001000 -01101010010010000000100010011000 -00000010000001100000010001100000 -00000000000000000000000000000000 -10100000000101011110010101100000 -11111001000000000011111001000000 -00001111100100000010001111100101 -00000000110010011000000000111110 -01000000000011111001001000000011 -00100101000010001100100111000000 -00110000010010001000100010010000 -00001011011010000000010001110000 -00000000000000000000000000000000 -00101000000000011010010000000000 -11111001000000000011111001000000 -00001111100100000001001111100100 -00000000111110010010000100111110 -01110001000011111001000000000011 -11100110000000001111100100101000 -00111110010000000010111100010000 -10011011110010100000000001100000 -00000000000000000000000000000000 -00101000000100001010000100000000 -11001000000000000011001000000000 -00001111100000000000001100100001 -00000001110010000000100000110110 -00000010000011111000000010000011 -00100011000010001111100001000000 -00110010000101100000111010000000 -00001011000010100000010000100000 -00000000000000000000000000000000 -00101000000001010010100000000000 -10001010000000010010101010000000 -00001011101000000001001000111001 -00000000100011100000010000100011 -10101001000010111110010000010010 -00111000000001001011011000100001 -10100011100000000000100011100100 -00000010000010100000000001000000 -00000000000000000000000000000000 -00101000000001010100110000000010 -10000001000000000010010011000000 -00001011001100000010001000101110 -10000000100000110000000000100100 -11100000000010111011110000100010 -00001100000000011011001010000000 -00100100101000001000101000110000 -00001010000010100000000001010000 -00000000000000000000000000000000 -10100000000000010001111011000000 -10000011100000000010110111000100 -00001011011110100000001000001101 -00001000100101111000000000100001 -11000000000010110111010000000010 -00011100000000001011011000000000 -00100101010000000000100001010000 -00010010001010000000000001000000 -00000000000000000000000000000000 -10101000000010000011111000000000 -11000101100000000011010111100010 -01011111111110101000001100011110 -00000010110001101000000000110101 -11100000000011110111100000001011 -00010110000000001111000010000000 -00110100111000001000111001111000 -00000011001010100000001000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111011000000000011101011011000 -00001111101101110000101111100100 -00010100111010110000000100111110 -11000000100001111001000000000011 -11100100000110001111100000000001 -00111010010000000000111110110000 -00000011110000100000011001100000 -00000000000000000000000000000000 -00000000000001011111111000000000 -11111101100000000011111111100000 -00001000111110000010001111110110 -00000000111101111000000100111011 -10100100000000111111101100000011 -00111110000000001111111010000000 -00110011111010000000111111111000 -00000011000000000000000001110000 -00000000000000000000000000000000 -10101000000100011001110001000000 -10110111000000000010111111000001 -00001101011100100000001011111100 -01000100110001100010000100100001 -11000000000010110110000101000010 -00011100000001001111010001100100 -00110101010000000000101101000001 -10000010101010100000010001100000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110101000000000010110111000000 -00001000011100000010001011010000 -00000000101001110000001000101001 -11000000000010110101001000000010 -00010000001000001011110000001000 -01100001010110000000101101110000 -00000010000000000000000000100000 -00000000000000000000000000000000 -00100000000101001100110000010000 -10110011000000000010110011000000 -00001001001110000000000011000000 -00000000100000110101100000100000 -11011100000010110000000000000010 -00000011000000001010000010000000 -01100000010000000000101110101000 -00000010100010000000010000110000 -00000000000000000000000000000000 -10101000000101011011110000000000 -11111001000000000011111111000000 -00001100111110001000001111101110 -01000000111010011000000000111010 -11100000000011111001101000001011 -00101100000000001011001011000000 -00100010101100000000111110111000 -00001011001010100000010001100000 -00000000000000000000000000000000 -10000000000000001110110000100000 -11111001000000000011110011000000 -00001111101100000001001111100001 -01000000111110110000000100111110 -01000000000011111001010001000011 -11101001001000001111101000000000 -00111110111000000000111110000000 -00000011111000000000000000110000 -00000000000000000000000000000000 -00000001000100001111110000000000 -11111101010000000011111111000000 -00001100111100000000001101011100 -00000000110011110000000000110011 -11000000000011110010000010000010 -00111101000000001000110000001000 -00110011110000000100110010110000 -00000011000000000100010000110000 -00000000000000000000000000000000 -10000001000001000110110000000000 -10111001000000010010111011000000 -10101000101100000000001000100011 -00000100101000101100110000100010 -01100000010010111000010000000011 -01001011000000001000100011000100 -00100000111000000000100010100000 -01000010001000000100000000010000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111001000000000010111011000000 -00001000001100000000001001100111 -00000000100010001000000000100010 -10100000000010111001100000000010 -10101100001000001010101010000000 -00100010111000000000100010110000 -10000010001000000000000001000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10110001000000000010110011000000 -00001000001100000001001000000000 -00000000101010110000000010100000 -01000000000110110000000000000010 -01101000000000001010001000000001 -00100000110000000000100000010000 -00001010000000100000000100000000 -00000000000000000000000000000000 -00000000000011010110110000000000 -11111001000000000010111111000000 -10001100111100000000001101100000 -00000000110010110000000000110010 -01000000000011111000000000100011 -10101000000001001110100000000000 -10110010010000000000110010110000 -00000011000000000000001101010000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11111101000000000011111111000000 -00001111111100000000001111110000 -00000000111111110000000000111111 -01000000010011111100000000010011 -11111000000000000101010100000000 -00111111010000000000111111110000 -01000011111010000000011001110000 -00000000000000000000000000000000 -11000000000001011101111000000000 -11011111100100000011001110100000 -00011111111101101010001100111100 -00000000110011010000000000110011 -00000100000011001111000000000001 -01110100000010001101011100000000 -00110011111000000000110001111000 -00000011111100000000000001110000 -00000000000000000000000000000000 -10000000000100001110111000001000 -10000001001000001010001000100000 -00001011111101000000011000111100 -10100010100010011000001000100010 -00001000000011011011100000000010 -00010100000001001010101111010000 -00110010011000000000100010111000 -00000010111000000000000000110000 -00000000000000000000000000000000 -10001000000001011100100000000000 -10111011000000000010000011100000 -00000011001100100000001000001100 -01000000100000010000000010100000 -00000000000010000000000000100010 -01000100000010001001000100000100 -00100110110000000000100000110000 -01000010101000100000000101110000 -00000000000000000000000000000000 -11000000000101011010110001000000 -10001011100000000010001000000000 -00011011101100000000001000101100 -00000100100010010010000000100010 -11000000000010011001010001000010 -00100100000000001010100100000010 -00100010110000000010100010111000 -00000010111100000000010001100000 -00000000000000000000000000000000 -01000000000101011100110000000000 -11011011100010001011001010000100 -00001011101100000100001000101100 -00000000100010100110000000110010 -00100000000111000010100000000011 -01100110000000001101100100000000 -00110100110000000000110010111010 -00000011110100000000010001110000 -00000000000000000000000000000000 -11100000000000011011110000100000 -11111111000000000011111100000000 -00001111101100000000001111111100 -00000000111111000000000000111111 -01101000001011101110101001000011 -11110110010000001111010100000010 -10111111111001000000111111110000 -00000011111110000000000001100000 -00000000000000000000000000000000 -01000000000100001010010001000000 -11011011000000000011111011000000 -00001111101100000011001100001100 -00000001111110100100000000010001 -00000000000011101000000000000011 -10100110000010001100100100100000 -00110010110000100100111110010010 -00001011000100000000010000100000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10100011000000010010001000000000 -00001011111100000000001000111101 -11000000101101000000001000100010 -11000001010010001000000000010010 -00100101000000001000100110100000 -00100010110000000000111010111100 -10000010001100100000000001000000 -00000000000000000000000000000000 -11100000000001010100111000000000 -10010011000000001010110000011000 -00001011101100000001001010001100 -00000000101100110000001100100000 -00000001000010100011000000000010 -00100101100000001000001111000000 -00100000111100000000101100110000 -00000010001110000000000001010000 -00000000000000000000000000000000 -00100000000000010011111001001000 -10100111100000000010000101100000 -10001011011110010000001010011110 -00000001101100011000000000100001 -00100000110000000011100100000010 -00010110110000001000011110010000 -00100001111000000000101001111001 -00000010000010000000010001000000 -00000000000000000000000000000000 -01001000000010000000110101000000 -11010011000000000011110011000100 -00001111001100000000001110001100 -00000100101100110000000010110010 -11000000010011100010000000001011 -10001100100000001100000100000000 -01110000110000100000111100110000 -00000011000100100000000000000000 -00000000000000000000000000000000 -01000000000111011011110001000000 -11111111000000000011111111000110 -10001111111100000000001101111100 -00000000111111010000100010111111 -11000000000011111111010001000011 -11111100100000001111110100000000 -10111111110000000000111111110000 -00000011110100000000010001100000 -00000000000000000000000000000000 -10101000010101011100110000001000 -11011010000000010011111000001010 -00001111101111100000001101101101 -00100000111110110000000000111110 -01000000100011110011000000000010 -01101100101000001100100100000000 -00110110110000000100111100110000 -00100011001010100000000001110000 -00000000000000000000000000000000 -01001000000100010001110000000000 -10001111000000000010000101000000 -00001011011100010010001000011100 -10000000101101010010000010100001 -01000100000010110111000000000010 -00001100000000001000010100000000 -00100001110000000000101101110000 -00000010000100100000010001100000 -00000000000000000000000000000000 -11000000000000001001111000100000 -10010111100000000010110111101000 -00001011001110010100001001011110 -01000000101100111100000000100101 -11100000000010110110100000000010 -01011110000001001000010110000000 -00100001111000000000101101111100 -00001010001100000000000000100000 -00000000000000000000000000000000 -01001000000101001100110100000000 -10000011010000000010000011000000 -00001011001100000010001000101100 -00001000101100011100000000100000 -11000000000010110011010000000010 -00001110000010001000000100000100 -00100000111000000000101100101000 -10000010000100100000010000110000 -00000000000000000000000000000000 -11101000000001011001101000000000 -11011110100001000011111010000000 -00001011101000000000001101101000 -00001000111111100000010000110110 -10010000000011111010000000000111 -01101010100000101100101000100000 -00110011101000010000111111101100 -00000011001110100000010001100000 -00000000000000000000000000000000 -01001000000000001110000110000000 -11111000000100000011111000000000 -00001111100000000010001111100000 -00000000111110000010000000011110 -00000010000011110000000000000011 -11100000000000001111100000000000 -10111110000001000000111110000100 -00000011110100100000000000110000 -00000000000000000000000000000000 -00001000000000001110011000001000 -11101001000010000011011001100000 -10001111100100000000001111100100 -00000000010000011010000000110010 -11000000000011101011000010000011 -00000100000000001100000100000000 -00110010011001000000111010011010 -00000011000000100000010000110000 -00000000000000000000000000000000 -10000000010001000110010001000000 -10000001000000000010001011000001 -00001011100100000010001011100100 -00000000100010011000000000100010 -01000000000010001001000000000010 -00100100000010001000100101010000 -00100000010000000000100000011100 -00000010001000000000000000010000 -00000000000000000000000000000000 -00011000000001010010010000000010 -10101001000000000010111001001000 -00001011100100000000001011100101 -00000000101010010000000000100000 -11000000010010101001000000000010 -00100100000000001000100100001000 -10100010010000000100101010010000 -00000010000001100000000001000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10001001000000000010100001000000 -00001011000100101000001011000100 -10110110001000010010001000100000 -01001000000010000001001000001010 -00000110100000101000000100100000 -10100000010000000000100000010000 -00001010000000100000000100000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11101000000000000011111010000000 -00001111100000100000001111100001 -11000000111010000000000010110010 -00000000010011101000000000001011 -00100001010000101100100000000100 -00110010000000000100111010100000 -00000011001011100000001101010000 -00000000000000000000000000000000 -10011000000111011111010000000000 -11111101001010010011011001000000 -00001011100100101000001111100100 -00000000110111010001000000111110 -01001111000011111001000100000011 -11110100010000001111010100010000 -00111111010000000000111111010000 -00000011111001100000011001110000 -00000000000000000000000000000000 -00011000000000011111010000000000 -11110001010000011011101001000000 -00001111100101100000011111110101 -00000000110001010010000000110110 -01001010010011111101001000000011 -00110101000000101100110100101000 -10110010010000000000111111010000 -00000011000001100000000001110000 -00000000000000000000000000000000 -00111000000100001110000000000100 -10111000000000000010001000000000 -00001111100000000000001011100001 -00000000100010000101000000101010 -10011000000010111000000001000010 -00000001000000001000100001000000 -00100010000000001000101110000000 -00000010100011100000010000110000 -00000000000000000000000000000000 -00001000010001011100011000010000 -10110001001000000010100001000000 -00011011000101100000001011001101 -10000000100000010000000010100100 -01000011000010110001010000100010 -00001101100000001000000100000000 -00100000010000000000101110010000 -00000010000000100000000101110000 -00000000000000000000000000000000 -00011000000100011010011000000000 -10111001000010100010001001000010 -00001010100100000001001011000100 -00000000100010010000000010100010 -01000000000010111001000010010010 -00100100000000001000100100000000 -00100010010000000000101110010100 -00000010100001100000010001100000 -00000000000000000000000000000000 -10100000000101011110010000000000 -11111001110000000011101001000000 -00001011100100000000001011100100 -00000010100010010000000010110110 -01110000000011111001010000001011 -00100100000001001100100100000000 -10110010010000000000111100010100 -00000010001010000000010001110000 -00000000000000000000000000000000 -00101000000000011010010000000000 -01111001110000000011111001001000 -00001111100100000000001111100100 -00000000111110010000000100111110 -01001001000111111001100100000011 -11100110010100001111000100100000 -00111110111001000000111110010001 -00000011110010100000000001100000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11011000010000000010001000010000 -00001110100000000000001100100000 -00000000110100000001000000110010 -00010000001011000000011000000011 -00100000000000101110100000010000 -00110110000000000000111110000000 -10000011110010100000010000100000 -00000000000000000000000000000000 -00101000000001010011101100000000 -00001010000000000010001010100100 -00001011101000000000001000111000 -00000000111010100000000000110110 -10000000000010001110110000000011 -01111000000000001000111010000000 -00100010101010000000101111101100 -01000010110010100000000001000000 -00000000000000000000000000000000 -00101000000001010100111110010000 -10011011000000000010000011010000 -10001011001100000000011000001100 -00000001100100110000000001100000 -11000000000010000000100000000010 -00101100000000001010001010000000 -00100100001000000000101100111000 -00000010110010100000000001010000 -00000000000000000000000000000000 -10100000010000010011101000100000 -10001111001000001110000110000010 -00001011011110000000001000010000 -00000000101111110000000000100101 -11101100000010000100000010000010 -01011100000000001000011100000000 -00100001010000000000101101110000 -10000010111010000000000001000000 -00000000000000000000000000000000 -10101000000010000001111000000000 -11010111101100000010000111100010 -00001110001110000000101100011110 -00000000110101011000010100110000 -11101010000011000000100000000011 -00011110000000001110011110000000 -00110101001001000000111101111000 -00000011111010100000001000000000 -00000000000000000000000000000000 -00001000000111011000110000000000 -11111011001100000011111010001000 -00001011101101010001001111100100 -00000100111010010000000100111110 -11000000100011111000000000000011 -11101000000000001111001100000000 -00111110110010000000111110110000 -00000011110000100000011001100000 -00000000000000000000000000000000 -00000000010001011101111011000100 -11010111100000000011001101100000 -00001111111111000000001110111110 -01000000110011111001000010110011 -11100000000011111110100000000011 -11111110000000001111111010000000 -00110011001000000000111111111000 -00000011100000000000000001110000 -00000000000000000000000000000000 -10101000000000011001110001000000 -11010111001000000011010101000000 -00001110011100000000001000010001 -00000000100001110011000000100001 -11001000000011110110001000000010 -11010100000001001011011100000000 -10100001010000000000101101110000 -00000010111010100000010001100000 -00000000000000000000000000000000 -00000000010000001001110110010100 -10111111000000000010000101000010 -00001010001100000000001011011100 -00000100100100010000000111100001 -11000000000010110110000000000010 -11011100000000001011011100000000 -00101001100000000000101101110000 -00000010100000000000000000100000 -00000000000000000000000000000000 -00100000000101000100110000000001 -10010011000000000010010001100000 -00001010001100000000001001000100 -00000000100100010000000001100000 -11000000000010110010010000000010 -11000000000000001011001100000000 -00101000111000000000101100100100 -10000010110010000000010000110000 -00000000000000000000000000000000 -10101000000101011000110000000000 -11111111111000001011001011100000 -00001110111100000000001111101100 -00000000110110110000000000110011 -11000000000011111001000000000011 -11101100000000001111101100000000 -00111000001000100000111110111010 -00000011101010100000010001100000 -00000000000000000000000000000000 -10000000000000001110111100000000 -11111011000010000011111011010010 -00001110101100000000001110101000 -00000000111000110001000000111100 -11001100000011100001001000000111 -11100100000000001111100100000000 -00100110010000000000111110110000 -00000011111000000000000000110000 -00000000000000000000000000000000 -00000001000100001111110000010000 -11011111000000000011011100100100 -00000100111100000010000100101011 -00000000111111011100000000110111 -11000000000001001101100000000011 -00111000100010001110001100000000 -00110011100000001000110011110000 -00000011000000000100010000110000 -00000000000000000000000000000000 -10000001010001000110110000000000 -10000011000000010010000000110000 -00001010101100000000001000101001 -00000000101110010000000000110010 -11000000010010001001010010011010 -00100010000000001011101111000010 -00100010111000000000100000011100 -00000010001000000100000000010000 -00000000000000000000000000000000 -10000000000001010010110110010000 -10011011000000100010011011000011 -00011010001100000000001010100100 -00000000101110010000000000100110 -11000000101010101000000100000010 -00101100000001011011101111000000 -00100010000001000000100010111000 -11000010001000000000000001000000 -00000000000000000000000000000000 -00001000010001000010110000000000 -10001011000000000010001011000000 -00011010001100000000001010000000 -00000001101100010000000010100000 -11000000000010100000000000000010 -00000110000000001011001100000000 -10100010010000000000100000110000 -00000010000000100000000100000000 -00000000000000000000000000000000 -00000000000001010110010000000000 -11011111000000000011011000000000 -00011110111100000000101110100000 -00000000111110010000000000110111 -11000000000011101000000000000011 -00101000000001001110101100000000 -10110010100000000000110010110000 -00001011000000000000001101010000 -00000000000000000000000000000000 -10100000000110011111110000001010 -11111111000000000011111100000000 -00001111111100000000001101110000 -00000000111111010000000010111011 -11000000010011011100000000000011 -11110000000000001111111100000000 -00111111110000001010111111110000 -00000011111010000000011001110000 -00000000000000000000000000000000 -11000000000001011101000001000000 -11001111000110000011111111000000 -00011111110010000000001101110010 -00000000110001011000000000111101 -01100000000011111100001100000011 -00010000000000001100111100010000 -00110011111000000000110011110010 -00000011001100000000000001110000 -00000000000000000000000000000000 -10000000000100001110010110001010 -10001111000000000010111111110100 -00000011100000100000001000100010 -00000000000010111000010100101110 -01100000010010111000001000001010 -00100010000000001010111101010000 -00100010110000000000101000100100 -00010010001000000000010000110000 -00000000000000000000000000000000 -10001000000001011100000100000000 -10100011000000100010110011000000 -00011011001000001100001011000000 -00000000100000110000001000101100 -01000000000110110000000100000010 -10001000000000001000001100000010 -00100000110000000000100100101001 -00000010001000100000000101110000 -00000000000000000000000000000000 -11000000000101011000000000000000 -10101011000000000010111011000000 -00001011101001100000001010101000 -10000000100010110000100000101110 -10100000010010110011100010000010 -10101010001000001010101100000000 -00100010110000000100101110111000 -00000010001100000000010001100000 -00000000000000000000000000000000 -01000000000101011110001000000000 -11101011000000000011111011000000 -00001011100110000000001111100011 -00100000110010111101000000111110 -01100000000011111000100000000010 -10100010000000001100101100000000 -10100010110000000000110110100000 -00000011000100000000010001110000 -00000000000000000000000000000000 -11100000000000011011010010000000 -11011111000000010011111111000000 -00001111110000000000001101110010 -00000000111111111000000000111111 -01000001000011111000000000100011 -01010000000001101111111100000100 -00111111111001000100111011100000 -00000011111110000000000001100000 -00000000000000000000000000000000 -01000000000100001010000000000000 -11101011000000000011111011000000 -00001111101101000100001111100101 -10000000111110111010000000110010 -11000000000011011001010000010011 -00100001000000101100101110100000 -00111110110010000000110000110000 -00001011000100000000010000100000 -00000000000000000000000000000000 -11001000000000010010000000000000 -10001111000000000010111111000000 -01001110101000000000001011000011 -10000000101110101100000000100010 -11100010000010001011000000000010 -00101000100000101000111100000100 -00101100111100000000110110110000 -00001010001100100000000001000000 -00000000000000000000000000000000 -11100000000001010100000000000000 -00100011000000000010110011100000 -00001011100000000000000011000000 -00000000101100110100000000100000 -11100000000010010000000000100010 -00001001001000001000101101000000 -01101100010101000000100000010000 -00000010001110000000000001010000 -00000000000000000000000000000000 -00100000000000010011011000000000 -10000111100000000010110111100010 -00001010011110000000001011011010 -00000100101101111000000000100001 -11100000000010010101100000100110 -00011110010000001000011110010000 -00101101111000000000100101011101 -00000010000010000000000001000000 -00000000000000000000000000000000 -01001000000010000000000000000000 -11100011000100000011110011000000 -00001111000000000000001111000100 -10000000101100110001000000110000 -11000000010011010000000000000011 -00001000010000001100001100000000 -00111100010000001000110000010000 -00000011000100100000001000000000 -00000000000000000000000000000000 -01000000000111011011000000000000 -11111111010000000011111111000000 -00001111111100010000001111110000 -00000000111111110001011010111111 -10000000000011101111000100000011 -11111100010000101111111101000000 -00111101110000000000111111010000 -00000011110100000000011001100000 -00000000000000000000000000000000 -10101000000001011110000000000000 -11001011010100010011111011001010 -10001111100100000000001111100000 -00000000111110110000000000101110 -11000000100011101011000000000011 -00100000000000001100101111010001 -10110000010000000000110010110000 -01000011001010100000000001110000 -00000000000000000000000000000000 -01001000000100011000010000000000 -10000111000000000010110111010000 -00001011011100000000001011010000 -00000000101101110000000000101101 -11000001000010001101000000010010 -00011000000000001010111100000000 -00100001110000000000111000110000 -00001010000100100000010001100000 -00000000000000000000000000000000 -11000000000000001001001000000010 -10000111101000000010110111100000 -00001011010110000000001011010010 -00000001101101011000000000101111 -11100000000010000111100000000010 -00010010000000001001011110000000 -00100001111000000000100001111000 -00000010001100000000000000100000 -00000000000000000000000000000000 -01001000000101001110100000000000 -10000011000000000010110011000000 -00001011001100000010001011000001 -00000000101100110000000001101100 -11000000000010000011110000001010 -00001100000000001011001100000001 -00100000111000000000101000111000 -00000010000100100000010000110000 -00000000000000000000000000000000 -11101000000101011011100000000000 -10001010000000000011111010000000 -00001011111000000000001111011000 -00000000111111100001100000111111 -10010010000011001110101000000011 -00011000001000101101101000000000 -00110010101000000000110011101010 -00000011001110100000010001100000 -00000000000000000000000000000000 -01001000000000001110000001000000 -11110000000000000011110000000000 -00001111100000000000001111100001 -01000000111110000000000100111110 -00000010001011111000000010000011 -11100010000000001110100000000010 -00111110000001000000111010001000 -00000011110100100000000000110000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11001001000000000011001001010000 -00001100100100001010001111100100 -01100000110010011000001000111110 -01101000000011000001000000010011 -00100100000000101100100111000000 -00101110011000000000111010010000 -00000011000000100000010000110000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10001001000000001010001001100000 -00001010100100000000001011100101 -00100000100010010000000100101100 -01100000001010001001000000100010 -10100101000001001101100110000001 -00101110010000000010100000010000 -00000011011000000000000000010000 -00000000000000000000000000000000 -00011000000001010010010000000010 -10001001000000000010001001000000 -00001000100100000000001011100100 -00000010100010010001000000101110 -01000000000010001001000000000010 -00100100010000011000100100000000 -00101100010001010000101010010000 -00000010000001100000000001000000 -00000000000000000000000000000000 -00001000000001000000010010000000 -10000001001000000010000001001000 -01001010000100000000001011100100 -00000000100000010000000001101100 -01000000000010000001001000000010 -10000100100000001001000110100100 -00101100011000000000100010110010 -00000010010000100000000100000000 -00000000000000000000000000000000 -10111000000011010110000101000000 -11001000000000000011001000000000 -00001000100001010100001111100000 -00000000110010000000000000101110 -00000000000011001000010100000011 -00101000000000101100100001010000 -00111110000101000100111010000101 -00000011001011100000001101010000 -00000000000000000000000000000000 -10011000000111011111010001000000 -11111001001110000011111001000100 -01001111110100000111001111110100 -00010000111111010000000000001101 -01000000010011111101000100100010 -11010100010000001111100100010000 -00111111010000000000111111010001 -00000011111001100000011001110000 -00000000000000000000000000000000 -00011000000001011110010000000000 -11101001000000000011001101000010 -00001111100100000000001111110100 -00000000111110010000010000110010 -01000000000011111101001000100011 -00110100000001001100110101100000 -10100011010100000000110011010010 -00000011000001100000000001110000 -00000000000000000000000000000000 -00111000000100001110100111000000 -10001000011010000010001000010000 -00001011100000000000001011100000 -00000000101110000000000010100010 -00000000000010111010010000000011 -01100001000001001000100001000000 -00110110000000001000111110000010 -10000010100011100000010000110000 -00000000000000000000000000000000 -00001000000001011100010000100000 -10100001010000001010000001000000 -00001011000100101001011011000100 -00010000101110010000000000100000 -01000000000010100001001111000010 -00000101000000101000000100010001 -00100010010010010000100000010100 -00001010010000100000000101110000 -00000000000000000000000000000000 -00011000000101011010010000000100 -10001001000000000010001001000000 -00001011100100000010010011100100 -00000000101110110000100000100010 -01000000010110111001000000000010 -01101100000000101000101100000000 -00100110110000000000101110010000 -00000010110001100000010001100000 -00000000000000000000000000000000 -10100000000100011110011101000000 -11101001000000000011001001000000 -00001111100110000000001111100110 -00110000111100011101000000110010 -01000010000011101001100100010011 -00100100100000001100100100000000 -00110000011000000000110010010010 -00001011011010000000010001110000 -00000000000000000000000000000000 -00101000000000011010010000000000 -01110001000000000011111001000000 -00001111100110010000001111100100 -10001000111110111000000000111110 -11110001000011110001100001000011 -11000111000000001111100100000000 -00111110011010000000111110010000 -00000011100010100000000001100000 -00000000000000000000000000000000 -00101000000100001000000100000010 -11001000000000000011001000000001 -01001111100000000000001111100000 -00010000111110000100000000111110 -00010000000011111000010000000011 -00100001000000001100100000000000 -00110010000000100000110010000100 -00000011000010100000010000100000 -00000000000000000000000000000000 -00101000000001010010100000000000 -10001010000000000010001010100000 -00001011101000000000001111111010 -00100000101110100100010000101110 -10001000100010111010000000000010 -00111001000000101101111010000000 -00111011100000000000100011101001 -10000010100010100000000001000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10000011000000000010000011000000 -00001011001100000000001011001111 -10000000101100110010000001101100 -00100000000010110011100000100010 -00001100100000001000101100100000 -00100000111000000000100010110100 -00000010000010100000000001010000 -00000000000000000000000000000000 -10100000000000010001110010010101 -10000111001000000010000111010000 -00001011011100000000001010011100 -00000000101101000000010000101101 -10000000000110110111010000010010 -00010000000000001001001101000000 -00101101010000100000100001110000 -00000010001010000000000001000000 -00000000000000000000000000000000 -10101000000010000000111001000000 -11001111111100000011000111100000 -00001011011110000000001011011010 -00000000111101011001000000111101 -10100100000011111111100000001011 -00010110000000001100010110000000 -00110001111000000010110000111000 -00001011001010100000001000000000 -00000000000000000000000000000000 -00001000000111011010110110000000 -11111011000000001011111011000000 -00001111101100010000001111101100 -00000100111110000100000000111110 -10001000000011111011010000000010 -11000000000001001011100100000000 -00111000010000000000111110100000 -00000011110000100000011001100000 -00000000000000000000000000000000 -00000000000001011111111000100000 -11001111100000000011101111100000 -00001100011110010000001110111110 -01000000111011101001000000111011 -00100000010011001101110000100011 -01111010000000001100111110010000 -00110001101000000000110011111000 -00000011000000000000000001110000 -00000000000000000000000000000000 -10101000000100011001110001000000 -11010111000000000010000111000000 -00001101011100000001001000011100 -01000000100001000001110000100001 -00000001000010000101000000000010 -00010000000000101000010000110000 -00110101000010100000101011110000 -00000010101010100000010001100000 -00000000000000000000000000000000 -00000000000000001000110000000000 -10000111000000000010100101000000 -00001000111100000000011010111100 -00000001101001000000000000101101 -00000000000010000101100010000010 -00010001010000101000001100000001 -00100001010000000000100001110000 -00000010000000000000000000100000 -00000000000000000000000000000000 -00100000000101001100110100100000 -10010011000000000110000001000000 -00001001001101000000001000001110 -00000000100000001100110000100100 -00011000000010000001101000100010 -00000000010000101000100000000000 -00100100000000000000101000100100 -00000010100010000000010000110000 -00000000000000000000000000000000 -10101000000101011011110000000000 -11001111000000000011100011000000 -00001100111100011000001110101101 -00100000111010000100000000111110 -10000000000010001001100000001011 -00000001000000001100101100000000 -00110010110000000000110010110100 -00001011001010100000010001100000 -00000000000000000000000000000000 -10000000000000001100110001000010 -11111011000000000011111001000000 -00001111101100000000001111101100 -10000000111110000000000000111010 -10000100001011111001000000000011 -11100000000000001111101101000000 -00111110010000000000111110110010 -00000011111000000000000000110000 -00000000000000000000000000000000 -00000001000100001111110000000000 -11001111000000000011111011100000 -00001101111100000000001100110000 -00000000011111001000000000111111 -10000000000011001101000100000010 -00110100000000001000110000000010 -00110011011010000010111011110000 -00000011100000000100010000110000 -00000000000000000000000000000000 -10000001000001000110110000000000 -10101011000000000010111001100000 -00001000001100000000001010100110 -00000000101110000100000000101100 -10000000000010001001000000000010 -00100010000000001000100011000000 -10100010010000000100101010101101 -10000010001000000100000000010000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10001011000000000010111011001000 -00001001101100000000001000101110 -00000000101110000001010000101110 -00001000000010100011000000000010 -10100010000000001010100110000100 -00100000110000001000101000000000 -00000010101000000000000001000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10100011000000000010110001000000 -00001000101100000000001010000100 -00010000101100000000000001101100 -00000000000010100011000000001010 -10100000000000001010000000000010 -00100000010000000000100000000000 -00000010000000100000000100000000 -00000000000000000000000000000000 -00000000000011010111110000000000 -11000111000000100011111001000000 -00001101101100000000001100100100 -00000000111110000000000000111110 -00000000000011100111000000100011 -10100000000000001110100000000000 -00010010010000000000111010000000 -00000011100000000000001101010000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11111111000000000011111101000000 -00001111111100000100001111010100 -00000000111101000000000000111101 -00000000000011011111000000000001 -01010000000001100101110000000000 -00111111010000001000111111000000 -00000011111010000000011001110000 -00000000000000000000000000000000 -11000000000001011111101000000000 -11111111001000000011001101000100 -00001100111010000001001111111010 -00000000111111101000000000111111 -11000100000011111100000000000011 -00111000000000001100110000000000 -00110011000000000000110011100000 -00000011001100000000000001110000 -00000000000000000000000000000000 -10000000000100001110101000000000 -10111111110100000010001101000000 -00001000100010000000001011101010 -00000000101110101000000000001111 -11011000000010111010100001000010 -00101110000010001000101010000010 -00100010101000000000100010101000 -00000010101000000000010000110000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10110011000000000010000001001000 -00001010001100000000001011000000 -00000000101100100000000000101100 -11000100000010110001000000001010 -00000000000000001000000000000000 -00100000010000000000100000110000 -00000010001000100000000101110000 -00000000000000000000000000000000 -11000000000101011010100000010000 -10111011000000000010001001000000 -00101010100000000000011011100000 -00000000101110100000000000101110 -11000000010010111011000000010010 -00101110001000001000101100000000 -00100010110010000000100010110000 -00000010101100000000010001100000 -00000000000000000000000000000000 -01000000000100011110100000000000 -11111011000000000011001001000000 -00001110100001011000001111101001 -00000100111110110100100000111110 -11000000000011111000000000000011 -00101001000000101100100100000000 -00110010000100100100110010001001 -10000011000100000000010001110000 -00000000000000000000000000000000 -11100000000000011011110001000000 -10111111000000100011111001100100 -00001101110010000000001111111010 -01001000111111111001000000111111 -11000000000011111110000000000011 -11101000000000001111011100000000 -10111101101000000000111100000000 -00000011111110000000000001100000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11110011000000000011111111000000 -00101100100100110000001111100101 -00100000111110110100001000111110 -11000000000011100011010000100011 -10000001000000101100101100000000 -00110010010000000000110010010101 -00000011000100000000010000100000 -00000000000000000000000000000000 -11001000000001010010111001000000 -10111111000001100010111011000000 -00000000100000000000001111101110 -10000000101110110001100000101111 -11000000000010001011000000000010 -00101000000000001000101100000010 -00110110110010001000100010010000 -00010010001100100000000001000000 -00000000000000000000000000000000 -11100000000001010100001100000000 -00110011000000000010111001000000 -00001000001011000000001011000101 -00000000101100101100000000101100 -11000000010010100000000001001010 -01000000000000001000000000000000 -10100000000000000000100000101010 -00000010001110000000000001010000 -00000000000000000000000000000000 -00100000000000010001001000100001 -10110111100000000010110101100000 -00001000010110000000001010010110 -00000000101101111000010000101101 -11100000100010000011101100000010 -01010110000000001000001010000000 -00100100111000000000100001101000 -00000010000010000000000001000000 -00000000000000000000000000000000 -01001000000010000000010000000000 -11110011000000000011110001000000 -00001100001100000000001011001000 -00000000111100100000000000111110 -11000000000011100001011000000011 -11000000100000001100000000000000 -00110000010000000000110000110000 -00001011000100100000001000000000 -00000000000000000000000000000000 -01000000000111011011000000100000 -11111111010000000011111101000000 -10001111110100001001011111111000 -00001000111111110000000000111111 -11010000010011111111001000010011 -10110100000000000111111100000000 -00111111110000000000111111110000 -00000011110100000000011001100000 -00000000000000000000000000000000 -10101000000001011110100100100000 -11011011101100000011001101001000 -00001111101001100000001111100101 -10001000111110000110000000111110 -11001000000011111000000000000011 -00111010000000001110100100000000 -00110010101000000000110010010000 -00000011001010100000000001110000 -00000000000000000000000000000000 -01001000000100011001110010000000 -10110111001000001010000101000100 -00001011011100001000001011010101 -10100000101101010010101000101101 -11010000000010110011000000000010 -00001100000000001000011100000010 -00100001110000000000100001110000 -00000010000100100000010001100000 -00000000000000000000000000000000 -11000000000000001001111000000000 -10010011100000000010000101100000 -00001011011110000000001011011110 -00000000101101001001000000101101 -11100000000010110111100000001110 -00010010000000001010001110000000 -00100000111000000000100000011000 -00000010001100000000000000100000 -00000000000000000000000000000000 -01001000000101001100110101100000 -10110011000000000010000001100000 -01011011001100000000001011001100 -00000000101100010010000000101100 -11000000000010110011000000000010 -00001101000000001000001101110000 -10100000111000000010100000111001 -01001010000100100000010000110000 -00000000000000000000000000000000 -11101000000101011010101000001000 -11011010000000000011001010101000 -00001111101000100000001111101000 -10000000111110100000100000111110 -10000000000011111110100000000011 -00111000110000101110011011000000 -00110011101010000000110011100100 -00000011001110100000010001100000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011111000000000 -00001111100001000000001111100010 -00000000111110000000000000111110 -00000000010011110000000100000011 -11100000000000001111100000000000 -00111110000000000000111100000000 -10000011110100100000000000110000 -00000000000000000000000000000000 -00001000000100001110011010000000 -11111001000000000011111001000000 -00001111100100000000001011100100 -00000000111110011000000000111110 -01000000000011101001000000100011 -00100100000000001111100100000000 -00110010010000000000111110010000 -00000001000000100000010000110000 -00000000000000000000000000000000 -10000000000000000110111000000000 -10111001000000100010111001000000 -00001011101100001000011111101100 -00000000101110111000000000101110 -01000000000010001001100000000010 -00100100000000001011100101000010 -00110010010100000100101110010100 -00000010001000000000000000010000 -00000000000000000000000000000000 -00011000000001010010010000000001 -10111001000000000010111001000000 -00001011100100000100001011101100 -00000000101110010010000000101100 -01000000000010101001000100000010 -00100100000011001011100100001100 -00100010010000100000101110010000 -10000010100001100000000001000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001001010010010110001001000 -00001011000100000000001010000100 -00000000101100010000000000101100 -01001010000110000001001000000010 -00000100100000001011000100100000 -00100000010010000000101100010010 -00000010100000100000000100000000 -00000000000000000000000000000000 -10111000000011010110000000000100 -11111000001000100011111000000000 -00001111100000000000001011100000 -00000000111110000000000000111110 -00001000000011101000000000000011 -00100000000000001111100000000000 -10110010000000000000111110000000 -00001011101011100000001101010000 -00000000000000000000000000000000 -10011000000111011110010000000000 -11111001000000000011111101001110 -00001111100100000000001111100100 -00000000111110010000000000111110 -01001010010011111101000100001011 -11110100010000001111110100010000 -00111011010001000000111111010001 -00000011011001100000011001110000 -00000000000000000000000000000000 -00011000000001011110010000000000 -11111001000010000011011001000100 -00001111100100000101001111100100 -00000001111110010000001000111110 -01011000000011111001001000000011 -00100100000000001100100100000000 -10110010010010000000110010010010 -00000011110001100000000001110000 -00000000000000000000000000000000 -00111000000100001110000000000000 -10111000010000000010001000010100 -00001011100000000000001001101000 -00000000101110000000000000101110 -00001000000010111000000000000010 -00100001010000001000100001010000 -00100010000100000000100011000101 -00000010110011100000010000110000 -00000000000000000000000000000000 -00001000000001011100010000000000 -10110001000000000010010001001000 -00001011000110000000001011000100 -00001000101100010000000000101100 -01011000000010110101110000000110 -00010100000000001000010110000000 -00100001011001000000100001011000 -00000010110000100000000101110000 -00000000000000000000000000000000 -00011000000101011010010000100100 -10111001000000000010001001000000 -00001011100100000000001001100100 -01000000101110010000000000101110 -01000000010010111001000100010010 -00110100000100001000110110000000 -00100011010000010001100011010000 -00000010110001100000010001100000 -00000000000000000000000000000000 -10100000000101011110010100001000 -11110001000000000011011001000100 -00001111100100000000001111100100 -00000000101110010000000000111110 -01000000000011111001110000000011 -00100110000000001100100100000000 -00110010010100000010110010010100 -00000011111010000000010001110000 -00000000000000000000000000000000 -00101000000000011010010000000000 -11111011000010000011111001000000 -00001111100100000000001111100110 -00000000111110010000001000111110 -01000000000011110001000000001011 -11000111000000101111000100000000 -00111110010000000000111110010000 -00000011110010100000000001100000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000000000111111000000000 -00001111100000000000001111100001 -00000000111110000000000000111110 -00000000000011001000001000001011 -00100010000000101100100000000000 -00110000000000000000111111000000 -00000011000010100000010000100000 -00000000000000000000000000000000 -00101000000001010010100000010000 -10111010100010000110111010000000 -00001011101011100001000011101010 -00100000101110101000000000101110 -10000000100010101010010000010011 -00101000000000001000101000000000 -00100010100000000000101110100000 -00000010000010100000000001000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110001000000000010110011000000 -00001011001101001000001011001100 -00000000101100110100100000101100 -11000000000010000011000000000010 -01001100000100001000001110000000 -00100000110000000000101100101000 -00000010000010100000000001010000 -00000000000000000000000000000000 -10100000000000010001110000000100 -10110101000000000010110111001000 -00001011010100000000001011011100 -00001000101101110000100000101100 -11101100000010100011000000001010 -00011100000000001000011101000000 -00100001010000000000101101101100 -00000010001010000000000001000000 -00000000000000000000000000000000 -10101000000010000001011000100000 -11110101100000000010110111110100 -00001111011110001000001111011110 -01000000111101111000100000111101 -11101010000011000101100000000011 -01001110000000001100001010000000 -10110001101000000000111100111000 -00001011001010100000001000000000 -00000000000000000000000000000000 -00001000000111011010010110000000 -01111001011010000011111011000000 -00001111100101100000001111101101 -10000000111110010000000000111110 -11000000000011111001000000000011 -11101100000000001111101000000000 -00111110000000000000111110110000 -00000011110000100000011001100000 -00000000000000000000000000000000 -00000000000001011111111000000000 -11001110100000000011111111100000 -00001100111110000000001100111110 -00000000110011001000000100110011 -11100001000011001110100000000011 -00111010000000001100110110000000 -00111111111000000000111111001000 -00000011000000000000000001110000 -00000000000000000000000000000000 -10101000000100011001110001010000 -11010110000000000010110111000001 -00001000010000000000001101010100 -00000000110101110000000000110101 -11000000000011010110000100000010 -00011000011010001101010100000010 -00101101010001000000101101000000 -00000010101010100000010001100000 -00000000000000000000000000000000 -00000000000000001011010000000000 -10000110000000000010110111000000 -00001000111100000000001000111100 -00000000100111000000000000100100 -11000000000010000100000000001010 -00011000000000001000010000000000 -00101101100000000000101100011000 -00000010000000000000000000100000 -00000000000000000000000000000000 -00100000000101001100010110000100 -10010010000000000010110011000000 -00001000000011000000001001000110 -00000000100100010100010000100100 -11000000000010010000011000001010 -00001001000000001001000001000000 -00101100000100000000101100010001 -00000010100010000000010000110000 -00000000000000000000000000000000 -10101000000101011010100000000000 -11001001000000000011111111000000 -00001100101000100000001100100010 -00000000110110110000000000110111 -11000000000011001011100000000011 -00000111000000001100101110000000 -00111110111000000000111110100000 -00000011001010100000010001100000 -00000000000000000000000000000000 -10000000000000001110010000000000 -11111001000000000011110011000000 -01001111101000000000001111101100 -01000000111110110010000000111110 -11000000000011111011100000001011 -11100100000000001110101110000001 -00111110011000000000111110100000 -00010011111000000000000000110000 -00000000000000000000000000000000 -00000001000100001111100000000000 -11111101000000000011101111000000 -00001101111100001000001111110001 -00000000111111110000000000111111 -11000000000011110001000000000011 -01110100001000001100111000001000 -00111111100000100000111111110000 -00000011110000000100010000110000 -00000000000000000000000000000000 -10000001000001000110011001100100 -10111001100101000010111011000000 -00001010101100000000001011101110 -00100000101110010000000000101110 -11000000000010111001000000000010 -00100100000100001000101000000000 -00101110000000001000101110110000 -00000010111000000100000000010000 -00000000000000000000000000000000 -10000000000001010010100000000000 -10111000000000000010111011000000 -00001001100100100000001011100000 -00000001101110000000000000101110 -11000000000010111010000000000010 -01100010000000001000100100000000 -00101110110000000001101110000000 -00000010111000000000000001000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110000000000000010110011000000 -00001010000010000000001011000100 -00010000101100110000000000101100 -11000000000010110010000000000010 -00000000000000001000000100000000 -00101100010000000000101100000000 -00000010110000100000000100000000 -00000000000000000000000000000000 -00000000000011010110100000010000 -11111000000000000011100111000000 -00001101100100000000001111100000 -00000000111110000000000000111111 -11000000000011111000000000000011 -01100000000100001100100000000000 -00111110100000000000111110010000 -01000011110000000000001101010000 -00000000000000000000000000000000 -10100000000111011101010000000000 -11111100000000010011111111000001 -00001111010000000000001111010100 -00000000111101010000000000111111 -11000001000011111100000000000011 -11010000000000001011110000000000 -00111111000000000000111111010000 -00000011111010000000011001110000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11111111110010000011001111011000 -10000100110010000000001100110010 -00000000101111110000000000110011 -00001000000011101100100000000000 -01110000000000001100010010000000 -00111111001000000000111111011000 -00100011001100000000000001110000 -00000000000000000000000000000000 -10000000000000001110110000000000 -10111111010000000010001111000100 -00001010100110000000001000000000 -00001000101111110000000000100010 -10110000000010001000000000010010 -00100000000000001010100010000000 -00101100000000000000101100010010 -00000010001000000000011000110000 -00000000000000000000000000000000 -10001000000001011000110000000000 -10110011001000000010000011001000 -00001010100100000100101000000000 -00000000101100110000000000100000 -10010000100010100000000000000010 -11001000000100001000000100000010 -01101100000000000000101100100000 -10000010001000100000000101110000 -00000000000000000000000000000000 -11000000000101011110110000000000 -10111011000000000010001011000000 -00111010100110000000001000101010 -00100000101110110000000110100010 -10100010010010001000100010000010 -10101010001100001010100100000000 -00001110000000001000101110100000 -00000010001100000000000001100000 -00000000000000000000000000000000 -00000000000001011110110000000001 -11111011000000001011000011000000 -01001100000010100000001100100010 -00000001111110110000000000110000 -10000000000011101000110001000011 -11100000000000001100100000000000 -00111110001000000000101110010000 -00001011000000000000010001110000 -00000000000000000000000000000000 -11100000000100011011110000000000 -11111111000000000011111011000000 -00001101110100000000001111111000 -00000000111101110000010000111111 -10000000000011111100000000000011 -01110000000000001111110000000000 -00111111000100010000111111010000 -00000011111110000000000001100000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011000000000011111011000000 -01001100100100011000001110100001 -00000000110010110000001000111110 -10010000010011001000010010001011 -00111000010100001110100100000000 -00111010000000100000111010100010 -00001011000100000000010000100000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10111111000001000010111111001000 -10100000100111000000001000101000 -00000000101011110000000000101110 -10100000000010001000110000100011 -01101000000000001000100100000000 -00100010000010010000100010101100 -00000010001100100000000001000000 -00000000000000000000000000000000 -11000000000001000000110000000000 -10111011000000100010110011000000 -10001001001001000000001010001000 -00000000100000110000000000101100 -10001000001010001000110000001010 -00100110100000001010000010010100 -00101100110000000000101010011000 -00000010011100000000000000010000 -00000000000000000000000000000000 -00100000000000010001111000000000 -10110111100000000010110111100100 -10001001111110000001001000011010 -00000001101001111010000000101101 -11100101000010001100100000100010 -01011110000000101000010010010000 -00101101111001000000100001011000 -00000010010110000000010000010000 -00000000000000000000000000000000 -01001000010110000000110000001000 -11110011000000100010110011000100 -00001101001100000000001110001000 -00000000110000110001000000111100 -10000110000011000000001010010011 -00101100100000101110000100000000 -00111100110101000000111000100000 -10000011010100100000001000010000 -00000000000000000000000000000000 -01000000000011011011110000000000 -11111111000000010011111111010100 -00001110011100000000001111111000 -00000000111111110111100000001101 -11000100000011110111000000000011 -11111000000000001111110100000001 -00110011110001000000111111101000 -00000011100100000000010001100000 -00000000000000000000000000000000 -00001000000001011110110000000000 -11111011001000000011111011010000 -00101100001010000000001100101010 -00000000110010110100000010110000 -10011010000010011000000000000011 -01100100000100001100000010000000 -00110110110000000000110010010000 -00001011000000100000000001110000 -00000000000000000000000000000000 -01001000000000011001110000000000 -10110111010010000010110111001000 -00101000010100000000001010111100 -00000000110100110010000000100001 -11000000000010001100000000000010 -00011100000000001000010000000000 -00100011110000000000110001010000 -00000010000100100000011001100000 -00000000000000000000000000000000 -00100000000000001001111000000000 -10110111101000000010110111100100 -00011000111011000000001000011010 -00000000100001111000000000100001 -10100010000010010100100000010010 -01111110000010001000010110000000 -00100101111000000001100011101000 -00000010000010000000000000100000 -00000000000000000000000000000000 -01101000000101001100110000000100 -10110011000000000010110011000000 -00001000001101001000001010001111 -00000000100110110000000000100000 -11100000010010000011000000000010 -01001100000000001000000100000000 -00100000110000000000100010100000 -00000010000110100000000000110000 -00000000000000000000000000000000 -11101000000001001010100000000000 -11111010000000000011110010000000 -00101100111011000000001100111010 -11000000110010100000000000110000 -10000000101011010110000000001011 -01111001000000101100101000000000 -00110100100000000010110010100000 -00000011001110100000010001110000 -00000000000000000000000000000000 -01001000000100001010000000000000 -11111000000000000011111000010000 -01101111100001000000001111100000 -00010000111110000000000000111110 -00000001001011111000000000010011 -10000000100001001111100000000000 -00111110000000001000111011000000 -00000011110100100000000001100000 -00000000000000000000000000000000 -00001000000100001010010000000000 -11111001000000000011111001100000 -00001100100100000000001111100100 -00000000111110010000000100110010 -11000000000011001001100000001011 -00100100000000101100100111000000 -00111110010000000000110010010000 -00000011000000100000010000100000 -00000000000000000000000000000000 -10000000000001000010010000001000 -10111001000000000010111001010000 -00101010100111100010001011100100 -00000000101110010000000000101010 -01000001000010001001100100001010 -00100110000010001010100110000000 -00101110010110000000100010010000 -00000010101000000000000000010000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010111001001000 -00001000100100100000001011100100 -00000000101010010000000100101010 -01000000000010001001000000000010 -00100100100000001000100100000000 -00101111010000000010100011010000 -00000010000011100000000001000000 -00000000000000000000000000000000 -00001000000001001000010000000000 -10110001001000000010110001001000 -00001010000100000000001011000100 -00000000001100010010001000101000 -01101001001010001001000000001110 -00000100100000001000000100000000 -00101111010000000000100001010000 -00001010100010100000010100000000 -00000000000000000000000000000000 -10111000000111010110000101000000 -11111000010100000011110010010100 -00001100100000000100001111100001 -01000000111010000101000000110010 -00000000000011001000010101000011 -00100001010010001100100000000100 -00111110000101000000110011000101 -00000011001011100000001101010000 -00000000000000000000000000000000 -10111000000111011110010000000000 -10111001000100100011111001000100 -00001111110100000000001111110100 -00000100111110010001000000111110 -01000100000011111101000000010011 -11010100010000001111110100000000 -00111110010000000000111100010000 -00000011011001100000010001110000 -00000000000000000000000000000000 -00111000000001011110010000000000 -11111001000000000011001101000110 -00001100110100000000101100100100 -00000000110010010110000000111011 -01000010000011001101010000000001 -11110100010000001100110100000000 -00110001010100000000110011010000 -00000011001001100000000101110000 -00000000000000000000000000000000 -00011000000100001110000010000000 -10111000001000100010000000010000 -10001000100000000000001000100000 -10001000100010000100010000110110 -00010000000011111000001000001010 -00101000000000101000100000000000 -00100010000010000000111100000010 -10001010000011100000011000110000 -00000000000000000000000000000000 -01001000000000001000010000101000 -10110001010010000010000001001000 -00101000100110000000001000100100 -00100000100000010011000100100000 -01000000000010001001001000000110 -11000101100000001000100110000100 -00100000010000000100100100010000 -00001010100100100000000101100000 -00000000000000000000000000000000 -00011000010101001010010000010000 -10110001000000000010001001000000 -00001000101100000000001000100100 -00000010100000010000001000100110 -01000000000010111001000100001110 -00100100000001101000100100000000 -10100010010000000000001010010000 -00000010100001100000000000100000 -00000000000000000000000000000000 -10100000000001001010010000000000 -11111001000000001011001001000000 -00001100100110010000001100000100 -01000000110010010000000000111010 -01000000000011001001000011000011 -11100111000000001100000100000000 -00110010010000000010100110010110 -00000011101010000000010001110000 -00000000000000000000000000000000 -01101000000100001010010000000000 -11111001000000000011111001000000 -10001111100110000001001111100110 -00000000111110010000010000111110 -01001000000011111001100000001011 -11100100010000001111100100000000 -00111110010000000100111110010001 -00000011010100100000000001100000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11001000000000000011111000000001 -00001100100000000000001111100000 -00000000111010000000000000111100 -00000010000111001000000000000011 -00100011000000001100100000000001 -00111110000000001000110010000100 -00000011000000100000010000100000 -00000000000000000000000000000000 -00001000000001000010100000000000 -10001010000000000010110110000000 -00101000011010000001001011101000 -00000000101110100000000000101111 -10110000000010100110100000000010 -00111000000000001000111000000000 -00101111101000000000100011100000 -00000000000010100000000001000000 -00000000000000000000000000000000 -00001000000001010100110000000000 -10000011000000000010110010100000 -00001010001110100010001011001100 -00000000101000110000000000101100 -11010000000010000011100110000110 -00101110000000001010001100010000 -00101110110001000001101010110000 -01000010000010100000000001010000 -00000000000000000000000000000000 -00100000000100010001111011000000 -10000111001000000010110110010000 -00101010011100001000001011011100 -10000000101101110010010000101101 -10010000000010101111000000000010 -00011001000100001000011100000000 -00101111010000000000101001110000 -00000010001000000000010001000000 -00000000000000000000000000000000 -00101000000010001011111000000010 -11000111101100000011110110100000 -00101110011110000000001111011111 -00000000111001111011000000111100 -11100000010010000111100000001011 -00000110000000101110011110000000 -00111101111000000000111001111000 -00001011001000100000001000000000 -00000000000000000000000000000000 -00001000000101011010110110100000 -11111011000000000011111010000000 -00001101101100000000000111101100 -00101000111110110000000000111110 -10000000000011110011000000000001 -10101000000001001111101100000000 -00111110000000000010110110110000 -00000011110000100000010001100000 -00000000000000000000000000000000 -01100000000001001011111000000000 -11111111100010000011101110100000 -01001100011110000010001100111110 -00000001111111111001100000111001 -11100000010011000101100000000011 -00111010000000001100011110010000 -00110011011000000000111111111000 -00000011000100000000000000100000 -00000000000000000000000000000000 -10101000000100001001110000000000 -10110111000000100010000110000000 -00001000010100000000101000011100 -00000000111101110001000000111101 -00000010000010000100000000001010 -00111000010000001000011100000000 -00100001010001000000101101110000 -10000010001010100000011000100000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110011000000000010110110000000 -00001001111101000000001000011100 -00100000101101110000000000101101 -11000000001010001101000100000010 -00010001001000001000111100000000 -00100101010000000000101101110000 -00000010000001000000000000100000 -00000000000000000000000000000000 -01000000000101001000110000010000 -10110011000000000010010010000000 -00000001000100000000001000001111 -00000000101100110000000100101100 -00110000000010000000010101000010 -00101010000000001000001100000000 -00000100000000000000101100111100 -00000010000110000000000000100000 -00000000000000000000000000000000 -10101000000001011011110000000000 -10111111000000000011111000000000 -00001101001110000000001100111111 -00000000111111110000000000111000 -11110000000011001001110000000011 -00101110000000101100100100000000 -00110110110000000100111110110100 -00000011001010100000010001100000 -00000000000000000000000000000000 -10100000000100001110110000000000 -11111011000000000011100000000000 -01001110101110000000001111101100 -10000000111010110000000000111010 -10000000000011111001000001000011 -11101000000000001111100100000000 -00111010110000000000111110000100 -00000011111001000000000000110000 -00000000000000000000000000000000 -00000001000100001111110000000010 -11000111000000000011001111100000 -00001100110100000000001100111100 -00001000101111110000000000111111 -11000010000011011101000010010011 -00110100000000001100110110000000 -00110011111100000000110011110000 -10000011001010000000010000110000 -00000000000000000000000000000000 -10000001000001000110110000001000 -10001011000000000010001011000000 -00101000100110000100101000101100 -00000000101110110000000000101110 -10111000000010100011100000000010 -00101010000001001000000110000100 -00100010101000001000100010001101 -00000010001011000100000000010000 -00000000000000000000000000000000 -10000000000001010000110000000000 -10001011000000000010001000010100 -00001000101110000000001000101100 -00000000101110110000000000101110 -01100000000010011001100000000010 -00100010000000001000100100100000 -11100000010000000000100000110100 -00100010001000000000000001000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10000011000000000010000010000000 -00001000000100000000001000001100 -00000000101100110000000000101100 -00000000000010001000000000001010 -00000000000001101000000100000000 -00100000010000000000100000000000 -00000010000000100000010100000000 -00000000000000000000000000000000 -00000000000011010111110000000000 -11001111000000001011000011000000 -00001100100100000000001100111100 -00000000111111110000000000111110 -01000000000011011001000000001011 -00100000000010001100100100000001 -00110010010000000010110000110000 -00000011001000000000001101010000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11111111000000000011111111000000 -10001111110000000000001111111100 -00000000111111110000000000111111 -01000000100011111100000000000011 -11110000000100001111111100000000 -00111111000000000000111111000000 -00000011111010000000000001110000 -00000000000000000000000000000000 -11000000000101011101111000000000 -11111110100000010011111110100000 -00001111111100110010001101111100 -11000000111111011000010000110001 -01100000000011001101000000000011 -00110000000001001101110010000000 -00110011101000000000110011110000 -00000011001100000000000001110000 -00000000000000000000000000000000 -11000000000010001110111000000000 -10001010100001000010111000100000 -00001011111100100000101000111100 -01000000101110010000000100100010 -00000000000010101000100000000010 -00100110000000001011100100000010 -00100010110000001100100010000000 -00001010001100000000010000110000 -00000000000000000000000000000000 -11001000000001011100110000000000 -10100011000000000010110010000000 -00001011001100010000001011001100 -00000000101100010010100010101010 -01000000000010000001000000000010 -00000000000010001001000000000000 -10100010110000000000100000110000 -00000010001100100000000101110000 -00000000000000000000000000000000 -11000000000001011010110000000100 -10101010000000000010111000010100 -00001011001100000000001010101100 -00000000101110010000000000100010 -11100000000010101000100000000010 -00101110001000000011000110001000 -00100010110000100000100000111100 -00000000001100000000010001100000 -00000000000000000000000000000000 -10000100000100011110110000000000 -11101010000000000011111010100000 -00001011101100000010001111101100 -00000000111110110000000000110000 -01101000000011001000101000001011 -00100110000000001101100110000000 -00110010110001000000110010111000 -00000001000000000000010001110000 -00000000000000000000000000000000 -11100000000000011011110001000000 -11011110000010000011111100000001 -00001111111100000100101001111100 -00000000111111110000000000011111 -11000000000011110000000000100011 -11100100000000001111111100000010 -00111111110000000000111111000000 -00000000111110000000000001100000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11011011000000000011111011010110 -00001110101100000000001100101100 -00000000111110010000000000111110 -01010000000011001011000000000011 -00100100000000001100101101100000 -00111110110100000100110010111100 -00001011000100000000010000100000 -00000000000000000000000000000000 -11011000000001010000111000000000 -00001010000010000010111001010000 -00001011111100000000001101111100 -00000000101110010000000000101110 -11000000000010101010100000010010 -00101110000100001000101101000000 -00101100111000000000100010111000 -01100010001101100000000001000000 -00000000000000000000000000000000 -11000000000001000000110000000000 -10010010110000000010110001010000 -00001011001100000000101010001100 -00000000101110010000000000100100 -01000000000010000001000000010010 -00001110000000000010000100000000 -00101100111000000000100000110000 -00000010101110100000000001010000 -00000000000000000000000000000000 -11110000000000000011011000000001 -10000111100000000010110101100000 -00001011011110010000001001011110 -00000000101101011000010001101111 -11100000000000100111110100000010 -00011110001000001010010110000000 -00101101111000000010100011111000 -00000000101111000000000001000000 -00000000000000000000000000000000 -01001000000110000000110010100010 -11010011000000000111110010000000 -10011111101100000000001110001100 -00000000111100010000000000111100 -01000100000011000001000010000011 -00000000010000001110000100000000 -00111110110000100100110000110000 -00001011100100100000001000000000 -00000000000000000000000000000000 -11000000100111001011110000000000 -11111111000000000011111110000010 -00001111111100000000001101111101 -01000000111111010000000000111111 -11000000000011111111000001001011 -11111100000000101101110100010000 -00111111110001000000111101110000 -00000011010100000000011001100000 -00000000000000000000000000000000 -00001000000001011110110000000000 -11011010010000000011111001010000 -00001111101101110000001100101101 -11000000111110110000000000111110 -01000000010011111001100000000011 -00101100000000001111101100000000 -00111100110000000000110010110000 -00000011001010100000000001110000 -00000000000000000000000000000000 -11001000100000011001110000000000 -10000111001010100010110101001010 -00001011111100110000001000011100 -00000000111001110000000000101101 -11000000000010110101000001000010 -00011100000000001011011100000000 -00101101110000000000100001110000 -00000010001100100000010001100000 -00000000000000000000000000000000 -00100001000000001011111000000000 -10010111100100000010110111100000 -00001011011110000000101000011110 -00000000101001011000000001101101 -01100000000010110011100000000010 -01010110000000001011011110000000 -00101111111000000000100001111000 -00001010001000000000000000100000 -00000000000000000000000000000000 -01101000000101001100110000001000 -10000011000000000010110011000000 -00001011001100000000001000001100 -00000000101000010000000000101100 -11100000000010110011110100000010 -01001101001000001011001111100000 -00101100010111000000100000110000 -00000010000100100000010000110000 -00000000000000000000000000000000 -11100000100001001010101010001000 -11011010000000000011111010010000 -00001011101000000000001100101000 -00000000111010100010000000111111 -10000010000011111110110100000011 -01111001000000001111111011000010 -00111111101100000010110011100000 -00000011001110100000010001100000 -00000000000000000000000000000000 -01001000000100001010000000000000 -11111000010000010011111000010010 -01001111000000000000001111100000 -00000000111010000000000000111110 -00000010100011111000000000001011 -10100001000001001111100000010001 -00111110000000000000111110000000 -00000011110100100000000000110000 -00000000000000000000000000000000 -00001000000100001010010000001010 -11001001000000000011111001000000 -00001111100100000000001100100100 -00010000111110010000000000110010 -01000000000011111001100000000011 -11100100000000001111100100000100 -00110010010000000000110000010000 -00000011000000100000010000110000 -00000000000000000000000000000000 -10000001010001000000010000000000 -10001011000000000010111011101000 -00000011100100000100001000100100 -00000000111100010000000000100010 -01000000000010111001100000000010 -11100111100010000011100100000110 -00100000010100001000110110011000 -11000010001000000000000000010000 -00000000000000000000000000000000 -00011000000000010010010000000000 -10001011000000000010111001000100 -00001011100100000000001000100100 -00010000101110010000000000100010 -01000000000010111001001000000110 -11100100010000000001000101100000 -10100010010110000100100010010001 -00000010000001100000000001000000 -00000000000000000000000000000000 -00001000000001000010010000010000 -10000011000000010110110001000000 -01001011000100101000001000000100 -10100000101110010000000000100000 -01000000000010110001101000000010 -11000100100000001011000100000000 -00100010010000000000100100010010 -00000010000000100000000100000000 -00000000000000000000000000000000 -10111000000111010110000000000000 -11001000000000000011111000000000 -01001111100000100000101100100000 -10000001101110000000000010110010 -00010100000011111000000000000011 -11100000000000001111100001010000 -00110010000101000000110000000101 -00001011001011100000001101010000 -00000000000000000000000000000000 -11111000100111011101010000000000 -11111001000000000011111001000000 -00011111100100101001101111100100 -10100000111011010010100000111111 -01000000000011111111000100000011 -11110100010010001111110100000000 -10111111010000000000111111010001 -00000011111001100000011001110000 -00000000000000000000000000000000 -10111001000011011111010000000000 -11111001000000000011111001000000 -01001111100100101000001101100100 -11000000111110010100000000111100 -01010000000011110101001000000011 -00110100000010001111110100010000 -00111110010000000000110010010010 -00000011001001100000000001110000 -00000000000000000000000000000000 -01011001000000000110000000000100 -11101000000000000010111000000000 -00001110100000100000001010100010 -01000000101110001000000000101110 -00001000000010111000000000010010 -00100001010000001011100000000000 -00101110000010100010100011000110 -10000011000011100000010000110000 -00000000000000000000000000000000 -01001000000000000000010000001000 -10110001100000000010110001000000 -10011011000100101000001011000100 -10000000101100010000000000101100 -01001000000010110001010001000010 -00001110000000001011000100100000 -00101101011000000000100001010001 -00000010010100100000000101110000 -00000000000000000000000000000000 -00011000000101001010010010010000 -10101001000000110010111001000000 -00000010000100000000001010100100 -00000000101110010000000000101110 -01010100000010111011100000010010 -00100100010000001011101100000000 -00101101011000000010100011010010 -00000010000001100000010001100000 -00000000000000000000000000000000 -10100000100001001010011000001000 -11111001000000000011111001111001 -00000111100100000000001111100100 -00000000111110011000000000111110 -01010000000011111001110000001011 -00100110000000001111100110000000 -00111110010000000000110010010010 -00000011011010000000010001110000 -00000000000000000000000000000000 -01101010000100001010011000000000 -11111001000000100011111001100100 -00001111100100000000101111100100 -00000000111110010010000000011110 -01100000000011110001000011000011 -11100110000000001111100101000000 -00111110010000000000111100010000 -00001011110110100000000001100000 -00000000000000000000000000000000 -01101010000100001010000000000000 -11111000000000000011111000010010 -01001111100000000000101110100000 -00011000110010000000000000111110 -00000001100011001000010000000011 -00100010000000001111100000000000 -00110010000000000000110010000100 -00000011000010100000010000100000 -00000000000000000000000000000000 -10000000000001000010101000000000 -10111010100000000010111010101000 -00001011101000000000001010101000 -00010010100010100000011000101110 -10000000011010001110101001000010 -00111000000001001011101000001000 -00100010100000100000100010100000 -00000010000010100000000001000000 -00000000000000000000000000000000 -01001000000001010100011001000000 -10110011100000000010110011000000 -00001011001100000000101010001100 -00000000100000110000000000101100 -11000000000010000010010000000010 -00000100000000001011000100000000 -00100000110000000010100000111000 -00001010000010100000000001010000 -00000000000000000000000000000000 -01100001000000010001110000000000 -10110110000010000010110111000000 -00011011011100000000001010011110 -00001000000001110000010000101111 -11101000000010000101000000001010 -00010100000000001011010010000000 -00100001110000000000100001110000 -10000010001010000000000001000000 -00000000000000000000000000000000 -00101000100000000001011000000000 -11110111100000000011110111100000 -00001111111110010000101110111110 -00000000010001111000010000111101 -11110000000011000101100000000011 -00010110000000001111010110000000 -00110011101000000000110011101000 -00001011001010100000001000000000 -00000000000000000000000000000000 -01001010000101011010110000000001 -10111011011010000011111000000010 -00001111101100000010101111101100 -00000000111110110000001000111110 -11000000000011111001000000010011 -11100100000001001111000000000000 -10111110100000000000111110100110 -00000011110000100000011001100000 -00000000000000000000000000000000 -11100010010001001011111000001101 -11111111100100000010111101100100 -00001101111110001000001110111110 -00010010100011111001000001111111 -11100000000011111110100000000011 -00010110010000001100110110000000 -00110001111000000100110011111100 -00001011010100000000000001110000 -00000000000000000000000000000000 -10101001000000001001110000001000 -11100100000000000010110111010000 -00001101011100010000001000011100 -10000000100001110001000101101101 -11001000000010110101000100000010 -00010100000010001000010000100000 -00100001110000000000101001110001 -00000011111010100000010001100000 -00000000000000000000000000000000 -00010010000000001001110001000000 -10100111000000100010111101000000 -10001000011100000000001011011100 -00000100100001110001010000101101 -11000010000010110101010000000010 -00010100000010001000110100001000 -01100011100100000000100001100000 -00000010000001000000000000100000 -00000000000000000000000000000000 -01000000000101001000110001000100 -10100001010000000010110000000000 -01001001001100000000001001001100 -00000000100000110000000000101110 -11110000000010110001100001000010 -00001101000000001000000011000000 -10100000100000000000101000101101 -00000010110110100000010000110000 -00000000000000000000000000000000 -11111000000000010010011000000000 -11101001000000000011111010000000 -00001100111100000000101111111100 -00000000100011110000000000111111 -11110100000011111010010010000011 -00100110000100001100100110000000 -00110000010000000000110010010100 -00000011001011100000010001100000 -00000000000000000000000000000000 -10100100000100001110110000000000 -11101001010001000011111010010100 -00001111101100000000001110001100 -00000000111110110000000000111110 -11000000000011111001000000001011 -11100110000000001111100101000000 -00111110011000000100111110010000 -00100011111000000000000000110000 -00000000000000000000000000000000 -11000001000100001111010000001100 -11001101010010000011001111000000 -00001111101100000000101100101100 -00000000110011110000000000111111 -11000000000010101111000000000011 -11010000001000001100110100011000 -00110011000100000000110010000100 -10000011001000000000010000110000 -00000000000000000000000000000000 -10000001010000000100110000010000 -10100001010000000010101000010000 -00001110101100000000001101101100 -00001000100010110000001000101110 -11000000000010001001110000000010 -11100001001000101000100000000001 -00100010000000000000100010000000 -00000010001000000000000000010000 -00000000000000000000000000000000 -10000000010001010110110000001001 -10011011010000000010101001000000 -01001011001100000000011000101100 -00000000100010110000000000101110 -11000000000010101011100000000010 -11100100000000001000001100000000 -00100010010000000100100000010000 -00000010001000000000000001000000 -00000000000000000000000000000000 -00001010000000000010110000000000 -10101001000000000010100011000000 -00001011001100000000101001001100 -00000000000000110000000000101100 -11000000000010100001000000000010 -11000100000000001000001100000000 -10100010110000000000100000110000 -00001010000000100000000100000000 -00000000000000000000000000000000 -10000000000110000110110000000001 -11011011000000100011101001000000 -00001111111100000000001100101100 -00000000110010110000010000111110 -11000000000011101001000000000011 -11100100000000001100100100000000 -00110010000000000010110010000000 -00000011001000000000001101010000 -00000000000000000000000000000000 -10100010000111011111110000000000 -11111101000000000011110100000000 -00001110111100000000001111111100 -00000000111111110000001000111111 -11000000000011010101000000000010 -11111100000000001101010000000000 -00111111000000000000111111000000 -00000011111010000000011001110000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11000100100000000011001100001000 -00001100011000000000001100111110 -00000000111111110100000000110011 -11000000010011110100100000000010 -00111100000000001100111100111000 -00110011011000000010110011101000 -00000011001100000000000001110000 -00000000000000000000000000000000 -10000000000100001110011000000010 -10001000100000000010001010110000 -01001000100001000001001000100110 -00000000101111110111000000101011 -11000000010010111000100000000010 -00111101010000001000111101000100 -00100010110000000000100010011000 -00010010101000000000010000110000 -00000000000000000000000000000000 -10001000000001011110110000000000 -10001010000000001010000010000100 -00001000001001000000001000001100 -00000000101100110000001000100000 -11000000000010110011000000001010 -00001100000000001000001100100000 -00100000010000000010100010010000 -00001010001000100000000101110000 -00000000000000000000000000000000 -11000000000101011010010000000000 -10001010000000000010001010100000 -00001000100100000000001000101100 -00010000101110110000000000101010 -11000000000010111001110000101010 -00101100000000001000001100000000 -00100010110000000000100010011000 -00000010101100000000010001100000 -00000000000000000000000000000000 -00000000000101011100110000000000 -10001000000000000011001001100000 -00101000101000001000001100101100 -00000000111110110000000000110010 -11000000010011111000110000001011 -00101100000000001100101100000000 -00110010010000001000110000001000 -00000010000000000000010001110000 -00000000000000000000000000000000 -11100000000000011011010001000000 -11111100010010000011111111000000 -00001111111000000000001111110100 -00000100111111110000001000111111 -11000000000011111100000000000011 -11111100000000001111101100000000 -00111111111100000000111111010000 -00000011111110000000000001100000 -00000000000000000000000000000000 -01000000000100001010110010000000 -11111010000000000011001010100000 -00001101101000100000001100101100 -00000000111110110000000000110010 -11000000000011111011100001000000 -00101100001000001100101100000000 -00110010010000100000110010010000 -01000001000100000000010000100000 -00000000000000000000000000000000 -11001000000001010010010100000000 -10110010000000000010000010000000 -00001000001011100000001000101101 -01000000101111110000000000100011 -11000000000010110000100000000010 -00111110000010001000111100000000 -10100010111100000010100010010010 -00000011011100100000000001000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10110001000000000010010000000001 -00001000001001000100001000001100 -00000000101110110000000000100000 -11000000000010110000000010000010 -00101101000000001000001110000000 -00100010111000000000100000000000 -01000010001110000000000001010000 -00000000000000000000000000000000 -00100000000000010001111000000000 -00110100100000000010011100110100 -01001000110010000000001000010110 -00000000101100111000000000100001 -11100000100010110100100100000010 -00011110001000011000011111001000 -00100001111001000010100001011100 -00000010010110000000000001000000 -00000000000000000000000000000000 -01001000010010000000110000000000 -11110001010000001011010000000100 -00001100001000000100001100001100 -00010000111100110001000010100000 -11000001100011110001000000000011 -00101100000000001100001100010011 -00110010110000110000110000010000 -00000011000100100000001000000000 -00000000000000000000000000000000 -01000000000111011011110000000000 -11111100000000000011100100000101 -00101110110000000000001111111100 -00000000111111110100001100111111 -11000000000011111101000000001011 -11111100001000001011111100000000 -00111111110000000010111101010000 -00000011110100000000011001100000 -00000000000000000000000000000000 -10101000000001011110110111000000 -11111001000000000011110001000000 -00001100101000000000101100101100 -11100000111110110000000000110110 -11110010000011100000000000000000 -10101100100001101100101100101000 -00111110110000000010110010000000 -00000011111010100000000001110000 -00000000000000000000000000000000 -01001000000100011001110010100000 -10110100000000100010110111000000 -01001000011000000000001000010100 -10000000101101110110000000100111 -11010000000010000101000000000010 -00011100001000001000011101000000 -00101111110000000000101001010000 -00010010110100100000010001100000 -00000000000000000000000000000000 -11000000000000001001111010000000 -10110100100000000010111110100000 -00001000011010000000001000011110 -10000000100001111010010001101101 -11100000010010101101100000000110 -10011110100010001000011110000000 -00101101111000000000100101011000 -00000010111100000000000000100000 -00000000000000000000000000000000 -01001000000101001100110000001000 -10110000010010000010110010001000 -00000000001011001000001000001100 -00000000101100110000000001101100 -11000000000010000001000000000010 -00001100000000000000001100000000 -00101110110000000000101100010000 -00000010110100100000010000110000 -00000000000000000000000000000000 -11101000000101011010100000001100 -11111110000000100011111110010000 -00100000111011100000000100101000 -00000000110010100000000000111110 -10000000000011101110010000000011 -10101000000000000100101000000001 -00111110100000000000110111100000 -00000011111110100000010001100000 -00000000000000000000000000000000 -01001000010000001110000100000000 -11111000010001000011110000010100 -01001111000000000000001111100000 -00000000111110000000000000110110 -00000000000011111000001000000011 -11100000000001001111100000000000 -00111110000000000010111010000000 -00000011110100100000000000110000 -00000000000000000000000000000000 -00001000000100001110010001000000 -11111001000000000011111001000000 -00001100100100000000101100100100 -10000000111110010000000000111110 -01000000000011111001100000000010 -01100110100000000100100100000000 -00100010011000000000100010010000 -00000011110000100000010000110000 -00000000000000000000000000000000 -10000000000001000110110100100000 -10111001010010110010111001010000 -00001000100101000000101000101110 -00000000101110010000000000101110 -01000000010010110001010000000010 -00100110000001001000100100000000 -00100010011101000010100010010000 -00000010111000000000000000010000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010111001000001 -00001000100100001000001000100100 -00000000101110010000000000101110 -01000000000010111001000100000010 -11000100000000101010000100010000 -00101010010000000100101010010000 -00000010110001100000000001000000 -00000000000000000000000000000000 -00001000000001001000010000000000 -10110001000000000010110001001001 -00001000000100100000001000000100 -00000000001100010010010000101100 -01001000000010111001000000000010 -10000100100000001010000100100000 -00101000011000000001101000010000 -00000010110000100000000100000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11111000000000000011111010000000 -00101100100001010000101100100000 -00000000111110000101000000111110 -00010100000011111010000000010011 -11000001010000001110100001010000 -00111010000101000010111010100000 -00100011111011100000001101010000 -00000000000000000000000000000000 -10011000000011011110010000000000 -11111101000000010011111101000100 -00000111010100010000001111100100 -00000000111110010001000000111110 -01000100000011111101000000000010 -01100100010000001101100100010000 -10110111010000000000110111010000 -00000011111001100000011001110000 -00000000000000000000000000000000 -00011000000001011110010000000000 -11111001000000000011011101000000 -00001100010100100000001100100100 -00000100111110010000100000111110 -01000000000011111101000000000011 -10110100010000001100110100010000 -00110011010000000010110011110000 -00000011001001100000000001110000 -00000000000000000000000000000000 -00111000000100001110000000000000 -10111000000000010010001000010100 -00001000100001101000000010100000 -00000000101110000100000000101110 -00010100000010111000000000000010 -00100001010000001000000000000000 -00100010000010100000100010100000 -00100010000011100000010000110000 -00000000000000000000000000000000 -00001000000001011100010000000000 -10111001100000000010010001000000 -00001010000100010000001000000100 -00000000101100010010100000101100 -01001010010010110001000000000110 -10000100100000101000000101100100 -00100010010000000000100000110000 -00000010010000100000000101110000 -00000000000000000000000000000000 -00011000010101011010010000000000 -10111001100000000010001001000000 -00001001000100001000001010100100 -00000100101110010000000000001110 -01000000000010111001001000000010 -00100100000000001010000100000000 -10101010010000000100000010110001 -00000010010001100000010001100000 -00000000000000000000000000000000 -10100000000101001010010000010100 -11110001000001000011011001001000 -00001110100101000000001100100110 -01000000101110010000000000011110 -01000000000011110001111000000011 -10100100000100001100100100000000 -00100000010000000000110000011000 -00001011011010000000010001110000 -00000000000000000000000000000000 -00101000010000001010010000100000 -11111011000000100011111001001000 -10101110100100000000001111100110 -00010000111110010000000000111110 -01000000000011111001100010000011 -11100100000000001101100100000000 -00110110010000100000111110011000 -10010011100010100000000001100000 -00000000000000000000000000000000 -00101000000100001010000001000000 -11111000000010000011110000010000 -01001101100001000000101101100000 -01111000111110000000010100111110 -00000000000011001000000100000011 -00000000001000001111100000001000 -00110010000000000000110010000100 -00000011110010100000010000100000 -00000000000000000000000000000000 -00101000000001000010100100000000 -10111010010001000010111110110000 -00101000111000100000001000101011 -00000000101110100000010100101110 -10000000000010001110100000000011 -01111000001001001011111001000000 -00100011101000000000110111100000 -00000010110010100000000001000000 -00000000000000000000000000000000 -00101000000001010100110100000000 -10110011010000000010110010110011 -10101000001000000000001001001101 -00000001101100110000001000101100 -11000000000110000011000000000110 -01001111000000001011000101000000 -00100000111000000100101000110100 -00000010110010100000000001010000 -00000000000000000000000000000000 -00100000000000010001100000000100 -10110111000000000010110110000010 -00001000011000000000001000011000 -00000000101101110010000000101100 -11101000000010000110000000000010 -01011100000000000011010100000000 -10100001110000100000101101110000 -00000010111010000000000001000000 -00000000000000000000000000000000 -00101000000010000001111001000000 -11110111100100010010110010100000 -00101100011110000100001101010110 -00110000101101111010001000111101 -11101100001011000111100000000011 -01011110000000001111011110000000 -00110011111000001000111001111000 -00000011111010100000001000000000 -00000000000000000000000000000000 -00001000000011011010100000010000 -10111011010000000011111011000000 -00001110101001000000001111100000 -00000000111110110110100000011110 -11011100000011110011000000000011 -11101100000000001111100100000000 -00111110010000000000110110110000 -00000011110000100000011001100000 -00000000000000000000000000000000 -01000000000001011111111000000000 -11111111100000000011111101100001 -00001100111011010000101100111110 -00000000101111111001100000110011 -11100000000011001111100000000010 -10111010010000101100110110000000 -00110011011000000000110011111000 -00100011110100000000000001110000 -00000000000000000000000000000000 -10101000000100011001110000000000 -10110110000000010010110110010000 -10001000010000111000101000011001 -00000000101101110000000000101001 -11000000000010000110000100000010 -00111000010000001000010000000000 -00100011010000000000100001110001 -00010010111010100000010001100000 -00000000000000000000000000000000 -00000000000000001001000000100000 -10110111000100000010110001000000 -10111001011110000100001000011100 -01100000101101110000001000100100 -11000000001010000110000000000010 -10011000000010001001001100000000 -00100001010000000010100101110000 -00000010110001000000000000100000 -00000000000000000000000000000000 -01100000000101001100001000000100 -10110011011000000000110011000000 -00001001000011000000101000001000 -00000001001100110000010000101000 -11000000000000000010000000000010 -00001000000000001001000000000000 -01100010010000000010100100111101 -00000010110110000000010000110000 -00000000000000000000000000000000 -10101000000101011010011000000000 -10111011010000000011111010100000 -00100001101010000000100100101110 -00000001101111110000000001110011 -11000000000011000011110000000011 -10101000000001001101000100000000 -00100010111000000110110110110000 -00100011111011100000010001100000 -00000000000000000000000000000000 -10000000000000001110000000000000 -11111011000000000011111011100000 -10001110001000000000001111101101 -00000101111110110000000001111110 -11000000010011111011111000000011 -11101100000001001110100100000000 -00111110110101000000111010110100 -00000011111000010000000000110000 -00000000000000000000000000000000 -00000001010100001111111001000000 -11111111000000000011111110000000 -00101100111100011000001100110111 -00000000110010110000001000110111 -11000000110011001111000000100011 -01011000000000001100110110100000 -00110011110000000000100011110000 -10000011001000000000010000110000 -00000000000000000000000000000000 -10000001000001000110101000000000 -10111011000000100010110011010001 -00001000101000000010101000000101 -00000000100010110000000000100010 -11000000000010001011110010000010 -00101101010001101000100100000000 -00100010011000000000100000110100 -01001010001000000100000000010000 -00000000000000000000000000000000 -10000000000001010010010000000000 -10111011000000000010111001000000 -00001000101000000000001000100000 -00000000100000110000000000100000 -11000000000010001010100000101010 -01101001000000011000100100000000 -10100010111100000000101010111000 -00000010001000000000000001000000 -00000000000000000000000000000000 -00001000000101000000010000000000 -00110011100000000010111011000000 -00011000001000000000001000100000 -00000000100000110000000000100000 -11000000000010001000000000000010 -00001000000000011000000000000000 -00100000110000000001101010010000 -00000010000000100000000100000000 -00000000000000000000000000000000 -00000000000011010110000000000000 -11111011000000000011111001000000 -01001100111100000000101100100000 -00000010110011110000000010110111 -11000000000011001010000000000011 -01101000000000001100100100000000 -01110010110000000010111010110000 -00000011001000000000001101010000 -00000000000000000000000000000000 -10100000000101011111000000000001 -11111111000000000011111111000000 -00011111011000000000001111110000 -00001001111111110000001000111111 -11000000001011110110000000000011 -11110000000000001111110000000000 -00111111000000000010110111000000 -00000011111010000000011001110000 -00000000000000000000000000000000 -11000000000001011111110000000000 -11001101100000000011011111001001 -00001100111100100010001100110010 -01000000110001001000001010110011 -11000000000011110100100000000011 -00010010000000001111110010000000 -00111101001000000000110011110000 -00100011001100000000000001110000 -00000000000000000000000000000000 -11000000000110001111111101000000 -10001001100000000000111111100001 -00001000111100101011001000100000 -00000000100010010000001100100011 -11010000000010111001000000000010 -10100010000000001011100010000000 -00101110100000000000101010111100 -00010010101100000000010000110000 -00000000000000000000000000000000 -11001000000001011100110000000001 -10000001000000000010010011010000 -00001000001100110001001000001000 -00000011100010100010100000100000 -11000100000010111000000000010010 -10000000000000011011000000000000 -00101100110000000000100100010100 -00000010001100100000000101110000 -00000000000000000000000000000000 -11000000000001011010110000000000 -10001001110000000010111011000000 -00001000101100000000001000101100 -00000000000010110000000000100010 -11000000000010111001000000000010 -10100011000000011011101000000000 -00101100111000000000101110011000 -00000010101100000000010001100000 -00000000000000000000000000000000 -11000000000101011110110000000000 -11001000100000000011011011000000 -00001100101100000010001100100000 -00010000110010000000000000110010 -11000000100011110001110100000011 -10100010000000001111100010000001 -00111110111000000000110100010000 -00000011000100000000010001110000 -00000000000000000000000000000000 -11100000000000011000110000000010 -11111101000000000011110011000001 -00001111111100000000001111110000 -00001000111111000000000000111111 -11000000000011111111000000000011 -11110100000000001111111000010000 -00111111110000011000111011010000 -00000011111110000000000001100000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11001000010000000011111011000000 -00001100101100000000001100101000 -00000000111110000000000000110110 -11100010000011001001010000000011 -00100101001000001100100000010000 -00111110111000000000110010110000 -00000011110101010000010000100000 -00000000000000000000000000000000 -11000000000001010011111000010000 -10001001101000000000111111000000 -10001000111100000000001000101100 -00000000101100000000000000100011 -11010000000000001001011000001010 -10100101100000001000101001010000 -00101110110000000000100010111000 -10000010111100100000000001000000 -00000000000000000000000000000000 -11000000000001000100110000001000 -10000000100001000000110011000000 -00001000101100000000001001100100 -00010000101100000000000000100100 -11000000000010000001000000010010 -01000010000000001001000010000000 -00101100100000000000100000010000 -00000010111110000000000001010000 -00000000000000000000000000000000 -10111000000100000101111000000000 -10010110100000000010110111100000 -00001001001110000001101001010110 -00000000101111011000010001100000 -11100000001010000111110100000010 -11011110000000011001010010000000 -00101111101100000010100001011100 -00000010111011000001000001000000 -00000000000000000000000000000000 -01001010000010000100110000100000 -11000011000000000011110011000001 -00001100001100000000001101001000 -00000100111100100000000000110100 -11000000010011000001000000100011 -01000100000000001101001000000000 -00111100110000000000110000110000 -00000011110100100000001000000000 -00000000000000000000000000000000 -11000000000101011011110000100000 -11101111000100000011111111000000 -00001110111100011000101110111101 -01001000111111110000000000111111 -11000000000011111101000000000001 -10111100010000001010111000010000 -00111111110000000000111111110001 -00000011110100000000011001100000 -00000000000000000000000000000000 -00001000000001011110110010100000 -11011011000000000011111011010110 -00001100101101101000001100000111 -00010000110010000000000000111010 -11010010001011000001000000000011 -10100000000000001111001010001000 -00110010111000000000110000010000 -00000011001010100000000001110000 -00000000000000000000000000000000 -11001000100110011000110010000100 -10000101000000000010110111001000 -00001000001100000000101000010100 -00000010100011000000000000101001 -11011000000010000111000000000010 -00011100000000001011011000000000 -00100001110000000000101001010000 -00000010101100100000010001100000 -00000000000000000000000000000000 -00100000000000000001111010000010 -10100111100011000110110111101001 -00111000011110100000001000111010 -00000000100001001000000000101001 -11101000000010101101110000000010 -10010110000000001011111010000000 -00100011110000100010101001111000 -00000010001000000000000000100000 -00000000000000000000000000000000 -01101000000001001100110000000000 -10100011101000000110110011000000 -00001000001100000100011000001100 -00000000100000000100000001101000 -11000000000010110001000000000010 -00001100000010001011001010010000 -00100010111000000000101000110000 -00000010100100100000010000110000 -00000000000000000000000000000000 -11100000000101010110100000000000 -11101110100000100011111010000000 -00001100101000000000001100101000 -00010000110011100010000000111000 -10000000000011101110010000000011 -10111001000000001111101000000000 -10110011100100000000111010100000 -00000011001110100000010001100000 -00000000000000000000000000000000 -01001000000000011010000000010000 -10001000000000000011111000000000 -00001111100000000000001111100000 -00001000111110000000100000110110 -00000000000001001000000001001011 -11100001000000001111100001000000 -00111110000100100000101110000000 -00000011110100100000000000110000 -00000000000000000000000000000000 -00001000000100001000010000000000 -11001001000000000010110001000000 -00001000000100000010011100101100 -00010000111110010000000000110110 -01100000000011001001101010000011 -00100100001010001011101110100000 -00111110010000000010010000010000 -00000011000000100000010000110000 -00000000000000000000000000000000 -10000000000000000110011000000000 -10001001000000000010111001000000 -00001000100100000000001101100100 -00000000101110010000000000100010 -01100000000010000001010000000010 -10100100100000001001100111000000 -00111010010100000000100010010000 -00000010001000000000000000010000 -00000000000000000000000000000000 -00111010000001010010010001000110 -10001001000000000010111001000000 -00001010100100000000101000101100 -00000000101100010000000100100110 -01001000000010001011010000000010 -00100100100000001011100101000000 -00101110010000000000101010010000 -00000010000001100000000001000000 -00000000000000000000000000000000 -00101000000101000000010010100000 -10000001000000100010110001001010 -00101010000100101000001000000100 -00000000001100010000000000100000 -01101000001110000001000000000010 -10000100000000011001000100000000 -00101000110000000000101000011010 -00001010000000100000000100000000 -00000000000000000000000000000000 -10111000000011010110000010000000 -11001000000000000011111000001000 -11001110100000100000001000100000 -00000000111110000101000000110100 -00010100000011001000010100000011 -00100000000011001111100000000000 -00111110000101000000111010000000 -00000011001011100000001101010000 -00000000000000000000000000000000 -11011000100101011110010000000100 -11111101000000000011110001000000 -10000101100100101100101111100100 -10100000111111010000000000111110 -01000100000011111101000000000001 -11110100000001000111100100000000 -00111001110000000100110111010001 -00000011111001100000011001110000 -00000000000000000000000000000000 -00011000010000011110010010101000 -11001001000000000011001001000000 -00001000100100000010001100100101 -00010000111110010000011010110011 -01011000000011001101010000000011 -00110100000000001100110100000000 -00111111010100000000110011110010 -00100011000001100000000001110000 -00000000000000000000000000000000 -01111000000110001110000100000000 -10001010000000000010001000000001 -00001000100000100001001000000000 -00000000101110000010100100100010 -00000000000010001000001000000010 -00100000000000001000100000000000 -00101110000000000000110110000100 -00000010100011100000010000110000 -00000000000000000000000000000000 -01001000000000001000010000000000 -10001001000001000010000001010000 -00001000000101001000001000000100 -10000000101100010000000000100000 -01011000000010000001000000001010 -00100100000000001010000100000000 -00101100010010000000100100010001 -00000010000100100000000101110000 -00000000000000000000000000000000 -00011000000001001010010000010010 -10001001000000000010001001000000 -00001000100100000000001000100100 -10000000101100010000000001100000 -01000000000010000001000100000010 -00100101000000001010100100000000 -00101100111000000000100110010010 -00000010100001100000010001100000 -00000000000000000000000000000000 -10100000000100011100010000000000 -11000001000000000011001001000000 -00101100100100000000101100100100 -10000000111110011000000000110010 -01000000010011001001000000000011 -00000100000000001110100100000001 -00111110010100000010110100010000 -00000011001010000000010001110000 -00000000000000000000000000000000 -01001000000000011010110000000000 -11111011100100101011110011000001 -00001111100100000010001111100100 -00000000111110011010000000111110 -01000000001011111001000000000011 -11100100000000101101100111000000 -00111110010000010010111110010000 -00000011110110100000000001100000 -00000000000000000000000000000000 -01001000000100001010000010001000 -11001000010000000011111000001000 -00001100100000000000001100100000 -00000000110010000000010000111110 -00000000000011001000000000000011 -00100000110000001111100000000001 -00111110000100000010110010000001 -00000011110010100000010000100000 -00000000000000000000000000000000 -00101000010001010010100000000000 -10001010010000000010111010100000 -00001000101000000000001101101000 -00000000100010100000010000111111 -10000000000010001110011100010010 -00111000000000001011111000000000 -00101111100000000000100011100000 -00000011100010100000000001000000 -00000000000000000000000000000000 -01101000000001010100110100000010 -10000010001000000010110011110001 -00101011101100000000001001001100 -00000000000100110000000000101100 -01000000001010000011110000010010 -00000110000000000011001100010000 -00101100111000000000100000010000 -00000010110010100000000001010000 -00000000000000000000000000000000 -10000000000100010001010000000001 -10000100000000000010110111000010 -00011011001100000001001001011110 -00000000100101110010000000001000 -01000000000010000111000000000010 -00011100000000001011011100000000 -00101101110100000000100001010000 -00000010101010000000000001000000 -00000000000000000000000000000000 -10001000100010001000011000000010 -11000110100100000011110011100010 -00101111011111110010001101011110 -10000000110101111100010000101101 -10100000000011001111100000001011 -00011110000000001111011110000001 -00111111111000000010110001011000 -00000011111010100000001000000000 -00000000000000000000000000000000 -00001010000101011010010000100100 -11111000010000000011111011001000 -00001100101100100000001111101100 -10110010111010110110000000111110 -00000000000011111001011010001011 -11101100000001001011101100000000 -00111110100000000100111110010000 -00000011110000100000011001100000 -00000000000000000000000000000000 -00000010000001001011101000000000 -11001111100100000011111100100000 -00001100111110000000001100111110 -00100000111111111100000000111111 -01100001000011101111100000000011 -00111110000100001111010110010000 -00110011011000000000110011011001 -00000011000000000000000001110000 -00000000000000000000000000000000 -10101000000110001001000000000010 -10000101000100100010110100011000 -00001000011100010100101000011100 -00000000101101110001000000101101 -01000100000010000111000000000010 -00011100000100001011010100000000 -00110101110001000000100001110000 -00000010101010100000010001100000 -00000000000000000000000000000000 -00000000100000001000000000000010 -10000111010110010010110000000000 -00111000011100000000101001011100 -00000000101101110000000000101101 -10000000000010100111000000000010 -00011000011000001011010100001000 -00100011010000000000100001010000 -00000110000000000000000000100000 -00000000000000000000000000000000 -00100000000001001000000000000000 -10000001000000010010110000000000 -00011000001100000000001001001101 -10000000101100110100000000101100 -00000000000010001001110000000010 -00001011100000001011000110000000 -00100100101000000000100000110000 -00000010100010000000010000110000 -00000000000000000000000000000000 -10101000000100011010110000000000 -11001010010000000011111010000000 -00101100111100000000001101111101 -00010000111111110000000000111110 -00000000000011101001000000000011 -00001111000000001111101100000000 -00110010100000100010110010010000 -00000011001010100000010001100000 -00000000000000000000000000000000 -10000000000000001110010000000100 -11111000000000010011111010010000 -00001111001100000010001110101100 -00000000111110110010000000111101 -01000000000011111001010100000011 -11101000000000001111101100000000 -00111110010100000000111110010000 -00000011111000000000000000110000 -00000000000000000000000000000000 -00100001000100001101010000001000 -11011110000000000011110110000000 -00001100111100000000001100111100 -00000000111111110000000000111110 -10000000000011001101000010000011 -00111100000000101100111000000001 -00111111101010000000110001010000 -00000011000000000100010000110000 -00000000000000000000000000000000 -10100001010001000110010000000010 -10001000011000000010111010000000 -00001100101100000000001000101100 -00000000101110110000000000101110 -00010000000010101001100000010010 -00101011110000001000100111000000 -00100110000100000000100010001100 -10000010001000000000000000010000 -00000000000000000000000000000000 -10000000000001010010100000000000 -10001010000000000010111000000000 -00001000101100000100101000101100 -00001000101110110000000000101110 -00010000000010001011100010000010 -00101100000010001000100110001001 -00101100000000000000100010011000 -00100010001000000000000001000000 -00000000000000000000000000000000 -00001010000101000000000000000000 -10000000000000000010110000000000 -00001000001100000000111000001100 -00010000101100110000000000101100 -01000000000010100011000000000010 -00001000000001001000000100000100 -00100100010000000010100000010000 -00000010000000100000000100000000 -00000000000000000000000000000000 -00000000000011010110000000000000 -11001010000000000011111000000000 -00101100011100000000001100111100 -00000000111111110000001000111110 -10000000000011000111000000000011 -00101000000000001100100000000000 -00111110000000000000110010010000 -00001011000000000000001101010000 -00000000000000000000000000000000 -10100010000101011111000000000000 -11111100000000000011111100000000 -00001110111100000000001111111100 -00001000111111110000010000111111 -00000000000011111100000000000011 -11111000000010000111110100000000 -00111101000000000000111101000000 -00000011111010000000011001110000 -00000000000000000000000000000000 -11000000000001011101011000000000 -11111111000000000011001111001000 -00001101110010010001001100111110 -00000000111111110011000000110011 -11001010000011001111100000000011 -11111100111010001111111110000000 -00110011110000000000110011100000 -00000011001100000000000001110000 -00000000000000000000000000000000 -10000000000100001110010000000000 -10111011100001000010001111110000 -00001000100010000001001000101110 -00000000101111110011000000111011 -11111010010010001011100000000010 -11111101000100001011101110000010 -00101011111100010000101010101100 -00010010001000000000010000110000 -00000000000000000000000000000000 -10001000000001011100010000000000 -10110011000000000010000011000101 -00101001001000100100001000001100 -00000000101100110000000000100000 -11000000001010000011000000000010 -11001100100000001011101100000000 -00100000110100000000100000000100 -00000010001000100000000101110000 -00000000000000000000000000000000 -11000000000101011010010000000100 -10111011000000001010001011000000 -01001000100000000000101000101100 -00000000101110110000010000101110 -11000000010010001011000000000010 -11101100000000001011101100000000 -00101010110000000000101010000000 -10000010001100000000010001100000 -00000000000000000000000000000000 -01000000000101011110010000000000 -11111011000000000011001011000000 -01001101100100000000001100100110 -01000000111110110000000000110010 -11000000000010001011000000000011 -11101100000000001111001100000000 -00110010110000000000110010111101 -00000011000100000000010001110000 -00000000000000000000000000000000 -11100000000000011011010000000000 -11110011000010000011111111000001 -01101111110100010000001111110100 -00001000111101110000000000111011 -11000000000011111111000111000011 -11111100000100001111111110010000 -00111111110000010000111101110000 -00000011111110000000000001100000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11101011000000100011001011100000 -00001111101100000010001101100100 -01100000111110110000000000111110 -11000000000011001011000000000011 -11101100000110001111101110000000 -00111110110000000000111110010000 -10000011000100000000010000100000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10001111000001000010000111010000 -00001011100100000000001011100101 -00000000101111110000010000101111 -11000000000010001011110000010010 -11111100000000001011101100000000 -00101101110000110100101110010100 -00000010001100100000000001000000 -00000000000000000000000000000000 -11100000000001010100010000000000 -10100011100100000010000011000010 -00001011100000000000001011001101 -00000000101100110000001000101110 -11000000000010000001010000000010 -01001100000000001011000101100000 -01101100110000001000101100110101 -01000010001110000000000001010000 -00000000000000000000000000000000 -00100000000000010011011000010000 -00000111100100000010000111100000 -00001011011110000000001011011110 -01000000101101111000000000101100 -11100000001010000101100010000010 -11011110000000001011010110000000 -00101101111000000000101100111000 -00000010000010000000000001000000 -00000000000000000000000000000000 -01001000000010000000010000000000 -11100011000000000011000011000000 -00001111001000000000001111001100 -00000000111100110000000000111100 -11000000000011000001000000000011 -01001100000000001111001100010000 -00111100110000000000111100110000 -00100011000100100000001000000000 -00000000000000000000000000000000 -01000000000111011011010000000000 -11111111000010001011111111000000 -00001111111100000000001111111100 -00000000111111110000000001111111 -11000000000011101101000000100011 -11111100011000001111111100000100 -00111111110000000100111111110001 -00000011110100000000011001100000 -00000000000000000000000000000000 -10101000000001011110010000000000 -11111011000000100011001011001010 -00001011100000000000001111101111 -11000000110110110011100000111110 -11000100000011001011101000000000 -00101110100000001100100101100000 -00111110110010000000111110110000 -00000011111010100000000001110000 -00000000000000000000000000000000 -01001000000100011001010000000000 -10110111001000001010000111010000 -00001011011100000001001011011100 -10110000100001110010000000101101 -11000010000010000111011010000010 -10001100001000001000010101101000 -00101101110100100100101101110000 -00000010110100100000010001100000 -00000000000000000000000000000000 -11000000000000001001111000000000 -10110011100000000010000111100000 -00001011011010000001001011111110 -10001000100101111010000000101101 -11100000000010001111100000000010 -00011110100000001000011110000000 -00101101111010000000101101111000 -00000010111100000000000000100000 -00000000000000000000000000000000 -01001000000101001100111000000000 -10110011000000000010000011000000 -00001011001100000000001011001110 -00000000100000110000000000101100 -11000000000010000011100000000010 -10001100000000001000001100000000 -00101100110000000001101100110000 -00100110110100100000010000110000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11111010000000000011001010000001 -00001111011001000000001111101000 -00100000110110100000000000101110 -10000000000011001010101000100011 -00101000000000101100101000000000 -00111110100000000000111111100100 -00000011111110100000010001100000 -00000000000000000000000000000000 -01001000000000001110000001000100 -11111000000000010011111000000000 -01001111100000001000001111100000 -00000000111100000000000000111110 -00000000001011111000000000000011 -11100000000000001111100001000010 -00111110000000010000111110000000 -10000011110100100000000000110000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11110001100100000011001001000000 -00101100100100000000001100100100 -00000000111110010000000000110000 -01000000000011001001000000000011 -11100100000000001111100100000000 -00111100011000000000110000010000 -00000011000000100000010000110000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000000000010000001000000 -00001000100100000000001000101110 -01000100101110010000000000100010 -01000001000010001011000000000010 -11100100000000001011101101000001 -00101110010001010000100010010010 -00000010001000000000000000010000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001010000001010001001000000 -00001000101100000000001000100100 -00001000101110010000000000100010 -01000000001010001001000000000010 -11100100000000001011100101000000 -00101110010000000000100010010000 -00000010000001100000000001000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001001000000010000001001000 -10001000100100000000001000001100 -00000000101100010010000000100000 -01001000000010000001000000000010 -11000100100000001011000100000000 -00101100010010000010100000010010 -00001010000000100000000100000000 -00000000000000000000000000000000 -10111000000011010110000101000000 -11111000000000000011001010000000 -00001100100001010000001100100000 -00000000111110000101000010110000 -00010100000011001000000000000011 -11100001010000001111100000000000 -00111110000000000100110010000000 -00000011001011100000001101010000 -00000000000000000000000000000000 -10011000000111011111010000000000 -11111001000100000011111001000100 -00001111110100000000101111000100 -00000000101110010001010000111110 -01000100000011110001000001000011 -11100100010000001111100100000100 -00111110010001010100111111010001 -00000011111001100000011001110000 -00000000000000000000000000000000 -00011000000001011110010001000000 -11111001000000000011001101000000 -00001110100100000000001111100100 -00010000111110010000110000110010 -01000010000011111001000000000011 -11100100010000001111100100000010 -00101111010000000000111111010000 -00100001000001100000000001110000 -00000000000000000000000000000000 -00111000000100001110000000001000 -10111000010100000010001000010100 -01001000100000101000001011100000 -00000000101110000000000000101010 -00001010100010111000000000000010 -11000001010000001011100000000000 -00101110000000001000101110000000 -00000010000011100000010000110000 -00000000000000000000000000000000 -00001000000001011100010010000000 -10110001000000001010000001000000 -00001010000100000100001011000100 -00000000101100010000100000100000 -01000000000010110001000000000010 -11000100100000001011000100000000 -00101100010100001101101100010100 -00000010000000100000000101110000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10111001000000000010001001000001 -00001000100100010000001011100100 -00000000101110010000000000101010 -01000000000010111001000000000110 -11100100000000001011100100100010 -01101110010000000001101110010010 -00100010000001100000010001100000 -00000000000000000000000000000000 -10100000000101011110010000000000 -11111001000000000011001001000000 -10001110100110000000001011100100 -00000000111110010000000000010010 -01000000000010111001000000000011 -11100100000001001111100100000000 -00111110010000000000111110010000 -00000011001010000000010001110000 -00000000000000000000000000000000 -00101000000000011010011001000000 -11110011000000001011111001000000 -01001111100100000000001111100100 -00001000111110010000010000111110 -01000000000011111001000000000011 -11100100000000001111100110000000 -00111110010000010100111110010000 -10001011110010100000000001100000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11001000000010000011110000000000 -00001101100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000101100100000000000 -00111110000000001000110010000001 -00000011000010100000010000100000 -00000000000000000000000000000000 -00101000000001010010100000000000 -10001010000000000010111110000000 -10001000101000000000001011101010 -10000000101110100000000000101110 -10000000000010111010001100000010 -11101000000001001000101000000000 -00101110100000000000100001100100 -00000010000010100000000001000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10000011100000000010110011000100 -00001001001100000000001011001100 -00000000101110110000000001101100 -11000000010010110011100000000010 -11001100000000001000001100010000 -00101100110001000000100100011100 -00001010000010100000000001010000 -00000000000000000000000000000000 -10100000000000010001111011000000 -00000101010000010010110011000000 -00001000011100110000001011011100 -00000100101101110010001000101101 -11001000000010110110000000000010 -11011110100000001000011000000000 -00101101111000000000100100110000 -00000010001010000000000001000000 -00000000000000000000000000000000 -10101000000010000011111010000010 -11000110100010000011110111100000 -00001101011110010001001111011010 -01001000111101111011000000111101 -11111010000011110111100000000011 -11011110000000001100011110001000 -00111100111000000010110101011000 -00000011001010100000001000000000 -00000000000000000000000000000000 -00001000000111011010110110100000 -11111011011000000011111010000000 -00001111101100100000001111100101 -10000000111110110000000000111110 -11000000100011111010000010000011 -11101100010000001111101100100010 -00111110010000000000111010110000 -00000011110000100000011001100000 -00000000000000000000000000000000 -00000000000001011111111000000000 -10111100100100000011001101100101 -00001100111110000000001110110110 -00000000111111111000100000111111 -11100000000011111101100100000011 -11111111000000001100110110010000 -00111111111000000000101111011001 -00000011000000000000000001110000 -00000000000000000000000000000000 -10101000000100011001110000000000 -10110101000100001010000111001100 -00101000011100001000001000011100 -00000000101101110000010000101101 -11000000000010110111000000000010 -11011100000000001000010000000000 -00101101110010010000101101010011 -00001010001010100000010001100000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110110000001010010000101000000 -00001000111100000000001011010000 -00000000101101110000000000101101 -11000000000010110101000000100010 -11011100000000001001010100000000 -01101101110000000000101100010000 -00100010000000000000000000100000 -00000000000000000000000000000000 -00100000000101001100110000000001 -10110011000000000010000010000000 -00011000001110100000001001000100 -00000000101100110000010000101100 -11000000000010110011000000000010 -11101100000000001001000100000000 -00101100010000000000101100010000 -00000010000010000000010000110000 -00000000000000000000000000000000 -10101000000101011011110000000000 -10111011000000000010001010000000 -00001100111100000000001011101100 -00000000101111110000001000101111 -11000000000011111011000000000011 -11111100000000001101101100000000 -00111110110000000000111110010000 -00000011001010100000010001100000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11111011010000000011111011000000 -00001111101100000000001100101000 -00000000111110110000000000111110 -11000000000011111000010000000011 -11101100000010001110100001000010 -00111110110000000000111110000100 -00010011111000000000000000110000 -00000000000000000000000000000000 -00000001000100001111110000000010 -11001011001000000011001110000000 -00001111111100000000001100111000 -00000000111111110000000010110011 -11000000000011111111000000000011 -11101100000001001100111010100000 -00111111110000000000111111010000 -00000011000000000100010000110000 -00000000000000000000000000000000 -10000001000001000110110000000000 -10000011110000100010001010100000 -00001011101100000010001000100000 -00000000101110110000000001100010 -11000000000010111000011000000010 -11101100000001001000100000000001 -00101110011000000000101100010000 -00000011011000000100000000010000 -00000000000000000000000000000000 -10000000000001010000110000000000 -10011011000010000010001010100000 -01001011001100000100001000100100 -00001000101100110000001000100010 -11000000000010111000100000000010 -11101100000000001000101101000010 -00101110010001000000101110010110 -00000010001000000000000001000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10000011000000000010000011100000 -10001011001100000000011000001010 -00000000101100110000000000100000 -11000000000010110000000000000010 -11001100000011001000000000000000 -00101100010000000100101100010000 -00000010010000100000000100000000 -00000000000000000000000000000000 -00000000000011010111110000000000 -11011011000000001011001010000000 -01001111111100000100001100100000 -00000100111111110000000001100011 -11000000000011111000000000000011 -11111100000000001100101000000010 -00011110010000000100111110010000 -00001011000000000000001101010000 -00000000000000000000000000000000 -10100000000111011111110000000000 -01111111000000000011110110000001 -00001111011100000000101111110000 -00000000111111110000010000111111 -11000000000011111100000000100011 -11111100000000001111110000000000 -00111111010000010100111111010000 -00000011111010000000011001110000 -00000000000000000000000000000000 -11000000000001011101110010000000 -11111101100000000011101100100000 -00001100110110000000001111110010 -00000100110011110010010000110011 -11000000000011001100010000000011 -10110000000100001100110110000000 -00110011010010000000110011110100 -00100011001100000000000001110000 -00000000000000000000000000000000 -10000000000100001111111101001000 -10111001100000000010001001100000 -10001000100110000010001011100110 -00000000100011110101000100100011 -11010000000010001000001000000010 -10100000001101001000001100001100 -00100010010101100000101011110101 -00010010001000000000010000110000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10111011000000000000100010000000 -00001000000000000000001011100000 -00000000100000110010100000100000 -11010001000010100000000000010010 -00000100100010001000001100100000 -00100000010010000000100100110010 -00000010001000100000000101110000 -00000000000000000000000000000000 -11000000000101011010110000000000 -10111011000001000010001011000000 -00101000100110000000001011100100 -00000000100000110000010010100010 -11000000001010100000010000000010 -10100110000000101000101100000000 -00100010010000000000001110110000 -00000010001100000000010001100000 -00000000000000000000000000000000 -01000000000100011110110000000000 -11110001100100000011100000010010 -00001100100011001000001111100010 -00000000110010110000000000110010 -11000000000011101011010100000010 -10100010100100001100101110010001 -00100010010000000010110110011000 -00001011000100000000010001110000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11111101000000000011111101000000 -00001111110000000010001111111110 -10000000111111110000000000111110 -11000000000011011001100000000011 -11110000001000001111111100000000 -10111100010000001010111001011001 -00000011111110000000000001100000 -00000000000000000000000000000000 -01000000000100001010110000000100 -11001011001001000111111010010001 -10001111100100000000011111100000 -10000000111110110000000000111100 -11000000000011001011010000000011 -00100101000000001111101100001000 -00110010010000000000110010010000 -00001011000100000000010000100000 -00000000000000000000000000000000 -11001000000001010011111000000000 -10001011110000000010111011000000 -00001011100100000000011111001100 -00010000101111110000000000101111 -11000000000000001001111000000001 -00100100000100001011101101000000 -00110011010000001000100010011010 -00000010001100100000000001000000 -00000000000000000000000000000000 -11100000000001010100110000000001 -10000011000100000010110000000000 -00001011000100000010001011001001 -00000001101100110000000000101100 -11000001000010000000001000101010 -00100000000001001011101100000010 -00100000010000010000101000010000 -01000010001110000000000001010000 -00000000000000000000000000000000 -00100000000000010001111000000000 -10000111100000000010110100100000 -00001011011110000000001011011110 -00000000101101111000000000101101 -11100000001010000110100101001010 -01010010000000001011011110000000 -00100101011000000000101000011000 -00000010000010000000000001000000 -00000000000000000000000000000000 -01001000000010000000110000100000 -11000011000000000010110011000000 -00001111001000000000001011001000 -01000000111100110000000000111100 -11000110000011000001000100001011 -00000100011000001111001100100000 -10110000010010000010111000010000 -00000011000100100000001000000000 -00000000000000000000000000000000 -01000000000111011011110000100010 -11111111000000000011111111010100 -00001111111100000000001110111101 -00000000111111110000000000111111 -11000001000011111111000100000000 -10110100000000001111111100000000 -00111011010000000000110111011001 -00000011110100000000011001100000 -00000000000000000000000000000000 -10101000000001011110111010000010 -11001011000000000011110000101000 -00001100101110000000001100100001 -00000000111110110010100000111110 -11010010000011111010000001000011 -00110000000000000011101100000001 -00111110011000010000110010110010 -00000011001010100000000001110000 -00000000000000000000000000000000 -01001000000100011000110011000000 -10000111000000000010110100000000 -00001000010100000001001000011100 -00000100101101110000000000101101 -11011000000010110010000000000010 -00010100000000001011011100000001 -00101101010110000000100000110001 -00000010000100100000010001100000 -00000000000000000000000000000000 -11000000000000001001111010000000 -10000111100000000010111111100000 -00001000111110000000101000010010 -00100000101101111001000000101101 -11101000000010110111110000000010 -00011110000000001011011110000100 -00101100010000000000100001111000 -00000010001100000000000000100000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10000011000000000010110011000000 -10001000001101010000001000001100 -00010000101100110000000000101100 -11000000000010111011110000000010 -00001100100000001011001110010001 -00101100010000000000100000110001 -00000010000100100000010000110000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11001010000000000011111010000000 -00101100111010000000001100101010 -00000000111110100000000000111110 -10000000000011111110100000001011 -00111001000000001111101000000010 -00111110100000000110110010101000 -01001011001110100000010001100000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000010011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000001111000000010000011 -11100000000000001111100000000000 -00111110000000000000111110000100 -00000011110100100000000000110000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001100000000011111011000100 -00011111100100011000001111101101 -00000000111110010000000010110010 -01000000000011111001000000000011 -00000100100000001100100110010001 -00110010010000000000110010010000 -00000011000000100000010000110000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001100000000110111001110000 -00001011100100000000001011100101 -00000000101110010000000000100010 -01000000000010111001000000000011 -01100111100000001101000111100000 -00100010010000000100100010010110 -00000010001000000000000000010000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001001000000010111001000010 -00001011100100000000001011100100 -00000000101100010000001001100010 -01000000000010111001000000000010 -00100100000000001000100100000000 -10100000011000000000100000010000 -00000010000001100000000001000000 -00000000000000000000000000000000 -00001000000001000000010010100000 -10110001000000000010110001000000 -00001011000100000000001011001100 -00000000101100010010100001100000 -01001000000010110001001000000010 -01000100100100001001100100000000 -00100000011010000010100000010010 -00001010000000100000000100000000 -00000000000000000000000000000000 -10111000000011010110000010000000 -11111010000000000010111000000000 -00001011100000000000001111100000 -00000000111110000111000000110010 -00010100000011111000010100000011 -00100001010000001100100001010000 -00110010000101000000110010000101 -00000011001011100000001101010000 -00000000000000000000000000000000 -10011000000111011110010000000000 -11111101000000100011111001000000 -00001111010100000000001111100100 -00000000111110010000000000111110 -01000100000011111101000100000011 -11111100010001001111110100000001 -00111111010001000000111111010001 -00000011111001100000011001110000 -00000000000000000000000000000000 -00011000000001011110010010100000 -11111101000001000011111001000000 -00001111100100000010001111100100 -00000000110010010010000000111011 -01001000000011001001001001000011 -00101101000000001100000101000000 -00111110010100100000110010010010 -00000011000001100000000001110000 -00000000000000000000000000000000 -00111000000100001110000100000000 -10111000000000010010111000000000 -00001011100000000000001011100000 -00000000100010000110100000100010 -00011010010010001000011010000011 -00100001110000001000100000100000 -00101110000100000000110111000110 -10000010000011100000010000110000 -00000000000000000000000000000000 -00001000000001011100110000000000 -10110001000000000110110001000000 -00001011001100000000001011000100 -00010000100000010001010000101000 -01000100000010010101010000000010 -01010100100000001000010100000000 -00101111010010000000100001010001 -00000010010000100000000101110000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10111001001000010010111001110000 -00001011100110000000001011100100 -00000000100010010000010000100010 -01000000000010010011010000000010 -00011100000000000000110100000001 -00101111110000000000100101010000 -00000010010001100000010001100000 -00000000000000000000000000000000 -10100000000101011110010000000000 -11111001000000000011111001000000 -00001111100101100000001111000100 -00000000110010010000000000111010 -01000000000011011001000000000011 -01100111000000001100100110000000 -00111100010000000000110010010000 -00000011011010000000010001110000 -00000000000000000000000000000000 -00101000000000011010110000001000 -11111001000000000011111011000001 -01001111101100000000001101101100 -00000010111110010000000010111100 -01000000100011101001000000001011 -11100110010000101111100100100000 -00111110010000100000111110010000 -10000011100010100000000001100000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000100000011001000010000 -10001111100011000000001111100000 -00000000111110000000000000110010 -00000000000011001000010000000011 -00100000000000001100100000100000 -00110010000001000000111110000000 -00000011000010100000010000100000 -00000000000000000000000000000000 -00101000000001010010100000010000 -10111110110000000010001010100000 -00001011101000000010001011101000 -00000000101110100000000000100010 -10001000000010001010010001000010 -00101000000100001000101001001000 -00100010100000000100101110100000 -00000010100010100000000001000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110011110010001010010011000000 -00001011001100000000001011001100 -00000000101110110000000000100000 -11100000001010000011100010000010 -00001110000000001010001110000001 -10100000111100010000101100111100 -00000010000010100000000001010000 -00000000000000000000000000000000 -10100000000000010001110000000000 -10110111100000000010010111010000 -00001011011100000000001011011100 -00000000101100110010000000100001 -11100000000010000111010000000010 -00011101000001001010111110000000 -00100001110000010000101101111100 -00000010101010000000000001000000 -00000000000000000000000000000000 -10101000000010000001111000000000 -11110101100000000011010110100010 -00001111010110010000001111010110 -00000000111101111010000010110000 -11000000000011001111100000001011 -00111110000000101110011110000000 -00110001111000000000111111110000 -10001011001010100000001000000000 -00000000000000000000000000000000 -00001000000111011010110000100000 -01110011000000000011101010001000 -00001111100101000000001111100001 -00000000111110110101000000111110 -11000001000011111011000000010011 -11101100000000001101101100000000 -00111110110000010000111110110110 -00000011110000100000011001100000 -00000000000000000000000000000000 -00000000000001011111111000000000 -11111111100000000011111111100000 -00001111111010000000001111111111 -00000000111111111100000000110011 -11100001000011001101100000000011 -00110110010000001111111010000100 -00110011101000000000110011001000 -00000011000000000000000001110000 -00000000000000000000000000000000 -10101000000100011001010000000100 -10110111000000000010110111000100 -00001011011000000011001011011101 -00000100101101110001000000100011 -01000000000010000111000100000010 -00011100110000001011011100011001 -00100001100001000010100001100000 -00000010001010100000010001100000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110110000100000010110100010000 -00001011010001000000001011010100 -01100000101100110000000000100001 -11000100000010000001000000000010 -00010101000000001011011000000000 -00100001110000000010100001010000 -00000010000000000000000000100000 -00000000000000000000000000000000 -00100000000101001100010000010000 -10110001000001000010110000000000 -00001011000010010100001011000011 -00000000101100110000000000100010 -01000000000010000011000000000010 -00000100000000001011101010000000 -10100010110000000000100000110000 -00000010000010000000010000110000 -00000000000000000000000000000000 -10101000000101011010000000000000 -11111001000000100011111001000000 -00001111101101000000001111101010 -00000000111111110000010010110010 -11000000000011001010000001001011 -00101000000000001111100100000000 -00110010010000000000110010110000 -00000011001010100000010001100000 -00000000000000000000000000000000 -10000000000000001110100000000100 -11111000010000000011111001000000 -00001111101100000000001111101101 -00000000111110110000000000111110 -11000000000011111011010100000011 -11101101000000001111100100000000 -00111110010100000010111100110100 -00000011111000000000000000110000 -00000000000000000000000000000000 -00000001000100001101001000000000 -11001101000000110011111100110000 -00001111111100000000001111110000 -00101000111111110000000000111111 -11000000000011000110101000000011 -00111000000000001100110100010000 -00110010110000000000110010111000 -00000011000000000100010000110000 -00000000000000000000000000000000 -10000001000001000110101000010000 -10001000100000000010111000100000 -00001011101110000100001011100000 -00000000101110110000000000101110 -11000000110010001011010000001010 -00101001000000001000100100000000 -00100010111101000000101010111000 -00000010001000000100000000010000 -00000000000000000000000000000000 -10000000000001010010000001000010 -10001001110000000010111011000000 -00001011100000010001001011101000 -00001000101110110000000000101110 -11000000000010001000000000000010 -00000000000010101000101000000000 -00100010000000001000100010000110 -00000010001000000000000001000000 -00000000000000000000000000000000 -00001000000001000000001000000000 -10000001000000000010110011000000 -00001011000000000000001011001100 -00001100101100110000000000101100 -01000000000010000000000000000010 -00001100000000001000001100000000 -10100000000000000000101000000000 -00000010000000100000000100000000 -00000000000000000000000000000000 -00000000000011010110000000000000 -11001000000000000011111000000000 -00001111100000000000001111100000 -00000000111111110000000000111110 -11000000000011001000000000000011 -00100000000000001100000000000000 -00110010000000000010110010000000 -01000011000000000000001101010000 -00000000000000000000000000000000 -10100000000111011111000000000000 -11111101000000000011111100000001 -00001111110000000000001111110000 -00000000111111110000010000111111 -01000000000011111100000000000011 -11110000000000001111110000000000 -00111111000000000000111111000000 -00000011111010000000011001110000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11111111100000000111101111010000 -00001100011100100000001111111100 -00000000010011111000000000111111 -11001000010011001111001100000011 -00111110000000001111111110000000 -00110001111000000000110011011000 -01000011011100000000000001110000 -00000000000000000000000000000000 -10000000000100001110110000000000 -10111111110000000010001011010100 -00001000111111010000001011111101 -10100000101010111000010000101111 -11000100000010000111001000000010 -10100110000101001011101110000001 -01101010111000000000101010011000 -01010010001100000000010000110000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10110011000100000010100011001000 -00001000001100000100000011001101 -00000000100000010000000000101100 -11001010000010000011001100010010 -00001100000000001011101100000000 -00100100110000000000100000010000 -00000010011100100000000101110000 -00000000000000000000000000000000 -11000000000101011010110000010000 -10111011000000000010000011000000 -00001000101100000000001011101100 -00001000101010010000000000101110 -11000000000010001011000000000010 -10100100000000001011101100000000 -00101110110000100000101010010000 -00000010001100000000010001100000 -00000000000000000000000000000000 -01000000000101011110110000000000 -11111011000000000010101011000000 -01101000101100000000001111101100 -00000000110010110000000000111110 -11000000001011001011000000000011 -00101110010001001111001100000000 -00100110110100000000110010011000 -00000011010000000000010001110000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11111111000000000011111011000000 -00001111111100001000001111011100 -00010000111111111001010000111101 -11000000000011110111000000000011 -11110100000100001111111110010000 -00111011011100000000111111011001 -00000011111110000000000001100000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11110011000000000011001011000001 -01001110101100000000001100101100 -00000001110010010000100000111110 -11000000001011001011000000000011 -10101110000000001111101100001000 -00111110110000000000110010010000 -00000011110101000000010000100000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10111111011000010010001111000000 -00001000111101000000001000111100 -00000000101010010000000000101111 -11000000010010001111000000000010 -00100100000000001011101111000000 -00101100110000100000110100011000 -00000010111100100000000001000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10110011100010000010000011000001 -00101010001110010000001000001100 -00000000101000111100000000101100 -11000000000010000011000000000010 -00001100100000001011000101010000 -00101100110000000000100000011001 -00000010111110100000000001010000 -00000000000000000000000000000000 -00100000000000010001111000000000 -10110111100000000010000111100000 -00001000011110000100001000011110 -01000000101001111000100000101100 -11100000000010000111100000000000 -00011110000000001011011110000000 -00101111111000000000100101011000 -00000010111111000000000001000000 -00000000000000000000000000000000 -01001000000010000000110000000000 -11110011000000000011000011000000 -00001110001100000000101100101100 -00000000100000110000001000111100 -11000000000011000011000000000011 -00001100000000001111000100000000 -00111100110000000000110000010000 -00000011110100100000001000000000 -00000000000000000000000000000000 -01000000000111011010110000000000 -11110011000000001001111011000000 -00001111101101000000001111101100 -00000000010110110000000000111110 -11000010000011111011000010000011 -11101101001000001111101101001000 -00111110110000000000111110010001 -00000011110100000000011001100000 -00000000000000000000000000000000 -10101000000001011110110000000000 -11111011010000000011111011000000 -10001001001101010000001110101111 -01000000110010110011100000101110 -11010010000011111011010000000011 -11101101000000001011100101000000 -00111100110000000100110110010000 -00000001111010100000000001110000 -00000000000000000000000000000000 -01001000000100011001110000000000 -10110111010010000010110111001000 -00001000011100000100001000001100 -10100000101001110000000000101101 -11000000000010110111001010000010 -11011100000000001011011100000000 -00101101100000000000100001110000 -00000010111100100000010001100000 -00000000000000000000000000000000 -11000000000000001001111000000000 -10110111100000000010110011101100 -00001001011110100110001010011110 -00000000100001111000000000101101 -11101000010010110111100000100010 -11011110100000001011010110000001 -00101011111000010000100101011000 -00000010111000000000000000100000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110011000000000010111011000000 -10001000001100000000001000001100 -00000001101000110000000000101100 -11000000000010111011000000000010 -11001100000001001011001100000000 -00101100111100100101100000111000 -00000010110100100000010000110000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11111010000000000011111010000000 -00001101101000000000001110101000 -00000000100010100000000100111110 -10000000000011111010000000000011 -11101000000000001111101000000000 -00111011100000100000110110101010 -00000011111110100000010001100000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011111000000000 -00001111000000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100001000100 -00111110000000000000111110000000 -00000011110100100000000000110000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000000000011111001000000 -00001100100100000000101100100100 -00000000111110011000000000111110 -01000000000011001001000000000011 -00100100000000001100100100010000 -00111110010000000010110010011000 -00000011110000100000010000110000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001010000000010111001000000 -00011000100101000000001000100100 -00000000001110111001000000101110 -01000000010010001001000000000010 -00001100000000001101101101001000 -00101100010000000100100010010000 -00000010111000000000000000010000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010111001000000 -01101000100100000000001000100100 -00000000001110010100000000101100 -01000000000010101001000000000010 -00100100000000001000100100000000 -00101110010010000000100010010001 -00000010110001100000000001000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001001000000010110001001000 -00001000000100100000001000000100 -10000100101100010000000000101100 -01001000000010100001001000000010 -00100110000000001001000100000000 -00001110010000000000100000010000 -00000010110000100000000100000000 -00000000000000000000000000000000 -10111000000011010110000101000000 -11111010000000000011111000010100 -00001000101000000100001100100001 -01000000111110000000000000111110 -00010100001011101000010100000011 -00100000000000001100100000000000 -00111110000000000000110010000000 -00000011111011100000001101010000 -00000000000000000000000000000000 -10011000000111011110010000000000 -11111001000100000010111001000100 -00001111100100010000001111100100 -01000000111110010000000000111110 -01000100000011011001000100001011 -11100100000000001111100100000100 -00111111010000000100111111010000 -00000011111001100000011001110000 -00000000000000000000000000000000 -00011000000001011110010001000000 -11001101000000000011101001000100 -00001101110100100000001111100100 -10000100110010010000000100111110 -01001001000010111001010000000011 -11100100000100000011100100000000 -00111111010000000000110001010000 -00000011111001100000000001110000 -00000000000000000000000000000000 -00111000000100001110000000000000 -10001000010100000010001000010100 -00001000100001000000001011100000 -00010000100010000000000000101110 -00011010000010111000000001000010 -11100000000000001011100000000000 -00101110000000000000101010000000 -00000010110011100000010000110000 -00000000000000000000000000000000 -00001000000001011100010010000000 -10000001000000000010100001001000 -00001000000100010000001011000101 -10100000100000010000000000101100 -01000100000010110001010000000010 -11000100000000001011000100000000 -00101110010000000000100000010000 -00000010110100100000000101110000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10001001000000000010001001000000 -01001000100100000000001011000100 -00000110100010010000000001101110 -01000000000110111001000000000010 -11100100000000001011100100000000 -00101110010000000001101010010000 -00000010110001100000010001100000 -00000000000000000000000000000000 -10100000000101011110010000000000 -11001001000000000011101001000000 -00001100100100000000001111100100 -00000000100010011000000000111110 -01000000100011111001000000000010 -11100100000000001111100100000000 -00111110011001100000110010010000 -00000011111010000000010001110000 -00000000000000000000000000000000 -00101000000000011010010000000010 -11110001000000000010110001000000 -00101110100100001000001111100100 -00000000111110010001000000111110 -01000000000011111001000001000011 -11100100000000001111100100001000 -00111110011000000000111110010000 -00000011110110100000000001100000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000000000011111000000001 -00000000100000000001001111100000 -00000001111110000000000100111110 -00000000001011001000000000000011 -11100000000000001111100000000100 -00111110000000000000110010000000 -00000011100010100000010000100000 -00000000000000000000000000000000 -00101000000001010010100000000000 -10111110000110000010111010000000 -00001000111000000000001011101000 -00000000101110100000100000101110 -10000000000010001010000000000010 -11101000000000001011101000000000 -00101100100000000000110110101000 -10000010000010100000000001000000 -00000000000000000000000000000000 -00101000000001010110110000000000 -10110011000000000010110011000000 -00101000001101010000001011001100 -00000000101100110000000000101100 -11000000000010010011000000000010 -11001110000000001011001100000000 -00101100111000000000100100110000 -00000010100010100000000001010000 -00000000000000000000000000000000 -10100000000000010001110000000000 -10110110000000000010110011001000 -00001000011100000000001011011100 -00000000101101010000000000101101 -11100000000010010111001100000010 -11010000001000001011011100000000 -00101111110000110000100111111000 -01000010001010000000000001000000 -00000000000000000000000000000000 -10101000000010000001111100000000 -11110111100000000011110111100000 -01001100011110000000001111011110 -00000000101101101000001000111111 -11100001010011010111100100010001 -11011110001001001111011110000000 -00111101111000000000110101111000 -00000011101010100000001000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111010000000000011111011011101 -01001111101000000000001111101100 -00000100111110110110100000111110 -11010000000011101011000000000001 -11100000100000001111100001101000 -00111100010000000000111110110000 -00000011110000100000011001100000 -00000000000000000000000000000000 -00000000000001011111111000000000 -11111111100000000011101111110000 -10001100111010010000001111111111 -00100000111111111001000000110011 -11110010000011111111100001000011 -11111110000001001111111010000000 -00111111111000000000110011111000 -00000011110100000000000001110000 -00000000000000000000000000000000 -10101000000100011001110001000000 -10110101000000000010000111000100 -00001000010100000000001011011100 -00000000101101010000000000101001 -11000100000010110111000000000010 -11010000000000001011011100010000 -00101101110001010000101001110001 -00000010111010100000010001100000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110110000000000010100111000000 -00101000011000000000001011011100 -00000000101111000000000001100001 -11000000000010010111000000000010 -11011100000000001011011000000000 -00101111110000000000100001110000 -10000010110001000000000000100000 -00000000000000000000000000000000 -00100000000101001100110000000000 -10110000000000000010000011000000 -00001000000000000000000011001100 -00000001101100010000000001101000 -11000000000010110011000000000010 -11000000000000001011000000010000 -00101100010100000000101000111000 -00000010110110000000010000110000 -00000000000000000000000000000000 -10101000000101011011110000000000 -11111001000000000011101111000000 -00000100100100000000001011111100 -00000000111110110000000000110011 -11000000000011011111000000000011 -11101110001000001111100110000000 -00111100111100100001110010110000 -00000011111010100000010001100000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11111000000001000011111011000000 -00001111100100000000001111101100 -00000000111110000100000000111110 -11000000000011110011000000000011 -11101100000000001111100100000001 -00111110110010000000111110110000 -00000011111001000000000000110000 -00000000000000000000000000000000 -00000001000100001111110000000000 -11111101100000000011110011000000 -10001100010100000000101100111100 -00000000111111100000000000111111 -11000000000011111111000000000011 -00111000000000001111111111000000 -00011111110010000000110011111000 -00000011111000000000010000110000 -00000000000000000000000000000000 -10000001000001000110110000000000 -10111000100000000010111011000001 -01001000100000000000001000101100 -00000000101110100000010000101110 -11000000000010111011000000000010 -00101000011001001011100010000000 -00101110011000000000100010111001 -00000010111000010000000000010000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000100000010111011000000 -00001000101000010000001000101100 -00000000101010110100000000101010 -11000000010010111011000000000110 -00100100000000011011100000000000 -00101110010000000000100010110000 -00100010111000000000000001000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10110001000000000010110011000000 -00101000000100000000001000001100 -00000000101100000000000000101100 -11000000000010110011000000001000 -00000100000000011011000100000000 -00101110010000000000100000110000 -00000010110000100000000100000000 -00000000000000000000000000000000 -00000000000011010110110000000000 -11111010000000000011111111000000 -00001100101000000000011100111100 -00000000111010000000000000111011 -11000000000011111111000000000011 -00100000000000001111101000000001 -00111110010000000010110010110000 -00000011111000000000001101010000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11110100000000000011111111000000 -00000111110000000000001111111100 -00000000111101000000000100111111 -11000000000011111111000000000010 -11110000000000001111110000000000 -00111101010000000000111111010000 -00000011111010000000011001110000 -00000000000000000000000000000000 -11000000000001011111001000000000 -11111100100000100011001100100001 -00001100110010000000001111010110 -00010000110011011000000000110001 -01100000100011001100100000000011 -11110000000000001100110000000000 -00110011110001000000110011101000 -00010011001100000000000001110000 -00000000000000000000000000000000 -10000000000100001110111000000000 -10111011100000100010001000100000 -00001000101010000000001011100110 -00000000100010000000000000100010 -01000000000010001010100000000010 -11101010000000101000100100000000 -00101011110000001000100010101000 -00000010001000000000010000110000 -00000000000000000000000000000000 -10001000000001011100000000000001 -10110000000000000010000000100000 -00001000000000000000011011000000 -00000000100010000000000000101000 -01000000001010000010000000100010 -11000100000000001000000000000000 -00100000110000000010100000100000 -00001010001000100000000101110000 -00000000000000000000000000000000 -11000000000101011010110000000001 -10111011000000100010001000000000 -01001000101000000000001011100010 -00000000100010011000000000101010 -11000000000010001010100000000010 -11100100000000101000100000000010 -00101010110000000010100010100000 -00000010001100000000010001100000 -00000000000000000000000000000000 -00000000000100011110000100100000 -11111000000000000011001001000000 -01001100100100000000001111100010 -00000000110000011010000000111000 -01000000000011001000110000000011 -11100000100000101100100010010000 -10110010110000000000110000101001 -10000011000100000000010001110000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11111110000010100011111100010000 -00001111111000000010001011110100 -00000000111111010000001000110111 -01000000000011111100000000000011 -11101000000000001111011100000000 -00111110110000010000111111110000 -00000011111110000000000001100000 -00000000000000000000000000000000 -01000000000100001010000001000000 -11111001000000000000111011000000 -00001111100101000010001111100100 -11000000110010000000000000111110 -11001000000011001000011000000001 -11001101000001001100100100100000 -10110000110000000010110010110100 -10000011110100000000010000100000 -00000000000000000000000000000000 -11001000000001010010111000010000 -10110011010000010010110010110100 -01001011101000000000001110000100 -00000000100010010000000000001110 -11010000001010001000001000000010 -11101111001000001000101100000000 -00100011110111000010100010111100 -10000010111100100000000001000000 -00000000000000000000000000000000 -11100000000001010100001000000000 -10110000100000000010110010010001 -00001011000000000000001011000101 -00000000100000010000000000101100 -01010100000010000000010000000010 -11000001001000001000001001000000 -00100000110000000000100000001000 -00000010111110000000000001010000 -00000000000000000000000000000000 -01100000000000010001101000000001 -10110111100101000010110111100010 -00001011011110000000001010111110 -00000000100001101000001000101101 -01100100000010000110100000000010 -11011010000000001000010110011000 -00100001111001000000100001001000 -00000010110010000000000001000000 -00000000000000000000000000000000 -01001000000010000000000000000000 -11110000000010000011110010000000 -00001111000001000000001111001100 -00000000110000110000000000111100 -01000100000011000010010100000011 -11000000000000101100101000010001 -01110000110001000100110000100000 -01000011110100100000001000000000 -00000000000000000000000000000000 -01000000000111011011100000000000 -11111111000000000011111111010000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000100000010111110000000000011 -11110000000000001111110000010000 -00111111110001100000111111100100 -00000011110100000000011001100000 -00000000000000000000000000000000 -10101000000001011110010000000000 -11110000110000000011001001001000 -00001111000111100000001100101000 -00000000111110110000000000110010 -01000000010011001000000000000011 -11100100000000101100101000000000 -10110000110010000000110010010110 -00000011111010100000000001110000 -00000000000000000000000000000000 -01001000000100011001110001000000 -10110110000100000010000101000000 -00001011011100001000001000011100 -00000000101111010000000000110111 -01000000000010000110000000000010 -11011100000000001000011100000000 -00100001110011000000100001010000 -00000010110100100000010001100000 -00000000000000000000000000000000 -11000001000000001001011000000001 -10111101100000000010100111110000 -00001011110110000000001001010110 -00100000101101111000000000100001 -11100000000010000110110000000010 -11001110000000001010001110000000 -00100001111010000000100001111000 -00000010111100000000000000100000 -00000000000000000000000000000000 -01001000000101001100110100000000 -10110011000000000010000011000000 -00001011001100000000001001001100 -00100100101110111111000000100100 -11100000000010000011100000000010 -11001110010000001010001101110000 -00100000110000000000100000110000 -00000010110100100000010000110000 -00000000000000000000000000000000 -11101000000101011000100100000000 -11111010010000000011101010000000 -00001111101001000000001101111010 -00000000111111100100000000110010 -10101000001011001110100000000011 -11111001000010001110111011000000 -00110010100000000000110010100100 -00000011111110100000010001100000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000010001011111000110000 -00001111100000001000101110100001 -00000000111110000000000000111110 -00000000001011111000000000000011 -11100000001000000001000000000000 -00111110000000000010111110001000 -00000011110100100000000000110000 -00000000000000000000000000000000 -00001000000100001110110000100000 -11011011010000000011111011000000 -00001111101110000000001111100100 -01000000101110010000000000110010 -01000000000011001001000010000011 -11000110100000001100100100000011 -00110000010000001000110010111000 -00000011110000100000010000110000 -00000000000000000000000000000000 -10000000100001000110010000000000 -10001001010000000010111001011000 -00001011100110000000001011100111 -00000000101110010000001000100000 -01100000000010001001000000000010 -11100110000000101000100101000010 -00100010010000000010100010011100 -00000010111000000000000000010000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10011001000010000010111001000100 -00001011100100100000001011101100 -00000000101110010000000010100010 -01001000000010001001001001000010 -11100101000000001000100101000000 -10100010010000000000100010010010 -00000010110001100000000001000000 -00000000000000000000000000000000 -00001000000001000010010000000000 -10000001000001000010110001000000 -00001011000100000010011011000100 -00000000101100010000000000100010 -01000000000010000001000000000010 -11000100100000101000000100100000 -00100000010010000000100000011000 -00000010110000100000000100000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11011000000000000011111000000000 -00001111100000000000001111101000 -00000100111110000101000000110010 -00010100000011001010000000010011 -11100000000000001100100001010000 -10110010000101000000110010000000 -00100011111011100000001101010000 -00000000000000000000000000000000 -10011000000111011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111110100 -00000000111111010000000000111111 -01000000001011111101000000000011 -11110100010000001111111100010000 -00111110010001000010111111010000 -00000011111001100000011001110000 -00000000000000000000000000000000 -10011001000101011100010000000000 -11111101000000010011111101000000 -00001100100100000000001111110100 -00000000111110010100000000111101 -01000000000011000101000000000011 -00110100001000001100110100000000 -00110011010110100100110010010000 -00000011110001100000000001110000 -00000000000000000000000000000000 -00111001000110001110000000010000 -10111000000000100010111000000000 -10001101100000000000001011101000 -00001000101110000000001000101110 -00000000000010001000000000000010 -00100000000000001000000001100000 -10100010000100000010101010000000 -00000010110011100000010000110000 -00000000000000000000000000000000 -00001000000001011100010000001000 -10110001000000000010111001000000 -00001000000100000010011011000100 -00000000101100010010000000101100 -01001010000010000001100000011010 -00000100000000101000000101001000 -10100000010000000010100000010000 -00000010110000100000000101110000 -00000000000000000000000000000000 -00011000000001011010010000000000 -10111001010000000010111001000000 -00001001100100000000011011100100 -01000000101110010010000100101110 -01001000001010001001000000000010 -00100101000000001000100100000010 -00100010010000000000101010010010 -10000010110001100000010001100000 -00000000000000000000000000000000 -10100000000101001010010000000000 -11111001010000100011111001000001 -00001100100100000000001111100111 -00000000111110010010000000111110 -01000000010011000001010000000011 -00100110000001001100100101000000 -10110010010000000010110010010000 -00000011111010000000010001110000 -00000000000000000000000000000000 -00101010000000001010110000001100 -11111001000000000011111001001000 -00001111101100000000001011100100 -00010000111110011000000000111110 -01100000100011111001001000000011 -11100111000000001111100100001010 -00111110010000000000111110110000 -00000011110010100000000001100000 -00000000000000000000000000000000 -00101010000100001010000000000000 -11001000001000000011111000000000 -00001111100000000000001111100010 -01000000101110000000000000111110 -00000000000011001000000010000011 -00000000000000001111100001000000 -10110000000000000010110010000000 -00000011000010100000010000100000 -00000000000000000000000000000000 -10100000100001000010100000000000 -10001110000000000010110110101000 -00001011101000000000000011111000 -00000000101110100000000000101111 -10100010001010001110010010001010 -00111010010000001011111011000000 -00100011100000001000110110100000 -00000010000010100000000001000000 -00000000000000000000000000000000 -00101000000001010100111001000000 -10000011000000000010110011100010 -01001011001110010000000011001100 -00000000101100110000000000101110 -11100000000010000011010000000110 -00001000010101001011101110000000 -00100000001000000000100000110010 -00100010000010100000000001010000 -00000000000000000000000000000000 -01100001000000010001111000000000 -10000101010000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -01000000000010001111000000000010 -00011100000000001011011101000000 -00100000010100000010100111111000 -00000010001010000000000001000000 -00000000000000000000000000000000 -00101000000010000001111000000000 -11000111100000000011110111100000 -00001111011110000000001111010110 -00000000101101111010001000111101 -11100000000011000111100000000011 -00011110000000001111011110000000 -00110001001000000010110001001000 -00001011001010100000001000000000 -00000000000000000000000000000000 -01001000000111011010110000101010 -11111010000000100011111010000000 -10001111101100000000001111101100 -00000000111110110000000000111110 -01000000000011111001000000000010 -11101100000000001111101000000000 -00111110010000000000111100000000 -10000011110000100000011001100000 -00000000000000000000000000000000 -11000000000001011111011000000000 -11111111100100000011111101100100 -00001111110111010000001111111110 -01000000111111111000100000111111 -11100000000011001111100000000011 -11111110010000001100111010000000 -10110011101000001000110011111000 -00000011000000000000000001110000 -00000000000000000000000000000000 -10101000000000011001110100000000 -10110111000000000010110111000000 -10001011010101000000001011011000 -00000000001101110000000000101111 -11000000000010000111000000000010 -11011100000000001101010100000000 -00110101010000000000101001110000 -00000010101010100000010001100000 -00000000000000000000000000000000 -00011001000000001001010000000000 -10110111000000010010110111000000 -00011011010100000001001011011100 -00000001101101110000000000101101 -11000000000010100110000000000010 -11001100001010001001011000000000 -00100001100000000000100001000000 -00000010000000000000000000100000 -00000000000000000000000000000000 -01100010000101001100110001001001 -10110001111000000010110000010000 -00001011000100100000001011000100 -10000001100100111100000000101100 -11000000000010100000010000000010 -11001110000000001001000000100010 -00100100010000000000101000000000 -10000010100010000000010000110000 -00000000000000000000000000000000 -11111000000101011010100000000000 -11111001000000000011111001000000 -00001111101010100000001111100101 -00000000111111110000000000111110 -10000000001011101011000100000011 -11001110000000001101100101000000 -00110010000000000000110010000000 -00100011001010100000010001100000 -00000000000000000000000000000000 -10000000000000001110000100100000 -11111001010100000011111001010000 -00001111101001000000001111100101 -01000000111110110011000000111110 -01010100100001011010100000000011 -11101101000000001111001100010000 -00111110000100000000111110100100 -00000011111000000000000000110000 -00000000000000000000000000000000 -11000001000100001111101000000000 -11111101000000100011111101000010 -00001111110000000000001100110000 -00000000111111110000000001111111 -00000000000011001111000100000011 -11111100000000001100110110010100 -00110001000000000000110011000000 -00000011000000000100010000110000 -00000000000000000000000000000000 -10000001000001000110001000000000 -10111000110001000010011001100001 -00001011000000000000001000100110 -10000000110010110000001001111100 -01101000001010001000011000000010 -01101111100000001000101010000010 -00100010000100001000100000000000 -00000011001000000100000000010000 -00000000000000000000000000000000 -10000000000000010110000001000000 -10111000110000000010111000100010 -00001011101000100000101000100110 -00000000101110110000010000101110 -10100000000010001001000000000010 -11100110000001001000100000000000 -00100010100000100000100010000110 -00000010001000000000000001000000 -00000000000000000000000000000000 -00001000000000000000000000000000 -10110001000000000110010001000000 -00001011001000000000001000000000 -00001000101000110000001000101000 -11000000000010000000000000000010 -01001100000000001000000100000000 -10100000000000001100100000110000 -00000010000000100000000100000000 -00000000000000000000000000000000 -10000000000000000110000000000000 -11111000000000000011111000000000 -00001111100000000000001100100000 -00000000111110110000000000101110 -00000001000011001000000000000011 -11101100000001001100000000000000 -10110000100000000100110010000000 -00001011000000000000001101010000 -00000000000000000000000000000000 -10100000010110011111000000010000 -11111101000000000011011101000000 -00001111110000000000001111110100 -00001000110011110000000000111111 -01000000000011111100000000000011 -01111100000010000111110000000000 -00111111000000000000111101000000 -00000011101010000000011001110000 -00000000000000000000000000000000 -00000000110001010100000100000011 -01110000010000001001110001010000 -00000111000001000000110111000101 -00000001011100010100000011011100 -00010000001101110000010000001101 -11000101000000110111000101000000 -11011100000100000011011100000100 -00001101110000000011000100000000 -00000000000000000000000000000000 -00000000110001010100010000000101 -01110001000000010101110001000000 -01110111000100000001010111000100 -00000101011100011000000101011100 -01000000010001110001000000010101 -11000100000001010111000100000001 -01011100010000000101011100010000 -00010101110000000011000101010000 -00000000000000000000000000000000 -00000000100000000000001000000001 -00100000100000000100100001100000 -00010010000010000000010010000110 -00000001001000001000000001001000 -00100000000100100000100000000100 -10000010000000010010000110000000 -01001000001000000001001000001000 -00000100100000000010000000000000 -00000000000000000000000000000000 -00000000100000000000000000000001 -01100000000000000101100000000000 -00010110000000000000010110000000 -00000101011000010000000001011000 -00000000000100100000000000000101 -10000100000000010110000000000000 -01011000000000000001011000000000 -00000101100000000010000000000000 -00000000000000000000000000000000 -00000000110001010100100000000101 -01110010000000010101110010000000 -01010111001000000001010111001001 -00000101011100100000000101011100 -10000000010101110011000000010101 -11001010000001010111001000000001 -01011100100000000101011100100000 -00010101110000000011000101010000 -00000000000000000000000000000000 -00000000110001010100000000000000 -01100000000000000001100001000000 -00000110000000000000000110000010 -00000000011000000000000000011000 -00000000000001100000000000000001 -10000000000000000110000101000000 -00011000000000000000011000000000 -00000001100000000011000100000000 -00000000000000000000000000000000 -00000000110001010100100000000100 -00100010000000010000100000100000 -01000010001000000001000010000100 -00000100001000100000000100001000 -10000000010000100011000000010000 -10001000000001000010001110000001 -00001000100000000100001000100000 -00010000100000000011000100000000 -00000000000000000000000000000000 -00000000110001010100111100000101 -01000010100000010101000001110000 -00010100001010000001010100000010 -00000001010000101000000101010000 -10100000010101000010100000010101 -00001010000001010100001010000001 -01010000101100000101010000111100 -00010101000000000011000101010000 -00000000000000000000000000000000 -00000000100000000000111000000001 -00010011000000000101010111000000 -00010001011100000000010101001100 -00000001010100110000000000010101 -11000000000101010111000000000101 -01001100000000010101011100000000 -01000000110000000001000100110000 -00000100010000000010000000000000 -00000000000000000000000000000000 -00000000100000000000010000000000 -00010000000000000001000001000000 -01000001000000000000000100001100 -00000000010000000000000000010000 -00000000000001000001000000000001 -00000000000000000100000100000000 -00000000000000000000000100011000 -00000000010000010010000000000000 -00000000000000000000000000000000 -00000000110001010110000000000010 -00011000000000001000001000000000 -00100001100000000000100000100000 -00000010000010000000000010000010 -00000000001000001000000000001000 -00100000000000100000100000000000 -10000010000000000010000110000000 -00001000010000010011000101010000 -00000000000000000000000000000000 -00000000110001010100000000000101 -01100000000000010101100100000000 -01010110010000000001010110000000 -00000111011000000000000101011001 -00000000010101100100000000010101 -10000000000001010110010000000001 -01001000000000000101011000000000 -00010101100000000011000100000000 -00000000000000000000000000000000 -00000000110001010100000000000011 -01100000000000001101100000000000 -00010110000000000000110110001000 -00000001011000000000000011011000 -00000000001101100000000000001101 -10000000000000110110000000000000 -11011000000000000011011000000000 -00001101100000000011000100000000 -00000000000000000000000000000000 -00000000110001010100001000000100 -00110000100000010000110000100000 -01100011000010000001000011000011 -00000100001100001000000100001100 -00100000010000110000100000010000 -11000010000001000011000010000001 -00001100001000000100001100001000 -00010000110000000011000101010000 -00000000000000000000000000000000 -00000000100000000000000000000000 -00110000000000000000110010000000 -00000011000000000000000011000000 -00000000001100000000000000001100 -00000000000000110000000000000000 -11000000000000000011000000000000 -00001100000000000000001100000000 -00000000110000000010000000000000 -00000000000000000000000000000000 -00000000100000000000001000000001 -00110000100000000100110010110000 -00010011000010000000010011000010 -00000101001100001000000001001100 -00100000000100110000100000000100 -11000010000000010011000010000000 -01001100001000000001001100001000 -00000100110000000010000000000000 -00000000000000000000000000000000 -00000000110001010100001000000101 -01100000100000010101100000110000 -01010111000010000001010110000011 -00000101011000001000000101011000 -00100000010101100000100000010101 -10000010000001010110000010000001 -01011000001000000101011000001000 -00010101100000000011000101010000 -00000000000000000000000000000000 -00000000110001010100001000000000 -00100000100000000000100000100000 -00000110000010000000000010000010 -00000000001100001000000000001000 -00100000000000100000100000000000 -10000010000000000010000010000000 -00001000001000000000001000001000 -00000000100000000011000100000000 -00000000000000000000000000000000 -00000000110001010101001000000100 -01100000100000010001100100100000 -01000010000010000001000110010010 -00000100001100001000000100011000 -00100000010001100100100000010001 -10000010000001000110010010000001 -00011001001000000100011001001000 -00010001100000000011000100000000 -00000000000000000000000000000000 -00000000110001010110000000000101 -01011000000000010101011000000000 -00010001100000000001010101100000 -00000000000110000000000101010110 -00000000010101011000000000010101 -01100000000001010101100000000001 -01010110000000000100010110000000 -00010101010000000011000101010000 -00000000000000000000000000000000 -00000000100000000000011000000001 -01000001100000000101000001100000 -00010100000110000000010100000110 -00000001010000011000000001010000 -01100000000101000001100000000101 -00000110000000010100000110000000 -01010000011000000000010000011000 -00000100000000000010000000000000 -00000000000000000000000000000000 -00000000100000000001001000000001 -00000000100000000100000100100000 -01010000000010000000010000010010 -00000001000000001000000001000000 -00100000000100000100100000000100 -00000010000000010000010010000000 -01000001001000000001000001001000 -00000100000000000010000100000000 -00000000000000000000000000000000 -00000000110001010100011000000011 -01010001100000001101010001100000 -00110101000110000000110101000110 -00000011010100011000000011010100 -01100000001101010001100000001101 -01000110000000110101000110000000 -11010100011000000011010100011000 -00001001010000000011000101010000 -00000000000000000000000000000000 -00000000110001010100011000000101 -01110001100000010101110001100000 -01010111000110000001010111000110 -00000111011100011000000100011100 -01100000010101110001100000010001 -11000110000001010111000110000001 -01011100011000000101011100011000 -00010101110000000011000100000000 -00000000000000000000000000000000 -00000000010001010100011000000011 -01110001100000001101110001100000 -00010111000110000000110111000110 -00000000011100011000000011011100 -01100000001101110001100000001001 -11000110000000110111000110000000 -11011100011000000011011100011000 -00001101110000000001000100000000 -00000000000000000000000000000000 -00000000010001010100011000000101 -01110001100000010101110001100000 -01100111000110000001010111000110 -00000000001100011000000101011100 -01100000010101110001100000010101 -11000110000001010111000110000001 -01011100011000000101011100011000 -00010101110000000001000101010000 -00000000000000000000000000000000 -00000000000000000000001000000001 -00100000100000000100100000100000 -00010010000010000000010010000010 -00000001011100001000000001001000 -00100000000100100000100000000100 -10000010000000010010000010000000 -01001000001000000001001000001000 -00000100100000000000000000000000 -00000000000000000000000000000000 -00000000010000000000011000000001 -01100001100000000101100001100000 -00010010000110000000010110000110 -00000101011000011000000001011000 -01100000000101100001100000000001 -10000110000000010110000110000000 -00011000011000000000011000011000 -00000101100000000000000100000000 -00000000000000000000000000000000 -00000000010001010100000000000101 -01110000000000010101110000000000 -01010111000000000001010111000000 -00000101011100000000000100011100 -00000000010001110000000000010100 -11000000000001010111000000000001 -01001100000000000100011100000000 -00010101110000000001000101010000 -00000000000000000000000000000000 -00000000010001000100001000000000 -01100000100000000001100000100000 -00000110000010000000000110000010 -00000000011000001000000000011000 -00100000000001100000110000000000 -10000010000000000110000011000000 -00001000001000000000011000001000 -00000001100000000001000100000000 -00000000000000000000000000000000 -00000000010001010100001000000100 -00100000100000010000100000100000 -01000010000010000001000010000010 -00000100001000001000000100001000 -00100000010000100000100000010001 -10000010000001000010001010000001 -00011000001000000100001000001000 -00010000100000000001000100000000 -00000000000000000000000000000000 -00000000010001010100001000000101 -01000000100000010101000000100000 -00010100000010000001010100000010 -00000001010000001000000101010000 -00100000010101000000100000010101 -01000010000001010100000010000001 -01010100001000000101010000001000 -00010101000000000001000101010000 -00000000000000000000000000000000 -00000000000000000000001000000001 -01010000110000000101010000100000 -00010101000011000000010101000011 -00000001010100001100000001010100 -00110000000101010000110000000101 -01000011000000010101001010000000 -01010100001100000001010100001000 -00000101010000000000000000000000 -00000000000000000000000000000000 -00000000010000000000100000000000 -01000010000000000001000010000000 -01000100001000000000000100001000 -00000000010000100000000000010000 -10000000000001000000000001000001 -00001000000000000100000000000000 -00010000100000000000010000100000 -00000001000000000000000000000000 -00000000000000000000000000000000 -00000000010001010100001000000010 -00100000100000001000000000100000 -00100000000010000000100000000010 -00000000000000001000000010000000 -00100000001000000010100000001000 -00000010000000100000000010000000 -10000000001100000010000000001000 -00001000000000000001000101010000 -00000000000000000000000000000000 -00000000010001000100000000000101 -01100000000000010101100000000000 -01010110000000000001010110000000 -00000111011000000000000101011000 -00000000010101100000000000010101 -10000000000001010110000000000001 -01011000000000000101011000000000 -00010101100000000001000100000000 -00000000000000000000000000000000 -00000000110001010100000000000011 -01100000000000011101100000000001 -01010010000000000000110110000000 -00000001011100000000000011011000 -00000000001101100000000000001101 -10000000000000010110000000000000 -11011000000000000011011000000000 -00001101100000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000100000100 -00110000000000000000110000010000 -01000010000000000001000011000000 -00000100011000000000000100001100 -00000000010000110000000000000000 -11000000000000000011000000000001 -00001100000000000100001100000100 -00010000110000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00110000000000000000110101000000 -00000010000110000000000011010000 -00000000001001000000000000001100 -01000000000000110001000000000000 -11010000000000000011010110000000 -00001100000000000000001100000000 -00000000110000000000000000000000 -00000000000000000000000000000000 -00000000000000000000010100000001 -00110001010000010100110001110000 -01010010000101000000010011000101 -00000101001100010100000001001100 -01010000000100110001110000000100 -11000101000000010011000100100000 -01001100010000000001001100010100 -00000100110000000000000000000000 -00000000000000000000000000000000 -00000000000000000010001100000101 -01101000110000000101101000110000 -00010110100011000001010110100011 -00000101011010001100000101011010 -01110000010101101001110000010101 -10100011000001010110100011000001 -01011010001100000101011010001100 -00010101100000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00100000000000000000100101000000 -00000010000100000000000010010000 -00000000001001000000000000001000 -00010000000000100010000000000000 -10010000000000000010010100000000 -00001000000000000000001000000000 -00000000100000000000000000000000 -00000000000000000000000000000000 -00000000000000000000100001000100 -01100010000100000001100010000000 -00000110001000000001000110001000 -01000100011000100001000100011000 -10000000010001100000000110010001 -10001000010001000110000000010001 -00011000100001000100011000100001 -00010001100000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000001000101 -01010000000100000101010000000100 -00010101000000010001010101000000 -10000000010100000001000100010100 -00000100010101010000000001010101 -01000000010001010101000000011001 -01010100000001000101010100000001 -00010101010000000000000000000000 -00000000000000000000000000000000 -00000000000000000000100000100000 -01000010000010000101000010000010 -00000100001000001000010100001000 -00100001010000100000000001010000 -10000010000101000010000010000101 -01001000000000010100001000000000 -00010100100000100001010000100000 -10000101000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000101000000001 -00000010100000000100000010111110 -01010000001010000000010000001010 -01000001000000101000000001000000 -10100000000100000010100000000000 -00001010000000010000001010000000 -00000000101000000001000000101010 -01000100000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000110010000011 -01010011000000000101010011001110 -00110101001100000000110101001100 -01000011010100110000000011010100 -11000000001101010011000000000000 -01001100000000010101001100100000 -10000100110000000011010100110010 -00001101010000000000000000000000 -00000000000000000000000000000000 -00000000000000000000100010000101 -01110010000000010101110010010000 -01000111001000000001010111001000 -00000110011100100000000101011100 -10000000010101110010000000010101 -11001000000001100111001000001001 -00011100100000000101011100100010 -00010101110000000000000000000000 -00000000000000000000000000000000 -00000000000000000010001100001000 -01001000110001100001000000110000 -00000100000011000110000100100011 -00000000010010001100010000010000 -00110001100001000000110000100001 -00100011000100000100000011000000 -00010010001100001000010010001100 -00100001000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -01001111111111111101001111111111 -11110100111111111111110100111111 -11111111010011111111111111010011 -11111111111101001111111111111101 -00111111111111110100111111111111 -11010011111111111111010011111111 -11111101000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000010110111111011 -00001011001101101100001001011111 -11110100100100110110110000101100 -10011111010010110011011001000010 -01001101101100001111101001101100 -00101100110110010000111111111110 -01000010110011011011000010110111 -11101100000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011001111111100 -01001100110011110001001101011111 -11110100110101001111000100110010 -10111111010011001100111101000011 -01010011110001001111101011110001 -00110011001111010000111111111111 -01000011001100111100010011001111 -11110001000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011101100011110 -01001110110111111001001110010001 -10000100111001011111100100111010 -01111000010011101101111110000011 -10010111111001001000100111111001 -00111011011111100000100011000111 -10000011101100011110010011101100 -01111001000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000100000110 -01110000010001011001110001010000 -00110011000001000000110111000101 -00000001011100010100000000011100 -00010000001001110000010000001001 -11000001000000100111000001000001 -00011100000100000110011100010100 -00000001110000000000000000000000 -00000000000000000000000000000000 -00000000000000000000010000000001 -01110001000000010101110001000000 -00010011000100000001010011000000 -00000111001100000000000101011100 -01000000010101110001000000010101 -11000100000001010111000100000001 -01011100010000000101011100010000 -00000101110000000000000000000000 -00000000000000000000000000000000 -00000000000000000000001000000001 -00100000100000000100100000100000 -00010010000010000000000010000010 -00000000001000001000000001001000 -00100000000100100000100000000100 -10000010000000010010000010000000 -01001000001000000001001000001000 -00000100100000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000100 -01100000000000010001100101100000 -00000110000000000000000110010010 -00000000011001000000000100011000 -00000000000001100000000000000001 -10000000000000000110000000000000 -00011000000000000100011000010000 -01000001100000000000000000000000 -00000000000000000000000000000000 -00000000000000000000100100000000 -01110010000000000001110010000000 -00010010001000000001000111001000 -00000100011100101000000100011100 -10000000010001110010010000010001 -11001000000001000111001000000001 -00011100100000000100011100101000 -00010001110000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01100000000000000001100100000000 -01000110000000000000000110010000 -00000000011001000000000000011000 -00000000000001100000000000000001 -10000000000000000110000000000000 -00011000000000000000011000000000 -00000001100000000000000000000000 -00000000000000000000000000000000 -00000000000000000000100000000000 -00100010000000000000100100000000 -01000010001000000001000010010000 -00000100001001000000000100001000 -10000000010000100010000000010000 -10001000000001000010010000000001 -00001000100000000100001001100000 -00010000100000000000000000000000 -00000000000000000000000000000000 -00000000000000000010111100000000 -01001010110001000001001000100000 -01000100101010000001000100100011 -00000000010010001000000000010010 -10100000010001001010000000010001 -00101010000001000100100011000001 -00010010101100000000010010101100 -00010001000000000000000000000000 -00000000000000000000000000000000 -00001000110000000000110000000000 -00010010000000000000010010000000 -00000000001100000000000101001000 -00000000000100110000000000010100 -11000000000001010011000000000100 -00001100000000000101001100000000 -01000000110000000000000100110000 -00000000010000000001000000000000 -00000000000000000000000000000000 -00000000110000000000010000000000 -00010001100000000000010101100000 -00000000000000000000000100010110 -00000100000101100000000000011000 -00000000000001000001000000000001 -00000000000000000100010000000001 -00000100000000000000000101000000 -00000000010000000011000000000000 -00000000000000000000000000000000 -00001000110000000100000000000000 -00010000000000001000010000000000 -01100000000000000000100000000000 -00000010000100000000000010000000 -00000000001000000000000000001000 -00000000000000100000000000000000 -10000000000000000010000100000000 -00000000010000000011000000000000 -00000000000000000000000000000000 -00001000110000000100000000000100 -01100000000000010001100000000000 -01000010000000000000000110000000 -00000000011000000000000110011000 -00000000010001100000000000010001 -10000000000001000110000000000001 -00011000000000000100011000000000 -00111001100000000011000000000000 -00000000000000000000000000000000 -00010000000000000100000000000000 -01100000000000100001100000000000 -00100110000000000000100110000000 -00000000011000100000000000011000 -00000000001001100000000000001001 -10000000000000100110000000000000 -00011000000000000010011000000000 -00001001100000100000000000000000 -00000000000000000000000000000000 -01000000010001010100001000000000 -00110000100000000000110000100000 -00000011000010000001000011000010 -00010110001100001000000100001100 -00100000010000110000100000010000 -11000010000001000011000010000001 -10001100001000000100001100001000 -00010000110000000001000101010000 -00000000000000000000000000000000 -01000000010000000000000000000000 -00110000000000000000110010000000 -00000011000000000000000011001000 -00000000001100000000000000001100 -00000000000000110000000000000000 -11000000000000000011001000000000 -00001100000000000000001100000000 -00000000110000000001000001000000 -00000000000000000000000000000000 -01000000000000000000001000000000 -00110000100000000000110010110000 -00000011000010000000000011001011 -00000000001100001100000100001100 -00100000000000110000100000000000 -11000010000000000001001011000000 -00001100001000000000001100001000 -00000000110000000000000000000000 -00000000000000000000000000000000 -01000000010001010100000000000100 -01100000000000010001100000011000 -00000011000010000001000110000001 -00000100011100001100000100011000 -00100000010001100000100000010001 -10000010000001000110000011000001 -00011100001000000100011000001000 -00010001100000000001000101010000 -00000000000000000000000000000000 -01000000000000010100001000000000 -00100000100000000000100000100000 -01000010000010000000000010000010 -00000000011000001000000000001100 -00100000000000100000100000000000 -10000010000000000010000010000000 -00011000001000000000001000001000 -00000000100000000000000000000000 -00000000000000000000000000000000 -01010000000000000100001000000100 -01100000100000010001100000100000 -01000010000010000001000110000010 -00000100001000001000000100001100 -00100000010001100000100000010001 -10000010000001000110000010000001 -00001000001000000100011000001000 -00010001100000000000000000000000 -00000000000000000000000000000000 -01000000010001010100000000000100 -01010000000000010001010000000000 -01010001000000000001000101000000 -00000000000100000000000000000100 -00000000010001010000000000010001 -01000000000001000101000000000000 -00000100000000000100010100000000 -00010001010000100001000101010000 -00000000000000000000000000000000 -01001000010000000000011000000000 -01000001100000000001000001100000 -00000100000110000000000100000110 -11000000010000011000000000010000 -01100000000001000001100000000001 -00000110000000000100000110000000 -00010000011000000000010000011000 -00000001000000000000000000000000 -00000000000000000000000000000000 -01001000000000000000001000000001 -00000000101010000100000000101100 -00010000000010000000010000000010 -11010101000000001001000001000000 -00100000000100000000100000000100 -00000010000000010000000010000001 -01000000001000000001000000001000 -00000100000000000000000000000000 -00000000000000000000000000000000 -01000000010001010100011000100001 -01010001101000000101010001100110 -01110001000110000000110101000110 -11000011010100011001000011010100 -01100000001101010001100000001101 -01000110000000110101000110000000 -11010100011000000011010100011000 -00001101010000000001000101010000 -00000000000000000000000000000000 -00000000000000010100011000101110 -01110001100010011001110001000010 -01010011000110000001000111000100 -10100100011100010010000110011100 -01100000010001110001100000010001 -11000110000001000111000110000001 -00011100011000000100011100011000 -00010001110000000000000000000000 -00000000000000000000000000000000 -01000000000000010100011000000010 -01110001100000001001110001100000 -00110111000110000000110111000110 -00000001011100011000000000011100 -01100000001001110001100000001001 -11000110000000100111000110000001 -00011100011000000010011100011000 -00001101110000000000000000000000 -00000000000000000000000000000000 -01010000010001010100011000000101 -01110001100000010101110001100100 -00000111000110000001010010000110 -00000111001100011000010100001100 -01100000010101110001100000010101 -11000110000001010111000110000001 -00001100011000000101011100011000 -00010100110000100001000101010000 -00000000000000000000000000000000 -01000000000000000001001000000001 -00100100100000000100100100100100 -00010010000010000000010010010010 -00000001011000001000000001011100 -00100000000100100100100000000100 -10000010000000010010010010000000 -00001001001000000001001001001000 -00000101100000000000000000000000 -00000000000000000000000000000000 -01000000000000000000011000000000 -01100001100000000001100001100000 -00000010000110000000000110000110 -00000001011000011000000100011000 -01100000000001100001100000000001 -10000110000000000110000110000001 -00001000011000000000011000011000 -00000001100000000000000000000000 -00000000000000000000000000000000 -00000000010001010110000000010100 -01111000000000010001111000000010 -00000011100000000001000111100000 -00000100011110000000000100011110 -00000000010001111000000000010001 -11100000000001000111100000000001 -00011110000000000100011110000000 -00010001110000000001000101010000 -00000000000000000000000000000000 -01000000000000010101001000000000 -01100100100000000001100100101000 -01000010000010000000000110010010 -00000000011000001000000000011000 -00100000000001100100100000000001 -10000010000000000110010010000000 -00011001001000000000011001001000 -00000001100000000000000000000000 -00000000000000000000000000000000 -01000000000000010101001000000100 -00100100100000010000100100101000 -01000110000010000001000010010010 -00000100001000001000000100001000 -00100000010000100000100000010000 -10000010000001000010000010000001 -00001000001000000100001000001000 -00010000100000000000000000000000 -00000000000000000000000000000000 -01000000010001010100001000000100 -01000000100000010001000000011000 -01000101000010000001000100000010 -00000000010000001000000000010000 -00100000010001000000100000010001 -00000010000101000100000010000000 -00010000001000000100010000001000 -00010001000000000001000101010000 -00000000000000000000000000000000 -01000000000000000001001000000000 -01010100100000000001010100100000 -00000101000011000000000101010010 -00000000010100001100000000010100 -00110000000001010000110000000001 -01000011000000000101000010000000 -00010100001000000000010100001000 -00000001010000000000000000000000 -00000000000000000000000000000000 -01000000000000010000100000000000 -01100010000000000001100100000100 -00000110001000000000000100001000 -00000100010000100000000000010000 -10000000000001000010000000000001 -00001000000000000100001000000001 -00010000100000000000010000100000 -00000001000000000000000000000000 -00000000000000000000000000000000 -01000000010001010100001000100010 -00000000100010001000000000100110 -00000000000010000000100000000010 -00100010000000001000000010000000 -00100000001000000000100000001000 -00000010000000100000000010000000 -10000000001000000010000000001000 -00001000000000000001000101010000 -00000000000000000000000000000000 -01000000000000010100000010000100 -01100000000000010001100100001100 -01000110000000000000000110000000 -01000100011000000001000110011000 -00000000010001100000000000010001 -10000000000001000110000000000001 -00011000000000000100011000000000 -00010001100000000000000000000000 -00000000000000000000000000000000 -01000000000000010100000010000010 -01100000001000001001100100001100 -00000010000000000000100110000000 -10100000001000000001000000011101 -00000000011001100100000001011001 -10000000000000100110010000000000 -00001000000000000010011000000000 -00001001100000000000000000000000 -00000000000000000000000000000000 -01000000010001010110000010000100 -00111000001000010000111000000110 -00000010100000000001000011100000 -00100110001010000000100100011010 -00000000011000111000000000010000 -11100000000001000011100000000001 -10001010000000000100001110000000 -00010000110000000001000101010000 -00000000000000000000000000000000 -01010000000000000000000100000000 -00110000010000000000110001010100 -00000010000001000000000011000001 -00000000001000000100000000001000 -01010000000000110001010000000000 -11000001000000000011000101000000 -00001000000100000000001100000100 -00000000110000000000000000000000 -00000000000000000000000000000000 -01000000000000000000010000000000 -00110001000000000000110101001000 -00000010000101000000000011000100 -00100000001000010100100100001101 -01010000000000110101010000010000 -11000101000000000011010100000000 -00001000010000000000001100010000 -00000000110000100000000000000000 -00000000000000000000000000000000 -01000000010001010100001100000100 -01100000110000010001100000111000 -00000110000011000001000110000011 -00000100011000001100000100011000 -00110000000001100000110000000001 -10000011000001000110000111000001 -00011000001100000100011000001100 -00010001100000000001000101010000 -00000000000000000000000000000000 -01000000000000010100000000000000 -00100000000000000000100011000000 -01000010000000000000000010000000 -00000000001000000000000000001000 -01000000000000100001000000000000 -10000000000000000010000000000000 -00001000000000000000001000000000 -00000000100000000000000000000000 -00000000000000000000000000000000 -01000000000000010100100001000100 -01100010000100010001100011000100 -01000110001000010001000110001000 -01000100011000100001000100011000 -10000000000001100010000000000001 -10001000010001000110001000000001 -00011000100001000100011000100001 -00010001100000000000000000000000 -00000000000000000000000000000000 -01000000010001010100000001000100 -01010000000100010001010000000100 -01000101000000010001000101000000 -01000001000000000001000000010100 -00010100000001010000010000000001 -01000000010001000101000100010000 -00010100000001000100010100000001 -00010001010000000001000101010000 -00000000000000000000000000000000 -01000000010000000000100000100000 -01000010000010000001000010001010 -00000101001000001000000100001000 -10100000010000100000100000010000 -10000010000001000010000010000001 -00001000001000000100001000001000 -00010000100000100000010000100000 -00000001000000000000000000000000 -00000000000000000000000000000000 -00000000000000000100101000000001 -00000010100000000100000010100000 -00000000001010000000010000001010 -01000101000000101000100001000000 -10100000000100000010100000000100 -00001010000000010000001010000001 -01000000101000000001000000101000 -00000100000000000000000000000000 -00000000000000000000000000000000 -01000000010001010100110100000011 -01010011010010001101010011010010 -00000001001101000000110101001101 -01000011010100110100000011010100 -11010000001101010011010000001101 -01001101000000110101001101000000 -11010100110100000011010100110100 -00001101010000000001000101010000 -00000000000000000000000000000000 -01000000000000010100100010000000 -01110010000000000001110010000000 -01100111001000000001000111001000 -10000100011100100000000110011100 -10000000010001110010000000010001 -11001000000001000111001000000001 -00011100100000000100011100100000 -00010001110000000000000000000000 -00000000000000000000000000000000 -00000000000000000010001100001000 -01001000110000100001000000110000 -00000100100011000110000100100011 -00000000010010001100010000010000 -00110001100001000000110000100001 -00100011000110000100000011000000 -00010010001100001000010010001100 -00000001000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -01001111111111111101001111111111 -11110100111111111111110100111111 -11111111010011111111111111010011 -11111111111101001111111111111101 -00111111111111110100111111111111 -11010011111111111111010011111111 -11111101000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000001000000 -00000000000100000000000010000100 -00100000000000000000000000000000 -01000010000000000000000010000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000010110111111011 -00001011011111101100001111111111 -11110100101100110110110000101101 -11111111010010110011011111010010 -01001101101100001001001001101100 -00101100110110110000100100110110 -11000010110011011011000010110011 -01111101000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011001111111100 -01001100111111110001001111111111 -11110100110011001111000100110011 -11111111010011001100111111010011 -01010011110001001101001011110001 -00110011001111000100110101001111 -00010011001100111100010011001100 -11111101000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011101100011110 -01001110110001111001001000110001 -10000100111011011111100100111011 -00011000010011101101111000010011 -10010111111001001110000111111001 -00111011011111100100111001000110 -00010011101100011110010011101100 -01111001000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000001010000100 -00000000101000010000000000101000 -01000000000010100001000000000010 -10000100000000001010000011001100 -00101000010000000000101000001100 -11000010100001000000000010100001 -00000000001010000100000000001010 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000100000000100 -00000010000000010000000010000000 -01000000001000000001000000001000 -00000100000000100000000100000000 -10000000010000000010000000010000 -00001000000001000000001000000001 -00000000100000000100000000100000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000010000100 -00000000001000010000000000001000 -01000000000000100001000000000000 -10000100000000000010000100000000 -00001000010000000000001000010000 -00000000100001000000000000100001 -00000000000010000100000000000010 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000100 -00000000000000010000000000000000 -01000000000000000001000000000000 -00000100000000000000000100000000 -00000000010000000000000000010000 -00000000000001000000000000000001 -00000000000000000100000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000010000000 -00000000001000001100110000001000 -00110011000000100000000000000000 -10000000000000000010000000000000 -00001000000000000000001000000000 -00000000100000000000000000100000 -00000000000010000000000000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000000000000001000000000 -00000000100000000000000000100000 -00000000000010000000000000000010 -00000000000000001000000000000000 -00100000000000000000100000000000 -00000010000000000000000010000000 -00000000001000000000000000001000 -00000000000000100000000000000000 -00000000000000000000000000000000 -00001000000000000000100010000000 -00000010001000000000000010001000 -00000000001000100000000000001000 -10000000000000100010000000000000 -10001000000000000010001000000000 -00001000100000000000001000100000 -00000000100010000000000000100010 -00000000000000100000000000000000 -00000000000000000000000000000000 -00001000000000000000100000000000 -00000010000000001100110010000000 -00110011001000000000000000001000 -00000000000000100000000000000000 -10000000000000000010000000000000 -00001000000000000000001000000000 -00000000100000000000000000100000 -00000000000000100000000000000000 -00000000000000000000000000000000 -00001000000000000000101010000100 -00000010101000010000000010101000 -01000000001010100001000000001010 -10000100000000101010000100000000 -10101000010000000010101000010000 -00001010100001000000001010100001 -00000000101010000100000000101010 -00010000000000100000000000000000 -00000000000000000000000000000000 -00001000000000000000100000000100 -00000010000000010000000010000000 -01000000001000000001000000001000 -00000100000000100000000100000000 -10000000010000000010000000010000 -00001000000001000000001000000001 -00000000100000000100000000100000 -00010000000000100000000000000000 -00000000000000000000000000000000 -00001000000000000000000010000100 -00000000001000010000000000001000 -01000000000000100001000000000000 -10000100000000000010000100000000 -00001000010000000000001000010000 -00000000100001000000000000100001 -00000000000010000100000000000010 -00010000000000100000000000000000 -00000000000000000000000000000000 -00001000000100000000000000000111 -00110000000000011100110000000000 -01110011000000000001110011000000 -00000111001100000000000111001100 -00000000011100110000000000011100 -11000000000001110011000000000001 -11001100000000000111001100000000 -00011100110000100000010000000000 -00000000000000000000000000000000 -00001000000000000000000010000100 -00000000001000010000000000001000 -01110011000000100001000000000000 -10000111001100000010000100000000 -00001000010000000000001000011100 -11000000100001000000000000100001 -00000000000010000100000000000010 -00010000000000100000000000000000 -00000000000000000000000000000000 -00000000000000000000001000000000 -00000000100000000000000000100000 -01000000000010000000000000000010 -00000100000000001000000000000000 -00100000000000000000100000010000 -00000010000000000000000010000000 -00000000001000000000000000001000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000010000000 -00000000001000000000000000001000 -01000000000000100000000000000000 -10000100000000000010000000000000 -00001000000000000000001000010000 -00000000100000000000000000100000 -00000000000010000000000000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000100001000000000000000 -00000000000000000000000000000000 -00110011000000000000000000000000 -00000011001100000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000010000100000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00111100001111000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000011110000111100000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111111111111111111111111111 -11000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111111111111111111111111111 -11000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111111111111111111111111111 -11000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111111111111111111111111111 -11000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111111111111111111111111111 -11000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111111111111111111111111111 -11000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000001010000100 -00000000101000010000000000101000 -01000000000010100001000000000010 -10000100000000001010000100000000 -00101000010000000000101000010000 -00000010100001000000000010100001 -00000000001010000100000000001010 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000100 -00000000000000010000000000000000 -01000000000000000001000000000000 -00000100000000100000000100000000 -10000000010000000010000000010000 -00001000000001000000001000000001 -00000000100000000100000000100000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000100010000100 -00000000001000010000000010001000 -01000000001000100001000000001000 -10000100000000100010000100000000 -00001000010000000000001000010000 -00000000100001000000000000100001 -00000000000010000100000000000010 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000100 -00000000000000010000000000000000 -01000000000000000001000000000000 -00000100000000000000000100000000 -00000000010000000000000000010000 -00000000000001000000000000000001 -00000000000000000100000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000010000000 -00000000001000000000000000001000 -00000000000000100000000000000000 -10000000000000000010000000000000 -00001000000000000000001000000000 -00000000100000000000000000100000 -00000000000010000000000000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000000000000001000000000 -00000000100000000000000000100000 -00000000000010000000000000000010 -00000000000000001000000000000000 -00100000000000000000100000000000 -00000010000000000000000010000000 -00000000001000000000000000001000 -00000000000000100000000000000000 -00000000000000000000000000000000 -00000000000000000000100010000000 -00000010001000000000000010001000 -00000000001000100000000000001000 -10000000000000100010000000000000 -10001000000000000010001000000000 -00001000100000000000001000100000 -00000000100010000000000000100010 -00000000000000100000000000000000 -00000000000000000000000000000000 -00001000000000000000000000000000 -00000000000000000000000000000000 -00000000001000000000000000000000 -00000000000000000000000000000000 -10000000000000000010000000000000 -00001000000000000000001000000000 -00000000100000000000000000100000 -00000000000000100000000000000000 -00000000000000000000000000000000 -00001000000000000000101010000111 -00110010101000010000000010101000 -01110011001010100001000000001010 -10000100000000101010000100000000 -10101000010000000010101000010000 -00001010100001000000001010100001 -00000000101010000100000000101010 -00011100110000100000000000000000 -00000000000000000000000000000000 -00001000000000000000100000000100 -00000010000000010000000010000000 -01000000001000000001000000001000 -00000100000000100000000100000000 -10000000010000000010000000010000 -00001000000001000000001000000001 -00000000100000000100000000100000 -00010000000000100000000000000000 -00000000000000000000000000000000 -00000000000000000000000010000000 -00000000001000010000000000001000 -00000000000000100001000000000000 -10000100000000000010000100000000 -00001000010000000000001000010000 -00000000100001000000000000100001 -00000000000010000100000000000010 -00010000000000100000000000000000 -00000000000000000000000000000000 -00001000000100000000000000000100 -00000000000000011100110000000000 -01000000000000000001110011000000 -00000100000000000000000111001100 -00000000011100110000000000011100 -11000000000001110011000000000001 -11001100000000000111001100000000 -00011100110000100000010000000000 -00000000000000000000000000000000 -00001000000000000000000010000100 -00000000001000010000000000001000 -01000000000000100001000000000000 -10000100000000000010000100000000 -00001000010000000000001000010000 -00000000100001000000000000100001 -00000000000010000100000000000010 -00010000000000100000000000000000 -00000000000000000000000000000000 -00000000000000000000001000000000 -00000000100000000000000000100000 -00000000000010000000000000000010 -00000000000000001000000000000000 -00100000000000000000100000000000 -00000010000000000000000010000000 -00000000001000000000000000001000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000010000000 -00000000001000000000000000001000 -00000000000000100000000000000000 -10000000000000000010000000000000 -00001000000000000000001000000000 -00000000100000000000000000100000 -00000000000010000000000000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000100001000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000010000100000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00111100001111000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000011110000111100000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111111111111111111111111111 -11000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111111111111111111111111111 -11000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111111111111111111111111111 -11000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111111111111111111111111111 -11000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111111111111111111111111111 -11000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111111111111111111111111111 -11000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00110000000000000010000000000001 -00000010000000000000000000000000 -00110000000000000100001001001001 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00110000000000000010000000000001 -00000010000000100000000000000000 -00110000000000000100001001000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00110000000000000000000000000001 -00000000000000001010001010111110 -00110000000000001000000000000001 -00000000000000000000000000000011 -00110000000000000100000000001001 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00110000000000001000000000000001 -00000000000000000000000000000101 -00110000000000001010000000000001 -00000000000000000000000000000000 -00110000000000000000000000000001 -00000000000000001100000101111101 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 diff --git a/proslic.h b/proslic.h deleted file mode 100644 index 933bd34..0000000 --- a/proslic.h +++ /dev/null @@ -1,190 +0,0 @@ -// ProSlic Header File - -typedef struct { - unsigned char address; - unsigned char altaddr; - char *name; - unsigned short initial; -} alpha; - -typedef struct { - unsigned char chip_number; - unsigned char DTMF_digit; - unsigned char interrupt_line; - unsigned char hook_status; - unsigned long half_pulses[20]; // Contains the time stamps of incomming half pulses. - unsigned char half_pulses_detected; // Contains the number of half pulses detected. - unsigned char Pulse_digit; - unsigned long On_Hook_time; - unsigned long Off_Hook_time; -} chipStruct; - -// Defines -#define LPT 0X378 - -#define IDA_LO 28 -#define IDA_HI 29 - -#define IAA 30 -#define ID_ACCES_STATUS 31 -#define IAS_BIT 1 - -#define I_STATUS 31 - -#define SPI_MODE 0 -#define PCM_MODE 1 -#define PCM_XMIT_START_COUNT_LSB 2 -#define PCM_XMIT_START_COUNT_MSB 3 -#define PCM_RCV_START_COUNT_LSB 4 -#define PCM_RCV_START_COUNT_MSB 5 -#define DIO 6 - -#define AUDIO_LOOPBACK 8 -#define AUDIO_GAIN 9 -#define LINE_IMPEDANCE 10 -#define HYBRID 11 -#define RESERVED12 12 -#define RESERVED13 13 -#define PWR_DOWN1 14 -#define PWR_DOWN2 15 -#define RESERVED16 16 -#define RESERVED17 17 -#define INTRPT_STATUS1 18 -#define INTRPT_STATUS2 19 -#define INTRPT_STATUS3 20 -#define INTRPT_MASK1 21 -#define INTRPT_MASK2 22 -#define INTRPT_MASK3 23 -#define DTMF_DIGIT 24 -#define RESERVED25 25 -#define RESERVED26 26 -#define RESERVED27 27 -#define I_DATA_LOW 28 -#define I_DATA_HIGH 29 -#define I_ADDRESS 30 -#define I_STATUS 31 -#define OSC1 32 -#define OSC2 33 -#define RING_OSC_CTL 34 -#define PULSE_OSC 35 -#define OSC1_ON__LO 36 -#define OSC1_ON_HI 37 -#define OSC1_OFF_LO 38 -#define OSC1_OFF_HI 39 -#define OSC2_ON__LO 40 -#define OSC2_ON_HI 41 -#define OSC2_OFF_LO 42 -#define OSC2_OFF_HI 43 -#define PULSE_ON__LO 44 -#define PULSE_ON_HI 45 -#define PULSE_OFF_LO 46 -#define PULSE_OFF_HI 47 -#define RING_ON__LO 48 -#define RING_ON_HI 49 -#define RING_OFF_LO 50 -#define RING_OFF_HI 51 -#define RESERVED52 52 -#define RESERVED53 53 -#define RESERVED54 54 -#define RESERVED55 55 -#define RESERVED56 56 -#define RESERVED57 57 -#define RESERVED58 58 -#define RESERVED59 59 -#define RESERVED60 60 -#define RESERVED61 61 -#define RESERVED62 62 -#define RESERVED63 63 -#define LINE_STATE 64 -#define ACTIVATE_LINE 0x11 -#define RING_LINE 0x44 -#define BIAS_SQUELCH 65 -#define BAT_FEED 66 -#define AUTO_STATE 67 -#define LOOP_STAT 68 -#define LOOP_DEBOUCE 69 -#define RT_DEBOUCE 70 -#define LOOP_I_LIMIT 71 -#define OFF_HOOK_V 72 -#define COMMON_V 73 -#define BAT_V_HI 74 -#define BAT_V_LO 75 -#define PWR_STAT_DEV 76 -#define PWR_STAT 77 -#define LOOP_V_SENSE 78 -#define LOOP_I_SENSE 79 -#define TIP_V_SENSE 80 -#define RING_V_SENSE 81 -#define BAT_V_HI_SENSE 82 -#define BAT_V_LO_SENSE 83 -#define IQ1 84 -#define IQ2 85 -#define IQ3 86 -#define IQ4 87 -#define IQ5 88 -#define IQ6 89 -#define RESERVED90 90 -#define RESERVED91 91 -#define DCDC_PWM_OFF 92 -#define DCDC 93 -#define DCDC_PW_OFF 94 -#define RESERVED95 95 -#define CALIBR1 96 -#define CALIBRATE_LINE 0x78 -#define NORMAL_CALIBRATION_COMPLETE 0x20 -#define CALIBR2 97 -#define RING_GAIN_CAL 98 -#define TIP_GAIN_CAL 99 -#define DIFF_I_CAL 100 -#define COMMON_I_CAL 101 -#define I_LIMIT_GAIN_CAL 102 -#define ADC_OFFSET_CAL 103 -#define DAC_ADC_OFFSET 104 -#define DAC_OFFSET_CAL 105 -#define COMMON_BAL_CAL 106 -#define DC_PEAK_CAL 107 - -// Indirect Register (decimal) -#define DTMF_ROW_0_PEAK 0 -#define DTMF_ROW_1_PEAK 1 -#define DTMF_ROW2_PEAK 2 -#define DTMF_ROW3_PEAK 3 -#define DTMF_COL1_PEAK 4 -#define DTMF_FWD_TWIST 5 -#define DTMF_RVS_TWIST 6 -#define DTMF_ROW_RATIO_THRESH 7 -#define DTMF_COL_RATIO_THRESH 8 -#define DTMF_ROW_2ND_HARM 9 -#define DTMF_COL_2ND_HARM 10 -#define DTMF_PWR_MIN_THRESH 11 -#define DTMF_HOT_LIM_THRESH 12 -#define OSC1_COEF 13 -#define OSC1X 14 -#define OSC1Y 15 -#define OSC2_COEF 16 -#define OSC2X 17 -#define OSC2Y 18 -#define RING_V_OFF 19 -#define RING_OSC_COEF 20 -#define RING_X 21 -#define RING_Y 22 -#define PULSE_ENVEL 23 -#define PULSE_X 24 -#define PULSE_Y 25 -#define RECV_DIGITAL_GAIN 26 -#define XMIT_DIGITAL_GAIN 27 -#define LOOP_CLOSE_THRESH 28 -#define RING_TRIP_THRESH 29 -#define COMMON_MIN_THRESH 30 -#define COMMON_MAX_THRESH 31 -#define PWR_ALARM_Q1Q2 32 -#define PWR_ALARM_Q3Q4 33 -#define PWR_ALARM_Q5Q6 34 -#define LOOP_CLOSURE_FILTER 35 -#define RING_TRIP_FILTER 36 -#define THERM_LP_POLE_Q1Q2 37 -#define THERM_LP_POLE_Q3Q4 38 -#define THERM_LP_POLE_Q5Q6 39 -#define CM_BIAS_RINGING 40 -#define DCDC_MIN_V 41 -#define DCDC_XTRA 42 diff --git a/sec-2.h b/sec-2.h deleted file mode 100644 index 49342ea..0000000 --- a/sec-2.h +++ /dev/null @@ -1,451 +0,0 @@ -/* - * SpanDSP - a series of DSP components for telephony - * - * echo.c - An echo cancellor, suitable for electrical and acoustic - * cancellation. This code does not currently comply with - * any relevant standards (e.g. G.164/5/7/8). One day.... - * - * Written by Steve Underwood - * - * Copyright (C) 2001 Steve Underwood - * - * Based on a bit from here, a bit from there, eye of toad, - * ear of bat, etc - plus, of course, my own 2 cents. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* TODO: - Finish the echo suppressor option, however nasty suppression may be - Add an option to reintroduce side tone at -24dB under appropriate conditions. - Improve double talk detector (iterative!) -*/ - -#ifndef _ZAPTEL_SEC_H -#define _ZAPTEL_SEC_H - -#ifdef __KERNEL__ -#include -#include -#define MALLOC(a) kmalloc((a), GFP_KERNEL) -#define FREE(a) kfree(a) -#else -#include -#include -#include -#include -#define MALLOC(a) malloc(a) -#define FREE(a) free(a) -#endif - -#include "fir.h" - -#ifndef NULL -#define NULL 0 -#endif -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE (!FALSE) -#endif - -#define NONUPDATE_DWELL_TIME 600 /* 600 samples, or 75ms */ - -struct echo_can_state -{ - int tx_power; - int rx_power; - int clean_rx_power; - - int rx_power_threshold; - int nonupdate_dwell; - - fir16_state_t fir_state; - int16_t *fir_taps16; /* 16-bit version of FIR taps */ - int32_t *fir_taps32; /* 32-bit version of FIR taps */ - - int curr_pos; - - int taps; - int tap_mask; - int use_nlp; - int use_suppressor; - - int32_t supp_test1; - int32_t supp_test2; - int32_t supp1; - int32_t supp2; - - int32_t latest_correction; /* Indication of the magnitude of the latest - adaption, or a code to indicate why adaption - was skipped, for test purposes */ -}; - -static void echo_can_free(struct echo_can_state *ec); -static int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx); - -static void echo_can_init(void) -{ - printk("Zaptel Echo Canceller: STEVE2%s\n", ZAPTEL_ECHO_AGGRESSIVE); -} - -static void echo_can_identify(char *buf, size_t len) -{ - strncpy(buf, "STEVE2", len); -} - -static void echo_can_shutdown(void) -{ -} - -/* - * According to Jim... - */ -#define MIN_TX_POWER_FOR_ADAPTION 512 -#define MIN_RX_POWER_FOR_ADAPTION 64 - -/* - * According to Steve... - */ -/* #define MIN_TX_POWER_FOR_ADAPTION 4096 -#define MIN_RX_POWER_FOR_ADAPTION 64 */ - -static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p, - struct echo_can_state **ec) -{ - size_t size; - - if (ecp->param_count > 0) { - printk(KERN_WARNING "SEC-2 echo canceler does not support parameters; failing request\n"); - return -EINVAL; - } - - size = sizeof(**ec) + ecp->tap_length * sizeof(int32_t) + ecp->tap_length * 3 * sizeof(int16_t); - - if (!(*ec = MALLOC(size))) - return -ENOMEM; - - memset(*ec, 0, size); - - (*ec)->taps = ecp->tap_length; - (*ec)->curr_pos = ecp->tap_length - 1; - (*ec)->tap_mask = ecp->tap_length - 1; - (*ec)->fir_taps32 = (int32_t *) (*ec + sizeof(**ec)); - (*ec)->fir_taps16 = (int16_t *) (*ec + sizeof(**ec) + ecp->tap_length * sizeof(int32_t)); - /* Create FIR filter */ - fir16_create(&(*ec)->fir_state, (*ec)->fir_taps16, (*ec)->taps); - (*ec)->rx_power_threshold = 10000000; - (*ec)->use_suppressor = FALSE; - /* Non-linear processor - a fancy way to say "zap small signals, to avoid - accumulating noise". */ - (*ec)->use_nlp = FALSE; - - return 0; -} -/*- End of function --------------------------------------------------------*/ - -static inline void echo_can_free(struct echo_can_state *ec) -{ - fir16_free(&ec->fir_state); - FREE(ec); -} -/*- End of function --------------------------------------------------------*/ - -static inline int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx) -{ - int offset1; - int offset2; - int32_t echo_value; - int clean_rx; - int nsuppr; - int i; - int correction; - - /* Evaluate the echo - i.e. apply the FIR filter */ - /* Assume the gain of the FIR does not exceed unity. Exceeding unity - would seem like a rather poor thing for an echo cancellor to do :) - This means we can compute the result with a total disregard for - overflows. 16bits x 16bits -> 31bits, so no overflow can occur in - any multiply. While accumulating we may overflow and underflow the - 32 bit scale often. However, if the gain does not exceed unity, - everything should work itself out, and the final result will be - OK, without any saturation logic. */ - /* Overflow is very much possible here, and we do nothing about it because - of the compute costs */ - /* 16 bit coeffs for the LMS give lousy results (maths good, actual sound - bad!), but 32 bit coeffs require some shifting. On balance 32 bit seems - best */ - echo_value = fir16 (&ec->fir_state, tx); - - /* And the answer is..... */ - clean_rx = rx - echo_value; - - /* That was the easy part. Now we need to adapt! */ - if (ec->nonupdate_dwell > 0) - ec->nonupdate_dwell--; - - /* If there is very little being transmitted, any attempt to train is - futile. We would either be training on the far end's noise or signal, - the channel's own noise, or our noise. Either way, this is hardly good - training, so don't do it (avoid trouble). */ - /* If the received power is very low, either we are sending very little or - we are already well adapted. There is little point in trying to improve - the adaption under these circumstanceson, so don't do it (reduce the - compute load). */ - if (ec->tx_power > MIN_TX_POWER_FOR_ADAPTION - && - ec->rx_power > MIN_RX_POWER_FOR_ADAPTION) - { - /* This is a really crude piece of decision logic, but it does OK - for now. */ - if (ec->tx_power > 2*ec->rx_power) - { - /* There is no far-end speech detected */ - if (ec->nonupdate_dwell == 0) - { - /* ... and we are not in the dwell time from previous speech. */ - //nsuppr = saturate((clean_rx << 16)/ec->tx_power); - nsuppr = clean_rx >> 3; - - /* Update the FIR taps */ - offset2 = ec->curr_pos + 1; - offset1 = ec->taps - offset2; - ec->latest_correction = 0; - for (i = ec->taps - 1; i >= offset1; i--) - { - correction = ec->fir_state.history[i - offset1]*nsuppr; - /* Leak to avoid false training on signals with multiple - strong correlations. */ - ec->fir_taps32[i] -= (ec->fir_taps32[i] >> 12); - ec->fir_taps32[i] += correction; - ec->fir_state.coeffs[i] = ec->fir_taps32[i] >> 15; - ec->latest_correction += abs(correction); - } - for ( ; i >= 0; i--) - { - correction = ec->fir_state.history[i + offset2]*nsuppr; - /* Leak to avoid false training on signals with multiple - strong correlations. */ - ec->fir_taps32[i] -= (ec->fir_taps32[i] >> 12); - ec->fir_taps32[i] += correction; - ec->fir_state.coeffs[i] = ec->fir_taps32[i] >> 15; - ec->latest_correction += abs(correction); - } - } - else - { - ec->latest_correction = -1; - } - } - else - { - ec->nonupdate_dwell = NONUPDATE_DWELL_TIME; - ec->latest_correction = -2; - } - } - else - { - ec->nonupdate_dwell = 0; - ec->latest_correction = -3; - } - /* Calculate short term power levels using very simple single pole IIRs */ - /* TODO: Is the nasty modulus approach the fastest, or would a real - tx*tx power calculation actually be faster? */ - ec->tx_power += ((abs(tx) - ec->tx_power) >> 5); - ec->rx_power += ((abs(rx) - ec->rx_power) >> 5); - ec->clean_rx_power += ((abs(clean_rx) - ec->clean_rx_power) >> 5); - -#if defined(XYZZY) - if (ec->use_suppressor) - { - ec->supp_test1 += (ec->fir_state.history[ec->curr_pos] - ec->fir_state.history[(ec->curr_pos - 7) & ec->tap_mask]); - ec->supp_test2 += (ec->fir_state.history[(ec->curr_pos - 24) & ec->tap_mask] - ec->fir_state.history[(ec->curr_pos - 31) & ec->tap_mask]); - if (ec->supp_test1 > 42 && ec->supp_test2 > 42) - supp_change = 25; - else - supp_change = 50; - supp = supp_change + k1*ec->supp1 + k2*ec->supp2; - ec->supp2 = ec->supp1; - ec->supp1 = supp; - clean_rx *= (1 - supp); - } -#endif - - if (ec->use_nlp && ec->rx_power < 32) - clean_rx = 0; - - /* Roll around the rolling buffer */ - if (ec->curr_pos <= 0) - ec->curr_pos = ec->taps; - ec->curr_pos--; - - return clean_rx; -} - -#if 0 -static inline int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx) -{ - int offset; - int limit; - int32_t echo_value; - int clean_rx; - int nsuppr; - int i; - int correction; - - ec->tx_history[ec->curr_pos] = tx; - - /* Evaluate the echo - i.e. apply the FIR filter */ - /* Assume the gain of the FIR does not exceed unity. Exceeding unity - would seem like a rather poor thing for an echo cancellor to do :) - This means we can compute the result with a total disregard for - overflows. 16bits x 16bits -> 31bits, so no overflow can occur in - any multiply. While accumulating we may overflow and underflow the - 32 bit scale often. However, if the gain does not exceed unity, - everything should work itself out, and the final result will be - OK, without any saturation logic. */ - /* Overflow is very much possible here, and we do nothing about it because - of the compute costs */ - /* 16 bit coeffs for the LMS give lousy results (maths good, actual sound - bad!), but 32 bit coeffs require some shifting. On balance 32 bit seems - best */ - offset = ec->curr_pos; - limit = ec->taps - offset; - echo_value = 0; - for (i = 0; i < limit; i++) - echo_value += (ec->fir_taps[i] >> 16)*ec->tx_history[i + offset]; - offset = ec->taps - ec->curr_pos; - for ( ; i < ec->taps; i++) - echo_value += (ec->fir_taps[i] >> 16)*ec->tx_history[i - offset]; - echo_value >>= 16; - - /* And the answer is..... */ - clean_rx = rx - echo_value; - - /* That was the easy part. Now we need to adapt! */ - if (ec->nonupdate_dwell > 0) - ec->nonupdate_dwell--; - - /* If there is very little being transmitted, any attempt to train is - futile. We would either be training on the far end's noise or signal, - the channel's own noise, or our noise. Either way, this is hardly good - training, so don't do it (avoid trouble). */ - /* If the received power is very low, either we are sending very little or - we are already well adapted. There is little point in trying to improve - the adaption under these circumstanceson, so don't do it (reduce the - compute load). */ - if (ec->tx_power > MIN_TX_POWER_FOR_ADAPTION - && - ec->rx_power > MIN_RX_POWER_FOR_ADAPTION) - { - /* This is a really crude piece of decision logic, but it does OK - for now. */ - if (ec->tx_power > 2*ec->rx_power) - { - /* There is no far-end speech detected */ - if (ec->nonupdate_dwell == 0) - { - /* ... and we are not in the dwell time from previous speech. */ - //nsuppr = saturate((clean_rx << 16)/ec->tx_power); - nsuppr = clean_rx >> 3; - - /* Update the FIR taps */ - offset = ec->curr_pos; - limit = ec->taps - offset; - ec->latest_correction = 0; - for (i = 0; i < limit; i++) - { - correction = ec->tx_history[i + offset]*nsuppr; - ec->fir_taps[i] += correction; - //ec->latest_correction += abs(correction); - } - offset = ec->taps - ec->curr_pos; - for ( ; i < ec->taps; i++) - { - correction = ec->tx_history[i - offset]*nsuppr; - ec->fir_taps[i] += correction; - //ec->latest_correction += abs(correction); - } - } - else - { - ec->latest_correction = -3; - } - } - else - { - ec->nonupdate_dwell = NONUPDATE_DWELL_TIME; - ec->latest_correction = -2; - } - } - else - { - ec->nonupdate_dwell = 0; - ec->latest_correction = -1; - } - /* Calculate short term power levels using very simple single pole IIRs */ - /* TODO: Is the nasty modulus approach the fastest, or would a real - tx*tx power calculation actually be faster? */ - ec->tx_power += ((abs(tx) - ec->tx_power) >> 5); - ec->rx_power += ((abs(rx) - ec->rx_power) >> 5); - ec->clean_rx_power += ((abs(clean_rx) - ec->clean_rx_power) >> 5); - -#if defined(XYZZY) - if (ec->use_suppressor) - { - ec->supp_test1 += (ec->tx_history[ec->curr_pos] - ec->tx_history[(ec->curr_pos - 7) & ec->tap_mask]); - ec->supp_test2 += (ec->tx_history[(ec->curr_pos - 24) & ec->tap_mask] - ec->tx_history[(ec->curr_pos - 31) & ec->tap_mask]); - if (ec->supp_test1 > 42 && ec->supp_test2 > 42) - supp_change = 25; - else - supp_change = 50; - supp = supp_change + k1*ec->supp1 + k2*ec->supp2; - ec->supp2 = ec->supp1; - ec->supp1 = supp; - clean_rx *= (1 - supp); - } -#endif - - if (ec->use_nlp && ec->rx_power < 32) - clean_rx = 0; - - /* Roll around the rolling buffer */ - ec->curr_pos = (ec->curr_pos + 1) & ec->tap_mask; - - return clean_rx; -} -/*- End of function --------------------------------------------------------*/ -#endif - -static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) -{ - /* Reset hang counter to avoid adjustments after - initial forced training */ - ec->nonupdate_dwell = ec->taps << 1; - if (pos >= ec->taps) - return 1; - ec->fir_taps32[pos] = val << 17; - ec->fir_taps16[pos] = val << 1; - if (++pos >= ec->taps) - return 1; - return 0; -} - -/*- End of file ------------------------------------------------------------*/ -#endif diff --git a/sec.h b/sec.h deleted file mode 100644 index 6c4b7c0..0000000 --- a/sec.h +++ /dev/null @@ -1,310 +0,0 @@ -/* - * SpanDSP - a series of DSP components for telephony - * - * echo.c - An echo cancellor, suitable for electrical and acoustic - * cancellation. This code does not currently comply with - * any relevant standards (e.g. G.164/5/7/8). One day.... - * - * Written by Steve Underwood - * Various optimizations and improvements by Mark Spencer - * - * Copyright (C) 2001 Steve Underwood - * - * Based on a bit from here, a bit from there, eye of toad, - * ear of bat, etc - plus, of course, my own 2 cents. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* TODO: - Finish the echo suppressor option, however nasty suppression may be - Add an option to reintroduce side tone at -24dB under appropriate conditions. - Improve double talk detector (iterative!) -*/ - -#ifndef _ZAPTEL_SEC_H -#define _ZAPTEL_SEC_H - -#ifdef __KERNEL__ -#include -#include -#define MALLOC(a) kmalloc((a), GFP_KERNEL) -#define FREE(a) kfree(a) -#else -#include -#include -#include -#include -#define MALLOC(a) malloc(a) -#define FREE(a) free(a) -#endif - -#include "arith.h" - -#ifndef NULL -#define NULL 0 -#endif -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE (!FALSE) -#endif - -#define USE_SHORTS - -#define NONUPDATE_DWELL_TIME 600 /* 600 samples, or 75ms */ - -struct echo_can_state -{ - int tx_power; - int rx_power; - int clean_rx_power; - - int rx_power_threshold; - int nonupdate_dwell; - - int16_t *tx_history; /* Last N tx samples */ - int32_t *fir_taps; /* Echo FIR taps */ - int16_t *fir_taps_short; /* Echo FIR taps, shorts instead of ints */ - - int curr_pos; - - int taps; - int tap_mask; - int use_nlp; - int use_suppressor; - - int32_t supp_test1; - int32_t supp_test2; - int32_t supp1; - int32_t supp2; - - int32_t latest_correction; /* Indication of the magnitude of the latest - adaption, or a code to indicate why adaption - was skipped, for test purposes */ -}; - -static void echo_can_init(void) -{ - printk("Zaptel Echo Canceller: STEVE%s\n", ZAPTEL_ECHO_AGGRESSIVE); -} - -static void echo_can_identify(char *buf, size_t len) -{ - strncpy(buf, "STEVE", len); -} - -static void echo_can_shutdown(void) -{ -} - -static void echo_can_free(struct echo_can_state *ec); -static int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx); - -/* Original parameters : -#define MIN_TX_POWER_FOR_ADAPTION 256 -#define MIN_RX_POWER_FOR_ADAPTION 128 -*/ - -#define MIN_TX_POWER_FOR_ADAPTION 256 -#define MIN_RX_POWER_FOR_ADAPTION 64 - -/* Better ones found by Jim -#define MIN_TX_POWER_FOR_ADAPTION 128 -#define MIN_RX_POWER_FOR_ADAPTION 64 -*/ - -static int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p, - struct echo_can_state **ec) -{ - size_t size; - - if (ecp->param_count > 0) { - printk(KERN_WARNING "SEC echo canceler does not support parameters; failing request\n"); - return -EINVAL; - } - - size = sizeof(**ec) + ecp->tap_length * sizeof(int32_t) + ecp->tap_length * 3 * sizeof(int16_t); - - if (!(*ec = MALLOC(size))) - return -ENOMEM; - - memset(*ec, 0, size); - - (*ec)->taps = ecp->tap_length; - (*ec)->tap_mask = ecp->tap_length - 1; - (*ec)->tx_history = (int16_t *) (*ec + sizeof(**ec)); - (*ec)->fir_taps = (int32_t *) (*ec + sizeof(**ec) + - ecp->tap_length * 2 * sizeof(int16_t)); - (*ec)->fir_taps_short = (int16_t *) (*ec + sizeof(**ec) + - ecp->tap_length * sizeof(int32_t) + - ecp->tap_length * 2 * sizeof(int16_t)); - (*ec)->rx_power_threshold = 10000000; - (*ec)->use_suppressor = FALSE; - /* Non-linear processor - a fancy way to say "zap small signals, to avoid - accumulating noise". */ - (*ec)->use_nlp = TRUE; - - return 0; -} -/*- End of function --------------------------------------------------------*/ - -static inline void echo_can_free(struct echo_can_state *ec) -{ - FREE(ec); -} -/*- End of function --------------------------------------------------------*/ - -static inline int16_t echo_can_update(struct echo_can_state *ec, int16_t tx, int16_t rx) -{ - int32_t echo_value; - int clean_rx; - int nsuppr; - - ec->tx_history[ec->curr_pos] = tx; - ec->tx_history[ec->curr_pos + ec->taps] = tx; - - /* Evaluate the echo - i.e. apply the FIR filter */ - /* Assume the gain of the FIR does not exceed unity. Exceeding unity - would seem like a rather poor thing for an echo cancellor to do :) - This means we can compute the result with a total disregard for - overflows. 16bits x 16bits -> 31bits, so no overflow can occur in - any multiply. While accumulating we may overflow and underflow the - 32 bit scale often. However, if the gain does not exceed unity, - everything should work itself out, and the final result will be - OK, without any saturation logic. */ - /* Overflow is very much possible here, and we do nothing about it because - of the compute costs */ - /* 16 bit coeffs for the LMS give lousy results (maths good, actual sound - bad!), but 32 bit coeffs require some shifting. On balance 32 bit seems - best */ -#ifdef USE_SHORTS - echo_value = CONVOLVE2(ec->fir_taps_short, ec->tx_history + ec->curr_pos, ec->taps); -#else - echo_value = CONVOLVE(ec->fir_taps, ec->tx_history + ec->curr_pos, ec->taps); -#endif - echo_value >>= 16; - - /* And the answer is..... */ - clean_rx = rx - echo_value; - - /* That was the easy part. Now we need to adapt! */ - if (ec->nonupdate_dwell > 0) - ec->nonupdate_dwell--; - - /* If there is very little being transmitted, any attempt to train is - futile. We would either be training on the far end's noise or signal, - the channel's own noise, or our noise. Either way, this is hardly good - training, so don't do it (avoid trouble). */ - /* If the received power is very low, either we are sending very little or - we are already well adapted. There is little point in trying to improve - the adaption under these circumstanceson, so don't do it (reduce the - compute load). */ - if (ec->tx_power > MIN_TX_POWER_FOR_ADAPTION - && - ec->rx_power > MIN_RX_POWER_FOR_ADAPTION) - { - /* This is a really crude piece of decision logic, but it does OK - for now. */ - if (ec->tx_power > ec->rx_power << 1) - { - /* There is no far-end speech detected */ - if (ec->nonupdate_dwell == 0) - { - /* ... and we are not in the dwell time from previous speech. */ - //nsuppr = saturate((clean_rx << 16)/ec->tx_power); - nsuppr = (clean_rx << 16) / ec->tx_power; - nsuppr >>= 4; - if (nsuppr > 512) - nsuppr = 512; - if (nsuppr < -512) - nsuppr = -512; - - /* Update the FIR taps */ - ec->latest_correction = 0; -#ifdef USE_SHORTS - UPDATE2(ec->fir_taps, ec->fir_taps_short, ec->tx_history + ec->curr_pos, nsuppr, ec->taps); -#else - UPDATE(ec->fir_taps, ec->fir_taps_short, ec->tx_history + ec->curr_pos, nsuppr, ec->taps); -#endif - } else - { - ec->latest_correction = -3; - } - } - else - { - ec->nonupdate_dwell = NONUPDATE_DWELL_TIME; - ec->latest_correction = -2; - } - } - else - { - ec->nonupdate_dwell = 0; - ec->latest_correction = -1; - } - /* Calculate short term power levels using very simple single pole IIRs */ - /* TODO: Is the nasty modulus approach the fastest, or would a real - tx*tx power calculation actually be faster? */ - ec->tx_power += ((abs(tx) - ec->tx_power) >> 5); - ec->rx_power += ((abs(rx) - ec->rx_power) >> 5); - ec->clean_rx_power += ((abs(clean_rx) - ec->clean_rx_power) >> 5); - -#if defined(XYZZY) - if (ec->use_suppressor) - { - ec->supp_test1 += (ec->tx_history[ec->curr_pos] - ec->tx_history[(ec->curr_pos - 7) & ec->tap_mask]); - ec->supp_test2 += (ec->tx_history[(ec->curr_pos - 24) & ec->tap_mask] - ec->tx_history[(ec->curr_pos - 31) & ec->tap_mask]); - if (ec->supp_test1 > 42 && ec->supp_test2 > 42) - supp_change = 25; - else - supp_change = 50; - supp = supp_change + k1*ec->supp1 + k2*ec->supp2; - ec->supp2 = ec->supp1; - ec->supp1 = supp; - clean_rx *= (1 - supp); - } -#endif - - if (ec->use_nlp && ec->rx_power < 32) - clean_rx = 0; - - /* Roll around the rolling buffer */ - ec->curr_pos = (ec->curr_pos - 1) & ec->tap_mask; - - return clean_rx; -} -/*- End of function --------------------------------------------------------*/ - -static inline int echo_can_traintap(struct echo_can_state *ec, int pos, short val) -{ - /* Reset hang counter to avoid adjustments after - initial forced training */ - ec->nonupdate_dwell = ec->taps << 1; - if (pos >= ec->taps) - return 1; - ec->fir_taps[pos] = val << 17; - ec->fir_taps_short[pos] = val << 1; - if (++pos >= ec->taps) - return 1; - return 0; -} - -/*- End of file ------------------------------------------------------------*/ -#endif diff --git a/timertest.c b/timertest.c index 10d9d66..3a0c2e4 100644 --- a/timertest.c +++ b/timertest.c @@ -9,7 +9,7 @@ #include #ifdef STANDALONE_ZAPATA -#include "zaptel.h" +#include "kernel/zaptel.h" #else #include #endif diff --git a/tonezone.h b/tonezone.h index fba3e91..f59940e 100644 --- a/tonezone.h +++ b/tonezone.h @@ -25,7 +25,7 @@ #define _TONEZONE_H #ifdef STANDALONE_ZAPATA -#include "zaptel.h" +#include "kernel/zaptel.h" #else #include #endif diff --git a/tor2-hw.h b/tor2-hw.h deleted file mode 100644 index 8da5c52..0000000 --- a/tor2-hw.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Tormenta 2 Quad-T1 PCI Driver - * - * Written by Mark Spencer - * - * Copyright (C) 2001 Jim Dixon / Zapata Telephony. - * Copyright (C) 2001, Linux Support Services, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef _TOR2_HW_H -#define _TOR2_HW_H - -/* - * The Tormenta two consists of the following block architecture: - * - * [ Spartan ] --- [ DS 21Q352 ] -- Xfrms -- Span 1 - * | | | | | | | - * Local Bus +----- Span 2 - * | | | | - * [ PCI 9030 ] +----- Span 3 - * | | | | | | - * PCI BUS +----- Span 4 - * - * All communicatiosn to the framer (21Q352) are performed - * through the PCI 9030 part using memory mapped I/O. - * - * The Tormenta 2 requires a 2 2k wondows memory space - * which is mapped as follows: - * - * First (32 bit) space: - * - * 0x0000 -> 0x07FF: Memory map of Tx and Rx buffers. They are stored - * with increasing channel number, with each span in - * a byte of a 32-bit long word: - * Bits 31-24: Span 1 - * Bits 23-16: Span 2 - * Bits 16- 8: Span 3 - * Bits 7- 0: Span 4 - * - * - * Second (8 bit) space: - * - * 0x0000 -> 0x00FF: Registers for Transceiver 1 - * 0x0100 -> 0x01FF: Registers for Transceiver 2 - * 0x0200 -> 0x02FF: Registers for Transceiver 3 - * 0x0300 -> 0x03FF: Registers for Transceiver 4 - * - * 0x400 Write -> Firmware load location for Xilinx. This is the only valid - * register until the Xilinx is programmed to decode - * the remainder! - * - * 0x400 Write -> clkreg (sync source) - * 0=free run, 1=span 1, 2=span 2, 3=span 3, 4=span 4. - * - * 0x400 Read -> statreg - * bit 0 - Interrupt Enabled - * bit 1 - Interrupt Active - * bit 2 - Dallas Interrupt Active - * - * 0x401 Write -> ctlreg as follows: - * bit 0 - Interrupt Enable - * bit 1 - Drives "TEST1" signal ("Interrupt" outbit) - * bit 2 - Dallas Interrupt Enable (Allows DINT signal to drive INT) - * bit 3 - External Syncronization Enable (MASTER signal). - * bit 4 - Select E1 Divisor Mode (0 for T1, 1 for E1). - * bit 5 - Remote serial loopback (When set to 1, TSER is driven from RSER) - * bit 6 - Local serial loopback (When set to 1, Rx buffers are driven from Tx buffers) - * bit 7 - Interrupt Acknowledge (set to 1 to acknowledge interrupt) - * - * 0x402 Write -> LED register as follows: - * bit 0 - Span 1 Green - * bit 1 - Span 1 Red - * bit 2 - Span 2 Green - * bit 3 - Span 2 Red - * bit 4 - Span 3 Green - * bit 5 - Span 3 Red - * bit 6 - Span 4 Green - * bit 7 - Span 4 Red - * NOTE: turning on both red and green yields yellow. - * - * 0x403 Write -> TEST2, writing to bit 0 drives TEST2 pin. - * - * 0x404 Write -> ctlreg1 as follows: - * bit 0 - Non-REV.A Mode (Set this bit for Dallas chips later then Rev. A) - */ - -#ifdef NEED_PCI_IDS -/* - * Provide routines for identifying a tormenta card - */ - -#define PCI_VENDOR_ID_PLX 0x10b5 - -#ifdef __KERNEL__ -static struct pci_device_id tor2_pci_ids[] = -#else -#define PCI_ANY_ID -1 -static struct tor2_pci_id { - int vendor; - int device; - int subvendor; - int subdevice; - int class; - int classmask; - unsigned long driver_data; -} tor2_pci_ids[] = -#endif /* __KERNEL__ */ -{ - { PCI_VENDOR_ID_PLX, 0x9030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)"PLX 9030" }, /* PLX 9030 Development board */ - { PCI_VENDOR_ID_PLX, 0x3001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)"PLX Development Board" }, /* PLX 9030 Development board */ - { PCI_VENDOR_ID_PLX, 0xD00D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)"Tormenta 2 Quad T1/PRI or E1/PRA" }, /* Tormenta 2 */ - { PCI_VENDOR_ID_PLX, 0x4000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)"Tormenta 2 Quad T1/E1 (non-Digium clone)" }, /* Tormenta 2 clone */ - { 0, } -}; - -#ifndef __KERNEL__ -/* We provide a simple routine to match the given ID's */ -static inline int tor2_pci_match(int vendorid, int deviceid, char **variant) -{ - /* Returns 1 if this is a tormenta card or 0 if it isn't */ - int x; - for (x = 0; x< sizeof(tor2_pci_ids) / sizeof(tor2_pci_ids[0]); x++) - if (((tor2_pci_ids[x].vendor == PCI_ANY_ID) || - (tor2_pci_ids[x].vendor == vendorid)) && - ((tor2_pci_ids[x].device == PCI_ANY_ID) || - (tor2_pci_ids[x].device == deviceid))) { - *variant = (char *)tor2_pci_ids[x].driver_data; - return 1; - } - if (variant) - *variant = NULL; - return 0; -} -#endif /* __KERNEL__ */ -#endif /* NEED_PCI_IDS */ - -/* - * PLX PCI9030 PCI Configuration Registers - * - * This is not an all-inclusive list, just some interesting ones - * that we need and that are not standard. - * - */ -#define PLX_PCI_VPD_ADDR 0x4e /* Set address here */ -#define PLX_PCI_VPD_DATA 0x50 /* Read/Write data here */ - -#define PLX_LOC_WP_BOUNDARY 0x4e /* Bits 6-0 here */ -#define PLX_LOC_GPIOC 0x54 /* GPIO control register */ - -/* The 4 GPIO data bits we are interested in */ - -#define LOC_GPIOC_GPIO4 0x4000 /* GPIO4 data */ -#define LOC_GPIOC_GPIO5 0x20000 /* GPIO5 data */ -#define LOC_GPIOC_GPIO6 0x100000 /* GPIO6 data */ -#define LOC_GPIOC_GPIO7 0x800000 /* GPIO7 data */ - -/* define the initialization of the GPIOC register */ - -#define LOC_GPIOC_INIT_VALUE 0x2036000 /* GPIO 4&5 in write and - both high and GPIO 8 in write low */ - -/* The defines by what they actually do */ - -#define GPIO_WRITE LOC_GPIOC_GPIO4 -#define GPIO_PROGRAM LOC_GPIOC_GPIO5 -#define GPIO_INIT LOC_GPIOC_GPIO6 -#define GPIO_DONE LOC_GPIOC_GPIO7 - -#endif /* _TOR2_HW_H */ - diff --git a/tor2.c b/tor2.c deleted file mode 100644 index ef2cf05..0000000 --- a/tor2.c +++ /dev/null @@ -1,1520 +0,0 @@ -/* - * Tormenta 2 Quad-T1 PCI Driver - * - * Written by Mark Spencer - * Based on previous works, designs, and archetectures conceived and - * written by Jim Dixon . - * - * Copyright (C) 2001 Jim Dixon / Zapata Telephony. - * Copyright (C) 2001, Linux Support Services, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "zaptel.h" -#ifdef LINUX26 -#include -#endif -#define NEED_PCI_IDS -#include "tor2-hw.h" -#include "tor2fw.h" - -/* - * Tasklets provide better system interactive response at the cost of the - * possibility of losing a frame of data at very infrequent intervals. If - * you are more concerned with the performance of your machine, enable the - * tasklets. If you are strict about absolutely no drops, then do not enable - * tasklets. - */ - -/* #define ENABLE_TASKLETS */ - -/* this stuff needs to work for 64 bit systems, however using the macro causes - it to take twice as long */ -/* #define FIXTHISFOR64 */ /* as of now, un-comment for 32 bit only system */ - -#define SPANS_PER_CARD 4 -#define MAX_SPANS 16 - -#define FLAG_STARTED (1 << 0) - -#define TYPE_T1 1 /* is a T1 card */ -#define TYPE_E1 2 /* is an E1 card */ - -struct tor2_chan { - /* Private pointer for channel. We want to know our - channel and span */ - struct tor2 *tor; - int span; /* Index from 0 */ -}; - -struct tor2_span { - /* Private pointer for span. We want to know our - span number and pointer to the tor device */ - struct tor2 *tor; - int span; /* Index from 0 */ -}; - -struct tor2 { - /* This structure exists one per card */ - struct pci_dev *pci; /* Pointer to PCI device */ - int num; /* Which card we are */ - int syncsrc; /* active sync source */ - int syncs[SPANS_PER_CARD]; /* sync sources */ - int psyncs[SPANS_PER_CARD]; /* span-relative sync sources */ - int alarmtimer[SPANS_PER_CARD]; /* Alarm timer */ - char *type; /* Type of tormenta 2 card */ - int irq; /* IRQ used by device */ - int order; /* Order */ - int flags; /* Device flags */ - int syncpos[SPANS_PER_CARD]; /* span-relative sync sources */ - int master; /* Are we master */ - unsigned long plx_region; /* phy addr of PCI9030 registers */ - unsigned long plx_len; /* length of PLX window */ - volatile unsigned short *plx; /* Virtual representation of local space */ - unsigned long xilinx32_region; /* 32 bit Region allocated to Xilinx */ - unsigned long xilinx32_len; /* Length of 32 bit Xilinx region */ - volatile unsigned int *mem32; /* Virtual representation of 32 bit Xilinx memory area */ - unsigned long xilinx8_region; /* 8 bit Region allocated to Xilinx */ - unsigned long xilinx8_len; /* Length of 8 bit Xilinx region */ - volatile unsigned char *mem8; /* Virtual representation of 8 bit Xilinx memory area */ - struct zt_span spans[SPANS_PER_CARD]; /* Spans */ - struct tor2_span tspans[SPANS_PER_CARD]; /* Span data */ - struct zt_chan *chans[SPANS_PER_CARD]; /* Pointers to blocks of 24(30/31) contiguous zt_chans for each span */ - struct tor2_chan tchans[32 * SPANS_PER_CARD]; /* Channel user data */ - unsigned char txsigs[SPANS_PER_CARD][16]; /* Copy of tx sig registers */ - int loopupcnt[SPANS_PER_CARD]; /* loop up code counter */ - int loopdowncnt[SPANS_PER_CARD];/* loop down code counter */ - int spansstarted; /* number of spans started */ - spinlock_t lock; /* lock context */ - unsigned char leds; /* copy of LED register */ - unsigned char ec_chunk1[SPANS_PER_CARD][32][ZT_CHUNKSIZE]; /* first EC chunk buffer */ - unsigned char ec_chunk2[SPANS_PER_CARD][32][ZT_CHUNKSIZE]; /* second EC chunk buffer */ -#ifdef ENABLE_TASKLETS - int taskletrun; - int taskletsched; - int taskletpending; - int taskletexec; - int txerrors; - struct tasklet_struct tor2_tlet; -#endif - int cardtype; /* card type, T1 or E1 */ - unsigned int *datxlt; /* pointer to datxlt structure */ - unsigned int passno; /* number of interrupt passes */ -}; - -#define t1out(tor,span,reg,val) tor->mem8[((span - 1) * 0x100) + reg] = val -#define t1in(tor,span,reg) tor->mem8[((span - 1) * 0x100) + reg] - -#ifdef ENABLE_TASKLETS -static void tor2_tasklet(unsigned long data); -#endif - -#define GPIOC (PLX_LOC_GPIOC >> 1) /* word-oriented address for PLX GPIOC reg. (32 bit reg.) */ -#define LAS2BRD (0x30 >> 1) -#define LAS3BRD (0x34 >> 1) -#define INTCSR (0x4c >> 1) /* word-oriented address for PLX INTCSR reg. */ -#define PLX_INTENA 0x43 /* enable, hi-going, level trigger */ - -#define SYNCREG 0x400 -#define CTLREG 0x401 -#define LEDREG 0x402 -#define STATREG 0x400 -#define SWREG 0x401 -#define CTLREG1 0x404 - -#define INTENA (1 + ((loopback & 3) << 5)) -#define OUTBIT (2 + ((loopback & 3) << 5)) -#define E1DIV 0x10 -#define INTACK (0x80 + ((loopback & 3) << 5)) -#define INTACTIVE 2 -#define MASTER (1 << 3) - -/* un-define this if you dont want NON-REV A hardware support */ -/* #define NONREVA 1 */ - -#define SYNCSELF 0 -#define SYNC1 1 -#define SYNC2 2 -#define SYNC3 3 -#define SYNC4 4 -#define SYNCEXTERN 5 - -#define LEDRED 2 -#define LEDGREEN 1 - -#define MAX_TOR_CARDS 64 - -struct tor2 *cards[MAX_TOR_CARDS]; - -/* signalling bits */ -#define TOR_ABIT 8 -#define TOR_BBIT 4 - -static int debug; -static int japan; -static int loopback; -static int highestorder; -static int timingcable; - -static void set_clear(struct tor2 *tor); -static int tor2_startup(struct zt_span *span); -static int tor2_shutdown(struct zt_span *span); -static int tor2_rbsbits(struct zt_chan *chan, int bits); -static int tor2_maint(struct zt_span *span, int cmd); -static int tor2_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data); -ZAP_IRQ_HANDLER(tor2_intr); - -/* translations of data channels for 24 channels in a 32 bit PCM highway */ -unsigned datxlt_t1[] = { - 1 ,2 ,3 ,5 ,6 ,7 ,9 ,10,11,13,14,15,17,18,19,21,22,23,25,26,27,29,30,31 }; - -/* translations of data channels for 30/31 channels in a 32 bit PCM highway */ -unsigned datxlt_e1[] = { - 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, - 25,26,27,28,29,30,31 }; - -static int tor2_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) -{ - int i; - struct tor2_span *p = span->pvt; - - if (debug) - printk("Tor2: Configuring span %d\n", span->spanno); - - span->syncsrc = p->tor->syncsrc; - - /* remove this span number from the current sync sources, if there */ - for (i = 0; i < SPANS_PER_CARD; i++) { - if (p->tor->syncs[i] == span->spanno) { - p->tor->syncs[i] = 0; - p->tor->psyncs[i] = 0; - } - } - p->tor->syncpos[p->span] = lc->sync; - /* if a sync src, put it in the proper place */ - if (lc->sync) { - p->tor->syncs[lc->sync - 1] = span->spanno; - p->tor->psyncs[lc->sync - 1] = p->span + 1; - } - /* If we're already running, then go ahead and apply the changes */ - if (span->flags & ZT_FLAG_RUNNING) - return tor2_startup(span); - - return 0; -} - -static int tor2_chanconfig(struct zt_chan *chan, int sigtype) -{ - int alreadyrunning; - unsigned long flags; - struct tor2_chan *p = chan->pvt; - - alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING; - if (debug) { - if (alreadyrunning) - printk("Tor2: Reconfigured channel %d (%s) sigtype %d\n", chan->channo, chan->name, sigtype); - else - printk("Tor2: Configured channel %d (%s) sigtype %d\n", chan->channo, chan->name, sigtype); - } - /* nothing more to do if an E1 */ - if (p->tor->cardtype == TYPE_E1) return 0; - spin_lock_irqsave(&p->tor->lock, flags); - if (alreadyrunning) - set_clear(p->tor); - spin_unlock_irqrestore(&p->tor->lock, flags); - return 0; -} - -static int tor2_open(struct zt_chan *chan) -{ -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#endif - return 0; -} - -static int tor2_close(struct zt_chan *chan) -{ -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#endif - return 0; -} - -static void init_spans(struct tor2 *tor) -{ - int x, y, c; - for (x = 0; x < SPANS_PER_CARD; x++) { - sprintf(tor->spans[x].name, "Tor2/%d/%d", tor->num, x + 1); - snprintf(tor->spans[x].desc, sizeof(tor->spans[x].desc) - 1, - "Tormenta 2 (PCI) fQuad %s Card %d Span %d", - (tor->cardtype == TYPE_T1) ? "T1" : "E1", tor->num, x + 1); - tor->spans[x].manufacturer = "Digium"; - strncpy(tor->spans[x].devicetype, tor->type, sizeof(tor->spans[x].devicetype) - 1); - snprintf(tor->spans[x].location, sizeof(tor->spans[x].location) - 1, - "PCI Bus %02d Slot %02d", tor->pci->bus->number, PCI_SLOT(tor->pci->devfn) + 1); - tor->spans[x].spanconfig = tor2_spanconfig; - tor->spans[x].chanconfig = tor2_chanconfig; - tor->spans[x].startup = tor2_startup; - tor->spans[x].shutdown = tor2_shutdown; - tor->spans[x].rbsbits = tor2_rbsbits; - tor->spans[x].maint = tor2_maint; - tor->spans[x].open = tor2_open; - tor->spans[x].close = tor2_close; - if (tor->cardtype == TYPE_T1) { - tor->spans[x].channels = 24; - tor->spans[x].deflaw = ZT_LAW_MULAW; - tor->spans[x].linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; - tor->spans[x].spantype = "T1"; - } else { - tor->spans[x].channels = 31; - tor->spans[x].deflaw = ZT_LAW_ALAW; - tor->spans[x].linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4; - tor->spans[x].spantype = "E1"; - } - tor->spans[x].chans = tor->chans[x]; - tor->spans[x].flags = ZT_FLAG_RBS; - tor->spans[x].ioctl = tor2_ioctl; - tor->spans[x].pvt = &tor->tspans[x]; - tor->tspans[x].tor = tor; - tor->tspans[x].span = x; - init_waitqueue_head(&tor->spans[x].maintq); - for (y=0;yspans[x].channels;y++) { - struct zt_chan *mychans = tor->chans[x] + y; - sprintf(mychans->name, "Tor2/%d/%d/%d", tor->num, x + 1, y + 1); - mychans->sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS | - ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF | ZT_SIG_EM_E1; - c = (x * tor->spans[x].channels) + y; - mychans->pvt = &tor->tchans[c]; - mychans->chanpos = y + 1; - tor->tchans[c].span = x; - tor->tchans[c].tor = tor; - } - } -} - -static int __devinit tor2_launch(struct tor2 *tor) -{ - if (tor->spans[0].flags & ZT_FLAG_REGISTERED) - return 0; - printk("Tor2: Launching card: %d\n", tor->order); - if (zt_register(&tor->spans[0], 0)) { - printk(KERN_ERR "Unable to register span %s\n", tor->spans[0].name); - return -1; - } - if (zt_register(&tor->spans[1], 0)) { - printk(KERN_ERR "Unable to register span %s\n", tor->spans[1].name); - zt_unregister(&tor->spans[0]); - return -1; - } - if (zt_register(&tor->spans[2], 0)) { - printk(KERN_ERR "Unable to register span %s\n", tor->spans[2].name); - zt_unregister(&tor->spans[0]); - zt_unregister(&tor->spans[1]); - return -1; - } - if (zt_register(&tor->spans[3], 0)) { - printk(KERN_ERR "Unable to register span %s\n", tor->spans[3].name); - zt_unregister(&tor->spans[0]); - zt_unregister(&tor->spans[1]); - zt_unregister(&tor->spans[2]); - return -1; - } - tor->plx[INTCSR] = cpu_to_le16(PLX_INTENA); /* enable PLX interrupt */ -#ifdef ENABLE_TASKLETS - tasklet_init(&tor->tor2_tlet, tor2_tasklet, (unsigned long)tor); -#endif - return 0; -} - -static int __devinit tor2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int res,x,f; - struct tor2 *tor; - unsigned long endjif; - volatile unsigned long *gpdata_io,*lasdata_io; - unsigned long gpdata,lasdata; - - res = pci_enable_device(pdev); - if (res) - return res; - tor = kmalloc(sizeof(struct tor2), GFP_KERNEL); - if (!tor) - return -ENOMEM; - memset(tor,0,sizeof(struct tor2)); - spin_lock_init(&tor->lock); - for (x = 0; x < SPANS_PER_CARD; x++) { - tor->chans[x] = kmalloc(sizeof(struct zt_chan) * 31,GFP_KERNEL); - if (!tor->chans[x]) - return -ENOMEM; - memset(tor->chans[x],0,sizeof(struct zt_chan) * 31); - } - /* Load the resources */ - tor->irq = pdev->irq; - if (tor->irq < 1) { - printk(KERN_ERR "No IRQ allocated for device\n"); - goto err_out_free_tor; - } - tor->plx_region = pci_resource_start(pdev, 0); - tor->plx_len = pci_resource_len(pdev, 0); - tor->plx = ioremap(tor->plx_region, tor->plx_len); - /* We don't use the I/O space, so we dont do anything with section 1 */ - tor->xilinx32_region = pci_resource_start(pdev, 2); - tor->xilinx32_len = pci_resource_len(pdev, 2); - tor->mem32 = ioremap(tor->xilinx32_region, tor->xilinx32_len); - tor->xilinx8_region = pci_resource_start(pdev, 3); - tor->xilinx8_len = pci_resource_len(pdev, 3); - tor->mem8 = ioremap(tor->xilinx8_region, tor->xilinx8_len); - /* Record what type */ - tor->type = (char *)ent->driver_data; - /* Verify existence and accuracy of resources */ - if (!tor->plx_region || !tor->plx || - (pci_resource_flags(pdev, 0) & IORESOURCE_IO)) { - printk(KERN_ERR "Invalid PLX 9030 Base resource\n"); - goto err_out_free_tor; - } - if (!tor->xilinx32_region || !tor->mem32 || - (pci_resource_flags(pdev, 2) & IORESOURCE_IO)) { - printk(KERN_ERR "Invalid Xilinx 32 bit Base resource\n"); - goto err_out_free_tor; - } - if (!tor->xilinx8_region || !tor->mem8 || - (pci_resource_flags(pdev, 3) & IORESOURCE_IO)) { - printk(KERN_ERR "Invalid Xilinx 8 bit Base resource\n"); - goto err_out_free_tor; - } - /* Request regions */ - if (!request_mem_region(tor->plx_region, tor->plx_len, tor->type)) { - printk(KERN_ERR "Unable to reserve PLX memory %08lx window at %08lx\n", - tor->plx_len, tor->plx_region); - goto err_out_free_tor; - } - if (!request_mem_region(tor->xilinx32_region, tor->xilinx32_len, tor->type)) { - printk(KERN_ERR "Unable to reserve Xilinx 32 bit memory %08lx window at %08lx\n", - tor->xilinx32_len, tor->xilinx32_region); - goto err_out_release_plx_region; - } - if (!request_mem_region(tor->xilinx8_region, tor->xilinx8_len, tor->type)) { - printk(KERN_ERR "Unable to reserve Xilinx memory %08lx window at %08lx\n", - tor->xilinx8_len, tor->xilinx8_region); - goto err_out_release_plx_region; - } - pci_set_drvdata(pdev, tor); - printk("Detected %s at 0x%lx/0x%lx irq %d\n", tor->type, - tor->xilinx32_region, tor->xilinx8_region,tor->irq); - - for (x = 0; x < MAX_TOR_CARDS; x++) { - if (!cards[x]) break; - } - if (x >= MAX_TOR_CARDS) { - printk("No cards[] slot available!!\n"); - goto err_out_release_all; - } - tor->num = x; - cards[x] = tor; - - /* start programming mode */ - gpdata_io = (unsigned long *)&tor->plx[GPIOC]; - gpdata = le32_to_cpu(*gpdata_io); - - gpdata |= GPIO_WRITE; /* make sure WRITE is not asserted */ - *gpdata_io = cpu_to_le32(gpdata); - - gpdata &= ~GPIO_PROGRAM; /* activate the PROGRAM signal */ - *gpdata_io = cpu_to_le32(gpdata); - - /* wait for INIT and DONE to go low */ - endjif = jiffies + 10; - while (le32_to_cpu(*gpdata_io) & (GPIO_INIT | GPIO_DONE) && (jiffies <= endjif)); - - if (endjif < jiffies) { - printk("Timeout waiting for INIT and DONE to go low\n"); - goto err_out_release_all; - } - if (debug) printk("fwload: Init and done gone to low\n"); - gpdata |= GPIO_PROGRAM; - *gpdata_io = cpu_to_le32(gpdata); /* de-activate the PROGRAM signal */ - /* wait for INIT to go high (clearing done */ - endjif = jiffies + 10; - while (!(le32_to_cpu(*gpdata_io) & GPIO_INIT) && (jiffies <= endjif)); - if (endjif < jiffies) { - printk("Timeout waiting for INIT to go high\n"); - goto err_out_release_all; - } - - if (debug) printk("fwload: Init went high (clearing done)\nNow loading...\n"); - /* assert WRITE signal */ - gpdata &= ~GPIO_WRITE; - *gpdata_io = cpu_to_le32(gpdata); - for (x = 0; x < sizeof(tor2fw); x++) - { - /* write the byte */ - *tor->mem8 = tor2fw[x]; - /* if DONE signal, we're done, exit */ - if (le32_to_cpu(*gpdata_io) & GPIO_DONE) break; - /* if INIT drops, we're screwed, exit */ - if (!(le32_to_cpu(*gpdata_io) & GPIO_INIT)) break; - } - if (debug) printk("fwload: Transferred %d bytes into chip\n",x); - /* Wait for FIFO to clear */ - endjif = jiffies + 2; - while (jiffies < endjif); /* wait */ - /* de-assert write signal */ - gpdata |= GPIO_WRITE; - *gpdata_io = cpu_to_le32(gpdata); - if (debug) printk("fwload: Loading done!\n"); - - /* Wait for FIFO to clear */ - endjif = jiffies + 2; - while (jiffies < endjif); /* wait */ - if (!(le32_to_cpu(*gpdata_io) & GPIO_INIT)) - { - printk("Drove Init low!! CRC Error!!!\n"); - goto err_out_release_all; - } - if (!(le32_to_cpu(*gpdata_io) & GPIO_DONE)) - { - printk("Did not get DONE signal. Short file maybe??\n"); - goto err_out_release_all; - } - printk("Xilinx Chip successfully loaded, configured and started!!\n"); - - tor->mem8[SYNCREG] = 0; - tor->mem8[CTLREG] = 0; - tor->mem8[CTLREG1] = 0; - tor->mem8[LEDREG] = 0; - - /* set the LA2BRD register so that we enable block transfer, read - pre-fetch, and set to maximum read pre-fetch size */ - lasdata_io = (unsigned long *)&tor->plx[LAS2BRD]; - lasdata = *lasdata_io; - lasdata |= 0x39; - *lasdata_io = lasdata; - - /* set the LA3BRD register so that we enable block transfer */ - lasdata_io = (unsigned long *)&tor->plx[LAS3BRD]; - lasdata = *lasdata_io; - lasdata |= 1; - *lasdata_io = lasdata; - - /* check part revision data */ - x = t1in(tor,1,0xf) & 15; -#ifdef NONREVA - if (x > 3) - { - tor->mem8[CTLREG1] = NONREVA; - } -#endif - for (x = 0; x < 256; x++) tor->mem32[x] = 0x7f7f7f7f; - - - if (request_irq(tor->irq, tor2_intr, ZAP_IRQ_SHARED_DISABLED, "tor2", tor)) { - printk(KERN_ERR "Unable to request tormenta IRQ %d\n", tor->irq); - goto err_out_release_all; - } - - if (t1in(tor,1,0xf) & 0x80) { - printk("Tormenta 2 Quad E1/PRA Card\n"); - tor->cardtype = TYPE_E1; - tor->datxlt = datxlt_e1; - } else { - printk("Tormenta 2 Quad T1/PRI Card\n"); - tor->cardtype = TYPE_T1; - tor->datxlt = datxlt_t1; - } - init_spans(tor); - - tor->order = tor->mem8[SWREG]; - printk("Detected Card number: %d\n", tor->order); - - /* Launch cards as appropriate */ - x = 0; - for (;;) { - /* Find a card to activate */ - f = 0; - for (x=0;cards[x];x++) { - if (cards[x]->order <= highestorder) { - tor2_launch(cards[x]); - if (cards[x]->order == highestorder) - f = 1; - } - } - /* If we found at least one, increment the highest order and search again, otherwise stop */ - if (f) - highestorder++; - else - break; - } - - return 0; - -err_out_release_all: - release_mem_region(tor->xilinx32_region, tor->xilinx32_len); - release_mem_region(tor->xilinx8_region, tor->xilinx8_len); -err_out_release_plx_region: - release_mem_region(tor->plx_region, tor->plx_len); -err_out_free_tor: - if (tor->plx) iounmap((void *)tor->plx); - if (tor->mem8) iounmap((void *)tor->mem8); - if (tor->mem32) iounmap((void *)tor->mem32); - if (tor) { - for (x = 0; x < 3; x++) kfree(tor->chans[x]); - kfree(tor); - } - return -ENODEV; -} - -static struct pci_driver tor2_driver; - -static void __devexit tor2_remove(struct pci_dev *pdev) -{ - int x; - struct tor2 *tor; - tor = pci_get_drvdata(pdev); - if (!tor) - BUG(); - tor->mem8[SYNCREG] = 0; - tor->mem8[CTLREG] = 0; - tor->mem8[LEDREG] = 0; - tor->plx[INTCSR] = cpu_to_le16(0); - free_irq(tor->irq, tor); - if (tor->spans[0].flags & ZT_FLAG_REGISTERED) - zt_unregister(&tor->spans[0]); - if (tor->spans[1].flags & ZT_FLAG_REGISTERED) - zt_unregister(&tor->spans[1]); - if (tor->spans[2].flags & ZT_FLAG_REGISTERED) - zt_unregister(&tor->spans[2]); - if (tor->spans[3].flags & ZT_FLAG_REGISTERED) - zt_unregister(&tor->spans[3]); - release_mem_region(tor->plx_region, tor->plx_len); - release_mem_region(tor->xilinx32_region, tor->xilinx32_len); - release_mem_region(tor->xilinx8_region, tor->xilinx8_len); - if (tor->plx) iounmap((void *)tor->plx); - if (tor->mem8) iounmap((void *)tor->mem8); - if (tor->mem32) iounmap((void *)tor->mem32); - - cards[tor->num] = 0; - pci_set_drvdata(pdev, NULL); - for (x = 0; x < 3; x++) - if (tor->chans[x]) - kfree(tor->chans[x]); - kfree(tor); -} - -static struct pci_driver tor2_driver = { - name: "tormenta2", - probe: tor2_probe, -#ifdef LINUX26 - remove: __devexit_p(tor2_remove), -#else - remove: tor2_remove, -#endif - id_table: tor2_pci_ids, -}; - -static int __init tor2_init(void) { - int res; - res = zap_pci_module(&tor2_driver); - printk("Registered Tormenta2 PCI\n"); - return res; -} - -static void __exit tor2_cleanup(void) { - pci_unregister_driver(&tor2_driver); - printk("Unregistered Tormenta2\n"); -} - -static void set_clear(struct tor2 *tor) -{ - int i,j,s; - unsigned short val=0; - for (s = 0; s < SPANS_PER_CARD; s++) { - for (i = 0; i < 24; i++) { - j = (i/8); - if (tor->spans[s].chans[i].flags & ZT_FLAG_CLEAR) - val |= 1 << (i % 8); - - if ((i % 8)==7) { -#if 0 - printk("Putting %d in register %02x on span %d\n", - val, 0x39 + j, 1 + s); -#endif - t1out(tor,1 + s, 0x39 + j, val); - val = 0; - } - } - } - -} - - -static int tor2_rbsbits(struct zt_chan *chan, int bits) -{ - u_char m,c; - int k,n,b; - struct tor2_chan *p = chan->pvt; - unsigned long flags; -#if 0 - printk("Setting bits to %d on channel %s\n", bits, chan->name); -#endif - if (p->tor->cardtype == TYPE_E1) { /* do it E1 way */ - if (chan->chanpos == 16) return 0; - n = chan->chanpos - 1; - if (chan->chanpos > 16) n--; - k = p->span; - b = (n % 15) + 1; - c = p->tor->txsigs[k][b]; - m = (n / 15) * 4; /* nibble selector */ - c &= (15 << m); /* keep the other nibble */ - c |= (bits & 15) << (4 - m); /* put our new nibble here */ - p->tor->txsigs[k][b] = c; - /* output them to the chip */ - t1out(p->tor,k + 1,0x40 + b,c); - return 0; - } - n = chan->chanpos - 1; - k = p->span; - b = (n / 8); /* get byte number */ - m = 1 << (n & 7); /* get mask */ - c = p->tor->txsigs[k][b]; - c &= ~m; /* clear mask bit */ - /* set mask bit, if bit is to be set */ - if (bits & ZT_ABIT) c |= m; - p->tor->txsigs[k][b] = c; - spin_lock_irqsave(&p->tor->lock, flags); - t1out(p->tor,k + 1,0x70 + b,c); - b += 3; /* now points to b bit stuff */ - /* get current signalling values */ - c = p->tor->txsigs[k][b]; - c &= ~m; /* clear mask bit */ - /* set mask bit, if bit is to be set */ - if (bits & ZT_BBIT) c |= m; - /* save new signalling values */ - p->tor->txsigs[k][b] = c; - /* output them into the chip */ - t1out(p->tor,k + 1,0x70 + b,c); - b += 3; /* now points to c bit stuff */ - /* get current signalling values */ - c = p->tor->txsigs[k][b]; - c &= ~m; /* clear mask bit */ - /* set mask bit, if bit is to be set */ - if (bits & ZT_CBIT) c |= m; - /* save new signalling values */ - p->tor->txsigs[k][b] = c; - /* output them into the chip */ - t1out(p->tor,k + 1,0x70 + b,c); - b += 3; /* now points to d bit stuff */ - /* get current signalling values */ - c = p->tor->txsigs[k][b]; - c &= ~m; /* clear mask bit */ - /* set mask bit, if bit is to be set */ - if (bits & ZT_DBIT) c |= m; - /* save new signalling values */ - p->tor->txsigs[k][b] = c; - /* output them into the chip */ - t1out(p->tor,k + 1,0x70 + b,c); - spin_unlock_irqrestore(&p->tor->lock, flags); - return 0; -} - -static int tor2_shutdown(struct zt_span *span) -{ - int i; - int tspan; - int wasrunning; - unsigned long flags; - struct tor2_span *p = span->pvt; - - tspan = p->span + 1; - if (tspan < 0) { - printk("Tor2: Span '%d' isn't us?\n", span->spanno); - return -1; - } - - spin_lock_irqsave(&p->tor->lock, flags); - wasrunning = span->flags & ZT_FLAG_RUNNING; - - span->flags &= ~ZT_FLAG_RUNNING; - /* Zero out all registers */ - if (p->tor->cardtype == TYPE_E1) { - for (i = 0; i < 192; i++) - t1out(p->tor,tspan, i, 0); - } else { - for (i = 0; i < 160; i++) - t1out(p->tor,tspan, i, 0); - } - if (wasrunning) - p->tor->spansstarted--; - spin_unlock_irqrestore(&p->tor->lock, flags); - if (!(p->tor->spans[0].flags & ZT_FLAG_RUNNING) && - !(p->tor->spans[1].flags & ZT_FLAG_RUNNING) && - !(p->tor->spans[2].flags & ZT_FLAG_RUNNING) && - !(p->tor->spans[3].flags & ZT_FLAG_RUNNING)) - /* No longer in use, disable interrupts */ - p->tor->mem8[CTLREG] = 0; - if (debug) - printk("Span %d (%s) shutdown\n", span->spanno, span->name); - return 0; -} - - -static int tor2_startup(struct zt_span *span) -{ - unsigned long endjif; - int i; - int tspan; - unsigned long flags; - char *coding; - char *framing; - char *crcing; - int alreadyrunning; - struct tor2_span *p = span->pvt; - - tspan = p->span + 1; - if (tspan < 0) { - printk("Tor2: Span '%d' isn't us?\n", span->spanno); - return -1; - } - - spin_lock_irqsave(&p->tor->lock, flags); - - alreadyrunning = span->flags & ZT_FLAG_RUNNING; - - /* initialize the start value for the entire chunk of last ec buffer */ - for (i = 0; i < span->channels; i++) - { - memset(p->tor->ec_chunk1[p->span][i], - ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); - memset(p->tor->ec_chunk2[p->span][i], - ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); - } - /* Force re-evaluation of the timing source */ - if (timingcable) - p->tor->syncsrc = -1; - - if (p->tor->cardtype == TYPE_E1) { /* if this is an E1 card */ - unsigned char tcr1,ccr1,tcr2; - if (!alreadyrunning) { - p->tor->mem8[SYNCREG] = SYNCSELF; - p->tor->mem8[CTLREG] = E1DIV; - p->tor->mem8[LEDREG] = 0; - /* Force re-evaluation of sync src */ - /* Zero out all registers */ - for (i = 0; i < 192; i++) - t1out(p->tor,tspan, i, 0); - - /* Set up for Interleaved Serial Bus operation in byte mode */ - /* Set up all the spans every time, so we are sure they are - in a consistent state. If we don't, a card without all - its spans configured misbehaves in strange ways. */ - t1out(p->tor,1,0xb5,9); - t1out(p->tor,2,0xb5,8); - t1out(p->tor,3,0xb5,8); - t1out(p->tor,4,0xb5,8); - - t1out(p->tor,tspan,0x1a,4); /* CCR2: set LOTCMC */ - for (i = 0; i <= 8; i++) t1out(p->tor,tspan,i,0); - for (i = 0x10; i <= 0x4f; i++) if (i != 0x1a) t1out(p->tor,tspan,i,0); - t1out(p->tor,tspan,0x10,0x20); /* RCR1: Rsync as input */ - t1out(p->tor,tspan,0x11,6); /* RCR2: Sysclk=2.048 Mhz */ - t1out(p->tor,tspan,0x12,9); /* TCR1: TSiS mode */ - } - ccr1 = 0; - crcing = ""; - tcr1 = 9; /* base TCR1 value: TSis mode */ - tcr2 = 0; - if (span->lineconfig & ZT_CONFIG_CCS) { - ccr1 |= 8; /* CCR1: Rx Sig mode: CCS */ - coding = "CCS"; - } else { - tcr1 |= 0x20; - coding = "CAS"; - } - if (span->lineconfig & ZT_CONFIG_HDB3) { - ccr1 |= 0x44; /* CCR1: TX and RX HDB3 */ - framing = "HDB3"; - } else framing = "AMI"; - if (span->lineconfig & ZT_CONFIG_CRC4) { - ccr1 |= 0x11; /* CCR1: TX and TX CRC4 */ - tcr2 |= 0x02; /* TCR2: CRC4 bit auto */ - crcing = "/CRC4"; - } - t1out(p->tor,tspan,0x12,tcr1); - t1out(p->tor,tspan,0x13,tcr2); - t1out(p->tor,tspan,0x14,ccr1); - t1out(p->tor,tspan, 0x18, 0x20); /* 120 Ohm, normal */ - - if (!alreadyrunning) { - t1out(p->tor,tspan,0x1b,0x8a); /* CCR3: LIRST & TSCLKM */ - t1out(p->tor,tspan,0x20,0x1b); /* TAFR */ - t1out(p->tor,tspan,0x21,0x5f); /* TNAFR */ - t1out(p->tor,tspan,0x40,0xb); /* TSR1 */ - for (i = 0x41; i <= 0x4f; i++) t1out(p->tor,tspan,i,0x55); - for (i = 0x22; i <= 0x25; i++) t1out(p->tor,tspan,i,0xff); - /* Wait 100 ms */ - endjif = jiffies + 10; - spin_unlock_irqrestore(&p->tor->lock, flags); - while (jiffies < endjif); /* wait 100 ms */ - spin_lock_irqsave(&p->tor->lock, flags); - t1out(p->tor,tspan,0x1b,0x9a); /* CCR3: set also ESR */ - t1out(p->tor,tspan,0x1b,0x82); /* CCR3: TSCLKM only now */ - - span->flags |= ZT_FLAG_RUNNING; - p->tor->spansstarted++; - - /* enable interrupts */ - p->tor->mem8[CTLREG] = INTENA | E1DIV; - } - - spin_unlock_irqrestore(&p->tor->lock, flags); - - if (debug) { - if (alreadyrunning) - printk("Tor2: Reconfigured span %d (%s/%s%s) 120 Ohms\n", span->spanno, coding, framing, crcing); - else - printk("Tor2: Startup span %d (%s/%s%s) 120 Ohms\n", span->spanno, coding, framing, crcing); - } - } else { /* is a T1 card */ - - if (!alreadyrunning) { - p->tor->mem8[SYNCREG] = SYNCSELF; - p->tor->mem8[CTLREG] = 0; - p->tor->mem8[LEDREG] = 0; - /* Zero out all registers */ - for (i = 0; i < 160; i++) - t1out(p->tor,tspan, i, 0); - - /* Set up for Interleaved Serial Bus operation in byte mode */ - /* Set up all the spans every time, so we are sure they are - in a consistent state. If we don't, a card without all - its spans configured misbehaves in strange ways. */ - t1out(p->tor,1,0x94,9); - t1out(p->tor,2,0x94,8); - t1out(p->tor,3,0x94,8); - t1out(p->tor,4,0x94,8); - /* Full-on Sync required (RCR1) */ - t1out(p->tor,tspan, 0x2b, 8); - /* RSYNC is an input (RCR2) */ - t1out(p->tor,tspan, 0x2c, 8); - /* RBS enable (TCR1) */ - t1out(p->tor,tspan, 0x35, 0x10); - /* TSYNC to be output (TCR2) */ - t1out(p->tor,tspan, 0x36, 4); - /* Tx & Rx Elastic store, sysclk(s) = 2.048 mhz, loopback controls (CCR1) */ - t1out(p->tor,tspan, 0x37, 0x9c); - /* Set up received loopup and loopdown codes */ - t1out(p->tor,tspan, 0x12, 0x22); - t1out(p->tor,tspan, 0x14, 0x80); - t1out(p->tor,tspan, 0x15, 0x80); - /* Setup japanese mode if appropriate */ - t1out(p->tor,tspan,0x19,(japan ? 0x80 : 0x00)); /* no local loop */ - t1out(p->tor,tspan,0x1e,(japan ? 0x80 : 0x00)); /* no local loop */ - } - /* Enable F bits pattern */ - i = 0x20; - if (span->lineconfig & ZT_CONFIG_ESF) - i = 0x88; - if (span->lineconfig & ZT_CONFIG_B8ZS) - i |= 0x44; - t1out(p->tor,tspan, 0x38, i); - if (i & 0x80) - coding = "ESF"; - else - coding = "SF"; - if (i & 0x40) - framing = "B8ZS"; - else { - framing = "AMI"; - t1out(p->tor,tspan,0x7e,0x1c); /* F bits pattern (0x1c) into FDL register */ - } - t1out(p->tor,tspan, 0x7c, span->txlevel << 5); - - if (!alreadyrunning) { - /* LIRST to reset line interface */ - t1out(p->tor,tspan, 0x0a, 0x80); - - /* Wait 100 ms */ - endjif = jiffies + 10; - - spin_unlock_irqrestore(&p->tor->lock, flags); - - while (jiffies < endjif); /* wait 100 ms */ - - spin_lock_irqsave(&p->tor->lock, flags); - - t1out(p->tor,tspan,0x0a,0x30); /* LIRST back to normal, Resetting elastic stores */ - - span->flags |= ZT_FLAG_RUNNING; - p->tor->spansstarted++; - - /* enable interrupts */ - p->tor->mem8[CTLREG] = INTENA; - } - - set_clear(p->tor); - - spin_unlock_irqrestore(&p->tor->lock, flags); - - if (debug) { - if (alreadyrunning) - printk("Tor2: Reconfigured span %d (%s/%s) LBO: %s\n", span->spanno, coding, framing, zt_lboname(span->txlevel)); - else - printk("Tor2: Startup span %d (%s/%s) LBO: %s\n", span->spanno, coding, framing, zt_lboname(span->txlevel)); - } - } - if (p->tor->syncs[0] == span->spanno) printk("SPAN %d: Primary Sync Source\n",span->spanno); - if (p->tor->syncs[1] == span->spanno) printk("SPAN %d: Secondary Sync Source\n",span->spanno); - if (p->tor->syncs[2] == span->spanno) printk("SPAN %d: Tertiary Sync Source\n",span->spanno); - if (p->tor->syncs[3] == span->spanno) printk("SPAN %d: Quaternary Sync Source\n",span->spanno); - return 0; -} - -static int tor2_maint(struct zt_span *span, int cmd) -{ - struct tor2_span *p = span->pvt; - - int tspan = p->span + 1; - - if (p->tor->cardtype == TYPE_E1) - { - switch(cmd) { - case ZT_MAINT_NONE: - t1out(p->tor,tspan,0xa8,0); /* no loops */ - break; - case ZT_MAINT_LOCALLOOP: - t1out(p->tor,tspan,0xa8,0x40); /* local loop */ - break; - case ZT_MAINT_REMOTELOOP: - t1out(p->tor,tspan,0xa8,0x80); /* remote loop */ - break; - case ZT_MAINT_LOOPUP: - case ZT_MAINT_LOOPDOWN: - case ZT_MAINT_LOOPSTOP: - return -ENOSYS; - default: - printk("Tor2: Unknown maint command: %d\n", cmd); - break; - } - return 0; - } - switch(cmd) { - case ZT_MAINT_NONE: - t1out(p->tor,tspan,0x19,(japan ? 0x80 : 0x00)); /* no local loop */ - t1out(p->tor,tspan,0x0a,0); /* no remote loop */ - break; - case ZT_MAINT_LOCALLOOP: - t1out(p->tor,tspan,0x19,0x40 | (japan ? 0x80 : 0x00)); /* local loop */ - t1out(p->tor,tspan,0x0a,0); /* no remote loop */ - break; - case ZT_MAINT_REMOTELOOP: - t1out(p->tor,tspan,0x1e,(japan ? 0x80 : 0x00)); /* no local loop */ - t1out(p->tor,tspan,0x0a,0x40); /* remote loop */ - break; - case ZT_MAINT_LOOPUP: - t1out(p->tor,tspan,0x30,2); /* send loopup code */ - t1out(p->tor,tspan,0x12,0x22); /* send loopup code */ - t1out(p->tor,tspan,0x13,0x80); /* send loopup code */ - break; - case ZT_MAINT_LOOPDOWN: - t1out(p->tor,tspan,0x30,2); /* send loopdown code */ - t1out(p->tor,tspan,0x12,0x62); /* send loopdown code */ - t1out(p->tor,tspan,0x13,0x90); /* send loopdown code */ - break; - case ZT_MAINT_LOOPSTOP: - t1out(p->tor,tspan,0x30,0); /* stop sending loopup code */ - break; - default: - printk("Tor2: Unknown maint command: %d\n", cmd); - break; - } - return 0; -} - -static inline void tor2_run(struct tor2 *tor) -{ - int x,y; - for (x = 0; x < SPANS_PER_CARD; x++) { - if (tor->spans[x].flags & ZT_FLAG_RUNNING) { - /* since the Tormenta 2 PCI is double-buffered, you - need to delay the transmit data 2 entire chunks so - that the transmit will be in sync with the receive */ - for (y=0;yspans[x].channels;y++) { - zt_ec_chunk(&tor->spans[x].chans[y], - tor->spans[x].chans[y].readchunk, - tor->ec_chunk2[x][y]); - memcpy(tor->ec_chunk2[x][y],tor->ec_chunk1[x][y], - ZT_CHUNKSIZE); - memcpy(tor->ec_chunk1[x][y], - tor->spans[x].chans[y].writechunk, - ZT_CHUNKSIZE); - } - zt_receive(&tor->spans[x]); - } - } - for (x = 0; x < SPANS_PER_CARD; x++) { - if (tor->spans[x].flags & ZT_FLAG_RUNNING) - zt_transmit(&tor->spans[x]); - } -} - -#ifdef ENABLE_TASKLETS -static void tor2_tasklet(unsigned long data) -{ - struct tor2 *tor = (struct tor2 *)data; - tor->taskletrun++; - if (tor->taskletpending) { - tor->taskletexec++; - tor2_run(tor); - } - tor->taskletpending = 0; -} -#endif - -static int syncsrc = 0; -static int syncnum = 0 /* -1 */; -static int syncspan = 0; -#ifdef DEFINE_SPINLOCK -static DEFINE_SPINLOCK(synclock); -#else -static spinlock_t synclock = SPIN_LOCK_UNLOCKED; -#endif - -static int tor2_findsync(struct tor2 *tor) -{ - int i; - int x; - unsigned long flags; - int p; - int nonzero; - int newsyncsrc = 0; /* Zaptel span number */ - int newsyncnum = 0; /* tor2 card number */ - int newsyncspan = 0; /* span on given tor2 card */ - spin_lock_irqsave(&synclock, flags); -#if 1 - if (!tor->num) { - /* If we're the first card, go through all the motions, up to 8 levels - of sync source */ - p = 1; - while (p < 8) { - nonzero = 0; - for (x=0;cards[x];x++) { - for (i = 0; i < SPANS_PER_CARD; i++) { - if (cards[x]->syncpos[i]) { - nonzero = 1; - if ((cards[x]->syncpos[i] == p) && - !(cards[x]->spans[i].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK)) && - (cards[x]->spans[i].flags & ZT_FLAG_RUNNING)) { - /* This makes a good sync source */ - newsyncsrc = cards[x]->spans[i].spanno; - newsyncnum = x; - newsyncspan = i + 1; - /* Jump out */ - goto found; - } - } - } - } - if (nonzero) - p++; - else - break; - } -found: - if ((syncnum != newsyncnum) || (syncsrc != newsyncsrc) || (newsyncspan != syncspan)) { - syncnum = newsyncnum; - syncsrc = newsyncsrc; - syncspan = newsyncspan; - if (debug) printk("New syncnum: %d, syncsrc: %d, syncspan: %d\n", syncnum, syncsrc, syncspan); - } - } -#endif - /* update sync src info */ - if (tor->syncsrc != syncsrc) { - tor->syncsrc = syncsrc; - /* Update sync sources */ - for (i = 0; i < SPANS_PER_CARD; i++) { - tor->spans[i].syncsrc = tor->syncsrc; - } - if (syncnum == tor->num) { -#if 1 - /* actually set the sync register */ - tor->mem8[SYNCREG] = syncspan; -#endif - if (debug) printk("Card %d, using sync span %d, master\n", tor->num, syncspan); - tor->master = MASTER; - } else { -#if 1 - /* time from the timing cable */ - tor->mem8[SYNCREG] = SYNCEXTERN; -#endif - tor->master = 0; - if (debug) printk("Card %d, using Timing Bus, NOT master\n", tor->num); - } - } - spin_unlock_irqrestore(&synclock, flags); - return 0; -} - -ZAP_IRQ_HANDLER(tor2_intr) -{ - int n, i, j, k, syncsrc; - unsigned int rxword,txword; - - unsigned char c, rxc; - unsigned char abits, bbits; - struct tor2 *tor = (struct tor2 *) dev_id; - - /* make sure its a real interrupt for us */ - if (!(tor->mem8[STATREG] & INTACTIVE)) /* if not, just return */ - { -#ifdef LINUX26 - return IRQ_NONE; -#else - return; -#endif - } - - if (tor->cardtype == TYPE_E1) - /* set outbit, interrupt enable, and ack interrupt */ - tor->mem8[CTLREG] = OUTBIT | INTENA | INTACK | E1DIV | tor->master; - else - /* set outbit, interrupt enable, and ack interrupt */ - tor->mem8[CTLREG] = OUTBIT | INTENA | INTACK | tor->master; - -#if 0 - if (!tor->passno) - printk("Interrupt handler\n"); -#endif - - /* do the transmit output */ - for (n = 0; n < tor->spans[0].channels; n++) { - for (i = 0; i < ZT_CHUNKSIZE; i++) { - /* span 1 */ - txword = tor->spans[0].chans[n].writechunk[i] << 24; - /* span 2 */ - txword |= tor->spans[1].chans[n].writechunk[i] << 16; - /* span 3 */ - txword |= tor->spans[2].chans[n].writechunk[i] << 8; - /* span 4 */ - txword |= tor->spans[3].chans[n].writechunk[i]; - /* write to part */ -#ifdef FIXTHISFOR64 - tor->mem32[tor->datxlt[n] + (32 * i)] = txword; -#else - tor->mem32[tor->datxlt[n] + (32 * i)] = cpu_to_le32(txword); -#endif - } - } - - /* Do the receive input */ - for (n = 0; n < tor->spans[0].channels; n++) { - for (i = 0; i < ZT_CHUNKSIZE; i++) { - /* read from */ -#ifdef FIXTHISFOR64 - rxword = tor->mem32[tor->datxlt[n] + (32 * i)]; -#else - rxword = le32_to_cpu(tor->mem32[tor->datxlt[n] + (32 * i)]); -#endif - /* span 1 */ - tor->spans[0].chans[n].readchunk[i] = rxword >> 24; - /* span 2 */ - tor->spans[1].chans[n].readchunk[i] = (rxword & 0xff0000) >> 16; - /* span 3 */ - tor->spans[2].chans[n].readchunk[i] = (rxword & 0xff00) >> 8; - /* span 4 */ - tor->spans[3].chans[n].readchunk[i] = rxword & 0xff; - } - } - - i = tor->passno & 15; - /* if an E1 card, do rx signalling for it */ - if ((i < 3) && (tor->cardtype == TYPE_E1)) { /* if an E1 card */ - for (j = (i * 5); j < (i * 5) + 5; j++) { - for (k = 1; k <= SPANS_PER_CARD; k++) { - c = t1in(tor,k,0x31 + j); - rxc = c & 15; - if (rxc != tor->spans[k - 1].chans[j + 16].rxsig) { - /* Check for changes in received bits */ - if (!(tor->spans[k - 1].chans[j + 16].sig & ZT_SIG_CLEAR)) - zt_rbsbits(&tor->spans[k - 1].chans[j + 16], rxc); - } - rxc = c >> 4; - if (rxc != tor->spans[k - 1].chans[j].rxsig) { - /* Check for changes in received bits */ - if (!(tor->spans[k - 1].chans[j].sig & ZT_SIG_CLEAR)) - zt_rbsbits(&tor->spans[k - 1].chans[j], rxc); - } - } - } - } - - /* if a T1, do the signalling */ - if ((i < 12) && (tor->cardtype == TYPE_T1)) { - k = (i / 3); /* get span */ - n = (i % 3); /* get base */ - abits = t1in(tor,k + 1, 0x60 + n); - bbits = t1in(tor,k + 1, 0x63 + n); - for (j=0; j< 8; j++) { - /* Get channel number */ - i = (n * 8) + j; - rxc = 0; - if (abits & (1 << j)) rxc |= ZT_ABIT; - if (bbits & (1 << j)) rxc |= ZT_BBIT; - if (tor->spans[k].chans[i].rxsig != rxc) { - /* Check for changes in received bits */ - if (!(tor->spans[k].chans[i].sig & ZT_SIG_CLEAR)) { - zt_rbsbits(&tor->spans[k].chans[i], rxc); - } - } - } - } - - for (i = 0; i < SPANS_PER_CARD; i++) { /* Go thru all the spans */ - /* if alarm timer, and it's timed out */ - if (tor->alarmtimer[i]) { - if (!--tor->alarmtimer[i]) { - /* clear recover status */ - tor->spans[i].alarms &= ~ZT_ALARM_RECOVER; - if (tor->cardtype == TYPE_E1) - t1out(tor,i + 1,0x21,0x5f); /* turn off yel */ - else - t1out(tor,i + 1,0x35,0x10); /* turn off yel */ - zt_alarm_notify(&tor->spans[i]); /* let them know */ - } - } - } - - i = tor->passno & 15; - if ((i >= 10) && (i <= 13) && !(tor->passno & 0x30)) - { - j = 0; /* clear this alarm status */ - i -= 10; - if (tor->cardtype == TYPE_T1) { - c = t1in(tor,i + 1,0x31); /* get RIR2 */ - tor->spans[i].rxlevel = c >> 6; /* get rx level */ - t1out(tor,i + 1,0x20,0xff); - c = t1in(tor,i + 1,0x20); /* get the status */ - /* detect the code, only if we are not sending one */ - if ((!tor->spans[i].mainttimer) && (c & 0x80)) /* if loop-up code detected */ - { - /* set into remote loop, if not there already */ - if ((tor->loopupcnt[i]++ > 80) && - (tor->spans[i].maintstat != ZT_MAINT_REMOTELOOP)) - { - t1out(tor,i + 1,0x1e,(japan ? 0x80 : 0x00)); /* no local loop */ - t1out(tor,i + 1,0x0a,0x40); /* remote loop */ - tor->spans[i].maintstat = ZT_MAINT_REMOTELOOP; - } - } else tor->loopupcnt[i] = 0; - /* detect the code, only if we are not sending one */ - if ((!tor->spans[i].mainttimer) && (c & 0x40)) /* if loop-down code detected */ - { - /* if in remote loop, get out of it */ - if ((tor->loopdowncnt[i]++ > 80) && - (tor->spans[i].maintstat == ZT_MAINT_REMOTELOOP)) - { - t1out(tor,i + 1,0x1e,(japan ? 0x80 : 0x00)); /* no local loop */ - t1out(tor,i + 1,0x0a,0); /* no remote loop */ - tor->spans[i].maintstat = ZT_MAINT_NONE; - } - } else tor->loopdowncnt[i] = 0; - if (c & 3) /* if red alarm */ - { - j |= ZT_ALARM_RED; - } - if (c & 8) /* if blue alarm */ - { - j |= ZT_ALARM_BLUE; - } - } else { /* its an E1 card */ - t1out(tor,i + 1,6,0xff); - c = t1in(tor,i + 1,6); /* get the status */ - if (c & 9) /* if red alarm */ - { - j |= ZT_ALARM_RED; - } - if (c & 2) /* if blue alarm */ - { - j |= ZT_ALARM_BLUE; - } - } - /* only consider previous carrier alarm state */ - tor->spans[i].alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); - n = 1; /* set to 1 so will not be in yellow alarm if we dont - care about open channels */ - /* if to have yellow alarm if nothing open */ - if (tor->spans[i].lineconfig & ZT_CONFIG_NOTOPEN) - { - /* go thru all chans, and count # open */ - for (n = 0,k = 0; k < tor->spans[i].channels; k++) - { - if (((tor->chans[i] + k)->flags & ZT_FLAG_OPEN) || - ((tor->chans[i] + k)->flags & ZT_FLAG_NETDEV)) n++; - } - /* if none open, set alarm condition */ - if (!n) j |= ZT_ALARM_NOTOPEN; - } - /* if no more alarms, and we had some */ - if ((!j) && tor->spans[i].alarms) - { - tor->alarmtimer[i] = ZT_ALARMSETTLE_TIME; - } - if (tor->alarmtimer[i]) j |= ZT_ALARM_RECOVER; - /* if going into alarm state, set yellow alarm */ - if ((j) && (!tor->spans[i].alarms)) { - if (tor->cardtype == TYPE_E1) - t1out(tor,i + 1,0x21,0x7f); - else - t1out(tor,i + 1,0x35,0x11); - } - if (c & 4) /* if yellow alarm */ - j |= ZT_ALARM_YELLOW; - if (tor->spans[i].maintstat || tor->spans[i].mainttimer) j |= ZT_ALARM_LOOPBACK; - tor->spans[i].alarms = j; - c = (LEDRED | LEDGREEN) << (2 * i); - tor->leds &= ~c; /* mask out bits for this span */ - /* light LED's if span configured and running */ - if (tor->spans[i].flags & ZT_FLAG_RUNNING) { - if (j & ZT_ALARM_RED) tor->leds |= LEDRED << (2 * i); - else if (j & ZT_ALARM_YELLOW) tor->leds |= (LEDRED | LEDGREEN) << (2 * i); - else tor->leds |= LEDGREEN << (2 * i); - } - tor->mem8[LEDREG] = tor->leds; - zt_alarm_notify(&tor->spans[i]); - } - if (!(tor->passno % 1000)) /* even second boundary */ - { - /* do all spans */ - for (i = 1; i <= SPANS_PER_CARD; i++) - { - if (tor->cardtype == TYPE_E1) - { - /* add this second's BPV count to total one */ - tor->spans[i - 1].bpvcount += t1in(tor,i,1) + (t1in(tor,i,0) << 8); - if (tor->spans[i - 1].lineconfig & ZT_CONFIG_CRC4) - { - tor->spans[i - 1].crc4count += t1in(tor,i,3) + ((t1in(tor,i,2) & 3) << 8); - tor->spans[i - 1].ebitcount += t1in(tor,i,5) + ((t1in(tor,i,4) & 3) << 8); - } - tor->spans[i - 1].fascount += (t1in(tor,i,4) >> 2) + ((t1in(tor,i,2) & 0x3F) << 6); - } - else - { - /* add this second's BPV count to total one */ - tor->spans[i - 1].bpvcount += t1in(tor,i,0x24) + (t1in(tor,i,0x23) << 8); - } - } - } - if (!timingcable) { - /* re-evaluate active sync src (no cable version) */ - tor->syncsrc = 0; - syncsrc = 0; - /* if primary sync specified, see if we can use it */ - if (tor->psyncs[0]) - { - /* if no alarms, use it */ - if (!(tor->spans[tor->psyncs[0] - 1].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | - ZT_ALARM_LOOPBACK))) { - tor->syncsrc = tor->psyncs[0]; - syncsrc = tor->syncs[0]; - } - } - /* if any others specified, see if we can use them */ - for (i = 1; i < SPANS_PER_CARD; i++) { - /* if we dont have one yet, and there is one specified at this level, see if we can use it */ - if ((!tor->syncsrc) && (tor->psyncs[i])) { - /* if no alarms, use it */ - if (!(tor->spans[tor->psyncs[i] - 1].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | - ZT_ALARM_LOOPBACK))) { - tor->syncsrc = tor->psyncs[i]; - syncsrc = tor->syncs[i]; - } - } - } - /* update sync src info */ - for (i = 0; i < SPANS_PER_CARD; i++) tor->spans[i].syncsrc = syncsrc; - - /* actually set the sync register */ - tor->mem8[SYNCREG] = tor->syncsrc; - } else /* Timing cable version */ - tor2_findsync(tor); - - tor->passno++; - -#ifdef ENABLE_TASKLETS - if (!tor->taskletpending) { - tor->taskletpending = 1; - tor->taskletsched++; - tasklet_hi_schedule(&tor->tor2_tlet); - } else { - tor->txerrors++; - } -#else - tor2_run(tor); -#endif - /* We are not the timing bus master */ - if (tor->cardtype == TYPE_E1) - /* clear OUTBIT and enable interrupts */ - tor->mem8[CTLREG] = INTENA | E1DIV | tor->master; - else - /* clear OUTBIT and enable interrupts */ - tor->mem8[CTLREG] = INTENA | tor->master; -#ifdef LINUX26 - return IRQ_RETVAL(1); -#endif -} - - -static int tor2_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) -{ - switch(cmd) { - default: - return -ENOTTY; - } - return 0; -} - -MODULE_AUTHOR("Mark Spencer"); -MODULE_DESCRIPTION("Tormenta 2 PCI Quad T1 or E1 Zaptel Driver"); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif - -#ifdef LINUX26 -module_param(debug, int, 0600); -module_param(loopback, int, 0600); -module_param(timingcable, int, 0600); -module_param(japan, int, 0600); -#else -MODULE_PARM(debug, "i"); -MODULE_PARM(loopback, "i"); -MODULE_PARM(timingcable, "i"); -MODULE_PARM(japan, "i"); -#endif - -MODULE_DEVICE_TABLE(pci, tor2_pci_ids); - -module_init(tor2_init); -module_exit(tor2_cleanup); diff --git a/torisa.c b/torisa.c deleted file mode 100644 index a8fb9d3..0000000 --- a/torisa.c +++ /dev/null @@ -1,1172 +0,0 @@ -/* - * Zapata Telephony "Tormenta" ISA card LINUX driver, version 2.2 11/29/01 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Modified from original tor.c by Mark Spencer - * original by Jim Dixon - */ - -#include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef STANDALONE_ZAPATA -#include "zaptel.h" -#else -#include -#endif -#ifdef LINUX26 -#include -#endif - -/* Board address offsets (specified in word (not byte) offsets) */ -#define DDATA 0 /* Data I/O Register */ -#define DADDR 0x100 /* Dallas Card Address Reg., 0x200 in byte offset higher */ -#define CTLREG 0x100 /* Control/Status Reg., 0x200 in byte offset */ - -/* Control register bits */ -#define OUTBIT 8 /* Status output bit (for external measurements) */ -#define INTENA 4 /* Interrupt enable bit */ -#define MASTERVAL 0x41 /* Enable E1 master clock on Rev. B board */ -#define ENA16 0x80 /* 16 bit bus cycle enable bit */ - -#define TYPE_T1 1 /* is a T1 card */ -#define TYPE_E1 2 /* is an E1 card */ - -#define E1SYNCSTABLETHRESH 15000 /* amount of samples needed for E1 Sync stability */ - -static int syncsrc; - -static int syncs[2]; - -static int debug; - -#define MASTERCLOCK (*clockvals) /* value for master clock */ - -/* clock values */ -static u_char clockvals_t1[] = {MASTERVAL,0x12,0x22,MASTERVAL}; -static u_char clockvals_e1[] = {MASTERVAL,0x13,0x23,MASTERVAL}; - -static u_char *clockvals; - -/* translations of data channels for 24 channels in a 32 bit PCM highway */ -unsigned datxlt_t1[] = { 0, - 1 ,2 ,3 ,5 ,6 ,7 ,9 ,10,11,13,14,15,17,18,19,21,22,23,25,26,27,29,30,31 }; - -/* translations of data channels for 30/31 channels in a 32 bit PCM highway */ -unsigned datxlt_e1[] = { 0, - 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, - 25,26,27,28,29,30,31 }; - -unsigned int *datxlt; - -/* This is the order that the data (audio) channels get -scanned in. This was done in this rather poopy manner because when outputting -(and inputting) a sine wave, such as in the case of TDD, any repeated samples -(because of PCM bus contention) will result in nasty-sounding distortion. The -Mitel STPA chips (MT8920) have a contention mechanism, which results in a -situation where, if the processor accesses a timeslot that is currently -being transmitted or received, it will HOLD the bus until it is done with -the timeslot. This means that there can be cases where we are trying -to write to a timeslot, and its already outputting the same value -as the last one (since we didnt get there in time), and in a sine-wave -output, distortion will occur. In any other output, it will be utterly -un-noticeable. So, what we do is use a pattern that gives us the most -flexibility in how long our interrupt latency is (note: Even with this, -our interrupt latency must be between 4 and 28 microseconds!!!) Essentially -we receive the interrupt just after the 24th channel is read. It will -take us AT LEAST 30 microseconds to read it, but could take as much as -35 microseconds to read all the channels. In any case it's the very -first thing we do in the interrupt handler. Worst case (30 microseconds) -is that the MT8920 has only moved 7 channels. That's where the 6 comes from. -*/ - -static int chseq_t1[] = - { 6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,1,2,3,4,5 } ; - -static int chseq_e1[] = - { 6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,1,2,3,4,5 } ; - -static int *chseq; - -struct torisa_pvt { - int span; -}; - -static struct zt_span spans[2]; -static struct zt_chan chans[64]; -static struct torisa_pvt pvts[64]; -static u_char txsigs[2][16]; -static int loopupcnt[2]; -static int loopdowncnt[2]; -static int alarmtimer[2]; - -static int channels_per_span = 24; - -static int card_type = TYPE_T1; - -static int prefmaster = 0; - -static int spansstarted = 0; - -#ifdef DEFINE_RWLOCK -static DEFINE_RWLOCK(torisa); -#else -static rwlock_t torisa = RW_LOCK_UNLOCKED; -#endif - -static u_char readdata[2][64][ZT_MAX_CHUNKSIZE]; -static u_char writedata[2][64][ZT_MAX_CHUNKSIZE]; -static u_char last_ecwrite[2][32]; -static int curread; - -static unsigned long base; -volatile static unsigned short *maddr; - -static int irq; -static unsigned int irqcount = 0; -static unsigned int taskletsched = 0; -static unsigned int taskletrun = 0; -static unsigned int taskletexec = 0; - -/* set the control register */ -static void setctlreg(unsigned char val) -{ -volatile register char *cp; - - cp = (char *) &maddr[CTLREG]; - *cp = val; -} - -/* output a byte to one of the registers in one of the Dallas T-1 chips */ -static void t1out(int spanno, int loc, unsigned char val) -{ -register int n; -volatile register char *cp; - - /* get the memory offset */ - n = spanno << 9; - /* point a char * at the address location */ - cp = (char *) &maddr[DADDR + n]; - *cp = loc; /* set address in T1 chip */ - /* point a char * at the data location */ - cp = (char *) &maddr[DDATA + n]; - *cp = val; /* out the value */ -} - -/* get a byte from one of the registers in one of the Dallas T-1 chips */ -static unsigned char t1in(int spanno, int loc) -{ -register int n; -volatile register char *cp; - - /* get the memory offset */ - n = spanno << 9; - /* point a char * at the address location */ - cp = (char *) &maddr[DADDR + n]; - *cp = loc; /* set address in T1 chip */ - cp = (char *) &maddr[DDATA + n]; - /* point a char * at the data location */ - return(*cp); -} - -/* get input from the status register */ -static unsigned char getctlreg(void) -{ -register char *cp; - - cp = (char *) &maddr[CTLREG]; - return(*cp); -} - -static void set_clear(void) -{ - int i,j,s; - unsigned short val=0; - for (s=0;s<2;s++) { - for (i=0;ipvt; - unsigned long flags; -#if 0 - printk("Setting bits to %x hex on channel %s\n", bits, chan->name); -#endif - if (card_type == TYPE_E1) { /* do it E1 way */ - if (chan->chanpos > 30) return 0; /* cant do this for chan 31 */ - n = chan->chanpos - 1; - k = p->span; - b = (n % 15) + 1; - c = txsigs[k][b]; - m = (n / 15) * 4; /* nibble selector */ - c &= (15 << m); /* keep the other nibble */ - c |= (bits & 15) << (4 - m); /* put our new nibble here */ - txsigs[k][b] = c; - /* output them into the chip */ - t1out(k + 1,0x40 + b,c); - return 0; - } - n = chan->chanpos - 1; - k = p->span; - b = (n / 8); /* get byte number */ - m = 1 << (n & 7); /* get mask */ - c = txsigs[k][b]; - c &= ~m; /* clear mask bit */ - /* set mask bit, if bit is to be set */ - if (bits & ZT_ABIT) c |= m; - txsigs[k][b] = c; - write_lock_irqsave(&torisa, flags); - t1out(k + 1,0x70 + b,c); - b += 3; /* now points to b bit stuff */ - /* get current signalling values */ - c = txsigs[k][b]; - c &= ~m; /* clear mask bit */ - /* set mask bit, if bit is to be set */ - if (bits & ZT_BBIT) c |= m; - /* save new signalling values */ - txsigs[k][b] = c; - /* output them into the chip */ - t1out(k + 1,0x70 + b,c); - b += 3; /* now points to c bit stuff */ - /* get current signalling values */ - c = txsigs[k][b]; - c &= ~m; /* clear mask bit */ - /* set mask bit, if bit is to be set */ - if (bits & ZT_CBIT) c |= m; - /* save new signalling values */ - txsigs[k][b] = c; - /* output them into the chip */ - t1out(k + 1,0x70 + b,c); - b += 3; /* now points to d bit stuff */ - /* get current signalling values */ - c = txsigs[k][b]; - c &= ~m; /* clear mask bit */ - /* set mask bit, if bit is to be set */ - if (bits & ZT_DBIT) c |= m; - /* save new signalling values */ - txsigs[k][b] = c; - /* output them into the chip */ - t1out(k + 1,0x70 + b,c); - write_unlock_irqrestore(&torisa, flags); - return 0; -} - -static inline int getspan(struct zt_span *span) -{ - if (span == spans) - return 1; - if (span == spans + 1) - return 2; - return -1; -} - -static int torisa_shutdown(struct zt_span *span) -{ - int i; - int tspan; - int wasrunning; - unsigned long flags; - - tspan = getspan(span); - if (tspan < 0) { - printk("TorISA: Span '%d' isn't us?\n", span->spanno); - return -1; - } - - write_lock_irqsave(&torisa, flags); - wasrunning = span->flags & ZT_FLAG_RUNNING; - - span->flags &= ~ZT_FLAG_RUNNING; - /* Zero out all registers */ - for (i = 0; i< 0xff; i++) t1out(tspan, i, 0); - if (wasrunning) - spansstarted--; - write_unlock_irqrestore(&torisa, flags); - if (!spans[0].flags & ZT_FLAG_RUNNING && - !spans[1].flags & ZT_FLAG_RUNNING) - /* No longer in use, disable interrupts */ - setctlreg(clockvals[syncsrc]); - - if (debug) - printk("Span %d (%s) shutdown\n", span->spanno, span->name); - return 0; -} - -static int torisa_startup(struct zt_span *span) -{ - unsigned long endjif; - int i; - int tspan; - unsigned long flags; - char *coding; - char *framing; - char *crcing; - int alreadyrunning; - - tspan = getspan(span); - if (tspan < 0) { - printk("TorISA: Span '%d' isn't us?\n", span->spanno); - return -1; - } - - - write_lock_irqsave(&torisa, flags); - - alreadyrunning = span->flags & ZT_FLAG_RUNNING; - - /* initialize the start value for the last ec buffer */ - for(i = 0; i < span->channels; i++) - { - last_ecwrite[tspan - 1][i] = ZT_LIN2X(0,&span->chans[i]); - } - crcing = ""; - if (card_type == TYPE_T1) { /* if its a T1 card */ - if (!alreadyrunning) { - - setctlreg(MASTERCLOCK); - /* Zero out all registers */ - for (i = 0x20; i< 0x40; i++) - t1out(tspan, i, 0); - for (i = 0x60; i< 0x80; i++) - t1out(tspan, i, 0); - - /* Full-on Sync required (RCR1) */ - t1out(tspan, 0x2b, 8); - /* RSYNC is an input (RCR2) */ - t1out(tspan, 0x2c, 8); - /* RBS enable (TCR1) */ - t1out(tspan, 0x35, 0x10); - /* TSYNC to be output (TCR2) */ - t1out(tspan, 0x36, 4); - /* Tx & Rx Elastic store, sysclk = 2.048 mhz, loopback controls (CCR1) */ - t1out(tspan, 0x37, 0x8c); - } - /* Enable F bits pattern */ - i = 0x20; - if (span->lineconfig & ZT_CONFIG_ESF) - i = 0x88; - if (span->lineconfig & ZT_CONFIG_B8ZS) - i |= 0x44; - t1out(tspan, 0x38, i); - if (i & 0x80) - coding = "ESF"; - else - coding = "SF"; - if (i & 0x40) - framing = "B8ZS"; - else { - framing = "AMI"; - t1out(tspan,0x7e,0x1c); /* F bits pattern (0x1c) into FDL register */ - } - t1out(tspan, 0x7c, span->txlevel << 5); - - if (!alreadyrunning) { - /* LIRST to 1 in CCR3 */ - t1out(tspan, 0x30, 1); - - /* Wait 100 ms */ - endjif = jiffies + 10; - write_unlock_irqrestore(&torisa, flags); - - while(jiffies < endjif); /* wait 100 ms */ - - write_lock_irqsave(&torisa, flags); - t1out(tspan,0x30,0x40); /* set CCR3 to 0x40, resetting Elastic Store */ - - span->flags |= ZT_FLAG_RUNNING; - spansstarted++; - -#if 0 - printk("Enabling interrupts: %d\n", clockvals[syncsrc] | INTENA); -#endif - - /* output the clock info and enable interrupts */ - setctlreg(clockvals[syncsrc] | INTENA); - } - set_clear(); /* this only applies to a T1 */ - } else { /* if its an E1 card */ - u_char ccr1 = 0, tcr1 = 0; - - if (!alreadyrunning) { - t1out(tspan,0x1a,4); /* CCR2: set LOTCMC */ - for(i = 0; i <= 8; i++) t1out(tspan,i,0); - for(i = 0x10; i <= 0x4f; i++) if (i != 0x1a) t1out(tspan,i,0); - t1out(tspan,0x10,0x20); /* RCR1: Rsync as input */ - t1out(tspan,0x11,6); /* RCR2: Sysclk=2.048 Mhz */ - t1out(tspan,0x12,8); /* TCR1: TSiS mode */ - } - tcr1 = 8; /* base TCR1 value: TSis mode */ - if (span->lineconfig & ZT_CONFIG_CCS) { - ccr1 |= 8; /* CCR1: Rx Sig mode: CCS */ - coding = "CCS"; - } else { - tcr1 |= 0x20; - coding = "CAS"; - } - if (span->lineconfig & ZT_CONFIG_HDB3) { - ccr1 |= 0x44; /* CCR1: TX and RX HDB3 */ - framing = "HDB3"; - } else framing = "AMI"; - if (span->lineconfig & ZT_CONFIG_CRC4) { - ccr1 |= 0x11; /* CCR1: TX and TX CRC4 */ - crcing = "/CRC4"; - } - t1out(tspan,0x12,tcr1); - t1out(tspan,0x14,ccr1); - t1out(tspan, 0x18, 0x80); - - if (!alreadyrunning) { - t1out(tspan,0x1b,0x8a); /* CCR3: LIRST & TSCLKM */ - t1out(tspan,0x20,0x1b); /* TAFR */ - t1out(tspan,0x21,0x5f); /* TNAFR */ - t1out(tspan,0x40,0xb); /* TSR1 */ - for(i = 0x41; i <= 0x4f; i++) t1out(tspan,i,0x55); - for(i = 0x22; i <= 0x25; i++) t1out(tspan,i,0xff); - /* Wait 100 ms */ - endjif = jiffies + 10; - write_unlock_irqrestore(&torisa, flags); - while(jiffies < endjif); /* wait 100 ms */ - write_lock_irqsave(&torisa, flags); - t1out(tspan,0x1b,0x9a); /* CCR3: set also ESR */ - t1out(tspan,0x1b,0x82); /* CCR3: TSCLKM only now */ - - /* output the clock info and enable interrupts */ - setctlreg(clockvals[syncsrc] | INTENA); - } - - } - - write_unlock_irqrestore(&torisa, flags); - - if (debug) { - if (card_type == TYPE_T1) { - if (alreadyrunning) - printk("TorISA: Reconfigured span %d (%s/%s) LBO: %s\n", span->spanno, coding, framing, zt_lboname(span->txlevel)); - else - printk("TorISA: Startup span %d (%s/%s) LBO: %s\n", span->spanno, coding, framing, zt_lboname(span->txlevel)); - } else { - if (alreadyrunning) - printk("TorISA: Reconfigured span %d (%s/%s%s) 120 ohms\n", span->spanno, coding, framing, crcing); - else - printk("TorISA: Startup span %d (%s/%s%s) 120 ohms\n", span->spanno, coding, framing, crcing); - } - } - if (syncs[0] == span->spanno) printk("SPAN %d: Primary Sync Source\n",span->spanno); - if (syncs[1] == span->spanno) printk("SPAN %d: Secondary Sync Source\n",span->spanno); - return 0; -} - -static int torisa_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) -{ - if (debug) - printk("TorISA: Configuring span %d\n", span->spanno); - - span->syncsrc = syncsrc; - - /* remove this span number from the current sync sources, if there */ - if (syncs[0] == span->spanno) syncs[0] = 0; - if (syncs[1] == span->spanno) syncs[1] = 0; - /* if a sync src, put it in proper place */ - if (lc->sync) syncs[lc->sync - 1] = span->spanno; - - /* If we're already running, then go ahead and apply the changes */ - if (span->flags & ZT_FLAG_RUNNING) - return torisa_startup(span); - - return 0; -} - -static int torisa_chanconfig(struct zt_chan *chan, int sigtype) -{ - int alreadyrunning; - unsigned long flags; - alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING; - if (debug) { - if (alreadyrunning) - printk("TorISA: Reconfigured channel %d (%s) sigtype %d\n", chan->channo, chan->name, sigtype); - else - printk("TorISA: Configured channel %d (%s) sigtype %d\n", chan->channo, chan->name, sigtype); - } - write_lock_irqsave(&torisa, flags); - if (alreadyrunning && (card_type == TYPE_T1)) - set_clear(); - write_unlock_irqrestore(&torisa, flags); - return 0; -} - -static int torisa_open(struct zt_chan *chan) -{ -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#endif - return 0; -} - -static int torisa_close(struct zt_chan *chan) -{ -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#endif - return 0; -} - -static int torisa_maint(struct zt_span *span, int cmd) -{ - int tspan = getspan(span); - - switch(cmd) { - case ZT_MAINT_NONE: - t1out(tspan,0x1a,4); /* clear system */ - break; - case ZT_MAINT_LOCALLOOP: - t1out(tspan,0x1a,5); /* local loopback */ - break; - case ZT_MAINT_REMOTELOOP: - t1out(tspan,0x37,6); /* remote loopback */ - break; - case ZT_MAINT_LOOPUP: - if (card_type == TYPE_E1) return -ENOSYS; - t1out(tspan,0x30,2); /* send loopup code */ - break; - case ZT_MAINT_LOOPDOWN: - if (card_type == TYPE_E1) return -ENOSYS; - t1out(tspan,0x30,4); /* send loopdown code */ - break; - case ZT_MAINT_LOOPSTOP: - if (card_type == TYPE_T1) - t1out(tspan,0x30,0); /* stop sending loopup code */ - break; - default: - printk("torisa: Unknown maint command: %d\n", cmd); - break; - } - return 0; -} - -static int taskletpending; - -static struct tasklet_struct torisa_tlet; - -static void torisa_tasklet(unsigned long data) -{ - int x,y; - u_char mychunk[2][ZT_CHUNKSIZE]; - taskletrun++; - if (taskletpending) { - taskletexec++; - /* Perform receive data calculations. Reverse to run most - likely master last */ - if (spans[1].flags & ZT_FLAG_RUNNING) { - /* Perform echo cancellation */ - for (x=0;x> (j * 8)) & 0xff; - readdata[curread][j * channels_per_span + n - 1][passno % ZT_CHUNKSIZE] = rxc; - } - } - - i = passno & 127; - /* if an E1 card, do rx signalling for it */ - if (i < 3 && (card_type == TYPE_E1)) { /* if an E1 card */ - for(j = (i * 3); j < (i * 3) + 5; j++) - { - for(k = 1,x = j; k <= 2; k++,x += channels_per_span) { - c = t1in(k,0x31 + j); - rxc = c & 15; - if (rxc != chans[x + 15].rxsig) { - /* Check for changes in received bits */ - if (!(chans[x + 15].sig & ZT_SIG_CLEAR)) - zt_rbsbits(&chans[x + 15], rxc); - } - rxc = c >> 4; - if (rxc != chans[x].rxsig) { - /* Check for changes in received bits */ - if (!(chans[x].sig & ZT_SIG_CLEAR)) - zt_rbsbits(&chans[x], rxc); - } - } - } - } - /* if a t1 card, do rx signalling for it */ - if ((i < 6) && (card_type == TYPE_T1)) { - k = (i / 3); /* get span */ - n = (i % 3); /* get base */ - abits = t1in(k + 1, 0x60 + n); - bbits = t1in(k + 1, 0x63 + n); - cbits = t1in(k + 1, 0x66 + n); - dbits = t1in(k + 1, 0x69 + n); - for (j=0; j< 8; j++) { - /* Get channel number */ - i = (k * 24) + (n * 8) + j; - rxc = 0; - if (abits & (1 << j)) rxc |= ZT_ABIT; - if (bbits & (1 << j)) rxc |= ZT_BBIT; - if (cbits & (1 << j)) rxc |= ZT_CBIT; - if (dbits & (1 << j)) rxc |= ZT_DBIT; - if (chans[i].rxsig != rxc) { - /* Check for changes in received bits */ - if (!(chans[i].sig & ZT_SIG_CLEAR)) - zt_rbsbits(&chans[i], rxc); - } - } - } - - if (!(passno & 0x7)) { - for(i = 0; i < 2; i++) - { - /* if alarm timer, and it's timed out */ - if (alarmtimer[i]) { - if (!--alarmtimer[i]) - { - /* clear recover status */ - spans[i].alarms &= ~ZT_ALARM_RECOVER; - if (card_type == TYPE_T1) - t1out(i + 1,0x35,0x10); /* turn off yel */ - else - t1out(i + 1,0x21,0x5f); /* turn off remote alarm */ - zt_alarm_notify(&spans[i]); /* let them know */ - } - } - } - } - - i = passno & 511; - if ((i == 100) || (i == 101)) - { - j = 0; /* clear this alarm status */ - i -= 100; - if (card_type == TYPE_T1) { - c = t1in(i + 1,0x31); /* get RIR2 */ - spans[i].rxlevel = c >> 6; /* get rx level */ - t1out(i + 1,0x20,0xff); - c = t1in(i + 1,0x20); /* get the status */ - /* detect the code, only if we are not sending one */ - if ((!spans[i].mainttimer) && (c & 0x80)) /* if loop-up code detected */ - { - /* set into remote loop, if not there already */ - if ((loopupcnt[i]++ > 80) && - (spans[i].maintstat != ZT_MAINT_REMOTELOOP)) - { - t1out(i + 1,0x37,0x9c); /* remote loopback */ - spans[i].maintstat = ZT_MAINT_REMOTELOOP; - } - } else loopupcnt[i] = 0; - /* detect the code, only if we are not sending one */ - if ((!spans[i].mainttimer) && (c & 0x40)) /* if loop-down code detected */ - { - /* if in remote loop, get out of it */ - if ((loopdowncnt[i]++ > 80) && - (spans[i].maintstat == ZT_MAINT_REMOTELOOP)) - { - t1out(i + 1,0x37,0x8c); /* normal */ - spans[i].maintstat = ZT_MAINT_NONE; - } - } else loopdowncnt[i] = 0; - if (c & 3) /* if red alarm */ - { - j |= ZT_ALARM_RED; - } - if (c & 8) /* if blue alarm */ - { - j |= ZT_ALARM_BLUE; - } - } else { /* its an E1 card */ - t1out(i + 1,6,0xff); - c = t1in(i + 1,6); /* get the status */ - if (c & 9) /* if red alarm */ - { - j |= ZT_ALARM_RED; - } - if (c & 2) /* if blue alarm */ - { - j |= ZT_ALARM_BLUE; - } - } - /* only consider previous carrier alarm state */ - spans[i].alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); - n = 1; /* set to 1 so will not be in yellow alarm if we dont - care about open channels */ - /* if to have yellow alarm if nothing open */ - if (spans[i].lineconfig & ZT_CONFIG_NOTOPEN) - { - /* go thru all chans, and count # open */ - for(n = 0,k = (i * channels_per_span); k < (i * channels_per_span) + channels_per_span; k++) - { - if ((chans[k].flags & ZT_FLAG_OPEN) || - (chans[k].flags & ZT_FLAG_NETDEV)) n++; - } - /* if none open, set alarm condition */ - if (!n) j |= ZT_ALARM_NOTOPEN; - } - /* if no more alarms, and we had some */ - if ((!j) && spans[i].alarms) - { - alarmtimer[i] = ZT_ALARMSETTLE_TIME; - } - if (alarmtimer[i]) j |= ZT_ALARM_RECOVER; - /* if going into alarm state, set yellow (remote) alarm */ - if ((j) && (!spans[i].alarms)) { - if (card_type == TYPE_T1) t1out(i + 1,0x35,0x11); - else t1out(i + 1,0x21,0x7f); - } - if (c & 4) /* if yellow alarm */ - j |= ZT_ALARM_YELLOW; - if (spans[i].maintstat || spans[i].mainttimer) j |= ZT_ALARM_LOOPBACK; - spans[i].alarms = j; - zt_alarm_notify(&spans[i]); - } - if (!(passno % 8000)) /* even second boundary */ - { - /* do both spans */ - for(i = 1; i <= 2; i++) - { - if (card_type == TYPE_T1) { - /* add this second's BPV count to total one */ - spans[i - 1].bpvcount += t1in(i,0x24) + (t1in(i,0x23) << 8); - } else { - /* add this second's BPV count to total one */ - spans[i - 1].bpvcount += t1in(i,1) + (t1in(i,0) << 8); - } - } - } - /* re-evaluate active sync src */ - mysyncsrc = 0; - /* if primary sync specified, see if we can use it */ - if (syncs[0]) - { - /* if no alarms, use it */ - if (!(spans[syncs[0] - 1].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | - ZT_ALARM_LOOPBACK))) mysyncsrc = syncs[0]; - } - /* if we dont have one yet, and there is a secondary, see if we can use it */ - if ((!mysyncsrc) && (syncs[1])) - { - /* if no alarms, use it */ - if (!(spans[syncs[1] - 1].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | - ZT_ALARM_LOOPBACK))) mysyncsrc = syncs[1]; - } - /* on the E1 card, the PLL takes a bit of time to lock going - between internal and external clocking. There needs to be some - settle time before actually changing the source, otherwise it will - oscillate between in and out of sync */ - if (card_type == TYPE_E1) - { - /* if stable, add to count */ - if (lastsyncsrc == mysyncsrc) mysynccnt++; else mysynccnt = 0; - lastsyncsrc = mysyncsrc; - /* if stable sufficiently long, change it */ - if (mysynccnt >= E1SYNCSTABLETHRESH) - { - mysynccnt = 0; - syncsrc = mysyncsrc; - } - } - else syncsrc = mysyncsrc; /* otherwise on a T1 card, just use current value */ - /* update sync src info */ - spans[0].syncsrc = spans[1].syncsrc = syncsrc; - /* If this is the last pass, then prepare the next set */ - /* clear outbit, restore interrupt enable */ - setctlreg(clockvals[syncsrc] | INTENA); -#ifdef LINUX26 - return IRQ_RETVAL(1); -#endif -} - - -static int torisa_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) -{ - struct torisa_debug td; - switch(cmd) { - case TORISA_GETDEBUG: - td.txerrors = txerrors; - td.irqcount = irqcount; - td.taskletsched = taskletsched; - td.taskletrun = taskletrun; - td.taskletexec = taskletexec; - td.span1flags = spans[0].flags; - td.span2flags = spans[1].flags; - if (copy_to_user((struct torisa_debug *)data, &td, sizeof(td))) - return -EFAULT; - return 0; - default: - return -ENOTTY; - } - return 0; -} - -static int __init tor_init(void) -{ - if (!base) { - printk("Specify address with base=0xNNNNN\n"); - return -EIO; - } - if (tor_probe()) { - printk(KERN_ERR "No ISA tormenta card found at %05lx\n", base); - return -EIO; - } - if (request_irq(irq, torisa_intr, ZAP_IRQ_DISABLED, "torisa", NULL)) { - printk(KERN_ERR "Unable to request tormenta IRQ %d\n", irq); - return -EIO; - } - if (!request_mem_region(base, 4096, "Tormenta ISA")) { - printk(KERN_ERR "Unable to request 4k memory window at %lx\n", base); - free_irq(irq, NULL); - return -EIO; - } - - strcpy(spans[0].name, "TorISA/1"); - strncpy(spans[0].desc, "ISA Tormenta Span 1", sizeof(spans[0].desc) - 1); - spans[0].manufacturer = "Digium"; - strncpy(spans[0].devicetype, "Tormenta ISA", sizeof(spans[0].devicetype) - 1); - spans[0].spanconfig = torisa_spanconfig; - spans[0].chanconfig = torisa_chanconfig; - spans[0].startup = torisa_startup; - spans[0].shutdown = torisa_shutdown; - spans[0].rbsbits = torisa_rbsbits; - spans[0].maint = torisa_maint; - spans[0].open = torisa_open; - spans[0].close = torisa_close; - spans[0].channels = channels_per_span; - spans[0].chans = &chans[0]; - spans[0].flags = ZT_FLAG_RBS; - spans[0].ioctl = torisa_ioctl; - spans[0].irq = irq; - - if (card_type == TYPE_E1) { - spans[0].spantype = "T1"; - spans[0].linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; - spans[0].deflaw = ZT_LAW_ALAW; - } else { - spans[0].spantype = "E1"; - spans[0].linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4; - spans[0].deflaw = ZT_LAW_MULAW; - } - - spans[1] = spans[0]; - strcpy(spans[1].name, "TorISA/2"); - strcpy(spans[1].desc, "ISA Tormenta Span 2"); - spans[1].chans = &chans[channels_per_span]; - - init_waitqueue_head(&spans[0].maintq); - init_waitqueue_head(&spans[1].maintq); - - make_chans(); - if (zt_register(&spans[0], prefmaster)) { - printk(KERN_ERR "Unable to register span %s\n", spans[0].name); - return -EIO; - } - if (zt_register(&spans[1], 0)) { - printk(KERN_ERR "Unable to register span %s\n", spans[1].name); - zt_unregister(&spans[0]); - return -EIO; - } - tasklet_init(&torisa_tlet, torisa_tasklet, (long)0); - printk("TORISA Loaded\n"); - return 0; -} - - -#if !defined(LINUX26) -static int __init set_tor_base(char *str) -{ - base = simple_strtol(str, NULL, 0); - return 1; -} - -__setup("tor=", set_tor_base); -#endif - -static void __exit tor_exit(void) -{ - free_irq(irq, NULL); - release_mem_region(base, 4096); - if (spans[0].flags & ZT_FLAG_REGISTERED) - zt_unregister(&spans[0]); - if (spans[1].flags & ZT_FLAG_REGISTERED) - zt_unregister(&spans[1]); -} - -MODULE_AUTHOR("Mark Spencer "); -MODULE_DESCRIPTION("Tormenta ISA Zapata Telephony Driver"); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif - -#ifdef LINUX26 -module_param(prefmaster, int, 0600); -module_param(base, long, 0600); -module_param(irq, int, 0600); -module_param(syncsrc, int, 0600); -module_param(debug, int, 0600); -#else -MODULE_PARM(prefmaster, "i"); -MODULE_PARM(base, "i"); -MODULE_PARM(irq, "i"); -MODULE_PARM(syncsrc, "i"); -MODULE_PARM(debug, "i"); -#endif - -module_init(tor_init); -module_exit(tor_exit); diff --git a/torisatool.c b/torisatool.c index 5334289..d8ab428 100644 --- a/torisatool.c +++ b/torisatool.c @@ -28,7 +28,7 @@ #include #include #include -#include "zaptel.h" +#include "kernel/zaptel.h" static void usage(void) { diff --git a/tormenta2.rbt b/tormenta2.rbt deleted file mode 100644 index 9238b8a..0000000 --- a/tormenta2.rbt +++ /dev/null @@ -1,17482 +0,0 @@ -Xilinx ASCII Bitstream -Created by Bitstream F.23 -Design name: tormenta2.ncd -Architecture: spartan2 -Part: 2s50pq208 -Date: Thu Oct 10 09:00:52 2002 -Bits: 559200 -11111111111111111111111111111111 -10101010100110010101010101100110 -00110000000000001000000000000001 -00000000000000000000000000000111 -00110000000000010110000000000001 -00000000000000000000000000001011 -00110000000000010010000000000001 -00000000100000000011111100101101 -00110000000000001100000000000001 -00000000000000000000000000000000 -00110000000000001000000000000001 -00000000000000000000000000001001 -00110000000000000010000000000001 -00000000000000000000000000000000 -00110000000000001000000000000001 -00000000000000000000000000000001 -00110000000000000100000000000000 -01010000000000000011111000000100 -00000000000100100011000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000100 -10000000000000000000000000000000 -00000000000000000000000000000000 -00000000000100100011000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000010000000000100 -10000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000100000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -10000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000100000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -10000000000000000000000000000000 -00000000000000000000000000000000 -00000000000100100000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000100 -10000000000000000000000000000000 -00000000000000000000000000000000 -00000000000100100000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000100 -10000000000000000000000000000000 -00000000000000000000000000000000 -00000000000100100000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000010000000000100 -00000000000000000000000000000000 -00000000000000000000000000000000 -11111111000100100000000000000000 -00000000000000011000000000000000 -01000000000000000001100000000000 -00000100000000000000000010000000 -00000000011000000000000000011000 -00000000000010100000000000000010 -10000000000000000010000000000000 -00101000000000000000001000000000 -00000000000000000000000000100000 -00000000000010000001111111000100 -00000000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111101000000000 -11111111100000000011111100000000 -10001111111110000000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111110000 -00000011011111100000000011111111 -10000000001111111110000000001111 -11111000000000111111000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001110001000000000 -10111011100000000010111000110100 -00001011101110000000001011101110 -00000000101110111000000000101110 -11100000000010111011100000000010 -11101110000000001011101110000000 -00101110111000000000101110111000 -00000010101011100000000010111011 -10000000001011101110000000001011 -10111000000000101110000000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100100000000000 -10100011000000000010110010000000 -00001011001100000010011010001100 -00000000101100110000000000101000 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010010011000000000010110011 -00000000001011001100000000001011 -00110000000001101110001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010000000000000 -10111011000000000010111011000010 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110010 -10000010111011000000000010111011 -00000000001011101100000000011011 -10110000000000101111000000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000101011110110100000000 -11111011000000000011111000010000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110111100 -00000011011011000000000011111011 -00000000001111101100000000001111 -10110000010000111100100000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011000001000000 -11111111000000000011111010100100 -00001111111100000000000111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111110111000 -00000011101111000000000011111111 -00000000001111111100000000001111 -11110000000000111111100000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011000000010011111000010000 -00101100101100000000001111101100 -00000000111110110000000000110110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111100110000 -00000011101011000000000011111011 -00000000001111101100000000001111 -10110000000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010010000000000000 -10111011000101100010111010000000 -00001000101100000000001011101100 -00000000101110110000000000100110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010001011000000000010111011 -00000000001011101100000000001011 -10111000100000101111001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100010000000000 -10110011000000000010110001000000 -00001000001100000000001001001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100000000 -00000010100011000000000010110011 -00000000001011001100000000001011 -00111110000000101111000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -01100000000000010001001000000000 -10110111100000000010110100100000 -00001000011110000100001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101001000 -00000010000111100000000010110111 -10000000001011011110000000001011 -01111000000000101101100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -01001000000010000000110001000000 -11110011000000000011110011000000 -00001100001100010010001111001100 -00000000111100110000000000111100 -11000000000011110011000000000011 -11001100000000001111001100000000 -00111100110000000000111100000000 -00000011100011000000000011110011 -00000000001111001100000000001111 -00110000000000111101101000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000111011011000000010000 -11111111000000000011111111000100 -00001111111100000000001111111100 -00001000111111110000000000110111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111000000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111101000000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -10101000000011011110010000010000 -11111011000000000011111001000000 -00001100101100000000001111101100 -00001000111110110000000001111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111100000000 -00000011001011000000000011111011 -00000000001111101100000000001111 -10110000000000111110101000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000000011001000000000000 -10110111000000000010110001000000 -00001000011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101000000 -00000010000111000000000010110111 -00000000001011011100000000001011 -01110000000000101101001000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000001000000001001111000000000 -10110111100000000010110111100000 -00011000011110000001001011011110 -00000001101101111000000100101001 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101111000000 -00000010000111100000000010110111 -10000000001011011110000000001011 -01111000000000101111000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000100101001100000000000000 -10110011000000000010110011000000 -00011000001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100000000 -00000010000011000000000010110011 -00000000001011001100000000001011 -00110000000000101101001100000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011011100000000000 -11111010000000000011111110011100 -00101100101000000000001111101000 -00000000111110100000000000111110 -10000000000011111010000000000011 -11101000000000001111101000000000 -00111110100000000000111111100000 -00000011001010000000000011111010 -00000000001111101000000000001111 -00100000000000111111101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000010000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000100000000111101001000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001100000000011110001000000 -00001101100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000110000001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000100000010111001000000 -00001000100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10011000000010100010000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010110000000000 -10111001000000000010111001000000 -00001000100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010010100000100000011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001100000000010110001001000 -00101000000100000000001011000100 -00000000100100010000000001101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000100100010010 -10000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000100000001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000001010110000000000000 -11111000000000000011111000000000 -00001100100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000010 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000110010111000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000101011111010000000000 -11111001000001000011111101000100 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111111010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110011000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -10011000000001011110010000000000 -11001001000000000011111001000000 -00001100100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011001001000000000011111001 -00000000001111100100000000001111 -01010000000000111110011000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000100001110000000000000 -10001000000000000010111000000000 -00001000100000000000001011100000 -00000000101110000000000000101110 -00000000000010111000000000000010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000010101000000000000010111000 -00000000001011100000000000001011 -10000000000000101100111000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000001011110010000000000 -10000001000000000010100001000000 -00001000000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -10000100000000001011000100000000 -00101100010000000000101110010000 -00000010000001000000000010110001 -00000000001011000100000000001011 -00010000000001101100001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10001001000000000010111001001010 -00001000100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010101001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011100010001000010 -11001001000000010011111001000000 -00101100100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111100010000 -00000011001001000000000011111001 -00000000001111100100000000001111 -10010000000000111110100000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000000011010011000000000 -11111011000000010011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11001000000000000011110000000000 -00001100100000000000001111100000 -00000000111110000000000000110110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000100000110000101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00100000000001010010100000000000 -10001010000000000010111010000000 -00001000101000000000001011101000 -00000000101110100000000000100110 -10000000000010111010000000000010 -11101000000000001011101000000000 -00101110100000000000101110100000 -00000010111010000000000010111010 -00000000001011101000000000001011 -11100000000000100000101000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000010 -10000010000001000010110011000000 -00001000001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000100100101000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000000010011110000000000 -10000111010000000010110111000000 -00001000011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01111000000000100100100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001111000000000 -11000100100000010011110011100000 -00101100011110000000001111011110 -00000000111101111000000000111101 -11100000000011110111100000000011 -11011110000000001111011110000000 -00111101111000000000111101111000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01101000000000110100101000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011000110000000000 -11111000011000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000110110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000010001111 -10000000000010111000001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11111110110000100011001111100000 -00001100111110000000001101111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011001111100000000011111111 -10000000001111111110000000001111 -11111000000000111101000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110000100000 -10110111000000000011010111000000 -00001000011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000011110111000000000010110111 -00000000001011011100000000001011 -01100010000000101110101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00010000000000001001110000000000 -10110110000000000010000111000000 -00001000011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010000111000000000010110111 -00000000001011011100000000001011 -01110000000000101100010000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01100000000101001100110000000000 -10110010000000000010010011000000 -00001000001100000000001011001100 -00000000101100110000000000100100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00000000000001101101100100000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11111000000101011010110100000000 -11111011000000000011001011000010 -00101100101100000000001101101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011001011000000000011111011 -00000000001111101100000000001111 -10010000000000111110101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000100000000001110110000000000 -11111011000000010011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111100110000 -00000011111011000000000011111011 -00000010001111101100000000001111 -10010000000000111110010000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001111110000100000 -11111101100000010011111011000010 -00001111111100000000001110111100 -00000000111111110000000000111111 -11000000000010111111000000000011 -11111100000000001111111100000000 -00111111110000000000111110110000 -00000011001111000000000011111111 -00000000001111111100000000001111 -11101000000000111110000001000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000001000001000110110000000100 -10111000110110000010111011000000 -00001001101100000000001011101100 -00000000101110110000000000101110 -11000000000010011011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010101011000000000010111011 -00000000001011101100000000001011 -10000000000000101110000101100000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111001000000000010111011000000 -00001011101100000000001001101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010001011000000000010111011 -00000000001011101100000001001011 -10010010000100101110000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10110001000000000010110011000000 -00001001001100000000001011001100 -00000000101100110000000000101100 -11000000000110010011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010100011000000000010110011 -00000000001011001100000000001011 -00000000000000101100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -10000000000011010110110000000000 -11111001000000000011111011000000 -00001111101100000000001110101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011001011000000000011111011 -00000000001111101100000000001111 -10110000000000111110000000000010 -00010000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11110100000001000011111111000000 -00001101111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11000000000000111110100000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11111111000000000011111111100000 -00001111111110000000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111110010000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11001000000000110111000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001110111000000000 -10111011110100010010111011100000 -00001011101110000000001110101110 -00000000101110111000000000101110 -11100000000010111011100000000010 -11101110000000001011100010000000 -00101110111000000000101110111000 -00000010111011100000000010111011 -10000000001011101110000000001011 -10001000000000100010000000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10100011000001000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011000000000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00000000000001100110001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010110000010000 -10111011000000000010111011000000 -00001011101100000000001010101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000011011100000001000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000011011 -10110000000000100111000000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000101011110110000000000 -11111111000000100011111011000000 -00001111101100000000001011101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000010111011 -00000000001111101100000000001011 -10011001000000110101000000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11111111000000000000111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000100001111111100100000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11000000000000111011100000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011001000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111100101000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10010000000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10111111100000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011100100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -00110000000000101111001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10110011010000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011000000000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00100010000000101111100100000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00100000000000010001111000000000 -10110111100000000010110111100000 -00001011011110000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011010010000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01001000000000101100100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -01001000000010000000110001000000 -11110011000010000011110011000000 -00001111001100000000001111001100 -00000000111100110000000000111100 -11000000000011110011000000000011 -11001100000000001111001100000000 -00111100110000000000111100110001 -00000011110011000000000011110011 -00000000001111001100000000001111 -00100000000000111101001000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000111011011110000010000 -11111111000000100011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111101000000 -00111111110000000000111111110000 -01000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111101000000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011110110000000000 -11111111100000000011001011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101000000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10111000000000110010101000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000100011001110000000000 -10110111100000000011010111000000 -00001110011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011000000000 -00101101110000000000101101110000 -00010010110111000000000010110111 -00000000001011011100000000001011 -01000000000000110101001000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000000001001111000000000 -10110011100000000010100111100000 -00011011011110000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -01101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000001100011000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110011000000000010110011000000 -00001010001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100110000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110010000000100101001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11111010000000000011101010000000 -00001111101000000000001111101000 -00000000111110100000000000111110 -10000000000011111010000000000011 -11101000000000001111101010000000 -00111110100000010001111110100000 -00000011111010000000000011111010 -00000000001111101000000000001111 -11100000000000110011101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011011000000000 -00001110100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000100000000111101001000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111101100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10011100000000101110000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001100000000010111001000000 -00001011100100000000001011100100 -00000000101010010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010101000000101100011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001101010000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11111000001000000011111000000000 -00001111100000000000001111100000 -00000000111010000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000011011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111101100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -01010000000000111110011000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000001011110010000000000 -11111101100000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -11010000000000111100011000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000100001110000000000000 -10111000010100000010111000000000 -00001110100000000000001011100000 -00000000101110000000000000101110 -00000000000010111000000000000010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000010111000000000000010111000 -00000000001011100000000000001011 -10100000000000101100111000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000001011100010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10111001000000000000111001000000 -00001010100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000011011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000011011 -10010000010000101100011000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101010110010000000000 -11111001000000000010111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100110010000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10011000000000111110100000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -00101000000000011010010000000100 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100110000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10011001000000111100101000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000000000011001000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000100000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010010100000000000 -10111110100001000010001010000000 -00001011101000000000001011101000 -00000000101110100000000000101110 -10000000000010111010000000000010 -11101000000000001011101000000000 -00101110100000000000101110100000 -00000010111010000000000010111010 -00000000001011101000000000001011 -11100000100000101100101000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110000000000001010100011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00111000000000101100001000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000000010001110000000000 -10110100110000000010100111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01100000000000101110000000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001111000001000 -11110100100000000011100111100000 -00001111011110000000001111011110 -00000000111101111000000000111101 -11100000000011110111100000000011 -11011110000000001111011110000000 -00111101111000000000111101111000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01011000000000111110101000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000010011011010110000000000 -11110000000000100011011011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10000000000000111100001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000001011111111000000000 -11111110100000000011001111100100 -00001111111110000000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111011110000000 -00110011111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111001000000110000000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110000000000 -10110110000000000010000111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101001110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000100001011 -01100000000010100010101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110110000000000010000111000000 -00011011011100000000001011011100 -00000000101001110000000000101101 -11000000000010110111000000000010 -11011100000000001011111100000000 -00100001110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -11110000100001100000000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00100000000101001100110000000000 -10110000000000000010000011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101000110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00101100000000100000100000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10101000000101011010110000000000 -11111001000000001011001011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00110010110000000000111110110000 -00000011111011000000000010111011 -00000000001111101100000000001011 -00110000000000110010101100000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11111000010000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110000000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -00000001000100001111110000000000 -11110101000000000011001111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11000100100000110000000001000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000001000001000110110000000000 -10111001000000000010001011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010011011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10001000000000101010000001000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000010000010001011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10010100000000100010000000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10110010000000000010000011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010010011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -10010000000000101000001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000011010110110000000000 -11111011000000000011001011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10000000000000110000100000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011111110000000100 -11110101000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011011111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -01000000000000111110000000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111101000000000 -11111100100000000011111111100000 -00001101111110010000001101111110 -01001000110011111000000000110111 -00000000000011111111100000000011 -11111100000000001101111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111111000000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000100001110011000000000 -10111000100000000010111011100000 -00001011101100000000001000001100 -00001000100010111000000000101110 -10110000000010111011100000000010 -11111110000000001010101110000000 -00101110111000000000101110111000 -00000010111011100000000010111011 -10000000001011101110000000001011 -10111000000000101111000000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11001000000001011100100000000000 -10110001000000000010110011000000 -00001011001100100001001001001100 -10000011100000110000000000101100 -00010000000010110011000000000010 -11001100000000001001001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101111001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000100011010010100000000 -10111011000000000010111011000000 -00001011001100000000001000001100 -00000000100010110000001000001110 -11000110000010111011000000000010 -11101100000000000010101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111000000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011110110000000000 -11111010010000000011111011000000 -01001101101100000001001101101100 -00000000110010110000000000111110 -01100000000010111011000000000011 -11101100000000001101101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111101010000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011011100000000 -11111110000000000011111111000000 -00000011111100000000001111111100 -00000000111111110000010000001110 -11100000000011111111000000000011 -11101100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111111100000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000100000100001010110100000000 -11101001010000000011111011000000 -00001101101100001000001111101100 -11000000110010110000000000111110 -00010000000011001011000000000011 -11001100000100001110101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111101010000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -11011000000001010010010000000001 -10001011000000000010111011000000 -00001001101111000000001011101111 -00000000110110110000000000101110 -11000000000011011011000000000010 -11111100000000001000101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111001000000100 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100000000010000 -10100001000000000010110011000000 -00001011001100000000001011001100 -00000000100100110000000000101100 -00000000010010000011000000000000 -11001100000000001010001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101111000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10110000100000010011001000001000 -10000100100000000110110111100001 -00001011011110000000001011011110 -00000000100101111000010000101101 -00100000000010010111100000000010 -11011110000000001010011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101110110000000100 -00010000000000000000000000000000 -00000000000000000000000000000000 -01001000000010000000000000000000 -10100001000000000011110011000000 -00001111001100001000001111001100 -00000000110100110001000000111100 -10000000000011000011000000000011 -11001100000000001110001100000000 -00111100110000000000111100110000 -00000011110011000000000011110011 -00000000001111001100000000001111 -00110001000000111101001000000010 -00010000000000000000000000000000 -00000000000000000000000000000000 -01000000000111011001000001000000 -11111110000100000011111111000000 -00001101111100000000001111111100 -00000000111111110000000000111111 -10000000000011111111000000000011 -11111100000000001101111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111101000000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011110100000010000 -11111011001010000001111011000000 -00001111101100000001101100101110 -00000000110010110000000000111110 -01000000000011001011000000000011 -11101100110000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11001000100100011001000000000000 -00110110000000000010110111000000 -00001011011100000000001000111100 -00000000101001110000000000101100 -11000000000010100111000000000010 -11011100010000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101111001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001001101000000000 -10110101110000000010110111100000 -00001011011110000000001000011110 -00000000100001111000000000101101 -01100000000010000111100000000010 -11011110100000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101100100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100001110000000 -10110010100000010110110011000000 -00001011101100000000001000001100 -00000000101000110000000000101100 -11111000000010100011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101101101000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -11100000000101011011100000100000 -11110010000000000011111010000000 -00001111101000000000001100101000 -00000000110010100000000000111111 -10110000000011001010000000000011 -11101000000000001111101000000000 -00111110100000000000111110100000 -00000011111010000000000011111010 -00000000001111101000000000001111 -10100000000000111111101100000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111100 -00000100000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111101001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000100 -11111011000000100011001001000000 -00001111100110000000001110100110 -00000000111110010000000000111110 -01000000000011001001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000000000010101001000000 -00001011100100000000001000100110 -00000000101110010000000000101110 -01000000000010001001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000100101110000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111011000000000010001001000000 -00001011100100100000001010100100 -10000000101110010000000000101110 -01000000000010001001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100111000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10111001000000000010100001000000 -00001011000100000000001000000100 -00000000101100010000000000101100 -01001000000010000001000000100010 -11000100101000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100101000000101 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11111000000000000011001000000000 -00001111001001010000001110101001 -01000000111110000000000000111110 -00000000001011001000000000000011 -11100000100000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111011111010000000000 -11111001000000000010111001000000 -00001111100100000000001111100100 -00000000111110010000000000111111 -01000100000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110011000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000001011100010000000000 -11111001000000000011111001000000 -00001111110100000000001100110100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100011000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01111000000100001110000000000000 -10111000000000100010111000000000 -00001011100000000000001101100000 -00000000101110000000000000101110 -00000000000010111000000000000010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000010111000000000000010111000 -00000000001011100000000000001011 -10000000000000101100111000000110 -00110000000000000000000000000000 -00000000000000000000000000000000 -01001000000001011100010000000000 -10110001000000000110110001000000 -00001011000100000000001000000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101101001000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10111001000110000110111001000000 -00001011100100000000001001100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011110010000000000 -11111001100000000011111001000000 -00001111100100000000001100100100 -00000000111110010000000000111110 -01101100000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110100000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -01101000000000011010010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000010000111110 -01100000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111101001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11101000010000000011111000000000 -00001111100000000000001111100000 -00000000110010000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111100001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010010100000000000 -10001010000000000010111010000000 -00001011111011000000001011111001 -00000000100010100000000000101110 -10000000000010111010000000000010 -11101000000000001011101000000000 -00101110100000000000101110100000 -00000010111010000000000010111010 -00000000001011101000000000001011 -10100000000000101100101000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10100011000000000010110011000000 -00001011101111001000001011001111 -00100000100000110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100101100000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000000010011111000000000 -10000111000000000010110111000000 -00001011011100001000001001011011 -00000000100001110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101110000000000100 -01000000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001111000000000 -11100111100000000011110111100000 -00001111011110000000001111111110 -00000010110001111000000000111101 -11100000000011110111100000000011 -11011110000000001111011110000000 -00111101111000000000111101111000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01111000011000111110001000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111011000000100011111011000000 -00001111101100000000001111100100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000001011111111000000000 -11111111100000100101111111100100 -00001111110110010000001100110110 -00000000110011111000000000111111 -11100000000011111111100000000011 -11111110000000001110111110000000 -00111111111000000000111111111000 -00000011011111100000000011111111 -10000000001111111110000000001111 -11111000000000111100000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110000000000 -10110111000000000110110111000000 -00001011110000000000001101010000 -00000000101001110000000000111101 -11000000000010110111000000000010 -11011100000000001000011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110001000000101110101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110111000000000010110111000000 -01001011010100000010001000011100 -00000000100001110000000000101101 -11000000000010110111000000000010 -11011100000000001010011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101100000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00100000000101001100110010000000 -10110011010100000010110011000000 -00001011100100000000001000100000 -00000000101000110000000000101000 -11100100000010110011000000000010 -11001100000000001000001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100100000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000101011010111110000000 -11111011010000000011111011000000 -00001111101000000010101000101100 -00000000110010110000000000101110 -11010100000011111011000000000011 -11101100000000001110101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000001000111 -10110000001100101110101100000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11111011001000000011111011000000 -00001111100000000000001111101001 -00000000111110110000000000111110 -11000000000011111011000000000011 -11001100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110000000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -00000001000100001111110000000000 -11111111000000000011111111000000 -00001111111010000000001100111000 -00000000110011110000000000111101 -11000000000011001111000000000011 -11101100000000001100111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000000011 -11110000000000111100100001000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110110000000000 -10111011000001000010111011000000 -00001011101011010000001010101011 -00100000110110110000000000101110 -11000000000010101011000000000010 -11101100000000001010101100000000 -00101110110000000000101110110000 -00000010011011000000000010111011 -00000000000011101100000000001011 -10110000000000101110100001000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000000010010110000000000 -10111011000000000110111011000000 -00001011101101000000001000100100 -01000000100010110000000000101110 -11000000000010001011000000000010 -11101100000000001000101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000000001101100000000001011 -10110000000000101110000000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10110011000000000010110011000001 -00001011000000000000001000000000 -00000000100100110000000000100100 -11000000001010000011000000000010 -11001100000000001010001100000000 -00101100110000000000101100110000 -00000010010011000000000010110011 -00000000001011001100000000001011 -00110000000000101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000011010110110000000000 -11111011000000000011111011000000 -01001111100000000000101100000100 -00000000110010110000000000111110 -11000000000011001011000000000011 -11101100000000001100101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100000000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11111111000000000010111111000000 -00001111110000000000001111110000 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000001111110100001000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11111111001000000011001111100000 -00001111111110000000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -00111110000000001111111110000000 -00111111111000000000111111110000 -00000011011111100000000011111111 -10000000001111111110000000001111 -11111000000000110011000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10100000000100001110111000000000 -10111111110100000000001011100000 -00001011101110000000001011101110 -00000000101110111000000000101110 -11100000000010111011100000000010 -10101110000000001011101110000000 -00101110111000000000101111110000 -00000010101011100000000010111011 -10000000001011101110000000001011 -10110000000000101010000000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100110000000100 -10110001000001000010000011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010111001000000000010 -00001100000000001011001100000000 -00101100110000000000101100110000 -00000010010011000000000010110011 -00000000001011001100000000001011 -00110000000000100010001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000101011010110000000000 -10111000000010000010001011000000 -00001011101100000000001011101100 -00000000101110110000000000100110 -11000000000110111001110000000010 -10101100000000001011101100000000 -00100110110000000000101110110000 -00000010101011000000000010111011 -00000000001011101100000000001011 -10110000000000101011000000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000101011110110000000000 -11111101000000001011001011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011110000000011 -00101100000000001111101100000000 -00111110110000000000111110110000 -00000011011011000000000011111011 -00000000001111101100000000001111 -10110000000000110000000000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000000011011110000000000 -11110101000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100001000 -00111111110000000000111110110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111111100000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011000000000011101011000000 -00001111101100000000001101101100 -00000000111110110000000000111110 -11000000000011111001000100000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011001011000000000011111011 -00000000001111101100000000001111 -10110000000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10111011000000000010001011000000 -00001001101100000000001001101100 -00000000101110110000000000101110 -11000000000010110001000000000010 -11101100000000001011101100001000 -00101110110000000000101111110000 -00001010001011000000000010011011 -00000000001011101100000000001011 -10110000000000101111001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10110011100100000010100011000000 -00001001001100000000001011001100 -00000000101100110000000000101100 -11000000000010110010000000000010 -11001100000000001011001111000000 -00101100110000000000101110110000 -00000010000011000000000010010011 -00000000001011001100000000001011 -10110000000000101111100000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -01100000000000010001111000000000 -10110111100000000010000111100000 -00001001011110000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110010000 -00101101111000000000101101111001 -00000010000111100000000010010111 -10000000001011011110000000001011 -01111000000000101101100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -01001000000010000000110001000000 -11110001000000000011100011000000 -00001101001100000000001111001100 -00000000111100110000000000111100 -11000000000011110011000000000011 -11001100000000001111001100000000 -00111100110000000000111100110000 -00000011000011000000000011010011 -00000000001111001100000000001111 -00110000000000111101001000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000111011011110000010100 -11110101100000000011111111000000 -00001101111100000000001101111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000100 -00111111110000000000111111110100 -00000011111111000000000011011111 -00000000001111111100000000001111 -11110000000000111101000000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011110110000000000 -11110001011000000011001011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -00101100000000001111001110000000 -00110010110000000000111110110001 -00001011001011000000000011111011 -00000000001111101100000000001111 -10110000000000111110101000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000100011001110000000000 -10110101000010010000000111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -10011100000000001011011100000000 -00110101110000000000101100110010 -00000010000111000000000010110111 -00000000001011011100000000001011 -01110000000000101101001000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000001000000001001111000000100 -10110111100000100000000111100000 -00001011011110000000001011011110 -00000000101101111000000000101101 -11100000000010111111100000000010 -00011110000000001011011110000000 -00100001111000000000101101111000 -00000010000111100000000010110111 -10000000001011011110000000001011 -01111000000000101111000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110011010100001010000011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -10001100000000001011001100000000 -00100100110000000000101100110000 -00000010000011000000000010110011 -00000000001011001100000000001011 -00110000010000101101001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11110110110000000011001010000000 -01001111101000000000001111101000 -00000000111110100000000000111110 -10000000000011111110000000000011 -00101000000000001111101000000000 -00110010100000000000111110100000 -00000011001010000000000011111010 -00000000001111101000000000001111 -10100000000000111111101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000010000 -11111000000010000011111000000000 -00001111100000000000000111100000 -00000000111110000000000000111110 -00000000000011111000100000000011 -11100000000000001111100001000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111101001000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000000000011001001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001100000000011 -00100100000000001111100100100000 -00111110010000000000111100010000 -00000011001001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000100001000110010000000000 -10111001000000000110001001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010110001100000000011 -01100100000000001011100111001000 -00101110010000000000101110010000 -00000010001001000000000010111001 -00000000001011100100000000001011 -10010000000000101110000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000001000010001001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001001000000010 -00100100000000001011100100000000 -00101110010000000000101110010000 -00000010001001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10111001001010000010100001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010111001000000000010 -01000100000000001011000100000000 -00101100010000000000101100010010 -10000010000001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11111000001000001010001000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -00100000000000001111100000000000 -00111110000000000100111110001010 -00001011001000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111011110010000000000 -11111101000000000011011001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011110101000000000011 -11100100000000001111100100000000 -00111110010000000000111110010010 -10000011111001000000000011111001 -00000000001111100100000000001111 -10010010100000111110011000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -10011000000001011110010000000000 -11111101100000001011001001000000 -00001011100100000000001111100100 -00000000111110010000000000111110 -01000000000011111101000000000011 -11100100000000001111110100000000 -00111110010000000000111110010000 -00000000101001000000000011111001 -00000000001111100100000000001111 -10010000000000111110011000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000100001110000000010000 -10111000000000000011011000000000 -00001011100000000000001011100000 -00000000101110000000000000101110 -00000000000010111000000000000010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000010101000000000000010111000 -00000000001011100000000000001011 -10000000000000101100111000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000001011100010000000000 -10110001010000001010000001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001100000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010000001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10111001001000000010011001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000001000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010101001000000000010111001 -00000000001011100100000000000011 -10010000010000101100011000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011110010000001000 -11111001001000100011001001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001010000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011001001000000000011111001 -00000000001111100100000000001111 -10010000000000111110100000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000000011010010000000000 -11110001100000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001101000000011 -11100100000000001111100100001000 -00111110010000000000111100010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000010000000011001000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000010000 -00111110000000000100111110000000 -00001011001000000001000011111000 -00000000001111100000000000001111 -10000000000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00100000000001010010100000000000 -10111010100000001010001010000000 -00001011101000000000001011101000 -00000000101110100000000000101110 -10000000000010111010101000000010 -11101000000000001011111000000000 -00101110100000000000101110100000 -00000010001010000000000010111010 -00000000001011101000000000001011 -10100000010000101100101000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110011100000000010000011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110001000000000010 -11001100000000001011001110000000 -00101100110000010000101100110000 -00000010000011000000000010110011 -00000000001011001100000000001011 -00110000000000101100101000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000000010001110000000000 -10110111010000000010000111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011010000000000 -00101101110000000000101101110000 -00000010000111000000000010110111 -00000000001011011100000000001011 -01110010000000101100100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001111000000000 -11110011100000001011000111100000 -00001111011110000000001111011110 -00000000111101111000000000111101 -11100000010011110111100000000011 -11011110000000001111010010000000 -00111101111000000000111100111000 -00000011000111100000000011110111 -10000000001111011110000000001111 -01111000000000111100101000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000000111100000000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110001000000111100001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11111111100000000011001111100000 -00001111111110000000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001011110010010000 -00111111111000000000111111111000 -10000011001111100000000011111111 -10000000001111111110000000001011 -11111001000000111101000000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110000000000 -10110101000000000010000111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011010000000000 -00101101110000000000101101110000 -00000010100111000000000010110111 -00000000001011011100000000001011 -01110000000100101110101000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -00010000000000001001110000000000 -10110011000000000010000111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011010000000010 -00101101110000000000101100110000 -00000010000111000000000010110111 -00000000001011011100000000001011 -01110000001000101100011000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01100000000101001100110000000000 -10110001001000000010000011000000 -00001011001100000000001011001100 -00000000101100110000000001101100 -11000000000010110011010010000010 -11001100000000001011000000000000 -00101100110000000000101110110000 -00000010100011000000000010110011 -00000000001011001100000000001011 -00110000000000101101100000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -11111000000101011010110000000000 -11111011000000001011001011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011010000000011 -11101100000000001111100000000000 -00111110110000000000111111110000 -00000011001011000000000011111011 -00000000001011101100000000001111 -11110000000000111110111000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000100000000001110110000000000 -11111011000000010011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111100001000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001011101100000000001111 -10110000000000111110000000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001111110000000000 -11110111000000000011001111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111100000000011 -11111100000010001111110000000000 -00111111110000000000111111110000 -00000011001111000000000011111111 -00000000001111111100000101001111 -11110000000100111110000001100100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000001000001000110110000001000 -10111011000000000000101011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011100000000010 -11101100000000001011100011100000 -00101110110000000000101110110000 -00000010101011000000000010111011 -00000010001011101100000000001011 -10110000000000101110000001000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000000000010001011000000 -00001011101100000000001011101100 -00000000101110110000000000101010 -11000000000010111011000100000010 -11101100000000001011100010000000 -00101110110000000000101110110000 -00000010001011000000000010111011 -00000000001011101100000000001011 -10110000000000101110000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10110001000000000010100011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000011011000000000000 -00101100110000000000101100110000 -00000010100011000000000010110011 -00000000001011001100000000001011 -00110000000000101100001000000101 -00000000000000000000000000000000 -00000000000000000000000000000000 -10000000000011010110110000000000 -11111011000000001011001011000000 -00001111101100000000001111101100 -00000000111110110000000000111010 -11000000000011111011000000000011 -11101100000000001111100000000000 -00111110110000000000111110110000 -00000011001011000000000011111011 -00000000001111101100000001001111 -10110000000100111110000000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011111110000010000 -11111101000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000000111110000000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000011111111100000000001111 -11110000000000111110100000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000011011111111000000000 -11101111100000000011111111100000 -01001111111110000000001100111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111011000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000000001110111000000000 -10111011100000000010111011100000 -00001011101000100000001000101110 -00000000101110111000000000101110 -11100000000010111011100000000010 -11101110000000001011101100000000 -00101110111000000000101110111000 -00000010111011100000000010111011 -10000000001011101110000000001011 -10111000000000101111000000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -11001000000001011100110000000000 -10100011000000000010110011000000 -00001011000100001000111001001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001010 -00110000000000101011001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010110000000000 -10111011000000000110111011000000 -00001011000100001000001001101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000010000101111000000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10010000000101011110110000000000 -11101011000000000011111011000000 -10001111100100010000001101101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001011101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111000100000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11111111000001000011111111000000 -00001111110000000001001110111100 -00000100111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111111100000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01010000000100001010110000000000 -11101011000000000011111011000000 -01001111100101100000101100101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000110001010100000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10111011000010000000111011000000 -10001011101101000000001000101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10111000000000100011001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000001000 -10110011111001000000110011000000 -00001011001100010000001001001100 -00000000001100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110011000000100011000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -11110000000000010001111000000100 -10110111100000000010110111100000 -00001011011010010000011001011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000010100011110000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01001010000000000000110000000000 -11110011000000000011110011000000 -10011111101100010110001101001100 -00000000111100110001000000111100 -11000000000011110011000000000011 -11001100000000001111001100000000 -00111100110000000000111100110000 -00000011110011000000000011110011 -00000000001111001100000000001111 -00110000000000110001101000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000101011011110000000000 -11111111000000000011111111000000 -00001111111000010000001110111100 -00000000111111110000010000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -01110000000001111101000000000110 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011110110000000000 -11111011000000000011111011000000 -00011111100111001000001100101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11001000100100011001110000000000 -10110111000000000010110111000000 -00001011110100000000001000011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101111001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001001111000000000 -10110111100000000010110111100000 -00001010010110000001001000011110 -00000000101001111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010100111 -10000000001011011110000000001010 -01111000000000101100100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110011000000000010110011000000 -00011011001100110000001000001100 -00010000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101101001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11100000000101011010100000000000 -11111010000000000011111010000000 -00001110101000000000101100101000 -00000000111010100000000000111110 -10000000000011111010000000000011 -11101000000000001111101000000000 -00101110100000000000111110100000 -00000011111010000000000011101010 -00000000001111101000000000001110 -10100000000000101111101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000100000000111101001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000000000011101001000000 -00001111101100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000110000001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10110001000000000010001001000000 -00001011100110010000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -00010000100000101010000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001010000000010001001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000100000011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001000000000010000001000000 -10001011001100000000001011000100 -00000000100100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101000001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000011010110000000000100 -11111000000000001011101000000000 -00001111100001010000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000110010111000000111 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100110101000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110111100000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -10011000000001011110010000000001 -11111101000000001011001001000000 -00001111110100000000001100100100 -00000000111110010000000000111110 -01000000000111111001000000000011 -11100100000000001111100100010000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -11010000000000111110111000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -01111000000100001110000000000000 -10111000000000000010001000000000 -00001011000000000000001000100000 -00000000101110000000000000101110 -00000000000011111000000000000010 -11100000000000001011100010100000 -00101110000000000000101110000000 -00000010111000000000000010111000 -00000000001011100000000000001011 -10000000000000101100011000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -01001000000001011100010000000000 -10110001000000000010010001000000 -00011011000100000000011001000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100100000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000001101101001000000001 -01100000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000000001 -10111011000000000010011001000000 -00001011001100000000001001100100 -00000000101110010000000000101110 -01000000000010101001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000010011011 -10010000000000101100011000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011110010000000000 -10111001000000100011011001000000 -01001111100111110000101101100100 -00000000111110010000000000111110 -01000000000010111001000000000011 -11100100000000001011100100000000 -00111110010000000000101110010000 -00000011111001000000000011111001 -00000000001111100100000000001011 -10010000000000111110000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01101000000000011010010000000000 -11111001000000000011101001000000 -00001111100110000000001110100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000100000111101101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000001000011111000000000 -00001111100000011000001100100000 -00000000111110000000000000111110 -00000000000011111000000001000011 -11100000000000001111100000000000 -00110010000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010010100000000000 -10110110000010010010111010000000 -00001011111010000000001000101000 -00000000101110100000000000101110 -10000000000010111010000000000010 -11101000000000001011101000000000 -00101010100000000000111010100000 -00000010111010000000000010111010 -00000000001011101000000000001011 -11101100000000101100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110000000000000010110011000000 -00001011001111000000001001001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00100000110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00111000000000101100001000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000000010001110000000000 -10110101000000000010110111000000 -00001011010000000000001001011100 -00000000101101110000001000101101 -11000000000010110111000000000010 -11011100000000001011011110000000 -00101001110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01100000100000101100100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001111000000000 -11110100100000000011110111100000 -01001111011110000000101101011110 -00000000101101111000000000111101 -11100000000011110111100000000011 -11011110000000001111111110000000 -00110001111000000000101101111000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01111000000000111100001000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111000000000000011111011000000 -10001111101000000000001110101100 -00001000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111010110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000001011111111000000000 -11111110100000000011111111100000 -00011111011110000000001110111110 -00000000111111111001000000111111 -11100100000001111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000101101100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110000000000 -11100111000100000010110111000000 -00001011010100100000001101011100 -00000000101101110000000000111101 -11000000000011110111000000000010 -11011100000000001011011100000000 -00101101110000000000111001110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01000000000000101110101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00010000000000001001110000000000 -10110110000000000010110111000000 -00001010111100000000001011011100 -00000000101101110000000100101101 -11000000000110110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001010 -01100000000000101100010000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01101000000101001100110000000000 -10100010000000000010110011000000 -00001011100000000000001000001100 -00000000101100110000000000101000 -11000000000010100011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000000011 -00000000000000101101000100000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10111000000101011010110000000000 -11111000000000000011111011000000 -00001110101100001000001011101100 -00001000111110110000000000101110 -11000000000010111011000000000011 -11101100000000001111111100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10010000000000101110001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11101001010000000011111011000000 -00001111100000001000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111010110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10000000001100111110010100000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001111110000000000 -11111100001000000011111111000000 -00001111110110000000001100111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11011000000000111110000001000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000000000110110000000000 -10111001110000000010111011000000 -00001011100001000000001111101100 -00000000101110110000000000101110 -11000000000011001011000000000010 -11101100000000001011111100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10010000000000101110000001100000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010110000001000 -10111010000000000010111011000000 -01001011101000100000011000101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110010000000101110100000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000000001 -10110001000000000010110011000000 -00001011000000000000101001001100 -00000000101100110000000000100100 -11000000000010000011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00000000000000101100101000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -10000000000011010110110000000000 -10111010000000000011111011000000 -00001111101100000000001100101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10100000000000111110000000000010 -00010000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11111101000000000011111111000000 -00001111110000000000001110111100 -00000000111111110000000000111111 -11000000000011101111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000001001111 -11000000000000111110100000100110 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000011011111111000000000 -11111111100000000011111111100000 -00001111111110000000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111110000000000110011111000 -00000011010100100000001011001111 -10000000001111111100000000001111 -11111000000000111111000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000000001110111000000000 -10111011100000000010111011100000 -00001011101110000000001110101110 -00000000101110111000000000101110 -11100001000010111011100000000010 -11101110000000001011101110000000 -00101111110000000000101000110000 -00000010001000100000000010001011 -10000000001011111110000000001011 -10111000000000101111000000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11001000000001011100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000100100110000 -00000010110010000000000010000011 -00000000001011001100000000001011 -00110000000000101111001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010110000000000 -10111011000000000010111011000000 -00001011101100000000001010101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000010 -00101110110000000000101110110000 -00000010111010000010000010001011 -00000000001011101100000000001011 -10110000000000101111000000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000100000101011110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000110110110000 -00000011111000010000000011001011 -00000000001111101100000000001111 -10110000000000111100000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111100110000000000111011110000 -01000011001101100100000011111111 -00000000001111101100000000001111 -11110000000000111111110000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000010110010110000 -00000011111010000000000011011011 -00000000001111101100000100001110 -10110000000000111101010000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11011000000000010010110000000000 -10111011000000000010111011000000 -00001110101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000010000010 -11101100000000001011101100000000 -00101111110000000000100010110000 -00000010000011000000000010001011 -00000000001011111100000000001000 -10110000000000101111001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10110011000000000010110011000000 -00001001001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011100000000010 -11001100000000001011001100000000 -00101100110000000000100010110000 -00000010100001000000000010010011 -00000000001011001100000000001010 -00110000000000101111000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -11110000100000010001111000000100 -10110111100000000010110111100000 -00001010011110000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000100001111001 -00000010001101100000000010000111 -10000000001011011100000000001000 -01111000000001101111110000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01001000000000000000110001000000 -11110011000000000011110011000000 -00001111001100000000001111001100 -00000000111100110000000000111100 -11000000000011110011000000000011 -11001100000000001111001100010000 -00111100110000000000110000110000 -00000011100001000000000011010011 -00000000001111001100010000001110 -00110000000000111101001000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000101011011110000000000 -11111111000000000011111111000000 -00001110111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000010 -11111100000000001111111100000000 -00111111110001000000111111110000 -01000011101101000000000011111111 -00000000001111111100100000001111 -11110000000000111101000000000110 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011110110000000100 -11111011000000100011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110111010100000110010110000 -00000011001010000000000011111011 -00000000001111101100110000001100 -10110000000000111100001000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11001000100100011001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110100000000101001110000 -00000010000111000000000010110111 -00000000001011001100010000001010 -01110000000000101111001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000001000000001001111000000000 -10110111100000000010110111100000 -00001011011110000000001010011110 -00000000101001111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101110000000000100001110000 -00000010000110100000000010110111 -10000000001011011110100000001000 -01111000000000101100100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000100101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001001001100000000 -00101100110000000000101000110000 -00000010000011110000000010110011 -00000000001011001100000000001010 -00110000010000101101101000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11100000000101011010100000001000 -11111010000000000011111010000000 -00001111101000000000001111101000 -00000000111110100000000000111110 -10000000000011111010000000000011 -11101000000000001111101000000000 -00111110100000000010110010100000 -00000010001110101000000010111010 -00000000001111101000000000001000 -10100000000000101111101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000010 -00111100000000000010111110000100 -00000011111000001000000011111000 -00000000001111000000000000001111 -10000000010000111101001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000000000011111001000000 -00001101100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001100000000011 -11100100000000001111100100000000 -00111110010000000000110110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000001000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001100000000010 -11100100000000001011100100000000 -00101110010000000000110110010110 -00000010111001000000000010111001 -00000000001011100100000000001000 -10010000000000101110100000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001001000000010 -11100100000000001011100100000000 -00101110010000000000100110010000 -00000010111001000000000010111001 -00000000001011100100000000001010 -10010000000000101100011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000110 -11000100000000001011000100000000 -00101100010010100010100100010000 -00000010110001000000000010110001 -00000010011011000100101000001000 -00010000000000101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000101110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111100001010000000110110000000 -00000011111000000000000111111000 -00000000001111100000100100011110 -10000000001001111110111000000111 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000001 -11100100000000001111100100000010 -00111110011010100000111100010010 -10000011111101000000000011111001 -00000000001111100100000000001110 -10010000000000111110011000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -10011000000101011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111101000000000011 -11100100000000001111100100000000 -00111110010000000000110011010000 -00000011001101000000000011111001 -00000000001111100100000000001111 -10010000000000111110111000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -01111000000010001110000000000000 -10111000000000000010111000000000 -00001011100000000000001011100000 -00000000111110000000000000101110 -00000000000010111000000000000010 -11100000000000001011100000000000 -00101110000000000000100010000000 -00000010001000000000000010111000 -00000000001011100000000000001011 -10000000000000111100111000000010 -00110000000000000000000000000000 -00000000000000000000000000000000 -01001000000001011100010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000010100000010000 -00000010010001000000000010110001 -00000000001011000100000000001011 -00010000000000101101001000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00011000000001011010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101010010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000100010010000 -00000010011001000000000010111001 -00000000001011100100000000001011 -10010000010000101000011000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10100000000001011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000101110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000110010010000 -01000011011001100100000011111001 -00000000001111100100000000001011 -10010000000000101110100000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -01101000000000011010010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011101001100000000011111001 -00000000001111100100000000001111 -10010000000000111101101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000000001010000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000110010000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00100000000001010010100000000000 -10111010000000000010111010000000 -00001011101000000000001011101000 -00000000101110100000000000101110 -10000000000010111010100000000010 -11101000000000001011101000000000 -00101110100000000000110101100000 -00000010111010000000000010111010 -00000000001011101000000000001011 -10100000000000101100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110001100000000110 -11001100000000001011001100000000 -00101110110000000000100000000000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100001100000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000100010001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000010000010 -11011100000000001011011100000000 -00101101110000000000100101001000 -00000010110111000000000010110111 -00000000001011011100000001001011 -01110000000000101100100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -10101000000000000001111000000000 -11110111100000000011110111100000 -00001111011110000000001111011110 -00000000101101111000000000111101 -11100000000011110111100000000011 -11011110000000001111011110000000 -00111111111100000000110001010000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01111000000000111100101000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000101011010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000100001111101100000000 -00111110110010100000111110010000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111001000000 -11111111100000000011111111100000 -00001111111110000000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111011001000 -00000011000111100000000011001111 -10000000001111111110000000001100 -11111001000000111101100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000001 -00101101110000000000100001000000 -00000011010111000100000011010111 -00000000001011011100000000001101 -01110000001000101110101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00010000000000001001110000001000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101001010000 -00000010001111000000000010000111 -00000000001011011100000000001000 -01110000001000001100010000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01100000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101110110000000000100010010000 -00000010010011000000000010010011 -00000000001011001100000000001001 -00110000000000101101000000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011110011000000000011 -11101100000000001111101100000000 -00111111110000000010111010100000 -00000011001011010000000011001011 -00000000001111101100000000001000 -10110000000000111110111000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10010100000000001110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000010011 -11101100000000001111101100000000 -00111110110000000000111110100000 -00000011111011001000000011111011 -00000000001111001100000100001111 -10110000000000111110100000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001111110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -00111100000000001111111100000000 -00111110110000000000110011110001 -00000011001111000000000011111111 -00000000001111101100000000001100 -11110000000000111110000001000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011100000000010 -00101100000000001011101100000000 -00101110110000000000100010110000 -01000010101011000000000010111011 -00000000001011101100000000001010 -10110000000000101110010001100000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000100000010 -00101100000000001011101100000000 -00101110110000000000100010100000 -00000010001011000000000010111011 -00000000001011101100000000001000 -10110000000100101110000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -00001100000000001011001100000000 -00101100110000000000100000100000 -00000010100011000000000010110011 -00000000001011001100000000001010 -00110000000000101100001000000100 -00000000000000000000000000000000 -00000000000000000000000000000000 -10000000000011010110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -00101100000000001111101100000000 -00111111110000000000110000110000 -00010011001011000001000011111011 -00000000001111101100000000001100 -10110000000000111110000000000010 -00010000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000010011111111000000000011 -11111100000000001111111100000010 -00111111110000000010111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111110100000100100 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000011011111111000000000 -11111111100000000011111111100000 -00001111111110000000011111111110 -01000000111111111000000000110011 -11100000000011111111110000000011 -00111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111111000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10000000000010001110111000000000 -10111011100000000010111011100000 -00001011101110000000001011101100 -10000000101110111000000000101010 -11100000000010111011000000000011 -01101110000000001011101110000000 -00101110111000000000101110111000 -00000010111011100000000010111011 -10000000001011101110000100001011 -10111000000000101111000000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10110011000000000010110011000000 -00001011001100000000011011001100 -00000000101100110000000000100000 -11000000000010110011001000000010 -00001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001010 -00110000000000101011001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011010110000000000 -10111011000000000010111011000000 -00001011101100000001001011101100 -00000000101110110000000000101010 -11000000000010111011000000000010 -01101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000010000101111100000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000101011110110000000000 -11111011000000000011111001000100 -00001111101100000000001011101100 -00000000111100110000000000110010 -11000000000011110011000000000011 -00101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000100111100100000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11111111000000000011111101100000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111111100000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011000000000011111001010000 -00001111101100000000001111101100 -01000000111110110000000000111110 -11000000000011111011001000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111101010000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10111011000000000010111011000010 -10001011101100000000001011101111 -01000000101110110110000000101110 -11000000000010111011101000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11000000000001000100110000000000 -10110011000000000010110010100000 -00001001001100000000001011001100 -00000000101100110010000000101100 -11000000000010110011010000100010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101111001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01100000000000000101111000000000 -10110111100000000010110111000000 -00001011011110000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101111110000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01001000000000000100110000000000 -11110011000000000011110010010100 -00001101001100000000001111001100 -00000000111100110000000101111100 -11000000010011110011000000000011 -11001100000000001111001100000000 -00111100110000000000111100110000 -00000011110011000000000011110011 -00000000001111001100000000001111 -00110000000000111101101000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000101011011110000000000 -11111111000000100011111110000000 -00001111111100000001001111111100 -00000000111111110000000101111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111101000000000110 -00100000000000000000000000000000 -00000000000000000000000000000000 -00001000000101011110110000000000 -11111011000000000011111010100000 -00011101101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100101000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000000011001110000000000 -10110111000000000010110111000000 -00001000011100000000001011011100 -00000001101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101111001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -00100000000100001001111000000000 -10110111100000000010111101100000 -01001000011110000101001010011110 -00010000101001111000000000101101 -11100000010010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101100000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01101000000101001100110000000000 -10110011000000000010110011000000 -00001000001100000000001011001100 -00000100101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101101001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011110100000000000 -11111010000000000011111110101100 -00001101101000000000001111101000 -00000000111110100000000000111110 -10000000000011111010000000000011 -11101000000000001111101000000000 -00111110100000000000111110100000 -00000011111010000000000011111010 -00000000001111101000000000001111 -10100000000000111111101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000011010000000000000 -11111000000000000011111000000000 -00001111100000000000001111100001 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111101001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001010010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -10000000110010010100000000111110 -01000000000011111001001000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000000000010111001100000 -00001011100100000000001011100100 -00100010100010011100000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101110100000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00111000000001010010010000000000 -10111001000000000010111001000100 -00001011100100000000001011000100 -00000000100010010000000000101110 -01000000000010111001000010000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001000000010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000100000110000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000001010110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100001 -01000000110010000000000000111110 -00000000000011111000010100000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111110011000000111 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000101011110010000000000 -11111001000000000011110111000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110011000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -10011000000101011010010000000000 -11111001000000000011111101000000 -00001111100100000000001111110100 -00000000111111010000000000111110 -01000000000011111101000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110111000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000100001110000000000000 -10111000000000000010111000000000 -01001011100000000000001110000000 -00000000111110000000000000101110 -00000000000010111000000000000010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000011101000000000000010111000 -00000000001011100000000000001011 -10000000000000101100011000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000001001000010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000010010110001000000000110 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101101001000000001 -00100000000000000000000000000000 -00000000000000000000000000000000 -00011000000000000010010000000000 -10111001000000000010111001000000 -00001011100100000000001010101100 -00000001101010010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010101001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10100000000001011110010000000000 -11111001000000000011111001110000 -00000111100100000000001111100100 -00000000101110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000101110100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000011010010000000000 -11111001000000000011111001110000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011101001000000000011111001 -00000000001111100100000000001111 -10010000000000111101001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00001000000000001010000000000000 -11111000000000000011111000010000 -00001111100000000000001111100000 -00000000110110000000000000111110 -00000000010011111000100000001011 -00100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000101010010100000000000 -10111010000000000010111010100000 -00001011101000000100001011111011 -00000000110111101000000000101110 -10000000000010111110000000000010 -00101000000000001011101000000000 -00101110100000000000101110100000 -00000010111010000000000010111010 -00000000001011101000000000001011 -10100000000000101100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001101 -00100000100000111000000000101100 -11000000000010110011000100000010 -01001100000000001010001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100001100000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10000000000100010001110000000000 -10110111000000000010110101010000 -00001011011100000000001011011011 -00000000100101110000100000101101 -11000000000010110101100000000010 -01011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101100100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -10001000000010000001111000000000 -11110111100000000011110111100000 -00001111011110000000001111011110 -00000000110001101000000000111101 -11100000000011111111100000000011 -01011110000000001110011110000000 -00111101111000000000101101111000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01111000000000111100101000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001011010110000000000 -11111011000000000011111001000000 -00001111101100000000001111100000 -00000000111110000000000000111110 -11000000000011111011000000000011 -10101100000000001101101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000011111 -10110000000000111100001000000010 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000001001011111000000000 -11111111100000000011110111100000 -00001110111110000000001111111110 -00000000110001011000000000110011 -11100000000010111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111101100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000110001001110000000000 -10110111000001000010110111000100 -00011000011100000000001110111000 -00000000101001110000000000110101 -11000000000010110100001000000010 -11011100000000001011011100000000 -00101101110000000000111001110000 -00000011110111000000000010110111 -00000000001011011100000000001111 -01110000000000101110001000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00010000000000001001110000000000 -10110111000000000010110101000000 -00001010011100000000001011011100 -00000000100001000000000000100001 -11000000000010110101000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101000011001000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01100000000001001000110000000000 -10110011000000000010110001110000 -00001000001100000000001010101000 -00000000101000000000000000100100 -11000000000010111001000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010100011000000000010110011 -00000000001011001100000000001010 -00110000000000101101000000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011010110000000000 -11111011000000000011110011000010 -00001110101100000000001111100100 -00001000110010110000000000110010 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000010111011000000000010111011 -00000000001111101100000001001011 -10110000000100111110111000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000100000000001110110000000000 -11111011000000000011111011000000 -00001111101100000000001111100101 -00000100111110100100000000111110 -11000000000011111001010000000011 -11101100000000001111101100000000 -00111110110000000000111010110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000001100111110100000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10100000000100001111110000000000 -11111111000000000011111111110010 -00001100111100000000001111111000 -01000000110011110000010000110011 -11000000000011111111100100001011 -00111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111110000001000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10100001000001000110110000000000 -10111011000000000010111011100000 -00001010101100000001001011100000 -00000000100000000110000000101010 -11000000000011111001000000000010 -00101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000011101011 -00000000001011101100000000001011 -10110000001000101110000001000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000000000010111011000000 -00001000101100000000001011100100 -00000000100010010000000000101010 -11000000000010111011000010000010 -00101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101110000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00001000000101000000110000000000 -10110011000000000010111011000000 -00001010001100000100001011000000 -00000010100000100000000000101000 -11000000000010100001000000000010 -00001100000000001011001100000000 -00101100110000000000101100110000 -00000010010011000000000010110011 -00000010001011001100000000001001 -00110000000000101100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -10000000000011010110110000000000 -10111011000000000011111011000000 -00001100101100000000001111100100 -00001000110010010000000000111010 -11000000000010111011000000000011 -00101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110000000000110 -00010000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011111110000000000 -11111111000000000001111111000000 -00001111111100000000001111110000 -00000000111111000000000000111111 -11000000000011111101000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011101111 -00000000001111111100000000001111 -11110000000000111110100000100110 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000011011111111000000000 -11111111100000000011111111100000 -00001111111110000000001101111110 -00000000111111111000000000111111 -00000000000011001100000000000011 -11110000000000001100110000000000 -00110011000000000000110011000000 -00000011111101000000000011001111 -10000000011111111110000000011111 -11111000000000111011000000000001 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000000001110111000000000 -10111011100000000010111011100000 -00001011101100000000001000101110 -00000000101110111000010000101110 -00000001000010001000100000000010 -11100000000000001100100010000000 -00100010001000000000100010001000 -00000010111001100000000010001011 -10000000001011101110000000001011 -10111000000101101111000000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -11001000000001011100110000000000 -10110011000000000010110011000000 -00001011001100000000001001001100 -00000000101100110000000000101100 -01000000000010010001000000000010 -11000000000000001001001000000001 -00100100000000000000100000000000 -00000010110001000000000010010011 -00000000001011001100000000001011 -00110000000000101111001000000001 -00110000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010110000000000 -10111011000000000010111011000000 -00001011001100000000001001101100 -00000000101110110000000000101110 -01000000000010011001000000000010 -11100000011000101000101000000000 -00100110000000000000100010000000 -10000010111001000010000010011011 -00000000001011101100000000001011 -10110000010001101111000000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10010000000101011110110000000000 -11111011000000000010111011000000 -00001111101100000000001101101100 -00000000111110110000000000111110 -10000000001011011000000100010011 -11100011000000101101100100000000 -10110110011000000010110010000101 -00010010111001010100001011011011 -00000000001011101100000000001011 -10110000000000111000100000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11111111000000000011111111000000 -00001111111100000000001110111100 -00000000111111110000000000111101 -10000000000011101000100000000011 -11100010000000001111110100000000 -00111011011001000000111110001000 -00000011110001100000000011101111 -00000000001111111100000000001111 -11110000000000111111100000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011000000000011111011000000 -00001111101100000000001110101100 -00000000111110110000000000111110 -11000000000011101001001000000011 -00000001000000101100001100000000 -00110100010000000000110010000100 -00000011001001010000000011001011 -00000000001111101100000000001111 -10110000001000111101010000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11011000000001010010110000000000 -10111011000000000010111011000000 -00001011101100000000001000101100 -00000000101110110000000000101110 -11000000000010001001011000000010 -00100000000000001101101100000100 -00100010011100100010100010000000 -00001010001001000000000010001011 -00000000001011101110010000001011 -10110000010000101111001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000001000 -10110011000000000010110011000000 -00001011001100000000001010001100 -00000000101100110000000000101100 -00000000000010100010110000001010 -00001100000000001000000010000100 -00100000101100100000100000110000 -00001010000010000000001010000011 -00000000001011001101000000001011 -00110000000001101111001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -11110000000000010001111000000000 -10110111100000000010110111100000 -00001011011110000000001000011110 -00000000101101111000000001101101 -00100000000010000110100000000010 -00011110000000101001010010001000 -00100000101001000000100001111001 -00000010000110100000000010010111 -10000000001011011110001000001011 -01111000000000101111110000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01001000000000000000110000000100 -11110011000000100011110011000000 -00001011101100000000001110001100 -00000000111100110000000000111110 -01000000000011100011000000000011 -00001100000000001100001000000000 -00110100100001000000100000110001 -00000011000010000000000011000011 -00000000001111001100000000001111 -00110000000000111101101000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000100101011011110000000000 -11111111000000000011111111000000 -00001111111100000000001110111100 -00000000111111110000000000111111 -01000000000011111111000100000011 -11111100010000001111011000010000 -10111111100001000000111111110001 -00000011111110100100000011101111 -00000000001111111100000000001111 -11110000000000111101000000000110 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -10000000000011011010000000000011 -00101110000000001100100100000000 -00110010110000000000110010111000 -00000011001010000000000011011011 -00000000001111101100000000011111 -10110000000000111100001000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11001000100100011001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101111 -10000000000010000110000000000010 -00001100000000001000010100000000 -00110001110000000000100000110000 -00000010000010000000010110000111 -00000000001011011100000000001011 -01110000000000111011001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000001000000001001111000010000 -10110111100000000010110111100000 -00001011011110000000001011011110 -00000000101101111000000000101101 -11100000000010010011100000000010 -00011110000000001000001110000000 -00100000111000000000100101111000 -00000010000110100000000010000111 -10000000001011011110000000001011 -01111000010000101100100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000100000010000011000000000010 -00001100000000001000001100000000 -00100000110000000000100000110000 -00000010000010000000000010000011 -00000000001011001100000000001011 -00110000000000101001001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11100000000101011010100000000000 -11111010000000000011111010000000 -00001111101000000000001011101000 -00000000111110100000000000111110 -10100000000011011010000000001011 -00101000000000101100101001000000 -10110010100100000010110110100000 -00001011001110000000001011001010 -00000000001011101000000000001011 -10100000000000101111101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000010000111100 -00000000000011110000010000000011 -11100000000000001111100000001000 -00111000000000100000111110000000 -00000011110100000000000011111000 -00000000001111100000000000001111 -10000000000000111001001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011001001010000000011 -00100100000000001111000100000000 -00110010010000000000110010010000 -00000011111001000000000011001001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10000010000001000110010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000010010001001111000000010 -00100100000000001011100100000000 -00100010010000000000100010010000 -00100010111001000000000010001001 -00000000001011100100000000001011 -10010000000000101110000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010011001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010001101000000000010 -00110100000000001011110100100000 -00100011010101000000100011010000 -00000010111101000000000010001001 -00000000001011100100000000001011 -10010000000000101100011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000100100010000000000101101 -01001011001010000101001010001010 -00010100101000001011010100101000 -10100001010010100000100001010010 -10000010110101001010000010000001 -00000000001011000100000000001011 -00010000000000101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00001000000011001000001000000011 -00100000100000001111100000100000 -00110010000010000010110010000010 -00000011111100001000001011001000 -00000000001111100000000100011111 -10000000000000111110111000000111 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111011110010000000000 -11111001000000000011111001000000 -00001111100100101000001111100100 -00000000111110010000000000111110 -01101010000011111001000000000011 -11100110101000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000001111110111000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -10011000000001011110010000000000 -11111001000000000011111001000000 -00001111100100000000001110100100 -00000000111110010000000000111110 -01000000000011010101000000000011 -11100100000000001100110100000000 -00110011010000000000110010010000 -00000011111001000000000011111001 -00000000001111110100000000001111 -10010000000000111110111000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01111000000100001110000000000000 -11111000000000000010111000000000 -00001011100000000000001011100000 -00000000101110000000000000101100 -00000000000011011000000000000010 -11000000000000001100100000000000 -00100010000000000000110110000000 -00000010111000000000000110111000 -00000000001011100000000000001111 -10000000000000101100011000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -01001000000001011100010000000000 -10110001000000000010110001000000 -00001011000100000000001010000100 -00000000101100010000000000101100 -01000000000010010001000000000010 -11000100000010001001000100000000 -00100000010000000000100000010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101101001000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10101001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101100 -01010000000010011001010000000010 -11100100000000001000100100100000 -00100010010000000000100110010000 -00000010111001000000000010111001 -00000000001011100100000000001010 -10010000000000101100011000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011110010000000000 -10111001000000000010111001000000 -00001111100100000000001110100100 -00000000111110010000000000111110 -01000000000011011001000000000011 -11100100000000101101100100000000 -10110010010000000000110010010000 -00000011111001000000000010111001 -00000000001111100100000000001011 -10010000000000111110100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01101000000000011010010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000011111100100000000001111 -10010000000000111101101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000000000011101000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011001000000010000011 -01100000000000001100000000000000 -00111110000000100000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001110 -10000000000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00100000000001010010100000000000 -10111010000000000010111010000000 -00001011101000000000001011101000 -00000000101110100000000000101110 -10000000000010001110010000000010 -00101000000000001000101010000000 -00101101101100000000101110100000 -00000010111110000000000010111010 -00000000001011111000011000001000 -10100000000000101100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110011000000000010100011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010000001010100000010 -00101100000000001000001110000000 -00101100111100000000101100110000 -00000010110010000000000010110011 -00000000001011001111000000001010 -00110000000000101100001000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000000010001110000000000 -10110111000000000010110111000000 -00001011011100100000001011011100 -00000000101101110000000000101101 -11000000000010000110100000000010 -00011100000000001000010100001000 -00101101000000100000101101110000 -00000010110110000000000010110111 -00000000001011011110000000001000 -01110000000000101100100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001111000000000 -11110111100000000011100111100000 -00001111011110110000001111011110 -00000000111101111000000000111101 -11101000000011000110100000000011 -01011111000000101100010110000000 -00111101001000000000111101111000 -00000011110110100000000011110111 -10000000001111011110000000001110 -01111000000100111100101000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111011000000000011111011000000 -00001111101101110000001111101100 -00000000111110110000000100111110 -11001100011011111010000000001011 -11101100100000001111100100000000 -00111110000000000000111110110000 -00000011111010000000000011111011 -00000000001111001100000000001111 -10110000000000111100001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111001000000 -11111111100000000011111111100000 -00001111111110000000001100111110 -00000000111111111000000000111011 -11110000000011000110100000100011 -00111111000001001111110110000010 -00110011001000000000111111111000 -00000011001110100100001011001111 -10000000001111111110000000001111 -11111000000000111101100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110000000000 -10110111000000000010110111000000 -00001011011100000000001101011100 -00000000101101110000000000111011 -11001000000011010110011000000010 -00111100000000001010010100000000 -00100001000100000000101101110000 -00000010000110000000000010000111 -00000000001011010000000000011011 -01110000000000111110101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00010000000000001001110000010000 -10110111000000000010110111000000 -00001011011100000000001001011100 -00000000101101110000000000101001 -11000000100010000110000000000010 -00011100000000001011010100000000 -00100001000000000000101101110000 -00000010000110010000100110000111 -00000000001011011100000000001011 -01110000000000101100010010000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01100000000101001100110000000000 -10110011000000000010110011000000 -10001011101100000000001001001100 -00000000101100110000000000101010 -11000000001010010010000000001010 -00001100000000001010000100000000 -00100000000000000000101100110000 -00000010000010100000000010000011 -00000000001011000000000000011011 -00110000000000101001100100000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010110000000000 -11111011000000000011111011000000 -00001111111100000000001001101100 -00000000111110110000000000111011 -11000000000010001010000000000011 -00111100000000101111100100000000 -10110010000000000000111110110000 -00001010001010011000000010001011 -00000000001111100000000000001011 -10110000000000101110111000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10010100000000001110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011110010010000000011 -11101100000000001111000100000000 -00111110000100000000111100110000 -00000011110010000000000011111011 -00000000001111100000000000001111 -10110000000000111110000000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001111110000000000 -11111111000000000011111111000000 -00011111111100000000001100111100 -00000000111111110000000000111111 -11000000000011001110001000000011 -00111100000000001110100100010000 -00110001000000000000110010110000 -00000011001010000000000011001111 -00000000001111110010000000001100 -11110000000000111110010001000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110110000000000 -10111011000000000010111011000000 -00001011101100000000001010101100 -00000000101110110000000000100110 -11000000000011011010110000000010 -00101100000000001101100100000000 -00100010001100000010100010110000 -00001010001010000000000010001011 -00000000001011000001000000001010 -10110000001000101110000001000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000000000010111011000000 -00001011101100000000011000101100 -00000000101110110000000000100110 -11000000000010001010000000000010 -00001100000000001010100100000000 -00100010001000000000100010110000 -00000010101010000000000010001011 -00000000001011101101100000001000 -10110000000000101110000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10110011000000000010110011000000 -00001011001100000000001010001100 -00000000101100110000000000100100 -11000000000010010010000000000010 -00001100000000001001000100000000 -10100000000000000010100000110000 -00011010100010000000000010000011 -00000000001011000000000000000010 -00110000000000101100101000000100 -00000000000000000000000000000000 -00000000000000000000000000000000 -10000000000011010110110000000000 -10111011000000000011111011000000 -00001011011100000000001100101100 -00000000111110110000000000110111 -11000000000011001010000000001011 -00111100000000101110100100000000 -00110010000000000000110010110000 -00010011101010000000001011001011 -00000000001111101100000000001100 -10110000000000111110000000100010 -00010000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000110111 -11000000000011111110000000000011 -11111100000000001111110100000010 -00111111000000000000111111110000 -00000011011110000000000011111111 -00000000001111110000000000001111 -11110000000100111110100000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11111100000000000011001111100000 -00001111111110000000001111111110 -00000000111111111000000000111111 -11100000110011111110100001000011 -00111110000000001111111110000000 -00111111111000000000110111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111111000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001110111000000000 -10111000110000000010001011100000 -00001011101110000000001011101110 -00000000101110111000000000101110 -11100000100010111001100000000010 -00101110000000001011101110000000 -00101110111000000000101110111000 -00000010111011100000000010111011 -10000000001011101110000000001011 -10111000000000101111000000000110 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10110000010000001010000011000000 -00001011001100000000001011001100 -00000000101000110000000000101100 -11000000000010111011000000000010 -00001100000010001011001100000000 -00101100110000000000100100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101111001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010110000000000 -10111000000110000010001011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011100000000010 -00101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000000011101100000000001011 -10110000000000101111000000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000101011110110000000000 -11111100110000000011001011000000 -00001111101100000000001111101100 -00000000111010110000000000111110 -11000000000011111010100000000011 -00101100000000001111101100000000 -00111110110000000000110110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111101010000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11110000100000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111111100000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111010011000001011001011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011001000000011 -10101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111101010000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010010111000000000 -10111000010000000110001011000000 -00001011101100000000001011101100 -00000000101110110000000000001110 -11000000000010110011000000000011 -01101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10110011100100000010000011000000 -00000011001100000000001011001100 -00000000101100110000000000001100 -11000000000010110010010000000010 -10001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101111100000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00100000000000010001111000000000 -10110111100000000010000111100000 -00001001011110000000001001011110 -00000001101101111000000000101101 -11100000000010110111100100000010 -01011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010010111 -10000000001011011110000000001011 -01111000000000101110110000000100 -00010000000000000000000000000000 -00000000000000000000000000000000 -01001000000010000000110000100000 -11110011000000000010000011000000 -00001111001100000000001111001100 -00000000111100110000000000111100 -11000000000011110011000000000011 -10001100010000001111001100000000 -00111100110000000000111100110000 -00000011110011000000000011110011 -00000000001111001100000000001111 -00110000000000111101101000000010 -00010000000000000000000000000000 -00000000000000000000000000000000 -01000000000111011011110000000000 -11111111000100000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011110111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111101000000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011110110000000000 -11111000000000000011001011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011110010000000000011 -00101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000100011001110000000000 -10110110000000000010000111000000 -00001011011100000000001011011100 -00010000101101110000000000101101 -11000000000010110111000000000010 -10011100000000001011011100000000 -00111101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101111001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000000001001111000000000 -10110010100000000010010111100000 -00001011011110000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -00011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101100100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110010011100000010000011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000100000010 -10001100000000001011001100000000 -00101000110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101101001000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11111110000000001011011010000001 -00001111101000000000001111101000 -00000000111110100000000000111110 -10000000000011110110100000000011 -00101000000000001111101000000000 -00101110100000000000111110100000 -00000011111010000000000011111010 -00000000001111101000000000001111 -10100000000000111111101000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000010000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111101001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000000000011001001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000001011 -00100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010100000000 -10110001110000000010001001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000100000010 -00100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000001000101110000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010100000000 -10111001001000000010001001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -00100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100111000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110011001000000010000001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110011000000000010 -00000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100101000000101 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11111000000000001011001000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -00100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111011110010000000000 -11111101000100000011111001000000 -00001111100100000000001111100100 -00000000101110010000000000111110 -01000000000011111101000000000011 -11100100000000001111100100000000 -01111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110011000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000001011110010000000000 -11111101100000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111101000001000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100011000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000100001110000000000000 -10111000000000000010111000000000 -00001011100000000000001011100000 -00000000101110000000000000101110 -00000000000010111000000000000010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000010111000000000000010111000 -00000000001011100000000000001011 -10000000000000101100111000000110 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000001011100010000000000 -10110001010000000010110001000000 -01001011000100000000011011000100 -00000001101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101101001000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001010000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011110010000000000 -11111001000000000010111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001110100000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110100000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -00101000000000011010110000100000 -11111001010000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000110011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111101001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000001000000011 -00100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111100001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010010101110000000 -10111110101000000010111010000000 -00001011101000000001001011101000 -00000000101110100000000000101110 -10000000000010111110011000000011 -01101000000000001011101000000000 -00101110100000000000101110100000 -00000010111010000000000010111010 -00000000001011101000000000001011 -10100000000000101100101000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100100100000000 -10110010000000000010110011000000 -00001011001100000000001011001100 -00000001101100110000000000101100 -11000000000010110011000000000010 -00001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100101000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000000010001000000000000 -10110100000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111100000000010 -01011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101110000000000100 -01000000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001101000001000 -11110111100000000010110111100001 -10001111011110000000001111011110 -00000000111101111000000000111101 -11100000010011110111100000100011 -00011110000000001111011110000000 -00111101111000000000111101111000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01111000000000111110001000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010000110101000 -11111010000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011110011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001101101100000000001111 -10110000000000111100001000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000001011111111000000000 -11100100100100000011101111100000 -00001111111110000000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -10111110010000001111111110010000 -00111111111001000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111100000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001010100000000 -10000100000000000010000111000100 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000001000010110111000000000010 -10011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101110101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10100101000000000110100111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010111111010010000010 -00011100000001001011011100000001 -00101101110000000000001101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101100000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00100000000101001100010000000000 -10000000100000000110000011000000 -00001011001100000000001011001100 -00000000101100110000000001101100 -11000000000010110011100000000010 -10001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000101011010100000000000 -11100010000010000011101011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011110010010000000011 -10101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110101000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110100100000000 -11111000000000000011111011000000 -00001111101100000000001111101100 -00000100111110110000000000111110 -11000000000011111011010000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001011101100000000001111 -10110000000000111110000000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -00000001000100001111111000000000 -11111111000000100011101111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111101000000000011 -00111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000001001111 -11110000000100111100100001000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000001010001000110111100000000 -10111011010000000010001011000001 -00001011101100000000001001101100 -00000000101110110000000000111010 -11000000000010111001100000000010 -10101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101110100001000100 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010000001000000 -10111000010000000010101011000000 -00011011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011100010000010 -00101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101110000000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000000000000000 -10111000000000000010100011000000 -00001011001100000000001001001100 -00000000101100110000000000101000 -11000000000010110011000000000010 -10001100000000001011001100000000 -00101100110000000000101100110000 -00000010010011000000000010110011 -00000000001011001100000000001011 -00110000000000101100001000000101 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000011010110010000000000 -11111001000000000011101011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -00101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100000000100011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000110011101010000000000 -11111101000000000011011111000000 -00001111111100000000001111111100 -00000000111111110000000000111011 -11000000000011110111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111110100100000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11111111100000000011111111100000 -00001111111110000000001111111110 -00000000111111111000000000110111 -11100000000011001111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11001000000000111111000000000101 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001110111000000000 -10111011100000000010111011100000 -00001011001100000000001011101110 -00000000101100110000000000100010 -11000000000011011011100000000010 -11101110000000001011101110000000 -00101110111000000000101110111000 -00000010111011100000000010111011 -10000000001011101110000000001011 -10101000000000101110000000000110 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10110011000000000010110011000000 -00001011001100000000001010001100 -00000000101100110000000000100100 -11000000000010000011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00010000000000101110001000000001 -00110000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000100010 -11000000000010011011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10000100010000101111000000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000101011110110000001000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000110110 -11000000000011001011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10000000000000111100000000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000000000 -10111111000000000011111111000000 -00001101111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001101111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11100000000000111111100000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011000000000011111011000000 -00001101101100000000001110101100 -00000000111110110000000000111010 -11000000000011101011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110100000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10111011000000000010111011000000 -00001011101100000000001000101100 -00000000101110110000000000100010 -11000000000010001011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10100000000000101111001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10110011000000000010110011000000 -00001011001100000000001010001100 -00000000101110110000000000101010 -11000000000010100011000000000010 -11001100000000001001001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00000000000000101111100000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00100000000000010001111000000000 -10110111100000000010110111100000 -00001011011110000000001000011110 -00000000101101111000000000100001 -11100000000010000111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101101100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -01001000000010000000110000000000 -11110011000000000011110011000000 -00001111001100000000001110001100 -00000000111100110000000000111010 -11000000000011100011000000000011 -11001100000000001111001100000000 -00111100110000000000101100110000 -00000011110011000000000011110011 -00000000001111001100000000001111 -00010000000000111101001000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000111011011110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11010000000000111101000000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011110110000000000 -11111011000000000011111011000000 -00001111101110000000001101101100 -00000000111110111000000000110010 -11000000001011001011000000000011 -11101100000000001111101100000000 -00111110110000000000111010110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10001000000000110110101000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000100011001110000000000 -10110111000000000010110111000000 -00001011111100000000001000011100 -00000000101101110000000000100011 -11000000000010000111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000010001011 -01110000000000100001001000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000000001001111000000000 -10110111100000000010110111100000 -00001011011110000000001001011110 -00000000101101111000000010100001 -11100000000010000111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -11111000000000100111000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001000001100 -00000000101100110000000000100000 -11000000000010000011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000100001001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11111010000000000011111010000000 -00001111101000000000001101101000 -00000000111110100000000000110010 -10000000000011001010000000000011 -11101000000000001111101000000000 -00111110100000000000111110100000 -00000011111010000000000011111010 -00000000001111101000000000001111 -11101000100000110111101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111101001000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011001001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000001010001001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101110000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101100 -01000000000010001001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010000001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111100000000000000111110 -00000000000011001000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111011110010000000000 -11111001000000000011111001000000 -00001111100100101000001111100100 -00000000111110011010100000111110 -01101010000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -01010000000000111110011000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000001011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000110010 -01000000000011001001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110011000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000100001110000000000000 -10111000000000000010111000000000 -00001011100000000000001011100000 -00000000101110000000000000101000 -00000000000010101000000000000010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000010111000000000000010111000 -00000000001011100000000000001011 -10100000000000101100111000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000001011100010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000100000 -01000000000010000001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101100010000000000101010 -01000000000010101001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011110010000001000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000110010 -01000000000011001001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110100000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000000011010010000000000 -10111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10011010000000111100101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000110010 -00000000000011001000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010010100000000000 -10111010000000000010111010000000 -00001001101000000000001001101000 -00000000101110100000000010100010 -10000000001010001010000000000010 -11101000000000001011101000000000 -00101110100000000000101110100000 -00000010111010000000000010111010 -00000000001011101000000000001011 -10100000000000101100101000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000100010 -11000000000010000011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100101000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000000010001110000000000 -10110111000000000010110111000000 -00001001011100100000001001011100 -00000000101101110001000000100001 -11000000000010000111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101100100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001111000000000 -11110111100000000011110111100000 -00001111011110000000001111011110 -00000000111111111010000000110001 -11100000000011000111100000000011 -11011110000000001111011110000000 -00111101111000000000111101111000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01111000000000111100101000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111011000000000011111011000000 -00000101101100011000001001101100 -00000000111110110000100000111110 -11010100000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011011011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000001011111111000000000 -11111111100000000011111111100000 -00001111111110000000001100111110 -00000000111111111000000000111011 -11110000000011011111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001101111110000000001110 -01111000000000110001000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110000000000 -10110111000000000010110111000000 -00001011011100000000001101011100 -00000000101101110000000000110101 -11000000000010100111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000100000110110101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110111000000000010110111000000 -00001011011100000000001000011100 -00000000101101110000000000101001 -11000000000010010111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010010111000000000010110111 -00000000001011011100000000001011 -11110000000000100000010010000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00100000000101001100110000000000 -10110011000000000010110011000000 -00001011101100000000001001001100 -00000000101110110000000000100100 -11000000000010100011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000010001011 -00111100000000100101101000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10101000000101011010110000000000 -11111011000000000011111011000000 -00001111111100000000001100101100 -00000000111111110000000000111011 -11000000000011011011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001101101100000000001110 -10111101000000110010101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110010000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -00000001000100001111110000000000 -11111111000000000011111111000000 -00001111111100000000001100111100 -00000000111111110000000000110011 -11000000000011001111000000000011 -11111100000000001110111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000000001 -11110000000000111110000001000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000001000001000110110000000000 -10111011000000000010111011000000 -00001011101100000000001010101100 -00000000101110110000000000101010 -11000000000010101011000000000010 -11101100000000001001101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000000011101100000001001001 -10110000001000101110000001000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000000000010111011000000 -00001011101100000000001010101100 -00000000101110110000000000100000 -11000000000010001011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000001000010111011 -00000000001001101100000000001001 -10110000000000101110000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10110011000000000010110011000000 -00001011001100000000001010001100 -00000000101100110000000000101000 -11000000000010100011000000000010 -11001100000000001001001100000000 -00101100110000000000101100110000 -00000000110011000000000010110011 -00000000001011001100000000001001 -00110000000000101100001000000100 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000011010110110000000000 -11111011000000000011111011000000 -00001111011100000000001100101100 -00000000111101110000000000110001 -11000000000011001011000000000011 -11101100000000001110101100000000 -00111110110000000000111110110000 -00000001111011000000000011111011 -00000000001111101100000000001101 -10110000000000111110000000000010 -00010000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11111111000000000011111111000000 -00001111111100000000001011111100 -00000000111111110000001000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000011000001110100000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11101111100000000011101111100000 -00001111111110000000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -00111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111111000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001110111000000000 -10111011100000000000111011100000 -00001011101110000000001011101110 -00000000101110111000000000101110 -11100000000010111011100000010010 -10101110000000001011101110000000 -00101110111000000000111010111000 -00000010111011100000000010111011 -10000000001011101110000000001011 -10111000000000101111000000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10110011000000000110100011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -00001100000010001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101111001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -10101100000000001011101100000000 -00101110110000000000100110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111000000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000101011110110000000000 -11101011000000000011101011000000 -00001111101100000000001011101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -00101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100010000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111011110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111111100000000100 -01000000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011000000000011011011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010010110000000100 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010110011110100000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000100100110000000000101100 -11000000000010110011000100000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101111000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00100000000000000001111000000000 -10110111100000000010110111100000 -00001011011110000000001011011110 -00000000101101111000000000101101 -11100001000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101110110000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01001000000010000000110000000000 -11110011000000000011110011000000 -00001111001100000000001111001100 -00000000110100110000000000111100 -11000000000011110011000000000011 -11001100010000001111001100000000 -00111100110000000000111100110000 -00000011110011000000000011110011 -00000000001111001100000000001111 -00110000000000111101001000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000111001011110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000000 -11111100000100001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001011111100000000001111 -11110000000000111101000000000110 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000101100001000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000100011001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101111001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000000001001111000000000 -10100111100000000010110111100000 -00001011011110000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101100100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101101101000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11101010000000000010111010000000 -00001011101000000000001111101000 -00000000111110100000000000111110 -10000000000011111010000000000011 -11101000000001001111101000000010 -00111110100000000000111110100000 -00000011111010000000000011111010 -00000000001111101000000000001111 -10100000000000101111101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111101001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001100000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000100000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101110000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11111000000001000111111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111010000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000111 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111011110010000000001 -11111001000000000111111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000001111110111000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000001011110010000000000 -11101001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111101000001000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001110 -10010000000000111000111000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000100001110000000000000 -10111000000000000010111000000000 -00001011100000000000001011100000 -00000000101110000000000000101110 -00000000000010111000000000000010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000010111000000000000010111000 -00000000001011100000000000001011 -10000000000000101100011000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00001000000001011100010000000000 -10100001000000000010110001000000 -00001011000100000000001010000100 -00000000101100010000000000101100 -01000000000010110001000000100010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001010 -00010000000000101001001000000001 -00100000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000010000 -10111001000001000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000001000010 -11100100000000001011100100000100 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000010000101100011000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011110010000000000 -11101001000000000011111001000000 -00001011100100000000001110100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001110 -10010000000000111010100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000000011010010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000100111111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111101101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11101000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000111111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010010100000000000 -10111010000000000010111010000000 -00001011101000000000001011101000 -00000000101110100000000000101110 -10000000000010111110110100000010 -11101000000000001011101000000000 -00101110100000000000100110100000 -00000010111010000000000011101010 -00000000001011101000000000001011 -10100000000000101100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10100011000000000010110011000000 -00001011001100000000011011001100 -00000000101100110000000000101100 -11000000000010110011110000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100101000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000000010001110000010000 -10110111000001000010110111000000 -00001011011100000000001011011100 -00000100101101110000000000101101 -11000000000010110110010000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010100111 -00000000001011011100000000001011 -01110000000000101100100000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001111000000000 -11100111100000000011110111100000 -00001111011110000000001111011110 -00000000111101111000000000111101 -11100000000010110101100000000011 -11011110000000001111011110000000 -00111101111000000000111101111000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01111000000000111100101000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000110110110000 -00000011111011000000000011101011 -00000000001111101100000000001111 -10110000000000111100001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000000011111111000000000 -11111111100000010011111111100000 -01001111111110000010001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110001000000 -11110111000100000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111010000000010 -11011100000000001110011100000000 -00111001110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101110101000000010 -00100000000000000000000000000000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101001110000000000100101 -11000000000010100111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101100000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00100000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001010001100000000 -00101000110000000000100100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101101000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000101011010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000110110 -11000000000011101000000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110101100000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11101011000000000011111011000000 -00001111101100000000001111101100 -00000100111110110000000000111110 -11000000000011111000000000000011 -11101100000010001111101100000000 -00111110110000000001111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110100000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000001000100001111110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111011110000000000111111 -11000000000011111101000000000011 -11111100000000001111111100000000 -00111111110000000001111111110000 -00100011111111000000000011111111 -00000000001111111100000001001111 -11110000000100111100000101000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000001000001000110110000000000 -11101011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111001110000000010 -11101100000000001001101100000000 -00101110110000000001101110110000 -00000010111011000000000011101011 -00000000001011101100000000001011 -10110000000000101110000001000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101010 -11000000000010111001100000000110 -11101100000000001011101100000001 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101110000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10100011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110001000000000110 -11001100000000001001001100000000 -00101100110000000000101100110000 -00000010110011000000000010100011 -00000000001011001100000000001011 -00110000000000101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000011010110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111010 -11000000000010111001000000000011 -11101100000000001111101100000000 -00111110110000000000101110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100000000100110 -00010000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111101000000000000 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000010001111111100000000001111 -11110000000000111110100000000011 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11111111100000000011111111100000 -00001111111110000000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11001000000000110011000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001110111000000000 -10111011100000000010111011100000 -00001011101110000000001011101110 -00000000101110111000000000101110 -11100000000010111011100000000010 -11101110000000001011101110000000 -00101110111000000000101110111000 -00000010111011100000000010111011 -10000000001011101110000000001011 -10001000000000100011000000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10100011000000000010110011000000 -00001011001100000000001010001100 -00000000101100110000000000101000 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010100011000000000010110011 -00000000001011001100000000001011 -10000000000000100011001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010110000000000 -10111011000000000010111011000000 -00001011101100000001001011101100 -00000000101110110000000000100110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000010100011000000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000101011110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10100100100000110000000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011011111000000000011111111 -00000000001111111100000000001111 -11000000000000111111100000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000100111110110000001000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10100000000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000001001011 -00110000000000101111011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10110011000000000010110011000000 -00001001001100000000001001001100 -00000000101100110000000000100100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010010011000000000010110011 -00000000001011001100000000001011 -00010000000000101111101000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00100000000000010001111000000000 -10110111100000000010110111100000 -00001011011110000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01011000000000101111110000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01001000000010000000110000000000 -11110011000000000011110011000000 -00001101001100000000001111001100 -00000000111100110000000000111100 -11000000000011110011000000000011 -11001100000000001111001100000000 -00111100110000000000111100110000 -00000011110011000000000011110011 -00000000001111001100000000001111 -00000000000000111101101000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000111011011110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111101000000000110 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000011011110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111010110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000000011001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01010000000000101111001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000000001001111000000000 -10110111100000000010110111100000 -00001011011110000000001011011110 -00000000101001111000000000101001 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01101000000000101100100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000001011011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101101001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11111010000000000011111010000000 -00001111101000000000001111101000 -00000000111010100000000000111110 -10000000000011111010000000000011 -11101000000000001111101000000000 -00111110100000000000111110100000 -00000011111010000000000011111010 -00000000001111101000000000001111 -11100000100000111111101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111101001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000110110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000011 -11100100000000001011100100000000 -00101110010000000000100110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101110000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010101001000000000010111001 -00000000001011100100000000011011 -10010000000000101100011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000100100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -00100000000000000000000000000000 -00000000000000000000000000000000 -10111000000001010110000000000000 -11111000000000000010111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011101000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000111 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000101011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -10100100000000001111100100000000 -00111110010000000000110110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -11010000000000111110111000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000001011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -00010000000000111110111000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000100001110000000000000 -10111000000000000010111000000000 -00001011100000000000001011100000 -00000000101110000000000000101110 -00000000000010111000000000000010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000010111000000000000010111000 -00000000001011100000000000001011 -10000000000000101100011000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000001011100010000000000 -10110001000000000010100001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101101001000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000011011 -10010000100000101100011000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010100001000111110100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000000011010010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10011010000000111101101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000100000000110000101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010010100000000000 -10111010000000000010111010000000 -00001011101000000000001011101000 -00000000101110100000000000101110 -10000000000010111010000000000010 -11101000000000001011101000000000 -00101110100000000000101110100000 -00000010111010000000000010111010 -00000000001011101000000000001011 -10100000000000100000001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000100100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000001001011 -00110000000000100100001000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000000010001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -11111000000000100100100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001111000000000 -11110111100000000011110111100000 -00001111011110000000001111011110 -00000000111101111000000000111101 -11100000000011110111100000000011 -11011110000000001111011110000000 -00111101111000000000111101111000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01111000000000110100101000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111011000000000011111011000001 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000010001111 -10110000000010111000001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000001011111111000000000 -11111111100000000011111111100000 -00001111111110000000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111101100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000100001011011100000000001011 -01110010000000101110101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101100010010000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00100000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000011011 -00111100000000101101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000101011010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10111000100000111110101000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000001001111101100000000001111 -10110000000000111110110000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -00000001000100001111110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000100000111110000001000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000001000001000110110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000001000010111011 -00000000001011101100000101001011 -10110000001000101110000101000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000000000010111011000000 -00001011101100000000001001101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101110000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000011010110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110000000100110 -00000000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000010100111110100000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11101111100000000011111111100000 -00001111111110010000001101110000 -10000000110011111000000000111011 -11100000000011111111000000000011 -00110010000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111111000000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001110111000000000 -11111011100000000011101011100000 -00001011101100000000001000101011 -00000000100010111000000000111010 -11100000000010111011110100000010 -00100000000000001011101110000000 -00101110111000000000101110111000 -00000010111011100000000010111011 -10000000001011101110000000001011 -10111000000000101110000000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10110011000000000010110011000000 -00001011001100000000101000000000 -01000100100000110000000001101100 -11000000000010110011000000000110 -00000100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101110001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010110000000000 -10111011000000000010111011000000 -00001011001100000000001000100001 -00000000100010110000000000101110 -11000000000010111011000001000010 -00100110001000001011101100000000 -00101110110000000000101110111000 -10000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111000000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000101011110110000000000 -11101011000000000011111011000000 -00001111101100000000001101100110 -01000010110010110000000000111110 -11000000000011111011000000000011 -00100010000000001111101100000000 -00111110110000000000111110111000 -00100011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11101111000000000011101111000000 -00001111111100000000000111111000 -00000000111111110000000000111011 -11000000000011111111000001001011 -11110000000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111111100000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011000000000011111011000000 -00001111101100000000001110001100 -00000000111110110000000000111110 -11000000000011111011000110000011 -11101101000000001100101100000000 -00111110110001000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111101000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10111011000000000010111011000000 -00001011101111110000001000101100 -00000000101110110000000000101110 -11000000000010110111000000000010 -11101100000000001010101100000000 -00101110111101000000101110010000 -00000010111011000000000010111011 -00000100001011101100000000001011 -10110000000000101111001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10110011000000000010110011000000 -00001011001100000000001000000000 -00001000101100110000000000101100 -11000000000010110011110000000010 -11000000000000001000001100000000 -00101100111000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101111000000000100 -00000000000000000000000000000000 -00000000000000000000000000000000 -00100000000000000001111000000000 -10110111100000000010110111100000 -00001011011110000100101000011110 -00000000101101111000000000100101 -11100000000010110111100000000010 -11010010000000001010011110000000 -00101101111000000000101101110001 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101100100000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01001000000010000000110000000000 -11110011000000000011110011000000 -00001111101100000001001110000000 -00000000111100110000000000111100 -11000000000011110011000000000011 -11100000000000001100001100000000 -00111100110000000000111100110000 -00000111110011000000000011110011 -00000000001111001100000000001111 -00110000000000111101001000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000111001011110000000000 -11111111000000000011111111000000 -00001111111100000000001111111000 -00000000111111110000000000111111 -11000000000011111111000010000011 -11110100000000011111111100000000 -00111111110000000000111111110001 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111101000000000110 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011110110000000000 -11111011000000000011111011000000 -00001111101100000000101100100100 -00000000110010110000000000111110 -11000000000011111011100000000011 -00100000000000001111101100000000 -00111100111000000000110010110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000000011001110000000000 -10110111000000000010110111000000 -00001011111100000000001000011100 -00000000110101110000000001101101 -11000000000010110111001000000010 -00011000000000001011011100000000 -00101101110000000000110101100000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101101001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000000001001111000000000 -10110111100000000010110111100000 -00001011011110000000001000000110 -00000000100001111000000000101001 -11100000000010110011101000000010 -00011010000000001011011110000000 -00101101111000000000100001111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101100100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110011000000000010110011000000 -00011011001100000000001000001110 -00000000100100110000000000101100 -11000000000010110011000001000010 -00101100000000001011001100000000 -00101100110000000000100100111101 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101101101000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11111010000000000011111010000000 -00001111101000000000001100111011 -00000000110010100000000000111110 -10000000000011111010000000000011 -00111010100000001111101000000000 -00111110100000000000110011100101 -00000011111010000000010011111010 -00000100001111101000000000001111 -10100000000000111111101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -01100000111110000000000000111110 -00000000000011111000000000001011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111101001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000000000011111001000000 -00001111100100000000001100000100 -00000000110010010000000000111110 -01000000000111111001100000000011 -11100110000000001100100100000000 -00111110010000000000111110010000 -00100011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000000000010111001000000 -00001011100110010000101000100100 -00000000101010010000000000101110 -01000000000110111001010000000010 -11100110000000001000100100000000 -00101110010100000000101110010000 -00000010111001000000000011111001 -00000000001011100100000000001011 -10010000000000101110000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010111001000000 -00001011000100001000001000100100 -00000000100010010000000000101110 -01000000010010111001000101000010 -11100100010000001000100100000000 -01101110010000100000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001000000000010110001000000 -00001011000100000000001000000100 -10000000101000010000000000101100 -01000000000010110001001000000010 -11000100000000101000000100000000 -01101100010000000000100100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000001000110000000000000 -11111000000000000011111000000000 -00001111100001010000001100100000 -00000000110010000000010000111110 -00000000000010111010000000000011 -11100001010010001100100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000111 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111001110010000000000 -11111001000000000011111001000000 -00001111100100000000001111110100 -01000000111110010000000000111110 -01000000000011111001000101000011 -11110100000000001111100100000000 -00111110010000000000111111010000 -00000011111001000000000011101001 -00000000001111100100000000001111 -10010000000000111110111000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000000011110010000000000 -11111001000000000011111001000000 -00001111110100000000001111100100 -00000000110110010000000000111110 -01000000000011111101000000001011 -01110100000000001100100100000000 -00111111010000000000110010010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100111000000101 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000100001110000000000000 -10111000000000000010111000000000 -00001110000000000000001011100000 -00000000110110000000000000101110 -00000000000010111000000000000010 -00100010100000001101100000000000 -00101110000000000000110110000000 -00000011101000000000000010111000 -00000000001011100000000000001011 -10000000000000101100011000000010 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000001011100010000000000 -10110001000000000010100001000000 -00001011000100000000011011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -00001110001000001000000100000000 -00101100010000000000100000010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101101001000000001 -01100000000000000000000000000000 -00000000000000000000000000000000 -00011000000100011010010000000000 -10111001000000000010111001000000 -00001010100100000000001011100100 -00000000100110010000000000101110 -01000000000010111001000000000010 -00100100100000001001100100000100 -00101110010000000000100110010100 -00000010101001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011110010000000000 -11111001000000000011101001000000 -00001111100100000000001111100111 -00100000111110010000000000111110 -01000000000011111001000000000011 -01100100000000001100100100000000 -00111100010000000000110010010000 -00000011111001000000010011111001 -00000000001111100100000000001111 -10010000000000111110100000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000000011010010000000000 -11111001000000000011111001000000 -00001110100100000000001111100111 -00000000111010010000000000111110 -01000000000011111001000010000011 -11100100000000001111100100000000 -00111110010000000000111110010100 -00000001111001000000000011111001 -00000000001011100100000000001111 -10010000000000111101101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000000000011111000000000 -00001111100000100000001100000000 -00000000110110000000000000111110 -00000000000111111000000100000011 -11100000000000001100100000000000 -00111110000010000000111110000100 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010010100000000000 -10111010000000000010111010000000 -00001011111011000000101000101000 -00000000111110100000000000111010 -10000000000010110110000000000010 -01101000000000101000101000000000 -00101111100110000000111110100000 -00000010111010000000000011101010 -00000000001011101000000000001011 -10100000000000101100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110011000000000010110011000000 -00001011001110000000001001001100 -00000000100000110000000000101100 -11000000000010110011110000000010 -11101100000000001000001100000000 -00101100001000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100001000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000000010001110000000000 -10110111000000000010110111000000 -00001011010110001000001001001100 -00000000101001110000000000100001 -11000000000010110111000000000110 -01011100000000001000011100000000 -00101101100000000000101001110000 -00000010110111000000000010100111 -00000000001011011100000000001011 -01110000000000101100100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001111000000000 -11110111100000000011110111100000 -00001111011110000000001101011110 -00000100100001111000000000111101 -11100000000010110110100000000011 -11110110000000001100011110000000 -00111101001000000000101101111000 -00000011110111100000000011110111 -10000000011111011110000000001111 -01111000000000111100101000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111011000000000011111011000000 -00001111101000000000001110101100 -00000000111110110000000000111010 -11000000000011111011000001000011 -11100100000000001111101100000000 -00111110100000000000111110110000 -00000011111011000000000011101011 -00000000001111101100000000001111 -10110000000000111100001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000001011111111000000000 -11111111100000000011111111100000 -00001111111110000000001100111110 -00000000111111111000000000111111 -11100000000011111110100000000011 -00111110000000001100111110000000 -00111111001000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111101100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110000000000 -10110111000000000011110111000000 -00001011110000000000011000011100 -00000000101101110000000000101101 -11000000000010110110000000000011 -01011100000000001101011100000000 -00101101000000000000111001110001 -10000011110111000000000010110111 -00000000001011011100000000001011 -01110000000000101110101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110111000000000010110111000000 -00001011010100000000001000011100 -00000000101101110000000000101101 -11000000000010110110000000000010 -00110100000000001001011100000000 -00101101010000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101100000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00100000000101001100110000000000 -10110011000000000010100011000000 -00001011100000000000001000001111 -01001000101100110000000000101100 -11000000000010110010000000000010 -01100101001000001001001100000000 -00101100000000000000101100110000 -00000010100011000000010010110011 -00000000001011001100000000001011 -00110000000000101101000100000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000101011010110000000000 -11111011000000000010111011000000 -00001111101000000000101100101100 -00001000111110110000000000111110 -11000000000011111001000000000011 -00101101000000001101101100000000 -00111110000000000000111110111000 -00000010111011000001000011111011 -00000000001111101100000000001111 -10110000000000111110101100000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11111011000000000011111011000000 -00001111101001000000001111101100 -10000100111110110000000000111110 -11000000000011111011000000000011 -11101110000000001111101100000000 -00111110000000000000111010110010 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110100000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -00000001000100001111110000000000 -11111111000000000011111111000000 -00001111111111000000001110011100 -00000000110011110000000000111111 -11000000000011111110000000000011 -00110100000000001100111100000000 -00111111000000000000111111110000 -00000011001111000000000011111111 -00000000001111111100000000001111 -11110000000000111100000101000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000001000001000110110000000000 -10111011000000000010111011000000 -00001011101000000000101000101100 -00000000100010110000000000101110 -11000000000010110011100000000011 -01110100000000001000101100000000 -00101110001000000000101100110000 -00000011111011000000000010111011 -00000000001011101100000000001011 -10110000000000101110000001000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000000000010111011000000 -00001011100101000000001000101100 -00000000100010110000000000101110 -11000000000010111010000100000010 -00100110000000001000101100000000 -00101110000001000000101110110000 -00000010001011000000000010111011 -00000000001011101100000000001011 -10110000000000101110000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10110011000000000010110011000000 -00001001000000000000001000001100 -00000010100000110000000000101100 -11000000000010110010000000000010 -01000100000000001000001100000000 -00101100000000000000101110110000 -00000010010011000000000010110011 -00000000001011001100000000001011 -00110000000000101100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000011010110110000000000 -11111011000000000010111011000000 -00001111100100000000001110101100 -00000000110010110000000000101110 -11000000000011111010000000000011 -00101100000000001100101100000000 -00111110010000000000111110110000 -00000011001011000000000011111011 -00000000001111101100000000001111 -10110000000000111100000000000110 -00010000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11111111000000000011111111000000 -00001111110000000000001111111100 -00000000111111110000000000111111 -11000000000011110110000000000011 -11011100000000001111111100000000 -00111111000000000100111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111110100000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11111111100000000011111111100000 -00001111111110000000001110111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011001111 -10000000001111111110000000001111 -11111000000000111011000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110111000000000 -10111011100000000010111011100000 -00001011101110000000001100101110 -00000000101110111000000000101110 -11100000000010111011100000000010 -11101110000000001011101110000000 -00101110111000000000101110111000 -00000010111011100000000011011011 -10000000001011101110000000001110 -10111000000000101111000000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10100011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00100100110000000000101100110000 -00000010110011000000000010000011 -00000000001011001100000000001011 -00110000000000101111001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010110000000000 -10111011000000000010111011000000 -00001011101100000000001010101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010011011 -00000000001011101100000000001010 -10110000000000101111100000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000001011110110000000000 -11111011000000000011111011000000 -00001111001100000000001111101100 -00000000111110110000000000111110 -11000000000010111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011110011000000000011001011 -00000000001111101100000000001111 -10110000000000111100100000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000100011011110000000000 -11111111000000000011111111000000 -00001111111100000000001101111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000011111111100000000001111 -11110000000000111111100000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011000000000011101011000000 -00001111101100000000001100101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011101011000100000011111011 -00000000001111101100000000001111 -10110000000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10111011000000000010111011000000 -00001011101100000000001000101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101110001100001011 -10110000000000101111000000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11000000000001000000110000000000 -10110011000000000010100011000000 -00001011001110010000001001001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -10001100000000001011001100000000 -00101100110000000000101100110000 -00000010100011110010000010110011 -00000000001011001111001000001011 -00110000000000101111000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00100000000000000001111000000000 -10110111100000000010110111100000 -00001011011100000000001001011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000011011 -01111000000000001111111000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01001000000110000000110000000000 -11110011000000000011100011000000 -00001111001100010000001101001100 -00000000111100110000000000111100 -11000000000011110011000000000011 -11001100000000001111001100000000 -00111100110000000000111100110000 -00000011100011000000000011110011 -00000000001111001100010000001111 -00110000000000111101101000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000111001011110000000000 -11111111000000000011111111000000 -00001111011100100000001110111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000100011111 -11110000000000111101000000000010 -00100000000000000000000000000000 -00000000000000000000000000000000 -00001000000101011110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111010110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100101000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000010011001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101111001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -00100000000000001001111000000000 -10110111100000000010110111100000 -00001011011110000000011011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101001111000000000101101111000 -00000010110111100000000110110111 -10000000001011011110000000001011 -01111000000000101100000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -11101000000001001100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000001011011001100000000001011 -00110000000000101101001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101001010100000000000 -11111010000000000011111010000000 -00001111101000000000001111101000 -00000000111110100000000000111110 -10000000000011111010000000000011 -11101000000000001111101000000000 -00111010100000000000111110100000 -00000011110010000000000011111010 -00000000001111101000000000001111 -10100000000000111111101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001010000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111101001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10001000000100001010010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011011001 -00000000001111100100010000001111 -10010000000000111100001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000010010000000000 -10111001000000000010111001000000 -00001011100100100000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001001000000010001001 -00000000001011100110000000001011 -10010000000000101110000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010101001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010011001 -00000000001011100100000000001011 -10010000000000101100011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010000001 -00000000001011001100000000001011 -00010000000000101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000111010110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011101000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011011000 -00000000001111100000000000001111 -10000000000000111110111000000111 -01010000000000000000000000000000 -00000000000000000000000000000000 -10111000000111011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110111100000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000101011110010000000000 -11111001000000000011111001000000 -00001111110100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111101000000000011111001 -00000000001111110100000000001111 -10010000000100111110111000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000000001010000000000000 -10111000000000000011101000000000 -00001011100000000000001011100000 -00000000101110000000000000101110 -00000000000010111000000000000010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000010111000000000000010111000 -00000000001011100000000000001011 -10000000000000101100011000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -01001000000001001000010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101000010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101101001000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00011000000101001010010000000000 -10111001000000000010101001000000 -10001011101100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000001001011100100000000001011 -10010000000000101100011000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101001110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111010010000000000111110010000 -00000011111001000000000011111001 -00000000011111100100000000001111 -10010000000000111110000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01101000000000001010010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100001000001111 -10010000000000111101101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000000000011101000000000 -00001111100000001000001110100000 -00000000111110000000000000111110 -00000000000011101000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000010000011111000 -00000000001111100000000000001111 -10000000000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000010100000000000 -10111010000000000010111010000000 -00001011111010000000001011101000 -00000000101110100000000000101110 -10000000000010111010000000000010 -11101000000000001011101000000000 -00101110100000000000101110100000 -00000010111110000000000010111010 -00000000001011111001000000000011 -10100000000000101100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001010100110000000000 -10110011000000000010100011000000 -00001011001100000000001010001100 -00000000101100110000000000101100 -11000000000010100011000000000010 -10001100000000001011001100000000 -00101000110000000000101100110000 -00000010110011100000000010110011 -00000000001011001110000000001011 -00110000000000101100001000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00100000000000010001110000000000 -10110111000000000010110111000000 -00001011011100001000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111010000000110110111 -00000000001011010101000000001011 -01110000000000101100000000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00101000000110000001111000000000 -11110111100000000011100111100000 -00001111011110000000001110011110 -00000000111101111000000000111101 -11100000000011100111100000000011 -11011110000000001111011110000000 -00111101111000000000111101111000 -00000011110111100000000011110111 -10000000001111011110000010001111 -01111000001000111100101000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111010000000000011111011 -00000000001111100000000000001111 -10110000000000111100001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -01100000000001001011111000000000 -11111111100000000011111111100000 -00001111111010010000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111110100100000011111111 -10000000001111111010000000001100 -11111000000000111101000000000001 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000000001001110000000000 -10110111000000000010110111000000 -00001011010000000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110101000000000011100111 -00000000001011011100000000001101 -01110000000000101110101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110111000000000010110111000000 -00001011011000000000011011011100 -00000000101001110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110110000000000110110111 -00000000001011010000000000001000 -01110000000000101100010000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01000000000101001000110000000000 -10110011000000000010110011000000 -00001011000000000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000110110000000000000010100011 -00000000001011000000000000011001 -00110000000000101101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011010110000000000 -11111011000000000011111011000000 -00001111100100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111001000000000011111011 -00000000001111001100000000001100 -10110000000000111110101000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10100000000100001110110000000000 -11111011000000000011111011000000 -00001111100100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000111101011 -00000010001111100100000000001111 -10110000000000111110110000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -00000001000100001111110000000000 -11111111000000000011111111000000 -00001111110000000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111101100000000011111111 -00000000001111111100000000101100 -11110000000000111110000001000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000001000001000110110000000000 -10111011000000000010111011000000 -00001011100011000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111010100000000010111011 -00000000001011100000000000001000 -10110000000000101110010001100000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010110110000000000 -10111011000000000010111011000000 -00001011101100010000001011101100 -00000000101110110000000000101110 -11000000000010101011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111000000100000010111011 -00000000001011101000000001001000 -10110000000100101110000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10110011000000000010110011000000 -00001011000100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110001000000000010110011 -00000000001011001100000000001000 -00110000000000101100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000110000110110000000000 -11111011000000000011111011000000 -00001111101000000000001111101100 -00000000111110110000000000111110 -11000000000011101011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111000000000000011111011 -00000000001111100000000000001100 -10110000000000101110100000000110 -00010000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011011110000000000 -11111111000000000011111111000000 -00001111110000000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111100000000000011111111 -00000000001111010000000000001111 -11110000000000111110000000100110 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11111111100000000011111111100000 -00001111111110000000001111111110 -00000000111111111000000000111111 -11100000000011111110100000000011 -10111100000000101100110110000000 -00110011111000000000111111111000 -00000011001111100000000011111111 -10000000001111111110000000001111 -11111000000000111111000000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001110111000000000 -10111011100000000010111011100000 -00001011101110000100001011101110 -00011000101110111000001000101110 -11100000000010111010100000000010 -00111110000000101000100100000000 -00100010111000010000101110111000 -00000011011011100000000010111011 -10000000001011101110000000001011 -10111000000000101110000000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010111010000000000010 -10000100000000001010001100000000 -00100000110000000000101100110000 -00000010000011000000000010110011 -00000000001011001100000000001011 -00110000000000101110001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111010100010010010 -00100100000000001000100100000000 -00100010110000000000101110110000 -00000010011011000000000010111011 -00000000001011101100000000001011 -10110000000000101111000000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000101011110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000100111110110000000000111110 -11000000010011111010110000000011 -10111100000000101110100100000000 -00110010110000000000111100110000 -00100011001011000000000011111011 -00000000001111101100000000001111 -10110000000000111101000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000100111 -11000000000011111110000000000011 -11101100011000101111111100000000 -10111111110000000000111111110000 -00010011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111111100000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111010010000000011 -11000100000000001100101100000000 -00111110110000000000110110110010 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111101000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10111011000000000010111011000000 -00001011101100000100001011101100 -00000000101110110000000000101110 -11000000000010110010000000000010 -11100101001000101000101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111001000000100 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10110011000000000010110011000000 -00001001001100000000001011001100 -00000000101100110000000000100100 -11000000000010110000100100000010 -11000100000000101000100100000000 -00101100110000000000100100110100 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101111100000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00100000000000010001111000000000 -10110111100000000010110111100000 -00001001011110000000001011011110 -00000100101101111000000000101101 -11100000000010110100100000000010 -11010110010000001000010110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000000011011110000000001011 -01111000000000101100100000000100 -00010000000000000000000000000000 -00000000000000000000000000000000 -01001000000010000000110000000000 -11110011000000000011110011000000 -00001101001100000000001111001100 -00000000111100110000000000111100 -11000000000011110010000000000011 -11001100000000001100001100000000 -00111100110000000000110100110000 -00000011110011000000000011110011 -00000000001111001100000000001111 -00110000000000111101101000000010 -00010000000000000000000000000000 -00000000000000000000000000000000 -01000000000111011011110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111100000100000011 -11111111000000001111110100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111101000000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111001000000000011 -11100101000000001110100100000000 -00111110110000000000111100111000 -00000011001011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000100011001110000000000 -10110111000000000010110111000000 -00001011011100000001001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11010100000000001000011100000000 -00101101110000000000101101110000 -00000011010111000000000010110111 -00000000001011011100000000001011 -01110000000000101101001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000000001001111000000000 -10110111100000000010110111100000 -00001011011110000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001010011111000000 -00101101111000000000101101111000 -00000010000111100000000010110111 -10000000001011011110000000001011 -01111000000000101100100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000111010010 -11001100000000001000001110000000 -00101100110000000000101100110000 -00000010010011000000000010110011 -00000000001011001100000000001011 -00110000000000101101001000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11111010000000000011111010000000 -00001111101000000000001111101000 -00000000111110100000000000111110 -10000000000011110110100000000011 -11101000000000001110101000000001 -00111110100000010000111110100000 -00000011001010000000000011111010 -00000000001111101000000000001111 -10100000000000111111101100000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000100 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111101001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001110001000011 -00100100000000001100100100000000 -00111110010000000000111110011001 -00000000111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001100000001010 -00000100000000001000100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101110000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -00100110001000101000100100000001 -00101110010000010000101110010000 -10000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100111000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001000000000010010001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -00000100100000001000000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100101000000101 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -00100000000000101100100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000010011111101000001000011 -11010100010000101111110100101000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001101100100000000001111 -10010000000000111110011000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000001011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111101000000000011 -10110110000000101100100100000000 -00110010010000000000111111010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100011000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000100001110000000000000 -10111000000000000010111000000000 -00001011100000000000001011100000 -00000000101110000000000000101110 -00000000000010111000000000000010 -00100000000000001000100010100000 -00110110000000010000101110000000 -00000000111000000000000010111000 -00000000001011100000000000001011 -10000000000000101100111000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000001011100010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101000010000000000101100 -01000000000010111001000000000010 -10000101000000001000100100001000 -00100000010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101101001000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001001000000010 -00100100100000001000100100000100 -00100110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011110010000000000 -11111001000000000011111001000000 -00001111100100000000001011100100 -00000000111010010000000000111110 -01000000000011111001100000000011 -10000100000000001100000110000000 -00110010010000000000111110010000 -01000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110100000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -00101000000000011010010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001100000000011 -11100110001000101111100100100000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111101001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -00100000000001001100100000000100 -00111110000000000000111110000001 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111100001000000100 -00000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010010100000000000 -10111010000000000010111010000000 -00001011101000000000001011101000 -00000000101110100000000000101110 -10000000000010110010100000000011 -01111001000001001010101000000000 -00101110100000000000101111101100 -00000010111010000000000010111010 -00000000001011101000000000001011 -10100000000000101100101000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110001000000000010 -00001000000000001000001100000000 -00101100110000000000101100101100 -10000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100101100000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000000010001110000000000 -10110111000000000010110111000000 -00001011011100000000001001011100 -00000000101101110000000000101101 -11000000000010111101010000000010 -01011001000000001010011100000000 -00101101110000000000101101100000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101110000000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001111000000000 -11110111100000000010110111100000 -00001111011110000000001111011110 -00000000111101111000000000111101 -11100000000011110101100000000011 -00011110000000001100011110000000 -00111101111000000000111101011000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01111000000000111110001000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111011000000000011111011000000 -00001111101100000100001111101100 -00000000111110110000000000111110 -11000000000011110001000000000011 -11000000000000001111101100000000 -00111110110000000000111110000000 -00000011111011000000000011111011 -00000000001101101100000000001111 -10110000000000111100001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000001011111111000000000 -11111111100000000011101111100000 -00001111111110000000001111111110 -00000000111111111000000000111111 -11100000000011111101100000000011 -10111010000000001100111110000000 -00111111111000000000111111001000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111100000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110000000000 -10110111000000000011100111000000 -00001011011100000000001111011100 -00000000101101110000000000111101 -11000000000010110101000000000010 -00011000010000001000011100000000 -00101101110000000000101101000000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101110101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010111111000000000010 -10010100000000001000011100001000 -00101101110000000000101101000000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101100000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00100000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001010001100 -00000000101100110000000000101000 -11000000000010110011100000000010 -00000000000000101000001110000000 -00101100110000000000101100000000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000101011010110000000000 -11111011000000000011111011000000 -00001111101100000000001011101100 -00000000111110110000000000101110 -11000000000011111011100010000011 -10000000000000101100111110000000 -00111110110000000000111110000000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110101000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11111011000000000011101011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111001000000100011 -01100000000000001111101100000000 -00111110110000000000111110000000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110000000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -00000001000100001111110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11100100000000001100111100000000 -00111111110000000000111111011000 -00000011111111000000000011111111 -00000000001101111100000000001111 -11110000000000111100100001000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000001000001000110110000000000 -10111011000000000010111011000000 -00001011101100000100001011101100 -00000000101110110000001000101110 -11000000000010111001100000010010 -11100010000000101000111100000000 -00101110110000000000101110001001 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101110100001000100 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000100000010 -11100010001000001000101100000000 -00101110110000000000101110000000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101110000000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10110011000000000010110011000000 -00001011001100000000001001001100 -00000000101100110000000000100100 -11000000000010010001000000000010 -11000000000000001000001100000000 -00101100110000000000101100000000 -00000010010011000000000010110011 -00000000001011001100000000001011 -00110000000000101100001000000101 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000011010110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000010011111011000000000011 -11100000000010001100101100000000 -00111110110000000000111110000000 -00000011111011000000000011111011 -00000000001101101100000000001111 -10110000000000111100000000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000001111110000000001111111 -11000000000011110111000000000011 -11110000000000001111111100000000 -00111111110000000000111111000000 -00000011111111000000000011111111 -00000000001111111100000000001101 -11110000000000111110100000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11111111100000000011111111100000 -00001111111110000000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111100 -10000000001111111110000000001111 -11111000000000111111000000000001 -01100000000000000000000000000000 -00000000000000000000000000000000 -10100000000100001110111000000000 -10111011100000000010111011100000 -00001011101110000000001011101110 -00000000101110111000000000101110 -11100000000010111011100000000010 -11101110000000001011101110000000 -00101110111000000000101110111000 -00000010111011100000000010111001 -10000000001011101110000000001011 -10111000000000101110100000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010100011000000000010110010 -00000000001011001100000000001011 -00110000000000101110001000000001 -00110000000000000000000000000000 -00000000000000000000000000000000 -11100000000101011010110000000000 -10111011000000000010111011000000 -00001011101100000100001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111100000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000100011110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111000 -10000000001111101100000000001111 -10110000000000111100000000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11111111000000000001111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111100 -10010000001111111100000000001111 -11110000000000111111100000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111001 -00000000001111101100000000001111 -10110000000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10111011000000000010111011000000 -00001011101100000000001110101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111001 -00000000001011101100000000001011 -10110000010000101111001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000000001 -10110011000000000010110011000000 -00001001001100000000001001001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010010000 -00000000001011001100000000001011 -00110000000000101111100000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00100000000000010001111000000100 -10110111100000000010110111100000 -00001011011110000000001010011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110101 -10000000001011011110000000001011 -01111000000000101101100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -01001000000010000000110000000000 -11110011000000000011110011000000 -00001111001100000000001111001100 -00000000111100110000000000111100 -11000000000011110011000000000011 -11001100000000001111001100000000 -00111100110000000000101100110000 -00000011110011000000000011110010 -00100000001111001100010000001111 -00110000000000111101001000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000011011011110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111101000000000010 -01100000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111010110000 -00000011111011000000000011111010 -00000000001111101100000000001111 -10110000000000111110001000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000100011001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110110 -00000000001011011100000000001011 -01110000000000101101001000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000000001001111000000000 -10110111100000000010110111100000 -00001011011110000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000010001101111000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -11000000001011001100000000001011 -00110000000000101101001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11111010000000000011111010000000 -00001111101000000000001111101000 -00000000111110100000000000111110 -10000000000011111010000000000011 -11101000000000001111101000000000 -00111110100000000000111110100000 -00000011111010000000000011111110 -11011000001111101000000000001111 -10100000000000111111101100000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111101001000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000100001110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101110000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000100011111101 -00000000001111100100000000001111 -10010000000000111110011000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000001011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110011000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000100001110000000000000 -10111000000000000010111000000000 -00001011100000000000001011100000 -00000000101110000000000000101110 -00000000000010111000000000000010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000010111000000000000010111000 -00000000001011100000000000001011 -10000000000000101100111000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000001011100010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00001100001011100100000000001011 -10010000000000101100011000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101001010010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -11000000001111100100000000001111 -10010000000000111110100000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000000001010010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00100000001111100100000000001111 -10010000000000111100101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000001000010100000000000 -10111010000000000010111010000000 -00001011101000000000001011101000 -00000000101110100000000000101110 -10000000000010111010000000000010 -11101000000000001011101000000000 -00101110100000000000101110100000 -00000010111010000000000010111010 -00000000001011101000000000001011 -10100000000000101100101000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100101000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00100000000000010001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000010001011 -01110000000000101100100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00101000000010000001111000000000 -11110111100000000011110111100000 -00001111011110000000001111011110 -00000000111101111000000000111101 -11100000000011110111100000000011 -11011110000000001111011110000000 -00111101111000000000111101111000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01111000000000111100101000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000001011111111000000000 -11111111100000000011111111100000 -00001111111110000000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011110111 -10000000001100111110000000001111 -11111000000100111101000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001101011100000000001011 -01110000000000101110101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010111111 -00000000001010011100000000001011 -01110000000000101100010000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01100000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00001000001011001100000000001011 -00110000000000101101100000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10101000000101011010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001110101100000000001111 -10110000000000111110101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001001101100000000000111 -10110000000000111110010000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -00000001000100001111110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001100111100000001001111 -11110000010100111110000001100100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000001000001000110110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010110011 -00000000001000101100000000001011 -10110000000000101110000101000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010110110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001000101100000001001011 -10110000010000101110000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00001000000000000000110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010111011 -00000000001000001100000000001011 -00110000000000101100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000010000110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001100101100000000001111 -10110000000000111110000000000010 -00010000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000101111111100000000001111 -11110000000000111110100000000010 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000000011111111000000000 -11111111100000000011111111100000 -00001111110110000001001101111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111111000000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110111000000000 -10111011100000000010111011100000 -00001011100110000000001000001100 -00100000101110111000000000101110 -11100000000010111011100000000010 -11101110000001001011101110000000 -00101110111000000000101110111000 -00000010111011100000000010111011 -10000000001011101110000000001011 -10111000000000101110000000000010 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10110011000000000010100011000000 -00001010001100000000001001001100 -10000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000001 -00101100110000000001101100110000 -00000010110011000000000010110011 -00000000001011001100000000001010 -00110000000000101010001000000001 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010110000000000 -10111011000000000010111011000000 -00001011101100001000001000101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111000000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -01000000000101011110110000000000 -11111011000000000011111011000000 -00001111101111000000001101101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100000000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11111111000000000011111111000000 -10001111111110100000001110111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00010011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111111100000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011000000000011111011000000 -00001111101110100010101100101100 -00100010110010110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10111011000000000010111011000000 -00001011001110000000001000101111 -00000000100010110000000000111110 -11000000000010111011000000000010 -11101100000010001011101100000000 -00101110110000000000101110110000 -00000011111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10110011000000000010110011000000 -00001011000001000000001000001101 -00000000100000110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101111000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00100000000000010001111000000000 -10110111100000000010110111100000 -00001011011010000000001000011110 -00100000100001111000000000101001 -11100000000010110111100000000010 -11011110000000011011011110000000 -00101101111000000000101101111000 -00000010100111100000000010110111 -10000000001011011110000000001011 -01111000000000101100100000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01001000000000000000110000000000 -11110011000000000011110011000000 -00001111000100000000001100001100 -00000000110000110000010001101100 -11000000000011110011000000000011 -11001100010000001111001100000000 -00111100110000000000111100110000 -00000010110011000000000011110011 -00000000001111001100000000001111 -00110000000000111101001000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000111011011110000000000 -11111111000000000011111111000000 -00001111011000000000001111111100 -01000000111111110000000000111111 -11000000000011111111000000000011 -11111100000100001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111101000000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011110110000000000 -11111011000000000011111011000000 -00001111001010000000001100001100 -00000000110010110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000100011001110000000000 -10110111000000000010110111000000 -00001011011100000000001101011100 -00000000101001110000000000111001 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101101001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000000001001111000000000 -10110111100000000010110111100000 -00001010011110000010001000011110 -00000000100001111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101100100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110011000000000010110011000000 -00001011001100100000101001001100 -00000000000000110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000100100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101101101000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11111010000000000011111010000000 -00001111111000001000001100101000 -00000010110010100000000000111110 -10000000000011111010000000000011 -11101000000000001111101000000000 -00111110100000000000111110100000 -00000011111010000000000011111010 -00000000001111101000000000001111 -10100000000000111111101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011111000000000 -10001111100001000000001111100000 -00000000111110000000000000111010 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111101001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100111 -00000000110010010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000000000010011001000000 -00001011100111001000001011100111 -00000000100010010000000000101110 -01000000000010111001000001000010 -11100100000000001011100100000000 -00101110010000000000100110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101110000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010011001000000 -00001011100110000000001011000101 -00000000100010010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001000000000010010001000000 -00001011000100000000001011000100 -00000010101000010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -00100000000000000000000000000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11111000000000000011011000000000 -00001111100000000000001111100001 -01000000110010000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000111 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111011110010000000000 -11111001000000000011011001000000 -00001111110100000000001111100100 -00000000110110010000000000111110 -01000000000011111001000000000010 -11100100000000001111100100000000 -00111110010000000000110110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110111100000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000001011110010000000000 -11101001000000000011111001000000 -00001111110100000000001111110100 -00000000110010010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100111000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000100001110000000000000 -10111000000000000010111000000000 -00001011100000000000001011100000 -00000010100010000000000000101110 -00000000000011111000000000000010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000010111000000000000010111000 -00000000001110100000000000001011 -10000000000000101100011000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000001011100010000000000 -10100001000000000010110001000000 -00001011000100000000001011000100 -00000000100100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101101001000000001 -01100000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10111001000000000010111001000000 -00001011100100100000001011000100 -00000000100110010000000000101110 -01000000000010101001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001010100100000000001011 -10010000000000101100011000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011110010000000000 -11101001000000000011111001000000 -00001111100101100000001111100100 -00000010110110010000000000111110 -01000000000010111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000000011010010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111010010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001110100100000000001111 -10010000000000111101101100000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000000000011111000000000 -00001111100001000000001111100000 -10000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000100 -00011110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010010100000000000 -10111010000000000010111010000000 -00001011111010001000001011111010 -10000000101110100000000000101110 -10000000000010111010000000000010 -11101000000000001011101000000000 -00101110100000000000101110100000 -00000010111010000000000010111010 -00000000001011101000000000001011 -10100000000000101100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110011000000000010110011000000 -00001011001101100000001011001110 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100001000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000000010001110000000000 -10110111000000000010110111000000 -00001011010100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101100100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001111000000000 -11110111100000000011110111100000 -00001111010110000000001111011110 -00000000111101111000000000111101 -11100000000011110111100000000011 -11011110000000001111011110000000 -00111101111000000000101101111000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01111000000000111100001000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111011000000000011111011000000 -00001111100100000000001111101000 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000101011111111000000000 -11111111100000000011111111100000 -00001111011110000000001100110110 -00000000110011111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111101100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110000000000 -10110111000000000010110111000000 -00001011011101000000001101011100 -00000000100001110000000000111101 -11000000000011110111000000000010 -11011100000000001011011100000000 -00111101110000000000111001110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101110101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110111000000000010110111000000 -00001010011000000000001001011000 -00000000100001110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001010 -01110000000000101100000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00100000000101001100110000000000 -10110011000000000010110011000000 -00001011001000010000101000001000 -00000000100000110000000000001000 -11000000000000100011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011010110000000000 -10111011000000000011111011000000 -00001111000100000000001001101000 -00000010110010110000000000101110 -11000000000010111011000000000011 -11101100000000001111101100000000 -00111110110000000000101110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11111011000000000011111011000000 -10001111100101100000001111101100 -00000000111110110000000000111110 -11000000000111111011000000000011 -11101100000001001111101100000000 -00111010110000000000111010110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110000000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -00000001000000001111110000000000 -11101111000000000011111111000000 -00001111110100000000001100110010 -00000000111111110000000000111111 -11000000000011111111000001000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111100000001000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000001000001000110110000000000 -10111011000000000010111011000000 -00001011100011000000001010101001 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000100001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101110000001000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000000000010111011000000 -00001011100110000000001000100101 -01000000101010110000000000101110 -11000000000010111011000000000110 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101110100000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10110011000000000010110011000000 -00001011000100000000101000001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100101000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000011010110110000000000 -11111011000000000011111011000000 -00001111100000000000001100000000 -00000000111010110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100000000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11111111000000000011111111000000 -00001111110000000000001110111000 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000001111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111110100000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000011011111111000000000 -11111111100000100011111111100000 -00001101111110000000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111111000000000001 -01100000000000000000000000000000 -00000000000000000000000000000000 -11100000000000001110111000000000 -10111011100000000010111011100000 -00001011101110000000001011101110 -00000000101110111000000000101110 -11100000000010111011100000000010 -11101110000000001011101110000000 -00101110111000000000101110111000 -00000010111011100000000010111011 -10000010001011101110000000001011 -10111000000000101111000000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -11001000000001011100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001001001100000000 -00101100110000000000101100110000 -00000010100011000000000010110011 -00000000001011001100000000001011 -00110000000000101111001000000001 -00110000000000000000000000000000 -00000000000000000000000000000000 -11100000000101011010110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111000000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000101011110110000000000 -11111011000000000011111011000000 -00001101101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000100001111 -10110000000000111100000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000010000 -11111111000000000011111111000000 -00000111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000001000111111100000000100 -01000000000000000000000000000000 -00000000000000000000000000000000 -01010100000100001010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000110110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000001000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010010011000000000010110011 -00000000001011001100000000001001 -00110000000000101111000100000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -10110000000000010001111000000000 -10110111100000000010110111100000 -00001011011110000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101111111000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01001000000000000000110000000000 -11110011000000000011110011000000 -00001111001100000000001111001100 -00000000111100110000000000111100 -11000000000011110011000000000011 -11001100000000001111001100000000 -00111100110000000000101100110000 -00000011110011000000000011110011 -00000000001111001100000000001111 -00110000000000111101001100000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000101011011110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111101000000000010 -00100000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111010110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11001000000100011001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000011110111000000000011110111 -00000000001011011100000000001111 -01110000000000111111001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001001111000000000 -10110111100000000010110111100000 -00001011011110000000001011011110 -00000000101001111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101100100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010100011000000000010100011 -00000000001011001100000000001010 -00110000000000101001101000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11111010000000000011111010000000 -00001111101000000000001111101000 -00000000111110100000000000111110 -10000000000011111010000000000011 -11101000000000001111101000000000 -00111110100000000000111110100000 -00000010111010000000000010111010 -00000000001011101000000000001011 -10100000000000101111101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111101001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10001000000100001110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000110110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000000011 -10010000000000101110000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010111001000000 -00001001100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -00100000000000000000000000000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000111 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000011111100100000000001111 -10010000000000111110111000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000011011110010000000000 -11111001000000000011111001000000 -00001111100100000000001110100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011101001000000000111111001 -00000000001111100100000000001111 -10010000000000111110111000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000000001110000000000000 -10111000000000000010111000000000 -00001011100000000000001011100000 -00000000111010000000000000101110 -00000000000010111000000000000010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000010111000000000000010111000 -00000000001011100000000000001111 -10000000000000111100011000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -01001000000001011100010000000000 -10110001000000000010110001000000 -00001011000100000000001010000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010100001000000000010110001 -00000000001011000100000000001011 -00010000000000101101001000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101010010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001010 -10010000000000101000011000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101001010010000000000 -11111001000000000011111001000000 -00001111100100000000001110100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011101001000000000010111001 -00000000001111100100000000001011 -10010000000000101110100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01101000000000001010010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111010010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111101101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000010001111100000000000001111 -10000000000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000001000010100000000000 -10111010000000000010111010000000 -00001011101000000000001011101000 -00000000101110100000000000101110 -10000000000010111010000000000011 -10101000000000001011101000000000 -00101110100000000000101110100000 -00000010111010000000000010111010 -00000000001011101000000000001011 -10100000000000101100001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100001100000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00100000000000010001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -10011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000100101100100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00101000000000000001111000000000 -11110111100000000010110111100000 -00001111011110000000001111011110 -00000000111101111000000000111101 -11100000000011110111100000000011 -11011110000000001111011110000000 -00111101111000000000111101111000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01111000000000111100101000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000101011010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -10101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000001011111111000000000 -11111111100000000011111111100000 -00001110111110000000001111111110 -00000000111011111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111101100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001111 -01110000000000101110101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110111000000000010110111000000 -00001010011100000000001011011100 -00000000101001110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101001110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101100010000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01100000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001010 -00110000000000101101001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000101011010110000000000 -11111011000000000011111011000000 -00001110101100000000001011101100 -00000000111010110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111010110000 -00000010111011000000000011111011 -00000000001111101100000000001011 -10110000000000111110101000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000010000111110110000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -00000001000100001111110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001101 -11110000000000111110000001000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000111110 -11000000000010111011000000000011 -10101100000000001011101100000000 -00101110110000000000101110110000 -00000011111011000000000010111011 -00000000001011101100000000001011 -10110000010000101110000001100000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010110110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101110000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00001000000000000000110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101000 -11000000000010110011000000000010 -10001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000010000110110000000000 -11111011000000000010111011000000 -00001111101100000000001111101100 -00000000111110110000000000101110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001101 -10110000000000111110000000000110 -00010000000000000000000000000000 -00000000000000000000000000000000 -10100000000110011111110000000000 -11111111000000000011111111000000 -00001111111100000000011111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011101111000000000011111111 -00000000001111111100000000001111 -11110000001000111110100000100010 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000000011111111000000000 -11111111100000000011111111100000 -00001101111110000000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111100000000001011111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111111000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110111000000000 -10111011100000000010111011100000 -00001011101110000000001011101110 -00000000101110111000000000101110 -11100000000010111011100000000010 -11111110000000001011101110000000 -00101110111000000000101110111000 -00000010011011100000000010111011 -10000000001011101110000000001011 -10111000000000101110000000000110 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10110011000000000010110011000001 -00001011001100000100001011001100 -00000000101100110000000000001000 -11000000000010110011000000000010 -11001100000000001001001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001010 -00110000000000101010001000000001 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11111100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111000000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -01000000000101011110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111010 -11000000000011111011000000000010 -11101100000000001111101100000000 -00111110110000011000111110110000 -00000001111011000000000011111011 -00000000001111101100000000001111 -10110000000000111101000000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011011111000000000011111111 -00000000001111111100000000001111 -11110000000000111111100000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011000000000011111011000000 -00011111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100001000001111101100000000 -00111110110000000000111110110000 -00000111111011000000000011111011 -00000000001111101100000000001111 -10110000000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10111011000000100010111011000001 -10001011101100000000001011101100 -00001000101110110000000000111110 -11000000000010111011000000000010 -11101111000000001110101100000000 -00101110110000000000101110110000 -00000011111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001101010000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101111000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00100000000000010001111000000000 -10110111100000000010110111100000 -10011011011110000010001011011110 -00000000101101111000000000101001 -11100000000010110111100000000010 -11011110000000001010011110000000 -00101101111000000000101101111000 -00000010100111100000000010110111 -10000000001011011110000000001011 -01111000000000101100100000000100 -00010000000000000000000000000000 -00000000000000000000000000000000 -01001000000000000000110000000000 -11110011000000000011110011000000 -00001011001100000000001111001100 -00000000111100110000000000101100 -11000000000011110011000000000011 -11001100000000001111001100000000 -00111100110000000000111100110000 -00000010110011000000000011110011 -00000000001111001100000000001111 -00110000000000111101001000000010 -00010000000000000000000000000000 -00000000000000000000000000000000 -01000000000111011011110000000000 -11111111000000000011111111000000 -00001111111100000010001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111110000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111101000000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011110110000000000 -11111011000000000011111011000000 -00001110101100000001001111101100 -00000000011110110000000000111110 -11000000000011111011000000000011 -11001100010000001100101100000000 -00111110110000000000101110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000100011001110000000000 -10110111000000000010110111000000 -00000011011100000000001011011100 -00000001101101110000000000111001 -11000000000010010111000000000010 -11011100100000001010011100000000 -00101101110000000000001101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101101001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000000001001111000000000 -10110111100000000010110111100000 -00001011011110000000001010011110 -00000001101001111000000000101101 -11100000000010110111100000000010 -11011110000000001000011110000000 -00101101111000000000101101111000 -00100010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101100100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000100001011001100 -00000000101100110000000000101100 -11000000000010010011000000000010 -11001100000000001010001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101101101000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11111010000000000011111010000000 -00001111101000000000001111101000 -00000000111110100000000000111110 -10000000000011111010000000000011 -11101000000000001100101000000000 -00111110100000000000111110100000 -00000011111010000000000011111010 -00000000001111101000000000001111 -10100000000000111111101000000100 -01010000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011111000000000 -00001111100000000001001111100000 -00000100111110000000000000111010 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111101001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001100100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000111010010000000000101110 -01000000000010111001000000010010 -11010101000000001000100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101110000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00011000000000010010010000000000 -10111001000000000010111001000000 -00011011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001000100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100111000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001000000000110110001000000 -00001011000100000000001011000100 -00000000101000010000000000101100 -01000000000010110001000000000010 -11000100001000101000000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100101000000101 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000011000010000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11101010100000001100100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000011011110010000000000 -11111001000000000011111001000000 -00001111100100000000001011100100 -00000000111010010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110011000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000001011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000101110010000000000111110 -01000000000011111001000000000011 -11110110000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100011000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000100001110000000000000 -10111000000000000010111000000000 -00001011100000000000001011100000 -00000000101110000000000000101110 -00000000000010111000000000000010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000110111000000000000010111000 -00000000001011100000000000001011 -10000000000000101100111000000110 -00100000000000000000000000000000 -00000000000000000000000000000000 -00001000000001011100010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000100101100010000000001101100 -01000000000010110001000000000010 -11000101000000001011000100000000 -00101100010000000000101100010000 -00000000110001000000000010110001 -00000000001011000100000000001010 -00010000000000101101001000000001 -00100000000000000000000000000000 -00000000000000000000000000000000 -00011000000100011010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000011011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011110010000001000 -11111001000000000011111001000000 -00001111100100000000001011100100 -00000001101110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000010111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110100000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -00101000010000011010010000000000 -11111001000000000011111001000000 -00001111100100000010001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111101001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000100000001011100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111100001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010010100000000000 -10111010000000000010111010000000 -00001011101000000001001011101000 -00000000111010100000000000101110 -10000000000010111010000000000010 -11111000000000001011101000000000 -00101110100000001000101110100000 -00000010111010000000000010111010 -00000000001011101000000000001011 -10100000000000101100101000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000001100110000000000001100 -11000000000010110011000000000010 -11000100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100101000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000000010001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11010101000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101110000000000100 -01000000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001111000000000 -11110111100000000011110111100000 -00001111011110000000001111011110 -00000000111101111000000001111101 -11100000010011110111100000100011 -11010110000000001111011110000000 -00111101111000000000111101111000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01111000000000111110001000000010 -00100000000000000000000000000000 -00000000000000000000000000000000 -00001000000011011010110000001000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111010110000000000111110 -11000000000011111011000000000011 -11100100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001011 -10110000000000111100001000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000001011111111000000000 -11111111100100000011111111100100 -00001011111110010000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11110110000000001100111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111100000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110000000000 -10110111000000000010110111000000 -00001011011100000100001011011100 -01010000101101110000000000101101 -11000000000010110111000000000010 -11010101000000001010011100000000 -00101101110000000000101101110000 -00000001100111000000000010110111 -00000000001011011100000000001011 -01110000000000101110001000000110 -00100000000000000000000000000000 -00000000000000000000000000000000 -00000000000000001001110000000000 -10110111000000010010110111000000 -00000010011100000010001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11000100000000001001011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101000000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00100000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000100101100110000001000101100 -11000000000010110011000000000010 -11000100000000001011001100000000 -00101100110000000000101100110000 -00000000100011000000000010110011 -00000000001011001100000000000011 -00110000000000101100100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000101011010110000000000 -11111011000000000011111011000000 -00001111101100000000001011101100 -00000000111110110000000000001110 -11000000000011111011000000000011 -11000100000000001101101100000000 -00111110110000000000101110110000 -00000010111011000000000011111011 -00000000001111101100000000001011 -10110000000000111110101100000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000100111110 -11000000010011111011000000000011 -11101100000000001110101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110000000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -00000001000100001111110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11110100100000001101111100000000 -00111111110000000001111111110000 -00000011101111000000000011111111 -00000000001111111100000000001111 -11110000000000111100100001000100 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000001000001000110110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000111110 -11000000000010111011000000000010 -11101110000000001000101100000000 -00101110110000000000101110110000 -00000011101011000000000010111011 -00000000001011101100000000001011 -10110000000000101110100001000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000000000010101011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101000000000001001101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101110000000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000000000 -10110011000000000010110011000000 -00011011001100000000001011001100 -00000001101100110000000000101000 -11000000000010110011000000000010 -11001100000000001000001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000011011 -00110000000000101100001000000100 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000011010110110000000000 -11111011000000000011101011000000 -00001111101100000000001111101100 -00000000111110110000000000101110 -11000000000011111011000000000011 -11101100000000001101101100000000 -00111110110000000000101110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100000000000011 -00010000000000000000000000000000 -00000000000000000000000000000000 -10100000000110011111110000000000 -11111111000000000011111111000000 -00001111111100000000011111111100 -00000000111111110000000001111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000001111111110000 -00000011101111000000000011111111 -00000000001111111100000000011111 -11110000000000111110100000000101 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11101111100000000011111111100001 -10001111111110000000001101111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111111000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001110111000000000 -10111011100000000011101011100000 -00001011101110000000001011101110 -00000000101110111000000000101110 -11100000000010111011100000000010 -11101110000000001011101110000000 -00101110111000000000101110111000 -00000011111011100000000010111011 -10000000001111101110000000001111 -10111000010000101110000000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10100011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00100100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101110001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010110000000000 -10111011000000000010101011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010101011000000000000111011 -00000000001010101100000000001010 -10110000000001101111000000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000101011110110000000000 -11101011000000000011111011000000 -00001111101100000000001101101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000010111011000000000011111011 -00000000001011101100000000001011 -10110000000000111100000000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11111111000000000011111111000000 -00001111111100000000000111111100 -00000000111111110000000000111111 -11000000000001111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111111100000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000010000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000010001010010110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101111100100000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -01100000000000010001111000000000 -10110111100000000010110111100000 -00001011011110000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101101100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -01001000000010000000110000000000 -11110011000000000011110011000000 -00001111001100000000001111001100 -00000000111100110000000000111100 -11000000000011110011000000000011 -11001100000000001111001100000000 -00111100110000000000111100110000 -00000011110011000000000011110011 -00000000001111001100000000001111 -00110000000000111101001000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000111011011110000000000 -11111111000000000011111111000000 -00001111111100000000011111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111101000000000010 -01100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011110110000000000 -11111011000000000011111011000000 -00001110101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000001111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110101000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000100011001110000000000 -10110111000000000010110111000000 -00001011011100000000001111011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001110011100000000001111 -01110000000000111101001000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000000001001111000000000 -10110111100000000010110111100000 -00001010011110000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -01000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101111000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001010001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000100100110000 -00000010110011000000000010110011 -00000000001010001100000000001010 -00110000000000101001001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11111010000000000011111010000000 -00001110101000000000001011101000 -00000000111110100000000000111110 -10000000000011111010000000000011 -11101000000000001111101000000000 -00111110100000000000111110100000 -00000011111010000000000011111010 -00000000001111101000000000001011 -10100000000000101111101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001110100000000001001111 -10000000000000111101001000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000000000000111001000000 -00001011100100000000001011100100 -00000000100110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101110000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000000000000010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -00100000000000000000000000000000 -00000000000000000000000000000000 -10111000000011000110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000110110010000000000111110 -01000000000011111001000000000010 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110011000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -10011000000001011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110011000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000100001110000000000000 -11111000000000000011101000000000 -00001011100000000000001011100000 -00000000101110000000000000101110 -00000000000010111000000000000010 -11100000000000001011100000000000 -00101110000000000000001110000000 -00000010111000000000000011111000 -00000000001011100000000000001111 -10000000000000101100111000000100 -00010000000000000000000000000000 -00000000000000000000000000000000 -00001000000001011100010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10101001000000000010101001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010101001 -00000000001011100100000000001010 -10010000000000101100011000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011110010000000000 -10111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000010111001 -00000000001111100100000000001011 -10010000000000111110100000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000000011010010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010010100000000000 -10111010000000000010111010000000 -00001011101000000000001011101000 -00000000101110100000000000101110 -10000000000010111010000000000010 -11101000000000001011101000000000 -00101110100000000000101110100000 -00000010111010000000000010111010 -00000000001011101000000000001011 -10100000000000101100101000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100101000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000000010001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101100100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001111000010000 -11110111100000000011110111100000 -00001111011110000000001111011110 -00000000111101111000000000111101 -11100000000011110111100000000011 -11011110000000001111011110000000 -00111101111000000000111101111000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01111000000000111100101000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000111111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000001000111100001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000001011111111000000000 -11111111100000000011111111100000 -00001111111110000000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111101000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110001000000 -10110111000000000010110111000000 -00001011011100000000001110011100 -00000000101101110000000001101101 -11000000000011100111000000000010 -11011100000000011011011100000000 -00101101110000000000101101110000 -00000011110111000000000011110111 -00000000001011011100000000001110 -01110000000000111110101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00010000000000001001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101100010000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01100000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001010001100 -00000000101100110000000000101100 -11000000000010100011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010100011000000000010100011 -00000000001011001100000000001010 -00110000000000101001100100000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10111000000101011010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000001000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000010111011000000000010111011 -00000000001111101100000000001011 -10110000000000101110101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11111011000000000011111011000000 -00001111101100000000001110101100 -00000000111110110000000000111110 -11000000000011101011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000011001110 -10110000000000111110010100000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -10010000000100001111110000000000 -11111111000000000011111111000000 -00001111111100000000001110111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000001111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111110000001000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000001000001000110110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000000011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101110000001100000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000001110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101010110000000000101110110000 -00000010111011000000000110111011 -00000000001011101100000000001011 -10110000000100101110000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000011000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -10000000000011010110110000000000 -11111011000000000011111011000000 -00001111101100000000001110101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000101110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110000000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000010000111111110000 -00000011111111000000000011111111 -00000000001111111100000000011111 -11110000000000111110100000000111 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111011000000000 -11001111100000000011001100000000 -00001000111110000000001100111110 -00000100111111111000010000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111111000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001110010000000000 -10001010000000000010001010000000 -00001000101100000000101000101110 -00000000101110111000000000101110 -11100000000010111011100000000010 -11101110000000001011101110000000 -00101110111000000000101110111000 -00000010111011100000100010111011 -10000000001011101110000000001011 -10111000000000101110000000000110 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011110110000000010 -10001011000000000010000000000000 -01001000001100000000001000001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000110110011000000000010110011 -00000000001011001100000000001011 -00110000000000101110001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010011000000000 -10001011000000000010001011010000 -00001000001100000100001000101100 -00000000101110110000000100101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000010000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111000000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000101011110111110000100 -11000010100000001011001000000000 -00101100101100000000001100101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000001001111101100000100001111 -10110000000000111101000000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011010000000000 -11111110101000100011111100000000 -00101111111100000010001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000100111111110000 -00010011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111111100000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110100000000 -11001011000100000011000011010010 -00001000101100000000001011101100 -00000000111110110000000000111110 -11000000010011111011000001000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000010111011 -00000000001111101100000000001111 -10110000000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010000110010000000 -10001010000000100010001011000011 -00001000101111011000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000001000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100010000000000 -10000011000010010010000001000000 -00101000001110000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101111000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00100000000000010001001000000010 -10001110100000000010000111100100 -00001000011110000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000100010110111 -10000000001011011110000000001011 -01111000000000101100100000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -01001000000010000010110000000000 -11000011000000010011001000000100 -00101100001100010000001111001100 -00000000111100110000000000111100 -11000000000011110011000000000011 -11001100000000001111001100000000 -00111100110000000000111100110000 -00000011110011000100000011110011 -00000000001111001100000000001111 -00110000000000111101001000000010 -00010000000000000000000000000000 -00000000000000000000000000000000 -01000000000111011011110000000010 -11110100000000101011111110000100 -00001111111100010000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000010 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111101000000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011100010000000010 -11001011000000000010001001010010 -01001100101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000000111101100000000001111 -10110000000000111100001000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000100011001010000000000 -10001110000000000010000101000000 -00001000011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000100101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101101001000000110 -01000000000000000000000000000000 -00000000000000000000000000000000 -11000000000000001011111000100000 -10000111100000000010000110100010 -00001000011110000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000001101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101100100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100111000000000 -10000000010010001010000011000000 -00001000001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101101101000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011001100100000000 -11001110010000010011001010010000 -00101100101000000000001111101000 -00010000111110100000000000111110 -10000000000011111010000000000011 -11101000000000001111101000000000 -00101110100000000000111110100000 -00000011111010000000000011111010 -00000000001111101000000000001111 -10100000000000111111101000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000100000 -11111000000000000011110000010010 -00001111100000000000001111100000 -00000100111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111101001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110011000000000 -11001001000100000011001011000100 -00001100100111000100001100100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110011100001000 -10001001110000000010001001110000 -00101000100110000000101000100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000010001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101110000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010001000010 -10000011010000000010001001000000 -01001000000100000000001000100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100111000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000010011000000000 -10000001010000001010000011001000 -00001000000101000010101000000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000010010110001 -00000000001011000100000000001011 -00010000000100101100101000000101 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000011010110000100000000 -11001000010000010011000000000101 -00001100101001000000001100100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -01111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111011111010000100000 -11111101000000000011111001010000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -01000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110011000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000001011110010000000000 -11001001000000000011001001000000 -00001100100100000000000111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000000111100100000000001111 -10010000000000111100011000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000100001100000000000010 -10001000000000001010001000000000 -00001000110000000000001011100000 -00000000101110000000000000101110 -00000000000010111000000000000010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000010111000000000000010111000 -00000000001011100000000000001011 -10000000000000101100111000000110 -00100000000000000000000000000000 -00000000000000000000000000000000 -00001000000001011101010000000010 -10000101000000000010000101000000 -00001000010100000100001001000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001001000100000000 -01101100010000000000001100010000 -00100000110001000000000010110001 -00000000001011000100000000001011 -00010000000000101101001000000001 -00100000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010011000001000 -10000101000000000010000101000000 -00001000111100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000100110010000 -00000000111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011110010010000010 -11001001001000000011001001101000 -00101100100100000000001101100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001101100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110100000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -00101000000000011010010000100100 -11111001100101000011111001001000 -00001111100100000000001111100100 -00000100111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111101001000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000100000000 -11001000110001000011001000100000 -00001111100000000000001100100000 -00001000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000001010011111000 -00000000000111100000000001001111 -10000000010000111100001000000100 -00000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010010101100000000 -10001010000000000010001010001000 -00001011101000000000001000101000 -00000000101110100000000000101110 -10000000000010111010000000000010 -11101000000010001011101000000010 -00101110100000000000101110100000 -00000010111010000000000010111010 -00000000001011101000000000001011 -10100000000000101100101000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010110110101000000 -10000011000000000010000011100000 -00001011001110000000001000001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100101000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000000010001110000000000 -10000111000000001010000111000000 -00001011011111000000001000011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000010 -00101101110000000000101101110000 -01000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101110000000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001101000000010 -11001111100000001011000111100000 -00001111111010010000101100011110 -00001000111101111000000000111101 -11100000100011110111100000000011 -11011110000000001111011110000000 -00011101111000000000111101111000 -00000011110111100000100011110111 -10000000001111011110000000001111 -01111000000000111110001000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010000000000000 -11111000000000000011111010000000 -00001111101000000010001111101100 -00000000111110110000000000111110 -11000000000011111011000000000010 -11101100000001001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001011101100000000001111 -10110000000000111100001000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000001011111111000000000 -11001111100000000011001111100100 -00001100111110000000001010111110 -01000000111111111000001000011111 -11100000100001111111100000000011 -11111110000000001111111110010000 -00111111111000000000111111111001 -00000010111111100100100011111111 -10000000001111111110000000001011 -11111001000000111100000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000000011001110000000000 -10000111001010000010000101000010 -00001000011100100000001000011100 -00000000001101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110001 -00010010010111000000000010110111 -00000000001011011100000000001011 -01110000000000101110101000000110 -00100000000000000000000000000000 -00000000000000000000000000000000 -00000000000100001001100000000000 -10000111000000010110000111000000 -10001000010000000100001000011100 -00000000101101110000000000100101 -11000000000010110111000000000010 -11011100000000001011011100000010 -00101101110000000000101101110000 -00100000110111000000100010110111 -00000000001011011100000000001011 -01110000001000101100000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00100000000101001110001001000000 -10001000000000100100001000110000 -00001000100000000000001000001100 -00000000101100110000000001100100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000010000100100110000 -00000010010011000000000010110011 -00000000001011001100000100001011 -00110000000000101100100100000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000101011010110000000010 -11001001010000010011001011000000 -00001100101100000000100100101100 -00000000111110110000000000110110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000001111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110110100000000 -11111011000000000011111011000000 -00001111100000000000001111101100 -00000000111110110000000100111110 -11000000010011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00010011011011000000000011111011 -00000000001111101100000001001111 -10110000000000111110000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000001000100001111110000100000 -11001101000010000011001101000010 -01001100111100000000001101111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111100100001000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000001000001000110010110010000 -10001000010000000010001000010000 -00001000101000000000011000101100 -00000000101110110000000000101110 -11000000000010111011000001000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101110100001000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010001000000010 -10001000100010000010001010110000 -00001000101110000010001000101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101010110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101110000000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000000000000010 -10000011000000001010000000000000 -01001000000000000000001000001100 -00000100101100110000000000101100 -11000000000010110011000000010010 -11001100000000001011001100000000 -00001100110000000000101100110000 -00000000110011000000000110110011 -00000000001011001100000001001011 -00110000000000101100001000000101 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000001010100100000000000 -11000000000000000011000011000000 -01001100000100000000101100101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100000000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011111000000000000 -11111100000000000011111100000000 -00000111110000000100001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000010000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111110100000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11111111100000000011111111100000 -00001110111110000000001101111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001101111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000001111111110000000001111 -11111000000000111111000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001110111000000000 -10111011100000000010111011100000 -00001011101110000001001011101110 -00000000101110111000000000101110 -11100000100010111011100000000010 -11101110000000001011101110000000 -00101110111000000000101110111000 -00000010111011100000000010111011 -10000000001011101110000000001011 -10111000000000101110000000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10110011000000000010110011000000 -00001010001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00100100110000001000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101110001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000100111011000000000000111011 -00000000001011101100000000001011 -10110000000000101111000000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000101011110110000000000 -11111011000001010011111011000000 -01001110101100000000001101101100 -00000000111110110000000000111110 -11000000000011111011000001000011 -11101100000000001101101100000000 -00111110110000000000111110110000 -00000011111011000001000011111011 -00000000001111101100000000001111 -10110000000000111100100000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11111111000000000011111111000000 -00000111111100000000001011111100 -00000000111111110000000000011111 -11000000000001111111000000000011 -11111100000000001111111100000000 -01111111110000000000111111110000 -00010011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111111100000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011000000000011111011000000 -00001110101100000000001110101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010010110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101111001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10110011000000000010110011000001 -00000011001100000100000011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000001000000110011 -00000000001011001100000000001011 -00110000000000101111000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -01100000000000010001111000000000 -10110111100000000010110111100000 -00001011011110000000001011011110 -00000000101101111000000001101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101101100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -01001000000010000000110000000000 -11110011000000000011110011000000 -00001111001100010000001110001100 -00000000111100110000000001111100 -11000000000011110011000001010011 -11001100000000001111001100000000 -00111100110001000000111100110000 -01000011110011000000000011110011 -00000000001111001100000000001111 -00110000000000111101101000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000111011011110000000000 -11111111000000000011111111000000 -00001111111100000100001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000010000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111101000000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110101000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000100011001110000000000 -10110111000000000010110111000000 -00001011011100000000011011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000001101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101101001000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000001000000001001111000000000 -10110111100000000010110111100000 -00001011011110000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101111000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000100101100110000000000101100 -11000000000010110011000000100010 -11001100000000001011001100000000 -00101100110000000001100100110000 -00000010010011000000000010110011 -00000000001011001100000000001011 -00110000000000101101001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000100101011010100000000000 -11111010000000000011111010000000 -00001111101000000000001111101000 -00000000111110100000000000111110 -10000000000011111010000000000011 -11101000000000001111101000000000 -00111110100000000000111110100000 -00000011111010000000000011111010 -00000000001111101000000000001111 -10100000000000111111101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01001010000000001110000000000000 -11111000000000010011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000001001111 -10000000000000111101001000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001010000100001110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101110000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -00100000000000000000000000000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000010 -11100100000000001011100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110011000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -10011000000001011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110011000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111000000100001110000000000001 -10111000000000000010111000000000 -00001011100000000000001011100000 -00000000101110000000000000101110 -00000000000010111000000000000010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000000111000000000000010111000 -00000000001011100000000000001011 -10000000010000101100111000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000001011100010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -01010000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000100010111001000000000010 -11100100000000001011100100000000 -00101110010000010000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011110010000000000 -10111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110100000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000000011010010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100101000010000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100001010000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000001000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00100000100001010010100000000000 -10111010000000000010111010000000 -00001011101000000000001011101000 -00000000101110100000000000101110 -10000000000010111010000000000010 -11101000000000001011101000000000 -00101110100000000000101110100000 -00000010111010000000000010111010 -00000000001011101000000000001011 -10100000000000101100101000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100101000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000000000010001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000001000010110111 -00000000001011011100000000001011 -01110000000000101100100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001111000000000 -11110111100000000011110111100000 -00001111011110000000001111011110 -00000000111101111000000000111101 -11100000000011110111100000000011 -11011110000000001111011110000000 -00111101111000000000111101111000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01111000000000111100101000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000010 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111000001000 -11111111100000000011111111100000 -00001111111110000000001111111110 -00000000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011111111100000000011111111 -10000000000111111110000000001111 -11111000000000111101000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -11101000000100011001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000100101101 -11000000000110110111000000000010 -11011100000001001011011100000000 -00101101110000000000101101110000 -00000010110111000100000010110111 -00000000001011011100000000011011 -01110000000000101110101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000000001001110000000000 -10110111000000000010110111000000 -00001011011100000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101100010001000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00100000000101001100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000001000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101101101000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000111111011000000000011111011 -00000010001111101100000011001111 -10110000000100111110111000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000010001111101100000100 -00111110110000000000111110110000 -00000011111011000000100011111011 -00000001001111101100000000001111 -10110000001000111110000000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -11000000000100001111110000000000 -11111111000000000011111111000000 -00001111111100000000001111111100 -00000000111111110000000000111011 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111110000001000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000001000001000110110000000000 -10111011000000000010111011000000 -00001011101100000000000011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101110000001000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11101100000000001011101100000001 -00101110110000000000101110110000 -00000010111011000000000010111011 -00000100000001101100000000001011 -10110000000000101110000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000000100 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000100010110011 -00000100001011001100000000001011 -00110000000000101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -10000000000011010110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111010 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110000000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -11100000000111011111110000000000 -11111111000000000011111111000001 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000010000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111110100000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111000000000 -11000100100000100011001111100000 -00001100111010000000001111111110 -00000000110011111000000000111111 -11100000000011111111100000000011 -11111110000000001100111110000110 -00111111111000000000111111111000 -00000011111111100000000011001111 -10000000001111111110000000001111 -11111000000000111111000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001110111000000000 -10001001100001100010001011100001 -00001000101010000000001011101110 -00000010100010111000000000101110 -11100001100010111011100000000010 -11101110000000101000101110000000 -00101110111000000000101110111000 -01000010111011100000010010001011 -10000000001011101110000000001011 -10111000000000101110000000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10011010000000000010010011000000 -00001001001000000000001011001100 -00000000100000110000000000101100 -11000000000010110011000000000010 -11001100000000001000001100000000 -00101100110000001000001100110000 -00000010110011000000001010010011 -00000000001011001100000000001011 -00110000000000101110001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000101011010110000000000 -10011001000000000010011011000000 -01001001101000000010001011101100 -00000000100010110000000000101110 -11000000000010111011000000000010 -11101100000000001000101100000000 -00101110110000010000101110110000 -00000010111011000000000010011011 -00000000001011101100000000001011 -10110000000000101111000000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000101001000110000000000 -11011011100100000011010011000000 -00001101101000000100001111101100 -00000010110010110000000000111110 -11000000000011111011000000000011 -11101100000000001100101100000000 -00111110110000000000101110110000 -00000011111011000000100011011011 -00000000001111101100000000001111 -10110000000000111100000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -11100001000000001011110000001000 -11101100000000010011101111000000 -00001110111000000001001111111100 -00000000111111110000000000110111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000100111111110000 -00010011111111000000000011101111 -00000000001111111100000000001111 -11110000000000111111100000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11001011000000000011001011000000 -00001100101000010010001100101100 -00010000111110110000000000111110 -11000000000011111011000000110011 -11101100000010001111101100000000 -00111110110000000000111110110000 -01100011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001000010110000000100 -10000010000000000010001011000001 -00001000101011000000001000001100 -00000000101110110000000000101110 -11000000000010111011000000000010 -11001100000000001011101100000000 -00101110110000000000101110110000 -00000010110011000000000010111011 -00000000001011101100000000001011 -10110000000000101111001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000000000 -10000000000000000010010011000000 -00001001001010000000001000001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101111000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00100000000000010001111100000000 -10001100110000000010010111110000 -10001001011011000000001000011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000000 -00101101111000000000101101111000 -00100010110111100000010010110111 -10000000001011011110000000001011 -01111000000000101100100000010100 -00000000000000000000000000000000 -00000000000000000000000000000000 -01001000000010000000110000000000 -11000010000000000011010011000100 -00001101001000010000001100001100 -00000000111100110000000000111100 -11000000100011110011000000000011 -11001100000000001111001100000000 -00111100110001000000111100110000 -00000011110011000000000011110011 -00000000001111001100000000001111 -00110000000000111101001000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000111011000110000000000 -11111010000000100011100011000001 -00001010001000000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000010001111101100000000 -00111110110000001000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011110110000000000 -11110000000000000010001011000000 -00001111101000000100001111101100 -00001000011110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000101110110000 -00000011110011100001001011001011 -00000000001111101100000000001111 -10110000000000111100001000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000100011001110000000000 -10110100000000000010000111000000 -00001011011000000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000000 -00101101110000000100101101110000 -00000010110111000000000010000111 -00000000001011011100000000001011 -01110000001000101101001000000100 -01000000000000000000000000000000 -00000000000000000000000000000000 -11000000000000001001111000000000 -10111110100000001010000111100000 -00001011011010000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000001 -00101101111000000000001101111000 -00000010110111100000000010000111 -10000000001011011110000000001011 -01111000000000101100100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10110010000000000010000011000000 -00001011001000000000001011001100 -00000000101100110000000001101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000010000101100110000 -00000010110011000000000010000011 -00000000001011001100000000001011 -00110000000000101101101000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11111110000000000011001010000000 -00001111111000000000001111101000 -00000000111110100000000000111110 -10000000000011111010000000000011 -11101000000000001111101000000010 -00111110100000000000111110100000 -00000011111010000000000011001010 -00000000001111101000000000001111 -10100000000000111111101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000001000 -11111000100000001011111000000000 -00001111100000000000001111100000 -00000100111110000000000000111110 -00000000000011111000000000000011 -11100000000010001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111101001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000000001011001001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000000110010000000000 -10110001000000000010001001000001 -00001011100100000000001110100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000100 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101110000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00011000000001000010011000000001 -10111011100001000010001001100000 -00001011100110000000001011100100 -00000000101110010000000000101010 -01000000000010111001000000000010 -11100100000000001011100100000010 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000010000 -10110001000000000010000001000000 -00001011000100000001001010000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000010011011000100000000 -00101100010000000000101100010000 -00000010110001000000010010110001 -00000000001011000100000000001011 -00010000000100101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000010010110000000000000 -11111000000000000011001000000001 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111011111010000000000 -11111101000000000011111001000000 -00001111100100000000001110100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -01000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110111000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -00011000000001011110010000000000 -11111011000000000011001001000000 -00001111100100000000001111110100 -00000000111110010000000000110110 -01000000000011111001000000000011 -11110100000000001111100100000000 -00111110010000000000111110010000 -00000011111101000000000011001001 -00000000001111100100000000001111 -10010000000000111100111000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -00111100000100001110000000000000 -10111000000000000010001000000000 -00001011110000000000001011100000 -00000000001110000000000000101110 -00000000000010111000000000010010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000010111000000000000010001000 -00000000001011100000000000001011 -10000000000000101100011000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00001000000001011101010000000000 -10111101000000000010010101000001 -00001011010100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000001010000001 -00000000001011000100000000001011 -00010000000000101101001000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10111101100000001010011101000000 -00001011110100000000001011100100 -00010000101110010000000000101110 -01000000000110111001000000100010 -11100100000001000011100100000101 -00101110010000000000100110010000 -00000010111001000000000010001001 -00000000011011100100000000001011 -10010000000000101100011000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000101001010010000010000 -11111001100000000011011001000000 -00001111100100000000001111100100 -00000000111110010000000100110110 -01000000100011111001000000100011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011001001 -00000000001111100100000010001111 -10010000000000111110100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101010000000001010010000000000 -11111001000000000011101001000000 -00001111100100000000001111100100 -00000100111110010000000000101110 -01000000000011111001000000000001 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111101101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101010000100001010000000000000 -11111000000000000011111000000000 -00001111110000100000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000001001111100000000000 -00111110000000000000011110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000100001000010100000000100 -10110010000000000010111010000000 -00001011101000000000001011101000 -00000000101110100000000000101110 -10000000000010111010000000000010 -11101000000000001011101000000000 -00101110100000000000101110100000 -00000010110010000000000010111010 -00000000001011101000000000001011 -10100000000000101100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000000000 -10110011000000100010110011000000 -00001011001000000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000100010110011 -00000000001011001100000000001011 -00110000000000101100001100000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00100000000000010001100000010000 -10110110000000000010110110000000 -00001011011000000000001011011100 -00000000101101110000000000101101 -11000000000010110111000000000010 -11011100000000001011011100000001 -00101101110000000000101101110000 -00000010110111000000000010110111 -00000000001011011100000000001011 -01110000000000101100100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00111000000010000001011000000000 -11110101100000000011110101100000 -00001111010010000000001111011110 -00000000111101111000001000111101 -11100000000011110111100000100011 -11011110000000001111011110000000 -00111101111000000000111101111000 -00000011110111100000000011110111 -10000000001111011110000000001111 -01111000000000111100101000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010000000000000 -11111000000000000011111000000000 -10001111100000000000001111101100 -00010100111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000010 -00111110110000000000111110110000 -01000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000001011111111000000010 -11001111100000000011111111100000 -00001111111110010000001111111110 -00000000111111111001000000111111 -11100000000011111111100000000011 -11111110000000001111111110010000 -00111111111001000000111111111000 -00000011110111100000000011001111 -10000000001111111110000000001111 -11111000000000111101100000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001100001010000 -11010110000100000010110110000000 -00001011011100000000001001011100 -00000100111101110000000100101101 -11000000010010110111000100000010 -11011100000000001011011100000000 -00111101110000000000101101110000 -01010010110111000000010010000111 -00000000001011011100000000001011 -01110000000000101110101000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001011010000000000 -10000101000010000010110101000000 -00001011010110000000011001011100 -00000000101001110000000001101101 -11000000000010110111000000000010 -11011100000000001011011100000010 -01100101110000000001101101110000 -00000010110111000000000010000111 -00000000001011011100000000001011 -01110000000000101100000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01100000000101001100000000000010 -10000000100000000010110000000000 -00001011000100000000001001001100 -00000100101100110000000000101100 -11000000000110110011000001000010 -11001100000100000011001100000100 -00101000110000010000101100110000 -00000010110011000001001010000011 -00000100001011001100000100001011 -00110000000000101101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -10101000000101011010110000000000 -10000011110000000011111011000000 -00001111101000000000001101101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001011101100000000 -00101110110000000000111110110000 -00000011111011000001000011001011 -00000000001111101100000000001111 -10110000001100111110101000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110100000010000 -11111010000010000011111010000000 -01001111101000000000001101101100 -00000000111010110000000100111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -01111110110000000000111110110000 -00000011111011000000000011111011 -00000010001111101100000001001111 -10110000000000111110100000010100 -00110000000000000000000000000000 -00000000000000000000000000000000 -00000001000100001111010000000000 -11111101000000000011001101000000 -00001111110000000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000100111111110000 -00010011111111000000100011111111 -00000000001111111100000000001111 -11110000000000111100000001000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11000001000001000110000000010000 -10111000000000000010001000000000 -00001011100000000100001011101100 -00010000101110110000000000101110 -11000001000110111011000000010010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000010111011000001000010111011 -00000000001011101100000000001011 -10110000000000101110000001000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -11000000000001010010110000001000 -10111011000000000010001011000000 -00001011101100000000001010101100 -00000000101110110000000000101110 -11000000010010101011000000010010 -11101100000010001011101100000000 -00101110110000000000101110110000 -00000000111011000000000010111011 -00000000001011101100000001001011 -10110000000100101110000000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00001000010000000000100000000000 -10111010000000001010000010000000 -01001011001100000001001011001100 -00000000101100110000000000101100 -11000000000010110011000000010010 -11001100000000001011001100000001 -00101100110000000000101100110000 -00000010110011000000010010110011 -00000000001011001100000001001011 -00110000000000101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000011000110010000000000 -11111001000000000011001001000000 -00001111100100000000001110101100 -00000000111110110000000000111110 -11000000000011101011000000000011 -11101100000010001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000011100000000000110 -00000000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011101000000000000 -01111100000001000011111100000001 -00001111110100000100001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000011111111100000000 -00111111110000010000111111110000 -01000011111111000001000011111111 -00000000001111111100000000001111 -11110000010000111110100000000010 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000001011111111000000010 -11001111100000000011111111100000 -10001111111110000000001101111110 -00001000111111111000000000111111 -11100000000011111111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111000 -00000011011111100000011011001111 -10000000001111111110000000001111 -11111000000000111111000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001110111000000000 -10001011100000000010111011100000 -00001011101110000001001011101110 -00001000101110111000001100101110 -11100000010010111011100000010010 -11101110000000001011101110000000 -00101110111000000000101110111000 -00010010011011100000000010001011 -10000000001011101110000000001011 -10111000000000101110000000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10001000000001011100110000000000 -10000011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101100110000 -00000010110011000000000010000011 -00000000001011001100000000001011 -00110000000000101110001000000001 -01110000000000000000000000000000 -00000000000000000000000000000000 -11000000000100011010110000000000 -10001011000001000010111011000000 -00001011101100000000001011101100 -00000000101110110000000000100110 -11000000000000111011000001000010 -11101100000000001011101100000000 -00101110110000001000101110110000 -00000110011011000000000010001011 -00000000001011101100000000000011 -10110000000000101111000000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00000000000101011110110000000000 -11001011000000000011111011000000 -00001111101100000000001101101100 -00000000111110110000000000111110 -11000001000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011011011000000010011001011 -00000100001111101100000000001111 -10110000000000111101000000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -11100000000000011011110000000000 -11111111000001000011111111000000 -00000111111100000100001111111100 -00000000111111110000000000101111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00010011111111000001000011111111 -00000000001111111100000000001111 -11110000000000111111100000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000100001010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00011000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00010011111011000000010011111011 -00000100001111101100000000001111 -10110000000000111101000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -11001000000001010000110000000000 -10111011000001000010111011000000 -00001011101100000100001011101100 -00000000111110110000010000101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000000101110110000 -00000000110011000001000010111011 -00000000001011101100000000001011 -10110000000000101111001000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -11100000000001010100110000010000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000001100110000 -00000010110011000000000010110011 -00000000001011001100000100000011 -00110000000000101111100000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -01100000010000010001111000000000 -10110111100000000110110111100000 -00001011011110000000001011011110 -00000000101101111000000000101101 -11100000000010110111100000000010 -11011110000000001011011110000100 -00101101111000000000101101111000 -00000010110111100000000010110111 -10000000001011011110000000001011 -01111000000000101100100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -01001000000010000000110000000000 -11110011000000000011110011000001 -00001111001100010000001111001100 -00000000111100110000000000111100 -11000000000011110011000000000011 -11001100000000001111001100000000 -00111100110001000100111100110000 -00000011110011000000000011110011 -00000000001111001100000000001111 -00110000000000111101001000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000111011011110000000001 -11111111000000000011111111000000 -00000111111100010100001111111100 -00000000111011110000000001111111 -11000000000011111111000000010011 -11111100010000001111111100010000 -00111111110000000000111111110001 -00010111111111000000000011111111 -00000000001111111100000000001111 -11110000000000111101000000000010 -01100000000000000000000000000000 -00000000000000000000000000000000 -10101000000001011100111000000000 -11001011000000000011111011000000 -00001111101100000000001111001110 -00000000110010110000000000111110 -11000000000011111011000000000011 -11001110000000001100101100000000 -00111110110000001000111110110000 -00000011110011100000000011001011 -00000000001111101100000000001111 -10110000000000111110101000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -01001000000100011001110000000000 -10000111000000000010110111000000 -00001011011100000001001011011100 -00000000100001110000000001101101 -11000000000010110111000000000010 -11011100000000001000011100000100 -00101101110000000000100101110000 -00000010110111000000000010000111 -00000000001011011100000000001011 -01110000000000101101001000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -11000000000000001001111000000010 -10000111100000000010110111100000 -00001011011110000000001011011110 -00010011100101111000000000101101 -11100000000010110111100001100010 -11011110000010101000011110000000 -00101101111000000000101101111000 -00000010110111100000011010000111 -10000100001011011110000000001011 -01111000000000101111000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01001000000101001100110000000000 -10000011000000010010110011000000 -00001011001100000000001011001100 -00000000100100110000000000101100 -11000000000010110011000000000010 -11001100000000001000001100000001 -00101100110000000001100100110000 -00000010110011000000000010000011 -00000000001011001100000000001011 -00110000000000101101001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -11101000000101011010100000000000 -11001010000000000011111010000000 -00001111101000000000001111101000 -00000000110110100000000000111110 -10000000000011111010000000000111 -11101000000000001100101000000000 -00111110100000000000111110100000 -01000011111010000000000011001010 -00000000011111101000000000001111 -10100000000000111111101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -01001000000000001110000000000000 -11111000000000100011111000000000 -00001011100000000000001111100000 -00000000111010000000000000111110 -00000000000011111000000000000111 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000001001111 -10000000000100111101001000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000100001110010000000000 -11111001000000000011101001000000 -00001111100100000000001111100100 -00000000111110010000000000111110 -01000000000011111001000000000011 -11100100000001001111100100000000 -00111110010000000000111110010000 -01100011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100001000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000001000110010000000000 -10111001000000000010111001000000 -00001011100100000000001011100100 -00000000100110010000000000101110 -01000000000010111001000000000010 -11100100000000001011100100000000 -00101110010000000000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101110000000000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -00011000000001010010010000000000 -10111001000000000010111001000001 -00001011100100000000001011100100 -00000000101110010000000000101110 -01000000000010111001000000000010 -10100100000000001011100100000000 -00101110010000000000001110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000010010 -11000100000000001011000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -10111000000011010110000000000000 -11111000000000000011101000000000 -00001111100000000000001111100000 -00000000111110000000000000111110 -00000000000011111000000000000011 -11100000000000001111100000000000 -00111110000000000000111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111110111000000011 -01010000000000000000000000000000 -00000000000000000000000000000000 -10011000000111011110010000000000 -11111001000000000011111001000000 -01001111100100000000001111100100 -00000000110110010000000000111110 -01000000000011111001000000000001 -11100100000001001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110011000000110 -01110000000000000000000000000000 -00000000000000000000000000000000 -10011000000001011111010000000000 -11111001000000000011111001000000 -00001111100100000000001111110100 -00000000111110010000000000110110 -01000000000011111001000000000011 -11110100000000001111100100000000 -00111110010000000000111110010000 -00000011111101000000000011111001 -00000000001111100100000000001111 -10010000000000111100011000000001 -01100000000000000000000000000000 -00000000000000000000000000000000 -00111000000100001110000000000000 -10111000000000000010111000000000 -00001011100000000000001011100000 -00000000101110000000000000101110 -00000000000010111000000000000010 -11100000000000001011100000000000 -00101110000000000000101110000000 -00000010111000000000010010111000 -00000000001011100000000000001011 -10000000000000101100111000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -00001000000000001100010000000000 -10110001000000000010110001000000 -00001011000100000000001011000100 -00000000101100010000000000101100 -01000000000010110001000000000010 -11000100000000001010000100000000 -00101100010000000000101100010000 -00000010110001000000000010110001 -00000000001011000100000000001011 -00010000000000101100001000000001 -00110000000000000000000000000000 -00000000000000000000000000000000 -00011000000101011010010000000000 -10111001000000000010111001000000 -00001011100100000000011011100100 -00000000101110010000000100101110 -01000000000010111001000001000010 -11100100000000001011100100000000 -00101110010000010000101110010000 -00000010111001000000000010111001 -00000000001011100100000000001011 -10010000000000101100011000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10100000000101011110010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00010000111110010000010000110110 -01000000000011111001000000000011 -11100100000000001110100100000000 -00111110010000000000111110010000 -00000010111001000000000011111001 -00000000001111100100000000001111 -10010000000000111110100000000100 -01110000000000000000000000000000 -00000000000000000000000000000000 -00101000000000011010010000000000 -11111001000000000011111001000000 -00001111100100000000001111100100 -00000000111110010000000000101110 -01000000000011111001000000000011 -11100100000000001111100100000000 -00111110010000000000111110010000 -00000011111001000000000011111001 -00000000001111100100000000001111 -10010000000000111100101000000000 -01100000000000000000000000000000 -00000000000000000000000000000000 -00101000000100000010000000000000 -11111000000000000011111000000000 -00001111100000000000001111100000 -00000000111110000000000001111110 -00000001000011111000000000000011 -11100000000000001111100000000000 -00111110000000000001111110000000 -00000011111000000000000011111000 -00000000001111100000000000001111 -10000000000000111100101000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010010100000000000 -10111010000000000010111010000000 -00001011101000000000001011101000 -00000000101110100000000000101110 -10000000000010111010000000000010 -11101000000000001011101000000000 -00101110100000000000101110100000 -00000011101010000000000010111010 -00000000001011101000000000001011 -10100000000000101100101000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00101000000001010100110000010000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000100 -00101100110000000000101100110000 -00000010110011000000000010110011 -00000000001011001100000000001011 -00110000010000101100101000000000 -01010000000000000000000000000000 -00000000000000000000000000000000 -10100000010000010001110000000000 -10110111000000000010110111000000 -00011011011100000000001011011100 -00000000101101110000000000001101 -11000000000010110111000000000010 -11011100000000001011011100000001 -00101101110000000000101101110000 -00000000100111000000000010110111 -00000000001011011100000000001011 -01110000000000101110100000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -10101000000010000001111000000000 -11110111100001000111110111100000 -00001111011110000000001111011110 -00000000111101111000000000101101 -11100000000011110111100000000011 -11011110000000001111011110000000 -00111101111000000000101101111000 -01000011110111100000000011110111 -10000000001111011110000000001111 -01111000000000111110101000000010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000111011010110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000100111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100001000000110 -01100000000000000000000000000000 -00000000000000000000000000000000 -01000000000001011111111000000000 -11111111100000000011111111100100 -00001111111110000000001111111110 -00000000111111111000011000111111 -11100000000011101111100000000011 -11111110000000001111111110000000 -00111111111000000000111111111001 -00000011111111100000000011111111 -00100000001111111110000000001111 -11111000000000111100000000000000 -01110000000000000000000000000000 -00000000000000000000000000000000 -10101000000100011001110000000000 -10110111000100000010110111000000 -00001011011100000000001011011100 -00000000101101110001000000101101 -11000000010010110111000000000010 -11011100000010001011011100000000 -00101101110000000000101101110001 -00000010110111000100000010110111 -00000000001011011100000010001011 -01110000000000101110101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -00011000000000001001110000000000 -10110111000000000010110111000001 -00011011011100000000001011011100 -00000000101101110000000000101101 -11000000000010100111000000000010 -11011100000000001011011100000000 -00101101110000000000101101110000 -00000110110111000000000010110111 -00010000001011011100000000001011 -01110000000000101100000000000000 -00100000000000000000000000000000 -00000000000000000000000000000000 -01100000000100001100110000000000 -10110011000000000010110011000000 -00001011001100000000001011001100 -00000101101100110000000000101100 -11000001000010110011000000000010 -11001100000000001011001100000000 -00101100110000000001101100110000 -01000010110011000000000010110011 -00000000001011001100000000001011 -00110000000000101100100000000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10111000000101011010110000000000 -11111011000000000111111011000000 -00001111101100000010001111101100 -00000000111110110000000000111110 -11000000000011101011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111110101000000100 -01100000000000000000000000000000 -00000000000000000000000000000000 -10000000000000001110110000000000 -11111011000000000011111011000000 -00001111101100000000001111101100 -00000000111110110000000000111110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000111110110000 -00000011111011000000000011111011 -00000001001111101100000000000111 -10110000000000111110000000000000 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000000000100001111110000000000 -11111111000000000011111111000000 -00001111111100000000001110111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000000000111111110000 -00000011111111000000000011111111 -00000000001111111100000000001111 -11110000000000111100000001000100 -00110000000000000000000000000000 -00000000000000000000000000000000 -10000001000001000110110000000000 -10111011000000010011101011000000 -00001011101100000000000011101100 -00000000101110110000000001101110 -11000000000010111011000000000010 -11101100000000001011101100000000 -00101110110000000001111010110000 -00000011101011000000110010111011 -00000100001011101100000000001011 -10110000000000101110000001000000 -00010000000000000000000000000000 -00000000000000000000000000000000 -10000000000001010010110000000000 -10111011000000000010111011000000 -00001011101100000000001011101100 -00000000101110110000010000101110 -11000000000010111011000000000110 -11101100000000001011101100000000 -00101110110000010000101110110000 -00000010111011000000000010111011 -00000000001011101100000000001011 -10110000000000101110000000000000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00001000000001000000110000000100 -10110011000000000010100011000001 -00001011001100000000001011001100 -00000000101100110000000000101100 -11000000000010110011000000000010 -11001100000000001011001100000000 -00101100110000000000101000110000 -00010010100011000001100010110011 -00000100001011001100000000001011 -00110000000000101100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -10000000000011010110110000000100 -11111011000000100011111011000000 -10001111101100000000001110101100 -00000000101110110000000000101110 -11000000000011111011000000000011 -11101100000000001111101100000000 -00111110110000000000101110110000 -00000011111011000000000011111011 -00000000001111101100000000001111 -10110000000000111100000000000011 -00010000000000000000000000000000 -00000000000000000000000000000000 -10100000000111011111110000000000 -11111111000000000011111111000001 -00001111111100000000001111111100 -00000000111111110000000000111111 -11000000000011111111000000000011 -11111100000000001111111100000000 -00111111110000010000111011110000 -00000011101111000000000011111111 -00000000001111111100000000001111 -11110000000000111110100100000011 -01110000000000000000000000000000 -00000000000000000000000000000000 -00000000110001010000000000000010 -01110001010000001001110000010000 -00110111000111000101010111000001 -00000011011100000100000010011100 -00010000001101110001010000001101 -11000111000000110111000111000001 -11011100010100000111011100010100 -00010101110000010000000101110000 -01000000010111000001000001010111 -00000100000111011100000000100001 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000110000010100010000100101 -01110001000000010101110001000000 -01010111000100000001010001000100 -00000101011100010000000001011100 -01000000010101110001000001010101 -11000100000001010011000100000001 -01011100010000000101011100010000 -00011100100001000000010000110001 -00000001110111000100000001010111 -00010000000101011100000000010001 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000000100001000000001000000001 -00100000100000000100100000100000 -00010010000110000000000010000010 -00000001001000001000000001001000 -00100000000100100000100000000100 -10000010000000000010000010000000 -01001000011000000001001000011000 -00000100100000100000000101110000 -10000000010010000010000000010010 -00001000000001001000000000100000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00000000100000000000000000000001 -01100000000000000101100000000000 -00010110000000000000010110000000 -00000001011000000000010001010000 -00000000000101100000000000000101 -10000100000000010110000100000000 -01011000000000000001011000001000 -00000001100000000010010101100000 -00000000010110000000000000010110 -00000000000101011000000000110001 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000000010001010100100101000101 -01110010000000010001110010000000 -01000111001000000000010111001000 -00000101011100100000000000011100 -10000000010101110010000000010101 -11001000000001010111001000000000 -01011100110000000001011100100000 -00000101110010000000010101110010 -00000001010111001000000001000111 -00100000000100011100000000010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -00000000110001010100000000000000 -01100000000000000001100000000000 -00000110000000000000000110000000 -00000000011000000000000100011000 -00010000000001100000000000000001 -10000000000000000110000000000000 -00011000000000000000011000000000 -00000000100001000000000001100000 -00000000000110000000000000000110 -00010000000000011000000000110001 -01000000000000000000000000000000 -00000000000000000000000000000000 -00000000110001010100100000000100 -00100010000000010000100010010000 -01000010000000000000000010001000 -00000100001000000000000100001000 -10000000010000100010000000010000 -10001000000001000010001000000000 -00001000101000000000001000000100 -00000000100001000000010000100000 -00000001000010000000000001000010 -00110000000100001000000000100001 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000110001010100111100000101 -01000010100000010101000011100000 -01010100000000000000010100001010 -00000101010000001000000101010000 -11100000010101000010110000010101 -00001010000001010100001111000001 -01010000111000000101010000000000 -00000100000000100000000101000000 -11000000010100000010000001000100 -00101100000000010000000000010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -00000000100000000001110100000001 -00010011000000000101010111000000 -00010101011100000001010101011100 -00000001000001110000000001000001 -11000000000100000111000000000100 -01011100000000010101001100000000 -01000101110000000001010100110000 -00000101010111000000000101010011 -00000000010001011100000000010101 -00110000000001000100000000100000 -01000000000000000000000000000000 -00000000000000000000000000000000 -00000000100001000000010000000000 -00010000000000000001000001000000 -00000100001110000000000100000000 -00000000000000000000000000000000 -01100001000001000000000000000000 -01000000000000000100000110000000 -00000100010000000000010000110000 -00000001000011000000000001000000 -00000001000001001000000000000100 -00010000000000000100000100100001 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000000110000010110000000000010 -00011000000000001000001000000000 -00100000100000000000100000100000 -00000010000010000000000110000010 -00000000001000001000000010001000 -01100000000000100000100000000000 -10000110000000000010000010000000 -00001000001001000000001000001000 -00000000100001100000000000100000 -10000000000010000100000100010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -00000000110001010001000000000101 -01100000000000010101100100000000 -01010110010000000000110110010000 -00000001001001000000000001001001 -00000000010101100100000000010101 -10010000000000010110000000000000 -01011001000000000001011000000000 -00011101100100100000011101100000 -00000001010110010000000001110110 -00000000000101011000000000010001 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000110001010100000000000001 -01100000000000001101100000000000 -00110110001000000000010110000000 -00000111011000000000000011011000 -00000001001101100000000000001101 -10000000000001110110000000000001 -11011000000000000101011000100000 -00010101100010000000010101110000 -00000000010110001000000001010110 -00000000000111011000000000100001 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000000110001010100001000000100 -00110000100001010000110000100000 -01000011000011000001000011000010 -00000100001100001000000000001100 -00100001010000110000100001010000 -11000010000001000011000010000001 -00001100001000000010001100001000 -00000000110000100000010001100000 -10000001100011000010000001100011 -00001000000100001100000000110001 -01010000000000000000000000000000 -00000000000000000000000000000000 -00000000100000000000000000000000 -00110000000000000000110000000000 -00000011000000000000000011000000 -00000000001100100000000000001100 -00000000000000110000000000000000 -11000000000000000011000000000000 -00001100000000000000001100000000 -00000000110000000000000000100010 -00000000000011000000000000000011 -00000000000000001100000000000001 -01000000000000000000000000000000 -00000000000000000000000000000000 -00000000100000000000001000000001 -00110000100000000100110000100000 -00010011000010000001010011000010 -00000101001100101100000001001100 -00100000000100110000100000000100 -11000010000000010011000010000000 -01001100001000000001001100001100 -00000100110000110000000100110010 -11000000010011000011000000010011 -00001000000001001100000000110001 -01000000000000000000000000000000 -00000000000000000000000000000000 -00000000110001010100001000000101 -01100000100000010101100000100000 -01010110000011000001000110000010 -00000001011000001100000000001000 -00100000010101100000100000010101 -10000010000000010110000010000000 -01011000001000000001011000001100 -00010101100000110000000101100000 -11000001010111000011000001010110 -00001000000001011000000000010000 -01010000000000000000000000000000 -00000000000000000000000000000000 -00000000110001010100001000000000 -00100000100000000000100000100000 -00000010000010000000000011000010 -00000000011000001000000100001000 -00100000000000100000100000000000 -10000010000000000010000010000000 -00001000001000000000001000001000 -00000000110000100000010000110000 -10000000000110000010000000000011 -00001000000000001000000000110001 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000110001010001001000000100 -01100000100000010001100100100000 -01000110010010000001000011010010 -00000000001001001000000100001001 -00100000010001100100100000010001 -10000010000000000110010010000000 -00011001001000000000011001001000 -00010000110100100000010000110100 -10000001000010000010000001000011 -01001000000000011000000000000001 -01000000000000000000000000000000 -00000000000000000000000000000000 -00000000010001010110000000000101 -01011000000000010101011000000000 -01000101100000000000000001100000 -00000001010110000000000100000010 -00000000010101011000000000010101 -01100000000001010101100000000001 -01010110000000000001010110000000 -00010100011000000000010100011000 -00000000010001100000000000010001 -10000000000101010100000000000001 -01010000000000000000000000000000 -00000000000000000000000000000000 -00000000100001000010011000000001 -01000001100000000101000001100000 -00010100000110000000010100000110 -00000001010000011000000001010000 -01100000000101000001100000000101 -00000110000000010100000110000000 -01010000011000000001010000011000 -00000001000000100000000101000001 -10000000010100000110000000010100 -00011000000001010000000000010001 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000000100000000001001000000001 -00000000100000000100000100100000 -00010000010010000000010000010010 -00000001000001001000000001000001 -00100000000100100100100000000100 -00000010000000010000010010000100 -01000001001000000001000001001000 -00010100000100100000000100000100 -10000001010000000010000000010000 -01001000000001000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000110001010100011000000011 -01010001100000001101010001100000 -00110101000110000000110101000110 -00000011010100011000000111000000 -01100000001101010001100000001101 -01000110000000110101000110000000 -11010100011000000001010100011000 -00000101010001100000001101010001 -10000000110101000110000000110101 -00011000000011010100000000110001 -01010000000000000000000000000000 -00000000000000000000000000000000 -00000000110001010100001000000111 -01110001100000010101110001100000 -00010111000110000000110111000110 -00000000011100011000001001011100 -01100000000101110001000000010101 -11000110000000010111000110000000 -01011100011000001110011100011000 -00010101110001100000011101110001 -10000001010111000110000001110111 -00011000000001011100000000010001 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000010001010100011000000011 -01110001100000001101110001100000 -01100111000110000101010111000110 -00000010011100011000000011011100 -01100000011101110001100000001101 -11000110000001100111000110000001 -11011100011000000010011100011000 -00010001110001100000010101110001 -10000000010111000110000001010111 -00011000000011011100000000000001 -01000000000000000000000000000000 -00000000000000000000000000000000 -00000000010001010100011000000101 -01110001100000010101110001100000 -01010111000110000001000011000110 -00000101011100011000000000011100 -01100001010101110001100000010100 -11000110000101010111000110000001 -01011100011000000101011100011000 -00011000110001100000011001110001 -10000001100111000110000001000011 -00011000000101011100000000000001 -01010000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000001000000001 -00100000100000000100100000100000 -00010010000010000000010111000010 -00000001001000001000000001001000 -00100000000100100000100000000101 -10000010000000010010000010000000 -01001000001000000001001000001000 -00000101110000100000000100110000 -10000000010010000010000000010111 -00001000000001001000000000010000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000010000000000011000000001 -01100001100000000101100001100000 -00010110000110000000010110000110 -00000001011000011000000001001000 -01100000000101100001100000000101 -10000110000001010110000110000001 -00011000011000000001011000011000 -00000101100001100000000101100001 -10000000010010000110000000010110 -00011000000001011000000000100001 -01000000000000000000000000000000 -00000000000000000000000000000000 -00000000010001010100000000000101 -01110000000000010101110000000000 -00010011000000000001010011000000 -00000101001100000000000001001100 -00000000000000110000000000010101 -11000000000000010111000000000001 -01011100000000000101011100000000 -00000101110000000000010100110000 -00000001000111000000000000010011 -00000000000101011100000000110001 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000000010001000100001100000000 -01100000100000000001100000110000 -00000010000010000000000010000010 -00000000001000001000000100011000 -00100000000000100000100000000001 -10000010000000000110000010000000 -00011000001000000000011000001000 -00000000000000100000000000100000 -10000000000110000010000000000010 -00001000000000011000000000000001 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000000010001000100001000000100 -00100000100000010000100000100000 -00000110000010000001000110001010 -00000100011000001000000100001000 -10100000000001100100100000010000 -10000010000000000010000010000001 -00001000001000000100001000001000 -00000000100000100000010000100000 -10000001000010000010000000000110 -00001000000100001000000000010001 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000010001000100001100000101 -01000000100000010101000000100000 -01010101000011000001010101000011 -00000101010100001100000101010100 -00110000010101010000100000010101 -00000010000000010100000010000000 -01010000001000000101010000001000 -00000100000100110000000100000000 -10000000010100000011000001000101 -00001000000101010000000000010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -00000000000000010000001100000001 -00010000110000000101010000110000 -00010101000011000000010101001010 -00000001010100001000000001010100 -10100000000101010000100000000101 -01000011000000010101000010000000 -01010100001100000001010100001100 -00000101010000110000000101010000 -10000000010101000011000000010101 -00001000000001010100000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000010000100000000000 -00010010000000000001000000000000 -00000100000000000000000100000000 -00000000011000000000000000011000 -00000000000001000010000000000001 -00001000000000000100001000000000 -00010000100000000000010000100000 -01000001000100000000000001000010 -00000001000110000000000000000100 -00100000000000010000000000010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -00000000010001000100001100000010 -00010000100000001000000010100000 -00100000001010000000100000000010 -00000010000000001000000110000000 -00100000001000000000100000001000 -00000010000000100000000010000000 -10000000001000000010000000001000 -00001000000110100100001000000000 -10000000100000001010000000100000 -00001000000010000000000000110001 -01010000000000000000000000000000 -00000000000000000000000000000000 -00000000000001010100000000001001 -01100000000000010101100000000000 -00010110000000000000110110000000 -00000101011000000000001001011000 -00000000000101100100000010010101 -10000000000000010110000000000001 -01011000000000000101011000000000 -00011101100000000000011101100000 -00000001010110000000000010110110 -00000000001001011000000000010001 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000110001010100000000000010 -01100000000000011101100000000000 -00010110000000000000010111000000 -00000000011000000000000001001000 -00000000001101100000000000000101 -10000000000000010110000000000000 -10011000000000000011011000000000 -00000101110000000000000101110000 -00000000110010000000000000010111 -00000000000011011000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000100 -00110000000000000000110000000000 -01000011000000000000000110000000 -00000100001100000000000000001000 -00000001010000110100000000000000 -11000000000000000011000000000001 -00001100000000000100001100000000 -00010001100000000000010001100000 -00000000100010000000000001000110 -00000000000100001100000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000010000000000 -00110100000000000000110001101000 -00000011010000000001000010000100 -00000000001101000000000000001000 -00000000000000110101000000000000 -11010100000001000011010000000000 -00001101010000000000001101000000 -00000000100101001000000000100100 -00000000000010010000000000000010 -00000000000000001100000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000011000000001 -00110001010000010100110001010000 -00010011000101000001010011000110 -10000001001100010000000001001000 -01000000000100110101100000000100 -11000101000000010011000100000000 -01001100010100000001001100010100 -01010100111001011000010100110001 -00000000010010000101000001010011 -00010000000001001100000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000010001100000101 -01101000110000000101101000110000 -01000110100011000001010100100011 -10000101011010001100000001011010 -00110000010101101101110000010101 -10100011000001010110100011000001 -01011010000100000101001010001100 -00010001101000100000010101101000 -11000001010110100011000001010110 -10001100000100011000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000010000000000 -00100100000000000000100011000000 -00000010011000000000000010000100 -00000000001001000000000100001000 -00000000000000100100000000000000 -10010101000000000010010000000000 -00001001000000000000001001000000 -00000000100111000000000000110100 -00000000000010011000000000000010 -00000000000000001000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000100000000100 -01100010000100000001100000000100 -01000110000000010001000110000000 -01000100011000000001000100011000 -00000100010001100010000000010001 -10001000000001000110001000010001 -00011000100000000100001000100001 -00010001100000000100010000110010 -00010001000110000000010001000110 -00100001000100011000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000001000101 -01010000000100000101010000000000 -01000101000000100000000101000000 -01100101010100000001000100010100 -00000100010001010000000100010101 -01000000010101010101000000010001 -00010100000100000100010100000000 -00000101010000010000000100010000 -00010000010101000000010000000101 -00000001000101010100000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000100000100001 -01000010000000000001000010000010 -00010101001000001000000101001000 -00100001010100100000100000010100 -10000010000101010010000000000101 -00001000000000010100001000000000 -01010000100000000001010000100010 -10000101000010000010000101010010 -00001000010100001000001000010101 -00100000100001010000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000101000000001 -00000010100000000100000010100000 -01000000001010010000010000001010 -00000100000000101000000100000000 -10100000000100000010100000000100 -00001010000000010000001010000000 -01000000101000000001000000101001 -01000100000010100000000100000010 -10000000010000001010000000000000 -00101000000001000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000110010000011 -01010011000000000101010011000000 -00100001001100000000000101001100 -00000010000100110000000000000100 -11001000001000010011000000000101 -01001100000000010101001100100000 -11010100110000000011010100110001 -00001101010011000000001000010011 -00000000010101001100000000100001 -00110010000011010100000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000100010000101 -01110010000000010001110010000000 -01010111001000000001010111001000 -00001101011100100000001101011100 -10001000010101100010000000011001 -11001000000001000111001000001001 -01011100100000000100011100100000 -00001001110010000000011101100010 -00000001010111001000000001110111 -00100000100101011100000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000001100001000 -01001000110001000001000000110000 -10000100000011000000000100000011 -00001000010000001100000000010000 -00110000100001000000110000000001 -00000011000100000100100011000000 -00010000001100000000010010001100 -00000001000000110000000001001000 -11000000000100000011000100000100 -10001100001000010000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -01001111111111111101001111111111 -11110100111111111111110100111111 -11111111010011111111111111010011 -11111111111101000111111111011101 -00011111111111110100111111111111 -11010011111111111111010011111111 -11111101001111111111111101001111 -11111111110100111111111111110100 -11111111111111010000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111011 -00001011001101111101001111111111 -10110000101101111111110100111110 -11011011000010110011011011000010 -11011111101100000111101101011101 -00011110110111110100101101111111 -11010011111111111111010010110111 -11111101001111111111101100001011 -00110110110000101100110110110000 -10110111111011000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111100 -01001100110011111101001111111111 -11000100110011111111110100111111 -00111100010011001100111100010011 -00111111110001000111110011011101 -00011111001111110100110011111111 -11010011111111111111010011001111 -11111101001111111111110001001100 -11001111000100110011001111000100 -11001111111100010000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011101100011110 -01001110110111111001001000110111 -11100100100011011110000100100011 -00011110010010001100011000010010 -00110001111001000110110001011101 -00011011011111100100111011000111 -10010011101101111110010011101101 -11100001001000110111100001001110 -11000110000100100011011110000100 -11101100011110010000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000100000010 -01110000010000001001110000010000 -00100111000001000000100111000001 -00000010011100000100000010011100 -00010000001100110000010000001001 -11000001000000100111000001000001 -10011100000100010110011100000100 -00001001110000010000001001110000 -01000000100111000001000001100111 -00000100000110011100000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000010000000101 -01110001000000010101110001000000 -01010111000100000001010111000100 -00000101011100010000000101011100 -01000000010100110001000000010101 -11000100000001010111000100000001 -01011100010000000101011100010000 -00010101110001000000010101110001 -00000001010111000100000001010111 -00010000000101011100000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000001000000001 -00100000100000000100100000100000 -00010010000010000000010010000010 -00000001001000001000000001001000 -00100000000100100000100000000100 -10000010000000010010000010000000 -01001000001000000001001000001000 -00000100100000100000000100100000 -10000000010010000010000000010010 -00001000000001001000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01100000000000000001100000000000 -00000110000000000000000110000000 -00000000011000000000000000011000 -00000000000001100000000000000001 -10000000000000000110000000000000 -00011000000000010000011000000000 -00000001100000000001000001100000 -00000000000110000000000000000110 -00000000000000011000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000100000000100 -01110010000000010001110010000000 -01000111001000000001000111001000 -00000100011100100000000100011100 -10000000010001110010000000010001 -11001000000001000111001000000000 -00011100100000000000011100100000 -00010001110010000000010001110010 -00000001000111001000000000000111 -00100000000000011100000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01100000000000000001100000000000 -00000110000000000000000110000000 -00000000011000000000000000011000 -00000000000001100000000000000001 -10000000000000000110000000000000 -00011000000000000000011000000000 -00000001100000000000000001100000 -00000000000110000000000000000110 -00000000000000011000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000100000000100 -00100010000000010000100010000000 -01000010001000000001000010001000 -00000100001000100000000100001000 -10000000010000100010000000010000 -10001000000001000010001000000000 -00001000100000000000001000100000 -00010000100010000000010000100010 -00000001000010001000000000000010 -00100000000000001000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000010101000000100 -01001010100000010001001010100000 -01000100101010000001000100101010 -00000100010010101000000100010010 -10100000010001001010100000010001 -00101010000001000100101010000001 -00010010101000000000010010101000 -00010001001010100000010001001010 -10000001000100101010000001000100 -10101000000100010000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000110000000000110000000000 -01010011000000000001010011000000 -00000101001100000000000101001100 -00000000010100110000000000010100 -11000000000001010011000000000001 -01001100000000000101001100000000 -00010100110000000100010100110000 -00000001010011000000000001010011 -00000000000101001100000000000101 -00110000000000010100000000010000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000110000000000000000000000 -01000000000000000001000000000000 -00000100000000000000000100000000 -00000000010000000000000000010000 -00000001000001000000000000000001 -00000000000000000100000000000000 -00010000000000000000010000000000 -00000001000000000000000001000000 -00000000000100000000000000000100 -00000000000000010000000000110000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000110000000100000000000010 -00000000000000001000000000000000 -00100000000000000000100000000000 -00000010000000000000000010000000 -00000000001000000000000000001000 -00000000000000100000000000000000 -10000000000000000010000000000000 -00001000000000000000001000000000 -00000000100000000000000000100000 -00000000000010000000000000110000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000110000000100000000000100 -01100000000000010001100000000000 -01000110000000000000000110000000 -00000000011000000000000100011000 -00000000010001100000000000010001 -10000000000010000110000000000000 -00011000000000000000011000000000 -00010001100000000000000001100000 -00000001000110000000000000000110 -00000000000000011000000000110000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00010000000000010100000000000010 -01100000000000001001100000000000 -00100110000000000000100110000000 -00010110011000000000000010011000 -00000000001001100000000000001001 -10000000000000100110000000000000 -10011000000000000010011000000000 -00001001100000000000001001100000 -00000000100110000000000000100110 -00000000000010011000001000010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -01000000010001010100001000000100 -00110000100000010000110000100000 -01000011000010000001000011000010 -00000100001100001000000100001100 -00100000010000110000100000010000 -11000010000001000011000010000001 -00001100001000000100001100001000 -00010000110000100000010000110000 -10000001000011000010000001000011 -00001000000100001100000000010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -01000000000000000000000000000000 -00110000000000000000110000000000 -00000011000000000000000011000000 -00000000001100000000000000001100 -00000000000000110000000000000000 -11000000000000000011000000000000 -00001100000000000000001100000000 -00000000110000000000000000110000 -00000000000011000000000000000011 -00000000000000001100000000110001 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000000000000001000000000 -00110000100000000000110000100000 -00000011000010000000000011000010 -00000000001100001000000000001100 -00100000000000110000100000000000 -11000010000000000011000010000000 -00001100001000000000001100001000 -00000000110000100000000000110000 -10000000000011000010000000000011 -00001000000000001100000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000010001010100001000000100 -01100000100000010001100000100000 -01000110000010000001000110000010 -00000000011000001000000100011000 -00100000010001100000100000010001 -10000010000001000110000010000001 -00011000001000000100011000001000 -00010001100000100000010001100000 -10000001000110000010000001000110 -00001000000100011000000000010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -01000000000000010100001000000000 -00100000100000000000100000100000 -00000010000010000000000010000010 -00000000001000001000000000001000 -00100000000000100000100000000000 -10000010000000000010000010000000 -00001000001000000000001000001000 -00000000100000100000000000100000 -10000000000010000010000000000010 -00001000000000001000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01010000010000010100001000000100 -01100000100000010001100000100000 -01000110000010000001000110000010 -00000000011000001000000100011000 -00100000010001100000100000010001 -10000010000001000110000010000001 -00011000001000000100011000001000 -00010001100000100000010001100000 -10000001000110000010000001000110 -00001000000100011000000000010000 -01000000000000000000000000000000 -00000000000000000000000000000000 -01000000010001010100000000000100 -01010000000000010001010000000000 -01000101000000000001000101000000 -00000000010100000000000100010100 -00000000010001010000000000010001 -01000000000001000101000000000001 -00010100000000000100010100000000 -00010001010000000000010001010000 -00000001000101000000000001000101 -00000000000100010100001000010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -01001000010000010000011000000000 -01000001100000000001000001100000 -00000100000110000000000100000110 -00000100010000011000000000010000 -01100000000001000001100000000001 -00000110000000000100000110000000 -00010000011000000000010000011000 -00000001000001100000000001000001 -10000000000100000110000000000100 -00011000000000010000000000010000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01001000000001000000001000000001 -00000000100000000100000000100000 -00010000000010000000010000000010 -00000001000000001000000001000000 -00100000000100000000100000000100 -00000010000000010000000010000000 -01000000001000000001000000001000 -00000100000000100000000100000000 -10000000010000000010000000010000 -00001000000001000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000010001010100011000000011 -01010001100000001101010001100000 -00110101000110000000110101000110 -00000011010100011000000011010100 -01100000001101010001100000001101 -01000110000000110101000110000000 -11010100011000000011010100011000 -00001101010001100000001101010001 -10000000110101000110000000110101 -00011000000011010100000000010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -00000000000000010000011000000100 -01110001100000010001110001100000 -01000111000110000001000111000110 -00000100011100011000000100011100 -01100000010001110001100000010001 -11000110000001000111000110000001 -00011100011000000100011100011000 -00010001110001100000010001110001 -10000001000111000110000001000111 -00011000000100011100000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000000010100011000000000 -01110001100000001001110001100000 -00100111000110000000100111000110 -00000010011100011000010110011100 -01100000001001110001100000001001 -11000110000000100111000110000000 -10011100011000000010011100011000 -00011001110001100000001001110001 -10000000100111000110000000100111 -00011000000010011100000000010001 -00010000000000000000000000000000 -00000000000000000000000000000000 -01010000010001010100011000000001 -01110001100000010101110001100000 -01010111000110000001010111000110 -00000101011100011000000101011100 -01100000010101110001100000010101 -11000110000001010111000110000001 -01011100011000000101011100011000 -00010101110001100000010101110001 -10000001010111000110000001010111 -00011000000101011100001000010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -01000000000000010000001000000001 -00100000100000000100100000100000 -00010010000010000000010010000010 -00000001001000001000000001001000 -00100000000100100000100000000100 -10000010000000010010000010000000 -01001000001000000001001000001000 -00000100100000100000000100100000 -10000000010010000010000000010010 -00001000000001001000000000010001 -01000000000000000000000000000000 -00000000000000000000000000000000 -01000000000000000000011000000000 -01100001100000000001100001100000 -00000110000110000000000110000110 -00000000011000011000000000011000 -01100000000001100001100000000001 -10000110000000000110000110000000 -00011000011000000000011000011000 -00000001100001100000000001100001 -10000000000110000110000000000110 -00011000000000011000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000010001010110000000000100 -01111000000000010001111000000000 -01000111100000000001000111100000 -00000100011110000000000000011110 -00000000010001111000000000010001 -11100000000001000111100000000001 -00011110000000000100011110000000 -00000001111000000000010001111000 -00000001000111100000000001000111 -10000000000100011100000000010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -01000000000000010100001000000000 -01100000100000000001100000100000 -00000110000010000000000110000010 -00000000011000001000000000011000 -00100000000001100000100000000001 -10000010000000000110000010000000 -00011000001000000000011000001000 -00000001100000100000000001100000 -10000000000110000010000000000110 -00001000000000011000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000000010100001000000100 -00100000100000010000100000100000 -01000010000010000001000010000010 -00000100001000001000000000001000 -00100000010000100000100000010000 -10000010000001000010000010000001 -00001000001000000100001000001000 -00000000100000100000010000100000 -10000001000010000010000001000010 -00001000000100001000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000010001010100001000000100 -01000000100000010001000000100000 -01000100000010000001000100000010 -00000100010000001000000100010000 -00100001010001000000100000010001 -00000010000001000100000010000001 -00010000001000000100010000001000 -00010001000000100000010001000000 -10000001000100000010000001000100 -00001000000100010000000000010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -01000000000000000000001100000001 -00000000110000000001010000110000 -00000101000011000000000101000011 -00000000010100001100000000010100 -00110000000001010000110000000001 -01000011000000000101000011000000 -00010100001100000000010100001100 -00000001010000110000000001010000 -11000000000101000011000000000101 -00001100000000010100000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000000000000100000000100 -01000010000000000001000010000001 -00000100001000000000000100001000 -00000000010000100000000000010000 -10000000000001000010000000000001 -00001000000000000100001000000000 -00010000100000000000010000100000 -00000000000010000000000001000010 -00000000000100001000000000000100 -00100000000000010000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000010001010100001000000000 -00000000100000001000000000100000 -00100000000010000000100000000010 -00000010000000001000000010000000 -00100000001000000000100000001000 -00000010000000100000000010000000 -10000000001000000010000000001000 -00001000000000100000001000000000 -10000000100000000010000000100000 -00001000000010000000000000010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -01000000000000010100000000000100 -01100000000000010001100000000000 -01000110000000000001000110000000 -00000100011000000000000000011000 -00000000010001100000000000010001 -10000000000001000110000000000001 -00011000000000000100011000000000 -00100100100000000000010001100000 -00000001000110000000000001000110 -00000000000100011000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000000010100000000000010 -01100000000000001001100000000000 -00000110000000000000100110000000 -00000010011000000000000010011000 -00000000001001100000000000001001 -10000000000100100110000000000000 -10011000000000000110011000000000 -00001001100000000000001001100000 -00000000100110000000000100100110 -00000000000010011000000000000001 -00010000000000000000000000000000 -00000000000000000000000000000000 -01000000010001010110000000000100 -00111000000000010000111000000000 -00000011100000000001000011100000 -00000100001110000000000100001110 -00000000010000111000000000010000 -11100000000000000011100000000001 -00001110000000000100001110000000 -00010000111000000000010000111000 -00000001000011100000000001000011 -10000000000100001100000000010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -01010000000000000000000100000000 -00110000010000000000110000010000 -00000011000001000000000011000001 -00000000001100000100000000001100 -00010000000000110000010000000000 -11000001000000000011000001000000 -00001100000100000000001100000100 -00000000110000010000000000110000 -01000000000011000001000000000011 -00000100000000001100000000000001 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000000000000010100000000 -00110001010000000000110001010000 -00000011000101000000000011000101 -00010000001100010100000000001100 -01010000000000110001010000000000 -11000101000000000011000101000000 -00001100010100000000001100010100 -00000000110001010000000000110001 -01000000000011000101000000000011 -00010100000000001100001000010000 -01000000000000000000000000000000 -00000000000000000000000000000000 -01000000010001010100001100000100 -01100000110000010001100000110000 -01000110000011000001000110000011 -00000100011000001100000100011000 -00110000010001100000110000010001 -10000011000001000110000011000001 -00011000001100000000011000001100 -00010001100000110000010001100000 -11000001000110000011000001000110 -00001100000100011000000000010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -01000000000000010100000000000000 -00100000000000000000100000000000 -00000010000000000000000010000000 -00000000001000000000000000001000 -00000000000000100000000000000000 -10000000000000000010000000000000 -00001000000000000000001000000000 -00000000100000000000000000100000 -00000000000010000000000000000010 -00000000000000001000000000110000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000000000010000100001000100 -01100010000100010001100010000100 -01000110001000010001000110001000 -01000100011000100001000100011000 -10000100010001100010000100010001 -10001000010001000110001000010001 -00011000100001000000011000100001 -00010001100010000100010001100010 -00010001000110001000010001000110 -00100001000100011000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -01000000010001010100000001000100 -01010000000100010001010000000100 -01000101000000010001000101000000 -01000100010100000001000100010100 -00000100010001010000000100010001 -01000000010001000101000000010001 -00010100000001000100010100000001 -00010100000000000100010001010000 -00010001000101000000010001000101 -00000001000100010100000000010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -01000000000001010000100000100000 -01000010000010000001000010000010 -00000100001000001000000100001000 -00100000010000100000100000010000 -10000010000001000010000010000001 -00001000001000000100001000001000 -00010000100000100000010000100000 -10000001000010000010000001000010 -00001000000100001000001000000100 -00100000100000010000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000101000000001 -00000010100000000100000010100000 -01010000001010000000010000001010 -00000001000000101000010001000000 -10100000000100000010100000000100 -00001010000000010000001010000000 -01000000101000000001000000101000 -00000100000010100000000100000010 -10000000010000001010000000010000 -00101000000001000000000000010001 -01000000000000000000000000000000 -00000000000000000000000000000000 -01000000010001010100110100000011 -01010011010000001101010011010000 -00010101001101000000110101001101 -00000011010100110100000011010100 -11010000001101010011010000001101 -01001101000000010101001101000000 -11010100110100000011010100110100 -00001101010011010000001101010011 -01000000110101001101000000110101 -00110100000011010100000000010001 -01010000000000000000000000000000 -00000000000000000000000000000000 -01000000000000010100100000000100 -01110010000000010001110010000000 -01000111001000000001000111001000 -00000000011100100000000100011100 -10000000010001110010000000010001 -11001000000001000111001000000001 -00011100100000000000011100100000 -00010001110010000000010001110010 -00000001000101001000000001000111 -00100000000100011100000000110001 -00010000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000010001100011000 -01001000110001100001001000110001 -10000100100011000110000100100011 -00011000010010001100011000010010 -00110001100001001000110001100001 -00100011000110000100100011000110 -00010010001100011000010010001100 -01100001001000110001100001001000 -11000110000100100011000110000100 -10001100011000010000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -01001111111111111101001111111111 -11110100111111111111110100111111 -11111111010011111111111111010011 -11111111111101001111111111111101 -00111111111111110100111111111111 -11010011111111111111010011111111 -11111101001111111111111101001111 -11111111110100111111111111110100 -11111111111111010000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000010110011011011 -00001011001101101100001011001101 -10110000101100110110110000101100 -11011011000010110011011011000010 -11001101101100001011001101101100 -00101100110110110000101100110110 -11000010110011011011000010110011 -01101100001011001101101100001011 -00110110110000101100110110110000 -10110011011011000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011001100111100 -01001100110011110001001100110011 -11000100110011001111000100110011 -00111100010011001100111100010011 -00110011110001001100110011110001 -00110011001111000100110011001111 -00010011001100111100010011001100 -11110001001100110011110001001100 -11001111000100110011001111000100 -11001100111100010000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011101101111110 -01001110110111111001001110110111 -11100100111011011111100100111011 -01111110010011101101111110010011 -10110111111001001110110111111001 -00111011011111100100111011011111 -10010011101101111110010011101101 -11111001001110110111111001001110 -11011111100100111011011111100100 -11101101111110010000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000001010000101 -00100000001000010000000100101000 -01000001000010100001000000010010 -10000010001100001010000011000101 -00101000010000000000101000011000 -00010010100001000010000010100001 -00000000001010000111000100001010 -00010100000000001000010000101100 -10100001000000000010010001000010 -00001001000100001000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000100 -00010000000100010000010000000000 -01000010001010000001000000111000 -00000110000001000000000100001000 -00000000010100110010000000010100 -00011000000001010011010000000001 -11000000000000000111000100000000 -00010000000000000000010000111000 -00000001000000000010010001000000 -00000000000100000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011000010000101 -00100100100000010000100000000000 -01000011000000100001000010000000 -10000101001000000001000100001000 -00001000011000100000001000011000 -10000000100001110011001000100001 -11001010000010000111001000000010 -00010100000100101000010000100000 -00100001000000110000000001000010 -00000001000100001000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000101 -00000000100100010000101100000000 -01000011000000000001000010000000 -00000100001000000001000100001111 -00000000010000110000000000010000 -10000000000001110000010000000001 -10001011000000000101001100000000 -00010100000000000000010000010000 -00000001000000000000000001000010 -00000000000100001000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000010000000 -00010100001000001100110100001000 -00000001000010100000010011000000 -10000001000001000010000011000001 -00001000001100000000001000000000 -00010000100000110001010000100000 -00001000000010000000000000000010 -00000100110100001000000000110000 -00100000000000000000000000000000 -00000010000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000000000000001000000001 -00000000100100000000000000000000 -00000010000000000000010001000010 -00000011000000001000000000001000 -00100000000100000000100000001000 -00000010000000100000000010000000 -00000000001000000000000000001000 -00000100100000100000000100110000 -10000000000000000000000000000000 -00001000000000000000001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000000000001000010000001 -00100010101000000000100110001100 -00000001001000100000100010001000 -10000011000001100010000000001010 -10001000001100000010001000000100 -00001000100000010010111000100000 -00001000100010000000000000100010 -00000000111110001000000100111110 -00100000000010011000110000000010 -00100010000000001000001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000000000000100000000011 -00000010000000001100110110100000 -00000001001010000000010001001000 -00000010000000100000000000001000 -10000000001000000000000000000000 -00001000000000000010001000000000 -00001010100000000000000000100000 -00001000110010000000001100011010 -00000000000010001010010000000010 -00100000000000001000001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000000000011101010000111 -00101010001000010000010010101000 -01000011001000010001000010001000 -10000101000100101010000101000000 -10101000011000000010101000010000 -01001010100001100001001010100001 -10000001101010000100000100101010 -00010100111010001000010100000010 -00100001000000001000100001000000 -00100010000100000000001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000000000001100000000100 -00101110000000010000100010000000 -01000011001010000001000011101000 -00000101000010100000000100000001 -10000000011100000010000000010000 -11101010000001010010011000000001 -00001100100000000100001100100000 -00010100110110100000011100100110 -00000001000001111000000001000001 -00101001000100000000001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000000000000000010000100 -00000000101000010000110100000100 -01000011000000100001000010100010 -10000000001010000010000101001010 -00001000011100000000001000010000 -11010000100001100001100000100000 -01001000000010000101001000000010 -00010100100000001000011100110000 -10100001000010100000100001000010 -00000010000100001000001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000100000000000000000111 -00100000000000010000110000000000 -01000001010010000001000011010010 -00000110000001000000000101001000 -00000000011000110100000000011100 -01110000000001010011010000000001 -01000000000000000101000001000000 -00011100100000100100011000100000 -10000001110001000000000001110001 -00000000000100001000001000000100 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000000000010000010000111 -00000100101000010000100000100000 -01110000010000100001010000010000 -10000101001101000010000111001110 -00001000010100100000001000011100 -01000010100001110000000000100001 -00000001000010000111001110000010 -00011000100000001000011100010000 -00100001110011010000100001000000 -00000001000100001000001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000001001000000001 -00001000000000000000010100000100 -01000010000000000000100010100010 -00000101000110001000000100001000 -00000000001000100100100000010000 -01000000000001000010100010000000 -00000000001000000111000001001000 -00010100100100000000011000100000 -10000001000000000000000000000011 -11000000000000000100000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000010000001 -00100100101000000000100100000000 -01000010010010100000010011000010 -10000111001001000010000100001110 -00001000000100110100001000010000 -10000000100001000011100000100000 -00001000000010000111000001000010 -00010100000000101000010100111000 -10100001000000000000000000000010 -01000010000000001000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000100001000000000000011 -00100000100000000000000100100100 -00000001100010000000000011000000 -00000001001100000000000011001000 -00100000000100101000000000000000 -00100010000000000010000000000000 -00001001000000000010001100000000 -00001100001000100100000100101000 -00000000110011010010000000000001 -00001000000000001000000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000001000000010000 -01000000100000000000000000000000 -00000000000000000001000000010000 -00000000000000000000000000000000 -00000000000100000000000000000000 -10010000000000000000000000000000 -00000000000000000001000000000000 -00000000100100000010000000000000 -00000000000000000000000000000000 -00000000001000001000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00111100001111000011000000000000 -10000000100000000000000000000000 -00010000000000000000000000110000 -10000000000000001000000000000000 -00000000000100000010000000010000 -00110000100000000000000010000000 -00000000000000000000000000100000 -00010000001100000000000000000000 -01000000000000000000000000010000 -00000000000000000000111100001111 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000011001 -10000000000110011000000000111111 -11011001101111111101100110000000 -00011001101111111101100100000000 -00011111101100101011100011001111 -10000000000000000001100110100110 -00000000000000011000111101001011 -01101000010000000001100110000000 -00011001110000000011111111011001 -10111111110110011000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000001000000000111110 -10111110101111101011111010000000 -00000000000000000010000000000000 -00010010000100101000011010000010 -00010110100000000001011010100000 -00000000000001100000010000000000 -00010000000000000000000000000000 -00000000000000000010100000010000 -00111110100101101100000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000010001000 -01000100100000010100000110000000 -00000000000000000000000000000000 -11000000000000000000000000000000 -00000000000000000000000000000000 -00000000110000000000000000000000 -00000000000000000000000000000000 -00000000000000001000000101111000 -01000001101100010000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111101111111111111111111111 -11000000000000000000000000000000 -00000000001111111111111111101111 -11111101110000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000101101 -11111111101011101111111111000000 -00000000000000000000000000000000 -00111111101111111111111111111110 -00000000000000000000000000000000 -00000000001101111111111011111111 -01111111110000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111101 -11111111111111111011111111000000 -00000000000000000000000000000000 -00111111101111111111111111111111 -11000000000000000000000000000000 -00000000001111111111111111111111 -11111111110000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111111111111111111111111111 -11000000000000000000000000000000 -00000000001111111111111111111111 -11111111110000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111111111111111111100111111 -11000000000000000000000000000000 -00000000001111111111111111111111 -11111111110000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111101111111111111111000000 -00000000000000000000000000000000 -00111111111111111011111111111111 -11000000000000000000000000000000 -00000000001111111111111100111111 -11111111110000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000011000111 -00100100101000010000100000001000 -01000001000000100001000010010010 -10000100000000001010000000001000 -00101000010000010000101000011000 -10110010110001010000010010100001 -00001000001010000100000100001010 -00010000101100101000011100000100 -10110001000001000000100001000000 -00000010000100000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000001000111 -00010000100000010000110000000000 -01000011000000000001000001110000 -00000101000010000000000000001001 -00000000010000100000000000011100 -01000000000001100000100000000001 -00000000000000000111001000000000 -00010000001000000000011100101100 -00000001000010000000000001000000 -00000000000100000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000001000011000111 -00101000001000010000100100101100 -01000011000010100001000010000000 -10000110000001000010000000001000 -00001000010000010000001100011100 -10000000100001010000010000100001 -00001000000010000101000000000001 -00010000100000001000011100000000 -00000001000011000000010001000000 -00001010000100000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000001000000000100 -00101000000000010000010100000000 -01000011000000000001000010000000 -00000100000001000000000000001101 -00000000010000000000000000011000 -00000000000001010000010000000001 -00000010000000000110000100000001 -00010000100000000000010000010000 -00010001000010110010000001000000 -00001000000100000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000010001011000000 -00100000101000000000000100001000 -00000010000000100000000010000000 -10000000000000000010000000000101 -00001000001100100000001000000100 -00100000110000000000000000100000 -10001001000010000010000000000010 -00001100000000000100000000000000 -00110000000000010000010000000000 -00000001000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000000000000000001000000 -00000000000000000000010000100000 -00000000000010000000000001000010 -00000000000000001000000000001100 -00100000000100010000100000001000 -00000010000000000000000010000000 -01000000001000000001000000001000 -00001100010000100100000000100000 -10000000000000000010000000000001 -00001000000000000100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000001101000000000 -00100110001000000000100110101100 -00000010001000100000010010001000 -10000001000001100010000000001101 -10001000001100100010001100000100 -10011000100000000000011000100000 -10001001100010000010000000100010 -00001100100010000100000000011110 -00100000000010011000000000000010 -00101010000000001000001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000000000010100000000000 -00000110100000000000000010000000 -00000010001000000000010000001000 -00000001000000100000000000000010 -10000000001000000010000000000000 -10001000000000000000011000000000 -00001000100000000000000000100000 -00000100000110000100000000001010 -00000000000010001000000000000010 -00100000000000001000001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000000000000101010000111 -00101010101000010000010110001000 -01000001001010100001000010001010 -10000101000100101010000110000001 -10101000011000000010101000010000 -01101000100001010001001010100001 -01000001101010000100000000101001 -00010100000010100000011100100010 -10000001000001011010000001000001 -00101001000100000000001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000000000010100000000111 -00110010000000010000110010000000 -01010011001000000001000001101000 -00000111000010100000000101000100 -10000000011100100010000000010000 -10101000000001100010001010000001 -10001000100000000100000000100001 -00011000110010000100011100010110 -00000001000010001000010001000010 -00100001000100000100001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000010000111 -00110000001000010000110100001000 -01000010000000010001000010100000 -10000111001010000010000110001000 -00001000010100010000001000010000 -01000010100001010000100000100001 -01000101000010000101000000000010 -00010100111000001000011100100000 -00100001000001100000000001000001 -00000001000100001000001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000100000001000000000111 -00010100000000011100010000100000 -01100011000000000001110001000000 -00000101000111000000000101001100 -00000000010100100000000000011100 -11000010000001110011010000000001 -11001100000000000101000010000000 -00011100010100000100011100010100 -00000001110011000000010001110010 -00000001000111001100001000000100 -00000000000000000000000000000000 -00000000000000000000000000000000 -00001000000000000000001010000100 -00001000001000010000000000001000 -01000010010000010001000010000000 -10000111000000000010000101000010 -00001000010000100000001000010100 -00010000100001110010100010100001 -01001010000010000101000000000010 -00011100000000001000010100100000 -00110001100001100000010001000010 -01000010000100000000001000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000001000000000000 -00000100100000000000000100100000 -00000010000010000000000011110010 -00000011000010001000000010001001 -00100000000100100000100000001000 -01100010000001000010000000000000 -10000001001000000011000000001000 -00011000100100100000001000101000 -10000000010010010010000000000010 -00001001000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000001000010000000 -00100100001000000000100000101000 -00000011000000100000000010010000 -10000011001001000010000001001100 -00001000000000111100001000000100 -10010010100001000010100000100000 -01001000000010000011000001000001 -00010100100000000100000100101000 -00100000000011000000010000000010 -01000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000100001010001000000000 -00100000000000000000101000000000 -00000010100000010000000011000000 -00000001001000000000000001001000 -00000000001000111000000000000000 -10000000000000110010000010000000 -00000000000000000000000010000001 -00000000100100000000000000110000 -00000000100010000000000000000011 -10000001000000000000000000000100 -00100000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000001000000000000 -01000000000000000000000000000000 -00000000000000000001000000010000 -00000000000000000000000000000000 -00000000000100000000000000000000 -10010000000000000000000000000000 -00000000000000000001000010000000 -00100000100100000000000000000000 -00000000000000000000000000000000 -00000000001000001000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00111100001111000011000000000000 -10100000000000000000000000000000 -00010000000000000000000000110000 -10000000000000001000000000000000 -00000000000000000010000000010000 -10110000100000000000000010000000 -00000000000000000001000000100000 -00010000101100000000000001000000 -11000000000000000000000000010000 -00000000000000000000111100001111 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000100000000111111 -11011001101111111101100110000000 -00100110010110011001100100000000 -00011111001100010111100000011101 -11011001100000000010011001000000 -00000000000010001000001111001000 -01101111100000000001100110000000 -00000000110000000011111111011001 -10111111110110011000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000101000 -00101001001010000010000001000000 -00000000000000000010000010000000 -00000100100001101000010010000110 -00000000000000000000000000100000 -10000000000000101001001000010000 -10000100000000000000000000000000 -00000000100000000010100000000000 -00101000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000010000100 -10000001000000010101000100000000 -00000000000000000000000000000000 -11000000000000000000000000000000 -00000000000000000000000000000000 -00000000100000000000000000000000 -00000000000000000000000000000000 -00000000000000001000000101111000 -01001000101100010100000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000101111 -11111011111111111110111111000000 -00000000000000000000000000000000 -00011111100111111001111111011111 -11000000000000000000000000000000 -00000000001011111111111111111111 -11110111110000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -01011111010011101111111111000000 -00000000000000000000000000000000 -00101111011011110110111111111101 -01000000000000000000000000000000 -00000000001111110011111101001111 -11111111110000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000011111 -11111111101111111111111111000000 -00000000000000000000000000000000 -00101111001111111011111111111111 -11000000000000000000000000000000 -00000000001111110111111110111111 -11111111110000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111111111111111111111111111 -11000000000000000000000000000000 -00000000001111111111111011111111 -11111111110000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111111111111111111110111111 -11000000000000000000000000000000 -00000000001111111111111111111111 -11111111110000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000011111111111111 -11111111111111111100000000000000 -00000000000000000000000000111111 -11111111111111111111111111000000 -00000000000000000000000000000000 -00111111111111111111111111111111 -11000000000000000000000000000000 -00000000001111111111111111111111 -11111111110000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00110000000000000010000000000001 -00000010000000000000000000000000 -00110000000000000100001100001100 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00110000000000000010000000000001 -00000010000000100000000000000000 -00110000000000000100001100000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00110000000000000000000000000001 -00000000000000001010100001101000 -00110000000000001000000000000001 -00000000000000000000000000000011 -00110000000000000100000000001100 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00110000000000001000000000000001 -00000000000000000000000000000101 -00110000000000001010000000000001 -00000000000000000000000000000000 -00110000000000000000000000000001 -00000000000000001110000101011010 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 diff --git a/wcfxo.c b/wcfxo.c deleted file mode 100644 index 5f48051..0000000 --- a/wcfxo.c +++ /dev/null @@ -1,1103 +0,0 @@ -/* - * Wilcard X100P FXO Interface Driver for Zapata Telephony interface - * - * Written by Mark Spencer - * Matthew Fredrickson - * - * Copyright (C) 2001, Linux Support Services, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef STANDALONE_ZAPATA -#include "zaptel.h" -#else -#include -#endif -#ifdef LINUX26 -#include -#endif - -/* Uncomment to enable tasklet handling in the FXO driver. Not recommended - in general, but may improve interactive performance */ - -/* #define ENABLE_TASKLETS */ - -/* Un-comment the following for POTS line support for Japan */ -/* #define JAPAN */ - -/* Un-comment for lines (eg from and ISDN TA) that remove */ -/* phone power during ringing */ -/* #define ZERO_BATT_RING */ - -#define WC_MAX_IFACES 128 - -#define WC_CNTL 0x00 -#define WC_OPER 0x01 -#define WC_AUXC 0x02 -#define WC_AUXD 0x03 -#define WC_MASK0 0x04 -#define WC_MASK1 0x05 -#define WC_INTSTAT 0x06 - -#define WC_DMAWS 0x08 -#define WC_DMAWI 0x0c -#define WC_DMAWE 0x10 -#define WC_DMARS 0x18 -#define WC_DMARI 0x1c -#define WC_DMARE 0x20 - -#define WC_AUXFUNC 0x2b -#define WC_SERCTL 0x2d -#define WC_FSCDELAY 0x2f - - -/* DAA registers */ -#define WC_DAA_CTL1 1 -#define WC_DAA_CTL2 2 -#define WC_DAA_DCTL1 5 -#define WC_DAA_DCTL2 6 -#define WC_DAA_PLL1_N1 7 -#define WC_DAA_PLL1_M1 8 -#define WC_DAA_PLL2_N2_M2 9 -#define WC_DAA_PLL_CTL 10 -#define WC_DAA_CHIPA_REV 11 -#define WC_DAA_LINE_STAT 12 -#define WC_DAA_CHIPB_REV 13 -#define WC_DAA_DAISY_CTL 14 -#define WC_DAA_TXRX_GCTL 15 -#define WC_DAA_INT_CTL1 16 -#define WC_DAA_INT_CTL2 17 -#define WC_DAA_INT_CTL3 18 -#define WC_DAA_INT_CTL4 19 - - -#define FLAG_EMPTY 0 -#define FLAG_WRITE 1 -#define FLAG_READ 2 - -#ifdef ZERO_BATT_RING /* Need to debounce Off/On hook too */ -#define JAPAN -#endif - -#define RING_DEBOUNCE 64 /* Ringer Debounce (in ms) */ -#ifdef JAPAN -#define BATT_DEBOUNCE 30 /* Battery debounce (in ms) */ -#define OH_DEBOUNCE 350 /* Off/On hook debounce (in ms) */ -#else -#define BATT_DEBOUNCE 80 /* Battery debounce (in ms) */ -#endif - -#define MINPEGTIME 10 * 8 /* 30 ms peak to peak gets us no more than 100 Hz */ -#define PEGTIME 50 * 8 /* 50ms peak to peak gets us rings of 10 Hz or more */ -#define PEGCOUNT 5 /* 5 cycles of pegging means RING */ - -#define wcfxo_printk(level, span, fmt, ...) \ - printk(KERN_ ## level "%s-%s: %s: " fmt, #level, \ - THIS_MODULE->name, (span).name, ## __VA_ARGS__) - -#define wcfxo_notice(span, fmt, ...) \ - wcfxo_printk(NOTICE, span, fmt, ## __VA_ARGS__) - -#define wcfxo_dbg(span, fmt, ...) \ - ((void)((debug) && wcfxo_printk(DEBUG, span, "%s: " fmt, \ - __FUNCTION__, ## __VA_ARGS__) ) ) - -struct reg { - unsigned long flags; - unsigned char index; - unsigned char reg; - unsigned char value; -}; - -static int wecareregs[] = -{ - WC_DAA_DCTL1, WC_DAA_DCTL2, WC_DAA_PLL2_N2_M2, WC_DAA_CHIPA_REV, - WC_DAA_LINE_STAT, WC_DAA_CHIPB_REV, WC_DAA_INT_CTL2, WC_DAA_INT_CTL4, -}; - -struct wcfxo { - struct pci_dev *dev; - char *variety; - struct zt_span span; - struct zt_chan chan; - int usecount; - int dead; - int pos; - unsigned long flags; - int freeregion; - int ring; - int offhook; - int battery; - int wregcount; - int readpos; - int rreadpos; - unsigned int pegtimer; - int pegcount; - int peg; - int battdebounce; - int nobatttimer; - int ringdebounce; -#ifdef JAPAN - int ohdebounce; -#endif - int allread; - int regoffset; /* How far off our registers are from what we expect */ - int alt; - int ignoreread; - int reset; - /* Up to 6 register can be written at a time */ - struct reg regs[ZT_CHUNKSIZE]; - struct reg oldregs[ZT_CHUNKSIZE]; - unsigned char lasttx[ZT_CHUNKSIZE]; - /* Up to 32 registers of whatever we most recently read */ - unsigned char readregs[32]; - unsigned long ioaddr; - dma_addr_t readdma; - dma_addr_t writedma; - volatile int *writechunk; /* Double-word aligned write memory */ - volatile int *readchunk; /* Double-word aligned read memory */ -#ifdef ZERO_BATT_RING - int onhook; -#endif -#ifdef ENABLE_TASKLETS - int taskletrun; - int taskletsched; - int taskletpending; - int taskletexec; - int txerrors; - int ints; - struct tasklet_struct wcfxo_tlet; -#endif -}; - -#define FLAG_INVERTSER (1 << 0) -#define FLAG_USE_XTAL (1 << 1) -#define FLAG_DOUBLE_CLOCK (1 << 2) -#define FLAG_RESET_ON_AUX5 (1 << 3) -#define FLAG_NO_I18N_REGS (1 << 4) /*!< Uses si3035, rather si3034 */ - -struct wcfxo_desc { - char *name; - unsigned long flags; -}; - - -static struct wcfxo_desc wcx100p = { "Wildcard X100P", - FLAG_INVERTSER | FLAG_USE_XTAL | FLAG_DOUBLE_CLOCK }; - -static struct wcfxo_desc wcx101p = { "Wildcard X101P", - FLAG_USE_XTAL | FLAG_DOUBLE_CLOCK }; - -static struct wcfxo_desc generic = { "Generic Clone", - FLAG_USE_XTAL | FLAG_DOUBLE_CLOCK }; - -static struct wcfxo *ifaces[WC_MAX_IFACES]; - -static void wcfxo_release(struct wcfxo *wc); - -static int debug = 0; - -static int monitor = 0; - -static int quiet = 0; - -static int boost = 0; - -static int opermode = 0; - -static struct fxo_mode { - char *name; - int ohs; - int act; - int dct; - int rz; - int rt; - int lim; - int vol; -} fxo_modes[] = -{ - { "FCC", 0, 0, 2, 0, 0, 0, 0 }, /* US */ - { "CTR21", 0, 0, 3, 0, 0, 3, 0 }, /* Austria, Belgium, Denmark, Finland, France, Germany, - Greece, Iceland, Ireland, Italy, Luxembourg, Netherlands, - Norway, Portugal, Spain, Sweden, Switzerland, and UK */ -}; - -static inline void wcfxo_transmitprep(struct wcfxo *wc, unsigned char ints) -{ - volatile int *writechunk; - int x; - int written=0; - unsigned short cmd; - - /* if nothing to transmit, have to do the zt_transmit() anyway */ - if (!(ints & 3)) { - /* Calculate Transmission */ - zt_transmit(&wc->span); - return; - } - - /* Remember what it was we just sent */ - memcpy(wc->lasttx, wc->chan.writechunk, ZT_CHUNKSIZE); - - if (ints & 0x01) { - /* Write is at interrupt address. Start writing from normal offset */ - writechunk = wc->writechunk; - } else { - writechunk = wc->writechunk + ZT_CHUNKSIZE * 2; - } - - zt_transmit(&wc->span); - - for (x=0;xflags & FLAG_INVERTSER) - writechunk[x << 1] = cpu_to_le32( - ~((unsigned short)(ZT_XLAW(wc->chan.writechunk[x], (&wc->chan)))| 0x1) << 16 - ); - else - writechunk[x << 1] = cpu_to_le32( - ((unsigned short)(ZT_XLAW(wc->chan.writechunk[x], (&wc->chan)))| 0x1) << 16 - ); - - /* We always have a command to follow our signal */ - if (!wc->regs[x].flags) { - /* Fill in an empty register command with a read for a potentially useful register */ - wc->regs[x].flags = FLAG_READ; - wc->regs[x].reg = wecareregs[wc->readpos]; - wc->regs[x].index = wc->readpos; - wc->readpos++; - if (wc->readpos >= (sizeof(wecareregs) / sizeof(wecareregs[0]))) { - wc->allread = 1; - wc->readpos = 0; - } - } - - /* Prepare the command to follow it */ - switch(wc->regs[x].flags) { - case FLAG_READ: - cmd = (wc->regs[x].reg | 0x20) << 8; - break; - case FLAG_WRITE: - cmd = (wc->regs[x].reg << 8) | (wc->regs[x].value & 0xff); - written = 1; - /* Wait at least four samples before reading */ - wc->ignoreread = 4; - break; - default: - printk("wcfxo: Huh? No read or write??\n"); - cmd = 0; - } - /* Setup the write chunk */ - if (wc->flags & FLAG_INVERTSER) - writechunk[(x << 1) + 1] = cpu_to_le32(~(cmd << 16)); - else - writechunk[(x << 1) + 1] = cpu_to_le32(cmd << 16); - } - if (written) - wc->readpos = 0; - wc->wregcount = 0; - - for (x=0;xoldregs[x] = wc->regs[x]; - wc->regs[x].flags = FLAG_EMPTY; - } - -} - -static inline void wcfxo_receiveprep(struct wcfxo *wc, unsigned char ints) -{ - volatile int *readchunk; - int x; - int realreg; - int realval; - int sample; - if (ints & 0x04) - /* Read is at interrupt address. Valid data is available at normal offset */ - readchunk = wc->readchunk; - else - readchunk = wc->readchunk + ZT_CHUNKSIZE * 2; - - /* Keep track of how quickly our peg alternates */ - wc->pegtimer+=ZT_CHUNKSIZE; - for (x=0;xoldregs[x].flags == FLAG_READ && !wc->ignoreread) { - realreg = wecareregs[(wc->regs[x].index + wc->regoffset) % - (sizeof(wecareregs) / sizeof(wecareregs[0]))]; - realval = (le32_to_cpu(readchunk[(x << 1) +wc->alt]) >> 16) & 0xff; - if ((realval == 0x89) && (realreg != WC_DAA_PLL2_N2_M2)) { - /* Some sort of slippage, correct for it */ - while(realreg != WC_DAA_PLL2_N2_M2) { - /* Find register 9 */ - realreg = wecareregs[(wc->regs[x].index + ++wc->regoffset) % - (sizeof(wecareregs) / sizeof(wecareregs[0]))]; - wc->regoffset = wc->regoffset % (sizeof(wecareregs) / sizeof(wecareregs[0])); - } - if (debug) - printk("New regoffset: %d\n", wc->regoffset); - } - /* Receive into the proper register */ - wc->readregs[realreg] = realval; - } - /* Look for pegging to indicate ringing */ - sample = (short)(le32_to_cpu(readchunk[(x << 1) + (1 - wc->alt)]) >> 16); - if ((sample > 32000) && (wc->peg != 1)) { - if ((wc->pegtimer < PEGTIME) && (wc->pegtimer > MINPEGTIME)) - wc->pegcount++; - wc->pegtimer = 0; - wc->peg = 1; - } else if ((sample < -32000) && (wc->peg != -1)) { - if ((wc->pegtimer < PEGTIME) && (wc->pegtimer > MINPEGTIME)) - wc->pegcount++; - wc->pegtimer = 0; - wc->peg = -1; - } - wc->chan.readchunk[x] = ZT_LIN2X((sample), (&wc->chan)); - } - if (wc->pegtimer > PEGTIME) { - /* Reset pegcount if our timer expires */ - wc->pegcount = 0; - } - /* Decrement debouncer if appropriate */ - if (wc->ringdebounce) - wc->ringdebounce--; - if (!wc->offhook && !wc->ringdebounce) { - if (!wc->ring && (wc->pegcount > PEGCOUNT)) { - /* It's ringing */ - if (debug) - printk("RING!\n"); - zt_hooksig(&wc->chan, ZT_RXSIG_RING); - wc->ring = 1; - } - if (wc->ring && !wc->pegcount) { - /* No more ring */ - if (debug) - printk("NO RING!\n"); - zt_hooksig(&wc->chan, ZT_RXSIG_OFFHOOK); - wc->ring = 0; - } - } - if (wc->ignoreread) - wc->ignoreread--; - - /* Do the echo cancellation... We are echo cancelling against - what we sent two chunks ago*/ - zt_ec_chunk(&wc->chan, wc->chan.readchunk, wc->lasttx); - - /* Receive the result */ - zt_receive(&wc->span); -} - -#ifdef ENABLE_TASKLETS -static void wcfxo_tasklet(unsigned long data) -{ - struct wcfxo *wc = (struct wcfxo *)data; - wc->taskletrun++; - /* Run tasklet */ - if (wc->taskletpending) { - wc->taskletexec++; - wcfxo_receiveprep(wc, wc->ints); - wcfxo_transmitprep(wc, wc->ints); - } - wc->taskletpending = 0; -} -#endif - -static void wcfxo_stop_dma(struct wcfxo *wc); -static void wcfxo_restart_dma(struct wcfxo *wc); - -ZAP_IRQ_HANDLER(wcfxo_interrupt) -{ - struct wcfxo *wc = dev_id; - unsigned char ints; - unsigned char b; -#ifdef DEBUG_RING - static int oldb = 0; - static int oldcnt = 0; -#endif - - ints = inb(wc->ioaddr + WC_INTSTAT); - - - if (!ints) -#ifdef LINUX26 - return IRQ_NONE; -#else - return; -#endif - - outb(ints, wc->ioaddr + WC_INTSTAT); - - if (ints & 0x0c) { /* if there is a rx interrupt pending */ -#ifdef ENABLE_TASKLETS - wc->ints = ints; - if (!wc->taskletpending) { - wc->taskletpending = 1; - wc->taskletsched++; - tasklet_hi_schedule(&wc->wcfxo_tlet); - } else - wc->txerrors++; -#else - wcfxo_receiveprep(wc, ints); - /* transmitprep looks to see if there is anything to transmit - and returns by itself if there is nothing */ - wcfxo_transmitprep(wc, ints); -#endif - } - - if (ints & 0x10) { - printk("FXO PCI Master abort\n"); - /* Stop DMA andlet the watchdog start it again */ - wcfxo_stop_dma(wc); -#ifdef LINUX26 - return IRQ_RETVAL(1); -#else - return; -#endif - } - - if (ints & 0x20) { - printk("PCI Target abort\n"); -#ifdef LINUX26 - return IRQ_RETVAL(1); -#else - return; -#endif - } - if (1 /* !(wc->report % 0xf) */) { - /* Check for BATTERY from register and debounce for 8 ms */ - b = wc->readregs[WC_DAA_LINE_STAT] & 0xf; - if (!b) { - wc->nobatttimer++; -#if 0 - if (wc->battery) - printk("Battery loss: %d (%d debounce)\n", b, wc->battdebounce); -#endif - if (wc->battery && !wc->battdebounce) { - if (debug) - printk("NO BATTERY!\n"); - wc->battery = 0; -#ifdef JAPAN - if ((!wc->ohdebounce) && wc->offhook) { - zt_hooksig(&wc->chan, ZT_RXSIG_ONHOOK); - if (debug) - printk("Signalled On Hook\n"); -#ifdef ZERO_BATT_RING - wc->onhook++; -#endif - } -#else - zt_hooksig(&wc->chan, ZT_RXSIG_ONHOOK); -#endif - wc->battdebounce = BATT_DEBOUNCE; - } else if (!wc->battery) - wc->battdebounce = BATT_DEBOUNCE; - if ((wc->nobatttimer > 5000) && -#ifdef ZERO_BATT_RING - !(wc->readregs[WC_DAA_DCTL1] & 0x04) && -#endif - (!wc->span.alarms)) { - wc->span.alarms = ZT_ALARM_RED; - zt_alarm_notify(&wc->span); - } - } else if (b == 0xf) { - if (!wc->battery && !wc->battdebounce) { - if (debug) - printk("BATTERY!\n"); -#ifdef ZERO_BATT_RING - if (wc->onhook) { - wc->onhook = 0; - zt_hooksig(&wc->chan, ZT_RXSIG_OFFHOOK); - if (debug) - printk("Signalled Off Hook\n"); - } -#else - zt_hooksig(&wc->chan, ZT_RXSIG_OFFHOOK); -#endif - wc->battery = 1; - wc->nobatttimer = 0; - wc->battdebounce = BATT_DEBOUNCE; - if (wc->span.alarms) { - wc->span.alarms = 0; - zt_alarm_notify(&wc->span); - } - } else if (wc->battery) - wc->battdebounce = BATT_DEBOUNCE; - } else { - /* It's something else... */ - wc->battdebounce = BATT_DEBOUNCE; - } - - if (wc->battdebounce) - wc->battdebounce--; -#ifdef JAPAN - if (wc->ohdebounce) - wc->ohdebounce--; -#endif - - } -#ifdef LINUX26 - return IRQ_RETVAL(1); -#endif -} - -static int wcfxo_setreg(struct wcfxo *wc, unsigned char reg, unsigned char value) -{ - int x; - if (wc->wregcount < ZT_CHUNKSIZE) { - x = wc->wregcount; - wc->regs[x].reg = reg; - wc->regs[x].value = value; - wc->regs[x].flags = FLAG_WRITE; - wc->wregcount++; - return 0; - } - printk("wcfxo: Out of space to write register %02x with %02x\n", reg, value); - return -1; -} - -static int wcfxo_open(struct zt_chan *chan) -{ - struct wcfxo *wc = chan->pvt; - if (wc->dead) - return -ENODEV; - wc->usecount++; -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#endif - return 0; -} - -static int wcfxo_watchdog(struct zt_span *span, int event) -{ - printk("FXO: Restarting DMA\n"); - wcfxo_restart_dma(span->pvt); - return 0; -} - -static int wcfxo_close(struct zt_chan *chan) -{ - struct wcfxo *wc = chan->pvt; - wc->usecount--; -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#endif - /* If we're dead, release us now */ - if (!wc->usecount && wc->dead) - wcfxo_release(wc); - return 0; -} - -static int wcfxo_hooksig(struct zt_chan *chan, zt_txsig_t txsig) -{ - struct wcfxo *wc = chan->pvt; - int reg=0; - switch(txsig) { - case ZT_TXSIG_START: - case ZT_TXSIG_OFFHOOK: - /* Take off hook and enable normal mode reception. This must - be done in two steps because of a hardware bug. */ - reg = wc->readregs[WC_DAA_DCTL1] & ~0x08; - wcfxo_setreg(wc, WC_DAA_DCTL1, reg); - - reg = reg | 0x1; - wcfxo_setreg(wc, WC_DAA_DCTL1, reg); - wc->offhook = 1; -#ifdef JAPAN - wc->battery = 1; - wc->battdebounce = BATT_DEBOUNCE; - wc->ohdebounce = OH_DEBOUNCE; -#endif - break; - case ZT_TXSIG_ONHOOK: - /* Put on hook and enable on hook line monitor */ - reg = wc->readregs[WC_DAA_DCTL1] & 0xfe; - wcfxo_setreg(wc, WC_DAA_DCTL1, reg); - - reg = reg | 0x08; - wcfxo_setreg(wc, WC_DAA_DCTL1, reg); - wc->offhook = 0; - /* Don't accept a ring for another 1000 ms */ - wc->ringdebounce = 1000; -#ifdef JAPAN - wc->ohdebounce = OH_DEBOUNCE; -#endif - break; - default: - printk("wcfxo: Can't set tx state to %d\n", txsig); - } - if (debug) - printk("Setting hook state to %d (%02x)\n", txsig, reg); - return 0; -} - -static int wcfxo_initialize(struct wcfxo *wc) -{ - /* Zapata stuff */ - sprintf(wc->span.name, "WCFXO/%d", wc->pos); - snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1); - sprintf(wc->chan.name, "WCFXO/%d/%d", wc->pos, 0); - snprintf(wc->span.location, sizeof(wc->span.location) - 1, - "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); - wc->span.manufacturer = "Digium"; - strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); - wc->chan.sigcap = ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF; - wc->chan.chanpos = 1; - wc->span.chans = &wc->chan; - wc->span.channels = 1; - wc->span.hooksig = wcfxo_hooksig; - wc->span.irq = wc->dev->irq; - wc->span.open = wcfxo_open; - wc->span.close = wcfxo_close; - wc->span.flags = ZT_FLAG_RBS; - wc->span.deflaw = ZT_LAW_MULAW; - wc->span.watchdog = wcfxo_watchdog; -#ifdef ENABLE_TASKLETS - tasklet_init(&wc->wcfxo_tlet, wcfxo_tasklet, (unsigned long)wc); -#endif - init_waitqueue_head(&wc->span.maintq); - - wc->span.pvt = wc; - wc->chan.pvt = wc; - if (zt_register(&wc->span, 0)) { - printk("Unable to register span with zaptel\n"); - return -1; - } - return 0; -} - -static int wcfxo_hardware_init(struct wcfxo *wc) -{ - /* Hardware stuff */ - /* Reset PCI Interface chip and registers */ - outb(0x0e, wc->ioaddr + WC_CNTL); - if (wc->flags & FLAG_RESET_ON_AUX5) { - /* Set hook state to on hook for when we switch. - Make sure reset is high */ - outb(0x34, wc->ioaddr + WC_AUXD); - } else { - /* Set hook state to on hook for when we switch */ - outb(0x24, wc->ioaddr + WC_AUXD); - } - /* Set all to outputs except AUX 4, which is an input */ - outb(0xef, wc->ioaddr + WC_AUXC); - - /* Back to normal, with automatic DMA wrap around */ - outb(0x01, wc->ioaddr + WC_CNTL); - - /* Make sure serial port and DMA are out of reset */ - outb(inb(wc->ioaddr + WC_CNTL) & 0xf9, wc->ioaddr + WC_CNTL); - - /* Configure serial port for MSB->LSB operation */ - if (wc->flags & FLAG_DOUBLE_CLOCK) - outb(0xc1, wc->ioaddr + WC_SERCTL); - else - outb(0xc0, wc->ioaddr + WC_SERCTL); - - if (wc->flags & FLAG_USE_XTAL) { - /* Use the crystal oscillator */ - outb(0x04, wc->ioaddr + WC_AUXFUNC); - } - - /* Delay FSC by 2 so it's properly aligned */ - outb(0x2, wc->ioaddr + WC_FSCDELAY); - - /* Setup DMA Addresses */ - outl(wc->writedma, wc->ioaddr + WC_DMAWS); /* Write start */ - outl(wc->writedma + ZT_CHUNKSIZE * 8 - 4, wc->ioaddr + WC_DMAWI); /* Middle (interrupt) */ - outl(wc->writedma + ZT_CHUNKSIZE * 16 - 4, wc->ioaddr + WC_DMAWE); /* End */ - - outl(wc->readdma, wc->ioaddr + WC_DMARS); /* Read start */ - outl(wc->readdma + ZT_CHUNKSIZE * 8 - 4, wc->ioaddr + WC_DMARI); /* Middle (interrupt) */ - outl(wc->readdma + ZT_CHUNKSIZE * 16 - 4, wc->ioaddr + WC_DMARE); /* End */ - - /* Clear interrupts */ - outb(0xff, wc->ioaddr + WC_INTSTAT); - return 0; -} - -static void wcfxo_enable_interrupts(struct wcfxo *wc) -{ - /* Enable interrupts (we care about all of them) */ - outb(0x3f, wc->ioaddr + WC_MASK0); - /* No external interrupts */ - outb(0x00, wc->ioaddr + WC_MASK1); -} - -static void wcfxo_start_dma(struct wcfxo *wc) -{ - /* Reset Master and TDM */ - outb(0x0f, wc->ioaddr + WC_CNTL); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - outb(0x01, wc->ioaddr + WC_CNTL); - outb(0x01, wc->ioaddr + WC_OPER); -} - -static void wcfxo_restart_dma(struct wcfxo *wc) -{ - /* Reset Master and TDM */ - outb(0x01, wc->ioaddr + WC_CNTL); - outb(0x01, wc->ioaddr + WC_OPER); -} - - -static void wcfxo_stop_dma(struct wcfxo *wc) -{ - outb(0x00, wc->ioaddr + WC_OPER); -} - -static void wcfxo_reset_tdm(struct wcfxo *wc) -{ - /* Reset TDM */ - outb(0x0f, wc->ioaddr + WC_CNTL); -} - -static void wcfxo_disable_interrupts(struct wcfxo *wc) -{ - outb(0x00, wc->ioaddr + WC_MASK0); - outb(0x00, wc->ioaddr + WC_MASK1); -} - -static void wcfxo_set_daa_mode(struct wcfxo *wc) -{ - /* Set country specific parameters (OHS, ACT, DCT, RZ, RT, LIM, VOL) */ - int reg16 = ((fxo_modes[opermode].ohs & 0x1) << 6) | - ((fxo_modes[opermode].act & 0x1) << 5) | - ((fxo_modes[opermode].dct & 0x3) << 2) | - ((fxo_modes[opermode].rz & 0x1) << 1) | - ((fxo_modes[opermode].rt & 0x1) << 0); - int reg17 = ((fxo_modes[opermode].lim & 0x3) << 3); - int reg18 = ((fxo_modes[opermode].vol & 0x3) << 3); - - if (wc->flags & FLAG_NO_I18N_REGS) { - wcfxo_dbg(wc->span, "This card does not support international settings.\n"); - return; - } - - wcfxo_setreg(wc, WC_DAA_INT_CTL1, reg16); - wcfxo_setreg(wc, WC_DAA_INT_CTL2, reg17); - wcfxo_setreg(wc, WC_DAA_INT_CTL3, reg18); - - - /* Wait a couple of jiffies for our writes to finish */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1 + (ZT_CHUNKSIZE * HZ) / 800); - - printk("wcfxo: DAA mode is '%s'\n", fxo_modes[opermode].name); -} - -static int wcfxo_init_daa(struct wcfxo *wc) -{ - /* This must not be called in an interrupt */ - /* We let things settle for a bit */ - unsigned char reg15; - int chip_revb; -// set_current_state(TASK_INTERRUPTIBLE); -// schedule_timeout(10); - - /* Soft-reset it */ - wcfxo_setreg(wc, WC_DAA_CTL1, 0x80); - - /* Let the reset go */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1 + (ZT_CHUNKSIZE * HZ) / 800); - - /* We have a clock at 18.432 Mhz, so N1=1, M1=2, CGM=0 */ - wcfxo_setreg(wc, WC_DAA_PLL1_N1, 0x0); /* This value is N1 - 1 */ - wcfxo_setreg(wc, WC_DAA_PLL1_M1, 0x1); /* This value is M1 - 1 */ - /* We want to sample at 8khz, so N2 = 9, M2 = 10 (N2-1, M2-1) */ - wcfxo_setreg(wc, WC_DAA_PLL2_N2_M2, 0x89); - - /* Wait until the PLL's are locked. Time is between 100 uSec and 1 mSec */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1 + HZ/1000 + (ZT_CHUNKSIZE * HZ) / 800); - - /* No additional ration is applied to the PLL and faster lock times - * are possible */ - wcfxo_setreg(wc, WC_DAA_PLL_CTL, 0x0); - /* Enable off hook pin */ - wcfxo_setreg(wc, WC_DAA_DCTL1, 0x0a); - if (monitor) { - /* Enable ISOcap and external speaker and charge pump if present */ - wcfxo_setreg(wc, WC_DAA_DCTL2, 0x80); - } else { - /* Enable ISOcap and charge pump if present (leave speaker disabled) */ - wcfxo_setreg(wc, WC_DAA_DCTL2, 0xe0); - } - - /* Wait a couple of jiffies for our writes to finish */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1 + (ZT_CHUNKSIZE * HZ) / 800); - reg15 = 0x0; - /* Go ahead and attenuate transmit signal by 6 db */ - if (quiet) { - printk("wcfxo: Attenuating transmit signal for quiet operation\n"); - reg15 |= (quiet & 0x3) << 4; - } - if (boost) { - printk("wcfxo: Boosting receive signal\n"); - reg15 |= (boost & 0x3); - } - wcfxo_setreg(wc, WC_DAA_TXRX_GCTL, reg15); - - /* REVB: reg. 13, bits 5:2 */ - chip_revb = (wc->readregs[WC_DAA_CHIPB_REV] >> 2) & 0xF; - wcfxo_dbg(wc->span, "DAA chip REVB is %x\n", chip_revb); - switch(chip_revb) { - case 1: case 2: case 3: - /* This is a si3034. Nothing to do */ - break; - case 4: case 5: case 7: - /* This is 3035. Has no support for international registers */ - wc->flags |= FLAG_NO_I18N_REGS; - break; - default: - wcfxo_notice(wc->span, "Unknown DAA chip revision: REVB=%d\n", - chip_revb); - } - - /* Didn't get it right. Register 9 is still garbage */ - if (wc->readregs[WC_DAA_PLL2_N2_M2] != 0x89) - return -1; -#if 0 - { int x; - int y; - for (y=0;y<100;y++) { - printk(" reg dump ====== %d ======\n", y); - for (x=0;xreadregs[wecareregs[x]]); - } - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(100); - } } -#endif - return 0; -} - -static int __devinit wcfxo_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct wcfxo *wc; - struct wcfxo_desc *d = (struct wcfxo_desc *)ent->driver_data; - int x; - - for (x=0;x= WC_MAX_IFACES) { - printk(KERN_ERR "Too many interfaces: Found %d, can only handle %d.\n", - x, WC_MAX_IFACES - 1); - return -EIO; - } - - if (pci_enable_device(pdev)) - return -EIO; - - wc = kmalloc(sizeof(struct wcfxo), GFP_KERNEL); - if (!wc) { - printk(KERN_ERR "wcfxo: Failed initializinf card. Not enough memory."); - return -ENOMEM; - } - - ifaces[x] = wc; - memset(wc, 0, sizeof(struct wcfxo)); - wc->ioaddr = pci_resource_start(pdev, 0); - wc->dev = pdev; - wc->pos = x; - wc->variety = d->name; - wc->flags = d->flags; - /* Keep track of whether we need to free the region */ - if (request_region(wc->ioaddr, 0xff, "wcfxo")) - wc->freeregion = 1; - - /* Allocate enough memory for two zt chunks, receive and transmit. Each sample uses - 32 bits. Allocate an extra set just for control too */ - wc->writechunk = (int *)pci_alloc_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, &wc->writedma); - if (!wc->writechunk) { - printk("wcfxo: Unable to allocate DMA-able memory\n"); - if (wc->freeregion) - release_region(wc->ioaddr, 0xff); - return -ENOMEM; - } - - wc->readchunk = wc->writechunk + ZT_MAX_CHUNKSIZE * 4; /* in doublewords */ - wc->readdma = wc->writedma + ZT_MAX_CHUNKSIZE * 16; /* in bytes */ - - if (wcfxo_initialize(wc)) { - printk("wcfxo: Unable to intialize modem\n"); - if (wc->freeregion) - release_region(wc->ioaddr, 0xff); - kfree(wc); - return -EIO; - } - - /* Enable bus mastering */ - pci_set_master(pdev); - - /* Keep track of which device we are */ - pci_set_drvdata(pdev, wc); - - if (request_irq(pdev->irq, wcfxo_interrupt, ZAP_IRQ_SHARED, "wcfxo", wc)) { - printk("wcfxo: Unable to request IRQ %d\n", pdev->irq); - if (wc->freeregion) - release_region(wc->ioaddr, 0xff); - kfree(wc); - return -EIO; - } - - - wcfxo_hardware_init(wc); - /* Enable interrupts */ - wcfxo_enable_interrupts(wc); - /* Initialize Write/Buffers to all blank data */ - memset((void *)wc->writechunk,0,ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4); - /* Start DMA */ - wcfxo_start_dma(wc); - - /* Initialize DAA (after it's started) */ - if (wcfxo_init_daa(wc)) { - printk("Failed to initailize DAA, giving up...\n"); - wcfxo_stop_dma(wc); - wcfxo_disable_interrupts(wc); - zt_unregister(&wc->span); - free_irq(pdev->irq, wc); - - /* Reset PCI chip and registers */ - outb(0x0e, wc->ioaddr + WC_CNTL); - - if (wc->freeregion) - release_region(wc->ioaddr, 0xff); - kfree(wc); - return -EIO; - } - wcfxo_set_daa_mode(wc); - printk("Found a Wildcard FXO: %s\n", wc->variety); - - return 0; -} - -static void wcfxo_release(struct wcfxo *wc) -{ - zt_unregister(&wc->span); - if (wc->freeregion) - release_region(wc->ioaddr, 0xff); - kfree(wc); - printk("Freed a Wildcard\n"); -} - -static void __devexit wcfxo_remove_one(struct pci_dev *pdev) -{ - struct wcfxo *wc = pci_get_drvdata(pdev); - if (wc) { - - /* Stop any DMA */ - wcfxo_stop_dma(wc); - wcfxo_reset_tdm(wc); - - /* In case hardware is still there */ - wcfxo_disable_interrupts(wc); - - /* Immediately free resources */ - pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma); - free_irq(pdev->irq, wc); - - /* Reset PCI chip and registers */ - outb(0x0e, wc->ioaddr + WC_CNTL); - - /* Release span, possibly delayed */ - if (!wc->usecount) - wcfxo_release(wc); - else - wc->dead = 1; - } -} - -static struct pci_device_id wcfxo_pci_tbl[] = { - { 0xe159, 0x0001, 0x8084, PCI_ANY_ID, 0, 0, (unsigned long) &generic }, - { 0xe159, 0x0001, 0x8085, PCI_ANY_ID, 0, 0, (unsigned long) &wcx101p }, - { 0xe159, 0x0001, 0x8086, PCI_ANY_ID, 0, 0, (unsigned long) &generic }, - { 0xe159, 0x0001, 0x8087, PCI_ANY_ID, 0, 0, (unsigned long) &generic }, - { 0x1057, 0x5608, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcx100p }, - { 0 } -}; - -MODULE_DEVICE_TABLE (pci, wcfxo_pci_tbl); - -static struct pci_driver wcfxo_driver = { - name: "wcfxo", - probe: wcfxo_init_one, -#ifdef LINUX26 - remove: __devexit_p(wcfxo_remove_one), -#else - remove: wcfxo_remove_one, -#endif - id_table: wcfxo_pci_tbl, -}; - -static int __init wcfxo_init(void) -{ - int res; - int x; - if ((opermode >= sizeof(fxo_modes) / sizeof(fxo_modes[0])) || (opermode < 0)) { - printk("Invalid/unknown operating mode specified. Please choose one of:\n"); - for (x=0;x"); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif - -module_init(wcfxo_init); -module_exit(wcfxo_cleanup); diff --git a/wct1xxp.c b/wct1xxp.c deleted file mode 100644 index bcfed97..0000000 --- a/wct1xxp.c +++ /dev/null @@ -1,1438 +0,0 @@ -/* - * Linux Support Services, Inc. Wildcard T100P T1/PRI card Driver - * - * Written by Mark Spencer - * Matthew Fredrickson - * William Meadows - * - * Copyright (C) 2001, Linux Support Services, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef STANDALONE_ZAPATA -#include "zaptel.h" -#else -#include -#endif -#ifdef LINUX26 -#include -#endif - -#define WC_MAX_CARDS 32 - -/* -#define TEST_REGS -*/ - -/* Define to get more attention-grabbing but slightly more I/O using - alarm status */ -#define FANCY_ALARM - - -#define DELAY 0x0 /* 30 = 15 cycles, 10 = 8 cycles, 0 = 3 cycles */ - -#define WC_CNTL 0x00 -#define WC_OPER 0x01 -#define WC_AUXC 0x02 -#define WC_AUXD 0x03 -#define WC_MASK0 0x04 -#define WC_MASK1 0x05 -#define WC_INTSTAT 0x06 - -#define WC_DMAWS 0x08 -#define WC_DMAWI 0x0c -#define WC_DMAWE 0x10 -#define WC_DMARS 0x18 -#define WC_DMARI 0x1c -#define WC_DMARE 0x20 -#define WC_CURPOS 0x24 - -#define WC_SERC 0x2d -#define WC_FSCDELAY 0x2f - -#define WC_USERREG 0xc0 - -#define WC_CLOCK 0x0 -#define WC_LEDTEST 0x1 -#define WC_VERSION 0x2 - -/* Offset between transmit and receive */ -#define WC_OFFSET 4 - -#define BIT_CS (1 << 7) -#define BIT_ADDR (0xf << 3) - -#define BIT_LED0 (1 << 0) -#define BIT_LED1 (1 << 1) -#define BIT_TEST (1 << 2) - -static char *chips[] = -{ - "DS2152", - "DS21352", - "DS21552", - "Unknown Chip (3)", - "DS2154", - "DS21354", - "DS21554", - "Unknown Chip (7)", -}; - -static int chanmap_t1[] = -{ 2,1,0, - 6,5,4, - 10,9,8, - 14,13,12, - 18,17,16, - 22,21,20, - 26,25,24, - 30,29,28 }; - -static int chanmap_e1[] = -{ 2,1,0, - 7,6,5,4, - 11,10,9,8, - 15,14,13,12, - 19,18,17,16, - 23,22,21,20, - 27,26,25,24, - 31,30,29,28 }; - -#ifdef FANCY_ALARM -static int altab[] = { -0, 0, 0, 1, 2, 3, 4, 6, 8, 9, 11, 13, 16, 18, 20, 22, 24, 25, 27, 28, 29, 30, 31, 31, 32, 31, 31, 30, 29, 28, 27, 25, 23, 22, 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0, -}; -#endif - -struct t1xxp { - struct pci_dev *dev; - spinlock_t lock; - int ise1; - int num; - /* Our offset for finding channel 1 */ - int offset; - char *variety; - unsigned int intcount; - int usecount; - int clocktimeout; - int sync; - int dead; - int blinktimer; - int alarmtimer; - int loopupcnt; - int loopdowncnt; - int miss; - int misslast; - int *chanmap; -#ifdef FANCY_ALARM - int alarmpos; -#endif - unsigned char ledtestreg; - unsigned char outbyte; - unsigned long ioaddr; - unsigned short canary; - /* T1 signalling */ - unsigned char txsiga[3]; - unsigned char txsigb[3]; - dma_addr_t readdma; - dma_addr_t writedma; - volatile unsigned char *writechunk; /* Double-word aligned write memory */ - volatile unsigned char *readchunk; /* Double-word aligned read memory */ - unsigned char ec_chunk1[31][ZT_CHUNKSIZE]; - unsigned char ec_chunk2[31][ZT_CHUNKSIZE]; - unsigned char tempo[32]; - struct zt_span span; /* Span */ - struct zt_chan chans[31]; /* Channels */ -}; - -#define CANARY 0xca1e - -int debug = 0; /* doesnt do anything */ - -static struct t1xxp *cards[WC_MAX_CARDS]; - -static inline void start_alarm(struct t1xxp *wc) -{ -#ifdef FANCY_ALARM - wc->alarmpos = 0; -#endif - wc->blinktimer = 0; -} - -static inline void stop_alarm(struct t1xxp *wc) -{ -#ifdef FANCY_ALARM - wc->alarmpos = 0; -#endif - wc->blinktimer = 0; -} - -static inline void __select_framer(struct t1xxp *wc, int reg) -{ - /* Top four bits of address from AUX 6-3 */ - wc->outbyte &= ~BIT_CS; - wc->outbyte &= ~BIT_ADDR; - wc->outbyte |= (reg & 0xf0) >> 1; - outb(wc->outbyte, wc->ioaddr + WC_AUXD); -} - -static inline void __select_control(struct t1xxp *wc) -{ - if (!(wc->outbyte & BIT_CS)) { - wc->outbyte |= BIT_CS; - outb(wc->outbyte, wc->ioaddr + WC_AUXD); - } -} - -static int t1xxp_open(struct zt_chan *chan) -{ - struct t1xxp *wc = chan->pvt; - if (wc->dead) - return -ENODEV; - wc->usecount++; -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#endif - return 0; -} - -static int __t1_get_reg(struct t1xxp *wc, int reg) -{ - unsigned char res; - __select_framer(wc, reg); - /* Get value */ - res = inb(wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2)); - return res; -} - -static int __t1_set_reg(struct t1xxp *wc, int reg, unsigned char val) -{ - __select_framer(wc, reg); - /* Send address */ - outb(val, wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2)); - return 0; -} - -static int __control_set_reg(struct t1xxp *wc, int reg, unsigned char val) -{ - __select_control(wc); - outb(val, wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2)); - return 0; -} - -static int control_set_reg(struct t1xxp *wc, int reg, unsigned char val) -{ - unsigned long flags; - int res; - spin_lock_irqsave(&wc->lock, flags); - res = __control_set_reg(wc, reg, val); - spin_unlock_irqrestore(&wc->lock, flags); - return res; -} - -static int __control_get_reg(struct t1xxp *wc, int reg) -{ - unsigned char res; - /* The following makes UTTERLY no sense, but what was happening - was that reads in some cases were not actually happening - on the physical bus. Why, we dunno. But in debugging, we found - that writing before reading (in this case to an unused position) - seems to get rid of the problem */ - __control_set_reg(wc,3,0x69); /* do magic here */ - /* now get the read byte from the Xilinx part */ - res = inb(wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2)); - return res; -} - -static int control_get_reg(struct t1xxp *wc, int reg) -{ - unsigned long flags; - int res; - spin_lock_irqsave(&wc->lock, flags); - res = __control_get_reg(wc, reg); - spin_unlock_irqrestore(&wc->lock, flags); - return res; -} - -static void t1xxp_release(struct t1xxp *wc) -{ - zt_unregister(&wc->span); - kfree(wc); - printk("Freed a Wildcard\n"); -} - -static int t1xxp_close(struct zt_chan *chan) -{ - struct t1xxp *wc = chan->pvt; - wc->usecount--; -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#endif - /* If we're dead, release us now */ - if (!wc->usecount && wc->dead) - t1xxp_release(wc); - return 0; -} - -static void t1xxp_enable_interrupts(struct t1xxp *wc) -{ - /* Clear interrupts */ - outb(0xff, wc->ioaddr + WC_INTSTAT); - /* Enable interrupts (we care about all of them) */ - outb(0x3c /* 0x3f */, wc->ioaddr + WC_MASK0); - /* No external interrupts */ - outb(0x00, wc->ioaddr + WC_MASK1); -} - -static void t1xxp_start_dma(struct t1xxp *wc) -{ - /* Reset Master and TDM */ - outb(DELAY | 0x0f, wc->ioaddr + WC_CNTL); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - outb(DELAY | 0x01, wc->ioaddr + WC_CNTL); - outb(0x01, wc->ioaddr + WC_OPER); - if (debug) printk("Started DMA\n"); -} - -static void __t1xxp_stop_dma(struct t1xxp *wc) -{ - outb(0x00, wc->ioaddr + WC_OPER); -} - -static void __t1xxp_disable_interrupts(struct t1xxp *wc) -{ - outb(0x00, wc->ioaddr + WC_MASK0); - outb(0x00, wc->ioaddr + WC_MASK1); -} - -static void __t1xxp_set_clear(struct t1xxp *wc) -{ - /* Setup registers */ - int x,y; - unsigned char b; - - /* No such thing under E1 */ - if (wc->ise1) { - printk("Can't set clear mode on an E1!\n"); - return; - } - - for (x=0;x<3;x++) { - b = 0; - for (y=0;y<8;y++) - if (wc->chans[x * 8 + y].sig & ZT_SIG_CLEAR) - b |= (1 << y); - __t1_set_reg(wc, 0x39 + x, b); - } -} - -static void t1xxp_t1_framer_start(struct t1xxp *wc) -{ - int i; - char *coding, *framing; - unsigned long endjiffies; - int alreadyrunning = wc->span.flags & ZT_FLAG_RUNNING; - unsigned long flags; - - spin_lock_irqsave(&wc->lock, flags); - - /* Build up config */ - i = 0x20; - if (wc->span.lineconfig & ZT_CONFIG_ESF) { - coding = "ESF"; - i = 0x88; - } else { - coding = "SF"; - } - if (wc->span.lineconfig & ZT_CONFIG_B8ZS) { - framing = "B8ZS"; - i |= 0x44; - } else { - framing = "AMI"; - } - __t1_set_reg(wc, 0x38, i); - if (!(wc->span.lineconfig & ZT_CONFIG_ESF)) { - /* 1c in FDL bit */ - __t1_set_reg(wc, 0x7e, 0x1c); - } else { - __t1_set_reg(wc, 0x7e, 0x00); - } - - /* Set outgoing LBO */ - __t1_set_reg(wc, 0x7c, wc->span.txlevel << 5); - - printk("Using %s/%s coding/framing\n", coding, framing); - if (!alreadyrunning) { - /* Setup the clear channels */ - __t1xxp_set_clear(wc); - - /* Set LIRST bit to 1 */ - __t1_set_reg(wc, 0x0a, 0x80); - spin_unlock_irqrestore(&wc->lock, flags); - - /* Wait 100ms to give plenty of time for reset */ - endjiffies = jiffies + 10; - while(endjiffies < jiffies); - - spin_lock_irqsave(&wc->lock, flags); - - /* Reset LIRST bit and reset elastic stores */ - __t1_set_reg(wc, 0xa, 0x30); - - wc->span.flags |= ZT_FLAG_RUNNING; - } - spin_unlock_irqrestore(&wc->lock, flags); -} - -static void t1xxp_e1_framer_start(struct t1xxp *wc) -{ - int i; - char *coding, *framing; - unsigned long endjiffies; - int alreadyrunning = wc->span.flags & ZT_FLAG_RUNNING; - unsigned long flags; - char *crcing = ""; - unsigned char ccr1, tcr1, tcr2; - - spin_lock_irqsave(&wc->lock, flags); - - /* Build up config */ - ccr1 = 0; - tcr1 = 8; - tcr2 = 0; - if (wc->span.lineconfig & ZT_CONFIG_CCS) { - coding = "CCS"; /* Receive CCS */ - ccr1 |= 8; - } else { - tcr1 |= 0x20; - coding = "CAS"; - } - if (wc->span.lineconfig & ZT_CONFIG_HDB3) { - ccr1 |= 0x44; /* TX/RX HDB3 */ - framing = "HDB3"; - } else { - framing = "AMI"; - } - if (wc->span.lineconfig & ZT_CONFIG_CRC4) { - ccr1 |= 0x11; - tcr2 |= 0x02; - crcing = " with CRC4"; - } - __t1_set_reg(wc, 0x12, tcr1); - __t1_set_reg(wc, 0x13, tcr2); - __t1_set_reg(wc, 0x14, ccr1); - __t1_set_reg(wc, 0x18, 0x20); /* 120 Ohm */ - - -#if 0 /* XXX Does LBO Matter? XXX */ - /* Set outgoing LBO */ - __t1_set_reg(wc, 0x7c, wc->span.txlevel << 5); -#endif - - printk("Using %s/%s coding/framing%s 120 Ohms\n", coding, framing,crcing); - if (!alreadyrunning) { - - __t1_set_reg(wc,0x1b,0x8a); /* CCR3: LIRST & TSCLKM */ - __t1_set_reg(wc,0x20,0x1b); /* TAFR */ - __t1_set_reg(wc,0x21,0x5f); /* TNAFR */ - __t1_set_reg(wc,0x40,0xb); /* TSR1 */ - for(i = 0x41; i <= 0x4f; i++) __t1_set_reg(wc,i,0x55); - for(i = 0x22; i <= 0x25; i++) __t1_set_reg(wc,i,0xff); - spin_unlock_irqrestore(&wc->lock, flags); - - /* Wait 100ms to give plenty of time for reset */ - endjiffies = jiffies + 10; - while(endjiffies < jiffies); - - spin_lock_irqsave(&wc->lock, flags); - - __t1_set_reg(wc, 0x1b, 0x9a); /* Set ESR */ - __t1_set_reg(wc, 0x1b, 0x82); /* TSCLKM only now */ - - /* Reset LIRST bit and reset elastic stores */ - - wc->span.flags |= ZT_FLAG_RUNNING; - } - spin_unlock_irqrestore(&wc->lock, flags); -} - -static int t1xxp_framer_sanity_check(struct t1xxp *wc) -{ - int res; - int chipid; - unsigned long flags; - int x; - - /* Sanity check */ - spin_lock_irqsave(&wc->lock, flags); - for (x=0x0;x<192;x++) - __t1_set_reg(wc, x, 0); - res = __t1_get_reg(wc, 0x0f); - res = __t1_get_reg(wc, 0x0f); - chipid = ((res & 0x80) >> 5) | ((res & 0x30) >> 4); - wc->ise1 = (res & 0x80) ? (1 << 4) : 0; - spin_unlock_irqrestore(&wc->lock, flags); - - printk("Framer: %s, Revision: %d (%s)\n", chips[chipid], res & 0xf, wc->ise1 ? "E1" : "T1"); - return 0; -} - -static int t1xxp_framer_hard_reset(struct t1xxp *wc) -{ - int x; - unsigned long flags; - - spin_lock_irqsave(&wc->lock, flags); - /* Initialize all registers to 0 */ - for (x=0x0;x<192;x++) - __t1_set_reg(wc, x, 0); - - if (wc->ise1) { - /* Set LOTCMC (switch to RCLCK if TCLK fails) */ - __t1_set_reg(wc, 0x1a, 0x04); - - /* RSYNC is an input */ - __t1_set_reg(wc, 0x10, 0x20); - - /* Rx elastic store enabled, 2.048 Mhz (in theory) */ - __t1_set_reg(wc, 0x11, 0x06); - - /* TSYNC is an input, Tsis mode */ - __t1_set_reg(wc, 0x12, 0x08); - - /* Tx elastic store enabled, 2.048 Mhz (in theory) */ - __t1_set_reg(wc, 0x1b, 0x82); - - - - } else { - /* Full-on sync required for T1 */ - __t1_set_reg(wc, 0x2b, 0x08); - /* RSYNC is an input */ - __t1_set_reg(wc, 0x2c, 0x08); - - /* Enable tx RBS bits */ - __t1_set_reg(wc, 0x35, 0x10); - - /* TSYNC is output */ - __t1_set_reg(wc, 0x36, 0x04); - - /* Tx and Rx elastic store enabled, 2.048 Mhz (in theory) */ - __t1_set_reg(wc, 0x37, 0x9c); - - /* Setup Loopup / Loopdown codes */ - __t1_set_reg(wc, 0x12, 0x22); - __t1_set_reg(wc, 0x14, 0x80); - __t1_set_reg(wc, 0x15, 0x80); - } - - spin_unlock_irqrestore(&wc->lock, flags); - return 0; -} - -static int t1xxp_rbsbits(struct zt_chan *chan, int bits) -{ - struct t1xxp *wc = chan->pvt; - unsigned long flags; - int b,o; - unsigned char mask; - - /* Byte offset */ - spin_lock_irqsave(&wc->lock, flags); - if (wc->ise1) { - if (chan->chanpos < 16) { - mask = ((bits << 4) | wc->chans[chan->chanpos - 1 + 16].txsig); - __t1_set_reg(wc, 0x40 + chan->chanpos, mask); - } - else if (chan->chanpos > 16) { - mask = (bits | (wc->chans[chan->chanpos - 1 - 16].txsig << 4)); - __t1_set_reg(wc, 0x40 + chan->chanpos - 16, mask); - } - wc->chans[chan->chanpos - 1].txsig = bits; - } else { - b = (chan->chanpos - 1) / 8; - o = (chan->chanpos - 1) % 8; - - mask = (1 << o); - - if (bits & ZT_ABIT) { - /* Set A-bit */ - wc->txsiga[b] |= mask; - } else { - /* Clear A-bit */ - wc->txsiga[b] &= ~mask; - } - if (bits & ZT_BBIT) { - /* Set B-bit */ - wc->txsigb[b] |= mask; - } else { - wc->txsigb[b] &= ~mask; - } - /* Output new values */ - __t1_set_reg(wc, 0x70 + b, wc->txsiga[b]); - __t1_set_reg(wc, 0x73 + b, wc->txsigb[b]); - __t1_set_reg(wc, 0x76 + b, wc->txsiga[b]); - __t1_set_reg(wc, 0x79 + b, wc->txsigb[b]); - } - spin_unlock_irqrestore(&wc->lock, flags); - return 0; -} - -static int t1xxp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) -{ - switch(cmd) { - default: - return -ENOTTY; - } -} - -static int t1xxp_startup(struct zt_span *span) -{ - struct t1xxp *wc = span->pvt; - - int i,alreadyrunning = span->flags & ZT_FLAG_RUNNING; - - /* initialize the start value for the entire chunk of last ec buffer */ - for(i = 0; i < span->channels; i++) - { - memset(wc->ec_chunk1[i], - ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); - memset(wc->ec_chunk2[i], - ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); - } - - /* Reset framer with proper parameters and start */ - if (wc->ise1) - t1xxp_e1_framer_start(wc); - else - t1xxp_t1_framer_start(wc); - printk("Calling startup (flags is %d)\n", span->flags); - - if (!alreadyrunning) { - /* Only if we're not already going */ - t1xxp_enable_interrupts(wc); - t1xxp_start_dma(wc); - span->flags |= ZT_FLAG_RUNNING; - } - return 0; -} - -static int t1xxp_shutdown(struct zt_span *span) -{ - struct t1xxp *wc = span->pvt; - unsigned long flags; - - spin_lock_irqsave(&wc->lock, flags); - __t1xxp_stop_dma(wc); - __t1xxp_disable_interrupts(wc); - span->flags &= ~ZT_FLAG_RUNNING; - spin_unlock_irqrestore(&wc->lock, flags); - - t1xxp_framer_hard_reset(wc); - return 0; -} - -static int t1xxp_maint(struct zt_span *span, int cmd) -{ - struct t1xxp *wc = span->pvt; - int res = 0; - unsigned long flags; - spin_lock_irqsave(&wc->lock, flags); - if (wc->ise1) { - switch(cmd) { - case ZT_MAINT_NONE: - __t1_set_reg(wc,0xa8,0); /* no loops */ - break; - case ZT_MAINT_LOCALLOOP: - __t1_set_reg(wc,0xa8,0x40); /* local loop */ - break; - case ZT_MAINT_REMOTELOOP: - __t1_set_reg(wc,0xa8,0x80); /* remote loop */ - break; - case ZT_MAINT_LOOPUP: - case ZT_MAINT_LOOPDOWN: - case ZT_MAINT_LOOPSTOP: - res = -ENOSYS; - break; - default: - printk("wct1xxp/E1: Unknown maint command: %d\n", cmd); - res = -EINVAL; - break; - } - } else { - switch(cmd) { - case ZT_MAINT_NONE: - __t1_set_reg(wc,0x19,0); /* no local loop */ - __t1_set_reg(wc,0x0a,0); /* no remote loop */ - break; - case ZT_MAINT_LOCALLOOP: - __t1_set_reg(wc,0x19,0x40); /* local loop */ - __t1_set_reg(wc,0x0a,0); /* no remote loop */ - break; - case ZT_MAINT_REMOTELOOP: - __t1_set_reg(wc,0x1e,0); /* no local loop */ - __t1_set_reg(wc,0x0a,0x40); /* remote loop */ - break; - case ZT_MAINT_LOOPUP: - __t1_set_reg(wc,0x30,2); /* send loopup code */ - __t1_set_reg(wc,0x12,0x22); /* send loopup code */ - __t1_set_reg(wc,0x13,0x80); /* send loopup code */ - break; - case ZT_MAINT_LOOPDOWN: - __t1_set_reg(wc,0x30,2); /* send loopdown code */ - __t1_set_reg(wc,0x12,0x62); /* send loopdown code */ - __t1_set_reg(wc,0x13,0x90); /* send loopdown code */ - break; - case ZT_MAINT_LOOPSTOP: - __t1_set_reg(wc,0x30,0); /* stop sending loopup code */ - break; - default: - printk("wct1xxp/T1: Unknown maint command: %d\n", cmd); - res = -EINVAL; - } - } - spin_unlock_irqrestore(&wc->lock, flags); - return res; -} - -static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype) -{ - struct t1xxp *wc = chan->pvt; - unsigned long flags; - int alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING; - - spin_lock_irqsave(&wc->lock, flags); - - if (alreadyrunning && !wc->ise1) - __t1xxp_set_clear(wc); - - spin_unlock_irqrestore(&wc->lock, flags); - return 0; -} - -static int t1xxp_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) -{ - struct t1xxp *wc = span->pvt; - - /* Do we want to SYNC on receive or not */ - wc->sync = lc->sync; - /* If already running, apply changes immediately */ - if (span->flags & ZT_FLAG_RUNNING) - return t1xxp_startup(span); - - return 0; -} -static int t1xxp_software_init(struct t1xxp *wc) -{ - int x; - /* Find position */ - for (x=0;x= WC_MAX_CARDS) - return -1; - wc->num = x; - sprintf(wc->span.name, "WCT1/%d", wc->num); - snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num); - wc->span.manufacturer = "Digium"; - strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); - snprintf(wc->span.location, sizeof(wc->span.location) - 1, - "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); - wc->span.spanconfig = t1xxp_spanconfig; - wc->span.chanconfig = t1xxp_chanconfig; - wc->span.irq = wc->dev->irq; - wc->span.startup = t1xxp_startup; - wc->span.shutdown = t1xxp_shutdown; - wc->span.rbsbits = t1xxp_rbsbits; - wc->span.maint = t1xxp_maint; - wc->span.open = t1xxp_open; - wc->span.close = t1xxp_close; - wc->span.chans = wc->chans; - wc->span.flags = ZT_FLAG_RBS; - wc->span.ioctl = t1xxp_ioctl; - wc->span.pvt = wc; - if (wc->ise1) { - wc->span.channels = 31; - wc->span.deflaw = ZT_LAW_ALAW; - wc->span.linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4; - wc->span.spantype = "E1"; - } else { - wc->span.channels = 24; - wc->span.deflaw = ZT_LAW_MULAW; - wc->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; - wc->span.spantype = "T1"; - } - init_waitqueue_head(&wc->span.maintq); - for (x=0;xspan.channels;x++) { - sprintf(wc->chans[x].name, "WCT1/%d/%d", wc->num, x + 1); - wc->chans[x].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_EM_E1 | - ZT_SIG_FXSLS | ZT_SIG_FXSGS | - ZT_SIG_FXSKS | ZT_SIG_FXOLS | ZT_SIG_DACS_RBS | - ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF; - wc->chans[x].pvt = wc; - wc->chans[x].chanpos = x + 1; - } - if (zt_register(&wc->span, 0)) { - printk("Unable to register span with zaptel\n"); - return -1; - } - return 0; -} - -static inline void __handle_leds(struct t1xxp *wc) -{ - int oldreg; - wc->blinktimer++; - - if (wc->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) { - /* Red/Blue alarm */ -#ifdef FANCY_ALARM - if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) { - wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0; - __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); - } - if (wc->blinktimer == 0xf) { - wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1); - __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); - wc->blinktimer = -1; - wc->alarmpos++; - if (wc->alarmpos >= (sizeof(altab) / sizeof(altab[0]))) - wc->alarmpos = 0; - } -#else - if (wc->blinktimer == 160) { - wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0; - __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); - } else if (wc->blinktimer == 480) { - wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1); - __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); - wc->blinktimer = 0; - } -#endif - } else if (wc->span.alarms & ZT_ALARM_YELLOW) { - /* Yellow Alarm */ - if (!(wc->blinktimer % 2)) - wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0; - else - wc->ledtestreg = (wc->ledtestreg | BIT_LED0) & ~BIT_LED1; - __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); - } else { - /* No Alarm */ - oldreg = wc->ledtestreg; - if (wc->span.maintstat != ZT_MAINT_NONE) - wc->ledtestreg |= BIT_TEST; - else - wc->ledtestreg &= ~BIT_TEST; - if (wc->span.flags & ZT_FLAG_RUNNING) - wc->ledtestreg = (wc->ledtestreg | BIT_LED0) & ~BIT_LED1; - else - wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1); - if (oldreg != wc->ledtestreg) - __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); - } -} - -static void t1xxp_transmitprep(struct t1xxp *wc, int ints) -{ - volatile unsigned char *txbuf; - int x,y; - int pos; - if (ints & 0x04 /* 0x01 */) { - /* We just finished sending the first buffer, start filling it - now */ - txbuf = wc->writechunk; - } else { - /* Just finished sending second buffer, fill it now */ - txbuf = wc->writechunk + 32 * ZT_CHUNKSIZE; - } - zt_transmit(&wc->span); - for (x=0;xoffset;x++) - txbuf[x] = wc->tempo[x]; - for (y=0;yspan.channels;x++) { - pos = y * 32 + wc->chanmap[x] + wc->offset; - /* Put channel number as outgoing data */ - if (pos < 32 * ZT_CHUNKSIZE) - txbuf[pos] = wc->chans[x].writechunk[y]; - else - wc->tempo[pos - 32 * ZT_CHUNKSIZE] = wc->chans[x].writechunk[y]; - } - } -} - -static void t1xxp_receiveprep(struct t1xxp *wc, int ints) -{ - volatile unsigned char *rxbuf; - volatile unsigned int *canary; - int x; - int y; - unsigned int oldcan; - if (ints & 0x04) { - /* Just received first buffer */ - rxbuf = wc->readchunk; - canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 64 - 4); - } else { - rxbuf = wc->readchunk + ZT_CHUNKSIZE * 32; - canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 32 - 4); - } - oldcan = *canary; - if (((oldcan & 0xffff0000) >> 16) != CANARY) { - /* Check top part */ - if (debug) printk("Expecting top %04x, got %04x\n", CANARY, (oldcan & 0xffff0000) >> 16); - wc->span.irqmisses++; - } else if ((oldcan & 0xffff) != ((wc->canary - 1) & 0xffff)) { - if (debug) printk("Expecting bottom %d, got %d\n", wc->canary - 1, oldcan & 0xffff); - wc->span.irqmisses++; - } - for (y=0;yspan.channels;x++) { - /* XXX Optimize, remove * and + XXX */ - /* Must map received channels into appropriate data */ - wc->chans[x].readchunk[y] = - rxbuf[32 * y + ((wc->chanmap[x] + WC_OFFSET + wc->offset) & 0x1f)]; - } - if (!wc->ise1) { - for (x=3;x<32;x+=4) { - if (rxbuf[32 * y + ((x + WC_OFFSET) & 0x1f)] == 0x7f) { - if (wc->offset != (x-3)) { - /* Resync */ - control_set_reg(wc, WC_CLOCK, 0x02 | wc->sync | wc->ise1); - wc->clocktimeout = 100; -#if 1 - if (debug) printk("T1: Lost our place, resyncing\n"); -#endif - } - } - } - } else { - if (!wc->clocktimeout && !wc->span.alarms) { - if ((rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)] & 0x7f) != 0x1b) { - if (wc->miss) { - if (debug) printk("Double miss (%d, %d)...\n", wc->misslast, rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)]); - control_set_reg(wc, WC_CLOCK, 0x02 | wc->sync | wc->ise1); - wc->clocktimeout = 100; - } else { - wc->miss = 1; - wc->misslast = rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)]; - } - } else { - wc->miss = 0; - } - } else { - wc->miss = 0; - } - } - } - /* Store the next canary */ - canary = (unsigned int *)(rxbuf + ZT_CHUNKSIZE * 32 - 4); - *canary = (wc->canary++) | (CANARY << 16); - for (x=0;xspan.channels;x++) { - zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, - wc->ec_chunk2[x]); - memcpy(wc->ec_chunk2[x],wc->ec_chunk1[x],ZT_CHUNKSIZE); - memcpy(wc->ec_chunk1[x],wc->chans[x].writechunk,ZT_CHUNKSIZE); - } - zt_receive(&wc->span); -} - -static void t1xxp_check_sigbits(struct t1xxp *wc, int x) -{ - int a,b,i,y,rxs; - unsigned long flags; - - spin_lock_irqsave(&wc->lock, flags); - if (wc->ise1) { - /* Read 5 registers at a time, loading 10 channels at a time */ - for (i = (x * 5); i < (x * 5) + 5; i++) { - a = __t1_get_reg(wc, 0x31 + i); - /* Get high channel in low bits */ - rxs = (a & 0xf); - if (!(wc->chans[i+16].sig & ZT_SIG_CLEAR)) { - if (wc->chans[i+16].rxsig != rxs) { - spin_unlock_irqrestore(&wc->lock, flags); - zt_rbsbits(&wc->chans[i+16], rxs); - spin_lock_irqsave(&wc->lock, flags); - } - } - rxs = (a >> 4) & 0xf; - if (!(wc->chans[i].sig & ZT_SIG_CLEAR)) { - if (wc->chans[i].rxsig != rxs) { - spin_unlock_irqrestore(&wc->lock, flags); - zt_rbsbits(&wc->chans[i], rxs); - spin_lock_irqsave(&wc->lock, flags); - } - } - } - } else { - a = __t1_get_reg(wc, 0x60 + x); - b = __t1_get_reg(wc, 0x63 + x); - for (y=0;y<8;y++) { - i = x * 8 + y; - rxs = 0; - if (a & (1 << y)) - rxs |= ZT_ABIT; - if (b & (1 << y)) - rxs |= ZT_BBIT; - if (!(wc->chans[i].sig & ZT_SIG_CLEAR)) { - if (wc->chans[i].rxsig != rxs) { - spin_unlock_irqrestore(&wc->lock, flags); - zt_rbsbits(&wc->chans[i], rxs); - spin_lock_irqsave(&wc->lock, flags); - } - } - } - } - spin_unlock_irqrestore(&wc->lock, flags); -} - -static void t1xxp_check_alarms(struct t1xxp *wc) -{ - unsigned char c,d; - int alarms; - int x,j; - unsigned long flags; - - spin_lock_irqsave(&wc->lock, flags); - - if (wc->ise1) { - __t1_set_reg(wc, 0x06, 0xff); - c = __t1_get_reg(wc, 0x6); - } else { - /* Get RIR2 */ - c = __t1_get_reg(wc, 0x31); - wc->span.rxlevel = c >> 6; - - /* Get status register s*/ - __t1_set_reg(wc, 0x20, 0xff); - c = __t1_get_reg(wc, 0x20); - } - - /* Assume no alarms */ - alarms = 0; - - /* And consider only carrier alarms */ - wc->span.alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); - - if (wc->ise1) { - /* XXX Implement me XXX */ - } else { - /* Detect loopup code if we're not sending one */ - if ((!wc->span.mainttimer) && (c & 0x80)) { - /* Loop-up code detected */ - if ((wc->loopupcnt++ > 80) && (wc->span.maintstat != ZT_MAINT_REMOTELOOP)) { - __t1_set_reg(wc, 0x1e, 0); /* No local loop */ - __t1_set_reg(wc, 0x0a, 0x40); /* Remote Loop */ - wc->span.maintstat = ZT_MAINT_REMOTELOOP; - } - } else { - wc->loopupcnt = 0; - } - /* Same for loopdown code */ - if ((!wc->span.mainttimer) && (c & 0x40)) { - /* Loop-down code detected */ - if ((wc->loopdowncnt++ > 80) && (wc->span.maintstat == ZT_MAINT_REMOTELOOP)) { - __t1_set_reg(wc, 0x1e, 0); /* No local loop */ - __t1_set_reg(wc, 0x0a, 0x0); /* No remote Loop */ - wc->span.maintstat = ZT_MAINT_NONE; - } - } else - wc->loopdowncnt = 0; - } - - if (wc->span.lineconfig & ZT_CONFIG_NOTOPEN) { - for (x=0,j=0;x < wc->span.channels;x++) - if ((wc->chans[x].flags & ZT_FLAG_OPEN) || - (wc->chans[x].flags & ZT_FLAG_NETDEV)) - j++; - if (!j) - alarms |= ZT_ALARM_NOTOPEN; - } - - if (wc->ise1) { - if (c & 0x9) - alarms |= ZT_ALARM_RED; - if (c & 0x2) - alarms |= ZT_ALARM_BLUE; - } else { - /* Check actual alarm status */ - if (c & 0x3) - alarms |= ZT_ALARM_RED; - if (c & 0x8) - alarms |= ZT_ALARM_BLUE; - } - /* Keep track of recovering */ - if ((!alarms) && wc->span.alarms) - wc->alarmtimer = ZT_ALARMSETTLE_TIME; - - /* If receiving alarms, go into Yellow alarm state */ - if (alarms && (!wc->span.alarms)) { -#if 0 - printk("Going into yellow alarm\n"); -#endif - if (wc->ise1) - __t1_set_reg(wc, 0x21, 0x7f); - else - __t1_set_reg(wc, 0x35, 0x11); - } - - if (wc->span.alarms != alarms) { - d = __control_get_reg(wc, WC_CLOCK); - start_alarm(wc); - if (!(alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK)) && - wc->sync) { - /* Use the recieve signalling */ - wc->span.syncsrc = wc->span.spanno; - d |= 1; - } else { - wc->span.syncsrc = 0; - d &= ~1; - } - __control_set_reg(wc, WC_CLOCK, d); - } - if (wc->alarmtimer) - alarms |= ZT_ALARM_RECOVER; - if (c & 0x4) - alarms |= ZT_ALARM_YELLOW; - - wc->span.alarms = alarms; - - spin_unlock_irqrestore(&wc->lock, flags); - - zt_alarm_notify(&wc->span); -} - -static void t1xxp_do_counters(struct t1xxp *wc) -{ - unsigned long flags; - - spin_lock_irqsave(&wc->lock, flags); - if (wc->alarmtimer) { - if (!--wc->alarmtimer) { - wc->span.alarms &= ~(ZT_ALARM_RECOVER); - /* Clear yellow alarm */ -#if 0 - printk("Coming out of alarm\n"); -#endif - if (wc->ise1) - __t1_set_reg(wc, 0x21, 0x5f); - else - __t1_set_reg(wc, 0x35, 0x10); - spin_unlock_irqrestore(&wc->lock, flags); - zt_alarm_notify(&wc->span); - spin_lock_irqsave(&wc->lock, flags); - } - } - spin_unlock_irqrestore(&wc->lock, flags); -} - -ZAP_IRQ_HANDLER(t1xxp_interrupt) -{ - struct t1xxp *wc = dev_id; - unsigned char ints; - unsigned long flags; - int x; - - ints = inb(wc->ioaddr + WC_INTSTAT); - if (!ints) -#ifdef LINUX26 - return IRQ_NONE; -#else - return; -#endif - - outb(ints, wc->ioaddr + WC_INTSTAT); - - if (!wc->intcount) { - if (debug) printk("Got interrupt: 0x%04x\n", ints); - } - wc->intcount++; - - if (wc->clocktimeout && !--wc->clocktimeout) - control_set_reg(wc, WC_CLOCK, 0x00 | wc->sync | wc->ise1); - - if (ints & 0x0f) { - t1xxp_receiveprep(wc, ints); - t1xxp_transmitprep(wc, ints); - } - spin_lock_irqsave(&wc->lock, flags); - -#if 1 - __handle_leds(wc); -#endif - - spin_unlock_irqrestore(&wc->lock, flags); - - /* Count down timers */ - t1xxp_do_counters(wc); - - /* Do some things that we don't have to do very often */ - x = wc->intcount & 15 /* 63 */; - switch(x) { - case 0: - case 1: - case 2: - t1xxp_check_sigbits(wc, x); - break; - case 4: - /* Check alarms 1/4 as frequently */ - if (!(wc->intcount & 0x30)) - t1xxp_check_alarms(wc); - break; - } - - if (ints & 0x10) - printk("PCI Master abort\n"); - - if (ints & 0x20) - printk("PCI Target abort\n"); - -#ifdef LINUX26 - return IRQ_RETVAL(1); -#endif -} - -static int t1xxp_hardware_init(struct t1xxp *wc) -{ - /* Hardware PCI stuff */ - /* Reset chip and registers */ - outb(DELAY | 0x0e, wc->ioaddr + WC_CNTL); - /* Set all outputs to 0 */ - outb(0x00, wc->ioaddr + WC_AUXD); - /* Set all to outputs except AUX1 (TDO). */ - outb(0xfd, wc->ioaddr + WC_AUXC); - /* Configure the serial port: double clock, 20ns width, no inversion, - MSB first */ - outb(0xc8, wc->ioaddr + WC_SERC); - - /* Internally delay FSC by one */ - outb(0x01, wc->ioaddr + WC_FSCDELAY); - - /* Back to normal, with automatic DMA wrap around */ - outb(DELAY | 0x01, wc->ioaddr + WC_CNTL); - - /* Make sure serial port and DMA are out of reset */ - outb(inb(wc->ioaddr + WC_CNTL) & 0xf9, WC_CNTL); - - /* Setup DMA Addresses */ - /* Start at writedma */ - outl(wc->writedma, wc->ioaddr + WC_DMAWS); /* Write start */ - /* First frame */ - outl(wc->writedma + ZT_CHUNKSIZE * 32 - 4, wc->ioaddr + WC_DMAWI); /* Middle (interrupt) */ - /* Second frame */ - outl(wc->writedma + ZT_CHUNKSIZE * 32 * 2 - 4, wc->ioaddr + WC_DMAWE); /* End */ - - outl(wc->readdma, wc->ioaddr + WC_DMARS); /* Read start */ - /* First frame */ - outl(wc->readdma + ZT_CHUNKSIZE * 32 - 4, wc->ioaddr + WC_DMARI); /* Middle (interrupt) */ - /* Second frame */ - outl(wc->readdma + ZT_CHUNKSIZE * 32 * 2 - 4, wc->ioaddr + WC_DMARE); /* End */ - - if (debug) printk("Setting up DMA (write/read = %08lx/%08lx)\n", (long)wc->writedma, (long)wc->readdma); - - /* Check out the controller */ - if (debug) printk("Controller version: %02x\n", control_get_reg(wc, WC_VERSION)); - - - control_set_reg(wc, WC_LEDTEST, 0x00); - - /* Sanity check also determines e1 or t1 */ - if (t1xxp_framer_sanity_check(wc)) - return -1; - if (wc->ise1) - wc->chanmap = chanmap_e1; - else - wc->chanmap = chanmap_t1; - /* Setup clock appropriately */ - control_set_reg(wc, WC_CLOCK, 0x02 | wc->sync | wc->ise1); - wc->clocktimeout = 100; - - /* Reset the T1 and report */ - t1xxp_framer_hard_reset(wc); - start_alarm(wc); - return 0; - -} - -static int __devinit t1xxp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int res; - struct t1xxp *wc; - unsigned int *canary; - - if (pci_enable_device(pdev)) { - res = -EIO; - } else { - wc = kmalloc(sizeof(struct t1xxp), GFP_KERNEL); - if (wc) { - memset(wc, 0x0, sizeof(struct t1xxp)); - spin_lock_init(&wc->lock); - wc->ioaddr = pci_resource_start(pdev, 0); - wc->dev = pdev; - wc->offset = 28; /* And you thought 42 was the answer */ - - wc->writechunk = - /* 32 channels, Double-buffer, Read/Write */ - (unsigned char *)pci_alloc_consistent(pdev, ZT_MAX_CHUNKSIZE * 32 * 2 * 2, &wc->writedma); - if (!wc->writechunk) { - printk("wct1xxp: Unable to allocate DMA-able memory\n"); - return -ENOMEM; - } - - /* Read is after the whole write piece (in bytes) */ - wc->readchunk = wc->writechunk + ZT_CHUNKSIZE * 32 * 2; - - /* Same thing... */ - wc->readdma = wc->writedma + ZT_CHUNKSIZE * 32 * 2; - - /* Initialize Write/Buffers to all blank data */ - memset((void *)wc->writechunk,0x00,ZT_MAX_CHUNKSIZE * 2 * 2 * 32); - /* Initialize canary */ - canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 64 - 4); - *canary = (CANARY << 16) | (0xffff); - - /* Enable bus mastering */ - pci_set_master(pdev); - - /* Keep track of which device we are */ - pci_set_drvdata(pdev, wc); - - if (request_irq(pdev->irq, t1xxp_interrupt, ZAP_IRQ_SHARED_DISABLED, "t1xxp", wc)) { - printk("t1xxp: Unable to request IRQ %d\n", pdev->irq); - kfree(wc); - return -EIO; - } - /* Initialize hardware */ - t1xxp_hardware_init(wc); - - /* We now know which version of card we have */ - if (wc->ise1) - wc->variety = "Digium Wildcard E100P E1/PRA"; - else - wc->variety = "Digium Wildcard T100P T1/PRI"; - - /* Misc. software stuff */ - t1xxp_software_init(wc); - - printk("Found a Wildcard: %s\n", wc->variety); - res = 0; - } else - res = -ENOMEM; - } - return res; -} - -static void t1xxp_stop_stuff(struct t1xxp *wc) -{ - /* Kill clock */ - control_set_reg(wc, WC_CLOCK, 0); - - /* Turn off LED's */ - control_set_reg(wc, WC_LEDTEST, 0); - - /* Reset the T1 */ - t1xxp_framer_hard_reset(wc); - -} - -static void __devexit t1xxp_remove_one(struct pci_dev *pdev) -{ - struct t1xxp *wc = pci_get_drvdata(pdev); - if (wc) { - - /* Stop any DMA */ - __t1xxp_stop_dma(wc); - - /* In case hardware is still there */ - __t1xxp_disable_interrupts(wc); - - t1xxp_stop_stuff(wc); - - /* Immediately free resources */ - pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 32 * 4, (void *)wc->writechunk, wc->writedma); - free_irq(pdev->irq, wc); - - /* Reset PCI chip and registers */ - outb(DELAY | 0x0e, wc->ioaddr + WC_CNTL); - - /* Release span, possibly delayed */ - if (!wc->usecount) - t1xxp_release(wc); - else - wc->dead = 1; - } -} - -static struct pci_device_id t1xxp_pci_tbl[] = { - { 0xe159, 0x0001, 0x6159, PCI_ANY_ID, 0, 0, (unsigned long) "Digium Wildcard T100P T1/PRI or E100P E1/PRA Board" }, - { 0 } -}; - -MODULE_DEVICE_TABLE(pci,t1xxp_pci_tbl); - -static struct pci_driver t1xxp_driver = { - name: "t1xxp", - probe: t1xxp_init_one, -#ifdef LINUX26 - remove: __devexit_p(t1xxp_remove_one), -#else - remove: t1xxp_remove_one, -#endif - suspend: NULL, - resume: NULL, - id_table: t1xxp_pci_tbl, -}; - -static int __init t1xxp_init(void) -{ - int res; - res = zap_pci_module(&t1xxp_driver); - if (res) - return -ENODEV; - return 0; -} - -static void __exit t1xxp_cleanup(void) -{ - pci_unregister_driver(&t1xxp_driver); -} - -#ifdef LINUX26 -module_param(debug, int, 0600); -#else -MODULE_PARM(debug, "i"); -#endif -MODULE_DESCRIPTION("Wildcard T100P/E100P Zaptel Driver"); -MODULE_AUTHOR("Mark Spencer "); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif - -module_init(t1xxp_init); -module_exit(t1xxp_cleanup); diff --git a/wct4xxp/Kbuild b/wct4xxp/Kbuild deleted file mode 100644 index e75a8ef..0000000 --- a/wct4xxp/Kbuild +++ /dev/null @@ -1,25 +0,0 @@ -obj-m += wct4xxp.o - -EXTRA_CFLAGS := -I$(src)/.. $(shell $(src)/../oct612x/octasic-helper cflags $(src)/../oct612x) -Wno-undef - -ifeq ($(HOTPLUG_FIRMWARE),yes) - EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE -endif - -wct4xxp-objs := base.o vpm450m.o $(shell $(src)/../oct612x/octasic-helper objects ../oct612x) - -ifneq ($(HOTPLUG_FIRMWARE),yes) -wct4xxp-objs += ../firmware/zaptel-fw-oct6114-064.o ../firmware/zaptel-fw-oct6114-128.o -endif - -$(obj)/../firmware/zaptel-fw-oct6114-064.o: $(obj)/base.o - $(MAKE) -C $(obj)/../firmware zaptel-fw-oct6114-064.o - -$(obj)/../firmware/zaptel-fw-oct6114-128.o: $(obj)/base.o - $(MAKE) -C $(obj)/../firmware zaptel-fw-oct6114-128.o - -$(obj)/base.o: $(src)/vpm450m.h $(src)/wct4xxp.h -$(obj)/base.o: $(src)/../zaptel.h - -$(obj)/vpm450m.o: $(src)/vpm450m.h -$(obj)/vpm450m.o: $(src)/../oct612x/include/oct6100api/oct6100_api.h diff --git a/wct4xxp/Makefile b/wct4xxp/Makefile deleted file mode 100644 index e1a2b83..0000000 --- a/wct4xxp/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -ifneq ($(KBUILD_EXTMOD),) -# We only get here on kernels 2.6.0-2.6.9 . -# For newer kernels, Kbuild will be included directly by the kernel -# build system. -include $(src)/Kbuild - -else - -OCTASIC_OBJS:=$(shell ../oct612x/octasic-helper objects ../oct612x) -OCTASIC_CFLAGS:=$(shell ../oct612x/octasic-helper cflags ../oct612x) -Wno-undef - -all: wct4xxp.o - -%.o: %.c - $(CC) $(KFLAGS) $(OCTASIC_CFLAGS) -o $@ -c $< - -base.o: ../zaptel.h vpm450m.h wct4xxp.h - -vpm450m.o: vpm450m.h ../oct612x/include/oct6100api/oct6100_api.h - -../firmware/zaptel-fw-oct6114-064.o: base.o - $(MAKE) -C ../firmware zaptel-fw-oct6114-064.o - -../firmware/zaptel-fw-oct6114-128.o: base.o - $(MAKE) -C ../firmware zaptel-fw-oct6114-128.o - -wct4xxp.o: base.o vpm450m.o $(OCTASIC_OBJS) ../firmware/zaptel-fw-oct6114-064.o ../firmware/zaptel-fw-oct6114-128.o - $(LD) -r -o $@ $^ - -clean: - rm -f *.o - rm -f $(OCTASIC_OBJS) - -endif diff --git a/wct4xxp/base.c b/wct4xxp/base.c deleted file mode 100644 index 0b4a2d9..0000000 --- a/wct4xxp/base.c +++ /dev/null @@ -1,3877 +0,0 @@ -/* - * TE410P Quad-T1/E1 PCI Driver version 0.1, 12/16/02 - * - * Written by Mark Spencer - * Based on previous works, designs, and archetectures conceived and - * written by Jim Dixon . - * - * Copyright (C) 2001 Jim Dixon / Zapata Telephony. - * Copyright (C) 2001-2005, Digium, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "zaptel.h" -#ifdef LINUX26 -#include -#endif - -#include "wct4xxp.h" -#include "vpm450m.h" - -/* Work queues are a way to better distribute load on SMP systems */ -#if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) -/* - * Work queues can significantly improve performance and scalability - * on multi-processor machines, but requires bypassing some kernel - * API's, so it's not guaranteed to be compatible with all kernels. - */ -/* #define ENABLE_WORKQUEUES */ -#endif - -/* Enable prefetching may help performance */ -#define ENABLE_PREFETCH - -/* Support first generation cards? */ -#define SUPPORT_GEN1 - -/* Define to get more attention-grabbing but slightly more I/O using - alarm status */ -#define FANCY_ALARM - -/* Define to support Digium Voice Processing Module expansion card */ -#define VPM_SUPPORT - -#define DEBUG_MAIN (1 << 0) -#define DEBUG_DTMF (1 << 1) -#define DEBUG_REGS (1 << 2) -#define DEBUG_TSI (1 << 3) -#define DEBUG_ECHOCAN (1 << 4) -#define DEBUG_RBS (1 << 5) -#define DEBUG_FRAMER (1 << 6) - -#ifdef ENABLE_WORKQUEUES -#include - -/* XXX UGLY!!!! XXX We have to access the direct structures of the workqueue which - are only defined within workqueue.c because they don't give us a routine to allow us - to nail a work to a particular thread of the CPU. Nailing to threads gives us substantially - higher scalability in multi-CPU environments though! */ - -/* - * The per-CPU workqueue (if single thread, we always use cpu 0's). - * - * The sequence counters are for flush_scheduled_work(). It wants to wait - * until until all currently-scheduled works are completed, but it doesn't - * want to be livelocked by new, incoming ones. So it waits until - * remove_sequence is >= the insert_sequence which pertained when - * flush_scheduled_work() was called. - */ - -struct cpu_workqueue_struct { - - spinlock_t lock; - - long remove_sequence; /* Least-recently added (next to run) */ - long insert_sequence; /* Next to add */ - - struct list_head worklist; - wait_queue_head_t more_work; - wait_queue_head_t work_done; - - struct workqueue_struct *wq; - task_t *thread; - - int run_depth; /* Detect run_workqueue() recursion depth */ -} ____cacheline_aligned; - -/* - * The externally visible workqueue abstraction is an array of - * per-CPU workqueues: - */ -struct workqueue_struct { - /* TODO: Find out exactly where the API changed */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) - struct cpu_workqueue_struct *cpu_wq; -#else - struct cpu_workqueue_struct cpu_wq[NR_CPUS]; -#endif - const char *name; - struct list_head list; /* Empty if single thread */ -}; - -/* Preempt must be disabled. */ -static void __t4_queue_work(struct cpu_workqueue_struct *cwq, - struct work_struct *work) -{ - unsigned long flags; - - spin_lock_irqsave(&cwq->lock, flags); - work->wq_data = cwq; - list_add_tail(&work->entry, &cwq->worklist); - cwq->insert_sequence++; - wake_up(&cwq->more_work); - spin_unlock_irqrestore(&cwq->lock, flags); -} - -/* - * Queue work on a workqueue. Return non-zero if it was successfully - * added. - * - * We queue the work to the CPU it was submitted, but there is no - * guarantee that it will be processed by that CPU. - */ -static inline int t4_queue_work(struct workqueue_struct *wq, struct work_struct *work, int cpu) -{ - int ret = 0; - get_cpu(); - if (!test_and_set_bit(0, &work->pending)) { - BUG_ON(!list_empty(&work->entry)); - __t4_queue_work(wq->cpu_wq + cpu, work); - ret = 1; - } - put_cpu(); - return ret; -} - -#endif - -static int pedanticpci = 1; -static int debug=0; -static int timingcable = 0; -static int highestorder; -static int t1e1override = -1; //0xFF; // -1 = jumper; 0xFF = E1 -static int j1mode = 0; -static int sigmode = FRMR_MODE_NO_ADDR_CMP; -static int loopback = 0; -static int alarmdebounce = 0; -#ifdef VPM_SUPPORT -static int vpmsupport = 1; -/* If set to auto, vpmdtmfsupport is enabled for VPM400M and disabled for VPM450M */ -static int vpmdtmfsupport = -1; /* -1=auto, 0=disabled, 1=enabled*/ -static int vpmspans = 4; -#define VPM_DEFAULT_DTMFTHRESHOLD 1000 -static int dtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD; -static int lastdtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD; -#endif -/* Enabling bursting can more efficiently utilize PCI bus bandwidth, but - can also cause PCI bus starvation, especially in combination with other - aggressive cards. Please note that burst mode has no effect on CPU - utilization / max number of calls / etc. */ -static int noburst = 1; -/* For 56kbps links, set this module parameter to 0x7f */ -static int hardhdlcmode = 0xff; - -#ifdef FANCY_ALARM -static int altab[] = { -0, 0, 0, 1, 2, 3, 4, 6, 8, 9, 11, 13, 16, 18, 20, 22, 24, 25, 27, 28, 29, 30, 31, 31, 32, 31, 31, 30, 29, 28, 27, 25, 23, 22, 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0, -}; -#endif - -#define MAX_SPANS 16 - -#define FLAG_STARTED (1 << 0) -#define FLAG_NMF (1 << 1) -#define FLAG_SENDINGYELLOW (1 << 2) - - -#define TYPE_T1 1 /* is a T1 card */ -#define TYPE_E1 2 /* is an E1 card */ -#define TYPE_J1 3 /* is a running J1 */ - -#define FLAG_2NDGEN (1 << 3) -#define FLAG_2PORT (1 << 4) -#define FLAG_VPM2GEN (1 << 5) -#define FLAG_OCTOPT (1 << 6) -#define FLAG_3RDGEN (1 << 7) -#define FLAG_BURST (1 << 8) -#define FLAG_EXPRESS (1 << 9) - -#define CANARY 0xc0de - -struct devtype { - char *desc; - unsigned int flags; -}; - -static struct devtype wct4xxp = { "Wildcard TE410P/TE405P (1st Gen)", 0 }; -static struct devtype wct420p4 = { "Wildcard TE420 (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_EXPRESS }; -static struct devtype wct410p4 = { "Wildcard TE410P (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN }; -static struct devtype wct410p3 = { "Wildcard TE410P (3rd Gen)", FLAG_2NDGEN | FLAG_3RDGEN }; -static struct devtype wct405p4 = { "Wildcard TE405P (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN }; -static struct devtype wct405p3 = { "Wildcard TE405P (3rd Gen)", FLAG_2NDGEN | FLAG_3RDGEN }; -static struct devtype wct410p2 = { "Wildcard TE410P (2nd Gen)", FLAG_2NDGEN }; -static struct devtype wct405p2 = { "Wildcard TE405P (2nd Gen)", FLAG_2NDGEN }; -static struct devtype wct220p4 = { "Wildcard TE220 (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT | FLAG_EXPRESS }; -static struct devtype wct205p4 = { "Wildcard TE205P (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; -static struct devtype wct205p3 = { "Wildcard TE205P (3rd Gen)", FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; -static struct devtype wct210p4 = { "Wildcard TE210P (4th Gen)", FLAG_BURST | FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; -static struct devtype wct210p3 = { "Wildcard TE210P (3rd Gen)", FLAG_2NDGEN | FLAG_3RDGEN | FLAG_2PORT }; -static struct devtype wct205 = { "Wildcard TE205P ", FLAG_2NDGEN | FLAG_2PORT }; -static struct devtype wct210 = { "Wildcard TE210P ", FLAG_2NDGEN | FLAG_2PORT }; - - -struct t4; - -struct t4_span { - struct t4 *owner; - unsigned int *writechunk; /* Double-word aligned write memory */ - unsigned int *readchunk; /* Double-word aligned read memory */ - int spantype; /* card type, T1 or E1 or J1 */ - int sync; - int psync; - int alarmtimer; - int redalarms; - int notclear; - int alarmcount; - int spanflags; - int syncpos; -#ifdef SUPPORT_GEN1 - int e1check; /* E1 check */ -#endif - struct zt_span span; - unsigned char txsigs[16]; /* Transmit sigs */ - int loopupcnt; - int loopdowncnt; -#ifdef SUPPORT_GEN1 - unsigned char ec_chunk1[31][ZT_CHUNKSIZE]; /* first EC chunk buffer */ - unsigned char ec_chunk2[31][ZT_CHUNKSIZE]; /* second EC chunk buffer */ -#endif - int irqmisses; - - /* HDLC controller fields */ - struct zt_chan *sigchan; - unsigned char sigmode; - int sigactive; - int frames_out; - int frames_in; - -#ifdef VPM_SUPPORT - unsigned long dtmfactive; - unsigned long dtmfmask; - unsigned long dtmfmutemask; - short dtmfenergy[31]; - short dtmfdigit[31]; -#endif -#ifdef ENABLE_WORKQUEUES - struct work_struct swork; -#endif - struct zt_chan chans[0]; /* Individual channels */ -}; - -struct t4 { - /* This structure exists one per card */ - struct pci_dev *dev; /* Pointer to PCI device */ - unsigned int intcount; - int num; /* Which card we are */ - int t1e1; /* T1/E1 select pins */ - int globalconfig; /* Whether global setup has been done */ - int syncsrc; /* active sync source */ - struct t4_span *tspans[4]; /* Individual spans */ - int numspans; /* Number of spans on the card */ - int blinktimer; -#ifdef FANCY_ALARM - int alarmpos; -#endif - int irq; /* IRQ used by device */ - int order; /* Order */ - int flags; /* Device flags */ - int master; /* Are we master */ - int ledreg; /* LED Register */ - unsigned int gpio; - unsigned int gpioctl; - int stopdma; /* Set to stop DMA */ - int e1recover; /* E1 recovery timer */ - spinlock_t reglock; /* lock register access */ - int spansstarted; /* number of spans started */ - volatile unsigned int *writechunk; /* Double-word aligned write memory */ - volatile unsigned int *readchunk; /* Double-word aligned read memory */ - unsigned short canary; -#ifdef ENABLE_WORKQUEUES - atomic_t worklist; - struct workqueue_struct *workq; -#endif - unsigned int passno; /* number of interrupt passes */ - char *variety; - int last0; /* for detecting double-missed IRQ */ - int checktiming; /* Set >0 to cause the timing source to be checked */ - - /* DMA related fields */ - unsigned int dmactrl; - dma_addr_t readdma; - dma_addr_t writedma; - unsigned long memaddr; /* Base address of card */ - unsigned long memlen; - volatile unsigned int *membase; /* Base address of card */ - - /* Flags for our bottom half */ - unsigned long checkflag; - struct tasklet_struct t4_tlet; - unsigned int vpm400checkstatus; - -#ifdef VPM_SUPPORT - struct vpm450m *vpm450m; - int vpm; -#endif - -}; - -#define T4_VPM_PRESENT (1 << 28) - - -#ifdef VPM_SUPPORT -static void t4_vpm400_init(struct t4 *wc); -static void t4_vpm450_init(struct t4 *wc); -static void t4_vpm_set_dtmf_threshold(struct t4 *wc, unsigned int threshold); -#endif -static void __set_clear(struct t4 *wc, int span); -static int t4_startup(struct zt_span *span); -static int t4_shutdown(struct zt_span *span); -static int t4_rbsbits(struct zt_chan *chan, int bits); -static int t4_maint(struct zt_span *span, int cmd); -#ifdef SUPPORT_GEN1 -static int t4_reset_dma(struct t4 *wc); -#endif -static void t4_hdlc_hard_xmit(struct zt_chan *chan); -static int t4_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data); -static void t4_tsi_assign(struct t4 *wc, int fromspan, int fromchan, int tospan, int tochan); -static void t4_tsi_unassign(struct t4 *wc, int tospan, int tochan); -static void __t4_set_timing_source(struct t4 *wc, int unit, int master, int slave); -static void t4_check_alarms(struct t4 *wc, int span); -static void t4_check_sigbits(struct t4 *wc, int span); - -#define WC_RDADDR 0 -#define WC_WRADDR 1 -#define WC_COUNT 2 -#define WC_DMACTRL 3 -#define WC_INTR 4 -/* #define WC_GPIO 5 */ -#define WC_VERSION 6 -#define WC_LEDS 7 -#define WC_GPIOCTL 8 -#define WC_GPIO 9 -#define WC_LADDR 10 -#define WC_LDATA 11 -#define WC_LCS (1 << 11) -#define WC_LCS2 (1 << 12) -#define WC_LALE (1 << 13) -#define WC_LFRMR_CS (1 << 10) /* Framer's ChipSelect signal */ -#define WC_ACTIVATE (1 << 12) -#define WC_LREAD (1 << 15) -#define WC_LWRITE (1 << 16) - -#define WC_OFF (0) -#define WC_RED (1) -#define WC_GREEN (2) -#define WC_YELLOW (3) - -#define MAX_T4_CARDS 64 - -static void t4_isr_bh(unsigned long data); - -static struct t4 *cards[MAX_T4_CARDS]; - - -#define MAX_TDM_CHAN 32 -#define MAX_DTMF_DET 16 - -#define HDLC_IMR0_MASK (FRMR_IMR0_RME | FRMR_IMR0_RPF) -#if 0 -#define HDLC_IMR1_MASK (FRMR_IMR1_ALLS | FRMR_IMR1_XDU | FRMR_IMR1_XPR) -#else -#define HDLC_IMR1_MASK (FRMR_IMR1_XDU | FRMR_IMR1_XPR) -#endif - -static inline unsigned int __t4_pci_in(struct t4 *wc, const unsigned int addr) -{ - unsigned int res = readl(&wc->membase[addr]); - return res; -} - -static inline void __t4_pci_out(struct t4 *wc, const unsigned int addr, const unsigned int value) -{ - unsigned int tmp; - writel(value, &wc->membase[addr]); - if (pedanticpci) { - tmp = __t4_pci_in(wc, WC_VERSION); - if ((tmp & 0xffff0000) != 0xc01a0000) - printk("TE4XXP: Version Synchronization Error!\n"); - } -#if 0 - tmp = __t4_pci_in(wc, addr); - if ((value != tmp) && (addr != WC_LEDS) && (addr != WC_LDATA) && - (addr != WC_GPIO) && (addr != WC_INTR)) - printk("Tried to load %08x into %08x, but got %08x instead\n", value, addr, tmp); -#endif -} - -static inline void __t4_gpio_set(struct t4 *wc, unsigned bits, unsigned int val) -{ - unsigned int newgpio; - newgpio = wc->gpio & (~bits); - newgpio |= val; - if (newgpio != wc->gpio) { - wc->gpio = newgpio; - __t4_pci_out(wc, WC_GPIO, wc->gpio); - } -} - -static inline void __t4_gpio_setdir(struct t4 *wc, unsigned int bits, unsigned int val) -{ - unsigned int newgpioctl; - newgpioctl = wc->gpioctl & (~bits); - newgpioctl |= val; - if (newgpioctl != wc->gpioctl) { - wc->gpioctl = newgpioctl; - __t4_pci_out(wc, WC_GPIOCTL, wc->gpioctl); - } -} - -static inline void t4_gpio_setdir(struct t4 *wc, unsigned int bits, unsigned int val) -{ - unsigned long flags; - spin_lock_irqsave(&wc->reglock, flags); - __t4_gpio_setdir(wc, bits, val); - spin_unlock_irqrestore(&wc->reglock, flags); -} - -static inline void t4_gpio_set(struct t4 *wc, unsigned int bits, unsigned int val) -{ - unsigned long flags; - spin_lock_irqsave(&wc->reglock, flags); - __t4_gpio_set(wc, bits, val); - spin_unlock_irqrestore(&wc->reglock, flags); -} - -static inline void t4_pci_out(struct t4 *wc, const unsigned int addr, const unsigned int value) -{ - unsigned long flags; - spin_lock_irqsave(&wc->reglock, flags); - __t4_pci_out(wc, addr, value); - spin_unlock_irqrestore(&wc->reglock, flags); -} - -static inline void __t4_set_led(struct t4 *wc, int span, int color) -{ - int oldreg = wc->ledreg; - wc->ledreg &= ~(0x3 << (span << 1)); - wc->ledreg |= (color << (span << 1)); - if (oldreg != wc->ledreg) - __t4_pci_out(wc, WC_LEDS, wc->ledreg); -} - -static inline void t4_activate(struct t4 *wc) -{ - wc->ledreg |= WC_ACTIVATE; - t4_pci_out(wc, WC_LEDS, wc->ledreg); -} - -static inline unsigned int t4_pci_in(struct t4 *wc, const unsigned int addr) -{ - unsigned int ret; - unsigned long flags; - - spin_lock_irqsave(&wc->reglock, flags); - ret = __t4_pci_in(wc, addr); - spin_unlock_irqrestore(&wc->reglock, flags); - return ret; -} - -static inline unsigned int __t4_framer_in(struct t4 *wc, int unit, const unsigned int addr) -{ - unsigned int ret; - unit &= 0x3; - __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); - __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | WC_LFRMR_CS | WC_LREAD); - if (pedanticpci) { - __t4_pci_out(wc, WC_VERSION, 0); - } - ret = __t4_pci_in(wc, WC_LDATA); - __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); - return ret & 0xff; -} - -static inline unsigned int t4_framer_in(struct t4 *wc, int unit, const unsigned int addr) -{ - unsigned long flags; - unsigned int ret; - spin_lock_irqsave(&wc->reglock, flags); - ret = __t4_framer_in(wc, unit, addr); - spin_unlock_irqrestore(&wc->reglock, flags); - return ret; - -} - -static inline void __t4_framer_out(struct t4 *wc, int unit, const unsigned int addr, const unsigned int value) -{ - unit &= 0x3; - if (unlikely(debug & DEBUG_REGS)) - printk("Writing %02x to address %02x of unit %d\n", value, addr, unit); - __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); - __t4_pci_out(wc, WC_LDATA, value); - __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | WC_LFRMR_CS | WC_LWRITE); - __t4_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); - if (unlikely(debug & DEBUG_REGS)) printk("Write complete\n"); -#if 0 - if ((addr != FRMR_TXFIFO) && (addr != FRMR_CMDR) && (addr != 0xbc)) - { unsigned int tmp; - tmp = __t4_framer_in(wc, unit, addr); - if (tmp != value) { - printk("Expected %d from unit %d register %d but got %d instead\n", value, unit, addr, tmp); - } } -#endif -} - -static inline void t4_framer_out(struct t4 *wc, int unit, const unsigned int addr, const unsigned int value) -{ - unsigned long flags; - spin_lock_irqsave(&wc->reglock, flags); - __t4_framer_out(wc, unit, addr, value); - spin_unlock_irqrestore(&wc->reglock, flags); -} - -#ifdef VPM_SUPPORT - -static inline void wait_a_little(void) -{ - unsigned long newjiffies=jiffies+2; - while(jiffies < newjiffies); -} - -static inline unsigned int __t4_vpm_in(struct t4 *wc, int unit, const unsigned int addr) -{ - unsigned int ret; - unit &= 0x7; - __t4_pci_out(wc, WC_LADDR, (addr & 0x1ff) | ( unit << 12)); - __t4_pci_out(wc, WC_LADDR, (addr & 0x1ff) | ( unit << 12) | (1 << 11) | WC_LREAD); - ret = __t4_pci_in(wc, WC_LDATA); - __t4_pci_out(wc, WC_LADDR, 0); - return ret & 0xff; -} - -static inline void __t4_raw_oct_out(struct t4 *wc, const unsigned int addr, const unsigned int value) -{ - int octopt = wc->tspans[0]->spanflags & FLAG_OCTOPT; - if (!octopt) - __t4_gpio_set(wc, 0xff, (addr >> 8)); - __t4_pci_out(wc, WC_LDATA, 0x10000 | (addr & 0xffff)); - if (!octopt) - __t4_pci_out(wc, WC_LADDR, (WC_LWRITE)); - __t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE)); - if (!octopt) - __t4_gpio_set(wc, 0xff, (value >> 8)); - __t4_pci_out(wc, WC_LDATA, (value & 0xffff)); - __t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE | WC_LCS)); - __t4_pci_out(wc, WC_LADDR, (0)); -} - -static inline unsigned int __t4_raw_oct_in(struct t4 *wc, const unsigned int addr) -{ - unsigned int ret; - int octopt = wc->tspans[0]->spanflags & FLAG_OCTOPT; - if (!octopt) - __t4_gpio_set(wc, 0xff, (addr >> 8)); - __t4_pci_out(wc, WC_LDATA, 0x10000 | (addr & 0xffff)); - if (!octopt) - __t4_pci_out(wc, WC_LADDR, (WC_LWRITE)); - __t4_pci_out(wc, WC_LADDR, (WC_LWRITE | WC_LALE)); -#ifdef PEDANTIC_OCTASIC_CHECKING - __t4_pci_out(wc, WC_LADDR, (WC_LALE)); -#endif - if (!octopt) { - __t4_gpio_setdir(wc, 0xff, 0x00); - __t4_gpio_set(wc, 0xff, 0x00); - } - __t4_pci_out(wc, WC_LADDR, (WC_LREAD | WC_LALE | WC_LCS)); - if (octopt) { - ret = __t4_pci_in(wc, WC_LDATA) & 0xffff; - } else { - ret = __t4_pci_in(wc, WC_LDATA) & 0xff; - ret |= (__t4_pci_in(wc, WC_GPIO) & 0xff) << 8; - } - __t4_pci_out(wc, WC_LADDR, (0)); - if (!octopt) - __t4_gpio_setdir(wc, 0xff, 0xff); - return ret & 0xffff; -} - -static inline unsigned int __t4_oct_in(struct t4 *wc, unsigned int addr) -{ -#ifdef PEDANTIC_OCTASIC_CHECKING - int count = 1000; -#endif - __t4_raw_oct_out(wc, 0x0008, (addr >> 20)); - __t4_raw_oct_out(wc, 0x000a, (addr >> 4) & ((1 << 16) - 1)); - __t4_raw_oct_out(wc, 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (1)); -#ifdef PEDANTIC_OCTASIC_CHECKING - while((__t4_raw_oct_in(wc, 0x0000) & (1 << 8)) && --count); - if (count != 1000) - printk("Yah, read can be slow...\n"); - if (!count) - printk("Read timed out!\n"); -#endif - return __t4_raw_oct_in(wc, 0x0004); -} - -static inline unsigned int t4_oct_in(struct t4 *wc, const unsigned int addr) -{ - unsigned long flags; - unsigned int ret; - spin_lock_irqsave(&wc->reglock, flags); - ret = __t4_oct_in(wc, addr); - spin_unlock_irqrestore(&wc->reglock, flags); - return ret; -} - -static inline unsigned int t4_vpm_in(struct t4 *wc, int unit, const unsigned int addr) -{ - unsigned long flags; - unsigned int ret; - spin_lock_irqsave(&wc->reglock, flags); - ret = __t4_vpm_in(wc, unit, addr); - spin_unlock_irqrestore(&wc->reglock, flags); - return ret; -} - -static inline void __t4_vpm_out(struct t4 *wc, int unit, const unsigned int addr, const unsigned int value) -{ - unit &= 0x7; - if (debug & DEBUG_REGS) - printk("Writing %02x to address %02x of ec unit %d\n", value, addr, unit); - __t4_pci_out(wc, WC_LADDR, (addr & 0xff)); - __t4_pci_out(wc, WC_LDATA, value); - __t4_pci_out(wc, WC_LADDR, (unit << 12) | (addr & 0x1ff) | (1 << 11)); - __t4_pci_out(wc, WC_LADDR, (unit << 12) | (addr & 0x1ff) | (1 << 11) | WC_LWRITE); - __t4_pci_out(wc, WC_LADDR, (unit << 12) | (addr & 0x1ff) | (1 << 11)); - __t4_pci_out(wc, WC_LADDR, (unit << 12) | (addr & 0x1ff)); - __t4_pci_out(wc, WC_LADDR, 0); - if (debug & DEBUG_REGS) printk("Write complete\n"); - - -#if 0 - { unsigned int tmp; - tmp = t4_vpm_in(wc, unit, addr); - if (tmp != value) { - printk("Expected %d from unit %d echo register %d but got %d instead\n", value, unit, addr, tmp); - } } -#endif -} - -static inline void __t4_oct_out(struct t4 *wc, unsigned int addr, unsigned int value) -{ -#ifdef PEDANTIC_OCTASIC_CHECKING - int count = 1000; -#endif - __t4_raw_oct_out(wc, 0x0008, (addr >> 20)); - __t4_raw_oct_out(wc, 0x000a, (addr >> 4) & ((1 << 16) - 1)); - __t4_raw_oct_out(wc, 0x0004, value); - __t4_raw_oct_out(wc, 0x0000, (((addr >> 1) & 0x7) << 9) | (1 << 8) | (3 << 12) | 1); -#ifdef PEDANTIC_OCTASIC_CHECKING - while((__t4_raw_oct_in(wc, 0x0000) & (1 << 8)) && --count); - if (count != 1000) - printk("Yah, write can be slow\n"); - if (!count) - printk("Write timed out!\n"); -#endif -} - -static inline void t4_oct_out(struct t4 *wc, const unsigned int addr, const unsigned int value) -{ - unsigned long flags; - spin_lock_irqsave(&wc->reglock, flags); - __t4_oct_out(wc, addr, value); - spin_unlock_irqrestore(&wc->reglock, flags); -} - -static inline void t4_vpm_out(struct t4 *wc, int unit, const unsigned int addr, const unsigned int value) -{ - unsigned long flags; - spin_lock_irqsave(&wc->reglock, flags); - __t4_vpm_out(wc, unit, addr, value); - spin_unlock_irqrestore(&wc->reglock, flags); -} - -static const char vpm_digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', '*', '#'}; - -static void t4_check_vpm450(struct t4 *wc) -{ - int channel, tone, start, span; - - if (vpm450m_checkirq(wc->vpm450m)) { - while(vpm450m_getdtmf(wc->vpm450m, &channel, &tone, &start)) { - span = channel & 0x3; - channel >>= 2; - if (!wc->t1e1) - channel -= 5; - else - channel -= 1; - if (unlikely(debug)) - printk("Got tone %s of '%c' on channel %d of span %d\n", - (start ? "START" : "STOP"), tone, channel, span + 1); - if (test_bit(channel, &wc->tspans[span]->dtmfmask) && (tone != 'u')) { - if (start) { - /* The octasic is supposed to mute us, but... Yah, you - guessed it. */ - if (test_bit(channel, &wc->tspans[span]->dtmfmutemask)) { - unsigned long flags; - struct zt_chan *chan = &wc->tspans[span]->span.chans[channel]; - int y; - spin_lock_irqsave(&chan->lock, flags); - for (y=0;ynumbufs;y++) { - if ((chan->inreadbuf > -1) && (chan->readidx[y])) - memset(chan->readbuf[chan->inreadbuf], ZT_XLAW(0, chan), chan->readidx[y]); - } - spin_unlock_irqrestore(&chan->lock, flags); - } - set_bit(channel, &wc->tspans[span]->dtmfactive); - zt_qevent_lock(&wc->tspans[span]->span.chans[channel], (ZT_EVENT_DTMFDOWN | tone)); - } else { - clear_bit(channel, &wc->tspans[span]->dtmfactive); - zt_qevent_lock(&wc->tspans[span]->span.chans[channel], (ZT_EVENT_DTMFUP | tone)); - } - } - } - } -} - -static void t4_check_vpm400(struct t4 *wc, unsigned int newio) -{ - unsigned int digit, regval = 0; - unsigned int regbyte; - int x, i; - short energy=0; - static unsigned int lastio = 0; - struct t4_span *ts; - - if (debug && (newio != lastio)) - printk("Last was %08x, new is %08x\n", lastio, newio); - - lastio = newio; - - for(x = 0; x < 8; x++) { - if (newio & (1 << (7 - x))) - continue; - ts = wc->tspans[x%4]; - /* Start of DTMF detection process */ - regbyte = t4_vpm_in(wc, x, 0xb8); - t4_vpm_out(wc, x, 0xb8, regbyte); /* Write 1 to clear */ - regval = regbyte << 8; - regbyte = t4_vpm_in(wc, x, 0xb9); - t4_vpm_out(wc, x, 0xb9, regbyte); - regval |= regbyte; - - for(i = 0; (i < MAX_DTMF_DET) && regval; i++) { - if(regval & 0x0001) { - int channel = (i << 1) + (x >> 2); - int base = channel - 1; - - if (!wc->t1e1) - base -= 4; - regbyte = t4_vpm_in(wc, x, 0xa8 + i); - digit = vpm_digits[regbyte]; - if (!(wc->tspans[0]->spanflags & FLAG_VPM2GEN)) { - energy = t4_vpm_in(wc, x, 0x58 + channel); - energy = ZT_XLAW(energy, ts->chans); - ts->dtmfenergy[base] = energy; - } - set_bit(base, &ts->dtmfactive); - if (ts->dtmfdigit[base]) { - if (ts->dtmfmask & (1 << base)) - zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFUP | ts->dtmfdigit[base])); - } - ts->dtmfdigit[base] = digit; - if (test_bit(base, &ts->dtmfmask)) - zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFDOWN | digit)); - if (test_bit(base, &ts->dtmfmutemask)) { - /* Mute active receive buffer*/ - unsigned long flags; - struct zt_chan *chan = &ts->span.chans[base]; - int y; - spin_lock_irqsave(&chan->lock, flags); - for (y=0;ynumbufs;y++) { - if ((chan->inreadbuf > -1) && (chan->readidx[y])) - memset(chan->readbuf[chan->inreadbuf], ZT_XLAW(0, chan), chan->readidx[y]); - } - spin_unlock_irqrestore(&chan->lock, flags); - } - if (debug) - printk("Digit Seen: %d, Span: %d, channel: %d, energy: %02x, 'channel %d' chip %d\n", digit, x % 4, base + 1, energy, channel, x); - - } - regval = regval >> 1; - } - if (!(wc->tspans[0]->spanflags & FLAG_VPM2GEN)) - continue; - - /* Start of DTMF off detection process */ - regbyte = t4_vpm_in(wc, x, 0xbc); - t4_vpm_out(wc, x, 0xbc, regbyte); /* Write 1 to clear */ - regval = regbyte << 8; - regbyte = t4_vpm_in(wc, x, 0xbd); - t4_vpm_out(wc, x, 0xbd, regbyte); - regval |= regbyte; - - for(i = 0; (i < MAX_DTMF_DET) && regval; i++) { - if(regval & 0x0001) { - int channel = (i << 1) + (x >> 2); - int base = channel - 1; - - if (!wc->t1e1) - base -= 4; - clear_bit(base, &ts->dtmfactive); - if (ts->dtmfdigit[base]) { - if (test_bit(base, &ts->dtmfmask)) - zt_qevent_lock(&ts->span.chans[base], (ZT_EVENT_DTMFUP | ts->dtmfdigit[base])); - } - digit = ts->dtmfdigit[base]; - ts->dtmfdigit[base] = 0; - if (debug) - printk("Digit Gone: %d, Span: %d, channel: %d, energy: %02x, 'channel %d' chip %d\n", digit, x % 4, base + 1, energy, channel, x); - - } - regval = regval >> 1; - } - - } -} -#endif - -static void hdlc_stop(struct t4 *wc, unsigned int span) -{ - struct t4_span *t = wc->tspans[span]; - unsigned char imr0, imr1, mode; - int i = 0; - - if (debug & DEBUG_FRAMER) printk("Stopping HDLC controller on span %d\n", span+1); - - /* Clear receive and transmit timeslots */ - for (i = 0; i < 4; i++) { - t4_framer_out(wc, span, FRMR_RTR_BASE + i, 0x00); - t4_framer_out(wc, span, FRMR_TTR_BASE + i, 0x00); - } - - imr0 = t4_framer_in(wc, span, FRMR_IMR0); - imr1 = t4_framer_in(wc, span, FRMR_IMR1); - - /* Disable HDLC interrupts */ - imr0 |= HDLC_IMR0_MASK; - t4_framer_out(wc, span, FRMR_IMR0, imr0); - - imr1 |= HDLC_IMR1_MASK; - t4_framer_out(wc, span, FRMR_IMR1, imr1); - - mode = t4_framer_in(wc, span, FRMR_MODE); - mode &= ~FRMR_MODE_HRAC; - t4_framer_out(wc, span, FRMR_MODE, mode); - - t->sigactive = 0; -} - -static inline void __t4_framer_cmd(struct t4 *wc, unsigned int span, int cmd) -{ - __t4_framer_out(wc, span, FRMR_CMDR, cmd); -} - -static inline void t4_framer_cmd_wait(struct t4 *wc, unsigned int span, int cmd) -{ - int sis; - int loops = 0; - - /* XXX could be time consuming XXX */ - for (;;) { - sis = t4_framer_in(wc, span, FRMR_SIS); - if (!(sis & 0x04)) - break; - if (!loops++ && (debug & DEBUG_FRAMER)) { - printk("!!!SIS Waiting before cmd %02x\n", cmd); - } - } - if (loops && (debug & DEBUG_FRAMER)) - printk("!!!SIS waited %d loops\n", loops); - - t4_framer_out(wc, span, FRMR_CMDR, cmd); -} - -static int hdlc_start(struct t4 *wc, unsigned int span, struct zt_chan *chan, unsigned char mode) -{ - struct t4_span *t = wc->tspans[span]; - unsigned char imr0, imr1; - int offset = chan->chanpos; - unsigned long flags; - - if (debug & DEBUG_FRAMER) printk("Starting HDLC controller for channel %d span %d\n", offset, span+1); - - if (mode != FRMR_MODE_NO_ADDR_CMP) - return -1; - - mode |= FRMR_MODE_HRAC; - - /* Make sure we're in the right mode */ - t4_framer_out(wc, span, FRMR_MODE, mode); - t4_framer_out(wc, span, FRMR_TSEO, 0x00); - t4_framer_out(wc, span, FRMR_TSBS1, hardhdlcmode); - - /* Set the interframe gaps, etc */ - t4_framer_out(wc, span, FRMR_CCR1, FRMR_CCR1_ITF|FRMR_CCR1_EITS); - - t4_framer_out(wc, span, FRMR_CCR2, FRMR_CCR2_RCRC); - - /* Set up the time slot that we want to tx/rx on */ - t4_framer_out(wc, span, FRMR_TTR_BASE + (offset / 8), (0x80 >> (offset % 8))); - t4_framer_out(wc, span, FRMR_RTR_BASE + (offset / 8), (0x80 >> (offset % 8))); - - imr0 = t4_framer_in(wc, span, FRMR_IMR0); - imr1 = t4_framer_in(wc, span, FRMR_IMR1); - - /* Enable our interrupts again */ - imr0 &= ~HDLC_IMR0_MASK; - t4_framer_out(wc, span, FRMR_IMR0, imr0); - - imr1 &= ~HDLC_IMR1_MASK; - t4_framer_out(wc, span, FRMR_IMR1, imr1); - - /* Reset the signaling controller */ - t4_framer_cmd_wait(wc, span, FRMR_CMDR_SRES); - - spin_lock_irqsave(&wc->reglock, flags); - t->sigchan = chan; - spin_unlock_irqrestore(&wc->reglock, flags); - - t->sigactive = 0; - - return 0; -} - -static void __set_clear(struct t4 *wc, int span) -{ - int i,j; - int oldnotclear; - unsigned short val=0; - struct t4_span *ts = wc->tspans[span]; - - oldnotclear = ts->notclear; - if ((ts->spantype == TYPE_T1) || (ts->spantype == TYPE_J1)) { - for (i=0;i<24;i++) { - j = (i/8); - if (ts->span.chans[i].flags & ZT_FLAG_CLEAR) { - val |= 1 << (7 - (i % 8)); - ts->notclear &= ~(1 << i); - } else - ts->notclear |= (1 << i); - if ((i % 8)==7) { - if (debug) - printk("Putting %d in register %02x on span %d\n", - val, 0x2f + j, span + 1); - __t4_framer_out(wc, span, 0x2f + j, val); - val = 0; - } - } - } else { - for (i=0;i<31;i++) { - if (ts->span.chans[i].flags & ZT_FLAG_CLEAR) - ts->notclear &= ~(1 << i); - else - ts->notclear |= (1 << i); - } - } - if (ts->notclear != oldnotclear) { - unsigned char reg; - reg = __t4_framer_in(wc, span, FRMR_IMR0); - if (ts->notclear) - reg &= ~0x08; - else - reg |= 0x08; - __t4_framer_out(wc, span, FRMR_IMR0, reg); - } -} - -#if 0 -static void set_clear(struct t4 *wc, int span) -{ - unsigned long flags; - spin_lock_irqsave(&wc->reglock, flags); - __set_clear(wc, span); - spin_unlock_irqrestore(&wc->reglock, flags); -} -#endif - -static int t4_dacs(struct zt_chan *dst, struct zt_chan *src) -{ - struct t4 *wc; - struct t4_span *ts; - wc = dst->pvt; - ts = wc->tspans[dst->span->offset]; - if (src && (src->pvt != dst->pvt)) { - if (ts->spanflags & FLAG_2NDGEN) - t4_tsi_unassign(wc, dst->span->offset, dst->chanpos); - wc = src->pvt; - if (ts->spanflags & FLAG_2NDGEN) - t4_tsi_unassign(wc, src->span->offset, src->chanpos); - if (debug) - printk("Unassigning %d/%d by default and...\n", src->span->offset, src->chanpos); - if (debug) - printk("Unassigning %d/%d by default\n", dst->span->offset, dst->chanpos); - return -1; - } - if (src) { - t4_tsi_assign(wc, src->span->offset, src->chanpos, dst->span->offset, dst->chanpos); - if (debug) - printk("Assigning channel %d/%d -> %d/%d!\n", src->span->offset, src->chanpos, dst->span->offset, dst->chanpos); - } else { - t4_tsi_unassign(wc, dst->span->offset, dst->chanpos); - if (debug) - printk("Unassigning channel %d/%d!\n", dst->span->offset, dst->chanpos); - } - return 0; -} - -#ifdef VPM_SUPPORT - -void oct_set_reg(void *data, unsigned int reg, unsigned int val) -{ - struct t4 *wc = data; - t4_oct_out(wc, reg, val); -} - -unsigned int oct_get_reg(void *data, unsigned int reg) -{ - struct t4 *wc = data; - unsigned int ret; - ret = t4_oct_in(wc, reg); - return ret; -} - -static int t4_vpm_unit(int span, int channel) -{ - int unit = 0; - switch(vpmspans) { - case 4: - unit = span; - unit += (channel & 1) << 2; - break; - case 2: - unit = span; - unit += (channel & 0x3) << 1; - break; - case 1: - unit = span; - unit += (channel & 0x7); - } - return unit; -} - -static int t4_echocan(struct zt_chan *chan, int eclen) -{ - struct t4 *wc = chan->pvt; - int channel; - int unit; - - if (!wc->vpm) - return -ENODEV; - - if (chan->span->offset >= vpmspans) - return -ENODEV; - - if (wc->t1e1) - channel = chan->chanpos; - else - channel = chan->chanpos + 4; - if (wc->vpm450m) { - channel = channel << 2; - channel |= chan->span->offset; - if(debug & DEBUG_ECHOCAN) - printk("echocan: Card is %d, Channel is %d, Span is %d, offset is %d length %d\n", - wc->num, chan->chanpos, chan->span->offset, channel, eclen); - vpm450m_setec(wc->vpm450m, channel, eclen); -// Mark msleep(10); -// msleep(100); // longer test - } else { - unit = t4_vpm_unit(chan->span->offset, channel); - if(debug & DEBUG_ECHOCAN) - printk("echocan: Card is %d, Channel is %d, Span is %d, unit is %d, unit offset is %d length %d\n", - wc->num, chan->chanpos, chan->span->offset, unit, channel, eclen); - if (eclen) - t4_vpm_out(wc,unit,channel,0x3e); - else - t4_vpm_out(wc,unit,channel,0x01); - } - return 0; -} -#endif - -static int t4_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) -{ - struct t4_regs regs; - int x; - struct t4 *wc = chan->pvt; -#ifdef VPM_SUPPORT - int j; - int channel; - struct t4_span *ts = wc->tspans[chan->span->offset]; -#endif - -#ifdef VPM_SUPPORT - if (dtmfthreshold == 0) - dtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD; - if (lastdtmfthreshold != dtmfthreshold) { - lastdtmfthreshold = dtmfthreshold; - t4_vpm_set_dtmf_threshold(wc, dtmfthreshold); - } -#endif - - switch(cmd) { - case WCT4_GET_REGS: - for (x=0;xspan->offset, x); - if (copy_to_user((struct t4_regs *)data, ®s, sizeof(regs))) - return -EFAULT; - break; -#ifdef VPM_SUPPORT - case ZT_TONEDETECT: - if (get_user(j, (int *)data)) - return -EFAULT; - if (!wc->vpm) - return -ENOSYS; - if (j && (vpmdtmfsupport == 0)) - return -ENOSYS; - if (j & ZT_TONEDETECT_ON) - set_bit(chan->chanpos - 1, &ts->dtmfmask); - else - clear_bit(chan->chanpos - 1, &ts->dtmfmask); - if (j & ZT_TONEDETECT_MUTE) - set_bit(chan->chanpos - 1, &ts->dtmfmutemask); - else - clear_bit(chan->chanpos - 1, &ts->dtmfmutemask); - if (wc->vpm450m) { - channel = (chan->chanpos) << 2; - if (!wc->t1e1) - channel += (4 << 2); - channel |= chan->span->offset; - vpm450m_setdtmf(wc->vpm450m, channel, j & ZT_TONEDETECT_ON, j & ZT_TONEDETECT_MUTE); - } - return 0; -#endif - default: - return -ENOTTY; - } - return 0; -} - -static void inline t4_hdlc_xmit_fifo(struct t4 *wc, unsigned int span, struct t4_span *ts) -{ - int res, i, size = 32; - unsigned char buf[32]; - - res = zt_hdlc_getbuf(ts->sigchan, buf, &size); - if (debug & DEBUG_FRAMER) printk("Got buffer sized %d and res %d for %d\n", size, res, span); - if (size > 0) { - ts->sigactive = 1; - - if (debug & DEBUG_FRAMER) { - printk("TX("); - for (i = 0; i < size; i++) - printk((i ? " %02x" : "%02x"), buf[i]); - printk(")\n"); - } - - for (i = 0; i < size; i++) - t4_framer_out(wc, span, FRMR_TXFIFO, buf[i]); - - if (res) /* End of message */ { - if (debug & DEBUG_FRAMER) printk("transmiting XHF|XME\n"); - t4_framer_cmd_wait(wc, span, FRMR_CMDR_XHF | FRMR_CMDR_XME); -#if 0 - ts->sigactive = (__t4_framer_in(wc, span, FRMR_SIS) & FRMR_SIS_XFW) ? 0 : 1; -#endif - ++ts->frames_out; - if ((debug & DEBUG_FRAMER) && !(ts->frames_out & 0x0f)) - printk("Transmitted %d frames on span %d\n", ts->frames_out, span); - } else { /* Still more to transmit */ - if (debug & DEBUG_FRAMER) printk("transmiting XHF\n"); - t4_framer_cmd_wait(wc, span, FRMR_CMDR_XHF); - } - } - else if (res < 0) - ts->sigactive = 0; -} - -static void t4_hdlc_hard_xmit(struct zt_chan *chan) -{ - struct t4 *wc = chan->pvt; - int span = chan->span->offset; - struct t4_span *ts = wc->tspans[span]; - unsigned long flags; - - spin_lock_irqsave(&wc->reglock, flags); - if (!ts->sigchan) { - printk("t4_hdlc_hard_xmit: Invalid (NULL) signalling channel\n"); - spin_unlock_irqrestore(&wc->reglock, flags); - return; - } - spin_unlock_irqrestore(&wc->reglock, flags); - - if (debug & DEBUG_FRAMER) printk("t4_hdlc_hard_xmit on channel %s (sigchan %s), sigactive=%d\n", chan->name, ts->sigchan->name, ts->sigactive); - - if ((ts->sigchan == chan) && !ts->sigactive) - t4_hdlc_xmit_fifo(wc, span, ts); -} - -static int t4_maint(struct zt_span *span, int cmd) -{ - struct t4_span *ts = span->pvt; - struct t4 *wc = ts->owner; - - if (ts->spantype == TYPE_E1) { - switch(cmd) { - case ZT_MAINT_NONE: - printk("XXX Turn off local and remote loops E1 XXX\n"); - break; - case ZT_MAINT_LOCALLOOP: - printk("XXX Turn on local loopback E1 XXX\n"); - break; - case ZT_MAINT_REMOTELOOP: - printk("XXX Turn on remote loopback E1 XXX\n"); - break; - case ZT_MAINT_LOOPUP: - printk("XXX Send loopup code E1 XXX\n"); - break; - case ZT_MAINT_LOOPDOWN: - printk("XXX Send loopdown code E1 XXX\n"); - break; - case ZT_MAINT_LOOPSTOP: - printk("XXX Stop sending loop codes E1 XXX\n"); - break; - default: - printk("TE%dXXP: Unknown E1 maint command: %d\n", wc->numspans, cmd); - break; - } - } else { - switch(cmd) { - case ZT_MAINT_NONE: - printk("XXX Turn off local and remote loops T1 XXX\n"); - break; - case ZT_MAINT_LOCALLOOP: - printk("XXX Turn on local loop and no remote loop XXX\n"); - break; - case ZT_MAINT_REMOTELOOP: - printk("XXX Turn on remote loopup XXX\n"); - break; - case ZT_MAINT_LOOPUP: - t4_framer_out(wc, span->offset, 0x21, 0x50); /* FMR5: Nothing but RBS mode */ - break; - case ZT_MAINT_LOOPDOWN: - t4_framer_out(wc, span->offset, 0x21, 0x60); /* FMR5: Nothing but RBS mode */ - break; - case ZT_MAINT_LOOPSTOP: - t4_framer_out(wc, span->offset, 0x21, 0x40); /* FMR5: Nothing but RBS mode */ - break; - default: - printk("TE%dXXP: Unknown T1 maint command: %d\n", wc->numspans, cmd); - break; - } - } - return 0; -} - -static int t4_rbsbits(struct zt_chan *chan, int bits) -{ - u_char m,c; - int k,n,b; - struct t4 *wc = chan->pvt; - struct t4_span *ts = wc->tspans[chan->span->offset]; - unsigned long flags; - - if(debug & DEBUG_RBS) printk("Setting bits to %d on channel %s\n", bits, chan->name); - spin_lock_irqsave(&wc->reglock, flags); - k = chan->span->offset; - if (ts->spantype == TYPE_E1) { /* do it E1 way */ - if (chan->chanpos == 16) { - spin_unlock_irqrestore(&wc->reglock, flags); - return 0; - } - n = chan->chanpos - 1; - if (chan->chanpos > 15) n--; - b = (n % 15); - c = ts->txsigs[b]; - m = (n / 15) << 2; /* nibble selector */ - c &= (0xf << m); /* keep the other nibble */ - c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ - ts->txsigs[b] = c; - /* output them to the chip */ - __t4_framer_out(wc,k,0x71 + b,c); - } else if (ts->span.lineconfig & ZT_CONFIG_D4) { - n = chan->chanpos - 1; - b = (n/4); - c = ts->txsigs[b]; - m = ((3 - (n % 4)) << 1); /* nibble selector */ - c &= ~(0x3 << m); /* keep the other nibble */ - c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */ - ts->txsigs[b] = c; - /* output them to the chip */ - __t4_framer_out(wc,k,0x70 + b,c); - __t4_framer_out(wc,k,0x70 + b + 6,c); - } else if (ts->span.lineconfig & ZT_CONFIG_ESF) { - n = chan->chanpos - 1; - b = (n/2); - c = ts->txsigs[b]; - m = ((n % 2) << 2); /* nibble selector */ - c &= (0xf << m); /* keep the other nibble */ - c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ - ts->txsigs[b] = c; - /* output them to the chip */ - __t4_framer_out(wc,k,0x70 + b,c); - } - spin_unlock_irqrestore(&wc->reglock, flags); - if (debug & DEBUG_RBS) - printk("Finished setting RBS bits\n"); - return 0; -} - -static int t4_shutdown(struct zt_span *span) -{ - int tspan; - int wasrunning; - unsigned long flags; - struct t4_span *ts = span->pvt; - struct t4 *wc = ts->owner; - - tspan = span->offset + 1; - if (tspan < 0) { - printk("T%dXXP: Span '%d' isn't us?\n", wc->numspans, span->spanno); - return -1; - } - - if (debug & DEBUG_MAIN) printk("Shutting down span %d (%s)\n", span->spanno, span->name); - - /* Stop HDLC controller if runned */ - if (ts->sigchan) - hdlc_stop(wc, span->offset); - - spin_lock_irqsave(&wc->reglock, flags); - wasrunning = span->flags & ZT_FLAG_RUNNING; - - span->flags &= ~ZT_FLAG_RUNNING; - __t4_set_led(wc, span->offset, WC_OFF); - if (((wc->numspans == 4) && - (!(wc->tspans[0]->span.flags & ZT_FLAG_RUNNING)) && - (!(wc->tspans[1]->span.flags & ZT_FLAG_RUNNING)) && - (!(wc->tspans[2]->span.flags & ZT_FLAG_RUNNING)) && - (!(wc->tspans[3]->span.flags & ZT_FLAG_RUNNING))) - || - ((wc->numspans == 2) && - (!(wc->tspans[0]->span.flags & ZT_FLAG_RUNNING)) && - (!(wc->tspans[1]->span.flags & ZT_FLAG_RUNNING)))) { - /* No longer in use, disable interrupts */ - printk("TE%dXXP: Disabling interrupts since there are no active spans\n", wc->numspans); - wc->stopdma = 1; - } else wc->checktiming = 1; - spin_unlock_irqrestore(&wc->reglock, flags); - - /* Wait for interrupt routine to shut itself down */ - msleep(10); - if (wasrunning) - wc->spansstarted--; - - if (debug & DEBUG_MAIN) - printk("Span %d (%s) shutdown\n", span->spanno, span->name); - return 0; -} - -static int t4_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) -{ - int i; - struct t4_span *ts = span->pvt; - struct t4 *wc = ts->owner; - - printk("About to enter spanconfig!\n"); - if (debug & DEBUG_MAIN) - printk("TE%dXXP: Configuring span %d\n", wc->numspans, span->spanno); - - if (lc->sync < 0) - lc->sync = 0; - if (lc->sync > 4) - lc->sync = 0; - - /* remove this span number from the current sync sources, if there */ - for(i = 0; i < wc->numspans; i++) { - if (wc->tspans[i]->sync == span->spanno) { - wc->tspans[i]->sync = 0; - wc->tspans[i]->psync = 0; - } - } - wc->tspans[span->offset]->syncpos = lc->sync; - /* if a sync src, put it in proper place */ - if (lc->sync) { - wc->tspans[lc->sync - 1]->sync = span->spanno; - wc->tspans[lc->sync - 1]->psync = span->offset + 1; - } - wc->checktiming = 1; - - /* If we're already running, then go ahead and apply the changes */ - if (span->flags & ZT_FLAG_RUNNING) - return t4_startup(span); - printk("Done with spanconfig!\n"); - return 0; -} - -static int t4_chanconfig(struct zt_chan *chan, int sigtype) -{ - int alreadyrunning; - unsigned long flags; - struct t4 *wc = chan->pvt; - struct t4_span *ts = wc->tspans[chan->span->offset]; - - alreadyrunning = ts->span.flags & ZT_FLAG_RUNNING; - if (debug & DEBUG_MAIN) { - if (alreadyrunning) - printk("TE%dXXP: Reconfigured channel %d (%s) sigtype %d\n", wc->numspans, chan->channo, chan->name, sigtype); - else - printk("TE%dXXP: Configured channel %d (%s) sigtype %d\n", wc->numspans, chan->channo, chan->name, sigtype); - } - - spin_lock_irqsave(&wc->reglock, flags); - - if (alreadyrunning) - __set_clear(wc, chan->span->offset); - - spin_unlock_irqrestore(&wc->reglock, flags); - - /* (re)configure signalling channel */ - if ((sigtype == ZT_SIG_HARDHDLC) || (ts->sigchan == chan)) { - if (debug & DEBUG_FRAMER) - printk("%sonfiguring hardware HDLC on %s\n", ((sigtype == ZT_SIG_HARDHDLC) ? "C" : "Unc"), chan->name); - if (alreadyrunning) { - if (ts->sigchan) - hdlc_stop(wc, ts->sigchan->span->offset); - if (sigtype == ZT_SIG_HARDHDLC) { - if (hdlc_start(wc, chan->span->offset, chan, ts->sigmode)) { - printk("Error initializing signalling controller\n"); - return -1; - } - } else { - spin_lock_irqsave(&wc->reglock, flags); - ts->sigchan = NULL; - spin_unlock_irqrestore(&wc->reglock, flags); - } - - } - else { - spin_lock_irqsave(&wc->reglock, flags); - ts->sigchan = (sigtype == ZT_SIG_HARDHDLC) ? chan : NULL; - spin_unlock_irqrestore(&wc->reglock, flags); - ts->sigactive = 0; - } - } - return 0; -} - -static int t4_open(struct zt_chan *chan) -{ -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#else - try_module_get(THIS_MODULE); -#endif - - return 0; -} - -static int t4_close(struct zt_chan *chan) -{ -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#else - module_put(THIS_MODULE); -#endif - return 0; -} - -/* The number of cards we have seen with each - possible 'order' switch setting. -*/ -static unsigned int order_index[16]; - -static void init_spans(struct t4 *wc) -{ - int x,y; - int gen2; - int offset = 1; - struct t4_span *ts; - - gen2 = (wc->tspans[0]->spanflags & FLAG_2NDGEN); - if (!wc->t1e1) - offset += 4; - for (x = 0; x < wc->numspans; x++) { - ts = wc->tspans[x]; - sprintf(ts->span.name, "TE%d/%d/%d", wc->numspans, wc->num, x + 1); - snprintf(ts->span.desc, sizeof(ts->span.desc) - 1, - "T%dXXP (PCI) Card %d Span %d", wc->numspans, wc->num, x+1); - ts->span.manufacturer = "Digium"; - strncpy(ts->span.devicetype, wc->variety, sizeof(ts->span.devicetype) - 1); - if (wc->vpm == T4_VPM_PRESENT) { - if (!wc->vpm450m) - strncat(ts->span.devicetype, " with VPM400M", sizeof(ts->span.devicetype) - 1); - else - strncat(ts->span.devicetype, (wc->numspans > 2) ? " with VPMOCT128" : " with VPMOCT064", - sizeof(ts->span.devicetype) - 1); - } - if (order_index[wc->order] == 1) - snprintf(ts->span.location, sizeof(ts->span.location) - 1, "Board ID Switch %d", wc->order); - else - snprintf(ts->span.location, sizeof(ts->span.location) - 1, - "PCI%s Bus %02d Slot %02d", (ts->spanflags & FLAG_EXPRESS) ? " Express" : " ", - wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); - switch (ts->spantype) { - case TYPE_T1: - ts->span.spantype = "T1"; - break; - case TYPE_E1: - ts->span.spantype = "E1"; - break; - case TYPE_J1: - ts->span.spantype = "J1"; - break; - } - ts->span.spanconfig = t4_spanconfig; - ts->span.chanconfig = t4_chanconfig; - ts->span.irq = wc->dev->irq; - ts->span.startup = t4_startup; - ts->span.shutdown = t4_shutdown; - ts->span.rbsbits = t4_rbsbits; - ts->span.maint = t4_maint; - ts->span.open = t4_open; - ts->span.close = t4_close; - - /* HDLC Specific init */ - ts->sigchan = NULL; - ts->sigmode = sigmode; - ts->sigactive = 0; - - if (ts->spantype == TYPE_T1 || ts->spantype == TYPE_J1) { - ts->span.channels = 24; - ts->span.deflaw = ZT_LAW_MULAW; - ts->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; - } else { - ts->span.channels = 31; - ts->span.deflaw = ZT_LAW_ALAW; - ts->span.linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4; - } - ts->span.chans = ts->chans; - ts->span.flags = ZT_FLAG_RBS; - ts->span.ioctl = t4_ioctl; - ts->span.hdlc_hard_xmit = t4_hdlc_hard_xmit; - if (gen2) { -#ifdef VPM_SUPPORT - ts->span.echocan = t4_echocan; -#endif - ts->span.dacs = t4_dacs; - } - ts->span.pvt = ts; - ts->owner = wc; - ts->span.offset = x; - ts->writechunk = (void *)(wc->writechunk + x * 32 * 2); - ts->readchunk = (void *)(wc->readchunk + x * 32 * 2); - init_waitqueue_head(&ts->span.maintq); - for (y=0;ytspans[x]->span.channels;y++) { - struct zt_chan *mychans = ts->chans + y; - sprintf(mychans->name, "TE%d/%d/%d/%d", wc->numspans, wc->num, x + 1, y + 1); - mychans->sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS | ZT_SIG_HARDHDLC | - ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_EM_E1 | ZT_SIG_DACS_RBS; - mychans->pvt = wc; - mychans->chanpos = y + 1; - if (gen2) { - mychans->writechunk = (void *)(wc->writechunk + (x * 32 + y + offset) * 2); - mychans->readchunk = (void *)(wc->readchunk + (x * 32 + y + offset) * 2); - } - } - } -} - -static void t4_serial_setup(struct t4 *wc, int unit) -{ - if (!wc->globalconfig) { - wc->globalconfig = 1; - printk("TE%dXXP: Setting up global serial parameters\n", wc->numspans); - t4_framer_out(wc, 0, 0x85, 0xe0); /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0 */ - t4_framer_out(wc, 0, 0x08, 0x01); /* IPC: Interrupt push/pull active low */ - - /* Global clocks (8.192 Mhz CLK) */ - t4_framer_out(wc, 0, 0x92, 0x00); - t4_framer_out(wc, 0, 0x93, 0x18); - t4_framer_out(wc, 0, 0x94, 0xfb); - t4_framer_out(wc, 0, 0x95, 0x0b); - t4_framer_out(wc, 0, 0x96, 0x00); - t4_framer_out(wc, 0, 0x97, 0x0b); - t4_framer_out(wc, 0, 0x98, 0xdb); - t4_framer_out(wc, 0, 0x99, 0xdf); - } - - /* Configure interrupts */ - t4_framer_out(wc, unit, FRMR_GCR, 0x00); /* GCR: Interrupt on Activation/Deactivation of each */ - - /* Configure system interface */ - t4_framer_out(wc, unit, FRMR_SIC1, 0xc2); /* SIC1: 8.192 Mhz clock/bus, double buffer receive / transmit, byte interleaved */ - t4_framer_out(wc, unit, FRMR_SIC2, 0x20 | (unit << 1)); /* SIC2: No FFS, no center receive eliastic buffer, phase */ - t4_framer_out(wc, unit, FRMR_SIC3, 0x04); /* SIC3: Edges for capture */ - t4_framer_out(wc, unit, FRMR_CMR2, 0x00); /* CMR2: We provide sync and clock for tx and rx. */ - if (!wc->t1e1) { /* T1 mode */ - t4_framer_out(wc, unit, FRMR_XC0, 0x03); /* XC0: Normal operation of Sa-bits */ - t4_framer_out(wc, unit, FRMR_XC1, 0x84); /* XC1: 0 offset */ - if (wc->tspans[unit]->spantype == TYPE_J1) - t4_framer_out(wc, unit, FRMR_RC0, 0x83); /* RC0: Just shy of 1023 */ - else - t4_framer_out(wc, unit, FRMR_RC0, 0x03); /* RC0: Just shy of 1023 */ - t4_framer_out(wc, unit, FRMR_RC1, 0x84); /* RC1: The rest of RC0 */ - } else { /* E1 mode */ - t4_framer_out(wc, unit, FRMR_XC0, 0x00); /* XC0: Normal operation of Sa-bits */ - t4_framer_out(wc, unit, FRMR_XC1, 0x04); /* XC1: 0 offset */ - t4_framer_out(wc, unit, FRMR_RC0, 0x04); /* RC0: Just shy of 1023 */ - t4_framer_out(wc, unit, FRMR_RC1, 0x04); /* RC1: The rest of RC0 */ - } - - /* Configure ports */ - t4_framer_out(wc, unit, 0x80, 0x00); /* PC1: SPYR/SPYX input on RPA/XPA */ - t4_framer_out(wc, unit, 0x81, 0x22); /* PC2: RMFB/XSIG output/input on RPB/XPB */ - t4_framer_out(wc, unit, 0x82, 0x65); /* PC3: Some unused stuff */ - t4_framer_out(wc, unit, 0x83, 0x35); /* PC4: Some more unused stuff */ - t4_framer_out(wc, unit, 0x84, 0x01); /* PC5: XMFS active low, SCLKR is input, RCLK is output */ - if (debug & DEBUG_MAIN) - printk("Successfully initialized serial bus for unit %d\n", unit); -} - -static int syncsrc = 0; -static int syncnum = 0 /* -1 */; -static int syncspan = 0; -#ifdef DEFINE_SPINLOCK -static DEFINE_SPINLOCK(synclock); -#else -static spinlock_t synclock = SPIN_LOCK_UNLOCKED; -#endif - -static void __t4_set_timing_source(struct t4 *wc, int unit, int master, int slave) -{ - unsigned int timing; - int x; - if (unit != wc->syncsrc) { - timing = 0x34; /* CMR1: RCLK unit, 8.192 Mhz TCLK, RCLK is 8.192 Mhz */ - if ((unit > -1) && (unit < 4)) { - timing |= (unit << 6); - for (x=0;xnumspans;x++) /* set all 4 receive reference clocks to unit */ - __t4_framer_out(wc, x, 0x44, timing); - wc->dmactrl |= (1 << 29); - } else { - for (x=0;xnumspans;x++) /* set each receive reference clock to itself */ - __t4_framer_out(wc, x, 0x44, timing | (x << 6)); - wc->dmactrl &= ~(1 << 29); - } - if (slave) - wc->dmactrl |= (1 << 25); - else - wc->dmactrl &= ~(1 << 25); - if (master) - wc->dmactrl |= (1 << 24); - else - wc->dmactrl &= ~(1 << 24); - __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); - if (!master && !slave) - wc->syncsrc = unit; - if ((unit < 0) || (unit > 3)) - unit = 0; - else - unit++; - if (!master && !slave) { - for (x=0;xnumspans;x++) - wc->tspans[x]->span.syncsrc = unit; - } - } else { - if (debug & DEBUG_MAIN) - printk("TE%dXXP: Timing source already set to %d\n", wc->numspans, unit); - } -#if 0 - printk("wct4xxp: Timing source set to %d\n",unit); -#endif -} - -static inline void __t4_update_timing(struct t4 *wc) -{ - int i; - /* update sync src info */ - if (wc->syncsrc != syncsrc) { - printk("Swapping card %d from %d to %d\n", wc->num, wc->syncsrc, syncsrc); - wc->syncsrc = syncsrc; - /* Update sync sources */ - for (i = 0; i < wc->numspans; i++) { - wc->tspans[i]->span.syncsrc = wc->syncsrc; - } - if (syncnum == wc->num) { - __t4_set_timing_source(wc, syncspan-1, 1, 0); - if (debug) printk("Card %d, using sync span %d, master\n", wc->num, syncspan); - } else { - __t4_set_timing_source(wc, syncspan-1, 0, 1); - if (debug) printk("Card %d, using Timing Bus, NOT master\n", wc->num); - } - } -} - -static int __t4_findsync(struct t4 *wc) -{ - int i; - int x; - unsigned long flags; - int p; - int nonzero; - int newsyncsrc = 0; /* Zaptel span number */ - int newsyncnum = 0; /* wct4xxp card number */ - int newsyncspan = 0; /* span on given wct4xxp card */ - spin_lock_irqsave(&synclock, flags); -#if 1 - if (!wc->num) { - /* If we're the first card, go through all the motions, up to 8 levels - of sync source */ - p = 1; - while (p < 8) { - nonzero = 0; - for (x=0;cards[x];x++) { - for (i = 0; i < wc->numspans; i++) { - if (cards[x]->tspans[i]->syncpos) { - nonzero = 1; - if ((cards[x]->tspans[i]->syncpos == p) && - !(cards[x]->tspans[i]->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK)) && - (cards[x]->tspans[i]->span.flags & ZT_FLAG_RUNNING)) { - /* This makes a good sync source */ - newsyncsrc = cards[x]->tspans[i]->span.spanno; - newsyncnum = x; - newsyncspan = i + 1; - /* Jump out */ - goto found; - } - } - } - } - if (nonzero) - p++; - else - break; - } -found: - if ((syncnum != newsyncnum) || (syncsrc != newsyncsrc) || (newsyncspan != syncspan)) { - if (debug) printk("New syncnum: %d (was %d), syncsrc: %d (was %d), syncspan: %d (was %d)\n", newsyncnum, syncnum, newsyncsrc, syncsrc, newsyncspan, syncspan); - syncnum = newsyncnum; - syncsrc = newsyncsrc; - syncspan = newsyncspan; - for (x=0;cards[x];x++) { - __t4_update_timing(cards[x]); - } - } - } else - cards[0]->checktiming = 1; -#endif - spin_unlock_irqrestore(&synclock, flags); - return 0; -} - -static void __t4_set_timing_source_auto(struct t4 *wc) -{ - int x; - printk("timing source auto card %d!\n", wc->num); - wc->checktiming = 0; - if (timingcable) { - __t4_findsync(wc); - } else { - for (x=0;xnumspans;x++) { - if (wc->tspans[x]->sync) { - if ((wc->tspans[wc->tspans[x]->psync - 1]->span.flags & ZT_FLAG_RUNNING) && - !(wc->tspans[wc->tspans[x]->psync - 1]->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE) )) { - /* Valid timing source */ - __t4_set_timing_source(wc, wc->tspans[x]->psync - 1, 0, 0); - return; - } - } - } - __t4_set_timing_source(wc, 4, 0, 0); - } -} - -static void __t4_configure_t1(struct t4 *wc, int unit, int lineconfig, int txlevel) -{ - unsigned int fmr4, fmr2, fmr1, fmr0, lim2; - char *framing, *line; - int mytxlevel; - if ((txlevel > 7) || (txlevel < 4)) - mytxlevel = 0; - else - mytxlevel = txlevel - 4; - fmr1 = 0x9c; /* FMR1: Mode 1, T1 mode, CRC on for ESF, 8.192 Mhz system data rate, no XAIS */ - fmr2 = 0x22; /* FMR2: no payload loopback, auto send yellow alarm */ - if (loopback) - fmr2 |= 0x4; - fmr4 = 0x0c; /* FMR4: Lose sync on 2 out of 5 framing bits, auto resync */ - lim2 = 0x21; /* LIM2: 50% peak is a "1", Advanced Loss recovery */ - lim2 |= (mytxlevel << 6); /* LIM2: Add line buildout */ - __t4_framer_out(wc, unit, 0x1d, fmr1); - __t4_framer_out(wc, unit, 0x1e, fmr2); - - /* Configure line interface */ - if (lineconfig & ZT_CONFIG_AMI) { - line = "AMI"; - fmr0 = 0xa0; - } else { - line = "B8ZS"; - fmr0 = 0xf0; - } - if (lineconfig & ZT_CONFIG_D4) { - framing = "D4"; - } else { - framing = "ESF"; - fmr4 |= 0x2; - fmr2 |= 0xc0; - } - __t4_framer_out(wc, unit, 0x1c, fmr0); - __t4_framer_out(wc, unit, 0x20, fmr4); - __t4_framer_out(wc, unit, 0x21, 0x40); /* FMR5: Enable RBS mode */ - - __t4_framer_out(wc, unit, 0x37, 0xf0 ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ - __t4_framer_out(wc, unit, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ - - __t4_framer_out(wc, unit, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ - __t4_framer_out(wc, unit, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ - - __t4_framer_out(wc, unit, 0x3a, lim2); /* LIM2: 50% peak amplitude is a "1" */ - __t4_framer_out(wc, unit, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ - __t4_framer_out(wc, unit, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ - - /* Generate pulse mask for T1 */ - switch(mytxlevel) { - case 3: - __t4_framer_out(wc, unit, 0x26, 0x07); /* XPM0 */ - __t4_framer_out(wc, unit, 0x27, 0x01); /* XPM1 */ - __t4_framer_out(wc, unit, 0x28, 0x00); /* XPM2 */ - break; - case 2: - __t4_framer_out(wc, unit, 0x26, 0x8c); /* XPM0 */ - __t4_framer_out(wc, unit, 0x27, 0x11); /* XPM1 */ - __t4_framer_out(wc, unit, 0x28, 0x01); /* XPM2 */ - break; - case 1: - __t4_framer_out(wc, unit, 0x26, 0x8c); /* XPM0 */ - __t4_framer_out(wc, unit, 0x27, 0x01); /* XPM1 */ - __t4_framer_out(wc, unit, 0x28, 0x00); /* XPM2 */ - break; - case 0: - default: - __t4_framer_out(wc, unit, 0x26, 0xd7); /* XPM0 */ - __t4_framer_out(wc, unit, 0x27, 0x22); /* XPM1 */ - __t4_framer_out(wc, unit, 0x28, 0x01); /* XPM2 */ - break; - } - - /* Don't mask framer interrupts if hardware HDLC is in use */ - __t4_framer_out(wc, unit, FRMR_IMR0, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR0_MASK : 0)); /* IMR0: We care about CAS changes, etc */ - __t4_framer_out(wc, unit, FRMR_IMR1, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR1_MASK : 0)); /* IMR1: We care about nothing */ - __t4_framer_out(wc, unit, 0x16, 0x00); /* IMR2: We care about all the alarm stuff! */ - __t4_framer_out(wc, unit, 0x17, 0xf4); /* IMR3: We care about AIS and friends */ - __t4_framer_out(wc, unit, 0x18, 0x3f); /* IMR4: We care about slips on transmit */ - - printk("TE%dXXP: Span %d configured for %s/%s\n", wc->numspans, unit + 1, framing, line); -} - -static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig) -{ - unsigned int fmr2, fmr1, fmr0; - unsigned int cas = 0; - unsigned int imr3extra=0; - char *crc4 = ""; - char *framing, *line; - fmr1 = 0x44; /* FMR1: E1 mode, Automatic force resync, PCM30 mode, 8.192 Mhz backplane, no XAIS */ - fmr2 = 0x03; /* FMR2: Auto transmit remote alarm, auto loss of multiframe recovery, no payload loopback */ - if (loopback) - fmr2 |= 0x4; - if (lineconfig & ZT_CONFIG_CRC4) { - fmr1 |= 0x08; /* CRC4 transmit */ - fmr2 |= 0xc0; /* CRC4 receive */ - crc4 = "/CRC4"; - } - __t4_framer_out(wc, unit, 0x1d, fmr1); - __t4_framer_out(wc, unit, 0x1e, fmr2); - - /* Configure line interface */ - if (lineconfig & ZT_CONFIG_AMI) { - line = "AMI"; - fmr0 = 0xa0; - } else { - line = "HDB3"; - fmr0 = 0xf0; - } - if (lineconfig & ZT_CONFIG_CCS) { - framing = "CCS"; - imr3extra = 0x28; - } else { - framing = "CAS"; - cas = 0x40; - } - __t4_framer_out(wc, unit, 0x1c, fmr0); - - __t4_framer_out(wc, unit, 0x37, 0xf0 /*| 0x6 */ ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ - __t4_framer_out(wc, unit, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ - - __t4_framer_out(wc, unit, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ - __t4_framer_out(wc, unit, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ - - /* Condition receive line interface for E1 after reset */ - __t4_framer_out(wc, unit, 0xbb, 0x17); - __t4_framer_out(wc, unit, 0xbc, 0x55); - __t4_framer_out(wc, unit, 0xbb, 0x97); - __t4_framer_out(wc, unit, 0xbb, 0x11); - __t4_framer_out(wc, unit, 0xbc, 0xaa); - __t4_framer_out(wc, unit, 0xbb, 0x91); - __t4_framer_out(wc, unit, 0xbb, 0x12); - __t4_framer_out(wc, unit, 0xbc, 0x55); - __t4_framer_out(wc, unit, 0xbb, 0x92); - __t4_framer_out(wc, unit, 0xbb, 0x0c); - __t4_framer_out(wc, unit, 0xbb, 0x00); - __t4_framer_out(wc, unit, 0xbb, 0x8c); - - __t4_framer_out(wc, unit, 0x3a, 0x20); /* LIM2: 50% peak amplitude is a "1" */ - __t4_framer_out(wc, unit, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ - __t4_framer_out(wc, unit, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ - - __t4_framer_out(wc, unit, 0x20, 0x9f); /* XSW: Spare bits all to 1 */ - __t4_framer_out(wc, unit, 0x21, 0x1c|cas); /* XSP: E-bit set when async. AXS auto, XSIF to 1 */ - - - /* Generate pulse mask for E1 */ - __t4_framer_out(wc, unit, 0x26, 0x54); /* XPM0 */ - __t4_framer_out(wc, unit, 0x27, 0x02); /* XPM1 */ - __t4_framer_out(wc, unit, 0x28, 0x00); /* XPM2 */ - - /* Don't mask framer interrupts if hardware HDLC is in use */ - __t4_framer_out(wc, unit, FRMR_IMR0, 0xff & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR0_MASK : 0)); /* IMR0: We care about CRC errors, CAS changes, etc */ - __t4_framer_out(wc, unit, FRMR_IMR1, 0x3f & ~((wc->tspans[unit]->sigchan) ? HDLC_IMR1_MASK : 0)); /* IMR1: We care about loopup / loopdown */ - __t4_framer_out(wc, unit, 0x16, 0x00); /* IMR2: We care about all the alarm stuff! */ - __t4_framer_out(wc, unit, 0x17, 0xc4 | imr3extra); /* IMR3: We care about AIS and friends */ - __t4_framer_out(wc, unit, 0x18, 0x3f); /* IMR4: We care about slips on transmit */ - - printk("TE%dXXP: Span %d configured for %s/%s%s\n", wc->numspans, unit + 1, framing, line, crc4); -} - -static int t4_startup(struct zt_span *span) -{ -#ifdef SUPPORT_GEN1 - int i; -#endif - int tspan; - unsigned long flags; - int alreadyrunning; - struct t4_span *ts = span->pvt; - struct t4 *wc = ts->owner; - - printk("About to enter startup!\n"); - tspan = span->offset + 1; - if (tspan < 0) { - printk("TE%dXXP: Span '%d' isn't us?\n", wc->numspans, span->spanno); - return -1; - } - - spin_lock_irqsave(&wc->reglock, flags); - - alreadyrunning = span->flags & ZT_FLAG_RUNNING; - -#ifdef SUPPORT_GEN1 - /* initialize the start value for the entire chunk of last ec buffer */ - for(i = 0; i < span->channels; i++) - { - memset(ts->ec_chunk1[i], - ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); - memset(ts->ec_chunk2[i], - ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); - } -#endif - /* Force re-evaluation fo timing source */ - if (timingcable) - wc->syncsrc = -1; - - if (ts->spantype == TYPE_E1) { /* if this is an E1 card */ - __t4_configure_e1(wc, span->offset, span->lineconfig); - } else { /* is a T1 card */ - __t4_configure_t1(wc, span->offset, span->lineconfig, span->txlevel); - } - - /* Note clear channel status */ - wc->tspans[span->offset]->notclear = 0; - __set_clear(wc, span->offset); - - if (!alreadyrunning) { - span->flags |= ZT_FLAG_RUNNING; - wc->spansstarted++; - /* enable interrupts */ - /* Start DMA, enabling DMA interrupts on read only */ - wc->dmactrl = 1 << 29; -#if 0 - /* Enable framer only interrupts */ - wc->dmactrl |= 1 << 27; -#endif - wc->dmactrl |= (ts->spanflags & FLAG_2NDGEN) ? 0xc0000000 : 0xc0000003; -#ifdef VPM_SUPPORT - wc->dmactrl |= wc->vpm; -#endif - /* Seed interrupt register */ - __t4_pci_out(wc, WC_INTR, 0x0c); - if (noburst && !(ts->spanflags & FLAG_BURST)) - wc->dmactrl |= (1 << 26); - __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); - - /* Startup HDLC controller too */ - } - - if (ts->sigchan) { - struct zt_chan *sigchan = ts->sigchan; - - spin_unlock_irqrestore(&wc->reglock, flags); - if (hdlc_start(wc, span->offset, sigchan, ts->sigmode)) { - printk("Error initializing signalling controller\n"); - return -1; - } - spin_lock_irqsave(&wc->reglock, flags); - } - - spin_unlock_irqrestore(&wc->reglock, flags); - - t4_check_alarms(wc, span->offset); - t4_check_sigbits(wc, span->offset); - - if (wc->tspans[0]->sync == span->spanno) printk("SPAN %d: Primary Sync Source\n",span->spanno); - if (wc->tspans[1]->sync == span->spanno) printk("SPAN %d: Secondary Sync Source\n",span->spanno); - if (wc->numspans == 4) { - if (wc->tspans[2]->sync == span->spanno) printk("SPAN %d: Tertiary Sync Source\n",span->spanno); - if (wc->tspans[3]->sync == span->spanno) printk("SPAN %d: Quaternary Sync Source\n",span->spanno); - } -#ifdef VPM_SUPPORT - if (!alreadyrunning && !wc->vpm) { - wait_a_little(); - t4_vpm400_init(wc); - if (!wc->vpm) - t4_vpm450_init(wc); - wc->dmactrl |= wc->vpm; - t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); - } -#endif - printk("Completed startup!\n"); - return 0; -} - -#ifdef SUPPORT_GEN1 -static inline void e1_check(struct t4 *wc, int span, int val) -{ - struct t4_span *ts = wc->tspans[span]; - if ((ts->span.channels > 24) && - (ts->span.flags & ZT_FLAG_RUNNING) && - !(ts->span.alarms) && - (!wc->e1recover)) { - if (val != 0x1b) { - ts->e1check++; - } else - ts->e1check = 0; - if (ts->e1check > 100) { - /* Wait 1000 ms */ - wc->e1recover = 1000 * 8; - wc->tspans[0]->e1check = wc->tspans[1]->e1check = 0; - if (wc->numspans == 4) - wc->tspans[2]->e1check = wc->tspans[3]->e1check = 0; - if (debug & DEBUG_MAIN) - printk("Detected loss of E1 alignment on span %d!\n", span); - t4_reset_dma(wc); - } - } -} - -static void t4_receiveprep(struct t4 *wc, int irq) -{ - volatile unsigned int *readchunk; - int dbl = 0; - int x,y,z; - unsigned int tmp; - int offset=0; - if (!wc->t1e1) - offset = 4; - if (irq & 1) { - /* First part */ - readchunk = wc->readchunk; - if (!wc->last0) - dbl = 1; - wc->last0 = 0; - } else { - readchunk = wc->readchunk + ZT_CHUNKSIZE * 32; - if (wc->last0) - dbl = 1; - wc->last0 = 1; - } - if (dbl) { - for (x=0;xnumspans;x++) - wc->tspans[x]->irqmisses++; - if (debug & DEBUG_MAIN) - printk("TE%dXXP: Double/missed interrupt detected\n", wc->numspans); - } - for (x=0;xnumspans == 4) { - wc->tspans[3]->span.chans[z].readchunk[x] = tmp & 0xff; - wc->tspans[2]->span.chans[z].readchunk[x] = (tmp & 0xff00) >> 8; - } - wc->tspans[1]->span.chans[z].readchunk[x] = (tmp & 0xff0000) >> 16; - wc->tspans[0]->span.chans[z].readchunk[x] = tmp >> 24; - } - if (wc->t1e1) { - if (wc->e1recover > 0) - wc->e1recover--; - tmp = readchunk[0]; - if (wc->numspans == 4) { - e1_check(wc, 3, (tmp & 0x7f)); - e1_check(wc, 2, (tmp & 0x7f00) >> 8); - } - e1_check(wc, 1, (tmp & 0x7f0000) >> 16); - e1_check(wc, 0, (tmp & 0x7f000000) >> 24); - for (z=24;z<31;z++) { - /* Only E1 channels now */ - tmp = readchunk[z+1]; - if (wc->numspans == 4) { - if (wc->tspans[3]->span.channels > 24) - wc->tspans[3]->span.chans[z].readchunk[x] = tmp & 0xff; - if (wc->tspans[2]->span.channels > 24) - wc->tspans[2]->span.chans[z].readchunk[x] = (tmp & 0xff00) >> 8; - } - if (wc->tspans[1]->span.channels > 24) - wc->tspans[1]->span.chans[z].readchunk[x] = (tmp & 0xff0000) >> 16; - if (wc->tspans[0]->span.channels > 24) - wc->tspans[0]->span.chans[z].readchunk[x] = tmp >> 24; - } - } - /* Advance pointer by 4 TDM frame lengths */ - readchunk += 32; - } - for (x=0;xnumspans;x++) { - if (wc->tspans[x]->span.flags & ZT_FLAG_RUNNING) { - for (y=0;ytspans[x]->span.channels;y++) { - /* Echo cancel double buffered data */ - zt_ec_chunk(&wc->tspans[x]->span.chans[y], - wc->tspans[x]->span.chans[y].readchunk, - wc->tspans[x]->ec_chunk2[y]); - memcpy(wc->tspans[x]->ec_chunk2[y],wc->tspans[x]->ec_chunk1[y], - ZT_CHUNKSIZE); - memcpy(wc->tspans[x]->ec_chunk1[y], - wc->tspans[x]->span.chans[y].writechunk, - ZT_CHUNKSIZE); - } - zt_receive(&wc->tspans[x]->span); - } - } -} -#endif - -#if (ZT_CHUNKSIZE != 8) -#error Sorry, nextgen does not support chunksize != 8 -#endif - -static inline void __receive_span(struct t4_span *ts) -{ -#ifdef VPM_SUPPORT - int y; - unsigned long merged; - merged = ts->dtmfactive & ts->dtmfmutemask; - if (merged) { - for (y=0;yspan.channels;y++) { - /* Mute any DTMFs which are supposed to be muted */ - if (test_bit(y, &merged)) { - memset(ts->span.chans[y].readchunk, ZT_XLAW(0, (ts->span.chans + y)), ZT_CHUNKSIZE); - } - } - } -#endif - -#ifdef ENABLE_PREFETCH - prefetch((void *)(ts->readchunk)); - prefetch((void *)(ts->writechunk)); - prefetch((void *)(ts->readchunk + 8)); - prefetch((void *)(ts->writechunk + 8)); - prefetch((void *)(ts->readchunk + 16)); - prefetch((void *)(ts->writechunk + 16)); - prefetch((void *)(ts->readchunk + 24)); - prefetch((void *)(ts->writechunk + 24)); - prefetch((void *)(ts->readchunk + 32)); - prefetch((void *)(ts->writechunk + 32)); - prefetch((void *)(ts->readchunk + 40)); - prefetch((void *)(ts->writechunk + 40)); - prefetch((void *)(ts->readchunk + 48)); - prefetch((void *)(ts->writechunk + 48)); - prefetch((void *)(ts->readchunk + 56)); - prefetch((void *)(ts->writechunk + 56)); -#endif - - zt_ec_span(&ts->span); - zt_receive(&ts->span); -} - -static inline void __transmit_span(struct t4_span *ts) -{ - zt_transmit(&ts->span); -} - -#ifdef ENABLE_WORKQUEUES -static void workq_handlespan(void *data) -{ - struct t4_span *ts = data; - struct t4 *wc = ts->owner; - - __receive_span(ts); - __transmit_span(ts); - atomic_dec(&wc->worklist); - if (!atomic_read(&wc->worklist)) - t4_pci_out(wc, WC_INTR, 0); -} -#else -static void t4_prep_gen2(struct t4 *wc) -{ - int x; - for (x=0;xnumspans;x++) { - if (wc->tspans[x]->span.flags & ZT_FLAG_RUNNING) { - __receive_span(wc->tspans[x]); - __transmit_span(wc->tspans[x]); - } - } -} - -#endif -#ifdef SUPPORT_GEN1 -static void t4_transmitprep(struct t4 *wc, int irq) -{ - volatile unsigned int *writechunk; - int x,y,z; - unsigned int tmp; - int offset=0; - if (!wc->t1e1) - offset = 4; - if (irq & 1) { - /* First part */ - writechunk = wc->writechunk + 1; - } else { - writechunk = wc->writechunk + ZT_CHUNKSIZE * 32 + 1; - } - for (y=0;ynumspans;y++) { - if (wc->tspans[y]->span.flags & ZT_FLAG_RUNNING) - zt_transmit(&wc->tspans[y]->span); - } - - for (x=0;xtspans[3]->span.chans[z].writechunk[x]) | - (wc->tspans[2]->span.chans[z].writechunk[x] << 8) | - (wc->tspans[1]->span.chans[z].writechunk[x] << 16) | - (wc->tspans[0]->span.chans[z].writechunk[x] << 24); - writechunk[z+offset] = tmp; - } - if (wc->t1e1) { - for (z=24;z<31;z++) { - /* Only E1 channels now */ - tmp = 0; - if (wc->numspans == 4) { - if (wc->tspans[3]->span.channels > 24) - tmp |= wc->tspans[3]->span.chans[z].writechunk[x]; - if (wc->tspans[2]->span.channels > 24) - tmp |= (wc->tspans[2]->span.chans[z].writechunk[x] << 8); - } - if (wc->tspans[1]->span.channels > 24) - tmp |= (wc->tspans[1]->span.chans[z].writechunk[x] << 16); - if (wc->tspans[0]->span.channels > 24) - tmp |= (wc->tspans[0]->span.chans[z].writechunk[x] << 24); - writechunk[z] = tmp; - } - } - /* Advance pointer by 4 TDM frame lengths */ - writechunk += 32; - } - -} -#endif - -static void t4_check_sigbits(struct t4 *wc, int span) -{ - int a,i,rxs; - struct t4_span *ts = wc->tspans[span]; - - if (debug & DEBUG_RBS) - printk("Checking sigbits on span %d\n", span + 1); - - if (!(ts->span.flags & ZT_FLAG_RUNNING)) - return; - if (ts->spantype == TYPE_E1) { - for (i = 0; i < 15; i++) { - a = t4_framer_in(wc, span, 0x71 + i); - /* Get high channel in low bits */ - rxs = (a & 0xf); - if (!(ts->span.chans[i+16].sig & ZT_SIG_CLEAR)) { - if (ts->span.chans[i+16].rxsig != rxs) - zt_rbsbits(&ts->span.chans[i+16], rxs); - } - rxs = (a >> 4) & 0xf; - if (!(ts->span.chans[i].sig & ZT_SIG_CLEAR)) { - if (ts->span.chans[i].rxsig != rxs) - zt_rbsbits(&ts->span.chans[i], rxs); - } - } - } else if (ts->span.lineconfig & ZT_CONFIG_D4) { - for (i = 0; i < 24; i+=4) { - a = t4_framer_in(wc, span, 0x70 + (i>>2)); - /* Get high channel in low bits */ - rxs = (a & 0x3) << 2; - if (!(ts->span.chans[i+3].sig & ZT_SIG_CLEAR)) { - if (ts->span.chans[i+3].rxsig != rxs) - zt_rbsbits(&ts->span.chans[i+3], rxs); - } - rxs = (a & 0xc); - if (!(ts->span.chans[i+2].sig & ZT_SIG_CLEAR)) { - if (ts->span.chans[i+2].rxsig != rxs) - zt_rbsbits(&ts->span.chans[i+2], rxs); - } - rxs = (a >> 2) & 0xc; - if (!(ts->span.chans[i+1].sig & ZT_SIG_CLEAR)) { - if (ts->span.chans[i+1].rxsig != rxs) - zt_rbsbits(&ts->span.chans[i+1], rxs); - } - rxs = (a >> 4) & 0xc; - if (!(ts->span.chans[i].sig & ZT_SIG_CLEAR)) { - if (ts->span.chans[i].rxsig != rxs) - zt_rbsbits(&ts->span.chans[i], rxs); - } - } - } else { - for (i = 0; i < 24; i+=2) { - a = t4_framer_in(wc, span, 0x70 + (i>>1)); - /* Get high channel in low bits */ - rxs = (a & 0xf); - if (!(ts->span.chans[i+1].sig & ZT_SIG_CLEAR)) { - /* XXX Not really reset on every trans! XXX */ - if (ts->span.chans[i+1].rxsig != rxs) { - zt_rbsbits(&ts->span.chans[i+1], rxs); - } - } - rxs = (a >> 4) & 0xf; - if (!(ts->span.chans[i].sig & ZT_SIG_CLEAR)) { - /* XXX Not really reset on every trans! XXX */ - if (ts->span.chans[i].rxsig != rxs) { - zt_rbsbits(&ts->span.chans[i], rxs); - } - } - } - } -} - -static void t4_check_alarms(struct t4 *wc, int span) -{ - unsigned char c,d; - int alarms; - int x,j; - struct t4_span *ts = wc->tspans[span]; - unsigned long flags; - - if (!(ts->span.flags & ZT_FLAG_RUNNING)) - return; - - spin_lock_irqsave(&wc->reglock, flags); - - c = __t4_framer_in(wc, span, 0x4c); - d = __t4_framer_in(wc, span, 0x4d); - - /* Assume no alarms */ - alarms = 0; - - /* And consider only carrier alarms */ - ts->span.alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); - - if (ts->spantype == TYPE_E1) { - if (c & 0x04) { - /* No multiframe found, force RAI high after 400ms only if - we haven't found a multiframe since last loss - of frame */ - if (!(ts->spanflags & FLAG_NMF)) { - __t4_framer_out(wc, span, 0x20, 0x9f | 0x20); /* LIM0: Force RAI High */ - ts->spanflags |= FLAG_NMF; - printk("NMF workaround on!\n"); - } - __t4_framer_out(wc, span, 0x1e, 0xc3); /* Reset to CRC4 mode */ - __t4_framer_out(wc, span, 0x1c, 0xf2); /* Force Resync */ - __t4_framer_out(wc, span, 0x1c, 0xf0); /* Force Resync */ - } else if (!(c & 0x02)) { - if ((ts->spanflags & FLAG_NMF)) { - __t4_framer_out(wc, span, 0x20, 0x9f); /* LIM0: Clear forced RAI */ - ts->spanflags &= ~FLAG_NMF; - printk("NMF workaround off!\n"); - } - } - } else { - /* Detect loopup code if we're not sending one */ - if ((!ts->span.mainttimer) && (d & 0x08)) { - /* Loop-up code detected */ - if ((ts->loopupcnt++ > 80) && (ts->span.maintstat != ZT_MAINT_REMOTELOOP)) { - __t4_framer_out(wc, span, 0x36, 0x08); /* LIM0: Disable any local loop */ - __t4_framer_out(wc, span, 0x37, 0xf6 ); /* LIM1: Enable remote loop */ - ts->span.maintstat = ZT_MAINT_REMOTELOOP; - } - } else - ts->loopupcnt = 0; - /* Same for loopdown code */ - if ((!ts->span.mainttimer) && (d & 0x10)) { - /* Loop-down code detected */ - if ((ts->loopdowncnt++ > 80) && (ts->span.maintstat == ZT_MAINT_REMOTELOOP)) { - __t4_framer_out(wc, span, 0x36, 0x08); /* LIM0: Disable any local loop */ - __t4_framer_out(wc, span, 0x37, 0xf0 ); /* LIM1: Disable remote loop */ - ts->span.maintstat = ZT_MAINT_NONE; - } - } else - ts->loopdowncnt = 0; - } - - if (ts->span.lineconfig & ZT_CONFIG_NOTOPEN) { - for (x=0,j=0;x < ts->span.channels;x++) - if ((ts->span.chans[x].flags & ZT_FLAG_OPEN) || - (ts->span.chans[x].flags & ZT_FLAG_NETDEV)) - j++; - if (!j) - alarms |= ZT_ALARM_NOTOPEN; - } - - if (c & 0xa0) { - if (ts->alarmcount >= alarmdebounce) - alarms |= ZT_ALARM_RED; - else - ts->alarmcount++; - } else - ts->alarmcount = 0; - if (c & 0x4) - alarms |= ZT_ALARM_BLUE; - - if (((!ts->span.alarms) && alarms) || - (ts->span.alarms && (!alarms))) - wc->checktiming = 1; - - /* Keep track of recovering */ - if ((!alarms) && ts->span.alarms) - ts->alarmtimer = ZT_ALARMSETTLE_TIME; - if (ts->alarmtimer) - alarms |= ZT_ALARM_RECOVER; - - /* If receiving alarms, go into Yellow alarm state */ - if (alarms && !(ts->spanflags & FLAG_SENDINGYELLOW)) { - unsigned char fmr4; -#if 1 - printk("wct%dxxp: Setting yellow alarm on span %d\n", wc->numspans, span + 1); -#endif - /* We manually do yellow alarm to handle RECOVER and NOTOPEN, otherwise it's auto anyway */ - fmr4 = __t4_framer_in(wc, span, 0x20); - __t4_framer_out(wc, span, 0x20, fmr4 | 0x20); - ts->spanflags |= FLAG_SENDINGYELLOW; - } else if ((!alarms) && (ts->spanflags & FLAG_SENDINGYELLOW)) { - unsigned char fmr4; -#if 1 - printk("wct%dxxp: Clearing yellow alarm on span %d\n", wc->numspans, span + 1); -#endif - /* We manually do yellow alarm to handle RECOVER */ - fmr4 = __t4_framer_in(wc, span, 0x20); - __t4_framer_out(wc, span, 0x20, fmr4 & ~0x20); - ts->spanflags &= ~FLAG_SENDINGYELLOW; - } - - /* Re-check the timing source when we enter/leave alarm, not withstanding - yellow alarm */ - if (c & 0x10) - alarms |= ZT_ALARM_YELLOW; - if (ts->span.mainttimer || ts->span.maintstat) - alarms |= ZT_ALARM_LOOPBACK; - ts->span.alarms = alarms; - spin_unlock_irqrestore(&wc->reglock, flags); - zt_alarm_notify(&ts->span); -} - -static void t4_do_counters(struct t4 *wc) -{ - int span; - for (span=0;spannumspans;span++) { - struct t4_span *ts = wc->tspans[span]; - int docheck=0; - - spin_lock(&wc->reglock); - if (ts->loopupcnt || ts->loopdowncnt) - docheck++; - if (ts->alarmtimer) { - if (!--ts->alarmtimer) { - docheck++; - ts->span.alarms &= ~(ZT_ALARM_RECOVER); - } - } - spin_unlock(&wc->reglock); - if (docheck) { - t4_check_alarms(wc, span); - zt_alarm_notify(&ts->span); - } - } -} - -static inline void __handle_leds(struct t4 *wc) -{ - int x; - - wc->blinktimer++; - for (x=0;xnumspans;x++) { - struct t4_span *ts = wc->tspans[x]; - if (ts->span.flags & ZT_FLAG_RUNNING) { - if (ts->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) { -#ifdef FANCY_ALARM - if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) { - __t4_set_led(wc, x, WC_RED); - } - if (wc->blinktimer == 0xf) { - __t4_set_led(wc, x, WC_OFF); - } -#else - if (wc->blinktimer == 160) { - __t4_set_led(wc, x, WC_RED); - } else if (wc->blinktimer == 480) { - __t4_set_led(wc, x, WC_OFF); - } -#endif - } else if (ts->span.alarms & ZT_ALARM_YELLOW) { - /* Yellow Alarm */ - __t4_set_led(wc, x, WC_YELLOW); - } else if (ts->span.mainttimer || ts->span.maintstat) { -#ifdef FANCY_ALARM - if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) { - __t4_set_led(wc, x, WC_GREEN); - } - if (wc->blinktimer == 0xf) { - __t4_set_led(wc, x, WC_OFF); - } -#else - if (wc->blinktimer == 160) { - __t4_set_led(wc, x, WC_GREEN); - } else if (wc->blinktimer == 480) { - __t4_set_led(wc, x, WC_OFF); - } -#endif - } else { - /* No Alarm */ - __t4_set_led(wc, x, WC_GREEN); - } - } else - __t4_set_led(wc, x, WC_OFF); - - } -#ifdef FANCY_ALARM - if (wc->blinktimer == 0xf) { - wc->blinktimer = -1; - wc->alarmpos++; - if (wc->alarmpos >= (sizeof(altab) / sizeof(altab[0]))) - wc->alarmpos = 0; - } -#else - if (wc->blinktimer == 480) - wc->blinktimer = 0; -#endif -} - -static inline void t4_framer_interrupt(struct t4 *wc, int span) -{ - /* Check interrupts for a given span */ - unsigned char gis, isr0, isr1, isr2, isr3, isr4; - int readsize = -1; - struct t4_span *ts = wc->tspans[span]; - struct zt_chan *sigchan; - unsigned long flags; - - if (debug & DEBUG_FRAMER) - printk("framer interrupt span %d:%d!\n", wc->num, span + 1); - - /* 1st gen cards isn't used interrupts */ - gis = t4_framer_in(wc, span, FRMR_GIS); - isr0 = (gis & FRMR_GIS_ISR0) ? t4_framer_in(wc, span, FRMR_ISR0) : 0; - isr1 = (gis & FRMR_GIS_ISR1) ? t4_framer_in(wc, span, FRMR_ISR1) : 0; - isr2 = (gis & FRMR_GIS_ISR2) ? t4_framer_in(wc, span, FRMR_ISR2) : 0; - isr3 = (gis & FRMR_GIS_ISR3) ? t4_framer_in(wc, span, FRMR_ISR3) : 0; - isr4 = (gis & FRMR_GIS_ISR4) ? t4_framer_in(wc, span, FRMR_ISR4) : 0; - - if (debug & DEBUG_FRAMER) - printk("gis: %02x, isr0: %02x, isr1: %02x, isr2: %02x, isr3: %02x, isr4: %02x\n", gis, isr0, isr1, isr2, isr3, isr4); - - if (isr0) - t4_check_sigbits(wc, span); - - if (ts->spantype == TYPE_E1) { - /* E1 checks */ - if ((isr3 & 0x38) || isr2 || isr1) - t4_check_alarms(wc, span); - } else { - /* T1 checks */ - if (isr2 || (isr3 & 0x08)) - t4_check_alarms(wc, span); - } - if (!ts->span.alarms) { - if ((isr3 & 0x3) || (isr4 & 0xc0)) - ts->span.timingslips++; - - if (debug & DEBUG_MAIN) { - if (isr3 & 0x02) - printk("TE%d10P: RECEIVE slip NEGATIVE on span %d\n", wc->numspans, span + 1); - if (isr3 & 0x01) - printk("TE%d10P: RECEIVE slip POSITIVE on span %d\n", wc->numspans, span + 1); - if (isr4 & 0x80) - printk("TE%dXXP: TRANSMIT slip POSITIVE on span %d\n", wc->numspans, span + 1); - if (isr4 & 0x40) - printk("TE%d10P: TRANSMIT slip NEGATIVE on span %d\n", wc->numspans, span + 1); - } - } else - ts->span.timingslips = 0; - - spin_lock_irqsave(&wc->reglock, flags); - /* HDLC controller checks - receive side */ - if (!ts->sigchan) { - spin_unlock_irqrestore(&wc->reglock, flags); - return; - } - - sigchan = ts->sigchan; - spin_unlock_irqrestore(&wc->reglock, flags); - - if (isr0 & FRMR_ISR0_RME) { - readsize = (t4_framer_in(wc, span, FRMR_RBCH) << 8) | t4_framer_in(wc, span, FRMR_RBCL); - if (debug & DEBUG_FRAMER) printk("Received data length is %d (%d)\n", readsize, readsize & FRMR_RBCL_MAX_SIZE); - /* RPF isn't set on last part of frame */ - if ((readsize > 0) && ((readsize &= FRMR_RBCL_MAX_SIZE) == 0)) - readsize = 32; - } else if (isr0 & FRMR_ISR0_RPF) - readsize = 32; - - if (readsize > 0) { - int i; - unsigned char readbuf[readsize]; - - if (debug & DEBUG_FRAMER) printk("Framer %d: Got RPF/RME! readsize is %d\n", sigchan->span->offset, readsize); - - for (i = 0; i < readsize; i++) - readbuf[i] = t4_framer_in(wc, span, FRMR_RXFIFO); - - /* Tell the framer to clear the RFIFO */ - t4_framer_cmd_wait(wc, span, FRMR_CMDR_RMC); - - if (debug & DEBUG_FRAMER) { - printk("RX("); - for (i = 0; i < readsize; i++) - printk((i ? " %02x" : "%02x"), readbuf[i]); - printk(")\n"); - } - - if (isr0 & FRMR_ISR0_RME) { - /* Do checks for HDLC problems */ - unsigned char rsis = readbuf[readsize-1]; -#if 0 - unsigned int olddebug = debug; -#endif - unsigned char rsis_reg = t4_framer_in(wc, span, FRMR_RSIS); - -#if 0 - if ((rsis != 0xA2) || (rsis != rsis_reg)) - debug |= DEBUG_FRAMER; -#endif - - ++ts->frames_in; - if ((debug & DEBUG_FRAMER) && !(ts->frames_in & 0x0f)) - printk("Received %d frames on span %d\n", ts->frames_in, span); - if (debug & DEBUG_FRAMER) printk("Received HDLC frame %d. RSIS = 0x%x (%x)\n", ts->frames_in, rsis, rsis_reg); - if (!(rsis & FRMR_RSIS_CRC16)) { - if (debug & DEBUG_FRAMER) printk("CRC check failed %d\n", span); - zt_hdlc_abort(sigchan, ZT_EVENT_BADFCS); - } else if (rsis & FRMR_RSIS_RAB) { - if (debug & DEBUG_FRAMER) printk("ABORT of current frame due to overflow %d\n", span); - zt_hdlc_abort(sigchan, ZT_EVENT_ABORT); - } else if (rsis & FRMR_RSIS_RDO) { - if (debug & DEBUG_FRAMER) printk("HDLC overflow occured %d\n", span); - zt_hdlc_abort(sigchan, ZT_EVENT_OVERRUN); - } else if (!(rsis & FRMR_RSIS_VFR)) { - if (debug & DEBUG_FRAMER) printk("Valid Frame check failed on span %d\n", span); - zt_hdlc_abort(sigchan, ZT_EVENT_ABORT); - } else { - zt_hdlc_putbuf(sigchan, readbuf, readsize - 1); - zt_hdlc_finish(sigchan); - if (debug & DEBUG_FRAMER) printk("Received valid HDLC frame on span %d\n", span); - } -#if 0 - debug = olddebug; -#endif - } else if (isr0 & FRMR_ISR0_RPF) - zt_hdlc_putbuf(sigchan, readbuf, readsize); - } - - /* Transmit side */ - if (isr1 & FRMR_ISR1_XDU) { - if (debug & DEBUG_FRAMER) printk("XDU: Resetting signal controler!\n"); - t4_framer_cmd_wait(wc, span, FRMR_CMDR_SRES); - } else if (isr1 & FRMR_ISR1_XPR) { - if (debug & DEBUG_FRAMER) - printk("Sigchan %d is %p\n", sigchan->chanpos, sigchan); - - if (debug & DEBUG_FRAMER) printk("Framer %d: Got XPR!\n", sigchan->span->offset); - t4_hdlc_xmit_fifo(wc, span, ts); - } - - if (isr1 & FRMR_ISR1_ALLS) { - if (debug & DEBUG_FRAMER) printk("ALLS received\n"); - } - -} - -#ifdef SUPPORT_GEN1 -ZAP_IRQ_HANDLER(t4_interrupt) -{ - struct t4 *wc = dev_id; - unsigned long flags; - int x; - - unsigned int status; - unsigned int status2; - -#if 0 - if (wc->intcount < 20) - printk("Pre-interrupt\n"); -#endif - - /* Make sure it's really for us */ - status = __t4_pci_in(wc, WC_INTR); - - /* Process framer interrupts */ - status2 = t4_framer_in(wc, 0, FRMR_CIS); - if (status2 & 0x0f) { - for (x = 0; x < wc->numspans; ++x) { - if (status2 & (1 << x)) - t4_framer_interrupt(wc, x); - } - } - - /* Ignore if it's not for us */ - if (!status) -#ifdef LINUX26 - return IRQ_NONE; -#else - return; -#endif - - __t4_pci_out(wc, WC_INTR, 0); - - if (!wc->spansstarted) { - printk("Not prepped yet!\n"); -#ifdef LINUX26 - return IRQ_NONE; -#else - return; -#endif - } - - wc->intcount++; -#if 0 - if (wc->intcount < 20) - printk("Got interrupt, status = %08x\n", status); -#endif - - if (status & 0x3) { - t4_receiveprep(wc, status); - t4_transmitprep(wc, status); - } - -#if 0 - if ((wc->intcount < 10) || !(wc->intcount % 1000)) { - status2 = t4_framer_in(wc, 0, FRMR_CIS); - printk("Status2: %04x\n", status2); - for (x = 0;x<4;x++) { - status2 = t4_framer_in(wc, x, FRMR_FRS0); - printk("FRS0/%d: %04x\n", x, status2); - } - } -#endif - t4_do_counters(wc); - - x = wc->intcount & 15 /* 63 */; - switch(x) { - case 0: - case 1: - case 2: - case 3: - t4_check_sigbits(wc, x); - break; - case 4: - case 5: - case 6: - case 7: - t4_check_alarms(wc, x - 4); - break; - } - - spin_lock_irqsave(&wc->reglock, flags); - - __handle_leds(wc); - - if (wc->checktiming > 0) - __t4_set_timing_source_auto(wc); - - spin_unlock_irqrestore(&wc->reglock, flags); -#ifdef LINUX26 - return IRQ_RETVAL(1); -#endif -} -#endif - -static void t4_isr_bh(unsigned long data) -{ - struct t4 *wc = (struct t4 *)data; - -#ifdef VPM_SUPPORT - if (wc->vpm) { - if (test_and_clear_bit(T4_CHECK_VPM, &wc->checkflag)) { - if (wc->vpm450m) { - /* How stupid is it that the octasic can't generate an - interrupt when there's a tone, in spite of what their - documentation says? */ - t4_check_vpm450(wc); - } else - t4_check_vpm400(wc, wc->vpm400checkstatus); - } - } -#endif -} - -ZAP_IRQ_HANDLER(t4_interrupt_gen2) -{ - struct t4 *wc = dev_id; - unsigned int status; - - /* Make sure it's really for us */ - status = __t4_pci_in(wc, WC_INTR); - - /* Ignore if it's not for us */ - if (!(status & 0x7)) { -#ifdef LINUX26 - return IRQ_NONE; -#else - return; -#endif - } - -#ifdef ENABLE_WORKQUEUES - __t4_pci_out(wc, WC_INTR, status & 0x00000008); -#endif - - if (unlikely(!wc->spansstarted)) { - printk("Not prepped yet!\n"); -#ifdef LINUX26 - return IRQ_NONE; -#else - return; -#endif - } - - wc->intcount++; - - if (unlikely((wc->intcount < 20) && debug)) - - printk("2G: Got interrupt, status = %08x, CIS = %04x\n", status, t4_framer_in(wc, 0, FRMR_CIS)); - - if (likely(status & 0x2)) { -#ifdef ENABLE_WORKQUEUES - int cpus = num_online_cpus(); - atomic_set(&wc->worklist, wc->numspans); - if (wc->tspans[0]->span.flags & ZT_FLAG_RUNNING) - t4_queue_work(wc->workq, &wc->tspans[0]->swork, 0); - else - atomic_dec(&wc->worklist); - if (wc->tspans[1]->span.flags & ZT_FLAG_RUNNING) - t4_queue_work(wc->workq, &wc->tspans[1]->swork, 1 % cpus); - else - atomic_dec(&wc->worklist); - if (wc->numspans == 4) { - if (wc->tspans[2]->span.flags & ZT_FLAG_RUNNING) - t4_queue_work(wc->workq, &wc->tspans[2]->swork, 2 % cpus); - else - atomic_dec(&wc->worklist); - if (wc->tspans[3]->span.flags & ZT_FLAG_RUNNING) - t4_queue_work(wc->workq, &wc->tspans[3]->swork, 3 % cpus); - else - atomic_dec(&wc->worklist); - } -#else - t4_prep_gen2(wc); -#endif - t4_do_counters(wc); - spin_lock(&wc->reglock); - __handle_leds(wc); - spin_unlock(&wc->reglock); - - } - - if (unlikely(status & 0x1)) { - unsigned char cis; - - cis = t4_framer_in(wc, 0, FRMR_CIS); - if (cis & FRMR_CIS_GIS1) - t4_framer_interrupt(wc, 0); - if (cis & FRMR_CIS_GIS2) - t4_framer_interrupt(wc, 1); - if (cis & FRMR_CIS_GIS3) - t4_framer_interrupt(wc, 2); - if (cis & FRMR_CIS_GIS4) - t4_framer_interrupt(wc, 3); - } - - if (wc->vpm) { - if (wc->vpm450m) { - /* How stupid is it that the octasic can't generate an - interrupt when there's a tone, in spite of what their - documentation says? */ - if (!(wc->intcount & 0xf)) { - set_bit(T4_CHECK_VPM, &wc->checkflag); - } - } else if ((status & 0xff00) != 0xff00) { - wc->vpm400checkstatus = (status & 0xff00) >> 8; - set_bit(T4_CHECK_VPM, &wc->checkflag); - } - } - - spin_lock(&wc->reglock); - - if (unlikely(wc->checktiming > 0)) { - __t4_set_timing_source_auto(wc); - } - - if (unlikely(wc->stopdma)) { - /* Stop DMA cleanly if requested */ - wc->dmactrl = 0x0; - __t4_pci_out(wc, WC_DMACTRL, 0x00000000); - /* Acknowledge any pending interrupts */ - __t4_pci_out(wc, WC_INTR, 0x00000000); - __t4_set_timing_source(wc, 4, 0, 0); - wc->stopdma = 0x0; - } - - spin_unlock(&wc->reglock); - - if (unlikely(test_bit(T4_CHECK_VPM, &wc->checkflag))) - tasklet_schedule(&wc->t4_tlet); - -#ifndef ENABLE_WORKQUEUES - __t4_pci_out(wc, WC_INTR, 0); -#endif -#ifdef LINUX26 - return IRQ_RETVAL(1); -#endif -} - -#ifdef SUPPORT_GEN1 -static int t4_reset_dma(struct t4 *wc) -{ - /* Turn off DMA and such */ - wc->dmactrl = 0x0; - t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); - t4_pci_out(wc, WC_COUNT, 0); - t4_pci_out(wc, WC_RDADDR, 0); - t4_pci_out(wc, WC_WRADDR, 0); - t4_pci_out(wc, WC_INTR, 0); - /* Turn it all back on */ - t4_pci_out(wc, WC_RDADDR, wc->readdma); - t4_pci_out(wc, WC_WRADDR, wc->writedma); - t4_pci_out(wc, WC_COUNT, ((ZT_MAX_CHUNKSIZE * 2 * 32 - 1) << 18) | ((ZT_MAX_CHUNKSIZE * 2 * 32 - 1) << 2)); - t4_pci_out(wc, WC_INTR, 0); -#ifdef VPM_SUPPORT - wc->dmactrl = 0xc0000000 | (1 << 29) | wc->vpm; -#else - wc->dmactrl = 0xc0000000 | (1 << 29); -#endif - if (noburst) - wc->dmactrl |= (1 << 26); - t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); - return 0; -} -#endif - -#ifdef VPM_SUPPORT -static void t4_vpm_set_dtmf_threshold(struct t4 *wc, unsigned int threshold) -{ - unsigned int x; - - for (x = 0; x < 8; x++) { - t4_vpm_out(wc, x, 0xC4, (threshold >> 8) & 0xFF); - t4_vpm_out(wc, x, 0xC5, (threshold & 0xFF)); - } - printk("VPM: DTMF threshold set to %d\n", threshold); -} - -static unsigned int t4_vpm_mask(int chip) -{ - unsigned int mask=0; - switch(vpmspans) { - case 4: - mask = 0x55555555 << (chip >> 2); - break; - case 2: - mask = 0x11111111 << (chip >> 1); - break; - case 1: - mask = 0x01010101 << chip; - break; - } - return mask; -} - -static int t4_vpm_spanno(int chip) -{ - int spanno = 0; - switch(vpmspans) { - case 4: - spanno = chip & 0x3; - break; - case 2: - spanno = chip & 0x1; - break; - /* Case 1 is implicit */ - } - return spanno; -} - -static int t4_vpm_echotail(void) -{ - int echotail = 0x01ff; - switch(vpmspans) { - case 4: - echotail = 0x007f; - break; - case 2: - echotail = 0x00ff; - break; - /* Case 1 is implicit */ - } - return echotail; -} - -static void t4_vpm450_init(struct t4 *wc) -{ - unsigned int check1, check2; - int laws[4] = { 0, }; - int x; - unsigned int vpm_capacity; - struct firmware embedded_firmware; - const struct firmware *firmware = &embedded_firmware; -#if !defined(HOTPLUG_FIRMWARE) - extern void _binary_zaptel_fw_oct6114_064_bin_size; - extern void _binary_zaptel_fw_oct6114_128_bin_size; - extern u8 _binary_zaptel_fw_oct6114_064_bin_start[]; - extern u8 _binary_zaptel_fw_oct6114_128_bin_start[]; -#else - static const char oct064_firmware[] = "zaptel-fw-oct6114-064.bin"; - static const char oct128_firmware[] = "zaptel-fw-oct6114-128.bin"; -#endif - - if (!vpmsupport) { - printk("VPM450: Support Disabled\n"); - return; - } - - /* Turn on GPIO/DATA mux if supported */ - t4_gpio_setdir(wc, (1 << 24), (1 << 24)); - __t4_raw_oct_out(wc, 0x000a, 0x5678); - __t4_raw_oct_out(wc, 0x0004, 0x1234); - check1 = __t4_raw_oct_in(wc, 0x0004); - check2 = __t4_raw_oct_in(wc, 0x000a); - if (debug) - printk("OCT Result: %04x/%04x\n", __t4_raw_oct_in(wc, 0x0004), __t4_raw_oct_in(wc, 0x000a)); - if (__t4_raw_oct_in(wc, 0x0004) != 0x1234) { - printk("VPM450: Not Present\n"); - return; - } - - /* Setup alaw vs ulaw rules */ - for (x = 0;x < wc->numspans; x++) { - if (wc->tspans[x]->span.channels > 24) - laws[x] = 1; - } - - switch ((vpm_capacity = get_vpm450m_capacity(wc))) { - case 64: -#if defined(HOTPLUG_FIRMWARE) - if ((request_firmware(&firmware, oct064_firmware, &wc->dev->dev) != 0) || - !firmware) { - printk("VPM450: firmware %s not available from userspace\n", oct064_firmware); - return; - } -#else - embedded_firmware.data = _binary_zaptel_fw_oct6114_064_bin_start; - /* Yes... this is weird. objcopy gives us a symbol containing - the size of the firmware, not a pointer a variable containing - the size. The only way we can get the value of the symbol - is to take its address, so we define it as a pointer and - then cast that value to the proper type. - */ - embedded_firmware.size = (size_t) &_binary_zaptel_fw_oct6114_064_bin_size; -#endif - break; - case 128: -#if defined(HOTPLUG_FIRMWARE) - if ((request_firmware(&firmware, oct128_firmware, &wc->dev->dev) != 0) || - !firmware) { - printk("VPM450: firmware %s not available from userspace\n", oct128_firmware); - return; - } -#else - embedded_firmware.data = _binary_zaptel_fw_oct6114_128_bin_start; - /* Yes... this is weird. objcopy gives us a symbol containing - the size of the firmware, not a pointer a variable containing - the size. The only way we can get the value of the symbol - is to take its address, so we define it as a pointer and - then cast that value to the proper type. - */ - embedded_firmware.size = (size_t) &_binary_zaptel_fw_oct6114_128_bin_size; -#endif - break; - default: - printk("Unsupported channel capacity found on VPM module (%d).\n", vpm_capacity); - return; - } - - if (!(wc->vpm450m = init_vpm450m(wc, laws, wc->numspans, firmware))) { - printk("VPM450: Failed to initialize\n"); - if (firmware != &embedded_firmware) - release_firmware(firmware); - return; - } - - if (firmware != &embedded_firmware) - release_firmware(firmware); - - if (vpmdtmfsupport == -1) { - printk("VPM450: hardware DTMF disabled.\n"); - vpmdtmfsupport = 0; - } - - wc->vpm = T4_VPM_PRESENT; - printk("VPM450: Present and operational servicing %d span(s)\n", wc->numspans); - -} - -static void t4_vpm400_init(struct t4 *wc) -{ - unsigned char reg; - unsigned int mask; - unsigned int ver; - unsigned int i, x, y, gen2vpm=0; - - if (!vpmsupport) { - printk("VPM400: Support Disabled\n"); - return; - } - - switch(vpmspans) { - case 4: - case 2: - case 1: - break; - default: - printk("VPM400: %d is not a valid vpmspans value, using 4\n", vpmspans); - vpmspans = 4; - } - - for (x=0;x<8;x++) { - int spanno = t4_vpm_spanno(x); - struct t4_span *ts = wc->tspans[spanno]; - int echotail = t4_vpm_echotail(); - - ver = t4_vpm_in(wc, x, 0x1a0); /* revision */ - if ((ver != 0x26) && (ver != 0x33)) { - printk("VPM400: %s\n", x ? "Inoperable" : "Not Present"); - return; - } - if (ver == 0x33) { - if (x && !gen2vpm) { - printk("VPM400: Inconsistent\n"); - return; - } - ts->spanflags |= FLAG_VPM2GEN; - gen2vpm++; - } else if (gen2vpm) { - printk("VPM400: Inconsistent\n"); - return; - } - - - /* Setup GPIO's */ - for (y=0;y<4;y++) { - t4_vpm_out(wc, x, 0x1a8 + y, 0x00); /* GPIO out */ - t4_vpm_out(wc, x, 0x1ac + y, 0x00); /* GPIO dir */ - t4_vpm_out(wc, x, 0x1b0 + y, 0x00); /* GPIO sel */ - } - - /* Setup TDM path - sets fsync and tdm_clk as inputs */ - reg = t4_vpm_in(wc, x, 0x1a3); /* misc_con */ - t4_vpm_out(wc, x, 0x1a3, reg & ~2); - - /* Setup timeslots */ - t4_vpm_out(wc, x, 0x02f, 0x20 | (spanno << 3)); - - /* Setup Echo length (128 taps) */ - t4_vpm_out(wc, x, 0x022, (echotail >> 8)); - t4_vpm_out(wc, x, 0x023, (echotail & 0xff)); - - /* Setup the tdm channel masks for all chips*/ - mask = t4_vpm_mask(x); - for (i = 0; i < 4; i++) - t4_vpm_out(wc, x, 0x30 + i, (mask >> (i << 3)) & 0xff); - - /* Setup convergence rate */ - reg = t4_vpm_in(wc,x,0x20); - reg &= 0xE0; - if (ts->spantype == TYPE_E1) { - if (x < vpmspans) - printk("VPM400: Span %d A-law mode\n", spanno); - reg |= 0x01; - } else { - if (x < vpmspans) - printk("VPM400: Span %d U-law mode\n", spanno); - reg &= ~0x01; - } - t4_vpm_out(wc,x,0x20,(reg | 0x20)); - - /* Initialize echo cans */ - for (i = 0 ; i < MAX_TDM_CHAN; i++) { - if (mask & (0x00000001 << i)) - t4_vpm_out(wc,x,i,0x00); - } - - wait_a_little(); - - /* Put in bypass mode */ - for (i = 0 ; i < MAX_TDM_CHAN ; i++) { - if (mask & (0x00000001 << i)) { - t4_vpm_out(wc,x,i,0x01); - } - } - - /* Enable bypass */ - for (i = 0 ; i < MAX_TDM_CHAN ; i++) { - if (mask & (0x00000001 << i)) - t4_vpm_out(wc,x,0x78 + i,0x01); - } - - /* set DTMF detection threshold */ - t4_vpm_set_dtmf_threshold(wc, dtmfthreshold); - - /* Enable DTMF detectors (always DTMF detect all spans) */ - for (i = 0; i < MAX_DTMF_DET; i++) { - t4_vpm_out(wc, x, 0x98 + i, 0x40 | (i * 2) | ((x < 4) ? 0 : 1)); - } - for (i = 0x34; i < 0x38; i++) - t4_vpm_out(wc, x, i, 0x00); - for (i = 0x3C; i < 0x40; i++) - t4_vpm_out(wc, x, i, 0x00); - - for (i = 0x48; i < 0x4B; i++) - t4_vpm_out(wc, x, i, 0x00); - for (i = 0x50; i < 0x53; i++) - t4_vpm_out(wc, x, i, 0x00); - for (i = 0xB8; i < 0xBE; i++) - t4_vpm_out(wc, x, i, 0xFF); - if (gen2vpm) { - for (i = 0xBE; i < 0xC0; i++) - t4_vpm_out(wc, x, i, 0xFF); - } else { - for (i = 0xBE; i < 0xC0; i++) - t4_vpm_out(wc, x, i, 0x00); - } - for (i = 0xC0; i < 0xC4; i++) - t4_vpm_out(wc, x, i, (x < 4) ? 0x55 : 0xAA); - - } - if (vpmdtmfsupport == -1) { - printk("VPM400: hardware DTMF enabled.\n"); - vpmdtmfsupport = 0; - } - printk("VPM400%s: Present and operational servicing %d span(s)\n", (gen2vpm ? " (2nd Gen)" : ""), wc->numspans); - wc->vpm = T4_VPM_PRESENT; -} - -#endif - -static void t4_tsi_reset(struct t4 *wc) -{ - int x; - for (x=0;x<128;x++) { - wc->dmactrl &= ~0x00007fff; - wc->dmactrl |= (0x00004000 | (x << 7)); - t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); - } - wc->dmactrl &= ~0x00007fff; - t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); -} - -/* Note that channels here start from 1 */ -static void t4_tsi_assign(struct t4 *wc, int fromspan, int fromchan, int tospan, int tochan) -{ - unsigned long flags; - int fromts, tots; - - fromts = (fromspan << 5) |(fromchan); - tots = (tospan << 5) | (tochan); - - if (!wc->t1e1) { - fromts += 4; - tots += 4; - } - spin_lock_irqsave(&wc->reglock, flags); - wc->dmactrl &= ~0x00007fff; - wc->dmactrl |= (0x00004000 | (tots << 7) | (fromts)); - __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); - wc->dmactrl &= ~0x00007fff; - __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); - spin_unlock_irqrestore(&wc->reglock, flags); -} - -static void t4_tsi_unassign(struct t4 *wc, int tospan, int tochan) -{ - unsigned long flags; - int tots; - - tots = (tospan << 5) | (tochan); - - if (!wc->t1e1) - tots += 4; - spin_lock_irqsave(&wc->reglock, flags); - wc->dmactrl &= ~0x00007fff; - wc->dmactrl |= (0x00004000 | (tots << 7)); - __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); - if (debug & DEBUG_TSI) - printk("Sending '%08x\n", wc->dmactrl); - wc->dmactrl &= ~0x00007fff; - __t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); - spin_unlock_irqrestore(&wc->reglock, flags); -} - -static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags) -{ - unsigned int version; - - version = t4_pci_in(wc, WC_VERSION); - printk("TE%dXXP version %08x, burst %s\n", wc->numspans, version, (!(cardflags & FLAG_BURST) && noburst) ? "OFF" : "ON"); -#ifdef ENABLE_WORKQUEUES - printk("TE%dXXP running with work queues.\n", wc->numspans); -#endif - - /* Make sure DMA engine is not running and interrupts are acknowledged */ - wc->dmactrl = 0x0; - t4_pci_out(wc, WC_DMACTRL, wc->dmactrl); - /* Reset Framer and friends */ - t4_pci_out(wc, WC_LEDS, 0x00000000); - - /* Set DMA addresses */ - t4_pci_out(wc, WC_RDADDR, wc->readdma); - t4_pci_out(wc, WC_WRADDR, wc->writedma); - - /* Setup counters, interrupt flags (ignored in Gen2) */ - if (cardflags & FLAG_2NDGEN) { - t4_tsi_reset(wc); - } else { - t4_pci_out(wc, WC_COUNT, ((ZT_MAX_CHUNKSIZE * 2 * 32 - 1) << 18) | ((ZT_MAX_CHUNKSIZE * 2 * 32 - 1) << 2)); - } - - /* Reset pending interrupts */ - t4_pci_out(wc, WC_INTR, 0x00000000); - - /* Read T1/E1 status */ - if (t1e1override > -1) - wc->t1e1 = t1e1override; - else - wc->t1e1 = ((t4_pci_in(wc, WC_LEDS)) & 0x0f00) >> 8; - wc->order = ((t4_pci_in(wc, WC_LEDS)) & 0xf0000000) >> 28; - order_index[wc->order]++; - return 0; -} - -static int t4_hardware_init_2(struct t4 *wc) -{ - int x; - unsigned int falcver; - - if (t4_pci_in(wc, WC_VERSION) >= 0xc01a0165) { - wc->tspans[0]->spanflags |= FLAG_OCTOPT; - printk("Octasic optimized!\n"); - } - /* Setup LEDS, take out of reset */ - t4_pci_out(wc, WC_LEDS, 0x000000ff); - t4_activate(wc); - - t4_framer_out(wc, 0, 0x4a, 0xaa); - falcver = t4_framer_in(wc, 0 ,0x4a); - printk("FALC version: %08x, Board ID: %02x\n", falcver, wc->order); - - for (x=0;x< 11;x++) - printk("Reg %d: 0x%08x\n", x, t4_pci_in(wc, x)); - return 0; -} - -static int __devinit t4_launch(struct t4 *wc) -{ - int x; - unsigned long flags; - if (wc->tspans[0]->span.flags & ZT_FLAG_REGISTERED) - return 0; - printk("TE%dXXP: Launching card: %d\n", wc->numspans, wc->order); - - /* Setup serial parameters and system interface */ - for (x=0;x<4;x++) - t4_serial_setup(wc, x); - - if (zt_register(&wc->tspans[0]->span, 0)) { - printk(KERN_ERR "Unable to register span %s\n", wc->tspans[0]->span.name); - return -1; - } - if (zt_register(&wc->tspans[1]->span, 0)) { - printk(KERN_ERR "Unable to register span %s\n", wc->tspans[1]->span.name); - zt_unregister(&wc->tspans[0]->span); - return -1; - } - - if (wc->numspans == 4) { - if (zt_register(&wc->tspans[2]->span, 0)) { - printk(KERN_ERR "Unable to register span %s\n", wc->tspans[2]->span.name); - zt_unregister(&wc->tspans[0]->span); - zt_unregister(&wc->tspans[1]->span); - return -1; - } - if (zt_register(&wc->tspans[3]->span, 0)) { - printk(KERN_ERR "Unable to register span %s\n", wc->tspans[3]->span.name); - zt_unregister(&wc->tspans[0]->span); - zt_unregister(&wc->tspans[1]->span); - zt_unregister(&wc->tspans[2]->span); - return -1; - } - } - wc->checktiming = 1; - spin_lock_irqsave(&wc->reglock, flags); - __t4_set_timing_source(wc,4, 0, 0); - spin_unlock_irqrestore(&wc->reglock, flags); - tasklet_init(&wc->t4_tlet, t4_isr_bh, (unsigned long)wc); - return 0; -} - -static int __devinit t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int res; - struct t4 *wc; - struct devtype *dt; - int x,f; - int basesize; -#if 0 - int y; - unsigned int *canary; -#endif - - - if (pci_enable_device(pdev)) { - res = -EIO; - } else { - wc = kmalloc(sizeof(struct t4), GFP_KERNEL); - if (wc) { - memset(wc, 0x0, sizeof(struct t4)); - spin_lock_init(&wc->reglock); - dt = (struct devtype *)(ent->driver_data); - if (dt->flags & FLAG_2NDGEN) - basesize = ZT_MAX_CHUNKSIZE * 32 * 4; - else - basesize = ZT_MAX_CHUNKSIZE * 32 * 2 * 4; - - if (dt->flags & FLAG_2PORT) - wc->numspans = 2; - else - wc->numspans = 4; - - wc->variety = dt->desc; - - wc->memaddr = pci_resource_start(pdev, 0); - wc->memlen = pci_resource_len(pdev, 0); - wc->membase = ioremap(wc->memaddr, wc->memlen); - /* This rids of the Double missed interrupt message after loading */ - wc->last0 = 1; -#if 0 - if (!request_mem_region(wc->memaddr, wc->memlen, wc->variety)) - printk("wct4: Unable to request memory region :(, using anyway...\n"); -#endif - if (pci_request_regions(pdev, wc->variety)) - printk("wct%dxxp: Unable to request regions\n", wc->numspans); - - printk("Found TE%dXXP at base address %08lx, remapped to %p\n", wc->numspans, wc->memaddr, wc->membase); - - wc->dev = pdev; - - wc->writechunk = - /* 32 channels, Double-buffer, Read/Write, 4 spans */ - (unsigned int *)pci_alloc_consistent(pdev, basesize * 2, &wc->writedma); - if (!wc->writechunk) { - printk("wct%dxxp: Unable to allocate DMA-able memory\n", wc->numspans); - return -ENOMEM; - } - - /* Read is after the whole write piece (in words) */ - wc->readchunk = wc->writechunk + basesize / 4; - - /* Same thing but in bytes... */ - wc->readdma = wc->writedma + basesize; - - /* Initialize Write/Buffers to all blank data */ - memset((void *)wc->writechunk,0x00, basesize); - memset((void *)wc->readchunk,0xff, basesize); -#if 0 - memset((void *)wc->readchunk,0xff,ZT_MAX_CHUNKSIZE * 2 * 32 * 4); - /* Initialize canary */ - canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 64 * 4 - 4); - *canary = (CANARY << 16) | (0xffff); -#endif - - /* Enable bus mastering */ - pci_set_master(pdev); - - /* Keep track of which device we are */ - pci_set_drvdata(pdev, wc); - - /* Initialize hardware */ - t4_hardware_init_1(wc, dt->flags); - - for(x = 0; x < MAX_T4_CARDS; x++) { - if (!cards[x]) break; - } - - if (x >= MAX_T4_CARDS) { - printk("No cards[] slot available!!\n"); - return -ENOMEM; - } - - wc->num = x; - cards[x] = wc; - - -#ifdef ENABLE_WORKQUEUES - if (dt->flags & FLAG_2NDGEN) { - char tmp[20]; - sprintf(tmp, "te%dxxp[%d]", wc->numspans, wc->num); - wc->workq = create_workqueue(tmp); - } -#endif - - /* Allocate pieces we need here */ - for (x=0;x<4;x++) { - if (wc->t1e1 & (1 << x)) { - wc->tspans[x] = kmalloc(sizeof(struct t4_span) + sizeof(struct zt_chan) * 31, GFP_KERNEL); - if (wc->tspans[x]) { - memset(wc->tspans[x], 0, sizeof(struct t4_span) + sizeof(struct zt_chan) * 31); - wc->tspans[x]->spantype = TYPE_E1; - } - } else { - wc->tspans[x] = kmalloc(sizeof(struct t4_span) + sizeof(struct zt_chan) * 24, GFP_KERNEL); - if (wc->tspans[x]) { - memset(wc->tspans[x], 0, sizeof(struct t4_span) + sizeof(struct zt_chan) * 24); - if (j1mode) - wc->tspans[x]->spantype = TYPE_J1; - else - wc->tspans[x]->spantype = TYPE_T1; - } - } - if (!wc->tspans[x]) - return -ENOMEM; -#ifdef ENABLE_WORKQUEUES - INIT_WORK(&wc->tspans[x]->swork, workq_handlespan, wc->tspans[x]); -#endif - wc->tspans[x]->spanflags |= dt->flags; - } - - - /* Continue hardware intiialization */ - t4_hardware_init_2(wc); - - -#ifdef SUPPORT_GEN1 - if (request_irq(pdev->irq, (dt->flags & FLAG_2NDGEN) ? t4_interrupt_gen2 :t4_interrupt, ZAP_IRQ_SHARED_DISABLED, (wc->numspans == 2) ? "wct2xxp" : "wct4xxp", wc)) -#else - if (!(wc->tspans[0]->spanflags & FLAG_2NDGEN)) { - printk("This driver does not support 1st gen modules\n"); - kfree(wc); - return -ENODEV; - } - if (request_irq(pdev->irq, t4_interrupt_gen2, ZAP_IRQ_SHARED_DISABLED, "t4xxp", wc)) -#endif - { - printk("t4xxp: Unable to request IRQ %d\n", pdev->irq); - kfree(wc); - return -EIO; - } - - init_spans(wc); - - /* Launch cards as appropriate */ - for (;;) { - /* Find a card to activate */ - f = 0; - for (x=0;cards[x];x++) { - if (cards[x]->order <= highestorder) { - t4_launch(cards[x]); - if (cards[x]->order == highestorder) - f = 1; - } - } - /* If we found at least one, increment the highest order and search again, otherwise stop */ - if (f) - highestorder++; - else - break; - } - - printk("Found a Wildcard: %s\n", wc->variety); - wc->gpio = 0x00000000; - t4_pci_out(wc, WC_GPIO, wc->gpio); - t4_gpio_setdir(wc, (1 << 17), (1 << 17)); - t4_gpio_setdir(wc, (0xff), (0xff)); - -#if 0 - for (x=0;x<0x10000;x++) { - __t4_raw_oct_out(wc, 0x0004, x); - __t4_raw_oct_out(wc, 0x000a, x ^ 0xffff); - if (__t4_raw_oct_in(wc, 0x0004) != x) - printk("Register 4 failed %04x\n", x); - if (__t4_raw_oct_in(wc, 0x000a) != (x ^ 0xffff)) - printk("Register 10 failed %04x\n", x); - } -#endif - res = 0; - } else - res = -ENOMEM; - } - return res; -} - -static int t4_hardware_stop(struct t4 *wc) -{ - - /* Turn off DMA, leave interrupts enabled */ - wc->stopdma = 1; - - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout((25 * HZ) / 1000); - - /* Turn off counter, address, etc */ - if (wc->tspans[0]->spanflags & FLAG_2NDGEN) { - t4_tsi_reset(wc); - } else { - t4_pci_out(wc, WC_COUNT, 0x000000); - } - t4_pci_out(wc, WC_RDADDR, 0x0000000); - t4_pci_out(wc, WC_WRADDR, 0x0000000); - wc->gpio = 0x00000000; - t4_pci_out(wc, WC_GPIO, wc->gpio); - t4_pci_out(wc, WC_LEDS, 0x00000000); - - printk("\nStopped TE%dXXP, Turned off DMA\n", wc->numspans); - return 0; -} - -static void __devexit t4_remove_one(struct pci_dev *pdev) -{ - struct t4 *wc = pci_get_drvdata(pdev); - int x; - if (wc) { - /* Stop hardware */ - t4_hardware_stop(wc); - - /* Release vpm450m */ - if (wc->vpm450m) - release_vpm450m(wc->vpm450m); - wc->vpm450m = NULL; - /* Unregister spans */ - if (wc->tspans[0]->span.flags & ZT_FLAG_REGISTERED) - zt_unregister(&wc->tspans[0]->span); - if (wc->tspans[1]->span.flags & ZT_FLAG_REGISTERED) - zt_unregister(&wc->tspans[1]->span); - if (wc->numspans == 4) { - if (wc->tspans[2]->span.flags & ZT_FLAG_REGISTERED) - zt_unregister(&wc->tspans[2]->span); - if (wc->tspans[3]->span.flags & ZT_FLAG_REGISTERED) - zt_unregister(&wc->tspans[3]->span); - } -#ifdef ENABLE_WORKQUEUES - if (wc->workq) { - flush_workqueue(wc->workq); - destroy_workqueue(wc->workq); - } -#endif -#if 0 - /* Stop any DMA */ - __t1xxp_stop_dma(wc); - - /* In case hardware is still there */ - __t1xxp_disable_interrupts(wc); - - t1xxp_stop_stuff(wc); -#endif - - if (wc->membase) - iounmap((void *)wc->membase); - - pci_release_regions(pdev); -#if 0 - if (wc->memaddr) - release_mem_region(wc->memaddr, wc->memlen); -#endif - - /* Immediately free resources */ - pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 32 * 4, (void *)wc->writechunk, wc->writedma); -#if 1 - free_irq(pdev->irq, wc); -#endif - - order_index[wc->order]--; - - cards[wc->num] = NULL; - pci_set_drvdata(pdev, NULL); - for (x=0;xnumspans;x++) { - if (wc->tspans[x]) - kfree(wc->tspans[x]); - } - kfree(wc); - } -} - - -static struct pci_device_id t4_pci_tbl[] __devinitdata = -{ - { 0x10ee, 0x0314, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct4xxp }, - - { 0xd161, 0x0420, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct420p4 }, - { 0xd161, 0x0410, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct410p4 }, - { 0xd161, 0x0405, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct405p4 }, - { 0xd161, 0x0410, 0x0003, PCI_ANY_ID, 0, 0, (unsigned long)&wct410p3 }, - { 0xd161, 0x0405, 0x0003, PCI_ANY_ID, 0, 0, (unsigned long)&wct405p3 }, - { 0xd161, 0x0410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct410p2 }, - { 0xd161, 0x0405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct405p2 }, - - { 0xd161, 0x0220, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct220p4 }, - { 0xd161, 0x0205, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct205p4 }, - { 0xd161, 0x0210, 0x0004, PCI_ANY_ID, 0, 0, (unsigned long)&wct210p4 }, - { 0xd161, 0x0205, 0x0003, PCI_ANY_ID, 0, 0, (unsigned long)&wct205p3 }, - { 0xd161, 0x0210, 0x0003, PCI_ANY_ID, 0, 0, (unsigned long)&wct210p3 }, - { 0xd161, 0x0205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct205 }, - { 0xd161, 0x0210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wct210 }, - { 0, } -}; - -static struct pci_driver t4_driver = { - name: "wct4xxp", - probe: t4_init_one, -#ifdef LINUX26 - remove: __devexit_p(t4_remove_one), -#else - remove: t4_remove_one, -#endif - suspend: NULL, - resume: NULL, - id_table: t4_pci_tbl, -}; - -static int __init t4_init(void) -{ - int res; - res = zap_pci_module(&t4_driver); - if (res) - return -ENODEV; - return 0; -} - -static void __exit t4_cleanup(void) -{ - pci_unregister_driver(&t4_driver); -} - - -MODULE_AUTHOR("Mark Spencer"); -MODULE_DESCRIPTION("Unified TE4XXP-TE2XXP PCI Driver"); -#if defined(MODULE_ALIAS) -MODULE_ALIAS("wct2xxp"); -#endif -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif -#ifdef LINUX26 -module_param(pedanticpci, int, 0600); -module_param(debug, int, 0600); -module_param(loopback, int, 0600); -module_param(noburst, int, 0600); -module_param(timingcable, int, 0600); -module_param(t1e1override, int, 0600); -module_param(alarmdebounce, int, 0600); -module_param(j1mode, int, 0600); -module_param(sigmode, int, 0600); -#ifdef VPM_SUPPORT -module_param(vpmsupport, int, 0600); -module_param(vpmdtmfsupport, int, 0600); -module_param(vpmspans, int, 0600); -module_param(dtmfthreshold, int, 0600); -#endif -#else -MODULE_PARM(pedanticpci, "i"); -MODULE_PARM(debug, "i"); -MODULE_PARM(loopback, "i"); -MODULE_PARM(noburst, "i"); -MODULE_PARM(hardhdlcmode, "i"); -MODULE_PARM(timingcable, "i"); -MODULE_PARM(t1e1override, "i"); -MODULE_PARM(alarmdebounce, "i"); -MODULE_PARM(j1mode, "i"); -MODULE_PARM(sigmode, "i"); -#ifdef VPM_SUPPORT -MODULE_PARM(vpmsupport, "i"); -MODULE_PARM(vpmdtmfsupport, "i"); -MODULE_PARM(vpmspans, "i"); -MODULE_PARM(dtmfthreshold, "i"); -#endif -#endif - -MODULE_DEVICE_TABLE(pci, t4_pci_tbl); - -module_init(t4_init); -module_exit(t4_cleanup); diff --git a/wct4xxp/vpm450m.c b/wct4xxp/vpm450m.c deleted file mode 100644 index 674dd49..0000000 --- a/wct4xxp/vpm450m.c +++ /dev/null @@ -1,577 +0,0 @@ -/* - * Copyright (C) 2005-2006 Digium, Inc. - * - * Mark Spencer - * - * All Rights Reserved - */ - -#include -#include -#include -#include -#include - -#include "vpm450m.h" -#include "oct6100api/oct6100_api.h" - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) -#include -#else -#include -#endif - -/* API for Octasic access */ -UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime) -{ - /* Why couldn't they just take a timeval like everyone else? */ - struct timeval tv; - unsigned long long total_usecs; - unsigned int mask = ~0; - - do_gettimeofday(&tv); - total_usecs = (((unsigned long long)(tv.tv_sec)) * 1000000) + - (((unsigned long long)(tv.tv_usec))); - f_pTime->aulWallTimeUs[0] = (total_usecs & mask); - f_pTime->aulWallTimeUs[1] = (total_usecs >> 32); - return cOCT6100_ERR_OK; -} - -UINT32 Oct6100UserMemSet(PVOID f_pAddress, UINT32 f_ulPattern, UINT32 f_ulLength) -{ - memset(f_pAddress, f_ulPattern, f_ulLength); - return cOCT6100_ERR_OK; -} - -UINT32 Oct6100UserMemCopy(PVOID f_pDestination, const void *f_pSource, UINT32 f_ulLength) -{ - memcpy(f_pDestination, f_pSource, f_ulLength); - return cOCT6100_ERR_OK; -} - -UINT32 Oct6100UserCreateSerializeObject(tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate) -{ - return cOCT6100_ERR_OK; -} - -UINT32 Oct6100UserDestroySerializeObject(tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy) -{ -#ifdef OCTASIC_DEBUG - printk("I should never be called! (destroy serialize object)\n"); -#endif - return cOCT6100_ERR_OK; -} - -UINT32 Oct6100UserSeizeSerializeObject(tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize) -{ - /* Not needed */ - return cOCT6100_ERR_OK; -} - -UINT32 Oct6100UserReleaseSerializeObject(tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease) -{ - /* Not needed */ - return cOCT6100_ERR_OK; -} - -UINT32 Oct6100UserDriverWriteApi(tPOCT6100_WRITE_PARAMS f_pWriteParams) -{ - oct_set_reg(f_pWriteParams->pProcessContext, f_pWriteParams->ulWriteAddress, f_pWriteParams->usWriteData); - return cOCT6100_ERR_OK; -} - -UINT32 Oct6100UserDriverWriteSmearApi(tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams) -{ - unsigned int x; - for (x=0;xulWriteLength;x++) { - oct_set_reg(f_pSmearParams->pProcessContext, f_pSmearParams->ulWriteAddress + (x << 1), f_pSmearParams->usWriteData); - } - return cOCT6100_ERR_OK; -} - -UINT32 Oct6100UserDriverWriteBurstApi(tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams) -{ - unsigned int x; - for (x=0;xulWriteLength;x++) { - oct_set_reg(f_pBurstParams->pProcessContext, f_pBurstParams->ulWriteAddress + (x << 1), f_pBurstParams->pusWriteData[x]); - } - return cOCT6100_ERR_OK; -} - -UINT32 Oct6100UserDriverReadApi(tPOCT6100_READ_PARAMS f_pReadParams) -{ - *(f_pReadParams->pusReadData) = oct_get_reg(f_pReadParams->pProcessContext, f_pReadParams->ulReadAddress); - return cOCT6100_ERR_OK; -} - -UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams) -{ - unsigned int x; - for (x=0;xulReadLength;x++) { - f_pBurstParams->pusReadData[x] = oct_get_reg(f_pBurstParams->pProcessContext, f_pBurstParams->ulReadAddress + (x << 1)); - } - return cOCT6100_ERR_OK; -} - -#define SOUT_G168_1100GB_ON 0x40000004 -#define SOUT_DTMF_1 0x40000011 -#define SOUT_DTMF_2 0x40000012 -#define SOUT_DTMF_3 0x40000013 -#define SOUT_DTMF_A 0x4000001A -#define SOUT_DTMF_4 0x40000014 -#define SOUT_DTMF_5 0x40000015 -#define SOUT_DTMF_6 0x40000016 -#define SOUT_DTMF_B 0x4000001B -#define SOUT_DTMF_7 0x40000017 -#define SOUT_DTMF_8 0x40000018 -#define SOUT_DTMF_9 0x40000019 -#define SOUT_DTMF_C 0x4000001C -#define SOUT_DTMF_STAR 0x4000001E -#define SOUT_DTMF_0 0x40000010 -#define SOUT_DTMF_POUND 0x4000001F -#define SOUT_DTMF_D 0x4000001D - -#define ROUT_G168_2100GB_ON 0x10000000 -#define ROUT_G168_2100GB_WSPR 0x10000002 -#define ROUT_SOUT_G168_2100HB_END 0x50000003 -#define ROUT_G168_1100GB_ON 0x10000004 - -#define ROUT_DTMF_1 0x10000011 -#define ROUT_DTMF_2 0x10000012 -#define ROUT_DTMF_3 0x10000013 -#define ROUT_DTMF_A 0x1000001A -#define ROUT_DTMF_4 0x10000014 -#define ROUT_DTMF_5 0x10000015 -#define ROUT_DTMF_6 0x10000016 -#define ROUT_DTMF_B 0x1000001B -#define ROUT_DTMF_7 0x10000017 -#define ROUT_DTMF_8 0x10000018 -#define ROUT_DTMF_9 0x10000019 -#define ROUT_DTMF_C 0x1000001C -#define ROUT_DTMF_STAR 0x1000001E -#define ROUT_DTMF_0 0x10000010 -#define ROUT_DTMF_POUND 0x1000001F -#define ROUT_DTMF_D 0x1000001D - -#if 0 -#define cOCT6100_ECHO_OP_MODE_DIGITAL cOCT6100_ECHO_OP_MODE_HT_FREEZE -#else -#define cOCT6100_ECHO_OP_MODE_DIGITAL cOCT6100_ECHO_OP_MODE_POWER_DOWN -#endif - -struct vpm450m { - tPOCT6100_INSTANCE_API pApiInstance; - UINT32 aulEchoChanHndl[ 128 ]; - int chanflags[128]; - int ecmode[128]; - int numchans; -}; - -#define FLAG_DTMF (1 << 0) -#define FLAG_MUTE (1 << 1) -#define FLAG_ECHO (1 << 2) - -static unsigned int tones[] = { - SOUT_DTMF_1, - SOUT_DTMF_2, - SOUT_DTMF_3, - SOUT_DTMF_A, - SOUT_DTMF_4, - SOUT_DTMF_5, - SOUT_DTMF_6, - SOUT_DTMF_B, - SOUT_DTMF_7, - SOUT_DTMF_8, - SOUT_DTMF_9, - SOUT_DTMF_C, - SOUT_DTMF_STAR, - SOUT_DTMF_0, - SOUT_DTMF_POUND, - SOUT_DTMF_D, - SOUT_G168_1100GB_ON, - - ROUT_DTMF_1, - ROUT_DTMF_2, - ROUT_DTMF_3, - ROUT_DTMF_A, - ROUT_DTMF_4, - ROUT_DTMF_5, - ROUT_DTMF_6, - ROUT_DTMF_B, - ROUT_DTMF_7, - ROUT_DTMF_8, - ROUT_DTMF_9, - ROUT_DTMF_C, - ROUT_DTMF_STAR, - ROUT_DTMF_0, - ROUT_DTMF_POUND, - ROUT_DTMF_D, - ROUT_G168_1100GB_ON, -}; - -static void vpm450m_setecmode(struct vpm450m *vpm450m, int channel, int mode) -{ - tOCT6100_CHANNEL_MODIFY *modify; - UINT32 ulResult; - - if (vpm450m->ecmode[channel] == mode) - return; - modify = kmalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC); - if (!modify) { - printk("wct4xxp: Unable to allocate memory for setec!\n"); - return; - } - Oct6100ChannelModifyDef(modify); - modify->ulEchoOperationMode = mode; - modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel]; - ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify); - if (ulResult != GENERIC_OK) { - printk("Failed to apply echo can changes on channel %d!\n", channel); - } else { -#ifdef OCTASIC_DEBUG - printk("Echo can on channel %d set to %d\n", channel, mode); -#endif - vpm450m->ecmode[channel] = mode; - } - kfree(modify); -} - -void vpm450m_setdtmf(struct vpm450m *vpm450m, int channel, int detect, int mute) -{ - tOCT6100_CHANNEL_MODIFY *modify; - UINT32 ulResult; - - modify = kmalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_KERNEL); - if (!modify) { - printk("wct4xxp: Unable to allocate memory for setdtmf!\n"); - return; - } - Oct6100ChannelModifyDef(modify); - modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel]; - if (mute) { - vpm450m->chanflags[channel] |= FLAG_MUTE; - modify->VqeConfig.fDtmfToneRemoval = TRUE; - } else { - vpm450m->chanflags[channel] &= ~FLAG_MUTE; - modify->VqeConfig.fDtmfToneRemoval = FALSE; - } - if (detect) - vpm450m->chanflags[channel] |= FLAG_DTMF; - else - vpm450m->chanflags[channel] &= ~FLAG_DTMF; - if (vpm450m->chanflags[channel] & (FLAG_DTMF|FLAG_MUTE)) { - if (!(vpm450m->chanflags[channel] & FLAG_ECHO)) { - vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET); - vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_FREEZE); - } - } else { - if (!(vpm450m->chanflags[channel] & FLAG_ECHO)) - vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_DIGITAL); - } - - ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify); - if (ulResult != GENERIC_OK) { - printk("Failed to apply dtmf mute changes on channel %d!\n", channel); - } -/* printk("VPM450m: Setting DTMF on channel %d: %s / %s\n", channel, (detect ? "DETECT" : "NO DETECT"), (mute ? "MUTE" : "NO MUTE")); */ - kfree(modify); -} - -void vpm450m_setec(struct vpm450m *vpm450m, int channel, int eclen) -{ - if (eclen) { - vpm450m->chanflags[channel] |= FLAG_ECHO; - vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET); - vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_NORMAL); - } else { - vpm450m->chanflags[channel] &= ~FLAG_ECHO; - if (vpm450m->chanflags[channel] & (FLAG_DTMF | FLAG_MUTE)) { - vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET); - vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_FREEZE); - } else - vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_DIGITAL); - } -/* printk("VPM450m: Setting EC on channel %d to %d\n", channel, eclen); */ -} - -int vpm450m_checkirq(struct vpm450m *vpm450m) -{ - tOCT6100_INTERRUPT_FLAGS InterruptFlags; - - Oct6100InterruptServiceRoutineDef(&InterruptFlags); - Oct6100InterruptServiceRoutine(vpm450m->pApiInstance, &InterruptFlags); - - return InterruptFlags.fToneEventsPending ? 1 : 0; -} - -int vpm450m_getdtmf(struct vpm450m *vpm450m, int *channel, int *tone, int *start) -{ - tOCT6100_TONE_EVENT tonefound; - tOCT6100_EVENT_GET_TONE tonesearch; - UINT32 ulResult; - - Oct6100EventGetToneDef(&tonesearch); - tonesearch.pToneEvent = &tonefound; - tonesearch.ulMaxToneEvent = 1; - ulResult = Oct6100EventGetTone(vpm450m->pApiInstance, &tonesearch); - if (tonesearch.ulNumValidToneEvent) { - if (channel) - *channel = tonefound.ulUserChanId; - if (tone) { - switch(tonefound.ulToneDetected) { - case SOUT_DTMF_1: - *tone = '1'; - break; - case SOUT_DTMF_2: - *tone = '2'; - break; - case SOUT_DTMF_3: - *tone = '3'; - break; - case SOUT_DTMF_A: - *tone = 'A'; - break; - case SOUT_DTMF_4: - *tone = '4'; - break; - case SOUT_DTMF_5: - *tone = '5'; - break; - case SOUT_DTMF_6: - *tone = '6'; - break; - case SOUT_DTMF_B: - *tone = 'B'; - break; - case SOUT_DTMF_7: - *tone = '7'; - break; - case SOUT_DTMF_8: - *tone = '8'; - break; - case SOUT_DTMF_9: - *tone = '9'; - break; - case SOUT_DTMF_C: - *tone = 'C'; - break; - case SOUT_DTMF_STAR: - *tone = '*'; - break; - case SOUT_DTMF_0: - *tone = '0'; - break; - case SOUT_DTMF_POUND: - *tone = '#'; - break; - case SOUT_DTMF_D: - *tone = 'D'; - break; - case SOUT_G168_1100GB_ON: - *tone = 'f'; - break; - default: -#ifdef OCTASIC_DEBUG - printk("Unknown tone value %08x\n", tonefound.ulToneDetected); -#endif - *tone = 'u'; - break; - } - } - if (start) - *start = (tonefound.ulEventType == cOCT6100_TONE_PRESENT); - return 1; - } - return 0; -} - -unsigned int get_vpm450m_capacity(void *wc) -{ - UINT32 ulResult; - - tOCT6100_API_GET_CAPACITY_PINS CapacityPins; - - Oct6100ApiGetCapacityPinsDef(&CapacityPins); - CapacityPins.pProcessContext = wc; - CapacityPins.ulMemoryType = cOCT6100_MEM_TYPE_DDR; - CapacityPins.fEnableMemClkOut = TRUE; - CapacityPins.ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ; - - ulResult = Oct6100ApiGetCapacityPins(&CapacityPins); - if (ulResult != cOCT6100_ERR_OK) { - printk("Failed to get chip capacity, code %08x!\n", ulResult); - return 0; - } - - return CapacityPins.ulCapacityValue; -} - -struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct firmware *firmware) -{ - tOCT6100_CHIP_OPEN *ChipOpen; - tOCT6100_GET_INSTANCE_SIZE InstanceSize; - tOCT6100_CHANNEL_OPEN *ChannelOpen; - UINT32 ulResult; - struct vpm450m *vpm450m; - int x,y,law; -#ifdef CONFIG_4KSTACKS - unsigned long flags; -#endif - - if (!(vpm450m = kmalloc(sizeof(struct vpm450m), GFP_KERNEL))) - return NULL; - - memset(vpm450m, 0, sizeof(struct vpm450m)); - - if (!(ChipOpen = kmalloc(sizeof(tOCT6100_CHIP_OPEN), GFP_KERNEL))) { - kfree(vpm450m); - return NULL; - } - - memset(ChipOpen, 0, sizeof(tOCT6100_CHIP_OPEN)); - - if (!(ChannelOpen = kmalloc(sizeof(tOCT6100_CHANNEL_OPEN), GFP_KERNEL))) { - kfree(vpm450m); - kfree(ChipOpen); - return NULL; - } - - memset(ChannelOpen, 0, sizeof(tOCT6100_CHANNEL_OPEN)); - - for (x=0;x<128;x++) - vpm450m->ecmode[x] = -1; - - vpm450m->numchans = numspans * 32; - printk("VPM450: echo cancellation for %d channels\n", vpm450m->numchans); - - Oct6100ChipOpenDef(ChipOpen); - - /* Setup Chip Open Parameters */ - ChipOpen->ulUpclkFreq = cOCT6100_UPCLK_FREQ_33_33_MHZ; - Oct6100GetInstanceSizeDef(&InstanceSize); - - ChipOpen->pProcessContext = wc; - - ChipOpen->pbyImageFile = firmware->data; - ChipOpen->ulImageSize = firmware->size; - ChipOpen->fEnableMemClkOut = TRUE; - ChipOpen->ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ; - ChipOpen->ulMaxChannels = vpm450m->numchans; - ChipOpen->ulMemoryType = cOCT6100_MEM_TYPE_DDR; - ChipOpen->ulMemoryChipSize = cOCT6100_MEMORY_CHIP_SIZE_32MB; - ChipOpen->ulNumMemoryChips = 1; - ChipOpen->ulMaxTdmStreams = 4; - ChipOpen->aulTdmStreamFreqs[0] = cOCT6100_TDM_STREAM_FREQ_8MHZ; - ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE; -#if 0 - ChipOpen->fEnableAcousticEcho = TRUE; -#endif - - ulResult = Oct6100GetInstanceSize(ChipOpen, &InstanceSize); - if (ulResult != cOCT6100_ERR_OK) { - printk("Failed to get instance size, code %08x!\n", ulResult); - kfree(vpm450m); - kfree(ChipOpen); - kfree(ChannelOpen); - return NULL; - } - - - vpm450m->pApiInstance = vmalloc(InstanceSize.ulApiInstanceSize); - if (!vpm450m->pApiInstance) { - printk("Out of memory (can't allocate %d bytes)!\n", InstanceSize.ulApiInstanceSize); - kfree(vpm450m); - kfree(ChipOpen); - kfree(ChannelOpen); - return NULL; - } - - /* I don't know what to curse more in this comment, the problems caused by - * the 4K kernel stack limit change or the octasic API for being so darn - * stack unfriendly. Stupid, stupid, stupid. So we disable IRQs so we - * don't run the risk of overflowing the stack while we initialize the - * octasic. */ -#ifdef CONFIG_4KSTACKS - local_irq_save(flags); -#endif - ulResult = Oct6100ChipOpen(vpm450m->pApiInstance, ChipOpen); - if (ulResult != cOCT6100_ERR_OK) { - printk("Failed to open chip, code %08x!\n", ulResult); -#ifdef CONFIG_4KSTACKS - local_irq_restore(flags); -#endif - kfree(vpm450m); - kfree(ChipOpen); - kfree(ChannelOpen); - return NULL; - } - for (x=0;x<128;x++) { - /* execute this loop always on 4 span cards but - * on 2 span cards only execute for the channels related to our spans */ - if (( numspans > 2) || ((x & 0x03) <2)) { - /* span timeslots are interleaved 12341234... - * therefore, the lower 2 bits tell us which span this - * timeslot/channel - */ - if (isalaw[x & 0x03]) - law = cOCT6100_PCM_A_LAW; - else - law = cOCT6100_PCM_U_LAW; - Oct6100ChannelOpenDef(ChannelOpen); - ChannelOpen->pulChannelHndl = &vpm450m->aulEchoChanHndl[x]; - ChannelOpen->ulUserChanId = x; - ChannelOpen->TdmConfig.ulRinPcmLaw = law; - ChannelOpen->TdmConfig.ulRinStream = 0; - ChannelOpen->TdmConfig.ulRinTimeslot = x; - ChannelOpen->TdmConfig.ulSinPcmLaw = law; - ChannelOpen->TdmConfig.ulSinStream = 1; - ChannelOpen->TdmConfig.ulSinTimeslot = x; - ChannelOpen->TdmConfig.ulSoutPcmLaw = law; - ChannelOpen->TdmConfig.ulSoutStream = 2; - ChannelOpen->TdmConfig.ulSoutTimeslot = x; - ChannelOpen->TdmConfig.ulRoutPcmLaw = law; - ChannelOpen->TdmConfig.ulRoutStream = 3; - ChannelOpen->TdmConfig.ulRoutTimeslot = x; - ChannelOpen->VqeConfig.fEnableNlp = TRUE; - ChannelOpen->VqeConfig.fRinDcOffsetRemoval = TRUE; - ChannelOpen->VqeConfig.fSinDcOffsetRemoval = TRUE; - - ChannelOpen->fEnableToneDisabler = TRUE; - ChannelOpen->ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_DIGITAL; - - ulResult = Oct6100ChannelOpen(vpm450m->pApiInstance, ChannelOpen); - if (ulResult != GENERIC_OK) { - printk("Failed to open channel %d!\n", x); - } - for (y=0;yaulEchoChanHndl[x]; - enable.ulToneNumber = tones[y]; - if (Oct6100ToneDetectionEnable(vpm450m->pApiInstance, &enable) != GENERIC_OK) - printk("Failed to enable tone detection on channel %d for tone %d!\n", x, y); - } - } - } - -#ifdef CONFIG_4KSTACKS - local_irq_restore(flags); -#endif - kfree(ChipOpen); - kfree(ChannelOpen); - return vpm450m; -} - -void release_vpm450m(struct vpm450m *vpm450m) -{ - UINT32 ulResult; - tOCT6100_CHIP_CLOSE ChipClose; - - Oct6100ChipCloseDef(&ChipClose); - ulResult = Oct6100ChipClose(vpm450m->pApiInstance, &ChipClose); - if (ulResult != cOCT6100_ERR_OK) { - printk("Failed to close chip, code %08x!\n", ulResult); - } - vfree(vpm450m->pApiInstance); - kfree(vpm450m); -} diff --git a/wct4xxp/vpm450m.h b/wct4xxp/vpm450m.h deleted file mode 100644 index 41d7c60..0000000 --- a/wct4xxp/vpm450m.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2005-2006 Digium, Inc. - * - * Mark Spencer - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef _VPM450M_H -#define _VPM450M_H - -#include - -struct vpm450m; - -/* From driver */ -unsigned int oct_get_reg(void *data, unsigned int reg); -void oct_set_reg(void *data, unsigned int reg, unsigned int val); - -/* From vpm450m */ -struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct firmware *firmware); -unsigned int get_vpm450m_capacity(void *wc); -void vpm450m_setec(struct vpm450m *instance, int channel, int eclen); -void vpm450m_setdtmf(struct vpm450m *instance, int channel, int dtmfdetect, int dtmfmute); -int vpm450m_checkirq(struct vpm450m *vpm450m); -int vpm450m_getdtmf(struct vpm450m *vpm450m, int *channel, int *tone, int *start); -void release_vpm450m(struct vpm450m *instance); - -#endif diff --git a/wct4xxp/wct4xxp-diag.c b/wct4xxp/wct4xxp-diag.c deleted file mode 100644 index 50a328d..0000000 --- a/wct4xxp/wct4xxp-diag.c +++ /dev/null @@ -1,414 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "zaptel.h" -#include "wct4xxp.h" - -static struct t4_reg_def { - int reg; - char *name; - int global; -}; -static struct t4_reg_def xreginfo[] = { - { 0x00, "RDADDR" }, - { 0x01, "WRADDR" }, - { 0x02, "COUNT" }, - { 0x03, "DMACTRL" }, - { 0x04, "WCINTR" }, - { 0x06, "VERSION" }, - { 0x07, "LEDS" }, - { 0x08, "GPIOCTL" }, - { 0x09, "GPIO" }, - { 0x0A, "LADDR" }, - { 0x0b, "LDATA" }, -}; - -static struct t4_reg_def reginfo[] = { - { 0x00, "XFIFO" }, - { 0x01, "XFIFO" }, - { 0x02, "CMDR" }, - { 0x03, "MODE" }, - { 0x04, "RAH1" }, - { 0x05, "RAH2" }, - { 0x06, "RAL1" }, - { 0x07, "RAL2" }, - { 0x08, "IPC", 1 }, - { 0x09, "CCR1" }, - { 0x0a, "CCR2" }, - { 0x0c, "RTR1" }, - { 0x0d, "RTR2" }, - { 0x0e, "RTR3" }, - { 0x0f, "RTR4" }, - { 0x10, "TTR1" }, - { 0x11, "TTR2" }, - { 0x12, "TTR3" }, - { 0x13, "TTR4" }, - { 0x14, "IMR0" }, - { 0x15, "IMR1" }, - { 0x16, "IMR2" }, - { 0x17, "IMR3" }, - { 0x18, "IMR4" }, - { 0x1b, "IERR" }, - { 0x1c, "FMR0" }, - { 0x1d, "FMR1" }, - { 0x1e, "FMR2" }, - { 0x1f, "LOOP" }, - { 0x20, "XSW" }, - { 0x21, "XSP" }, - { 0x22, "XC0" }, - { 0x23, "XC1" }, - { 0x24, "RC0" }, - { 0x25, "RC1" }, - { 0x26, "XPM0" }, - { 0x27, "XPM1" }, - { 0x28, "XPM2" }, - { 0x29, "TSWM" }, - { 0x2b, "IDLE" }, - { 0x2c, "XSA4" }, - { 0x2d, "XSA5" }, - { 0x2e, "XSA6" }, - { 0x2f, "XSA7" }, - { 0x30, "XSA8" }, - { 0x31, "FMR3" }, - { 0x32, "ICB1" }, - { 0x33, "ICB2" }, - { 0x34, "ICB3" }, - { 0x35, "ICB4" }, - { 0x36, "LIM0" }, - { 0x37, "LIM1" }, - { 0x38, "PCD" }, - { 0x39, "PCR" }, - { 0x3a, "LIM2" }, - { 0x3b, "LCR1" }, - { 0x3c, "LCR2" }, - { 0x3d, "LCR3" }, - { 0x3e, "SIC1" }, - { 0x3f, "SIC2" }, - { 0x40, "SIC3" }, - { 0x44, "CMR1" }, - { 0x45, "CMR2" }, - { 0x46, "GCR" }, - { 0x47, "ESM" }, - { 0x60, "DEC" }, - { 0x70, "XS1" }, - { 0x71, "XS2" }, - { 0x72, "XS3" }, - { 0x73, "XS4" }, - { 0x74, "XS5" }, - { 0x75, "XS6" }, - { 0x76, "XS7" }, - { 0x77, "XS8" }, - { 0x78, "XS9" }, - { 0x79, "XS10" }, - { 0x7a, "XS11" }, - { 0x7b, "XS12" }, - { 0x7c, "XS13" }, - { 0x7d, "XS14" }, - { 0x7e, "XS15" }, - { 0x7f, "XS16" }, - { 0x80, "PC1" }, - { 0x81, "PC2" }, - { 0x82, "PC3" }, - { 0x83, "PC4" }, - { 0x84, "PC5" }, - { 0x85, "GPC1", 1 }, - { 0x87, "CMDR2" }, - { 0x8d, "CCR5" }, - { 0x92, "GCM1", 1 }, - { 0x93, "GCM2", 1 }, - { 0x94, "GCM3", 1 }, - { 0x95, "GCM4", 1 }, - { 0x96, "GCM5", 1 }, - { 0x97, "GCM6", 1 }, - { 0x98, "GCM7", 1 }, - { 0x99, "GCM8", 1 }, - { 0xa0, "TSEO" }, - { 0xa1, "TSBS1" }, - { 0xa8, "TPC0" }, -}; - -static struct t4_reg_def t1_reginfo[] = { - { 0x00, "XFIFO" }, - { 0x01, "XFIFO" }, - { 0x02, "CMDR" }, - { 0x03, "MODE" }, - { 0x04, "RAH1" }, - { 0x05, "RAH2" }, - { 0x06, "RAL1" }, - { 0x07, "RAL2" }, - { 0x08, "IPC", 1 }, - { 0x09, "CCR1" }, - { 0x0a, "CCR2" }, - { 0x0c, "RTR1" }, - { 0x0d, "RTR2" }, - { 0x0e, "RTR3" }, - { 0x0f, "RTR4" }, - { 0x10, "TTR1" }, - { 0x11, "TTR2" }, - { 0x12, "TTR3" }, - { 0x13, "TTR4" }, - { 0x14, "IMR0" }, - { 0x15, "IMR1" }, - { 0x16, "IMR2" }, - { 0x17, "IMR3" }, - { 0x18, "IMR4" }, - { 0x1b, "IERR" }, - { 0x1c, "FMR0" }, - { 0x1d, "FMR1" }, - { 0x1e, "FMR2" }, - { 0x1f, "LOOP" }, - { 0x20, "FMR4" }, - { 0x21, "FMR5" }, - { 0x22, "XC0" }, - { 0x23, "XC1" }, - { 0x24, "RC0" }, - { 0x25, "RC1" }, - { 0x26, "XPM0" }, - { 0x27, "XPM1" }, - { 0x28, "XPM2" }, - { 0x2b, "IDLE" }, - { 0x2c, "XDL1" }, - { 0x2d, "XDL2" }, - { 0x2e, "XDL3" }, - { 0x2f, "CCB1" }, - { 0x30, "CCB2" }, - { 0x31, "CCB3" }, - { 0x32, "ICB1" }, - { 0x33, "ICB2" }, - { 0x34, "ICB3" }, - { 0x36, "LIM0" }, - { 0x37, "LIM1" }, - { 0x38, "PCD" }, - { 0x39, "PCR" }, - { 0x3a, "LIM2" }, - { 0x3b, "LCR1" }, - { 0x3c, "LCR2" }, - { 0x3d, "LCR3" }, - { 0x3e, "SIC1" }, - { 0x3f, "SIC2" }, - { 0x40, "SIC3" }, - { 0x44, "CMR1" }, - { 0x45, "CMR2" }, - { 0x46, "GCR" }, - { 0x47, "ESM" }, - { 0x60, "DEC" }, - { 0x70, "XS1" }, - { 0x71, "XS2" }, - { 0x72, "XS3" }, - { 0x73, "XS4" }, - { 0x74, "XS5" }, - { 0x75, "XS6" }, - { 0x76, "XS7" }, - { 0x77, "XS8" }, - { 0x78, "XS9" }, - { 0x79, "XS10" }, - { 0x7a, "XS11" }, - { 0x7b, "XS12" }, - { 0x80, "PC1" }, - { 0x81, "PC2" }, - { 0x82, "PC3" }, - { 0x83, "PC4" }, - { 0x84, "PC5" }, - { 0x85, "GPC1", 1 }, - { 0x87, "CMDR2" }, - { 0x8d, "CCR5" }, - { 0x92, "GCM1", 1 }, - { 0x93, "GCM2", 1 }, - { 0x94, "GCM3", 1 }, - { 0x95, "GCM4", 1 }, - { 0x96, "GCM5", 1 }, - { 0x97, "GCM6", 1 }, - { 0x98, "GCM7", 1 }, - { 0x99, "GCM8", 1 }, - { 0xa0, "TSEO" }, - { 0xa1, "TSBS1" }, - { 0xa8, "TPC0" }, -}; - -static struct t4_reg_def t1_sreginfo[] = { - { 0x00, "RFIFO" }, - { 0x01, "RFIFO" }, - { 0x49, "RBD" }, - { 0x4a, "VSTR", 1 }, - { 0x4b, "RES" }, - { 0x4c, "FRS0" }, - { 0x4d, "FRS1" }, - { 0x4e, "FRS2" }, - { 0x4f, "Old FRS1" }, - { 0x50, "FECL" }, - { 0x51, "FECH" }, - { 0x52, "CVCL" }, - { 0x53, "CVCH" }, - { 0x54, "CECL" }, - { 0x55, "CECH" }, - { 0x56, "EBCL" }, - { 0x57, "EBCH" }, - { 0x58, "BECL" }, - { 0x59, "BECH" }, - { 0x5a, "COEC" }, - { 0x5c, "RDL1" }, - { 0x5d, "RDL2" }, - { 0x5e, "RDL3" }, - { 0x62, "RSP1" }, - { 0x63, "RSP2" }, - { 0x64, "SIS" }, - { 0x65, "RSIS" }, - { 0x66, "RBCL" }, - { 0x67, "RBCH" }, - { 0x68, "ISR0" }, - { 0x69, "ISR1" }, - { 0x6a, "ISR2" }, - { 0x6b, "ISR3" }, - { 0x6c, "ISR4" }, - { 0x6e, "GIS" }, - { 0x6f, "CIS", 1 }, - { 0x70, "RS1" }, - { 0x71, "RS2" }, - { 0x72, "RS3" }, - { 0x73, "RS4" }, - { 0x74, "RS5" }, - { 0x75, "RS6" }, - { 0x76, "RS7" }, - { 0x77, "RS8" }, - { 0x78, "RS9" }, - { 0x79, "RS10" }, - { 0x7a, "RS11" }, - { 0x7b, "RS12" }, -}; - -static struct t4_reg_def sreginfo[] = { - { 0x00, "RFIFO" }, - { 0x01, "RFIFO" }, - { 0x49, "RBD" }, - { 0x4a, "VSTR", 1 }, - { 0x4b, "RES" }, - { 0x4c, "FRS0" }, - { 0x4d, "FRS1" }, - { 0x4e, "RSW" }, - { 0x4f, "RSP" }, - { 0x50, "FECL" }, - { 0x51, "FECH" }, - { 0x52, "CVCL" }, - { 0x53, "CVCH" }, - { 0x54, "CEC1L" }, - { 0x55, "CEC1H" }, - { 0x56, "EBCL" }, - { 0x57, "EBCH" }, - { 0x58, "CEC2L" }, - { 0x59, "CEC2H" }, - { 0x5a, "CEC3L" }, - { 0x5b, "CEC3H" }, - { 0x5c, "RSA4" }, - { 0x5d, "RSA5" }, - { 0x5e, "RSA6" }, - { 0x5f, "RSA7" }, - { 0x60, "RSA8" }, - { 0x61, "RSA6S" }, - { 0x62, "RSP1" }, - { 0x63, "RSP2" }, - { 0x64, "SIS" }, - { 0x65, "RSIS" }, - { 0x66, "RBCL" }, - { 0x67, "RBCH" }, - { 0x68, "ISR0" }, - { 0x69, "ISR1" }, - { 0x6a, "ISR2" }, - { 0x6b, "ISR3" }, - { 0x6c, "ISR4" }, - { 0x6e, "GIS" }, - { 0x6f, "CIS", 1 }, - { 0x70, "RS1" }, - { 0x71, "RS2" }, - { 0x72, "RS3" }, - { 0x73, "RS4" }, - { 0x74, "RS5" }, - { 0x75, "RS6" }, - { 0x76, "RS7" }, - { 0x77, "RS8" }, - { 0x78, "RS9" }, - { 0x79, "RS10" }, - { 0x7a, "RS11" }, - { 0x7b, "RS12" }, - { 0x7c, "RS13" }, - { 0x7d, "RS14" }, - { 0x7e, "RS15" }, - { 0x7f, "RS16" }, -}; - -static char *tobin(int x) -{ - static char s[9] = ""; - int y,z=0; - for (y=7;y>=0;y--) { - if (x & (1 << y)) - s[z++] = '1'; - else - s[z++] = '0'; - } - s[z] = '\0'; - return s; -} - -static char *tobin32(unsigned int x) -{ - static char s[33] = ""; - int y,z=0; - for (y=31;y>=0;y--) { - if (x & (1 << y)) - s[z++] = '1'; - else - s[z++] = '0'; - } - s[z] = '\0'; - return s; -} - -int main(int argc, char *argv[]) -{ - int fd; - int x; - char fn[256]; - struct t4_regs regs; - if ((argc < 2) || ((*(argv[1]) != '/') && !atoi(argv[1]))) { - fprintf(stderr, "Usage: wct4xxp-diag \n"); - exit(1); - } - if (*(argv[1]) == '/') - strncpy(fn, argv[1], sizeof(fn) - 1); - else - snprintf(fn, sizeof(fn), "/dev/zap/%d", atoi(argv[1])); - fd = open(fn, O_RDWR); - if (fd <0) { - fprintf(stderr, "Unable to open '%s': %s\n", fn, strerror(errno)); - exit(1); - } - if (ioctl(fd, WCT4_GET_REGS, ®s)) { - fprintf(stderr, "Unable to get registers: %s\n", strerror(errno)); - exit(1); - } - printf("PCI Registers:\n"); - for (x=0;x - * - * Copyright (C) 2001, Linux Support Services, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include - -#define FRMR_TTR_BASE 0x10 -#define FRMR_RTR_BASE 0x0c -#define FRMR_TSEO 0xa0 -#define FRMR_TSBS1 0xa1 -#define FRMR_CCR1 0x09 -#define FRMR_CCR1_ITF 0x08 -#define FRMR_CCR1_EITS 0x10 -#define FRMR_CCR2 0x0a -#define FRMR_CCR2_RCRC 0x04 -#define FRMR_CCR2_RADD 0x10 -#define FRMR_MODE 0x03 -#define FRMR_MODE_NO_ADDR_CMP 0x80 -#define FRMR_MODE_SS7 0x20 -#define FRMR_MODE_HRAC 0x08 -#define FRMR_IMR0 0x14 -#define FRMR_IMR0_RME 0x80 -#define FRMR_IMR0_RPF 0x01 -#define FRMR_IMR1 0x15 -#define FRMR_IMR1_ALLS 0x20 -#define FRMR_IMR1_XDU 0x10 -#define FRMR_IMR1_XPR 0x01 -#define FRMR_XC0 0x22 -#define FRMR_XC1 0x23 -#define FRMR_RC0 0x24 -#define FRMR_RC1 0x25 -#define FRMR_SIC1 0x3e -#define FRMR_SIC2 0x3f -#define FRMR_SIC3 0x40 -#define FRMR_CMR1 0x44 -#define FRMR_CMR2 0x45 -#define FRMR_GCR 0x46 -#define FRMR_ISR0 0x68 -#define FRMR_ISR0_RME 0x80 -#define FRMR_ISR0_RPF 0x01 -#define FRMR_ISR1 0x69 -#define FRMR_ISR1_ALLS 0x20 -#define FRMR_ISR1_XDU 0x10 -#define FRMR_ISR1_XPR 0x01 -#define FRMR_ISR2 0x6a -#define FRMR_ISR3 0x6b -#define FRMR_ISR4 0x6c -#define FRMR_GIS 0x6e -#define FRMR_GIS_ISR0 0x01 -#define FRMR_GIS_ISR1 0x02 -#define FRMR_GIS_ISR2 0x04 -#define FRMR_GIS_ISR3 0x08 -#define FRMR_GIS_ISR4 0x10 -#define FRMR_CIS 0x6f -#define FRMR_CIS_GIS1 0x01 -#define FRMR_CIS_GIS2 0x02 -#define FRMR_CIS_GIS3 0x04 -#define FRMR_CIS_GIS4 0x08 -#define FRMR_CMDR 0x02 -#define FRMR_CMDR_SRES 0x01 -#define FRMR_CMDR_XRES 0x10 -#define FRMR_CMDR_RMC 0x80 -#define FRMR_CMDR_XTF 0x04 -#define FRMR_CMDR_XHF 0x08 -#define FRMR_CMDR_XME 0x02 -#define FRMR_RSIS 0x65 -#define FRMR_RSIS_VFR 0x80 -#define FRMR_RSIS_RDO 0x40 -#define FRMR_RSIS_CRC16 0x20 -#define FRMR_RSIS_RAB 0x10 -#define FRMR_RBCL 0x66 -#define FRMR_RBCL_MAX_SIZE 0x1f -#define FRMR_RBCH 0x67 -#define FRMR_RXFIFO 0x00 -#define FRMR_SIS 0x64 -#define FRMR_SIS_XFW 0x40 -#define FRMR_TXFIFO 0x00 - -#define NUM_REGS 0xa9 -#define NUM_PCI 12 - -struct t4_regs { - unsigned int pci[NUM_PCI]; - unsigned char regs[NUM_REGS]; -}; - -#define T4_CHECK_VPM 0 - -#define WCT4_GET_REGS _IOW (ZT_CODE, 60, struct t4_regs) - diff --git a/wctc4xxp/Kbuild b/wctc4xxp/Kbuild deleted file mode 100644 index 3ffe8bf..0000000 --- a/wctc4xxp/Kbuild +++ /dev/null @@ -1,18 +0,0 @@ -obj-m += wctc4xxp.o - -EXTRA_CFLAGS := -I$(src)/.. -Wno-undef -DSTANDALONE_ZAPATA - -ifeq ($(HOTPLUG_FIRMWARE),yes) - EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE -endif - -wctc4xxp-objs := base.o - -ifneq ($(HOTPLUG_FIRMWARE),yes) -wctc4xxp-objs += ../firmware/zaptel-fw-tc400m.o -endif - -$(obj)/base.o: $(src)/../zaptel.h - -$(obj)/../firmware/zaptel-fw-tc400m.o: $(obj)/base.o - $(MAKE) -C $(obj)/../firmware zaptel-fw-tc400m.o diff --git a/wctc4xxp/Makefile b/wctc4xxp/Makefile deleted file mode 100644 index 725abc4..0000000 --- a/wctc4xxp/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -ifneq ($(KBUILD_EXTMOD),) -# We only get here on kernels 2.6.0-2.6.9 . -# For newer kernels, Kbuild will be included directly by the kernel -# build system. -include $(src)/Kbuild - -else - -tests: codec_test - -codec_test: codec_test.c ../zaptel.h - $(CC) -o $@ $< $(CFLAGS) - -clean: - rm -rf codec_test -endif diff --git a/wctc4xxp/base.c b/wctc4xxp/base.c deleted file mode 100644 index 3dcb1f4..0000000 --- a/wctc4xxp/base.c +++ /dev/null @@ -1,2027 +0,0 @@ -/* - * Wildcard TC400B Driver - * - * Written by John Sloan - * - * Copyright (C) 2006, Digium, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_DEVFS_FS -#include -#endif -#ifdef STANDALONE_ZAPATA -#include "zaptel.h" -#else -#include -#endif - -/* #define USE_TEST_HW */ -#define USE_TDM_CONFIG -#define QUIET_DSP - -#define WC_MAX_IFACES 128 - -#define NUM_CARDS 24 -#define NUM_EC 4 - -/* NUM_CHANNELS must be checked if new firmware (dte_firm.h) is used */ -#define NUM_CHANNELS 120 - -#define DTE_FORMAT_ULAW 0x00 -#define DTE_FORMAT_G723_1 0x04 -#define DTE_FORMAT_ALAW 0x08 -#define DTE_FORMAT_G729A 0x12 -#define DTE_FORMAT_UNDEF 0xFF - -#define G729_LENGTH 20 -#define G723_LENGTH 30 - -#define G729_SAMPLES 160 /* G.729 */ -#define G723_SAMPLES 240 /* G.723.1 */ - -#define G729_BYTES 20 /* G.729 */ -#define G723_6K_BYTES 24 /* G.723.1 at 6.3kb/s */ -#define G723_5K_BYTES 20 /* G.723.1 at 5.3kb/s */ -#define G723_SID_BYTES 4 /* G.723.1 SID frame */ - -#define ACK_SPACE 20 - -#define MAX_COMMANDS (NUM_CHANNELS + ACK_SPACE) -#define MAX_RCV_COMMANDS 16 - -/* 1432 for boot, 274 for 30msec ulaw, 194 for 20mec ulaw */ -#define BOOT_CMD_LEN 1500 -#define OTHER_CMD_LEN 300 - -#define MAX_COMMAND_LEN BOOT_CMD_LEN /* Must be the larger of BOOT_CMD_LEN or OTHER_CMD_LEN */ - -#define ERING_SIZE (NUM_CHANNELS / 2) /* Maximum ring size */ - -#define SFRAME_SIZE MAX_COMMAND_LEN - -#define PCI_WINDOW_SIZE ((2* 2 * ERING_SIZE * SFRAME_SIZE) + (2 * ERING_SIZE * 4)) - -#define MDIO_SHIFT_CLK 0x10000 -#define MDIO_DATA_WRITE0 0x00000 -#define MDIO_DATA_WRITE1 0x20000 -#define MDIO_ENB 0x00000 -#define MDIO_ENB_IN 0x40000 -#define MDIO_DATA_READ 0x80000 - -#define RCV_CSMENCAPS 1 -#define RCV_RTP 2 -#define RCV_CSMENCAPS_ACK 3 -#define RCV_OTHER 99 - - -/* TDM Commands */ -#define CMD_MSG_TDM_SELECT_BUS_MODE_LEN 30 -#define CMD_MSG_TDM_SELECT_BUS_MODE(s) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x01, 0x00,0x06,0x17,0x04, 0xFF,0xFF, \ - 0x04,0x00 } -#define CMD_MSG_TDM_ENABLE_BUS_LEN 30 -#define CMD_MSG_TDM_ENABLE_BUS(s) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x02, 0x00,0x06,0x05,0x04, 0xFF,0xFF, \ - 0x04,0x00 } -#define CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN 34 -#define CMD_MSG_SUPVSR_SETUP_TDM_PARMS(s,p1,p2,p3) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x10, p1, 0x00,0x06,0x07,0x04, 0xFF,0xFF, \ - p2,0x83, 0x00,0x0C, 0x00,0x00, p3,0x00 } -#define CMD_MSG_TDM_OPT_LEN 30 -#define CMD_MSG_TDM_OPT(s) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x35,0x04, 0xFF,0xFF, \ - 0x00,0x00 } -#define CMD_MSG_DEVICE_SET_COUNTRY_CODE_LEN 30 -#define CMD_MSG_DEVICE_SET_COUNTRY_CODE(s) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x1B,0x04, 0xFF,0xFF, \ - 0x00,0x00 } - -/* CPU Commands */ -#define CMD_MSG_SET_ARM_CLK_LEN 32 -#define CMD_MSG_SET_ARM_CLK(s) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0C, 0x00, 0x00,0x06,0x11,0x04, 0x00,0x00, \ - 0x2C,0x01, 0x00,0x00 } -#define CMD_MSG_SET_SPU_CLK_LEN 32 -#define CMD_MSG_SET_SPU_CLK(s) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0C, 0x00, 0x00,0x06,0x12,0x04, 0x00,0x00, \ - 0x2C,0x01, 0x00,0x00 } -#define CMD_MSG_SPU_FEATURES_CONTROL_LEN 30 -#define CMD_MSG_SPU_FEATURES_CONTROL(s,p1) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x13,0x00, 0xFF,0xFF, \ - p1,0x00 } -#define CMD_MSG_DEVICE_STATUS_CONFIG_LEN 30 -#define CMD_MSG_DEVICE_STATUS_CONFIG(s) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x0F,0x04, 0xFF,0xFF, \ - 0x05,0x00 } - -/* General IP/RTP Commands */ -#define CMD_MSG_SET_ETH_HEADER_LEN 44 -#define CMD_MSG_SET_ETH_HEADER(s) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x18, 0x00, 0x00,0x06,0x00,0x01, 0xFF,0xFF, \ - 0x01,0x00, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x00,0x11,0x22,0x33,0x44,0x55, 0x08,0x00 } -#define CMD_MSG_IP_SERVICE_CONFIG_LEN 30 -#define CMD_MSG_IP_SERVICE_CONFIG(s) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x02,0x03, 0xFF,0xFF, \ - 0x00,0x02 } -#define CMD_MSG_ARP_SERVICE_CONFIG_LEN 30 -#define CMD_MSG_ARP_SERVICE_CONFIG(s) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x05,0x01, 0xFF,0xFF, \ - 0x01,0x00 } -#define CMD_MSG_ICMP_SERVICE_CONFIG_LEN 30 -#define CMD_MSG_ICMP_SERVICE_CONFIG(s) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x04,0x03, 0xFF,0xFF, \ - 0x01,0xFF } -#define CMD_MSG_IP_OPTIONS_LEN 30 -#define CMD_MSG_IP_OPTIONS(s) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x06,0x03, 0xFF,0xFF, \ - 0x02,0x00 } - -/* Supervisor channel commands */ -#define CMD_MSG_CREATE_CHANNEL_LEN 32 -#define CMD_MSG_CREATE_CHANNEL(s,t) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0C, 0x00, 0x00,0x06,0x10,0x00, 0x00,0x00, \ - 0x02,0x00, (t&0x00FF), ((t&0xFF00) >> 8) } -#define CMD_MSG_QUERY_CHANNEL_LEN 30 -#define CMD_MSG_QUERY_CHANNEL(s,t) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x01,0x06,0x10,0x00, 0x00,0x00, \ - (t&0x00FF), ((t&0xFF00) >> 8) } -#define CMD_MSG_TRANS_CONNECT_LEN 38 -#define CMD_MSG_TRANS_CONNECT(s,e,c1,c2,f1,f2) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x12, 0x00, 0x00,0x06,0x22,0x93, 0x00,0x00, \ - e,0x00, (c1&0x00FF),((c1&0xFF00)>>8), f1,0x00, (c2&0x00FF),((c2&0xFF00)>>8), f2,0x00 } -#define CMD_MSG_DESTROY_CHANNEL_LEN 32 -#define CMD_MSG_DESTROY_CHANNEL(s,t) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x11,0x00, 0x00,0x00, \ - (t&0x00FF),((t&0xFF00)>>8), 0x00, 0x00 } - -/* Individual channel config commands */ -#define CMD_MSG_SET_IP_HDR_CHANNEL_LEN 58 -#define CMD_MSG_SET_IP_HDR_CHANNEL(s,c,t2,t1) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00) >> 8),(c&0x00FF), 0x26, 0x00, 0x00,0x02,0x00,0x90, 0x00,0x00, \ - 0x00,0x00, 0x45,0x00, 0x00,0x00, 0x00,0x00, 0x40,0x00, 0x80,0x11, 0x00,0x00, \ - 0xC0,0xA8,0x09,0x03, 0xC0,0xA8,0x09,0x03, \ - ((t2&0xFF00)>>8)+0x50,(t2&0x00FF), ((t1&0xFF00)>>8)+0x50,(t1&0x00FF), 0x00,0x00, 0x00,0x00 } -#define CMD_MSG_VOIP_VCEOPT_LEN 40 -#define CMD_MSG_VOIP_VCEOPT(s,c,l,w) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x12, 0x00, 0x00,0x02,0x01,0x80, 0x00,0x00, \ - 0x21,l, 0x00,0x1C, 0x04,0x00, 0x00,0x00, w,0x00, 0x80,0x11 } -#define CMD_MSG_VOIP_VOPENA_LEN 44 -#define CMD_MSG_VOIP_VOPENA(s,c,f) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x16, 0x00, 0x00,0x02,0x00,0x80, 0x00,0x00, \ - 0x01,0x00, 0x80,f, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x12,0x34, 0x56,0x78, 0x00,0x00 } -#define CMD_MSG_VOIP_VOPENA_CLOSE_LEN 32 -#define CMD_MSG_VOIP_VOPENA_CLOSE(s,c) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x00,0x80, 0x00,0x00, \ - 0x00,0x00, 0x00,0x00 } -#define CMD_MSG_VOIP_INDCTRL_LEN 32 -#define CMD_MSG_VOIP_INDCTRL(s,c) {0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x84,0x80, 0x00,0x00, \ - 0x07,0x00, 0x00,0x00 } -#define CMD_MSG_VOIP_DTMFOPT_LEN 32 -#define CMD_MSG_VOIP_DTMFOPT(s,c) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x02,0x80, 0x00,0x00, \ - 0x08,0x00, 0x00,0x00 } - -#define CMD_MSG_VOIP_TONECTL_LEN 32 -#define CMD_MSG_VOIP_TONECTL(s,c) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, ((c&0xFF00)>>8),(c&0x00FF), 0x0A, 0x00, 0x00,0x02,0x5B,0x80, 0x00,0x00, \ - 0x00,0x00, 0x00,0x00 } - -/* CPU ACK command */ -#define CMD_MSG_ACK_LEN 20 -#define CMD_MSG_ACK(s,c) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s, 0xE0, (c&0x00FF), ((c>>8)&0x00FF) } - -/* Wrapper for RTP packets */ -#define CMD_MSG_IP_UDP_RTP_LEN 54 -#define CMD_MSG_IP_UDP_RTP(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20,s) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x08,0x00, \ - 0x45,0x00, p1,p2, 0x00,p3, 0x40,0x00, 0x80,0x11, p4,p5, \ - 0xC0,0xA8,0x09,0x03, 0xC0,0xA8,0x09,0x03, p6,p7, p8,p9, p10,p11, p12,p13, \ - 0x80,p14, p15,p16, p17,p18,p19,p20, 0x12,0x34,0x56,(s&0xFF)} - -#define CMD_MSG_DW_WRITE_LEN 38 -#define CMD_MSG_DW_WRITE(s,a,d) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01,s&0x0F,0x00,0x00,0x00,0x00,0x00,0x04,0x17,0x00,0x00, \ - ((a>>24)&0x00FF),((a>>16)&0x00FF), ((a>>8)&0x00FF),(a&0x00FF), \ - ((d>>24)&0x00FF),((d>>16)&0x00FF), ((d>>8)&0x00FF),(d&0x00FF) } - -#define CMD_MSG_FORCE_ALERT_LEN 32 -#define CMD_MSG_FORCE_ALERT(s) { \ - 0x00,0x11,0x22,0x33,0x44,0x55, 0xAA,0xBB,0xCC,0xDD,0xEE,0xFF, 0x88,0x9B, \ - 0x00,0x01, s&0x0F, 0x01, 0xFF,0xFF, 0x0A, 0x00, 0x00,0x06,0x09,0x04, 0x00,0x00, \ - 0x24,0x00, 0x00,0x00 } - -#define zt_send_cmd(wc, command, length, hex) \ - ({ \ - int ret = 0; \ - do { \ - if (ret == 2) \ - { \ - wc->ztsnd_rtx++; \ - if (hex == 0x0010) \ - wc->ztsnd_0010_rtx++; \ - } \ - down(&wc->cmdqsem); \ - wc->last_command_sent = hex; \ - if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug ) \ - printk("wcdte error: cmdq is full.\n"); \ - else { \ - unsigned char fifo[OTHER_CMD_LEN] = command; \ - int i; \ - wc->cmdq[wc->cmdq_wndx].cmdlen = length; \ - for (i = 0; i < length; i++) \ - wc->cmdq[wc->cmdq_wndx].cmd[i] = fifo[i]; \ - wc->last_seqno = fifo[16]; \ - wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS; \ - } \ - __transmit_demand(wc); \ - up(&wc->cmdqsem); \ - if (hex == 0x0000) \ - ret = wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS_ACK, 2); \ - else { \ - ret = wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS, 0); \ - if (wc->dsp_crashed) \ - return 1; \ - } \ - if (ret == 1) \ - return(1); \ - } while (ret == 2); \ - }) - - -struct cmdq { - unsigned int cmdlen; - unsigned char cmd[MAX_COMMAND_LEN]; -}; - -struct wcdte { - struct pci_dev *dev; - char *variety; - unsigned int intcount; - unsigned int rxints; - unsigned int txints; - unsigned int intmask; - int pos; - int freeregion; - int rdbl; - int tdbl; - int cards; - spinlock_t reglock; - wait_queue_head_t regq; - int rcvflags; - - struct semaphore chansem; - struct semaphore cmdqsem; - struct cmdq cmdq[MAX_COMMANDS]; - unsigned int cmdq_wndx; - unsigned int cmdq_rndx; - - unsigned int last_seqno; - unsigned int last_rseqno; - unsigned int last_command_sent; - unsigned int last_rcommand; - unsigned int last_rparm1; - unsigned int seq_num; - long timeout; - - unsigned int dsp_crashed; - unsigned int dumping; - - unsigned int ztsnd_rtx; - unsigned int ztsnd_0010_rtx; - - unsigned char numchannels; - unsigned char complexname[40]; - - unsigned long iobase; - dma_addr_t readdma; - dma_addr_t writedma; - dma_addr_t descripdma; - volatile unsigned int *writechunk; /* Double-word aligned write memory */ - volatile unsigned int *readchunk; /* Double-word aligned read memory */ - volatile unsigned int *descripchunk; /* Descriptors */ - - int wqueints; - struct workqueue_struct *dte_wq; - struct work_struct dte_work; - - struct zt_transcoder *uencode; - struct zt_transcoder *udecode; -}; - -struct wcdte_desc { - char *name; - int flags; -}; - -static struct wcdte_desc wctc400p = { "Wildcard TC400P+TC400M", 0 }; -static struct wcdte_desc wctce400 = { "Wildcard TCE400+TC400M", 0 }; - -static struct wcdte *ifaces[WC_MAX_IFACES]; - - - -/* - * The following is the definition of the state structure - * used by the G.721/G.723 encoder and decoder to preserve their internal - * state between successive calls. The meanings of the majority - * of the state structure fields are explained in detail in the - * CCITT Recommendation G.721. The field names are essentially indentical - * to variable names in the bit level description of the coding algorithm - * included in this Recommendation. - */ -struct dte_state { - int encoder; /* If we're an encoder */ - struct wcdte *wc; - - unsigned int timestamp; - unsigned int seqno; - - unsigned int cmd_seqno; - - unsigned int timeslot_in_num; /* DTE chennel on which results we be received from */ - unsigned int timeslot_out_num; /* DTE channel to send data to */ - - unsigned int chan_in_num; /* DTE chennel on which results we be received from */ - unsigned int chan_out_num; /* DTE channel to send data to */ - - unsigned int packets_sent; - unsigned int packets_received; - - unsigned int last_dte_seqno; - unsigned int dte_seqno_rcv; - - unsigned char ssrc; -}; - - -static struct zt_transcoder *uencode; -static struct zt_transcoder *udecode; -static struct dte_state *encoders; -static struct dte_state *decoders; -static int debug = 0; -static int debug_des = 0; /* Set the number of descriptor packet bytes to output on errors, 0 disables output */ -static int debug_des_cnt = 0; /* Set the number of times descriptor packets are displayed before the output is disabled */ -static int force_alert = 0; -static int debug_notimeout = 0; -static char *mode; -static int debug_packets = 0; - -static int wcdte_create_channel(struct wcdte *wc, int simple, int complicated, int part1_id, int part2_id, unsigned int *dte_chan1, unsigned int *dte_chan2); -static int wcdte_destroy_channel(struct wcdte *wc, unsigned int chan1, unsigned int chan2); -static int __wcdte_setup_channels(struct wcdte *wc); - -static int __dump_descriptors(struct wcdte *wc) -{ - volatile unsigned char *writechunk, *readchunk; - int o2, i, j; - - if (debug_des_cnt == 0) - return 1; - - printk("Transmit Descriptors (wc->tdbl = %d)\n", wc->tdbl); - for (i = 0; i < ERING_SIZE; i++) - { - writechunk = (volatile unsigned char *)(wc->writechunk); - writechunk += i * SFRAME_SIZE; - o2 = i * 4; - - if (i == wc->tdbl) - printk("->"); - else - printk(" "); - if ((le32_to_cpu(wc->descripchunk[o2]) & 0x80000000)) - printk("AN983 owns : "); - else - printk("Driver owns: "); - - for (j = 0; j < debug_des; j++) - printk("%02X ", writechunk[j]); - printk("\n"); - } - - printk("Receive Descriptors (wc->rdbl = %d)\n", wc->rdbl); - for (i = 0; i < ERING_SIZE; i++) - { - readchunk = (volatile unsigned char *)wc->readchunk; - readchunk += i * SFRAME_SIZE; - o2 = i * 4; - o2 += ERING_SIZE * 4; - - if (i == wc->rdbl) - printk("->"); - else - printk(" "); - if ((le32_to_cpu(wc->descripchunk[o2]) & 0x80000000)) - printk("AN983 owns : "); - else - printk("Driver owns: "); - - for (j = 0; j < debug_des; j++) - printk("%02X ", readchunk[j]); - printk("\n"); - } - if (debug_des_cnt > 0) - debug_des_cnt--; - return 0; -} - -/* Sanity check values */ -static inline int zt_tc_sanitycheck(struct zt_transcode_header *zth, unsigned int outbytes) -{ - if (zth->dstoffset >= sizeof(zth->dstdata)) - return 0; - if (zth->dstlen >= sizeof(zth->dstdata)) - return 0; - if (outbytes >= sizeof(zth->dstdata)) - return 0; - if ((zth->dstoffset + zth->dstlen + outbytes) >= sizeof(zth->dstdata)) - return 0; - if (zth->srcoffset >= sizeof(zth->srcdata)) - return 0; - if (zth->srclen >= sizeof(zth->srcdata)) - return 0; - if ((zth->srcoffset + zth->srclen) > sizeof(zth->srcdata)) - return 0; - return 1; -} - -static void dte_init_state(struct dte_state *state_ptr, int encoder, unsigned int channel, struct wcdte *wc) -{ - state_ptr->encoder = encoder; - state_ptr->wc = wc; - state_ptr->timestamp = 0; - state_ptr->seqno = 0; - - state_ptr->cmd_seqno = 0; - - state_ptr->packets_sent = 0; - state_ptr->packets_received = 0; - state_ptr->last_dte_seqno = 0; - state_ptr->dte_seqno_rcv = 0; - - state_ptr->chan_in_num = 999; - state_ptr->chan_out_num = 999; - - state_ptr->ssrc = 0x78; - - if (encoder == 1) - { - state_ptr->timeslot_in_num = channel * 2; - state_ptr->timeslot_out_num = channel * 2 + 1; - } else { - state_ptr->timeslot_in_num = channel * 2 + 1; - state_ptr->timeslot_out_num = channel * 2; - } -} - -static unsigned int wcdte_zapfmt_to_dtefmt(unsigned int fmt) -{ - unsigned int pt; - - switch(fmt) - { - case ZT_FORMAT_G723_1: - pt = DTE_FORMAT_G723_1; - break; - case ZT_FORMAT_ULAW: - pt = DTE_FORMAT_ULAW; - break; - case ZT_FORMAT_ALAW: - pt = DTE_FORMAT_ALAW; - break; - case ZT_FORMAT_G729A: - pt = DTE_FORMAT_G729A; - break; - default: - pt = DTE_FORMAT_UNDEF; - } - - return(pt); -} - -static inline void __wcdte_setctl(struct wcdte *wc, unsigned int addr, unsigned int val) -{ - outl(val, wc->iobase + addr); -} - -static inline unsigned int __wcdte_getctl(struct wcdte *wc, unsigned int addr) -{ - return inl(wc->iobase + addr); -} - -static inline void wcdte_setctl(struct wcdte *wc, unsigned int addr, unsigned int val) -{ - unsigned long flags; - spin_lock_irqsave(&wc->reglock, flags); - __wcdte_setctl(wc, addr, val); - spin_unlock_irqrestore(&wc->reglock, flags); -} - -static inline void wcdte_reinit_descriptor(struct wcdte *wc, int tx, int dbl, char *s) -{ - int o2 = 0; - o2 += dbl * 4; - - if (!tx) - o2 += ERING_SIZE * 4; - wc->descripchunk[o2] = cpu_to_le32(0x80000000); - - wcdte_setctl(wc, 0x0008, 0x00000000); -} - -static inline unsigned int wcdte_getctl(struct wcdte *wc, unsigned int addr) -{ - unsigned long flags; - unsigned int val; - spin_lock_irqsave(&wc->reglock, flags); - val = __wcdte_getctl(wc, addr); - spin_unlock_irqrestore(&wc->reglock, flags); - return val; -} - -static inline int __transmit_demand(struct wcdte *wc) -{ - volatile unsigned char *writechunk; - int o2,i,j; - unsigned int reg, xmt_length; - - reg = wcdte_getctl(wc, 0x0028) & 0x00700000; - - /* Already transmiting, no need to demand another */ - if (!((reg == 0) || (reg = 6))) - return(1); - - /* Nothing to transmit */ - if (wc->cmdq_rndx == wc->cmdq_wndx) - return(1); - - /* Nothing to transmit */ - if (wc->cmdq[wc->cmdq_rndx].cmdlen == 0 ) - return(1); - - writechunk = (volatile unsigned char *)(wc->writechunk); - - writechunk += wc->tdbl * SFRAME_SIZE; - - o2 = wc->tdbl * 4; - - do - { - } while ((le32_to_cpu(wc->descripchunk[o2]) & 0x80000000)); - - xmt_length = wc->cmdq[wc->cmdq_rndx].cmdlen; - if (xmt_length < 64) - xmt_length = 64; - - wc->descripchunk[o2+1] = cpu_to_le32((le32_to_cpu(wc->descripchunk[o2+1]) & 0xFBFFF800) | xmt_length); - - for(i = 0; i < wc->cmdq[wc->cmdq_rndx].cmdlen; i++) - writechunk[i] = wc->cmdq[wc->cmdq_rndx].cmd[i]; - for (j = i; j < xmt_length; j++) - writechunk[j] = 0; - - if (debug_packets && (writechunk[12] == 0x88) && (writechunk[13] == 0x9B)) - { - printk("wcdte debug: TX: "); - for (i=0; icmdq[wc->cmdq_rndx].cmdlen = 0; - - wc->descripchunk[o2] = cpu_to_le32(0x80000000); - wcdte_setctl(wc, 0x0008, 0x00000000); /* Transmit Poll Demand */ - - wc->tdbl = (wc->tdbl + 1) % ERING_SIZE; - - wc->cmdq_rndx = (wc->cmdq_rndx + 1) % MAX_COMMANDS; - - return(0); -} - -static inline int transmit_demand(struct wcdte *wc) -{ - int val; - down(&wc->cmdqsem); - val = __transmit_demand(wc); - up(&wc->cmdqsem); - return val; -} - -static int dte_operation(struct zt_transcoder_channel *ztc, int op) -{ - struct zt_transcoder_channel *compl_ztc; - struct dte_state *st = ztc->pvt, *compl_st; - struct zt_transcode_header *zth = ztc->tch; - struct wcdte *wc = st->wc; - unsigned char *chars; - unsigned int inbytes = 0; - unsigned int timestamp_inc = 0; - int i = 0; - int res = 0; - unsigned int ipchksum, ndx; - switch(op) { - case ZT_TCOP_ALLOCATE: - down(&wc->chansem); - if (ztc->chan_built == 0) - { - if (st->encoder == 1) - wcdte_create_channel(wc, wcdte_zapfmt_to_dtefmt(zth->srcfmt), wcdte_zapfmt_to_dtefmt(zth->dstfmt), - st->timeslot_in_num, st->timeslot_out_num, &(st->chan_in_num), &(st->chan_out_num)); - else - wcdte_create_channel(wc, wcdte_zapfmt_to_dtefmt(zth->dstfmt), wcdte_zapfmt_to_dtefmt(zth->srcfmt), - st->timeslot_out_num, st->timeslot_in_num, &(st->chan_out_num), &(st->chan_in_num)); - /* Mark this channel as built */ - ztc->chan_built = 1; - ztc->built_fmts = zth->dstfmt | zth->srcfmt; - - /* Mark the channel complement (other half of encoder/decoder pair) as built */ - ndx = st->timeslot_in_num/2; - if (st->encoder == 1) - compl_ztc = &(wc->udecode->channels[ndx]); - else - compl_ztc = &(wc->uencode->channels[ndx]); - compl_ztc->chan_built = 1; - compl_ztc->built_fmts = zth->dstfmt | zth->srcfmt; - compl_st = compl_ztc->pvt; - compl_st->chan_in_num = st->chan_out_num; - compl_st->chan_out_num = st->chan_in_num; - } - up(&wc->chansem); - break; - case ZT_TCOP_RELEASE: - down(&wc->chansem); - ndx = st->timeslot_in_num/2; - - if (st->encoder == 1) - compl_ztc = &(wc->udecode->channels[ndx]); - else - compl_ztc = &(wc->uencode->channels[ndx]); - - /* If the channel complement (other half of the encoder/decoder pair) is not being used... */ - if ((compl_ztc->flags & ZT_TC_FLAG_BUSY) == 0) - { - if (st->encoder == 1) - wcdte_destroy_channel(wc, st->chan_in_num, st->chan_out_num); - else - wcdte_destroy_channel(wc, st->chan_out_num, st->chan_in_num); - - /* Mark this channel as not built */ - ztc->chan_built = 0; - ztc->built_fmts = 0; - st->chan_in_num = 999; - st->chan_out_num = 999; - - /* Mark the channel complement as not built */ - compl_ztc->chan_built = 0; - compl_ztc->built_fmts = 0; - compl_st = compl_ztc->pvt; - compl_st->chan_in_num = 999; - compl_st->chan_out_num = 999; - } - st->dte_seqno_rcv = 0; - up(&wc->chansem); - break; - case ZT_TCOP_TRANSCODE: - if ( (((zth->srcfmt == ZT_FORMAT_ULAW) || (zth->srcfmt == ZT_FORMAT_ALAW)) && ((zth->dstfmt == ZT_FORMAT_G729A && zth->srclen >= G729_SAMPLES) ||(zth->dstfmt == ZT_FORMAT_G723_1 && zth->srclen >= G723_SAMPLES)) ) - || ((zth->srcfmt == ZT_FORMAT_G729A) && (zth->srclen >= G729_BYTES)) - || ((zth->srcfmt == ZT_FORMAT_G723_1) && (zth->srclen >= G723_SID_BYTES)) ) - { - do - { - chars = (unsigned char *)(zth->srcdata + zth->srcoffset); - - if ((zth->srcfmt == ZT_FORMAT_ULAW) || (zth->srcfmt == ZT_FORMAT_ALAW)) { - if (zth->dstfmt == ZT_FORMAT_G729A) { - inbytes = G729_SAMPLES; - timestamp_inc = G729_SAMPLES; - } else if (zth->dstfmt == ZT_FORMAT_G723_1) { - inbytes = G723_SAMPLES; - timestamp_inc = G723_SAMPLES; - } - } else if (zth->srcfmt == ZT_FORMAT_G729A) { - inbytes = G729_BYTES; - timestamp_inc = G729_SAMPLES; - } else if (zth->srcfmt == ZT_FORMAT_G723_1) { - /* determine the size of the frame */ - switch (chars[0] & 0x03) { - case 0x00: - inbytes = G723_6K_BYTES; - break; - case 0x01: - inbytes = G723_5K_BYTES; - break; - case 0x02: - inbytes = G723_SID_BYTES; - break; - case 0x03: - /* this is a 'reserved' value in the G.723.1 - spec and should never occur in real media streams */ - inbytes = G723_SID_BYTES; - break; - } - timestamp_inc = G723_SAMPLES; - } - - zth->srclen -= inbytes; - - { - unsigned char fifo[OTHER_CMD_LEN] = CMD_MSG_IP_UDP_RTP( - ((inbytes+40) >> 8) & 0xFF, - (inbytes+40) & 0xFF, - st->seqno & 0xFF, - 0x00, - 0x00, - (((st->timeslot_out_num) >> 8)+0x50) & 0xFF, - (st->timeslot_out_num) & 0xFF, - (((st->timeslot_in_num) >> 8)+0x50) & 0xFF, - (st->timeslot_in_num) & 0xFF, - ((inbytes+20) >> 8) & 0xFF, - (inbytes+20) & 0xFF, - 0x00, - 0x00, - wcdte_zapfmt_to_dtefmt(zth->srcfmt), - ((st->seqno) >> 8) & 0xFF, - (st->seqno) & 0xFF, - ((st->timestamp) >> 24) & 0xFF, - ((st->timestamp) >> 16) & 0xFF, - ((st->timestamp) >> 8) & 0xFF, - (st->timestamp) & 0xFF, - (st->ssrc) & 0xFF); - - ipchksum = 0x9869 + (fifo[16] << 8) + fifo[17] - + (fifo[18] << 8) + fifo[19]; - while (ipchksum >> 16) - ipchksum = (ipchksum & 0xFFFF) + (ipchksum >> 16); - ipchksum = (~ipchksum) & 0xFFFF; - - fifo[24] = ipchksum >> 8; - fifo[25] = ipchksum & 0xFF; - - st->seqno += 1; - st->timestamp += timestamp_inc; - - for (i = 0; i < inbytes; i++) - fifo[i+CMD_MSG_IP_UDP_RTP_LEN]= chars[i]; - - down(&wc->cmdqsem); - - if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug ) - printk("wcdte error: cmdq is full.\n"); - else - { - wc->cmdq[wc->cmdq_wndx].cmdlen = CMD_MSG_IP_UDP_RTP_LEN+inbytes; - for (i = 0; i < CMD_MSG_IP_UDP_RTP_LEN+inbytes; i++) - wc->cmdq[wc->cmdq_wndx].cmd[i] = fifo[i]; - wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS; - } - - __transmit_demand(wc); - up(&wc->cmdqsem); - } - st->packets_sent++; - - - - zth->srcoffset += inbytes; - - - } while ((((zth->srcfmt == ZT_FORMAT_ULAW) || (zth->srcfmt == ZT_FORMAT_ALAW)) && ((zth->dstfmt == ZT_FORMAT_G729A && zth->srclen >= G729_SAMPLES) ||(zth->dstfmt == ZT_FORMAT_G723_1 && zth->srclen >= G723_SAMPLES)) ) - || ((zth->srcfmt == ZT_FORMAT_G729A) && (zth->srclen >= G729_BYTES)) - || ((zth->srcfmt == ZT_FORMAT_G723_1) && (zth->srclen >= G723_SID_BYTES)) ); - - } else { - zt_transcoder_alert(ztc); - } - - res = 0; - break; - } - return res; -} - -static void wcdte_stop_dma(struct wcdte *wc); - -static inline void wcdte_receiveprep(struct wcdte *wc, int dbl) -{ - volatile unsigned char *readchunk; - struct zt_transcoder_channel *ztc = NULL; - struct zt_transcode_header *zth = NULL; - struct dte_state *st = NULL; - int o2,i; - unsigned char rseq, rcodec; - unsigned int rcommand, rchannel, rlen, rtp_rseq, rtp_eseq; - unsigned char *chars = NULL; - unsigned int ztc_ndx; - - readchunk = (volatile unsigned char *)wc->readchunk; - readchunk += dbl * SFRAME_SIZE; - - o2 = dbl * 4; - o2 += ERING_SIZE * 4; - - /* Control in packet */ - if ((readchunk[12] == 0x88) && (readchunk[13] == 0x9B)) - { - if (debug_packets) - { - printk("wcdte debug: RX: "); - for (i=0; icmdqsem); - if ((readchunk[17] & 0x40) == 0) { - if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug ) - printk("wcdte error: cmdq is full (rndx = %d, wndx = %d).\n", wc->cmdq_rndx, wc->cmdq_wndx); - else - { - unsigned char fifo[OTHER_CMD_LEN] = CMD_MSG_ACK(rseq++, rchannel); - - wc->cmdq[wc->cmdq_wndx].cmdlen = CMD_MSG_ACK_LEN; - for (i = 0; i < wc->cmdq[wc->cmdq_wndx].cmdlen; i++) - wc->cmdq[wc->cmdq_wndx].cmd[i] = fifo[i]; - wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS; - } - - __transmit_demand(wc); - } - - wc->rcvflags = RCV_CSMENCAPS; - if (rcommand == wc->last_command_sent) { - wc->last_rcommand = rcommand; - wc->last_rparm1 = readchunk[28] | (readchunk[29] << 8); - wake_up(&wc->regq); - } else { - if (debug) - printk("wcdte error: unexpected command response received (sent: %04X, received: %04X)\n", wc->last_command_sent, rcommand); - } - up(&wc->cmdqsem); - } - else - { - wc->last_rseqno = readchunk[16]; - wc->rcvflags = RCV_CSMENCAPS_ACK; - if (!wc->dumping) - wake_up_interruptible(&wc->regq); - else - wake_up(&wc->regq); - } - - if ((readchunk[22] == 0x75) && (readchunk[23] = 0xC1)) - { - if (debug) - printk("wcdte error: received alert (0x%02X%02X) from dsp\n", readchunk[29], readchunk[28]); - if (debug_des) { - down(&wc->cmdqsem); - __dump_descriptors(wc); - up(&wc->cmdqsem); - } - } - - if (wc->dumping && (readchunk[22] == 0x04) && (readchunk[23] = 0x14)) { - for (i = 27; i < 227; i++) - printk("%02X ", readchunk[i]); - printk("\n"); - } - } - - /* IP/UDP in packet */ - else if ((readchunk[12] == 0x08) && (readchunk[13] == 0x00) - && (readchunk[50] == 0x12) && (readchunk[51] == 0x34) && (readchunk[52] = 0x56) && (readchunk[53] == 0x78)) - { - rchannel = (readchunk[37] | (readchunk[36] << 8)) - 0x5000; - rlen = (readchunk[39] | (readchunk[38] << 8)) - 20; - rtp_rseq = (readchunk[45] | (readchunk[44] << 8)); - rcodec = readchunk[43]; - - ztc_ndx = rchannel/2; - - if (ztc_ndx >= wc->numchannels) - { - if (debug) - printk("wcdte error: Invalid channel number received (ztc_ndx = %d) (numchannels = %d)\n", ztc_ndx, wc->numchannels); - rcodec = DTE_FORMAT_UNDEF; - } - - if ((rcodec == 0x00) || (rcodec == 0x08)) /* ulaw or alaw (decoders) */ - { - ztc = &(wc->udecode->channels[ztc_ndx]); - zth = ztc->tch; - st = ztc->pvt; - - if (zth == NULL) - { - if (debug) - printk("wcdte error: Tried to put DTE data into a freed zth header! (ztc_ndx = %d, ztc->chan_built = %d)\n", ztc_ndx, ztc->chan_built); - if (debug_des) { - down(&wc->cmdqsem); - __dump_descriptors(wc); - up(&wc->cmdqsem); - } - rcodec = DTE_FORMAT_UNDEF; - } else { - chars = (unsigned char *)(zth->dstdata + zth->dstoffset + zth->dstlen); - st->packets_received++; - } - - } - - if ((rcodec == 0x04) || (rcodec == 0x12)) /* g.723 or g.729 (encoders) */ - { - ztc = &(wc->uencode->channels[ztc_ndx]); - zth = ztc->tch; - st = ztc->pvt; - - if (zth == NULL) - { - if (debug) - printk("wcdte error: Tried to put DTE data into a freed zth header! (ztc_ndx = %d, ztc->chan_built = %d)\n", ztc_ndx, ztc->chan_built); - if (debug_des) { - down(&wc->cmdqsem); - __dump_descriptors(wc); - up(&wc->cmdqsem); - } - rcodec = DTE_FORMAT_UNDEF; - } else { - chars = (unsigned char *)(zth->dstdata + zth->dstoffset + zth->dstlen); - st->packets_received++; - } - - } - - if (st->dte_seqno_rcv == 0) - { - st->dte_seqno_rcv = 1; - st->last_dte_seqno = rtp_rseq; - } else { - rtp_eseq = (st->last_dte_seqno + 1) & 0xFFFF; - if ( (rtp_rseq != rtp_eseq) && debug ) - printk("wcdte error: Bad seqno from DTE! [%04X][%d][%d][%d]\n", (readchunk[37] | (readchunk[36] << 8)), rchannel, rtp_rseq, st->last_dte_seqno); - - st->last_dte_seqno = rtp_rseq; - } - - if (rcodec == 0x00) /* ulaw */ - { - if (zt_tc_sanitycheck(zth, rlen) && ((zth->srcfmt == ZT_FORMAT_G729A && rlen == G729_SAMPLES) || (zth->srcfmt == ZT_FORMAT_G723_1 && rlen == G723_SAMPLES))) { - for (i = 0; i < rlen; i++) - chars[i] = readchunk[i+54]; - - zth->dstlen += rlen; - zth->dstsamples = zth->dstlen; - - } else { - ztc->errorstatus = -EOVERFLOW; - } - zt_transcoder_alert(ztc); - } - else if (rcodec == 0x08) /* alaw */ - { - if (zt_tc_sanitycheck(zth, rlen) && ((zth->srcfmt == ZT_FORMAT_G729A && rlen == G729_SAMPLES) || (zth->srcfmt == ZT_FORMAT_G723_1 && rlen == G723_SAMPLES))) { - - for (i = 0; i < rlen; i++) - chars[i] = readchunk[i+54]; - - zth->dstlen += rlen; - zth->dstsamples = zth->dstlen; - - } else { - ztc->errorstatus = -EOVERFLOW; - } - zt_transcoder_alert(ztc); - } - else if (rcodec == 0x04) /* G.723.1 */ - { - if (zt_tc_sanitycheck(zth, rlen) && - ((rlen == G723_6K_BYTES) || (rlen == G723_5K_BYTES) || (rlen == G723_SID_BYTES))) - { - for (i = 0; i < rlen; i++) - chars[i] = readchunk[i+54]; - - zth->dstlen += rlen; - zth->dstsamples += G723_SAMPLES; - - } else { - ztc->errorstatus = -EOVERFLOW; - } - - if (!(zth->dstsamples % G723_SAMPLES)) - { - zt_transcoder_alert(ztc); - } - } - else if (rcodec == 0x12) /* G.729a */ - { - if (zt_tc_sanitycheck(zth, rlen) && (rlen == G729_BYTES)) - { - for (i = 0; i < rlen; i++) - chars[i] = readchunk[i+54]; - - zth->dstlen += rlen; - zth->dstsamples = zth->dstlen * 8; - - } else { - ztc->errorstatus = -EOVERFLOW; - } - - if (!(zth->dstsamples % G729_SAMPLES)) - { - zt_transcoder_alert(ztc); - } - } - } -} - - - - - -/* static inline int wcdte_check_descriptor(struct wcdte *wc) */ -static int wcdte_check_descriptor(struct wcdte *wc) -{ - int o2 = 0; - - o2 += ERING_SIZE * 4; - o2 += wc->rdbl * 4; - - if (!(le32_to_cpu(wc->descripchunk[o2]) & 0x80000000)) { - wc->rxints++; - wcdte_receiveprep(wc, wc->rdbl); - wcdte_reinit_descriptor(wc, 0, wc->rdbl, "rxchk"); - wc->rdbl = (wc->rdbl + 1) % ERING_SIZE; - - return 1; - } - return 0; -} - -static void wcdte_init_descriptors(struct wcdte *wc) -{ - volatile unsigned int *descrip; - dma_addr_t descripdma; - dma_addr_t writedma; - dma_addr_t readdma; - int x; - - descrip = wc->descripchunk; - descripdma = wc->descripdma; - writedma = wc->writedma; - readdma = wc->readdma; - - for (x=0;xdescripdma; - - /* Transmit descriptor */ - descrip[0 ] = cpu_to_le32(0x00000000); - descrip[1 ] = cpu_to_le32(0xe5800000 | (SFRAME_SIZE)); - descrip[2 ] = cpu_to_le32(writedma + x*SFRAME_SIZE); - descrip[3 ] = cpu_to_le32(descripdma); - - /* Receive descriptor */ - descrip[0 + ERING_SIZE * 4] = cpu_to_le32(0x80000000); - descrip[1 + ERING_SIZE * 4] = cpu_to_le32(0x01000000 | (SFRAME_SIZE)); - descrip[2 + ERING_SIZE * 4] = cpu_to_le32(readdma + x*SFRAME_SIZE); - descrip[3 + ERING_SIZE * 4] = cpu_to_le32(descripdma + ERING_SIZE * 16); - - /* Advance descriptor */ - descrip += 4; - } -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) -static void dte_wque_run(struct work_struct *work) -{ - struct wcdte *wc = container_of(work, struct wcdte, dte_work); -#else -static void dte_wque_run(void *work_data) -{ - struct wcdte *wc = work_data; -#endif - int res; - - do { - res = wcdte_check_descriptor(wc); - } while(res); - - transmit_demand(wc); -} - -ZAP_IRQ_HANDLER(wcdte_interrupt) -{ - struct wcdte *wc = dev_id; - unsigned int ints; - - /* Read and clear interrupts */ - ints = wcdte_getctl(wc, 0x0028); - wcdte_setctl(wc, 0x0028, ints); - - if (!ints) - return IRQ_NONE; - ints &= wc->intmask; - - if (ints & 0x00000041) { - wc->wqueints = ints; - queue_work(wc->dte_wq, &wc->dte_work); - } - - if ((ints & 0x00008000) && debug) - printk("wcdte: Abnormal Interrupt: "); - - if ((ints & 0x00002000) && debug) - printk("wcdte: Fatal Bus Error INT\n"); - - if ((ints & 0x00000100) && debug) - printk("wcdte: Receive Stopped INT\n"); - - if ((ints & 0x00000080) && debug) - printk("wcdte: Receive Desciptor Unavailable INT\n"); - - if ((ints & 0x00000020) && debug) - printk("wcdte: Transmit Under-flow INT\n"); - - if ((ints & 0x00000008) && debug) - printk("wcdte: Jabber Timer Time-out INT\n"); - - if ((ints & 0x00000004) && debug) - printk("wcdte: Transmit Descriptor Unavailable INT\n"); - - if ((ints & 0x00000002) && debug) - printk("wcdte: Transmit Processor Stopped INT\n"); - - return IRQ_RETVAL(1); - -} - -static int wcdte_hardware_init(struct wcdte *wc) -{ - /* Hardware stuff */ - unsigned int reg; - unsigned long newjiffies; - - /* Initialize descriptors */ - wcdte_init_descriptors(wc); - - /* Enable I/O Access */ - pci_read_config_dword(wc->dev, 0x0004, ®); - reg |= 0x00000007; - pci_write_config_dword(wc->dev, 0x0004, reg); - - wcdte_setctl(wc, 0x0000, 0xFFF88001); - - newjiffies = jiffies + HZ/10; - while(((reg = wcdte_getctl(wc,0x0000)) & 0x00000001) && (newjiffies > jiffies)); - - wcdte_setctl(wc, 0x0000, 0xFFFA0000); - - /* Configure watchdogs, access, etc */ - wcdte_setctl(wc, 0x0030, 0x00280048); - wcdte_setctl(wc, 0x0078, 0x00000013 /* | (1 << 28) */); - - reg = wcdte_getctl(wc, 0x00fc); - wcdte_setctl(wc, 0x00fc, (reg & ~0x7) | 0x7); - - reg = wcdte_getctl(wc, 0x00fc); - - return 0; -} - -static void wcdte_setintmask(struct wcdte *wc, unsigned int intmask) -{ - wc->intmask = intmask; - wcdte_setctl(wc, 0x0038, intmask); -} - -static void wcdte_enable_interrupts(struct wcdte *wc) -{ - /* Enable interrupts */ - if (!debug) - wcdte_setintmask(wc, 0x00010041); - else - wcdte_setintmask(wc, 0x0001A1EB); -} - -static void wcdte_start_dma(struct wcdte *wc) -{ - unsigned int reg; - wmb(); - wcdte_setctl(wc, 0x0020, wc->descripdma); - wcdte_setctl(wc, 0x0018, wc->descripdma + (16 * ERING_SIZE)); - /* Start receiver/transmitter */ - reg = wcdte_getctl(wc, 0x0030); - wcdte_setctl(wc, 0x0030, reg | 0x00002002); /* Start XMT and RCD */ - wcdte_setctl(wc, 0x0010, 0x00000000); /* Receive Poll Demand */ - reg = wcdte_getctl(wc, 0x0028); - wcdte_setctl(wc, 0x0028, reg); - -} - -static void wcdte_stop_dma(struct wcdte *wc) -{ - /* Disable interrupts and reset */ - unsigned int reg; - /* Disable interrupts */ - wcdte_setintmask(wc, 0x00000000); - wcdte_setctl(wc, 0x0084, 0x00000000); - wcdte_setctl(wc, 0x0048, 0x00000000); - /* Reset the part to be on the safe side */ - reg = wcdte_getctl(wc, 0x0000); - reg |= 0x00000001; - wcdte_setctl(wc, 0x0000, reg); -} - -static void wcdte_disable_interrupts(struct wcdte *wc) -{ - /* Disable interrupts */ - wcdte_setintmask(wc, 0x00000000); - wcdte_setctl(wc, 0x0084, 0x00000000); -} - -static int wcdte_waitfor_csmencaps(struct wcdte *wc, unsigned int mask, int wait_mode) -{ - int ret; - - - if (wait_mode == 1) - ret = wait_event_interruptible_timeout(wc->regq, (wc->rcvflags == mask), wc->timeout); - else if (wait_mode == 2) - ret = wait_event_timeout(wc->regq, (wc->rcvflags == mask), wc->timeout); - else { - if (!debug_notimeout) { - ret = wait_event_timeout(wc->regq, ((wc->last_rcommand == wc->last_command_sent) && (wc->last_seqno == wc->last_rseqno) && (wc->rcvflags == mask)), wc->timeout); - } - else { - ret = wait_event_interruptible(wc->regq, ((wc->last_rcommand == wc->last_command_sent) && (wc->last_seqno == wc->last_rseqno) && (wc->rcvflags == mask))); - if (ret == 0) - ret = 1; - } - } - wc->rcvflags = 0; - wc->last_rcommand = 0; - wc->last_seqno = 0; - - if (ret < 0) - { - if (debug) - printk("wcdte error: Wait interrupted, need to stop boot (ret = %d)\n", ret); - return(1); - } - if (ret == 0) - { - if (debug) - printk("wcdte error: Waitfor CSMENCAPS response timed out (ret = %d) (cmd_snt = %04X)\n", ret, wc->last_command_sent); - if (debug_des) { - down(&wc->cmdqsem); - __dump_descriptors(wc); - up(&wc->cmdqsem); - } - return(2); - } - if (wait_mode == 0) - wc->last_command_sent = 999; - wc->last_rseqno = 999; - return(0); -} - - -static int wcdte_read_phy(struct wcdte *wc, int location) -{ - int i; - long mdio_addr = 0x0048; - int read_cmd = (0xf6 << 10) | (1 << 5) | location; - int retval = 0; - - /* Establish sync by sending at least 32 logic ones. */ - for (i = 32; i >= 0; i--) { - wcdte_setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1); - wcdte_getctl(wc, mdio_addr); - wcdte_setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK); - wcdte_getctl(wc, mdio_addr); - } - /* Shift the read command bits out. */ - for (i = 17; i >= 0; i--) { - int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; - - wcdte_setctl(wc, mdio_addr, MDIO_ENB | dataval); - wcdte_getctl(wc, mdio_addr); - wcdte_setctl(wc, mdio_addr, MDIO_ENB | dataval | MDIO_SHIFT_CLK); - wcdte_getctl(wc, mdio_addr); - } - - /* Read the two transition, 16 data, and wire-idle bits. */ - for (i = 19; i > 0; i--) { - wcdte_setctl(wc, mdio_addr, MDIO_ENB_IN); - wcdte_getctl(wc, mdio_addr); - retval = (retval << 1) | ((wcdte_getctl(wc, mdio_addr) & MDIO_DATA_READ) ? 1 : 0); - wcdte_setctl(wc, mdio_addr, MDIO_ENB_IN | MDIO_SHIFT_CLK); - wcdte_getctl(wc, mdio_addr); - } - retval = (retval>>1) & 0xffff; - return retval; -} - -void wcdte_write_phy(struct wcdte *wc, int location, int value) -{ - int i; - int cmd = (0x5002 << 16) | (1 << 23) | (location<<18) | value; - long mdio_addr = 0x0048; - - /* Establish sync by sending 32 logic ones. */ - for (i = 32; i >= 0; i--) { - wcdte_setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1); - wcdte_getctl(wc, mdio_addr); - wcdte_setctl(wc, mdio_addr, MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK); - wcdte_getctl(wc, mdio_addr); - } - /* Shift the command bits out. */ - for (i = 31; i >= 0; i--) { - int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; - wcdte_setctl(wc, mdio_addr, MDIO_ENB | dataval); - wcdte_getctl(wc, mdio_addr); - wcdte_setctl(wc, mdio_addr, MDIO_ENB | dataval | MDIO_SHIFT_CLK); - wcdte_getctl(wc, mdio_addr); - } - /* Clear out extra bits. */ - for (i = 2; i > 0; i--) { - wcdte_setctl(wc, mdio_addr, MDIO_ENB_IN); - wcdte_getctl(wc, mdio_addr); - wcdte_setctl(wc, mdio_addr, MDIO_ENB_IN | MDIO_SHIFT_CLK); - wcdte_getctl(wc, mdio_addr); - } - return; -} - -static int wcdte_boot_processor(struct wcdte *wc, const struct firmware *firmware, int full) -{ - int i, j, byteloc, last_byteloc, length, delay_count; - unsigned int reg, ret; - -#ifndef USE_TEST_HW - /* Turn off auto negotiation */ - wcdte_write_phy(wc, 0, 0x2100); - if (debug) - printk("wcdte: PHY register 0 = %X", wcdte_read_phy(wc, 0)); - - /* Set reset */ - wcdte_setctl(wc, 0x00A0, 0x04000000); - - /* Wait 1000msec to ensure processor reset */ - mdelay(4); - - /* Clear reset */ - wcdte_setctl(wc, 0x00A0, 0x04080000); - - /* Waitfor ethernet link */ - delay_count = 0; - do - { - reg = wcdte_getctl(wc, 0x00fc); - mdelay(2); - delay_count++; - - if (delay_count >= 5000) - { - printk("wcdte error: Failed to link to DTE processor!\n"); - return(1); - } - } while ((reg & 0xE0000000) != 0xE0000000); - - - /* Turn off booted LED */ - wcdte_setctl(wc, 0x00A0, 0x04084000); - - -#endif - - reg = wcdte_getctl(wc, 0x00fc); - if (debug) - printk("wcdte: LINK STATUS: reg(0xfc) = %X\n", reg); - - reg = wcdte_getctl(wc, 0x00A0); - - byteloc = 17; - j = 0; - do - { - last_byteloc = byteloc; - - length = (firmware->data[byteloc] << 8) |firmware->data[byteloc+1]; - byteloc += 2; - - down(&wc->cmdqsem); - if ( (((wc->cmdq_wndx + 1) % MAX_COMMANDS) == wc->cmdq_rndx) && debug ) - printk("wcdte error: cmdq is full.\n"); - else - { - wc->cmdq[wc->cmdq_wndx].cmdlen = length; - for (i = 0; i < length; i++) - wc->cmdq[wc->cmdq_wndx].cmd[i] = firmware->data[byteloc++]; - wc->cmdq_wndx = (wc->cmdq_wndx + 1) % MAX_COMMANDS; - } - - ret = __transmit_demand(wc); - up(&wc->cmdqsem); - - ret = wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS_ACK, 1); - if (ret == 1) - return(1); - else if (ret == 2) /* Retransmit if dte processor times out */ - byteloc = last_byteloc; - j++; - - if (!full && (byteloc > 189)) { /* Quit if not fully booting */ - wcdte_setctl(wc, 0x00A0, 0x04080000); - return 0; - } - - - } while (byteloc < firmware->size-20); - wc->timeout = 10 * HZ; - wc->last_command_sent = 0; - if (wcdte_waitfor_csmencaps(wc, RCV_CSMENCAPS, 1)) - return(1); - - /* Turn on booted LED */ - wcdte_setctl(wc, 0x00A0, 0x04080000); - if(debug) - printk("wcdte: Successfully booted DTE processor.\n"); - - return(0); -} - -static int wcdte_create_channel(struct wcdte *wc, int simple, int complicated, int part1_id, int part2_id, unsigned int *dte_chan1, unsigned int *dte_chan2) -{ - int length = 0; - unsigned char chan1, chan2; - struct zt_transcoder_channel *ztc1, *ztc2; - struct dte_state *st1, *st2; - if(complicated == DTE_FORMAT_G729A) - length = G729_LENGTH; - else if (complicated == DTE_FORMAT_G723_1) - length = G723_LENGTH; - - /* Create complex channel */ - zt_send_cmd(wc, CMD_MSG_CREATE_CHANNEL(wc->seq_num++, part1_id), CMD_MSG_CREATE_CHANNEL_LEN, 0x0010); - zt_send_cmd(wc, CMD_MSG_QUERY_CHANNEL(wc->seq_num++, part1_id), CMD_MSG_QUERY_CHANNEL_LEN, 0x0010); - chan1 = wc->last_rparm1; - - /* Create simple channel */ - zt_send_cmd(wc, CMD_MSG_CREATE_CHANNEL(wc->seq_num++, part2_id), CMD_MSG_CREATE_CHANNEL_LEN, 0x0010); - zt_send_cmd(wc, CMD_MSG_QUERY_CHANNEL(wc->seq_num++, part2_id), CMD_MSG_QUERY_CHANNEL_LEN, 0x0010); - chan2 = wc->last_rparm1; - - ztc1 = &(wc->uencode->channels[part1_id/2]); - ztc2 = &(wc->udecode->channels[part2_id/2]); - st1 = ztc1->pvt; - st2 = ztc2->pvt; - - /* Configure complex channel */ - zt_send_cmd(wc, CMD_MSG_SET_IP_HDR_CHANNEL(st1->cmd_seqno++, chan1, part2_id, part1_id), CMD_MSG_SET_IP_HDR_CHANNEL_LEN, 0x9000); - zt_send_cmd(wc, CMD_MSG_VOIP_VCEOPT(st1->cmd_seqno++, chan1, length, 0), CMD_MSG_VOIP_VCEOPT_LEN, 0x8001); - - /* Configure simple channel */ - zt_send_cmd(wc, CMD_MSG_SET_IP_HDR_CHANNEL(st2->cmd_seqno++, chan2, part1_id, part2_id), CMD_MSG_SET_IP_HDR_CHANNEL_LEN, 0x9000); - zt_send_cmd(wc, CMD_MSG_VOIP_VCEOPT(st2->cmd_seqno++, chan2, length, 0), CMD_MSG_VOIP_VCEOPT_LEN, 0x8001); - -#ifdef QUIET_DSP - zt_send_cmd(wc, CMD_MSG_VOIP_TONECTL(st1->cmd_seqno++, chan1), CMD_MSG_VOIP_TONECTL_LEN, 0x805B); - zt_send_cmd(wc, CMD_MSG_VOIP_DTMFOPT(st1->cmd_seqno++, chan1), CMD_MSG_VOIP_DTMFOPT_LEN, 0x8002); - zt_send_cmd(wc, CMD_MSG_VOIP_TONECTL(st2->cmd_seqno++, chan2), CMD_MSG_VOIP_TONECTL_LEN, 0x805B); - zt_send_cmd(wc, CMD_MSG_VOIP_DTMFOPT(st2->cmd_seqno++, chan2), CMD_MSG_VOIP_DTMFOPT_LEN, 0x8002); - zt_send_cmd(wc, CMD_MSG_VOIP_INDCTRL(st1->cmd_seqno++, chan1), CMD_MSG_VOIP_INDCTRL_LEN, 0x8084); - zt_send_cmd(wc, CMD_MSG_VOIP_INDCTRL(st2->cmd_seqno++, chan2), CMD_MSG_VOIP_INDCTRL_LEN, 0x8084); -#endif - - zt_send_cmd(wc, CMD_MSG_TRANS_CONNECT(wc->seq_num++, 1, chan1, chan2, complicated, simple), CMD_MSG_TRANS_CONNECT_LEN, 0x9322); - zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA(st1->cmd_seqno++, chan1, complicated), CMD_MSG_VOIP_VOPENA_LEN, 0x8000); - zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA(st2->cmd_seqno++, chan2, simple), CMD_MSG_VOIP_VOPENA_LEN, 0x8000); - - *dte_chan1 = chan1; - *dte_chan2 = chan2; - - return 1; -} - -static int wcdte_destroy_channel(struct wcdte *wc, unsigned int chan1, unsigned int chan2) -{ - struct zt_transcoder_channel *ztc1, *ztc2; - struct dte_state *st1, *st2; - - ztc1 = &(wc->uencode->channels[chan1/2]); - ztc2 = &(wc->udecode->channels[chan2/2]); - st1 = ztc1->pvt; - st2 = ztc2->pvt; - - /* Turn off both channels */ - zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA_CLOSE(st1->cmd_seqno++, chan1), CMD_MSG_VOIP_VOPENA_CLOSE_LEN, 0x8000); - zt_send_cmd(wc, CMD_MSG_VOIP_VOPENA_CLOSE(st2->cmd_seqno++, chan2), CMD_MSG_VOIP_VOPENA_CLOSE_LEN, 0x8000); - - /* Disconnect the channels */ - zt_send_cmd(wc, CMD_MSG_TRANS_CONNECT(wc->seq_num++, 0, chan1, chan2, 0, 0), CMD_MSG_TRANS_CONNECT_LEN, 0x9322); - - /* Remove the channels */ - zt_send_cmd(wc, CMD_MSG_DESTROY_CHANNEL(wc->seq_num++, chan1), CMD_MSG_DESTROY_CHANNEL_LEN, 0x0011); - zt_send_cmd(wc, CMD_MSG_DESTROY_CHANNEL(wc->seq_num++, chan2), CMD_MSG_DESTROY_CHANNEL_LEN, 0x0011); - - return 1; -} - - -static int __wcdte_setup_channels(struct wcdte *wc) -{ - wc->seq_num = 6; - -#ifndef USE_TEST_HW - zt_send_cmd(wc, CMD_MSG_SET_ARM_CLK(wc->seq_num++), CMD_MSG_SET_ARM_CLK_LEN, 0x0411); - zt_send_cmd(wc, CMD_MSG_SET_SPU_CLK(wc->seq_num++), CMD_MSG_SET_SPU_CLK_LEN, 0x0412); -#endif - -#ifdef USE_TDM_CONFIG - zt_send_cmd(wc, CMD_MSG_TDM_SELECT_BUS_MODE(wc->seq_num++), CMD_MSG_TDM_SELECT_BUS_MODE_LEN, 0x0417); - zt_send_cmd(wc, CMD_MSG_TDM_ENABLE_BUS(wc->seq_num++), CMD_MSG_TDM_ENABLE_BUS_LEN, 0x0405); - zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x03, 0x20, 0x00), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); - zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x04, 0x80, 0x04), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); - zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x05, 0x20, 0x08), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); - zt_send_cmd(wc, CMD_MSG_SUPVSR_SETUP_TDM_PARMS(wc->seq_num++, 0x06, 0x80, 0x0C), CMD_MSG_SUPVSR_SETUP_TDM_PARMS_LEN, 0x0407); -#endif - - zt_send_cmd(wc, CMD_MSG_SET_ETH_HEADER(wc->seq_num++), CMD_MSG_SET_ETH_HEADER_LEN, 0x0100); - zt_send_cmd(wc, CMD_MSG_IP_SERVICE_CONFIG(wc->seq_num++), CMD_MSG_IP_SERVICE_CONFIG_LEN, 0x0302); - zt_send_cmd(wc, CMD_MSG_ARP_SERVICE_CONFIG(wc->seq_num++), CMD_MSG_ARP_SERVICE_CONFIG_LEN, 0x0105); - zt_send_cmd(wc, CMD_MSG_ICMP_SERVICE_CONFIG(wc->seq_num++), CMD_MSG_ICMP_SERVICE_CONFIG_LEN, 0x0304); - -#ifdef USE_TDM_CONFIG - zt_send_cmd(wc, CMD_MSG_DEVICE_SET_COUNTRY_CODE(wc->seq_num++), CMD_MSG_DEVICE_SET_COUNTRY_CODE_LEN, 0x041B); -#endif - - zt_send_cmd(wc, CMD_MSG_SPU_FEATURES_CONTROL(wc->seq_num++, 0x02), CMD_MSG_SPU_FEATURES_CONTROL_LEN, 0x0013); - zt_send_cmd(wc, CMD_MSG_IP_OPTIONS(wc->seq_num++), CMD_MSG_IP_OPTIONS_LEN, 0x0306); - zt_send_cmd(wc, CMD_MSG_SPU_FEATURES_CONTROL(wc->seq_num++, 0x04), CMD_MSG_SPU_FEATURES_CONTROL_LEN, 0x0013); - -#ifdef USE_TDM_CONFIG - zt_send_cmd(wc, CMD_MSG_TDM_OPT(wc->seq_num++), CMD_MSG_TDM_OPT_LEN, 0x0435); -#endif - - wc->timeout = HZ/10 + 1; /* 100msec */ - - return(0); -} - -static int wcdte_setup_channels(struct wcdte *wc) -{ - down(&wc->chansem); - __wcdte_setup_channels(wc); - up(&wc->chansem); - - return 0; -} - -static int __devinit wcdte_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int res, reg; - struct wcdte *wc; - struct wcdte_desc *d = (struct wcdte_desc *)ent->driver_data; - int x; - static int initd_ifaces=0; - unsigned char g729_numchannels, g723_numchannels, min_numchannels, dte_firmware_ver, dte_firmware_ver_minor; - unsigned int complexfmts; - - struct firmware embedded_firmware; - const struct firmware *firmware = &embedded_firmware; -#if !defined(HOTPLUG_FIRMWARE) - extern void _binary_zaptel_fw_tc400m_bin_size; - extern u8 _binary_zaptel_fw_tc400m_bin_start[]; -#else - static const char tc400m_firmware[] = "zaptel-fw-tc400m.bin"; -#endif - - if (!initd_ifaces) { - memset((void *)ifaces,0,(sizeof(struct wcdte *))*WC_MAX_IFACES); - initd_ifaces=1; - } - for (x=0;x= WC_MAX_IFACES) { - printk("wcdte: Too many interfaces\n"); - return -EIO; - } - - if (pci_enable_device(pdev)) { - res = -EIO; - } else { - - wc = vmalloc(sizeof(struct wcdte)); - if (wc) { - ifaces[x] = wc; - memset(wc, 0, sizeof(struct wcdte)); - spin_lock_init(&wc->reglock); - sema_init(&wc->chansem, 1); - sema_init(&wc->cmdqsem, 1); - wc->cards = NUM_CARDS; - wc->iobase = pci_resource_start(pdev, 0); - wc->dev = pdev; - wc->pos = x; - wc->variety = d->name; - - wc->tdbl = 0; - wc->rdbl = 0; - wc->rcvflags = 0; - wc->last_seqno = 999; - wc->last_command_sent = 0; - wc->last_rcommand = 0; - wc->last_rparm1 = 0; - wc->cmdq_wndx = 0; - wc->cmdq_rndx = 0; - wc->seq_num = 6; - wc->timeout = 1 * HZ; /* 1 sec */ - wc->dsp_crashed = 0; - wc->dumping = 0; - wc->ztsnd_rtx = 0; - wc->ztsnd_0010_rtx = 0; - - /* Keep track of whether we need to free the region */ - if (request_region(wc->iobase, 0xff, "wcdte")) - wc->freeregion = 1; - - /* Allocate enought memory for all TX buffers, RX buffers, and descriptors */ - wc->writechunk = (int *)pci_alloc_consistent(pdev, PCI_WINDOW_SIZE, &wc->writedma); - if (!wc->writechunk) { - printk("wcdte error: Unable to allocate DMA-able memory\n"); - if (wc->freeregion) - release_region(wc->iobase, 0xff); - return -ENOMEM; - } - - wc->readchunk = wc->writechunk + (SFRAME_SIZE * ERING_SIZE) / 4; /* in doublewords */ - wc->readdma = wc->writedma + (SFRAME_SIZE * ERING_SIZE); /* in bytes */ - - wc->descripchunk = wc->readchunk + (SFRAME_SIZE * ERING_SIZE) / 4; /* in doublewords */ - wc->descripdma = wc->readdma + (SFRAME_SIZE * ERING_SIZE); /* in bytes */ - - /* Initialize Write/Buffers to all blank data */ - memset((void *)wc->writechunk,0x00, SFRAME_SIZE * 2); - memset((void *)wc->readchunk, 0x00, SFRAME_SIZE * 2); - - init_waitqueue_head(&wc->regq); - - /* Initialize the work queue */ - wc->dte_wq = create_singlethread_workqueue("tc400b"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) - INIT_WORK(&wc->dte_work, dte_wque_run); -#else - INIT_WORK(&wc->dte_work, dte_wque_run, wc); -#endif - -#if defined(HOTPLUG_FIRMWARE) - if ((request_firmware(&firmware, tc400m_firmware, &wc->dev->dev) != 0) || - !firmware) { - printk("TC400M: firmware %s not available from userspace\n", tc400m_firmware); - return -EIO; - } -#else - embedded_firmware.data = _binary_zaptel_fw_tc400m_bin_start; - embedded_firmware.size = (size_t) &_binary_zaptel_fw_tc400m_bin_size; -#endif - - dte_firmware_ver = firmware->data[0]; - dte_firmware_ver_minor = firmware->data[16]; - g729_numchannels = firmware->data[1]; - g723_numchannels = firmware->data[2]; - - if (g723_numchannels < g729_numchannels) - min_numchannels = g723_numchannels; - else - min_numchannels = g729_numchannels; - - /* Setup Encoders and Decoders */ - - if (!mode || strlen(mode) < 4) { - sprintf(wc->complexname, "G.729a / G.723.1"); - complexfmts = ZT_FORMAT_G729A | ZT_FORMAT_G723_1; - wc->numchannels = min_numchannels; - } else if (mode[3] == '9') { /* "G.729" */ - sprintf(wc->complexname, "G.729a"); - complexfmts = ZT_FORMAT_G729A; - wc->numchannels = g729_numchannels; - } else if (mode[3] == '3') { /* "G.723.1" */ - sprintf(wc->complexname, "G.723.1"); - complexfmts = ZT_FORMAT_G723_1; - wc->numchannels = g723_numchannels; - } else { - sprintf(wc->complexname, "G.729a / G.723.1"); - complexfmts = ZT_FORMAT_G729A | ZT_FORMAT_G723_1; - wc->numchannels = min_numchannels; - } - - uencode = zt_transcoder_alloc(wc->numchannels); - udecode = zt_transcoder_alloc(wc->numchannels); - encoders = vmalloc(sizeof(struct dte_state) * wc->numchannels); - decoders = vmalloc(sizeof(struct dte_state) * wc->numchannels); - memset(encoders, 0, sizeof(struct dte_state) * wc->numchannels); - memset(decoders, 0, sizeof(struct dte_state) * wc->numchannels); - if (!uencode || !udecode || !encoders || !decoders) { - if (uencode) - zt_transcoder_free(uencode); - if (udecode) - zt_transcoder_free(udecode); - if (encoders) - vfree(encoders); - if (decoders) - vfree(decoders); - return -ENOMEM; - } - sprintf(udecode->name, "DTE Decoder"); - sprintf(uencode->name, "DTE Encoder"); - - udecode->srcfmts = uencode->dstfmts = complexfmts; - udecode->dstfmts = uencode->srcfmts = ZT_FORMAT_ULAW | ZT_FORMAT_ALAW; - - udecode->operation = uencode->operation = dte_operation; - - for (x=0;xnumchannels;x++) { - dte_init_state(encoders + x, 1, x, wc); - encoders[x].encoder = 1; - decoders[x].encoder = 0; - dte_init_state(decoders + x, 0, x, wc); - uencode->channels[x].pvt = encoders + x; - udecode->channels[x].pvt = decoders + x; - } - - wc->uencode = uencode; - wc->udecode = udecode; - - zt_transcoder_register(uencode); - zt_transcoder_register(udecode); - - printk("Zaptel DTE (%s) Transcoder support LOADED (firm ver = %d.%d)\n", wc->complexname, dte_firmware_ver, dte_firmware_ver_minor); - - - /* Enable bus mastering */ - pci_set_master(pdev); - - /* Keep track of which device we are */ - pci_set_drvdata(pdev, wc); - - if (request_irq(pdev->irq, wcdte_interrupt, ZAP_IRQ_SHARED, "tc400b", wc)) { - printk("wcdte error: Unable to request IRQ %d\n", pdev->irq); - if (wc->freeregion) - release_region(wc->iobase, 0xff); - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); - pci_set_drvdata(pdev, NULL); - vfree(wc); - return -EIO; - } - - - if (wcdte_hardware_init(wc)) { - /* Set Reset Low */ - wcdte_stop_dma(wc); - /* Free Resources */ - free_irq(pdev->irq, wc); - if (wc->freeregion) - release_region(wc->iobase, 0xff); - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); - pci_set_drvdata(pdev, NULL); - vfree(wc); - return -EIO; - - } - - /* Enable interrupts */ - wcdte_enable_interrupts(wc); - - /* Start DMA */ - wcdte_start_dma(wc); - - if (wcdte_boot_processor(wc,firmware,1)) { - if (firmware != &embedded_firmware) - release_firmware(firmware); - - /* Set Reset Low */ - wcdte_stop_dma(wc); - /* Free Resources */ - free_irq(pdev->irq, wc); - if (wc->freeregion) - release_region(wc->iobase, 0xff); - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); - pci_set_drvdata(pdev, NULL); - vfree(wc); - return -EIO; - } - if (firmware != &embedded_firmware) - release_firmware(firmware); - - if (wcdte_setup_channels(wc)) { - /* Set Reset Low */ - wcdte_stop_dma(wc); - /* Free Resources */ - free_irq(pdev->irq, wc); - if (wc->freeregion) - release_region(wc->iobase, 0xff); - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); - pci_set_drvdata(pdev, NULL); - vfree(wc); - return -EIO; - } - - reg = wcdte_getctl(wc, 0x00fc); - if (debug) - printk("wcdte debug: (post-boot) Reg fc is %08x\n", reg); - - printk("Found and successfully installed a Wildcard TC: %s \n", wc->variety); - if (debug) { - printk("TC400B operating in DEBUG mode\n"); - printk("debug_des = %d, debug_des_cnt = %d, force_alert = %d,\n debug_notimeout = %d, debug_packets = %d\n", - debug_des, debug_des_cnt, force_alert, debug_notimeout, debug_packets); - } - res = 0; - } else - res = -ENOMEM; - } - return res; -} - -static void wcdte_release(struct wcdte *wc) -{ - if (wc->freeregion) - release_region(wc->iobase, 0xff); - vfree(wc); -} - -static void __devexit wcdte_remove_one(struct pci_dev *pdev) -{ - int i; - struct wcdte *wc = pci_get_drvdata(pdev); - struct zt_transcoder_channel *ztc_en, *ztc_de; - struct dte_state *st_en, *st_de; - - if (wc) { - if (debug) - { - printk("wcdte debug: wc->ztsnd_rtx = %d\n", wc->ztsnd_rtx); - printk("wcdte debug: wc->ztsnd_0010_rtx = %d\n", wc->ztsnd_0010_rtx); - - for(i = 0; i < wc->numchannels; i++) - { - ztc_en = &(wc->uencode->channels[i]); - st_en = ztc_en->pvt; - - ztc_de = &(wc->udecode->channels[i]); - st_de = ztc_de->pvt; - - printk("wcdte debug: en[%d] snt = %d, rcv = %d [%d]\n", i, st_en->packets_sent, st_en->packets_received, st_en->packets_sent - st_en->packets_received); - printk("wcdte debug: de[%d] snt = %d, rcv = %d [%d]\n", i, st_de->packets_sent, st_de->packets_received, st_de->packets_sent - st_de->packets_received); - } - } - - zt_transcoder_unregister(wc->udecode); - zt_transcoder_unregister(wc->uencode); - zt_transcoder_free(wc->uencode); - zt_transcoder_free(wc->udecode); - vfree(wc->uencode->channels[0].pvt); - vfree(wc->udecode->channels[0].pvt); - - /* Stop any DMA */ - wcdte_stop_dma(wc); - - /* In case hardware is still there */ - wcdte_disable_interrupts(wc); - - /* Kill workqueue */ - destroy_workqueue(wc->dte_wq); - - /* Immediately free resources */ - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); - free_irq(pdev->irq, wc); - - /* Release span, possibly delayed */ - wcdte_release(wc); - } -} - -static struct pci_device_id wcdte_pci_tbl[] = { -#ifndef USE_TEST_HW - { 0xd161, 0x3400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctc400p }, /* Digium board */ - { 0xd161, 0x8004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctce400 }, /* Digium board */ -#else - { 0x1317, 0x0985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctc400p }, /* reference board */ -#endif - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, wcdte_pci_tbl); - -static struct pci_driver wcdte_driver = { - name: "wctc4xxp", - probe: wcdte_init_one, - remove: __devexit_p(wcdte_remove_one), - suspend: NULL, - resume: NULL, - id_table: wcdte_pci_tbl, -}; - -int ztdte_init(void) -{ - int res; - - res = zap_pci_module(&wcdte_driver); - if (res) - return -ENODEV; - return 0; -} - -void ztdte_cleanup(void) -{ - pci_unregister_driver(&wcdte_driver); -} - -module_param(debug, int, S_IRUGO | S_IWUSR); -module_param(debug_des, int, S_IRUGO | S_IWUSR); -module_param(debug_des_cnt, int, S_IRUGO | S_IWUSR); -module_param(debug_notimeout, int, S_IRUGO | S_IWUSR); -module_param(force_alert, int, S_IRUGO | S_IWUSR); -module_param(mode, charp, S_IRUGO | S_IWUSR); -MODULE_DESCRIPTION("Wildcard TC400P+TC400M Driver"); -MODULE_AUTHOR("John Sloan "); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif - -module_init(ztdte_init); -module_exit(ztdte_cleanup); diff --git a/wctc4xxp/codec_test.c b/wctc4xxp/codec_test.c deleted file mode 100644 index 287979d..0000000 --- a/wctc4xxp/codec_test.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Wilcard TC400B Digium Transcoder Engine Interface Driver for Zapata Telephony interface test tool. - * - * Written by Matt O'Gorman - * - * Copyright (C) 2006-2007, Digium, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef STANDALONE_ZAPATA -#include "zaptel.h" -#else -#include -#endif - -#define MAX_CARDS_TO_TEST 6 -#define MAX_CHANNELS_PER_CARD 96 - -#define AST_FORMAT_ULAW (1 << 2) -#define AST_FORMAT_G729A (1 << 8) - -#define AST_FRIENDLY_OFFSET 64 - -static int debug = 0; - -static unsigned char ulaw_slin_ex[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static unsigned char g729a_expected[] = { - 0xE9, 0x88, 0x4C, 0xA0, 0x00, 0xFA, 0xDD, 0xA2, 0x06, 0x2D, - 0x69, 0x88, 0x00, 0x60, 0x68, 0xD5, 0x9E, 0x20, 0x80, 0x50 -}; - - -struct format_map { - unsigned int map[32][32]; -}; - - -struct tcpvt { - int fd; - int fake; - int inuse; - struct zt_transcode_header *hdr; -// struct ast_frame f; -}; - -struct tctest_info { - int numcards; - int numchans[MAX_CARDS_TO_TEST]; - int total_chans; - int errors; - int overcnt_error; /* Too many cards found */ - int undercnt_error; /* Too few cards found */ - int timeout_error[MAX_CARDS_TO_TEST]; - int data_error[MAX_CARDS_TO_TEST]; - int numcards_werrors; -}; - - -static int find_transcoders(struct tctest_info *tctest_info) -{ - struct zt_transcode_info info = { 0, }; - int fd, res; - - if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0) { - printf("Warning: No Zaptel transcoder support!\n"); - return 0; - } - - tctest_info->total_chans = 0; - info.op = ZT_TCOP_GETINFO; - for (info.tcnum = 0; !(res = ioctl(fd, ZT_TRANSCODE_OP, &info)); info.tcnum++) { - if (debug) - printf("Found transcoder %d, '%s' with %d channels.\n", info.tcnum, info.name, info.numchannels); - if ((info.tcnum % 2) == 0) - { - tctest_info->numchans[info.tcnum/2] = info.numchannels; - tctest_info->total_chans += info.numchannels; - } - } - tctest_info->numcards = info.tcnum / 2; - - close(fd); - if (!info.tcnum) - printf("No hardware transcoders found.\n"); - return 0; -} - - -static int open_transcoder(struct tcpvt *ztp, int dest, int source) -{ - int fd; - unsigned int x = ZT_TCOP_ALLOCATE; - struct zt_transcode_header *hdr; - int flags; - - if ((fd = open("/dev/zap/transcode", O_RDWR)) < 0) - return -1; - flags = fcntl(fd, F_GETFL); - if (flags > - 1) { - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) - printf("Could not set non-block mode!\n"); - } - - if ((hdr = mmap(NULL, sizeof(*hdr), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { - printf("Memory Map failed for transcoding (%s)\n", strerror(errno)); - close(fd); - - return -1; - } - - if (hdr->magic != ZT_TRANSCODE_MAGIC) { - printf("Transcoder header (%08x) wasn't magic. Abandoning\n", hdr->magic); - munmap(hdr, sizeof(*hdr)); - close(fd); - - return -1; - } - - hdr->srcfmt = source; - hdr->dstfmt = dest; - - if (ioctl(fd, ZT_TRANSCODE_OP, &x)) { - printf("Unable to attach transcoder: %s\n", strerror(errno)); - munmap(hdr, sizeof(*hdr)); - close(fd); - - return -1; - } - - ztp->fd = fd; - ztp->hdr = hdr; - - return 0; -} - - -static void close_transcoder(struct tcpvt *ztp) -{ - unsigned int x; - - x = ZT_TCOP_RELEASE; - if (ioctl(ztp->fd, ZT_TRANSCODE_OP, &x)) - printf("Failed to release transcoder channel: %s\n", strerror(errno)); - - munmap(ztp->hdr, sizeof(*ztp->hdr)); - close(ztp->fd); -} - - -static int encode_packet(struct tcpvt *ztp, unsigned char *packet_in, unsigned char *packet_out) -{ - struct zt_transcode_header *hdr = ztp->hdr; - unsigned int x; - - hdr->srcoffset = 0; - - memcpy(hdr->srcdata + hdr->srcoffset + hdr->srclen, packet_in, 160); - hdr->srclen += 160; - - - hdr->dstoffset = AST_FRIENDLY_OFFSET; - x = ZT_TCOP_TRANSCODE; - if (ioctl(ztp->fd, ZT_TRANSCODE_OP, &x)) - printf("Failed to transcode: %s\n", strerror(errno)); - - usleep(20000); - if (hdr->dstlen) - { - memcpy(packet_out, hdr->dstdata + hdr->dstoffset, hdr->dstlen); - return 0; - } - else - return -1; -} - - -static void print_failed() -{ - printf("______ ___ _____ _ _____ ______\n"); - printf("| ___| / _ \\ |_ _| | | | ___| | _ \\\n"); - printf("| |_ / /_\\ \\ | | | | | |__ | | | |\n"); - printf("| _| | _ | | | | | | __| | | | |\n"); - printf("| | | | | | _| |_ | |____ | |___ | |/ /\n"); - printf("\\_| \\_| |_/ \\___/ \\_____/ \\____/ |___/ \n"); -} - - -int main(int argc, char *argv[]) -{ - int arg1, arg2, i, j, card_testing, chan_testing; - struct tcpvt ztp[MAX_CHANNELS_PER_CARD * MAX_CARDS_TO_TEST]; - unsigned char packet_out[200]; - struct tctest_info tctest_info; - - memset(&tctest_info, 0, sizeof(tctest_info)); - - if ((argc < 2) || (argc > 3)) - { - printf("codec_test requires one argument.\n"); - printf(" arg1 = number of cards to test\n"); - return -1; - } - - if (argc == 2) - sscanf(argv[1], "%d", &arg1); - else if (argc == 3) - { - sscanf(argv[1], "%d %d", &arg1, &arg2); - debug = arg2; - } - - printf("Beginning test of %d TC400B cards\n", arg1); - - - /* Search for TC400Bs */ - find_transcoders(&tctest_info); - - if (tctest_info.numcards > arg1) - { - tctest_info.errors++; - tctest_info.overcnt_error = 1; - } - if (tctest_info.numcards < arg1) - { - tctest_info.errors++; - tctest_info.undercnt_error = 1; - } - - if (tctest_info.errors == 0) - { - /* Begin testing transcoder channels */ - for (card_testing = 0; card_testing < tctest_info.numcards; card_testing++) - { - tctest_info.data_error[card_testing] = 0; - tctest_info.timeout_error[card_testing] = 0; - for (chan_testing = 0; chan_testing < tctest_info.numchans[card_testing]; chan_testing++) - { - i = chan_testing; - for(j = 0; j < card_testing; j++) - i += tctest_info.numchans[j]; - - open_transcoder(&ztp[i], AST_FORMAT_G729A, AST_FORMAT_ULAW); - - if ((tctest_info.timeout_error[card_testing] = encode_packet(&ztp[i], ulaw_slin_ex, packet_out) == -1)) - tctest_info.errors++; - - if (memcmp(g729a_expected, packet_out, 20) != 0) - { - tctest_info.errors++; - tctest_info.data_error[card_testing] += 1; - } - } - if ( (tctest_info.data_error[card_testing]) || (tctest_info.timeout_error[card_testing]) ) - tctest_info.numcards_werrors++; - } - - for (i = 0; i < tctest_info.total_chans; i++) - close_transcoder(&ztp[i]); - } - - if (debug) - { - printf("\n\n"); - printf("tctest_info.errors = %d\n", tctest_info.errors); - printf("tctest_info.overcnt_error = %d\n", tctest_info.overcnt_error); - printf("tctest_info.undercnt_error = %d\n", tctest_info.undercnt_error); - printf("tctest_info.numcards_werrors = %d\n", tctest_info.numcards_werrors); - - for (i = 0; i < tctest_info.numcards; i++) - { - printf("tctest_info.data_error[%d] = %d\n", i, tctest_info.data_error[i]); - printf("tctest_info.timeout_error[%d] = %d\n", i, tctest_info.timeout_error[i]); - } - } - - if (tctest_info.errors) - { - printf("\n\n\n"); - if (tctest_info.numcards_werrors) - printf("%d of %d cards\n", tctest_info.numcards_werrors, tctest_info.numcards); - print_failed(); - if (tctest_info.overcnt_error) - printf("\n%d cards found, %d expected\n", tctest_info.numcards, arg1); - if (tctest_info.undercnt_error) - printf("\n%d cards found, %d expected\n", tctest_info.numcards, arg1); - printf("\n\n\n"); - } - else - printf("%d of %d cards PASSED\n", tctest_info.numcards - tctest_info.numcards_werrors, tctest_info.numcards); - - return 0; -} diff --git a/wctdm.c b/wctdm.c deleted file mode 100644 index 68a21e7..0000000 --- a/wctdm.c +++ /dev/null @@ -1,2602 +0,0 @@ -/* - * Wilcard TDM400P TDM FXS/FXO Interface Driver for Zapata Telephony interface - * - * Written by Mark Spencer - * Matthew Fredrickson - * - * Copyright (C) 2001, Linux Support Services, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "proslic.h" -#include "wctdm.h" -/* - * Define for audio vs. register based ring detection - * - */ -/* #define AUDIO_RINGCHECK */ - -/* - Experimental max loop current limit for the proslic - Loop current limit is from 20 mA to 41 mA in steps of 3 - (according to datasheet) - So set the value below to: - 0x00 : 20mA (default) - 0x01 : 23mA - 0x02 : 26mA - 0x03 : 29mA - 0x04 : 32mA - 0x05 : 35mA - 0x06 : 37mA - 0x07 : 41mA -*/ -static int loopcurrent = 20; - -static int reversepolarity = 0; - -static alpha indirect_regs[] = -{ -{0,255,"DTMF_ROW_0_PEAK",0x55C2}, -{1,255,"DTMF_ROW_1_PEAK",0x51E6}, -{2,255,"DTMF_ROW2_PEAK",0x4B85}, -{3,255,"DTMF_ROW3_PEAK",0x4937}, -{4,255,"DTMF_COL1_PEAK",0x3333}, -{5,255,"DTMF_FWD_TWIST",0x0202}, -{6,255,"DTMF_RVS_TWIST",0x0202}, -{7,255,"DTMF_ROW_RATIO_TRES",0x0198}, -{8,255,"DTMF_COL_RATIO_TRES",0x0198}, -{9,255,"DTMF_ROW_2ND_ARM",0x0611}, -{10,255,"DTMF_COL_2ND_ARM",0x0202}, -{11,255,"DTMF_PWR_MIN_TRES",0x00E5}, -{12,255,"DTMF_OT_LIM_TRES",0x0A1C}, -{13,0,"OSC1_COEF",0x7B30}, -{14,1,"OSC1X",0x0063}, -{15,2,"OSC1Y",0x0000}, -{16,3,"OSC2_COEF",0x7870}, -{17,4,"OSC2X",0x007D}, -{18,5,"OSC2Y",0x0000}, -{19,6,"RING_V_OFF",0x0000}, -{20,7,"RING_OSC",0x7EF0}, -{21,8,"RING_X",0x0160}, -{22,9,"RING_Y",0x0000}, -{23,255,"PULSE_ENVEL",0x2000}, -{24,255,"PULSE_X",0x2000}, -{25,255,"PULSE_Y",0x0000}, -//{26,13,"RECV_DIGITAL_GAIN",0x4000}, // playback volume set lower -{26,13,"RECV_DIGITAL_GAIN",0x2000}, // playback volume set lower -{27,14,"XMIT_DIGITAL_GAIN",0x4000}, -//{27,14,"XMIT_DIGITAL_GAIN",0x2000}, -{28,15,"LOOP_CLOSE_TRES",0x1000}, -{29,16,"RING_TRIP_TRES",0x3600}, -{30,17,"COMMON_MIN_TRES",0x1000}, -{31,18,"COMMON_MAX_TRES",0x0200}, -{32,19,"PWR_ALARM_Q1Q2",0x07C0}, -{33,20,"PWR_ALARM_Q3Q4",0x2600}, -{34,21,"PWR_ALARM_Q5Q6",0x1B80}, -{35,22,"LOOP_CLOSURE_FILTER",0x8000}, -{36,23,"RING_TRIP_FILTER",0x0320}, -{37,24,"TERM_LP_POLE_Q1Q2",0x008C}, -{38,25,"TERM_LP_POLE_Q3Q4",0x0100}, -{39,26,"TERM_LP_POLE_Q5Q6",0x0010}, -{40,27,"CM_BIAS_RINGING",0x0C00}, -{41,64,"DCDC_MIN_V",0x0C00}, -{42,255,"DCDC_XTRA",0x1000}, -{43,66,"LOOP_CLOSE_TRES_LOW",0x1000}, -}; - -static struct fxo_mode { - char *name; - /* FXO */ - int ohs; - int ohs2; - int rz; - int rt; - int ilim; - int dcv; - int mini; - int acim; - int ring_osc; - int ring_x; -} fxo_modes[] = -{ - { "FCC", 0, 0, 0, 1, 0, 0x3, 0, 0, }, /* US, Canada */ - { "TBR21", 0, 0, 0, 0, 1, 0x3, 0, 0x2, 0x7e6c, 0x023a, }, - /* Austria, Belgium, Denmark, Finland, France, Germany, - Greece, Iceland, Ireland, Italy, Luxembourg, Netherlands, - Norway, Portugal, Spain, Sweden, Switzerland, and UK */ - { "ARGENTINA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "AUSTRALIA", 1, 0, 0, 0, 0, 0, 0x3, 0x3, }, - { "AUSTRIA", 0, 1, 0, 0, 1, 0x3, 0, 0x3, }, - { "BAHRAIN", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "BELGIUM", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "BRAZIL", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "BULGARIA", 0, 0, 0, 0, 1, 0x3, 0x0, 0x3, }, - { "CANADA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "CHILE", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "CHINA", 0, 0, 0, 0, 0, 0, 0x3, 0xf, }, - { "COLUMBIA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "CROATIA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "CYRPUS", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "CZECH", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "DENMARK", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "ECUADOR", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "EGYPT", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "ELSALVADOR", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "FINLAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "FRANCE", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "GERMANY", 0, 1, 0, 0, 1, 0x3, 0, 0x3, }, - { "GREECE", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "GUAM", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "HONGKONG", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "HUNGARY", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "ICELAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "INDIA", 0, 0, 0, 0, 0, 0x3, 0, 0x4, }, - { "INDONESIA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "IRELAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "ISRAEL", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "ITALY", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "JAPAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "JORDAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "KAZAKHSTAN", 0, 0, 0, 0, 0, 0x3, 0, }, - { "KUWAIT", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "LATVIA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "LEBANON", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "LUXEMBOURG", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "MACAO", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "MALAYSIA", 0, 0, 0, 0, 0, 0, 0x3, 0, }, /* Current loop >= 20ma */ - { "MALTA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "MEXICO", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "MOROCCO", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "NETHERLANDS", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "NEWZEALAND", 0, 0, 0, 0, 0, 0x3, 0, 0x4, }, - { "NIGERIA", 0, 0, 0, 0, 0x1, 0x3, 0, 0x2, }, - { "NORWAY", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "OMAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "PAKISTAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "PERU", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "PHILIPPINES", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "POLAND", 0, 0, 1, 1, 0, 0x3, 0, 0, }, - { "PORTUGAL", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "ROMANIA", 0, 0, 0, 0, 0, 3, 0, 0, }, - { "RUSSIA", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "SAUDIARABIA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "SINGAPORE", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "SLOVAKIA", 0, 0, 0, 0, 0, 0x3, 0, 0x3, }, - { "SLOVENIA", 0, 0, 0, 0, 0, 0x3, 0, 0x2, }, - { "SOUTHAFRICA", 1, 0, 1, 0, 0, 0x3, 0, 0x3, }, - { "SOUTHKOREA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "SPAIN", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "SWEDEN", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "SWITZERLAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "SYRIA", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "TAIWAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "THAILAND", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "UAE", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "UK", 0, 1, 0, 0, 1, 0x3, 0, 0x5, }, - { "USA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "YEMEN", 0, 0, 0, 0, 0, 0x3, 0, 0, }, -}; - -#include "zaptel.h" - -#ifdef LINUX26 -#include -#endif - -#define NUM_FXO_REGS 60 - -#define WC_MAX_IFACES 128 - -#define WC_CNTL 0x00 -#define WC_OPER 0x01 -#define WC_AUXC 0x02 -#define WC_AUXD 0x03 -#define WC_MASK0 0x04 -#define WC_MASK1 0x05 -#define WC_INTSTAT 0x06 -#define WC_AUXR 0x07 - -#define WC_DMAWS 0x08 -#define WC_DMAWI 0x0c -#define WC_DMAWE 0x10 -#define WC_DMARS 0x18 -#define WC_DMARI 0x1c -#define WC_DMARE 0x20 - -#define WC_AUXFUNC 0x2b -#define WC_SERCTL 0x2d -#define WC_FSCDELAY 0x2f - -#define WC_REGBASE 0xc0 - -#define WC_SYNC 0x0 -#define WC_TEST 0x1 -#define WC_CS 0x2 -#define WC_VER 0x3 - -#define BIT_CS (1 << 2) -#define BIT_SCLK (1 << 3) -#define BIT_SDI (1 << 4) -#define BIT_SDO (1 << 5) - -#define FLAG_EMPTY 0 -#define FLAG_WRITE 1 -#define FLAG_READ 2 - -#define DEFAULT_RING_DEBOUNCE 64 /* Ringer Debounce (64 ms) */ - -/* the constants below control the 'debounce' periods enforced by the - check_hook routines; these routines are called once every 4 interrupts - (the interrupt cycles around the four modules), so the periods are - specified in _4 millisecond_ increments -*/ -#define DEFAULT_BATT_DEBOUNCE 4 /* Battery debounce (64 ms) */ -#define POLARITY_DEBOUNCE 4 /* Polarity debounce (64 ms) */ -#define DEFAULT_BATT_THRESH 3 /* Anything under this is "no battery" */ - -#define OHT_TIMER 6000 /* How long after RING to retain OHT */ - -#define FLAG_3215 (1 << 0) - -#define NUM_CARDS 4 - -#define MAX_ALARMS 10 - -#define MOD_TYPE_FXS 0 -#define MOD_TYPE_FXO 1 - -#define MINPEGTIME 10 * 8 /* 30 ms peak to peak gets us no more than 100 Hz */ -#define PEGTIME 50 * 8 /* 50ms peak to peak gets us rings of 10 Hz or more */ -#define PEGCOUNT 5 /* 5 cycles of pegging means RING */ - -#define NUM_CAL_REGS 12 - -struct calregs { - unsigned char vals[NUM_CAL_REGS]; -}; - -enum proslic_power_warn { - PROSLIC_POWER_UNKNOWN = 0, - PROSLIC_POWER_ON, - PROSLIC_POWER_WARNED, -}; - -struct wctdm { - struct pci_dev *dev; - char *variety; - struct zt_span span; - unsigned char ios; - int usecount; - unsigned int intcount; - int dead; - int pos; - int flags[NUM_CARDS]; - int freeregion; - int alt; - int curcard; - int cardflag; /* Bit-map of present cards */ - enum proslic_power_warn proslic_power; - spinlock_t lock; - - union { - struct { -#ifdef AUDIO_RINGCHECK - unsigned int pegtimer; - int pegcount; - int peg; - int ring; -#else - int wasringing; - int lastrdtx; -#endif - int ringdebounce; - int offhook; - int battdebounce; - int nobatttimer; - int battery; - int lastpol; - int polarity; - int polaritydebounce; - } fxo; - struct { - int oldrxhook; - int debouncehook; - int lastrxhook; - int debounce; - int ohttimer; - int idletxhookstate; /* IDLE changing hook state */ - int lasttxhook; - int palarms; - struct calregs calregs; - } fxs; - } mod[NUM_CARDS]; - - /* Receive hook state and debouncing */ - int modtype[NUM_CARDS]; - unsigned char reg0shadow[NUM_CARDS]; - unsigned char reg1shadow[NUM_CARDS]; - - unsigned long ioaddr; - dma_addr_t readdma; - dma_addr_t writedma; - volatile unsigned int *writechunk; /* Double-word aligned write memory */ - volatile unsigned int *readchunk; /* Double-word aligned read memory */ - struct zt_chan chans[NUM_CARDS]; -}; - - -struct wctdm_desc { - char *name; - int flags; -}; - -static struct wctdm_desc wctdm = { "Wildcard S400P Prototype", 0 }; -static struct wctdm_desc wctdme = { "Wildcard TDM400P REV E/F", 0 }; -static struct wctdm_desc wctdmh = { "Wildcard TDM400P REV H", 0 }; -static struct wctdm_desc wctdmi = { "Wildcard TDM400P REV I", 0 }; -static int acim2tiss[16] = { 0x0, 0x1, 0x4, 0x5, 0x7, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0, 0x3 }; - -static struct wctdm *ifaces[WC_MAX_IFACES]; - -static void wctdm_release(struct wctdm *wc); - -static int battdebounce = DEFAULT_BATT_DEBOUNCE; -static int battthresh = DEFAULT_BATT_THRESH; -static int ringdebounce = DEFAULT_RING_DEBOUNCE; -static int fwringdetect = 0; -static int debug = 0; -static int robust = 0; -static int timingonly = 0; -static int lowpower = 0; -static int boostringer = 0; -static int fastringer = 0; -static int _opermode = 0; -static char *opermode = "FCC"; -static int fxshonormode = 0; -static int alawoverride = 0; -static int fastpickup = 0; -static int fxotxgain = 0; -static int fxorxgain = 0; -static int fxstxgain = 0; -static int fxsrxgain = 0; - -static int wctdm_init_proslic(struct wctdm *wc, int card, int fast , int manual, int sane); - -static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char ints) -{ - volatile unsigned int *writechunk; - int x; - if (ints & 0x01) - /* Write is at interrupt address. Start writing from normal offset */ - writechunk = wc->writechunk; - else - writechunk = wc->writechunk + ZT_CHUNKSIZE; - /* Calculate Transmission */ - zt_transmit(&wc->span); - - for (x=0;xcardflag & (1 << 3)) - writechunk[x] |= (wc->chans[3].writechunk[x]); - if (wc->cardflag & (1 << 2)) - writechunk[x] |= (wc->chans[2].writechunk[x] << 8); - if (wc->cardflag & (1 << 1)) - writechunk[x] |= (wc->chans[1].writechunk[x] << 16); - if (wc->cardflag & (1 << 0)) - writechunk[x] |= (wc->chans[0].writechunk[x] << 24); -#else - if (wc->cardflag & (1 << 3)) - writechunk[x] |= (wc->chans[3].writechunk[x] << 24); - if (wc->cardflag & (1 << 2)) - writechunk[x] |= (wc->chans[2].writechunk[x] << 16); - if (wc->cardflag & (1 << 1)) - writechunk[x] |= (wc->chans[1].writechunk[x] << 8); - if (wc->cardflag & (1 << 0)) - writechunk[x] |= (wc->chans[0].writechunk[x]); -#endif - } - -} - -#ifdef AUDIO_RINGCHECK -static inline void ring_check(struct wctdm *wc, int card) -{ - int x; - short sample; - if (wc->modtype[card] != MOD_TYPE_FXO) - return; - wc->mod[card].fxo.pegtimer += ZT_CHUNKSIZE; - for (x=0;xchans[card].readchunk[x], (&(wc->chans[card]))); - if ((sample > 10000) && (wc->mod[card].fxo.peg != 1)) { - if (debug > 1) printk("High peg!\n"); - if ((wc->mod[card].fxo.pegtimer < PEGTIME) && (wc->mod[card].fxo.pegtimer > MINPEGTIME)) - wc->mod[card].fxo.pegcount++; - wc->mod[card].fxo.pegtimer = 0; - wc->mod[card].fxo.peg = 1; - } else if ((sample < -10000) && (wc->mod[card].fxo.peg != -1)) { - if (debug > 1) printk("Low peg!\n"); - if ((wc->mod[card].fxo.pegtimer < (PEGTIME >> 2)) && (wc->mod[card].fxo.pegtimer > (MINPEGTIME >> 2))) - wc->mod[card].fxo.pegcount++; - wc->mod[card].fxo.pegtimer = 0; - wc->mod[card].fxo.peg = -1; - } - } - if (wc->mod[card].fxo.pegtimer > PEGTIME) { - /* Reset pegcount if our timer expires */ - wc->mod[card].fxo.pegcount = 0; - } - /* Decrement debouncer if appropriate */ - if (wc->mod[card].fxo.ringdebounce) - wc->mod[card].fxo.ringdebounce--; - if (!wc->mod[card].fxo.offhook && !wc->mod[card].fxo.ringdebounce) { - if (!wc->mod[card].fxo.ring && (wc->mod[card].fxo.pegcount > PEGCOUNT)) { - /* It's ringing */ - if (debug) - printk("RING on %d/%d!\n", wc->span.spanno, card + 1); - if (!wc->mod[card].fxo.offhook) - zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); - wc->mod[card].fxo.ring = 1; - } - if (wc->mod[card].fxo.ring && !wc->mod[card].fxo.pegcount) { - /* No more ring */ - if (debug) - printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); - zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); - wc->mod[card].fxo.ring = 0; - } - } -} -#endif -static inline void wctdm_receiveprep(struct wctdm *wc, unsigned char ints) -{ - volatile unsigned int *readchunk; - int x; - - if (ints & 0x08) - readchunk = wc->readchunk + ZT_CHUNKSIZE; - else - /* Read is at interrupt address. Valid data is available at normal offset */ - readchunk = wc->readchunk; - for (x=0;xcardflag & (1 << 3)) - wc->chans[3].readchunk[x] = (readchunk[x]) & 0xff; - if (wc->cardflag & (1 << 2)) - wc->chans[2].readchunk[x] = (readchunk[x] >> 8) & 0xff; - if (wc->cardflag & (1 << 1)) - wc->chans[1].readchunk[x] = (readchunk[x] >> 16) & 0xff; - if (wc->cardflag & (1 << 0)) - wc->chans[0].readchunk[x] = (readchunk[x] >> 24) & 0xff; -#else - if (wc->cardflag & (1 << 3)) - wc->chans[3].readchunk[x] = (readchunk[x] >> 24) & 0xff; - if (wc->cardflag & (1 << 2)) - wc->chans[2].readchunk[x] = (readchunk[x] >> 16) & 0xff; - if (wc->cardflag & (1 << 1)) - wc->chans[1].readchunk[x] = (readchunk[x] >> 8) & 0xff; - if (wc->cardflag & (1 << 0)) - wc->chans[0].readchunk[x] = (readchunk[x]) & 0xff; -#endif - } -#ifdef AUDIO_RINGCHECK - for (x=0;xcards;x++) - ring_check(wc, x); -#endif - /* XXX We're wasting 8 taps. We should get closer :( */ - for (x = 0; x < NUM_CARDS; x++) { - if (wc->cardflag & (1 << x)) - zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->chans[x].writechunk); - } - zt_receive(&wc->span); -} - -static void wctdm_stop_dma(struct wctdm *wc); -static void wctdm_reset_tdm(struct wctdm *wc); -static void wctdm_restart_dma(struct wctdm *wc); - -static inline void __write_8bits(struct wctdm *wc, unsigned char bits) -{ - /* Drop chip select */ - int x; - wc->ios |= BIT_SCLK; - outb(wc->ios, wc->ioaddr + WC_AUXD); - wc->ios &= ~BIT_CS; - outb(wc->ios, wc->ioaddr + WC_AUXD); - for (x=0;x<8;x++) { - /* Send out each bit, MSB first, drop SCLK as we do so */ - if (bits & 0x80) - wc->ios |= BIT_SDI; - else - wc->ios &= ~BIT_SDI; - wc->ios &= ~BIT_SCLK; - outb(wc->ios, wc->ioaddr + WC_AUXD); - /* Now raise SCLK high again and repeat */ - wc->ios |= BIT_SCLK; - outb(wc->ios, wc->ioaddr + WC_AUXD); - bits <<= 1; - } - /* Finally raise CS back high again */ - wc->ios |= BIT_CS; - outb(wc->ios, wc->ioaddr + WC_AUXD); - -} - -static inline void __reset_spi(struct wctdm *wc) -{ - /* Drop chip select and clock once and raise and clock once */ - wc->ios |= BIT_SCLK; - outb(wc->ios, wc->ioaddr + WC_AUXD); - wc->ios &= ~BIT_CS; - outb(wc->ios, wc->ioaddr + WC_AUXD); - wc->ios |= BIT_SDI; - wc->ios &= ~BIT_SCLK; - outb(wc->ios, wc->ioaddr + WC_AUXD); - /* Now raise SCLK high again and repeat */ - wc->ios |= BIT_SCLK; - outb(wc->ios, wc->ioaddr + WC_AUXD); - /* Finally raise CS back high again */ - wc->ios |= BIT_CS; - outb(wc->ios, wc->ioaddr + WC_AUXD); - /* Clock again */ - wc->ios &= ~BIT_SCLK; - outb(wc->ios, wc->ioaddr + WC_AUXD); - /* Now raise SCLK high again and repeat */ - wc->ios |= BIT_SCLK; - outb(wc->ios, wc->ioaddr + WC_AUXD); - -} - -static inline unsigned char __read_8bits(struct wctdm *wc) -{ - unsigned char res=0, c; - int x; - wc->ios |= BIT_SCLK; - outb(wc->ios, wc->ioaddr + WC_AUXD); - /* Drop chip select */ - wc->ios &= ~BIT_CS; - outb(wc->ios, wc->ioaddr + WC_AUXD); - for (x=0;x<8;x++) { - res <<= 1; - /* Get SCLK */ - wc->ios &= ~BIT_SCLK; - outb(wc->ios, wc->ioaddr + WC_AUXD); - /* Read back the value */ - c = inb(wc->ioaddr + WC_AUXR); - if (c & BIT_SDO) - res |= 1; - /* Now raise SCLK high again */ - wc->ios |= BIT_SCLK; - outb(wc->ios, wc->ioaddr + WC_AUXD); - } - /* Finally raise CS back high again */ - wc->ios |= BIT_CS; - outb(wc->ios, wc->ioaddr + WC_AUXD); - wc->ios &= ~BIT_SCLK; - outb(wc->ios, wc->ioaddr + WC_AUXD); - - /* And return our result */ - return res; -} - -static void __wctdm_setcreg(struct wctdm *wc, unsigned char reg, unsigned char val) -{ - outb(val, wc->ioaddr + WC_REGBASE + ((reg & 0xf) << 2)); -} - -static unsigned char __wctdm_getcreg(struct wctdm *wc, unsigned char reg) -{ - return inb(wc->ioaddr + WC_REGBASE + ((reg & 0xf) << 2)); -} - -static inline void __wctdm_setcard(struct wctdm *wc, int card) -{ - if (wc->curcard != card) { - __wctdm_setcreg(wc, WC_CS, (1 << card)); - wc->curcard = card; - } -} - -static void __wctdm_setreg(struct wctdm *wc, int card, unsigned char reg, unsigned char value) -{ - __wctdm_setcard(wc, card); - if (wc->modtype[card] == MOD_TYPE_FXO) { - __write_8bits(wc, 0x20); - __write_8bits(wc, reg & 0x7f); - } else { - __write_8bits(wc, reg & 0x7f); - } - __write_8bits(wc, value); -} - -static void wctdm_setreg(struct wctdm *wc, int card, unsigned char reg, unsigned char value) -{ - unsigned long flags; - spin_lock_irqsave(&wc->lock, flags); - __wctdm_setreg(wc, card, reg, value); - spin_unlock_irqrestore(&wc->lock, flags); -} - -static unsigned char __wctdm_getreg(struct wctdm *wc, int card, unsigned char reg) -{ - __wctdm_setcard(wc, card); - if (wc->modtype[card] == MOD_TYPE_FXO) { - __write_8bits(wc, 0x60); - __write_8bits(wc, reg & 0x7f); - } else { - __write_8bits(wc, reg | 0x80); - } - return __read_8bits(wc); -} - -static inline void reset_spi(struct wctdm *wc, int card) -{ - unsigned long flags; - spin_lock_irqsave(&wc->lock, flags); - __wctdm_setcard(wc, card); - __reset_spi(wc); - __reset_spi(wc); - spin_unlock_irqrestore(&wc->lock, flags); -} - -static unsigned char wctdm_getreg(struct wctdm *wc, int card, unsigned char reg) -{ - unsigned long flags; - unsigned char res; - spin_lock_irqsave(&wc->lock, flags); - res = __wctdm_getreg(wc, card, reg); - spin_unlock_irqrestore(&wc->lock, flags); - return res; -} - -static int __wait_access(struct wctdm *wc, int card) -{ - unsigned char data = 0; - long origjiffies; - int count = 0; - - #define MAX 6000 /* attempts */ - - - origjiffies = jiffies; - /* Wait for indirect access */ - while (count++ < MAX) - { - data = __wctdm_getreg(wc, card, I_STATUS); - - if (!data) - return 0; - - } - - if(count > (MAX-1)) printk(" ##### Loop error (%02x) #####\n", data); - - return 0; -} - -static unsigned char translate_3215(unsigned char address) -{ - int x; - for (x=0;xflags[card] & FLAG_3215) { - address = translate_3215(address); - if (address == 255) - return 0; - } - spin_lock_irqsave(&wc->lock, flags); - if(!__wait_access(wc, card)) { - __wctdm_setreg(wc, card, IDA_LO,(unsigned char)(data & 0xFF)); - __wctdm_setreg(wc, card, IDA_HI,(unsigned char)((data & 0xFF00)>>8)); - __wctdm_setreg(wc, card, IAA,address); - res = 0; - }; - spin_unlock_irqrestore(&wc->lock, flags); - return res; -} - -static int wctdm_proslic_getreg_indirect(struct wctdm *wc, int card, unsigned char address) -{ - unsigned long flags; - int res = -1; - char *p=NULL; - /* Translate 3215 addresses */ - if (wc->flags[card] & FLAG_3215) { - address = translate_3215(address); - if (address == 255) - return 0; - } - spin_lock_irqsave(&wc->lock, flags); - if (!__wait_access(wc, card)) { - __wctdm_setreg(wc, card, IAA, address); - if (!__wait_access(wc, card)) { - unsigned char data1, data2; - data1 = __wctdm_getreg(wc, card, IDA_LO); - data2 = __wctdm_getreg(wc, card, IDA_HI); - res = data1 | (data2 << 8); - } else - p = "Failed to wait inside\n"; - } else - p = "failed to wait\n"; - spin_unlock_irqrestore(&wc->lock, flags); - if (p) - printk(p); - return res; -} - -static int wctdm_proslic_init_indirect_regs(struct wctdm *wc, int card) -{ - unsigned char i; - - for (i=0; iflags[card] & FLAG_3215) || (indirect_regs[i].altaddr != 255))) - { - printk("!!!!!!! %s iREG %X = %X should be %X\n", - indirect_regs[i].name,indirect_regs[i].address,j,initial ); - passed = 0; - } - } - - if (passed) { - if (debug) - printk("Init Indirect Registers completed successfully.\n"); - } else { - printk(" !!!!! Init Indirect Registers UNSUCCESSFULLY.\n"); - return -1; - } - return 0; -} - -static inline void wctdm_proslic_recheck_sanity(struct wctdm *wc, int card) -{ - int res; - /* Check loopback */ - res = wc->reg1shadow[card]; - if (!res && (res != wc->mod[card].fxs.lasttxhook)) { - res = wctdm_getreg(wc, card, 8); - if (res) { - printk("Ouch, part reset, quickly restoring reality (%d)\n", card); - wctdm_init_proslic(wc, card, 1, 0, 1); - } else { - if (wc->mod[card].fxs.palarms++ < MAX_ALARMS) { - printk("Power alarm on module %d, resetting!\n", card + 1); - if (wc->mod[card].fxs.lasttxhook == 4) - wc->mod[card].fxs.lasttxhook = 1; - wctdm_setreg(wc, card, 64, wc->mod[card].fxs.lasttxhook); - } else { - if (wc->mod[card].fxs.palarms == MAX_ALARMS) - printk("Too many power alarms on card %d, NOT resetting!\n", card + 1); - } - } - } -} - -static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card) -{ -#ifndef AUDIO_RINGCHECK - unsigned char res; -#endif - signed char b; - int poopy = 0; - /* Try to track issues that plague slot one FXO's */ - b = wc->reg0shadow[card]; - if ((b & 0x2) || !(b & 0x8)) { - /* Not good -- don't look at anything else */ - if (debug) - printk("Poopy (%02x) on card %d!\n", b, card + 1); - poopy++; - } - b &= 0x9b; - if (wc->mod[card].fxo.offhook) { - if (b != 0x9) - wctdm_setreg(wc, card, 5, 0x9); - } else { - if (b != 0x8) - wctdm_setreg(wc, card, 5, 0x8); - } - if (poopy) - return; -#ifndef AUDIO_RINGCHECK - if (!wc->mod[card].fxo.offhook) { - if (fwringdetect) { - res = wc->reg0shadow[card] & 0x60; - if (wc->mod[card].fxo.ringdebounce--) { - if (res && (res != wc->mod[card].fxo.lastrdtx) && (wc->mod[card].fxo.battery == 1)) { - if (!wc->mod[card].fxo.wasringing) { - wc->mod[card].fxo.wasringing = 1; - if (debug) - printk("RING on %d/%d!\n", wc->span.spanno, card + 1); - zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); - } - wc->mod[card].fxo.lastrdtx = res; - wc->mod[card].fxo.ringdebounce = 10; - } else if (!res) { - if ((wc->mod[card].fxo.ringdebounce == 0) && wc->mod[card].fxo.wasringing) { - wc->mod[card].fxo.wasringing = 0; - if (debug) - printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); - zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); - } - } - } else if (res && (wc->mod[card].fxo.battery == 1)) { - wc->mod[card].fxo.lastrdtx = res; - wc->mod[card].fxo.ringdebounce = 10; - } - } else { - res = wc->reg0shadow[card]; - if ((res & 0x60) && (wc->mod[card].fxo.battery == 1)) { - wc->mod[card].fxo.ringdebounce += (ZT_CHUNKSIZE * 16); - if (wc->mod[card].fxo.ringdebounce >= ZT_CHUNKSIZE * ringdebounce) { - if (!wc->mod[card].fxo.wasringing) { - wc->mod[card].fxo.wasringing = 1; - zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); - if (debug) - printk("RING on %d/%d!\n", wc->span.spanno, card + 1); - } - wc->mod[card].fxo.ringdebounce = ZT_CHUNKSIZE * ringdebounce; - } - } else { - wc->mod[card].fxo.ringdebounce -= ZT_CHUNKSIZE * 4; - if (wc->mod[card].fxo.ringdebounce <= 0) { - if (wc->mod[card].fxo.wasringing) { - wc->mod[card].fxo.wasringing = 0; - zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); - if (debug) - printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); - } - wc->mod[card].fxo.ringdebounce = 0; - } - } - } - } -#endif - b = wc->reg1shadow[card]; -#if 0 - { - static int count = 0; - if (!(count++ % 100)) { - printk("Card %d: Voltage: %d Debounce %d\n", card + 1, - b, wc->mod[card].fxo.battdebounce); - } - } -#endif - if (abs(b) < battthresh) { - wc->mod[card].fxo.nobatttimer++; -#if 0 - if (wc->mod[card].fxo.battery == 1) - printk("Battery loss: %d (%d debounce)\n", b, wc->mod[card].fxo.battdebounce); -#endif - if (wc->mod[card].fxo.battery && !wc->mod[card].fxo.battdebounce) { - if (debug) - printk("NO BATTERY on %d/%d!\n", wc->span.spanno, card + 1); - wc->mod[card].fxo.battery = 0; -#ifdef JAPAN - if ((!wc->ohdebounce) && wc->offhook) { - zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); - if (debug) - printk("Signalled On Hook\n"); -#ifdef ZERO_BATT_RING - wc->onhook++; -#endif - } -#else - zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); - zt_alarm_channel(&wc->chans[card], ZT_ALARM_RED); -#endif - wc->mod[card].fxo.battdebounce = battdebounce; - } else if (!wc->mod[card].fxo.battery) - wc->mod[card].fxo.battdebounce = battdebounce; - } else if (abs(b) > battthresh) { - if ((wc->mod[card].fxo.battery < 1) && !wc->mod[card].fxo.battdebounce) { - if (debug) - printk("BATTERY on %d/%d (%s)!\n", wc->span.spanno, card + 1, - (b < 0) ? "-" : "+"); -#ifdef ZERO_BATT_RING - if (wc->onhook) { - wc->onhook = 0; - zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); - if (debug) - printk("Signalled Off Hook\n"); - } -#else - zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); - zt_alarm_channel(&wc->chans[card], ZT_ALARM_NONE); -#endif - wc->mod[card].fxo.battery = 1; - wc->mod[card].fxo.nobatttimer = 0; - wc->mod[card].fxo.battdebounce = battdebounce; - } else if (wc->mod[card].fxo.battery == 1) - wc->mod[card].fxo.battdebounce = battdebounce; - - if (wc->mod[card].fxo.lastpol >= 0) { - if (b < 0) { - wc->mod[card].fxo.lastpol = -1; - wc->mod[card].fxo.polaritydebounce = POLARITY_DEBOUNCE; - } - } - if (wc->mod[card].fxo.lastpol <= 0) { - if (b > 0) { - wc->mod[card].fxo.lastpol = 1; - wc->mod[card].fxo.polaritydebounce = POLARITY_DEBOUNCE; - } - } - } else { - /* It's something else... */ - wc->mod[card].fxo.battdebounce = battdebounce; - } - if (wc->mod[card].fxo.battdebounce) - wc->mod[card].fxo.battdebounce--; - if (wc->mod[card].fxo.polaritydebounce) { - wc->mod[card].fxo.polaritydebounce--; - if (wc->mod[card].fxo.polaritydebounce < 1) { - if (wc->mod[card].fxo.lastpol != wc->mod[card].fxo.polarity) { - if (debug) - printk("%lu Polarity reversed (%d -> %d)\n", jiffies, - wc->mod[card].fxo.polarity, - wc->mod[card].fxo.lastpol); - if (wc->mod[card].fxo.polarity) - zt_qevent_lock(&wc->chans[card], ZT_EVENT_POLARITY); - wc->mod[card].fxo.polarity = wc->mod[card].fxo.lastpol; - } - } - } -} - -static inline void wctdm_proslic_check_hook(struct wctdm *wc, int card) -{ - char res; - int hook; - - /* For some reason we have to debounce the - hook detector. */ - - res = wc->reg0shadow[card]; - hook = (res & 1); - if (hook != wc->mod[card].fxs.lastrxhook) { - /* Reset the debounce (must be multiple of 4ms) */ - wc->mod[card].fxs.debounce = 8 * (4 * 8); -#if 0 - printk("Resetting debounce card %d hook %d, %d\n", card, hook, wc->mod[card].fxs.debounce); -#endif - } else { - if (wc->mod[card].fxs.debounce > 0) { - wc->mod[card].fxs.debounce-= 16 * ZT_CHUNKSIZE; -#if 0 - printk("Sustaining hook %d, %d\n", hook, wc->mod[card].fxs.debounce); -#endif - if (!wc->mod[card].fxs.debounce) { -#if 0 - printk("Counted down debounce, newhook: %d...\n", hook); -#endif - wc->mod[card].fxs.debouncehook = hook; - } - if (!wc->mod[card].fxs.oldrxhook && wc->mod[card].fxs.debouncehook) { - /* Off hook */ -#if 1 - if (debug) -#endif - printk("wctdm: Card %d Going off hook\n", card); - zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); - if (robust) - wctdm_init_proslic(wc, card, 1, 0, 1); - wc->mod[card].fxs.oldrxhook = 1; - - } else if (wc->mod[card].fxs.oldrxhook && !wc->mod[card].fxs.debouncehook) { - /* On hook */ -#if 1 - if (debug) -#endif - printk("wctdm: Card %d Going on hook\n", card); - zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); - wc->mod[card].fxs.oldrxhook = 0; - } - } - } - wc->mod[card].fxs.lastrxhook = hook; -} - -ZAP_IRQ_HANDLER(wctdm_interrupt) -{ - struct wctdm *wc = dev_id; - unsigned char ints; - int x; - int mode; - - ints = inb(wc->ioaddr + WC_INTSTAT); - - if (!ints) -#ifdef LINUX26 - return IRQ_NONE; -#else - return; -#endif - - outb(ints, wc->ioaddr + WC_INTSTAT); - - if (ints & 0x10) { - /* Stop DMA, wait for watchdog */ - printk("TDM PCI Master abort\n"); - wctdm_stop_dma(wc); -#ifdef LINUX26 - return IRQ_RETVAL(1); -#else - return; -#endif - } - - if (ints & 0x20) { - printk("PCI Target abort\n"); -#ifdef LINUX26 - return IRQ_RETVAL(1); -#else - return; -#endif - } - - for (x=0;x<4;x++) { - if (wc->cardflag & (1 << x) && - (wc->modtype[x] == MOD_TYPE_FXS)) { - if (wc->mod[x].fxs.lasttxhook == 0x4) { - /* RINGing, prepare for OHT */ - wc->mod[x].fxs.ohttimer = OHT_TIMER << 3; - if (reversepolarity) - wc->mod[x].fxs.idletxhookstate = 0x6; /* OHT mode when idle */ - else - wc->mod[x].fxs.idletxhookstate = 0x2; - } else { - if (wc->mod[x].fxs.ohttimer) { - wc->mod[x].fxs.ohttimer-= ZT_CHUNKSIZE; - if (!wc->mod[x].fxs.ohttimer) { - if (reversepolarity) - wc->mod[x].fxs.idletxhookstate = 0x5; /* Switch to active */ - else - wc->mod[x].fxs.idletxhookstate = 0x1; - if ((wc->mod[x].fxs.lasttxhook == 0x2) || (wc->mod[x].fxs.lasttxhook == 0x6)) { - /* Apply the change if appropriate */ - if (reversepolarity) - wc->mod[x].fxs.lasttxhook = 0x5; - else - wc->mod[x].fxs.lasttxhook = 0x1; - wctdm_setreg(wc, x, 64, wc->mod[x].fxs.lasttxhook); - } - } - } - } - } - } - - if (ints & 0x0f) { - wc->intcount++; - x = wc->intcount & 0x3; - mode = wc->intcount & 0xc; - if (wc->cardflag & (1 << x)) { - switch(mode) { - case 0: - /* Rest */ - break; - case 4: - /* Read first shadow reg */ - if (wc->modtype[x] == MOD_TYPE_FXS) - wc->reg0shadow[x] = wctdm_getreg(wc, x, 68); - else if (wc->modtype[x] == MOD_TYPE_FXO) - wc->reg0shadow[x] = wctdm_getreg(wc, x, 5); - break; - case 8: - /* Read second shadow reg */ - if (wc->modtype[x] == MOD_TYPE_FXS) - wc->reg1shadow[x] = wctdm_getreg(wc, x, 64); - else if (wc->modtype[x] == MOD_TYPE_FXO) - wc->reg1shadow[x] = wctdm_getreg(wc, x, 29); - break; - case 12: - /* Perform processing */ - if (wc->modtype[x] == MOD_TYPE_FXS) { - wctdm_proslic_check_hook(wc, x); - if (!(wc->intcount & 0xf0)) - wctdm_proslic_recheck_sanity(wc, x); - } else if (wc->modtype[x] == MOD_TYPE_FXO) { - wctdm_voicedaa_check_hook(wc, x); - } - break; - } - } - if (!(wc->intcount % 10000)) { - /* Accept an alarm once per 10 seconds */ - for (x=0;x<4;x++) - if (wc->modtype[x] == MOD_TYPE_FXS) { - if (wc->mod[x].fxs.palarms) - wc->mod[x].fxs.palarms--; - } - } - wctdm_receiveprep(wc, ints); - wctdm_transmitprep(wc, ints); - } -#ifdef LINUX26 - return IRQ_RETVAL(1); -#endif - -} - -static int wctdm_voicedaa_insane(struct wctdm *wc, int card) -{ - int blah; - blah = wctdm_getreg(wc, card, 2); - if (blah != 0x3) - return -2; - blah = wctdm_getreg(wc, card, 11); - if (debug) - printk("VoiceDAA System: %02x\n", blah & 0xf); - return 0; -} - -static int wctdm_proslic_insane(struct wctdm *wc, int card) -{ - int blah,insane_report; - insane_report=0; - - blah = wctdm_getreg(wc, card, 0); - if (debug) - printk("ProSLIC on module %d, product %d, version %d\n", card, (blah & 0x30) >> 4, (blah & 0xf)); - -#if 0 - if ((blah & 0x30) >> 4) { - printk("ProSLIC on module %d is not a 3210.\n", card); - return -1; - } -#endif - if (((blah & 0xf) == 0) || ((blah & 0xf) == 0xf)) { - /* SLIC not loaded */ - return -1; - } - if ((blah & 0xf) < 2) { - printk("ProSLIC 3210 version %d is too old\n", blah & 0xf); - return -1; - } - if (wctdm_getreg(wc, card, 1) & 0x80) - /* ProSLIC 3215, not a 3210 */ - wc->flags[card] |= FLAG_3215; - - blah = wctdm_getreg(wc, card, 8); - if (blah != 0x2) { - printk("ProSLIC on module %d insane (1) %d should be 2\n", card, blah); - return -1; - } else if ( insane_report) - printk("ProSLIC on module %d Reg 8 Reads %d Expected is 0x2\n",card,blah); - - blah = wctdm_getreg(wc, card, 64); - if (blah != 0x0) { - printk("ProSLIC on module %d insane (2)\n", card); - return -1; - } else if ( insane_report) - printk("ProSLIC on module %d Reg 64 Reads %d Expected is 0x0\n",card,blah); - - blah = wctdm_getreg(wc, card, 11); - if (blah != 0x33) { - printk("ProSLIC on module %d insane (3)\n", card); - return -1; - } else if ( insane_report) - printk("ProSLIC on module %d Reg 11 Reads %d Expected is 0x33\n",card,blah); - - /* Just be sure it's setup right. */ - wctdm_setreg(wc, card, 30, 0); - - if (debug) - printk("ProSLIC on module %d seems sane.\n", card); - return 0; -} - -static int wctdm_proslic_powerleak_test(struct wctdm *wc, int card) -{ - unsigned long origjiffies; - unsigned char vbat; - - /* Turn off linefeed */ - wctdm_setreg(wc, card, 64, 0); - - /* Power down */ - wctdm_setreg(wc, card, 14, 0x10); - - /* Wait for one second */ - origjiffies = jiffies; - - while((vbat = wctdm_getreg(wc, card, 82)) > 0x6) { - if ((jiffies - origjiffies) >= (HZ/2)) - break;; - } - - if (vbat < 0x06) { - printk("Excessive leakage detected on module %d: %d volts (%02x) after %d ms\n", card, - 376 * vbat / 1000, vbat, (int)((jiffies - origjiffies) * 1000 / HZ)); - return -1; - } else if (debug) { - printk("Post-leakage voltage: %d volts\n", 376 * vbat / 1000); - } - return 0; -} - -static int wctdm_powerup_proslic(struct wctdm *wc, int card, int fast) -{ - unsigned char vbat; - unsigned long origjiffies; - int lim; - - /* Set period of DC-DC converter to 1/64 khz */ - wctdm_setreg(wc, card, 92, 0xff /* was 0xff */); - - /* Wait for VBat to powerup */ - origjiffies = jiffies; - - /* Disable powerdown */ - wctdm_setreg(wc, card, 14, 0); - - /* If fast, don't bother checking anymore */ - if (fast) - return 0; - - while((vbat = wctdm_getreg(wc, card, 82)) < 0xc0) { - /* Wait no more than 500ms */ - if ((jiffies - origjiffies) > HZ/2) { - break; - } - } - - if (vbat < 0xc0) { - if (wc->proslic_power == PROSLIC_POWER_UNKNOWN) - printk("ProSLIC on module %d failed to powerup within %d ms (%d mV only)\n\n -- DID YOU REMEMBER TO PLUG IN THE HD POWER CABLE TO THE TDM400P??\n", - card, (int)(((jiffies - origjiffies) * 1000 / HZ)), - vbat * 375); - wc->proslic_power = PROSLIC_POWER_WARNED; - return -1; - } else if (debug) { - printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n", - card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ))); - } - wc->proslic_power = PROSLIC_POWER_ON; - - /* Proslic max allowed loop current, reg 71 LOOP_I_LIMIT */ - /* If out of range, just set it to the default value */ - lim = (loopcurrent - 20) / 3; - if ( loopcurrent > 41 ) { - lim = 0; - if (debug) - printk("Loop current out of range! Setting to default 20mA!\n"); - } - else if (debug) - printk("Loop current set to %dmA!\n",(lim*3)+20); - wctdm_setreg(wc,card,LOOP_I_LIMIT,lim); - - /* Engage DC-DC converter */ - wctdm_setreg(wc, card, 93, 0x19 /* was 0x19 */); -#if 0 - origjiffies = jiffies; - while(0x80 & wctdm_getreg(wc, card, 93)) { - if ((jiffies - origjiffies) > 2 * HZ) { - printk("Timeout waiting for DC-DC calibration on module %d\n", card); - return -1; - } - } - -#if 0 - /* Wait a full two seconds */ - while((jiffies - origjiffies) < 2 * HZ); - - /* Just check to be sure */ - vbat = wctdm_getreg(wc, card, 82); - printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n", - card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ))); -#endif -#endif - return 0; - -} - -static int wctdm_proslic_manual_calibrate(struct wctdm *wc, int card){ - unsigned long origjiffies; - unsigned char i; - - wctdm_setreg(wc, card, 21, 0);//(0) Disable all interupts in DR21 - wctdm_setreg(wc, card, 22, 0);//(0)Disable all interupts in DR21 - wctdm_setreg(wc, card, 23, 0);//(0)Disable all interupts in DR21 - wctdm_setreg(wc, card, 64, 0);//(0) - - wctdm_setreg(wc, card, 97, 0x18); //(0x18)Calibrations without the ADC and DAC offset and without common mode calibration. - wctdm_setreg(wc, card, 96, 0x47); //(0x47) Calibrate common mode and differential DAC mode DAC + ILIM - - origjiffies=jiffies; - while( wctdm_getreg(wc,card,96)!=0 ){ - if((jiffies-origjiffies)>80) - return -1; - } -//Initialized DR 98 and 99 to get consistant results. -// 98 and 99 are the results registers and the search should have same intial conditions. - -/*******************************The following is the manual gain mismatch calibration****************************/ -/*******************************This is also available as a function *******************************************/ - // Delay 10ms - origjiffies=jiffies; - while((jiffies-origjiffies)<1); - wctdm_proslic_setreg_indirect(wc, card, 88,0); - wctdm_proslic_setreg_indirect(wc,card,89,0); - wctdm_proslic_setreg_indirect(wc,card,90,0); - wctdm_proslic_setreg_indirect(wc,card,91,0); - wctdm_proslic_setreg_indirect(wc,card,92,0); - wctdm_proslic_setreg_indirect(wc,card,93,0); - - wctdm_setreg(wc, card, 98,0x10); // This is necessary if the calibration occurs other than at reset time - wctdm_setreg(wc, card, 99,0x10); - - for ( i=0x1f; i>0; i--) - { - wctdm_setreg(wc, card, 98,i); - origjiffies=jiffies; - while((jiffies-origjiffies)<4); - if((wctdm_getreg(wc,card,88)) == 0) - break; - } // for - - for ( i=0x1f; i>0; i--) - { - wctdm_setreg(wc, card, 99,i); - origjiffies=jiffies; - while((jiffies-origjiffies)<4); - if((wctdm_getreg(wc,card,89)) == 0) - break; - }//for - -/*******************************The preceding is the manual gain mismatch calibration****************************/ -/**********************************The following is the longitudinal Balance Cal***********************************/ - wctdm_setreg(wc,card,64,1); - while((jiffies-origjiffies)<10); // Sleep 100? - - wctdm_setreg(wc, card, 64, 0); - wctdm_setreg(wc, card, 23, 0x4); // enable interrupt for the balance Cal - wctdm_setreg(wc, card, 97, 0x1); // this is a singular calibration bit for longitudinal calibration - wctdm_setreg(wc, card, 96,0x40); - - wctdm_getreg(wc,card,96); /* Read Reg 96 just cause */ - - wctdm_setreg(wc, card, 21, 0xFF); - wctdm_setreg(wc, card, 22, 0xFF); - wctdm_setreg(wc, card, 23, 0xFF); - - /**The preceding is the longitudinal Balance Cal***/ - return(0); - -} -#if 1 -static int wctdm_proslic_calibrate(struct wctdm *wc, int card) -{ - unsigned long origjiffies; - int x; - /* Perform all calibrations */ - wctdm_setreg(wc, card, 97, 0x1f); - - /* Begin, no speedup */ - wctdm_setreg(wc, card, 96, 0x5f); - - /* Wait for it to finish */ - origjiffies = jiffies; - while(wctdm_getreg(wc, card, 96)) { - if ((jiffies - origjiffies) > 2 * HZ) { - printk("Timeout waiting for calibration of module %d\n", card); - return -1; - } - } - - if (debug) { - /* Print calibration parameters */ - printk("Calibration Vector Regs 98 - 107: \n"); - for (x=98;x<108;x++) { - printk("%d: %02x\n", x, wctdm_getreg(wc, card, x)); - } - } - return 0; -} -#endif - -static void wait_just_a_bit(int foo) -{ - long newjiffies; - newjiffies = jiffies + foo; - while(jiffies < newjiffies); -} - -/********************************************************************* - * Set the hwgain on the analog modules - * - * card = the card position for this module (0-23) - * gain = gain in dB x10 (e.g. -3.5dB would be gain=-35) - * tx = (0 for rx; 1 for tx) - * - *******************************************************************/ -static int wctdm_set_hwgain(struct wctdm *wc, int card, __s32 gain, __u32 tx) -{ - if (!(wc->modtype[card] == MOD_TYPE_FXO)) { - printk("Cannot adjust gain. Unsupported module type!\n"); - return -1; - } - if (tx) { - if (debug) - printk("setting FXO tx gain for card=%d to %d\n", card, gain); - if (gain >= -150 && gain <= 0) { - wctdm_setreg(wc, card, 38, 16 + (gain/-10)); - wctdm_setreg(wc, card, 40, 16 + (-gain%10)); - } else if (gain <= 120 && gain > 0) { - wctdm_setreg(wc, card, 38, gain/10); - wctdm_setreg(wc, card, 40, (gain%10)); - } else { - printk("FXO tx gain is out of range (%d)\n", gain); - return -1; - } - } else { /* rx */ - if (debug) - printk("setting FXO rx gain for card=%d to %d\n", card, gain); - if (gain >= -150 && gain <= 0) { - wctdm_setreg(wc, card, 39, 16+ (gain/-10)); - wctdm_setreg(wc, card, 41, 16 + (-gain%10)); - } else if (gain <= 120 && gain > 0) { - wctdm_setreg(wc, card, 39, gain/10); - wctdm_setreg(wc, card, 41, (gain%10)); - } else { - printk("FXO rx gain is out of range (%d)\n", gain); - return -1; - } - } - - return 0; -} - -static int wctdm_init_voicedaa(struct wctdm *wc, int card, int fast, int manual, int sane) -{ - unsigned char reg16=0, reg26=0, reg30=0, reg31=0; - long newjiffies; - wc->modtype[card] = MOD_TYPE_FXO; - /* Sanity check the ProSLIC */ - reset_spi(wc, card); - if (!sane && wctdm_voicedaa_insane(wc, card)) - return -2; - - /* Software reset */ - wctdm_setreg(wc, card, 1, 0x80); - - /* Wait just a bit */ - wait_just_a_bit(HZ/10); - - /* Enable PCM, ulaw */ - if (alawoverride) - wctdm_setreg(wc, card, 33, 0x20); - else - wctdm_setreg(wc, card, 33, 0x28); - - /* Set On-hook speed, Ringer impedence, and ringer threshold */ - reg16 |= (fxo_modes[_opermode].ohs << 6); - reg16 |= (fxo_modes[_opermode].rz << 1); - reg16 |= (fxo_modes[_opermode].rt); - wctdm_setreg(wc, card, 16, reg16); - - if(fwringdetect) { - /* Enable ring detector full-wave rectifier mode */ - wctdm_setreg(wc, card, 18, 2); - wctdm_setreg(wc, card, 24, 0); - } else { - /* Set to the device defaults */ - wctdm_setreg(wc, card, 18, 0); - wctdm_setreg(wc, card, 24, 0x19); - } - - /* Set DC Termination: - Tip/Ring voltage adjust, minimum operational current, current limitation */ - reg26 |= (fxo_modes[_opermode].dcv << 6); - reg26 |= (fxo_modes[_opermode].mini << 4); - reg26 |= (fxo_modes[_opermode].ilim << 1); - wctdm_setreg(wc, card, 26, reg26); - - /* Set AC Impedence */ - reg30 = (fxo_modes[_opermode].acim); - wctdm_setreg(wc, card, 30, reg30); - - /* Misc. DAA parameters */ - if (fastpickup) - reg31 = 0xb3; - else - reg31 = 0xa3; - - reg31 |= (fxo_modes[_opermode].ohs2 << 3); - wctdm_setreg(wc, card, 31, reg31); - - /* Set Transmit/Receive timeslot */ - wctdm_setreg(wc, card, 34, (3-card) * 8); - wctdm_setreg(wc, card, 35, 0x00); - wctdm_setreg(wc, card, 36, (3-card) * 8); - wctdm_setreg(wc, card, 37, 0x00); - - /* Enable ISO-Cap */ - wctdm_setreg(wc, card, 6, 0x00); - - if (fastpickup) - wctdm_setreg(wc, card, 17, wctdm_getreg(wc, card, 17) | 0x20); - - /* Wait 1000ms for ISO-cap to come up */ - newjiffies = jiffies; - newjiffies += 2 * HZ; - while((jiffies < newjiffies) && !(wctdm_getreg(wc, card, 11) & 0xf0)) - wait_just_a_bit(HZ/10); - - if (!(wctdm_getreg(wc, card, 11) & 0xf0)) { - printk("VoiceDAA did not bring up ISO link properly!\n"); - return -1; - } - if (debug) - printk("ISO-Cap is now up, line side: %02x rev %02x\n", - wctdm_getreg(wc, card, 11) >> 4, - (wctdm_getreg(wc, card, 13) >> 2) & 0xf); - /* Enable on-hook line monitor */ - wctdm_setreg(wc, card, 5, 0x08); - - /* Take values for fxotxgain and fxorxgain and apply them to module */ - wctdm_set_hwgain(wc, card, fxotxgain, 1); - wctdm_set_hwgain(wc, card, fxorxgain, 0); - - /* NZ -- crank the tx gain up by 7 dB */ - if (!strcmp(fxo_modes[_opermode].name, "NEWZEALAND")) { - printk("Adjusting gain\n"); - wctdm_set_hwgain(wc, card, 7, 1); - } - - if(debug) - printk("DEBUG fxotxgain:%i.%i fxorxgain:%i.%i\n", (wctdm_getreg(wc, card, 38)/16)?-(wctdm_getreg(wc, card, 38) - 16) : wctdm_getreg(wc, card, 38), (wctdm_getreg(wc, card, 40)/16)? -(wctdm_getreg(wc, card, 40) - 16):wctdm_getreg(wc, card, 40), (wctdm_getreg(wc, card, 39)/16)? -(wctdm_getreg(wc, card, 39) - 16) : wctdm_getreg(wc, card, 39),(wctdm_getreg(wc, card, 41)/16)?-(wctdm_getreg(wc, card, 41) - 16):wctdm_getreg(wc, card, 41)); - - /* battery state still unknown */ - wc->mod[card].fxo.battery = -1; - - return 0; - -} - -static int wctdm_init_proslic(struct wctdm *wc, int card, int fast, int manual, int sane) -{ - - unsigned short tmp[5]; - unsigned char r19,r9; - int x; - int fxsmode=0; - - /* Sanity check the ProSLIC */ - if (!sane && wctdm_proslic_insane(wc, card)) - return -2; - - /* By default, don't send on hook */ - if (reversepolarity) - wc->mod[card].fxs.idletxhookstate = 5; - else - wc->mod[card].fxs.idletxhookstate = 1; - - if (sane) { - /* Make sure we turn off the DC->DC converter to prevent anything from blowing up */ - wctdm_setreg(wc, card, 14, 0x10); - } - - if (wctdm_proslic_init_indirect_regs(wc, card)) { - printk(KERN_INFO "Indirect Registers failed to initialize on module %d.\n", card); - return -1; - } - - /* Clear scratch pad area */ - wctdm_proslic_setreg_indirect(wc, card, 97,0); - - /* Clear digital loopback */ - wctdm_setreg(wc, card, 8, 0); - - /* Revision C optimization */ - wctdm_setreg(wc, card, 108, 0xeb); - - /* Disable automatic VBat switching for safety to prevent - Q7 from accidently turning on and burning out. */ - wctdm_setreg(wc, card, 67, 0x07); /* Note, if pulse dialing has problems at high REN loads - change this to 0x17 */ - - /* Turn off Q7 */ - wctdm_setreg(wc, card, 66, 1); - - /* Flush ProSLIC digital filters by setting to clear, while - saving old values */ - for (x=0;x<5;x++) { - tmp[x] = wctdm_proslic_getreg_indirect(wc, card, x + 35); - wctdm_proslic_setreg_indirect(wc, card, x + 35, 0x8000); - } - - /* Power up the DC-DC converter */ - if (wctdm_powerup_proslic(wc, card, fast)) { - printk("Unable to do INITIAL ProSLIC powerup on module %d\n", card); - return -1; - } - - if (!fast) { - - /* Check for power leaks */ - if (wctdm_proslic_powerleak_test(wc, card)) { - printk("ProSLIC module %d failed leakage test. Check for short circuit\n", card); - } - /* Power up again */ - if (wctdm_powerup_proslic(wc, card, fast)) { - printk("Unable to do FINAL ProSLIC powerup on module %d\n", card); - return -1; - } -#ifndef NO_CALIBRATION - /* Perform calibration */ - if(manual) { - if (wctdm_proslic_manual_calibrate(wc, card)) { - //printk("Proslic failed on Manual Calibration\n"); - if (wctdm_proslic_manual_calibrate(wc, card)) { - printk("Proslic Failed on Second Attempt to Calibrate Manually. (Try -DNO_CALIBRATION in Makefile)\n"); - return -1; - } - printk("Proslic Passed Manual Calibration on Second Attempt\n"); - } - } - else { - if(wctdm_proslic_calibrate(wc, card)) { - //printk("ProSlic died on Auto Calibration.\n"); - if (wctdm_proslic_calibrate(wc, card)) { - printk("Proslic Failed on Second Attempt to Auto Calibrate\n"); - return -1; - } - printk("Proslic Passed Auto Calibration on Second Attempt\n"); - } - } - /* Perform DC-DC calibration */ - wctdm_setreg(wc, card, 93, 0x99); - r19 = wctdm_getreg(wc, card, 107); - if ((r19 < 0x2) || (r19 > 0xd)) { - printk("DC-DC cal has a surprising direct 107 of 0x%02x!\n", r19); - wctdm_setreg(wc, card, 107, 0x8); - } - - /* Save calibration vectors */ - for (x=0;xmod[card].fxs.calregs.vals[x] = wctdm_getreg(wc, card, 96 + x); -#endif - - } else { - /* Restore calibration registers */ - for (x=0;xmod[card].fxs.calregs.vals[x]); - } - /* Calibration complete, restore original values */ - for (x=0;x<5;x++) { - wctdm_proslic_setreg_indirect(wc, card, x + 35, tmp[x]); - } - - if (wctdm_proslic_verify_indirect_regs(wc, card)) { - printk(KERN_INFO "Indirect Registers failed verification.\n"); - return -1; - } - - -#if 0 - /* Disable Auto Power Alarm Detect and other "features" */ - wctdm_setreg(wc, card, 67, 0x0e); - blah = wctdm_getreg(wc, card, 67); -#endif - -#if 0 - if (wctdm_proslic_setreg_indirect(wc, card, 97, 0x0)) { // Stanley: for the bad recording fix - printk(KERN_INFO "ProSlic IndirectReg Died.\n"); - return -1; - } -#endif - - if (alawoverride) - wctdm_setreg(wc, card, 1, 0x20); - else - wctdm_setreg(wc, card, 1, 0x28); - // U-Law 8-bit interface - wctdm_setreg(wc, card, 2, (3-card) * 8); // Tx Start count low byte 0 - wctdm_setreg(wc, card, 3, 0); // Tx Start count high byte 0 - wctdm_setreg(wc, card, 4, (3-card) * 8); // Rx Start count low byte 0 - wctdm_setreg(wc, card, 5, 0); // Rx Start count high byte 0 - wctdm_setreg(wc, card, 18, 0xff); // clear all interrupt - wctdm_setreg(wc, card, 19, 0xff); - wctdm_setreg(wc, card, 20, 0xff); - wctdm_setreg(wc, card, 73, 0x04); - if (fxshonormode) { - fxsmode = acim2tiss[fxo_modes[_opermode].acim]; - wctdm_setreg(wc, card, 10, 0x08 | fxsmode); - if (fxo_modes[_opermode].ring_osc) - wctdm_proslic_setreg_indirect(wc, card, 20, fxo_modes[_opermode].ring_osc); - if (fxo_modes[_opermode].ring_x) - wctdm_proslic_setreg_indirect(wc, card, 21, fxo_modes[_opermode].ring_x); - } - if (lowpower) - wctdm_setreg(wc, card, 72, 0x10); - -#if 0 - wctdm_setreg(wc, card, 21, 0x00); // enable interrupt - wctdm_setreg(wc, card, 22, 0x02); // Loop detection interrupt - wctdm_setreg(wc, card, 23, 0x01); // DTMF detection interrupt -#endif - -#if 0 - /* Enable loopback */ - wctdm_setreg(wc, card, 8, 0x2); - wctdm_setreg(wc, card, 14, 0x0); - wctdm_setreg(wc, card, 64, 0x0); - wctdm_setreg(wc, card, 1, 0x08); -#endif - - if (fastringer) { - /* Speed up Ringer */ - wctdm_proslic_setreg_indirect(wc, card, 20, 0x7e6d); - wctdm_proslic_setreg_indirect(wc, card, 21, 0x01b9); - /* Beef up Ringing voltage to 89V */ - if (boostringer) { - wctdm_setreg(wc, card, 74, 0x3f); - if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x247)) - return -1; - printk("Boosting fast ringer on slot %d (89V peak)\n", card + 1); - } else if (lowpower) { - if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x14b)) - return -1; - printk("Reducing fast ring power on slot %d (50V peak)\n", card + 1); - } else - printk("Speeding up ringer on slot %d (25Hz)\n", card + 1); - } else { - /* Beef up Ringing voltage to 89V */ - if (boostringer) { - wctdm_setreg(wc, card, 74, 0x3f); - if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x1d1)) - return -1; - printk("Boosting ringer on slot %d (89V peak)\n", card + 1); - } else if (lowpower) { - if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x108)) - return -1; - printk("Reducing ring power on slot %d (50V peak)\n", card + 1); - } - } - - if(fxstxgain || fxsrxgain) { - r9 = wctdm_getreg(wc, card, 9); - switch (fxstxgain) { - - case 35: - r9+=8; - break; - case -35: - r9+=4; - break; - case 0: - break; - } - - switch (fxsrxgain) { - - case 35: - r9+=2; - break; - case -35: - r9+=1; - break; - case 0: - break; - } - wctdm_setreg(wc,card,9,r9); - } - - if(debug) - printk("DEBUG: fxstxgain:%s fxsrxgain:%s\n",((wctdm_getreg(wc, card, 9)/8) == 1)?"3.5":(((wctdm_getreg(wc,card,9)/4) == 1)?"-3.5":"0.0"),((wctdm_getreg(wc, card, 9)/2) == 1)?"3.5":((wctdm_getreg(wc,card,9)%2)?"-3.5":"0.0")); - - wctdm_setreg(wc, card, 64, 0x01); - return 0; -} - - -static int wctdm_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) -{ - struct wctdm_stats stats; - struct wctdm_regs regs; - struct wctdm_regop regop; - struct wctdm_echo_coefs echoregs; - struct zt_hwgain hwgain; - struct wctdm *wc = chan->pvt; - int x; - switch (cmd) { - case ZT_ONHOOKTRANSFER: - if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) - return -EINVAL; - if (get_user(x, (int *)data)) - return -EFAULT; - wc->mod[chan->chanpos - 1].fxs.ohttimer = x << 3; - if (reversepolarity) - wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 0x6; /* OHT mode when idle */ - else - wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 0x2; - if (wc->mod[chan->chanpos - 1].fxs.lasttxhook == 0x1 || wc->mod[chan->chanpos - 1].fxs.lasttxhook == 0x5) { - /* Apply the change if appropriate */ - if (reversepolarity) - wc->mod[chan->chanpos - 1].fxs.lasttxhook = 0x6; - else - wc->mod[chan->chanpos - 1].fxs.lasttxhook = 0x2; - wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook); - } - break; - case ZT_SETPOLARITY: - if (get_user(x, (int *)data)) - return -EFAULT; - if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) - return -EINVAL; - /* Can't change polarity while ringing or when open */ - if ((wc->mod[chan->chanpos -1 ].fxs.lasttxhook == 0x04) || - (wc->mod[chan->chanpos -1 ].fxs.lasttxhook == 0x00)) - return -EINVAL; - - if ((x && !reversepolarity) || (!x && reversepolarity)) - wc->mod[chan->chanpos - 1].fxs.lasttxhook |= 0x04; - else - wc->mod[chan->chanpos - 1].fxs.lasttxhook &= ~0x04; - wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook); - break; - case WCTDM_GET_STATS: - if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { - stats.tipvolt = wctdm_getreg(wc, chan->chanpos - 1, 80) * -376; - stats.ringvolt = wctdm_getreg(wc, chan->chanpos - 1, 81) * -376; - stats.batvolt = wctdm_getreg(wc, chan->chanpos - 1, 82) * -376; - } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { - stats.tipvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; - stats.ringvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; - stats.batvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; - } else - return -EINVAL; - if (copy_to_user((struct wctdm_stats *)data, &stats, sizeof(stats))) - return -EFAULT; - break; - case WCTDM_GET_REGS: - if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { - for (x=0;xchanpos -1, x); - for (x=0;xchanpos - 1, x); - } else { - memset(®s, 0, sizeof(regs)); - for (x=0;xchanpos - 1, x); - } - if (copy_to_user((struct wctdm_regs *)data, ®s, sizeof(regs))) - return -EFAULT; - break; - case WCTDM_SET_REG: - if (copy_from_user(®op, (struct wctdm_regop *)data, sizeof(regop))) - return -EFAULT; - if (regop.indirect) { - if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) - return -EINVAL; - printk("Setting indirect %d to 0x%04x on %d\n", regop.reg, regop.val, chan->chanpos); - wctdm_proslic_setreg_indirect(wc, chan->chanpos - 1, regop.reg, regop.val); - } else { - regop.val &= 0xff; - printk("Setting direct %d to %04x on %d\n", regop.reg, regop.val, chan->chanpos); - wctdm_setreg(wc, chan->chanpos - 1, regop.reg, regop.val); - } - break; - case WCTDM_SET_ECHOTUNE: - printk("-- Setting echo registers: \n"); - if (copy_from_user(&echoregs, (struct wctdm_echo_coefs*)data, sizeof(echoregs))) - return -EFAULT; - - if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { - /* Set the ACIM register */ - wctdm_setreg(wc, chan->chanpos - 1, 30, echoregs.acim); - - /* Set the digital echo canceller registers */ - wctdm_setreg(wc, chan->chanpos - 1, 45, echoregs.coef1); - wctdm_setreg(wc, chan->chanpos - 1, 46, echoregs.coef2); - wctdm_setreg(wc, chan->chanpos - 1, 47, echoregs.coef3); - wctdm_setreg(wc, chan->chanpos - 1, 48, echoregs.coef4); - wctdm_setreg(wc, chan->chanpos - 1, 49, echoregs.coef5); - wctdm_setreg(wc, chan->chanpos - 1, 50, echoregs.coef6); - wctdm_setreg(wc, chan->chanpos - 1, 51, echoregs.coef7); - wctdm_setreg(wc, chan->chanpos - 1, 52, echoregs.coef8); - - printk("-- Set echo registers successfully\n"); - - break; - } else { - return -EINVAL; - - } - break; - case ZT_SET_HWGAIN: - if (copy_from_user(&hwgain, (struct zt_hwgain*) data, sizeof(hwgain))) - return -EFAULT; - - wctdm_set_hwgain(wc, chan->chanpos-1, hwgain.newgain, hwgain.tx); - - if (debug) - printk("Setting hwgain on channel %d to %d for %s direction\n", - chan->chanpos-1, hwgain.newgain, hwgain.tx ? "tx" : "rx"); - break; - default: - return -ENOTTY; - } - return 0; - -} - -static int wctdm_open(struct zt_chan *chan) -{ - struct wctdm *wc = chan->pvt; - if (!(wc->cardflag & (1 << (chan->chanpos - 1)))) - return -ENODEV; - if (wc->dead) - return -ENODEV; - wc->usecount++; -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#else - try_module_get(THIS_MODULE); -#endif - return 0; -} - -static int wctdm_watchdog(struct zt_span *span, int event) -{ - printk("TDM: Restarting DMA\n"); - wctdm_restart_dma(span->pvt); - return 0; -} - -static int wctdm_close(struct zt_chan *chan) -{ - struct wctdm *wc = chan->pvt; - wc->usecount--; -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#else - module_put(THIS_MODULE); -#endif - if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { - if (reversepolarity) - wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 5; - else - wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 1; - } - /* If we're dead, release us now */ - if (!wc->usecount && wc->dead) - wctdm_release(wc); - return 0; -} - -static int wctdm_hooksig(struct zt_chan *chan, zt_txsig_t txsig) -{ - struct wctdm *wc = chan->pvt; - int reg=0; - if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { - /* XXX Enable hooksig for FXO XXX */ - switch(txsig) { - case ZT_TXSIG_START: - case ZT_TXSIG_OFFHOOK: - wc->mod[chan->chanpos - 1].fxo.offhook = 1; - wctdm_setreg(wc, chan->chanpos - 1, 5, 0x9); - break; - case ZT_TXSIG_ONHOOK: - wc->mod[chan->chanpos - 1].fxo.offhook = 0; - wctdm_setreg(wc, chan->chanpos - 1, 5, 0x8); - break; - default: - printk("wcfxo: Can't set tx state to %d\n", txsig); - } - } else { - switch(txsig) { - case ZT_TXSIG_ONHOOK: - switch(chan->sig) { - case ZT_SIG_EM: - case ZT_SIG_FXOKS: - case ZT_SIG_FXOLS: - wc->mod[chan->chanpos-1].fxs.lasttxhook = wc->mod[chan->chanpos-1].fxs.idletxhookstate; - break; - case ZT_SIG_FXOGS: - wc->mod[chan->chanpos-1].fxs.lasttxhook = 3; - break; - } - break; - case ZT_TXSIG_OFFHOOK: - switch(chan->sig) { - case ZT_SIG_EM: - wc->mod[chan->chanpos-1].fxs.lasttxhook = 5; - break; - default: - wc->mod[chan->chanpos-1].fxs.lasttxhook = wc->mod[chan->chanpos-1].fxs.idletxhookstate; - break; - } - break; - case ZT_TXSIG_START: - wc->mod[chan->chanpos-1].fxs.lasttxhook = 4; - break; - case ZT_TXSIG_KEWL: - wc->mod[chan->chanpos-1].fxs.lasttxhook = 0; - break; - default: - printk("wctdm: Can't set tx state to %d\n", txsig); - } - if (debug) - printk("Setting FXS hook state to %d (%02x)\n", txsig, reg); - -#if 1 - wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos-1].fxs.lasttxhook); -#endif - } - return 0; -} - -static int wctdm_initialize(struct wctdm *wc) -{ - int x; - - /* Zapata stuff */ - sprintf(wc->span.name, "WCTDM/%d", wc->pos); - snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1); - snprintf(wc->span.location, sizeof(wc->span.location) - 1, - "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); - wc->span.manufacturer = "Digium"; - strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); - if (alawoverride) { - printk("ALAW override parameter detected. Device will be operating in ALAW\n"); - wc->span.deflaw = ZT_LAW_ALAW; - } else - wc->span.deflaw = ZT_LAW_MULAW; - for (x = 0; x < NUM_CARDS; x++) { - sprintf(wc->chans[x].name, "WCTDM/%d/%d", wc->pos, x); - wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR; - wc->chans[x].sigcap |= ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR; - wc->chans[x].chanpos = x+1; - wc->chans[x].pvt = wc; - } - wc->span.chans = wc->chans; - wc->span.channels = NUM_CARDS; - wc->span.hooksig = wctdm_hooksig; - wc->span.irq = wc->dev->irq; - wc->span.open = wctdm_open; - wc->span.close = wctdm_close; - wc->span.flags = ZT_FLAG_RBS; - wc->span.ioctl = wctdm_ioctl; - wc->span.watchdog = wctdm_watchdog; - init_waitqueue_head(&wc->span.maintq); - - wc->span.pvt = wc; - if (zt_register(&wc->span, 0)) { - printk("Unable to register span with zaptel\n"); - return -1; - } - return 0; -} - -static void wctdm_post_initialize(struct wctdm *wc) -{ - int x; - - /* Finalize signalling */ - for (x = 0; x < NUM_CARDS; x++) { - if (wc->cardflag & (1 << x)) { - if (wc->modtype[x] == MOD_TYPE_FXO) - wc->chans[x].sigcap = ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR; - else - wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR; - } else if (!(wc->chans[x].sigcap & ZT_SIG_BROKEN)) { - wc->chans[x].sigcap = 0; - } - } -} - -static int wctdm_hardware_init(struct wctdm *wc) -{ - /* Hardware stuff */ - unsigned char ver; - unsigned char x,y; - int failed; - - /* Signal Reset */ - outb(0x01, wc->ioaddr + WC_CNTL); - - /* Check Freshmaker chip */ - x=inb(wc->ioaddr + WC_CNTL); - ver = __wctdm_getcreg(wc, WC_VER); - failed = 0; - if (ver != 0x59) { - printk("Freshmaker version: %02x\n", ver); - for (x=0;x<255;x++) { - /* Test registers */ - if (ver >= 0x70) { - __wctdm_setcreg(wc, WC_CS, x); - y = __wctdm_getcreg(wc, WC_CS); - } else { - __wctdm_setcreg(wc, WC_TEST, x); - y = __wctdm_getcreg(wc, WC_TEST); - } - if (x != y) { - printk("%02x != %02x\n", x, y); - failed++; - } - } - if (!failed) { - printk("Freshmaker passed register test\n"); - } else { - printk("Freshmaker failed register test\n"); - return -1; - } - /* Go to half-duty FSYNC */ - __wctdm_setcreg(wc, WC_SYNC, 0x01); - y = __wctdm_getcreg(wc, WC_SYNC); - } else { - printk("No freshmaker chip\n"); - } - - /* Reset PCI Interface chip and registers (and serial) */ - outb(0x06, wc->ioaddr + WC_CNTL); - /* Setup our proper outputs for when we switch for our "serial" port */ - wc->ios = BIT_CS | BIT_SCLK | BIT_SDI; - - outb(wc->ios, wc->ioaddr + WC_AUXD); - - /* Set all to outputs except AUX 5, which is an input */ - outb(0xdf, wc->ioaddr + WC_AUXC); - - /* Select alternate function for AUX0 */ - outb(0x4, wc->ioaddr + WC_AUXFUNC); - - /* Wait 1/4 of a sec */ - wait_just_a_bit(HZ/4); - - /* Back to normal, with automatic DMA wrap around */ - outb(0x30 | 0x01, wc->ioaddr + WC_CNTL); - - /* Make sure serial port and DMA are out of reset */ - outb(inb(wc->ioaddr + WC_CNTL) & 0xf9, wc->ioaddr + WC_CNTL); - - /* Configure serial port for MSB->LSB operation */ - outb(0xc1, wc->ioaddr + WC_SERCTL); - - /* Delay FSC by 0 so it's properly aligned */ - outb(0x0, wc->ioaddr + WC_FSCDELAY); - - /* Setup DMA Addresses */ - outl(wc->writedma, wc->ioaddr + WC_DMAWS); /* Write start */ - outl(wc->writedma + ZT_CHUNKSIZE * 4 - 4, wc->ioaddr + WC_DMAWI); /* Middle (interrupt) */ - outl(wc->writedma + ZT_CHUNKSIZE * 8 - 4, wc->ioaddr + WC_DMAWE); /* End */ - - outl(wc->readdma, wc->ioaddr + WC_DMARS); /* Read start */ - outl(wc->readdma + ZT_CHUNKSIZE * 4 - 4, wc->ioaddr + WC_DMARI); /* Middle (interrupt) */ - outl(wc->readdma + ZT_CHUNKSIZE * 8 - 4, wc->ioaddr + WC_DMARE); /* End */ - - /* Clear interrupts */ - outb(0xff, wc->ioaddr + WC_INTSTAT); - - /* Wait 1/4 of a second more */ - wait_just_a_bit(HZ/4); - - for (x = 0; x < NUM_CARDS; x++) { - int sane=0,ret=0,readi=0; -#if 1 - /* Init with Auto Calibration */ - if (!(ret=wctdm_init_proslic(wc, x, 0, 0, sane))) { - wc->cardflag |= (1 << x); - if (debug) { - readi = wctdm_getreg(wc,x,LOOP_I_LIMIT); - printk("Proslic module %d loop current is %dmA\n",x, - ((readi*3)+20)); - } - printk("Module %d: Installed -- AUTO FXS/DPO\n",x); - } else { - if(ret!=-2) { - sane=1; - /* Init with Manual Calibration */ - if (!wctdm_init_proslic(wc, x, 0, 1, sane)) { - wc->cardflag |= (1 << x); - if (debug) { - readi = wctdm_getreg(wc,x,LOOP_I_LIMIT); - printk("Proslic module %d loop current is %dmA\n",x, - ((readi*3)+20)); - } - printk("Module %d: Installed -- MANUAL FXS\n",x); - } else { - printk("Module %d: FAILED FXS (%s)\n", x, fxshonormode ? fxo_modes[_opermode].name : "FCC"); - wc->chans[x].sigcap = __ZT_SIG_FXO | ZT_SIG_BROKEN; - } - } else if (!(ret = wctdm_init_voicedaa(wc, x, 0, 0, sane))) { - wc->cardflag |= (1 << x); - printk("Module %d: Installed -- AUTO FXO (%s mode)\n",x, fxo_modes[_opermode].name); - } else - printk("Module %d: Not installed\n", x); - } -#endif - } - - /* Return error if nothing initialized okay. */ - if (!wc->cardflag && !timingonly) - return -1; - __wctdm_setcreg(wc, WC_SYNC, (wc->cardflag << 1) | 0x1); - return 0; -} - -static void wctdm_enable_interrupts(struct wctdm *wc) -{ - /* Enable interrupts (we care about all of them) */ - outb(0x3f, wc->ioaddr + WC_MASK0); - /* No external interrupts */ - outb(0x00, wc->ioaddr + WC_MASK1); -} - -static void wctdm_restart_dma(struct wctdm *wc) -{ - /* Reset Master and TDM */ - outb(0x01, wc->ioaddr + WC_CNTL); - outb(0x01, wc->ioaddr + WC_OPER); -} - -static void wctdm_start_dma(struct wctdm *wc) -{ - /* Reset Master and TDM */ - outb(0x0f, wc->ioaddr + WC_CNTL); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - outb(0x01, wc->ioaddr + WC_CNTL); - outb(0x01, wc->ioaddr + WC_OPER); -} - -static void wctdm_stop_dma(struct wctdm *wc) -{ - outb(0x00, wc->ioaddr + WC_OPER); -} - -static void wctdm_reset_tdm(struct wctdm *wc) -{ - /* Reset TDM */ - outb(0x0f, wc->ioaddr + WC_CNTL); -} - -static void wctdm_disable_interrupts(struct wctdm *wc) -{ - outb(0x00, wc->ioaddr + WC_MASK0); - outb(0x00, wc->ioaddr + WC_MASK1); -} - -static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int res; - struct wctdm *wc; - struct wctdm_desc *d = (struct wctdm_desc *)ent->driver_data; - int x; - int y; - - for (x=0;x= WC_MAX_IFACES) { - printk("Too many interfaces\n"); - return -EIO; - } - - if (pci_enable_device(pdev)) { - res = -EIO; - } else { - wc = kmalloc(sizeof(struct wctdm), GFP_KERNEL); - if (wc) { - int cardcount = 0; - - ifaces[x] = wc; - memset(wc, 0, sizeof(struct wctdm)); - spin_lock_init(&wc->lock); - wc->curcard = -1; - wc->ioaddr = pci_resource_start(pdev, 0); - wc->dev = pdev; - wc->pos = x; - wc->variety = d->name; - for (y=0;yflags[y] = d->flags; - /* Keep track of whether we need to free the region */ - if (request_region(wc->ioaddr, 0xff, "wctdm")) - wc->freeregion = 1; - - /* Allocate enough memory for two zt chunks, receive and transmit. Each sample uses - 32 bits. Allocate an extra set just for control too */ - wc->writechunk = pci_alloc_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, &wc->writedma); - if (!wc->writechunk) { - printk("wctdm: Unable to allocate DMA-able memory\n"); - if (wc->freeregion) - release_region(wc->ioaddr, 0xff); - return -ENOMEM; - } - - wc->readchunk = wc->writechunk + ZT_MAX_CHUNKSIZE * 2; /* in doublewords */ - wc->readdma = wc->writedma + ZT_MAX_CHUNKSIZE * 8; /* in bytes */ - - if (wctdm_initialize(wc)) { - printk("wctdm: Unable to intialize FXS\n"); - /* Set Reset Low */ - x=inb(wc->ioaddr + WC_CNTL); - outb((~0x1)&x, wc->ioaddr + WC_CNTL); - /* Free Resources */ - free_irq(pdev->irq, wc); - if (wc->freeregion) - release_region(wc->ioaddr, 0xff); - pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma); - kfree(wc); - return -EIO; - } - - /* Enable bus mastering */ - pci_set_master(pdev); - - /* Keep track of which device we are */ - pci_set_drvdata(pdev, wc); - - if (request_irq(pdev->irq, wctdm_interrupt, ZAP_IRQ_SHARED, "wctdm", wc)) { - printk("wctdm: Unable to request IRQ %d\n", pdev->irq); - if (wc->freeregion) - release_region(wc->ioaddr, 0xff); - pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma); - pci_set_drvdata(pdev, NULL); - kfree(wc); - return -EIO; - } - - - if (wctdm_hardware_init(wc)) { - unsigned char x; - - /* Set Reset Low */ - x=inb(wc->ioaddr + WC_CNTL); - outb((~0x1)&x, wc->ioaddr + WC_CNTL); - /* Free Resources */ - free_irq(pdev->irq, wc); - if (wc->freeregion) - release_region(wc->ioaddr, 0xff); - pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma); - pci_set_drvdata(pdev, NULL); - zt_unregister(&wc->span); - kfree(wc); - return -EIO; - - } - - wctdm_post_initialize(wc); - - /* Enable interrupts */ - wctdm_enable_interrupts(wc); - /* Initialize Write/Buffers to all blank data */ - memset((void *)wc->writechunk,0,ZT_MAX_CHUNKSIZE * 2 * 2 * 4); - - /* Start DMA */ - wctdm_start_dma(wc); - - for (x = 0; x < NUM_CARDS; x++) { - if (wc->cardflag & (1 << x)) - cardcount++; - } - - printk("Found a Wildcard TDM: %s (%d modules)\n", wc->variety, cardcount); - res = 0; - } else - res = -ENOMEM; - } - return res; -} - -static void wctdm_release(struct wctdm *wc) -{ - zt_unregister(&wc->span); - if (wc->freeregion) - release_region(wc->ioaddr, 0xff); - kfree(wc); - printk("Freed a Wildcard\n"); -} - -static void __devexit wctdm_remove_one(struct pci_dev *pdev) -{ - struct wctdm *wc = pci_get_drvdata(pdev); - if (wc) { - - /* Stop any DMA */ - wctdm_stop_dma(wc); - wctdm_reset_tdm(wc); - - /* In case hardware is still there */ - wctdm_disable_interrupts(wc); - - /* Immediately free resources */ - pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma); - free_irq(pdev->irq, wc); - - /* Reset PCI chip and registers */ - outb(0x0e, wc->ioaddr + WC_CNTL); - - /* Release span, possibly delayed */ - if (!wc->usecount) - wctdm_release(wc); - else - wc->dead = 1; - } -} - -static struct pci_device_id wctdm_pci_tbl[] = { - { 0xe159, 0x0001, 0xa159, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm }, - { 0xe159, 0x0001, 0xe159, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm }, - { 0xe159, 0x0001, 0xb100, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme }, - { 0xe159, 0x0001, 0xb1d9, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmi }, - { 0xe159, 0x0001, 0xb118, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmi }, - { 0xe159, 0x0001, 0xb119, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmi }, - { 0xe159, 0x0001, 0xa9fd, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, - { 0xe159, 0x0001, 0xa8fd, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, - { 0xe159, 0x0001, 0xa800, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, - { 0xe159, 0x0001, 0xa801, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, - { 0xe159, 0x0001, 0xa908, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, - { 0xe159, 0x0001, 0xa901, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, -#ifdef TDM_REVH_MATCHALL - { 0xe159, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, -#endif - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, wctdm_pci_tbl); - -static struct pci_driver wctdm_driver = { - name: "wctdm", - probe: wctdm_init_one, -#ifdef LINUX26 - remove: __devexit_p(wctdm_remove_one), -#else - remove: wctdm_remove_one, -#endif - suspend: NULL, - resume: NULL, - id_table: wctdm_pci_tbl, -}; - -static int __init wctdm_init(void) -{ - int res; - int x; - for (x=0;x<(sizeof(fxo_modes) / sizeof(fxo_modes[0])); x++) { - if (!strcmp(fxo_modes[x].name, opermode)) - break; - } - if (x < sizeof(fxo_modes) / sizeof(fxo_modes[0])) { - _opermode = x; - } else { - printk("Invalid/unknown operating mode '%s' specified. Please choose one of:\n", opermode); - for (x=0;x"); -#if defined(MODULE_ALIAS) -MODULE_ALIAS("wcfxs"); -#endif -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif - -module_init(wctdm_init); -module_exit(wctdm_cleanup); diff --git a/wctdm.h b/wctdm.h deleted file mode 100644 index 73703aa..0000000 --- a/wctdm.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Wilcard S100P FXS Interface Driver for Zapata Telephony interface - * - * Written by Mark Spencer - * - * Copyright (C) 2001, Linux Support Services, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef _WCTDM_H -#define _WCTDM_H - -#include - -#define NUM_REGS 109 -#define NUM_INDIRECT_REGS 105 - -struct wctdm_stats { - int tipvolt; /* TIP voltage (mV) */ - int ringvolt; /* RING voltage (mV) */ - int batvolt; /* VBAT voltage (mV) */ -}; - -struct wctdm_regs { - unsigned char direct[NUM_REGS]; - unsigned short indirect[NUM_INDIRECT_REGS]; -}; - -struct wctdm_regop { - int indirect; - unsigned char reg; - unsigned short val; -}; - -struct wctdm_echo_coefs { - unsigned char acim; - unsigned char coef1; - unsigned char coef2; - unsigned char coef3; - unsigned char coef4; - unsigned char coef5; - unsigned char coef6; - unsigned char coef7; - unsigned char coef8; -}; - -#define WCTDM_GET_STATS _IOR (ZT_CODE, 60, struct wctdm_stats) -#define WCTDM_GET_REGS _IOR (ZT_CODE, 61, struct wctdm_regs) -#define WCTDM_SET_REG _IOW (ZT_CODE, 62, struct wctdm_regop) -#define WCTDM_SET_ECHOTUNE _IOW (ZT_CODE, 63, struct wctdm_echo_coefs) - - -#endif /* _WCTDM_H */ diff --git a/wctdm24xxp/GpakApi.c b/wctdm24xxp/GpakApi.c deleted file mode 100644 index abdb09f..0000000 --- a/wctdm24xxp/GpakApi.c +++ /dev/null @@ -1,1636 +0,0 @@ -/* - * Copyright (c) 2005, Adaptive Digital Technologies, Inc. - * - * File Name: GpakApi.c - * - * Description: - * This file contains user API functions to communicate with DSPs executing - * G.PAK software. The file is integrated into the host processor connected - * to C55X G.PAK DSPs via a Host Port Interface. - * - * Version: 1.0 - * - * Revision History: - * 06/15/05 - Initial release. - * 11/15/2006 - 24 TDM-TDM Channels EC release - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. The standard - * GPL disclaimer is given inline below for your convenience. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include - -#include "zaptel.h" - -#include "GpakHpi.h" -#include "GpakCust.h" -#include "GpakApi.h" -#include "gpakenum.h" - -/* DSP to Host interface block offsets. */ -#define REPLY_MSG_PNTR_OFFSET 0 /* I/F blk offset to Reply Msg Pointer */ -#define CMD_MSG_PNTR_OFFSET 2 /* I/F blk offset to Command Msg Pointer */ -#define EVENT_MSG_PNTR_OFFSET 4 /* I/F blk offset to Event Msg Pointer */ -#define PKT_BUFR_MEM_OFFSET 6 /* I/F blk offset to Packet Buffer memory */ -#define DSP_STATUS_OFFSET 8 /* I/F blk offset to DSP Status */ -#define VERSION_ID_OFFSET 9 /* I/F blk offset to G.PAK Version Id */ -#define MAX_CMD_MSG_LEN_OFFSET 10 /* I/F blk offset to Max Cmd Msg Length */ -#define CMD_MSG_LEN_OFFSET 11 /* I/F blk offset to Command Msg Length */ -#define REPLY_MSG_LEN_OFFSET 12 /* I/F blk offset to Reply Msg Length */ -#define NUM_CHANNELS_OFFSET 13 /* I/F blk offset to Num Built Channels */ -#define NUM_PKT_CHANNELS_OFFSET 14 /* I/F blk offset to Num Pkt Channels */ -#define NUM_CONFERENCES_OFFSET 15 /* I/F blk offset to Num Conferences */ -//#define CPU_USAGE_OFFSET_1MS 16 /* I/F blk offset to CPU Usage statistics */ -#define CPU_USAGE_OFFSET 18 /* I/F blk offset to CPU Usage statistics */ -//#define CPU_USAGE_OFFSET_10MS 20 /* I/F blk offset to CPU Usage statistics */ -#define FRAMING_STATS_OFFSET 22 /* I/F blk offset to Framing statistics */ - -//#define GPAK_RELEASE_Rate rate10ms -// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -// Macro to reconstruct a 32-bit value from two 16-bit values. -// Parameter p32: 32-bit-wide destination -// Parameter p16: 16-bit-wide source array of length 2 words -#define RECONSTRUCT_LONGWORD(p32, p16) p32 = (DSP_ADDRESS)p16[0]<<16; \ - p32 |= (unsigned long)p16[1] -// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = - -/* DSP Status value definitions. */ -#define DSP_INIT_STATUS 0x5555 /* DSP Initialized status value */ -#define HOST_INIT_STATUS 0xAAAA /* Host Initialized status value */ - -/* Circular packet buffer information structure offsets. */ -#define CB_BUFR_BASE 0 /* pointer to base of circular buffer */ -#define CB_BUFR_SIZE 2 /* size of buffer (words) */ -#define CB_BUFR_PUT_INDEX 3 /* offset in buffer for next write */ -#define CB_BUFR_TAKE_INDEX 4 /* offset in buffer for next read */ -#define CIRC_BUFFER_INFO_STRUCT_SIZE 6 - -/* Miscellaneous definitions. */ -#define MSG_BUFFER_SIZE 100 /* size (words) of Host msg buffer */ -#define WORD_BUFFER_SIZE 84 /* size of DSP Word buffer (words) */ - -#ifdef __TMS320C55XX__ // debug sections if not on host -#pragma DATA_SECTION(pDspIfBlk,"GPAKAPIDEBUG_SECT") -#pragma DATA_SECTION(MaxCmdMsgLen,"GPAKAPIDEBUG_SECT") -#pragma DATA_SECTION(MaxChannels,"GPAKAPIDEBUG_SECT") -#pragma DATA_SECTION(DlByteBufr,"GPAKAPIDEBUG_SECT") -#pragma DATA_SECTION(DlWordBufr,"GPAKAPIDEBUG_SECT") -#pragma DATA_SECTION(pEventFifoAddress,"GPAKAPIDEBUG_SECT") -#endif - -/* Host variables related to Host to DSP interface. */ -static DSP_ADDRESS pDspIfBlk[MAX_DSP_CORES]; /* DSP address of I/F block */ -static DSP_WORD MaxCmdMsgLen[MAX_DSP_CORES]; /* max Cmd msg length (octets) */ -static unsigned short int MaxChannels[MAX_DSP_CORES]; /* max num channels */ - -//static unsigned short int MaxPktChannels[MAX_DSP_CORES]; /* max num pkt channels */ -//static unsigned short int MaxConfs[MAX_DSP_CORES]; /* max num conferences */ -//static DSP_ADDRESS pPktInBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt In buffer */ -//static DSP_ADDRESS pPktOutBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt Out buffer */ -static DSP_ADDRESS pEventFifoAddress[MAX_DSP_CORES]; /* event fifo */ - -static unsigned char DlByteBufr[DOWNLOAD_BLOCK_SIZE * 2]; /* Dowload byte buf */ -static DSP_WORD DlWordBufr[DOWNLOAD_BLOCK_SIZE]; /* Dowload word buffer */ - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CheckDspReset - Check if the DSP was reset. - * - * FUNCTION - * This function determines if the DSP was reset and is ready. If reset - * occurred, it reads interface parameters and calculates DSP addresses. - * - * RETURNS - * -1 = DSP is not ready. - * 0 = Reset did not occur. - * 1 = Reset occurred. - * - */ -static int CheckDspReset( - int DspId /* DSP Identifier (0 to MaxDSPCores-1) */ - ) -{ - DSP_ADDRESS IfBlockPntr; /* Interface Block pointer */ - DSP_WORD DspStatus; /* DSP Status */ - DSP_WORD DspChannels; /* number of DSP channels */ - DSP_WORD Temp[2]; -#if 0 - DSP_WORD DspConfs; /* number of DSP conferences */ - DSP_ADDRESS PktBufrMem; /* address of Packet Buffer */ - unsigned short int i; /* loop index / counter */ -#endif - - /* Read the pointer to the Interface Block. */ - gpakReadDspMemory(DspId, DSP_IFBLK_ADDRESS, 2, Temp); - RECONSTRUCT_LONGWORD(IfBlockPntr, Temp); - - /* If the pointer is zero, return with an indication the DSP is not - ready. */ - if (IfBlockPntr == 0) - return (-1); - - /* Read the DSP's Status. */ - gpakReadDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, &DspStatus); - - /* If status indicates the DSP was reset, read the DSP's interface - parameters and calculate DSP addresses. */ - if (DspStatus == DSP_INIT_STATUS || - ((DspStatus == HOST_INIT_STATUS) && (pDspIfBlk[DspId] == 0))) - { - /* Save the address of the DSP's Interface Block. */ - pDspIfBlk[DspId] = IfBlockPntr; - - /* Read the DSP's interface parameters. */ - gpakReadDspMemory(DspId, IfBlockPntr + MAX_CMD_MSG_LEN_OFFSET, 1, - &(MaxCmdMsgLen[DspId])); - - /* read the number of configured DSP channels */ - gpakReadDspMemory(DspId, IfBlockPntr + NUM_CHANNELS_OFFSET, 1, - &DspChannels); - if (DspChannels > MAX_CHANNELS) - MaxChannels[DspId] = MAX_CHANNELS; - else - MaxChannels[DspId] = (unsigned short int) DspChannels; -#if 0 - /* read the number of configured DSP conferences */ - gpakReadDspMemory(DspId, IfBlockPntr + NUM_CONFERENCES_OFFSET, 1, - &DspConfs); - if (DspConfs > MAX_CONFS) - MaxConfs[DspId] = MAX_CONFS; - else - MaxConfs[DspId] = (unsigned short int) DspConfs; - - - /* read the number of configured DSP packet channels */ - gpakReadDspMemory(DspId, IfBlockPntr + NUM_PKT_CHANNELS_OFFSET, 1, - &DspChannels); - if (DspChannels > MAX_PKT_CHANNELS) - MaxPktChannels[DspId] = MAX_PKT_CHANNELS; - else - MaxPktChannels[DspId] = (unsigned short int) DspChannels; - - - /* read the pointer to the circular buffer infor struct table */ - gpakReadDspMemory(DspId, IfBlockPntr + PKT_BUFR_MEM_OFFSET, 2, Temp); - RECONSTRUCT_LONGWORD(PktBufrMem, Temp); - - - /* Determine the addresses of each channel's Packet buffers. */ - for (i = 0; i < MaxPktChannels[DspId]; i++) - { - pPktInBufr[DspId][i] = PktBufrMem; - pPktOutBufr[DspId][i] = PktBufrMem + CIRC_BUFFER_INFO_STRUCT_SIZE; - PktBufrMem += (CIRC_BUFFER_INFO_STRUCT_SIZE*2); - } -#endif - - /* read the pointer to the event fifo info struct */ - gpakReadDspMemory(DspId, IfBlockPntr + EVENT_MSG_PNTR_OFFSET, 2, Temp); - RECONSTRUCT_LONGWORD(pEventFifoAddress[DspId], Temp); - - /* Set the DSP Status to indicate the host recognized the reset. */ - DspStatus = HOST_INIT_STATUS; - gpakWriteDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, - &DspStatus); - - /* Return with an indication that a reset occurred. */ - return (1); - } - - /* If status doesn't indicate the host recognized a reset, return with an - indication the DSP is not ready. */ - if ((DspStatus != HOST_INIT_STATUS) || (pDspIfBlk[DspId] == 0)) - return (-1); - - /* Return with an indication that a reset did not occur. */ - return (0); -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * WriteDspCmdMessage - Write a Host Command/Request message to DSP. - * - * FUNCTION - * This function writes a Host Command/Request message into DSP memory and - * informs the DSP of the presence of the message. - * - * RETURNS - * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) - * 0 = Temporarily unable to write message (previous Cmd Msg busy) - * 1 = Message written successfully - * - */ -static int WriteDspCmdMessage( - int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ - DSP_WORD *pMessage, /* pointer to Command message */ - DSP_WORD MsgLength /* length of message (octets) */ - ) -{ - DSP_WORD CmdMsgLength; /* current Cmd message length */ - DSP_WORD Temp[2]; - DSP_ADDRESS BufferPointer; /* message buffer pointer */ - - /* Check if the DSP was reset and is ready. */ - if (CheckDspReset(DspId) == -1) - return (-1); - - /* Make sure the message length is valid. */ - if ((MsgLength < 1) || (MsgLength > MaxCmdMsgLen[DspId])) - return (-1); - - /* Make sure a previous Command message is not in use by the DSP. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, - &CmdMsgLength); - if (CmdMsgLength != 0) - return (0); - - /* Purge any previous Reply message that wasn't read. */ - gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, - &CmdMsgLength); - - /* Copy the Command message into DSP memory. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_PNTR_OFFSET, 2, Temp); - RECONSTRUCT_LONGWORD(BufferPointer, Temp); - gpakWriteDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); - - /* Store the message length in DSP's Command message length (flags DSP that - a Command message is ready). */ - CmdMsgLength = MsgLength; - gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, - &CmdMsgLength); - - /* Return with an indication the message was written. */ - return (1); -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * ReadDspReplyMessage - Read a DSP Reply message from DSP. - * - * FUNCTION - * This function reads a DSP Reply message from DSP memory. - * - * RETURNS - * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) - * 0 = No message available (DSP Reply message empty) - * 1 = Message read successfully (message and length stored in variables) - * - */ -static int ReadDspReplyMessage( - int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ - DSP_WORD *pMessage, /* pointer to Reply message buffer */ - DSP_WORD *pMsgLength /* pointer to msg length var (octets) */ - ) -{ - DSP_WORD MsgLength; /* message length */ - DSP_ADDRESS BufferPointer; /* message buffer pointer */ - DSP_WORD Temp[2]; - - /* Check if the DSP was reset and is ready. */ - if (CheckDspReset(DspId) == -1) - return (-1); - - /* Check if a Reply message is ready. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, - &MsgLength); - if (MsgLength == 0) - return (0); - - /* Make sure the message length is valid. */ - if (MsgLength > *pMsgLength) - return (-1); - - /* Copy the Reply message from DSP memory. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_PNTR_OFFSET, 2, Temp); - RECONSTRUCT_LONGWORD(BufferPointer, Temp); - gpakReadDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); - - /* Store the message length in the message length variable. */ - *pMsgLength = MsgLength; - - /* Indicate a Reply message is not ready. */ - MsgLength = 0; - gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, - &MsgLength); - - /* Return with an indication the message was read. */ - return (1); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * ReadCircBuffer - Read from a DSP circular buffer. - * - * FUNCTION - * This function reads a block of words from a DSP circular buffer. The Take - * address is incremented by the number of words read adjusting for buffer - * wrap. - * - * RETURNS - * nothing - * - */ -static void ReadCircBuffer( - int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ - DSP_ADDRESS BufrBaseAddress, /* address of base of circular buffer */ - DSP_ADDRESS BufrLastAddress, /* address of last word in buffer */ - DSP_ADDRESS *TakeAddress, /* pointer to address in buffer for read */ - DSP_WORD *pWordBuffer, /* pointer to buffer for words read */ - DSP_WORD NumWords /* number of words to read */ - ) -{ - DSP_WORD WordsTillEnd; /* number of words until end of buffer */ - - /* Determine the number of words from the start address until the end of the - buffer. */ - WordsTillEnd = BufrLastAddress - *TakeAddress + 1; - - /* If a buffer wrap will occur, read the first part at the end of the - buffer followed by the second part at the beginning of the buffer. */ - if (NumWords > WordsTillEnd) - { - gpakReadDspMemory(DspId, *TakeAddress, WordsTillEnd, pWordBuffer); - gpakReadDspMemory(DspId, BufrBaseAddress, NumWords - WordsTillEnd, - &(pWordBuffer[WordsTillEnd])); - *TakeAddress = BufrBaseAddress + NumWords - WordsTillEnd; - } - - /* If a buffer wrap will not occur, read all words starting at the current - take address in the buffer. */ - else - { - gpakReadDspMemory(DspId, *TakeAddress, NumWords, pWordBuffer); - if (NumWords == WordsTillEnd) - *TakeAddress = BufrBaseAddress; - else - *TakeAddress = *TakeAddress + NumWords; - } - return; -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * VerifyReply - Verify the reply message is correct for the command sent. - * - * FUNCTION - * This function verifies correct reply message content for the command that - * was just sent. - * - * RETURNS - * 0 = Incorrect - * 1 = Correct - * - */ -static int VerifyReply( - DSP_WORD *pMsgBufr, /* pointer to Reply message buffer */ - int CheckType, /* reply check type */ - DSP_WORD CheckValue /* reply check value */ - ) -{ - - /* Verify Channel or Conference Id. */ - if (CheckType == 1) - { - if (((pMsgBufr[1] >> 8) & 0xFF) != CheckValue) - return (0); - } - - /* Verify Test Mode Id. */ - else if (CheckType == 2) - { - if (pMsgBufr[1] != CheckValue) - return (0); - } - - /* Return with an indication of correct reply. */ - return (1); -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * TransactCmd - Send a command to the DSP and receive it's reply. - * - * FUNCTION - * This function sends the specified command to the DSP and receives the DSP's - * reply. - * - * RETURNS - * Length of reply message (0 = Failure) - * - */ -static unsigned int TransactCmd( - int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ - DSP_WORD *pMsgBufr, /* pointer to Cmd/Reply message buffer */ - DSP_WORD CmdLength, /* length of command message (octets) */ - DSP_WORD ReplyType, /* required type of reply message */ - DSP_WORD ReplyLength, /* required length of reply message (octets) */ - int ReplyCheckType, /* reply check type */ - DSP_WORD ReplyCheckValue /* reply check value */ - ) -{ - int FuncStatus; /* function status */ - int LoopCount; /* wait loop counter */ - DSP_WORD RcvReplyLength; /* received Reply message length */ - DSP_WORD RcvReplyType; /* received Reply message type code */ - DSP_WORD RetValue; /* return value */ - - /* Default the return value to indicate a failure. */ - RetValue = 0; - - /* Lock access to the DSP. */ - gpakLockAccess(DspId); - - /* Attempt to write the command message to the DSP. */ - LoopCount = 0; - while ((FuncStatus = WriteDspCmdMessage(DspId, pMsgBufr, CmdLength)) != 1) - { - if (FuncStatus == -1) - break; - if (++LoopCount > MAX_WAIT_LOOPS) - break; - gpakHostDelay(); - } - - /* Attempt to read the reply message from the DSP if the command message was - sent successfully. */ - if (FuncStatus == 1) - { - for (LoopCount = 0; LoopCount < MAX_WAIT_LOOPS; LoopCount++) - { - RcvReplyLength = MSG_BUFFER_SIZE * 2; - FuncStatus = ReadDspReplyMessage(DspId, pMsgBufr, &RcvReplyLength); - if (FuncStatus == 1) - { - RcvReplyType = (pMsgBufr[0] >> 8) & 0xFF; - if ((RcvReplyLength >= ReplyLength) && - (RcvReplyType == ReplyType) && - VerifyReply(pMsgBufr, ReplyCheckType, ReplyCheckValue)) - { - RetValue = RcvReplyLength; - break; - } - else if (RcvReplyType == MSG_NULL_REPLY) - break; - } - else if (FuncStatus == -1) - break; - gpakHostDelay(); - } - } - - /* Unlock access to the DSP. */ - gpakUnlockAccess(DspId); - - /* Return the length of the reply message (0 = failure). */ - return (RetValue); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakConfigurePorts - Configure a DSP's serial ports. - * - * FUNCTION - * This function configures a DSP's serial ports. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakConfigPortStatus_t gpakConfigurePorts( - unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ - GpakPortConfig_t *pPortConfig, /* pointer to Port Config info */ - GPAK_PortConfigStat_t *pStatus /* pointer to Port Config Status */ - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (CpsInvalidDsp); - - /* Build the Configure Serial Ports message. */ - MsgBuffer[0] = MSG_CONFIGURE_PORTS << 8; - MsgBuffer[1] = (DSP_WORD) - ((pPortConfig->SlotsSelect1 << 12) | - ((pPortConfig->FirstBlockNum1 << 8) & 0x0F00) | - ((pPortConfig->SecBlockNum1 << 4) & 0x00F0)); - MsgBuffer[2] = (DSP_WORD) pPortConfig->FirstSlotMask1; - MsgBuffer[3] = (DSP_WORD) pPortConfig->SecSlotMask1; - MsgBuffer[4] = (DSP_WORD) - ((pPortConfig->SlotsSelect2 << 12) | - ((pPortConfig->FirstBlockNum2 << 8) & 0x0F00) | - ((pPortConfig->SecBlockNum2 << 4) & 0x00F0)); - MsgBuffer[5] = (DSP_WORD) pPortConfig->FirstSlotMask2; - MsgBuffer[6] = (DSP_WORD) pPortConfig->SecSlotMask2; - MsgBuffer[7] = (DSP_WORD) - ((pPortConfig->SlotsSelect3 << 12) | - ((pPortConfig->FirstBlockNum3 << 8) & 0x0F00) | - ((pPortConfig->SecBlockNum3 << 4) & 0x00F0)); - MsgBuffer[8] = (DSP_WORD) pPortConfig->FirstSlotMask3; - MsgBuffer[9] = (DSP_WORD) pPortConfig->SecSlotMask3; - - MsgBuffer[10] = (DSP_WORD) - (((pPortConfig->DxDelay1 << 11) & 0x0800) | - ((pPortConfig->RxDataDelay1 << 9) & 0x0600) | - ((pPortConfig->TxDataDelay1 << 7) & 0x0180) | - ((pPortConfig->RxClockPolarity1 << 6) & 0x0040) | - ((pPortConfig->TxClockPolarity1 << 5) & 0x0020) | - ((pPortConfig->RxFrameSyncPolarity1 << 4) & 0x0010) | - ((pPortConfig->TxFrameSyncPolarity1 << 3) & 0x0008) | - ((pPortConfig->CompandingMode1 << 1) & 0x0006) | - (pPortConfig->SerialWordSize1 & 0x0001)); - - MsgBuffer[11] = (DSP_WORD) - (((pPortConfig->DxDelay2 << 11) & 0x0800) | - ((pPortConfig->RxDataDelay2 << 9) & 0x0600) | - ((pPortConfig->TxDataDelay2 << 7) & 0x0180) | - ((pPortConfig->RxClockPolarity2 << 6) & 0x0040) | - ((pPortConfig->TxClockPolarity2 << 5) & 0x0020) | - ((pPortConfig->RxFrameSyncPolarity2 << 4) & 0x0010) | - ((pPortConfig->TxFrameSyncPolarity2 << 3) & 0x0008) | - ((pPortConfig->CompandingMode2 << 1) & 0x0006) | - (pPortConfig->SerialWordSize1 & 0x0001)); - - MsgBuffer[12] = (DSP_WORD) - (((pPortConfig->DxDelay3 << 11) & 0x0800) | - ((pPortConfig->RxDataDelay3 << 9) & 0x0600) | - ((pPortConfig->TxDataDelay3 << 7) & 0x0180) | - ((pPortConfig->RxClockPolarity3 << 6) & 0x0040) | - ((pPortConfig->TxClockPolarity3 << 5) & 0x0020) | - ((pPortConfig->RxFrameSyncPolarity3 << 4) & 0x0010) | - ((pPortConfig->TxFrameSyncPolarity3 << 3) & 0x0008) | - ((pPortConfig->CompandingMode3 << 1) & 0x0006) | - (pPortConfig->SerialWordSize3 & 0x0001)); - - MsgBuffer[13] = (DSP_WORD) pPortConfig->ThirdSlotMask1; - MsgBuffer[14] = (DSP_WORD) pPortConfig->FouthSlotMask1; - MsgBuffer[15] = (DSP_WORD) pPortConfig->FifthSlotMask1; - MsgBuffer[16] = (DSP_WORD) pPortConfig->SixthSlotMask1; - MsgBuffer[17] = (DSP_WORD) pPortConfig->SevenSlotMask1; - MsgBuffer[18] = (DSP_WORD) pPortConfig->EightSlotMask1; - - MsgBuffer[19] = (DSP_WORD) pPortConfig->ThirdSlotMask2;; - MsgBuffer[20] = (DSP_WORD) pPortConfig->FouthSlotMask2; - MsgBuffer[21] = (DSP_WORD) pPortConfig->FifthSlotMask2;; - MsgBuffer[22] = (DSP_WORD) pPortConfig->SixthSlotMask2; - MsgBuffer[23] = (DSP_WORD) pPortConfig->SevenSlotMask2;; - MsgBuffer[24] = (DSP_WORD) pPortConfig->EightSlotMask2; - - MsgBuffer[25] = (DSP_WORD) pPortConfig->ThirdSlotMask3;; - MsgBuffer[26] = (DSP_WORD) pPortConfig->FouthSlotMask3; - MsgBuffer[27] = (DSP_WORD) pPortConfig->FifthSlotMask3;; - MsgBuffer[28] = (DSP_WORD) pPortConfig->SixthSlotMask3; - MsgBuffer[29] = (DSP_WORD) pPortConfig->SevenSlotMask3;; - MsgBuffer[30] = (DSP_WORD) pPortConfig->EightSlotMask3; - - - /* Attempt to send the Configure Serial Ports message to the DSP and receive - it's reply. */ - if (!TransactCmd(DspId, MsgBuffer, 62, MSG_CONFIG_PORTS_REPLY, 4, 0, 0)) - return (CpsDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - *pStatus = (GPAK_PortConfigStat_t) (MsgBuffer[1] & 0xFF); - if (*pStatus == Pc_Success) - return (CpsSuccess); - else - return (CpsParmError); -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakConfigureChannel - Configure a DSP's Channel. - * - * FUNCTION - * This function configures a DSP's Channel. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakConfigChanStatus_t gpakConfigureChannel( - unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ - unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ - GpakChanType ChannelType, /* Channel Type */ - GpakChannelConfig_t *pChanConfig, /* pointer to Channel Config info */ - GPAK_ChannelConfigStat_t *pStatus /* pointer to Channel Config Status */ - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD MsgLength; /* message length */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (CcsInvalidDsp); - - /* Make sure the Channel Id is valid. */ - if (ChannelId >= MaxChannels[DspId]) - return (CcsInvalidChannel); - - /* Build the Configure Channel message based on the Channel Type. */ - switch (ChannelType) - { - - /* PCM to Packet channel type. */ - case tdmToTdm: - - MsgBuffer[2] = (DSP_WORD) - ((pChanConfig->PcmInPortA << 8) | - (pChanConfig->PcmInSlotA & 0xFF)); - MsgBuffer[3] = (DSP_WORD) - ((pChanConfig->PcmOutPortA << 8) | - (pChanConfig->PcmOutSlotA & 0xFF)); - - MsgBuffer[4] = (DSP_WORD) - ((pChanConfig->PcmInPortB << 8) | - (pChanConfig->PcmInSlotB & 0xFF)); - MsgBuffer[5] = (DSP_WORD) - ((pChanConfig->PcmOutPortB << 8) | - (pChanConfig->PcmOutSlotB & 0xFF)); - - MsgBuffer[6] = (DSP_WORD) - ( - ((pChanConfig->FaxCngDetB <<11) & 0x0800) | - ((pChanConfig->FaxCngDetA <<10) & 0x0400) | - ((pChanConfig->MuteToneB << 9) & 0x0200) | - ((pChanConfig->MuteToneA << 8) & 0x0100) | - ((pChanConfig->FrameRate << 6) & 0x00C0) | - ((pChanConfig->ToneTypesB << 5) & 0x0020) | - ((pChanConfig->ToneTypesA << 4) & 0x0010) | - ((pChanConfig->SoftwareCompand & 3) << 2) | - (pChanConfig->EcanEnableB << 1) | - (pChanConfig->EcanEnableA & 1) - ); - - MsgBuffer[7] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanTapLength; - MsgBuffer[8] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNlpType; - MsgBuffer[9] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanAdaptEnable; - MsgBuffer[10] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanG165DetEnable; - MsgBuffer[11] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanDblTalkThresh; - MsgBuffer[12] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNlpThreshold; - MsgBuffer[13] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNlpConv; - MsgBuffer[14] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNlpUnConv; - MsgBuffer[15] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNlpMaxSuppress; - - MsgBuffer[16] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanCngThreshold; - MsgBuffer[17] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanAdaptLimit; - MsgBuffer[18] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanCrossCorrLimit; - MsgBuffer[19] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNumFirSegments; - MsgBuffer[20] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanFirSegmentLen; - - MsgBuffer[21] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanTapLength; - MsgBuffer[22] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNlpType; - MsgBuffer[23] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanAdaptEnable; - MsgBuffer[24] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanG165DetEnable; - MsgBuffer[25] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanDblTalkThresh; - MsgBuffer[26] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNlpThreshold; - MsgBuffer[27] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNlpConv; - MsgBuffer[28] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNlpUnConv; - MsgBuffer[29] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNlpMaxSuppress; - MsgBuffer[30] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanCngThreshold; - MsgBuffer[31] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanAdaptLimit; - MsgBuffer[32] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanCrossCorrLimit; - MsgBuffer[33] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNumFirSegments; - MsgBuffer[34] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanFirSegmentLen; - - MsgLength = 70; // byte number == 35*2 - break; - - - /* Unknown (invalid) channel type. */ - default: - *pStatus = Cc_InvalidChannelType; - return (CcsParmError); - } - - MsgBuffer[0] = MSG_CONFIGURE_CHANNEL << 8; - MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ChannelType & 0xFF)); - - /* Attempt to send the Configure Channel message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, MsgLength, MSG_CONFIG_CHAN_REPLY, 4, 1, - (DSP_WORD) ChannelId)) - return (CcsDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - *pStatus = (GPAK_ChannelConfigStat_t) (MsgBuffer[1] & 0xFF); - if (*pStatus == Cc_Success) - return (CcsSuccess); - else - return (CcsParmError); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakTearDownChannel - Tear Down a DSP's Channel. - * - * FUNCTION - * This function tears down a DSP's Channel. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakTearDownStatus_t gpakTearDownChannel( - unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ - unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ - GPAK_TearDownChanStat_t *pStatus /* pointer to Tear Down Status */ - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (TdsInvalidDsp); - - /* Make sure the Channel Id is valid. */ - if (ChannelId >= MaxChannels[DspId]) - return (TdsInvalidChannel); - - /* Build the Tear Down Channel message. */ - MsgBuffer[0] = MSG_TEAR_DOWN_CHANNEL << 8; - MsgBuffer[1] = (DSP_WORD) (ChannelId << 8); - - /* Attempt to send the Tear Down Channel message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, 3, MSG_TEAR_DOWN_REPLY, 4, 1, - (DSP_WORD) ChannelId)) - return (TdsDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - *pStatus = (GPAK_TearDownChanStat_t) (MsgBuffer[1] & 0xFF); - if (*pStatus == Td_Success) - return (TdsSuccess); - else - return (TdsError); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAlgControl - Control an Algorithm. - * - * FUNCTION - * This function controls an Algorithm - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakAlgControlStat_t gpakAlgControl( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GpakAlgCtrl_t ControlCode, // algorithm control code - GPAK_AlgControlStat_t *pStatus // pointer to return status - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (AcInvalidDsp); - - /* Make sure the Channel Id is valid. */ - if (ChannelId >= MaxChannels[DspId]) - return (AcInvalidChannel); - - MsgBuffer[0] = MSG_ALG_CONTROL << 8; - MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ControlCode & 0xFF)); - - /* Attempt to send the Tear Down Channel message to the DSP and receive it's - reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ALG_CONTROL_REPLY, 4, 1, - (DSP_WORD) ChannelId)) - return (AcDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - *pStatus = (GPAK_AlgControlStat_t) (MsgBuffer[1] & 0xFF); - if (*pStatus == Ac_Success) - return (AcSuccess); - else - return (AcParmError); - -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadEventFIFOMessage - read from the event fifo - * - * FUNCTION - * This function reads a single event from the event fifo if one is available - * - * RETURNS - * Status code indicating success or a specific error. - * - * Notes: This function should be called in a loop until the return status - * indicates that the fifo is empty. - * - * If the event code equals "EventLoopbackTeardownComplete", then the - * contents of *pChannelId hold the coderBlockId that was assigned to - * the loopback coder that was torn down. - */ -gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( - unsigned short int DspId, // DSP identifier - unsigned short int *pChannelId, // pointer to channel identifier - GpakAsyncEventCode_t *pEventCode, // pointer to Event Code - GpakAsyncEventData_t *pEventData // pointer to Event Data Struct - ) -{ - DSP_WORD WordBuffer[WORD_BUFFER_SIZE]; /* DSP words buffer */ - GpakAsyncEventCode_t EventCode; /* DSP's event code */ - DSP_WORD EventDataLength; /* Length of event to read */ - DSP_WORD ChannelId; /* DSP's channel Id */ - DSP_ADDRESS EventInfoAddress; /* address of EventFIFO info structure */ - DSP_ADDRESS BufrBaseAddress; /* base address of EventFIFO buffer */ - DSP_ADDRESS BufrLastAddress; /* last address of EventFIFO buffer */ - DSP_ADDRESS TakeAddress; /* current take address in fifo buffer */ - DSP_WORD BufrSize; /* size (in words) of event FIFO buffer */ - DSP_WORD PutIndex; /* event fifo put index */ - DSP_WORD TakeIndex; /* event fifo take index */ - DSP_WORD WordsReady; /* number words ready for read out of event fifo */ - DSP_WORD EventError; /* flag indicating error with event fifo msg */ -#if 0 - DSP_WORD *pDebugData; /* debug data buffer pointer in event data struct */ -#endif - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) { -#if 0 - printk("Invalid DSP\n"); -#endif - return (RefInvalidDsp); - } - - /* Lock access to the DSP. */ - gpakLockAccess(DspId); - -#if 1 - /* Check if the DSP was reset and is ready. */ - if (CheckDspReset(DspId) == -1) - { - gpakUnlockAccess(DspId); -#if 0 - printk("CheckDspReset failed (DspId %d)\n", DspId); -#endif - return (RefDspCommFailure); - } -#endif - - /* Check if an event message is ready in the DSP. */ - EventInfoAddress = pEventFifoAddress[DspId]; - gpakReadDspMemory(DspId, EventInfoAddress, CIRC_BUFFER_INFO_STRUCT_SIZE, - WordBuffer); - RECONSTRUCT_LONGWORD(BufrBaseAddress, ((DSP_WORD *)&WordBuffer[CB_BUFR_BASE])); - BufrSize = WordBuffer[CB_BUFR_SIZE]; - PutIndex = WordBuffer[CB_BUFR_PUT_INDEX]; - TakeIndex = WordBuffer[CB_BUFR_TAKE_INDEX]; - if (PutIndex >= TakeIndex) - WordsReady = PutIndex - TakeIndex; - else - WordsReady = PutIndex + BufrSize - TakeIndex; - - if (WordsReady < 2) - { - gpakUnlockAccess(DspId); - return (RefNoEventAvail); - } - - /* Read the event header from the DSP's Event FIFO. */ - TakeAddress = BufrBaseAddress + TakeIndex; - BufrLastAddress = BufrBaseAddress + BufrSize - 1; - ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, - WordBuffer, 2); - TakeIndex += 2; - if (TakeIndex >= BufrSize) - TakeIndex -= BufrSize; - - ChannelId = (WordBuffer[0] >> 8) & 0xFF; - EventCode = (GpakAsyncEventCode_t)(WordBuffer[0] & 0xFF); - EventDataLength = WordBuffer[1]; - EventError = 0; - - switch (EventCode) - { - case EventToneDetect: - if (EventDataLength > WORD_BUFFER_SIZE) - { - gpakUnlockAccess(DspId); -#if 0 - printk("EventDataLength > WORD_BUFFER_SIZE (%d)\n", EventDataLength); -#endif - return (RefInvalidEvent); - } - ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, - WordBuffer, EventDataLength); - pEventData->toneEvent.ToneCode = (GpakToneCodes_t) - (WordBuffer[0] & 0xFF); - pEventData->toneEvent.ToneDuration = WordBuffer[1]; - pEventData->toneEvent.Direction = WordBuffer[2]; - pEventData->toneEvent.DebugToneStatus = WordBuffer[3]; - TakeIndex += EventDataLength; - if (TakeIndex >= BufrSize) - TakeIndex -= BufrSize; - if (EventDataLength != 4) { -#if 0 - printk("EventDataLength != 4 it's %d\n", EventDataLength); -#endif - EventError = 1; - } - break; - - default: -#if 0 - printk("Event Code not in switch\n"); -#endif - EventError = 1; - break; - }; - - /* Update the Take index in the DSP's Packet Out buffer information. */ - gpakWriteDspMemory(DspId, EventInfoAddress + CB_BUFR_TAKE_INDEX, 1, - &TakeIndex); - - /* Unlock access to the DSP. */ - gpakUnlockAccess(DspId); - - if (EventError) - return(RefInvalidEvent); - - *pChannelId = ChannelId; - *pEventCode = EventCode; - return(RefEventAvail); - -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakPingDsp - ping the DSP to see if it's alive - * - * FUNCTION - * This function checks if the DSP is still communicating with the host - * and returns the DSP SW version - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakPingDspStat_t gpakPingDsp( - unsigned short int DspId, // DSP identifier - unsigned short int *pDspSwVersion // DSP software version - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (PngInvalidDsp); - - /* send value of 1, DSP increments it */ - MsgBuffer[0] = (MSG_PING << 8); - - /* Attempt to send the ping message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, 1, MSG_PING_REPLY, 6, 0, 0)) - return (PngDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - { - *pDspSwVersion = MsgBuffer[2]; - return (PngSuccess); - } - else - return (PngDspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakSerialTxFixedValue - transmit a fixed value on a timeslot - * - * FUNCTION - * This function controls transmission of a fixed value out onto a serial - * port's timeslot. - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id - unsigned short int PcmOutSlot, // PCM Output Time Slot - unsigned short int Value, // 16-bit value - GpakActivation State // activation state - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (TfvInvalidDsp); - - /* Make sure the Channel Id is valid. */ - if (ChannelId >= MaxChannels[DspId]) - return (TfvInvalidChannel); - - - /* Build the message. */ - MsgBuffer[0] = MSG_SERIAL_TXVAL << 8; - MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (State & 0xFF)); - MsgBuffer[2] = (DSP_WORD) ((PcmOutPort << 8) | (PcmOutSlot & 0xFF)); - MsgBuffer[3] = (DSP_WORD) Value; - - /* Attempt to send the message to the DSP and receive it's - reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 8, MSG_SERIAL_TXVAL_REPLY, 4, - 1, ChannelId)) - return (TfvDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - return (TfvSuccess); - else - return (TfvDspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakControlTdmLoopBack - control a serial port's loopback state - * - * FUNCTION - * This function enables/disables the tdm input to output looback mode on a - * serial port - * - * RETURNS - * Status code indicating success or a specific error. - */ - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ -gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( - unsigned short int DspId, // DSP identifier - GpakSerialPort_t SerialPort, // Serial Port Id - GpakActivation LoopBackState // Loopback State - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (ClbInvalidDsp); - - /* Build the message. */ - MsgBuffer[0] = MSG_TDM_LOOPBACK << 8; - MsgBuffer[1] = (DSP_WORD) ((SerialPort << 8) | (LoopBackState & 0xFF)); - - /* Attempt to send the message to the DSP and receive it's - reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 4, MSG_TDM_LOOPBACK_REPLY, 4, 0, 0)) - return (ClbDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - return (ClbSuccess); - else - return (ClbDspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - Read CPU usage statistics from a DSP. - * - * FUNCTION - * This function reads the CPU usage statistics from a DSP's memory. The - * average CPU usage in units of .1 percent are obtained for each of the frame - * rates. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakReadCpuUsageStat_t gpakReadCpuUsage( - unsigned short int DspId, // Dsp Identifier - unsigned short int *pPeakUsage, // pointer to peak usage variable - unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second - ) -{ - DSP_WORD ReadBuffer[2]; /* DSP read buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RcuInvalidDsp); - - /* Lock access to the DSP. */ - gpakLockAccess(DspId); - - /* Check if the DSP was reset and is ready. */ - if (CheckDspReset(DspId) == -1) - return (RcuDspCommFailure); - - /* Read the CPU Usage statistics from the DSP. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CPU_USAGE_OFFSET, 2, - ReadBuffer); - - /* Unlock access to the DSP. */ - gpakUnlockAccess(DspId); - - /* Store the usage statistics in the specified variables. */ - *pPrev1SecPeakUsage = ReadBuffer[0]; - *pPeakUsage = ReadBuffer[1]; - - /* Return with an indication the usage staistics were read successfully. */ - return (RcuSuccess); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetCpuUsageStats - reset the cpu usage statistics - * - * FUNCTION - * This function resets the cpu utilization statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakResetCpuUsageStat_t gpakResetCpuUsageStats( - unsigned short int DspId // DSP identifier - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RstcInvalidDsp); - - MsgBuffer[0] = (MSG_RESET_USAGE_STATS << 8); - - /* Attempt to send the message to the DSP and receive it's reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_USAGE_STATS_REPLY, 4, 0, 0)) - return (RstcDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - return (RstcSuccess); - else - return (RstcDspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFramingStats - * - * FUNCTION - * This function reads a DSP's framing interrupt statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakReadFramingStatsStatus_t gpakReadFramingStats( - unsigned short int DspId, // DSP identifier - unsigned short int *pFramingError1Count, // port 1 Framing error count - unsigned short int *pFramingError2Count, // port 2 Framing error count - unsigned short int *pFramingError3Count, // port 3 Framing error count - unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count - unsigned short int *pDmaSlipStatsBuffer // DMA slips count - ) -{ - DSP_WORD ReadBuffer[10]; /* DSP read buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RfsInvalidDsp); - - /* Lock access to the DSP. */ - gpakLockAccess(DspId); - - /* Check if the DSP was reset and is ready. */ - if (CheckDspReset(DspId) == -1) - return (RfsDspCommFailure); - - /* Read the framing interrupt statistics from the DSP. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + FRAMING_STATS_OFFSET, 10, - ReadBuffer); - - /* Unlock access to the DSP. */ - gpakUnlockAccess(DspId); - - /* Store the framing statistics in the specified variables. */ - *pFramingError1Count = ReadBuffer[0]; - *pFramingError2Count = ReadBuffer[1]; - *pFramingError3Count = ReadBuffer[2]; - *pDmaStopErrorCount = ReadBuffer[3]; - - if(pDmaSlipStatsBuffer != 0) - // If users want to get the DMA slips count - { - pDmaSlipStatsBuffer[0] = ReadBuffer[4]; - pDmaSlipStatsBuffer[1] = ReadBuffer[5]; - pDmaSlipStatsBuffer[2] = ReadBuffer[6]; - pDmaSlipStatsBuffer[3] = ReadBuffer[7]; - pDmaSlipStatsBuffer[4] = ReadBuffer[8]; - pDmaSlipStatsBuffer[5] = ReadBuffer[9]; - - } - /* Return with an indication the statistics were read successfully. */ - return (RfsSuccess); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - reset a DSP's framing interrupt statistics - * - * FUNCTION - * This function resets a DSP's framing interrupt statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakResetFramingStatsStatus_t gpakResetFramingStats( - unsigned short int DspId // DSP identifier - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RstfInvalidDsp); - - MsgBuffer[0] = (MSG_RESET_FRAME_STATS << 8); - - /* Attempt to send the message to the DSP and receive it's reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_FRAME_STATS_REPLY, 4, 0, 0)) - return (RstfDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - return (RstfSuccess); - else - return (RstfDspCommFailure); -} - -/* - * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. - * - * FUNCTION - * This function reads a DSP's Program and Data memory image from the - * specified file and writes the image to the DSP's memory. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakDownloadStatus_t gpakDownloadDsp( - unsigned short DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ - GPAK_FILE_ID FileId /* G.PAK Download File Identifier */ - ) -{ - gpakDownloadStatus_t RetStatus; /* function return status */ - int NumRead; /* number of file bytes read */ - DSP_ADDRESS Address; /* DSP address */ - unsigned int WordCount; /* number of words in record */ - unsigned int NumWords; /* number of words to read/write */ - unsigned int i; /* loop index / counter */ - unsigned int j; /* loop index */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (GdlInvalidDsp); - - /* Lock access to the DSP. */ - gpakLockAccess(DspId); - - RetStatus = GdlSuccess; - while (RetStatus == GdlSuccess) - { - - /* Read a record header from the file. */ - NumRead = gpakReadFile(FileId, DlByteBufr, 6); - if (NumRead == -1) - { - RetStatus = GdlFileReadError; - break; - } - if (NumRead != 6) - { - RetStatus = GdlInvalidFile; - break; - } - Address = (((DSP_ADDRESS) DlByteBufr[1]) << 16) | - (((DSP_ADDRESS) DlByteBufr[2]) << 8) | - ((DSP_ADDRESS) DlByteBufr[3]); - WordCount = (((unsigned int) DlByteBufr[4]) << 8) | - ((unsigned int) DlByteBufr[5]); - - /* Check for the End Of File record. */ - if (DlByteBufr[0] == 0xFF) - break; - - /* Verify the record is for a valid memory type. */ - if ((DlByteBufr[0] != 0x00) && (DlByteBufr[0] != 0x01)) - { - RetStatus = GdlInvalidFile; - break; - } - - /* Read a block of words at a time from the file and write to the - DSP's memory .*/ - while (WordCount != 0) - { - if (WordCount < DOWNLOAD_BLOCK_SIZE) - NumWords = WordCount; - else - NumWords = DOWNLOAD_BLOCK_SIZE; - WordCount -= NumWords; - NumRead = gpakReadFile(FileId, DlByteBufr, NumWords * 2); - if (NumRead == -1) - { - RetStatus = GdlFileReadError; - break; - } - if (NumRead != (NumWords * 2)) - { - RetStatus = GdlInvalidFile; - break; - } - for (i = 0, j = 0; i < NumWords; i++, j += 2) - DlWordBufr[i] = (((DSP_WORD) DlByteBufr[j]) << 8) | - ((DSP_WORD) DlByteBufr[j + 1]); - gpakWriteDspMemory(DspId, Address, NumWords, DlWordBufr); - Address += ((DSP_ADDRESS) NumWords); - } - } - - /* Unlock access to the DSP. */ - gpakUnlockAccess(DspId); - - /* Return with an indication of success or failure. */ - return (RetStatus); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - Read CPU usage statistics from a DSP. - * - * FUNCTION - * This function reads the memory map register section of DSP memory. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( - unsigned short int DspId, // Dsp Identifier - unsigned short int *pDest, // Buffer on host to hold DSP memory map - DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out - unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP reply's status */ - int i; /* loop index / counter */ - - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RmmInvalidDsp); - - /* Verify the message buffer is large enough */ - if (MSG_BUFFER_SIZE < MemoryLength_Word16 ) - return (RmmSizeTooBig); - - MsgBuffer[0] = MSG_READ_DSP_MEMORY << 8; - MsgBuffer[1] = (DSP_WORD) ((BufrBaseAddress >> 16) & 0xFFFF); - MsgBuffer[2] = (DSP_WORD) (BufrBaseAddress & 0xFFFF); - MsgBuffer[3] = (DSP_WORD) MemoryLength_Word16; - - /* Attempt to send the Read memory section message to the DSP and receive it's - reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 8, MSG_READ_DSP_MEMORY_REPLY, - (MemoryLength_Word16+2)*2, 0, 0) ) - return (RmmInvalidAddress); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus != 0) - return (RmmFailure); - - for (i = 0; i < MemoryLength_Word16; i++) - pDest[i] = (short int) MsgBuffer[2 + i]; - - - return (RmmSuccess); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAccessGPIO - change Direction/read/write the GPIO on DSP - * - * FUNCTION - * This function read/write GPIO and change the GPIO direction - * - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakAccessGPIOStat_t gpakAccessGPIO( - unsigned short int DspId, // DSP identifier - GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read - unsigned short int *pGPIOValue // DSP software version - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (GPIOInvalidDsp); - - /* send value of 1, DSP increments it */ - MsgBuffer[0] = (MSG_ACCESSGPIO << 8); - MsgBuffer[1] = (DSP_WORD) ((gpakControlGPIO << 8) | (*pGPIOValue & 0xFF) ); - /* Attempt to send the ping message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ACCESSGPIO_REPLY, 6, 0, 0)) - return (GPIODspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - { - *pGPIOValue = MsgBuffer[2]; - return (GPIOSuccess); - } - else - return (GPIODspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakWriteSystemParms - Write a DSP's System Parameters. - * - * FUNCTION - * This function writes a DSP's System Parameters information. - * - * Note: - * Or-together the desired bit-mask #defines that are listed below. Only - * those algorithm parameters whose bit-mask is selected in the UpdateBits - * function parameter will be updated. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ - -gpakWriteSysParmsStatus_t gpakWriteSystemParms( - unsigned short int DspId, // DSP identifier - GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ - unsigned short int UpdateBits, /* input: flags indicating which parms to update */ - GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (WspInvalidDsp); - - /* Build the Write System Parameters message. */ - MsgBuffer[0] = MSG_WRITE_SYS_PARMS << 8; - - if (UpdateBits & DTMF_UPDATE_MASK) - { - MsgBuffer[1] |= DTMF_UPDATE_MASK; - MsgBuffer[8] = (DSP_WORD) pSysParms->MinSigLevel; - MsgBuffer[9] = (DSP_WORD) (pSysParms->FreqDeviation & 0xff); - if (pSysParms->SNRFlag) - MsgBuffer[9] |= (1<<8); - } - - MsgBuffer[10] = (DSP_WORD) 0; - if (UpdateBits & DTMF_TWIST_UPDATE_MASK) - { - MsgBuffer[1] |= DTMF_TWIST_UPDATE_MASK; - MsgBuffer[10] |= (DSP_WORD) (pSysParms->DtmfFwdTwist & 0x000f); - MsgBuffer[10] |= (DSP_WORD) ((pSysParms->DtmfRevTwist << 4) & 0x00f0); - } - - - if (UpdateBits & DTMF_VALID_MASK) - { - MsgBuffer[1] |= DTMF_VALID_MASK; - MsgBuffer[11] = (DSP_WORD) (pSysParms->DtmfValidityMask & 0x00ff); - } - - /* Attempt to send the ping message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, 24, MSG_WRITE_SYS_PARMS_REPLY, 6, 0, 0)) - return (WspDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - *pStatus = (GPAK_SysParmsStat_t) (MsgBuffer[2] ); - - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - return (WspSuccess); - else - return (WspDspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadSystemParms - Read a DSP's System Parameters. - * - * FUNCTION - * This function reads a DSP's System Parameters information. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakReadSysParmsStatus_t gpakReadSystemParms( - unsigned short int DspId, // DSP identifier - GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ - ) -{ - - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RspInvalidDsp); - - /* Build the Read System Parameters message. */ - MsgBuffer[0] = MSG_READ_SYS_PARMS << 8; - - /* Attempt to send the ping message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, 2, MSG_READ_SYS_PARMS_REPLY, 22, 0, 0)) - return (RspDspCommFailure); - - /* Extract the System Parameters information from the message. */ - pSysParms->DtmfValidityMask = (short int)(MsgBuffer[7]) ; - - pSysParms->MinSigLevel = (short int)MsgBuffer[8]; - pSysParms->SNRFlag = (short int)((MsgBuffer[9]>>8) & 0x1); - pSysParms->FreqDeviation = (short int)(MsgBuffer[9] & 0xff); - pSysParms->DtmfFwdTwist = (short int)MsgBuffer[10] & 0x000f; - pSysParms->DtmfRevTwist = (short int)(MsgBuffer[10] >> 4) & 0x000f; - - /* Return with an indication that System Parameters info was obtained. */ - return (RspSuccess); -} diff --git a/wctdm24xxp/GpakApi.h b/wctdm24xxp/GpakApi.h deleted file mode 100644 index df57c09..0000000 --- a/wctdm24xxp/GpakApi.h +++ /dev/null @@ -1,637 +0,0 @@ -/* - * Copyright (c) 2005 , Adaptive Digital Technologies, Inc. - * - * File Name: GpakApi.h - * - * Description: - * This file contains the function prototypes and data types for the user - * API functions that communicate with DSPs executing G.PAK software. The - * file is used by application software in the host processor connected to - * C55X G.PAK DSPs via a Host Port Interface. - * - * Version: 1.0 - * - * Revision History: - * 06/15/05 - Initial release. - * 11/15/2006 - 24 TDM-TDM Channels EC release - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. The standard - * GPL disclaimer is given inline below for your convenience. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _GPAKAPI_H /* prevent multiple inclusion */ -#define _GPAKAPI_H -#include "gpakErrs.h" -#include "gpakenum.h" - -// Bit masks to select which algorithm's parameters to update: Or-together the -// desired masks into the UpdateBits function parameter. -#define DTMF_UPDATE_MASK 0x0010 // update DTMF params, MinLevel, SNRFlag and Freq -#define DTMF_TWIST_UPDATE_MASK 0x0020 // update DTMF TWIST system params -#define DTMF_VALID_MASK 0x0080 // update DTMF ValidMask params - -#define DSP_DEBUG_BUFF_SIZE 42 // units of 16-bit words - -/* Definition of an Asynchronous Event Data Structure */ -typedef union -{ - struct - { - GpakToneCodes_t ToneCode; // detected tone code - unsigned short int ToneDuration; // tone duration - GpakTdmDirection Direction; // detected on A r B side - short int DebugToneStatus;// reserved for debug info - } toneEvent; - -} GpakAsyncEventData_t; - -/* Definition of an Echo Canceller Parameters information structure. */ -typedef struct -{ - short int EcanTapLength; // Echo Can Num Taps (tail length) - short int EcanNlpType; // Echo Can NLP Type - short int EcanAdaptEnable; // Echo Can Adapt Enable flag - short int EcanG165DetEnable; // Echo Can G165 Detect Enable flag - short int EcanDblTalkThresh; // Echo Can Double Talk threshold - short int EcanNlpThreshold; // Echo Can NLP threshold - short int EcanNlpConv; // Dynamic NLP control, NLP limit when EC about to converged - short int EcanNlpUnConv;// Dynamic NLP control, NLP limit when EC not converged yet - short int EcanNlpMaxSuppress; // suppression level for NLP_SUPP mode - short int EcanCngThreshold; // Echo Can CNG Noise threshold - short int EcanAdaptLimit; // Echo Can Max Adapts per frame - short int EcanCrossCorrLimit; // Echo Can Cross Correlation limit - short int EcanNumFirSegments; // Echo Can Num FIR Segments - short int EcanFirSegmentLen; // Echo Can FIR Segment Length -} GpakEcanParms_t; - -/* Definition of a Channel Configuration information structure. */ -typedef struct -{ - GpakSerialPort_t PcmInPortA; // A side PCM Input Serial Port Id - unsigned short int PcmInSlotA; // A side PCM Input Time Slot - GpakSerialPort_t PcmOutPortA; // A side PCM Output Serial Port Id - unsigned short int PcmOutSlotA; // A side PCM Output Time Slot - GpakSerialPort_t PcmInPortB; // B side PCM Input Serial Port Id - unsigned short int PcmInSlotB; // B side PCM Input Time Slot - GpakSerialPort_t PcmOutPortB; // B side PCM Output Serial Port Id - unsigned short int PcmOutSlotB; // B side PCM Output Time Slot - GpakToneTypes ToneTypesA; // A side Tone Detect Types - GpakToneTypes ToneTypesB; // B side Tone Detect Types - GpakActivation EcanEnableA; // Echo Cancel A Enabled - GpakActivation EcanEnableB; // Echo Cancel B Enabled - GpakEcanParms_t EcanParametersA; // Echo Cancel parameters - GpakEcanParms_t EcanParametersB; // Echo Cancel parameters - GpakCompandModes SoftwareCompand; // software companding - GpakRate_t FrameRate; // Gpak Frame Rate - GpakActivation MuteToneA; // A side mute DTMF Enabled - GpakActivation MuteToneB; // B side mute DTMF Enabled - GpakActivation FaxCngDetA; // A side FaxCng Tone Detector Enabled - GpakActivation FaxCngDetB; // B side FaxCng Tone Detector Enabled - -} GpakChannelConfig_t; - - -/* Definition of a Serial Port Configuration Structure */ -typedef struct -{ - GpakSlotCfg_t SlotsSelect1; // port 1 Slot selection - unsigned short int FirstBlockNum1; // port 1 first group Block Number - unsigned short int FirstSlotMask1; // port 1 first group Slot Mask - unsigned short int SecBlockNum1; // port 1 second group Block Number - unsigned short int SecSlotMask1; // port 1 second group Slot Mask - - GpakSerWordSize_t SerialWordSize1; // port 1 serial word size - GpakCompandModes CompandingMode1; // port 1 companding mode - GpakSerFrameSyncPol_t TxFrameSyncPolarity1; // port 1 Tx Frame Sync Polarity - GpakSerFrameSyncPol_t RxFrameSyncPolarity1; // port 1 Rx Frame Sync Polarity - GpakSerClockPol_t TxClockPolarity1; // port 1 Tx Clock Polarity - GpakSerClockPol_t RxClockPolarity1; // port 1 Rx Clock Polarity - GpakSerDataDelay_t TxDataDelay1; // port 1 Tx data delay - GpakSerDataDelay_t RxDataDelay1; // port 1 Rx data delay - GpakActivation DxDelay1; // port 1 DX Delay - - unsigned short int ThirdSlotMask1; // port 1 3rd group Slot Mask - unsigned short int FouthSlotMask1; // port 1 4th group Slot Mask - unsigned short int FifthSlotMask1; // port 1 5th group Slot Mask - unsigned short int SixthSlotMask1; // port 1 6th group Slot Mask - unsigned short int SevenSlotMask1; // port 1 7th group Slot Mask - unsigned short int EightSlotMask1; // port 1 8th group Slot Mask - - - GpakSlotCfg_t SlotsSelect2; // port 2 Slot selection - unsigned short int FirstBlockNum2; // port 2 first group Block Number - unsigned short int FirstSlotMask2; // port 2 first group Slot Mask - unsigned short int SecBlockNum2; // port 2 second group Block Number - unsigned short int SecSlotMask2; // port 2 second group Slot Mask - GpakSerWordSize_t SerialWordSize2; // port 2 serial word size - GpakCompandModes CompandingMode2; // port 2 companding mode - GpakSerFrameSyncPol_t TxFrameSyncPolarity2; // port 2 Tx Frame Sync Polarity - GpakSerFrameSyncPol_t RxFrameSyncPolarity2; // port 2 Rx Frame Sync Polarity - GpakSerClockPol_t TxClockPolarity2; // port 2 Tx Clock Polarity - GpakSerClockPol_t RxClockPolarity2; // port 2 Rx Clock Polarity - GpakSerDataDelay_t TxDataDelay2; // port 2 Tx data delay - GpakSerDataDelay_t RxDataDelay2; // port 2 Rx data delay - GpakActivation DxDelay2; // port 2 DX Delay - - unsigned short int ThirdSlotMask2; // port 2 3rd group Slot Mask - unsigned short int FouthSlotMask2; // port 2 4th group Slot Mask - unsigned short int FifthSlotMask2; // port 2 5th group Slot Mask - unsigned short int SixthSlotMask2; // port 2 6th group Slot Mask - unsigned short int SevenSlotMask2; // port 2 7th group Slot Mask - unsigned short int EightSlotMask2; // port 2 8th group Slot Mask - - GpakSlotCfg_t SlotsSelect3; // port 3 Slot selection - unsigned short int FirstBlockNum3; // port 3 first group Block Number - unsigned short int FirstSlotMask3; // port 3 first group Slot Mask - unsigned short int SecBlockNum3; // port 3 second group Block Number - unsigned short int SecSlotMask3; // port 3 second group Slot Mask - GpakSerWordSize_t SerialWordSize3; // port 3 serial word size - GpakCompandModes CompandingMode3; // port 3 companding mode - GpakSerFrameSyncPol_t TxFrameSyncPolarity3; // port 3 Tx Frame Sync Polarity - GpakSerFrameSyncPol_t RxFrameSyncPolarity3; // port 3 Rx Frame Sync Polarity - GpakSerClockPol_t TxClockPolarity3; // port 3 Tx Clock Polarity - GpakSerClockPol_t RxClockPolarity3; // port 3 Rx Clock Polarity - GpakSerDataDelay_t TxDataDelay3; // port 3 Tx data delay - GpakSerDataDelay_t RxDataDelay3; // port 3 Rx data delay - GpakActivation DxDelay3; // port 3 DX Delay - - unsigned short int ThirdSlotMask3; // port 3 3rd group Slot Mask - unsigned short int FouthSlotMask3; // port 3 4th group Slot Mask - unsigned short int FifthSlotMask3; // port 3 5th group Slot Mask - unsigned short int SixthSlotMask3; // port 3 6th group Slot Mask - unsigned short int SevenSlotMask3; // port 3 7th group Slot Mask - unsigned short int EightSlotMask3; // port 3 8th group Slot Mask - -} GpakPortConfig_t; - -/* Definition of a Tone Generation Parameter Structure */ -/* -typedef struct -{ - GpakToneGenType_t ToneType; // Tone Type - unsigned short int Frequency[4]; // Frequency (Hz) - short int Level[4]; // Frequency's Level (1 dBm) - unsigned short int OnTime[4]; // On Times (msecs) - unsigned short int OffTime[4]; // Off Times (msecs) -} GpakToneGenParms_t; -*/ -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakConfigureChannel return status. */ -typedef enum -{ - CcsSuccess = 0, /* Channel Configured successfully */ - CcsParmError = 1, /* Channel Config Parameter error */ - CcsInvalidChannel = 2, /* invalid channel */ - CcsInvalidDsp = 3, /* invalid DSP */ - CcsDspCommFailure = 4 /* failed to communicate with DSP */ -} gpakConfigChanStatus_t; - -/* - * gpakConfigureChannel - Configure a DSP's Channel. - * - * FUNCTION - * This function configures a DSP's Channel. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -extern gpakConfigChanStatus_t gpakConfigureChannel( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GpakChanType ChannelType, // channel type - GpakChannelConfig_t *pChanConfig, // pointer to channel config info - GPAK_ChannelConfigStat_t *pStatus // pointer to Channel Config Status - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakTearDownChannel return status. */ -typedef enum -{ - TdsSuccess = 0, /* Channel Tear Down successful */ - TdsError = 1, /* Channel Tear Down error */ - TdsInvalidChannel = 2, /* invalid channel */ - TdsInvalidDsp = 3, /* invalid DSP */ - TdsDspCommFailure = 4 /* failed to communicate with DSP */ -} gpakTearDownStatus_t; - -/* - * gpakTearDownChannel - Tear Down a DSP's Channel. - * - * FUNCTION - * This function tears down a DSP's Channel. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ - -extern gpakTearDownStatus_t gpakTearDownChannel( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GPAK_TearDownChanStat_t *pStatus // pointer to Tear Down Status - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakAlgControl return status. */ -typedef enum -{ - AcSuccess = 0, /* control successful */ - AcInvalidChannel = 1, /* invalid channel identifier */ - AcInvalidDsp = 2, /* invalid DSP */ - AcParmError = 3, /* invalid control parameter */ - AcDspCommFailure = 4 /* failed to communicate with DSP */ -} gpakAlgControlStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAlgControl - Control an Algorithm. - * - * FUNCTION - * This function controls an Algorithm - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -extern gpakAlgControlStat_t gpakAlgControl( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GpakAlgCtrl_t ControlCode, // algorithm control code - GPAK_AlgControlStat_t *pStatus // pointer to return status - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakConfigurePorts return status. */ -typedef enum -{ - CpsSuccess = 0, /* Serial Ports configured successfully */ - CpsParmError = 1, /* Configure Ports Parameter error */ - CpsInvalidDsp = 2, /* invalid DSP */ - CpsDspCommFailure = 3 /* failed to communicate with DSP */ -} gpakConfigPortStatus_t; - -/* - * gpakConfigurePorts - Configure a DSP's serial ports. - * - * FUNCTION - * This function configures a DSP's serial ports. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -extern gpakConfigPortStatus_t gpakConfigurePorts( - unsigned short int DspId, // DSP identifier - GpakPortConfig_t *pPortConfig, // pointer to Port Config info - GPAK_PortConfigStat_t *pStatus // pointer to Port Config Status - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakDownloadDsp return status. */ -typedef enum -{ - GdlSuccess = 0, /* DSP download successful */ - GdlFileReadError = 1, /* error reading Download file */ - GdlInvalidFile = 2, /* invalid Download file content */ - GdlInvalidDsp = 3 /* invalid DSP */ -} gpakDownloadStatus_t; - -/* - * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. - * - * FUNCTION - * This function reads a DSP's Program and Data memory image from the - * specified file and writes the image to the DSP's memory. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -extern gpakDownloadStatus_t gpakDownloadDsp( - unsigned short int DspId, // DSP identifier - GPAK_FILE_ID FileId // G.PAK download file identifier - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakReadEventFIFOMessage return status */ -typedef enum -{ - RefEventAvail = 0, /* an event was successfully read from the fifo */ - RefNoEventAvail = 1, /* no event was in the fifo */ - RefInvalidDsp = 2, /* invalid DSP identifier */ - RefInvalidEvent = 3, /* invalid event */ - RefDspCommFailure = 4 /* error communicating with DSP */ -} gpakReadEventFIFOMessageStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadEventFIFOMessage - read from the event fifo - * - * FUNCTION - * This function reads a single event from the event fifo if one is available - * - * RETURNS - * Status code indicating success or a specific error. - * - * Note: This function should be called in a loop until the return status - * indicates that the fifo is empty. - */ -extern gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( - unsigned short int DspId, // DSP identifier - unsigned short int *pChannelId, // pointer to channel identifier - GpakAsyncEventCode_t *pEventCode, // pointer to Event Code - GpakAsyncEventData_t *pEventData // pointer to Event Data Struct - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakPingDsp return status values */ -typedef enum -{ - PngSuccess = 0, /* DSP responded successfully */ - PngInvalidDsp = 1, /* invalid DSP identifier */ - PngDspCommFailure = 2 /* error communicating with DSP */ -} gpakPingDspStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakPingDsp - ping the DSP to see if it's alive - * - * FUNCTION - * This function checks if the DSP is still communicating with the host - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakPingDspStat_t gpakPingDsp( - unsigned short int DspId, // DSP identifier - unsigned short int *pDspSwVersion // DSP software version - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakSerialTxFixedValue return status values */ -typedef enum -{ - TfvSuccess = 0, /* operation successful */ - TfvInvalidChannel = 1, /* invalid channel identifier */ - TfvInvalidDsp = 2, /* invalid DSP identifier */ - TfvDspCommFailure = 3 /* failed to communicate with DSP */ -} gpakSerialTxFixedValueStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakSerialTxFixedValue - transmit a fixed value on a timeslot - * - * FUNCTION - * This function controls transmission of a fixed value out onto a serial - * port's timeslot. - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id - unsigned short int PcmOutSlot, // PCM Output Time Slot - unsigned short int Value, // 16-bit value - GpakActivation State // activation state - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakControlTdmLoopBack return status values */ -typedef enum -{ - ClbSuccess = 0, /* operation successful */ - ClbSerPortInactive = 1, /* serial port is inactive */ - ClbInvalidDsp = 2, /* invalid DSP identifier */ - ClbDspCommFailure = 3 /* failed to communicate with DSP */ -} gpakControlTdmLoopBackStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakControlTdmLoopBack - control a serial port's loopback state - * - * FUNCTION - * This function enables/disables the tdm input to output looback mode on a - * serial port - * - * RETURNS - * Status code indicating success or a specific error. - */ - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ -gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( - unsigned short int DspId, // DSP identifier - GpakSerialPort_t SerialPort, // Serial Port Id - GpakActivation LoopBackState // Loopback State - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakReadCpuUsage return status values */ -typedef enum -{ - RcuSuccess = 0, /* operation successful */ - RcuInvalidDsp = 1, /* invalid DSP identifier */ - RcuDspCommFailure = 2 /* communication failure */ -} gpakReadCpuUsageStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - read the cpu usage statistics - * - * FUNCTION - * This function reads cpu utilization from the DSP. - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakReadCpuUsageStat_t gpakReadCpuUsage( - unsigned short int DspId, // DSP identifier - unsigned short int *pPeakUsage, // pointer to peak usage variable - unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakResetCpuUsageStats return status values */ -typedef enum -{ - RstcSuccess = 0, /* operation successful */ - RstcInvalidDsp = 1, /* invalid DSP identifier */ - RstcDspCommFailure = 2 /* communication failure */ -} gpakResetCpuUsageStat_t; -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetCpuUsageStats - reset the cpu usage statistics - * - * FUNCTION - * This function resets the cpu utilization statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakResetCpuUsageStat_t gpakResetCpuUsageStats( - unsigned short int DspId // DSP identifier - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakReadFramingStats return status values */ -typedef enum -{ - RfsSuccess = 0, /* operation successful */ - RfsInvalidDsp = 1, /* invalid DSP identifier */ - RfsDspCommFailure = 2 /* communication failure */ -} gpakReadFramingStatsStatus_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFramingStats - * - * FUNCTION - * This function reads a DSP's framing interrupt statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakReadFramingStatsStatus_t gpakReadFramingStats( - unsigned short int DspId, // DSP identifier - unsigned short int *pFramingError1Count, // port 1 Framing error count - unsigned short int *pFramingError2Count, // port 2 Framing error count - unsigned short int *pFramingError3Count, // port 3 Framing error count - unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count - unsigned short int *pDmaSlipStatsBuffer // DMA slips count - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakResetFramingStats return values */ -typedef enum -{ - RstfSuccess = 0, /* operation successful */ - RstfInvalidDsp = 1, /* invalid DSP identifier */ - RstfDspCommFailure = 2 /* communication failure */ -} gpakResetFramingStatsStatus_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - reset a DSP's framing interrupt statistics - * - * FUNCTION - * This function resets a DSP's framing interrupt statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakResetFramingStatsStatus_t gpakResetFramingStats( - unsigned short int DspId // DSP identifier - ); - - -typedef enum -{ - RmmSuccess =0, - RmmInvalidDsp = 1, - RmmSizeTooBig = 2, - RmmFailure = 3, - RmmInvalidAddress = 4 - -} gpakReadDSPMemoryStat_t; -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - read a section of DSP memory - * to get access DSP registers, since 0x00--0x60 not HPI-accessable - * - * FUNCTION - * This function resets a DSP's framing interrupt statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ - -extern gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( - unsigned short int DspId, // Dsp Identifier - unsigned short int *pDest, // Buffer on host to hold DSP memory map - DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out - unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word - ); - -typedef enum -{ - GPIOSuccess =0, - GPIOInvalidDsp = 1, - GPIODspCommFailure = 2 -}gpakAccessGPIOStat_t; - -extern gpakAccessGPIOStat_t gpakAccessGPIO( - unsigned short int DspId, // DSP identifier - GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read - unsigned short int *pGPIOValue // pointer for the read/write value or DIR mask - ); - -/* gpakWriteSystemParms return status. */ -typedef enum -{ - WspSuccess = 0, /* System Parameters written successfully */ - WspParmError = 1, /* Write System Parms's Parameter error */ - WspInvalidDsp = 2, /* invalid DSP */ - WspDspCommFailure = 3 /* failed to communicate with DSP */ -} gpakWriteSysParmsStatus_t; - -/* Definition of a System Parameters information structure. */ -typedef struct -{ - /* DTMF Parameters */ - short int MinSigLevel; /* 0 = Disabled, Min Sig Power Level for detection */ - short int SNRFlag; /* 0 = Disabled, relax SNR tolerances */ - short int FreqDeviation; /* 0 = Disabled, X Percent Deviation times 10 (e.g. 1.7% is entered as 17) */ - short int DtmfFwdTwist; /* 0 to 8 db */ - short int DtmfRevTwist; /* 0 to 8 db */ - - short int DtmfValidityMask; /* This flag allows users to relax the trailing conditions of the tone */ - -} GpakSystemParms_t; -/* gpakReadSystemParms return status. */ -typedef enum -{ - RspSuccess = 0, /* System Parameters read successfully */ - RspInvalidDsp = 1, /* invalid DSP */ - RspDspCommFailure = 2 /* failed to communicate with DSP */ -} gpakReadSysParmsStatus_t; - -extern gpakReadSysParmsStatus_t gpakReadSystemParms( - unsigned short int DspId, // DSP identifier - GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ - ); - -extern gpakWriteSysParmsStatus_t gpakWriteSystemParms( - unsigned short int DspId, // DSP identifier - GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ - unsigned short int UpdateBits, /* input: flags indicating which parms to update */ - GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ - ); - -#endif // end multiple inclusion - diff --git a/wctdm24xxp/GpakCust.c b/wctdm24xxp/GpakCust.c deleted file mode 100644 index 23f2096..0000000 --- a/wctdm24xxp/GpakCust.c +++ /dev/null @@ -1,476 +0,0 @@ -/* - * Copyright (c) 2005, Adaptive Digital Technologies, Inc. - * - * File Name: GpakCust.c - * - * Description: - * This file contains host system dependent functions to support generic - * G.PAK API functions. The file is integrated into the host processor - * connected to C55x G.PAK DSPs via a Host Port Interface. - * - * Note: This file needs to be modified by the G.PAK system integrator. - * - * Version: 1.0 - * - * Revision History: - * 06/15/05 - Initial release. - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. The standard - * GPL disclaimer is given inline below for your convenience. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include - -#include "zaptel.h" -#include "wctdm24xxp.h" -#include "GpakCust.h" - -char vpm150mtone_to_zaptone(GpakToneCodes_t tone) -{ - switch (tone) { - case DtmfDigit0: - return '0'; - case DtmfDigit1: - return '1'; - case DtmfDigit2: - return '2'; - case DtmfDigit3: - return '3'; - case DtmfDigit4: - return '4'; - case DtmfDigit5: - return '5'; - case DtmfDigit6: - return '6'; - case DtmfDigit7: - return '7'; - case DtmfDigit8: - return '8'; - case DtmfDigit9: - return '9'; - case DtmfDigitPnd: - return '#'; - case DtmfDigitSt: - return '*'; - case DtmfDigitA: - return 'A'; - case DtmfDigitB: - return 'B'; - case DtmfDigitC: - return 'C'; - case DtmfDigitD: - return 'D'; - case EndofCngDigit: - return 'f'; - default: - return 0; - } -} - -static inline struct wctdm * wc_find_iface(unsigned short dspid) -{ - int i; - struct wctdm *ret = NULL; - unsigned long flags; - - spin_lock_irqsave(&ifacelock, flags); - for (i = 0; i < WC_MAX_IFACES; i++) - if (ifaces[i] && ifaces[i]->vpm150m && (ifaces[i]->vpm150m->dspid == dspid)) - ret = ifaces[i]; - spin_unlock_irqrestore(&ifacelock, flags); - - return ret; -} - -static inline struct vpm150m_cmd * vpm150m_empty_slot(struct wctdm *wc) -{ - int x; - - for (x = 0; x < VPM150M_MAX_COMMANDS; x++) - if (!wc->vpm150m->cmdq[x].desc) { - return &wc->vpm150m->cmdq[x]; - } - return NULL; -} - -/* Wait for any outstanding commands to be completed. */ -static inline int vpm150m_io_wait(struct wctdm *wc) -{ - int x; - int ret=0; - for (x=0; x < VPM150M_MAX_COMMANDS;) { - if (wc->vpm150m->cmdq[x].desc) { - if ((ret=schluffen(&wc->regq))) { - return ret; - } - x=0; - } - else { - ++x; - } - } - return ret; -} - -int wctdm_vpm150m_getreg_full_async(struct wctdm *wc, int pagechange, unsigned int len, - unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) -{ - int ret=0; - unsigned long flags; - BUG_ON(!hit_p); - spin_lock_irqsave(&wc->reglock, flags); - (*hit_p) = vpm150m_empty_slot(wc); - if (*hit_p) { - (*hit_p)->desc = __VPM150M_RD; - if (pagechange) { - (*hit_p)->desc |= __VPM150M_RWPAGE; - } - (*hit_p)->datalen = len; - (*hit_p)->addr = addr; - memset((*hit_p)->data, 0, len*sizeof(outbuf[0])); - } - else { - ret = -EBUSY; - } - spin_unlock_irqrestore(&wc->reglock, flags); - return ret; -} - -int wctdm_vpm150m_getreg_full_return(struct wctdm *wc, int pagechange, unsigned int len, - unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) -{ - int ret = 0; - unsigned long flags; - BUG_ON(!hit_p); - spin_lock_irqsave(&wc->reglock, flags); - do { - if ((*hit_p)->desc & __VPM150M_FIN) { - memcpy(outbuf, (*hit_p)->data, len*(sizeof(outbuf[0]))); - (*hit_p)->desc = 0; - (*hit_p) = NULL; - ret = 0; - } - else { - spin_unlock_irqrestore(&wc->reglock, flags); - if ((ret=schluffen(&wc->regq))) { - return ret; - } - spin_lock_irqsave(&wc->reglock, flags); - ret = -EBUSY; - } - } while (-EBUSY == ret); - spin_unlock_irqrestore(&wc->reglock, flags); - return ret; -} - -int wctdm_vpm150m_getreg_full(struct wctdm *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf) -{ - struct vpm150m_cmd *hit = 0; - int ret = 0; - do { - ret = wctdm_vpm150m_getreg_full_async(wc, pagechange, len, addr, outbuf, &hit); - if (!hit) { - if ( -EBUSY == ret ) { - if ((ret = schluffen(&wc->regq))) - return ret; - } - BUG_ON(0 != ret); - } - } while (!hit); - ret = wctdm_vpm150m_getreg_full_return(wc, pagechange, len, addr, outbuf, &hit); - return ret; -} - -int wctdm_vpm150m_setreg_full(struct wctdm *wc, int pagechange, unsigned int len, unsigned int addr, unsigned short *data) -{ - unsigned long flags; - struct vpm150m_cmd *hit; - int ret, i; - do { - spin_lock_irqsave(&wc->reglock, flags); - hit = vpm150m_empty_slot(wc); - if (hit) { - hit->desc = __VPM150M_WR; - if (pagechange) - hit->desc |= __VPM150M_RWPAGE; - hit->addr = addr; - hit->datalen = len; - for (i = 0; i < len; i++) - hit->data[i] = data[i]; - } - spin_unlock_irqrestore(&wc->reglock, flags); - if (!hit) { - if ((ret = schluffen(&wc->regq))) - return ret; - } - } while (!hit); - return (hit) ? 0 : -1; -} - -int wctdm_vpm150m_setpage(struct wctdm *wc, unsigned short addr) -{ - addr &= 0xf; - /* Let's optimize this a little bit */ - if (wc->vpm150m->curpage == addr) - return 0; - else { - wc->vpm150m->curpage = addr; - } - - return wctdm_vpm150m_setreg_full(wc, 1, 1, 0, &addr); -} - -unsigned char wctdm_vpm150m_getpage(struct wctdm *wc) -{ - unsigned short res; - wctdm_vpm150m_getreg_full(wc, 1, 1, 0, &res); - return res; -} - -unsigned short wctdm_vpm150m_getreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data) -{ - unsigned short res; - wctdm_vpm150m_setpage(wc, addr >> 16); - if ((addr >> 16) != ((addr + len) >> 16)) - printk("getreg: You found it!\n"); - res = wctdm_vpm150m_getreg_full(wc, 0, len, addr & 0xffff, data); - return res; -} - -int wctdm_vpm150m_setreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data) -{ - int res; - wctdm_vpm150m_setpage(wc, addr >> 16); - if ((addr >> 16) != ((addr + len) >> 16)) - printk("getreg: You found it!\n"); - res = wctdm_vpm150m_setreg_full(wc, 0, len, addr & 0xffff, data); - return res; -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadDspMemory - Read DSP memory. - * - * FUNCTION - * This function reads a contiguous block of words from DSP memory starting at - * the specified address. - * - * RETURNS - * nothing - * - */ -void gpakReadDspMemory( - unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ - unsigned int NumWords, /* number of contiguous words to read */ - DSP_WORD *pWordValues /* pointer to array of word values variable */ - ) -{ - struct wctdm *wc = wc_find_iface(DspId); - int i; - int transcount; - int ret; - - vpm150m_io_wait(wc); - if ( NumWords < VPM150M_MAX_COMMANDS ) { - struct vpm150m_cmd* cmds[VPM150M_MAX_COMMANDS] = {0}; - wctdm_vpm150m_setpage(wc, DspAddress >> 16); - DspAddress &= 0xffff; - for (i=0; i < NumWords; ++i) { - ret = wctdm_vpm150m_getreg_full_async(wc,0,1,DspAddress+i,&pWordValues[i], - &cmds[i]); - if (0 != ret) { - return; - } - } - for (i=NumWords-1; i >=0; --i) { - ret = wctdm_vpm150m_getreg_full_return(wc,0,1,DspAddress+i,&pWordValues[i], - &cmds[i]); - if (0 != ret) { - return; - } - } - } - else { - for (i = 0; i < NumWords;) { - if ((NumWords - i) > VPM150M_MAX_DATA) - transcount = VPM150M_MAX_DATA; - else - transcount = NumWords - i; - wctdm_vpm150m_getreg(wc, transcount, DspAddress + i, &pWordValues[i]); - i += transcount; - } - } - return; -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakWriteDspMemory - Write DSP memory. - * - * FUNCTION - * This function writes a contiguous block of words to DSP memory starting at - * the specified address. - * - * RETURNS - * nothing - * - */ -void gpakWriteDspMemory( - unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ - unsigned int NumWords, /* number of contiguous words to write */ - DSP_WORD *pWordValues /* pointer to array of word values to write */ - ) -{ - - struct wctdm *wc = wc_find_iface(DspId); - int i; - int transcount; - - //printk("Writing %d words to memory\n", NumWords); - if (wc && wc->vpm150m) { - for (i = 0; i < NumWords;) { - if ((NumWords - i) > VPM150M_MAX_DATA) - transcount = VPM150M_MAX_DATA; - else - transcount = NumWords - i; - - wctdm_vpm150m_setreg(wc, transcount, DspAddress + i, &pWordValues[i]); - i += transcount; - } -#if 0 - for (i = 0; i < NumWords; i++) { - if (wctdm_vpm150m_getreg(wc, DspAddress + i) != pWordValues[i]) { - printk("Error in write. Address %x is not %x\n", DspAddress + i, pWordValues[i]); - } - } -#endif - } - return; - -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakHostDelay - Delay for a fixed time interval. - * - * FUNCTION - * This function delays for a fixed time interval before returning. The time - * interval is the Host Port Interface sampling period when polling a DSP for - * replies to command messages. - * - * RETURNS - * nothing - * - */ -void gpakHostDelay(void) -{ -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakLockAccess - Lock access to the specified DSP. - * - * FUNCTION - * This function aquires exclusive access to the specified DSP. - * - * RETURNS - * nothing - * - */ -void gpakLockAccess(unsigned short DspId) -{ - struct wctdm *wc; - - wc = wc_find_iface(DspId); - - if (wc) { - struct vpm150m *vpm = wc->vpm150m; - - if (vpm) - down_interruptible(&vpm->sem); - } -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakUnlockAccess - Unlock access to the specified DSP. - * - * FUNCTION - * This function releases exclusive access to the specified DSP. - * - * RETURNS - * nothing - * - */ -void gpakUnlockAccess(unsigned short DspId) -{ - struct wctdm *wc; - - wc = wc_find_iface(DspId); - - if (wc) { - struct vpm150m *vpm = wc->vpm150m; - - if (vpm) - up(&vpm->sem); - } -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFile - Read a block of bytes from a G.PAK Download file. - * - * FUNCTION - * This function reads a contiguous block of bytes from a G.PAK Download file - * starting at the current file position. - * - * RETURNS - * The number of bytes read from the file. - * -1 indicates an error occurred. - * 0 indicates all bytes have been read (end of file) - * - */ -int gpakReadFile( - GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ - unsigned char *pBuffer, /* pointer to buffer for storing bytes */ - unsigned int NumBytes /* number of bytes to read */ - ) -{ -#ifdef VPM150M_SUPPORT - struct wctdm_firmware *fw = FileId; - unsigned int i, count; - - if (!fw || !fw->fw) - return -1; - - if (NumBytes > (fw->fw->size - fw->offset)) - count = fw->fw->size - fw->offset; - else - count = NumBytes; - - for (i = 0; i < count; i++) - pBuffer[i] = fw->fw->data[fw->offset + i]; - - fw->offset += count; - - return count; -#endif -} diff --git a/wctdm24xxp/GpakCust.h b/wctdm24xxp/GpakCust.h deleted file mode 100644 index 418d6a7..0000000 --- a/wctdm24xxp/GpakCust.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2005, Adaptive Digital Technologies, Inc. - * - * File Name: GpakCust.h - * - * Description: - * This file contains host system dependent definitions and prototypes of - * functions to support generic G.PAK API functions. The file is used when - * integrating G.PAK API functions in a specific host processor environment. - * - * Note: This file may need to be modified by the G.PAK system integrator. - * - * Version: 1.0 - * - * Revision History: - * 06/15/05 - Initial release. - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. The standard - * GPL disclaimer is given inline below for your convenience. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _GPAKCUST_H /* prevent multiple inclusion */ -#define _GPAKCUST_H - -#include "wctdm24xxp.h" -#ifdef VPM150M_SUPPORT -#include -#include -#endif -#include "gpakenum.h" - - -struct wctdm_firmware { - const struct firmware *fw; - unsigned int offset; -}; - -/* Host and DSP system dependent related definitions. */ -#define MAX_DSP_CORES 128 /* maximum number of DSP cores */ -//#define MAX_CONFS 1 /* maximum number of conferences */ -//#define MAX_PKT_CHANNELS 8 /* maximum number of packet channels */ -#define MAX_CHANNELS 32 /* maximum number of channels */ -#define MAX_WAIT_LOOPS 50 /* max number of wait delay loops */ -#define DSP_IFBLK_ADDRESS 0x0100 /* DSP address of I/F block pointer */ -#define DOWNLOAD_BLOCK_SIZE 512 /* download block size (DSP words) */ -//#define MAX_CIDPAYLOAD_BYTES 512 /* max size of a CID payload (octets) */ -typedef unsigned short DSP_WORD; /* 16 bit DSP word */ -typedef unsigned int DSP_ADDRESS; /* 32 bit DSP address */ -typedef struct wctdm_firmware* GPAK_FILE_ID; /* G.PAK Download file identifier */ - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadDspMemory - Read DSP memory. - * - * FUNCTION - * This function reads a contiguous block of words from DSP memory starting at - * the specified address. - * - * RETURNS - * nothing - * - */ -extern void gpakReadDspMemory( - unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ - unsigned int NumWords, /* number of contiguous words to read */ - DSP_WORD *pWordValues /* pointer to array of word values variable */ - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakWriteDspMemory - Write DSP memory. - * - * FUNCTION - * This function writes a contiguous block of words to DSP memory starting at - * the specified address. - * - * RETURNS - * nothing - * - */ -extern void gpakWriteDspMemory( - unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ - unsigned int NumWords, /* number of contiguous words to write */ - DSP_WORD *pWordValues /* pointer to array of word values to write */ - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakHostDelay - Delay for a fixed time interval. - * - * FUNCTION - * This function delays for a fixed time interval before returning. The time - * interval is the Host Port Interface sampling period when polling a DSP for - * replies to command messages. - * - * RETURNS - * nothing - * - */ -extern void gpakHostDelay(void); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakLockAccess - Lock access to the specified DSP. - * - * FUNCTION - * This function aquires exclusive access to the specified DSP. - * - * RETURNS - * nothing - * - */ -extern void gpakLockAccess( - unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakUnlockAccess - Unlock access to the specified DSP. - * - * FUNCTION - * This function releases exclusive access to the specified DSP. - * - * RETURNS - * nothing - * - */ -extern void gpakUnlockAccess( - unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFile - Read a block of bytes from a G.PAK Download file. - * - * FUNCTION - * This function reads a contiguous block of bytes from a G.PAK Download file - * starting at the current file position. - * - * RETURNS - * The number of bytes read from the file. - * -1 indicates an error occurred. - * 0 indicates all bytes have been read (end of file) - * - */ -extern int gpakReadFile( - GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ - unsigned char *pBuffer, /* pointer to buffer for storing bytes */ - unsigned int NumBytes /* number of bytes to read */ - ); - - -unsigned char wctdm_vpm150m_getpage(struct wctdm *wc); - -int wctdm_vpm150m_setpage(struct wctdm *wc, unsigned short addr); - -int wctdm_vpm150m_setreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data); - -unsigned short wctdm_vpm150m_getreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data); - -char vpm150mtone_to_zaptone(GpakToneCodes_t tone); - -#endif /* prevent multiple inclusion */ - - diff --git a/wctdm24xxp/GpakHpi.h b/wctdm24xxp/GpakHpi.h deleted file mode 100644 index 49e4ef9..0000000 --- a/wctdm24xxp/GpakHpi.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2001, Adaptive Digital Technologies, Inc. - * - * File Name: GpakHpi.h - * - * Description: - * This file contains common definitions related to the G.PAK interface - * between a host processor and a DSP processor via the Host Port Interface. - * - * Version: 1.0 - * - * Revision History: - * 10/17/01 - Initial release. - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. The standard - * GPL disclaimer is given inline below for your convenience. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _GPAKHPI_H /* prevent multiple inclusion */ -#define _GPAKHPI_H - - -/* Definition of G.PAK Command/Reply message type codes. */ -#define MSG_NULL_REPLY 0 /* Null Reply (unsupported Command) */ -#define MSG_SYS_CONFIG_RQST 1 /* System Configuration Request */ -#define MSG_SYS_CONFIG_REPLY 2 /* System Configuration Reply */ -#define MSG_READ_SYS_PARMS 3 /* Read System Parameters */ -#define MSG_READ_SYS_PARMS_REPLY 4 /* Read System Parameters Reply */ -#define MSG_WRITE_SYS_PARMS 5 /* Write System Parameters */ -#define MSG_WRITE_SYS_PARMS_REPLY 6 /* Write System Parameters Reply */ -#define MSG_CONFIGURE_PORTS 7 /* Configure Serial Ports */ -#define MSG_CONFIG_PORTS_REPLY 8 /* Configure Serial Ports Reply */ -#define MSG_CONFIGURE_CHANNEL 9 /* Configure Channel */ -#define MSG_CONFIG_CHAN_REPLY 10 /* Configure Channel Reply */ -#define MSG_TEAR_DOWN_CHANNEL 11 /* Tear Down Channel */ -#define MSG_TEAR_DOWN_REPLY 12 /* Tear Down Channel Reply */ -#define MSG_CHAN_STATUS_RQST 13 /* Channel Status Request */ -#define MSG_CHAN_STATUS_REPLY 14 /* Channel Status Reply */ - -#define MSG_TEST_MODE 17 /* Configure/Perform Test Mode */ -#define MSG_TEST_REPLY 18 /* Configure/Perform Test Mode Reply */ - -#define MSG_ALG_CONTROL 27 /* algorithm control */ -#define MSG_ALG_CONTROL_REPLY 28 /* algorithm control reply */ -#define MSG_GET_TXCID_ADDRESS 29 /* get tx cid buffer start address */ -#define MSG_GET_TXCID_ADDRESS_REPLY 30 /* get tx cid buffer start addr reply */ - -#define MSG_PING 35 /* ping command */ -#define MSG_PING_REPLY 36 /* ping command reply */ -#define MSG_SERIAL_TXVAL 37 /* transmit serial fixed value */ -#define MSG_SERIAL_TXVAL_REPLY 38 /* transmit serial fixed value reply */ -#define MSG_TDM_LOOPBACK 39 /* tdm loopback control */ -#define MSG_TDM_LOOPBACK_REPLY 40 /* tdm loopback control reply */ -#define MSG_RESET_USAGE_STATS 41 /* reset cpu usage stats */ -#define MSG_RESET_USAGE_STATS_REPLY 42 /* reset cpu usage stats reply */ - -#define MSG_RESET_FRAME_STATS 47 /* reset framing stats */ -#define MSG_RESET_FRAME_STATS_REPLY 48 /* reset framing stats reply */ - -#define MSG_READ_DSP_MEMORY 49 /* read small section of DSP's memory */ -#define MSG_READ_DSP_MEMORY_REPLY 50 /* read memory reply */ - -#define MSG_ACCESSGPIO 51 -#define MSG_ACCESSGPIO_REPLY 52 -#endif /* prevent multiple inclusion */ diff --git a/wctdm24xxp/Kbuild b/wctdm24xxp/Kbuild deleted file mode 100644 index 69fe21b..0000000 --- a/wctdm24xxp/Kbuild +++ /dev/null @@ -1,23 +0,0 @@ -obj-m += wctdm24xxp.o - -EXTRA_CFLAGS := -I$(src)/.. -Wno-undef - -ifeq ($(HOTPLUG_FIRMWARE),yes) - EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE -endif - -wctdm24xxp-objs := base.o GpakCust.o GpakApi.o - -ifneq ($(HOTPLUG_FIRMWARE),yes) -wctdm24xxp-objs += ../firmware/zaptel-fw-vpmadt032.o -endif - -$(obj)/../firmware/zaptel-fw-vpmadt032.o: $(obj)/base.o - $(MAKE) -C $(obj)/../firmware zaptel-fw-vpmadt032.o - -$(obj)/base.o: $(src)/GpakCust.h $(src)/wctdm24xxp.h -$(obj)/base.o: $(src)/../zaptel.h - -$(obj)/GpakCust.o: $(src)/GpakCust.h - -$(obj)/GpakApi.o: $(src)/GpakApi.h diff --git a/wctdm24xxp/Makefile b/wctdm24xxp/Makefile deleted file mode 100644 index 9c4cd51..0000000 --- a/wctdm24xxp/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -ifneq ($(KBUILD_EXTMOD),) -# We only get here on kernels 2.6.0-2.6.9 . -# For newer kernels, Kbuild will be included directly by the kernel -# build system. -include $(src)/Kbuild - -else - -all: wctdm24xxp.o - -%.o: %.c - $(CC) $(KFLAGS) -o $@ -c $< - -base.o: ../zaptel.h GpakCust.h ../wctdm.h - -GpakCust.o: GpakCust.h - -../firmware/zaptel-fw-vpmadt032.o: base.o - $(MAKE) -C ../firmware zaptel-fw-vpmadt032.o - -wctdm24xxp.o: base.o GpakCust.o GpakApi.o ../firmware/zaptel-fw-vpmadt032.o - $(LD) -r -o $@ $^ - -clean: - rm -f *.o - -endif diff --git a/wctdm24xxp/base.c b/wctdm24xxp/base.c deleted file mode 100644 index 58afbb9..0000000 --- a/wctdm24xxp/base.c +++ /dev/null @@ -1,4485 +0,0 @@ -/* - * Wildcard TDM2400P TDM FXS/FXO Interface Driver for Zapata Telephony interface - * - * Written by Mark Spencer - * Support for TDM800P and VPM150M by Matthew Fredrickson - * - * Copyright (C) 2005,2006, Digium, Inc. - * All rights reserved. - * - * Sections for QRV cards written by Jim Dixon - * Copyright (C) 2006, Jim Dixon and QRV Communications - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -/* For QRV DRI cards, gain is signed short, expressed in hundredths of -db (in reference to 1v Peak @ 1000Hz) , as follows: - -Rx Gain: -11.99 to 15.52 db -Tx Gain - No Pre-Emphasis: -35.99 to 12.00 db -Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef LINUX26 -#include -#endif - -#include "zaptel.h" -#include "proslic.h" -#include "wctdm.h" - -#include "wctdm24xxp.h" - -#ifdef VPM150M_SUPPORT -#include "adt_lec.h" -#endif - -#include "GpakCust.h" -#include "GpakApi.h" - -/* - Experimental max loop current limit for the proslic - Loop current limit is from 20 mA to 41 mA in steps of 3 - (according to datasheet) - So set the value below to: - 0x00 : 20mA (default) - 0x01 : 23mA - 0x02 : 26mA - 0x03 : 29mA - 0x04 : 32mA - 0x05 : 35mA - 0x06 : 37mA - 0x07 : 41mA -*/ -static int loopcurrent = 20; - -static alpha indirect_regs[] = -{ -{0,255,"DTMF_ROW_0_PEAK",0x55C2}, -{1,255,"DTMF_ROW_1_PEAK",0x51E6}, -{2,255,"DTMF_ROW2_PEAK",0x4B85}, -{3,255,"DTMF_ROW3_PEAK",0x4937}, -{4,255,"DTMF_COL1_PEAK",0x3333}, -{5,255,"DTMF_FWD_TWIST",0x0202}, -{6,255,"DTMF_RVS_TWIST",0x0202}, -{7,255,"DTMF_ROW_RATIO_TRES",0x0198}, -{8,255,"DTMF_COL_RATIO_TRES",0x0198}, -{9,255,"DTMF_ROW_2ND_ARM",0x0611}, -{10,255,"DTMF_COL_2ND_ARM",0x0202}, -{11,255,"DTMF_PWR_MIN_TRES",0x00E5}, -{12,255,"DTMF_OT_LIM_TRES",0x0A1C}, -{13,0,"OSC1_COEF",0x7B30}, -{14,1,"OSC1X",0x0063}, -{15,2,"OSC1Y",0x0000}, -{16,3,"OSC2_COEF",0x7870}, -{17,4,"OSC2X",0x007D}, -{18,5,"OSC2Y",0x0000}, -{19,6,"RING_V_OFF",0x0000}, -{20,7,"RING_OSC",0x7EF0}, -{21,8,"RING_X",0x0160}, -{22,9,"RING_Y",0x0000}, -{23,255,"PULSE_ENVEL",0x2000}, -{24,255,"PULSE_X",0x2000}, -{25,255,"PULSE_Y",0x0000}, -//{26,13,"RECV_DIGITAL_GAIN",0x4000}, // playback volume set lower -{26,13,"RECV_DIGITAL_GAIN",0x2000}, // playback volume set lower -{27,14,"XMIT_DIGITAL_GAIN",0x4000}, -//{27,14,"XMIT_DIGITAL_GAIN",0x2000}, -{28,15,"LOOP_CLOSE_TRES",0x1000}, -{29,16,"RING_TRIP_TRES",0x3600}, -{30,17,"COMMON_MIN_TRES",0x1000}, -{31,18,"COMMON_MAX_TRES",0x0200}, -{32,19,"PWR_ALARM_Q1Q2",0x07C0}, -{33,20,"PWR_ALARM_Q3Q4", 0x4C00 /* 0x2600 */}, -{34,21,"PWR_ALARM_Q5Q6",0x1B80}, -{35,22,"LOOP_CLOSURE_FILTER",0x8000}, -{36,23,"RING_TRIP_FILTER",0x0320}, -{37,24,"TERM_LP_POLE_Q1Q2",0x008C}, -{38,25,"TERM_LP_POLE_Q3Q4",0x0100}, -{39,26,"TERM_LP_POLE_Q5Q6",0x0010}, -{40,27,"CM_BIAS_RINGING",0x0C00}, -{41,64,"DCDC_MIN_V",0x0C00}, -{42,255,"DCDC_XTRA",0x1000}, -{43,66,"LOOP_CLOSE_TRES_LOW",0x1000}, -}; - -#ifdef FANCY_ECHOCAN -static char ectab[] = { -0, 0, 0, 1, 2, 3, 4, 6, 8, 9, 11, 13, 16, 18, 20, 22, 24, 25, 27, 28, 29, 30, 31, 31, 32, -32, 32, 32, 32, 32, 32, 32, 32, 32, 32 ,32 ,32, 32, -32, 32, 32, 32, 32, 32, 32, 32, 32, 32 ,32 ,32, 32, -32, 32, 32, 32, 32, 32, 32, 32, 32, 32 ,32 ,32, 32, -31, 31, 30, 29, 28, 27, 25, 23, 22, 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0, -}; -static int ectrans[4] = { 0, 1, 3, 2 }; -#define EC_SIZE (sizeof(ectab)) -#define EC_SIZE_Q (sizeof(ectab) / 4) -#endif - -/* Undefine to enable Power alarm / Transistor debug -- note: do not - enable for normal operation! */ -/* #define PAQ_DEBUG */ - -static struct fxo_mode { - char *name; - /* FXO */ - int ohs; - int ohs2; - int rz; - int rt; - int ilim; - int dcv; - int mini; - int acim; - int ring_osc; - int ring_x; -} fxo_modes[] = -{ - { "FCC", 0, 0, 0, 1, 0, 0x3, 0, 0, }, /* US, Canada */ - { "TBR21", 0, 0, 0, 0, 1, 0x3, 0, 0x2, 0x7e6c, 0x023a, }, - /* Austria, Belgium, Denmark, Finland, France, Germany, - Greece, Iceland, Ireland, Italy, Luxembourg, Netherlands, - Norway, Portugal, Spain, Sweden, Switzerland, and UK */ - { "ARGENTINA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "AUSTRALIA", 1, 0, 0, 0, 0, 0, 0x3, 0x3, }, - { "AUSTRIA", 0, 1, 0, 0, 1, 0x3, 0, 0x3, }, - { "BAHRAIN", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "BELGIUM", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "BRAZIL", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "BULGARIA", 0, 0, 0, 0, 1, 0x3, 0x0, 0x3, }, - { "CANADA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "CHILE", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "CHINA", 0, 0, 0, 0, 0, 0, 0x3, 0xf, }, - { "COLUMBIA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "CROATIA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "CYRPUS", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "CZECH", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "DENMARK", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "ECUADOR", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "EGYPT", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "ELSALVADOR", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "FINLAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "FRANCE", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "GERMANY", 0, 1, 0, 0, 1, 0x3, 0, 0x3, }, - { "GREECE", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "GUAM", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "HONGKONG", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "HUNGARY", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "ICELAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "INDIA", 0, 0, 0, 0, 0, 0x3, 0, 0x4, }, - { "INDONESIA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "IRELAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "ISRAEL", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "ITALY", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "JAPAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "JORDAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "KAZAKHSTAN", 0, 0, 0, 0, 0, 0x3, 0, }, - { "KUWAIT", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "LATVIA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "LEBANON", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "LUXEMBOURG", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "MACAO", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "MALAYSIA", 0, 0, 0, 0, 0, 0, 0x3, 0, }, /* Current loop >= 20ma */ - { "MALTA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "MEXICO", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "MOROCCO", 0, 0, 0, 0, 1, 0x3, 0, 0x2, }, - { "NETHERLANDS", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "NEWZEALAND", 0, 0, 0, 0, 0, 0x3, 0, 0x4, }, - { "NIGERIA", 0, 0, 0, 0, 0x1, 0x3, 0, 0x2, }, - { "NORWAY", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "OMAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "PAKISTAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "PERU", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "PHILIPPINES", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "POLAND", 0, 0, 1, 1, 0, 0x3, 0, 0, }, - { "PORTUGAL", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "ROMANIA", 0, 0, 0, 0, 0, 3, 0, 0, }, - { "RUSSIA", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "SAUDIARABIA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "SINGAPORE", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "SLOVAKIA", 0, 0, 0, 0, 0, 0x3, 0, 0x3, }, - { "SLOVENIA", 0, 0, 0, 0, 0, 0x3, 0, 0x2, }, - { "SOUTHAFRICA", 1, 0, 1, 0, 0, 0x3, 0, 0x3, }, - { "SOUTHKOREA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "SPAIN", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "SWEDEN", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "SWITZERLAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, }, - { "SYRIA", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "TAIWAN", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "THAILAND", 0, 0, 0, 0, 0, 0, 0x3, 0, }, - { "UAE", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "UK", 0, 1, 0, 0, 1, 0x3, 0, 0x5, }, - { "USA", 0, 0, 0, 0, 0, 0x3, 0, 0, }, - { "YEMEN", 0, 0, 0, 0, 0, 0x3, 0, 0, }, -}; - -#define DEBUG_CARD (1 << 0) -#define DEBUG_ECHOCAN (1 << 1) - -struct wctdm_desc { - char *name; - int flags; - int ports; -}; - -static struct wctdm_desc wctdm2400 = { "Wildcard TDM2400P", 0, 24 }; -static struct wctdm_desc wctdm800 = { "Wildcard TDM800P", 0, 8 }; -static struct wctdm_desc wctdm410 = { "Wildcard TDM410P", 0, 4 }; -static struct wctdm_desc wcaex2400 = { "Wildcard AEX2400", FLAG_EXPRESS, 24 }; -static struct wctdm_desc wcaex800 = { "Wildcard AEX800", FLAG_EXPRESS, 8 }; - -static int acim2tiss[16] = { 0x0, 0x1, 0x4, 0x5, 0x7, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0, 0x3 }; - -struct wctdm *ifaces[WC_MAX_IFACES]; -spinlock_t ifacelock = SPIN_LOCK_UNLOCKED; - -static void wctdm_release(struct wctdm *wc); - -static int fxovoltage = 0; -static int battdebounce = DEFAULT_BATT_DEBOUNCE; -static int battthresh = DEFAULT_BATT_THRESH; -static int debug = 0; -static int robust = 0; -static int lowpower = 0; -static int boostringer = 0; -static int fastringer = 0; -static int _opermode = 0; -static char *opermode = "FCC"; -static int fxshonormode = 0; -static int alawoverride = 0; -static int fxo_addrs[4] = { 0x00, 0x08, 0x04, 0x0c }; -static int fxotxgain = 0; -static int fxorxgain = 0; -static int fxstxgain = 0; -static int fxsrxgain = 0; -static int nativebridge = 0; -static int ringdebounce = DEFAULT_RING_DEBOUNCE; -static int fwringdetect = 0; -#ifdef VPM_SUPPORT -static int vpmsupport = 1; -static int vpmdtmfsupport = 0; -#define VPM_DEFAULT_DTMFTHRESHOLD 1250 -static int dtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD; -/* - * This parameter is used to adjust the NLP type used. The options are: - * 0 : None - * 1 : Mute - * 2 : Random Noise - * 3 : Hoth Noise - * 4 : Suppression NLP - In order to use this, you must set the vpmnlpmaxsupp parameter to - * some value in order to give the amount of dB to suppress to the suppressor - */ -static int vpmnlptype = 1; -/* This is the threshold (in dB) for enabling and disabling of the NLP */ -static int vpmnlpthresh = 24; -/* See vpmnlptype = 4 for more info */ -static int vpmnlpmaxsupp = 0; -#endif - -static int wctdm_init_proslic(struct wctdm *wc, int card, int fast , int manual, int sane); - -static inline int CMD_BYTE(int card, int bit, int altcs) -{ - /* Let's add some trickery to make the TDM410 work */ - if (altcs == 3) { - if (card == 2) { - card = 4; - altcs = 0; - } else if (card == 3) { - card = 5; - altcs = 2; - } - } - - return (((((card) & 0x3) * 3 + (bit)) * 7) \ - + ((card) >> 2) + (altcs) + ((altcs) ? -21 : 0)); -} - -/* sleep in user space until woken up. Equivilant of tsleep() in BSD */ -int schluffen(wait_queue_head_t *q) -{ - DECLARE_WAITQUEUE(wait, current); - add_wait_queue(q, &wait); - current->state = TASK_INTERRUPTIBLE; - if (!signal_pending(current)) schedule(); - current->state = TASK_RUNNING; - remove_wait_queue(q, &wait); - if (signal_pending(current)) return -ERESTARTSYS; - return(0); -} - -static inline int empty_slot(struct wctdm *wc, int card) -{ - int x; - for (x=0;xcmdq[card].cmds[x]) - return x; - } - return -1; -} - -#ifdef VPM_SUPPORT -static inline void cmd_dequeue_vpm150m(struct wctdm *wc, volatile unsigned char *writechunk, int whichframe) -{ - unsigned long flags; - struct vpm150m_cmd *curcmd = NULL; - struct vpm150m *vpm150m = wc->vpm150m; - int x; - unsigned char leds = ~((wc->intcount / 1000) % 8) & 0x7; - - /* Skip audio */ - writechunk += 24; - - spin_lock_irqsave(&wc->reglock, flags); - - if (test_bit(VPM150M_SPIRESET, &vpm150m->control) || test_bit(VPM150M_HPIRESET, &vpm150m->control)) { - if (debug & DEBUG_ECHOCAN) - printk("HW Resetting VPMADT032...\n"); - for (x = 24; x < 28; x++) { - if (x == 24) { - if (test_and_clear_bit(VPM150M_SPIRESET, &vpm150m->control)) - writechunk[CMD_BYTE(x, 0, 0)] = 0x08; - else if (test_and_clear_bit(VPM150M_HPIRESET, &vpm150m->control)) - writechunk[CMD_BYTE(x, 0, 0)] = 0x0b; - } else - writechunk[CMD_BYTE(x, 0, 0)] = 0x00 | leds; - writechunk[CMD_BYTE(x, 1, 0)] = 0; - writechunk[CMD_BYTE(x, 2, 0)] = 0x00; - } - spin_unlock_irqrestore(&wc->reglock, flags); - return; - } - - - /* Search for something waiting to transmit */ - for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { - if ((vpm150m->cmdq[x].desc & (__VPM150M_RD | __VPM150M_WR)) && - !(vpm150m->cmdq[x].desc & (__VPM150M_FIN | __VPM150M_TX))) { - curcmd = &vpm150m->cmdq[x]; - curcmd->txident = wc->txident; - curcmd->desc |= __VPM150M_TX; - break; - } - } - if (curcmd) { -#if 0 - printk("Found command txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", curcmd->txident, curcmd->desc, curcmd->addr, curcmd->data); -#endif - if (curcmd->desc & __VPM150M_RWPAGE) { - /* Set CTRL access to page*/ - writechunk[CMD_BYTE(24, 0, 0)] = (0x8 << 4); - writechunk[CMD_BYTE(24, 1, 0)] = 0; - writechunk[CMD_BYTE(24, 2, 0)] = 0x20; - - /* Do a page write */ - if (curcmd->desc & __VPM150M_WR) - writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | 0x4) << 4); - else - writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | 0x4 | 0x1) << 4); - writechunk[CMD_BYTE(25, 1, 0)] = 0; - if (curcmd->desc & __VPM150M_WR) - writechunk[CMD_BYTE(25, 2, 0)] = curcmd->data[0] & 0xf; - else - writechunk[CMD_BYTE(25, 2, 0)] = 0; - - /* Clear XADD */ - writechunk[CMD_BYTE(26, 0, 0)] = (0x8 << 4); - writechunk[CMD_BYTE(26, 1, 0)] = 0; - writechunk[CMD_BYTE(26, 2, 0)] = 0; - - /* Fill in to buffer to size */ - writechunk[CMD_BYTE(27, 0, 0)] = 0; - writechunk[CMD_BYTE(27, 1, 0)] = 0; - writechunk[CMD_BYTE(27, 2, 0)] = 0; - - } else { - /* Set address */ - writechunk[CMD_BYTE(24, 0, 0)] = ((0x8 | 0x4) << 4); - writechunk[CMD_BYTE(24, 1, 0)] = (curcmd->addr >> 8) & 0xff; - writechunk[CMD_BYTE(24, 2, 0)] = curcmd->addr & 0xff; - - /* Send/Get our data */ - if (curcmd->desc & __VPM150M_WR) { - if (curcmd->datalen > 1) - writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | (0x1 << 1)) << 4); - else - writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | (0x3 << 1)) << 4); - } else - if (curcmd->datalen > 1) - writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | (0x1 << 1) | 0x1) << 4); - else - writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | (0x3 << 1) | 0x1) << 4); - writechunk[CMD_BYTE(25, 1, 0)] = (curcmd->data[0] >> 8) & 0xff; - writechunk[CMD_BYTE(25, 2, 0)] = curcmd->data[0] & 0xff; - - if (curcmd->datalen > 1) { - if (curcmd->desc & __VPM150M_WR) - writechunk[CMD_BYTE(26, 0, 0)] = ((0x8 | (0x1 << 1)) << 4); - else - writechunk[CMD_BYTE(26, 0, 0)] = ((0x8 | (0x1 << 1) | 0x1) << 4); - writechunk[CMD_BYTE(26, 1, 0)] = (curcmd->data[1] >> 8) & 0xff; - writechunk[CMD_BYTE(26, 2, 0)] = curcmd->data[1] & 0xff; - } else { - /* Fill in the rest */ - writechunk[CMD_BYTE(26, 0, 0)] = 0; - writechunk[CMD_BYTE(26, 1, 0)] = 0; - writechunk[CMD_BYTE(26, 2, 0)] = 0; - } - - if (curcmd->datalen > 2) { - if (curcmd->desc & __VPM150M_WR) - writechunk[CMD_BYTE(27, 0, 0)] = ((0x8 | (0x1 << 1)) << 4); - else - writechunk[CMD_BYTE(27, 0, 0)] = ((0x8 | (0x1 << 1) | 0x1) << 4); - writechunk[CMD_BYTE(27, 1, 0)] = (curcmd->data[2] >> 8) & 0xff; - writechunk[CMD_BYTE(27, 2, 0)] = curcmd->data[2] & 0xff; - } else { - /* Fill in the rest */ - writechunk[CMD_BYTE(27, 0, 0)] = 0; - writechunk[CMD_BYTE(27, 1, 0)] = 0; - writechunk[CMD_BYTE(27, 2, 0)] = 0; - } - - - } - } else if (test_and_clear_bit(VPM150M_SWRESET, &vpm150m->control)) { - printk("Booting VPMADT032\n"); - for (x = 24; x < 28; x++) { - if (x == 24) - writechunk[CMD_BYTE(x, 0, 0)] = (0x8 << 4); - else - writechunk[CMD_BYTE(x, 0, 0)] = 0x00; - writechunk[CMD_BYTE(x, 1, 0)] = 0; - if (x == 24) - writechunk[CMD_BYTE(x, 2, 0)] = 0x01; - else - writechunk[CMD_BYTE(x, 2, 0)] = 0x00; - } - } else { - for (x = 24; x < 28; x++) { - writechunk[CMD_BYTE(x, 0, 0)] = 0x00; - writechunk[CMD_BYTE(x, 1, 0)] = 0x00; - writechunk[CMD_BYTE(x, 2, 0)] = 0x00; - } - } - -#ifdef VPM150M_SUPPORT - /* Add our leds in */ - for (x = 24; x < 28; x++) - writechunk[CMD_BYTE(x, 0, 0)] |= leds; - - /* Now let's figure out if we need to check for DTMF */ - if (test_bit(VPM150M_ACTIVE, &vpm150m->control) && !whichframe && !(wc->intcount % 100)) - queue_work(vpm150m->wq, &vpm150m->work); -#endif - - spin_unlock_irqrestore(&wc->reglock, flags); -} -#endif /* VPM_SUPPORT */ - -static inline void cmd_dequeue(struct wctdm *wc, volatile unsigned char *writechunk, int card, int pos) -{ - unsigned long flags; - unsigned int curcmd=0; - int x; - int subaddr = card & 0x3; -#ifdef FANCY_ECHOCAN - int ecval; - ecval = wc->echocanpos; - ecval += EC_SIZE_Q * ectrans[(card & 0x3)]; - ecval = ecval % EC_SIZE; -#endif - - /* if a QRV card, map it to its first channel */ - if ((wc->modtype[card] == MOD_TYPE_QRV) && (card & 3)) - { - return; - } - if (wc->altcs[card]) - subaddr = 0; - - - - /* Skip audio */ - writechunk += 24; - spin_lock_irqsave(&wc->reglock, flags); - /* Search for something waiting to transmit */ - if (pos) { - for (x=0;xcmdq[card].cmds[x] & (__CMD_RD | __CMD_WR)) && - !(wc->cmdq[card].cmds[x] & (__CMD_TX | __CMD_FIN))) { - curcmd = wc->cmdq[card].cmds[x]; -#if 0 - printk("Transmitting command '%08x' in slot %d\n", wc->cmdq[card].cmds[x], wc->txident); -#endif - wc->cmdq[card].cmds[x] |= (wc->txident << 24) | __CMD_TX; - break; - } - } - } - if (!curcmd) { - /* If nothing else, use filler */ - if (wc->modtype[card] == MOD_TYPE_FXS) - curcmd = CMD_RD(64); - else if (wc->modtype[card] == MOD_TYPE_FXO) - curcmd = CMD_RD(12); - else if (wc->modtype[card] == MOD_TYPE_QRV) - curcmd = CMD_RD(3); - else if (wc->modtype[card] == MOD_TYPE_VPM) { -#ifdef FANCY_ECHOCAN - if (wc->blinktimer >= 0xf) { - curcmd = CMD_WR(0x1ab, 0x0f); - } else if (wc->blinktimer == (ectab[ecval] >> 1)) { - curcmd = CMD_WR(0x1ab, 0x00); - } else -#endif - curcmd = CMD_RD(0x1a0); - } - } - if (wc->modtype[card] == MOD_TYPE_FXS) { - writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = (1 << (subaddr)); - if (curcmd & __CMD_WR) - writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0x7f; - else - writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x80 | ((curcmd >> 8) & 0x7f); - writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff; - } else if (wc->modtype[card] == MOD_TYPE_FXO) { - if (curcmd & __CMD_WR) - writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x20 | fxo_addrs[subaddr]; - else - writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x60 | fxo_addrs[subaddr]; - writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0xff; - writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff; - } else if (wc->modtype[card] == MOD_TYPE_FXSINIT) { - /* Special case, we initialize the FXS's into the three-byte command mode then - switch to the regular mode. To send it into thee byte mode, treat the path as - 6 two-byte commands and in the last one we initialize register 0 to 0x80. All modules - read this as the command to switch to daisy chain mode and we're done. */ - writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00; - writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00; - if ((card & 0x1) == 0x1) - writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x80; - else - writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00; -#ifdef VPM_SUPPORT - } else if (wc->modtype[card] == MOD_TYPE_VPM) { - if (curcmd & __CMD_WR) - writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = ((card & 0x3) << 4) | 0xc | ((curcmd >> 16) & 0x1); - else - writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = ((card & 0x3) << 4) | 0xa | ((curcmd >> 16) & 0x1); - writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0xff; - writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff; - } else if (wc->modtype[card] == MOD_TYPE_VPM150M) { -#endif - } else if (wc->modtype[card] == MOD_TYPE_QRV) { - - writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00; - if (!curcmd) - { - writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00; - writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00; - } - else - { - if (curcmd & __CMD_WR) - writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x40 | ((curcmd >> 8) & 0x3f); - else - writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0xc0 | ((curcmd >> 8) & 0x3f); - writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff; - } - } else if (wc->modtype[card] == MOD_TYPE_NONE) { - writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00; - writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00; - writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00; - } -#if 0 - /* XXX */ - if (cmddesc < 40) - printk("Pass %d, card = %d (modtype=%d), pos = %d, CMD_BYTES = %d,%d,%d, (%02x,%02x,%02x) curcmd = %08x\n", cmddesc, card, wc->modtype[card], pos, CMD_BYTE(card, 0), CMD_BYTE(card, 1), CMD_BYTE(card, 2), writechunk[CMD_BYTE(card, 0)], writechunk[CMD_BYTE(card, 1)], writechunk[CMD_BYTE(card, 2)], curcmd); -#endif - spin_unlock_irqrestore(&wc->reglock, flags); -#if 0 - /* XXX */ - cmddesc++; -#endif -} - -#ifdef VPM_SUPPORT -static inline void cmd_decifer_vpm150m(struct wctdm *wc, volatile unsigned char *readchunk) -{ - unsigned long flags; - unsigned char ident; - int x, i; - - /* Skip audio */ - readchunk += 24; - spin_lock_irqsave(&wc->reglock, flags); - /* Search for any pending results */ - for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { - if ((wc->vpm150m->cmdq[x].desc & (__VPM150M_RD | __VPM150M_WR)) && - (wc->vpm150m->cmdq[x].desc & (__VPM150M_TX)) && - !(wc->vpm150m->cmdq[x].desc & (__VPM150M_FIN))) { - ident = wc->vpm150m->cmdq[x].txident; - if (ident == wc->rxident) { - /* Store result */ - for (i = 0; i < wc->vpm150m->cmdq[x].datalen; i++) { - wc->vpm150m->cmdq[x].data[i] = (0xff & readchunk[CMD_BYTE((25 + i), 1, 0)]) << 8; - wc->vpm150m->cmdq[x].data[i] |= readchunk[CMD_BYTE((25 + i), 2, 0)]; - } - if (wc->vpm150m->cmdq[x].desc & __VPM150M_WR) { - /* Go ahead and clear out writes since they need no acknowledgement */ - wc->vpm150m->cmdq[x].desc = 0; - } else - wc->vpm150m->cmdq[x].desc |= __VPM150M_FIN; - break; - } - } - } - spin_unlock_irqrestore(&wc->reglock, flags); -} -#endif /* VPM_SUPPORT */ - -static inline void cmd_decifer(struct wctdm *wc, volatile unsigned char *readchunk, int card) -{ - unsigned long flags; - unsigned char ident; - int x; - - /* if a QRV card, map it to its first channel */ - if ((wc->modtype[card] == MOD_TYPE_QRV) && (card & 3)) - { - return; - } - /* Skip audio */ - readchunk += 24; - spin_lock_irqsave(&wc->reglock, flags); - /* Search for any pending results */ - for (x=0;xcmdq[card].cmds[x] & (__CMD_RD | __CMD_WR)) && - (wc->cmdq[card].cmds[x] & (__CMD_TX)) && - !(wc->cmdq[card].cmds[x] & (__CMD_FIN))) { - ident = (wc->cmdq[card].cmds[x] >> 24) & 0xff; - if (ident == wc->rxident) { - /* Store result */ - wc->cmdq[card].cmds[x] |= readchunk[CMD_BYTE(card, 2, wc->altcs[card])]; - wc->cmdq[card].cmds[x] |= __CMD_FIN; - if (wc->cmdq[card].cmds[x] & __CMD_WR) { - /* Go ahead and clear out writes since they need no acknowledgement */ - wc->cmdq[card].cmds[x] = 0x00000000; - } else if (x >= USER_COMMANDS) { - /* Clear out ISR reads */ - wc->cmdq[card].isrshadow[x - USER_COMMANDS] = wc->cmdq[card].cmds[x] & 0xff; - wc->cmdq[card].cmds[x] = 0x00000000; - } - break; - } - } - } -#if 0 - /* XXX */ - if (!pos && (cmddesc < 256)) - printk("Card %d: Command '%08x' => %02x\n",card, wc->cmdq[card].lasttx[pos], wc->cmdq[card].lastrd[pos]); -#endif - spin_unlock_irqrestore(&wc->reglock, flags); -} - -static inline void cmd_checkisr(struct wctdm *wc, int card) -{ - if (!wc->cmdq[card].cmds[USER_COMMANDS + 0]) { - if (wc->sethook[card]) { - wc->cmdq[card].cmds[USER_COMMANDS + 0] = wc->sethook[card]; - wc->sethook[card] = 0; - } else if (wc->modtype[card] == MOD_TYPE_FXS) { - wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(68); /* Hook state */ - } else if (wc->modtype[card] == MOD_TYPE_FXO) { - wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(5); /* Hook/Ring state */ - } else if (wc->modtype[card] == MOD_TYPE_QRV) { - wc->cmdq[card & 0xfc].cmds[USER_COMMANDS + 0] = CMD_RD(3); /* COR/CTCSS state */ -#ifdef VPM_SUPPORT - } else if (wc->modtype[card] == MOD_TYPE_VPM) { - wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(0xb9); /* DTMF interrupt */ -#endif - } - } - if (!wc->cmdq[card].cmds[USER_COMMANDS + 1]) { - if (wc->modtype[card] == MOD_TYPE_FXS) { -#ifdef PAQ_DEBUG - wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(19); /* Transistor interrupts */ -#else - wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(64); /* Battery mode */ -#endif - } else if (wc->modtype[card] == MOD_TYPE_FXO) { - wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(29); /* Battery */ - } else if (wc->modtype[card] == MOD_TYPE_QRV) { - wc->cmdq[card & 0xfc].cmds[USER_COMMANDS + 1] = CMD_RD(3); /* Battery */ -#ifdef VPM_SUPPORT - } else if (wc->modtype[card] == MOD_TYPE_VPM) { - wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(0xbd); /* DTMF interrupt */ -#endif - } - } -} - -static inline void wctdm_transmitprep(struct wctdm *wc, int dbl) -{ - volatile unsigned char *writechunk; - int x,y; - - dbl = dbl % 2; - - writechunk = (volatile unsigned char *)(wc->writechunk); - if (dbl) - /* Write is at interrupt address. Start writing from normal offset */ - writechunk += SFRAME_SIZE; - - /* Calculate Transmission */ - zt_transmit(&wc->span); - - for (x=0;xcards;y++) { - if (!x) - cmd_checkisr(wc, y); - - if (y < wc->type) - writechunk[y] = wc->chans[y].writechunk[x]; - cmd_dequeue(wc, writechunk, y, x); - } -#ifdef VPM_SUPPORT - if (!x) - wc->blinktimer++; - if (wc->vpm) { - for (y=24;y<28;y++) { - if (!x) - cmd_checkisr(wc, y); - cmd_dequeue(wc, writechunk, y, x); - } -#ifdef FANCY_ECHOCAN - if (wc->vpm && wc->blinktimer >= 0xf) { - wc->blinktimer = -1; - wc->echocanpos++; - } -#endif - } else if (wc->vpm150m) { - cmd_dequeue_vpm150m(wc, writechunk, x); - } -#endif - if (x < ZT_CHUNKSIZE - 1) { - writechunk[EFRAME_SIZE] = wc->ctlreg; - writechunk[EFRAME_SIZE + 1] = wc->txident++; -#if 1 - if ((wc->type == 4) && ((wc->ctlreg & 0x10) || (wc->modtype[NUM_CARDS] == MOD_TYPE_NONE))) { - writechunk[EFRAME_SIZE + 2] = 0; - for (y = 0; y < 4; y++) { - if (wc->modtype[y] == MOD_TYPE_NONE) - writechunk[EFRAME_SIZE + 2] |= (1 << y); - } - } else - writechunk[EFRAME_SIZE + 2] = 0xf; -#endif - } - writechunk += (EFRAME_SIZE + EFRAME_GAP); - } -} - -static inline void __wctdm_setctl(struct wctdm *wc, unsigned int addr, unsigned int val) -{ - outl(val, wc->iobase + addr); -} - -static inline unsigned int __wctdm_getctl(struct wctdm *wc, unsigned int addr) -{ - return inl(wc->iobase + addr); -} - -static inline void wctdm_setctl(struct wctdm *wc, unsigned int addr, unsigned int val) -{ - unsigned long flags; - spin_lock_irqsave(&wc->reglock, flags); - __wctdm_setctl(wc, addr, val); - spin_unlock_irqrestore(&wc->reglock, flags); -} - -static inline int wctdm_setreg_full(struct wctdm *wc, int card, int addr, int val, int inisr) -{ - unsigned long flags; - int hit=0; - int ret; - - /* if a QRV card, use only its first channel */ - if (wc->modtype[card] == MOD_TYPE_QRV) - { - if (card & 3) return(0); - } - do { - spin_lock_irqsave(&wc->reglock, flags); - hit = empty_slot(wc, card); - if (hit > -1) { - wc->cmdq[card].cmds[hit] = CMD_WR(addr, val); - } - spin_unlock_irqrestore(&wc->reglock, flags); - if (inisr) - break; - if (hit < 0) { - if ((ret = schluffen(&wc->regq))) - return ret; - } - } while (hit < 0); - return (hit > -1) ? 0 : -1; -} - -static inline int wctdm_setreg_intr(struct wctdm *wc, int card, int addr, int val) -{ - return wctdm_setreg_full(wc, card, addr, val, 1); -} -static inline int wctdm_setreg(struct wctdm *wc, int card, int addr, int val) -{ - return wctdm_setreg_full(wc, card, addr, val, 0); -} - -static inline int wctdm_getreg(struct wctdm *wc, int card, int addr) -{ - unsigned long flags; - int hit; - int ret=0; - - /* if a QRV card, use only its first channel */ - if (wc->modtype[card] == MOD_TYPE_QRV) - { - if (card & 3) return(0); - } - do { - spin_lock_irqsave(&wc->reglock, flags); - hit = empty_slot(wc, card); - if (hit > -1) { - wc->cmdq[card].cmds[hit] = CMD_RD(addr); - } - spin_unlock_irqrestore(&wc->reglock, flags); - if (hit < 0) { - if ((ret = schluffen(&wc->regq))) - return ret; - } - } while (hit < 0); - do { - spin_lock_irqsave(&wc->reglock, flags); - if (wc->cmdq[card].cmds[hit] & __CMD_FIN) { - ret = wc->cmdq[card].cmds[hit] & 0xff; - wc->cmdq[card].cmds[hit] = 0x00000000; - hit = -1; - } - spin_unlock_irqrestore(&wc->reglock, flags); - if (hit > -1) { - if ((ret = schluffen(&wc->regq))) - return ret; - } - } while (hit > -1); - return ret; -} - -static inline unsigned int wctdm_getctl(struct wctdm *wc, unsigned int addr) -{ - unsigned long flags; - unsigned int val; - spin_lock_irqsave(&wc->reglock, flags); - val = __wctdm_getctl(wc, addr); - spin_unlock_irqrestore(&wc->reglock, flags); - return val; -} - -static inline int __wctdm_sdi_clk(struct wctdm *wc) -{ - unsigned int ret; - wc->sdi &= ~SDI_CLK; - __wctdm_setctl(wc, 0x0048, wc->sdi); - ret = __wctdm_getctl(wc, 0x0048); - wc->sdi |= SDI_CLK; - __wctdm_setctl(wc, 0x0048, wc->sdi); - return ret & SDI_DIN; -} - -static inline void __wctdm_sdi_sendbits(struct wctdm *wc, unsigned int bits, int count) -{ - wc->sdi &= ~SDI_DREAD; - __wctdm_setctl(wc, 0x0048, wc->sdi); - while(count--) { - if (bits & (1 << count)) - wc->sdi |= SDI_DOUT; - else - wc->sdi &= ~SDI_DOUT; - __wctdm_sdi_clk(wc); - } -} - -static inline unsigned int __wctdm_sdi_recvbits(struct wctdm *wc, int count) -{ - unsigned int bits=0; - wc->sdi |= SDI_DREAD; - __wctdm_setctl(wc, 0x0048, wc->sdi); - while(count--) { - bits <<= 1; - if (__wctdm_sdi_clk(wc)) - bits |= 1; - else - bits &= ~1; - } - return bits; -} - -static inline void __wctdm_setsdi(struct wctdm *wc, unsigned char addr, unsigned short value) -{ - unsigned int bits; - /* Send preamble */ - bits = 0xffffffff; - __wctdm_sdi_sendbits(wc, bits, 32); - bits = (0x5 << 12) | (1 << 7) | (addr << 2) | 0x2; - __wctdm_sdi_sendbits(wc, bits, 16); - __wctdm_sdi_sendbits(wc, value, 16); - -} - -static inline unsigned short __wctdm_getsdi(struct wctdm *wc, unsigned char addr) -{ - unsigned int bits; - /* Send preamble */ - bits = 0xffffffff; - __wctdm_sdi_sendbits(wc, bits, 32); - bits = (0x6 << 10) | (1 << 5) | (addr); - __wctdm_sdi_sendbits(wc, bits, 14); - return __wctdm_sdi_recvbits(wc, 18); -} - -static inline void wctdm_setsdi(struct wctdm *wc, unsigned char addr, unsigned short value) -{ - unsigned long flags; - spin_lock_irqsave(&wc->reglock, flags); - __wctdm_setsdi(wc, addr, value); - spin_unlock_irqrestore(&wc->reglock, flags); -} - -static inline unsigned short wctdm_getsdi(struct wctdm *wc, unsigned char addr) -{ - unsigned long flags; - unsigned short val; - spin_lock_irqsave(&wc->reglock, flags); - val = __wctdm_getsdi(wc, addr); - spin_unlock_irqrestore(&wc->reglock, flags); - return val; -} - -#ifdef VPM_SUPPORT -static inline unsigned char wctdm_vpm_in(struct wctdm *wc, int unit, const unsigned int addr) -{ - return wctdm_getreg(wc, unit + NUM_CARDS, addr); -} - -static inline void wctdm_vpm_out(struct wctdm *wc, int unit, const unsigned int addr, const unsigned char val) -{ - wctdm_setreg(wc, unit + NUM_CARDS, addr, val); -} - -static inline void cmd_vpm150m_retransmit(struct wctdm *wc) -{ - unsigned long flags; - int x; - - spin_lock_irqsave(&wc->reglock, flags); - for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { - if (!(wc->vpm150m->cmdq[x].desc & __VPM150M_FIN)) { - //printk("Retransmit!\n"); - wc->vpm150m->cmdq[x].desc &= ~(__VPM150M_TX); - } - } - spin_unlock_irqrestore(&wc->reglock, flags); - -} -#endif - -static inline void cmd_retransmit(struct wctdm *wc) -{ - int x,y; - unsigned long flags; - /* Force retransmissions */ - spin_lock_irqsave(&wc->reglock, flags); - for (x=0;xcards;y++) { - if (!(wc->cmdq[y].cmds[x] & __CMD_FIN)) - wc->cmdq[y].cmds[x] &= ~(__CMD_TX | (0xff << 24)); - } - } - spin_unlock_irqrestore(&wc->reglock, flags); -#ifdef VPM_SUPPORT - if (wc->vpm150m) - cmd_vpm150m_retransmit(wc); -#endif -} - -static inline void wctdm_receiveprep(struct wctdm *wc, int dbl) -{ - volatile unsigned char *readchunk; - int x,y; - unsigned char expected; - - dbl = dbl % 2; - - readchunk = (volatile unsigned char *)wc->readchunk; - if (dbl) - readchunk += SFRAME_SIZE; - for (x=0;xrxident+1; - wc->rxident = readchunk[EFRAME_SIZE + 1]; - if (wc->rxident != expected) { - wc->span.irqmisses++; - cmd_retransmit(wc); - } - } - for (y=0;y < wc->cards;y++) { - if (y < wc->type) { - wc->chans[y].readchunk[x] = readchunk[y]; - } - cmd_decifer(wc, readchunk, y); - } -#ifdef VPM_SUPPORT - if (wc->vpm) { - for (y=NUM_CARDS;y < NUM_CARDS + NUM_EC; y++) - cmd_decifer(wc, readchunk, y); - } else if (wc->vpm150m) - cmd_decifer_vpm150m(wc, readchunk); -#endif -#if 0 - if (cmddesc < 1024) { - printk("RC Result: %02x\n", readchunk[EFRAME_SIZE+1]); - } -#endif - readchunk += (EFRAME_SIZE + EFRAME_GAP); - } - /* XXX We're wasting 8 taps. We should get closer :( */ - for (x=0;xtype;x++) { - if (wc->cardflag & (1 << x)) - zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->chans[x].writechunk); - } - zt_receive(&wc->span); - /* Wake up anyone sleeping to read/write a new register */ - wake_up_interruptible(&wc->regq); -} - -static void wctdm_stop_dma(struct wctdm *wc); -static void wctdm_restart_dma(struct wctdm *wc); - -static int wait_access(struct wctdm *wc, int card) -{ - unsigned char data=0; - long origjiffies; - int count = 0; - - #define MAX 10 /* attempts */ - - - origjiffies = jiffies; - /* Wait for indirect access */ - while (count++ < MAX) - { - data = wctdm_getreg(wc, card, I_STATUS); - - if (!data) - return 0; - - } - - if(count > (MAX-1)) printk(" ##### Loop error (%02x) #####\n", data); - - return 0; -} - -static unsigned char translate_3215(unsigned char address) -{ - int x; - for (x=0;xflags[card] & FLAG_3215) { - address = translate_3215(address); - if (address == 255) - return 0; - } - if(!wait_access(wc, card)) { - wctdm_setreg(wc, card, IDA_LO,(unsigned char)(data & 0xFF)); - wctdm_setreg(wc, card, IDA_HI,(unsigned char)((data & 0xFF00)>>8)); - wctdm_setreg(wc, card, IAA,address); - res = 0; - }; - return res; -} - -static int wctdm_proslic_getreg_indirect(struct wctdm *wc, int card, unsigned char address) -{ - int res = -1; - char *p=NULL; - /* Translate 3215 addresses */ - if (wc->flags[card] & FLAG_3215) { - address = translate_3215(address); - if (address == 255) - return 0; - } - if (!wait_access(wc, card)) { - wctdm_setreg(wc, card, IAA, address); - if (!wait_access(wc, card)) { - unsigned char data1, data2; - data1 = wctdm_getreg(wc, card, IDA_LO); - data2 = wctdm_getreg(wc, card, IDA_HI); - res = data1 | (data2 << 8); - } else - p = "Failed to wait inside\n"; - } else - p = "failed to wait\n"; - if (p) - printk(p); - return res; -} - -static int wctdm_proslic_init_indirect_regs(struct wctdm *wc, int card) -{ - unsigned char i; - - for (i=0; iflags[card] & FLAG_3215) || (indirect_regs[i].altaddr != 255))) - { - printk("!!!!!!! %s iREG %X = %X should be %X\n", - indirect_regs[i].name,indirect_regs[i].address,j,initial ); - passed = 0; - } - } - - if (passed) { - if (debug & DEBUG_CARD) - printk("Init Indirect Registers completed successfully.\n"); - } else { - printk(" !!!!! Init Indirect Registers UNSUCCESSFULLY.\n"); - return -1; - } - return 0; -} - -static inline void wctdm_proslic_recheck_sanity(struct wctdm *wc, int card) -{ - int res; -#ifdef PAQ_DEBUG - res = wc->cmdq[card].isrshadow[1]; - res &= ~0x3; - if (res) { - wc->cmdq[card].isrshadow[1]=0; - wc->mods[card].fxs.palarms++; - if (wc->mods[card].fxs.palarms < MAX_ALARMS) { - printk("Power alarm (%02x) on module %d, resetting!\n", res, card + 1); - if (wc->mods[card].fxs.lasttxhook == 4) - wc->mods[card].fxs.lasttxhook = 0x11; - wc->sethook[card] = CMD_WR(19, res); -#if 0 - wc->sethook[card] = CMD_WR(64, wc->mods[card].fxs.lasttxhook); -#endif - - /* wctdm_setreg_intr(wc, card, 64, wc->mods[card].fxs.lasttxhook); */ - /* Update shadow register to avoid extra power alarms until next read */ - wc->cmdq[card].isrshadow[1] = 0; - } else { - if (wc->mods[card].fxs.palarms == MAX_ALARMS) - printk("Too many power alarms on card %d, NOT resetting!\n", card + 1); - } - } -#else - res = wc->cmdq[card].isrshadow[1]; - /* This makes sure the lasthook was put in reg 64 the linefeed reg */ - if (((res & 0x0f) | 0x10) == wc->mods[card].fxs.lasttxhook) - wc->mods[card].fxs.lasttxhook &= 0x0f; - - res = !res && /* reg 64 has to be zero at last isr read */ - !(wc->mods[card].fxs.lasttxhook & 0x10 ) && /* not a transition */ - wc->mods[card].fxs.lasttxhook; /* not an intended zero */ - - if (res) { - wc->mods[card].fxs.palarms++; - if (wc->mods[card].fxs.palarms < MAX_ALARMS) { - printk("Power alarm on module %d, resetting!\n", card + 1); - if (wc->mods[card].fxs.lasttxhook == 4) - wc->mods[card].fxs.lasttxhook = 0x11; - wc->mods[card].fxs.lasttxhook |= 0x10; - wc->sethook[card] = CMD_WR(64, wc->mods[card].fxs.lasttxhook); - - /* wctdm_setreg_intr(wc, card, 64, wc->mods[card].fxs.lasttxhook); */ - /* Update shadow register to avoid extra power alarms until next read */ - wc->cmdq[card].isrshadow[1] = wc->mods[card].fxs.lasttxhook; - } else { - if (wc->mods[card].fxs.palarms == MAX_ALARMS) - printk("Too many power alarms on card %d, NOT resetting!\n", card + 1); - } - } -#endif -} - -static inline void wctdm_qrvdri_check_hook(struct wctdm *wc, int card) -{ - signed char b,b1; - int qrvcard = card & 0xfc; - - - if (wc->qrvdebtime[card] >= 2) wc->qrvdebtime[card]--; - b = wc->cmdq[qrvcard].isrshadow[0]; /* Hook/Ring state */ - b &= 0xcc; /* use bits 3-4 and 6-7 only */ - - if (wc->radmode[qrvcard] & RADMODE_IGNORECOR) b &= ~4; - else if (!(wc->radmode[qrvcard] & RADMODE_INVERTCOR)) b ^= 4; - if (wc->radmode[qrvcard + 1] | RADMODE_IGNORECOR) b &= ~0x40; - else if (!(wc->radmode[qrvcard + 1] | RADMODE_INVERTCOR)) b ^= 0x40; - - if ((wc->radmode[qrvcard] & RADMODE_IGNORECT) || - (!(wc->radmode[qrvcard] & RADMODE_EXTTONE))) b &= ~8; - else if (!(wc->radmode[qrvcard] & RADMODE_EXTINVERT)) b ^= 8; - if ((wc->radmode[qrvcard + 1] & RADMODE_IGNORECT) || - (!(wc->radmode[qrvcard + 1] & RADMODE_EXTTONE))) b &= ~0x80; - else if (!(wc->radmode[qrvcard + 1] & RADMODE_EXTINVERT)) b ^= 0x80; - /* now b & MASK should be zero, if its active */ - /* check for change in chan 0 */ - if ((!(b & 0xc)) != wc->qrvhook[qrvcard + 2]) - { - wc->qrvdebtime[qrvcard] = wc->debouncetime[qrvcard]; - wc->qrvhook[qrvcard + 2] = !(b & 0xc); - } - /* if timed-out and ready */ - if (wc->qrvdebtime[qrvcard] == 1) - { - b1 = wc->qrvhook[qrvcard + 2]; -if (debug) printk("QRV channel %d rx state changed to %d\n",qrvcard,wc->qrvhook[qrvcard + 2]); - zt_hooksig(&wc->chans[qrvcard], - (b1) ? ZT_RXSIG_OFFHOOK : ZT_RXSIG_ONHOOK); - wc->qrvdebtime[card] = 0; - } - /* check for change in chan 1 */ - if ((!(b & 0xc0)) != wc->qrvhook[qrvcard + 3]) - { - wc->qrvdebtime[qrvcard + 1] = QRV_DEBOUNCETIME; - wc->qrvhook[qrvcard + 3] = !(b & 0xc0); - } - if (wc->qrvdebtime[qrvcard + 1] == 1) - { - b1 = wc->qrvhook[qrvcard + 3]; -if (debug) printk("QRV channel %d rx state changed to %d\n",qrvcard + 1,wc->qrvhook[qrvcard + 3]); - zt_hooksig(&wc->chans[qrvcard + 1], - (b1) ? ZT_RXSIG_OFFHOOK : ZT_RXSIG_ONHOOK); - wc->qrvdebtime[card] = 0; - } - return; -} - -static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card) -{ - unsigned char res; - signed char b; - /* Try to track issues that plague slot one FXO's */ - b = wc->cmdq[card].isrshadow[0]; /* Hook/Ring state */ - b &= 0x9b; - if (wc->mods[card].fxo.offhook) { - if (b != 0x9) - wctdm_setreg_intr(wc, card, 5, 0x9); - } else { - if (b != 0x8) - wctdm_setreg_intr(wc, card, 5, 0x8); - } - if (!wc->mods[card].fxo.offhook) { - if (fwringdetect) { - res = wc->cmdq[card].isrshadow[0] & 0x60; - if (wc->mods[card].fxo.ringdebounce--) { - if (res && (res != wc->mods[card].fxo.lastrdtx) && (wc->mods[card].fxo.battery == 1)) { - if (!wc->mods[card].fxo.wasringing) { - wc->mods[card].fxo.wasringing = 1; - if (debug) - printk("RING on %d/%d!\n", wc->span.spanno, card + 1); - zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); - } - wc->mods[card].fxo.lastrdtx = res; - wc->mods[card].fxo.ringdebounce = 10; - } else if (!res) { - if ((wc->mods[card].fxo.ringdebounce == 0) && wc->mods[card].fxo.wasringing) { - wc->mods[card].fxo.wasringing = 0; - if (debug) - printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); - zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); - } - } - } else if (res && (wc->mods[card].fxo.battery == 1)) { - wc->mods[card].fxo.lastrdtx = res; - wc->mods[card].fxo.ringdebounce = 10; - } - } else { - res = wc->cmdq[card].isrshadow[0]; - if ((res & 0x60) && (wc->mods[card].fxo.battery == 1)) { - wc->mods[card].fxo.ringdebounce += (ZT_CHUNKSIZE * 16); - if (wc->mods[card].fxo.ringdebounce >= ZT_CHUNKSIZE * ringdebounce) { - if (!wc->mods[card].fxo.wasringing) { - wc->mods[card].fxo.wasringing = 1; - zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); - if (debug) - printk("RING on %d/%d!\n", wc->span.spanno, card + 1); - } - wc->mods[card].fxo.ringdebounce = ZT_CHUNKSIZE * ringdebounce; - } - } else { - wc->mods[card].fxo.ringdebounce -= ZT_CHUNKSIZE * 4; - if (wc->mods[card].fxo.ringdebounce <= 0) { - if (wc->mods[card].fxo.wasringing) { - wc->mods[card].fxo.wasringing = 0; - zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); - if (debug) - printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); - } - wc->mods[card].fxo.ringdebounce = 0; - } - - } - } - } - b = wc->cmdq[card].isrshadow[1]; /* Voltage */ - - if (fxovoltage) { - if (!(wc->intcount % 100)) { - printk("Port %d: Voltage: %d Debounce %d\n", card + 1, - b, wc->mods[card].fxo.battdebounce); - } - } - - if (abs(b) < battthresh) { - wc->mods[card].fxo.nobatttimer++; -#if 0 - if (wc->mods[card].fxo.battery == 1) - printk("Battery loss: %d (%d debounce)\n", b, wc->mods[card].fxo.battdebounce); -#endif - if (wc->mods[card].fxo.battery && !wc->mods[card].fxo.battdebounce) { - if (debug & DEBUG_CARD) - printk("NO BATTERY on %d/%d!\n", wc->span.spanno, card + 1); - wc->mods[card].fxo.battery = 0; -#ifdef JAPAN - if ((!wc->ohdebounce) && wc->offhook) { - zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); - if (debug & DEBUG_CARD) - printk("Signalled On Hook\n"); -#ifdef ZERO_BATT_RING - wc->onhook++; -#endif - } -#else - zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); - zt_alarm_channel(&wc->chans[card], ZT_ALARM_RED); -#endif - wc->mods[card].fxo.battdebounce = battdebounce; - } else if (!wc->mods[card].fxo.battery) - wc->mods[card].fxo.battdebounce = battdebounce; - } else if (abs(b) > battthresh) { - if ((wc->mods[card].fxo.battery < 1) && !wc->mods[card].fxo.battdebounce) { - if (debug & DEBUG_CARD) - printk("BATTERY on %d/%d (%s)!\n", wc->span.spanno, card + 1, - (b < 0) ? "-" : "+"); -#ifdef ZERO_BATT_RING - if (wc->onhook) { - wc->onhook = 0; - zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); - if (debug & DEBUG_CARD) - printk("Signalled Off Hook\n"); - } -#else - zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); - zt_alarm_channel(&wc->chans[card], ZT_ALARM_NONE); -#endif - wc->mods[card].fxo.battery = 1; - wc->mods[card].fxo.nobatttimer = 0; - wc->mods[card].fxo.battdebounce = battdebounce; - } else if (wc->mods[card].fxo.battery == 1) - wc->mods[card].fxo.battdebounce = battdebounce; - - if (wc->mods[card].fxo.lastpol >= 0) { - if (b < 0) { - wc->mods[card].fxo.lastpol = -1; - wc->mods[card].fxo.polaritydebounce = POLARITY_DEBOUNCE; - } - } - if (wc->mods[card].fxo.lastpol <= 0) { - if (b > 0) { - wc->mods[card].fxo.lastpol = 1; - wc->mods[card].fxo.polaritydebounce = POLARITY_DEBOUNCE; - } - } - } else { - /* It's something else... */ - wc->mods[card].fxo.battdebounce = battdebounce; - } - if (wc->mods[card].fxo.battdebounce) - wc->mods[card].fxo.battdebounce--; - if (wc->mods[card].fxo.polaritydebounce) { - wc->mods[card].fxo.polaritydebounce--; - if (wc->mods[card].fxo.polaritydebounce < 1) { - if (wc->mods[card].fxo.lastpol != wc->mods[card].fxo.polarity) { - if (debug & DEBUG_CARD) - printk("%lu Polarity reversed (%d -> %d)\n", jiffies, - wc->mods[card].fxo.polarity, - wc->mods[card].fxo.lastpol); - if (wc->mods[card].fxo.polarity) - zt_qevent_lock(&wc->chans[card], ZT_EVENT_POLARITY); - wc->mods[card].fxo.polarity = wc->mods[card].fxo.lastpol; - } - } - } -} - -static inline void wctdm_proslic_check_hook(struct wctdm *wc, int card) -{ - char res; - int hook; - - /* For some reason we have to debounce the - hook detector. */ - - res = wc->cmdq[card].isrshadow[0]; /* Hook state */ - hook = (res & 1); - - if (hook != wc->mods[card].fxs.lastrxhook) { - /* Reset the debounce (must be multiple of 4ms) */ - wc->mods[card].fxs.debounce = 8 * (4 * 8); -#if 0 - printk("Resetting debounce card %d hook %d, %d\n", card, hook, wc->mods[card].fxs.debounce); -#endif - } else { - if (wc->mods[card].fxs.debounce > 0) { - wc->mods[card].fxs.debounce-= 4 * ZT_CHUNKSIZE; -#if 0 - printk("Sustaining hook %d, %d\n", hook, wc->mods[card].fxs.debounce); -#endif - if (!wc->mods[card].fxs.debounce) { -#if 0 - printk("Counted down debounce, newhook: %d...\n", hook); -#endif - wc->mods[card].fxs.debouncehook = hook; - } - if (!wc->mods[card].fxs.oldrxhook && wc->mods[card].fxs.debouncehook) { - /* Off hook */ - if (debug & DEBUG_CARD) - printk("wctdm: Card %d Going off hook\n", card); - zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); - if (robust) - wctdm_init_proslic(wc, card, 1, 0, 1); - wc->mods[card].fxs.oldrxhook = 1; - - } else if (wc->mods[card].fxs.oldrxhook && !wc->mods[card].fxs.debouncehook) { - /* On hook */ - if (debug & DEBUG_CARD) - printk("wctdm: Card %d Going on hook\n", card); - zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); - wc->mods[card].fxs.oldrxhook = 0; - } - } - } - wc->mods[card].fxs.lastrxhook = hook; -} - - -static inline void wctdm_reinit_descriptor(struct wctdm *wc, int tx, int dbl, char *s) -{ - int o2 = 0; - o2 += dbl * 4; - if (!tx) - o2 += ERING_SIZE * 4; - wc->descripchunk[o2] = 0x80000000; -} - -#ifdef VPM_SUPPORT -static inline void wctdm_vpm_check(struct wctdm *wc, int x) -{ - if (wc->cmdq[x].isrshadow[0]) { - if (debug & DEBUG_ECHOCAN) - printk("VPM: Detected dtmf ON channel %02x on chip %d!\n", wc->cmdq[x].isrshadow[0], x - NUM_CARDS); - wc->sethook[x] = CMD_WR(0xb9, wc->cmdq[x].isrshadow[0]); - wc->cmdq[x].isrshadow[0] = 0; - /* Cancel most recent lookup, if there is one */ - wc->cmdq[x].cmds[USER_COMMANDS+0] = 0x00000000; - } else if (wc->cmdq[x].isrshadow[1]) { - if (debug & DEBUG_ECHOCAN) - printk("VPM: Detected dtmf OFF channel %02x on chip %d!\n", wc->cmdq[x].isrshadow[1], x - NUM_CARDS); - wc->sethook[x] = CMD_WR(0xbd, wc->cmdq[x].isrshadow[1]); - wc->cmdq[x].isrshadow[1] = 0; - /* Cancel most recent lookup, if there is one */ - wc->cmdq[x].cmds[USER_COMMANDS+1] = 0x00000000; - } -} - -#include "adt_lec.c" - -static int wctdm_echocan_with_params(struct zt_chan *chan, struct zt_echocanparams *ecp, struct zt_echocanparam *p) -{ - struct wctdm *wc = chan->pvt; - - if (wc->vpm) { - int channel; - int unit; - - channel = (chan->chanpos - 1); - unit = (chan->chanpos - 1) & 0x3; - if (wc->vpm < 2) - channel >>= 2; - - if(debug & DEBUG_ECHOCAN) - printk("echocan: Unit is %d, Channel is %d length %d\n", - unit, channel, ecp->tap_length); - if (ecp->tap_length) - wctdm_vpm_out(wc,unit,channel,0x3e); - else - wctdm_vpm_out(wc,unit,channel,0x01); - - return 0; -#ifdef VPM150M_SUPPORT - } else if (wc->vpm150m) { - struct vpm150m *vpm150m = wc->vpm150m; - unsigned int ret; - int channo = chan->chanpos - 1; - - if ((ret = adt_lec_parse_params(&vpm150m->desiredecstate[channo], ecp, p))) - return ret; - - vpm150m->desiredecstate[channo].tap_length = ecp->tap_length; - - if (memcmp(&vpm150m->curecstate[channo], &vpm150m->desiredecstate[channo], sizeof(vpm150m->curecstate[channo])) - && test_bit(VPM150M_ACTIVE, &vpm150m->control)) - queue_work(vpm150m->wq, &vpm150m->work); - - return 0; -#endif - } else - return -ENODEV; -} -#endif - -static inline void wctdm_isr_misc(struct wctdm *wc) -{ - int x; - - for (x=0;xcards;x++) { - if (wc->cardflag & (1 << x)) { - if (wc->modtype[x] == MOD_TYPE_FXS) { - if (!(wc->intcount % 10000)) { - /* Accept an alarm once per 10 seconds */ - if (wc->mods[x].fxs.palarms) - wc->mods[x].fxs.palarms--; - } - wctdm_proslic_check_hook(wc, x); - if (!(wc->intcount & 0xfc)) - wctdm_proslic_recheck_sanity(wc, x); - if (wc->mods[x].fxs.lasttxhook == 0x4) { - /* RINGing, prepare for OHT */ - wc->mods[x].fxs.ohttimer = OHT_TIMER << 3; - wc->mods[x].fxs.idletxhookstate = 0x2; /* OHT mode when idle */ - } else { - if (wc->mods[x].fxs.ohttimer) { - wc->mods[x].fxs.ohttimer-= ZT_CHUNKSIZE; - if (!wc->mods[x].fxs.ohttimer) { - wc->mods[x].fxs.idletxhookstate = 0x1; /* Switch to active */ - if (wc->mods[x].fxs.lasttxhook == 0x2) { - /* Apply the change if appropriate */ - wc->mods[x].fxs.lasttxhook = 0x11; - wc->sethook[x] = CMD_WR(64, wc->mods[x].fxs.lasttxhook); - /* wctdm_setreg_intr(wc, x, 64, wc->mods[x].fxs.lasttxhook); */ - } - } - } - } - } else if (wc->modtype[x] == MOD_TYPE_FXO) { - wctdm_voicedaa_check_hook(wc, x); - } else if (wc->modtype[x] == MOD_TYPE_QRV) { - wctdm_qrvdri_check_hook(wc, x); - } - } - } -#ifdef VPM_SUPPORT - if (wc->vpm > 0) { - for (x=NUM_CARDS;xrdbl * 4; - } else { - o2 += wc->tdbl * 4; - } - if (!(wc->descripchunk[o2] & 0x80000000)) { - if (tx) { - wc->txints++; - wctdm_transmitprep(wc, wc->tdbl); - wctdm_reinit_descriptor(wc, tx, wc->tdbl, "txchk"); - wc->tdbl = (wc->tdbl + 1) % ERING_SIZE; - wctdm_isr_misc(wc); - wc->intcount++; - } else { - wc->rxints++; - wctdm_receiveprep(wc, wc->rdbl); - wctdm_reinit_descriptor(wc, tx, wc->rdbl, "rxchk"); - wc->rdbl = (wc->rdbl + 1) % ERING_SIZE; - } - return 1; - } - return 0; -} - -static void wctdm_init_descriptors(struct wctdm *wc) -{ - volatile unsigned int *descrip; - dma_addr_t descripdma; - dma_addr_t writedma; - dma_addr_t readdma; - int x; - - descrip = wc->descripchunk; - descripdma = wc->descripdma; - writedma = wc->writedma; - readdma = wc->readdma; - - for (x=0;xdescripdma; - - /* Transmit descriptor */ - descrip[0 ] = 0x80000000; - descrip[1 ] = 0xe5800000 | (SFRAME_SIZE); - if (x % 2) - descrip[2 ] = writedma + SFRAME_SIZE; - else - descrip[2 ] = writedma; - descrip[3 ] = descripdma; - - /* Receive descriptor */ - descrip[0 + ERING_SIZE * 4] = 0x80000000; - descrip[1 + ERING_SIZE * 4] = 0x01000000 | (SFRAME_SIZE); - if (x % 2) - descrip[2 + ERING_SIZE * 4] = readdma + SFRAME_SIZE; - else - descrip[2 + ERING_SIZE * 4] = readdma; - descrip[3 + ERING_SIZE * 4] = descripdma + ERING_SIZE * 16; - - /* Advance descriptor */ - descrip += 4; - } -} - -ZAP_IRQ_HANDLER(wctdm_interrupt) -{ - struct wctdm *wc = dev_id; - unsigned int ints; - int res; - - /* Read and clear interrupts */ - ints = wctdm_getctl(wc, 0x0028); - - if (!ints) -#ifdef LINUX26 - return IRQ_NONE; -#else - return; -#endif - - wctdm_setctl(wc, 0x0028, ints); - - ints &= wc->intmask; - if (ints & 0x00000041) { - do { - res = wctdm_check_descriptor(wc, 0); - res |= wctdm_check_descriptor(wc, 1); - } while(res); -#if 0 - while(wctdm_check_descriptor(wc, 0)); - wctdm_setctl(wc, 0x0010, 0x00000000); - } - if (ints & 0x00000005) { - while(wctdm_check_descriptor(wc, 1)); - wctdm_setctl(wc, 0x0008, 0x00000000); -#endif - } - - if (ints & 0x0000a3ae) { - /* This will allow us to recover if interrupts are held for a long period of time */ - if (debug & DEBUG_CARD) - printk("Abnormal interrupt %08x detected\n", ints); - wctdm_setctl(wc, 0x0008, 0x00000000); - wctdm_setctl(wc, 0x0010, 0x00000000); - } - -#ifdef LINUX26 - return IRQ_RETVAL(1); -#endif - -} - -static int wctdm_voicedaa_insane(struct wctdm *wc, int card) -{ - int blah; - blah = wctdm_getreg(wc, card, 2); - if (blah != 0x3) - return -2; - blah = wctdm_getreg(wc, card, 11); - if (debug & DEBUG_CARD) - printk("VoiceDAA System: %02x\n", blah & 0xf); - return 0; -} - -static int wctdm_proslic_insane(struct wctdm *wc, int card) -{ - int blah,insane_report; - insane_report=0; - - blah = wctdm_getreg(wc, card, 0); - if (debug & DEBUG_CARD) - printk("ProSLIC on module %d, product %d, version %d\n", card, (blah & 0x30) >> 4, (blah & 0xf)); - -#if 0 - if ((blah & 0x30) >> 4) { - printk("ProSLIC on module %d is not a 3210.\n", card); - return -1; - } -#endif - if (((blah & 0xf) == 0) || ((blah & 0xf) == 0xf)) { - /* SLIC not loaded */ - return -1; - } - if ((blah & 0xf) < 2) { - printk("ProSLIC 3210 version %d is too old\n", blah & 0xf); - return -1; - } - if (wctdm_getreg(wc, card, 1) & 0x80) - /* ProSLIC 3215, not a 3210 */ - wc->flags[card] |= FLAG_3215; - - blah = wctdm_getreg(wc, card, 8); - if (blah != 0x2) { - printk("ProSLIC on module %d insane (1) %d should be 2\n", card, blah); - return -1; - } else if ( insane_report) - printk("ProSLIC on module %d Reg 8 Reads %d Expected is 0x2\n",card,blah); - - blah = wctdm_getreg(wc, card, 64); - if (blah != 0x0) { - printk("ProSLIC on module %d insane (2)\n", card); - return -1; - } else if ( insane_report) - printk("ProSLIC on module %d Reg 64 Reads %d Expected is 0x0\n",card,blah); - - blah = wctdm_getreg(wc, card, 11); - if (blah != 0x33) { - printk("ProSLIC on module %d insane (3)\n", card); - return -1; - } else if ( insane_report) - printk("ProSLIC on module %d Reg 11 Reads %d Expected is 0x33\n",card,blah); - - /* Just be sure it's setup right. */ - wctdm_setreg(wc, card, 30, 0); - - if (debug & DEBUG_CARD) - printk("ProSLIC on module %d seems sane.\n", card); - return 0; -} - -static int wctdm_proslic_powerleak_test(struct wctdm *wc, int card) -{ - unsigned long origjiffies; - unsigned char vbat; - - /* Turn off linefeed */ - wctdm_setreg(wc, card, 64, 0); - - /* Power down */ - wctdm_setreg(wc, card, 14, 0x10); - - /* Wait for one second */ - origjiffies = jiffies; - - while((vbat = wctdm_getreg(wc, card, 82)) > 0x6) { - if ((jiffies - origjiffies) >= (HZ/2)) - break;; - } - - if (vbat < 0x06) { - printk("Excessive leakage detected on module %d: %d volts (%02x) after %d ms\n", card, - 376 * vbat / 1000, vbat, (int)((jiffies - origjiffies) * 1000 / HZ)); - return -1; - } else if (debug & DEBUG_CARD) { - printk("Post-leakage voltage: %d volts\n", 376 * vbat / 1000); - } - return 0; -} - -static int wctdm_powerup_proslic(struct wctdm *wc, int card, int fast) -{ - unsigned char vbat; - unsigned long origjiffies; - int lim; - - /* Set period of DC-DC converter to 1/64 khz */ - wctdm_setreg(wc, card, 92, 0xc0 /* was 0xff */); - - /* Wait for VBat to powerup */ - origjiffies = jiffies; - - /* Disable powerdown */ - wctdm_setreg(wc, card, 14, 0); - - /* If fast, don't bother checking anymore */ - if (fast) - return 0; - - while((vbat = wctdm_getreg(wc, card, 82)) < 0xc0) { - /* Wait no more than 500ms */ - if ((jiffies - origjiffies) > HZ/2) { - break; - } - } - - if (vbat < 0xc0) { - printk("ProSLIC on module %d failed to powerup within %d ms (%d mV only)\n\n -- DID YOU REMEMBER TO PLUG IN THE HD POWER CABLE TO THE TDM CARD??\n", - card, (int)(((jiffies - origjiffies) * 1000 / HZ)), - vbat * 375); - return -1; - } else if (debug & DEBUG_CARD) { - printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n", - card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ))); - } - - /* Proslic max allowed loop current, reg 71 LOOP_I_LIMIT */ - /* If out of range, just set it to the default value */ - lim = (loopcurrent - 20) / 3; - if ( loopcurrent > 41 ) { - lim = 0; - if (debug & DEBUG_CARD) - printk("Loop current out of range! Setting to default 20mA!\n"); - } - else if (debug & DEBUG_CARD) - printk("Loop current set to %dmA!\n",(lim*3)+20); - wctdm_setreg(wc,card,LOOP_I_LIMIT,lim); - - /* Engage DC-DC converter */ - wctdm_setreg(wc, card, 93, 0x19 /* was 0x19 */); -#if 0 - origjiffies = jiffies; - while(0x80 & wctdm_getreg(wc, card, 93)) { - if ((jiffies - origjiffies) > 2 * HZ) { - printk("Timeout waiting for DC-DC calibration on module %d\n", card); - return -1; - } - } - -#if 0 - /* Wait a full two seconds */ - while((jiffies - origjiffies) < 2 * HZ); - - /* Just check to be sure */ - vbat = wctdm_getreg(wc, card, 82); - printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n", - card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ))); -#endif -#endif - return 0; - -} - -static int wctdm_proslic_manual_calibrate(struct wctdm *wc, int card) -{ - unsigned long origjiffies; - unsigned char i; - - wctdm_setreg(wc, card, 21, 0);//(0) Disable all interupts in DR21 - wctdm_setreg(wc, card, 22, 0);//(0)Disable all interupts in DR21 - wctdm_setreg(wc, card, 23, 0);//(0)Disable all interupts in DR21 - wctdm_setreg(wc, card, 64, 0);//(0) - - wctdm_setreg(wc, card, 97, 0x18); //(0x18)Calibrations without the ADC and DAC offset and without common mode calibration. - wctdm_setreg(wc, card, 96, 0x47); //(0x47) Calibrate common mode and differential DAC mode DAC + ILIM - - origjiffies=jiffies; - while( wctdm_getreg(wc,card,96)!=0 ){ - if((jiffies-origjiffies)>80) - return -1; - } -//Initialized DR 98 and 99 to get consistant results. -// 98 and 99 are the results registers and the search should have same intial conditions. - -/*******************************The following is the manual gain mismatch calibration****************************/ -/*******************************This is also available as a function *******************************************/ - // Delay 10ms - origjiffies=jiffies; - while((jiffies-origjiffies)<1); - wctdm_proslic_setreg_indirect(wc, card, 88,0); - wctdm_proslic_setreg_indirect(wc,card,89,0); - wctdm_proslic_setreg_indirect(wc,card,90,0); - wctdm_proslic_setreg_indirect(wc,card,91,0); - wctdm_proslic_setreg_indirect(wc,card,92,0); - wctdm_proslic_setreg_indirect(wc,card,93,0); - - wctdm_setreg(wc, card, 98,0x10); // This is necessary if the calibration occurs other than at reset time - wctdm_setreg(wc, card, 99,0x10); - - for ( i=0x1f; i>0; i--) - { - wctdm_setreg(wc, card, 98,i); - origjiffies=jiffies; - while((jiffies-origjiffies)<4); - if((wctdm_getreg(wc,card,88)) == 0) - break; - } // for - - for ( i=0x1f; i>0; i--) - { - wctdm_setreg(wc, card, 99,i); - origjiffies=jiffies; - while((jiffies-origjiffies)<4); - if((wctdm_getreg(wc,card,89)) == 0) - break; - }//for - -/*******************************The preceding is the manual gain mismatch calibration****************************/ -/**********************************The following is the longitudinal Balance Cal***********************************/ - wctdm_setreg(wc,card,64,1); - while((jiffies-origjiffies)<10); // Sleep 100? - - wctdm_setreg(wc, card, 64, 0); - wctdm_setreg(wc, card, 23, 0x4); // enable interrupt for the balance Cal - wctdm_setreg(wc, card, 97, 0x1); // this is a singular calibration bit for longitudinal calibration - wctdm_setreg(wc, card, 96,0x40); - - wctdm_getreg(wc,card,96); /* Read Reg 96 just cause */ - - wctdm_setreg(wc, card, 21, 0xFF); - wctdm_setreg(wc, card, 22, 0xFF); - wctdm_setreg(wc, card, 23, 0xFF); - - /**The preceding is the longitudinal Balance Cal***/ - return(0); - -} - -static int wctdm_proslic_calibrate(struct wctdm *wc, int card) -{ - unsigned long origjiffies; - int x; - /* Perform all calibrations */ - wctdm_setreg(wc, card, 97, 0x1f); - - /* Begin, no speedup */ - wctdm_setreg(wc, card, 96, 0x5f); - - /* Wait for it to finish */ - origjiffies = jiffies; - while(wctdm_getreg(wc, card, 96)) { - if ((jiffies - origjiffies) > 2 * HZ) { - printk("Timeout waiting for calibration of module %d\n", card); - return -1; - } - } - - if (debug & DEBUG_CARD) { - /* Print calibration parameters */ - printk("Calibration Vector Regs 98 - 107: \n"); - for (x=98;x<108;x++) { - printk("%d: %02x\n", x, wctdm_getreg(wc, card, x)); - } - } - return 0; -} - -static void wait_just_a_bit(int foo) -{ - long newjiffies; - newjiffies = jiffies + foo; - while(jiffies < newjiffies); -} - -/********************************************************************* - * Set the hwgain on the analog modules - * - * card = the card position for this module (0-23) - * gain = gain in dB x10 (e.g. -3.5dB would be gain=-35) - * tx = (0 for rx; 1 for tx) - * - *******************************************************************/ -static int wctdm_set_hwgain(struct wctdm *wc, int card, __s32 gain, __u32 tx) -{ - if (!(wc->modtype[card] == MOD_TYPE_FXO)) { - printk("Cannot adjust gain. Unsupported module type!\n"); - return -1; - } - if (tx) { - if (debug) - printk("setting FXO tx gain for card=%d to %d\n", card, gain); - if (gain >= -150 && gain <= 0) { - wctdm_setreg(wc, card, 38, 16 + (gain/-10)); - wctdm_setreg(wc, card, 40, 16 + (-gain%10)); - } else if (gain <= 120 && gain > 0) { - wctdm_setreg(wc, card, 38, gain/10); - wctdm_setreg(wc, card, 40, (gain%10)); - } else { - printk("FXO tx gain is out of range (%d)\n", gain); - return -1; - } - } else { /* rx */ - if (debug) - printk("setting FXO rx gain for card=%d to %d\n", card, gain); - if (gain >= -150 && gain <= 0) { - wctdm_setreg(wc, card, 39, 16+ (gain/-10)); - wctdm_setreg(wc, card, 41, 16 + (-gain%10)); - } else if (gain <= 120 && gain > 0) { - wctdm_setreg(wc, card, 39, gain/10); - wctdm_setreg(wc, card, 41, (gain%10)); - } else { - printk("FXO rx gain is out of range (%d)\n", gain); - return -1; - } - } - - return 0; -} - -static int wctdm_init_voicedaa(struct wctdm *wc, int card, int fast, int manual, int sane) -{ - unsigned char reg16=0, reg26=0, reg30=0, reg31=0; - long newjiffies; - - if (wc->modtype[card & 0xfc] == MOD_TYPE_QRV) return -2; - - wc->modtype[card] = MOD_TYPE_NONE; - /* Wait just a bit */ - wait_just_a_bit(HZ/10); - - wc->modtype[card] = MOD_TYPE_FXO; - wait_just_a_bit(HZ/10); - - if (!sane && wctdm_voicedaa_insane(wc, card)) - return -2; - - /* Software reset */ - wctdm_setreg(wc, card, 1, 0x80); - - /* Wait just a bit */ - wait_just_a_bit(HZ/10); - - /* Enable PCM, ulaw */ - if (alawoverride) - wctdm_setreg(wc, card, 33, 0x20); - else - wctdm_setreg(wc, card, 33, 0x28); - - /* Set On-hook speed, Ringer impedence, and ringer threshold */ - reg16 |= (fxo_modes[_opermode].ohs << 6); - reg16 |= (fxo_modes[_opermode].rz << 1); - reg16 |= (fxo_modes[_opermode].rt); - wctdm_setreg(wc, card, 16, reg16); - - if(fwringdetect) { - /* Enable ring detector full-wave rectifier mode */ - wctdm_setreg(wc, card, 18, 2); - wctdm_setreg(wc, card, 24, 0); - } else { - /* Set to the device defaults */ - wctdm_setreg(wc, card, 18, 0); - wctdm_setreg(wc, card, 24, 0x19); - } - - /* Set DC Termination: - Tip/Ring voltage adjust, minimum operational current, current limitation */ - reg26 |= (fxo_modes[_opermode].dcv << 6); - reg26 |= (fxo_modes[_opermode].mini << 4); - reg26 |= (fxo_modes[_opermode].ilim << 1); - wctdm_setreg(wc, card, 26, reg26); - - /* Set AC Impedence */ - reg30 = (fxo_modes[_opermode].acim); - wctdm_setreg(wc, card, 30, reg30); - - /* Misc. DAA parameters */ - reg31 = 0xa3; - reg31 |= (fxo_modes[_opermode].ohs2 << 3); - wctdm_setreg(wc, card, 31, reg31); - - /* Set Transmit/Receive timeslot */ - wctdm_setreg(wc, card, 34, (card * 8) & 0xff); - wctdm_setreg(wc, card, 35, (card * 8) >> 8); - wctdm_setreg(wc, card, 36, (card * 8) & 0xff); - wctdm_setreg(wc, card, 37, (card * 8) >> 8); - - /* Enable ISO-Cap */ - wctdm_setreg(wc, card, 6, 0x00); - - /* Wait 1000ms for ISO-cap to come up */ - newjiffies = jiffies; - newjiffies += 2 * HZ; - while((jiffies < newjiffies) && !(wctdm_getreg(wc, card, 11) & 0xf0)) - wait_just_a_bit(HZ/10); - - if (!(wctdm_getreg(wc, card, 11) & 0xf0)) { - printk("VoiceDAA did not bring up ISO link properly!\n"); - return -1; - } - if (debug & DEBUG_CARD) - printk("ISO-Cap is now up, line side: %02x rev %02x\n", - wctdm_getreg(wc, card, 11) >> 4, - (wctdm_getreg(wc, card, 13) >> 2) & 0xf); - /* Enable on-hook line monitor */ - wctdm_setreg(wc, card, 5, 0x08); - - /* Take values for fxotxgain and fxorxgain and apply them to module */ - wctdm_set_hwgain(wc, card, fxotxgain, 1); - wctdm_set_hwgain(wc, card, fxorxgain, 0); - - if(debug) - printk("DEBUG fxotxgain:%i.%i fxorxgain:%i.%i\n", (wctdm_getreg(wc, card, 38)/16) ? -(wctdm_getreg(wc, card, 38) - 16) : wctdm_getreg(wc, card, 38), (wctdm_getreg(wc, card, 40)/16) ? -(wctdm_getreg(wc, card, 40) - 16) : wctdm_getreg(wc, card, 40), (wctdm_getreg(wc, card, 39)/16) ? -(wctdm_getreg(wc, card, 39) - 16): wctdm_getreg(wc, card, 39), (wctdm_getreg(wc, card, 41)/16)?-(wctdm_getreg(wc, card, 41) - 16) : wctdm_getreg(wc, card, 41)); - - /* battery state still unknown */ - wc->mods[card].fxo.battery = -1; - - return 0; - -} - -static int wctdm_init_proslic(struct wctdm *wc, int card, int fast, int manual, int sane) -{ - - unsigned short tmp[5]; - unsigned char r19,r9; - int x; - int fxsmode=0; - - if (wc->modtype[card & 0xfc] == MOD_TYPE_QRV) return -2; - - /* Sanity check the ProSLIC */ - if (!sane && wctdm_proslic_insane(wc, card)) - return -2; - - /* By default, don't send on hook */ - wc->mods[card].fxs.idletxhookstate = 1; - wc->mods[card].fxs.lasttxhook = 0x10; - - if (sane) { - /* Make sure we turn off the DC->DC converter to prevent anything from blowing up */ - wctdm_setreg(wc, card, 14, 0x10); - } - - if (wctdm_proslic_init_indirect_regs(wc, card)) { - printk(KERN_INFO "Indirect Registers failed to initialize on module %d.\n", card); - return -1; - } - - /* Clear scratch pad area */ - wctdm_proslic_setreg_indirect(wc, card, 97,0); - - /* Clear digital loopback */ - wctdm_setreg(wc, card, 8, 0); - - /* Revision C optimization */ - wctdm_setreg(wc, card, 108, 0xeb); - - /* Disable automatic VBat switching for safety to prevent - Q7 from accidently turning on and burning out. */ - wctdm_setreg(wc, card, 67, 0x07); /* If pulse dialing has trouble at high REN - loads change this to 0x17 */ - - /* Turn off Q7 */ - wctdm_setreg(wc, card, 66, 1); - - /* Flush ProSLIC digital filters by setting to clear, while - saving old values */ - for (x=0;x<5;x++) { - tmp[x] = wctdm_proslic_getreg_indirect(wc, card, x + 35); - wctdm_proslic_setreg_indirect(wc, card, x + 35, 0x8000); - } - - /* Power up the DC-DC converter */ - if (wctdm_powerup_proslic(wc, card, fast)) { - printk("Unable to do INITIAL ProSLIC powerup on module %d\n", card); - return -1; - } - - if (!fast) { - - /* Check for power leaks */ - if (wctdm_proslic_powerleak_test(wc, card)) { - printk("ProSLIC module %d failed leakage test. Check for short circuit\n", card); - } - /* Power up again */ - if (wctdm_powerup_proslic(wc, card, fast)) { - printk("Unable to do FINAL ProSLIC powerup on module %d\n", card); - return -1; - } -#ifndef NO_CALIBRATION - /* Perform calibration */ - if(manual) { - if (wctdm_proslic_manual_calibrate(wc, card)) { - //printk("Proslic failed on Manual Calibration\n"); - if (wctdm_proslic_manual_calibrate(wc, card)) { - printk("Proslic Failed on Second Attempt to Calibrate Manually. (Try -DNO_CALIBRATION in Makefile)\n"); - return -1; - } - printk("Proslic Passed Manual Calibration on Second Attempt\n"); - } - } - else { - if(wctdm_proslic_calibrate(wc, card)) { - //printk("ProSlic died on Auto Calibration.\n"); - if (wctdm_proslic_calibrate(wc, card)) { - printk("Proslic Failed on Second Attempt to Auto Calibrate\n"); - return -1; - } - printk("Proslic Passed Auto Calibration on Second Attempt\n"); - } - } - /* Perform DC-DC calibration */ - wctdm_setreg(wc, card, 93, 0x99); - r19 = wctdm_getreg(wc, card, 107); - if ((r19 < 0x2) || (r19 > 0xd)) { - printk("DC-DC cal has a surprising direct 107 of 0x%02x!\n", r19); - wctdm_setreg(wc, card, 107, 0x8); - } - - /* Save calibration vectors */ - for (x=0;xmods[card].fxs.calregs.vals[x] = wctdm_getreg(wc, card, 96 + x); -#endif - - } else { - /* Restore calibration registers */ - for (x=0;xmods[card].fxs.calregs.vals[x]); - } - /* Calibration complete, restore original values */ - for (x=0;x<5;x++) { - wctdm_proslic_setreg_indirect(wc, card, x + 35, tmp[x]); - } - - if (wctdm_proslic_verify_indirect_regs(wc, card)) { - printk(KERN_INFO "Indirect Registers failed verification.\n"); - return -1; - } - - -#if 0 - /* Disable Auto Power Alarm Detect and other "features" */ - wctdm_setreg(wc, card, 67, 0x0e); - blah = wctdm_getreg(wc, card, 67); -#endif - -#if 0 - if (wctdm_proslic_setreg_indirect(wc, card, 97, 0x0)) { // Stanley: for the bad recording fix - printk(KERN_INFO "ProSlic IndirectReg Died.\n"); - return -1; - } -#endif - - if (alawoverride) - wctdm_setreg(wc, card, 1, 0x20); - else - wctdm_setreg(wc, card, 1, 0x28); - // U-Law 8-bit interface - wctdm_setreg(wc, card, 2, (card * 8) & 0xff); // Tx Start count low byte 0 - wctdm_setreg(wc, card, 3, (card * 8) >> 8); // Tx Start count high byte 0 - wctdm_setreg(wc, card, 4, (card * 8) & 0xff); // Rx Start count low byte 0 - wctdm_setreg(wc, card, 5, (card * 8) >> 8); // Rx Start count high byte 0 - wctdm_setreg(wc, card, 18, 0xff); // clear all interrupt - wctdm_setreg(wc, card, 19, 0xff); - wctdm_setreg(wc, card, 20, 0xff); - wctdm_setreg(wc, card, 22, 0xff); - wctdm_setreg(wc, card, 73, 0x04); - if (fxshonormode) { - fxsmode = acim2tiss[fxo_modes[_opermode].acim]; - wctdm_setreg(wc, card, 10, 0x08 | fxsmode); - if (fxo_modes[_opermode].ring_osc) - wctdm_proslic_setreg_indirect(wc, card, 20, fxo_modes[_opermode].ring_osc); - if (fxo_modes[_opermode].ring_x) - wctdm_proslic_setreg_indirect(wc, card, 21, fxo_modes[_opermode].ring_x); - } - if (lowpower) - wctdm_setreg(wc, card, 72, 0x10); - -#if 0 - wctdm_setreg(wc, card, 21, 0x00); // enable interrupt - wctdm_setreg(wc, card, 22, 0x02); // Loop detection interrupt - wctdm_setreg(wc, card, 23, 0x01); // DTMF detection interrupt -#endif - -#if 0 - /* Enable loopback */ - wctdm_setreg(wc, card, 8, 0x2); - wctdm_setreg(wc, card, 14, 0x0); - wctdm_setreg(wc, card, 64, 0x0); - wctdm_setreg(wc, card, 1, 0x08); -#endif - - if (fastringer) { - /* Speed up Ringer */ - wctdm_proslic_setreg_indirect(wc, card, 20, 0x7e6d); - wctdm_proslic_setreg_indirect(wc, card, 21, 0x01b9); - /* Beef up Ringing voltage to 89V */ - if (boostringer) { - wctdm_setreg(wc, card, 74, 0x3f); - if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x247)) - return -1; - printk("Boosting fast ringer on slot %d (89V peak)\n", card + 1); - } else if (lowpower) { - if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x14b)) - return -1; - printk("Reducing fast ring power on slot %d (50V peak)\n", card + 1); - } else - printk("Speeding up ringer on slot %d (25Hz)\n", card + 1); - } else { - /* Beef up Ringing voltage to 89V */ - if (boostringer) { - wctdm_setreg(wc, card, 74, 0x3f); - if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x1d1)) - return -1; - printk("Boosting ringer on slot %d (89V peak)\n", card + 1); - } else if (lowpower) { - if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x108)) - return -1; - printk("Reducing ring power on slot %d (50V peak)\n", card + 1); - } - } - - if (fxstxgain || fxsrxgain) { - r9 = wctdm_getreg(wc, card, 9); - switch (fxstxgain) { - - case 35: - r9+=8; - break; - case -35: - r9+=4; - break; - case 0: - break; - } - - switch (fxsrxgain) { - - case 35: - r9+=2; - break; - case -35: - r9+=1; - break; - case 0: - break; - } - wctdm_setreg(wc, card, 9, r9); - } - - if (debug) - printk("DEBUG: fxstxgain:%s fxsrxgain:%s\n",((wctdm_getreg(wc, card, 9)/8) == 1)?"3.5":(((wctdm_getreg(wc,card,9)/4) == 1)?"-3.5":"0.0"),((wctdm_getreg(wc, card, 9)/2) == 1)?"3.5":((wctdm_getreg(wc,card,9)%2)?"-3.5":"0.0")); - - wc->mods[card].fxs.lasttxhook = 0x11; - wctdm_setreg(wc, card, 64, 0x01); - return 0; -} - -static int wctdm_init_qrvdri(struct wctdm *wc, int card) -{ - unsigned char x,y; - unsigned long endjif; - - /* have to set this, at least for now */ - wc->modtype[card] = MOD_TYPE_QRV; - if (!(card & 3)) /* if at base of card, reset and write it */ - { - wctdm_setreg(wc,card,0,0x80); - wctdm_setreg(wc,card,0,0x55); - wctdm_setreg(wc,card,1,0x69); - wc->qrvhook[card] = wc->qrvhook[card + 1] = 0; - wc->qrvhook[card + 2] = wc->qrvhook[card + 3] = 0xff; - wc->debouncetime[card] = wc->debouncetime[card + 1] = QRV_DEBOUNCETIME; - wc->qrvdebtime[card] = wc->qrvdebtime[card + 1] = 0; - wc->radmode[card] = wc->radmode[card + 1] = 0; - wc->txgain[card] = wc->txgain[card + 1] = 3599; - wc->rxgain[card] = wc->rxgain[card + 1] = 1199; - } else { /* channel is on same card as base, no need to test */ - if (wc->modtype[card & 0x7c] == MOD_TYPE_QRV) - { - /* only lower 2 are valid */ - if (!(card & 2)) return 0; - } - wc->modtype[card] = MOD_TYPE_NONE; - return 1; - } - x = wctdm_getreg(wc,card,0); - y = wctdm_getreg(wc,card,1); - /* if not a QRV card, return as such */ - if ((x != 0x55) || (y != 0x69)) - { - wc->modtype[card] = MOD_TYPE_NONE; - return 1; - } - for(x = 0; x < 0x30; x++) - { - if ((x >= 0x1c) && (x <= 0x1e)) wctdm_setreg(wc,card,x,0xff); - else wctdm_setreg(wc,card,x,0); - } - wctdm_setreg(wc,card,0,0x80); - endjif = jiffies + (HZ/10); - while(endjif > jiffies); - wctdm_setreg(wc,card,0,0x10); - wctdm_setreg(wc,card,0,0x10); - endjif = jiffies + (HZ/10); - while(endjif > jiffies); - /* set up modes */ - wctdm_setreg(wc,card,0,0x1c); - /* set up I/O directions */ - wctdm_setreg(wc,card,1,0x33); - wctdm_setreg(wc,card,2,0x0f); - wctdm_setreg(wc,card,5,0x0f); - /* set up I/O to quiescent state */ - wctdm_setreg(wc,card,3,0x11); /* D0-7 */ - wctdm_setreg(wc,card,4,0xa); /* D8-11 */ - wctdm_setreg(wc,card,7,0); /* CS outputs */ - /* set up timeslots */ - wctdm_setreg(wc,card,0x13,card + 0x80); /* codec 2 tx, ts0 */ - wctdm_setreg(wc,card,0x17,card + 0x80); /* codec 0 rx, ts0 */ - wctdm_setreg(wc,card,0x14,card + 0x81); /* codec 1 tx, ts1 */ - wctdm_setreg(wc,card,0x18,card + 0x81); /* codec 1 rx, ts1 */ - /* set up for max gains */ - wctdm_setreg(wc,card,0x26,0x24); - wctdm_setreg(wc,card,0x27,0x24); - wctdm_setreg(wc,card,0x0b,0x01); /* "Transmit" gain codec 0 */ - wctdm_setreg(wc,card,0x0c,0x01); /* "Transmit" gain codec 1 */ - wctdm_setreg(wc,card,0x0f,0xff); /* "Receive" gain codec 0 */ - wctdm_setreg(wc,card,0x10,0xff); /* "Receive" gain codec 1 */ - return 0; -} - -static void qrv_dosetup(struct zt_chan *chan,struct wctdm *wc) -{ -int qrvcard; -unsigned char r; -long l; - - /* actually do something with the values */ - qrvcard = (chan->chanpos - 1) & 0xfc; - if (debug) printk("@@@@@ radmodes: %d,%d rxgains: %d,%d txgains: %d,%d\n", - wc->radmode[qrvcard],wc->radmode[qrvcard + 1], - wc->rxgain[qrvcard],wc->rxgain[qrvcard + 1], - wc->txgain[qrvcard],wc->txgain[qrvcard + 1]); - r = 0; - if (wc->radmode[qrvcard] & RADMODE_DEEMP) r |= 4; - if (wc->radmode[qrvcard + 1] & RADMODE_DEEMP) r |= 8; - if (wc->rxgain[qrvcard] < 1200) r |= 1; - if (wc->rxgain[qrvcard + 1] < 1200) r |= 2; - wctdm_setreg(wc, qrvcard, 7, r); - if (debug) printk("@@@@@ setting reg 7 to %02x hex\n",r); - r = 0; - if (wc->radmode[qrvcard] & RADMODE_PREEMP) r |= 3; - else if (wc->txgain[qrvcard] >= 3600) r |= 1; - else if (wc->txgain[qrvcard] >= 1200) r |= 2; - if (wc->radmode[qrvcard + 1] & RADMODE_PREEMP) r |= 0xc; - else if (wc->txgain[qrvcard + 1] >= 3600) r |= 4; - else if (wc->txgain[qrvcard + 1] >= 1200) r |= 8; - wctdm_setreg(wc, qrvcard, 4, r); - if (debug) printk("@@@@@ setting reg 4 to %02x hex\n",r); - r = 0; - if (wc->rxgain[qrvcard] >= 2400) r |= 1; - if (wc->rxgain[qrvcard + 1] >= 2400) r |= 2; - wctdm_setreg(wc, qrvcard, 0x25, r); - if (debug) printk("@@@@@ setting reg 0x25 to %02x hex\n",r); - r = 0; - if (wc->txgain[qrvcard] < 2400) r |= 1; else r |= 4; - if (wc->txgain[qrvcard + 1] < 2400) r |= 8; else r |= 0x20; - wctdm_setreg(wc, qrvcard, 0x26, r); - if (debug) printk("@@@@@ setting reg 0x26 to %02x hex\n",r); - l = ((long)(wc->rxgain[qrvcard] % 1200) * 10000) / 46875; - if (l == 0) l = 1; - if (wc->rxgain[qrvcard] >= 2400) l += 181; - wctdm_setreg(wc, qrvcard, 0x0b, (unsigned char)l); - if (debug) printk("@@@@@ setting reg 0x0b to %02x hex\n",(unsigned char)l); - l = ((long)(wc->rxgain[qrvcard + 1] % 1200) * 10000) / 46875; - if (l == 0) l = 1; - if (wc->rxgain[qrvcard + 1] >= 2400) l += 181; - wctdm_setreg(wc, qrvcard, 0x0c, (unsigned char)l); - if (debug) printk("@@@@@ setting reg 0x0c to %02x hex\n",(unsigned char)l); - l = ((long)(wc->txgain[qrvcard] % 1200) * 10000) / 46875; - if (l == 0) l = 1; - wctdm_setreg(wc, qrvcard, 0x0f, (unsigned char)l); - if (debug) printk("@@@@@ setting reg 0x0f to %02x hex\n", (unsigned char)l); - l = ((long)(wc->txgain[qrvcard + 1] % 1200) * 10000) / 46875; - if (l == 0) l = 1; - wctdm_setreg(wc, qrvcard, 0x10,(unsigned char)l); - if (debug) printk("@@@@@ setting reg 0x10 to %02x hex\n",(unsigned char)l); - return; -} - -static int wctdm_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) -{ - struct wctdm_stats stats; - struct wctdm_regs regs; - struct wctdm_regop regop; - struct wctdm_echo_coefs echoregs; - struct zt_hwgain hwgain; - struct wctdm *wc = chan->pvt; - int x; - union { - struct zt_radio_stat s; - struct zt_radio_param p; - } stack; - -#if 0 - /* XXX */ - printk("RxInts: %d, TxInts: %d\n", wc->rxints, wc->txints); - printk("RxIdent: %d, TxIdent: %d\n", wc->rxident, wc->txident); - for (x=0;xcards;x++) - printk("Card %d isrshadow: %02x/%02x\n", x, wc->cmdq[x].isrshadow[0], wc->cmdq[x].isrshadow[1]); - cmddesc = 0; -#endif -#if 0 - if (wc->vpm) { - char tmp[80]; - for (x=0;x<0x200;x++) { - switch (x & 0xf) { - case 0: - sprintf(tmp, "%03x: %02x ", x, wctdm_vpm_in(wc, 0, x)); - break; - case 0xf: - printk("%s%02x\n", tmp, wctdm_vpm_in(wc, 0, x)); - break; - default: - sprintf(tmp + strlen(tmp), "%02x ", wctdm_vpm_in(wc, 0, x)); - break; - } - } - } - -#endif - switch (cmd) { - case ZT_ONHOOKTRANSFER: - if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) - return -EINVAL; - if (get_user(x, (int *)data)) - return -EFAULT; - wc->mods[chan->chanpos - 1].fxs.ohttimer = x << 3; - wc->mods[chan->chanpos - 1].fxs.idletxhookstate = 0x2; /* OHT mode when idle */ - if (wc->mods[chan->chanpos - 1].fxs.lasttxhook == 0x1) { - /* Apply the change if appropriate */ - wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x12; - wc->sethook[chan->chanpos - 1] = CMD_WR(64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); - /* wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); */ - } - break; - case WCTDM_GET_STATS: - if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { - stats.tipvolt = wctdm_getreg(wc, chan->chanpos - 1, 80) * -376; - stats.ringvolt = wctdm_getreg(wc, chan->chanpos - 1, 81) * -376; - stats.batvolt = wctdm_getreg(wc, chan->chanpos - 1, 82) * -376; - } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { - stats.tipvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; - stats.ringvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; - stats.batvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; - } else - return -EINVAL; - if (copy_to_user((struct wctdm_stats *)data, &stats, sizeof(stats))) - return -EFAULT; - break; - case WCTDM_GET_REGS: - if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { - for (x=0;xchanpos -1, x); - for (x=0;xchanpos - 1, x); - } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_QRV) { - memset(®s, 0, sizeof(regs)); - for (x=0;x<0x32;x++) - regs.direct[x] = wctdm_getreg(wc, chan->chanpos - 1, x); - } else { - memset(®s, 0, sizeof(regs)); - for (x=0;xchanpos - 1, x); - } - if (copy_to_user((struct wctdm_regs *)data, ®s, sizeof(regs))) - return -EFAULT; - break; - case WCTDM_SET_REG: - if (copy_from_user(®op, (struct wctdm_regop *)data, sizeof(regop))) - return -EFAULT; - if (regop.indirect) { - if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) - return -EINVAL; - printk("Setting indirect %d to 0x%04x on %d\n", regop.reg, regop.val, chan->chanpos); - wctdm_proslic_setreg_indirect(wc, chan->chanpos - 1, regop.reg, regop.val); - } else { - regop.val &= 0xff; - if (regop.reg == 64) - wc->mods[chan->chanpos-1].fxs.lasttxhook = (regop.val & 0x0f) | 0x10; - - printk("Setting direct %d to %04x on %d\n", regop.reg, regop.val, chan->chanpos); - wctdm_setreg(wc, chan->chanpos - 1, regop.reg, regop.val); - } - break; - case WCTDM_SET_ECHOTUNE: - printk("-- Setting echo registers: \n"); - if (copy_from_user(&echoregs, (struct wctdm_echo_coefs*)data, sizeof(echoregs))) - return -EFAULT; - - if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { - /* Set the ACIM register */ - wctdm_setreg(wc, chan->chanpos - 1, 30, echoregs.acim); - - /* Set the digital echo canceller registers */ - wctdm_setreg(wc, chan->chanpos - 1, 45, echoregs.coef1); - wctdm_setreg(wc, chan->chanpos - 1, 46, echoregs.coef2); - wctdm_setreg(wc, chan->chanpos - 1, 47, echoregs.coef3); - wctdm_setreg(wc, chan->chanpos - 1, 48, echoregs.coef4); - wctdm_setreg(wc, chan->chanpos - 1, 49, echoregs.coef5); - wctdm_setreg(wc, chan->chanpos - 1, 50, echoregs.coef6); - wctdm_setreg(wc, chan->chanpos - 1, 51, echoregs.coef7); - wctdm_setreg(wc, chan->chanpos - 1, 52, echoregs.coef8); - - printk("-- Set echo registers successfully\n"); - - break; - } else { - return -EINVAL; - - } - break; - case ZT_SET_HWGAIN: - if (copy_from_user(&hwgain, (struct zt_hwgain*) data, sizeof(hwgain))) - return -EFAULT; - - wctdm_set_hwgain(wc, chan->chanpos-1, hwgain.newgain, hwgain.tx); - - if (debug) - printk("Setting hwgain on channel %d to %d for %s direction\n", - chan->chanpos-1, hwgain.newgain, hwgain.tx ? "tx" : "rx"); - break; -#ifdef VPM_SUPPORT - case ZT_TONEDETECT: - if (get_user(x, (int *) data)) - return -EFAULT; - if (!wc->vpm && !wc->vpm150m) - return -ENOSYS; - if ((wc->vpm || wc->vpm150m) && (x && !vpmdtmfsupport)) - return -ENOSYS; - if (x & ZT_TONEDETECT_ON) { - set_bit(chan->chanpos - 1, &wc->dtmfmask); - } else { - clear_bit(chan->chanpos - 1, &wc->dtmfmask); - } - if (x & ZT_TONEDETECT_MUTE) { - if (wc->vpm150m) { - set_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); - } - } else { - if (wc->vpm150m) { - clear_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); - } - } - return 0; -#endif - case ZT_RADIO_GETPARAM: - if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_QRV) - return -ENOTTY; - if (copy_from_user(&stack.p,(struct zt_radio_param *)data,sizeof(struct zt_radio_param))) return -EFAULT; - stack.p.data = 0; /* start with 0 value in output */ - switch(stack.p.radpar) { - case ZT_RADPAR_INVERTCOR: - if (wc->radmode[chan->chanpos - 1] & RADMODE_INVERTCOR) - stack.p.data = 1; - break; - case ZT_RADPAR_IGNORECOR: - if (wc->radmode[chan->chanpos - 1] & RADMODE_IGNORECOR) - stack.p.data = 1; - break; - case ZT_RADPAR_IGNORECT: - if (wc->radmode[chan->chanpos - 1] & RADMODE_IGNORECT) - stack.p.data = 1; - break; - case ZT_RADPAR_EXTRXTONE: - stack.p.data = 0; - if (wc->radmode[chan->chanpos - 1] & RADMODE_EXTTONE) - { - stack.p.data = 1; - if (wc->radmode[chan->chanpos - 1] & RADMODE_EXTINVERT) - { - stack.p.data = 2; - } - } - break; - case ZT_RADPAR_DEBOUNCETIME: - stack.p.data = wc->debouncetime[chan->chanpos - 1]; - break; - case ZT_RADPAR_RXGAIN: - stack.p.data = wc->rxgain[chan->chanpos - 1] - 1199; - break; - case ZT_RADPAR_TXGAIN: - stack.p.data = wc->txgain[chan->chanpos - 1] - 3599; - break; - case ZT_RADPAR_DEEMP: - stack.p.data = 0; - if (wc->radmode[chan->chanpos - 1] & RADMODE_DEEMP) - { - stack.p.data = 1; - } - break; - case ZT_RADPAR_PREEMP: - stack.p.data = 0; - if (wc->radmode[chan->chanpos - 1] & RADMODE_PREEMP) - { - stack.p.data = 1; - } - break; - default: - return -EINVAL; - } - if (copy_to_user((struct zt_radio_param *)data,&stack.p,sizeof(struct zt_radio_param))) return -EFAULT; - break; - case ZT_RADIO_SETPARAM: - if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_QRV) - return -ENOTTY; - if (copy_from_user(&stack.p,(struct zt_radio_param *)data,sizeof(struct zt_radio_param))) return -EFAULT; - switch(stack.p.radpar) { - case ZT_RADPAR_INVERTCOR: - if (stack.p.data) - wc->radmode[chan->chanpos - 1] |= RADMODE_INVERTCOR; - else - wc->radmode[chan->chanpos - 1] &= ~RADMODE_INVERTCOR; - return 0; - case ZT_RADPAR_IGNORECOR: - if (stack.p.data) - wc->radmode[chan->chanpos - 1] |= RADMODE_IGNORECOR; - else - wc->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECOR; - return 0; - case ZT_RADPAR_IGNORECT: - if (stack.p.data) - wc->radmode[chan->chanpos - 1] |= RADMODE_IGNORECT; - else - wc->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECT; - return 0; - case ZT_RADPAR_EXTRXTONE: - if (stack.p.data) - wc->radmode[chan->chanpos - 1] |= RADMODE_EXTTONE; - else - wc->radmode[chan->chanpos - 1] &= ~RADMODE_EXTTONE; - if (stack.p.data > 1) - wc->radmode[chan->chanpos - 1] |= RADMODE_EXTINVERT; - else - wc->radmode[chan->chanpos - 1] &= ~RADMODE_EXTINVERT; - return 0; - case ZT_RADPAR_DEBOUNCETIME: - wc->debouncetime[chan->chanpos - 1] = stack.p.data; - return 0; - case ZT_RADPAR_RXGAIN: - /* if out of range */ - if ((stack.p.data <= -1200) || (stack.p.data > 1552)) - { - return -EINVAL; - } - wc->rxgain[chan->chanpos - 1] = stack.p.data + 1199; - break; - case ZT_RADPAR_TXGAIN: - /* if out of range */ - if (wc->radmode[chan->chanpos -1] & RADMODE_PREEMP) - { - if ((stack.p.data <= -2400) || (stack.p.data > 0)) - { - return -EINVAL; - } - } - else - { - if ((stack.p.data <= -3600) || (stack.p.data > 1200)) - { - return -EINVAL; - } - } - wc->txgain[chan->chanpos - 1] = stack.p.data + 3599; - break; - case ZT_RADPAR_DEEMP: - if (stack.p.data) - wc->radmode[chan->chanpos - 1] |= RADMODE_DEEMP; - else - wc->radmode[chan->chanpos - 1] &= ~RADMODE_DEEMP; - wc->rxgain[chan->chanpos - 1] = 1199; - break; - case ZT_RADPAR_PREEMP: - if (stack.p.data) - wc->radmode[chan->chanpos - 1] |= RADMODE_PREEMP; - else - wc->radmode[chan->chanpos - 1] &= ~RADMODE_PREEMP; - wc->txgain[chan->chanpos - 1] = 3599; - break; - default: - return -EINVAL; - } - qrv_dosetup(chan,wc); - return 0; - default: - return -ENOTTY; - } - return 0; -} - -static int wctdm_open(struct zt_chan *chan) -{ - struct wctdm *wc = chan->pvt; - if (!(wc->cardflag & (1 << (chan->chanpos - 1)))) - return -ENODEV; - if (wc->dead) - return -ENODEV; - wc->usecount++; -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#else - try_module_get(THIS_MODULE); -#endif - return 0; -} - -static int wctdm_watchdog(struct zt_span *span, int event) -{ - printk("TDM: Restarting DMA\n"); - wctdm_restart_dma(span->pvt); - return 0; -} - -static int wctdm_close(struct zt_chan *chan) -{ - struct wctdm *wc = chan->pvt; - int x; - signed char reg; - wc->usecount--; -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#else - module_put(THIS_MODULE); -#endif - for (x=0;xcards;x++) { - if (wc->modtype[x] == MOD_TYPE_FXS) - wc->mods[x].fxs.idletxhookstate = 1; - if (wc->modtype[x] == MOD_TYPE_QRV) - { - int qrvcard = x & 0xfc; - - wc->qrvhook[x] = 0; - wc->qrvhook[x + 2] = 0xff; - wc->debouncetime[x] = QRV_DEBOUNCETIME; - wc->qrvdebtime[x] = 0; - wc->radmode[x] = 0; - wc->txgain[x] = 3599; - wc->rxgain[x] = 1199; - reg = 0; - if (!wc->qrvhook[qrvcard]) reg |= 1; - if (!wc->qrvhook[qrvcard + 1]) reg |= 0x10; - wc->sethook[qrvcard] = CMD_WR(3, reg); - qrv_dosetup(chan,wc); - } - } - /* If we're dead, release us now */ - if (!wc->usecount && wc->dead) - wctdm_release(wc); - return 0; -} - -static int wctdm_hooksig(struct zt_chan *chan, zt_txsig_t txsig) -{ - struct wctdm *wc = chan->pvt; - int reg=0,qrvcard; - if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_QRV) { - qrvcard = (chan->chanpos - 1) & 0xfc; - switch(txsig) { - case ZT_TXSIG_START: - case ZT_TXSIG_OFFHOOK: - wc->qrvhook[chan->chanpos - 1] = 1; - break; - case ZT_TXSIG_ONHOOK: - wc->qrvhook[chan->chanpos - 1] = 0; - break; - default: - printk("wctdm24xxp: Can't set tx state to %d\n", txsig); - } - reg = 0; - if (!wc->qrvhook[qrvcard]) reg |= 1; - if (!wc->qrvhook[qrvcard + 1]) reg |= 0x10; - wc->sethook[qrvcard] = CMD_WR(3, reg); - /* wctdm_setreg(wc, qrvcard, 3, reg); */ - } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { - switch(txsig) { - case ZT_TXSIG_START: - case ZT_TXSIG_OFFHOOK: - wc->mods[chan->chanpos - 1].fxo.offhook = 1; - wc->sethook[chan->chanpos - 1] = CMD_WR(5, 0x9); - /* wctdm_setreg(wc, chan->chanpos - 1, 5, 0x9); */ - break; - case ZT_TXSIG_ONHOOK: - wc->mods[chan->chanpos - 1].fxo.offhook = 0; - wc->sethook[chan->chanpos - 1] = CMD_WR(5, 0x8); - /* wctdm_setreg(wc, chan->chanpos - 1, 5, 0x8); */ - break; - default: - printk("wctdm24xxp: Can't set tx state to %d\n", txsig); - } - } else { - switch(txsig) { - case ZT_TXSIG_ONHOOK: - switch(chan->sig) { - case ZT_SIG_EM: - case ZT_SIG_FXOKS: - case ZT_SIG_FXOLS: - wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x10 | - wc->mods[chan->chanpos - 1].fxs.idletxhookstate; - break; - case ZT_SIG_FXOGS: - wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x13; - break; - } - break; - case ZT_TXSIG_OFFHOOK: - switch(chan->sig) { - case ZT_SIG_EM: - wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x15; - break; - default: - wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x10 | - wc->mods[chan->chanpos - 1].fxs.idletxhookstate; - break; - } - break; - case ZT_TXSIG_START: - wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x14; - break; - case ZT_TXSIG_KEWL: - wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x10; - break; - default: - printk("wctdm24xxp: Can't set tx state to %d\n", txsig); - } - if (debug & DEBUG_CARD) - printk("Setting FXS hook state to %d (%02x)\n", txsig, reg); - - - wc->sethook[chan->chanpos - 1] = CMD_WR(64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); - /* wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); */ - } - return 0; -} - -static void wctdm_dacs_connect(struct wctdm *wc, int srccard, int dstcard) -{ - - if (wc->dacssrc[dstcard] > - 1) { - printk("wctdm_dacs_connect: Can't have double sourcing yet!\n"); - return; - } - if (!((wc->modtype[srccard] == MOD_TYPE_FXS)||(wc->modtype[srccard] == MOD_TYPE_FXO))){ - printk("wctdm_dacs_connect: Unsupported modtype for card %d\n", srccard); - return; - } - if (!((wc->modtype[dstcard] == MOD_TYPE_FXS)||(wc->modtype[dstcard] == MOD_TYPE_FXO))){ - printk("wctdm_dacs_connect: Unsupported modtype for card %d\n", dstcard); - return; - } - if (debug) - printk("connect %d => %d\n", srccard, dstcard); - wc->dacssrc[dstcard] = srccard; - - /* make srccard transmit to srccard+24 on the TDM bus */ - if (wc->modtype[srccard] == MOD_TYPE_FXS) { - /* proslic */ - wctdm_setreg(wc, srccard, PCM_XMIT_START_COUNT_LSB, ((srccard+24) * 8) & 0xff); - wctdm_setreg(wc, srccard, PCM_XMIT_START_COUNT_MSB, ((srccard+24) * 8) >> 8); - } else if(wc->modtype[srccard] == MOD_TYPE_FXO) { - /* daa */ - wctdm_setreg(wc, srccard, 34, ((srccard+24) * 8) & 0xff); /* TX */ - wctdm_setreg(wc, srccard, 35, ((srccard+24) * 8) >> 8); /* TX */ - } - - /* have dstcard receive from srccard+24 on the TDM bus */ - if (wc->modtype[dstcard] == MOD_TYPE_FXS) { - /* proslic */ - wctdm_setreg(wc, dstcard, PCM_RCV_START_COUNT_LSB, ((srccard+24) * 8) & 0xff); - wctdm_setreg(wc, dstcard, PCM_RCV_START_COUNT_MSB, ((srccard+24) * 8) >> 8); - } else if(wc->modtype[dstcard] == MOD_TYPE_FXO) { - /* daa */ - wctdm_setreg(wc, dstcard, 36, ((srccard+24) * 8) & 0xff); /* RX */ - wctdm_setreg(wc, dstcard, 37, ((srccard+24) * 8) >> 8); /* RX */ - } - -} - -static void wctdm_dacs_disconnect(struct wctdm *wc, int card) -{ - if (wc->dacssrc[card] > -1) { - if (debug) - printk("wctdm_dacs_disconnect: restoring TX for %d and RX for %d\n",wc->dacssrc[card], card); - - /* restore TX (source card) */ - if(wc->modtype[wc->dacssrc[card]] == MOD_TYPE_FXS){ - wctdm_setreg(wc, wc->dacssrc[card], PCM_XMIT_START_COUNT_LSB, (wc->dacssrc[card] * 8) & 0xff); - wctdm_setreg(wc, wc->dacssrc[card], PCM_XMIT_START_COUNT_MSB, (wc->dacssrc[card] * 8) >> 8); - } else if(wc->modtype[wc->dacssrc[card]] == MOD_TYPE_FXO){ - wctdm_setreg(wc, card, 34, (card * 8) & 0xff); - wctdm_setreg(wc, card, 35, (card * 8) >> 8); - } else { - printk("WARNING: wctdm_dacs_disconnect() called on unsupported modtype\n"); - } - - /* restore RX (this card) */ - if(wc->modtype[card] == MOD_TYPE_FXS){ - wctdm_setreg(wc, card, PCM_RCV_START_COUNT_LSB, (card * 8) & 0xff); - wctdm_setreg(wc, card, PCM_RCV_START_COUNT_MSB, (card * 8) >> 8); - } else if(wc->modtype[card] == MOD_TYPE_FXO){ - wctdm_setreg(wc, card, 36, (card * 8) & 0xff); - wctdm_setreg(wc, card, 37, (card * 8) >> 8); - } else { - printk("WARNING: wctdm_dacs_disconnect() called on unsupported modtype\n"); - } - - wc->dacssrc[card] = -1; - } -} - -static int wctdm_dacs(struct zt_chan *dst, struct zt_chan *src) -{ - struct wctdm *wc; - - if(!nativebridge) - return 0; /* should this return -1 since unsuccessful? */ - - wc = dst->pvt; - - if(src) { - wctdm_dacs_connect(wc, src->chanpos - 1, dst->chanpos - 1); - if (debug) - printk("dacs connecct: %d -> %d!\n\n", src->chanpos, dst->chanpos); - } else { - wctdm_dacs_disconnect(wc, dst->chanpos - 1); - if (debug) - printk("dacs disconnect: %d!\n", dst->chanpos); - } - return 0; -} - -static int wctdm_initialize(struct wctdm *wc) -{ - int x; - - /* Zapata stuff */ - sprintf(wc->span.name, "WCTDM/%d", wc->pos); - snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1); - snprintf(wc->span.location, sizeof(wc->span.location) - 1, - "PCI%s Bus %02d Slot %02d", (wc->flags[0] & FLAG_EXPRESS) ? " Express" : "", - wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); - wc->span.manufacturer = "Digium"; - strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); - if (alawoverride) { - printk("ALAW override parameter detected. Device will be operating in ALAW\n"); - wc->span.deflaw = ZT_LAW_ALAW; - } else - wc->span.deflaw = ZT_LAW_MULAW; - for (x=0;xcards;x++) { - sprintf(wc->chans[x].name, "WCTDM/%d/%d", wc->pos, x); - wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR; - wc->chans[x].sigcap |= ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR; - wc->chans[x].chanpos = x+1; - wc->chans[x].pvt = wc; - } - wc->span.chans = wc->chans; - wc->span.channels = wc->type; - wc->span.irq = wc->dev->irq; - wc->span.hooksig = wctdm_hooksig; - wc->span.open = wctdm_open; - wc->span.close = wctdm_close; - wc->span.flags = ZT_FLAG_RBS; - wc->span.ioctl = wctdm_ioctl; - wc->span.watchdog = wctdm_watchdog; - wc->span.dacs= wctdm_dacs; -#ifdef VPM_SUPPORT - wc->span.echocan_with_params = wctdm_echocan_with_params; -#endif - init_waitqueue_head(&wc->span.maintq); - - wc->span.pvt = wc; - if (zt_register(&wc->span, 0)) { - printk("Unable to register span with zaptel\n"); - return -1; - } - return 0; -} - -static void wctdm_post_initialize(struct wctdm *wc) -{ - int x; - - /* Finalize signalling */ - for (x = 0; x cards; x++) { - if (wc->cardflag & (1 << x)) { - if (wc->modtype[x] == MOD_TYPE_FXO) - wc->chans[x].sigcap = ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR; - else if (wc->modtype[x] == MOD_TYPE_FXS) - wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR; - else if (wc->modtype[x] == MOD_TYPE_QRV) - wc->chans[x].sigcap = ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR; - } else if (!(wc->chans[x].sigcap & ZT_SIG_BROKEN)) { - wc->chans[x].sigcap = 0; - } - } - - if (wc->vpm) - strncat(wc->span.devicetype, " with VPM100M", sizeof(wc->span.devicetype) - 1); - else if (wc->vpm150m) - strncat(wc->span.devicetype, " with VPMADT032", sizeof(wc->span.devicetype) - 1); -} - -static int wctdm_hardware_init(struct wctdm *wc) -{ - /* Hardware stuff */ - unsigned int reg; - unsigned long newjiffies; - - /* Initialize descriptors */ - wctdm_init_descriptors(wc); - - /* Enable I/O Access */ - pci_read_config_dword(wc->dev, 0x0004, ®); - reg |= 0x00000007; - pci_write_config_dword(wc->dev, 0x0004, reg); - printk("PCI Config reg is %08x\n", reg); - - wctdm_setctl(wc, 0x0000, 0xfff88001); - - newjiffies = jiffies + HZ/10; - while(((reg = wctdm_getctl(wc,0x0000)) & 0x00000001) && (newjiffies > jiffies)); - printk("%s: New Reg: %08x!\n", wc->variety, reg); - wctdm_setctl(wc, 0x0000, 0xfff88000); - - - /* Configure watchdogs, access, etc */ - wctdm_setctl(wc, 0x0030, 0x00080048); - wctdm_setctl(wc, 0x0078, 0x00000013 /* | (1 << 28) */); - -#if 0 - /* XXX Enable loopback XXX */ - reg = wctdm_getctl(wc, 0x0030); - wctdm_setctl(wc, 0x0030, reg | 0x00000400); - -#else - reg = wctdm_getctl(wc, 0x00fc); - wctdm_setctl(wc, 0x00fc, (reg & ~0x7) | 0x7); - wctdm_setsdi(wc, 0x00, 0x0100); - wctdm_setsdi(wc, 0x16, 0x2100); - printk("Detected REG0: %08x\n", wctdm_getsdi(wc, 0x00)); - printk("Detected REG1: %08x\n", wctdm_getsdi(wc, 0x01)); - printk("Detected REG2: %08x\n", wctdm_getsdi(wc, 0x02)); - - reg = wctdm_getctl(wc, 0x00fc); - printk("(pre) Reg fc is %08x\n", reg); - - wctdm_setctl(wc, 0x00fc, (reg & ~0x7) | 0x4); - wctdm_setsdi(wc, 0x00, 0x0100); - wctdm_setsdi(wc, 0x16, 0x2100); - reg = wctdm_getctl(wc, 0x00fc); - printk("(post) Reg fc is %08x\n", reg); - printk("Detected REG2: %08x\n", wctdm_getsdi(wc, 0x02)); -#endif - printk("wctdm24xxp: reg is %08x\n", wctdm_getctl(wc, 0x0088)); - - return 0; -} - -static void wctdm_setintmask(struct wctdm *wc, unsigned int intmask) -{ - wc->intmask = intmask; - wctdm_setctl(wc, 0x0038, intmask); -} - -static void wctdm_enable_interrupts(struct wctdm *wc) -{ - /* Enable interrupts */ - wctdm_setintmask(wc, 0x00010041); -} - -static void wctdm_restart_dma(struct wctdm *wc) -{ -} - -static void wctdm_start_dma(struct wctdm *wc) -{ - unsigned int reg; - wmb(); - wctdm_setctl(wc, 0x0020, wc->descripdma); - wctdm_setctl(wc, 0x0018, wc->descripdma + (16 * ERING_SIZE)); - /* Start receiver/transmitter */ - reg = wctdm_getctl(wc, 0x0030); - wctdm_setctl(wc, 0x0030, reg | 0x00002002); - wctdm_setctl(wc, 0x0008, 0x00000000); - wctdm_setctl(wc, 0x0010, 0x00000000); - reg = wctdm_getctl(wc, 0x0028); - wctdm_setctl(wc, 0x0028, reg); - -} - -static void wctdm_stop_dma(struct wctdm *wc) -{ - /* Disable interrupts and reset */ - unsigned int reg; - /* Disable interrupts */ - wctdm_setintmask(wc, 0x00000000); - wctdm_setctl(wc, 0x0084, 0x00000000); - wctdm_setctl(wc, 0x0048, 0x00000000); - /* Reset the part to be on the safe side */ - reg = wctdm_getctl(wc, 0x0000); - reg |= 0x00000001; - wctdm_setctl(wc, 0x0000, reg); -} - -static void wctdm_disable_interrupts(struct wctdm *wc) -{ - /* Disable interrupts */ - wctdm_setintmask(wc, 0x00000000); - wctdm_setctl(wc, 0x0084, 0x00000000); -} - -#ifdef VPM_SUPPORT - -#ifdef VPM150M_SUPPORT - -void vpm150m_set_chanconfig_from_state(struct adt_lec_params * parms, int channum, GpakChannelConfig_t *chanconfig) -{ - chanconfig->PcmInPortA = 3; - chanconfig->PcmInSlotA = channum; - chanconfig->PcmOutPortA = SerialPortNull; - chanconfig->PcmOutSlotA = channum; - chanconfig->PcmInPortB = 2; - chanconfig->PcmInSlotB = channum; - chanconfig->PcmOutPortB = 3; - chanconfig->PcmOutSlotB = channum; - if (vpmdtmfsupport) { - chanconfig->ToneTypesA = DTMF_tone; - chanconfig->MuteToneA = Enabled; - chanconfig->FaxCngDetA = Enabled; - } else { - chanconfig->ToneTypesA = Null_tone; - chanconfig->MuteToneA = Disabled; - chanconfig->FaxCngDetA = Disabled; - } - chanconfig->ToneTypesB = Null_tone; - chanconfig->EcanEnableA = Enabled; - chanconfig->EcanEnableB = Disabled; - chanconfig->MuteToneB = Disabled; - chanconfig->FaxCngDetB = Disabled; - - if (alawoverride) - chanconfig->SoftwareCompand = cmpPCMA; - else - chanconfig->SoftwareCompand = cmpPCMU; - - chanconfig->FrameRate = rate2ms; - chanconfig->EcanParametersA.EcanTapLength = 1024; - chanconfig->EcanParametersA.EcanNlpType = parms->nlp_type; - chanconfig->EcanParametersA.EcanAdaptEnable = 1; - chanconfig->EcanParametersA.EcanG165DetEnable = 1; - chanconfig->EcanParametersA.EcanDblTalkThresh = 6; - chanconfig->EcanParametersA.EcanNlpThreshold = parms->nlp_threshold; - chanconfig->EcanParametersA.EcanNlpConv = 0; - chanconfig->EcanParametersA.EcanNlpUnConv = 0; - chanconfig->EcanParametersA.EcanNlpMaxSuppress = parms->nlp_max_suppress; - chanconfig->EcanParametersA.EcanCngThreshold = 43; - chanconfig->EcanParametersA.EcanAdaptLimit = 50; - chanconfig->EcanParametersA.EcanCrossCorrLimit = 15; - chanconfig->EcanParametersA.EcanNumFirSegments = 3; - chanconfig->EcanParametersA.EcanFirSegmentLen = 64; - - chanconfig->EcanParametersB.EcanTapLength = 1024; - chanconfig->EcanParametersB.EcanNlpType = parms->nlp_type; - chanconfig->EcanParametersB.EcanAdaptEnable = 1; - chanconfig->EcanParametersB.EcanG165DetEnable = 1; - chanconfig->EcanParametersB.EcanDblTalkThresh = 6; - chanconfig->EcanParametersB.EcanNlpThreshold = parms->nlp_threshold; - chanconfig->EcanParametersB.EcanNlpConv = 0; - chanconfig->EcanParametersB.EcanNlpUnConv = 0; - chanconfig->EcanParametersB.EcanNlpMaxSuppress = parms->nlp_max_suppress; - chanconfig->EcanParametersB.EcanCngThreshold = 43; - chanconfig->EcanParametersB.EcanAdaptLimit = 50; - chanconfig->EcanParametersB.EcanCrossCorrLimit = 15; - chanconfig->EcanParametersB.EcanNumFirSegments = 3; - chanconfig->EcanParametersB.EcanFirSegmentLen = 64; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void vpm150m_bh(void *data) -{ - struct vpm150m *vpm150m = data; -#else -static void vpm150m_bh(struct work_struct *data) -{ - struct vpm150m *vpm150m = container_of(data, struct vpm150m, work); -#endif - struct wctdm *wc = vpm150m->wc; - int i; - - for (i = 0; i < wc->type; i++) { - int enable = -1; - if (test_bit(i, &vpm150m->desireddtmfmutestate)) { - if (!test_bit(i, &vpm150m->curdtmfmutestate)) { - enable = 1; - } - } else { - if (test_bit(i, &vpm150m->curdtmfmutestate)) { - enable = 0; - } - } - if (enable > -1) { - unsigned int start = wc->intcount; - GPAK_AlgControlStat_t pstatus; - int res; - - if (enable) { - res = gpakAlgControl(vpm150m->dspid, i, EnableDTMFMuteA, &pstatus); - if (debug & DEBUG_ECHOCAN) - printk("DTMF mute enable took %d ms\n", wc->intcount - start); - } else { - res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &pstatus); - if (debug & DEBUG_ECHOCAN) - printk("DTMF mute disable took %d ms\n", wc->intcount - start); - } - if (!res) - change_bit(i, &vpm150m->curdtmfmutestate); - } - } - - if (test_bit(VPM150M_DTMFDETECT, &vpm150m->control)) { - unsigned short channel; - GpakAsyncEventCode_t eventcode; - GpakAsyncEventData_t eventdata; - gpakReadEventFIFOMessageStat_t res; - unsigned int start = wc->intcount; - - do { - res = gpakReadEventFIFOMessage(vpm150m->dspid, &channel, &eventcode, &eventdata); - - if (debug & DEBUG_ECHOCAN) - printk("ReadEventFIFOMessage took %d ms\n", wc->intcount - start); - - if (res == RefInvalidEvent || res == RefDspCommFailure) { - printk("Uh oh (%d)\n", res); - continue; - } - - if (eventcode == EventToneDetect) { - GpakToneCodes_t tone = eventdata.toneEvent.ToneCode; - int duration = eventdata.toneEvent.ToneDuration; - char zaptone = vpm150mtone_to_zaptone(tone); - - if (debug & DEBUG_ECHOCAN) - printk("Channel %d: Detected DTMF tone %d of duration %d!!!\n", channel + 1, tone, duration); - - if (test_bit(channel, &wc->dtmfmask) && (eventdata.toneEvent.ToneDuration > 0)) { - struct zt_chan *chan = &wc->chans[channel]; - - if ((tone != EndofMFDigit) && (zaptone != 0)) { - vpm150m->curtone[channel] = tone; - - if (test_bit(channel, &vpm150m->curdtmfmutestate)) { - unsigned long flags; - int y; - - /* Mute the audio data buffers */ - spin_lock_irqsave(&chan->lock, flags); - for (y = 0; y < chan->numbufs; y++) { - if ((chan->inreadbuf > -1) && (chan->readidx[y])) - memset(chan->readbuf[chan->inreadbuf], ZT_XLAW(0, chan), chan->readidx[y]); - } - spin_unlock_irqrestore(&chan->lock, flags); - } - if (!test_bit(channel, &wc->dtmfactive)) { - if (debug & DEBUG_ECHOCAN) - printk("Queuing DTMFDOWN %c\n", zaptone); - set_bit(channel, &wc->dtmfactive); - zt_qevent_lock(chan, (ZT_EVENT_DTMFDOWN | zaptone)); - } - } else if ((tone == EndofMFDigit) && test_bit(channel, &wc->dtmfactive)) { - if (debug & DEBUG_ECHOCAN) - printk("Queuing DTMFUP %c\n", vpm150mtone_to_zaptone(vpm150m->curtone[channel])); - zt_qevent_lock(chan, (ZT_EVENT_DTMFUP | vpm150mtone_to_zaptone(vpm150m->curtone[channel]))); - clear_bit(channel, &wc->dtmfactive); - } - } - } - } while ((res != RefNoEventAvail) && (res != RefInvalidEvent) && (res != RefDspCommFailure)); - } - - for (i = 0; i < wc->type; i++) { - unsigned int start = wc->intcount; - GPAK_AlgControlStat_t pstatus; - int res = 1; - - if ((vpm150m->desiredecstate[i].nlp_type != vpm150m->curecstate[i].nlp_type) - || (vpm150m->desiredecstate[i].nlp_threshold != vpm150m->curecstate[i].nlp_threshold) - || (vpm150m->desiredecstate[i].nlp_max_suppress != vpm150m->curecstate[i].nlp_max_suppress)) { - - GPAK_ChannelConfigStat_t cstatus; - GPAK_TearDownChanStat_t tstatus; - GpakChannelConfig_t chanconfig; - - if (debug & DEBUG_ECHOCAN) - printk("Reconfiguring chan %d for nlp %d, nlp_thresh %d, and max_supp %d\n", i + 1, vpm150m->desiredecstate[i].nlp_type, - vpm150m->desiredecstate[i].nlp_threshold, vpm150m->desiredecstate[i].nlp_max_suppress); - - vpm150m_set_chanconfig_from_state(&vpm150m->desiredecstate[i], i, &chanconfig); - - if ((res = gpakTearDownChannel(vpm150m->dspid, i, &tstatus))) { - goto vpm_bh_out; - } - - if ((res = gpakConfigureChannel(vpm150m->dspid, i, tdmToTdm, &chanconfig, &cstatus))) { - goto vpm_bh_out; - } - - if (!vpm150m->desiredecstate[i].tap_length) - res = gpakAlgControl(vpm150m->dspid, i, BypassEcanA, &pstatus); - - } else if (vpm150m->desiredecstate[i].tap_length != vpm150m->curecstate[i].tap_length) { - if (vpm150m->desiredecstate[i].tap_length) { - res = gpakAlgControl(vpm150m->dspid, i, EnableEcanA, &pstatus); - if (debug & DEBUG_ECHOCAN) - printk("Echocan enable took %d ms\n", wc->intcount - start); - } else { - res = gpakAlgControl(vpm150m->dspid, i, BypassEcanA, &pstatus); - if (debug & DEBUG_ECHOCAN) - printk("Echocan disable took %d ms\n", wc->intcount - start); - } - } - -vpm_bh_out: - if (!res) - vpm150m->curecstate[i] = vpm150m->desiredecstate[i]; - } - - return; -} - -static int vpm150m_config_hw(struct wctdm *wc) -{ - struct vpm150m *vpm150m = wc->vpm150m; - gpakConfigPortStatus_t configportstatus; - GpakPortConfig_t portconfig; - GPAK_PortConfigStat_t pstatus; - GpakChannelConfig_t chanconfig; - GPAK_ChannelConfigStat_t cstatus; - GPAK_AlgControlStat_t algstatus; - - int res, i; - - memset(&portconfig, 0, sizeof(GpakPortConfig_t)); - - /* First Serial Port config */ - portconfig.SlotsSelect1 = SlotCfgNone; - portconfig.FirstBlockNum1 = 0; - portconfig.FirstSlotMask1 = 0x0000; - portconfig.SecBlockNum1 = 1; - portconfig.SecSlotMask1 = 0x0000; - portconfig.SerialWordSize1 = SerWordSize8; - portconfig.CompandingMode1 = cmpNone; - portconfig.TxFrameSyncPolarity1 = FrameSyncActHigh; - portconfig.RxFrameSyncPolarity1 = FrameSyncActHigh; - portconfig.TxClockPolarity1 = SerClockActHigh; - portconfig.RxClockPolarity1 = SerClockActHigh; - portconfig.TxDataDelay1 = DataDelay0; - portconfig.RxDataDelay1 = DataDelay0; - portconfig.DxDelay1 = Disabled; - portconfig.ThirdSlotMask1 = 0x0000; - portconfig.FouthSlotMask1 = 0x0000; - portconfig.FifthSlotMask1 = 0x0000; - portconfig.SixthSlotMask1 = 0x0000; - portconfig.SevenSlotMask1 = 0x0000; - portconfig.EightSlotMask1 = 0x0000; - - /* Second Serial Port config */ - portconfig.SlotsSelect2 = SlotCfg2Groups; - portconfig.FirstBlockNum2 = 0; - portconfig.FirstSlotMask2 = 0xffff; - portconfig.SecBlockNum2 = 1; - portconfig.SecSlotMask2 = 0xffff; - portconfig.SerialWordSize2 = SerWordSize8; - portconfig.CompandingMode2 = cmpNone; - portconfig.TxFrameSyncPolarity2 = FrameSyncActHigh; - portconfig.RxFrameSyncPolarity2 = FrameSyncActHigh; - portconfig.TxClockPolarity2 = SerClockActHigh; - portconfig.RxClockPolarity2 = SerClockActLow; - portconfig.TxDataDelay2 = DataDelay0; - portconfig.RxDataDelay2 = DataDelay0; - portconfig.DxDelay2 = Disabled; - portconfig.ThirdSlotMask2 = 0x0000; - portconfig.FouthSlotMask2 = 0x0000; - portconfig.FifthSlotMask2 = 0x0000; - portconfig.SixthSlotMask2 = 0x0000; - portconfig.SevenSlotMask2 = 0x0000; - portconfig.EightSlotMask2 = 0x0000; - - /* Third Serial Port Config */ - portconfig.SlotsSelect3 = SlotCfg2Groups; - portconfig.FirstBlockNum3 = 0; - portconfig.FirstSlotMask3 = 0xffff; - portconfig.SecBlockNum3 = 1; - portconfig.SecSlotMask3 = 0xffff; - portconfig.SerialWordSize3 = SerWordSize8; - portconfig.CompandingMode3 = cmpNone; - portconfig.TxFrameSyncPolarity3 = FrameSyncActHigh; - portconfig.RxFrameSyncPolarity3 = FrameSyncActHigh; - portconfig.TxClockPolarity3 = SerClockActHigh; - portconfig.RxClockPolarity3 = SerClockActLow; - portconfig.TxDataDelay3 = DataDelay0; - portconfig.RxDataDelay3 = DataDelay0; - portconfig.DxDelay3 = Disabled; - portconfig.ThirdSlotMask3 = 0x0000; - portconfig.FouthSlotMask3 = 0x0000; - portconfig.FifthSlotMask3 = 0x0000; - portconfig.SixthSlotMask3 = 0x0000; - portconfig.SevenSlotMask3 = 0x0000; - portconfig.EightSlotMask3 = 0x0000; - - if ((configportstatus = gpakConfigurePorts(vpm150m->dspid, &portconfig, &pstatus))) { - printk("Configuration of ports failed (%d)!\n", configportstatus); - return -1; - } else { - if (debug & DEBUG_ECHOCAN) - printk("Configured McBSP ports successfully\n"); - } - - if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { - printk("Error pinging DSP (%d)\n", res); - return -1; - } - - for (i = 0; i < wc->type; i++) { - vpm150m->curecstate[i].tap_length = 0; - vpm150m->curecstate[i].nlp_type = vpmnlptype; - vpm150m->curecstate[i].nlp_threshold = vpmnlpthresh; - vpm150m->curecstate[i].nlp_max_suppress = vpmnlpmaxsupp; - - vpm150m->desiredecstate[i].tap_length = 0; - vpm150m->desiredecstate[i].nlp_type = vpmnlptype; - vpm150m->desiredecstate[i].nlp_threshold = vpmnlpthresh; - vpm150m->desiredecstate[i].nlp_max_suppress = vpmnlpmaxsupp; - - vpm150m_set_chanconfig_from_state(&vpm150m->curecstate[i], i, &chanconfig); - - if ((res = gpakConfigureChannel(vpm150m->dspid, i, tdmToTdm, &chanconfig, &cstatus))) { - printk("Unable to configure channel (%d)\n", res); - if (res == 1) { - printk("Reason %d\n", cstatus); - } - - return -1; - } - - if ((res = gpakAlgControl(vpm150m->dspid, i, BypassEcanA, &algstatus))) { - printk("Unable to disable echo can on channel %d (reason %d:%d)\n", i + 1, res, algstatus); - return -1; - } - - if (vpmdtmfsupport) { - if ((res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &algstatus))) { - printk("Unable to disable dtmf muting on channel %d (reason %d:%d)\n", i + 1, res, algstatus); - return -1; - } - } - } - - if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { - printk("Error pinging DSP (%d)\n", res); - return -1; - } - - vpm150m->wq = create_singlethread_workqueue("wctdm24xxp"); - vpm150m->wc = wc; - - if (!vpm150m->wq) { - printk("Unable to create work queue!\n"); - return -1; - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - INIT_WORK(&vpm150m->work, vpm150m_bh, vpm150m); -#else - INIT_WORK(&vpm150m->work, vpm150m_bh); -#endif - - /* Turn on DTMF detection */ - if (vpmdtmfsupport) - set_bit(VPM150M_DTMFDETECT, &vpm150m->control); - - set_bit(VPM150M_ACTIVE, &vpm150m->control); - - return 0; -} -#endif /* VPM150M_SUPPORT */ - -enum vpmadt032_init_result { - VPMADT032_SUCCESS, - VPMADT032_NOT_FOUND, - VPMADT032_FAILED, - VPMADT032_DISABLED, -}; - -static enum vpmadt032_init_result wctdm_vpm150m_init(struct wctdm *wc) -{ - unsigned short i; - struct vpm150m *vpm150m; - unsigned short reg; - unsigned long flags; - enum vpmadt032_init_result res = VPMADT032_FAILED; - -#ifdef VPM150M_SUPPORT - struct wctdm_firmware fw; - struct firmware embedded_firmware; - const struct firmware *firmware = &embedded_firmware; -#if !defined(HOTPLUG_FIRMWARE) - extern void _binary_zaptel_fw_vpmadt032_bin_size; - extern u8 _binary_zaptel_fw_vpmadt032_bin_start[]; -#else - static const char vpmadt032_firmware[] = "zaptel-fw-vpmadt032.bin"; -#endif - gpakDownloadStatus_t downloadstatus; - gpakPingDspStat_t pingstatus; -#endif - - if (!vpmsupport) { - printk("VPM: Support Disabled\n"); - wc->vpm150m = NULL; - return VPMADT032_DISABLED; - } - - vpm150m = kmalloc(sizeof(struct vpm150m), GFP_KERNEL); - - if (!vpm150m) { - printk("Unable to allocate VPM150M!\n"); - return VPMADT032_FAILED; - } - - memset(vpm150m, 0, sizeof(struct vpm150m)); - - /* Init our vpm150m struct */ - sema_init(&vpm150m->sem, 1); - vpm150m->curpage = 0x80; - - for (i = 0; i < WC_MAX_IFACES; i++) { - if (ifaces[i] == wc) - vpm150m->dspid = i; - } - - if (debug & DEBUG_ECHOCAN) - printk("Setting VPMADT032 DSP ID to %d\n", vpm150m->dspid); - - spin_lock_irqsave(&wc->reglock, flags); - wc->vpm150m = vpm150m; - spin_unlock_irqrestore(&wc->reglock, flags); - - for (i = 0; i < 10; i++) - schluffen(&wc->regq); - - if (debug & DEBUG_ECHOCAN) - printk("VPMADT032 Testing page access: "); - for (i = 0; i < 0xf; i++) { - int x; - for (x = 0; x < 3; x++) { - wctdm_vpm150m_setpage(wc, i); - reg = wctdm_vpm150m_getpage(wc); - if (reg != i) { - if (debug & DEBUG_ECHOCAN) - printk("Failed: Sent %x != %x VPMADT032 Failed HI page test\n", i, reg); - res = VPMADT032_NOT_FOUND; - goto failed_exit; - } - } - } - if (debug & DEBUG_ECHOCAN) - printk("Passed\n"); - - /* Set us up to page 0 */ - wctdm_vpm150m_setpage(wc, 0); - if (debug & DEBUG_ECHOCAN) - printk("VPMADT032 now doing address test: "); - for (i = 0; i < 16; i++) { - int x; - for (x = 0; x < 2; x++) { - wctdm_vpm150m_setreg(wc, 1, 0x1000, &i); - wctdm_vpm150m_getreg(wc, 1, 0x1000, ®); - if (reg != i) { - printk("VPMADT032 Failed address test\n"); - goto failed_exit; - } - - } - } - if (debug & DEBUG_ECHOCAN) - printk("Passed\n"); - -#ifndef VPM150M_SUPPORT - printk("Found VPMADT032 module but it is not able to function in anything less than a version 2.6 kernel\n"); - printk("Please update your kernel to a 2.6 or later kernel to enable it\n"); - goto failed_exit; -#else - -#if 0 - /* Load the firmware */ - set_bit(VPM150M_SPIRESET, &vpm150m->control); - - /* Wait for it to boot */ - msleep(7000); - - pingstatus = gpakPingDsp(vpm150m->dspid, &version); - - if (pingstatus || (version != 0x106)) { -#endif -#if defined(HOTPLUG_FIRMWARE) - if ((request_firmware(&firmware, vpmadt032_firmware, &wc->dev->dev) != 0) || - !firmware) { - printk("VPMADT032: firmware %s not available from userspace\n", vpmadt032_firmware); - goto failed_exit; - } -#else - embedded_firmware.data = _binary_zaptel_fw_vpmadt032_bin_start; - embedded_firmware.size = (size_t) &_binary_zaptel_fw_vpmadt032_bin_size; -#endif - fw.fw = firmware; - fw.offset = 0; - - set_bit(VPM150M_HPIRESET, &vpm150m->control); - - while (test_bit(VPM150M_HPIRESET, &vpm150m->control)) - schluffen(&wc->regq); - - printk("VPMADT032 Loading firwmare... "); - downloadstatus = gpakDownloadDsp(vpm150m->dspid, &fw); - - if (firmware != &embedded_firmware) - release_firmware(firmware); - - if (downloadstatus != 0) { - printk("Unable to download firmware to VPMADT032 with cause %d\n", downloadstatus); - goto failed_exit; - } else { - printk("Success\n"); - } - - set_bit(VPM150M_SWRESET, &vpm150m->control); - - while (test_bit(VPM150M_SWRESET, &vpm150m->control)) - schluffen(&wc->regq); - -#if 0 - } -#endif - - pingstatus = gpakPingDsp(vpm150m->dspid, &vpm150m->version); - - if (!pingstatus) { - if (debug & DEBUG_ECHOCAN) - printk("Version of DSP is %x\n", vpm150m->version); - } else { - printk("VPMADT032 Failed! Unable to ping the DSP (%d)!\n", pingstatus); - goto failed_exit; - } - - if (vpm150m_config_hw(wc)) { - goto failed_exit; - } - - return VPMADT032_SUCCESS; -#endif /* VPM150M_SUPPORT */ - -failed_exit: - spin_lock_irqsave(&wc->reglock, flags); - wc->vpm150m = NULL; - spin_unlock_irqrestore(&wc->reglock, flags); - kfree(vpm150m); - - return res; -} - -static void wctdm_vpm_set_dtmf_threshold(struct wctdm *wc, unsigned int threshold) -{ - unsigned int x; - - for (x = 0; x < 4; x++) { - wctdm_vpm_out(wc, x, 0xC4, (threshold >> 8) & 0xFF); - wctdm_vpm_out(wc, x, 0xC5, (threshold & 0xFF)); - } - printk("VPM: DTMF threshold set to %d\n", threshold); -} - -static void wctdm_vpm_init(struct wctdm *wc) -{ - unsigned char reg; - unsigned int mask; - unsigned int ver; - unsigned char vpmver=0; - unsigned int i, x, y; - - if (!vpmsupport) { - printk("VPM: Support Disabled\n"); - wc->vpm = 0; - return; - } - - for (x=0;xvpm = 0; - return; - } - - if (!x) { - vpmver = wctdm_vpm_in(wc, x, 0x1a6) & 0xf; - printk("VPM Revision: %02x\n", vpmver); - } - - - /* Setup GPIO's */ - for (y=0;y<4;y++) { - wctdm_vpm_out(wc, x, 0x1a8 + y, 0x00); /* GPIO out */ - if (y == 3) - wctdm_vpm_out(wc, x, 0x1ac + y, 0x00); /* GPIO dir */ - else - wctdm_vpm_out(wc, x, 0x1ac + y, 0xff); /* GPIO dir */ - wctdm_vpm_out(wc, x, 0x1b0 + y, 0x00); /* GPIO sel */ - } - - /* Setup TDM path - sets fsync and tdm_clk as inputs */ - reg = wctdm_vpm_in(wc, x, 0x1a3); /* misc_con */ - wctdm_vpm_out(wc, x, 0x1a3, reg & ~2); - - /* Setup Echo length (256 taps) */ - wctdm_vpm_out(wc, x, 0x022, 0); - - /* Setup timeslots */ - if (vpmver == 0x01) { - wctdm_vpm_out(wc, x, 0x02f, 0x00); - wctdm_vpm_out(wc, x, 0x023, 0xff); - mask = 0x11111111 << x; - } else { - wctdm_vpm_out(wc, x, 0x02f, 0x20 | (x << 3)); - wctdm_vpm_out(wc, x, 0x023, 0x3f); - mask = 0x0000003f; - } - - /* Setup the tdm channel masks for all chips*/ - for (i = 0; i < 4; i++) - wctdm_vpm_out(wc, x, 0x33 - i, (mask >> (i << 3)) & 0xff); - - /* Setup convergence rate */ - reg = wctdm_vpm_in(wc,x,0x20); - reg &= 0xE0; - if (alawoverride) { - if (!x) - printk("VPM: A-law mode\n"); - reg |= 0x01; - } else { - if (!x) - printk("VPM: U-law mode\n"); - reg &= ~0x01; - } - wctdm_vpm_out(wc,x,0x20,(reg | 0x20)); - - /* Initialize echo cans */ - for (i = 0 ; i < MAX_TDM_CHAN; i++) { - if (mask & (0x00000001 << i)) - wctdm_vpm_out(wc,x,i,0x00); - } - - for (i=0;i<30;i++) - schluffen(&wc->regq); - - /* Put in bypass mode */ - for (i = 0 ; i < MAX_TDM_CHAN ; i++) { - if (mask & (0x00000001 << i)) { - wctdm_vpm_out(wc,x,i,0x01); - } - } - - /* Enable bypass */ - for (i = 0 ; i < MAX_TDM_CHAN ; i++) { - if (mask & (0x00000001 << i)) - wctdm_vpm_out(wc,x,0x78 + i,0x01); - } - - /* Enable DTMF detectors (always DTMF detect all spans) */ - for (i = 0; i < 6; i++) { - if (vpmver == 0x01) - wctdm_vpm_out(wc, x, 0x98 + i, 0x40 | (i << 2) | x); - else - wctdm_vpm_out(wc, x, 0x98 + i, 0x40 | i); - } - - for (i = 0xB8; i < 0xC0; i++) - wctdm_vpm_out(wc, x, i, 0xFF); - for (i = 0xC0; i < 0xC4; i++) - wctdm_vpm_out(wc, x, i, 0xff); - - } - /* set DTMF detection threshold */ - wctdm_vpm_set_dtmf_threshold(wc, dtmfthreshold); - - if (vpmver == 0x01) - wc->vpm = 2; - else - wc->vpm = 1; - - printk("Enabling VPM100 gain adjustments on any FXO ports found\n"); - for (i = 0; i < wc->type; i++) { - if (wc->modtype[i] == MOD_TYPE_FXO) { - /* Apply negative Tx gain of 4.5db to DAA */ - wctdm_setreg(wc, i, 38, 0x14); /* 4db */ - wctdm_setreg(wc, i, 40, 0x15); /* 0.5db */ - - /* Apply negative Rx gain of 4.5db to DAA */ - wctdm_setreg(wc, i, 39, 0x14); /* 4db */ - wctdm_setreg(wc, i, 41, 0x15); /* 0.5db */ - } - } - -} - -#endif - -static int wctdm_locate_modules(struct wctdm *wc) -{ - int x; - unsigned long flags; - printk("Resetting the modules...\n"); - /* Initialize control register */ - wc->ctlreg = 0x00; - /* Set Reset */ - wctdm_setctl(wc, 0x0048, 0x00000000); - for (x=0;x<10;x++) - schluffen(&wc->regq); - printk("During Resetting the modules...\n"); - /* Clear reset */ - wctdm_setctl(wc, 0x0048, 0x00010000); - for (x=0;x<10;x++) - schluffen(&wc->regq); - printk("After resetting the modules...\n"); - - wctdm_setintmask(wc, 0x0001f7fe); - - /* Make sure all units go into daisy chain mode */ - spin_lock_irqsave(&wc->reglock, flags); - wc->span.irqmisses = 0; - for (x=0;xcards;x++) - wc->modtype[x] = MOD_TYPE_FXSINIT; -#ifdef VPM_SUPPORT - wc->vpm = -1; - for (x = wc->cards; x < wc->cards+NUM_EC; x++) - wc->modtype[x] = MOD_TYPE_VPM; -#endif - spin_unlock_irqrestore(&wc->reglock, flags); - /* Wait just a bit */ - for (x=0;x<10;x++) - schluffen(&wc->regq); - spin_lock_irqsave(&wc->reglock, flags); - for (x=0;xcards;x++) - wc->modtype[x] = MOD_TYPE_FXS; - spin_unlock_irqrestore(&wc->reglock, flags); - -#if 0 - /* XXX */ - cmddesc = 0; -#endif - /* Now that all the cards have been reset, we can stop checking them all if there aren't as many */ - spin_lock_irqsave(&wc->reglock, flags); - wc->cards = wc->type; - spin_unlock_irqrestore(&wc->reglock, flags); - - /* Reset modules */ - for (x=0;xcards;x++) { - int sane=0,ret=0,readi=0; -retry: - /* Init with Auto Calibration */ - if (!(ret = wctdm_init_proslic(wc, x, 0, 0, sane))) { - wc->cardflag |= (1 << x); - if (debug & DEBUG_CARD) { - readi = wctdm_getreg(wc,x,LOOP_I_LIMIT); - printk("Proslic module %d loop current is %dmA\n",x, - ((readi*3)+20)); - } - printk("Port %d: Installed -- AUTO FXS/DPO\n", x + 1); - } else { - if(ret!=-2) { - sane=1; - /* Init with Manual Calibration */ - if (!wctdm_init_proslic(wc, x, 0, 1, sane)) { - wc->cardflag |= (1 << x); - if (debug & DEBUG_CARD) { - readi = wctdm_getreg(wc,x,LOOP_I_LIMIT); - printk("Proslic module %d loop current is %dmA\n",x, - ((readi*3)+20)); - } - printk("Port %d: Installed -- MANUAL FXS\n",x + 1); - } else { - printk("Port %d: FAILED FXS (%s)\n", x + 1, fxshonormode ? fxo_modes[_opermode].name : "FCC"); - wc->chans[x].sigcap = ZT_SIG_BROKEN | __ZT_SIG_FXO; - } - } else if (!(ret = wctdm_init_voicedaa(wc, x, 0, 0, sane))) { - wc->cardflag |= (1 << x); - printk("Port %d: Installed -- AUTO FXO (%s mode)\n",x + 1, fxo_modes[_opermode].name); - } else if (!wctdm_init_qrvdri(wc,x)) { - wc->cardflag |= 1 << x; - printk("Port %d: Installed -- QRV DRI card\n",x + 1); - } else { - if ((wc->type != 24) && ((x & 0x3) == 1) && !wc->altcs[x]) { - spin_lock_irqsave(&wc->reglock, flags); - wc->altcs[x] = 2; - if (wc->type == 4) { - wc->altcs[x+1] = 3; - wc->altcs[x+2] = 3; - } - wc->modtype[x] = MOD_TYPE_FXSINIT; - spin_unlock_irqrestore(&wc->reglock, flags); - - schluffen(&wc->regq); - schluffen(&wc->regq); - spin_lock_irqsave(&wc->reglock, flags); - wc->modtype[x] = MOD_TYPE_FXS; - spin_unlock_irqrestore(&wc->reglock, flags); - if (debug & DEBUG_CARD) - printk("Trying port %d with alternate chip select\n", x + 1); - goto retry; - } else { - printk("Port %d: Not installed\n", x + 1); - wc->modtype[x] = MOD_TYPE_NONE; - wc->cardflag |= (1 << x); - } - } - } - } -#ifdef VPM_SUPPORT - wctdm_vpm_init(wc); - if (wc->vpm) { - printk("VPM: Present and operational (Rev %c)\n", 'A' + wc->vpm - 1); - wc->ctlreg |= 0x10; - } else { - spin_lock_irqsave(&wc->reglock, flags); - for (x = NUM_CARDS; x < NUM_CARDS + NUM_EC; x++) - wc->modtype[x] = MOD_TYPE_NONE; - spin_unlock_irqrestore(&wc->reglock, flags); - switch (wctdm_vpm150m_init(wc)) { - case VPMADT032_SUCCESS: - printk("VPMADT032: Present and operational (Firmware version %x)\n", wc->vpm150m->version); - wc->ctlreg |= 0x10; - break; - case VPMADT032_DISABLED: - case VPMADT032_NOT_FOUND: - /* nothing */ - break; - default: - return -1; - } - } -#endif - - return 0; -} - -static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct wctdm *wc; - struct wctdm_desc *d = (struct wctdm_desc *)ent->driver_data; - int x; - int y; - - if (pci_enable_device(pdev)) - return -EIO; - - if (!(wc = kmalloc(sizeof(struct wctdm), GFP_KERNEL))) - return -ENOMEM; - - spin_lock(&ifacelock); - for (x = 0; x < WC_MAX_IFACES; x++) - if (!ifaces[x]) break; - - ifaces[x] = wc; - spin_unlock(&ifacelock); - - memset(wc, 0, sizeof(struct wctdm)); - spin_lock_init(&wc->reglock); - wc->curcard = -1; - wc->cards = NUM_CARDS; - wc->iobase = pci_resource_start(pdev, 0); - wc->type = d->ports; - wc->dev = pdev; - wc->pos = x; - wc->variety = d->name; - for (y=0;yflags[y] = d->flags; - wc->dacssrc[y] = -1; - } - /* Keep track of whether we need to free the region */ - if (request_region(wc->iobase, 0xff, "wctdm24xxp")) - wc->freeregion = 1; - - /* Allocate enough memory for two zt chunks, receive and transmit. Each sample uses - 32 bits. Allocate an extra set just for control too */ - wc->writechunk = pci_alloc_consistent(pdev, PCI_WINDOW_SIZE, &wc->writedma); - if (!wc->writechunk) { - printk("wctdm: Unable to allocate DMA-able memory\n"); - if (wc->freeregion) - release_region(wc->iobase, 0xff); - return -ENOMEM; - } - - wc->readchunk = wc->writechunk + SFRAME_SIZE / 2; /* in doublewords */ - wc->readdma = wc->writedma + SFRAME_SIZE * 2; /* in bytes */ - - wc->descripchunk = wc->readchunk + SFRAME_SIZE / 2; /* in doublewords */ - wc->descripdma = wc->readdma + SFRAME_SIZE * 2; /* in bytes */ - - /* Initialize Write/Buffers to all blank data */ - memset((void *)wc->writechunk,0x00, SFRAME_SIZE * 2); - memset((void *)wc->readchunk, 0x00, SFRAME_SIZE * 2); - - init_waitqueue_head(&wc->regq); - - if (wctdm_initialize(wc)) { - printk("%s: Unable to register span with zaptel\n", wc->variety); - /* Set Reset Low */ - wctdm_stop_dma(wc); - /* Free Resources */ - if (wc->freeregion) - release_region(wc->iobase, 0xff); - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); - zt_unregister(&wc->span); - kfree(wc); - return -EIO; - } - - /* Enable bus mastering */ - pci_set_master(pdev); - - /* Keep track of which device we are */ - pci_set_drvdata(pdev, wc); - - if (request_irq(pdev->irq, wctdm_interrupt, ZAP_IRQ_SHARED, wc->variety, wc)) { - printk("wctdm24xxp: Unable to request IRQ %d\n", pdev->irq); - /* Set Reset Low */ - wctdm_stop_dma(wc); - /* Free Resources */ - if (wc->freeregion) - release_region(wc->iobase, 0xff); - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); - pci_set_drvdata(pdev, NULL); - zt_unregister(&wc->span); - kfree(wc); - return -EIO; - } - - - if (wctdm_hardware_init(wc)) { - /* Set Reset Low */ - wctdm_stop_dma(wc); - /* Free Resources */ - free_irq(pdev->irq, wc); - if (wc->freeregion) - release_region(wc->iobase, 0xff); - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); - pci_set_drvdata(pdev, NULL); - zt_unregister(&wc->span); - kfree(wc); - return -EIO; - - } - - /* Enable interrupts */ - wctdm_enable_interrupts(wc); - - /* Start DMA */ - wctdm_start_dma(wc); - - /* Now track down what modules are installed */ - if (wctdm_locate_modules(wc)) { - wctdm_disable_interrupts(wc); - /* Set Reset Low */ - wctdm_stop_dma(wc); - /* Free Resources */ - free_irq(pdev->irq, wc); - if (wc->freeregion) - release_region(wc->iobase, 0xff); - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); - pci_set_drvdata(pdev, NULL); - zt_unregister(&wc->span); - kfree(wc); - return -EIO; - } - - /* Final initialization */ - wctdm_post_initialize(wc); - - printk("Found a Wildcard TDM: %s (%d modules)\n", wc->variety, wc->type); - - return 0; -} - -static void wctdm_release(struct wctdm *wc) -{ - int i; - - zt_unregister(&wc->span); - - if (wc->freeregion) - release_region(wc->iobase, 0xff); - - spin_lock(&ifacelock); - - for (i = 0; i < WC_MAX_IFACES; i++) - if (ifaces[i] == wc) - break; - - ifaces[i] = NULL; - - spin_unlock(&ifacelock); - - kfree(wc); - printk("Freed a Wildcard\n"); -} - -static void __devexit wctdm_remove_one(struct pci_dev *pdev) -{ - struct wctdm *wc = pci_get_drvdata(pdev); - -#ifdef VPM150M_SUPPORT - unsigned long flags; - struct vpm150m *vpm150m = wc->vpm150m; -#endif - - if (wc) { - -#ifdef VPM150M_SUPPORT - if (vpm150m) { - clear_bit(VPM150M_DTMFDETECT, &vpm150m->control); - clear_bit(VPM150M_ACTIVE, &vpm150m->control); - flush_workqueue(vpm150m->wq); - destroy_workqueue(vpm150m->wq); - } -#endif - - /* Stop any DMA */ - wctdm_stop_dma(wc); - - /* In case hardware is still there */ - wctdm_disable_interrupts(wc); - - /* Immediately free resources */ - free_irq(pdev->irq, wc); - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); - -#ifdef VPM150M_SUPPORT - if (vpm150m) { - spin_lock_irqsave(&wc->reglock, flags); - wc->vpm150m = NULL; - vpm150m->wc = NULL; - spin_unlock_irqrestore(&wc->reglock, flags); - kfree(wc->vpm150m); - } -#endif - /* Release span, possibly delayed */ - if (!wc->usecount) - wctdm_release(wc); - else - wc->dead = 1; - } -} - -static struct pci_device_id wctdm_pci_tbl[] = { - { 0xd161, 0x2400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm2400 }, - { 0xd161, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm800 }, - { 0xd161, 0x8002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcaex800 }, - { 0xd161, 0x8003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcaex2400 }, - { 0xd161, 0x8005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm410 }, - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, wctdm_pci_tbl); - -static struct pci_driver wctdm_driver = { - name: "wctdm24xxp", - probe: wctdm_init_one, -#ifdef LINUX26 - remove: __devexit_p(wctdm_remove_one), -#else - remove: wctdm_remove_one, -#endif - suspend: NULL, - resume: NULL, - id_table: wctdm_pci_tbl, -}; - -static int __init wctdm_init(void) -{ - int res; - int x; - - for (x=0;x<(sizeof(fxo_modes) / sizeof(fxo_modes[0])); x++) { - if (!strcmp(fxo_modes[x].name, opermode)) - break; - } - if (x < sizeof(fxo_modes) / sizeof(fxo_modes[0])) { - _opermode = x; - } else { - printk("Invalid/unknown operating mode '%s' specified. Please choose one of:\n", opermode); - for (x=0;x"); -#if defined(MODULE_ALIAS) -MODULE_ALIAS("wctdm8xxp"); -#endif -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif - -module_init(wctdm_init); -module_exit(wctdm_cleanup); diff --git a/wctdm24xxp/gpakErrs.h b/wctdm24xxp/gpakErrs.h deleted file mode 100644 index 3413f97..0000000 --- a/wctdm24xxp/gpakErrs.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2002 - 2004, Adaptive Digital Technologies, Inc. - * - * File Name: GpakErrs.h - * - * Description: - * This file contains DSP reply status codes used by G.PAK API functions to - * indicate specific errors. - * - * Version: 1.0 - * - * Revision History: - * 10/17/01 - Initial release. - * 07/03/02 - Updates for conferencing. - * 06/15/04 - Tone type updates. - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. The standard - * GPL disclaimer is given inline below for your convenience. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _GPAKERRS_H /* prevent multiple inclusion */ -#define _GPAKERRS_H - -/* Configure Serial Ports reply status codes. */ -typedef enum -{ - Pc_Success = 0, /* serial ports configured successfully */ - Pc_ChannelsActive = 1, /* unable to configure while channels active */ - Pc_TooManySlots1 = 2, /* too many slots selected for port 1 */ - Pc_InvalidBlockCombo1 = 3, /* invalid combination of blocks for port 1 */ - Pc_NoSlots1 = 4, /* no slots selected for port 1 */ - Pc_InvalidSlots1 = 5, /* invalid slot (> max) selected for port 1 */ - Pc_TooManySlots2 = 6, /* too many slots selected for port 2 */ - Pc_InvalidBlockCombo2 = 7, /* invalid combination of blocks for port 2 */ - Pc_NoSlots2 = 8, /* no slots selected for port 2 */ - Pc_InvalidSlots2 = 9, /* invalid slot (> max) selected for port 2 */ - Pc_TooManySlots3 = 10, /* too many slots selected for port 3 */ - Pc_InvalidBlockCombo3 = 11, /* invalid combination of blocks for port 3 */ - Pc_NoSlots3 = 12, /* no slots selected for port 3 */ - Pc_InvalidSlots3 = 13 /* invalid slot (> max) selected for port 3 */ -} GPAK_PortConfigStat_t; - -/* Configure Channel reply status codes. */ -typedef enum -{ - Cc_Success = 0, /* channel configured successfully */ - Cc_InvalidChannelType = 1, /* invalid Channel Type */ - Cc_InvalidChannel = 2, /* invalid Channel A Id */ - Cc_ChannelActiveA = 3, /* Channel A is currently active */ - Cc_InvalidInputPortA = 4, /* invalid Input A Port */ - Cc_InvalidInputSlotA = 5, /* invalid Input A Slot */ - Cc_BusyInputSlotA = 6, /* busy Input A Slot */ - Cc_InvalidOutputPortA = 7, /* invalid Output A Port */ - Cc_InvalidOutputSlotA = 8, /* invalid Output A Slot */ - Cc_BusyOutputSlotA = 9, /* busy Output A Slot */ - Cc_InvalidInputPortB = 10, /* invalid Input B Port */ - Cc_InvalidInputSlotB = 11, /* invalid Input B Slot */ - Cc_BusyInputSlotB = 12, /* busy Input B Slot */ - Cc_InvalidPktInCodingA = 13, /* invalid Packet In A Coding */ - Cc_InvalidPktOutCodingA = 14, /* invalid Packet Out A Coding */ - Cc_InvalidPktInSizeA = 15, /* invalid Packet In A Frame Size */ - Cc_InvalidPktOutSizeA = 16, /* invalid Packet Out A Frame Size */ - - Cc_ChanTypeNotConfigured = 21, /* channel type was not configured */ - Cc_InsuffECResources = 22, /* insufficient ecan resources avail. */ - Cc_InsuffTDMResources = 23, /* insufficient tdm block resources avail. */ - - Cc_InsuffPktBufResources = 25, /* insufficient pkt buffer resources avail. */ - Cc_InsuffPcmBufResources = 26, /* insufficient pcm buffer resources avail. */ - - Cc_BadPcmEcNlpType = 30, /* invalid EC Nlp type */ - Cc_BadPcmEcTapLength = 31, /* invalid EC tap length */ - Cc_BadPcmEcDblTalkThresh = 32, /* invalid EC double-talk threshold */ - Cc_BadPcmEcNlpThreshold = 33, /* invalid EC Nlp threshold */ - Cc_BadPcmEcCngThreshold = 34, /* invalid EC Cng threshold */ - Cc_BadPcmEcAdaptLimit = 35, /* invalid EC Adapt Limit */ - Cc_BadPcmEcCrossCorrLim = 36, /* invalid EC Cross Correlation Limit */ - Cc_BadPcmEcNumFirSegs = 37, /* invalid EC Number of FirSegments */ - Cc_BadPcmEcFirSegLen = 38, /* invalid EC Fir Segment Length */ - - /*Cc_InvalidNumEcsEnabled = 48, */ /* more than 1 Ec enabled on channel */ - Cc_InvalidFrameRate = 49, /* invalid gpak frame rate */ - Cc_InvalidSoftCompand = 50, /* invalid softCompanding type */ - - Cc_InvalidMuteToneA = 51, /* invalid MuteToneA set, no detector */ - Cc_InvalidMuteToneB = 52, /* invalid MuteToneB set, no detector */ - Cc_InsuffFaxCngDetResources = 53 /* insufficient tdm block resources avail. */ - -} GPAK_ChannelConfigStat_t; - -/* Tear Down Channel reply status codes. */ -typedef enum -{ - Td_Success = 0, /* channel torn down successfully */ - Td_InvalidChannel = 1, /* invalid Channel Id */ - Td_ChannelNotActive = 2 /* channel is not active */ -} GPAK_TearDownChanStat_t; - - -typedef enum -{ - Ac_Success = 0, /* algorithm control is successfull */ - Ac_InvalidChannel = 1, /* invalid channel identifier */ - Ac_InvalidCode = 2, /* invalid algorithm control code */ - Ac_ECNotEnabled = 3, /* echo canceller was not allocated */ - Ac_InvalidSoftComp = 4, /* invalid softcompanding, 'cause serial port not in companding mode */ - Ac_InvalidDTMFMuteA = 5, /* A side invalid Mute, since no dtmf detector */ - Ac_InvalidDTMFMuteB = 6, /* B side invalid Mute, since no dtmf detector */ - Ac_InvalidFaxCngA = 7, /* A side FAXCNG detector not available */ - Ac_InvalidFaxCngB = 8, /* B side FAXCNG detector not available */ - Ac_InvalidSysConfig = 9 /* No new system parameters (DTMF config) wrriten yet */ -} GPAK_AlgControlStat_t; - -/* Write System Parameters reply status codes. */ -typedef enum -{ - Sp_Success = 0, /* System Parameters written successfully */ - Sp_BadTwistThresh = 29 /* invalid twist threshold */ - -} GPAK_SysParmsStat_t; - -#endif /* prevent multiple inclusion */ - - - - - - - - - - - - - - - - - - - diff --git a/wctdm24xxp/gpakenum.h b/wctdm24xxp/gpakenum.h deleted file mode 100644 index 91e4311..0000000 --- a/wctdm24xxp/gpakenum.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2005, Adaptive Digital Technologies, Inc. - * - * File Name: gpakenum.h - * - * Description: - * This file contains common enumerations related to G.PAK application - * software. - * - * Version: 1.0 - * - * Revision History: - * 06/15/05 - Initial release. - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. The standard - * GPL disclaimer is given inline below for your convenience. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _GPAKENUM_H /* prevent multiple inclusion */ -#define _GPAKENUM_H - -/* G.PAK Serial Port Word Size */ -typedef enum -{ - SerWordSize8 = 0, // 8-bit seial word - SerWordSize16 = 1 // 16-bit serial word -} GpakSerWordSize_t; - -/* G.PAK Serial Port FrameSync Polarity */ -typedef enum -{ - FrameSyncActLow = 0, // active low frame sync signal - FrameSyncActHigh = 1 // active high frame sync signal -} GpakSerFrameSyncPol_t; - -/* G.PAK Serial Port Clock Polarity */ -typedef enum -{ - SerClockActLow = 0, // active low serial clock - SerClockActHigh = 1 // active high serial clock -} GpakSerClockPol_t; - -/* G.PAK Serial Port Data Delay */ -typedef enum -{ - DataDelay0 = 0, // no data delay - DataDelay1 = 1, // 1-bit data delay - DataDelay2 = 2 // 2-bit data delay -} GpakSerDataDelay_t; - -/* G.PAK Serial Port Ids. */ -typedef enum -{ - SerialPortNull = 0, // null serial port - SerialPort1 = 1, // first PCM serial stream port (McBSP0) - SerialPort2 = 2, // second PCM serial stream port (McBSP1) - SerialPort3 = 3 // third PCM serial stream port (McBSP2) -} GpakSerialPort_t; - -/* G.PAK serial port Slot Configuration selection codes. */ -typedef enum -{ - SlotCfgNone = 0, // no time slots used - SlotCfg2Groups = 2, // 2 groups of 16 time slots used, 32 Channels system - SlotCfg8Groups = 8 // 8-partition mode for 128-channel system -} GpakSlotCfg_t; - -/* G.PAK serial port Companding Mode codes. */ -typedef enum -{ - cmpPCMU=0, // u-Law - cmpPCMA=1, // A-Law - cmpNone=2 // none -} GpakCompandModes; - -/* G.PAK Active/Inactive selection codes. */ -typedef enum -{ - Disabled=0, // Inactive - Enabled=1 // Active -} GpakActivation; - -/* G.PAK Channel Type codes. */ -typedef enum -{ - inactive=0, // channel inactive - tdmToTdm=1 // tdmToTdm -} GpakChanType; - -/* G.PAK Algorithm control commands */ -typedef enum -{ - EnableEcanA = 0, // Enable A side echo canceller - BypassEcanA = 1, // Bypass A side echo canceller - ResetEcanA = 2, // Reset A side echo canceller - EnableEcanB = 3, // Enable B side echo canceller - BypassEcanB = 4, // Bypass B side echo canceller - ResetEcanB = 5, // Reset B side echo canceller - - EnableMuLawSwCompanding = 6,// Enable Mu-law Software companding - EnableALawSwCompanding = 7, // Enable Mu-law Software companding - BypassSwCompanding = 8, // Bypass Software companding - EnableDTMFMuteA = 9, // Mute A side Dtmf digit after tone detected - DisableDTMFMuteA = 10, // Do not mute A side Dtmf digit once tone detected - EnableDTMFMuteB = 11, // Mute B side Dtmf digit after tone detected - DisableDTMFMuteB = 12, // Do not mute B side Dtmf digit once tone detected - EnableFaxCngDetectA = 13, // Enable A side Fax CNG detector, channel must be configed already - DisableFaxCngDetectA = 14, // Disable A side Fax CNG detector, channel must be configed already - EnableFaxCngDetectB = 15, // Enable B side Fax CNG detector, channel must be configed already - DisableFaxCngDetectB = 16 // Disable B side Fax CNG detector, channel must be configed already -} GpakAlgCtrl_t; - -/* G.PAK Tone types. */ -typedef enum -{ - Null_tone = 0, // no tone detection - DTMF_tone = 1 // DTMF tone -} GpakToneTypes; - -/* G.PAK direction. */ -typedef enum -{ - TDMAToB = 0, // A to B - TDMBToA = 1 // B to A -} GpakTdmDirection; - - -typedef enum -{ - rate1ms=0, - rate2ms=1, - rate10ms=2 -} GpakRate_t; - -/* G.PAK Asynchronous Event Codes */ -typedef enum -{ - EventToneDetect = 0, // Tone detection event - EventDSPDebug = 7 // DSP debug data event -} GpakAsyncEventCode_t; - -/* G.PAK MF Tone Code Indices */ -typedef enum -{ - DtmfDigit1 = 0, // DTMF Digit 1 - DtmfDigit2 = 1, // DTMF Digit 2 - DtmfDigit3 = 2, // DTMF Digit 3 - DtmfDigitA = 3, // DTMF Digit A - DtmfDigit4 = 4, // DTMF Digit 4 - DtmfDigit5 = 5, // DTMF Digit 5 - DtmfDigit6 = 6, // DTMF Digit 6 - DtmfDigitB = 7, // DTMF Digit B - DtmfDigit7 = 8, // DTMF Digit 7 - DtmfDigit8 = 9, // DTMF Digit 8 - DtmfDigit9 = 10, // DTMF Digit 9 - DtmfDigitC = 11, // DTMF Digit C - DtmfDigitSt = 12, // DTMF Digit * - DtmfDigit0 = 13, // DTMF Digit 0 - DtmfDigitPnd = 14, // DTMF Digit # - DtmfDigitD = 15, // DTMF Digit D - - FaxCngDigit = 90, // Fax Calling Tone (1100 Hz) - - EndofMFDigit = 100, // End of MF digit - EndofCngDigit = 101 // End of Cng Digit -} GpakToneCodes_t; - -/* GPIO control code*/ -typedef enum -{ - GPIO_READ = 0, - GPIO_WRITE = 1, - GPIO_DIR = 2 -} GpakGPIOCotrol_t; - - -#endif // end multiple inclusion diff --git a/wctdm24xxp/wctdm24xxp.h b/wctdm24xxp/wctdm24xxp.h deleted file mode 100644 index fd7f39b..0000000 --- a/wctdm24xxp/wctdm24xxp.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Wildcard TDM2400P TDM FXS/FXO Interface Driver for Zapata Telephony interface - * - * Written by Mark Spencer - * Support for TDM800P and VPM150M by Matthew Fredrickson - * - * Copyright (C) 2005, 2006, Digium, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef _WCTDM24XXP_H -#define _WCTDM24XXP_H - -#define NUM_FXO_REGS 60 - -#define WC_MAX_IFACES 128 - -/*! - * \brief Default ringer debounce (in ms) - * - * \todo This value differs from that in wctdm. In that module, it is 64 ms - * instead of 128 ms. Which one is more appropriate? - */ -#define DEFAULT_RING_DEBOUNCE 128 -#define DEFAULT_BATT_DEBOUNCE 64 /* Battery debounce (in ms) */ -#define POLARITY_DEBOUNCE 64 /* Polarity debounce (in ms) */ -#define DEFAULT_BATT_THRESH 3 /* Anything under this is "no battery" */ - -#define OHT_TIMER 6000 /* How long after RING to retain OHT */ - -#define FLAG_3215 (1 << 0) -#define FLAG_EXPRESS (1 << 1) - -#define EFRAME_SIZE 108 -#define ERING_SIZE 16 /* Maximum ring size */ -#define EFRAME_GAP 20 -#define SFRAME_SIZE ((EFRAME_SIZE * ZT_CHUNKSIZE) + (EFRAME_GAP * (ZT_CHUNKSIZE - 1))) - -#define MAX_ALARMS 10 - -#define MOD_TYPE_NONE 0 -#define MOD_TYPE_FXS 1 -#define MOD_TYPE_FXO 2 -#define MOD_TYPE_FXSINIT 3 -#define MOD_TYPE_VPM 4 -#define MOD_TYPE_QRV 5 -#define MOD_TYPE_VPM150M 6 - -#define MINPEGTIME 10 * 8 /* 30 ms peak to peak gets us no more than 100 Hz */ -#define PEGTIME 50 * 8 /* 50ms peak to peak gets us rings of 10 Hz or more */ -#define PEGCOUNT 5 /* 5 cycles of pegging means RING */ - -#define SDI_CLK (0x00010000) -#define SDI_DOUT (0x00020000) -#define SDI_DREAD (0x00040000) -#define SDI_DIN (0x00080000) - -#define PCI_WINDOW_SIZE ((2 * 2 * 2 * SFRAME_SIZE) + (2 * ERING_SIZE * 4)) - -#define __CMD_RD (1 << 20) /* Read Operation */ -#define __CMD_WR (1 << 21) /* Write Operation */ -#define __CMD_FIN (1 << 22) /* Has finished receive */ -#define __CMD_TX (1 << 23) /* Has been transmitted */ - -#define CMD_WR(a,b) (((a) << 8) | (b) | __CMD_WR) -#define CMD_RD(a) (((a) << 8) | __CMD_RD) - -#if 0 -#define CMD_BYTE(card,bit,altcs) (((((card) & 0x3) * 3 + (bit)) * 7) \ - + ((card) >> 2) + (altcs) + ((altcs) ? -21 : 0)) -#endif -#define NUM_CARDS 24 -#define NUM_EC 4 -#define NUM_SLOTS 6 -#define MAX_TDM_CHAN 31 - -#define NUM_CAL_REGS 12 - -#define USER_COMMANDS 8 -#define ISR_COMMANDS 2 -#define QRV_DEBOUNCETIME 20 - -#define MAX_COMMANDS (USER_COMMANDS + ISR_COMMANDS) - -#define __VPM150M_RWPAGE (1 << 4) -#define __VPM150M_RD (1 << 3) -#define __VPM150M_WR (1 << 2) -#define __VPM150M_FIN (1 << 1) -#define __VPM150M_TX (1 << 0) - -#define VPM150M_HPI_CONTROL 0x00 -#define VPM150M_HPI_ADDRESS 0x02 -#define VPM150M_HPI_DATA 0x03 - -#define VPM150M_MAX_COMMANDS 8 - -/* Some Bit ops for different operations */ -#define VPM150M_SPIRESET 0 -#define VPM150M_HPIRESET 1 -#define VPM150M_SWRESET 2 -#define VPM150M_DTMFDETECT 3 -#define VPM150M_ACTIVE 4 - -#define VPM150M_MAX_DATA 1 - -#define VPM_SUPPORT - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -#define VPM150M_SUPPORT -#endif - -#ifdef VPM_SUPPORT - -/* Define to get more attention-grabbing but slightly more CPU using echocan status */ -#define FANCY_ECHOCAN - -#endif - -#ifdef VPM150M_SUPPORT -#include "adt_lec.h" -#endif - -struct vpm150m_cmd { - unsigned int addr; - unsigned char datalen; - unsigned char desc; - unsigned char txident; - unsigned short data[VPM150M_MAX_DATA]; -}; - -struct vpm150m { -#ifdef VPM150M_SUPPORT - struct workqueue_struct *wq; - struct work_struct work; -#endif - struct wctdm *wc; - - int dspid; - struct semaphore sem; - unsigned long control; - unsigned char curpage; - unsigned short version; - struct adt_lec_params curecstate[24]; - struct adt_lec_params desiredecstate[24]; - unsigned long curdtmfmutestate; - unsigned long desireddtmfmutestate; - struct vpm150m_cmd cmdq[VPM150M_MAX_COMMANDS]; - unsigned char curtone[24]; -}; - -struct calregs { - unsigned char vals[NUM_CAL_REGS]; -}; - -struct cmdq { - unsigned int cmds[MAX_COMMANDS]; - unsigned char isrshadow[ISR_COMMANDS]; -}; - -struct wctdm { - struct pci_dev *dev; - char *variety; - struct zt_span span; - unsigned char ios; - unsigned int sdi; - int usecount; - unsigned int intcount; - unsigned int rxints; - unsigned int txints; - unsigned int intmask; - unsigned char txident; - unsigned char rxident; - int dead; - int pos; - int flags[NUM_CARDS]; - int freeregion; - int alt; - int rdbl; - int tdbl; - int curcard; - unsigned char ctlreg; - int cards; - int cardflag; /* Bit-map of present cards */ - int altcs[NUM_CARDS + NUM_EC]; - char qrvhook[NUM_CARDS]; - unsigned short qrvdebtime[NUM_CARDS]; - int radmode[NUM_CARDS]; -#define RADMODE_INVERTCOR 1 -#define RADMODE_IGNORECOR 2 -#define RADMODE_EXTTONE 4 -#define RADMODE_EXTINVERT 8 -#define RADMODE_IGNORECT 16 -#define RADMODE_PREEMP 32 -#define RADMODE_DEEMP 64 - unsigned short debouncetime[NUM_CARDS]; - signed short rxgain[NUM_CARDS]; - signed short txgain[NUM_CARDS]; - spinlock_t reglock; - wait_queue_head_t regq; - /* FXO Stuff */ - union { - struct { - int wasringing; - int lastrdtx; - int ringdebounce; - int offhook; - int battdebounce; - int nobatttimer; - int battery; - int lastpol; - int polarity; - int polaritydebounce; - } fxo; - struct { - int oldrxhook; - int debouncehook; - int lastrxhook; - int debounce; - int ohttimer; - int idletxhookstate; /* IDLE changing hook state */ - int lasttxhook; - int palarms; - struct calregs calregs; - } fxs; - } mods[NUM_CARDS]; - struct cmdq cmdq[NUM_CARDS + NUM_EC]; - /* Receive hook state and debouncing */ - int modtype[NUM_CARDS + NUM_EC]; - /* Set hook */ - int sethook[NUM_CARDS + NUM_EC]; - int dacssrc[NUM_CARDS]; - int type; - -#ifdef VPM_SUPPORT - int vpm; - unsigned long dtmfactive; - unsigned long dtmfmask; - unsigned long dtmfmutemask; - short dtmfenergy[NUM_CARDS]; - short dtmfdigit[NUM_CARDS]; - - struct vpm150m *vpm150m; -#ifdef FANCY_ECHOCAN - int echocanpos; - int blinktimer; -#endif -#endif - unsigned long iobase; - dma_addr_t readdma; - dma_addr_t writedma; - dma_addr_t descripdma; - volatile unsigned int *writechunk; /* Double-word aligned write memory */ - volatile unsigned int *readchunk; /* Double-word aligned read memory */ - volatile unsigned int *descripchunk; /* Descriptors */ - struct zt_chan chans[NUM_CARDS]; -}; - - -int schluffen(wait_queue_head_t *q); - -extern spinlock_t ifacelock; -extern struct wctdm *ifaces[WC_MAX_IFACES]; - -#endif diff --git a/wcte11xp.c b/wcte11xp.c deleted file mode 100644 index 68cc827..0000000 --- a/wcte11xp.c +++ /dev/null @@ -1,1644 +0,0 @@ -/* - * Digium, Inc. Wildcard TE110P T1/PRI card Driver - * - * Written by Mark Spencer - * Matthew Fredrickson - * William Meadows - * - * Copyright (C) 2004, Digium, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "zaptel.h" -#ifdef LINUX26 -#include -#endif - -/* XXX: fix this */ -#include "wct4xxp/wct4xxp.h" /* For certain definitions */ - -#define WC_MAX_CARDS 32 - -/* -#define TEST_REGS -*/ - -/* Define to get more attention-grabbing but slightly more I/O using - alarm status */ -#define FANCY_ALARM - -/* Define to enable the V2.1 errata register settings */ -#if 0 -#define TRUST_INFINEON_ERRATA -#endif - -#define DELAY 0x0 /* 30 = 15 cycles, 10 = 8 cycles, 0 = 3 cycles */ - -#define WC_CNTL 0x00 -#define WC_OPER 0x01 -#define WC_AUXC 0x02 -#define WC_AUXD 0x03 -#define WC_MASK0 0x04 -#define WC_MASK1 0x05 -#define WC_INTSTAT 0x06 - -#define WC_DMAWS 0x08 -#define WC_DMAWI 0x0c -#define WC_DMAWE 0x10 -#define WC_DMARS 0x18 -#define WC_DMARI 0x1c -#define WC_DMARE 0x20 -#define WC_CURPOS 0x24 - -#define WC_SERC 0x2d -#define WC_FSCDELAY 0x2f - -#define WC_USERREG 0xc0 - -#define WC_CLOCK 0x0 -#define WC_LEDTEST 0x1 -#define WC_VERSION 0x2 - -/* Offset between transmit and receive */ -#define WC_OFFSET 4 - -#define BIT_CS (1 << 7) -#define BIT_ADDR (0xf << 3) - -#define BIT_LED1 (1 << 0) -#define BIT_LED0 (1 << 1) -#define BIT_TEST (1 << 2) - -#define FLAG_STARTED (1 << 0) -#define FLAG_NMF (1 << 1) -#define FLAG_SENDINGYELLOW (1 << 2) -#define FLAG_FALC12 (1 << 3) - -#define TYPE_T1 1 /* is a T1 card */ -#define TYPE_E1 2 /* is an E1 card */ - -static int chanmap_t1[] = -{ 2,1,0, - 6,5,4, - 10,9,8, - 14,13,12, - 18,17,16, - 22,21,20, - 26,25,24, - 30,29,28 }; - -static int chanmap_e1[] = -{ 2,1,0, - 7,6,5,4, - 11,10,9,8, - 15,14,13,12, - 19,18,17,16, - 23,22,21,20, - 27,26,25,24, - 31,30,29,28 }; - -static int chanmap_e1uc[] = -{ 3,2,1,0, - 7,6,5,4, - 11,10,9,8, - 15,14,13,12, - 19,18,17,16, - 23,22,21,20, - 27,26,25,24, - 31,30,29,28 }; - - -#ifdef FANCY_ALARM -static int altab[] = { -0, 0, 0, 1, 2, 3, 4, 6, 8, 9, 11, 13, 16, 18, 20, 22, 24, 25, 27, 28, 29, 30, 31, 31, 32, 31, 31, 30, 29, 28, 27, 25, 23, 22, 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0, -}; -#endif - -struct t1 { - struct pci_dev *dev; - spinlock_t lock; - int spantype; - int spanflags; /* Span flags */ - unsigned char txsigs[16]; /* Copy of tx sig registers */ - int num; - int alarmcount; /* How much red alarm we've seen */ - int alarmdebounce; - /* Our offset for finding channel 1 */ - int offset; - char *variety; - unsigned int intcount; - int usecount; - int clocktimeout; - int sync; - int dead; - int blinktimer; - int alarmtimer; - int checktiming; /* Set >0 to cause the timing source to be checked */ - int loopupcnt; - int loopdowncnt; - int miss; - int misslast; - int *chanmap; -#ifdef FANCY_ALARM - int alarmpos; -#endif - unsigned char ledtestreg; - unsigned char outbyte; - unsigned long ioaddr; - unsigned short canary; - /* T1 signalling */ - dma_addr_t readdma; - dma_addr_t writedma; - volatile unsigned char *writechunk; /* Double-word aligned write memory */ - volatile unsigned char *readchunk; /* Double-word aligned read memory */ - unsigned char ec_chunk1[32][ZT_CHUNKSIZE]; - unsigned char ec_chunk2[32][ZT_CHUNKSIZE]; - unsigned char tempo[33]; - struct zt_span span; /* Span */ - struct zt_chan chans[32]; /* Channels */ -}; - -#define CANARY 0xca1e - -static int debug = 0; /* doesnt do anything */ -static int j1mode = 0; -static int alarmdebounce = 0; -static int loopback = 0; -static int clockextra = 0; -static int t1e1override = -1; -static int unchannelized = 0; - -static struct t1 *cards[WC_MAX_CARDS]; - -static inline void start_alarm(struct t1 *wc) -{ -#ifdef FANCY_ALARM - wc->alarmpos = 0; -#endif - wc->blinktimer = 0; -} - -static inline void stop_alarm(struct t1 *wc) -{ -#ifdef FANCY_ALARM - wc->alarmpos = 0; -#endif - wc->blinktimer = 0; -} - -static inline void __select_framer(struct t1 *wc, int reg) -{ - /* Top four bits of address from AUX 6-3 */ - wc->outbyte &= ~BIT_CS; - wc->outbyte &= ~BIT_ADDR; - wc->outbyte |= (reg & 0xf0) >> 1; - outb(wc->outbyte, wc->ioaddr + WC_AUXD); -} - -static inline void __select_control(struct t1 *wc) -{ - if (!(wc->outbyte & BIT_CS)) { - wc->outbyte |= BIT_CS; - outb(wc->outbyte, wc->ioaddr + WC_AUXD); - } -} - -static int t1xxp_open(struct zt_chan *chan) -{ - struct t1 *wc = chan->pvt; - if (wc->dead) - return -ENODEV; - wc->usecount++; -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#else - try_module_get(THIS_MODULE); -#endif - return 0; -} - -static int __control_set_reg(struct t1 *wc, int reg, unsigned char val) -{ - __select_control(wc); - outb(val, wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2)); - return 0; -} - -static int control_set_reg(struct t1 *wc, int reg, unsigned char val) -{ - unsigned long flags; - int res; - spin_lock_irqsave(&wc->lock, flags); - res = __control_set_reg(wc, reg, val); - spin_unlock_irqrestore(&wc->lock, flags); - return res; -} - -static int __control_get_reg(struct t1 *wc, int reg) -{ - unsigned char res; - /* The following makes UTTERLY no sense, but what was happening - was that reads in some cases were not actually happening - on the physical bus. Why, we dunno. But in debugging, we found - that writing before reading (in this case to an unused position) - seems to get rid of the problem */ - __control_set_reg(wc,3,0x69); /* do magic here */ - /* now get the read byte from the Xilinx part */ - res = inb(wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2)); - return res; -} - -static int control_get_reg(struct t1 *wc, int reg) -{ - unsigned long flags; - int res; - spin_lock_irqsave(&wc->lock, flags); - res = __control_get_reg(wc, reg); - spin_unlock_irqrestore(&wc->lock, flags); - return res; -} - -static inline unsigned int __t1_framer_in(struct t1 *wc, const unsigned int reg) -{ - unsigned char res; - __select_framer(wc, reg); - /* Get value */ - res = inb(wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2)); - return res; -#if 0 - unsigned int ret; - __t1_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); - __t1_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | ( 1 << 10) | WC_LREAD); - ret = __t1_pci_in(wc, WC_LDATA); - __t1_pci_out(wc, WC_LADDR, 0); - return ret & 0xff; -#endif -} - -static inline unsigned int t1_framer_in(struct t1 *wc, const unsigned int addr) -{ - unsigned long flags; - unsigned int ret; - spin_lock_irqsave(&wc->lock, flags); - ret = __t1_framer_in(wc, addr); - spin_unlock_irqrestore(&wc->lock, flags); - return ret; - -} - -static inline void __t1_framer_out(struct t1 *wc, const unsigned int reg, const unsigned int val) -{ - if (debug > 1) - printk("Writing %02x to address %02x\n", val, reg); - __select_framer(wc, reg); - /* Send address */ - outb(val, wc->ioaddr + WC_USERREG + ((reg & 0xf) << 2)); -#if 0 - __t1_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); - __t1_pci_out(wc, WC_LDATA, value); - __t1_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | (1 << 10)); - __t1_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | (1 << 10) | WC_LWRITE); - __t1_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff) | (1 << 10)); - __t1_pci_out(wc, WC_LADDR, (unit << 8) | (addr & 0xff)); - __t1_pci_out(wc, WC_LADDR, 0); - if (debug) printk("Write complete\n"); -#endif -#if 0 - { unsigned int tmp; - tmp = t1_framer_in(wc, unit, addr); - if (tmp != value) { - printk("Expected %d from unit %d register %d but got %d instead\n", value, unit, addr, tmp); - } } -#endif -} - -static inline void t1_framer_out(struct t1 *wc, const unsigned int addr, const unsigned int value) -{ - unsigned long flags; - spin_lock_irqsave(&wc->lock, flags); - __t1_framer_out(wc, addr, value); - spin_unlock_irqrestore(&wc->lock, flags); -} - -static void t1xxp_release(struct t1 *wc) -{ - zt_unregister(&wc->span); - kfree(wc); - printk("Freed a Wildcard\n"); -} - -static int t1xxp_close(struct zt_chan *chan) -{ - struct t1 *wc = chan->pvt; - wc->usecount--; -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#else - module_put(THIS_MODULE); -#endif - /* If we're dead, release us now */ - if (!wc->usecount && wc->dead) - t1xxp_release(wc); - return 0; -} - -static void t1xxp_enable_interrupts(struct t1 *wc) -{ - /* Clear interrupts */ - outb(0xff, wc->ioaddr + WC_INTSTAT); - /* Enable interrupts (we care about all of them) */ - outb(0x3c /* 0x3f */, wc->ioaddr + WC_MASK0); - /* No external interrupts */ - outb(0x00, wc->ioaddr + WC_MASK1); - if (debug) printk("Enabled interrupts!\n"); -} - -static void t1xxp_start_dma(struct t1 *wc) -{ - /* Reset Master and TDM */ - outb(DELAY | 0x0f, wc->ioaddr + WC_CNTL); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - outb(DELAY | 0x01, wc->ioaddr + WC_CNTL); - outb(0x01, wc->ioaddr + WC_OPER); - if (debug) printk("Started DMA\n"); - outb(0x03, wc->ioaddr + WC_OPER); - outb(0x01, wc->ioaddr + WC_OPER); -} - -static void __t1xxp_stop_dma(struct t1 *wc) -{ - outb(0x00, wc->ioaddr + WC_OPER); -} - -static void __t1xxp_disable_interrupts(struct t1 *wc) -{ - outb(0x00, wc->ioaddr + WC_MASK0); - outb(0x00, wc->ioaddr + WC_MASK1); -} - -static void __t1xxp_set_clear(struct t1 *wc) -{ - int i,j; - unsigned short val=0; - for (i=0;i<24;i++) { - j = (i/8); - if (wc->span.chans[i].flags & ZT_FLAG_CLEAR) - val |= 1 << (7 - (i % 8)); - if ((i % 8)==7) { - if (debug > 1) - printk("Putting %d in register %02x\n", - val, 0x2f + j); - __t1_framer_out(wc, 0x2f + j, val); - val = 0; - } - } -} - -static int t1xxp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) -{ - struct t4_regs regs; - int x; - struct t1 *wc; - switch(cmd) { - case WCT4_GET_REGS: - wc = chan->pvt; - for (x=0;xioaddr + (x << 2))) | - (inb(wc->ioaddr + (x << 2) + 1) << 8) | - (inb(wc->ioaddr + (x << 2) + 2) << 16) | - (inb(wc->ioaddr + (x << 2) + 3) << 24); -#else - regs.pci[x] = (inb(wc->ioaddr + x)); -#endif - - for (x=0;xpvt; - - if (wc->spantype == TYPE_E1) { - switch(cmd) { - case ZT_MAINT_NONE: - printk("XXX Turn off local and remote loops E1 XXX\n"); - break; - case ZT_MAINT_LOCALLOOP: - printk("XXX Turn on local loopback E1 XXX\n"); - break; - case ZT_MAINT_REMOTELOOP: - printk("XXX Turn on remote loopback E1 XXX\n"); - break; - case ZT_MAINT_LOOPUP: - printk("XXX Send loopup code E1 XXX\n"); - break; - case ZT_MAINT_LOOPDOWN: - printk("XXX Send loopdown code E1 XXX\n"); - break; - case ZT_MAINT_LOOPSTOP: - printk("XXX Stop sending loop codes E1 XXX\n"); - break; - default: - printk("TE110P: Unknown E1 maint command: %d\n", cmd); - break; - } - } else { - switch(cmd) { - case ZT_MAINT_NONE: - printk("XXX Turn off local and remote loops T1 XXX\n"); - break; - case ZT_MAINT_LOCALLOOP: - printk("XXX Turn on local loop and no remote loop XXX\n"); - break; - case ZT_MAINT_REMOTELOOP: - printk("XXX Turn on remote loopup XXX\n"); - break; - case ZT_MAINT_LOOPUP: - t1_framer_out(wc, 0x21, 0x50); /* FMR5: Nothing but RBS mode */ - break; - case ZT_MAINT_LOOPDOWN: - t1_framer_out(wc, 0x21, 0x60); /* FMR5: Nothing but RBS mode */ - break; - case ZT_MAINT_LOOPSTOP: - t1_framer_out(wc, 0x21, 0x40); /* FMR5: Nothing but RBS mode */ - break; - default: - printk("TE110P: Unknown T1 maint command: %d\n", cmd); - break; - } - } - return 0; -} - -static int t1xxp_rbsbits(struct zt_chan *chan, int bits) -{ - u_char m,c; - int n,b; - struct t1 *wc = chan->pvt; - unsigned long flags; - - if(debug > 1) printk("Setting bits to %d on channel %s\n", bits, chan->name); - spin_lock_irqsave(&wc->lock, flags); - if (wc->spantype == TYPE_E1) { /* do it E1 way */ - if (chan->chanpos == 16) { - spin_unlock_irqrestore(&wc->lock, flags); - return 0; - } - n = chan->chanpos - 1; - if (chan->chanpos > 15) n--; - b = (n % 15); - c = wc->txsigs[b]; - m = (n / 15) << 2; /* nibble selector */ - c &= (0xf << m); /* keep the other nibble */ - c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ - wc->txsigs[b] = c; - /* output them to the chip */ - __t1_framer_out(wc,0x71 + b,c); - } else if (wc->span.lineconfig & ZT_CONFIG_D4) { - n = chan->chanpos - 1; - b = (n/4); - c = wc->txsigs[b]; - m = ((3 - (n % 4)) << 1); /* nibble selector */ - c &= ~(0x3 << m); /* keep the other nibble */ - c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */ - wc->txsigs[b] = c; - /* output them to the chip */ - __t1_framer_out(wc,0x70 + b,c); - __t1_framer_out(wc,0x70 + b + 6,c); - } else if (wc->span.lineconfig & ZT_CONFIG_ESF) { - n = chan->chanpos - 1; - b = (n/2); - c = wc->txsigs[b]; - m = ((n % 2) << 2); /* nibble selector */ - c &= (0xf << m); /* keep the other nibble */ - c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ - wc->txsigs[b] = c; - /* output them to the chip */ - __t1_framer_out(wc,0x70 + b,c); - } - spin_unlock_irqrestore(&wc->lock, flags); - if (debug > 1) - printk("Finished setting RBS bits\n"); - return 0; -} - -static void t1_check_sigbits(struct t1 *wc) -{ - int a,i,rxs; - unsigned long flags; - - if (!(wc->span.flags & ZT_FLAG_RUNNING)) - return; - - spin_lock_irqsave(&wc->lock, flags); - - if (wc->spantype == TYPE_E1) { - for (i = 0; i < 15; i++) { - a = __t1_framer_in(wc, 0x71 + i); - /* Get high channel in low bits */ - rxs = (a & 0xf); - if (!(wc->span.chans[i+16].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i+16].rxsig != rxs) { - spin_unlock_irqrestore(&wc->lock, flags); - zt_rbsbits(&wc->span.chans[i+16], rxs); - spin_lock_irqsave(&wc->lock, flags); - } - } - rxs = (a >> 4) & 0xf; - if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i].rxsig != rxs) { - spin_unlock_irqrestore(&wc->lock, flags); - zt_rbsbits(&wc->span.chans[i], rxs); - spin_lock_irqsave(&wc->lock, flags); - } - } - } - } else if (wc->span.lineconfig & ZT_CONFIG_D4) { - for (i = 0; i < 24; i+=4) { - a = __t1_framer_in(wc, 0x70 + (i>>2)); - /* Get high channel in low bits */ - rxs = (a & 0x3) << 2; - if (!(wc->span.chans[i+3].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i+3].rxsig != rxs) { - spin_unlock_irqrestore(&wc->lock, flags); - zt_rbsbits(&wc->span.chans[i+3], rxs); - spin_lock_irqsave(&wc->lock, flags); - } - } - rxs = (a & 0xc); - if (!(wc->span.chans[i+2].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i+2].rxsig != rxs) { - spin_unlock_irqrestore(&wc->lock, flags); - zt_rbsbits(&wc->span.chans[i+2], rxs); - spin_lock_irqsave(&wc->lock, flags); - } - } - rxs = (a >> 2) & 0xc; - if (!(wc->span.chans[i+1].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i+1].rxsig != rxs) { - spin_unlock_irqrestore(&wc->lock, flags); - zt_rbsbits(&wc->span.chans[i+1], rxs); - spin_lock_irqsave(&wc->lock, flags); - } - } - rxs = (a >> 4) & 0xc; - if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i].rxsig != rxs) { - spin_unlock_irqrestore(&wc->lock, flags); - zt_rbsbits(&wc->span.chans[i], rxs); - spin_lock_irqsave(&wc->lock, flags); - } - } - } - } else { - for (i = 0; i < 24; i+=2) { - a = __t1_framer_in(wc, 0x70 + (i>>1)); - /* Get high channel in low bits */ - rxs = (a & 0xf); - if (!(wc->span.chans[i+1].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i+1].rxsig != rxs) { - spin_unlock_irqrestore(&wc->lock, flags); - zt_rbsbits(&wc->span.chans[i+1], rxs); - spin_lock_irqsave(&wc->lock, flags); - } - } - rxs = (a >> 4) & 0xf; - if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i].rxsig != rxs) { - spin_unlock_irqrestore(&wc->lock, flags); - zt_rbsbits(&wc->span.chans[i], rxs); - spin_lock_irqsave(&wc->lock, flags); - } - } - } - } - spin_unlock_irqrestore(&wc->lock, flags); -} - -static void t4_serial_setup(struct t1 *wc) -{ - printk("TE110P: Setting up global serial parameters for %s %s\n", - wc->spantype == TYPE_E1 ? (unchannelized ? "Unchannelized E1" : "E1") : "T1", - wc->spanflags & FLAG_FALC12 ? "FALC V1.2" : "FALC V2.2"); - t1_framer_out(wc, 0x85, 0xe0); /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0 */ - t1_framer_out(wc, 0x08, 0x05); /* IPC: Interrupt push/pull active low */ - if (wc->spanflags & FLAG_FALC12) { - t1_framer_out(wc, 0x92, 0x00); - t1_framer_out(wc, 0x93, 0x58); - t1_framer_out(wc, 0x94, 0xd2); - t1_framer_out(wc, 0x95, 0xc2); - t1_framer_out(wc, 0x96, 0x03); - t1_framer_out(wc, 0x97, 0x10); - } else { - /* Global clocks (8.192 Mhz CLK) */ - t1_framer_out(wc, 0x92, 0x00); - t1_framer_out(wc, 0x93, 0x18); - t1_framer_out(wc, 0x94, 0xfb); - t1_framer_out(wc, 0x95, 0x0b); - t1_framer_out(wc, 0x96, 0x00); - t1_framer_out(wc, 0x97, 0x0b); - t1_framer_out(wc, 0x98, 0xdb); - t1_framer_out(wc, 0x99, 0xdf); - } - /* Configure interrupts */ - t1_framer_out(wc, 0x46, 0x40); /* GCR: Interrupt on Activation/Deactivation of AIX, LOS */ - - /* Configure system interface */ - t1_framer_out(wc, 0x3e, 0x02); /* SIC1: 4.096 Mhz clock/bus, double buffer receive / transmit, byte interleaved */ - t1_framer_out(wc, 0x3f, 0x00); /* SIC2: No FFS, no center receive eliastic buffer, phase 0 */ - t1_framer_out(wc, 0x40, 0x04); /* SIC3: Edges for capture */ - t1_framer_out(wc, 0x44, 0x30); /* CMR1: RCLK is at 8.192 Mhz dejittered */ - t1_framer_out(wc, 0x45, 0x00); /* CMR2: We provide sync and clock for tx and rx. */ - t1_framer_out(wc, 0x22, 0x00); /* XC0: Normal operation of Sa-bits */ - t1_framer_out(wc, 0x23, 0x04); /* XC1: 0 offset */ - t1_framer_out(wc, 0x24, 0x07); /* RC0: Just shy of 255 */ - if (wc->spanflags & FLAG_FALC12) - t1_framer_out(wc, 0x25, 0x04); /* RC1: The rest of RC0 */ - else - t1_framer_out(wc, 0x25, 0x05); /* RC1: The rest of RC0 */ - - /* Configure ports */ - t1_framer_out(wc, 0x80, 0x00); /* PC1: SPYR/SPYX input on RPA/XPA */ - t1_framer_out(wc, 0x81, 0x22); /* PC2: RMFB/XSIG output/input on RPB/XPB */ - t1_framer_out(wc, 0x82, 0x65); /* PC3: Some unused stuff */ - t1_framer_out(wc, 0x83, 0x35); /* PC4: Some more unused stuff */ - t1_framer_out(wc, 0x84, 0x31); /* PC5: XMFS active low, SCLKR is input, RCLK is output */ - t1_framer_out(wc, 0x86, 0x03); /* PC6: CLK1 is Tx Clock output, CLK2 is 8.192 Mhz from DCO-R */ - t1_framer_out(wc, 0x3b, 0x00); /* Clear LCR1 */ - printk("TE110P: Successfully initialized serial bus for card\n"); -} - -static void __t1_configure_t1(struct t1 *wc, int lineconfig, int txlevel) -{ - unsigned int fmr4, fmr2, fmr1, fmr0, lim2; - char *framing, *line; - int mytxlevel; - if ((txlevel > 7) || (txlevel < 4)) - mytxlevel = 0; - else - mytxlevel = txlevel - 4; - fmr1 = 0x1c; /* FMR1: Mode 0, T1 mode, CRC on for ESF, 2.048 Mhz system data rate, no XAIS */ - fmr2 = 0x22; /* FMR2: no payload loopback, auto send yellow alarm */ - if (loopback) - fmr2 |= 0x4; - - if (j1mode) - fmr4 = 0x1c; - else - fmr4 = 0x0c; /* FMR4: Lose sync on 2 out of 5 framing bits, auto resync */ - - - lim2 = 0x21; /* LIM2: 50% peak is a "1", Advanced Loss recovery */ - lim2 |= (mytxlevel << 6); /* LIM2: Add line buildout */ - __t1_framer_out(wc, 0x1d, fmr1); - __t1_framer_out(wc, 0x1e, fmr2); - - /* Configure line interface */ - if (lineconfig & ZT_CONFIG_AMI) { - line = "AMI"; - fmr0 = 0xa0; - } else { - line = "B8ZS"; - fmr0 = 0xf0; - } - if (lineconfig & ZT_CONFIG_D4) { - framing = "D4"; - } else { - framing = "ESF"; - fmr4 |= 0x2; - fmr2 |= 0xc0; - } - __t1_framer_out(wc, 0x1c, fmr0); - - __t1_framer_out(wc, 0x20, fmr4); - __t1_framer_out(wc, 0x21, 0x40); /* FMR5: Enable RBS mode */ - - __t1_framer_out(wc, 0x37, 0xf8); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ - __t1_framer_out(wc, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ - - __t1_framer_out(wc, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ - __t1_framer_out(wc, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ - - __t1_framer_out(wc, 0x3a, lim2); /* LIM2: 50% peak amplitude is a "1" */ - __t1_framer_out(wc, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ - __t1_framer_out(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ - - if (j1mode) - __t1_framer_out(wc, 0x24, 0x80); /* J1 overide */ - - /* Generate pulse mask for T1 */ - switch(mytxlevel) { - case 3: - __t1_framer_out(wc, 0x26, 0x07); /* XPM0 */ - __t1_framer_out(wc, 0x27, 0x01); /* XPM1 */ - __t1_framer_out(wc, 0x28, 0x00); /* XPM2 */ - break; - case 2: - __t1_framer_out(wc, 0x26, 0x8c); /* XPM0 */ - __t1_framer_out(wc, 0x27, 0x11); /* XPM1 */ - __t1_framer_out(wc, 0x28, 0x01); /* XPM2 */ - break; - case 1: - __t1_framer_out(wc, 0x26, 0x8c); /* XPM0 */ - __t1_framer_out(wc, 0x27, 0x01); /* XPM1 */ - __t1_framer_out(wc, 0x28, 0x00); /* XPM2 */ - break; - case 0: - default: - __t1_framer_out(wc, 0x26, 0xd7); /* XPM0 */ - __t1_framer_out(wc, 0x27, 0x22); /* XPM1 */ - __t1_framer_out(wc, 0x28, 0x01); /* XPM2 */ - break; - } - printk("TE110P: Span configured for %s/%s\n", framing, line); -} - -static void __t1_configure_e1(struct t1 *wc, int lineconfig) -{ - unsigned int fmr2, fmr1, fmr0; - unsigned int cas = 0; - char *crc4 = ""; - char *framing, *line; - fmr1 = 0x44; /* FMR1: E1 mode, Automatic force resync, PCM30 mode, 8.192 Mhz backplane, no XAIS */ - fmr2 = 0x03; /* FMR2: Auto transmit remote alarm, auto loss of multiframe recovery, no payload loopback */ - if (unchannelized) - fmr2 |= 0x30; - if (loopback) - fmr2 |= 0x4; - if (lineconfig & ZT_CONFIG_CRC4) { - fmr1 |= 0x08; /* CRC4 transmit */ - fmr2 |= 0xc0; /* CRC4 receive */ - crc4 = "/CRC4"; - } - __t1_framer_out(wc, 0x1d, fmr1); - __t1_framer_out(wc, 0x1e, fmr2); - - /* Configure line interface */ - if (lineconfig & ZT_CONFIG_AMI) { - line = "AMI"; - fmr0 = 0xa0; - } else { - line = "HDB3"; - fmr0 = 0xf0; - } - if (lineconfig & ZT_CONFIG_CCS) { - framing = "CCS"; - } else { - framing = "CAS"; - cas = 0x40; - } - __t1_framer_out(wc, 0x1c, fmr0); - - if (unchannelized) - __t1_framer_out(wc, 0x1f, 0x40); - - __t1_framer_out(wc, 0x37, 0xf0 /*| 0x6 */ ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ - __t1_framer_out(wc, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ - - __t1_framer_out(wc, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ - __t1_framer_out(wc, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ - - /* Condition receive line interface for E1 after reset */ - __t1_framer_out(wc, 0xbb, 0x17); - __t1_framer_out(wc, 0xbc, 0x55); - __t1_framer_out(wc, 0xbb, 0x97); - __t1_framer_out(wc, 0xbb, 0x11); - __t1_framer_out(wc, 0xbc, 0xaa); - __t1_framer_out(wc, 0xbb, 0x91); - __t1_framer_out(wc, 0xbb, 0x12); - __t1_framer_out(wc, 0xbc, 0x55); - __t1_framer_out(wc, 0xbb, 0x92); - __t1_framer_out(wc, 0xbb, 0x0c); - __t1_framer_out(wc, 0xbb, 0x00); - __t1_framer_out(wc, 0xbb, 0x8c); - - __t1_framer_out(wc, 0x3a, 0x20); /* LIM2: 50% peak amplitude is a "1" */ - __t1_framer_out(wc, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ - __t1_framer_out(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ - - __t1_framer_out(wc, 0x20, 0x9f); /* XSW: Spare bits all to 1 */ - if (unchannelized) - __t1_framer_out(wc, 0x21, 0x3c); - else - __t1_framer_out(wc, 0x21, 0x1c|cas); /* XSP: E-bit set when async. AXS auto, XSIF to 1 */ - - - /* Generate pulse mask for E1 */ - __t1_framer_out(wc, 0x26, 0x54); /* XPM0 */ - __t1_framer_out(wc, 0x27, 0x02); /* XPM1 */ - __t1_framer_out(wc, 0x28, 0x00); /* XPM2 */ - printk("TE110P: Span configured for %s/%s%s\n", framing, line, crc4); -} - -static void t1xxp_framer_start(struct t1 *wc, struct zt_span *span) -{ - int alreadyrunning = wc->span.flags & ZT_FLAG_RUNNING; - unsigned long flags; - - spin_lock_irqsave(&wc->lock, flags); - - if (wc->spantype == TYPE_E1) { /* if this is an E1 card */ - __t1_configure_e1(wc, span->lineconfig); - } else { /* is a T1 card */ - __t1_configure_t1(wc, span->lineconfig, span->txlevel); - __t1xxp_set_clear(wc); - } - - if (!alreadyrunning) - wc->span.flags |= ZT_FLAG_RUNNING; - - spin_unlock_irqrestore(&wc->lock, flags); -} - - -static int t1xxp_startup(struct zt_span *span) -{ - struct t1 *wc = span->pvt; - - int i,alreadyrunning = span->flags & ZT_FLAG_RUNNING; - - /* initialize the start value for the entire chunk of last ec buffer */ - for(i = 0; i < span->channels; i++) - { - memset(wc->ec_chunk1[i], - ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); - memset(wc->ec_chunk2[i], - ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); - } - - /* Reset framer with proper parameters and start */ - t1xxp_framer_start(wc, span); - printk("Calling startup (flags is %d)\n", span->flags); - - if (!alreadyrunning) { - /* Only if we're not already going */ - t1xxp_enable_interrupts(wc); - t1xxp_start_dma(wc); - span->flags |= ZT_FLAG_RUNNING; - } - return 0; -} - -static int t1xxp_shutdown(struct zt_span *span) -{ - struct t1 *wc = span->pvt; - unsigned long flags; - - spin_lock_irqsave(&wc->lock, flags); - __t1_framer_out(wc, 0x46, 0x41); /* GCR: Interrupt on Activation/Deactivation of AIX, LOS */ - __t1xxp_stop_dma(wc); - __t1xxp_disable_interrupts(wc); - span->flags &= ~ZT_FLAG_RUNNING; - spin_unlock_irqrestore(&wc->lock, flags); - return 0; -} - - -static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype) -{ - struct t1 *wc = chan->pvt; - unsigned long flags; - int alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING; - - spin_lock_irqsave(&wc->lock, flags); - - if (alreadyrunning && (wc->spantype != TYPE_E1)) - __t1xxp_set_clear(wc); - - spin_unlock_irqrestore(&wc->lock, flags); - return 0; -} - -static int t1xxp_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) -{ - struct t1 *wc = span->pvt; - - /* Do we want to SYNC on receive or not */ - wc->sync = lc->sync; - /* If already running, apply changes immediately */ - if (span->flags & ZT_FLAG_RUNNING) - return t1xxp_startup(span); - - return 0; -} - -static int t1xxp_software_init(struct t1 *wc) -{ - int x; - /* Find position */ - for (x=0;x= WC_MAX_CARDS) - return -1; - t4_serial_setup(wc); - wc->num = x; - sprintf(wc->span.name, "WCT1/%d", wc->num); - snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num); - wc->span.manufacturer = "Digium"; - strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); - snprintf(wc->span.location, sizeof(wc->span.location) - 1, - "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); - wc->span.spanconfig = t1xxp_spanconfig; - wc->span.chanconfig = t1xxp_chanconfig; - wc->span.irq = wc->dev->irq; - wc->span.startup = t1xxp_startup; - wc->span.shutdown = t1xxp_shutdown; - wc->span.rbsbits = t1xxp_rbsbits; - wc->span.maint = t1xxp_maint; - wc->span.open = t1xxp_open; - wc->span.close = t1xxp_close; - if (wc->spantype == TYPE_E1) { - if (unchannelized) - wc->span.channels = 32; - else - wc->span.channels = 31; - wc->span.deflaw = ZT_LAW_ALAW; - wc->span.spantype = "E1"; - wc->span.linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4; - } else { - wc->span.channels = 24; - wc->span.deflaw = ZT_LAW_MULAW; - wc->span.spantype = "T1"; - wc->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; - } - wc->span.chans = wc->chans; - wc->span.flags = ZT_FLAG_RBS; - wc->span.ioctl = t1xxp_ioctl; - wc->span.pvt = wc; - init_waitqueue_head(&wc->span.maintq); - for (x=0;xspan.channels;x++) { - sprintf(wc->chans[x].name, "WCT1/%d/%d", wc->num, x + 1); - wc->chans[x].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_EM_E1 | - ZT_SIG_FXSLS | ZT_SIG_FXSGS | - ZT_SIG_FXSKS | ZT_SIG_FXOLS | ZT_SIG_DACS_RBS | - ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF; - wc->chans[x].pvt = wc; - wc->chans[x].chanpos = x + 1; - } - if (zt_register(&wc->span, 0)) { - printk("Unable to register span with zaptel\n"); - return -1; - } - return 0; -} - -static inline void __handle_leds(struct t1 *wc) -{ - int oldreg; - - if (wc->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) { - /* Red/Blue alarm */ - wc->blinktimer++; -#ifdef FANCY_ALARM - if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) { - wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0; - __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); - } - if (wc->blinktimer >= 0xf) { - wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1); - __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); - wc->blinktimer = -1; - wc->alarmpos++; - if (wc->alarmpos >= (sizeof(altab) / sizeof(altab[0]))) - wc->alarmpos = 0; - } -#else - if (wc->blinktimer == 160) { - wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0; - __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); - } else if (wc->blinktimer == 480) { - wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1); - __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); - wc->blinktimer = 0; - } -#endif - } else if (wc->span.alarms & ZT_ALARM_YELLOW) { - /* Yellow Alarm */ - if (!(wc->blinktimer % 2)) - wc->ledtestreg = (wc->ledtestreg | BIT_LED1) & ~BIT_LED0; - else - wc->ledtestreg = (wc->ledtestreg | BIT_LED0) & ~BIT_LED1; - __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); - } else { - /* No Alarm */ - oldreg = wc->ledtestreg; - if (wc->span.maintstat != ZT_MAINT_NONE) - wc->ledtestreg |= BIT_TEST; - else - wc->ledtestreg &= ~BIT_TEST; - if (wc->span.flags & ZT_FLAG_RUNNING) - wc->ledtestreg = (wc->ledtestreg | BIT_LED0) & ~BIT_LED1; - else - wc->ledtestreg = wc->ledtestreg & ~(BIT_LED0 | BIT_LED1); - if (oldreg != wc->ledtestreg) - __control_set_reg(wc, WC_LEDTEST, wc->ledtestreg); - } -} - -static void t1xxp_transmitprep(struct t1 *wc, int ints) -{ - volatile unsigned char *txbuf; - int x,y; - int pos; - if (ints & 0x04 /* 0x01 */) { - /* We just finished sending the first buffer, start filling it - now */ - txbuf = wc->writechunk; - } else { - /* Just finished sending second buffer, fill it now */ - txbuf = wc->writechunk + 32 * ZT_CHUNKSIZE; - } - zt_transmit(&wc->span); - for (x=0;xoffset;x++) - txbuf[x] = wc->tempo[x]; - for (y=0;yspan.channels;x++) { - pos = y * 32 + wc->chanmap[x] + wc->offset; - /* Put channel number as outgoing data */ - if (pos < 32 * ZT_CHUNKSIZE) - txbuf[pos] = wc->chans[x].writechunk[y]; - else - wc->tempo[pos - 32 * ZT_CHUNKSIZE] = wc->chans[x].writechunk[y]; - } - } -} - -static void t1xxp_receiveprep(struct t1 *wc, int ints) -{ - volatile unsigned char *rxbuf; - volatile unsigned int *canary; - int x; - int y; - unsigned int oldcan; - if (ints & 0x04) { - /* Just received first buffer */ - rxbuf = wc->readchunk; - canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 64 - 4); - } else { - rxbuf = wc->readchunk + ZT_CHUNKSIZE * 32; - canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 32 - 4); - } - oldcan = *canary; - if (((oldcan & 0xffff0000) >> 16) != CANARY) { - /* Check top part */ - if (debug) printk("Expecting top %04x, got %04x\n", CANARY, (oldcan & 0xffff0000) >> 16); - wc->span.irqmisses++; - } else if ((oldcan & 0xffff) != ((wc->canary - 1) & 0xffff)) { - if (debug) printk("Expecting bottom %d, got %d\n", wc->canary - 1, oldcan & 0xffff); - wc->span.irqmisses++; - } - for (y=0;yspan.channels;x++) { - /* XXX Optimize, remove * and + XXX */ - /* Must map received channels into appropriate data */ - wc->chans[x].readchunk[y] = - rxbuf[32 * y + ((wc->chanmap[x] + WC_OFFSET + wc->offset) & 0x1f)]; - } - if (wc->spantype != TYPE_E1) { - for (x=3;x<32;x+=4) { - if (rxbuf[32 * y + ((x + WC_OFFSET) & 0x1f)] == 0x7f) { - if (wc->offset != (x-3)) { - /* Resync */ - control_set_reg(wc, WC_CLOCK, 0x06 | wc->sync | clockextra); - wc->clocktimeout = 100; -#if 1 - if (debug) printk("T1: Lost our place, resyncing\n"); -#endif - } - } - } - } else if (!unchannelized) { - if (!wc->clocktimeout && !wc->span.alarms) { - if ((rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)] & 0x7f) != 0x1b) { - if (wc->miss) { - if (debug) printk("Double miss (%d, %d)...\n", wc->misslast, rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)]); - control_set_reg(wc, WC_CLOCK, 0x06 | wc->sync | clockextra); - wc->clocktimeout = 100; - } else { - wc->miss = 1; - wc->misslast = rxbuf[32 * y + ((3 + WC_OFFSET + wc->offset) & 0x1f)]; - } - } else { - wc->miss = 0; - } - } else { - wc->miss = 0; - } - } - } - /* Store the next canary */ - canary = (unsigned int *)(rxbuf + ZT_CHUNKSIZE * 32 - 4); - *canary = (wc->canary++) | (CANARY << 16); - for (x=0;xspan.channels;x++) { - zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, - wc->ec_chunk2[x]); - memcpy(wc->ec_chunk2[x],wc->ec_chunk1[x],ZT_CHUNKSIZE); - memcpy(wc->ec_chunk1[x],wc->chans[x].writechunk,ZT_CHUNKSIZE); - } - zt_receive(&wc->span); -} - -static void t1_check_alarms(struct t1 *wc) -{ - unsigned char c,d; - int alarms; - int x,j; - unsigned long flags; - - if (!(wc->span.flags & ZT_FLAG_RUNNING)) - return; - - spin_lock_irqsave(&wc->lock, flags); - - c = __t1_framer_in(wc, 0x4c); - if (wc->spanflags & FLAG_FALC12) - d = __t1_framer_in(wc, 0x4f); - else - d = __t1_framer_in(wc, 0x4d); - - /* Assume no alarms */ - alarms = 0; - - /* And consider only carrier alarms */ - wc->span.alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); - - if (wc->spantype == TYPE_E1) { - if (c & 0x04) { - /* No multiframe found, force RAI high after 400ms only if - we haven't found a multiframe since last loss - of frame */ - if (!(wc->spanflags & FLAG_NMF)) { - __t1_framer_out(wc, 0x20, 0x9f | 0x20); /* LIM0: Force RAI High */ - wc->spanflags |= FLAG_NMF; - printk("NMF workaround on!\n"); - } - __t1_framer_out(wc, 0x1e, 0xc3); /* Reset to CRC4 mode */ - __t1_framer_out(wc, 0x1c, 0xf2); /* Force Resync */ - __t1_framer_out(wc, 0x1c, 0xf0); /* Force Resync */ - } else if (!(c & 0x02)) { - if ((wc->spanflags & FLAG_NMF)) { - __t1_framer_out(wc, 0x20, 0x9f); /* LIM0: Clear forced RAI */ - wc->spanflags &= ~FLAG_NMF; - printk("NMF workaround off!\n"); - } - } - } else { - /* Detect loopup code if we're not sending one */ - if ((!wc->span.mainttimer) && (d & 0x08)) { - /* Loop-up code detected */ - if ((wc->loopupcnt++ > 80) && (wc->span.maintstat != ZT_MAINT_REMOTELOOP)) { - __t1_framer_out(wc, 0x36, 0x08); /* LIM0: Disable any local loop */ - __t1_framer_out(wc, 0x37, 0xf6 ); /* LIM1: Enable remote loop */ - wc->span.maintstat = ZT_MAINT_REMOTELOOP; - } - } else - wc->loopupcnt = 0; - /* Same for loopdown code */ - if ((!wc->span.mainttimer) && (d & 0x10)) { - /* Loop-down code detected */ - if ((wc->loopdowncnt++ > 80) && (wc->span.maintstat == ZT_MAINT_REMOTELOOP)) { - __t1_framer_out(wc, 0x36, 0x08); /* LIM0: Disable any local loop */ - __t1_framer_out(wc, 0x37, 0xf0 ); /* LIM1: Disable remote loop */ - wc->span.maintstat = ZT_MAINT_NONE; - } - } else - wc->loopdowncnt = 0; - } - - if (wc->span.lineconfig & ZT_CONFIG_NOTOPEN) { - for (x=0,j=0;x < wc->span.channels;x++) - if ((wc->span.chans[x].flags & ZT_FLAG_OPEN) || - (wc->span.chans[x].flags & ZT_FLAG_NETDEV)) - j++; - if (!j) - alarms |= ZT_ALARM_NOTOPEN; - } - - if (c & 0xa0) { - if (wc->alarmcount >= alarmdebounce) { - if (!unchannelized) - alarms |= ZT_ALARM_RED; - } else - wc->alarmcount++; - } else - wc->alarmcount = 0; - if (c & 0x4) - alarms |= ZT_ALARM_BLUE; - - if (((!wc->span.alarms) && alarms) || - (wc->span.alarms && (!alarms))) - wc->checktiming = 1; - - /* Keep track of recovering */ - if ((!alarms) && wc->span.alarms) - wc->alarmtimer = ZT_ALARMSETTLE_TIME; - if (wc->alarmtimer) - alarms |= ZT_ALARM_RECOVER; - - /* If receiving alarms, go into Yellow alarm state */ - if (alarms && !(wc->spanflags & FLAG_SENDINGYELLOW)) { - unsigned char fmr4; -#if 1 - printk("wcte1xxp: Setting yellow alarm\n"); -#endif - /* We manually do yellow alarm to handle RECOVER and NOTOPEN, otherwise it's auto anyway */ - fmr4 = __t1_framer_in(wc, 0x20); - __t1_framer_out(wc, 0x20, fmr4 | 0x20); - wc->spanflags |= FLAG_SENDINGYELLOW; - } else if ((!alarms) && (wc->spanflags & FLAG_SENDINGYELLOW)) { - unsigned char fmr4; -#if 1 - printk("wcte1xxp: Clearing yellow alarm\n"); -#endif - /* We manually do yellow alarm to handle RECOVER */ - fmr4 = __t1_framer_in(wc, 0x20); - __t1_framer_out(wc, 0x20, fmr4 & ~0x20); - wc->spanflags &= ~FLAG_SENDINGYELLOW; - } - - /* Re-check the timing source when we enter/leave alarm, not withstanding - yellow alarm */ - if ((c & 0x10) && !unchannelized) - alarms |= ZT_ALARM_YELLOW; - if (wc->span.mainttimer || wc->span.maintstat) - alarms |= ZT_ALARM_LOOPBACK; - wc->span.alarms = alarms; - spin_unlock_irqrestore(&wc->lock, flags); - zt_alarm_notify(&wc->span); -} - - -static void t1_do_counters(struct t1 *wc) -{ - unsigned long flags; - - spin_lock_irqsave(&wc->lock, flags); - if (wc->alarmtimer) { - if (!--wc->alarmtimer) { - wc->span.alarms &= ~(ZT_ALARM_RECOVER); - spin_unlock_irqrestore(&wc->lock, flags); - zt_alarm_notify(&wc->span); - spin_lock_irqsave(&wc->lock, flags); - } - } - spin_unlock_irqrestore(&wc->lock, flags); -} - -ZAP_IRQ_HANDLER(t1xxp_interrupt) -{ - struct t1 *wc = dev_id; - unsigned char ints; - unsigned long flags; - int x; - - ints = inb(wc->ioaddr + WC_INTSTAT); - if (!ints) -#ifdef LINUX26 - return IRQ_NONE; -#else - return; -#endif - - outb(ints, wc->ioaddr + WC_INTSTAT); - - if (!wc->intcount) { - if (debug) printk("Got interrupt: 0x%04x\n", ints); - } - wc->intcount++; - - if (wc->clocktimeout && !--wc->clocktimeout) - control_set_reg(wc, WC_CLOCK, 0x04 | wc->sync | clockextra); - - if (ints & 0x0f) { - t1xxp_receiveprep(wc, ints); - t1xxp_transmitprep(wc, ints); - } - spin_lock_irqsave(&wc->lock, flags); - -#if 1 - __handle_leds(wc); -#endif - - spin_unlock_irqrestore(&wc->lock, flags); - - /* Count down timers */ - t1_do_counters(wc); - - /* Do some things that we don't have to do very often */ - x = wc->intcount & 15 /* 63 */; - switch(x) { - case 0: - case 1: - break; - case 2: - t1_check_sigbits(wc); - break; - case 4: - /* Check alarms 1/4 as frequently */ - if (!(wc->intcount & 0x30)) - t1_check_alarms(wc); - break; - } - - if (ints & 0x10) - printk("PCI Master abort\n"); - - if (ints & 0x20) - printk("PCI Target abort\n"); - -#ifdef LINUX26 - return IRQ_RETVAL(1); -#endif -} - -static int t1xxp_hardware_init(struct t1 *wc) -{ - unsigned int falcver; - unsigned int x; - /* Hardware PCI stuff */ - /* Reset chip and registers */ - outb(DELAY | 0x0e, wc->ioaddr + WC_CNTL); - /* Set all outputs to 0 */ - outb(0x00, wc->ioaddr + WC_AUXD); - /* Set all to outputs except AUX1 (TDO). */ - outb(0xfd, wc->ioaddr + WC_AUXC); - /* Configure the serial port: double clock, 20ns width, no inversion, - MSB first */ - outb(0xc8, wc->ioaddr + WC_SERC); - - /* Internally delay FSC by one */ - outb(0x01, wc->ioaddr + WC_FSCDELAY); - - /* Back to normal, with automatic DMA wrap around */ - outb(DELAY | 0x01, wc->ioaddr + WC_CNTL); - - /* Make sure serial port and DMA are out of reset */ - outb(inb(wc->ioaddr + WC_CNTL) & 0xf9, WC_CNTL); - - /* Setup DMA Addresses */ - /* Start at writedma */ - outl(wc->writedma, wc->ioaddr + WC_DMAWS); /* Write start */ - /* First frame */ - outl(wc->writedma + ZT_CHUNKSIZE * 32 - 4, wc->ioaddr + WC_DMAWI); /* Middle (interrupt) */ - /* Second frame */ - outl(wc->writedma + ZT_CHUNKSIZE * 32 * 2 - 4, wc->ioaddr + WC_DMAWE); /* End */ - - outl(wc->readdma, wc->ioaddr + WC_DMARS); /* Read start */ - /* First frame */ - outl(wc->readdma + ZT_CHUNKSIZE * 32 - 4, wc->ioaddr + WC_DMARI); /* Middle (interrupt) */ - /* Second frame */ - outl(wc->readdma + ZT_CHUNKSIZE * 32 * 2 - 4, wc->ioaddr + WC_DMARE); /* End */ - - if (debug) printk("Setting up DMA (write/read = %08lx/%08lx)\n", (long)wc->writedma, (long)wc->readdma); - - if (t1e1override > -1) { - if (t1e1override) - wc->spantype = TYPE_E1; - else - wc->spantype = TYPE_T1; - } else { - if (control_get_reg(wc, WC_CLOCK) & 0x20) - wc->spantype = TYPE_T1; - else - wc->spantype = TYPE_E1; - } - - /* Check out the controller */ - if (debug) printk("Controller version: %02x\n", control_get_reg(wc, WC_VERSION)); - - - control_set_reg(wc, WC_LEDTEST, 0x00); - - if (wc->spantype == TYPE_E1) { - if (unchannelized) - wc->chanmap = chanmap_e1uc; - else - wc->chanmap = chanmap_e1; - } else - wc->chanmap = chanmap_t1; - /* Setup clock appropriately */ - control_set_reg(wc, WC_CLOCK, 0x06 | wc->sync | clockextra); - wc->clocktimeout = 100; - - /* Perform register test on FALC */ - for (x=0;x<256;x++) { - t1_framer_out(wc, 0x14, x); - if ((falcver = t1_framer_in(wc, 0x14)) != x) - printk("Wrote '%x' but read '%x'\n", x, falcver); - } - - t1_framer_out(wc, 0x4a, 0xaa); - falcver = t1_framer_in(wc ,0x4a); - printk("FALC version: %08x\n", falcver); - if (!falcver) - wc->spanflags |= FLAG_FALC12; - - - start_alarm(wc); - return 0; - -} - -static int __devinit t1xxp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int res; - struct t1 *wc; - unsigned int *canary; - - if (pci_enable_device(pdev)) { - res = -EIO; - } else { - wc = kmalloc(sizeof(struct t1), GFP_KERNEL); - if (wc) { - memset(wc, 0x0, sizeof(struct t1)); - spin_lock_init(&wc->lock); - wc->ioaddr = pci_resource_start(pdev, 0); - wc->dev = pdev; - wc->offset = 28; /* And you thought 42 was the answer */ - - wc->writechunk = - /* 32 channels, Double-buffer, Read/Write */ - (unsigned char *)pci_alloc_consistent(pdev, ZT_MAX_CHUNKSIZE * 32 * 2 * 2, &wc->writedma); - if (!wc->writechunk) { - printk("wcte11xp: Unable to allocate DMA-able memory\n"); - return -ENOMEM; - } - - /* Read is after the whole write piece (in bytes) */ - wc->readchunk = wc->writechunk + ZT_CHUNKSIZE * 32 * 2; - - /* Same thing... */ - wc->readdma = wc->writedma + ZT_CHUNKSIZE * 32 * 2; - - /* Initialize Write/Buffers to all blank data */ - memset((void *)wc->writechunk,0x00,ZT_MAX_CHUNKSIZE * 2 * 2 * 32); - /* Initialize canary */ - canary = (unsigned int *)(wc->readchunk + ZT_CHUNKSIZE * 64 - 4); - *canary = (CANARY << 16) | (0xffff); - - /* Enable bus mastering */ - pci_set_master(pdev); - - /* Keep track of which device we are */ - pci_set_drvdata(pdev, wc); - - if (request_irq(pdev->irq, t1xxp_interrupt, ZAP_IRQ_SHARED_DISABLED, "wcte11xp", wc)) { - printk("wcte11xp: Unable to request IRQ %d\n", pdev->irq); - kfree(wc); - return -EIO; - } - /* Initialize hardware */ - t1xxp_hardware_init(wc); - - /* We now know which version of card we have */ - wc->variety = "Digium Wildcard TE110P T1/E1"; - - /* Misc. software stuff */ - t1xxp_software_init(wc); - - printk("Found a Wildcard: %s\n", wc->variety); - res = 0; - } else - res = -ENOMEM; - } - return res; -} - -static void t1xxp_stop_stuff(struct t1 *wc) -{ - /* Kill clock */ - control_set_reg(wc, WC_CLOCK, 0); - - /* Turn off LED's */ - control_set_reg(wc, WC_LEDTEST, 0); - -} - -static void __devexit t1xxp_remove_one(struct pci_dev *pdev) -{ - struct t1 *wc = pci_get_drvdata(pdev); - if (wc) { - - /* Stop any DMA */ - __t1xxp_stop_dma(wc); - - /* In case hardware is still there */ - __t1xxp_disable_interrupts(wc); - - t1xxp_stop_stuff(wc); - - /* Immediately free resources */ - pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 32 * 4, (void *)wc->writechunk, wc->writedma); - free_irq(pdev->irq, wc); - - /* Reset PCI chip and registers */ - outb(DELAY | 0x0e, wc->ioaddr + WC_CNTL); - - /* Release span, possibly delayed */ - if (!wc->usecount) - t1xxp_release(wc); - else - wc->dead = 1; - } -} - -static struct pci_device_id t1xxp_pci_tbl[] = { - { 0xe159, 0x0001, 0x71fe, PCI_ANY_ID, 0, 0, (unsigned long) "Digium Wildcard TE110P T1/E1 Board" }, - { 0xe159, 0x0001, 0x79fe, PCI_ANY_ID, 0, 0, (unsigned long) "Digium Wildcard TE110P T1/E1 Board" }, - { 0xe159, 0x0001, 0x795e, PCI_ANY_ID, 0, 0, (unsigned long) "Digium Wildcard TE110P T1/E1 Board" }, - { 0xe159, 0x0001, 0x79de, PCI_ANY_ID, 0, 0, (unsigned long) "Digium Wildcard TE110P T1/E1 Board" }, - { 0xe159, 0x0001, 0x797e, PCI_ANY_ID, 0, 0, (unsigned long) "Digium Wildcard TE110P T1/E1 Board" }, - { 0 } -}; - -MODULE_DEVICE_TABLE(pci,t1xxp_pci_tbl); - -static struct pci_driver t1xxp_driver = { - name: "wcte11xp", - probe: t1xxp_init_one, -#ifdef LINUX26 - remove: __devexit_p(t1xxp_remove_one), -#else - remove: t1xxp_remove_one, -#endif - suspend: NULL, - resume: NULL, - id_table: t1xxp_pci_tbl, -}; - -static int __init t1xxp_init(void) -{ - int res; - res = zap_pci_module(&t1xxp_driver); - if (res) - return -ENODEV; - return 0; -} - -static void __exit t1xxp_cleanup(void) -{ - pci_unregister_driver(&t1xxp_driver); -} - -#ifdef LINUX26 -module_param(alarmdebounce, int, 0600); -module_param(loopback, int, 0600); -module_param(t1e1override, int, 0600); -module_param(unchannelized, int, 0600); -module_param(clockextra, int, 0600); -module_param(debug, int, 0600); -module_param(j1mode, int, 0600); -#else -MODULE_PARM(alarmdebounce, "i"); -MODULE_PARM(loopback, "i"); -MODULE_PARM(t1e1override, "i"); -MODULE_PARM(unchannelized, "i"); -MODULE_PARM(clockextra, "i"); -MODULE_PARM(debug, "i"); -MODULE_PARM(j1mode, "i"); -#endif -MODULE_DESCRIPTION("Wildcard TE110P Zaptel Driver"); -MODULE_AUTHOR("Mark Spencer "); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif - -module_init(t1xxp_init); -module_exit(t1xxp_cleanup); diff --git a/wcte12xp/GpakApi.c b/wcte12xp/GpakApi.c deleted file mode 100644 index 43b844a..0000000 --- a/wcte12xp/GpakApi.c +++ /dev/null @@ -1,1613 +0,0 @@ -/* - * Copyright (c) 2005, Adaptive Digital Technologies, Inc. - * - * File Name: GpakApi.c - * - * Description: - * This file contains user API functions to communicate with DSPs executing - * G.PAK software. The file is integrated into the host processor connected - * to C55X G.PAK DSPs via a Host Port Interface. - * - * Version: 1.0 - * - * Revision History: - * 06/15/05 - Initial release. - * 11/15/2006 - 24 TDM-TDM Channels EC release - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. The standard - * GPL disclaimer is given inline below for your convenience. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "zaptel.h" - -#include "GpakHpi.h" -#include "vpmadt032.h" -#include "GpakApi.h" -#include "gpakenum.h" - -#ifdef VPM_SUPPORT - -/* DSP to Host interface block offsets. */ -#define REPLY_MSG_PNTR_OFFSET 0 /* I/F blk offset to Reply Msg Pointer */ -#define CMD_MSG_PNTR_OFFSET 2 /* I/F blk offset to Command Msg Pointer */ -#define EVENT_MSG_PNTR_OFFSET 4 /* I/F blk offset to Event Msg Pointer */ -#define PKT_BUFR_MEM_OFFSET 6 /* I/F blk offset to Packet Buffer memory */ -#define DSP_STATUS_OFFSET 8 /* I/F blk offset to DSP Status */ -#define VERSION_ID_OFFSET 9 /* I/F blk offset to G.PAK Version Id */ -#define MAX_CMD_MSG_LEN_OFFSET 10 /* I/F blk offset to Max Cmd Msg Length */ -#define CMD_MSG_LEN_OFFSET 11 /* I/F blk offset to Command Msg Length */ -#define REPLY_MSG_LEN_OFFSET 12 /* I/F blk offset to Reply Msg Length */ -#define NUM_CHANNELS_OFFSET 13 /* I/F blk offset to Num Built Channels */ -#define NUM_PKT_CHANNELS_OFFSET 14 /* I/F blk offset to Num Pkt Channels */ -#define NUM_CONFERENCES_OFFSET 15 /* I/F blk offset to Num Conferences */ -//#define CPU_USAGE_OFFSET_1MS 16 /* I/F blk offset to CPU Usage statistics */ -#define CPU_USAGE_OFFSET 18 /* I/F blk offset to CPU Usage statistics */ -//#define CPU_USAGE_OFFSET_10MS 20 /* I/F blk offset to CPU Usage statistics */ -#define FRAMING_STATS_OFFSET 22 /* I/F blk offset to Framing statistics */ - -//#define GPAK_RELEASE_Rate rate10ms -// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -// Macro to reconstruct a 32-bit value from two 16-bit values. -// Parameter p32: 32-bit-wide destination -// Parameter p16: 16-bit-wide source array of length 2 words -#define RECONSTRUCT_LONGWORD(p32, p16) p32 = (DSP_ADDRESS)p16[0]<<16; \ - p32 |= (unsigned long)p16[1] -// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = - -/* DSP Status value definitions. */ -#define DSP_INIT_STATUS 0x5555 /* DSP Initialized status value */ -#define HOST_INIT_STATUS 0xAAAA /* Host Initialized status value */ - -/* Circular packet buffer information structure offsets. */ -#define CB_BUFR_BASE 0 /* pointer to base of circular buffer */ -#define CB_BUFR_SIZE 2 /* size of buffer (words) */ -#define CB_BUFR_PUT_INDEX 3 /* offset in buffer for next write */ -#define CB_BUFR_TAKE_INDEX 4 /* offset in buffer for next read */ -#define CIRC_BUFFER_INFO_STRUCT_SIZE 6 - -/* Miscellaneous definitions. */ -#define MSG_BUFFER_SIZE 100 /* size (words) of Host msg buffer */ -#define WORD_BUFFER_SIZE 84 /* size of DSP Word buffer (words) */ - -#ifdef __TMS320C55XX__ // debug sections if not on host -#pragma DATA_SECTION(pDspIfBlk,"GPAKAPIDEBUG_SECT") -#pragma DATA_SECTION(MaxCmdMsgLen,"GPAKAPIDEBUG_SECT") -#pragma DATA_SECTION(MaxChannels,"GPAKAPIDEBUG_SECT") -#pragma DATA_SECTION(DlByteBufr,"GPAKAPIDEBUG_SECT") -#pragma DATA_SECTION(DlWordBufr,"GPAKAPIDEBUG_SECT") -#pragma DATA_SECTION(pEventFifoAddress,"GPAKAPIDEBUG_SECT") -#endif - -/* Host variables related to Host to DSP interface. */ -static DSP_ADDRESS pDspIfBlk[MAX_DSP_CORES]; /* DSP address of I/F block */ -static DSP_WORD MaxCmdMsgLen[MAX_DSP_CORES]; /* max Cmd msg length (octets) */ -static unsigned short int MaxChannels[MAX_DSP_CORES]; /* max num channels */ - -//static unsigned short int MaxPktChannels[MAX_DSP_CORES]; /* max num pkt channels */ -//static unsigned short int MaxConfs[MAX_DSP_CORES]; /* max num conferences */ -//static DSP_ADDRESS pPktInBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt In buffer */ -//static DSP_ADDRESS pPktOutBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt Out buffer */ -static DSP_ADDRESS pEventFifoAddress[MAX_DSP_CORES]; /* event fifo */ - -static unsigned char DlByteBufr[DOWNLOAD_BLOCK_SIZE * 2]; /* Dowload byte buf */ -static DSP_WORD DlWordBufr[DOWNLOAD_BLOCK_SIZE]; /* Dowload word buffer */ - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CheckDspReset - Check if the DSP was reset. - * - * FUNCTION - * This function determines if the DSP was reset and is ready. If reset - * occurred, it reads interface parameters and calculates DSP addresses. - * - * RETURNS - * -1 = DSP is not ready. - * 0 = Reset did not occur. - * 1 = Reset occurred. - * - */ -static int CheckDspReset( - int DspId /* DSP Identifier (0 to MaxDSPCores-1) */ - ) -{ - DSP_ADDRESS IfBlockPntr; /* Interface Block pointer */ - DSP_WORD DspStatus; /* DSP Status */ - DSP_WORD DspChannels; /* number of DSP channels */ - //DSP_WORD DspConfs; /* number of DSP conferences */ - //DSP_ADDRESS PktBufrMem; /* address of Packet Buffer */ - DSP_WORD Temp[2]; - //unsigned short int i; /* loop index / counter */ - - /* Read the pointer to the Interface Block. */ - gpakReadDspMemory(DspId, DSP_IFBLK_ADDRESS, 2, Temp); - RECONSTRUCT_LONGWORD(IfBlockPntr, Temp); - - /* If the pointer is zero, return with an indication the DSP is not - ready. */ - if (IfBlockPntr == 0) - return (-1); - - /* Read the DSP's Status. */ - gpakReadDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, &DspStatus); - - /* If status indicates the DSP was reset, read the DSP's interface - parameters and calculate DSP addresses. */ - if (DspStatus == DSP_INIT_STATUS || - ((DspStatus == HOST_INIT_STATUS) && (pDspIfBlk[DspId] == 0))) - { - /* Save the address of the DSP's Interface Block. */ - pDspIfBlk[DspId] = IfBlockPntr; - - /* Read the DSP's interface parameters. */ - gpakReadDspMemory(DspId, IfBlockPntr + MAX_CMD_MSG_LEN_OFFSET, 1, - &(MaxCmdMsgLen[DspId])); - - /* read the number of configured DSP channels */ - gpakReadDspMemory(DspId, IfBlockPntr + NUM_CHANNELS_OFFSET, 1, - &DspChannels); - if (DspChannels > MAX_CHANNELS) - MaxChannels[DspId] = MAX_CHANNELS; - else - MaxChannels[DspId] = (unsigned short int) DspChannels; -#if 0 - /* read the number of configured DSP conferences */ - gpakReadDspMemory(DspId, IfBlockPntr + NUM_CONFERENCES_OFFSET, 1, - &DspConfs); - if (DspConfs > MAX_CONFS) - MaxConfs[DspId] = MAX_CONFS; - else - MaxConfs[DspId] = (unsigned short int) DspConfs; - - - /* read the number of configured DSP packet channels */ - gpakReadDspMemory(DspId, IfBlockPntr + NUM_PKT_CHANNELS_OFFSET, 1, - &DspChannels); - if (DspChannels > MAX_PKT_CHANNELS) - MaxPktChannels[DspId] = MAX_PKT_CHANNELS; - else - MaxPktChannels[DspId] = (unsigned short int) DspChannels; - - - /* read the pointer to the circular buffer infor struct table */ - gpakReadDspMemory(DspId, IfBlockPntr + PKT_BUFR_MEM_OFFSET, 2, Temp); - RECONSTRUCT_LONGWORD(PktBufrMem, Temp); - - - /* Determine the addresses of each channel's Packet buffers. */ - for (i = 0; i < MaxPktChannels[DspId]; i++) - { - pPktInBufr[DspId][i] = PktBufrMem; - pPktOutBufr[DspId][i] = PktBufrMem + CIRC_BUFFER_INFO_STRUCT_SIZE; - PktBufrMem += (CIRC_BUFFER_INFO_STRUCT_SIZE*2); - } -#endif - - /* read the pointer to the event fifo info struct */ - gpakReadDspMemory(DspId, IfBlockPntr + EVENT_MSG_PNTR_OFFSET, 2, Temp); - RECONSTRUCT_LONGWORD(pEventFifoAddress[DspId], Temp); - - /* Set the DSP Status to indicate the host recognized the reset. */ - DspStatus = HOST_INIT_STATUS; - gpakWriteDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, - &DspStatus); - - /* Return with an indication that a reset occurred. */ - return (1); - } - - /* If status doesn't indicate the host recognized a reset, return with an - indication the DSP is not ready. */ - if ((DspStatus != HOST_INIT_STATUS) || (pDspIfBlk[DspId] == 0)) - return (-1); - - /* Return with an indication that a reset did not occur. */ - return (0); -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * WriteDspCmdMessage - Write a Host Command/Request message to DSP. - * - * FUNCTION - * This function writes a Host Command/Request message into DSP memory and - * informs the DSP of the presence of the message. - * - * RETURNS - * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) - * 0 = Temporarily unable to write message (previous Cmd Msg busy) - * 1 = Message written successfully - * - */ -static int WriteDspCmdMessage( - int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ - DSP_WORD *pMessage, /* pointer to Command message */ - DSP_WORD MsgLength /* length of message (octets) */ - ) -{ - DSP_WORD CmdMsgLength; /* current Cmd message length */ - DSP_WORD Temp[2]; - DSP_ADDRESS BufferPointer; /* message buffer pointer */ - - /* Check if the DSP was reset and is ready. */ - if (CheckDspReset(DspId) == -1) - return (-1); - - /* Make sure the message length is valid. */ - if ((MsgLength < 1) || (MsgLength > MaxCmdMsgLen[DspId])) - return (-1); - - /* Make sure a previous Command message is not in use by the DSP. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, - &CmdMsgLength); - if (CmdMsgLength != 0) - return (0); - - /* Purge any previous Reply message that wasn't read. */ - gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, - &CmdMsgLength); - - /* Copy the Command message into DSP memory. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_PNTR_OFFSET, 2, Temp); - RECONSTRUCT_LONGWORD(BufferPointer, Temp); - gpakWriteDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); - - /* Store the message length in DSP's Command message length (flags DSP that - a Command message is ready). */ - CmdMsgLength = MsgLength; - gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, - &CmdMsgLength); - - /* Return with an indication the message was written. */ - return (1); -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * ReadDspReplyMessage - Read a DSP Reply message from DSP. - * - * FUNCTION - * This function reads a DSP Reply message from DSP memory. - * - * RETURNS - * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) - * 0 = No message available (DSP Reply message empty) - * 1 = Message read successfully (message and length stored in variables) - * - */ -static int ReadDspReplyMessage( - int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ - DSP_WORD *pMessage, /* pointer to Reply message buffer */ - DSP_WORD *pMsgLength /* pointer to msg length var (octets) */ - ) -{ - DSP_WORD MsgLength; /* message length */ - DSP_ADDRESS BufferPointer; /* message buffer pointer */ - DSP_WORD Temp[2]; - - /* Check if the DSP was reset and is ready. */ - if (CheckDspReset(DspId) == -1) - return (-1); - - /* Check if a Reply message is ready. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, - &MsgLength); - if (MsgLength == 0) - return (0); - - /* Make sure the message length is valid. */ - if (MsgLength > *pMsgLength) - return (-1); - - /* Copy the Reply message from DSP memory. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_PNTR_OFFSET, 2, Temp); - RECONSTRUCT_LONGWORD(BufferPointer, Temp); - gpakReadDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); - - /* Store the message length in the message length variable. */ - *pMsgLength = MsgLength; - - /* Indicate a Reply message is not ready. */ - MsgLength = 0; - gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, - &MsgLength); - - /* Return with an indication the message was read. */ - return (1); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * ReadCircBuffer - Read from a DSP circular buffer. - * - * FUNCTION - * This function reads a block of words from a DSP circular buffer. The Take - * address is incremented by the number of words read adjusting for buffer - * wrap. - * - * RETURNS - * nothing - * - */ -static void ReadCircBuffer( - int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ - DSP_ADDRESS BufrBaseAddress, /* address of base of circular buffer */ - DSP_ADDRESS BufrLastAddress, /* address of last word in buffer */ - DSP_ADDRESS *TakeAddress, /* pointer to address in buffer for read */ - DSP_WORD *pWordBuffer, /* pointer to buffer for words read */ - DSP_WORD NumWords /* number of words to read */ - ) -{ - DSP_WORD WordsTillEnd; /* number of words until end of buffer */ - - /* Determine the number of words from the start address until the end of the - buffer. */ - WordsTillEnd = BufrLastAddress - *TakeAddress + 1; - - /* If a buffer wrap will occur, read the first part at the end of the - buffer followed by the second part at the beginning of the buffer. */ - if (NumWords > WordsTillEnd) - { - gpakReadDspMemory(DspId, *TakeAddress, WordsTillEnd, pWordBuffer); - gpakReadDspMemory(DspId, BufrBaseAddress, NumWords - WordsTillEnd, - &(pWordBuffer[WordsTillEnd])); - *TakeAddress = BufrBaseAddress + NumWords - WordsTillEnd; - } - - /* If a buffer wrap will not occur, read all words starting at the current - take address in the buffer. */ - else - { - gpakReadDspMemory(DspId, *TakeAddress, NumWords, pWordBuffer); - if (NumWords == WordsTillEnd) - *TakeAddress = BufrBaseAddress; - else - *TakeAddress = *TakeAddress + NumWords; - } - return; -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * VerifyReply - Verify the reply message is correct for the command sent. - * - * FUNCTION - * This function verifies correct reply message content for the command that - * was just sent. - * - * RETURNS - * 0 = Incorrect - * 1 = Correct - * - */ -static int VerifyReply( - DSP_WORD *pMsgBufr, /* pointer to Reply message buffer */ - int CheckType, /* reply check type */ - DSP_WORD CheckValue /* reply check value */ - ) -{ - - /* Verify Channel or Conference Id. */ - if (CheckType == 1) - { - if (((pMsgBufr[1] >> 8) & 0xFF) != CheckValue) - return (0); - } - - /* Verify Test Mode Id. */ - else if (CheckType == 2) - { - if (pMsgBufr[1] != CheckValue) - return (0); - } - - /* Return with an indication of correct reply. */ - return (1); -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * TransactCmd - Send a command to the DSP and receive it's reply. - * - * FUNCTION - * This function sends the specified command to the DSP and receives the DSP's - * reply. - * - * RETURNS - * Length of reply message (0 = Failure) - * - */ -static unsigned int TransactCmd( - int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ - DSP_WORD *pMsgBufr, /* pointer to Cmd/Reply message buffer */ - DSP_WORD CmdLength, /* length of command message (octets) */ - DSP_WORD ReplyType, /* required type of reply message */ - DSP_WORD ReplyLength, /* required length of reply message (octets) */ - int ReplyCheckType, /* reply check type */ - DSP_WORD ReplyCheckValue /* reply check value */ - ) -{ - int FuncStatus; /* function status */ - int LoopCount; /* wait loop counter */ - DSP_WORD RcvReplyLength; /* received Reply message length */ - DSP_WORD RcvReplyType; /* received Reply message type code */ - DSP_WORD RetValue; /* return value */ - - /* Default the return value to indicate a failure. */ - RetValue = 0; - - /* Lock access to the DSP. */ - gpakLockAccess(DspId); - - /* Attempt to write the command message to the DSP. */ - LoopCount = 0; - while ((FuncStatus = WriteDspCmdMessage(DspId, pMsgBufr, CmdLength)) != 1) - { - if (FuncStatus == -1) - break; - if (++LoopCount > MAX_WAIT_LOOPS) - break; - gpakHostDelay(); - } - - /* Attempt to read the reply message from the DSP if the command message was - sent successfully. */ - if (FuncStatus == 1) - { - for (LoopCount = 0; LoopCount < MAX_WAIT_LOOPS; LoopCount++) - { - RcvReplyLength = MSG_BUFFER_SIZE * 2; - FuncStatus = ReadDspReplyMessage(DspId, pMsgBufr, &RcvReplyLength); - if (FuncStatus == 1) - { - RcvReplyType = (pMsgBufr[0] >> 8) & 0xFF; - if ((RcvReplyLength >= ReplyLength) && - (RcvReplyType == ReplyType) && - VerifyReply(pMsgBufr, ReplyCheckType, ReplyCheckValue)) - { - RetValue = RcvReplyLength; - break; - } - else if (RcvReplyType == MSG_NULL_REPLY) - break; - } - else if (FuncStatus == -1) - break; - gpakHostDelay(); - } - } - - /* Unlock access to the DSP. */ - gpakUnlockAccess(DspId); - - /* Return the length of the reply message (0 = failure). */ - return (RetValue); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakConfigurePorts - Configure a DSP's serial ports. - * - * FUNCTION - * This function configures a DSP's serial ports. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakConfigPortStatus_t gpakConfigurePorts( - unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ - GpakPortConfig_t *pPortConfig, /* pointer to Port Config info */ - GPAK_PortConfigStat_t *pStatus /* pointer to Port Config Status */ - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (CpsInvalidDsp); - - /* Build the Configure Serial Ports message. */ - MsgBuffer[0] = MSG_CONFIGURE_PORTS << 8; - MsgBuffer[1] = (DSP_WORD) - ((pPortConfig->SlotsSelect1 << 12) | - ((pPortConfig->FirstBlockNum1 << 8) & 0x0F00) | - ((pPortConfig->SecBlockNum1 << 4) & 0x00F0)); - MsgBuffer[2] = (DSP_WORD) pPortConfig->FirstSlotMask1; - MsgBuffer[3] = (DSP_WORD) pPortConfig->SecSlotMask1; - MsgBuffer[4] = (DSP_WORD) - ((pPortConfig->SlotsSelect2 << 12) | - ((pPortConfig->FirstBlockNum2 << 8) & 0x0F00) | - ((pPortConfig->SecBlockNum2 << 4) & 0x00F0)); - MsgBuffer[5] = (DSP_WORD) pPortConfig->FirstSlotMask2; - MsgBuffer[6] = (DSP_WORD) pPortConfig->SecSlotMask2; - MsgBuffer[7] = (DSP_WORD) - ((pPortConfig->SlotsSelect3 << 12) | - ((pPortConfig->FirstBlockNum3 << 8) & 0x0F00) | - ((pPortConfig->SecBlockNum3 << 4) & 0x00F0)); - MsgBuffer[8] = (DSP_WORD) pPortConfig->FirstSlotMask3; - MsgBuffer[9] = (DSP_WORD) pPortConfig->SecSlotMask3; - - MsgBuffer[10] = (DSP_WORD) - (((pPortConfig->DxDelay1 << 11) & 0x0800) | - ((pPortConfig->RxDataDelay1 << 9) & 0x0600) | - ((pPortConfig->TxDataDelay1 << 7) & 0x0180) | - ((pPortConfig->RxClockPolarity1 << 6) & 0x0040) | - ((pPortConfig->TxClockPolarity1 << 5) & 0x0020) | - ((pPortConfig->RxFrameSyncPolarity1 << 4) & 0x0010) | - ((pPortConfig->TxFrameSyncPolarity1 << 3) & 0x0008) | - ((pPortConfig->CompandingMode1 << 1) & 0x0006) | - (pPortConfig->SerialWordSize1 & 0x0001)); - - MsgBuffer[11] = (DSP_WORD) - (((pPortConfig->DxDelay2 << 11) & 0x0800) | - ((pPortConfig->RxDataDelay2 << 9) & 0x0600) | - ((pPortConfig->TxDataDelay2 << 7) & 0x0180) | - ((pPortConfig->RxClockPolarity2 << 6) & 0x0040) | - ((pPortConfig->TxClockPolarity2 << 5) & 0x0020) | - ((pPortConfig->RxFrameSyncPolarity2 << 4) & 0x0010) | - ((pPortConfig->TxFrameSyncPolarity2 << 3) & 0x0008) | - ((pPortConfig->CompandingMode2 << 1) & 0x0006) | - (pPortConfig->SerialWordSize1 & 0x0001)); - - MsgBuffer[12] = (DSP_WORD) - (((pPortConfig->DxDelay3 << 11) & 0x0800) | - ((pPortConfig->RxDataDelay3 << 9) & 0x0600) | - ((pPortConfig->TxDataDelay3 << 7) & 0x0180) | - ((pPortConfig->RxClockPolarity3 << 6) & 0x0040) | - ((pPortConfig->TxClockPolarity3 << 5) & 0x0020) | - ((pPortConfig->RxFrameSyncPolarity3 << 4) & 0x0010) | - ((pPortConfig->TxFrameSyncPolarity3 << 3) & 0x0008) | - ((pPortConfig->CompandingMode3 << 1) & 0x0006) | - (pPortConfig->SerialWordSize3 & 0x0001)); - - MsgBuffer[13] = (DSP_WORD) pPortConfig->ThirdSlotMask1; - MsgBuffer[14] = (DSP_WORD) pPortConfig->FouthSlotMask1; - MsgBuffer[15] = (DSP_WORD) pPortConfig->FifthSlotMask1; - MsgBuffer[16] = (DSP_WORD) pPortConfig->SixthSlotMask1; - MsgBuffer[17] = (DSP_WORD) pPortConfig->SevenSlotMask1; - MsgBuffer[18] = (DSP_WORD) pPortConfig->EightSlotMask1; - - MsgBuffer[19] = (DSP_WORD) pPortConfig->ThirdSlotMask2;; - MsgBuffer[20] = (DSP_WORD) pPortConfig->FouthSlotMask2; - MsgBuffer[21] = (DSP_WORD) pPortConfig->FifthSlotMask2;; - MsgBuffer[22] = (DSP_WORD) pPortConfig->SixthSlotMask2; - MsgBuffer[23] = (DSP_WORD) pPortConfig->SevenSlotMask2;; - MsgBuffer[24] = (DSP_WORD) pPortConfig->EightSlotMask2; - - MsgBuffer[25] = (DSP_WORD) pPortConfig->ThirdSlotMask3;; - MsgBuffer[26] = (DSP_WORD) pPortConfig->FouthSlotMask3; - MsgBuffer[27] = (DSP_WORD) pPortConfig->FifthSlotMask3;; - MsgBuffer[28] = (DSP_WORD) pPortConfig->SixthSlotMask3; - MsgBuffer[29] = (DSP_WORD) pPortConfig->SevenSlotMask3;; - MsgBuffer[30] = (DSP_WORD) pPortConfig->EightSlotMask3; - - - /* Attempt to send the Configure Serial Ports message to the DSP and receive - it's reply. */ - if (!TransactCmd(DspId, MsgBuffer, 62, MSG_CONFIG_PORTS_REPLY, 4, 0, 0)) - return (CpsDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - *pStatus = (GPAK_PortConfigStat_t) (MsgBuffer[1] & 0xFF); - if (*pStatus == Pc_Success) - return (CpsSuccess); - else - return (CpsParmError); -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakConfigureChannel - Configure a DSP's Channel. - * - * FUNCTION - * This function configures a DSP's Channel. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakConfigChanStatus_t gpakConfigureChannel( - unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ - unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ - GpakChanType ChannelType, /* Channel Type */ - GpakChannelConfig_t *pChanConfig, /* pointer to Channel Config info */ - GPAK_ChannelConfigStat_t *pStatus /* pointer to Channel Config Status */ - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD MsgLength; /* message length */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (CcsInvalidDsp); - - /* Make sure the Channel Id is valid. */ - if (ChannelId >= MaxChannels[DspId]) - return (CcsInvalidChannel); - - /* Build the Configure Channel message based on the Channel Type. */ - switch (ChannelType) - { - - /* PCM to Packet channel type. */ - case tdmToTdm: - - MsgBuffer[2] = (DSP_WORD) - ((pChanConfig->PcmInPortA << 8) | - (pChanConfig->PcmInSlotA & 0xFF)); - MsgBuffer[3] = (DSP_WORD) - ((pChanConfig->PcmOutPortA << 8) | - (pChanConfig->PcmOutSlotA & 0xFF)); - - MsgBuffer[4] = (DSP_WORD) - ((pChanConfig->PcmInPortB << 8) | - (pChanConfig->PcmInSlotB & 0xFF)); - MsgBuffer[5] = (DSP_WORD) - ((pChanConfig->PcmOutPortB << 8) | - (pChanConfig->PcmOutSlotB & 0xFF)); - - MsgBuffer[6] = (DSP_WORD) - ( - ((pChanConfig->FaxCngDetB <<11) & 0x0800) | - ((pChanConfig->FaxCngDetA <<10) & 0x0400) | - ((pChanConfig->MuteToneB << 9) & 0x0200) | - ((pChanConfig->MuteToneA << 8) & 0x0100) | - ((pChanConfig->FrameRate << 6) & 0x00C0) | - ((pChanConfig->ToneTypesB << 5) & 0x0020) | - ((pChanConfig->ToneTypesA << 4) & 0x0010) | - ((pChanConfig->SoftwareCompand & 3) << 2) | - (pChanConfig->EcanEnableB << 1) | - (pChanConfig->EcanEnableA & 1) - ); - - MsgBuffer[7] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanTapLength; - MsgBuffer[8] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNlpType; - MsgBuffer[9] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanAdaptEnable; - MsgBuffer[10] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanG165DetEnable; - MsgBuffer[11] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanDblTalkThresh; - MsgBuffer[12] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNlpThreshold; - MsgBuffer[13] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNlpConv; - MsgBuffer[14] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNlpUnConv; - MsgBuffer[15] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNlpMaxSuppress; - - MsgBuffer[16] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanCngThreshold; - MsgBuffer[17] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanAdaptLimit; - MsgBuffer[18] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanCrossCorrLimit; - MsgBuffer[19] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanNumFirSegments; - MsgBuffer[20] = (DSP_WORD) - pChanConfig->EcanParametersA.EcanFirSegmentLen; - - MsgBuffer[21] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanTapLength; - MsgBuffer[22] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNlpType; - MsgBuffer[23] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanAdaptEnable; - MsgBuffer[24] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanG165DetEnable; - MsgBuffer[25] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanDblTalkThresh; - MsgBuffer[26] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNlpThreshold; - MsgBuffer[27] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNlpConv; - MsgBuffer[28] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNlpUnConv; - MsgBuffer[29] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNlpMaxSuppress; - MsgBuffer[30] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanCngThreshold; - MsgBuffer[31] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanAdaptLimit; - MsgBuffer[32] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanCrossCorrLimit; - MsgBuffer[33] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanNumFirSegments; - MsgBuffer[34] = (DSP_WORD) - pChanConfig->EcanParametersB.EcanFirSegmentLen; - - MsgLength = 70; // byte number == 35*2 - break; - - - /* Unknown (invalid) channel type. */ - default: - *pStatus = Cc_InvalidChannelType; - return (CcsParmError); - } - - MsgBuffer[0] = MSG_CONFIGURE_CHANNEL << 8; - MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ChannelType & 0xFF)); - - /* Attempt to send the Configure Channel message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, MsgLength, MSG_CONFIG_CHAN_REPLY, 4, 1, - (DSP_WORD) ChannelId)) - return (CcsDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - *pStatus = (GPAK_ChannelConfigStat_t) (MsgBuffer[1] & 0xFF); - if (*pStatus == Cc_Success) - return (CcsSuccess); - else - return (CcsParmError); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakTearDownChannel - Tear Down a DSP's Channel. - * - * FUNCTION - * This function tears down a DSP's Channel. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakTearDownStatus_t gpakTearDownChannel( - unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ - unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ - GPAK_TearDownChanStat_t *pStatus /* pointer to Tear Down Status */ - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (TdsInvalidDsp); - - /* Make sure the Channel Id is valid. */ - if (ChannelId >= MaxChannels[DspId]) - return (TdsInvalidChannel); - - /* Build the Tear Down Channel message. */ - MsgBuffer[0] = MSG_TEAR_DOWN_CHANNEL << 8; - MsgBuffer[1] = (DSP_WORD) (ChannelId << 8); - - /* Attempt to send the Tear Down Channel message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, 3, MSG_TEAR_DOWN_REPLY, 4, 1, - (DSP_WORD) ChannelId)) - return (TdsDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - *pStatus = (GPAK_TearDownChanStat_t) (MsgBuffer[1] & 0xFF); - if (*pStatus == Td_Success) - return (TdsSuccess); - else - return (TdsError); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAlgControl - Control an Algorithm. - * - * FUNCTION - * This function controls an Algorithm - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakAlgControlStat_t gpakAlgControl( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GpakAlgCtrl_t ControlCode, // algorithm control code - GPAK_AlgControlStat_t *pStatus // pointer to return status - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (AcInvalidDsp); - - /* Make sure the Channel Id is valid. */ - if (ChannelId >= MaxChannels[DspId]) - return (AcInvalidChannel); - - MsgBuffer[0] = MSG_ALG_CONTROL << 8; - MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ControlCode & 0xFF)); - - /* Attempt to send the Tear Down Channel message to the DSP and receive it's - reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ALG_CONTROL_REPLY, 4, 1, - (DSP_WORD) ChannelId)) - return (AcDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - *pStatus = (GPAK_AlgControlStat_t) (MsgBuffer[1] & 0xFF); - if (*pStatus == Ac_Success) - return (AcSuccess); - else - return (AcParmError); - -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadEventFIFOMessage - read from the event fifo - * - * FUNCTION - * This function reads a single event from the event fifo if one is available - * - * RETURNS - * Status code indicating success or a specific error. - * - * Notes: This function should be called in a loop until the return status - * indicates that the fifo is empty. - * - * If the event code equals "EventLoopbackTeardownComplete", then the - * contents of *pChannelId hold the coderBlockId that was assigned to - * the loopback coder that was torn down. - */ -gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( - unsigned short int DspId, // DSP identifier - unsigned short int *pChannelId, // pointer to channel identifier - GpakAsyncEventCode_t *pEventCode, // pointer to Event Code - GpakAsyncEventData_t *pEventData // pointer to Event Data Struct - ) -{ - DSP_WORD WordBuffer[WORD_BUFFER_SIZE]; /* DSP words buffer */ - GpakAsyncEventCode_t EventCode; /* DSP's event code */ - DSP_WORD EventDataLength; /* Length of event to read */ - DSP_WORD ChannelId; /* DSP's channel Id */ - DSP_ADDRESS EventInfoAddress; /* address of EventFIFO info structure */ - DSP_ADDRESS BufrBaseAddress; /* base address of EventFIFO buffer */ - DSP_ADDRESS BufrLastAddress; /* last address of EventFIFO buffer */ - DSP_ADDRESS TakeAddress; /* current take address in fifo buffer */ - DSP_WORD BufrSize; /* size (in words) of event FIFO buffer */ - DSP_WORD PutIndex; /* event fifo put index */ - DSP_WORD TakeIndex; /* event fifo take index */ - DSP_WORD WordsReady; /* number words ready for read out of event fifo */ - DSP_WORD EventError; /* flag indicating error with event fifo msg */ - //DSP_WORD *pDebugData; /* debug data buffer pointer in event data struct */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RefInvalidDsp); - - /* Lock access to the DSP. */ - gpakLockAccess(DspId); - - /* Check if the DSP was reset and is ready. */ - if (CheckDspReset(DspId) == -1) - { - gpakUnlockAccess(DspId); - return (RefDspCommFailure); - } - - /* Check if an event message is ready in the DSP. */ - EventInfoAddress = pEventFifoAddress[DspId]; - gpakReadDspMemory(DspId, EventInfoAddress, CIRC_BUFFER_INFO_STRUCT_SIZE, - WordBuffer); - RECONSTRUCT_LONGWORD(BufrBaseAddress, ((DSP_WORD *)&WordBuffer[CB_BUFR_BASE])); - BufrSize = WordBuffer[CB_BUFR_SIZE]; - PutIndex = WordBuffer[CB_BUFR_PUT_INDEX]; - TakeIndex = WordBuffer[CB_BUFR_TAKE_INDEX]; - if (PutIndex >= TakeIndex) - WordsReady = PutIndex - TakeIndex; - else - WordsReady = PutIndex + BufrSize - TakeIndex; - - if (WordsReady < 2) - { - gpakUnlockAccess(DspId); - return (RefNoEventAvail); - } - - /* Read the event header from the DSP's Event FIFO. */ - TakeAddress = BufrBaseAddress + TakeIndex; - BufrLastAddress = BufrBaseAddress + BufrSize - 1; - ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, - WordBuffer, 2); - TakeIndex += 2; - if (TakeIndex >= BufrSize) - TakeIndex -= BufrSize; - - ChannelId = (WordBuffer[0] >> 8) & 0xFF; - EventCode = (GpakAsyncEventCode_t)(WordBuffer[0] & 0xFF); - EventDataLength = WordBuffer[1]; - EventError = 0; - - switch (EventCode) - { - case EventToneDetect: - if (EventDataLength > WORD_BUFFER_SIZE) - { - gpakUnlockAccess(DspId); - return (RefInvalidEvent); - } - ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, - WordBuffer, EventDataLength); - pEventData->toneEvent.ToneCode = (GpakToneCodes_t) - (WordBuffer[0] & 0xFF); - pEventData->toneEvent.ToneDuration = WordBuffer[1]; - pEventData->toneEvent.Direction = WordBuffer[2]; - pEventData->toneEvent.DebugToneStatus = WordBuffer[3]; - TakeIndex += EventDataLength; - if (TakeIndex >= BufrSize) - TakeIndex -= BufrSize; - if (EventDataLength != 4) - EventError = 1; - break; - - default: - EventError = 1; - break; - }; - - /* Update the Take index in the DSP's Packet Out buffer information. */ - gpakWriteDspMemory(DspId, EventInfoAddress + CB_BUFR_TAKE_INDEX, 1, - &TakeIndex); - - /* Unlock access to the DSP. */ - gpakUnlockAccess(DspId); - - if (EventError) - return(RefInvalidEvent); - - *pChannelId = ChannelId; - *pEventCode = EventCode; - return(RefEventAvail); - -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakPingDsp - ping the DSP to see if it's alive - * - * FUNCTION - * This function checks if the DSP is still communicating with the host - * and returns the DSP SW version - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakPingDspStat_t gpakPingDsp( - unsigned short int DspId, // DSP identifier - unsigned short int *pDspSwVersion // DSP software version - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (PngInvalidDsp); - - /* send value of 1, DSP increments it */ - MsgBuffer[0] = (MSG_PING << 8); - - /* Attempt to send the ping message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, 1, MSG_PING_REPLY, 6, 0, 0)) - return (PngDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - { - *pDspSwVersion = MsgBuffer[2]; - return (PngSuccess); - } - else - return (PngDspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakSerialTxFixedValue - transmit a fixed value on a timeslot - * - * FUNCTION - * This function controls transmission of a fixed value out onto a serial - * port's timeslot. - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id - unsigned short int PcmOutSlot, // PCM Output Time Slot - unsigned short int Value, // 16-bit value - GpakActivation State // activation state - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (TfvInvalidDsp); - - /* Make sure the Channel Id is valid. */ - if (ChannelId >= MaxChannels[DspId]) - return (TfvInvalidChannel); - - - /* Build the message. */ - MsgBuffer[0] = MSG_SERIAL_TXVAL << 8; - MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (State & 0xFF)); - MsgBuffer[2] = (DSP_WORD) ((PcmOutPort << 8) | (PcmOutSlot & 0xFF)); - MsgBuffer[3] = (DSP_WORD) Value; - - /* Attempt to send the message to the DSP and receive it's - reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 8, MSG_SERIAL_TXVAL_REPLY, 4, - 1, ChannelId)) - return (TfvDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - return (TfvSuccess); - else - return (TfvDspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakControlTdmLoopBack - control a serial port's loopback state - * - * FUNCTION - * This function enables/disables the tdm input to output looback mode on a - * serial port - * - * RETURNS - * Status code indicating success or a specific error. - */ - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ -gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( - unsigned short int DspId, // DSP identifier - GpakSerialPort_t SerialPort, // Serial Port Id - GpakActivation LoopBackState // Loopback State - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (ClbInvalidDsp); - - /* Build the message. */ - MsgBuffer[0] = MSG_TDM_LOOPBACK << 8; - MsgBuffer[1] = (DSP_WORD) ((SerialPort << 8) | (LoopBackState & 0xFF)); - - /* Attempt to send the message to the DSP and receive it's - reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 4, MSG_TDM_LOOPBACK_REPLY, 4, 0, 0)) - return (ClbDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - return (ClbSuccess); - else - return (ClbDspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - Read CPU usage statistics from a DSP. - * - * FUNCTION - * This function reads the CPU usage statistics from a DSP's memory. The - * average CPU usage in units of .1 percent are obtained for each of the frame - * rates. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakReadCpuUsageStat_t gpakReadCpuUsage( - unsigned short int DspId, // Dsp Identifier - unsigned short int *pPeakUsage, // pointer to peak usage variable - unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second - ) -{ - DSP_WORD ReadBuffer[2]; /* DSP read buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RcuInvalidDsp); - - /* Lock access to the DSP. */ - gpakLockAccess(DspId); - - /* Check if the DSP was reset and is ready. */ - if (CheckDspReset(DspId) == -1) - return (RcuDspCommFailure); - - /* Read the CPU Usage statistics from the DSP. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CPU_USAGE_OFFSET, 2, - ReadBuffer); - - /* Unlock access to the DSP. */ - gpakUnlockAccess(DspId); - - /* Store the usage statistics in the specified variables. */ - *pPrev1SecPeakUsage = ReadBuffer[0]; - *pPeakUsage = ReadBuffer[1]; - - /* Return with an indication the usage staistics were read successfully. */ - return (RcuSuccess); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetCpuUsageStats - reset the cpu usage statistics - * - * FUNCTION - * This function resets the cpu utilization statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakResetCpuUsageStat_t gpakResetCpuUsageStats( - unsigned short int DspId // DSP identifier - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RstcInvalidDsp); - - MsgBuffer[0] = (MSG_RESET_USAGE_STATS << 8); - - /* Attempt to send the message to the DSP and receive it's reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_USAGE_STATS_REPLY, 4, 0, 0)) - return (RstcDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - return (RstcSuccess); - else - return (RstcDspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFramingStats - * - * FUNCTION - * This function reads a DSP's framing interrupt statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakReadFramingStatsStatus_t gpakReadFramingStats( - unsigned short int DspId, // DSP identifier - unsigned short int *pFramingError1Count, // port 1 Framing error count - unsigned short int *pFramingError2Count, // port 2 Framing error count - unsigned short int *pFramingError3Count, // port 3 Framing error count - unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count - unsigned short int *pDmaSlipStatsBuffer // DMA slips count - ) -{ - DSP_WORD ReadBuffer[10]; /* DSP read buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RfsInvalidDsp); - - /* Lock access to the DSP. */ - gpakLockAccess(DspId); - - /* Check if the DSP was reset and is ready. */ - if (CheckDspReset(DspId) == -1) - return (RfsDspCommFailure); - - /* Read the framing interrupt statistics from the DSP. */ - gpakReadDspMemory(DspId, pDspIfBlk[DspId] + FRAMING_STATS_OFFSET, 10, - ReadBuffer); - - /* Unlock access to the DSP. */ - gpakUnlockAccess(DspId); - - /* Store the framing statistics in the specified variables. */ - *pFramingError1Count = ReadBuffer[0]; - *pFramingError2Count = ReadBuffer[1]; - *pFramingError3Count = ReadBuffer[2]; - *pDmaStopErrorCount = ReadBuffer[3]; - - if(pDmaSlipStatsBuffer != 0) - // If users want to get the DMA slips count - { - pDmaSlipStatsBuffer[0] = ReadBuffer[4]; - pDmaSlipStatsBuffer[1] = ReadBuffer[5]; - pDmaSlipStatsBuffer[2] = ReadBuffer[6]; - pDmaSlipStatsBuffer[3] = ReadBuffer[7]; - pDmaSlipStatsBuffer[4] = ReadBuffer[8]; - pDmaSlipStatsBuffer[5] = ReadBuffer[9]; - - } - /* Return with an indication the statistics were read successfully. */ - return (RfsSuccess); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - reset a DSP's framing interrupt statistics - * - * FUNCTION - * This function resets a DSP's framing interrupt statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakResetFramingStatsStatus_t gpakResetFramingStats( - unsigned short int DspId // DSP identifier - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RstfInvalidDsp); - - MsgBuffer[0] = (MSG_RESET_FRAME_STATS << 8); - - /* Attempt to send the message to the DSP and receive it's reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_FRAME_STATS_REPLY, 4, 0, 0)) - return (RstfDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - return (RstfSuccess); - else - return (RstfDspCommFailure); -} - -/* - * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. - * - * FUNCTION - * This function reads a DSP's Program and Data memory image from the - * specified file and writes the image to the DSP's memory. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakDownloadStatus_t gpakDownloadDsp( - unsigned short DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ - GPAK_FILE_ID FileId /* G.PAK Download File Identifier */ - ) -{ - gpakDownloadStatus_t RetStatus; /* function return status */ - int NumRead; /* number of file bytes read */ - DSP_ADDRESS Address; /* DSP address */ - unsigned int WordCount; /* number of words in record */ - unsigned int NumWords; /* number of words to read/write */ - unsigned int i; /* loop index / counter */ - unsigned int j; /* loop index */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (GdlInvalidDsp); - - /* Lock access to the DSP. */ - gpakLockAccess(DspId); - - RetStatus = GdlSuccess; - while (RetStatus == GdlSuccess) - { - - /* Read a record header from the file. */ - NumRead = gpakReadFile(FileId, DlByteBufr, 6); - if (NumRead == -1) - { - RetStatus = GdlFileReadError; - break; - } - if (NumRead != 6) - { - RetStatus = GdlInvalidFile; - break; - } - Address = (((DSP_ADDRESS) DlByteBufr[1]) << 16) | - (((DSP_ADDRESS) DlByteBufr[2]) << 8) | - ((DSP_ADDRESS) DlByteBufr[3]); - WordCount = (((unsigned int) DlByteBufr[4]) << 8) | - ((unsigned int) DlByteBufr[5]); - - /* Check for the End Of File record. */ - if (DlByteBufr[0] == 0xFF) - break; - - /* Verify the record is for a valid memory type. */ - if ((DlByteBufr[0] != 0x00) && (DlByteBufr[0] != 0x01)) - { - RetStatus = GdlInvalidFile; - break; - } - - /* Read a block of words at a time from the file and write to the - DSP's memory .*/ - while (WordCount != 0) - { - if (WordCount < DOWNLOAD_BLOCK_SIZE) - NumWords = WordCount; - else - NumWords = DOWNLOAD_BLOCK_SIZE; - WordCount -= NumWords; - NumRead = gpakReadFile(FileId, DlByteBufr, NumWords * 2); - if (NumRead == -1) - { - RetStatus = GdlFileReadError; - break; - } - if (NumRead != (NumWords * 2)) - { - RetStatus = GdlInvalidFile; - break; - } - for (i = 0, j = 0; i < NumWords; i++, j += 2) - DlWordBufr[i] = (((DSP_WORD) DlByteBufr[j]) << 8) | - ((DSP_WORD) DlByteBufr[j + 1]); - gpakWriteDspMemory(DspId, Address, NumWords, DlWordBufr); - Address += ((DSP_ADDRESS) NumWords); - } - } - - /* Unlock access to the DSP. */ - gpakUnlockAccess(DspId); - - /* Return with an indication of success or failure. */ - return (RetStatus); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - Read CPU usage statistics from a DSP. - * - * FUNCTION - * This function reads the memory map register section of DSP memory. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( - unsigned short int DspId, // Dsp Identifier - unsigned short int *pDest, // Buffer on host to hold DSP memory map - DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out - unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP reply's status */ - int i; /* loop index / counter */ - - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RmmInvalidDsp); - - /* Verify the message buffer is large enough */ - if (MSG_BUFFER_SIZE < MemoryLength_Word16 ) - return (RmmSizeTooBig); - - MsgBuffer[0] = MSG_READ_DSP_MEMORY << 8; - MsgBuffer[1] = (DSP_WORD) ((BufrBaseAddress >> 16) & 0xFFFF); - MsgBuffer[2] = (DSP_WORD) (BufrBaseAddress & 0xFFFF); - MsgBuffer[3] = (DSP_WORD) MemoryLength_Word16; - - /* Attempt to send the Read memory section message to the DSP and receive it's - reply. */ - //need_reply_len; - if (!TransactCmd(DspId, MsgBuffer, 8, MSG_READ_DSP_MEMORY_REPLY, - (MemoryLength_Word16+2)*2, 0, 0) ) - return (RmmInvalidAddress); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus != 0) - return (RmmFailure); - - for (i = 0; i < MemoryLength_Word16; i++) - pDest[i] = (short int) MsgBuffer[2 + i]; - - - return (RmmSuccess); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAccessGPIO - change Direction/read/write the GPIO on DSP - * - * FUNCTION - * This function read/write GPIO and change the GPIO direction - * - * - * RETURNS - * Status code indicating success or a specific error. - */ -gpakAccessGPIOStat_t gpakAccessGPIO( - unsigned short int DspId, // DSP identifier - GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read - unsigned short int *pGPIOValue // DSP software version - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (GPIOInvalidDsp); - - /* send value of 1, DSP increments it */ - MsgBuffer[0] = (MSG_ACCESSGPIO << 8); - MsgBuffer[1] = (DSP_WORD) ((gpakControlGPIO << 8) | (*pGPIOValue & 0xFF) ); - /* Attempt to send the ping message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ACCESSGPIO_REPLY, 6, 0, 0)) - return (GPIODspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - { - *pGPIOValue = MsgBuffer[2]; - return (GPIOSuccess); - } - else - return (GPIODspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakWriteSystemParms - Write a DSP's System Parameters. - * - * FUNCTION - * This function writes a DSP's System Parameters information. - * - * Note: - * Or-together the desired bit-mask #defines that are listed below. Only - * those algorithm parameters whose bit-mask is selected in the UpdateBits - * function parameter will be updated. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ - -gpakWriteSysParmsStatus_t gpakWriteSystemParms( - unsigned short int DspId, // DSP identifier - GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ - unsigned short int UpdateBits, /* input: flags indicating which parms to update */ - GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ - ) -{ - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - DSP_WORD DspStatus; /* DSP's reply status */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (WspInvalidDsp); - - /* Build the Write System Parameters message. */ - MsgBuffer[0] = MSG_WRITE_SYS_PARMS << 8; - - if (UpdateBits & DTMF_UPDATE_MASK) - { - MsgBuffer[1] |= DTMF_UPDATE_MASK; - MsgBuffer[8] = (DSP_WORD) pSysParms->MinSigLevel; - MsgBuffer[9] = (DSP_WORD) (pSysParms->FreqDeviation & 0xff); - if (pSysParms->SNRFlag) - MsgBuffer[9] |= (1<<8); - } - - MsgBuffer[10] = (DSP_WORD) 0; - if (UpdateBits & DTMF_TWIST_UPDATE_MASK) - { - MsgBuffer[1] |= DTMF_TWIST_UPDATE_MASK; - MsgBuffer[10] |= (DSP_WORD) (pSysParms->DtmfFwdTwist & 0x000f); - MsgBuffer[10] |= (DSP_WORD) ((pSysParms->DtmfRevTwist << 4) & 0x00f0); - } - - - if (UpdateBits & DTMF_VALID_MASK) - { - MsgBuffer[1] |= DTMF_VALID_MASK; - MsgBuffer[11] = (DSP_WORD) (pSysParms->DtmfValidityMask & 0x00ff); - } - - /* Attempt to send the ping message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, 24, MSG_WRITE_SYS_PARMS_REPLY, 6, 0, 0)) - return (WspDspCommFailure); - - /* Return with an indication of success or failure based on the return - status in the reply message. */ - *pStatus = (GPAK_SysParmsStat_t) (MsgBuffer[2] ); - - DspStatus = (MsgBuffer[1] & 0xFF); - if (DspStatus == 0) - return (WspSuccess); - else - return (WspDspCommFailure); -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadSystemParms - Read a DSP's System Parameters. - * - * FUNCTION - * This function reads a DSP's System Parameters information. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -gpakReadSysParmsStatus_t gpakReadSystemParms( - unsigned short int DspId, // DSP identifier - GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ - ) -{ - - DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ - - /* Make sure the DSP Id is valid. */ - if (DspId >= MAX_DSP_CORES) - return (RspInvalidDsp); - - /* Build the Read System Parameters message. */ - MsgBuffer[0] = MSG_READ_SYS_PARMS << 8; - - /* Attempt to send the ping message to the DSP and receive it's - reply. */ - if (!TransactCmd(DspId, MsgBuffer, 2, MSG_READ_SYS_PARMS_REPLY, 22, 0, 0)) - return (RspDspCommFailure); - - /* Extract the System Parameters information from the message. */ - pSysParms->DtmfValidityMask = (short int)(MsgBuffer[7]) ; - - pSysParms->MinSigLevel = (short int)MsgBuffer[8]; - pSysParms->SNRFlag = (short int)((MsgBuffer[9]>>8) & 0x1); - pSysParms->FreqDeviation = (short int)(MsgBuffer[9] & 0xff); - pSysParms->DtmfFwdTwist = (short int)MsgBuffer[10] & 0x000f; - pSysParms->DtmfRevTwist = (short int)(MsgBuffer[10] >> 4) & 0x000f; - - /* Return with an indication that System Parameters info was obtained. */ - return (RspSuccess); -} -#endif diff --git a/wcte12xp/GpakApi.h b/wcte12xp/GpakApi.h deleted file mode 100644 index e676b32..0000000 --- a/wcte12xp/GpakApi.h +++ /dev/null @@ -1,637 +0,0 @@ -/* - * Copyright (c) 2005 , Adaptive Digital Technologies, Inc. - * - * File Name: GpakApi.h - * - * Description: - * This file contains the function prototypes and data types for the user - * API functions that communicate with DSPs executing G.PAK software. The - * file is used by application software in the host processor connected to - * C55X G.PAK DSPs via a Host Port Interface. - * - * Version: 1.0 - * - * Revision History: - * 06/15/05 - Initial release. - * 11/15/2006 - 24 TDM-TDM Channels EC release - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. The standard - * GPL disclaimer is given inline below for your convenience. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _GPAKAPI_H /* prevent multiple inclusion */ -#define _GPAKAPI_H -#include "GpakErrs.h" -#include "gpakenum.h" - -// Bit masks to select which algorithm's parameters to update: Or-together the -// desired masks into the UpdateBits function parameter. -#define DTMF_UPDATE_MASK 0x0010 // update DTMF params, MinLevel, SNRFlag and Freq -#define DTMF_TWIST_UPDATE_MASK 0x0020 // update DTMF TWIST system params -#define DTMF_VALID_MASK 0x0080 // update DTMF ValidMask params - -#define DSP_DEBUG_BUFF_SIZE 42 // units of 16-bit words - -/* Definition of an Asynchronous Event Data Structure */ -typedef union -{ - struct - { - GpakToneCodes_t ToneCode; // detected tone code - unsigned short int ToneDuration; // tone duration - GpakTdmDirection Direction; // detected on A r B side - short int DebugToneStatus;// reserved for debug info - } toneEvent; - -} GpakAsyncEventData_t; - -/* Definition of an Echo Canceller Parameters information structure. */ -typedef struct -{ - short int EcanTapLength; // Echo Can Num Taps (tail length) - short int EcanNlpType; // Echo Can NLP Type - short int EcanAdaptEnable; // Echo Can Adapt Enable flag - short int EcanG165DetEnable; // Echo Can G165 Detect Enable flag - short int EcanDblTalkThresh; // Echo Can Double Talk threshold - short int EcanNlpThreshold; // Echo Can NLP threshold - short int EcanNlpConv; // Dynamic NLP control, NLP limit when EC about to converged - short int EcanNlpUnConv;// Dynamic NLP control, NLP limit when EC not converged yet - short int EcanNlpMaxSuppress; // suppression level for NLP_SUPP mode - short int EcanCngThreshold; // Echo Can CNG Noise threshold - short int EcanAdaptLimit; // Echo Can Max Adapts per frame - short int EcanCrossCorrLimit; // Echo Can Cross Correlation limit - short int EcanNumFirSegments; // Echo Can Num FIR Segments - short int EcanFirSegmentLen; // Echo Can FIR Segment Length -} GpakEcanParms_t; - -/* Definition of a Channel Configuration information structure. */ -typedef struct -{ - GpakSerialPort_t PcmInPortA; // A side PCM Input Serial Port Id - unsigned short int PcmInSlotA; // A side PCM Input Time Slot - GpakSerialPort_t PcmOutPortA; // A side PCM Output Serial Port Id - unsigned short int PcmOutSlotA; // A side PCM Output Time Slot - GpakSerialPort_t PcmInPortB; // B side PCM Input Serial Port Id - unsigned short int PcmInSlotB; // B side PCM Input Time Slot - GpakSerialPort_t PcmOutPortB; // B side PCM Output Serial Port Id - unsigned short int PcmOutSlotB; // B side PCM Output Time Slot - GpakToneTypes ToneTypesA; // A side Tone Detect Types - GpakToneTypes ToneTypesB; // B side Tone Detect Types - GpakActivation EcanEnableA; // Echo Cancel A Enabled - GpakActivation EcanEnableB; // Echo Cancel B Enabled - GpakEcanParms_t EcanParametersA; // Echo Cancel parameters - GpakEcanParms_t EcanParametersB; // Echo Cancel parameters - GpakCompandModes SoftwareCompand; // software companding - GpakRate_t FrameRate; // Gpak Frame Rate - GpakActivation MuteToneA; // A side mute DTMF Enabled - GpakActivation MuteToneB; // B side mute DTMF Enabled - GpakActivation FaxCngDetA; // A side FaxCng Tone Detector Enabled - GpakActivation FaxCngDetB; // B side FaxCng Tone Detector Enabled - -} GpakChannelConfig_t; - - -/* Definition of a Serial Port Configuration Structure */ -typedef struct -{ - GpakSlotCfg_t SlotsSelect1; // port 1 Slot selection - unsigned short int FirstBlockNum1; // port 1 first group Block Number - unsigned short int FirstSlotMask1; // port 1 first group Slot Mask - unsigned short int SecBlockNum1; // port 1 second group Block Number - unsigned short int SecSlotMask1; // port 1 second group Slot Mask - - GpakSerWordSize_t SerialWordSize1; // port 1 serial word size - GpakCompandModes CompandingMode1; // port 1 companding mode - GpakSerFrameSyncPol_t TxFrameSyncPolarity1; // port 1 Tx Frame Sync Polarity - GpakSerFrameSyncPol_t RxFrameSyncPolarity1; // port 1 Rx Frame Sync Polarity - GpakSerClockPol_t TxClockPolarity1; // port 1 Tx Clock Polarity - GpakSerClockPol_t RxClockPolarity1; // port 1 Rx Clock Polarity - GpakSerDataDelay_t TxDataDelay1; // port 1 Tx data delay - GpakSerDataDelay_t RxDataDelay1; // port 1 Rx data delay - GpakActivation DxDelay1; // port 1 DX Delay - - unsigned short int ThirdSlotMask1; // port 1 3rd group Slot Mask - unsigned short int FouthSlotMask1; // port 1 4th group Slot Mask - unsigned short int FifthSlotMask1; // port 1 5th group Slot Mask - unsigned short int SixthSlotMask1; // port 1 6th group Slot Mask - unsigned short int SevenSlotMask1; // port 1 7th group Slot Mask - unsigned short int EightSlotMask1; // port 1 8th group Slot Mask - - - GpakSlotCfg_t SlotsSelect2; // port 2 Slot selection - unsigned short int FirstBlockNum2; // port 2 first group Block Number - unsigned short int FirstSlotMask2; // port 2 first group Slot Mask - unsigned short int SecBlockNum2; // port 2 second group Block Number - unsigned short int SecSlotMask2; // port 2 second group Slot Mask - GpakSerWordSize_t SerialWordSize2; // port 2 serial word size - GpakCompandModes CompandingMode2; // port 2 companding mode - GpakSerFrameSyncPol_t TxFrameSyncPolarity2; // port 2 Tx Frame Sync Polarity - GpakSerFrameSyncPol_t RxFrameSyncPolarity2; // port 2 Rx Frame Sync Polarity - GpakSerClockPol_t TxClockPolarity2; // port 2 Tx Clock Polarity - GpakSerClockPol_t RxClockPolarity2; // port 2 Rx Clock Polarity - GpakSerDataDelay_t TxDataDelay2; // port 2 Tx data delay - GpakSerDataDelay_t RxDataDelay2; // port 2 Rx data delay - GpakActivation DxDelay2; // port 2 DX Delay - - unsigned short int ThirdSlotMask2; // port 2 3rd group Slot Mask - unsigned short int FouthSlotMask2; // port 2 4th group Slot Mask - unsigned short int FifthSlotMask2; // port 2 5th group Slot Mask - unsigned short int SixthSlotMask2; // port 2 6th group Slot Mask - unsigned short int SevenSlotMask2; // port 2 7th group Slot Mask - unsigned short int EightSlotMask2; // port 2 8th group Slot Mask - - GpakSlotCfg_t SlotsSelect3; // port 3 Slot selection - unsigned short int FirstBlockNum3; // port 3 first group Block Number - unsigned short int FirstSlotMask3; // port 3 first group Slot Mask - unsigned short int SecBlockNum3; // port 3 second group Block Number - unsigned short int SecSlotMask3; // port 3 second group Slot Mask - GpakSerWordSize_t SerialWordSize3; // port 3 serial word size - GpakCompandModes CompandingMode3; // port 3 companding mode - GpakSerFrameSyncPol_t TxFrameSyncPolarity3; // port 3 Tx Frame Sync Polarity - GpakSerFrameSyncPol_t RxFrameSyncPolarity3; // port 3 Rx Frame Sync Polarity - GpakSerClockPol_t TxClockPolarity3; // port 3 Tx Clock Polarity - GpakSerClockPol_t RxClockPolarity3; // port 3 Rx Clock Polarity - GpakSerDataDelay_t TxDataDelay3; // port 3 Tx data delay - GpakSerDataDelay_t RxDataDelay3; // port 3 Rx data delay - GpakActivation DxDelay3; // port 3 DX Delay - - unsigned short int ThirdSlotMask3; // port 3 3rd group Slot Mask - unsigned short int FouthSlotMask3; // port 3 4th group Slot Mask - unsigned short int FifthSlotMask3; // port 3 5th group Slot Mask - unsigned short int SixthSlotMask3; // port 3 6th group Slot Mask - unsigned short int SevenSlotMask3; // port 3 7th group Slot Mask - unsigned short int EightSlotMask3; // port 3 8th group Slot Mask - -} GpakPortConfig_t; - -/* Definition of a Tone Generation Parameter Structure */ -/* -typedef struct -{ - GpakToneGenType_t ToneType; // Tone Type - unsigned short int Frequency[4]; // Frequency (Hz) - short int Level[4]; // Frequency's Level (1 dBm) - unsigned short int OnTime[4]; // On Times (msecs) - unsigned short int OffTime[4]; // Off Times (msecs) -} GpakToneGenParms_t; -*/ -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakConfigureChannel return status. */ -typedef enum -{ - CcsSuccess = 0, /* Channel Configured successfully */ - CcsParmError = 1, /* Channel Config Parameter error */ - CcsInvalidChannel = 2, /* invalid channel */ - CcsInvalidDsp = 3, /* invalid DSP */ - CcsDspCommFailure = 4 /* failed to communicate with DSP */ -} gpakConfigChanStatus_t; - -/* - * gpakConfigureChannel - Configure a DSP's Channel. - * - * FUNCTION - * This function configures a DSP's Channel. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -extern gpakConfigChanStatus_t gpakConfigureChannel( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GpakChanType ChannelType, // channel type - GpakChannelConfig_t *pChanConfig, // pointer to channel config info - GPAK_ChannelConfigStat_t *pStatus // pointer to Channel Config Status - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakTearDownChannel return status. */ -typedef enum -{ - TdsSuccess = 0, /* Channel Tear Down successful */ - TdsError = 1, /* Channel Tear Down error */ - TdsInvalidChannel = 2, /* invalid channel */ - TdsInvalidDsp = 3, /* invalid DSP */ - TdsDspCommFailure = 4 /* failed to communicate with DSP */ -} gpakTearDownStatus_t; - -/* - * gpakTearDownChannel - Tear Down a DSP's Channel. - * - * FUNCTION - * This function tears down a DSP's Channel. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ - -extern gpakTearDownStatus_t gpakTearDownChannel( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GPAK_TearDownChanStat_t *pStatus // pointer to Tear Down Status - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakAlgControl return status. */ -typedef enum -{ - AcSuccess = 0, /* control successful */ - AcInvalidChannel = 1, /* invalid channel identifier */ - AcInvalidDsp = 2, /* invalid DSP */ - AcParmError = 3, /* invalid control parameter */ - AcDspCommFailure = 4 /* failed to communicate with DSP */ -} gpakAlgControlStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAlgControl - Control an Algorithm. - * - * FUNCTION - * This function controls an Algorithm - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -extern gpakAlgControlStat_t gpakAlgControl( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GpakAlgCtrl_t ControlCode, // algorithm control code - GPAK_AlgControlStat_t *pStatus // pointer to return status - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakConfigurePorts return status. */ -typedef enum -{ - CpsSuccess = 0, /* Serial Ports configured successfully */ - CpsParmError = 1, /* Configure Ports Parameter error */ - CpsInvalidDsp = 2, /* invalid DSP */ - CpsDspCommFailure = 3 /* failed to communicate with DSP */ -} gpakConfigPortStatus_t; - -/* - * gpakConfigurePorts - Configure a DSP's serial ports. - * - * FUNCTION - * This function configures a DSP's serial ports. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -extern gpakConfigPortStatus_t gpakConfigurePorts( - unsigned short int DspId, // DSP identifier - GpakPortConfig_t *pPortConfig, // pointer to Port Config info - GPAK_PortConfigStat_t *pStatus // pointer to Port Config Status - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakDownloadDsp return status. */ -typedef enum -{ - GdlSuccess = 0, /* DSP download successful */ - GdlFileReadError = 1, /* error reading Download file */ - GdlInvalidFile = 2, /* invalid Download file content */ - GdlInvalidDsp = 3 /* invalid DSP */ -} gpakDownloadStatus_t; - -/* - * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. - * - * FUNCTION - * This function reads a DSP's Program and Data memory image from the - * specified file and writes the image to the DSP's memory. - * - * RETURNS - * Status code indicating success or a specific error. - * - */ -extern gpakDownloadStatus_t gpakDownloadDsp( - unsigned short int DspId, // DSP identifier - GPAK_FILE_ID FileId // G.PAK download file identifier - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -/* gpakReadEventFIFOMessage return status */ -typedef enum -{ - RefEventAvail = 0, /* an event was successfully read from the fifo */ - RefNoEventAvail = 1, /* no event was in the fifo */ - RefInvalidDsp = 2, /* invalid DSP identifier */ - RefInvalidEvent = 3, /* invalid event */ - RefDspCommFailure = 4 /* error communicating with DSP */ -} gpakReadEventFIFOMessageStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadEventFIFOMessage - read from the event fifo - * - * FUNCTION - * This function reads a single event from the event fifo if one is available - * - * RETURNS - * Status code indicating success or a specific error. - * - * Note: This function should be called in a loop until the return status - * indicates that the fifo is empty. - */ -extern gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( - unsigned short int DspId, // DSP identifier - unsigned short int *pChannelId, // pointer to channel identifier - GpakAsyncEventCode_t *pEventCode, // pointer to Event Code - GpakAsyncEventData_t *pEventData // pointer to Event Data Struct - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakPingDsp return status values */ -typedef enum -{ - PngSuccess = 0, /* DSP responded successfully */ - PngInvalidDsp = 1, /* invalid DSP identifier */ - PngDspCommFailure = 2 /* error communicating with DSP */ -} gpakPingDspStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakPingDsp - ping the DSP to see if it's alive - * - * FUNCTION - * This function checks if the DSP is still communicating with the host - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakPingDspStat_t gpakPingDsp( - unsigned short int DspId, // DSP identifier - unsigned short int *pDspSwVersion // DSP software version - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakSerialTxFixedValue return status values */ -typedef enum -{ - TfvSuccess = 0, /* operation successful */ - TfvInvalidChannel = 1, /* invalid channel identifier */ - TfvInvalidDsp = 2, /* invalid DSP identifier */ - TfvDspCommFailure = 3 /* failed to communicate with DSP */ -} gpakSerialTxFixedValueStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakSerialTxFixedValue - transmit a fixed value on a timeslot - * - * FUNCTION - * This function controls transmission of a fixed value out onto a serial - * port's timeslot. - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( - unsigned short int DspId, // DSP identifier - unsigned short int ChannelId, // channel identifier - GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id - unsigned short int PcmOutSlot, // PCM Output Time Slot - unsigned short int Value, // 16-bit value - GpakActivation State // activation state - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakControlTdmLoopBack return status values */ -typedef enum -{ - ClbSuccess = 0, /* operation successful */ - ClbSerPortInactive = 1, /* serial port is inactive */ - ClbInvalidDsp = 2, /* invalid DSP identifier */ - ClbDspCommFailure = 3 /* failed to communicate with DSP */ -} gpakControlTdmLoopBackStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakControlTdmLoopBack - control a serial port's loopback state - * - * FUNCTION - * This function enables/disables the tdm input to output looback mode on a - * serial port - * - * RETURNS - * Status code indicating success or a specific error. - */ - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ -gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( - unsigned short int DspId, // DSP identifier - GpakSerialPort_t SerialPort, // Serial Port Id - GpakActivation LoopBackState // Loopback State - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakReadCpuUsage return status values */ -typedef enum -{ - RcuSuccess = 0, /* operation successful */ - RcuInvalidDsp = 1, /* invalid DSP identifier */ - RcuDspCommFailure = 2 /* communication failure */ -} gpakReadCpuUsageStat_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - read the cpu usage statistics - * - * FUNCTION - * This function reads cpu utilization from the DSP. - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakReadCpuUsageStat_t gpakReadCpuUsage( - unsigned short int DspId, // DSP identifier - unsigned short int *pPeakUsage, // pointer to peak usage variable - unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakResetCpuUsageStats return status values */ -typedef enum -{ - RstcSuccess = 0, /* operation successful */ - RstcInvalidDsp = 1, /* invalid DSP identifier */ - RstcDspCommFailure = 2 /* communication failure */ -} gpakResetCpuUsageStat_t; -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetCpuUsageStats - reset the cpu usage statistics - * - * FUNCTION - * This function resets the cpu utilization statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakResetCpuUsageStat_t gpakResetCpuUsageStats( - unsigned short int DspId // DSP identifier - ); - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakReadFramingStats return status values */ -typedef enum -{ - RfsSuccess = 0, /* operation successful */ - RfsInvalidDsp = 1, /* invalid DSP identifier */ - RfsDspCommFailure = 2 /* communication failure */ -} gpakReadFramingStatsStatus_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFramingStats - * - * FUNCTION - * This function reads a DSP's framing interrupt statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakReadFramingStatsStatus_t gpakReadFramingStats( - unsigned short int DspId, // DSP identifier - unsigned short int *pFramingError1Count, // port 1 Framing error count - unsigned short int *pFramingError2Count, // port 2 Framing error count - unsigned short int *pFramingError3Count, // port 3 Framing error count - unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count - unsigned short int *pDmaSlipStatsBuffer // DMA slips count - ); - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - -/* gpakResetFramingStats return values */ -typedef enum -{ - RstfSuccess = 0, /* operation successful */ - RstfInvalidDsp = 1, /* invalid DSP identifier */ - RstfDspCommFailure = 2 /* communication failure */ -} gpakResetFramingStatsStatus_t; - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - reset a DSP's framing interrupt statistics - * - * FUNCTION - * This function resets a DSP's framing interrupt statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ -extern gpakResetFramingStatsStatus_t gpakResetFramingStats( - unsigned short int DspId // DSP identifier - ); - - -typedef enum -{ - RmmSuccess =0, - RmmInvalidDsp = 1, - RmmSizeTooBig = 2, - RmmFailure = 3, - RmmInvalidAddress = 4 - -} gpakReadDSPMemoryStat_t; -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - read a section of DSP memory - * to get access DSP registers, since 0x00--0x60 not HPI-accessable - * - * FUNCTION - * This function resets a DSP's framing interrupt statistics - * - * RETURNS - * Status code indicating success or a specific error. - */ - -extern gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( - unsigned short int DspId, // Dsp Identifier - unsigned short int *pDest, // Buffer on host to hold DSP memory map - DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out - unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word - ); - -typedef enum -{ - GPIOSuccess =0, - GPIOInvalidDsp = 1, - GPIODspCommFailure = 2 -}gpakAccessGPIOStat_t; - -extern gpakAccessGPIOStat_t gpakAccessGPIO( - unsigned short int DspId, // DSP identifier - GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read - unsigned short int *pGPIOValue // pointer for the read/write value or DIR mask - ); - -/* gpakWriteSystemParms return status. */ -typedef enum -{ - WspSuccess = 0, /* System Parameters written successfully */ - WspParmError = 1, /* Write System Parms's Parameter error */ - WspInvalidDsp = 2, /* invalid DSP */ - WspDspCommFailure = 3 /* failed to communicate with DSP */ -} gpakWriteSysParmsStatus_t; - -/* Definition of a System Parameters information structure. */ -typedef struct -{ - /* DTMF Parameters */ - short int MinSigLevel; /* 0 = Disabled, Min Sig Power Level for detection */ - short int SNRFlag; /* 0 = Disabled, relax SNR tolerances */ - short int FreqDeviation; /* 0 = Disabled, X Percent Deviation times 10 (e.g. 1.7% is entered as 17) */ - short int DtmfFwdTwist; /* 0 to 8 db */ - short int DtmfRevTwist; /* 0 to 8 db */ - - short int DtmfValidityMask; /* This flag allows users to relax the trailing conditions of the tone */ - -} GpakSystemParms_t; -/* gpakReadSystemParms return status. */ -typedef enum -{ - RspSuccess = 0, /* System Parameters read successfully */ - RspInvalidDsp = 1, /* invalid DSP */ - RspDspCommFailure = 2 /* failed to communicate with DSP */ -} gpakReadSysParmsStatus_t; - -extern gpakReadSysParmsStatus_t gpakReadSystemParms( - unsigned short int DspId, // DSP identifier - GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ - ); - -extern gpakWriteSysParmsStatus_t gpakWriteSystemParms( - unsigned short int DspId, // DSP identifier - GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ - unsigned short int UpdateBits, /* input: flags indicating which parms to update */ - GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ - ); - -#endif // end multiple inclusion - diff --git a/wcte12xp/GpakErrs.h b/wcte12xp/GpakErrs.h deleted file mode 100644 index 3413f97..0000000 --- a/wcte12xp/GpakErrs.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2002 - 2004, Adaptive Digital Technologies, Inc. - * - * File Name: GpakErrs.h - * - * Description: - * This file contains DSP reply status codes used by G.PAK API functions to - * indicate specific errors. - * - * Version: 1.0 - * - * Revision History: - * 10/17/01 - Initial release. - * 07/03/02 - Updates for conferencing. - * 06/15/04 - Tone type updates. - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. The standard - * GPL disclaimer is given inline below for your convenience. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _GPAKERRS_H /* prevent multiple inclusion */ -#define _GPAKERRS_H - -/* Configure Serial Ports reply status codes. */ -typedef enum -{ - Pc_Success = 0, /* serial ports configured successfully */ - Pc_ChannelsActive = 1, /* unable to configure while channels active */ - Pc_TooManySlots1 = 2, /* too many slots selected for port 1 */ - Pc_InvalidBlockCombo1 = 3, /* invalid combination of blocks for port 1 */ - Pc_NoSlots1 = 4, /* no slots selected for port 1 */ - Pc_InvalidSlots1 = 5, /* invalid slot (> max) selected for port 1 */ - Pc_TooManySlots2 = 6, /* too many slots selected for port 2 */ - Pc_InvalidBlockCombo2 = 7, /* invalid combination of blocks for port 2 */ - Pc_NoSlots2 = 8, /* no slots selected for port 2 */ - Pc_InvalidSlots2 = 9, /* invalid slot (> max) selected for port 2 */ - Pc_TooManySlots3 = 10, /* too many slots selected for port 3 */ - Pc_InvalidBlockCombo3 = 11, /* invalid combination of blocks for port 3 */ - Pc_NoSlots3 = 12, /* no slots selected for port 3 */ - Pc_InvalidSlots3 = 13 /* invalid slot (> max) selected for port 3 */ -} GPAK_PortConfigStat_t; - -/* Configure Channel reply status codes. */ -typedef enum -{ - Cc_Success = 0, /* channel configured successfully */ - Cc_InvalidChannelType = 1, /* invalid Channel Type */ - Cc_InvalidChannel = 2, /* invalid Channel A Id */ - Cc_ChannelActiveA = 3, /* Channel A is currently active */ - Cc_InvalidInputPortA = 4, /* invalid Input A Port */ - Cc_InvalidInputSlotA = 5, /* invalid Input A Slot */ - Cc_BusyInputSlotA = 6, /* busy Input A Slot */ - Cc_InvalidOutputPortA = 7, /* invalid Output A Port */ - Cc_InvalidOutputSlotA = 8, /* invalid Output A Slot */ - Cc_BusyOutputSlotA = 9, /* busy Output A Slot */ - Cc_InvalidInputPortB = 10, /* invalid Input B Port */ - Cc_InvalidInputSlotB = 11, /* invalid Input B Slot */ - Cc_BusyInputSlotB = 12, /* busy Input B Slot */ - Cc_InvalidPktInCodingA = 13, /* invalid Packet In A Coding */ - Cc_InvalidPktOutCodingA = 14, /* invalid Packet Out A Coding */ - Cc_InvalidPktInSizeA = 15, /* invalid Packet In A Frame Size */ - Cc_InvalidPktOutSizeA = 16, /* invalid Packet Out A Frame Size */ - - Cc_ChanTypeNotConfigured = 21, /* channel type was not configured */ - Cc_InsuffECResources = 22, /* insufficient ecan resources avail. */ - Cc_InsuffTDMResources = 23, /* insufficient tdm block resources avail. */ - - Cc_InsuffPktBufResources = 25, /* insufficient pkt buffer resources avail. */ - Cc_InsuffPcmBufResources = 26, /* insufficient pcm buffer resources avail. */ - - Cc_BadPcmEcNlpType = 30, /* invalid EC Nlp type */ - Cc_BadPcmEcTapLength = 31, /* invalid EC tap length */ - Cc_BadPcmEcDblTalkThresh = 32, /* invalid EC double-talk threshold */ - Cc_BadPcmEcNlpThreshold = 33, /* invalid EC Nlp threshold */ - Cc_BadPcmEcCngThreshold = 34, /* invalid EC Cng threshold */ - Cc_BadPcmEcAdaptLimit = 35, /* invalid EC Adapt Limit */ - Cc_BadPcmEcCrossCorrLim = 36, /* invalid EC Cross Correlation Limit */ - Cc_BadPcmEcNumFirSegs = 37, /* invalid EC Number of FirSegments */ - Cc_BadPcmEcFirSegLen = 38, /* invalid EC Fir Segment Length */ - - /*Cc_InvalidNumEcsEnabled = 48, */ /* more than 1 Ec enabled on channel */ - Cc_InvalidFrameRate = 49, /* invalid gpak frame rate */ - Cc_InvalidSoftCompand = 50, /* invalid softCompanding type */ - - Cc_InvalidMuteToneA = 51, /* invalid MuteToneA set, no detector */ - Cc_InvalidMuteToneB = 52, /* invalid MuteToneB set, no detector */ - Cc_InsuffFaxCngDetResources = 53 /* insufficient tdm block resources avail. */ - -} GPAK_ChannelConfigStat_t; - -/* Tear Down Channel reply status codes. */ -typedef enum -{ - Td_Success = 0, /* channel torn down successfully */ - Td_InvalidChannel = 1, /* invalid Channel Id */ - Td_ChannelNotActive = 2 /* channel is not active */ -} GPAK_TearDownChanStat_t; - - -typedef enum -{ - Ac_Success = 0, /* algorithm control is successfull */ - Ac_InvalidChannel = 1, /* invalid channel identifier */ - Ac_InvalidCode = 2, /* invalid algorithm control code */ - Ac_ECNotEnabled = 3, /* echo canceller was not allocated */ - Ac_InvalidSoftComp = 4, /* invalid softcompanding, 'cause serial port not in companding mode */ - Ac_InvalidDTMFMuteA = 5, /* A side invalid Mute, since no dtmf detector */ - Ac_InvalidDTMFMuteB = 6, /* B side invalid Mute, since no dtmf detector */ - Ac_InvalidFaxCngA = 7, /* A side FAXCNG detector not available */ - Ac_InvalidFaxCngB = 8, /* B side FAXCNG detector not available */ - Ac_InvalidSysConfig = 9 /* No new system parameters (DTMF config) wrriten yet */ -} GPAK_AlgControlStat_t; - -/* Write System Parameters reply status codes. */ -typedef enum -{ - Sp_Success = 0, /* System Parameters written successfully */ - Sp_BadTwistThresh = 29 /* invalid twist threshold */ - -} GPAK_SysParmsStat_t; - -#endif /* prevent multiple inclusion */ - - - - - - - - - - - - - - - - - - - diff --git a/wcte12xp/GpakHpi.h b/wcte12xp/GpakHpi.h deleted file mode 100644 index 790bb3c..0000000 --- a/wcte12xp/GpakHpi.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2001, Adaptive Digital Technologies, Inc. - * - * File Name: GpakHpi.h - * - * Description: - * This file contains common definitions related to the G.PAK interface - * between a host processor and a DSP processor via the Host Port Interface. - * - * Version: 1.0 - * - * Revision History: - * 10/17/01 - Initial release. - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. The standard - * GPL disclaimer is given inline below for your convenience. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _GPAKHPI_H /* prevent multiple inclusion */ -#define _GPAKHPI_H - - -/* Definition of G.PAK Command/Reply message type codes. */ -#define MSG_NULL_REPLY 0 /* Null Reply (unsupported Command) */ -#define MSG_SYS_CONFIG_RQST 1 /* System Configuration Request */ -#define MSG_SYS_CONFIG_REPLY 2 /* System Configuration Reply */ -#define MSG_READ_SYS_PARMS 3 /* Read System Parameters */ -#define MSG_READ_SYS_PARMS_REPLY 4 /* Read System Parameters Reply */ -#define MSG_WRITE_SYS_PARMS 5 /* Write System Parameters */ -#define MSG_WRITE_SYS_PARMS_REPLY 6 /* Write System Parameters Reply */ -#define MSG_CONFIGURE_PORTS 7 /* Configure Serial Ports */ -#define MSG_CONFIG_PORTS_REPLY 8 /* Configure Serial Ports Reply */ -#define MSG_CONFIGURE_CHANNEL 9 /* Configure Channel */ -#define MSG_CONFIG_CHAN_REPLY 10 /* Configure Channel Reply */ -#define MSG_TEAR_DOWN_CHANNEL 11 /* Tear Down Channel */ -#define MSG_TEAR_DOWN_REPLY 12 /* Tear Down Channel Reply */ -#define MSG_CHAN_STATUS_RQST 13 /* Channel Status Request */ -#define MSG_CHAN_STATUS_REPLY 14 /* Channel Status Reply */ - -#define MSG_TEST_MODE 17 /* Configure/Perform Test Mode */ -#define MSG_TEST_REPLY 18 /* Configure/Perform Test Mode Reply */ - -#define MSG_ALG_CONTROL 27 /* algorithm control */ -#define MSG_ALG_CONTROL_REPLY 28 /* algorithm control reply */ -#define MSG_GET_TXCID_ADDRESS 29 /* get tx cid buffer start address */ -#define MSG_GET_TXCID_ADDRESS_REPLY 30 /* get tx cid buffer start addr reply */ - -#define MSG_PING 35 /* ping command */ -#define MSG_PING_REPLY 36 /* ping command reply */ -#define MSG_SERIAL_TXVAL 37 /* transmit serial fixed value */ -#define MSG_SERIAL_TXVAL_REPLY 38 /* transmit serial fixed value reply */ -#define MSG_TDM_LOOPBACK 39 /* tdm loopback control */ -#define MSG_TDM_LOOPBACK_REPLY 40 /* tdm loopback control reply */ -#define MSG_RESET_USAGE_STATS 41 /* reset cpu usage stats */ -#define MSG_RESET_USAGE_STATS_REPLY 42 /* reset cpu usage stats reply */ - -#define MSG_RESET_FRAME_STATS 47 /* reset framing stats */ -#define MSG_RESET_FRAME_STATS_REPLY 48 /* reset framing stats reply */ - -#define MSG_READ_DSP_MEMORY 49 /* read small section of DSP's memory */ -#define MSG_READ_DSP_MEMORY_REPLY 50 /* read memory reply */ - -#define MSG_ACCESSGPIO 51 -#define MSG_ACCESSGPIO_REPLY 52 -#endif /* prevent multiple inclusion */ diff --git a/wcte12xp/Kbuild b/wcte12xp/Kbuild deleted file mode 100644 index 14d7494..0000000 --- a/wcte12xp/Kbuild +++ /dev/null @@ -1,23 +0,0 @@ -obj-m += wcte12xp.o - -EXTRA_CFLAGS := -I$(src)/.. -Wno-undef - -ifeq ($(HOTPLUG_FIRMWARE),yes) - EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE -endif - -wcte12xp-objs := base.o vpmadt032.o GpakApi.o - -ifneq ($(HOTPLUG_FIRMWARE),yes) -wcte12xp-objs += ../firmware/zaptel-fw-vpmadt032.o -endif - -$(obj)/../firmware/zaptel-fw-vpmadt032.o: $(obj)/base.o - $(MAKE) -C $(obj)/../firmware zaptel-fw-vpmadt032.o - -$(obj)/base.o: $(src)/vpmadt032.h $(src)/wcte12xp.h -$(obj)/base.o: $(src)/../zaptel.h - -$(obj)/vpmadt032.o: $(src)/vpmadt032.h - -$(obj)/GpakApi.o: $(src)/GpakApi.h diff --git a/wcte12xp/Makefile b/wcte12xp/Makefile deleted file mode 100644 index fb0fbc5..0000000 --- a/wcte12xp/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -ifneq ($(KBUILD_EXTMOD),) -# We only get here on kernels 2.6.0-2.6.9 . -# For newer kernels, Kbuild will be included directly by the kernel -# build system. -include $(src)/Kbuild - -else - -# building for 2.4 kernels means no VPM support, so none of the VPM support -# modules are included in the Makefile rules - -all: wcte12xp.o - -%.o: %.c - $(CC) $(KFLAGS) -o $@ -c $< - -base.o: ../zaptel.h - -wcte12xp.o: base.o - $(LD) -r -o $@ $^ - -clean: - rm -f *.o - -endif diff --git a/wcte12xp/base.c b/wcte12xp/base.c deleted file mode 100644 index 5dd83db..0000000 --- a/wcte12xp/base.c +++ /dev/null @@ -1,2139 +0,0 @@ -/* - * Digium, Inc. Wildcard TE12xP T1/E1 card Driver - * - * Written by Michael Spiceland - * - * Adapted from the wctdm24xxp and wcte11xp drivers originally - * written by Mark Spencer - * Matthew Fredrickson - * William Meadows - * - * Copyright (C) 2007, Digium, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef LINUX26 -#include -#endif - -#include "zaptel.h" - -#include "../wct4xxp/wct4xxp.h" /* For certain definitions */ - -#include "wcte12xp.h" - -#if defined(VPM_SUPPORT) -#include "vpmadt032.h" -#include "GpakApi.h" -#endif - -struct pci_driver te12xp_driver; - -static int chanmap_t1[] = -{ 2,1,0, - 6,5,4, - 10,9,8, - 14,13,12, - 18,17,16, - 22,21,20, - 26,25,24, - 30,29,28 }; - -static int chanmap_e1[] = -{ 2,1,0, - 7,6,5,4, - 11,10,9,8, - 15,14,13,12, - 19,18,17,16, - 23,22,21,20, - 27,26,25,24, - 31,30,29,28 }; - -static int chanmap_e1uc[] = -{ 3,2,1,0, - 7,6,5,4, - 11,10,9,8, - 15,14,13,12, - 19,18,17,16, - 23,22,21,20, - 27,26,25,24, - 31,30,29,28 }; - -int debug = 0; -static int j1mode = 0; -static int alarmdebounce = 0; -static int loopback = 0; -static int t1e1override = -1; -static int unchannelized = 0; -#ifdef VPM_SUPPORT -int vpmsupport = 1; -int vpmdtmfsupport = 0; -int vpmtsisupport = 0; -int vpmnlptype = 1; -int vpmnlpthresh = 24; -int vpmnlpmaxsupp = 0; -#endif - -struct t1 *ifaces[WC_MAX_IFACES]; -spinlock_t ifacelock = SPIN_LOCK_UNLOCKED; - -struct t1_desc { - char *name; - int flags; -}; - -static struct t1_desc te120p = { "Wildcard TE120P", 0 }; -static struct t1_desc te122 = { "Wildcard TE122", 0 }; -static struct t1_desc te121 = { "Wildcard TE121", 0 }; - -int schluffen(wait_queue_head_t *q) -{ - DECLARE_WAITQUEUE(wait, current); - add_wait_queue(q, &wait); - current->state = TASK_INTERRUPTIBLE; - if (!signal_pending(current)) schedule(); - current->state = TASK_RUNNING; - remove_wait_queue(q, &wait); - if (signal_pending(current)) return -ERESTARTSYS; - return(0); -} - -static inline int empty_slot(struct t1 *wc) -{ - unsigned int x; - - for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { - if (!wc->cmdq.cmds[x].flags && !wc->cmdq.cmds[x].address) - return x; - } - return -1; -} - -static inline void __t1_setctl(struct t1 *wc, unsigned int addr, unsigned int val) -{ - outl(val, wc->iobase + addr); -} - -static inline void t1_setctl(struct t1 *wc, unsigned int addr, unsigned int val) -{ - unsigned long flags; - - spin_lock_irqsave(&wc->reglock, flags); - __t1_setctl(wc, addr, val); - spin_unlock_irqrestore(&wc->reglock, flags); -} - -static inline unsigned int __t1_getctl(struct t1 *wc, unsigned int addr) -{ - return inl(wc->iobase + addr); -} - -static inline unsigned int t1_getctl(struct t1 *wc, unsigned int addr) -{ - unsigned long flags; - unsigned int val; - - spin_lock_irqsave(&wc->reglock, flags); - val = __t1_getctl(wc, addr); - spin_unlock_irqrestore(&wc->reglock, flags); - - return val; -} - -static void t1_init_descriptors(struct t1 *wc) -{ - volatile unsigned int *descrip; - dma_addr_t descripdma; - dma_addr_t writedma; - dma_addr_t readdma; - int x; - - descrip = wc->descripchunk; - descripdma = wc->descripdma; - writedma = wc->writedma; - readdma = wc->readdma; - - for (x = 0; x < ERING_SIZE; x++) { - if (x < ERING_SIZE - 1) - descripdma += 16; - else - descripdma = wc->descripdma; - - /* Transmit descriptor */ - descrip[0] = 0x80000000; - descrip[1] = 0xe5800000 | (SFRAME_SIZE); - if (x % 2) - descrip[2] = writedma + SFRAME_SIZE; - else - descrip[2] = writedma; - descrip[3] = descripdma; - - /* Receive descriptor */ - descrip[0 + ERING_SIZE * 4] = 0x80000000; - descrip[1 + ERING_SIZE * 4] = 0x01000000 | (SFRAME_SIZE); - if (x % 2) - descrip[2 + ERING_SIZE * 4] = readdma + SFRAME_SIZE; - else - descrip[2 + ERING_SIZE * 4] = readdma; - descrip[3 + ERING_SIZE * 4] = descripdma + ERING_SIZE * 16; - - /* Advance descriptor */ - descrip += 4; - } -} - -static inline void t1_reinit_descriptor(struct t1 *wc, int tx, int dbl, char *s) -{ - int o2 = dbl * 4; - - if (!tx) - o2 += ERING_SIZE * 4; - - wc->descripchunk[o2] = 0x80000000; -} - -static inline void cmd_dequeue(struct t1 *wc, volatile unsigned char *writechunk, int eframe, int slot) -{ - struct command *curcmd=NULL; - unsigned int x; - - /* Skip audio */ - writechunk += 66; - /* Search for something waiting to transmit */ - if ((slot < 6) && (eframe) && (eframe < ZT_CHUNKSIZE - 1)) { - /* only 6 useable cs slots per */ - - /* framer */ - for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { - if ((wc->cmdq.cmds[x].flags & (__CMD_RD | __CMD_WR | __CMD_LEDS | __CMD_PINS)) && - !(wc->cmdq.cmds[x].flags & (__CMD_TX | __CMD_FIN))) { - curcmd = &wc->cmdq.cmds[x]; - wc->cmdq.cmds[x].flags |= __CMD_TX; - wc->cmdq.cmds[x].ident = wc->txident; - break; - } - } - if (!curcmd) { - curcmd = &wc->dummy; - /* If nothing else, use filler */ - curcmd->address = 0x4a; - curcmd->data = 0x00; - curcmd->flags = __CMD_RD; - } - curcmd->cs_slot = slot; - if (curcmd->flags & __CMD_WR) - writechunk[CMD_BYTE(slot,0,0)] = 0x0c; /* 0c write command */ - else if (curcmd->flags & __CMD_LEDS) - writechunk[CMD_BYTE(slot,0,0)] = 0x10 | ((curcmd->address) & 0x0E); /* led set command */ - else if (curcmd->flags & __CMD_PINS) - writechunk[CMD_BYTE(slot,0,0)] = 0x30; /* CPLD2 pin state */ - else - writechunk[CMD_BYTE(slot,0,0)] = 0x0a; /* read command */ - writechunk[CMD_BYTE(slot,1,0)] = curcmd->address; - writechunk[CMD_BYTE(slot,2,0)] = curcmd->data; - } - -} - -static inline void cmd_decipher(struct t1 *wc, volatile unsigned char *readchunk) -{ - unsigned char ident, cs_slot; - unsigned int x; - unsigned int is_vpm = 0; - - /* Skip audio */ - readchunk += 66; - /* Search for any pending results */ - for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { - if ((wc->cmdq.cmds[x].flags & (__CMD_RD | __CMD_WR | __CMD_LEDS | __CMD_PINS)) && - (wc->cmdq.cmds[x].flags & (__CMD_TX)) && - !(wc->cmdq.cmds[x].flags & (__CMD_FIN))) { - ident = wc->cmdq.cmds[x].ident; - cs_slot = wc->cmdq.cmds[x].cs_slot; - - if (ident == wc->rxident) { - /* Store result */ - wc->cmdq.cmds[x].data |= readchunk[CMD_BYTE(cs_slot,2,is_vpm)]; - /*printk("answer in rxident=%d cs_slot=%d is %d CMD_BYTE=%d jiffies=%d\n", ident, cs_slot, last_read_command, CMD_BYTE(cs_slot, 2), jiffies); */ - wc->cmdq.cmds[x].flags |= __CMD_FIN; - if (wc->cmdq.cmds[x].flags & (__CMD_WR | __CMD_LEDS)) - /* clear out writes (and leds) since they need no ack */ - memset(&wc->cmdq.cmds[x], 0, sizeof(wc->cmdq.cmds[x])); - } - } - } -} - -static inline unsigned int __t1_sdi_clk(struct t1 *wc) -{ - unsigned int ret; - - wc->sdi &= ~SDI_CLK; - __t1_setctl(wc, 0x0048, wc->sdi); - ret = __t1_getctl(wc, 0x0048); - wc->sdi |= SDI_CLK; - __t1_setctl(wc, 0x0048, wc->sdi); - return ret & SDI_DIN; -} - -static inline void __t1_sdi_sendbits(struct t1 *wc, unsigned int bits, int count) -{ - wc->sdi &= ~SDI_DREAD; - __t1_setctl(wc, 0x0048, wc->sdi); - while (count--) { - if (bits & (1 << count)) - wc->sdi |= SDI_DOUT; - else - wc->sdi &= ~SDI_DOUT; - __t1_sdi_clk(wc); - } -} - -static inline unsigned int __t1_sdi_recvbits(struct t1 *wc, int count) -{ - unsigned int bits=0; - - wc->sdi |= SDI_DREAD; - __t1_setctl(wc, 0x0048, wc->sdi); - while (count--) { - bits <<= 1; - if (__t1_sdi_clk(wc)) - bits |= 1; - else - bits &= ~1; - } - return bits; -} - -static inline unsigned short __t1_getsdi(struct t1 *wc, unsigned char addr) -{ - unsigned int bits; - - /* Send preamble */ - bits = 0xffffffff; - __t1_sdi_sendbits(wc, bits, 32); - bits = (0x6 << 10) | (1 << 5) | (addr); - __t1_sdi_sendbits(wc, bits, 14); - - return __t1_sdi_recvbits(wc, 18); -} - -static inline unsigned short t1_getsdi(struct t1 *wc, unsigned char addr) -{ - unsigned long flags; - unsigned short val; - - spin_lock_irqsave(&wc->reglock, flags); - val = __t1_getsdi(wc, addr); - spin_unlock_irqrestore(&wc->reglock, flags); - - return val; -} - -static inline void __t1_setsdi(struct t1 *wc, unsigned char addr, unsigned short value) -{ - unsigned int bits; - - /* Send preamble */ - bits = 0xffffffff; - __t1_sdi_sendbits(wc, bits, 32); - bits = (0x5 << 12) | (1 << 7) | (addr << 2) | 0x2; - __t1_sdi_sendbits(wc, bits, 16); - __t1_sdi_sendbits(wc, value, 16); -} - -static inline void t1_setsdi(struct t1 *wc, unsigned char addr, unsigned short value) -{ - unsigned long flags; - - spin_lock_irqsave(&wc->reglock, flags); - __t1_setsdi(wc, addr, value); - spin_unlock_irqrestore(&wc->reglock, flags); -} - -static inline int t1_setreg_full(struct t1 *wc, int addr, int val, int inisr, int vpm_num) -{ - unsigned long flags; - int hit; - int ret; - - - do { - if (!inisr) - spin_lock_irqsave(&wc->reglock, flags); - hit = empty_slot(wc); - if (hit > -1) { - wc->cmdq.cmds[hit].address = addr; - wc->cmdq.cmds[hit].data = val; - wc->cmdq.cmds[hit].flags |= __CMD_WR; - if(vpm_num >= 0) { - wc->cmdq.cmds[hit].flags |= __CMD_VPM; - wc->cmdq.cmds[hit].vpm_num = vpm_num; - } - } - if (inisr) - break; - - spin_unlock_irqrestore(&wc->reglock, flags); - if (hit < 0) { - if ((ret = schluffen(&wc->regq))) - return ret; - } - } while (hit < 0); - - return (hit > -1) ? 0 : -1; -} - -static inline int t1_setreg(struct t1 *wc, int addr, int val) -{ - return t1_setreg_full(wc, addr, val, 0, NOT_VPM); -} - -/*************************************************************************** - * clean_leftovers() - * - * Check for unconsumed isr register reads and clean them up. - **************************************************************************/ -static inline void clean_leftovers(struct t1 *wc) -{ - unsigned int x; - int count = 0; - - /* find our requested command */ - for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { - if ((wc->cmdq.cmds[x].flags & __CMD_RD) && - (wc->cmdq.cmds[x].flags & __CMD_ISR) && - !(wc->cmdq.cmds[x].flags & __CMD_FIN)) { - debug_printk(1,"leftover isr read! %d", count); - memset(&wc->cmdq.cmds[x], 0, sizeof(wc->cmdq.cmds[x])); - } - } -} - -/******************************************************************** - * t1_getreg_isr() - * - * Called in interrupt context to retrieve a value already requested - * by the normal t1_getreg(). - *******************************************************************/ -static inline int t1_getreg_isr(struct t1 *wc, int addr) -{ - int hit=-1; - int ret; - unsigned int x; - - /* find our requested command */ - for (x = 0;x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { - if ((wc->cmdq.cmds[x].flags & __CMD_RD) && - (wc->cmdq.cmds[x].flags & __CMD_FIN) && - (wc->cmdq.cmds[x].address==addr)) { - hit = x; - break; - } - } - - if (hit < 0) { - debug_printk(2, "t1_getreg_isr() no addr=%02x\n", addr); - return -1; /* oops, couldn't find it */ - } - - ret = wc->cmdq.cmds[hit].data; - memset(&wc->cmdq.cmds[hit], 0, sizeof(struct command)); - - return ret; -} - -static inline int t1_getreg_full(struct t1 *wc, int addr, int inisr, int vpm_num) -{ - unsigned long flags; - int hit; - int ret = 0; - - do { - if (!inisr) { - spin_lock_irqsave(&wc->reglock, flags); - } - hit = empty_slot(wc); - if (hit > -1) { - wc->cmdq.cmds[hit].address = addr; - wc->cmdq.cmds[hit].data = 0x00; - wc->cmdq.cmds[hit].flags |= __CMD_RD; - if(vpm_num >= 0) { - wc->cmdq.cmds[hit].flags |= __CMD_VPM; - wc->cmdq.cmds[hit].vpm_num = vpm_num; - } - if (inisr) - wc->cmdq.cmds[hit].flags |= __CMD_ISR; - } - if (inisr) /* must be requested in t1_getreg_isr() */ - return (hit > -1) ? 0 : -1; - else { - spin_unlock_irqrestore(&wc->reglock, flags); - } - if (hit < 0) { - if ((ret = schluffen(&wc->regq))) - return ret; - } - } while (hit < 0); - - do { - spin_lock_irqsave(&wc->reglock, flags); - if (wc->cmdq.cmds[hit].flags & __CMD_FIN) { - ret = wc->cmdq.cmds[hit].data; - memset(&wc->cmdq.cmds[hit], 0, sizeof(wc->cmdq.cmds[hit])); - hit = -1; - } - spin_unlock_irqrestore(&wc->reglock, flags); - if (hit > -1) { - if ((ret = schluffen(&wc->regq))) - return ret; - } - } while (hit > -1); - - return ret; -} - -static inline int t1_getreg(struct t1 *wc, int addr, int inisr) -{ - return t1_getreg_full(wc, addr, inisr, NOT_VPM); -} - -static inline int t1_setleds(struct t1 *wc, int leds, int inisr) -{ - unsigned long flags; - int hit; - int ret = 0; - - leds = ~leds & 0x0E; /* invert the LED bits (3 downto 1)*/ - - do { - if (!inisr) { - spin_lock_irqsave(&wc->reglock, flags); - } - hit = empty_slot(wc); - if (hit > -1) { - wc->cmdq.cmds[hit].flags |= __CMD_LEDS; - wc->cmdq.cmds[hit].address = leds; - } - if (inisr) { - break; - } else { - spin_unlock_irqrestore(&wc->reglock, flags); - } - if (hit < 0) { - if ((ret = schluffen(&wc->regq))) - return ret; - } - } while (hit < 0); - - return (hit > -1) ? 0 : -1; -} - -static inline int t1_getpins(struct t1 *wc, int inisr) -{ - unsigned long flags; - int hit; - int ret = 0; - - do { - spin_lock_irqsave(&wc->reglock, flags); - hit = empty_slot(wc); - if (hit > -1) { - wc->cmdq.cmds[hit].address = 0x00; - wc->cmdq.cmds[hit].data = 0x00; - wc->cmdq.cmds[hit].flags |= __CMD_PINS; - } - spin_unlock_irqrestore(&wc->reglock, flags); - if (inisr) - return (hit > -1) ? 0 : -1; - if (hit < 0) { - if ((ret = schluffen(&wc->regq))) - return ret; - } - } while (hit < 0); - - do { - spin_lock_irqsave(&wc->reglock, flags); - if (wc->cmdq.cmds[hit].flags & __CMD_FIN) { - ret = wc->cmdq.cmds[hit].data; - memset(&wc->cmdq.cmds[hit], 0, sizeof(wc->cmdq.cmds[hit])); - hit = -1; - } - spin_unlock_irqrestore(&wc->reglock, flags); - if (hit > -1) { - if ((ret = schluffen(&wc->regq))) - return ret; - } - } while (hit > -1); - - return ret; -} - -static void t1_setintmask(struct t1 *wc, unsigned int intmask) -{ - wc->intmask = intmask; - t1_setctl(wc, 0x0038, intmask); -} - -static void t1_enable_interrupts(struct t1 *wc) -{ - /* Enable interrupts */ - t1_setintmask(wc, 0x00010041); /* only RX */ -} - -static void t1_disable_interrupts(struct t1 *wc) -{ - /* Disable interrupts */ - t1_setintmask(wc, 0x00000000); - t1_setctl(wc, 0x0084, 0x00000000); -} - -static void t1_start_dma(struct t1 *wc) -{ - unsigned int reg; - int x; - - wmb(); - t1_setctl(wc, 0x0020, wc->descripdma); - t1_setctl(wc, 0x0018, wc->descripdma + (16 * ERING_SIZE)); - /* Start receiver/transmitter */ - reg = t1_getctl(wc, 0x0030); - t1_setctl(wc, 0x0030, reg | 0x00002002); - t1_setctl(wc, 0x0008, 0x00000000); - t1_setctl(wc, 0x0010, 0x00000000); - reg = t1_getctl(wc, 0x0028); - t1_setctl(wc, 0x0028, reg); - - /* Set Reset - now with MAGIC TIPS */ - t1_setctl(wc, 0x0048, 0x00000000); - for (x = 0; x < 10; x++) - schluffen(&wc->regq); - /* Clear reset */ - t1_setctl(wc, 0x0048, 0x00010000); - for (x = 0; x < 10; x++) - schluffen(&wc->regq); - /* Switch to caring only about receive interrupts */ - t1_setintmask(wc, 0x00010040); -} - -static void t1_stop_dma(struct t1 *wc) -{ - /* Disable interrupts and reset */ - unsigned int reg; - - /* Disable interrupts */ - t1_setintmask(wc, 0x00000000); - t1_setctl(wc, 0x0084, 0x00000000); - t1_setctl(wc, 0x0048, 0x00000000); - /* Reset the part to be on the safe side */ - reg = t1_getctl(wc, 0x0000); - reg |= 0x00000001; - t1_setctl(wc, 0x0000, reg); -} - -static void __t1xxp_set_clear(struct t1 *wc, int channo) -{ - int i,j; - int ret; - unsigned short val=0; - - for (i = 0; i < 24; i++) { - j = (i / 8); - if (wc->span.chans[i].flags & ZT_FLAG_CLEAR) - val |= 1 << (7 - (i % 8)); - if (((i % 8)==7) && /* write byte every 8 channels */ - ((channo < 0) || /* channo=-1 means all channels */ - (j == (channo-1)/8) )) { /* only the register for this channo */ - ret = t1_setreg_full(wc, 0x2f + j, val, 1, NOT_VPM); - if (ret < 0) - module_printk("set_clear failed for chan %d!\n",i); - val = 0; - } - } -} - -static void t1_release(struct t1 *wc) -{ - zt_unregister(&wc->span); - if (wc->freeregion) - release_region(wc->iobase, 0xff); - kfree(wc); - printk("Freed a Wildcard TE12xP\n"); -} - -static void t4_serial_setup(struct t1 *wc) -{ - module_printk("Setting up global serial parameters for %s\n", - wc->spantype == TYPE_E1 ? (unchannelized ? "Unchannelized E1" : "E1") : "T1"); - - t1_setreg(wc, 0x85, 0xe0); /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0 */ - t1_setreg(wc, 0x08, 0x05); /* IPC: Interrupt push/pull active low */ - - /* Global clocks (8.192 Mhz CLK) */ - t1_setreg(wc, 0x92, 0x00); - t1_setreg(wc, 0x93, 0x18); - t1_setreg(wc, 0x94, 0xfb); - t1_setreg(wc, 0x95, 0x0b); - t1_setreg(wc, 0x96, 0x00); - t1_setreg(wc, 0x97, 0x0b); - t1_setreg(wc, 0x98, 0xdb); - t1_setreg(wc, 0x99, 0xdf); - - /* Configure interrupts */ - t1_setreg(wc, 0x46, 0xc0); /* GCR: Interrupt on Activation/Deactivation of AIX, LOS */ - - /* Configure system interface */ - t1_setreg(wc, 0x3e, 0x0a /* 0x02 */); /* SIC1: 4.096 Mhz clock/bus, double buffer receive / transmit, byte interleaved */ - t1_setreg(wc, 0x3f, 0x00); /* SIC2: No FFS, no center receive eliastic buffer, phase 0 */ - t1_setreg(wc, 0x40, 0x04); /* SIC3: Edges for capture */ - t1_setreg(wc, 0x44, 0x30); /* CMR1: RCLK is at 8.192 Mhz dejittered */ - t1_setreg(wc, 0x45, 0x00); /* CMR2: We provide sync and clock for tx and rx. */ - t1_setreg(wc, 0x22, 0x00); /* XC0: Normal operation of Sa-bits */ - t1_setreg(wc, 0x23, 0x04); /* XC1: 0 offset */ - t1_setreg(wc, 0x24, 0x00); /* RC0: Just shy of 255 */ - t1_setreg(wc, 0x25, 0x05); /* RC1: The rest of RC0 */ - - /* Configure ports */ - t1_setreg(wc, 0x80, 0x00); /* PC1: SPYR/SPYX input on RPA/XPA */ - t1_setreg(wc, 0x81, 0x22); /* PC2: RMFB/XSIG output/input on RPB/XPB */ - t1_setreg(wc, 0x82, 0x65); /* PC3: Some unused stuff */ - t1_setreg(wc, 0x83, 0x35); /* PC4: Some more unused stuff */ - t1_setreg(wc, 0x84, 0x31); /* PC5: XMFS active low, SCLKR is input, RCLK is output */ - t1_setreg(wc, 0x86, 0x03); /* PC6: CLK1 is Tx Clock output, CLK2 is 8.192 Mhz from DCO-R */ - t1_setreg(wc, 0x3b, 0x00); /* Clear LCR1 */ -} - -static void t1_configure_t1(struct t1 *wc, int lineconfig, int txlevel) -{ - unsigned int fmr4, fmr2, fmr1, fmr0, lim2; - char *framing, *line; - int mytxlevel; - - if ((txlevel > 7) || (txlevel < 4)) - mytxlevel = 0; - else - mytxlevel = txlevel - 4; - fmr1 = 0x9e; /* FMR1: Mode 0, T1 mode, CRC on for ESF, 2.048 Mhz system data rate, no XAIS */ - fmr2 = 0x22; /* FMR2: no payload loopback, auto send yellow alarm */ - if (loopback) - fmr2 |= 0x4; - - if (j1mode) - fmr4 = 0x1c; - else - fmr4 = 0x0c; /* FMR4: Lose sync on 2 out of 5 framing bits, auto resync */ - - lim2 = 0x21; /* LIM2: 50% peak is a "1", Advanced Loss recovery */ - lim2 |= (mytxlevel << 6); /* LIM2: Add line buildout */ - t1_setreg(wc, 0x1d, fmr1); - t1_setreg(wc, 0x1e, fmr2); - - /* Configure line interface */ - if (lineconfig & ZT_CONFIG_AMI) { - line = "AMI"; - fmr0 = 0xa0; - } else { - line = "B8ZS"; - fmr0 = 0xf0; - } - if (lineconfig & ZT_CONFIG_D4) { - framing = "D4"; - } else { - framing = "ESF"; - fmr4 |= 0x2; - fmr2 |= 0xc0; - } - t1_setreg(wc, 0x1c, fmr0); - - t1_setreg(wc, 0x20, fmr4); - t1_setreg(wc, 0x21, 0x40); /* FMR5: Enable RBS mode */ - - t1_setreg(wc, 0x37, 0xf8); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ - t1_setreg(wc, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ - - t1_setreg(wc, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ - t1_setreg(wc, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ - - t1_setreg(wc, 0x3a, lim2); /* LIM2: 50% peak amplitude is a "1" */ - t1_setreg(wc, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ - t1_setreg(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ - - if (j1mode) - t1_setreg(wc, 0x24, 0x80); /* J1 overide */ - - /* Generate pulse mask for T1 */ - switch (mytxlevel) { - case 3: - t1_setreg(wc, 0x26, 0x07); /* XPM0 */ - t1_setreg(wc, 0x27, 0x01); /* XPM1 */ - t1_setreg(wc, 0x28, 0x00); /* XPM2 */ - break; - case 2: - t1_setreg(wc, 0x26, 0x8c); /* XPM0 */ - t1_setreg(wc, 0x27, 0x11); /* XPM1 */ - t1_setreg(wc, 0x28, 0x01); /* XPM2 */ - break; - case 1: - t1_setreg(wc, 0x26, 0x8c); /* XPM0 */ - t1_setreg(wc, 0x27, 0x01); /* XPM1 */ - t1_setreg(wc, 0x28, 0x00); /* XPM2 */ - break; - case 0: - default: - t1_setreg(wc, 0x26, 0xd7); /* XPM0 */ - t1_setreg(wc, 0x27, 0x22); /* XPM1 */ - t1_setreg(wc, 0x28, 0x01); /* XPM2 */ - break; - } - - module_printk("Span configured for %s/%s\n", framing, line); -} - -static void t1_configure_e1(struct t1 *wc, int lineconfig) -{ - unsigned int fmr2, fmr1, fmr0; - unsigned int cas = 0; - char *crc4 = ""; - char *framing, *line; - - fmr1 = 0x46; /* FMR1: E1 mode, Automatic force resync, PCM30 mode, 8.192 Mhz backplane, no XAIS */ - fmr2 = 0x03; /* FMR2: Auto transmit remote alarm, auto loss of multiframe recovery, no payload loopback */ - if (unchannelized) - fmr2 |= 0x30; - if (loopback) - fmr2 |= 0x4; - if (lineconfig & ZT_CONFIG_CRC4) { - fmr1 |= 0x08; /* CRC4 transmit */ - fmr2 |= 0xc0; /* CRC4 receive */ - crc4 = "/CRC4"; - } - t1_setreg(wc, 0x1d, fmr1); - t1_setreg(wc, 0x1e, fmr2); - - /* Configure line interface */ - if (lineconfig & ZT_CONFIG_AMI) { - line = "AMI"; - fmr0 = 0xa0; - } else { - line = "HDB3"; - fmr0 = 0xf0; - } - if (lineconfig & ZT_CONFIG_CCS) { - framing = "CCS"; - } else { - framing = "CAS"; - cas = 0x40; - } - t1_setreg(wc, 0x1c, fmr0); - - if (unchannelized) - t1_setreg(wc, 0x1f, 0x40); - - t1_setreg(wc, 0x37, 0xf0 /*| 0x6 */ ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ - t1_setreg(wc, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ - - t1_setreg(wc, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ - t1_setreg(wc, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ - - /* Condition receive line interface for E1 after reset */ - t1_setreg(wc, 0xbb, 0x17); - t1_setreg(wc, 0xbc, 0x55); - t1_setreg(wc, 0xbb, 0x97); - t1_setreg(wc, 0xbb, 0x11); - t1_setreg(wc, 0xbc, 0xaa); - t1_setreg(wc, 0xbb, 0x91); - t1_setreg(wc, 0xbb, 0x12); - t1_setreg(wc, 0xbc, 0x55); - t1_setreg(wc, 0xbb, 0x92); - t1_setreg(wc, 0xbb, 0x0c); - t1_setreg(wc, 0xbb, 0x00); - t1_setreg(wc, 0xbb, 0x8c); - - t1_setreg(wc, 0x3a, 0x20); /* LIM2: 50% peak amplitude is a "1" */ - t1_setreg(wc, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ - t1_setreg(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ - - t1_setreg(wc, 0x20, 0x9f); /* XSW: Spare bits all to 1 */ - if (unchannelized) - t1_setreg(wc, 0x21, 0x3c); - else - t1_setreg(wc, 0x21, 0x1c|cas); /* XSP: E-bit set when async. AXS auto, XSIF to 1 */ - - - /* Generate pulse mask for E1 */ - t1_setreg(wc, 0x26, 0x54); /* XPM0 */ - t1_setreg(wc, 0x27, 0x02); /* XPM1 */ - t1_setreg(wc, 0x28, 0x00); /* XPM2 */ - module_printk("Span configured for %s/%s%s\n", framing, line, crc4); -} - -static void t1xxp_framer_start(struct t1 *wc, struct zt_span *span) -{ - int alreadyrunning = wc->span.flags & ZT_FLAG_RUNNING; - unsigned long flags; - - if (wc->spantype == TYPE_E1) { /* if this is an E1 card */ - t1_configure_e1(wc, span->lineconfig); - } else { /* is a T1 card */ - t1_configure_t1(wc, span->lineconfig, span->txlevel); - __t1xxp_set_clear(wc, -1); - } - - spin_lock_irqsave(&wc->reglock, flags); - if (!alreadyrunning) - wc->span.flags |= ZT_FLAG_RUNNING; - spin_unlock_irqrestore(&wc->reglock, flags); -} - -static int t1xxp_startup(struct zt_span *span) -{ - struct t1 *wc = span->pvt; - int i; - - /* initialize the start value for the entire chunk of last ec buffer */ - for (i = 0; i < span->channels; i++) { - memset(wc->ec_chunk1[i], ZT_LIN2X(0, &span->chans[i]), ZT_CHUNKSIZE); - memset(wc->ec_chunk2[i], ZT_LIN2X(0, &span->chans[i]), ZT_CHUNKSIZE); - } - - /* Reset framer with proper parameters and start */ - t1xxp_framer_start(wc, span); - debug_printk(1, "Calling startup (flags is %d)\n", span->flags); - - return 0; -} - -static int t1xxp_shutdown(struct zt_span *span) -{ - struct t1 *wc = span->pvt; - unsigned long flags; - - t1_setreg(wc, 0x46, 0x41); /* GCR: Interrupt on Activation/Deactivation of AIX, LOS */ - spin_lock_irqsave(&wc->reglock, flags); - span->flags &= ~ZT_FLAG_RUNNING; - spin_unlock_irqrestore(&wc->reglock, flags); - return 0; -} - -static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype) -{ - struct t1 *wc = chan->pvt; - int alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING; - - if (alreadyrunning && (wc->spantype != TYPE_E1)) - __t1xxp_set_clear(wc, chan->channo); - - return 0; -} - -static int t1xxp_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) -{ - struct t1 *wc = span->pvt; - - /* Do we want to SYNC on receive or not */ - wc->sync = lc->sync; - if (wc->sync) - wc->ctlreg |= 0x80; - else - wc->ctlreg &= ~0x80; - - /* If already running, apply changes immediately */ - if (span->flags & ZT_FLAG_RUNNING) - return t1xxp_startup(span); - - return 0; -} - -static int t1xxp_rbsbits(struct zt_chan *chan, int bits) -{ - u_char m,c; - int n,b; - struct t1 *wc = chan->pvt; - unsigned long flags; - - debug_printk(2, "Setting bits to %d on channel %s\n", bits, chan->name); - if (wc->spantype == TYPE_E1) { /* do it E1 way */ - if (chan->chanpos == 16) - return 0; - - n = chan->chanpos - 1; - if (chan->chanpos > 15) n--; - b = (n % 15); - spin_lock_irqsave(&wc->reglock, flags); - c = wc->txsigs[b]; - m = (n / 15) << 2; /* nibble selector */ - c &= (0xf << m); /* keep the other nibble */ - c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ - wc->txsigs[b] = c; - spin_unlock_irqrestore(&wc->reglock, flags); - /* output them to the chip */ - t1_setreg_full(wc,0x71 + b,c,1,NOT_VPM); - } else if (wc->span.lineconfig & ZT_CONFIG_D4) { - n = chan->chanpos - 1; - b = (n / 4); - spin_lock_irqsave(&wc->reglock, flags); - c = wc->txsigs[b]; - m = ((3 - (n % 4)) << 1); /* nibble selector */ - c &= ~(0x3 << m); /* keep the other nibble */ - c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */ - wc->txsigs[b] = c; - spin_unlock_irqrestore(&wc->reglock, flags); - /* output them to the chip */ - t1_setreg_full(wc,0x70 + b,c,1,NOT_VPM); - t1_setreg_full(wc,0x70 + b + 6,c,1,NOT_VPM); - } else if (wc->span.lineconfig & ZT_CONFIG_ESF) { - n = chan->chanpos - 1; - b = (n / 2); - spin_lock_irqsave(&wc->reglock, flags); - c = wc->txsigs[b]; - m = ((n % 2) << 2); /* nibble selector */ - c &= (0xf << m); /* keep the other nibble */ - c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ - wc->txsigs[b] = c; - spin_unlock_irqrestore(&wc->reglock, flags); - /* output them to the chip */ - t1_setreg_full(wc,0x70 + b,c,1,NOT_VPM); - } - debug_printk(2,"Finished setting RBS bits\n"); - - return 0; -} - -static inline void __t1_check_sigbits_reads(struct t1 *wc) -{ - int i; - - if (!(wc->span.flags & ZT_FLAG_RUNNING)) - return; - if (wc->spantype == TYPE_E1) { - for (i = 0; i < 15; i++) { - if (t1_getreg(wc, 0x71 + i, 1)) - wc->isrreaderrors++; - } - } else if (wc->span.lineconfig & ZT_CONFIG_D4) { - for (i = 0; i < 24; i+=4) { - if (t1_getreg(wc, 0x70 + (i >> 2), 1)) - wc->isrreaderrors++; - } - } else { - for (i = 0; i < 24; i+=2) { - if (t1_getreg(wc, 0x70 + (i >> 1), 1)) - wc->isrreaderrors++; - } - } -} - -static inline void __t1_check_sigbits(struct t1 *wc) -{ - int a,i,rxs; - - if (!(wc->span.flags & ZT_FLAG_RUNNING)) - return; - if (wc->spantype == TYPE_E1) { - for (i = 0; i < 15; i++) { - a = t1_getreg_isr(wc, 0x71 + i); - if (a > -1) { - /* Get high channel in low bits */ - rxs = (a & 0xf); - if (!(wc->span.chans[i+16].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i+16].rxsig != rxs) { - spin_unlock(&wc->reglock); - zt_rbsbits(&wc->span.chans[i+16], rxs); - spin_lock(&wc->reglock); - } - } - rxs = (a >> 4) & 0xf; - if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i].rxsig != rxs) { - spin_unlock(&wc->reglock); - zt_rbsbits(&wc->span.chans[i], rxs); - spin_lock(&wc->reglock); - } - } - } else { - debug_printk(1, "no space to request register in isr\n"); - } - } - } else if (wc->span.lineconfig & ZT_CONFIG_D4) { - for (i = 0; i < 24; i+=4) { - a = t1_getreg_isr(wc, 0x70 + (i>>2)); - if (a > -1) { - /* Get high channel in low bits */ - rxs = (a & 0x3) << 2; - if (!(wc->span.chans[i+3].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i+3].rxsig != rxs) { - spin_unlock(&wc->reglock); - zt_rbsbits(&wc->span.chans[i+3], rxs); - spin_lock(&wc->reglock); - } - } - rxs = (a & 0xc); - if (!(wc->span.chans[i+2].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i+2].rxsig != rxs) { - spin_unlock(&wc->reglock); - zt_rbsbits(&wc->span.chans[i+2], rxs); - spin_lock(&wc->reglock); - } - } - rxs = (a >> 2) & 0xc; - if (!(wc->span.chans[i+1].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i+1].rxsig != rxs) { - spin_unlock(&wc->reglock); - zt_rbsbits(&wc->span.chans[i+1], rxs); - spin_lock(&wc->reglock); - } - } - rxs = (a >> 4) & 0xc; - if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i].rxsig != rxs) { - spin_unlock(&wc->reglock); - zt_rbsbits(&wc->span.chans[i], rxs); - spin_lock(&wc->reglock); - } - } - } - } - } else { - for (i = 0; i < 24; i+=2) { - a = t1_getreg_isr(wc, 0x70 + (i>>1)); - if (a > -1) { - /* Get high channel in low bits */ - rxs = (a & 0xf); - if (!(wc->span.chans[i+1].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i+1].rxsig != rxs) { - spin_unlock(&wc->reglock); - zt_rbsbits(&wc->span.chans[i+1], rxs); - spin_lock(&wc->reglock); - } - } - rxs = (a >> 4) & 0xf; - if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { - if (wc->span.chans[i].rxsig != rxs) { - spin_unlock(&wc->reglock); - zt_rbsbits(&wc->span.chans[i], rxs); - spin_lock(&wc->reglock); - } - } - } - } - } -} - -static int t1xxp_maint(struct zt_span *span, int cmd) -{ - struct t1 *wc = span->pvt; - - if (wc->spantype == TYPE_E1) { - switch (cmd) { - case ZT_MAINT_NONE: - module_printk("XXX Turn off local and remote loops E1 XXX\n"); - break; - case ZT_MAINT_LOCALLOOP: - module_printk("XXX Turn on local loopback E1 XXX\n"); - break; - case ZT_MAINT_REMOTELOOP: - module_printk("XXX Turn on remote loopback E1 XXX\n"); - break; - case ZT_MAINT_LOOPUP: - module_printk("XXX Send loopup code E1 XXX\n"); - break; - case ZT_MAINT_LOOPDOWN: - module_printk("XXX Send loopdown code E1 XXX\n"); - break; - case ZT_MAINT_LOOPSTOP: - module_printk("XXX Stop sending loop codes E1 XXX\n"); - break; - default: - module_printk("Unknown E1 maint command: %d\n", cmd); - break; - } - } else { - switch (cmd) { - case ZT_MAINT_NONE: - module_printk("XXX Turn off local and remote loops T1 XXX\n"); - break; - case ZT_MAINT_LOCALLOOP: - module_printk("XXX Turn on local loop and no remote loop XXX\n"); - break; - case ZT_MAINT_REMOTELOOP: - module_printk("XXX Turn on remote loopup XXX\n"); - break; - case ZT_MAINT_LOOPUP: - t1_setreg(wc, 0x21, 0x50); /* FMR5: Nothing but RBS mode */ - break; - case ZT_MAINT_LOOPDOWN: - t1_setreg(wc, 0x21, 0x60); /* FMR5: Nothing but RBS mode */ - break; - case ZT_MAINT_LOOPSTOP: - t1_setreg(wc, 0x21, 0x40); /* FMR5: Nothing but RBS mode */ - break; - default: - module_printk("Unknown T1 maint command: %d\n", cmd); - break; - } - } - - return 0; -} - -static int t1xxp_open(struct zt_chan *chan) -{ - struct t1 *wc = chan->pvt; - - if (wc->dead) - return -ENODEV; - wc->usecount++; - -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#else - try_module_get(THIS_MODULE); -#endif - - return 0; -} - -static int t1xxp_close(struct zt_chan *chan) -{ - struct t1 *wc = chan->pvt; - - wc->usecount--; - -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#else - module_put(THIS_MODULE); -#endif - - /* If we're dead, release us now */ - if (!wc->usecount && wc->dead) - t1_release(wc); - - return 0; -} - -static int t1xxp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) -{ - struct t4_regs regs; - unsigned int x; - struct t1 *wc = chan->pvt; - - switch (cmd) { - case WCT4_GET_REGS: - wc = chan->pvt; - for (x = 0; x < sizeof(regs.pci) / sizeof(regs.pci[0]); x++) -#if 1 - regs.pci[x] = (inb(wc->iobase + (x << 2))) | - (inb(wc->iobase + (x << 2) + 1) << 8) | - (inb(wc->iobase + (x << 2) + 2) << 16) | - (inb(wc->iobase + (x << 2) + 3) << 24); -#else - regs.pci[x] = (inb(wc->iobase + x)); -#endif - - for (x = 0; x < sizeof(regs.regs) / sizeof(regs.regs[0]); x++) - regs.regs[x] = t1_getreg(wc, x, 0); - - if (copy_to_user((struct t4_regs *) data, ®s, sizeof(regs))) - return -EFAULT; - break; -#ifdef VPM_SUPPORT - case ZT_TONEDETECT: - if (get_user(x, (int *) data)) - return -EFAULT; - if (!wc->vpm150m) - return -ENOSYS; - if (wc->vpm150m && (x && !vpmdtmfsupport)) - return -ENOSYS; - if (x & ZT_TONEDETECT_ON) { - set_bit(chan->chanpos - 1, &wc->dtmfmask); - module_printk("turning on tone detection\n"); - } else { - clear_bit(chan->chanpos - 1, &wc->dtmfmask); - module_printk("turning off tone detection\n"); - } - if (x & ZT_TONEDETECT_MUTE) { - if(wc->vpm150m) - set_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); - } else { - if(wc->vpm150m) - clear_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); - } - return 0; -#endif - default: - return -ENOTTY; - } - return 0; -} - -#ifdef VPM_SUPPORT - -#include "adt_lec.c" - -static int t1xxp_echocan_with_params(struct zt_chan *chan, struct zt_echocanparams *ecp, struct zt_echocanparam *p) -{ - struct adt_lec_params params; - struct t1 *wc = chan->pvt; - struct vpm150m *vpm150m = wc->vpm150m; - unsigned int flags; - struct vpm150m_workentry *work; - unsigned int ret; - - if (!wc->vpm150m) - return -ENODEV; - - adt_lec_init_defaults(¶ms, 32); - - if ((ret = adt_lec_parse_params(¶ms, ecp, p))) - return ret; - - /* we can't really control the tap length, but the value is used - to control whether the ec is on or off, so translate it */ - params.tap_length = ecp->tap_length ? 1 : 0; - - if (!(work = kmalloc(sizeof(*work), GFP_KERNEL))) - return -ENOMEM; - - work->params = params; - work->wc = wc; - work->chan = chan; - spin_lock_irqsave(&vpm150m->lock, flags); - list_add_tail(&work->list, &vpm150m->worklist); - spin_unlock_irqrestore(&vpm150m->lock, flags); - - /* we must do this later since we cannot sleep in the echocan function */ - if (test_bit(VPM150M_ACTIVE, &vpm150m->control)) - queue_work(vpm150m->wq, &vpm150m->work_echocan); - - return 0; /* how do I return the status since it is done later by the workqueue? */ -} -#endif - -static int t1_software_init(struct t1 *wc) -{ - int x; - - /* Find position */ - for (x = 0; x < sizeof(ifaces) / sizeof(ifaces[0]); x++) { - if (ifaces[x] == wc) { - debug_printk(1, "software init for card %d\n",x); - break; - } - } - - if (x == sizeof(ifaces) / sizeof(ifaces[0])) - return -1; - - t4_serial_setup(wc); - - wc->num = x; - sprintf(wc->span.name, "WCT1/%d", wc->num); - snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num); - wc->span.manufacturer = "Digium"; - strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); - -#if defined(VPM_SUPPORT) - if (wc->vpm150m) - strncat(wc->span.devicetype, " with VPMADT032", sizeof(wc->span.devicetype) - 1); -#endif - - snprintf(wc->span.location, sizeof(wc->span.location) - 1, - "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); - - wc->span.spanconfig = t1xxp_spanconfig; - wc->span.chanconfig = t1xxp_chanconfig; - wc->span.irq = wc->dev->irq; - wc->span.startup = t1xxp_startup; - wc->span.shutdown = t1xxp_shutdown; - wc->span.rbsbits = t1xxp_rbsbits; - wc->span.maint = t1xxp_maint; - wc->span.open = t1xxp_open; - wc->span.close = t1xxp_close; - wc->span.ioctl = t1xxp_ioctl; -#ifdef VPM_SUPPORT - wc->span.echocan_with_params = t1xxp_echocan_with_params; -#endif - - if (wc->spantype == TYPE_E1) { - if (unchannelized) - wc->span.channels = 32; - else - wc->span.channels = 31; - wc->span.spantype = "E1"; - wc->span.linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4; - wc->span.deflaw = ZT_LAW_ALAW; - } else { - wc->span.channels = 24; - wc->span.spantype = "T1"; - wc->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; - wc->span.deflaw = ZT_LAW_MULAW; - } - wc->span.chans = wc->chans; - wc->span.flags = ZT_FLAG_RBS; - wc->span.pvt = wc; - init_waitqueue_head(&wc->span.maintq); - for (x = 0; x < wc->span.channels; x++) { - sprintf(wc->chans[x].name, "WCT1/%d/%d", wc->num, x + 1); - wc->chans[x].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_EM_E1 | - ZT_SIG_FXSLS | ZT_SIG_FXSGS | - ZT_SIG_FXSKS | ZT_SIG_FXOLS | ZT_SIG_DACS_RBS | - ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF; - wc->chans[x].pvt = wc; - wc->chans[x].chanpos = x + 1; - } - if (zt_register(&wc->span, 0)) { - module_printk("Unable to register span with Zaptel\n"); - return -1; - } - wc->initialized = 1; - - return 0; -} - -#ifdef VPM_SUPPORT -static inline unsigned char t1_vpm_in(struct t1 *wc, int unit, const unsigned int addr) -{ - return t1_getreg_full(wc, addr, 0, unit); -} - -static inline unsigned char t1_vpm_out(struct t1 *wc, int unit, const unsigned int addr, const unsigned char val) -{ - return t1_setreg_full(wc, addr, val, 0, unit); -} - -#endif - -static int t1_hardware_post_init(struct t1 *wc) -{ - unsigned int reg; - int x; - - /* T1 or E1 */ - if (t1e1override > -1) { - if (t1e1override) - wc->spantype = TYPE_E1; - else - wc->spantype = TYPE_T1; - } else { - if (t1_getpins(wc,0) & 0x01) /* returns 1 for T1 mode */ - wc->spantype = TYPE_T1; - else - wc->spantype = TYPE_E1; - } - debug_printk(1, "spantype: %s\n", wc->spantype==1 ? "T1" : "E1"); - - if (wc->spantype == TYPE_E1) { - if (unchannelized) - wc->chanmap = chanmap_e1uc; - else - wc->chanmap = chanmap_e1; - } else - wc->chanmap = chanmap_t1; - /* what version of the FALC are we using? */ - reg = t1_setreg(wc, 0x4a, 0xaa); - reg = t1_getreg(wc, 0x4a, 0); - debug_printk(1, "FALC version: %08x\n", reg); - - /* make sure reads and writes work */ - for (x = 0; x < 256; x++) { - t1_setreg(wc, 0x14, x); - if ((reg = t1_getreg(wc, 0x14, 0)) != x) - module_printk("Wrote '%x' but read '%x'\n", x, reg); - } - - /* all LED's blank */ - wc->ledtestreg = UNSET_LED_ORANGE(wc->ledtestreg); - wc->ledtestreg = UNSET_LED_REDGREEN(wc->ledtestreg); - t1_setleds(wc, wc->ledtestreg, 0); - -#ifdef VPM_SUPPORT - t1_vpm150m_init(wc); - if (wc->vpm150m) { - module_printk("VPM present and operational (Firmware version %x)\n", wc->vpm150m->version); - wc->ctlreg |= 0x10; /* turn on vpm (RX audio from vpm module) */ - if (vpmtsisupport) { - debug_printk(1, "enabling VPM TSI pin\n"); - wc->ctlreg |= 0x01; /* turn on vpm timeslot interchange pin */ - } - } -#endif - - return 0; -} - -static inline void __t1_check_alarms_reads(struct t1 *wc) -{ - if (!(wc->span.flags & ZT_FLAG_RUNNING)) - return; - - if (t1_getreg(wc, 0x4c, 1)) - wc->isrreaderrors++; - if (t1_getreg(wc, 0x20, 1)) - wc->isrreaderrors++; - if (t1_getreg(wc, 0x4d, 1)) - wc->isrreaderrors++; -} - -static inline void __t1_check_alarms(struct t1 *wc) -{ - unsigned char c,d; - int alarms; - int x,j; - unsigned char fmr4; /* must read this always */ - - if (!(wc->span.flags & ZT_FLAG_RUNNING)) - return; - - c = t1_getreg_isr(wc, 0x4c); - fmr4 = t1_getreg_isr(wc, 0x20); /* must read this even if we don't use it */ - d = t1_getreg_isr(wc, 0x4d); - - /* Assume no alarms */ - alarms = 0; - - /* And consider only carrier alarms */ - wc->span.alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); - - if (wc->spantype == TYPE_E1) { - if (c & 0x04) { - /* No multiframe found, force RAI high after 400ms only if - we haven't found a multiframe since last loss - of frame */ - if (!wc->flags.nmf) { - t1_setreg_full(wc, 0x20, 0x9f | 0x20, 1, NOT_VPM); /* LIM0: Force RAI High */ - wc->flags.nmf = 1; - module_printk("NMF workaround on!\n"); - } - t1_setreg_full(wc, 0x1e, 0xc3, 1, NOT_VPM); /* Reset to CRC4 mode */ - t1_setreg_full(wc, 0x1c, 0xf2, 1, NOT_VPM); /* Force Resync */ - t1_setreg_full(wc, 0x1c, 0xf0, 1, NOT_VPM); /* Force Resync */ - } else if (!(c & 0x02)) { - if (wc->flags.nmf) { - t1_setreg_full(wc, 0x20, 0x9f, 1, NOT_VPM); /* LIM0: Clear forced RAI */ - wc->flags.nmf = 0; - module_printk("NMF workaround off!\n"); - } - } - } else { - /* Detect loopup code if we're not sending one */ - if ((!wc->span.mainttimer) && (d & 0x08)) { - /* Loop-up code detected */ - if ((wc->loopupcnt++ > 80) && (wc->span.maintstat != ZT_MAINT_REMOTELOOP)) { - t1_setreg_full(wc, 0x36, 0x08, 1, NOT_VPM); /* LIM0: Disable any local loop */ - t1_setreg_full(wc, 0x37, 0xf6, 1, NOT_VPM); /* LIM1: Enable remote loop */ - wc->span.maintstat = ZT_MAINT_REMOTELOOP; - } - } else - wc->loopupcnt = 0; - /* Same for loopdown code */ - if ((!wc->span.mainttimer) && (d & 0x10)) { - /* Loop-down code detected */ - if ((wc->loopdowncnt++ > 80) && (wc->span.maintstat == ZT_MAINT_REMOTELOOP)) { - t1_setreg_full(wc, 0x36, 0x08, 1, NOT_VPM); /* LIM0: Disable any local loop */ - t1_setreg_full(wc, 0x37, 0xf0, 1, NOT_VPM); /* LIM1: Disable remote loop */ - wc->span.maintstat = ZT_MAINT_NONE; - } - } else - wc->loopdowncnt = 0; - } - - if (wc->span.lineconfig & ZT_CONFIG_NOTOPEN) { - for (x=0,j=0;x < wc->span.channels;x++) - if ((wc->span.chans[x].flags & ZT_FLAG_OPEN) || - (wc->span.chans[x].flags & ZT_FLAG_NETDEV)) - j++; - if (!j) - alarms |= ZT_ALARM_NOTOPEN; - } - - if (c & 0xa0) { - if (wc->alarmcount >= alarmdebounce) { - if (!unchannelized) - alarms |= ZT_ALARM_RED; - } else - wc->alarmcount++; - } else - wc->alarmcount = 0; - if (c & 0x4) - alarms |= ZT_ALARM_BLUE; - - /* Keep track of recovering */ - if ((!alarms) && wc->span.alarms) - wc->alarmtimer = ZT_ALARMSETTLE_TIME; - if (wc->alarmtimer) - alarms |= ZT_ALARM_RECOVER; - - /* If receiving alarms, go into Yellow alarm state */ - if (alarms && !wc->flags.sendingyellow) { - module_printk("Setting yellow alarm\n"); - - /* We manually do yellow alarm to handle RECOVER and NOTOPEN, otherwise it's auto anyway */ - t1_setreg_full(wc, 0x20, fmr4 | 0x20, 1, NOT_VPM); - wc->flags.sendingyellow = 1; - } else if (!alarms && wc->flags.sendingyellow) { - module_printk("Clearing yellow alarm\n"); - /* We manually do yellow alarm to handle RECOVER */ - t1_setreg_full(wc, 0x20, fmr4 & ~0x20, 1, NOT_VPM); - wc->flags.sendingyellow = 0; - } - - if ((c & 0x10) && !unchannelized) - alarms |= ZT_ALARM_YELLOW; - if (wc->span.mainttimer || wc->span.maintstat) - alarms |= ZT_ALARM_LOOPBACK; - wc->span.alarms = alarms; - spin_unlock(&wc->reglock); - zt_alarm_notify(&wc->span); - spin_lock(&wc->reglock); -} - -static inline void __handle_leds(struct t1 *wc) -{ - if (wc->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) { - wc->blinktimer++; - if (wc->blinktimer == 160) - wc->ledtestreg = SET_LED_RED(wc->ledtestreg); - if (wc->blinktimer == 480) { - wc->ledtestreg = UNSET_LED_REDGREEN(wc->ledtestreg); - wc->blinktimer = 0; - } - } else if (wc->span.alarms & ZT_ALARM_YELLOW) { - wc->yellowtimer++; - if (!(wc->yellowtimer % 2)) - wc->ledtestreg = SET_LED_RED(wc->ledtestreg); - else - wc->ledtestreg = SET_LED_GREEN(wc->ledtestreg); - } else { - if (wc->span.maintstat != ZT_MAINT_NONE) - wc->ledtestreg = SET_LED_ORANGE(wc->ledtestreg); - else - wc->ledtestreg = UNSET_LED_ORANGE(wc->ledtestreg); - if (wc->span.flags & ZT_FLAG_RUNNING) - wc->ledtestreg = SET_LED_GREEN(wc->ledtestreg); - else - wc->ledtestreg = UNSET_LED_REDGREEN(wc->ledtestreg); - } - - if (wc->ledtestreg != wc->ledlastvalue) { - t1_setleds(wc, wc->ledtestreg, 1); - wc->ledlastvalue = wc->ledtestreg; - } -} - - -static void __t1_do_counters(struct t1 *wc) -{ - if (wc->alarmtimer) { - if (!--wc->alarmtimer) { - wc->span.alarms &= ~(ZT_ALARM_RECOVER); - zt_alarm_notify(&wc->span); - } - } -} - -static inline void t1_isr_misc(struct t1 *wc) -{ - unsigned int x; - - if (unlikely(!wc->initialized)) return; - - __handle_leds(wc); - - __t1_do_counters(wc); - - x = wc->intcount & 0xF; - switch (x) { - case 0: - __t1_check_sigbits_reads(wc); - break; - case 1: - if (!(wc->intcount & 0x30)) { - __t1_check_alarms_reads(wc); - wc->alarms_read=1; - } - break; - case 2: - break; - case 4: - break; - case 5: - break; - case 7: - __t1_check_sigbits(wc); - break; - case 8: - if (wc->alarms_read) { - __t1_check_alarms(wc); - wc->alarms_read=0; - } - break; - case 9: - clean_leftovers(wc); - break; - } -} - -static inline void t1_transmitprep(struct t1 *wc, int dbl) -{ - volatile unsigned char *writechunk; - int x; - int y; - int chan; - - dbl = dbl % 2; - - writechunk = (volatile unsigned char *)(wc->writechunk); - if (dbl) - /* Write is at interrupt address. Start writing from normal offset */ - writechunk += SFRAME_SIZE; - - /* Calculate Transmission */ - if (likely(wc->initialized)) { - spin_unlock(&wc->reglock); - zt_transmit(&wc->span); - spin_lock(&wc->reglock); - } - - for (x = 0; x < ZT_CHUNKSIZE; x++) { - if (likely(wc->initialized)) { - for (chan = 0; chan < wc->span.channels; chan++) - writechunk[(chan+1)*2] = wc->chans[chan].writechunk[x]; - } - - /* process the command queue */ - for (y = 0; y < 7; y++) { - cmd_dequeue(wc, writechunk, x, y); - } -#ifdef VPM_SUPPORT - if(likely(wc->vpm150m)) { - vpm150m_cmd_dequeue(wc, writechunk, x); - } -#endif - - if (x < ZT_CHUNKSIZE - 1) { - writechunk[EFRAME_SIZE] = wc->ctlreg; - writechunk[EFRAME_SIZE + 1] = wc->txident++; - } - writechunk += (EFRAME_SIZE + EFRAME_GAP); - } -} - -static inline void cmd_retransmit(struct t1 *wc) -{ - unsigned int x; - - for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { - if (!(wc->cmdq.cmds[x].flags & __CMD_FIN)) { - wc->cmdq.cmds[x].flags &= ~(__CMD_TX) ; /* clear __CMD_TX */ - wc->cmdq.cmds[x].ident = 0; - } - } -} - -static inline void t1_receiveprep(struct t1 *wc, int dbl) -{ - volatile unsigned char *readchunk; - int x,chan; - unsigned char expected; - - dbl = dbl % 2; - - readchunk = (volatile unsigned char *)wc->readchunk; - if (dbl) - readchunk += SFRAME_SIZE; - for (x = 0; x < ZT_CHUNKSIZE; x++) { - if (likely(wc->initialized)) { - for (chan = 0; chan < wc->span.channels; chan++) { - wc->chans[chan].readchunk[x]= readchunk[(chan+1)*2]; - } - } - if (x < ZT_CHUNKSIZE - 1) { - expected = wc->rxident+1; - wc->rxident = readchunk[EFRAME_SIZE + 1]; - wc->statreg = readchunk[EFRAME_SIZE + 2]; - if (wc->rxident != expected) { - wc->span.irqmisses++; - cmd_retransmit(wc); - if (unlikely(debug && wc->initialized)) - module_printk("oops: rxident=%d expected=%d\n", wc->rxident, expected); - } - } - cmd_decipher(wc, readchunk); -#ifdef VPM_SUPPORT - if(wc->vpm150m) - vpm150m_cmd_decipher(wc, readchunk); -#endif - readchunk += (EFRAME_SIZE + EFRAME_GAP); - } - - /* echo cancel */ - if (likely(wc->initialized)) { - spin_unlock(&wc->reglock); - for (x = 0; x < wc->span.channels; x++) { - zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->ec_chunk2[x]); - memcpy(wc->ec_chunk2[x],wc->ec_chunk1[x],ZT_CHUNKSIZE); - memcpy(wc->ec_chunk1[x],wc->chans[x].writechunk,ZT_CHUNKSIZE); - } - zt_receive(&wc->span); - spin_lock(&wc->reglock); - } - - /* Wake up anyone sleeping to read/write a new register */ - wake_up_interruptible(&wc->regq); -} - -static inline int t1_check_descriptor(struct t1 *wc, int tx) -{ - int o2 = 0; - - if (!tx) { - o2 += ERING_SIZE * 4; - o2 += wc->rdbl * 4; - } else { - o2 += wc->tdbl * 4; - } - - if (!(wc->descripchunk[o2] & 0x80000000)) { - if (tx) { - wc->txints++; - t1_transmitprep(wc, wc->tdbl); - t1_reinit_descriptor(wc, tx, wc->tdbl, "txchk"); - wc->tdbl = (wc->tdbl + 1) % ERING_SIZE; - wc->intcount++; - t1_isr_misc(wc); - } else { - wc->rxints++; - t1_receiveprep(wc, wc->rdbl); - t1_reinit_descriptor(wc, tx, wc->rdbl, "rxchk"); - wc->rdbl = (wc->rdbl + 1) % ERING_SIZE; - } - return 1; - } - return 0; -} - -static int t1_hardware_init(struct t1 *wc) -{ - /* Hardware stuff */ - unsigned int reg; - unsigned long newjiffies; - - /* Initialize descriptors */ - t1_init_descriptors(wc); - - /* Enable I/O Access */ - pci_read_config_dword(wc->dev, PCI_COMMAND, ®); - reg |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - pci_write_config_dword(wc->dev, PCI_COMMAND, reg); - debug_printk(1, "PCI Config reg is %08x\n", reg); - - t1_setctl(wc, 0x0000, 0xfff88001); - - newjiffies = jiffies + HZ/10; - while(((reg = t1_getctl(wc,0x0000)) & 0x00000001) && ( time_after(newjiffies,jiffies) )); - debug_printk(1, "ctlreg 0x0000 now=%08x!\n", reg); - - t1_setctl(wc, 0x0000, 0xfff88000); - - /* Configure watchdogs, access, etc */ - t1_setctl(wc, 0x0030, 0x00280048); - t1_setctl(wc, 0x0078, 0x00000013 /* | (1 << 28) */); - - reg = t1_getctl(wc, 0x00fc); - t1_setctl(wc, 0x00fc, (reg & ~0x7) | 0x7); /* normal mode */ - t1_setsdi(wc, 0x00, 0x0100); - t1_setsdi(wc, 0x16, 0x2100); - debug_printk(1, "Detected SDI REG0: %08x\n", t1_getsdi(wc, 0x00)); - debug_printk(1, "Detected SDI REG1: %08x\n", t1_getsdi(wc, 0x01)); - debug_printk(1, "Detected SDI REG2: %08x\n", t1_getsdi(wc, 0x02)); - - reg = t1_getctl(wc, 0x00fc); - debug_printk(1, "(pre) Reg fc is %08x\n", reg); - - t1_setctl(wc, 0x00fc, (reg & ~0x7) | 0x4); /* mac only */ - t1_setsdi(wc, 0x00, 0x0100); /* full duplex */ - t1_setsdi(wc, 0x16, 0x2100); - reg = t1_getctl(wc, 0x00fc); - debug_printk(1, "(post) ctlreg 0xfc=%08x\n", reg); - debug_printk(1, "Detected SDI REG2: %08x\n", t1_getsdi(wc, 0x02)); - debug_printk(1, "ctlreg 0x0088=%08x\n", t1_getctl(wc, 0x0088)); - - return 0; -} - - -ZAP_IRQ_HANDLER(te12xp_interrupt) -{ - struct t1 *wc = dev_id; - unsigned int ints; - int res; - - /* Read interrupts */ - spin_lock(&wc->reglock); - ints = __t1_getctl(wc, 0x0028); - - if (!ints) { - spin_unlock(&wc->reglock); -#ifdef LINUX26 - return IRQ_NONE; -#else - return; -#endif - } - - /* clear interrupts interrupts (we only get here if interrupt is for us) */ - __t1_setctl(wc, 0x0028, ints); - ints &= wc->intmask; - - if (ints & 0x00000041) { - do { - res = t1_check_descriptor(wc, 0); - res |= t1_check_descriptor(wc, 1); - } while(res); - } - spin_unlock(&wc->reglock); - -#ifdef LINUX26 - return IRQ_RETVAL(1); -#endif -} - -static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct t1 *wc; - struct t1_desc *d = (struct t1_desc *) ent->driver_data; - unsigned int x; - - for (x = 0; x < sizeof(ifaces) / sizeof(ifaces[0]); x++) - if (!ifaces[x]) break; - - if (x >= sizeof(ifaces) / sizeof(ifaces[0])) { - module_printk("Too many interfaces\n"); - return -EIO; - } - - if (pci_enable_device(pdev)) - return -EIO; - - wc = kmalloc(sizeof(*wc), GFP_KERNEL); - if (!wc) - return -ENOMEM; - - ifaces[x] = wc; - memset(wc, 0, sizeof(*wc)); - spin_lock_init(&wc->reglock); - wc->iobase = pci_resource_start(pdev, 0); - wc->dev = pdev; - wc->variety = d->name; - /* Keep track of whether we need to free the region */ - if (request_region(wc->iobase, 0xff, te12xp_driver.name)) - wc->freeregion = 1; - - /* Allocate enough memory for two zt chunks, receive and transmit. - * Each sample uses 32 bits. Allocate an extra set just for - * control too */ - wc->writechunk = (int *) pci_alloc_consistent(pdev, PCI_WINDOW_SIZE, &wc->writedma); - if (!wc->writechunk) { - module_printk("Unable to allocate DMA-able memory\n"); - if (wc->freeregion) - release_region(wc->iobase, 0xff); - kfree(wc); - return -ENOMEM; - } - - wc->readchunk = wc->writechunk + SFRAME_SIZE / 2; /* in doublewords */ - wc->readdma = wc->writedma + SFRAME_SIZE * 2; /* in bytes */ - - wc->descripchunk = wc->readchunk + SFRAME_SIZE / 2; /* in doublewords */ - wc->descripdma = wc->readdma + SFRAME_SIZE * 2; /* in bytes */ - - /* Initialize Write/Buffers to all blank data */ - memset((void *)wc->writechunk, 0x00, SFRAME_SIZE * 2); - memset((void *)wc->readchunk, 0x00, SFRAME_SIZE * 2); - - init_waitqueue_head(&wc->regq); - - /* Enable bus mastering */ - pci_set_master(pdev); - - /* Keep track of which device we are */ - pci_set_drvdata(pdev, wc); - - if (request_irq(pdev->irq, te12xp_interrupt, ZAP_IRQ_SHARED, te12xp_driver.name, wc)) { - module_printk("Unable to request IRQ %d\n", pdev->irq); - if (wc->freeregion) - release_region(wc->iobase, 0xff); - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *) wc->writechunk, wc->writedma); - pci_set_drvdata(pdev, NULL); - kfree(wc); - return -EIO; - } - - if (t1_hardware_init(wc)) { - /* Set Reset Low */ - t1_stop_dma(wc); - /* Free Resources */ - free_irq(pdev->irq, wc); - if (wc->freeregion) - release_region(wc->iobase, 0xff); - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *) wc->writechunk, wc->writedma); - pci_set_drvdata(pdev, NULL); - - kfree(wc); - return -EIO; - - } - - t1_enable_interrupts(wc); - t1_start_dma(wc); - t1_hardware_post_init(wc); - t1_software_init(wc); - module_printk("Found a %s\n", wc->variety); - - return 0; -} - -static void __devexit te12xp_remove_one(struct pci_dev *pdev) -{ - struct t1 *wc = pci_get_drvdata(pdev); -#ifdef VPM_SUPPORT - unsigned long flags; - struct vpm150m *vpm150m = wc->vpm150m; -#endif - if (!wc) - return; - -#ifdef VPM_SUPPORT - if(vpm150m) { - clear_bit(VPM150M_DTMFDETECT, &vpm150m->control); - clear_bit(VPM150M_ACTIVE, &vpm150m->control); - flush_workqueue(vpm150m->wq); - destroy_workqueue(vpm150m->wq); - } -#endif - /* Stop any DMA */ - t1_stop_dma(wc); - - /* In case hardware is still there */ - t1_disable_interrupts(wc); - - if (debug && wc->isrreaderrors) - debug_printk(1, "isrreaderrors=%d\n", wc->isrreaderrors); - - /* Immediately free resources */ - free_irq(pdev->irq, wc); - pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma); - -#ifdef VPM_SUPPORT - if(vpm150m) { - spin_lock_irqsave(&wc->reglock, flags); - wc->vpm150m = NULL; - vpm150m->wc = NULL; - spin_unlock_irqrestore(&wc->reglock, flags); - kfree(wc->vpm150m); - } -#endif - /* Release span, possibly delayed */ - if (!wc->usecount) - t1_release(wc); - else - wc->dead = 1; -} - -static struct pci_device_id te12xp_pci_tbl[] = { - { 0xd161, 0x0120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &te120p}, - { 0xd161, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &te121}, - { 0xd161, 0x8001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &te122}, - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, te12xp_pci_tbl); - -struct pci_driver te12xp_driver = { - name: "wcte12x[p]", - probe: te12xp_init_one, -#ifdef LINUX26 - remove: __devexit_p(te12xp_remove_one), -#else - remove: te12xp_remove_one, -#endif - suspend: NULL, - resume: NULL, - id_table: te12xp_pci_tbl, -}; - -static int __init te12xp_init(void) -{ - int res; - - res = zap_pci_module(&te12xp_driver); - - return res ? -ENODEV : 0; -} - - -static void __exit te12xp_cleanup(void) -{ - pci_unregister_driver(&te12xp_driver); -} - -#ifdef LINUX26 -module_param(debug, int, S_IRUGO | S_IWUSR); -module_param(loopback, int, S_IRUGO | S_IWUSR); -module_param(t1e1override, int, S_IRUGO | S_IWUSR); -module_param(j1mode, int, S_IRUGO | S_IWUSR); -module_param(alarmdebounce, int, S_IRUGO | S_IWUSR); -#ifdef VPM_SUPPORT -module_param(vpmsupport, int, S_IRUGO | S_IWUSR); -module_param(vpmdtmfsupport, int, S_IRUGO | S_IWUSR); -module_param(vpmtsisupport, int, S_IRUGO | S_IWUSR); -#endif -#else -MODULE_PARM(debug, "i"); -MODULE_PARM(loopback, "i"); -MODULE_PARM(t1e1override, "i"); -MODULE_PARM(j1mode, "i"); -MODULE_PARM(alarmdebounce, "i"); -#ifdef VPM_SUPPORT -MODULE_PARM(vpmsupport, "i"); -MODULE_PARM(vpmdtmfsupport, "i"); -MODULE_PARM(vpmtsisupport, "i"); -MODULE_PARM(vpmnlptype, "i"); -MODULE_PARM(vpmnlpthresh, "i"); -MODULE_PARM(vpmnlpmaxsupp, "i"); -#endif -#endif - -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif - -module_init(te12xp_init); -module_exit(te12xp_cleanup); diff --git a/wcte12xp/gpakenum.h b/wcte12xp/gpakenum.h deleted file mode 100644 index ed14a1a..0000000 --- a/wcte12xp/gpakenum.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2005, Adaptive Digital Technologies, Inc. - * - * File Name: gpakenum.h - * - * Description: - * This file contains common enumerations related to G.PAK application - * software. - * - * Version: 1.0 - * - * Revision History: - * 06/15/05 - Initial release. - * - * This program has been released under the terms of the GPL version 2 by - * permission of Adaptive Digital Technologies, Inc. The standard - * GPL disclaimer is given inline below for your convenience. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _GPAKENUM_H /* prevent multiple inclusion */ -#define _GPAKENUM_H - -/* G.PAK Serial Port Word Size */ -typedef enum -{ - SerWordSize8 = 0, // 8-bit seial word - SerWordSize16 = 1 // 16-bit serial word -} GpakSerWordSize_t; - -/* G.PAK Serial Port FrameSync Polarity */ -typedef enum -{ - FrameSyncActLow = 0, // active low frame sync signal - FrameSyncActHigh = 1 // active high frame sync signal -} GpakSerFrameSyncPol_t; - -/* G.PAK Serial Port Clock Polarity */ -typedef enum -{ - SerClockActLow = 0, // active low serial clock - SerClockActHigh = 1 // active high serial clock -} GpakSerClockPol_t; - -/* G.PAK Serial Port Data Delay */ -typedef enum -{ - DataDelay0 = 0, // no data delay - DataDelay1 = 1, // 1-bit data delay - DataDelay2 = 2 // 2-bit data delay -} GpakSerDataDelay_t; - -/* G.PAK Serial Port Ids. */ -typedef enum -{ - SerialPortNull = 0, // null serial port - SerialPort1 = 1, // first PCM serial stream port (McBSP0) - SerialPort2 = 2, // second PCM serial stream port (McBSP1) - SerialPort3 = 3 // third PCM serial stream port (McBSP2) -} GpakSerialPort_t; - -/* G.PAK serial port Slot Configuration selection codes. */ -typedef enum -{ - SlotCfgNone = 0, // no time slots used - SlotCfg2Groups = 2, // 2 groups of 16 time slots used, 32 Channels system - SlotCfg8Groups = 8 // 8-partition mode for 128-channel system -} GpakSlotCfg_t; - -/* G.PAK serial port Companding Mode codes. */ -typedef enum -{ - cmpPCMU=0, // u-Law - cmpPCMA=1, // A-Law - cmpNone=2 // none -} GpakCompandModes; - -/* G.PAK Active/Inactive selection codes. */ -typedef enum -{ - Disabled=0, // Inactive - Enabled=1 // Active -} GpakActivation; - -/* G.PAK Channel Type codes. */ -typedef enum -{ - inactive=0, // channel inactive - tdmToTdm=1 // tdmToTdm -} GpakChanType; - -/* G.PAK Algorithm control commands */ -typedef enum -{ - EnableEcanA = 0, // Enable A side echo canceller - BypassEcanA = 1, // Bypass A side echo canceller - ResetEcanA = 2, // Reset A side echo canceller - EnableEcanB = 3, // Enable B side echo canceller - BypassEcanB = 4, // Bypass B side echo canceller - ResetEcanB = 5, // Reset B side echo canceller - - EnableMuLawSwCompanding = 6,// Enable Mu-law Software companding - EnableALawSwCompanding = 7, // Enable Mu-law Software companding - BypassSwCompanding = 8, // Bypass Software companding - EnableDTMFMuteA = 9, // Mute A side Dtmf digit after tone detected - DisableDTMFMuteA = 10, // Do not mute A side Dtmf digit once tone detected - EnableDTMFMuteB = 11, // Mute B side Dtmf digit after tone detected - DisableDTMFMuteB = 12, // Do not mute B side Dtmf digit once tone detected - EnableFaxCngDetectA = 13, // Enable A side Fax CNG detector, channel must be configed already - DisableFaxCngDetectA = 14, // Disable A side Fax CNG detector, channel must be configed already - EnableFaxCngDetectB = 15, // Enable B side Fax CNG detector, channel must be configed already - DisableFaxCngDetectB = 16 // Disable B side Fax CNG detector, channel must be configed already -} GpakAlgCtrl_t; - -/* G.PAK Tone types. */ -typedef enum -{ - Null_tone = 0, // no tone detection - DTMF_tone = 1 // DTMF tone -} GpakToneTypes; - -/* G.PAK direction. */ -typedef enum -{ - TDMAToB = 0, // A to B - TDMBToA = 1 // B to A -} GpakTdmDirection; - - -typedef enum -{ - rate1ms=0, - rate2ms=1, - rate10ms=2 -} GpakRate_t; - -/* G.PAK Asynchronous Event Codes */ -typedef enum -{ - EventToneDetect = 0, // Tone detection event - EventDSPDebug = 7 // DSP debug data event -} GpakAsyncEventCode_t; - -/* G.PAK MF Tone Code Indices */ -typedef enum -{ - DtmfDigit1 = 0, // DTMF Digit 1 - DtmfDigit2 = 1, // DTMF Digit 2 - DtmfDigit3 = 2, // DTMF Digit 3 - DtmfDigitA = 3, // DTMF Digit A - DtmfDigit4 = 4, // DTMF Digit 4 - DtmfDigit5 = 5, // DTMF Digit 5 - DtmfDigit6 = 6, // DTMF Digit 6 - DtmfDigitB = 7, // DTMF Digit B - DtmfDigit7 = 8, // DTMF Digit 7 - DtmfDigit8 = 9, // DTMF Digit 8 - DtmfDigit9 = 10, // DTMF Digit 9 - DtmfDigitC = 11, // DTMF Digit C - DtmfDigitSt = 12, // DTMF Digit * - DtmfDigit0 = 13, // DTMF Digit 0 - DtmfDigitPnd = 14, // DTMF Digit # - DtmfDigitD = 15, // DTMF Digit D - - FaxCngDigit = 90, // Fax Calling Tone (1100 Hz) - - EndofMFDigit = 100, // End of MF digit - EndofCngDigit = 101 // End of Cng Digit -} GpakToneCodes_t; - -/* GPIO control code*/ -typedef enum -{ - GPIO_READ = 0, - GPIO_WRITE = 1, - GPIO_DIR = 2 -} GpakGPIOCotrol_t; - -#endif // end multiple inclusion diff --git a/wcte12xp/vpmadt032.c b/wcte12xp/vpmadt032.c deleted file mode 100644 index 89fd372..0000000 --- a/wcte12xp/vpmadt032.c +++ /dev/null @@ -1,1385 +0,0 @@ -/* - * Digium, Inc. Wildcard TE12xP T1/E1 card Driver - * - * Written by Michael Spiceland - * - * Adapted from the wctdm24xxp and wcte11xp drivers originally - * written by Mark Spencer - * Matthew Fredrickson - * William Meadows - * - * Copyright (C) 2007, Digium, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include - -#include "zaptel.h" - -#include "wcte12xp.h" -#include "vpmadt032.h" -#include "GpakApi.h" - -extern struct t1 *ifaces[WC_MAX_IFACES]; - -extern int vpmnlptype; -extern int vpmnlpthresh; -extern int vpmnlpmaxsupp; - -#ifdef VPM_SUPPORT - -inline void vpm150m_cmd_dequeue(struct t1 *wc, volatile unsigned char *writechunk, int whichframe) -{ - struct vpm150m_cmd *curcmd = NULL; - struct vpm150m *vpm150m = wc->vpm150m; - int x; - unsigned char leds = ~((wc->intcount / 1000) % 8) & 0x7; - - /* Skip audio */ - writechunk += 66; - - if (test_bit(VPM150M_SPIRESET, &vpm150m->control) || test_bit(VPM150M_HPIRESET, &vpm150m->control)) { - debug_printk(1, "HW Resetting VPMADT032 ...\n"); - for (x = 0; x < 4; x++) { - if (!x) { - if (test_and_clear_bit(VPM150M_SPIRESET, &vpm150m->control)) - writechunk[CMD_BYTE(x, 0, 1)] = 0x08; - else if (test_and_clear_bit(VPM150M_HPIRESET, &vpm150m->control)) - writechunk[CMD_BYTE(x, 0, 1)] = 0x0b; - } else - writechunk[CMD_BYTE(x, 0, 1)] = 0x00 | leds; - writechunk[CMD_BYTE(x, 1, 1)] = 0; - writechunk[CMD_BYTE(x, 2, 1)] = 0x00; - } - return; - } - - /* Search for something waiting to transmit */ - for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { - if ((vpm150m->cmdq[x].flags & (__VPM150M_RD | __VPM150M_WR)) && - !(vpm150m->cmdq[x].flags & (__VPM150M_FIN | __VPM150M_TX))) { - curcmd = &vpm150m->cmdq[x]; - curcmd->ident = wc->txident; - curcmd->flags |= __VPM150M_TX; - break; - } - } - if (curcmd) { -#if 0 - printk("Found command txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", curcmd->txident, curcmd->desc, curcmd->addr, curcmd->data); -#endif - if (curcmd->flags & __VPM150M_RWPAGE) { - /* Set CTRL access to page*/ - writechunk[CMD_BYTE(0, 0, 1)] = (0x8 << 4); - writechunk[CMD_BYTE(0, 1, 1)] = 0; - writechunk[CMD_BYTE(0, 2, 1)] = 0x20; - - /* Do a page write */ - if (curcmd->flags & __VPM150M_WR) - writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | 0x4) << 4); - else - writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | 0x4 | 0x1) << 4); - writechunk[CMD_BYTE(1, 1, 1)] = 0; - if (curcmd->flags & __VPM150M_WR) - writechunk[CMD_BYTE(1, 2, 1)] = curcmd->data[0] & 0xf; - else - writechunk[CMD_BYTE(1, 2, 1)] = 0; - - if (curcmd->flags & __VPM150M_WR) { - /* Fill in buffer to size */ - writechunk[CMD_BYTE(2, 0, 1)] = 0; - writechunk[CMD_BYTE(2, 1, 1)] = 0; - writechunk[CMD_BYTE(2, 2, 1)] = 0; - } else { - /* Do reads twice b/c of vpmadt032 bug */ - writechunk[CMD_BYTE(2, 0, 1)] = ((0x8 | 0x4 | 0x1) << 4); - writechunk[CMD_BYTE(2, 1, 1)] = 0; - writechunk[CMD_BYTE(2, 2, 1)] = 0; - } - - /* Clear XADD */ - writechunk[CMD_BYTE(3, 0, 1)] = (0x8 << 4); - writechunk[CMD_BYTE(3, 1, 1)] = 0; - writechunk[CMD_BYTE(3, 2, 1)] = 0; - - /* Fill in buffer to size */ - writechunk[CMD_BYTE(4, 0, 1)] = 0; - writechunk[CMD_BYTE(4, 1, 1)] = 0; - writechunk[CMD_BYTE(4, 2, 1)] = 0; - - } else { - /* Set address */ - writechunk[CMD_BYTE(0, 0, 1)] = ((0x8 | 0x4) << 4); - writechunk[CMD_BYTE(0, 1, 1)] = (curcmd->address >> 8) & 0xff; - writechunk[CMD_BYTE(0, 2, 1)] = curcmd->address & 0xff; - - /* Send/Get our data */ - if (curcmd->flags & __VPM150M_WR) { - if (curcmd->datalen > 1) - writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x1 << 1)) << 4); - else - writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x3 << 1)) << 4); - } else - if (curcmd->datalen > 1) - writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x1 << 1) | 0x1) << 4); - else - writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x3 << 1) | 0x1) << 4); - writechunk[CMD_BYTE(1, 1, 1)] = (curcmd->data[0] >> 8) & 0xff; - writechunk[CMD_BYTE(1, 2, 1)] = curcmd->data[0] & 0xff; - - if (curcmd->flags & __VPM150M_WR) { - /* Fill in */ - writechunk[CMD_BYTE(2, 0, 1)] = 0; - writechunk[CMD_BYTE(2, 1, 1)] = 0; - writechunk[CMD_BYTE(2, 2, 1)] = 0; - } else { - /* Do this again for reads b/c of the bug in vpmadt032 */ - writechunk[CMD_BYTE(2, 0, 1)] = ((0x8 | (0x3 << 1) | 0x1) << 4); - writechunk[CMD_BYTE(2, 1, 1)] = (curcmd->data[0] >> 8) & 0xff; - writechunk[CMD_BYTE(2, 2, 1)] = curcmd->data[0] & 0xff; - } - - if (curcmd->datalen > 1) { - if (curcmd->flags & __VPM150M_WR) - writechunk[CMD_BYTE(3, 0, 1)] = ((0x8 | (0x1 << 1)) << 4); - else - writechunk[CMD_BYTE(3, 0, 1)] = ((0x8 | (0x1 << 1) | 0x1) << 4); - writechunk[CMD_BYTE(3, 1, 1)] = (curcmd->data[1] >> 8) & 0xff; - writechunk[CMD_BYTE(3, 2, 1)] = curcmd->data[1] & 0xff; - } else { - /* Fill in the rest */ - writechunk[CMD_BYTE(3, 0, 1)] = 0; - writechunk[CMD_BYTE(3, 1, 1)] = 0; - writechunk[CMD_BYTE(3, 2, 1)] = 0; - } - - if (curcmd->datalen > 2) { - if (curcmd->flags & __VPM150M_WR) - writechunk[CMD_BYTE(4, 0, 1)] = ((0x8 | (0x1 << 1)) << 4); - else - writechunk[CMD_BYTE(4, 0, 1)] = ((0x8 | (0x1 << 1) | 0x1) << 4); - writechunk[CMD_BYTE(4, 1, 1)] = (curcmd->data[2] >> 8) & 0xff; - writechunk[CMD_BYTE(4, 2, 1)] = curcmd->data[2] & 0xff; - } else { - /* Fill in the rest */ - writechunk[CMD_BYTE(4, 0, 1)] = 0; - writechunk[CMD_BYTE(4, 1, 1)] = 0; - writechunk[CMD_BYTE(4, 2, 1)] = 0; - } - } - } else if (test_and_clear_bit(VPM150M_SWRESET, &vpm150m->control)) { - debug_printk(1, "Booting VPMADT032\n"); - for (x = 0; x < 7; x++) { - if (x == 0) - writechunk[CMD_BYTE(x, 0, 1)] = (0x8 << 4); - else - writechunk[CMD_BYTE(x, 0, 1)] = 0x00; - writechunk[CMD_BYTE(x, 1, 1)] = 0; - if (x == 0) - writechunk[CMD_BYTE(x, 2, 1)] = 0x01; - else - writechunk[CMD_BYTE(x, 2, 1)] = 0x00; - } - } else { - for (x = 0; x < 7; x++) { - writechunk[CMD_BYTE(x, 0, 1)] = 0x00; - writechunk[CMD_BYTE(x, 1, 1)] = 0x00; - writechunk[CMD_BYTE(x, 2, 1)] = 0x00; - } - } - - /* Add our leds in */ - for (x = 0; x < 7; x++) - writechunk[CMD_BYTE(x, 0, 1)] |= leds; - -#if 0 - int y; - for (x = 0; x < 7; x++) { - for (y = 0; y < 3; y++) { - if (writechunk[CMD_BYTE(x, y, 1)] & 0x2) { - module_printk("the test bit is high for byte %d\n", y); - } - } - } -#endif - - /* Now let's figure out if we need to check for DTMF */ - /* polling */ - if (test_bit(VPM150M_ACTIVE, &vpm150m->control) && !whichframe && !(wc->intcount % 100)) - queue_work(vpm150m->wq, &vpm150m->work_dtmf); - -#if 0 - /* This may be needed sometime in the future to troubleshoot ADT related issues. */ - if (test_bit(VPM150M_ACTIVE, &vpm150m->control) && !whichframe && !(wc->intcount % 10000)) - queue_work(vpm150m->wq, &vpm150m->work_debug); -#endif -} - -inline void vpm150m_cmd_decipher(struct t1 *wc, volatile unsigned char *readchunk) -{ - unsigned char ident; - int x, i; - - /* Skip audio */ - readchunk += 66; - /* Search for any pending results */ - for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { - if ((wc->vpm150m->cmdq[x].flags & (__VPM150M_RD | __VPM150M_WR)) && - (wc->vpm150m->cmdq[x].flags & (__VPM150M_TX)) && - !(wc->vpm150m->cmdq[x].flags & (__VPM150M_FIN))) { - ident = wc->vpm150m->cmdq[x].ident; - if (ident == wc->rxident) { - /* Store result */ - for (i = 0; i < wc->vpm150m->cmdq[x].datalen; i++) { - wc->vpm150m->cmdq[x].data[i] = (0xff & readchunk[CMD_BYTE((2 + i), 1, 1)]) << 8; - wc->vpm150m->cmdq[x].data[i] |= readchunk[CMD_BYTE((2 + i), 2, 1)]; - } - if (wc->vpm150m->cmdq[x].flags & __VPM150M_WR) { - /* Go ahead and clear out writes since they need no acknowledgement */ - wc->vpm150m->cmdq[x].flags = 0; - } else - wc->vpm150m->cmdq[x].flags |= __VPM150M_FIN; - break; - } - } - } -} - -static inline struct t1 * wc_find_iface(unsigned short dspid) -{ - int i; - struct t1 *ret = NULL; - unsigned long flags; - - spin_lock_irqsave(&ifacelock, flags); - for (i = 0; i < WC_MAX_IFACES; i++) - if (ifaces[i] && ifaces[i]->vpm150m && (ifaces[i]->vpm150m->dspid == dspid)) - ret = ifaces[i]; - spin_unlock_irqrestore(&ifacelock, flags); - - return ret; -} - -static struct vpm150m_cmd * vpm150m_empty_slot(struct t1 *wc) -{ - unsigned int x; - - for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { - if (!wc->vpm150m->cmdq[x].flags) { - return &wc->vpm150m->cmdq[x]; - } - } - return NULL; -} - -/* Wait for any outstanding commands to be completed. */ -static inline int vpm150m_io_wait(struct t1 *wc) -{ - int x; - int ret=0; - for (x=0; x < VPM150M_MAX_COMMANDS;) { - if (wc->vpm150m->cmdq[x].flags) { - if ((ret=schluffen(&wc->regq))) { - return ret; - } - x=0; - } - else { - ++x; - } - } - return ret; -} - -int t1_vpm150m_getreg_full_async(struct t1 *wc, int pagechange, unsigned int len, - unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) -{ - int ret=0; - unsigned long flags; - BUG_ON(!hit_p); - spin_lock_irqsave(&wc->reglock, flags); - (*hit_p) = vpm150m_empty_slot(wc); - if (*hit_p) { - (*hit_p)->flags = __VPM150M_RD; - if (pagechange) { - (*hit_p)->flags |= __VPM150M_RWPAGE; - } - (*hit_p)->datalen = len; - (*hit_p)->address = addr; - memset((*hit_p)->data, 0, len*sizeof(outbuf[0])); - } - else { - ret = -EBUSY; - } - spin_unlock_irqrestore(&wc->reglock, flags); - return ret; -} - -int t1_vpm150m_getreg_full_return(struct t1 *wc, int pagechange, unsigned int len, - unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) -{ - int ret = 0; - unsigned long flags; - BUG_ON(!hit_p); - spin_lock_irqsave(&wc->reglock, flags); - do { - if ((*hit_p)->flags & __VPM150M_FIN) { - memcpy(outbuf, (*hit_p)->data, len*(sizeof(outbuf[0]))); - (*hit_p)->flags = 0; - (*hit_p) = NULL; - ret = 0; - } - else { - spin_unlock_irqrestore(&wc->reglock, flags); - if ((ret=schluffen(&wc->regq))) { - return ret; - } - spin_lock_irqsave(&wc->reglock, flags); - ret = -EBUSY; - } - } while (-EBUSY == ret); - spin_unlock_irqrestore(&wc->reglock, flags); - return ret; -} - -int t1_vpm150m_getreg_full(struct t1 *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf) -{ - struct vpm150m_cmd *hit = 0; - int ret = 0; - do { - ret = t1_vpm150m_getreg_full_async(wc, pagechange, len, addr, outbuf, &hit); - if (!hit) { - if ( -EBUSY == ret ) { - if ((ret = schluffen(&wc->regq))) - return ret; - } - BUG_ON( 0 != ret); - } - } while (!hit); - - ret = t1_vpm150m_getreg_full_return(wc, pagechange, len, addr, outbuf, &hit); - return ret; -} - -int t1_vpm150m_setreg_full(struct t1 *wc, int pagechange, unsigned int len, unsigned int addr, unsigned short *data) -{ - unsigned long flags; - struct vpm150m_cmd *hit; - int ret, i; - do { - spin_lock_irqsave(&wc->reglock, flags); - hit = vpm150m_empty_slot(wc); - if (hit) { - hit->flags = __VPM150M_WR; - if (pagechange) - hit->flags |= __VPM150M_RWPAGE; - hit->address = addr; - hit->datalen = len; - for (i = 0; i < len; i++) - hit->data[i] = data[i]; - } - spin_unlock_irqrestore(&wc->reglock, flags); - if (!hit) { - if ((ret = schluffen(&wc->regq))) - return ret; - } - } while (!hit); - return (hit) ? 0 : -1; -} - -int t1_vpm150m_setpage(struct t1 *wc, unsigned short addr) -{ - addr &= 0xf; - /* Let's optimize this a little bit */ - if (wc->vpm150m->curpage == addr) - return 0; - else { - wc->vpm150m->curpage = addr; - } - - return t1_vpm150m_setreg_full(wc, 1, 1, 0, &addr); -} - -unsigned char t1_vpm150m_getpage(struct t1 *wc) -{ - unsigned short res; - t1_vpm150m_getreg_full(wc, 1, 1, 0, &res); - return res; -} - -int t1_vpm150m_setreg(struct t1 *wc, unsigned int len, unsigned int addr, unsigned short *data) -{ - int res; - t1_vpm150m_setpage(wc, addr >> 16); - if ((addr >> 16) != ((addr + len) >> 16)) - module_printk("setreg: You found it!\n"); - res = t1_vpm150m_setreg_full(wc, 0, len, addr & 0xffff, data); - return res; -} - -unsigned short t1_vpm150m_getreg(struct t1 *wc, unsigned int len, unsigned int addr, unsigned short *data) -{ - unsigned short res; - t1_vpm150m_setpage(wc, addr >> 16); - if ((addr >> 16) != ((addr + len) >> 16)) - module_printk("getreg: You found it!\n"); - res = t1_vpm150m_getreg_full(wc, 0, len, addr & 0xffff, data); - return res; -} - -static char vpm150mtone_to_zaptone(GpakToneCodes_t tone) -{ - switch (tone) { - case DtmfDigit0: - return '0'; - case DtmfDigit1: - return '1'; - case DtmfDigit2: - return '2'; - case DtmfDigit3: - return '3'; - case DtmfDigit4: - return '4'; - case DtmfDigit5: - return '5'; - case DtmfDigit6: - return '6'; - case DtmfDigit7: - return '7'; - case DtmfDigit8: - return '8'; - case DtmfDigit9: - return '9'; - case DtmfDigitPnd: - return '#'; - case DtmfDigitSt: - return '*'; - case DtmfDigitA: - return 'A'; - case DtmfDigitB: - return 'B'; - case DtmfDigitC: - return 'C'; - case DtmfDigitD: - return 'D'; - case EndofCngDigit: - return 'f'; - default: - return 0; - } -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void vpm150m_echocan_bh(void *data) -{ - struct vpm150m *vpm150m = data; -#else -static void vpm150m_echocan_bh(struct work_struct *data) -{ - struct vpm150m *vpm150m = container_of(data, struct vpm150m, work_echocan); -#endif - struct t1 *wc = vpm150m->wc; - struct list_head *task; - struct list_head *next_task; - unsigned long flags; - - list_for_each_safe(task, next_task, &vpm150m->worklist) { - struct vpm150m_workentry *we = list_entry(task, struct vpm150m_workentry, list); - struct zt_chan *chan = we->chan; - int deflaw; - int res; - GPAK_AlgControlStat_t pstatus; - - if (we->params.tap_length) { - /* configure channel for the ulaw/alaw */ - unsigned int start = wc->intcount; - - if (memcmp(&we->params, &vpm150m->chan_params[chan->chanpos - 1], sizeof(we->params))) { - /* set parameters */ - vpm150m->chan_params[chan->chanpos - 1] = we->params; - } - - deflaw = chan->span->deflaw; - debug_printk(1, "Enabling EC on channel %d (law %d)\n", chan->chanpos, deflaw); - if (deflaw == 2) /* alaw */ - res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, EnableALawSwCompanding, &pstatus); - else if (deflaw == 1) /* alaw */ - res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, EnableMuLawSwCompanding, &pstatus); - else { - module_printk("Undefined law for channel %d.\n", chan->chanpos); - res = -1; - } - - if (res) { - module_printk("Unable to set SW Companding on channel %d (reason %d)\n", chan->chanpos, res); - } - - res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, EnableEcanA, &pstatus); - debug_printk(2, "Echo can enable took %d ms\n", wc->intcount - start); - } else { - unsigned int start = wc->intcount; - debug_printk(1, "Disabling EC on channel %d\n", chan->chanpos); - res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, BypassSwCompanding, &pstatus); - if (res) - module_printk("Unable to disable sw companding on echo cancellation channel %d (reason %d)\n", chan->chanpos, res); - res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, BypassEcanA, &pstatus); - if (res) - module_printk("Unable to disable echo can on channel %d (reason %d)\n", chan->chanpos, res); - debug_printk(2, "Echocan disable took %d ms\n", wc->intcount - start); - } - if (res) { - module_printk("Unable to toggle echo cancellation on channel %d (reason %d)\n", chan->chanpos, res); - } - - spin_lock_irqsave(&vpm150m->lock, flags); - list_del(task); - spin_unlock_irqrestore(&vpm150m->lock, flags); - kfree(we); - } -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void vpm150m_debug_bh(void *data) -{ - struct vpm150m *vpm150m = data; -#else -static void vpm150m_debug_bh(struct work_struct *data) -{ - struct vpm150m *vpm150m = container_of(data, struct vpm150m, work_debug); -#endif - unsigned short int FrammingError1Count, FramingError2Count, FramingError3Count, - DmaStopErrorCount, DmaSlipStatsBuffer; - - if (gpakReadFramingStats(vpm150m->dspid, &FrammingError1Count, &FramingError2Count, &FramingError3Count, - &DmaStopErrorCount, &DmaSlipStatsBuffer)) - { - module_printk("There was an error getting framing stats.\n"); - } - if (FrammingError1Count||FramingError2Count||FramingError3Count||DmaStopErrorCount||DmaSlipStatsBuffer) - { - module_printk("FramingStats Error: %d %d %d %d %d\n", - FrammingError1Count, FramingError2Count, FramingError3Count, DmaStopErrorCount, DmaSlipStatsBuffer); - } -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void vpm150m_dtmf_bh(void *data) -{ - struct vpm150m *vpm150m = data; -#else -static void vpm150m_dtmf_bh(struct work_struct *data) -{ - struct vpm150m *vpm150m = container_of(data, struct vpm150m, work_dtmf); -#endif - struct t1 *wc = vpm150m->wc; - int i; - - for (i = 0; i < wc->span.channels; i++) { - int enable = -1; - if (test_bit(i, &vpm150m->desireddtmfmutestate)) { - if (!test_bit(i, &vpm150m->curdtmfmutestate)) { - enable = 1; - } - } else { - if (test_bit(i, &vpm150m->curdtmfmutestate)) { - enable = 0; - } - } - if (enable > -1) { - unsigned int start = wc->intcount; - GPAK_AlgControlStat_t pstatus; - int res; - - if (enable) { - res = gpakAlgControl(vpm150m->dspid, i, EnableDTMFMuteA, &pstatus); - debug_printk(2, "DTMF mute enable took %d ms\n", wc->intcount - start); - } else { - res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &pstatus); - debug_printk(2, "DTMF mute disable took %d ms\n", wc->intcount - start); - } - if (!res) - change_bit(i, &vpm150m->curdtmfmutestate); - } - } - - if (test_bit(VPM150M_DTMFDETECT, &vpm150m->control)) { - unsigned short channel; - GpakAsyncEventCode_t eventcode; - GpakAsyncEventData_t eventdata; - gpakReadEventFIFOMessageStat_t res; - unsigned int start = wc->intcount; - - do { - res = gpakReadEventFIFOMessage(vpm150m->dspid, &channel, &eventcode, &eventdata); - debug_printk(3, "ReadEventFIFOMessage took %d ms\n", wc->intcount - start); - - if (res == RefInvalidEvent || res == RefDspCommFailure) { - module_printk("Uh oh (%d)\n", res); - continue; - } - - if (eventcode == EventToneDetect) { - GpakToneCodes_t tone = eventdata.toneEvent.ToneCode; - int duration = eventdata.toneEvent.ToneDuration; - char zaptone = vpm150mtone_to_zaptone(tone); - - debug_printk(1, "Channel %d: Detected DTMF tone %d of duration %d\n", channel + 1, tone, duration); - - if (test_bit(channel, &wc->dtmfmask) && (eventdata.toneEvent.ToneDuration > 0)) { - struct zt_chan *chan = &wc->chans[channel]; - - module_printk("DTMF detected channel=%d tone=%d duration=%d\n", channel + 1, tone, duration); - - if ((tone != EndofMFDigit) && (zaptone != 0)) { - vpm150m->curtone[channel] = tone; - - if (test_bit(channel, &vpm150m->curdtmfmutestate)) { - unsigned long flags; - int y; - - /* Mute the audio data buffers */ - spin_lock_irqsave(&chan->lock, flags); - for (y = 0; y < chan->numbufs; y++) { - if ((chan->inreadbuf > -1) && (chan->readidx[y])) - memset(chan->readbuf[chan->inreadbuf], ZT_XLAW(0, chan), chan->readidx[y]); - } - spin_unlock_irqrestore(&chan->lock, flags); - } - if (!test_bit(channel, &wc->dtmfactive)) { - debug_printk(1,"Queuing DTMFDOWN %c\n", zaptone); - set_bit(channel, &wc->dtmfactive); - zt_qevent_lock(chan, (ZT_EVENT_DTMFDOWN | zaptone)); - } - } else if ((tone == EndofMFDigit) && test_bit(channel, &wc->dtmfactive)) { - debug_printk(1,"Queuing DTMFUP %c\n", vpm150mtone_to_zaptone(vpm150m->curtone[channel])); - zt_qevent_lock(chan, (ZT_EVENT_DTMFUP | vpm150mtone_to_zaptone(vpm150m->curtone[channel]))); - clear_bit(channel, &wc->dtmfactive); - } - } - } - } while ((res == RefEventAvail)); - } - - return; -} - -void t1_vpm150m_init(struct t1 *wc) { - struct vpm150m *vpm150m; - unsigned short i; - unsigned short reg; - unsigned long flags; - gpakPingDspStat_t pingstatus; - gpakDownloadStatus_t downloadstatus; - struct t1_firmware fw; - struct firmware embedded_firmware; - const struct firmware *firmware = &embedded_firmware; -#if !defined(HOTPLUG_FIRMWARE) - extern void _binary_zaptel_fw_vpmadt032_bin_size; - extern u8 _binary_zaptel_fw_vpmadt032_bin_start[]; -#else - static const char vpmadt032_firmware[] = "zaptel-fw-vpmadt032.bin"; -#endif - -#if 0 - unsigned short omsg[4] = { 0xdead, 0xbeef, 0x1111, 0x2222}; - unsigned short imsg[4]; -#endif - - if (!vpmsupport) { - module_printk("VPM Support Disabled\n"); - wc->vpm150m = NULL; - return; - } - - vpm150m = kmalloc(sizeof(struct vpm150m), GFP_KERNEL); - - if (!vpm150m) { - module_printk("Unable to allocate VPMADT032!\n"); - return; - } - memset(vpm150m, 0, sizeof(struct vpm150m)); - - /* Init our vpm150m struct */ - sema_init(&vpm150m->sem, 1); - vpm150m->curpage = 0x80; - - for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++) { - if (ifaces[i] == wc) - vpm150m->dspid = i; - } - - debug_printk(1, "Setting VPMADT032 DSP ID to %d\n", vpm150m->dspid); - spin_lock_irqsave(&wc->reglock, flags); - wc->vpm150m = vpm150m; - spin_unlock_irqrestore(&wc->reglock, flags); - - for (i = 0; i < 10; i++) - schluffen(&wc->regq); - - debug_printk(1, "Looking for VPMADT032 by testing page access: "); - for (i = 0; i < 0xf; i++) { - int x; - for (x = 0; x < 3; x++) { - t1_vpm150m_setpage(wc, i); - reg = t1_vpm150m_getpage(wc); - if (reg != i) { - /* If they have debug turned on we want them to be able to - * report where in the code the module failed to come up. */ - debug_printk(1, "Either no VPMADT032 module present or the module failed VPM page access test (%x != %x)\n", i, reg); - goto failed_exit; - } - } - } - debug_printk(1, "Passed\n"); - - set_bit(VPM150M_HPIRESET, &vpm150m->control); - msleep(2000); - - /* Set us up to page 0 */ - t1_vpm150m_setpage(wc, 0); - debug_printk(1, "VPMADT032 now doing address test: "); - for (i = 0; i < 16; i++) { - int x; - for (x = 0; x < 2; x++) { - t1_vpm150m_setreg(wc, 1, 0x1000, &i); - t1_vpm150m_getreg(wc, 1, 0x1000, ®); - if (reg != i) { - module_printk("VPMADT032 Failed address test: sent %x != %x on try %d\n", i, reg, x); - goto failed_exit; - } - } - } - debug_printk(1, "Passed\n"); - -#if 0 - /* begin short test */ -#define TEST_SIZE 1 - { - int i; - unsigned short msg[TEST_SIZE]; - - set_bit(VPM150M_HPIRESET, &vpm150m->control); - msleep(2000); - - /* lets see whats in there to start with*/ - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - printk("at first :"); - for (i = 0; i< TEST_SIZE; i++) - printk("%04x ", msg[i]); - printk("\n"); - - /* what if we put dead in there*/ - for (i = 0; i< TEST_SIZE; i++) - msg[i] = 0xdead; - gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - printk("now :"); - for (i = 0; i< TEST_SIZE; i++) - printk("%04x ", msg[i]); - printk("\n"); - - /* lets see if its in there now */ - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - printk("try again:"); - for (i = 0; i< TEST_SIZE; i++) - printk("%04x ", msg[i]); - printk("\n"); - } - - goto failed_exit; -#endif - -#define TEST_SIZE 2 - if (debug) { - int i; - unsigned short msg[TEST_SIZE]; - - set_bit(VPM150M_HPIRESET, &vpm150m->control); - msleep(2000); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - for (i = 0; i< TEST_SIZE; i++) - msg[i] = 0xdead; - gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - for (i = 0; i< TEST_SIZE; i++) - msg[i] = 0xbeef; - gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - for (i = 0; i< TEST_SIZE; i++) - msg[i] = 0x1111; - gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - for (i = 0; i< TEST_SIZE; i++) - msg[i] = 0x2222; - gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); - for (i = 0; i< TEST_SIZE; i++) - printk("%x ", msg[i]); - printk("\n"); - } -#if 0 - printk("Sending\n"); - - for (i = 0; i < 4; i++) { - unsigned short x = 0xffff; - t1_vpm150m_setreg(wc, 1, 0x1000 + i, &x); - } - - gpakReadDspMemory(vpm150m->dspid, 0x1000, 4, imsg); - - printk("Read back:\n"); - for (i = 0; i < 4; i++) - printk("%x ", imsg[i]); - printk("\n"); - - printk("Sending\n"); - gpakWriteDspMemory(vpm150m->dspid, 0x1000, 4, omsg); - for (i = 0; i < 4; i++) - t1_vpm150m_getreg(wc, 1, 0x1000 + i, &imsg[i]); - - printk("Read back\n"); - for (i = 0; i < 4; i++) - printk("%x ", imsg[i]); - printk("\n"); - -#endif - -#if 0 - /* Load the firmware */ - set_bit(VPM150M_SPIRESET, &vpm150m->control); - - /* Wait for it to boot */ - msleep(7000); - - pingstatus = gpakPingDsp(vpm150m->dspid, &version); - - if (pingstatus) { - module_printk("Pingstatus %d, you failed!!! Ha ha ha ha\n", pingstatus); - } else - module_printk("version is 0x%08x\n", version); - - if (pingstatus || (version != 0x106)) { -#endif -#if defined(HOTPLUG_FIRMWARE) - if ((request_firmware(&firmware, vpmadt032_firmware, &wc->dev->dev) != 0) || - !firmware) { - printk("VPMADT032: firmware %s not available from userspace\n", vpmadt032_firmware); - goto failed_exit; - } -#else - embedded_firmware.data = _binary_zaptel_fw_vpmadt032_bin_start; - embedded_firmware.size = (size_t) &_binary_zaptel_fw_vpmadt032_bin_size; -#endif - fw.fw = firmware; - fw.offset = 0; - - set_bit(VPM150M_HPIRESET, &vpm150m->control); - - while (test_bit(VPM150M_HPIRESET, &vpm150m->control)) - schluffen(&wc->regq); - - module_printk("VPMADT032 Loading firwmare... "); - downloadstatus = gpakDownloadDsp(vpm150m->dspid, &fw); - - if (firmware != &embedded_firmware) - release_firmware(firmware); - - if (downloadstatus != 0) { - module_printk("Unable to download firmware to VPMADT032 with cause %d\n", downloadstatus); - goto failed_exit; - } else { - module_printk("Success\n"); - } - - set_bit(VPM150M_SWRESET, &vpm150m->control); - - while (test_bit(VPM150M_SWRESET, &vpm150m->control)) - schluffen(&wc->regq); - - msleep(700); -#if 0 - } -#endif - - pingstatus = gpakPingDsp(vpm150m->dspid, &vpm150m->version); - - if (!pingstatus) { - debug_printk(1, "Version of DSP is %x\n", vpm150m->version); - } else { - module_printk("Unable to ping the DSP (%d)!\n", pingstatus); - goto failed_exit; - } - - /* workqueue for DTMF and wc->span functions that cannot sleep */ - spin_lock_init(&vpm150m->lock); - vpm150m->wq = create_singlethread_workqueue("wcte12xp"); - vpm150m->wc = wc; - if (!vpm150m->wq) { - module_printk("Unable to create work queue!\n"); - goto failed_exit; - } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - INIT_WORK(&vpm150m->work_echocan, vpm150m_echocan_bh, vpm150m); - INIT_WORK(&vpm150m->work_dtmf, vpm150m_dtmf_bh, vpm150m); - INIT_WORK(&vpm150m->work_debug, vpm150m_debug_bh, vpm150m); -#else - INIT_WORK(&vpm150m->work_echocan, vpm150m_echocan_bh); - INIT_WORK(&vpm150m->work_dtmf, vpm150m_dtmf_bh); - INIT_WORK(&vpm150m->work_debug, vpm150m_debug_bh); -#endif - INIT_LIST_HEAD(&wc->vpm150m->worklist); /* list of echocan tasks */ - - if (vpm150m_config_hw(wc)) { - goto failed_exit; - } - - return; - -failed_exit: - if (vpm150m->wq) { - destroy_workqueue(vpm150m->wq); - } - spin_lock_irqsave(&wc->reglock, flags); - wc->vpm150m = NULL; - spin_unlock_irqrestore(&wc->reglock, flags); - kfree(vpm150m); - - return; -} - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadDspMemory - Read DSP memory. - * - * FUNCTION - * This function reads a contiguous block of words from DSP memory starting at - * the specified address. - * - * RETURNS - * nothing - * - */ -void gpakReadDspMemory( - unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ - unsigned int NumWords, /* number of contiguous words to read */ - DSP_WORD *pWordValues /* pointer to array of word values variable */ - ) -{ - struct t1 *wc = wc_find_iface(DspId); - int i; - int transcount; - int ret; - - vpm150m_io_wait(wc); - if ( NumWords < VPM150M_MAX_COMMANDS ) { - struct vpm150m_cmd* cmds[VPM150M_MAX_COMMANDS] = {0}; - t1_vpm150m_setpage(wc, DspAddress >> 16); - DspAddress &= 0xffff; - for (i=0; i < NumWords; ++i) { - ret = t1_vpm150m_getreg_full_async(wc,0,1,DspAddress+i,&pWordValues[i], - &cmds[i]); - if (0 != ret) { - return; - } - } - for (i=NumWords-1; i >=0; --i) { - ret = t1_vpm150m_getreg_full_return(wc,0,1,DspAddress+i,&pWordValues[i], - &cmds[i]); - if (0 != ret) { - return; - } - } - } - else { - for (i = 0; i < NumWords;) { - if ((NumWords - i) > VPM150M_MAX_DATA) - transcount = VPM150M_MAX_DATA; - else - transcount = NumWords - i; - t1_vpm150m_getreg(wc, transcount, DspAddress + i, &pWordValues[i]); - i += transcount; - } - } - return; -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakWriteDspMemory - Write DSP memory. - * - * FUNCTION - * This function writes a contiguous block of words to DSP memory starting at - * the specified address. - * - * RETURNS - * nothing - * - */ -void gpakWriteDspMemory( - unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ - unsigned int NumWords, /* number of contiguous words to write */ - DSP_WORD *pWordValues /* pointer to array of word values to write */ - ) -{ - - struct t1 *wc = wc_find_iface(DspId); - int i; - int transcount; - - if (wc && wc->vpm150m) { - for (i = 0; i < NumWords;) { - if ((NumWords - i) > VPM150M_MAX_DATA) - transcount = VPM150M_MAX_DATA; - else - transcount = NumWords - i; - t1_vpm150m_setreg(wc, transcount, DspAddress + i, &pWordValues[i]); - i += transcount; - } - } - return; - -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakHostDelay - Delay for a fixed time interval. - * - * FUNCTION - * This function delays for a fixed time interval before returning. The time - * interval is the Host Port Interface sampling period when polling a DSP for - * replies to command messages. - * - * RETURNS - * nothing - * - */ -void gpakHostDelay(void) -{ -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakLockAccess - Lock access to the specified DSP. - * - * FUNCTION - * This function aquires exclusive access to the specified DSP. - * - * RETURNS - * nothing - * - */ -void gpakLockAccess(unsigned short DspId) -{ - struct t1 *wc; - - wc = wc_find_iface(DspId); - - if (wc) { - struct vpm150m *vpm = wc->vpm150m; - - if (vpm) - down_interruptible(&vpm->sem); - } -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakUnlockAccess - Unlock access to the specified DSP. - * - * FUNCTION - * This function releases exclusive access to the specified DSP. - * - * RETURNS - * nothing - * - */ -void gpakUnlockAccess(unsigned short DspId) -{ - struct t1 *wc; - - wc = wc_find_iface(DspId); - - if (wc) { - struct vpm150m *vpm = wc->vpm150m; - - if (vpm) - up(&vpm->sem); - } -} - - -/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFile - Read a block of bytes from a G.PAK Download file. - * - * FUNCTION - * This function reads a contiguous block of bytes from a G.PAK Download file - * starting at the current file position. - * - * RETURNS - * The number of bytes read from the file. - * -1 indicates an error occurred. - * 0 indicates all bytes have been read (end of file) - * - */ -int gpakReadFile( - GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ - unsigned char *pBuffer, /* pointer to buffer for storing bytes */ - unsigned int NumBytes /* number of bytes to read */ - ) -{ - struct t1_firmware *fw = FileId; - unsigned int i, count; - - if (!fw || !fw->fw) - return -1; - - if (NumBytes > (fw->fw->size - fw->offset)) - count = fw->fw->size - fw->offset; - else - count = NumBytes; - - for (i = 0; i < count; i++) - pBuffer[i] = fw->fw->data[fw->offset + i]; - - fw->offset += count; - - return count; -} - -int vpm150m_config_hw(struct t1 *wc) -{ - struct vpm150m *vpm150m = wc->vpm150m; - gpakConfigPortStatus_t configportstatus; - GpakPortConfig_t portconfig; - GPAK_PortConfigStat_t pstatus; - GpakChannelConfig_t chanconfig; - GPAK_ChannelConfigStat_t cstatus; - GPAK_AlgControlStat_t algstatus; - - int res, i; - - memset(&portconfig, 0, sizeof(GpakPortConfig_t)); - - /* First Serial Port config */ - portconfig.SlotsSelect1 = SlotCfgNone; - portconfig.FirstBlockNum1 = 0; - portconfig.FirstSlotMask1 = 0x0000; - portconfig.SecBlockNum1 = 1; - portconfig.SecSlotMask1 = 0x0000; - portconfig.SerialWordSize1 = SerWordSize8; - portconfig.CompandingMode1 = cmpNone; - portconfig.TxFrameSyncPolarity1 = FrameSyncActHigh; - portconfig.RxFrameSyncPolarity1 = FrameSyncActHigh; - portconfig.TxClockPolarity1 = SerClockActHigh; - portconfig.RxClockPolarity1 = SerClockActHigh; - portconfig.TxDataDelay1 = DataDelay0; - portconfig.RxDataDelay1 = DataDelay0; - portconfig.DxDelay1 = Disabled; - portconfig.ThirdSlotMask1 = 0x0000; - portconfig.FouthSlotMask1 = 0x0000; - portconfig.FifthSlotMask1 = 0x0000; - portconfig.SixthSlotMask1 = 0x0000; - portconfig.SevenSlotMask1 = 0x0000; - portconfig.EightSlotMask1 = 0x0000; - - /* Second Serial Port config */ - portconfig.SlotsSelect2 = SlotCfg8Groups; - portconfig.FirstBlockNum2 = 0; - portconfig.FirstSlotMask2 = 0x5554; - portconfig.SecBlockNum2 = 1; - portconfig.SecSlotMask2 = 0x5555; - portconfig.ThirdSlotMask2 = 0x5555; - portconfig.FouthSlotMask2 = 0x5555; - portconfig.SerialWordSize2 = SerWordSize8; - portconfig.CompandingMode2 = cmpNone; - portconfig.TxFrameSyncPolarity2 = FrameSyncActHigh; - portconfig.RxFrameSyncPolarity2 = FrameSyncActHigh; - portconfig.TxClockPolarity2 = SerClockActHigh; - portconfig.RxClockPolarity2 = SerClockActHigh; - portconfig.TxDataDelay2 = DataDelay0; - portconfig.RxDataDelay2 = DataDelay0; - portconfig.DxDelay2 = Disabled; - portconfig.FifthSlotMask2 = 0x0001; - portconfig.SixthSlotMask2 = 0x0000; - portconfig.SevenSlotMask2 = 0x0000; - portconfig.EightSlotMask2 = 0x0000; - - /* Third Serial Port Config */ - portconfig.SlotsSelect3 = SlotCfg8Groups; - portconfig.FirstBlockNum3 = 0; - portconfig.FirstSlotMask3 = 0x5554; - portconfig.SecBlockNum3 = 1; - portconfig.SecSlotMask3 = 0x5555; - portconfig.SerialWordSize3 = SerWordSize8; - portconfig.CompandingMode3 = cmpNone; - portconfig.TxFrameSyncPolarity3 = FrameSyncActHigh; - portconfig.RxFrameSyncPolarity3 = FrameSyncActHigh; - portconfig.TxClockPolarity3 = SerClockActHigh; - portconfig.RxClockPolarity3 = SerClockActLow; - portconfig.TxDataDelay3 = DataDelay0; - portconfig.RxDataDelay3 = DataDelay0; - portconfig.DxDelay3 = Disabled; - portconfig.ThirdSlotMask3 = 0x5555; - portconfig.FouthSlotMask3 = 0x5555; - portconfig.FifthSlotMask3 = 0x0001; - portconfig.SixthSlotMask3 = 0x0000; - portconfig.SevenSlotMask3 = 0x0000; - portconfig.EightSlotMask3 = 0x0000; - - if ((configportstatus = gpakConfigurePorts(vpm150m->dspid, &portconfig, &pstatus))) { - module_printk("Configuration of ports failed (%d)!\n", configportstatus); - return -1; - } else { - debug_printk(1, "Configured McBSP ports successfully\n"); - } - - if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { - module_printk("Error pinging DSP (%d)\n", res); - return -1; - } - - for (i = 0; i < 32; i++) { - /* Let's configure a channel */ - chanconfig.PcmInPortA = 3; - chanconfig.PcmInSlotA = (i + 1) * 2; - chanconfig.PcmOutPortA = 2; - chanconfig.PcmOutSlotA = (i + 1) * 2; - chanconfig.PcmInPortB = 2; - chanconfig.PcmInSlotB = (i + 1) * 2; - chanconfig.PcmOutPortB = 3; - chanconfig.PcmOutSlotB = (i + 1) * 2; - if (vpmdtmfsupport) { - chanconfig.ToneTypesA = DTMF_tone; - chanconfig.MuteToneA = Enabled; - chanconfig.FaxCngDetA = Enabled; - } else { - chanconfig.ToneTypesA = Null_tone; - chanconfig.MuteToneA = Disabled; - chanconfig.FaxCngDetA = Disabled; - } - chanconfig.ToneTypesB = Null_tone; - chanconfig.EcanEnableA = Enabled; - chanconfig.EcanEnableB = Disabled; - chanconfig.MuteToneB = Disabled; - chanconfig.FaxCngDetB = Disabled; - - chanconfig.SoftwareCompand = cmpNone; - - chanconfig.FrameRate = rate10ms; - - chanconfig.EcanParametersA.EcanTapLength = 1024; - chanconfig.EcanParametersA.EcanNlpType = vpmnlptype; - chanconfig.EcanParametersA.EcanAdaptEnable = 1; - chanconfig.EcanParametersA.EcanG165DetEnable = 1; - chanconfig.EcanParametersA.EcanDblTalkThresh = 6; - chanconfig.EcanParametersA.EcanNlpThreshold = vpmnlpthresh; - chanconfig.EcanParametersA.EcanNlpConv = 0; - chanconfig.EcanParametersA.EcanNlpUnConv = 0; - chanconfig.EcanParametersA.EcanNlpMaxSuppress = vpmnlpmaxsupp; - chanconfig.EcanParametersA.EcanCngThreshold = 43; - chanconfig.EcanParametersA.EcanAdaptLimit = 50; - chanconfig.EcanParametersA.EcanCrossCorrLimit = 15; - chanconfig.EcanParametersA.EcanNumFirSegments = 3; - chanconfig.EcanParametersA.EcanFirSegmentLen = 64; - - chanconfig.EcanParametersB.EcanTapLength = 1024; - chanconfig.EcanParametersB.EcanNlpType = vpmnlptype; - chanconfig.EcanParametersB.EcanAdaptEnable = 1; - chanconfig.EcanParametersB.EcanG165DetEnable = 1; - chanconfig.EcanParametersB.EcanDblTalkThresh = 6; - chanconfig.EcanParametersB.EcanNlpThreshold = vpmnlpthresh; - chanconfig.EcanParametersB.EcanNlpConv = 0; - chanconfig.EcanParametersB.EcanNlpUnConv = 0; - chanconfig.EcanParametersB.EcanNlpMaxSuppress = vpmnlpmaxsupp; - chanconfig.EcanParametersB.EcanCngThreshold = 43; - chanconfig.EcanParametersB.EcanAdaptLimit = 50; - chanconfig.EcanParametersB.EcanCrossCorrLimit = 15; - chanconfig.EcanParametersB.EcanNumFirSegments = 3; - chanconfig.EcanParametersB.EcanFirSegmentLen = 64; - - if ((res = gpakConfigureChannel(vpm150m->dspid, i, tdmToTdm, &chanconfig, &cstatus))) { - module_printk("Unable to configure channel (%d)\n", res); - if (res == 1) { - module_printk("Reason %d\n", cstatus); - } - - return -1; - } - - if ((res = gpakAlgControl(vpm150m->dspid, i, BypassEcanA, &algstatus))) { - module_printk("Unable to disable echo can on channel %d (reason %d:%d)\n", i + 1, res, algstatus); - return -1; - } - - if (vpmdtmfsupport) { - if ((res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &algstatus))) { - module_printk("Unable to disable dtmf muting on channel %d (reason %d:%d)\n", i + 1, res, algstatus); - return -1; - } - } - } - - if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { - module_printk("Error pinging DSP (%d)\n", res); - return -1; - } - - /* Turn on DTMF detection */ - if (vpmdtmfsupport) - set_bit(VPM150M_DTMFDETECT, &vpm150m->control); - set_bit(VPM150M_ACTIVE, &vpm150m->control); - - return 0; -} - -#endif diff --git a/wcte12xp/vpmadt032.h b/wcte12xp/vpmadt032.h deleted file mode 100644 index e103e05..0000000 --- a/wcte12xp/vpmadt032.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Digium, Inc. Wildcard TE12xP T1/E1 card Driver - * - * Written by Michael Spiceland - * - * Adapted from the wctdm24xxp and wcte11xp drivers originally - * written by Mark Spencer - * Matthew Fredrickson - * William Meadows - * - * Copyright (C) 2007, Digium, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef _VPM150M_H -#define _VPM150M_H - -#include "wcte12xp.h" -#include "adt_lec.h" - -struct t1_firmware { - const struct firmware *fw; - unsigned int offset; -}; - -/* Host and DSP system dependent related definitions. */ -#define MAX_DSP_CORES 128 /* maximum number of DSP cores */ -//#define MAX_CONFS 1 /* maximum number of conferences */ -//#define MAX_PKT_CHANNELS 8 /* maximum number of packet channels */ -#define MAX_CHANNELS 32 /* maximum number of channels */ -#define MAX_WAIT_LOOPS 50 /* max number of wait delay loops */ -#define DSP_IFBLK_ADDRESS 0x0100 /* DSP address of I/F block pointer */ -#define DOWNLOAD_BLOCK_SIZE 512 /* download block size (DSP words) */ -//#define MAX_CIDPAYLOAD_BYTES 512 /* max size of a CID payload (octets) */ -typedef unsigned short DSP_WORD; /* 16 bit DSP word */ -typedef unsigned int DSP_ADDRESS; /* 32 bit DSP address */ -typedef struct t1_firmware* GPAK_FILE_ID; /* G.PAK Download file identifier */ - -#define __VPM150M_RWPAGE (1 << 4) -#define __VPM150M_RD (1 << 3) -#define __VPM150M_WR (1 << 2) -#define __VPM150M_FIN (1 << 1) -#define __VPM150M_TX (1 << 0) - -#define VPM150M_HPI_CONTROL 0x00 -#define VPM150M_HPI_ADDRESS 0x02 -#define VPM150M_HPI_DATA 0x03 - -#define VPM150M_MAX_COMMANDS 8 - -/* Some Bit ops for different operations */ -#define VPM150M_SPIRESET 0 -#define VPM150M_HPIRESET 1 -#define VPM150M_SWRESET 2 -#define VPM150M_DTMFDETECT 3 -#define VPM150M_ACTIVE 4 -#define VPM150M_MAX_DATA 1 - -struct vpm150m_cmd { - unsigned short address; - unsigned short data[VPM150M_MAX_DATA]; - unsigned char ident; - unsigned char datalen; - unsigned int flags; - unsigned char cs_slot; -}; - -struct vpm150m { - unsigned short dspid; - unsigned long control; - unsigned char curpage; - unsigned short version; - struct vpm150m_cmd cmdq[VPM150M_MAX_COMMANDS]; - spinlock_t lock; /* control access to list of bottom half tasks */ - struct semaphore sem; - struct workqueue_struct *wq; - struct work_struct work_dtmf; - struct work_struct work_debug; - struct work_struct work_echocan; - struct list_head worklist; - unsigned char curtone[32]; - unsigned long curdtmfmutestate; - unsigned long desireddtmfmutestate; - struct adt_lec_params chan_params[32]; - struct t1 *wc; -}; - -/* linked list for vpm echocan workqueue*/ -struct vpm150m_workentry { - struct list_head list; - struct t1 *wc; /* what card are we dealing with? */ - struct zt_chan *chan; /* what channels are we going to deal with? */ - struct adt_lec_params params; /* how should we behave? */ -}; - -extern int debug; -extern int vpmsupport; -extern int vpmdtmfsupport; -extern struct pci_driver te12xp_driver; - -void t1_vpm150m_init(struct t1 *wc); -void vpm150m_cmd_dequeue(struct t1 *wc, volatile unsigned char *writechunk, int whichframe); -void vpm150m_cmd_decipher(struct t1 *wc, volatile unsigned char *readchunk); -int vpm150m_config_hw(struct t1 *wc); - -/* gpak API functions */ -void gpakReadDspMemory( - unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ - unsigned int NumWords, /* number of contiguous words to read */ - DSP_WORD *pWordValues /* pointer to array of word values variable */ - ); -void gpakWriteDspMemory( - unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ - unsigned int NumWords, /* number of contiguous words to write */ - DSP_WORD *pWordValues /* pointer to array of word values to write */ - ); -void gpakHostDelay(void); -void gpakLockAccess( - unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - ); -void gpakUnlockAccess( - unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ - ); -int gpakReadFile( - GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ - unsigned char *pBuffer, /* pointer to buffer for storing bytes */ - unsigned int NumBytes /* number of bytes to read */ - ); - -#endif diff --git a/wcte12xp/wcte12xp.h b/wcte12xp/wcte12xp.h deleted file mode 100644 index 20e0558..0000000 --- a/wcte12xp/wcte12xp.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Digium, Inc. Wildcard TE12xP T1/E1 card Driver - * - * Written by Michael Spiceland - * - * Adapted from the wctdm24xxp and wcte11xp drivers originally - * written by Mark Spencer - * Matthew Fredrickson - * William Meadows - * - * Copyright (C) 2007, Digium, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef _WCTE12XP_H -#define _WCTE12XP_H - -#ifdef LINUX26 -/* Comment to disable VPM support */ -#define VPM_SUPPORT 1 -#endif - -#define WC_MAX_IFACES 8 - -#ifdef VPM_SUPPORT -#define MAX_TDM_CHAN 31 -#endif - -#define SDI_CLK (0x00010000) -#define SDI_DOUT (0x00020000) -#define SDI_DREAD (0x00040000) -#define SDI_DIN (0x00080000) - -#define EFRAME_SIZE 108 -#define ERING_SIZE 16 /* Maximum ring size */ -#define EFRAME_GAP 20 -#define SFRAME_SIZE ((EFRAME_SIZE * ZT_CHUNKSIZE) + (EFRAME_GAP * (ZT_CHUNKSIZE - 1))) - -#define PCI_WINDOW_SIZE ((2 * 2 * 2 * SFRAME_SIZE) + (2 * ERING_SIZE * 4)) - -#define MAX_COMMANDS 7*7*2 /* 42 bytes /3 (cntl,addr,data) /2 (cs) */ - -#define ISR_COMMANDS 2 -#define NUM_EC 4 - -#define __CMD_VPM (1 << 16) /* flag for VPM action */ -#define __CMD_ISR (1 << 17) /* flag for ISR reads */ -#define __CMD_PINS (1 << 18) /* CPLD pin read */ -#define __CMD_LEDS (1 << 19) /* LED Operation */ -#define __CMD_RD (1 << 20) /* Read Operation */ -#define __CMD_WR (1 << 21) /* Write Operation */ -#define __CMD_FIN (1 << 22) /* Has finished receive */ -#define __CMD_TX (1 << 23) /* Has been transmitted */ - -#define __LED_ORANGE (1<<3) -#define __LED_GREEN (1<<2) -#define __LED_RED (1<<1) - -#define SET_LED_ORANGE(a) a | __LED_ORANGE -#define SET_LED_RED(a) (a | __LED_RED) & ~__LED_GREEN -#define SET_LED_GREEN(a) (a | __LED_GREEN) & ~__LED_RED - -#define UNSET_LED_ORANGE(a) a & ~__LED_ORANGE -#define UNSET_LED_REDGREEN(a) a | __LED_RED | __LED_GREEN - -#define CMD_WR(a,b) (((a) << 8) | (b) | __CMD_WR) -#define CMD_RD(a) (((a) << 8) | __CMD_RD) -#define CMD_LEDS(a) (((a) << 8) | __CMD_LEDS) -//#define CMD_BYTE(slot, a) (slot*6)+(a*2) /* only even slots */ -#define CMD_BYTE(slot, a, is_vpm) (slot*6)+(a*2)+is_vpm /* only even slots */ -//TODO: make a separate macro - -#define TYPE_T1 1 -#define TYPE_E1 2 - -#define NOT_VPM -1 - -#define module_printk(fmt, args...) printk("%s: " fmt, te12xp_driver.name, ## args) -#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, te12xp_driver.name, __FUNCTION__, ## args) -extern spinlock_t ifacelock; - -struct command { - unsigned short address; - unsigned char data; - unsigned char ident; - unsigned int flags; - unsigned char cs_slot; - unsigned char vpm_num; /* ignored for all but vpm commmands */ -}; - -struct cmdq { - struct command cmds[MAX_COMMANDS]; - unsigned char isrshadow[ISR_COMMANDS]; -}; - -struct vpm150m; - -struct t1 { - struct pci_dev *dev; - spinlock_t reglock; - unsigned char txident; - unsigned char rxident; - unsigned char statreg; /* bit 0 = vpmadt032 int */ - int spantype; - struct { - unsigned int nmf:1; - unsigned int sendingyellow:1; - } flags; - unsigned char txsigs[16]; /* Copy of tx sig registers */ - int num; - int alarmcount; /* How much red alarm we've seen */ - int alarmdebounce; - char *variety; - unsigned int intcount; - int sync; - int dead; - int blinktimer; - int alarmtimer; - int yellowtimer; - int ledlastvalue; - int alarms_read; - int checktiming; /* Set >0 to cause the timing source to be checked */ - int loopupcnt; - int loopdowncnt; - int initialized; - int *chanmap; - unsigned char ledtestreg; - unsigned long iobase; - unsigned char ec_chunk1[32][ZT_CHUNKSIZE]; - unsigned char ec_chunk2[32][ZT_CHUNKSIZE]; - struct zt_span span; /* Span */ - struct zt_chan chans[32]; /* Channels */ - int freeregion; - unsigned int intmask; - wait_queue_head_t regq; - struct cmdq cmdq; - struct command dummy; /* preallocate for dummy noop command */ - unsigned char ctlreg; - int rdbl; - int tdbl; - unsigned int rxints; - unsigned int txints; - unsigned int sdi; - int usecount; - dma_addr_t readdma; - dma_addr_t writedma; - dma_addr_t descripdma; - volatile unsigned int *writechunk; - volatile unsigned int *readchunk; - volatile unsigned int *descripchunk; - unsigned int isrreaderrors; -#ifdef VPM_SUPPORT - int vpm; - struct vpm150m *vpm150m; - unsigned long dtmfactive; - unsigned long dtmfmask; - unsigned long dtmfmutemask; -#endif -}; - -int schluffen(wait_queue_head_t *q); - -#endif diff --git a/wcusb.c b/wcusb.c deleted file mode 100644 index 615d4c0..0000000 --- a/wcusb.c +++ /dev/null @@ -1,1490 +0,0 @@ -/* - * Wildcard S100U USB FXS Interface Zapata Telephony Driver - * - * Written by Mark Spencer - * Matthew Fredrickson - * - * Copyright (C) 2001, Linux Support Services, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* Save power at the expense of not always being able to transmit on hook. If - this is set, we only transit on hook for some time after a ring - (POWERSAVE_TIMEOUT) */ - -/* #define PROSLIC_POWERSAVE */ -#define POWERSAVE_TIME 4000 - -#include -#include -#include -#include -#include -#include -#include - -#include -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19) -#define USB2420 -#endif - -#ifdef STANDALONE_ZAPATA -#include "zaptel.h" -#else -#include -#endif /* STANDALONE_ZAPATA */ - -#include "wcusb.h" -#include "proslic.h" - -#ifndef FILL_CONTROL_URB -#define FILL_CONTROL_URB usb_fill_control_urb -#endif - -#ifdef DEBUG_WILDCARD -#define DPRINTK(x) printk x -#else -#define DPRINTK(x) -#endif - -// Function prototypes -static int readProSlicDirectReg(struct usb_device *dev, unsigned char address, unsigned char* data); -static int initializeIndirectRegisters(struct usb_device *dev); -static int verifyIndirectRegisters(struct usb_device *dev); -static int writeProSlicDirectReg(struct usb_device *dev, unsigned char address, unsigned char data); -static int writeProSlicInDirectReg(struct usb_device *dev, unsigned char address, unsigned short data); -static int readProSlicInDirectReg(struct usb_device *dev, unsigned char address, unsigned short *data); -static int writeProSlicInDirectReg(struct usb_device *dev, unsigned char address, unsigned short data); - -static alpha indirect_regs[] = -{ -{0,255,"DTMF_ROW_0_PEAK",0x55C2}, -{1,255,"DTMF_ROW_1_PEAK",0x51E6}, -{2,255,"DTMF_ROW2_PEAK",0x4B85}, -{3,255,"DTMF_ROW3_PEAK",0x4937}, -{4,255,"DTMF_COL1_PEAK",0x3333}, -{5,255,"DTMF_FWD_TWIST",0x0202}, -{6,255,"DTMF_RVS_TWIST",0x0202}, -{7,255,"DTMF_ROW_RATIO_TRES",0x0198}, -{8,255,"DTMF_COL_RATIO_TRES",0x0198}, -{9,255,"DTMF_ROW_2ND_ARM",0x0611}, -{10,255,"DTMF_COL_2ND_ARM",0x0202}, -{11,255,"DTMF_PWR_MIN_TRES",0x00E5}, -{12,255,"DTMF_OT_LIM_TRES",0x0A1C}, -{13,0,"OSC1_COEF",0x7B30}, -{14,1,"OSC1X",0x0063}, -{15,2,"OSC1Y",0x0000}, -{16,3,"OSC2_COEF",0x7870}, -{17,4,"OSC2X",0x007D}, -{18,5,"OSC2Y",0x0000}, -{19,6,"RING_V_OFF",0x0000}, -{20,7,"RING_OSC",0x7EF0}, -{21,8,"RING_X",0x0160}, -{22,9,"RING_Y",0x0000}, -{23,255,"PULSE_ENVEL",0x2000}, -{24,255,"PULSE_X",0x2000}, -{25,255,"PULSE_Y",0x0000}, -//{26,"RECV_DIGITAL_GAIN",0x4000}, // playback volume set lower -{26,13,"RECV_DIGITAL_GAIN",0x2000}, // playback volume set lower -{27,14,"XMIT_DIGITAL_GAIN",0x4000}, -//{27,"XMIT_DIGITAL_GAIN",0x2000}, -{28,15,"LOOP_CLOSE_TRES",0x1000}, -{29,16,"RING_TRIP_TRES",0x3600}, -{30,17,"COMMON_MIN_TRES",0x1000}, -{31,18,"COMMON_MAX_TRES",0x0200}, -{32,19,"PWR_ALARM_Q1Q2",0x07C0}, -{33,20,"PWR_ALARM_Q3Q4",0x2600}, -{34,21,"PWR_ALARM_Q5Q6",0x1B80}, -{35,22,"LOOP_CLOSURE_FILTER",0x8000}, -{36,23,"RING_TRIP_FILTER",0x0320}, -{37,24,"TERM_LP_POLE_Q1Q2",0x008C}, -{38,25,"TERM_LP_POLE_Q3Q4",0x0100}, -{39,26,"TERM_LP_POLE_Q5Q6",0x0010}, -{40,27,"CM_BIAS_RINGING",0x0C00}, -{41,64,"DCDC_MIN_V",0x0C00}, -{42,255,"DCDC_XTRA",0x1000}, -{43,66,"LOOP_CLOSE_TRES_LOW",0x1000}, -}; - -static int debug = 0; - -#define FLAG_FLIP_RELAYS (1 << 0) - -static struct wc_usb_desc wcusb = { "Wildcard S100U USB FXS Interface" }; -static struct wc_usb_desc wcusb2 = { "Wildcard S110U USB FXS Interface", FLAG_FLIP_RELAYS }; -static struct wc_usb_desc wc_usb_phone = { "Wildcard Phone Test driver" }; -static struct wc_usb_pvt *ifaces[WC_MAX_IFACES]; - - - -static void wcusb_check_keypad(struct wc_usb_pvt *p); -static int set_aux_ctrl(struct wc_usb_pvt *p, char auxpins, int on); - - - -static int Wcusb_WriteWcRegs(struct usb_device *dev, unsigned char index, - unsigned char *data, int len) -{ - unsigned int pipe = usb_sndctrlpipe(dev, 0); - int requesttype; - int res; - - requesttype = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; - - res = usb_control_msg(dev, pipe, REQUEST_NORMAL, requesttype, - 0, index, data, len, CONTROL_TIMEOUT_JIFFIES); - if (res == -ETIMEDOUT) { - printk("wcusb: timeout on vendor write\n"); - return -1; - } else if (res < 0) { - printk("wcusb: Error executing control: status=%d\n", le32_to_cpu(res)); - return -1; - } - return 0; -} - -static int Wcusb_ReadWcRegs(struct usb_device *dev, unsigned char index, - unsigned char *data, int len) -{ - unsigned int pipe = usb_rcvctrlpipe(dev, 0); - int requesttype; - int res; - - requesttype = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; - - res = usb_control_msg(dev, pipe, REQUEST_NORMAL, requesttype, - 0, index, data, len, CONTROL_TIMEOUT_JIFFIES); - if (res == -ETIMEDOUT) { - printk("wcusb: timeout on vendor write\n"); - return -1; - } else if (res < 0) { - printk("wcusb: Error executing control: status=%d\n", le32_to_cpu(res)); - return -1; - } else { - DPRINTK(("wcusb: Executed read, result = %d (data = %04x)\n", le32_to_cpu(res), (int) *data)); - } - return 0; -} - -#ifdef USB2420 -#if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) -static int wcusb_async_read(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb, struct pt_regs *regs)); -static int wcusb_async_write(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb, struct pt_regs *regs)); -static void wcusb_async_control(struct urb *urb, struct pt_regs *regs); -#else -static int wcusb_async_read(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb)); -static int wcusb_async_write(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb)); -static void wcusb_async_control(struct urb *urb); -#endif /* LINUX26 */ -#else -static int wcusb_async_read(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(urb_t *urb)); -static int wcusb_async_write(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(urb_t *urb)); -static void wcusb_async_control(urb_t *urb); -#endif - -static void proslic_read_direct_async(struct wc_usb_pvt *p, unsigned char address) -{ - p->wcregindex = address; - p->wcregbuf[0] = address | 0x80; - p->wcregbuf[1] = 0; - p->wcregbuf[2] = 0; - p->wcregbuf[3] = 0x67; - wcusb_async_write(p, WCUSB_SPORT0, p->wcregbuf, 4, STATE_WCREAD_WRITEREG, wcusb_async_control); -} - -static void proslic_write_direct_async(struct wc_usb_pvt *p, unsigned char address, unsigned char val) -{ - p->wcregindex = address; - p->wcregbuf[0] = address & 0x7f; - p->wcregbuf[1] = val; - p->wcregbuf[2] = 0; - p->wcregbuf[3] = 0x27; - wcusb_async_write(p, WCUSB_SPORT0, p->wcregbuf, 4, STATE_WCWRITE_WRITERES, wcusb_async_control); -} - -#ifdef USB2420 -#if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) -static void wcusb_async_control(struct urb *urb, struct pt_regs *regs) -#else -static void wcusb_async_control(struct urb *urb) -#endif -#else -static void wcusb_async_control(urb_t *urb) -#endif -{ - struct wc_usb_pvt *p = urb->context; - p->urbcount--; - if (urb->status) { - printk("Error in transfer...\n"); - /* return is the "right thing", but don't... */ - p->timer = 50; - /* return; */ - } - if (!(p->flags & FLAG_RUNNING)) { - return; - } - switch (p->controlstate) { - case STATE_WCREAD_WRITEREG: - /* We've written the register to sport0, now read form sport 1 */ - wcusb_async_read(p, WCUSB_SPORT1, &p->wcregval, 1, STATE_WCREAD_READRES, wcusb_async_control); - return; - case STATE_WCREAD_READRES: - switch(p->wcregindex) { - case 68: - if (!p->hookstate && (p->wcregval & 1)) { - p->hookstate = 1; - if (debug) - printk("Going off hook...\n"); - zt_hooksig(&p->chan, ZT_RXSIG_OFFHOOK); - } else if (p->hookstate && !(p->wcregval & 1)) { - p->hookstate = 0; - if (debug) - printk("Going on hook...\n"); - zt_hooksig(&p->chan, ZT_RXSIG_ONHOOK); - } - /* Set outgoing hook state if necessary */ - if (p->txhook != p->newtxhook) { - if (debug) - printk("Really setting hook state to %d\n", p->newtxhook); - p->txhook = p->newtxhook; - proslic_write_direct_async(p, 64, p->newtxhook); - } else - p->timer = 50; - break; - case 64: - if (debug) - printk("Read hook state as %02x\n", p->wcregval); - p->timer = 50; - break; - default: - printk("dunno what to do with read/regindex %d\n", p->wcregindex); - p->wcregindex = 0; - } - return; - case STATE_WCWRITE_WRITERES: - switch(p->wcregindex) { - case 64: - if (debug) { - printk("Hook transition complete to %d\n", ((char *)(urb->transfer_buffer))[1]); -#ifdef BOOST_RINGER - } - if (p->txhook == 4) { - /* Ringing -- boost battery to 96V */ - proslic_write_direct_async(p, 74, 0x3f); - } else { - /* Leave battery at default 75V */ - proslic_write_direct_async(p, 74, 0x32); - } - break; - case 74: - if (debug) { - printk("Battery set to -%dV\n", ((char *)(urb->transfer_buffer))[1] * 3 / 2); -#endif - proslic_read_direct_async(p, 64); - } else - p->timer = 50; - break; - default: - printk("dunno what to do with write/regindex %d\n", p->wcregindex); - p->wcregindex = 0; - } - return; - default: - printk("async control in unknown state %d\n", p->controlstate); - } -} - -#ifdef USB2420 -#if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) -static void keypad_check_done(struct urb *urb, struct pt_regs *regs) -#else -static void keypad_check_done(struct urb *urb) -#endif -#else -static void keypad_check_done(urb_t *urb) -#endif -{ - struct wc_usb_pvt *p = urb->context; - struct wc_keypad_data *d = p->pvt_data; - static char aux_pattern[] = {0x1e, 0x1d, 0x17, 0xf}; - char digit = 'z'; - - p->urbcount--; - if (!d->running) { - printk("Stopping stream (check_done)\n"); - return; - } - - if (urb->status) { - printk("status %d\n", urb->status); - } - - if (debug) printk("i is %d\n", d->i); - switch (d->state) { -loop_start: - case STATE_FOR_LOOP_1_OUT: - if (debug) printk("data12 is %x\n", d->data12); - if(d->i < sizeof(aux_pattern) / sizeof(char)) { - d->tmp = aux_pattern[d->i] | (d->data12 & 0xe0); - d->state = STATE_FOR_LOOP_2_IN; - if (debug) printk("tmp is %x\n", d->tmp); - wcusb_async_write(p, 0x12, &d->tmp, 1, 0, keypad_check_done); - return; - } else { - goto func_end; - } - case STATE_FOR_LOOP_2_IN: - d->state = STATE_FOR_LOOP_PROC_DATA; - wcusb_async_read(p, 0xc0, &d->data, 1, 0, keypad_check_done); - return; - case STATE_FOR_LOOP_PROC_DATA: - d->state = STATE_FOR_LOOP_CLEAR_DIGIT; - if(debug) printk("data is %x\n", d->data); - if ((d->data & 0x1f) != 0x1f) { - if(d->data == 0xe && aux_pattern[d->i] == 0x1e) { digit = '1';} - else if(d->data == 0xd && aux_pattern[d->i] == 0x1e) { digit = '2';} - else if(d->data == 0xb && aux_pattern[d->i] == 0x1e) { digit = '3';} - else if(d->data == 0x7 && aux_pattern[d->i] == 0x1e) { - p->hookstate = 0; /* On||Off */ - zt_hooksig(&p->chan, ZT_RXSIG_ONHOOK); - } - - else if(d->data == 0xe && aux_pattern[d->i] == 0x1d) { digit = '4';} - else if(d->data == 0xd && aux_pattern[d->i] == 0x1d) { digit = '5';} - else if(d->data == 0xb && aux_pattern[d->i] == 0x1d) { digit = '6';} - else if(d->data == 0x7 && aux_pattern[d->i] == 0x1d) { - p->hookstate = 1;/* Dial */ - zt_hooksig(&p->chan, ZT_RXSIG_OFFHOOK); - } - - else if(d->data == 0xe && aux_pattern[d->i] == 0x17) { digit = '7';} - else if(d->data == 0xd && aux_pattern[d->i] == 0x17) { digit = '8';} - else if(d->data == 0xb && aux_pattern[d->i] == 0x17) { digit = '9';} - else if(d->data == 0x7 && aux_pattern[d->i] == 0x17) d->scanned_event = 15; /* ReDial */ - - else if(d->data == 0xe && aux_pattern[d->i] == 0xf) { digit = '*';}/* '*' */ - else if(d->data == 0xd && aux_pattern[d->i] == 0xf) { digit = '0';} - else if(d->data == 0xb && aux_pattern[d->i] == 0xf) { digit = '#';} /* '#' */ - else if(d->data == 0x7 && aux_pattern[d->i] == 0xf) d->scanned_event = 16; /* Volume? */ - else { - (d->i)++; - if (debug) printk("Scanned event %d; data = %x\n", d->scanned_event, d->data); - goto loop_start; - } - } else { - if(debug) printk("Hit new if\n"); - goto func_end; - } - if (debug) printk("wcusb: got digit %d\n", d->scanned_event); - if (digit != 'z') { - d->tone = zt_dtmf_tone(&p->chan, digit); - if (!d->tone) { - printk("wcusb: Didn't get a tone structure\n"); - goto func_end; - } - zt_init_tone_state(&d->ts, d->tone); - p->sample = STREAM_DTMF; - } - d->count = 0; - case STATE_FOR_LOOP_CLEAR_DIGIT: - if (((d->data & 0xf) != 0xf) && d->count < 200) { - wcusb_async_read(p, 0xc0, &d->data, 1, 0, keypad_check_done); - return; - } - (d->i)++; - p->sample = STREAM_NORMAL; - goto loop_start; - } -func_end: - p->timer = 100; - return; -} - -static void wcusb_check_interrupt(struct wc_usb_pvt *p) -{ - /* Start checking for interrupts */ - if (p->devclass == WC_KEYPAD) { - wcusb_check_keypad(p); - } else { - proslic_read_direct_async(p, 68); - } - return; -} - -#ifdef USB2420 -#if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) -static int wcusb_async_read(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb, struct pt_regs *regs)) -#else -static int wcusb_async_read(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb)) -#endif /* LINUX26 */ -#else -static int wcusb_async_read(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(urb_t *urb)) -#endif -{ - __u16 size = len; - __u16 ind = index; -#ifdef USB2420 - struct urb *urb = &p->control; - memset(urb, 0, sizeof(struct urb)); - - p->dr.bRequestType = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; - p->dr.bRequest = REQUEST_NORMAL; - p->dr.wValue = 0; - p->dr.wIndex = cpu_to_le16(ind); - p->dr.wLength = cpu_to_le16(size); -#else - urb_t *urb = &p->control; - memset(urb, 0, sizeof(urb_t)); - - p->dr.requesttype = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; - p->dr.request = REQUEST_NORMAL; - p->dr.value = 0; - p->dr.index = cpu_to_le16(ind); - p->dr.length = cpu_to_le16(size); -#endif - - FILL_CONTROL_URB(urb, p->dev, usb_rcvctrlpipe(p->dev, 0), (unsigned char *)&p->dr, data, len, complete, p); -#ifdef LINUX26 - if (usb_submit_urb(urb, GFP_KERNEL)) -#else - if (usb_submit_urb(urb)) -#endif - { - printk("wcusb_async_read: control URB died\n"); - p->timer = 50; - return -1; - } - p->controlstate = state; - p->urbcount++; - return 0; -} - -#ifdef USB2420 -#if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) -static int wcusb_async_write(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb, struct pt_regs *regs)) -#else -static int wcusb_async_write(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(struct urb *urb)) -#endif /* LINUX26 */ -#else -static int wcusb_async_write(struct wc_usb_pvt *p, unsigned char index, unsigned char *data, int len, int state, void (*complete)(urb_t *urb)) -#endif -{ - __u16 size = len; - __u16 ind = index; -#ifdef USB2420 - struct urb *urb = &p->control; - memset(urb, 0, sizeof(struct urb)); - - p->dr.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; - p->dr.bRequest = REQUEST_NORMAL; - p->dr.wValue = 0; - p->dr.wIndex = cpu_to_le16(ind); - p->dr.wLength = cpu_to_le16(size); -#else - urb_t *urb = &p->control; - memset(urb, 0, sizeof(urb_t)); - - p->dr.requesttype = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; - p->dr.request = REQUEST_NORMAL; - p->dr.value = 0; - p->dr.index = cpu_to_le16(ind); - p->dr.length = cpu_to_le16(size); -#endif - - FILL_CONTROL_URB(urb, p->dev, usb_sndctrlpipe(p->dev, 0), (unsigned char *)&p->dr, data, len, complete, p); -#ifdef LINUX26 - if (usb_submit_urb(urb, GFP_KERNEL)) -#else - if (usb_submit_urb(urb)) -#endif - { - printk("wcusb_async_write: control URB died\n"); - return -1; - } - p->controlstate = state; - p->urbcount++; - return 0; -} - -/* -** Write register to Wc560 -*/ -static int wcoutp(struct usb_device *dev, unsigned char address, unsigned char data) -{ - if (!Wcusb_WriteWcRegs(dev, address, &data, 1)) - return 0; - - return -1; -} - -/* -** read register from Wc560 -*/ -static int wcinp(struct usb_device *dev, unsigned char address, unsigned char* data ) -{ - if (!Wcusb_ReadWcRegs(dev, address, data, 1)) - return 0; - - return -1; -} - -static int waitForProSlicIndirectRegAccess(struct usb_device *dev) -{ - unsigned char count, data; - count = 0; - while (count++ < 3) - { - data = 0; - readProSlicDirectReg(dev, I_STATUS, &data); - - if (!data) - return 0; - - } - - if(count > 2) printk(" ##### Loop error #####\n"); - - return -1; -} - -static int writeProSlicInDirectReg(struct usb_device *dev, unsigned char address, unsigned short data) -{ - - if(!waitForProSlicIndirectRegAccess(dev)) - { - if (!writeProSlicDirectReg(dev, IDA_LO,(unsigned char)(data & 0xFF))) - { - if(!writeProSlicDirectReg(dev, IDA_HI,(unsigned char)((data & 0xFF00)>>8))) - { - if(!writeProSlicDirectReg(dev, IAA,address)) - return 0; - } - } - } - - return -1; -} - -/* -** Read register from ProSlic -*/ -int readProSlicDirectReg(struct usb_device *dev, unsigned char address, unsigned char* dataRead) -{ - unsigned char data[4]; - - data[0] = address | 0x80; - data[1] = 0; - data[2] = 0; - data[3] = 0x67; - - // write to WC register 0x26 - Wcusb_WriteWcRegs(dev, WCUSB_SPORT0, data, 4); - Wcusb_ReadWcRegs(dev, WCUSB_SPORT1, data, 1); - *dataRead = data[0]; - - return 0; -} - -/* -** Write register to ProSlic -*/ -int writeProSlicDirectReg(struct usb_device *dev, unsigned char address, unsigned char RegValue) -{ - unsigned char data[4]; - - data[0] = address & 0x7f; - data[1] = RegValue; - data[2] = 0; - data[3] = 0x27; - - // write to WC register 0x26 - return Wcusb_WriteWcRegs(dev, WCUSB_SPORT0, data, 4); -} - -static int readProSlicInDirectReg(struct usb_device *dev, unsigned char address, unsigned short *data) -{ - if (!waitForProSlicIndirectRegAccess(dev)) - { - if (!writeProSlicDirectReg(dev,IAA,address)) - { - if(!waitForProSlicIndirectRegAccess(dev)) - { - unsigned char data1, data2; - - if (!readProSlicDirectReg(dev,IDA_LO, &data1) && !readProSlicDirectReg (dev, IDA_HI, &data2)) - { - *data = data1 | (data2 << 8); - return 0; - } else - printk("Failed to read direct reg\n"); - } else - printk("Failed to wait inside\n"); - } else - printk("failed write direct IAA\n"); - } else - printk("failed to wait\n"); - - return -1; -} - -static int initializeIndirectRegisters(struct usb_device *dev) -{ - unsigned char i; - - for (i=0; i<43; i++) - { - if(writeProSlicInDirectReg(dev, i,indirect_regs[i].initial)) - return -1; - } - - return 0; -} - -static int verifyIndirectRegisters(struct usb_device *dev) -{ - int passed = 1; - unsigned short i,j, initial; - - for (i=0; i<43; i++) - { - if(readProSlicInDirectReg(dev, (unsigned char) i, &j)) { - printk("Failed to read indirect register %d\n", i); - return -1; - } - initial= indirect_regs[i].initial; - - if ( j != initial ) - { - printk("!!!!!!! %s iREG %X = %X should be %X\n", - indirect_regs[i].name,i,j,initial ); - passed = 0; - } - } - - if (passed) { - if (debug) - printk("Init Indirect Registers completed successfully.\n"); - } else { - printk(" !!!!! Init Indirect Registers UNSUCCESSFULLY.\n"); - } - - return 0; -} - -static int calibrateAndActivateProSlic(struct usb_device *dev) -{ - unsigned char x; - - if(writeProSlicDirectReg(dev, 92, 0xc8)) - return -1; - - if(writeProSlicDirectReg(dev, 97, 0)) - return -1; - - if(writeProSlicDirectReg(dev, 93, 0x19)) - return -1; - - if(writeProSlicDirectReg(dev, 14, 0)) - return -1; - - if(writeProSlicDirectReg(dev, 93, 0x99)) - return -1; - - if(!readProSlicDirectReg (dev, 93, &x)) - { - if (debug) - printk("DC Cal x=%x\n",x); - - if (!writeProSlicDirectReg(dev, 97, 0)) - { - if(!writeProSlicDirectReg(dev, CALIBR1, CALIBRATE_LINE)) - { - unsigned char data; - - if(!readProSlicDirectReg(dev, CALIBR1, &data)) - return writeProSlicDirectReg(dev, LINE_STATE,ACTIVATE_LINE); - } - } - } - - return -1; -} - -static int InitProSlic(struct usb_device *dev) -{ - if (writeProSlicDirectReg(dev, 67, 0x0e)) - /* Disable Auto Power Alarm Detect and other "features" */ - return -1; - if (initializeIndirectRegisters(dev)) { - printk(KERN_INFO "Indirect Registers failed to initialize.\n"); - return -1; - } - if (verifyIndirectRegisters(dev)) { - printk(KERN_INFO "Indirect Registers failed verification.\n"); - return -1; - } - if (calibrateAndActivateProSlic(dev)) { - printk(KERN_INFO "ProSlic Died on Activation.\n"); - return -1; - } - if (writeProSlicInDirectReg(dev, 97, 0x0)) { // Stanley: for the bad recording fix - printk(KERN_INFO "ProSlic IndirectReg Died.\n"); - return -1; - } - if (writeProSlicDirectReg(dev, 1, 0x2a)) { // U-Law GCI 8-bit interface - printk(KERN_INFO "ProSlic DirectReg Died.\n"); - return -1; - } - if (writeProSlicDirectReg(dev, 2, 0)) // Tx Start count low byte 0 - return -1; - if (writeProSlicDirectReg(dev, 3, 0)) // Tx Start count high byte 0 - return -1; - if (writeProSlicDirectReg(dev, 4, 0)) // Rx Start count low byte 0 - return -1; - if (writeProSlicDirectReg(dev, 5, 0)) // Rx Start count high byte 0 - return -1; - if (writeProSlicDirectReg(dev, 8, 0x0)) // disable loopback - return -1; - if (writeProSlicDirectReg(dev, 18, 0xff)) // clear all interrupt - return -1; - if (writeProSlicDirectReg(dev, 19, 0xff)) - return -1; - if (writeProSlicDirectReg(dev, 20, 0xff)) - return -1; - if (writeProSlicDirectReg(dev, 21, 0x00)) // enable interrupt - return -1; - if (writeProSlicDirectReg(dev, 22, 0x02)) // Loop detection interrupt - return -1; - if (writeProSlicDirectReg(dev, 23, 0x01)) // DTMF detection interrupt - return -1; - if (writeProSlicDirectReg(dev, 72, 0x20)) - return -1; -#ifdef BOOST_RINGER - /* Beef up Ringing voltage to 89V */ - if (writeProSlicInDirectReg(dev, 23, 0x1d1)) - return -1; -#endif - return 0; -} - -static int init_hardware(struct wc_usb_pvt *p) -{ - struct usb_device *dev = p->dev; - - switch (p->devclass) { - case WC_PROSLIC: - if (wcoutp(dev, 0x12, 0x00)) /* AUX6 as output, set to low */ - return -1; - if (wcoutp(dev, 0x13, 0x40)) /* AUX6 is output */ - return -1; - if (wcoutp(dev, 0, 0x50)) /* extrst, AUX2 is suspend */ - return -1; - if (wcoutp(dev, 0x29, 0x20)) /* enable SerialUP AUX pin definition */ - return -1; - if (wcoutp(dev, 0, 0x51)) /* no extrst, AUX2 is suspend */ - return -1; - /* Make sure there is no gain */ - if (wcoutp(dev, 0x22, 0x00)) - return -1; - if (wcoutp(dev, 0x23, 0xf2)) - return -1; - if (wcoutp(dev, 0x24, 0x00)) - return -1; - if (wcoutp(dev, 0x25, 0xc9)) - return -1; - if (InitProSlic(dev)) { - printk("wcusb: Failed to initialize proslic\n"); - return -1; - } - case WC_KEYPAD: - set_aux_ctrl(p, WC_AUX0, 1); - set_aux_ctrl(p, WC_AUX1, 1); - set_aux_ctrl(p, WC_AUX2, 1); - set_aux_ctrl(p, WC_AUX3, 1); - } - - if (debug) printk("wcusb: Setting correct interfaces.\n"); - - /* Setup correct settings (8000 Hz, signed linear) */ - if (usb_set_interface(dev, 2, 1)) { - printk("wcusb: Unable to setup USB interface 2 to altsetting 1\n"); - return -1; - } - if (usb_set_interface(dev, 3, 1)) { - printk("wcusb: Unable to setup USB interface 3 to altsetting 1\n"); - return -1; - } - return 0; -} - -/* Don't call from an interrupt context */ -static int set_aux_ctrl(struct wc_usb_pvt *p, char uauxpins, int on) -{ - char udata12 = 0; - char udata13 = 0; - - wcinp(p->dev, 0x12, &udata12); - wcinp(p->dev, 0x13, &udata13); - - wcoutp(p->dev, 0x12, on ? (uauxpins | udata12) : (~uauxpins & udata12)); - wcoutp(p->dev, 0x13, uauxpins | udata13); - - return 0; -} - -static void wcusb_check_keypad(struct wc_usb_pvt *p) -{ - struct wc_keypad_data *d = p->pvt_data; - - if (!d->running) { - printk("Stopping keypad stream\n"); - return; - } - if (debug) printk("Launched a packet\n"); - d->state = STATE_FOR_LOOP_1_OUT; - d->data = -1; - d->data12 = -1; - d->scanned_event = -1; - d->i = 0; - wcusb_async_read(p, 0x12, &d->data12, 1, 0, keypad_check_done); - return; -} - -static char wc_dtmf(struct wc_usb_pvt *p) -{ - struct wc_keypad_data *d = p->pvt_data; - short linsample = 0; - - if (!d) { - printk("NULL pointer, go away\n"); - return 0; - } - - linsample = zt_tone_nextsample(&d->ts, d->tone); - - - return ZT_LIN2MU(linsample); -} - -#if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) -static void wcusb_read_complete(struct urb *q, struct pt_regs *regs) -#else -static void wcusb_read_complete(struct urb *q) -#endif -{ - struct wc_usb_pvt *p = q->context; - short *chunk = q->transfer_buffer; - int x; - - if (!p->flags & FLAG_RUNNING) { - /* Stop sending URBs since we're not running anymore */ - p->urbcount--; - return; - } - - switch (p->sample) { - case STREAM_NORMAL: - for (x = 0; x < ZT_CHUNKSIZE; x++) { - p->chan.readchunk[x] = ZT_LIN2MU(le16_to_cpu(chunk[x])); - } - break; - case STREAM_DTMF: - for (x = 0; x < ZT_CHUNKSIZE; x++) { - p->chan.readchunk[x] = wc_dtmf(p); - } - break; - } - /* XXX We could probably optimize some here XXX */ - zt_ec_chunk(&p->chan, p->chan.readchunk, p->chan.writechunk); - - zt_receive(&p->span); - - q->dev = p->dev; - -#ifdef LINUX26 - if (usb_submit_urb(q, GFP_KERNEL)) -#else - if (usb_submit_urb(q)) -#endif - { - printk("wcusb: Read cycle failed\n"); - } - - if (p->timer && !--p->timer) { - if (p->devclass == WC_KEYPAD) { - if(debug) printk("Checking keypad\n"); - wcusb_check_keypad(p); - } else { - wcusb_check_interrupt(p); - } - } - -#ifdef PROSLIC_POWERSAVE - if (p->devclass != WC_KEYPAD) { - if (p->lowpowertimer && !--p->lowpowertimer) { - /* Switch back into low power mode */ - p->idletxhookstate = 1; - if (p->txhook == 2) - p->newtxhook = p->idletxhookstate; - } - } -#endif - return; -} - -#if defined(LINUX26) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) -static void wcusb_write_complete(struct urb *q, struct pt_regs *regs) -#else -static void wcusb_write_complete(struct urb *q) -#endif -{ - struct wc_usb_pvt *p = q->context; - short *chunk = q->transfer_buffer; - int x; - - if (!p->flags & FLAG_RUNNING) { - /* Stop sending URBs since we're not running anymore */ - p->urbcount--; - return; - } - - zt_transmit(&p->span); - for (x = 0; x < ZT_CHUNKSIZE; x++) { - chunk[x] = cpu_to_le16(ZT_MULAW(p->chan.writechunk[x])); - } - q->dev = p->dev; - -#ifdef LINUX26 - if (usb_submit_urb(q, GFP_KERNEL)) -#else - if (usb_submit_urb(q)) -#endif - { - printk("wcusb: Write cycle failed\n"); - } - - return; -} - -static int StopTransmit(struct wc_usb_pvt *p) -{ - p->flags &= ~FLAG_RUNNING; - - if (p->devclass == WC_KEYPAD) { - struct wc_keypad_data *d = p->pvt_data; - d->running = 0; - } - while(p->urbcount) { - schedule_timeout(1); - } - printk("ending transmit\n"); - return 0; -} - -static int flip_relays(struct wc_usb_pvt *p, int onoff) -{ - unsigned char ctl; - unsigned char data; - /* Read data */ - if (wcinp(p->dev, 0x12, &data)) - return -1; - /* Read control */ - if (wcinp(p->dev, 0x13, &ctl)) - return -1; - /* Setup values properly -- Pins AUX3 & AUX4 control the relays */ - ctl |= 0x18; - if (onoff) { - data |= 0x18; - } else { - data &= 0xe7; - } - if (wcoutp(p->dev, 0x12, data)) - return -1; - if (wcoutp(p->dev, 0x13, ctl)) - return -1; - return 0; -} - -static int prepare_transfer_urbs(struct wc_usb_pvt *p) -{ - int x; - /* Endpoint 6 is the wave-in device */ - unsigned int readpipe = usb_rcvisocpipe(p->dev, 0x06); - /* Endpoint 7 is the wave-out device */ - unsigned int writepipe = usb_sndisocpipe(p->dev, 0x07); - - for (x = 0; x < 2; x++) { - p->dataread[x].urb.dev = p->dev; - p->dataread[x].urb.pipe = readpipe; -#ifdef LINUX26 - p->dataread[x].urb.transfer_flags = URB_ISO_ASAP; -#else - p->dataread[x].urb.transfer_flags = USB_ISO_ASAP; -#endif - p->dataread[x].urb.number_of_packets = 1; - p->dataread[x].urb.context = p; - p->dataread[x].urb.complete = wcusb_read_complete; - p->dataread[x].urb.iso_frame_desc[0].length = ZT_CHUNKSIZE * 2; - p->dataread[x].urb.iso_frame_desc[0].offset = 0; - p->dataread[x].urb.transfer_buffer = p->readchunk + ZT_CHUNKSIZE * x; - p->dataread[x].urb.transfer_buffer_length = ZT_CHUNKSIZE * 2; - - p->datawrite[x].urb.dev = p->dev; - p->datawrite[x].urb.pipe = writepipe; -#ifdef LINUX26 - p->datawrite[x].urb.transfer_flags = URB_ISO_ASAP; -#else - p->datawrite[x].urb.transfer_flags = USB_ISO_ASAP; -#endif - p->datawrite[x].urb.number_of_packets = 1; - p->datawrite[x].urb.context = p; - p->datawrite[x].urb.complete = wcusb_write_complete; - p->datawrite[x].urb.iso_frame_desc[0].length = ZT_CHUNKSIZE * 2; - p->datawrite[x].urb.iso_frame_desc[0].offset = 0; - p->datawrite[x].urb.transfer_buffer = p->writechunk + ZT_CHUNKSIZE * x; - p->datawrite[x].urb.transfer_buffer_length = ZT_CHUNKSIZE * 2; - - } - return 0; -} - -static int begin_transfer(struct wc_usb_pvt *p) -{ - - int x; - p->urbcount = 4; - p->flags |= FLAG_RUNNING; - - for (x = 0; x < 2; x++) { -#ifdef LINUX26 - if (usb_submit_urb(&p->dataread[x].urb, GFP_KERNEL)) -#else - if (usb_submit_urb(&p->dataread[x].urb)) -#endif - { - printk(KERN_ERR "wcusb: Read submit failed\n"); - return -1; - } -#ifdef LINUX26 - if (usb_submit_urb(&p->datawrite[x].urb, GFP_KERNEL)) -#else - if (usb_submit_urb(&p->datawrite[x].urb)) -#endif - { - printk(KERN_ERR "wcusb: Write submit failed\n"); - return -1; - } - } - /* Start checking for interrupts */ - wcusb_check_interrupt(p); - return 0; -} - -static int wc_usb_hooksig(struct zt_chan *chan, zt_txsig_t txsig) -{ - struct wc_usb_pvt *p = chan->pvt; - - switch (p->devclass) { - case WC_PROSLIC: -#ifdef PROSLIC_POWERSAVE - if (p->txhook == 4) { - /* Switching out of ring... Be sure we idle at 2, not 1 at least - for a bit so we can transmit caller*ID */ - p->idletxhookstate = 2; - p->lowpowertimer = POWERSAVE_TIME; - } -#endif - - p->txhook = -1; - switch(txsig) { - case ZT_TXSIG_ONHOOK: - switch(chan->sig) { - case ZT_SIG_FXOKS: - case ZT_SIG_FXOLS: - p->newtxhook = p->idletxhookstate; - break; - case ZT_SIG_FXOGS: - p->newtxhook = 3; - break; - } - break; - case ZT_TXSIG_OFFHOOK: - p->newtxhook = p->idletxhookstate; - break; - case ZT_TXSIG_START: - p->newtxhook = 4; - break; - case ZT_TXSIG_KEWL: - p->newtxhook = 0; - break; - } - case WC_KEYPAD: - switch (txsig) { - case ZT_TXSIG_ONHOOK: - break; - case ZT_TXSIG_OFFHOOK: - break; - case ZT_TXSIG_START: - break; - case ZT_TXSIG_KEWL: - break; - } - break; - } - return 0; -} - -static int wc_usb_open(struct zt_chan *chan) -{ - struct wc_usb_pvt *p = chan->pvt; - if (p->dead) - return -1; - switch (p->devclass) { - case WC_KEYPAD: - p->hookstate = 0; - zt_hooksig(&p->chan, ZT_RXSIG_ONHOOK); - break; - default: - break; - } -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#endif - p->usecount++; - return 0; -} - -static int wc_usb_close(struct zt_chan *chan) -{ - struct wc_usb_pvt *p = chan->pvt; - p->usecount--; - if (!p->usecount && p->dead) { - /* Someone unplugged us while we were running, so now - that the program exited, we can release our resources */ - zt_unregister(&p->span); - ifaces[p->pos] = NULL; - if (p->pvt_data) - kfree(p->pvt_data); - kfree(p); - } -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#endif - return 0; -} - -static struct wc_usb_pvt *wc_detect_device(struct usb_device *dev, struct wc_usb_pvt *orig) -{ - struct wc_usb_pvt *p; - - p = orig; - if (!p) { - p = kmalloc(sizeof(struct wc_usb_pvt), GFP_KERNEL); - if (!p) { - printk("wcusb: kmalloc failed\n"); - return NULL; - } - - memset(p, 0, sizeof(struct wc_usb_pvt)); - } - p->dev = dev; - -#ifdef PROSLIC_POWERSAVE - /* By default we can't send on hook */ - p->idletxhookstate = 1; -#else - /* By default we can always send on hook */ - p->idletxhookstate = 2; -#endif - - printk("wcusb: wc_detect_device\n"); - if (dev->descriptor.idProduct == 0xb210) { - struct wc_keypad_data *d = kmalloc(sizeof(struct wc_keypad_data), GFP_KERNEL); - printk("wcusb: Found a WC Keyed Phone\n"); - p->devclass = WC_KEYPAD; - if (!d) { - printk("wcusb: kmalloc failed in init_device_pvt\n"); - return NULL; - } - memset(d, 0, sizeof(struct wc_keypad_data)); - p->pvt_data = d; - d->count = 0; - d->running = 1; - d->tone = NULL; - return p; - } else { - p->pvt_data = NULL; - p->devclass = WC_PROSLIC; - } - printk("Second exit\n"); - return p; -} - -static int wc_set_zaptel(struct wc_usb_pvt *p) -{ - int x; - - for (x = 0; x < WC_MAX_IFACES; x++) - if (!ifaces[x]) break; - if (x >= WC_MAX_IFACES) { - printk("wcusb: Too many interfaces\n"); - return -1; - } - - sprintf(p->span.name, "WCUSB/%d", x); - snprintf(p->span.desc, sizeof(p->span.desc) - 1, "%s %d", p->span.name, x); - sprintf(p->chan.name, "WCUSB/%d/%d", x, 0); - p->span.manufacturer = "Digium"; - strncpy(p->span.devicetype, p->variety, sizeof(p->span.devicetype) - 1); - - p->chan.sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS; /* We're capabable of both FXOKS and FXOLS */ - p->chan.chanpos = 1; - p->span.deflaw = ZT_LAW_MULAW; - p->span.chans = &p->chan; - p->span.channels = 1; - p->span.hooksig = wc_usb_hooksig; - p->span.open = wc_usb_open; - p->span.close = wc_usb_close; - - ifaces[x] = p; - p->pos = x; - p->span.flags = ZT_FLAG_RBS; - init_waitqueue_head(&p->span.maintq); - p->span.pvt = p; - p->chan.pvt = p; - - /* Set the stream to just pass the data from the device uninhibited */ - p->sample = STREAM_NORMAL; - - if (zt_register(&p->span, 0)) { - printk("wcusb: Unable to register span %s\n", p->span.name); - return -1; - } - - return 0; -} - -#ifdef LINUX26 -static int wc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) -#else -static void *wc_usb_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id) -#endif -{ - struct wc_usb_pvt *p = NULL; - struct wc_usb_desc *d = (struct wc_usb_desc *)id->driver_info; -#ifdef LINUX26 - struct usb_device *dev = interface_to_usbdev(intf); -#endif - - int x; - for (x=0;xdead) { - if (debug) - printk("Device slot %d can be revived\n", x); - break; - } - if (debug) - printk("Device slot %d is still in use\n", x); - } - - if (!(p = wc_detect_device(dev, p))) { - printk("wcusb: No wcusb devices found\n"); -#ifdef LINUX26 - return -ENODEV; -#else - return NULL; -#endif - } - -#ifndef LINUX26 - if (usb_set_configuration(dev, dev->config[0].bConfigurationValue) < 0) { - printk("wcusb: set_configuration failed (ConfigValue 0x%x)\n", dev->config[0].bConfigurationValue); - return NULL; - } -#endif - - if (init_hardware(p)) { - printk("wcusb: Hardware intialization failed.\n"); - goto cleanup; - } - - if (prepare_transfer_urbs(p)) { - printk("wcusb: problem preparing the urbs for transfer\n"); - goto cleanup; - } - - if (d->flags & FLAG_FLIP_RELAYS) { - flip_relays(p, 1); - } - - if (!p->dead && wc_set_zaptel(p)) { - printk("wcusb: Error in starting the zaptel stuff\n"); - goto cleanup; - } - - if (begin_transfer(p)) { - printk("wcusb: Something went wrong when starting the transfer\n"); - goto cleanup; - } - - if (p->dead) - printk("wcusb: Rekindling a %s (%s)\n", d->name, p->span.name); - else - printk("wcusb: Found a %s (%s)\n", d->name, p->span.name); - - /* Reset deadness */ - p->dead = 0; - /* Clear alarms */ - p->span.alarms = 0; - p->variety = d->name; - zt_alarm_notify(&p->span); -#ifdef LINUX26 - usb_set_intfdata(intf, p); - return 0; -#else - return p; -#endif - -cleanup: - printk("cleanup\n"); - if (p) { - if (p->pvt_data) { - kfree(p->pvt_data); - } - kfree(p); - } -#ifdef LINUX26 - return -ENODEV; -#else - return NULL; -#endif -} - -#ifdef LINUX26 -static void wc_usb_disconnect(struct usb_interface *intf) -#else -static void wc_usb_disconnect(struct usb_device *dev, void *ptr) -#endif -{ - /* Doesn't handle removal if we're in use right */ -#ifdef LINUX26 - struct wc_usb_pvt *p = usb_get_intfdata(intf); -#else - struct wc_usb_pvt *p = ptr; -#endif - if (p) { - StopTransmit(p); - p->dev = NULL; - if (!p->usecount) { - zt_unregister(&p->span); - if (p->pvt_data) - kfree(p->pvt_data); - ifaces[p->pos] = NULL; - kfree(p); - } else { - /* Generate alarm and note that we're dead */ - p->span.alarms = ZT_ALARM_RED; - zt_alarm_notify(&p->span); - p->dead = 1; - } - } - printk("wcusb: Removed a Wildcard device\n"); -#ifdef LINUX26 - usb_set_intfdata(intf, NULL); -#endif - return; -} - -static struct usb_device_id wc_dev_ids[] = { - /* This needs to be a USB audio device, and it needs to be made by us and have the right device ID */ - { - match_flags: (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_DEVICE), - bInterfaceClass: USB_CLASS_AUDIO, - bInterfaceSubClass: 1, - idVendor: 0x06e6, - idProduct: 0x831c, /* Product ID / Chip configuration (you can't change this) */ - driver_info: (unsigned long)&wcusb, - }, - { - match_flags: (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_DEVICE), - bInterfaceClass: USB_CLASS_AUDIO, - bInterfaceSubClass: 1, - idVendor: 0x06e6, - idProduct: 0x831e, - driver_info: (unsigned long)&wcusb2, - }, - { - match_flags: (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_DEVICE), - bInterfaceClass: USB_CLASS_AUDIO, - bInterfaceSubClass: 1, - idVendor: 0x06e6, - idProduct: 0xb210, - driver_info: (unsigned long)&wc_usb_phone, - }, - { } /* Terminating Entry */ -}; - -static struct usb_driver wc_usb_driver = -{ -#ifdef LINUX26 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) - owner: THIS_MODULE, -#endif -#else - fops: NULL, - minor: 0, -#endif - name: "wcusb", - probe: wc_usb_probe, - disconnect: wc_usb_disconnect, - id_table: wc_dev_ids, -}; - -static int __init wc_init (void) -{ - int res; - res = usb_register(&wc_usb_driver); - if (res) - return res; - printk("Wildcard USB FXS Interface driver registered\n"); - return 0; -} - -static void __exit wc_cleanup(void) -{ - usb_deregister(&wc_usb_driver); -} - -MODULE_AUTHOR("Matthew Fredrickson "); -MODULE_DESCRIPTION("Wildcard USB FXS Interface driver"); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif - -MODULE_DEVICE_TABLE(usb, wc_dev_ids); - -module_init(wc_init); -module_exit(wc_cleanup); diff --git a/wcusb.h b/wcusb.h deleted file mode 100644 index f22d0ac..0000000 --- a/wcusb.h +++ /dev/null @@ -1,142 +0,0 @@ - -#ifndef _WCUSB_H -#define _WCUSB_H - -#include -#include -#include -#include - -#include -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19) -#define USB2420 -#endif - -#include "zaptel.h" - -#define WC_MAX_IFACES 128 - -#define POWERSAVE_TIME 4000 /* Powersaving timeout for devices with a proslic */ - -/* Various registers and data ports on the tigerjet part */ -#define WCUSB_SPORT0 0x26 -#define WCUSB_SPORT1 0x27 -#define WCUSB_SPORT2 0x28 -#define WCUSB_SPORT_CTRL 0x29 - -#define WC_AUX0 0x1 -#define WC_AUX1 0x2 -#define WC_AUX2 0x4 -#define WC_AUX3 0x8 - -#define CONTROL_TIMEOUT_MS (500) /* msec */ -#define CONTROL_TIMEOUT_JIFFIES ((CONTROL_TIMEOUT_MS * HZ) / 1000) - -#define REQUEST_NORMAL 4 - -#define FLAG_RUNNING (1 << 0) - -/* Important data structures and data types */ - - -/* States for the Proslic read state machine */ -typedef enum { - STATE_WCREAD_WRITEREG, - STATE_WCREAD_READRES, - STATE_WCWRITE_WRITEREG, - STATE_WCWRITE_WRITERES, -} proslic_state_t; - -/* Used for current stream state */ -typedef enum { - STREAM_NORMAL, /* Sends normal (unmodified) audio data */ - STREAM_DTMF, /* (For keypad device) Sends dtmf data */ -} stream_t; - -/* States for the Keypad state machine */ -typedef enum { - STATE_FOR_LOOP_1_OUT, - STATE_FOR_LOOP_2_IN, - STATE_FOR_LOOP_PROC_DATA, - STATE_FOR_LOOP_CLEAR_DIGIT, -} keypad_state_t; - -/* Device types. For radical changes in a new device, use a switch based on the device type */ -typedef enum { - WC_KEYPAD, /* The tigerjet phone with the keypad. That was a bugger to implement */ - WC_PROSLIC, /* For various devices with a proslic */ -} dev_type_t; - -struct wc_keypad_data { - keypad_state_t state; /* Current state in the keypad detect routine */ -#ifdef USB2420 - struct urb urb; /* urb used for the keypad data transport ... can't remember whether it is used or not */ -#else - urb_t urb; /* urb used for the keypad data transport ... can't remember whether it is used or not */ -#endif - int running; - char data; - char data12; - char tmp; - int scanned_event; - int i; - int count; - /* DTMF tone generation stuff for zaptel */ - struct zt_tone_state ts; - struct zt_tone *tone; -}; - -struct stinky_urb { -#ifdef USB2420 - struct urb urb; -#ifndef LINUX26 - struct iso_packet_descriptor isoframe[1]; -#endif -#else - urb_t urb; - iso_packet_descriptor_t isoframe[1]; -#endif -}; - -struct wc_usb_pvt { - const char *variety; - struct usb_device *dev; - dev_type_t devclass; - int usecount; - int dead; - struct zt_span span; - struct zt_chan chan; - struct stinky_urb dataread[2]; - struct stinky_urb datawrite[2]; -#ifdef USB2420 - struct urb control; - struct usb_ctrlrequest dr; -#else - urb_t control; - devrequest dr; -#endif - proslic_state_t controlstate; - int urbcount; - int flags; - int timer; - int lowpowertimer; - int idletxhookstate; - int hookstate; - __u8 newtxhook; - __u8 txhook; - int pos; - unsigned char auxstatus; - unsigned char wcregindex; - unsigned char wcregbuf[4]; - unsigned char wcregval; - short readchunk[ZT_MAX_CHUNKSIZE * 2]; - short writechunk[ZT_MAX_CHUNKSIZE * 2]; - stream_t sample; - void *pvt_data; -}; - -struct wc_usb_desc { - char *name; - int flags; -}; -#endif diff --git a/xpp/.version b/xpp/.version deleted file mode 100644 index d658f52..0000000 --- a/xpp/.version +++ /dev/null @@ -1 +0,0 @@ -trunk-r5254 diff --git a/xpp/Changelog_xpp b/xpp/Changelog_xpp deleted file mode 100644 index 31684e0..0000000 --- a/xpp/Changelog_xpp +++ /dev/null @@ -1,232 +0,0 @@ -Thu Jan 10 2008 Oron Peled - xpp.r5254 - * Improved polarity reversal hangups in FXO (r5194). - Fixed false detection of polarity reversals. - * Optimize xframe allocation, by not zeroing the whole - memory (in get_xframe()). - * Fixed erronous error message that appeared sometimes - from fpga_load during USB renumeration. - * Zaptel::Chans now provides battery() reporting for some FXO - channels (Astribank FXO and wcfxo). - -Tue Dec 25 2007 Tzafrir Cohen - xpp.r5179 - * xpd_pri: Basically ready. - * PCM synchronization changes: - - Each Astribank unit ticks independently. Each with its own PLL. - - HOST synchronization is gone. Loading of xpp will no longer cause - useless 250 ticks per second if you have no Astribank. - - Synchronization from the zaptel sync master requires setting - ZAPTEL as sync source (xpp_sync ZAPTEL). - * rx_tasklet is now a parameter of the module xpp, rather than of xpp_usb. - * New FPGA firmware: 5128 (1151) / 5122 (1141, 1131): - - Fixes synchronization issues. - - PRI module: E1/T1 should now work. - * perl module and utilities: - - Modules no longer magically scan system on initialization. - - Scanning is by calling explicit methods. - - "Serial" has been renamed "Label". It is basically unique, but - should be modifieble. - - Some basic documentation of zaptel perl modules. - * Default sort order of zt_registration is back to SORT_CONNCTOR. - * zt_registration proc file now shows the number of span registered to - if registered. Try: grep . /proc/xpp/XBUS-*/XPD-*/zt_registration - * genzaptelconf: Allow using a custom command instead of - /etc/init.d/asterisk to start/stop asterisk. - * Fixed the typo "Slagish". - -Wed Nov 14 2007 Tzafrir Cohen - xpp.r5010 - * Fix a deadlock spotted on some SMP installations. - * increase FXS ring detect debounce interval. - * Improve (reduce) signal attenuation on FXO ports. - * zaptel-perl: further fixes to handling of empty slots. - -Wed Oct 3 2007 Tzafrir Cohen - xpp.r4900 - * Zaptel/Hardware perl modules: - - Use sysfs directly. Don't rely on lspci/lsusb. - - Each device has a description and driver name. - - Zaptel::Hardware::drivers() to show the list of required drivers - for this system (see zaptel_drivers). - - zaptel_hardware shows a description and a (suggested?) driver. - * zt_registration sorts by Serial first and only then by connector. - * USB_FW.hex replaces all the USB_11x0.hex . - - Separate USB interface for the management processor. - - Hence fpga_load can now work even with drivers loaded. - * Fix firmware upgrading. - * Fix manual firmware loading while auto-loading. - * Fix opermode parameter for FXO initialization (broken in r4648). - -Wed Oct 3 2007 Oron Peled - xpp.r4786 - * New firmware protocol version: 2.9 . - * fpga_load: initial clean-ups before interface split. - * genzaptelconf: Don't leave an empty directory behind (4784) - * Increase xpp poll_timeout to 1000ms - useful for CentOS 4 (r4781). - * Fix initialization anoyance: if AB don't answer to polls, don't - waitfor_xpds, and show no waiting XPDs (r4725). - * Disable dtmf_detect by default once again (r4712). - * Don't check twice for asterisk to stop. The second test was done - while Asterisk was still stopping (r4708). - * Support building the kernel with M= instead of with SUBDIRS= , as - used in some newer build systems (r4677). - -Tue Sep 11 2007 Oron Peled - xpp.r4648 - * New firmware protocol version: 2.8 . - * Cleanup INFO() messages during module loading. - - * USB: Receive queue with TASKLETS [r4600]. Controlled by rx_tasklet - parameter to xpp_usb module (can be changed in runtime). - * The pcm_tasklet parameter in xpp module is deprecated: - - Does not actually do anything. - - If set during module loading, shows an ERR() message. - - Also appears in /proc/xpp/sync - - * FXS: Hardware DTMF detection by default, can be disabled - by setting dtmf_detection=0 parameter to xpd_fxs. - PCM is muted when DTMF key is pressed. - - * zapconf: - - Can now generate users.conf compatible with asterisk-gui. - - Optional command-line arguments denoting which files to generate. - Possible values are 'zaptel', 'zapata' and 'users'. - - Defaults to creating zaptel and zapata. - - * Update to zaptel-1.4.5.1, zaptel-1.2.20.1 - * Fix building on kernel 2.6.23rc1, from Axel Thimm. - * New firmware to fix FXS leds irregularities. - * Less noise at build time - don't echo version, test compile ony once. - * zapconf can generate users.conf snippets. - -Thu Aug 16 2007 Tzafrir Cohen - xpp.r4515 - * Don't use Astribanks connected to USB1 interfaces - Unless the user set the option usb1=1 for xpp_usb (r4504). - * README.Astribank can now be generated from the makefile (r4503). - * Demote the messages about PCM in non-PCM from notice to debug (r4501). - * Fix sample BRI zapata.conf: NT instead of TE (r4498). - * Disable FXS hardware DTMF detection by default (r4492). - * Extra Zaptel PCI IDs (from Philipp Kempgen) (r4466). - -Thu Aug 2 2007 Oron Peled - xpp.r4464 - * Jump to zaptel-1.2.19 and zaptel-1.4.4 (with/without bristuff) - * BRI improvement: an 'nt_keepalive' parameter to xpd_bri forces - a BRI_NT to retry a connection indefinitely (this is our default). - When false it revert to the behaviour in changeset:4415 ("Bezeq like") - * Improvement in DBG macros. The print_dbg parameter is now set of - flags to debug. They are defined in zap_debug.h - * PRI configuration improvements (r4462): - - Hardcoded default (in init_card_9_26) is TE. - - The variable XPP_PRI_SETUP (in /etc/default/zaptel) may config - all PRI ports or some of them as we wish. Full docs are in - the utils/example_default_zaptel. - * PRI D-channel indication: Similar to BRI (r4464). - -Thu Jul 30 2007 Oron Peled - xpp.r4415 - * Show Astribank 6+2 as 6/2 channels and not 8/8 channels. - - Added as a "subtype" to the device type (r4391). - * Fixed a panic in BRI span shutdown method (r4393). - * Changes to debug macros. - * Add proper sysfs support (r4406) - - A bus on whuch all of the Astribanks reside. - - Replaces useless sysfs code that existed in the module. - - Currently used to set the sync source automatically at device - adition / removal. - * BRI: We do need the T1 timer in NT. If it gets into G2 state (rr4407). - -Thu Jul 12 2007 Oron Peled - xpp.r4372 - * Update to zaptel-1.2.18 and zaptel-1.4.3 (r4308 onward) - * Fix a critical race with zaptel synchronization (r4362) - * Added a /proc/xpp/cmds for statistics about command timing (r4360) - * Fix a digit mapping bug with hardware dtmf detection (r4357) - * In xpp/utils/Makefile add perl syntax checks to our scripts (r4337) - * Better USB data error checking (r4336) - * udev rules (xpp.rules) avoid false calls from wrong nodes (r4331) - * Improve hardware detection and reporting in lszaptel, - zaptel_hardware. zapconf is basically functional. - * Leds are blinked synchronously on all Astribanks now (r4262) - * Fix a BRI bug if OPTIMIZE_CHANMUTE was compiled into zaptel (r4258) - (This feature was not yet accepted into official zaptel) - * Removed compile warning about HZ != 1000 (r4218) - * Firmware updates. - * xpd_pri: the PRI module - * fpga_load now supports USB pathes without zeros (r4211) - * XPD numbers have changed to '' (r4196) - * Proper support for ZT_VMWI ioctl, if used in zaptel (r4092) - * Fix FXO power denial detection (r4054) - * FXO could accidentally go off-hook with some compilers (r4048) - -Tue May 1 2007 Oron Peled - xpp.r3898 - * Tested with zaptel-1.2.17.1 - * Add D-Channel TX, RX and BAD frames count in /proc/xpp/XBUS-*/XPD-*/bri_info - * Adjust output of xpp_sync script. Pad for 8 port BRI. - * Added a debugging module parport_debug (not compiled by default). - * Added an optional patch to zaptel: - - compiles only if ZAPTEL_SYNC_TICK is defined - - Allow interested driver to register for "sync" notification. - - Does not affect drivers that do not use this feature. - * Added external synchronization feature: - - Only if ZAPTEL_SYNC_TICK feature is compiled in - - Than XPP may be synchronized by another card (e.g: an Astribank - with FXS can be synchronized by a Digium PRI card). - - May be enabled/disabled in runtime via the 'sync_tick_active' module - parameter to the xpp.ko module. - * Fixed a potential bug in D-Channel hexdump printing. - * New visual indications in BRI leds: - - Constant ON RED/GREEN: Shows the port type -- NT/TE. - - Very fast "double blink": Layer1 work, no D-Channel yet. - - Steady blinking (1/2 sec): D-Channel trafic detected. - * xpp_fxloader moved to /usr/share/zaptel . - * adj_clock removed: never really used. - -Thu, 19 Apr 2007 Tzafrir Cohen - xpp.r3814 - * No need for extra patch beyond bristuff for Astribank BRI. - * Protocol no. 2.6: syncing improvements. - * Default poll intervals changed: 500 in BRI and FXO. - * Allow changing FXS polls interval at run time. - * BRI initalization fixed on SUSE (path to logger). - * When using the SUSE zaptel rpm package, set modules_var=ZAPTEL_MODULES in - /etc/sysconfig/zaptel . - * zt_registration not verbose by default. - * xpp_sync warns if FXO is sync slave. - * Extra PCM metrics data in /proc/xpp/XBUS-NN/summary . - * Extra USB metrics data in /proc/xpp/XBUS-NN/usb_info . - -Wed, 11 Apr 2007 Tzafrir Cohen - xpp.r3768 - * Removed "go away" notice and solved sync of a restarted device. - * Resetting firmware: rmmod xpp_usb; /etc/hotplug/usb/xpp_fxloader reset - * Perl modules use strict. - * genzaptelconf -F will not generate zapata configuration for NT spans. - * genzaptelconf uses perl utilities to start. - * Initial support for 2nd XHFC (BRI) chip. - -Sun, 1 Apr 2007 Tzafrir Cohen - xpp.r3712 - * New protocol version (2.5). - * Luckily firmware unloading now works. - * Solves "multiple ticks" bug. No need for pcm_tasklets workaround. - * genzaptelconf -z will generate zapscan.conf for the asterisk-gui. - * Fixed hardware detection for the BRI. - -Wed, 14 Mar 2007 Tzafrir Cohen - xpp.r3608 - * Initial verssion of firmware unloading. - * PCM bugfixes. - * Defaults of kernel parameters are now part of parameter description. - * Removed zaptel sync code for now. - * genzaptelconf will detect vzaphfc. - * genzaptelconf defaults to ptmp for BRI. - * Documentation updates. - -Mon, 26 Feb 2007 Tzafrir Cohen - xpp.r3517 - * genzaptelconf now uses ls for FXS lines by default . - * World-readable kernel parameters. - -Thu, 22 Feb 2007 Tzafrir Cohen - xpp.r3440 - * /proc/xpp/sync: 'm 0' is, while depracated, can still be used. - * New firmware with PCM improvements. - * Improvements to the xpp helper scripts. - * Bug fixes. - * zaptel/perl is now installed by xpp/utils/Makefile. - -Wed, 14 Feb 2007 Tzafrir Cohen - xpp.r3365 - * Kewlstart support on the FXS ports (already existed on the FXO ports). - * The format of /proc/xpp/sync has changed (still self-documented). - * Better notification of FXS lines that were off-hook on registration time. - * Parallel polling of Astribanks (faster startup when there are multiple - devices) - * zconf: scripts and perl modules to automate the work with Zaptel and the - Astribank. Current scripts: zt_registration, xpp_sync. diff --git a/xpp/Kbuild b/xpp/Kbuild deleted file mode 100644 index 9ec225f..0000000 --- a/xpp/Kbuild +++ /dev/null @@ -1,58 +0,0 @@ -ifdef SUBDIRS - ZAPTEL_DIR = $(SUBDIRS) -else - ZAPTEL_DIR = $(M) -endif - -EXTRA_CFLAGS = $(XPP_LOCAL_CFLAGS) \ - -I$(ZAPTEL_DIR) \ - -DDEBUG \ - -DPOLL_DIGITAL_INPUTS \ - -DWITH_ECHO_SUPPRESSION \ - -DDEBUG_PCMTX \ - -DPROTOCOL_DEBUG \ - -g - # - -ifneq (,$(shell grep -w echo_can_state_t $(ZAPTEL_DIR)/zaptel.h)) -EXTRA_CFLAGS += -DZAPTEL_EC_TYPEDEF -endif - -obj-m += xpp.o xpd_fxs.o xpd_fxo.o xpd_pri.o - -HAS_BRISTUFF := $(shell cpp $(CPPFLAGS) -dM $(ZAPTEL_DIR)/zconfig.h | sed -n 's/^.*CONFIG_ZAPATA_BRI_DCHANS/y/p') - -# Build only supported modules -ifneq (,$(filter y m,$(CONFIG_USB))) -obj-m += xpp_usb.o -endif -ifneq (,$(HAS_BRISTUFF)) -obj-m += xpd_bri.o -endif - -xpp-y += xbus-core.o xbus-sysfs.o xbus-pcm.o xframe_queue.o xpp_zap.o xproto.o card_global.o zap_debug.o -xpd_fxs-y += card_fxs.o -xpd_fxo-y += card_fxo.o -xpd_bri-y += card_bri.o -xpd_pri-y += card_pri.o - -ifeq (y,$(PARPORT_DEBUG)) -EXTRA_CFLAGS += -DDEBUG_SYNC_PARPORT -obj-m += parport_debug.o -endif - -# Handle versioning -XPP_VERSION_STR ?= $(shell if [ -r $(obj)/.version ]; then echo "\"`cat $(obj)/.version`\""; else echo '"Unknown"'; fi) -clean-files := xpp_version.h - -$(obj)/card_fxs.o $(obj)/card_fxo.o $(obj)/card_bri.o $(obj)/card_pri.o $(obj)/xpp_usb.o $(obj)/xpp.o: $(obj)/xpp_version.h - -$(obj)/xpp_version.h: FORCE - $(Q)echo '#define XPP_VERSION $(XPP_VERSION_STR)' > $@.tmp - $(Q)if cmp -s $@.tmp $@ ; then echo; else \ - mv $@.tmp $@ ; \ - fi - $(Q)rm -f $@.tmp - -.PHONY: FORCE -FORCE: diff --git a/xpp/Makefile b/xpp/Makefile deleted file mode 100644 index 00fc5ee..0000000 --- a/xpp/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# We only get here on kernels 2.6.0-2.6.9 . -# For newer kernels, Kbuild will be included directly by the kernel -# build system. --include $(src)/Kbuild - -ctags: - ctags *.[ch] diff --git a/xpp/README.Astribank b/xpp/README.Astribank deleted file mode 100644 index 342c6a9..0000000 --- a/xpp/README.Astribank +++ /dev/null @@ -1,1131 +0,0 @@ -Xorcom Astribank Documentation -============================== -Xorcom Team -$Revision$, $Date$ - -This file documents the Zaptel drivers for the Xorcom Channel Bank. -The drivers reside in a separate subdirectory, xpp/ . - -It is generally a more technical document than the -http://www.xorcom.com/documentation/manuals/[Astribank User Manual] - -An HTML version of the latest version of this document could be found at -http://zaptel.tzafrir.org.il/README.Astribank.html[] - -Building and Installation -------------------------- -Building and installation is basically like the normal procedure of -installing Zaptel with some additions. - -Building drivers -~~~~~~~~~~~~~~~~ -On zaptel 1.2 you will need to run the following extra step to build the -Astribank drivers, apart from the standard 'make': - - make -C xpp/utils install - -In order to build the user space utilities, you will need the libusb-dev -package on Debian (and derivatives like Ubuntu) or libusb-devel on RedHat -(and derivatives like CentOS/Trixbox). - -Apart from the standard 'make install' in the zaptel directory, -run: - - make -C xpp/utils install - -Though this should be done automatically on zaptel >= 1.4.1 . - -PRI Port Setup -~~~~~~~~~~~~~~ -A port in the PRI module can be either E1 (default) or T1. It can also be -either "TE" or "NT". - -TE:: - Use the bottom port (green LED) and don't invert any wiring. Hint to - higher layers that this will be the TE (CPE) side of the connection. - This is the default setup. - -NT:: - Use the top port (orange LED) and invert wiring (this is done to allow - connecting an NT port and a TE port using a standard straight 8 wires - "ethernet" cable). Hint to higher layers that this will be the NT (Net) - side of the connection. - -The value XPP_PRI_SETUP in the init configuration file (see example -below) can be used to change those defaults. This value is a -whitelist-separated list of conditions. When a port is initialized it -checks those conditions and uses the firs one that matches. - -Match expressions may be: -- CONNECTOR/usb..../XPD-nn To identify by physical connector -- NUM/XBUS-mm/XPD-nn To identify by bus number - -Match expressions may contain "wildcards": -- * matches zero or more characters. -- ? matches one charater -- [xyz] - any of 'x', 'y', or 'z'. - -For each line you should define both if it is E1 or T1 and if it is NT -or TE. - -The list implicitly contains an 'NUM/*=TE,E1' catch all default, appended -to its end. - - -Sample Configurations ---------------------- -We generally recommend to generate the configuration by using utility -genzaptelconf. The following reference configuration will work for a -system where Astribank devices are used. - - -[[sect-default]] -Zaptel Init Configuration File -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The zaptel init.d script, genzaptelconf and the XPD init scripts uses the -parameters located in file /etc/default/zaptel (on Debian) or -/etc/sysconfig/zaptel (on RedHats). There is a number of useful parameters -that may be defined there: - ------------------------------------------------------------ -# Lines beginning with '#' are considered comments and ignored. - -# A two-letter country code. genzaptelconf uses it to better guess -# the configuration it generates. E.g: the signalling of E1 spans, and -# a few other country-specific settings. -#lc_country=us - -# See genzaptelconf(8) and the script itself for a longer list of -# variables. - -# Equivalent to the parameter opermode to the module wctdm: country-specific -# settings to the FXO lines. For a complete list of possible values, see -# /usr/share/zaptel/init_fxo_mode . -#opermode=FRANCE - -# xpp_sync runs with the value of 'XPP_SYNC' as its parameter to set the -# synchronization source. The default is 'auto' that selects the best -# Astribank. 'ZAPTEL' gets synchronization from the Zaptel sync master -# span. Or a specific xbus number. -#XPP_SYNC=ZAPTEL - -# Disables hotplug firmware loading -#XPP_HOTPLUG_DISABLED=yes -# - -# Disables udev hook called when an astribank is added and ready -# or removed. -#ASTRIBANK_HOOK_DISABLED=yes - -# Setup for the Astribank PRI module: -# All the ports in the unit connected to the USB port 0000:00:1d.7-1 -# will be NT and E1. Ports no. 1 and 3 of all the other Astribanks will -# be NT and E1 (and thus ports 0 and 2 will be TE and E1). -#XPP_PRI_SETUP=' -# CONNECTOR/usb-0000:00:1d.7-1/XPD-01=NT,E1 -# NUM/*/XPD-0[13]=NT,E1 -# ' ------------------------------------------------------------ - -/etc/zaptel.conf -~~~~~~~~~~~~~~~~ - -Astribank 8 -^^^^^^^^^^^ - fxoks=1-14 - -Astribank 6FXS/2FXO -^^^^^^^^^^^^^^^^^^^ - fxoks=1-12 - fxsks=13-14 - -Astribank 16: 8FXS/8FXO -^^^^^^^^^^^^^^^^^^^^^^^ - fxoks=1-14 - fxsks=15-22 - -Astribank 4 BRI -^^^^^^^^^^^^^^^ - # Assumed ports settings: - # Ports 1,3: TE - # Ports 2,4: NT - span=1,1,1,ccs,ami - span=2,0,1,ccs,ami - span=3,2,1,ccs,ami - span=4,0,1,ccs,ami - bchan=1-2,4-5,7-8,10-11 - dchan=3,6,9,12 - -Astribank 4 PRI E1 -^^^^^^^^^^^^^^^^^^ - # Assumed ports settings: - # Ports 1,3: TE (CPE) - # Ports 2,4: NT (Net) - span=1,1,1,ccs,hdb3,crc4 - span=2,0,1,ccs,hdb3,crc4 - span=3,2,1,ccs,hdb3,crc4 - span=4,0,1,ccs,hdb3,crc4 - bchan=1-15,17-30,31-45,47-60,61-75,77-90,91-105,107-120 - dchan=16,46,76,106 - -Astribank 4 PRI T1 -^^^^^^^^^^^^^^^^^^ - # Assumed ports settings: - # Ports 1,3: TE (CPE) - # Ports 2,4: NT (Net) - span=1,1,1,esf,b8zs - span=2,0,1,esf,b8zs - span=3,2,1,esf,b8zs - span=4,0,1,esf,b8zs - bchan=1-23,25-47,49-71,73-95 - dchan=24,48,72,96 - - -/etc/asterisk/zapata.conf -~~~~~~~~~~~~~~~~~~~~~~~~~ -Astribank 8 -^^^^^^^^^^^ - [channels] - signalling=fxo_ks - ; The real analog ports: - context=from-internal - echocancel=yes - ; echocancelwhenbriged=yes - ; echotraining=no - channel => 1-8 - - ; output ports: - context=astbank-output - channel => 9-10 - ; input ports: - immediate=yes - context=astbank-input - channel => 11-14 - immediate=no - -Astribank 6FXS/2FXO -^^^^^^^^^^^^^^^^^^^ - [channels] - signalling=fxo_ks - ; The real analog ports: - context=from-internal - echocancel=yes - ; echocancelwhenbriged=yes - ; echotraining=no - channel => 1-6 - - ; output ports: - context=astbank-output - channel => 7-8 - ; input ports: - immediate=yes - context=astbank-input - channel => 9-12 - immediate=no - - ; FXO ports - signalling=fxs_ks - context=from-pstn - callerid=asreceived - channel => 13-14 - -Astribank 16: 8FXS/8FXO -^^^^^^^^^^^^^^^^^^^^^^^ - [channels] - signalling=fxo_ks - ; The real analog ports: - context=from-internal - echocancel=yes - ; echocancelwhenbriged=yes - ; echotraining=no - channel => 1-8 - - ; output ports: - context=astbank-output - channel => 9-10 - ; input ports: - immediate=yes - context=astbank-input - channel => 11-14 - immediate=no - - ; FXO ports - signalling=fxs_ks - context=from-pstn - callerid=asreceived - channel => 15-22 - -Astribank 4 BRI -^^^^^^^^^^^^^^^ - ; Assumed ports settings: - ; Ports 1,3: TE - ; Ports 2,4: NT - [channels] - switchtype = euroisdn - callerid = asreceived - - ; TE ports: - signalling = bri_cpe_ptmp - ;signalling = bri_cpe - context = from-pstn - group = 1,11 - channel => 1,2 - - group = 1,13 - channel => 7,8 - - ; NT ports: - signalling = bri_net_ptmp - ;signalling = bri_net - context = from-internal - group = 2,12 - channel => 4,5 - - group = 2,14 - channel => 10,11 - -Astribank 4 PRI E1 -^^^^^^^^^^^^^^^^^^ - ; Assumed ports settings: - ; Ports 1,3: TE - ; Ports 2,4: NT - [channels] - switchtype = euroisdn - callerid = asreceived - - ; TE ports: - signalling = pri_cpe - context = from-pstn - group = 1,11 - channel => 1-15,17-30 - - group = 1,13 - channel => 61-75,77-90 - - ; NT ports: - signalling = bri_net_ptmp - ;signalling = bri_net - context = from-internal - group = 2,12 - channel => 31-45,47-60 - - group = 2,14 - channel => 91-105,107-120 - -Astribank 4 PRI T1 -^^^^^^^^^^^^^^^^^^ - ; Assumed ports settings: - ; Ports 1,3: TE - ; Ports 2,4: NT - [channels] - switchtype = national - callerid = asreceived - - ; TE ports: - signalling = pri_cpe - context = from-pstn - group = 1,11 - channel => 1-23 - - group = 1,13 - channel => 49-71 - - ; NT ports: - signalling = bri_net_ptmp - ;signalling = bri_net - context = from-internal - group = 2,12 - channel => 25-47 - - group = 2,14 - channel => 73-95 - - -Please check, that the mailbox and callerid parameters generated by -genzaptelconf are good for you and change them if necessary. - - -If you have Astribank device with 8 FXS and 8FXO ports connected and set -up, then the Zaptel channels will be allocated as the following: - - root@rapid:~# cat /proc/zaptel/* - Span 1: XBUS-00/XPD-00 "Xorcom XPD #00/00: FXS" - - 1 XPP_FXS/00/00/0 FXOLS (In use) - 2 XPP_FXS/00/00/1 FXOLS (In use) - 3 XPP_FXS/00/00/2 FXOLS (In use) - 4 XPP_FXS/00/00/3 FXOLS (In use) - 5 XPP_FXS/00/00/4 FXOLS (In use) - 6 XPP_FXS/00/00/5 FXOLS (In use) - 7 XPP_FXS/00/00/6 FXOLS (In use) - 8 XPP_FXS/00/00/7 FXOLS (In use) - 9 XPP_OUT/00/00/8 FXOLS (In use) (no pcm) - 10 XPP_OUT/00/00/9 FXOLS (In use) (no pcm) - 11 XPP_IN/00/00/10 FXOLS (In use) (no pcm) - 12 XPP_IN/00/00/11 FXOLS (In use) (no pcm) - 13 XPP_IN/00/00/12 FXOLS (In use) (no pcm) - 14 XPP_IN/00/00/13 FXOLS (In use) (no pcm) - Span 2: XBUS-00/XPD-01 "Xorcom XPD #00/01: FXO" (MASTER) - - 15 XPP_FXO/00/01/0 FXSKS (In use) - 16 XPP_FXO/00/01/1 FXSKS (In use) (no pcm) - 17 XPP_FXO/00/01/2 FXSKS (In use) (no pcm) - 18 XPP_FXO/00/01/3 FXSKS (In use) (no pcm) - 19 XPP_FXO/00/01/4 FXSKS (In use) (no pcm) - 20 XPP_FXO/00/01/5 FXSKS (In use) (no pcm) - 21 XPP_FXO/00/01/6 FXSKS (In use) (no pcm) - 22 XPP_FXO/00/01/7 FXSKS (In use) (no pcm) - - - -/etc/asterisk/extensions.conf -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Sample dialplan (extensions.conf) for all the above: - ------------------------------------------------------------ -[phones-zap] -; 6001 will dial to channel 1, 6020, to zaptel channel 20, etc. -exten => _6XXX,1,Dial(ZAP/${EXTEN:1}) -; Useful for debugging trunks. Will potentially allow users to -; bypass context limitations. -;exten => _6XXX.,1,Dial(ZAP/${EXTEN:1:3}/${EXTEN:4}) - -[trunk] -; A number that begins with 9: dial it through a trunk -; (we put FXO channels and TE channels in group 0). -; The leading 9 is stripped. -exten => _9.,1,Dial(Zap/g0/${EXTEN:1}) -; dialing a number that begins with 83 will dial it through -; span 3, and so forth. The two leading digits are stripped. -; (Each digital span is also added to group 10+span number). -exten => _8X.,1,Dial(Zap/g1${EXTEN:1:1}/${EXTEN:2}) - -[from-internal] -; The context of FXS ports: analog phones. -; They are allowed to dial to all other phones -include => phones-zap -; They are also allowed to call through the trunk: -include => trunk -; some simple tests: -include => astbank-test - -[from-pstn] -; Calls from the PSTN enter here. Redirect calls to an IVR -; or a default extension in the s context here. In this case we -; redirect calls to Zaptel channel 1: -exten => s,1,Dial(Zap/1) - -; Alternatively, the following will redirect you to the demo IVR -; from the sample extensions.conf of Asterisk: -include => demo - -; An extra context with some simple tests -[astbank-test] -; 200: echo test -exten => 200,1,Answer -exten => 200,n,Wait(1) -exten => 200,n,Echo() -exten => 200,n,Hangup - -; 203: say extension number. Will only work if caller ID -; is properly set in zapata.conf / zapata-channels.conf -exten => 203,1,Answer -exten => 203,n,Wait(1) -exten => 203,n,SayNumber(${CALLERID(num)}) -exten => 203,n,Hangup - -[astbank-input] -exten => s,1,Set(ZAP_CHAN=${CUT(CHANNEL,-,1)}) -exten => s,n,Set(ZAP_CHAN=${CUT(ZAP_CHAN,/,2)}) -; 11 is the number of the first input port. At least in the sample -; configuration below. -;exten => s,n,Set(INPUT_NUM=$[${ZAP_CHAN}-11)]) -; The sample below just logs the signal. -exten => s,n,NoOp(Got signal from Zaptel Channel ${ZAP_CHAN}) -; Alternatively: -;exten => s,n,System(run something) - -; No. We did not forget the context astbank-outputs. Output -; ports only get calls from the PBX. Thus they don't need a context -; of their own. Sending them to a context of their on makes -; 'zap show channels' in the CLI provide useful display, though. ------------------------------------------------------------ - - - - -Troubleshhoting ---------------- -The following commands provide useful information for debugging: - -* Check USB level status. You can use one of the following utilities for it: - - zaptel_hardware -v - or - lsusb | grep e4e4 - - - Look for the USB Product ID (the second number after e4e4). - - If you see *11x2* (e.g: 1152)- the FPGA firmware has been loaded. - Move on. - zaptel_hardware will also show you some more details if the driver - is loaded while the lsusb will just list the device. - - If it shows something as product ID *11x0* - the USB firmware is not - loaded. Maybe you need to run fxload. Or maybe just unplug and plug again - the device. Also make sure that you have fxload installed. - - If lsusb shows the Product ID as *11x1* - only the USB firmware is loaded - and not the FPGA firmware is loaded. If this is still the case after - a while - either the firmware loading has failed or you don't have - fpga_load. Make sure you have libusb-dev(el) installed when - building Zaptel. - - It should list all of your Astribank devices. If it doesn't (for - more than period of time needed for the initial firmware - loading) - Check that the Astribank is connected indeed. - -* Check if the Astribank spans are registered in Zaptel - - zt_registration - - - This should give useful results after the drivers have identified - and your devices are initialized. - - It should list all Astribank XPDs. For each of them it should write - "on" or "off". If the registration status is "off", then it means that - the span has not been registered in Zaptel and therefore can not be used - yet. - - Registration is normally done as part of `/etc/init.d/zaptel start`. - If you want to register the spans manually, then run command: - `zt_registration on` . - - Disabling of the automatic Astribank spans registration give you full - control on the order of Zaptel spans. See the module parameter - **zap_autoreg** for the further details. - -* Check the Zaptel information: - You can get some information regarding Zaptel channels by running one of the - following commands: - - lszaptel - or - cat /proc/zaptel/* - - - Those two are almost the same. The lszaptel produced more correctly sorted - output if you have more than 10 spans, and also make the output listing - looks a little bit nicer. - - You can see if your Zaptel spans and channels were loaded, if - they were configured by ztcfg and if they are in use (typically by - Asterisk). - For example: - Not configured Astribank FXS channel will be displayed as: - - 42 FXS - - When a channel has been configured with *ztcfg* (that applies - /etc/zaptel.conf), you will see an extra column for the signalling - type of the channel. The same channel after it has been configured: - - 42 FXS FXOKS - - If a program (which is typically Asterisk) uses it, you'll see: - - 42 FXS FXOKS (In use) - -* Check the Asterisk information: - - asterisk -rx 'zap show channels' - - - If you get error "Unable to connect to remote asterisk" then it - means that the Asterisk is not running. It is possible that Asterisk - has failed to start due to misconfigured zapata.conf or whatever reason. - Check /var/log/asterisk/messages or /var/log/asterisk/full . - - If you get the error that "there is no such command" then it means that - chan_zap.so is not loaded. There are two reasons for such problem: - (a) chan_zap.so is not even built. Check if the file exists: - - ls -l /usr/lib/asterisk/modules/chan_zap.so - - (b) the chan_zap.so file exists but it is not loaded. Try to load it manually: - - asterisk -rx 'load module chan_zap.so' - - - You see "pseudo" channel only. It means that you have not configured any - channels. If you have configured channels in zapata.conf, you may - need either to restart the Asterisk or unload/load chan_zap.so manually. - You can use the following Asterisk CLI commands for it: `unload chan_zap.so` and - `load chan_zap.so` - - -Reference ---------- -LEDs Indication -~~~~~~~~~~~~~~~ -The Astribank has 4 global indication leds and one or two per-port leds. -On some of the models the LEDs are located on the left side on the front -panel. If there are no separate LEDs there, then the red LEDs of the -upper left-most ports of the device are used as the indication leds. Don't -confuse them with green port status leds. - -The first led is the "Power" led. It is on if the unit gets power. -The second led is the "Active" led, which is on when there is at -least one "active" port (in a call / off-hook, though the meaning of this is -different in BRI). -The last led is called "Hardware OK", but is actually only is on in case of -the hardware failure. - -The third led is the "Sync" led. If it blinks, the device is synchronized -with the driver on the computer. If the device is selected to be the -synchronization source for all of the Astribank devices then it will blink -a quick single blink. -If the device gets synchronization from the driver, it will blink in a -more steady frequency. - -"Double blink" indicates that the unit has an FXO module, and still is -getting synchronization from the computer, and is not the synchronization -source. - -The per-port green led on analog (both FXS and FXO) indicates that the -port is off-hook. - -On the BRI, the green led indicates a TE port whereas an orange led -indicates an NT port. If the led is solid, the port is down (not even -layer-1 connection is up). If it is blinking a double blink, layer 1 -is up. A slower single blinking indicates that layer 2 is up as well -(which means that Asterisk is driving the port). - - -Device Startup -~~~~~~~~~~~~~~ -This section describes in great depth the initialization of the Xorcom -Astribank. Normally it would not be really needed, as the standard -installation of Zaptel should put everything in place. - -Terminology -^^^^^^^^^^^ -There are some technical terms that are used in this document and in the -driver / zaptel. - -span: -Zaptel breaks the channels it knows about to logical units called -"spans". A port in a E1/T1/ISDN card is usually a span. An whole -analog card is also a "span". You can see the list of spans as the list -of files under /proc/zaptel directory or in output of the zttool -utility. - -XBUS: -A funny way to call an Astribank device. - -XPD: -Basically this is a logical unit of the Astribank. It will be registered in -Zaptel as a single span. This can be either an analog (FXS or FXO) -module or a single port in case of a BRI module. - - -Loading Firmware -^^^^^^^^^^^^^^^^ -Normally this is done using the script /usr/share/zaptel/xpp_fxloader. -If it works fine, you don't need to bother reading this section. -Once the firmware is loaded the USB Vendor ID and Product ID of the Astribank -became to be e4e4 11x2, and now the driver can pick it up. - -First and foremost: the simplest and most useful tool to debug problems -is lsusb. The output of lsusb should show you if the device is connected -if its firmware is loaded. - -The firmware files are named *.hex. They are presented in the text -hexadecimal format The files are copied from xpp/utils to /usr/share/zaptel -folder during the Zaptel installation. - -The Astribank needs a firmware loaded into it. Without the firmware, -the device will appear in lsusb with Vendor ID e4e4 and Product ID 1130. -The firmware loading process consists of two stages. In the first stage the -"USB" firmware is loaded by using program fxload. When the first stage is -completed the Vendor ID is e4e4 and the Product ID is 1131. - -You can use the following command in order to load the "USB" firmware -manually: - - fxload -t fx2 -D /proc/bus/usb/MMM/NNN -I /usr/share/zaptel/USB_FW.hex - -where, - -fxload:: - A standard program that is typically part either of package 'fxload' - or 'hotplug-utils' . -/proc/bus/usb:: - The mount point of the USB file-system (usbfs). -MMM:: - the first number (bus number) -NNN:: - the second number (device number) you see for the device in lsusb - -If the loading process has been completed successfully, the device -disconnects and then connects again itself with USB Product ID 1131 -(and a new device number). - -In the second stage, the "FPGA" firmware is loaded. -The second-stage firmware loading is performed by using program fpga_load, -which is built in the directory xpp/utils and then copied to folder -/usr/sbin during Zaptel installation. - -The command syntax is similar to the syntax of fxload. You can use the -following command in order to load the FPGA firmware manually: - - fpga_load -D /proc/bus/usb/MMM/NNN -I /usr/share/zaptel/FPGA_1151.hex - -Please note, that NNN value differs from that that was used for the -fxload command due to the fact that device has "reconnected" itself -with another Product ID number. So you need to run lsusb again and get -the new NNN value. Usually, the new value is equal to the old value -incremented by 1. - - -Firmware Loading with Hotplug -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The Hotplug framework was popular for hotplugging different devices and -usually also for automatic device drivers loading. If Hotplug is used in -your system, you'll see many files in folder /etc/hotplug. Hotplug will -automatically load the most relevant USB and PCI kernel modules according -to the USB and PCI IDs provided by devices. Please note, that if the -Hotplug framework is in place and the correct configuration files are -located in the right place, then the firmware should be loaded automatically. - -In order to get the Hotplug framework to load the firmware into the -Astribank automatically, the configuration file xpp_fxloader.usermap and -the script xpp_fxloader should be copied into /etc/hotplug/usb/ . This is -done by 'make -C xpp/utils install'. - -File xpp_fxloader.usermap includes a map of USB IDs and the command to run -when such devices are encountered. It instructs the Hotplug to run the script -xpp_fxloader from that directory. This is also done by 'make -C -xpp/utils install' . - -When xpp_fxloader is run without any parameters it assumes that it was -run by the hotplug scripts. Then it will check if the "add" event was -accepted and if so, xpp_fxloader will install the required firmware file. -The xpp_fxloader will be called twice, as after the load of the USB -firmware the device will re-enumerate itself and thus "unplug" and -"replug" in order to load the FPGA firmware. - - -Firmware Loading with UDEV -^^^^^^^^^^^^^^^^^^^^^^^^^^ -The UDEV framework has replaced Hotplug in most recent systems. If you -have a recent 2.6 system without Hotplug and with many files in folder -/etc/udev, then there are good chances that are you using udev. -As in case of Hotplug, if your udev framework is configured properly -then the firmware should be loaded automatically. - -In order to get udev to automatically load the firmware into the Astribank, -the configuration file xpp.rules should be copied into folder /etc/udev/rules.d -and the script xpp_fxloader should be copied into folder /etc/hotplug/usb/ . -This is done by 'make -C xpp/utils install' during Zaptel installation. - -File xpp.rules instructs the udevd daemon to run xpp_fxloader script with -the option "udev" and with the Astribank USB ID obtained from the -device when it is plugged in. -Please note, that exactly like in case of Hotplug, the xpp_fxloader will be -called twice by the udevd. First time for the USB firmware loading and the -second time for FPGA firmware loading. - - -Firmware Resetting -^^^^^^^^^^^^^^^^^^ -Newer versions of the USB firmware can now be reset using 'fpga_load -r'. - -Also you can try the following: - - /usr/share/zaptel/xpp_fxloader reset - # if asterisk was running: you may need to stop/restart it now. - # if there are some "disconnected" spans in /proc/xpp/xbuses - # wait a while, until you see the 1152 IDs again, and then: - /etc/init.d/zaptel start - # and start/restart asterisk. - - -Loading The Modules -^^^^^^^^^^^^^^^^^^^ -Here is what should happen: -In short: you should plug the Astribank device(s) or have them plugged in at -the boot time. Then all the modules should be loaded automatically. -You will see xpp_usb , xpd_fxs and, possibly, xpd_fxo in the modules list -(the output of lsmod). - -After the module xpp is loaded, you'll also be able to see the directory -/proc/xpp. For any Astribank device discovered, you will see there a -directory /proc/xpp/XBUS-n (where n is a number: typically 0). Once a unit have -been discovered you'll see subdirectories: /proc/xpp/XBUS-n/XPD-m (where -m may be another number: 0, 1 ,etc). - -Now to the ugly details: - -The driver of the Astribank is composed of several modules: -* xpp - the basic module, that communicates with Zaptel and provides - some common services to other modules. -* xpd_fxs - the module for controlling FXS modules. -* xpd_fxo - the module for controlling FXO modules. -* xpd_bri - the module for controlling BRI modules. -* xpd_pri - the module for controlling E1/T1 modules. -* xpd_usb - the module that holds the functionality needed to connect to the - USB bus. - -All modules depend on xpp, and modprobing them will install xpp as well. -However the xpd_* modules are installed on-demand: no need to install -the xpd_fxo if you have only Astribank FXS. - -Once an Astribank device connected and the firmware is loaded, the -Vendor-ID/Product-ID of the device will be e4e4/1132 . The handler for that -combination is listed as the kernel module xpp_usb. Therefore, the system -runs 'modprobe xpp_usb' if that module is not already loaded. - -The module xpp_usb depends on the zaptel and xpp modules. Both of them -are loaded before xpp_usb. As usual, parameters and rules form -/etc/modprobe.conf and/or from /etc/modprobe.d/* will be applied to -the module. - -When command 'modprobe xpp_usb' returns, the span type specific modules -(e.g., xpd_fxs, xpd_fxo) may or may not have been loaded yet. - -At this point the xpp driver "asks" the box about type of telephony modules -it has. According to the answers it receives, the xpp driver will "modprobe" -the required xpd_* modules. - - -Device Initializations Scripts -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The chips in the device need to be initialized. This requires sending a -bunch of values to certain registers in those chips. We decided that -hardwriting those values in the driver code is not a good idea. -Before registering a XPD as a span in Zaptel, we run an initialization -script: /usr/share/zaptel/init_card_N_MM ( -where, - -* N - is 3 for an FXS span and 4 for an FXO span, and 6 or 7 for BRI. -* MM - is a version number. Currently it equals 26 - -If because of some reasons this fails (the script is not in the place, or the -file doesn't have the executable permissions), then you will get an error -message in the logs and the XPD will then be removed (you won't see directory -for that XPD under the corresponding /proc/xpp/XBUS-* directory) and will not -be registered in Zaptel. - -As the XPD is initialized, you'll see the green LEDs of the ports steadily -turn on and later off ("a train of lights"). This is a bit slower than the -faster "blinking" when the XPDs register as Zaptel spans. The initializaton -of an FXS XPD may take a few seconds. - - -Astribank in Sysfs -^^^^^^^^^^^^^^^^^^ -When an Astribank device loads it generates a device node in the bus -'astribanks' in sysfs. You can see a directory for each device under -/sys/bus/astribanks/devices/ and under it there are several attributes -for each Astribank (such as its connector string). - -On each time an Astribank is initialized or destroyed a udev event is -generated. The rules from our sample udev rules file (xpp/utils/xpp.rules) -make that event run the script /usr/share/zaptel/astribank_hook with the -parameter 'add' or 'remove', if such script exists. An example script -that just adjusts the Astribank sync settings is included in xpp/utils. - - -Registering in Zaptel -^^^^^^^^^^^^^^^^^^^^^ -The XPDs will not automatically register as zaptel spans. This is -intended to allow you to set the registration order (and hence the order -of Zaptel spans and channels) among multiple Astribank devices, -or between an Astribank and a different Zaptel device. - -When the XPD registers to Zaptel, all the green LEDs will be lit for a -short while. - -Spans are normally registered with the utility zt_registration. Simply -running 'zt_registration' shows the available XPDs and whether or not -they are registered. To register: - - zt_registration on - -For a system with several spans you'll see a "fast train of lights". - -If you have multiple Astribank devices, zt_registration will register -them by the order of the "connector" field. This means that as long as -the same Astribank is connected to the same port, the order of plugging -is not important.. - -zt_registration checks if a span is registered or tries to register a -span using the file /proc/xpp/XBUS-nn/XPD-mm/zt_registration . Reading -from that file returns 0 if the span is unregisteres or 1 if it is -registered. You can register a span or ask to unregister it by writing 1 -(register) or 0 (unregister) to that file. Registeration should -generally always succeed. Unregistration may fail if a span is in use. - -You may choose to register the XPDs in Zaptel automatically, in order to -allow finer control of the process. This behavior may be defined by setting -parameter zap_autoreg in the modprobe configuration file (A file under -/etc/modprobe.d or /etc/modprobe.conf): - - options xpp zap_autoreg=1 - - -Zaptel And Above -^^^^^^^^^^^^^^^^ -From here you get a standard Zaptel span. It still needs to be -configured by ztcfg and used by a program such as Asterisk like any -other Zaptel device. In order for you to get a dialtone in a phone -connected to the FXS port or a fully synchronized BRI port (layer 2 -activated, as signalled by a more steady blink) you will actually need -both the span configured by Zaptel and the channels configured in -Asterisk. - -You should generally refer to the general Zaptel documentation on how to -configure those levels. e.g, the README file in the toplevel directory, -and - - http://voip-info.org/wiki/view/Asterisk+config+zapata.conf[] - - -Zaptel now includes a utility called genzaptelconf (written as a big -ugly shell script) to configure Zaptel automatically as good as -possible. For analog channels it works quite well (because, IMHO, the -"configuration" level on Zaptel should be optional there - there are -already sane defaults). For digital spans - BRI and PRI , it may take -some tuning. - -Alternatively, write you own configuration, based on the sample from the -"Sample Configurations" section. - - -/proc Interface -~~~~~~~~~~~~~~~ -The Astribank drivers provide their own /proc interface under /proc/xpp. -(Note that the details of this interface are still potentially subject to -changes) - - -/proc/xpp/xbuses -^^^^^^^^^^^^^^^^ -File /proc/xpp/xbuses lists the connected Astribank devices (one line -per device). - -A device is normally has status "connected". The status "missing" means that -the device has been disconnected, but Asterisk still holds channels from it -open. - - -/proc/xpp/sync -^^^^^^^^^^^^^^ -A read/write file. It contains information about current synchronization -source. You can change the synchronization source by writing special -command to the file. For example, command - echo SYNC=01 > /proc/xpp/sync - -Possible values are: - -:: - Make the Astribank XBUS- the sync source for other Astribanks. - -ZAPTEL:: - Make the astribanks synchronize with the Zaptel timing master span. - You probably ned this to get faxes from a non-Astribank adapter to an - Astribank. - -Though you'll normally use xpp_sync(8) for that. - -For each Astribank device there is folder /proc/xpp/XBUS-nn and for each device -module (span in the therms of Zaptel) there is folder /proc/XBUS-nn/XPD-mm. - - -/proc/xpp/XBUS-nn/XPD-mm/zt_registration -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -is a read/write file. Reading from it gives 0 if the span is -unregistered, or the span number if it is registered. - -Writing to it allows manual registration / unregistration from Zaptel: -writing 1 registers a span (if it wasn't already registered) and writing -0 attempts to unregister it (if it is registered. Span unregistration -will fail if some channels from the span are used (e.g: by Asterisk). - -A more convient interface to this is the command zt_registration that -registers or unregisters all the spans at once with a predefined order, -and this is what you should normally use. - -Alternatively you can use the parameter zap_autoreg to register spans -automatically. But this is only recommended on a system with a single -Astribank and no other Zaptel device. - - -/proc/xpp/XBUS-nn/XPD-mm/summary -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Contains detailed information about port statuses of the device module -(off-hook, on-hook etc.) For example, you can run the following command -in order to monitor the port statuses in the real time: - - watch -n1 cat /proc/xpp/XBUS-00/XPD-00/summary - - -/proc/xpp/XBUS-nn/XPD-mm/slics -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Provides direct read/write interface to the registers of each chip. -Reading from the file shows the result of the last read request. To make -either a read request or a write request you need to write to that file. - -It is mainly used by the initialization scripts (card_init_*). - - -/proc/xpp/XBUS-nn/XPD-mm/fxo_info -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Only for FXO modules. Apart from showing the status of the LEDs, it also -shows for each FXO port if it is connected to a provider: look for the -value of "battery" for that specific port. - - -/proc/xpp/XBUS-nn/XPD-mm/bri_info -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -In addition to the usual information about the LEDs, this file also -provides useful information regarding ISDN Layer 1 and Layer 2 status. -For example, you can run the following command in order to monitor -the Layer 1 port statuses for all BRI devices in the real time: - - watch -n1 -d 'grep "Layer 1:" /proc/xpp/XBUS-*/XPD-*/bri_info' - -For the status of the D channel of the ports on all BRI spans, run: - - watch -n1 -d 'grep D-Channel: /proc/xpp/XBUS-*/XPD-*/bri_info' - - -/proc/xpp/XBUS-nn/XPD-mm/pri_info -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -In addition to the usual information about the LEDs, this file also -provides useful information regarding ISDN Layer 1 and Layer 2 status. -For example, you can run the following command in order to monitor -the Layer 1 port statuses for all E1/T1 devices in the real time: - - watch -n1 -d 'grep "Layer 1:" /proc/xpp/XBUS-*/XPD-*/pri_info' - -For the status of the D channel of the ports on all PRI spans, run: - - watch -n1 -d 'grep D-Channel: /proc/xpp/XBUS-*/XPD-*/pri_info' - -Note: the layer 2 status is much more of a guesswork based on changes in -the contents of the channel that is supposed to be the D channel. - -Writing to this file can be used to change the type of the device. The -device type can only be changed when the XPD is not registered as a -Zaptel span. The value is a whitespace-separated list of values that can -be of: - -E1:: - Provides 31 channels, of which channel 16 is normally the D-channel. - Common in places outside of North America and Japan. This is the - default setup. - -T1:: - T1 provides 24 channels. The last one is normally the D-Channel. - Common in North America. - -TE:: - Use the bottom port (green LED) and don't invert any wiring. Hint to - higher layers that this will be the TE side of the connection. This is - the default setup. - -NT:: - Use the top port (orange LED) and invert wiring (this is done to allow - connecting an NT port and a TE port using a standard straight 8 wires - "ethernet" cable). Hint to higher layers that this will be the NT side - of the connection. - -LOCALOOP:: - Set the device into local loop mode: loops the transmitted channels - directly into the recieved channels. - -NOLOCALLOOP:: - Ends local loop mode. - -Normally those are set by the PRI initialization script . See the -definition of XPP_PRI_SETUP in xref:sect-default[the sample Zaptel init -configuration file] . - -There are a bunch of other status files under /proc/xpp/. - - -Useful Module Parameters -~~~~~~~~~~~~~~~~~~~~~~~~ -Compilation-time defaults for the all modules can be shown as part of the -description line for the parameter in the "modinfo" command output. - -zap_autoreg (xpp):: - Register spans automatically (1) or not (0). Default: 0. - Setting it simplifies operations with a single Astribank and no other - zaptel hardware. However if you have such systems, automatic - registration can cause the order of spans to be unpredictable. - The standard startup scripts use 'zt_registration on' instead of this. - -initdir (xpp):: - This is the directory containing the initialization scripts. - The default is /usr/share/zaptel . - Setting this value could be useful if that location is inconvenient for you. - -rx_tasklet (xpp):: - Enable (1) or disable (0) doing most of the packets processing in - separate tasklets. This should probably help on higher-end systes with - multiple Astribanks. - -print_dbg (all modules):: - It will make the driver to print tons of debugging messages. You can - set/unset the parameter at run-time. - - The parameter value is a bitmask of several values. The different bits - meaning as it defined in xpp/zap_debug.h: - - * 0 - Disable debug messages - * 1 - GENERAL - General debug comments. - * 2 - PCM - PCM-related messages. Tend to flood logs. - * 4 - LEDS - Anything related to the leds status control. The driver - produces a lot of messages when the option is enabled. - * 8 - SYNC - Synchronization related messages. - * 16 - SIGNAL - Zaptel signalling related messages. - * 32 - PROC - procfs interface related messages. - * 64 - REGS - Reading and writing to chip registers. The driver produces - a lot of messages when the option is enabled. - - For example, - - echo 33 >/sys/modules/xpp/parameters/print_dbg - - forces module xpp to print general debugging messages (1) and procfs - debugging messages (32). - -vmwineon (xpd_fxs):: - Enable (1) or disable (0) sending the voicemail message waiting indication - signal to phones equipped with the Message Wainting neon lamp. It is - disabled by default because the feature requires extra work of the driver - even when such a phone is not used and also may cause some unusual - side effects with some phone models. - -usb1 (xpp_usb):: - Enable (1) or disable (0) support of USB1 devices. Disabled by default. - + - + - USB1 devices are not well-tested. It seems that they don't work at all - for Astribank BRI. Generally they should work with the current code, but - we expect the voice quality issues. Hence we would like to make it very clear that - you if you have a USB1 port (rather than a USB2 one, as recommended) you - will have to take an action to enable the device. - -poll intervals (various):: - There are various values which the driver occasionally polls the device - for. For instance, the parameter poll_battery_interval for xpd_fxo - to poll the battery (in order to know if the telco line is actually - connected.) - + - + - The value of those parameters is typically a number in milliseconds or 0 - to disable. Under normal operation there should be no reason to play - with those parameters. - -dtmf_detection (xpd_fxs):: - Enable (1) or disable (0) support of hardware DTMF detection by the - Astribank. - - -NOTE: XPP here does not stand for X Printing Panel, XML Pull Parser, -X-Windows Phase Plane or XML Professional Publisher. It is simply the -Xorcom Peripheral Protocol, which connects a computer to a XPD (Xorcom -Peripheral Device). An XBUS (originally XPP Bus) is actually a single -Astribank device and the XPDs have become the single modules in it. diff --git a/xpp/calibrate_slics b/xpp/calibrate_slics deleted file mode 100755 index c1e6064..0000000 --- a/xpp/calibrate_slics +++ /dev/null @@ -1,308 +0,0 @@ -#!/usr/bin/perl -w - -# -# $Id$ -# - -use strict; - -my $SlicsFile = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/$ENV{XPD_NAME}/slics"; - -my @SlicNums = (0 .. 7); - -if ( ! -f $SlicsFile ) { - exit 1 -} - -my $debug = 0; -# set DEBUG_CALIBRATION in /etc/default/zaptel or similar -if (exists $ENV{DEBUG_CALIBRATION}) { - $debug = 1; -} - -sub mysleep($) { - my $timeout = shift; - select(undef,undef,undef,$timeout); -} - -sub logger($) { - print STDERR "LOG: @_\n"; - system("logger @_"); -} - -sub debug($) { - logger(@_) if ($debug); -} - -sub write_to_slic_file($) { - my $write_str = shift; - - open(SLICS,">$SlicsFile") or - die("Failed writing to slics file $SlicsFile"); - print SLICS $write_str; - close(SLICS); - mysleep(0.001); - -} - -sub read_reg($$$) { - my $read_slic = shift; - my $read_reg = shift; - my $direct = shift; - - write_to_slic_file( - sprintf("%d R%s %02X", $read_slic, $direct, $read_reg)); - mysleep(0.001); - open(SLICS,$SlicsFile) or - die("Failed reading from slics file $SlicsFile"); - #awk '/^SLIC_REPLY:/{print $5}' $SLICS | cut -dx -f2 - my @reply = (); - while(){ - #if (/^ /) { - # debug "answer line: $_"; - #} - if (/^ \d*\s+[RW][DIS]\s+[[:xdigit:]]+\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)/){ - @reply = (hex($1), hex($2)); - #debug "got [$reply]\n"; - last; - } - } - close(SLICS); - if ($direct eq 'I') { - return @reply; - } else { - return $reply[0]; - } -} - -# TODO: rearange arguments -sub write_reg{#($$$$$) { - my $read_slic = shift; - my $read_reg = shift; - my $direct = shift; - my $reg_val_low = shift; - my $reg_val_hi = shift; - - my $str = sprintf "%d W%s %02X %02X", - $read_slic, $direct, $read_reg, $reg_val_low; - if ($direct eq 'I') { - $str .= sprintf " %02X", $reg_val_hi; - } - write_to_slic_file($str); -} - -sub log_calib_params() { - for my $i (100 .. 107) { - my $line="Calib Reg $i: "; - for my $slic (@SlicNums) { - $line .= " ".read_reg($slic, $i, 'D'); - } - debug($line); - } -} - -sub init_indirect_registers() { - return write_to_slic_file("# -31 WI 00 C2 55 -31 WI 01 E6 51 -31 WI 02 85 4B -31 WI 03 37 49 - -31 WI 04 33 33 -31 WI 05 02 02 -31 WI 06 02 02 -31 WI 07 98 01 - -31 WI 08 98 01 -31 WI 09 11 06 -31 WI 0A 02 02 -31 WI 0B E5 00 - -31 WI 0C 1C 0A -31 WI 0D 30 7B -31 WI 0E 63 00 -31 WI 0F 00 00 - -31 WI 10 70 78 -31 WI 11 7D 00 -31 WI 12 00 00 -31 WI 13 00 00 - -31 WI 14 F0 7E -31 WI 15 60 01 -31 WI 16 00 00 -31 WI 17 00 20 - -31 WI 18 00 20 -31 WI 19 00 00 -31 WI 1A 00 20 -31 WI 1B 00 40 - -31 WI 1C 00 10 -31 WI 1D 00 36 -31 WI 1E 00 10 -31 WI 1F 00 02 - -31 WI 20 C0 07 -31 WI 21 00 26 -31 WI 22 F4 0F -31 WI 23 00 80 - -#31 WI 24 20 03 -#31 WI 25 8C 08 -#31 WI 26 00 01 -#31 WI 27 10 00 - -31 WI 24 00 08 -31 WI 25 00 08 -31 WI 26 00 08 -31 WI 27 00 08 - -31 WI 28 00 0C -31 WI 29 00 0C -31 WI 2B 00 01 - -31 WI 63 DA 00 -31 WI 64 60 6B -31 WI 65 74 00 -31 WI 66 C0 79 - -31 WI 67 20 11 -31 WI 68 E0 3B -#"); -} - -sub init_early_direct_regs() { - return write_to_slic_file("# -31 WD 08 00 -31 WD 4A 34 -31 WD 4B 10 -31 WD 40 00 -#") -} - -my @FilterParams = (); - -sub save_indirect_filter_params() { - for my $slic (@SlicNums) { - for my $reg (35 .. 39) { - $FilterParams[$slic][$reg] = - [read_reg($slic, $reg, 'I')]; - write_reg($slic, $reg, 'I', 0, 0x80); - } - } - -} - -sub restore_indirect_filter_params() { - for my $slic (@SlicNums) { - for my $reg (35 .. 39) { - write_reg($slic, $reg, 'I', - @{$FilterParams[$slic][$reg]}); - } - } -} - -my $ManualCalibrationSleepTime = 0.04; # 40ms - -sub manual_calibrate_loop($$) { - my $write_reg = shift; - my $read_reg = shift; - - # counters to count down to (at most) 0 - my @slic_counters = (); - for my $i (0 .. $#SlicNums) { - $slic_counters[$i] = 0x1F; - } - - # start calibration: - my $calibration_in_progress = 1; - write_reg(31, $write_reg, 'D', 0x1F); - mysleep $ManualCalibrationSleepTime; - - # wait until all slics have finished calibration, or for timeout - while ($calibration_in_progress) { - $calibration_in_progress = 0; # until proven otherwise - my $debug_calib_str = "ManualCalib:: "; - for my $slic(@SlicNums) { - my $value = read_reg($slic, $read_reg, 'D'); - $debug_calib_str .= " [$slic_counters[$slic]:$value]"; - if ($value != 0 && $slic_counters[$slic] >= 0) { - $calibration_in_progress = 1; - $slic_counters[$slic]--; - write_reg($slic,$write_reg,'D',$slic_counters[$slic]); - } - } - debug($debug_calib_str); - # TODO: unnecessary sleep in the last round: - mysleep $ManualCalibrationSleepTime; - } -} - -sub manual_calibrate() { - manual_calibrate_loop(98, 88); - manual_calibrate_loop(99, 89); -} - -sub auto_calibrate($$) { - my $calib_96 = shift; - my $calib_97 = shift; - - #log_calib_params(); - # start calibration: - write_to_slic_file( - sprintf - "31 WD 61 %02X\n". - "31 WD 60 %02X\n". - "", $calib_96, $calib_97 - - ); - # wait until all slics have finished calibration, or for timeout - my $sleep_cnt = 0; - # time periods in seconds: - my $sleep_time = 0.1; - my $timeout_time = 2; - CALIB_LOOP: for my $slic (@SlicNums) { - debug("checking slic $slic"); - while(1) { - if ((read_reg($slic, 60, 'D')) == 0) { - # move to next register - debug("slic $slic calibrated"); - last; - } - if ( $sleep_cnt > $timeout_time/$sleep_time) { - debug("Auto Calibration: Exiting on timeout: $timeout_time."); - last CALIB_LOOP; - } - debug("auto_calibrate not done yet: slic #$slic\n"); - mysleep(0.1); - $sleep_cnt++; - } - } - #log_calib_params(); -} - -########################################################### -# -# main -# - -# TODO: for all slics check the following reads to check communication -#read_reg($slic, 0x08, 'D'): 0x02 -#read_reg($slic, 0x0B, 'D'): 0x33 -#read_reg($slic, 0x40, 'D'): 0x00 (?) - -debug "starting\n"; - -init_indirect_registers(); -debug "after init_indirect_registers\n"; -init_early_direct_regs(); -debug "after init_early_direct_regs\n"; -auto_calibrate(0x47, 0x1E); -debug "after auto_calibrate\n"; -manual_calibrate(); -debug "after manul_calibrate\n"; -auto_calibrate(0x40, 0x01); -debug "after auto_calibrate 2\n"; - - diff --git a/xpp/card_bri.c b/xpp/card_bri.c deleted file mode 100644 index 998d22a..0000000 --- a/xpp/card_bri.c +++ /dev/null @@ -1,1731 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * Parts derived from Cologne demo driver for the chip. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include "xpd.h" -#include "xproto.h" -#include "xpp_zap.h" -#include "card_bri.h" -#include "zap_debug.h" -#include "xpd.h" -#include "xbus-core.h" - -static const char rcsid[] = "$Id$"; - -#ifndef CONFIG_ZAPATA_BRI_DCHANS -#error CONFIG_ZAPATA_BRI_DCHANS is not defined -#endif - -DEF_PARM(int, print_dbg, 0, 0644, "Print DBG statements"); /* must be before zap_debug.h */ -DEF_PARM(uint, poll_interval, 500, 0644, "Poll channel state interval in milliseconds (0 - disable)"); -DEF_PARM_BOOL(nt_keepalive, 1, 0644, "Force BRI_NT to keep trying connection"); -#ifdef DEBUG_PCMTX -DEF_PARM(int, pcmtx, -1, 0644, "Forced PCM value to transmit (negative to disable)"); -DEF_PARM(int, pcmtx_chan, 0, 0644, "channel to force PCM value"); -#endif - -enum xhfc_states { - ST_RESET = 0, /* G/F0 */ - /* TE */ - ST_TE_SENSING = 2, /* F2 */ - ST_TE_DEACTIVATED = 3, /* F3 */ - ST_TE_SIGWAIT = 4, /* F4 */ - ST_TE_IDENT = 5, /* F5 */ - ST_TE_SYNCED = 6, /* F6 */ - ST_TE_ACTIVATED = 7, /* F7 */ - ST_TE_LOST_FRAMING = 8, /* F8 */ - /* NT */ - ST_NT_DEACTIVATED = 1, /* G1 */ - ST_NT_ACTIVATING = 2, /* G2 */ - ST_NT_ACTIVATED = 3, /* G3 */ - ST_NT_DEACTIVTING = 4, /* G4 */ -}; - -static const char *xhfc_state_name(xpd_type_t xpd_type, enum xhfc_states state) -{ - const char *p; - -#define _E(x) [ST_ ## x] = #x - static const char *te_names[] = { - _E(RESET), - _E(TE_SENSING), - _E(TE_DEACTIVATED), - _E(TE_SIGWAIT), - _E(TE_IDENT), - _E(TE_SYNCED), - _E(TE_ACTIVATED), - _E(TE_LOST_FRAMING), - }; - static const char *nt_names[] = { - _E(RESET), - _E(NT_DEACTIVATED), - _E(NT_ACTIVATING), - _E(NT_ACTIVATED), - _E(NT_DEACTIVTING), - }; -#undef _E - if(xpd_type == XPD_TYPE_BRI_TE) { - if ((state < ST_RESET) || (state > ST_TE_LOST_FRAMING)) - p = "TE ???"; - else - p = te_names[state]; - } else { - if ((state < ST_RESET) || (state > ST_NT_DEACTIVTING)) - p = "NT ???"; - else - p = nt_names[state]; - } - return p; -} - -/* xhfc Layer1 physical commands */ -#define HFC_L1_ACTIVATE_TE 0x01 -#define HFC_L1_FORCE_DEACTIVATE_TE 0x02 -#define HFC_L1_ACTIVATE_NT 0x03 -#define HFC_L1_DEACTIVATE_NT 0x04 - -#define HFC_L1_ACTIVATING 1 -#define HFC_L1_ACTIVATED 2 -#define TIMER_T1_MAX 2500 -#define HFC_TIMER_T3 8000 /* 8s activation timer T3 */ -#define HFC_TIMER_T4 500 /* 500ms deactivation timer T4 */ -#define HFC_TIMER_OFF -1 /* timer disabled */ - -#define A_SU_WR_STA 0x30 /* ST/Up state machine register */ -#define V_SU_LD_STA 0x10 -#define V_SU_ACT 0x60 /* start activation/deactivation */ -#define STA_DEACTIVATE 0x40 /* start deactivation in A_SU_WR_STA */ -#define STA_ACTIVATE 0x60 /* start activation in A_SU_WR_STA */ -#define V_SU_SET_G2_G3 0x80 - -#define A_SU_RD_STA 0x30 -typedef union { - struct { - byte v_su_sta:4; - byte v_su_fr_sync:1; - byte v_su_t2_exp:1; - byte v_su_info0:1; - byte v_g2_g3:1; - } bits; - byte reg; -} su_rd_sta_t; - -#define REG30_LOST 3 /* in polls */ -#define DCHAN_LOST 15000 /* in ticks */ - -#define BRI_DCHAN_SIGCAP ( \ - ZT_SIG_EM | \ - ZT_SIG_CLEAR | \ - ZT_SIG_FXSLS | \ - ZT_SIG_FXSGS | \ - ZT_SIG_FXSKS | \ - ZT_SIG_FXOLS | \ - ZT_SIG_FXOGS | \ - ZT_SIG_FXOKS | \ - ZT_SIG_CAS | \ - ZT_SIG_SF \ - ) -#define BRI_BCHAN_SIGCAP ZT_SIG_CLEAR - -#define IS_NT(xpd) ((xpd)->type == XPD_TYPE_BRI_NT) - -/* shift in PCM highway */ -#define SUBUNIT_PCM_SHIFT 4 -#define PCM_SHIFT(mask, sunit) ((mask) << (SUBUNIT_PCM_SHIFT * (sunit))) - -/*---------------- BRI Protocol Commands ----------------------------------*/ - -static int write_state_register(xpd_t *xpd, byte value); -static bool bri_packet_is_valid(xpacket_t *pack); -static void bri_packet_dump(const char *msg, xpacket_t *pack); -static int proc_bri_info_read(char *page, char **start, off_t off, int count, int *eof, void *data); -static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data); -static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data); -static int bri_spanconfig(struct zt_span *span, struct zt_lineconfig *lc); -static int bri_chanconfig(struct zt_chan *chan, int sigtype); -static int bri_startup(struct zt_span *span); -static int bri_shutdown(struct zt_span *span); - -#define PROC_REGISTER_FNAME "slics" -#define PROC_BRI_INFO_FNAME "bri_info" - -#define VALID_CHIPSEL(x) ((x) == 0) - -enum led_state { - BRI_LED_OFF = 0x0, - BRI_LED_ON = 0x1, - /* - * We blink by software from driver, so that - * if the driver malfunction that blink would stop. - */ - // BRI_LED_BLINK_SLOW = 0x2, /* 1/2 a second blink cycle */ - // BRI_LED_BLINK_FAST = 0x3 /* 1/4 a second blink cycle */ -}; - -enum bri_led_names { - GREEN_LED = 0, - RED_LED = 1 -}; - -#define NUM_LEDS 2 -#define LED_TICKS 100 - - -struct bri_leds { - byte state:2; - byte led_sel:1; /* 0 - GREEN, 1 - RED */ - byte reserved:5; -}; - -#ifndef MAX_DFRAME_LEN_L1 -#define MAX_DFRAME_LEN_L1 300 -#endif - -#define DCHAN_BUFSIZE MAX_DFRAME_LEN_L1 - -struct BRI_priv_data { - struct proc_dir_entry *regfile; - struct proc_dir_entry *bri_info; - su_rd_sta_t state_register; - bool initialized; - int t1; /* timer 1 for NT deactivation */ - int t3; /* timer 3 for activation */ - int t4; /* timer 4 for deactivation */ - ulong l1_flags; - bool reg30_good; - uint reg30_ticks; - bool layer1_up; - xpp_line_t card_pcm_mask; - - /* - * D-Chan: buffers + extra state info. - */ - int dchan_r_idx; - byte dchan_rbuf[DCHAN_BUFSIZE]; - byte dchan_tbuf[DCHAN_BUFSIZE]; - bool txframe_begin; - - reg_cmd_t requested_reply; - reg_cmd_t last_reply; - uint tick_counter; - uint poll_counter; - uint dchan_tx_counter; - uint dchan_rx_counter; - uint dchan_rx_drops; - bool dchan_alive; - uint dchan_alive_ticks; - uint dchan_notx_ticks; - uint dchan_norx_ticks; - enum led_state ledstate[NUM_LEDS]; -}; - -static xproto_table_t PROTO_TABLE(BRI_NT); -static xproto_table_t PROTO_TABLE(BRI_TE); - - -DEF_RPACKET_DATA(BRI, SET_LED, /* Set one of the LED's */ - struct bri_leds bri_leds; - ); - -static /* 0x33 */ DECLARE_CMD(BRI, SET_LED, enum bri_led_names which_led, enum led_state to_led_state); - -#define DO_LED(xpd, which, tostate) \ - CALL_PROTO(BRI, SET_LED, (xpd)->xbus, (xpd), (which), (tostate)) - -#define DEBUG_BUF_SIZE (100) -static void dump_hex_buf(xpd_t *xpd, char *msg, byte *buf, size_t len) -{ - char debug_buf[DEBUG_BUF_SIZE + 1]; - int i; - int n = 0; - - debug_buf[0] = '\0'; - for(i = 0; i < len && n < DEBUG_BUF_SIZE; i++) - n += snprintf(&debug_buf[n], DEBUG_BUF_SIZE - n, "%02X ", buf[i]); - XPD_DBG(GENERAL, xpd, "%s[0..%zd]: %s%s\n", msg, len-1, debug_buf, - (n >= DEBUG_BUF_SIZE)?"...":""); -} - -static void dump_dchan_packet(xpd_t *xpd, bool transmit, byte *buf, int len) -{ - struct BRI_priv_data *priv; - char msgbuf[MAX_PROC_WRITE]; - char ftype = '?'; - char *direction; - int frame_begin; - - priv = xpd->priv; - BUG_ON(!priv); - if(transmit) { - direction = "TX"; - frame_begin = priv->txframe_begin; - } else { - direction = "RX"; - frame_begin = 1; - } - if(frame_begin) { /* Packet start */ - if(!IS_SET(buf[0], 7)) - ftype = 'I'; /* Information */ - else if(IS_SET(buf[0], 7) && !IS_SET(buf[0], 6)) - ftype = 'S'; /* Supervisory */ - else if(IS_SET(buf[0], 7) && IS_SET(buf[0], 6)) - ftype = 'U'; /* Unnumbered */ - else - XPD_NOTICE(xpd, "Unknown frame type 0x%X\n", buf[0]); - - snprintf(msgbuf, MAX_PROC_WRITE, "D-Chan %s = (%c) ", direction, ftype); - } else { - snprintf(msgbuf, MAX_PROC_WRITE, "D-Chan %s = ", direction); - } - dump_hex_buf(xpd, msgbuf, buf, len); -} - -static void layer1_state(xpd_t *xpd, bool up) -{ - struct BRI_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - if(priv->layer1_up == up) - return; - priv->layer1_up = up; - XPD_DBG(SIGNAL, xpd, "STATE CHANGE: Layer1 %s\n", (up)?"UP":"DOWN"); -} - -static void dchan_state(xpd_t *xpd, bool up) -{ - struct BRI_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - if(priv->dchan_alive == up) - return; - if(up) { - XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel RUNNING\n"); - priv->dchan_alive = 1; - } else { - XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel STOPPED\n"); - priv->dchan_rx_counter = priv->dchan_tx_counter = priv->dchan_rx_drops = 0; - priv->dchan_alive = 0; - priv->dchan_alive_ticks = 0; - } -} - -static void xpd_activation(xpd_t *xpd, bool on) -{ - struct BRI_priv_data *priv; - xbus_t *xbus; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - xbus = xpd->xbus; - XPD_DBG(SIGNAL, xpd, "%s\n", (on)?"ON":"OFF"); - switch(xpd->type) { - case XPD_TYPE_BRI_TE: - if(on) { - XPD_DBG(SIGNAL, xpd, "HFC_L1_ACTIVATE_TE\n"); - set_bit(HFC_L1_ACTIVATING, &priv->l1_flags); - write_state_register(xpd, STA_ACTIVATE); - priv->t3 = HFC_TIMER_T3; - } else { - XPD_DBG(SIGNAL, xpd, "HFC_L1_FORCE_DEACTIVATE_TE\n"); - write_state_register(xpd, STA_DEACTIVATE); - } - break; - case XPD_TYPE_BRI_NT: - if(on) { - XPD_DBG(SIGNAL, xpd, "HFC_L1_ACTIVATE_NT\n"); - priv->t1 = TIMER_T1_MAX; - set_bit(HFC_L1_ACTIVATING, &priv->l1_flags); - write_state_register(xpd, STA_ACTIVATE | V_SU_SET_G2_G3); - } else { - XPD_DBG(SIGNAL, xpd, "HFC_L1_DEACTIVATE_NT\n"); - write_state_register(xpd, STA_DEACTIVATE); - } - break; - default: - XPD_ERR(xpd, "%s: Bad xpd type %d\n", __FUNCTION__, xpd->type); - BUG(); - } -} - - -/* - * D-Chan receive - */ -static int rx_dchan(xpd_t *xpd, reg_cmd_t *regcmd) -{ - xbus_t *xbus; - struct BRI_priv_data *priv; - byte *src; - byte *dst; - byte *dchan_buf; - struct zt_chan *dchan; - uint len; - bool eoframe; - int idx; - int ret = 0; - - src = REG_XDATA(regcmd); - len = regcmd->bytes; - eoframe = regcmd->eoframe; - if(len <= 0) - return 0; - if(!SPAN_REGISTERED(xpd)) /* Nowhere to copy data */ - return 0; - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - xbus = xpd->xbus; -#ifdef XPP_DEBUGFS - xbus_log(xbus, xpd, 0, regcmd, sizeof(reg_cmd_t)); /* 0 = RX */ -#endif - dchan = &xpd->span.chans[2]; - if(!IS_SET(xpd->offhook, 2)) { /* D-chan is used? */ - static int rate_limit; - - if((rate_limit++ % 1000) == 0) - XPD_DBG(SIGNAL, xpd, "D-Chan unused\n"); - dchan->bytes2receive = 0; - dchan->bytes2transmit = 0; - goto out; - } - dchan_buf = dchan->readchunk; - idx = priv->dchan_r_idx; - if(idx + len >= DCHAN_BUFSIZE) { - XPD_ERR(xpd, "D-Chan RX overflow: %d\n", idx); - dump_hex_buf(xpd, " current packet", src, len); - dump_hex_buf(xpd, " dchan_buf", dchan_buf, idx); - ret = -ENOSPC; - if(eoframe) - goto drop; - goto out; - } - dst = dchan_buf + idx; - idx += len; - priv->dchan_r_idx = idx; - memcpy(dst, src, len); - if(!eoframe) - goto out; - if(idx < 4) { - XPD_NOTICE(xpd, "D-Chan RX short frame (idx=%d)\n", idx); - dump_hex_buf(xpd, "D-Chan RX: current packet", src, len); - dump_hex_buf(xpd, "D-Chan RX: chan_buf", dchan_buf, idx); - ret = -EPROTO; - goto drop; - } - if(dchan_buf[idx-1]) { - XPD_NOTICE(xpd, "D-Chan RX Bad checksum: [%02X:%02X=%02X] (%d)\n", - dchan_buf[idx-3], dchan_buf[idx-2], dchan_buf[idx-1], dchan_buf[idx-1]); - dump_hex_buf(xpd, "D-Chan RX: current packet", src, len); - dump_hex_buf(xpd, "D-Chan RX: chan_buf", dchan_buf, idx); - ret = -EPROTO; - goto drop; - } - if(print_dbg) - dump_dchan_packet(xpd, 0, dchan_buf, idx /* - 3 */); /* Print checksum? */ - /* - * Tell Zaptel that we received idx-1 bytes. They include the data and a 2-byte checksum. - * The last byte (that we don't pass on) is 0 if the checksum is correct. If it were wrong, - * we would drop the packet in the "if(dchan_buf[idx-1])" above. - */ - dchan->bytes2receive = idx - 1; - dchan->eofrx = 1; - priv->dchan_rx_counter++; - priv->dchan_norx_ticks = 0; -drop: - priv->dchan_r_idx = 0; -out: - return ret; -} - -static int send_bri_multibyte(xpd_t *xpd, byte *buf, int len, bool eoftx) -{ - xbus_t *xbus = xpd->xbus; - xframe_t *xframe; - xpacket_t *pack; - reg_cmd_t *reg_cmd; - int ret; - - BUG_ON(len < 0); - /* - * Zero length multibyte is legal and has special meaning for the - * firmware: - * eoftx==1: Start sending us D-channel packets. - * eoftx==0: Stop sending us D-channel packets. - */ - if(len > MULTIBYTE_MAX_LEN) { - XPD_ERR(xpd, "%s: len=%d is too long. dropping.\n", __FUNCTION__, len); - return -EINVAL; - } - XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx); - reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd); - reg_cmd->bytes = len; - reg_cmd->eoframe = eoftx; - reg_cmd->multibyte = 1; - if(len > 0) { - memcpy(REG_XDATA(reg_cmd), (byte *)buf, len); - } else { - XPD_DBG(REGS, xpd, "Magic Packet (eoftx=%d)\n", eoftx); - } -#ifdef XPP_DEBUGFS - xbus_log(xbus, xpd, 1, reg_cmd, sizeof(reg_cmd_t)); /* 1 = TX */ -#else - if(print_dbg) - dump_xframe("SEND_BRI_MULTI", xbus, xframe); -#endif - ret = send_cmd_frame(xbus, xframe); - if(ret < 0) - XPD_NOTICE(xpd, "%s: failed sending xframe\n", __FUNCTION__); - return ret; -} - -/* - * D-Chan transmit - */ -static int tx_dchan(xpd_t *xpd) -{ - struct BRI_priv_data *priv; - struct zt_chan *dchan; - int len; - int eoframe; - int ret; - - priv = xpd->priv; - BUG_ON(!priv); - if(!IS_NT(xpd)) { - static int rate_limit; - - if (priv->t3 > HFC_TIMER_OFF) { - /* timer expired ? */ - if (--priv->t3 == 0) { - if ((rate_limit % 1003) >= 5) - XPD_DBG(SIGNAL, xpd, "T3 expired\n"); - priv->t3 = HFC_TIMER_OFF; - clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); - xpd_activation(xpd, 0); /* Deactivate TE */ - } - } - if (priv->t4 > HFC_TIMER_OFF) { - /* timer expired ? */ - if (--priv->t4 == 0) { - if ((rate_limit % 1003) >= 5) - XPD_DBG(SIGNAL, xpd, "T4 expired\n"); - priv->t4 = HFC_TIMER_OFF; - } - } - rate_limit++; - } - if(!SPAN_REGISTERED(xpd) || !(xpd->span.flags & ZT_FLAG_RUNNING)) - return 0; - dchan = &xpd->chans[2]; - len = dchan->bytes2transmit; /* dchan's hdlc package len */ - eoframe = dchan->eoftx; /* dchan's end of frame */ - dchan->bytes2transmit = 0; - dchan->eoftx = 0; - dchan->bytes2receive = 0; - dchan->eofrx = 0; - if(len <= 0) - return 0; /* Nothing to transmit on D channel */ - if(len > MULTIBYTE_MAX_LEN) { - XPD_ERR(xpd, "%s: len=%d. need to split. Unimplemented.\n", __FUNCTION__, len); - return -EINVAL; - } - if(!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags) && !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) { - XPD_DBG(SIGNAL, xpd, "Want to transmit: Kick D-Channel transmiter\n"); - xpd_activation(xpd, 1); - return 0; - } - if(print_dbg) - dump_dchan_packet(xpd, 1, priv->dchan_tbuf, len); - if(eoframe) - priv->txframe_begin = 1; - else - priv->txframe_begin = 0; - ret = send_bri_multibyte(xpd, priv->dchan_tbuf, len, eoframe); - if(ret < 0) - XPD_NOTICE(xpd, "%s: failed sending xframe\n", __FUNCTION__); - if(eoframe) - priv->dchan_tx_counter++; - priv->dchan_notx_ticks = 0; - return ret; -} - -/*---------------- BRI: Methods -------------------------------------------*/ - -static xpd_t *BRI_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table, byte subtype, byte revision) -{ - xpd_t *xpd = NULL; - int channels = min(3, CHANNELS_PERXPD); - - XBUS_DBG(GENERAL, xbus, "\n"); - xpd = xpd_alloc(sizeof(struct BRI_priv_data), proto_table, channels); - if(!xpd) - return NULL; - xpd->direction = (proto_table == &PROTO_TABLE(BRI_NT)) ? TO_PHONE : TO_PSTN; - xpd->revision = revision; - xpd->type_name = proto_table->name; - return xpd; -} - -static void clean_proc(xbus_t *xbus, xpd_t *xpd) -{ - struct BRI_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - XPD_DBG(PROC, xpd, "\n"); -#ifdef CONFIG_PROC_FS - if(priv->regfile) { - XPD_DBG(PROC, xpd, "Removing registers file\n"); - priv->regfile->data = NULL; - remove_proc_entry(PROC_REGISTER_FNAME, xpd->proc_xpd_dir); - } - if(priv->bri_info) { - XPD_DBG(PROC, xpd, "Removing xpd BRI_INFO file\n"); - remove_proc_entry(PROC_BRI_INFO_FNAME, xpd->proc_xpd_dir); - } -#endif -} - -static int BRI_card_init(xbus_t *xbus, xpd_t *xpd) -{ - struct BRI_priv_data *priv; - int ret = 0; - - BUG_ON(!xpd); - XPD_DBG(GENERAL, xpd, "\n"); - priv = xpd->priv; -#ifdef CONFIG_PROC_FS - XPD_DBG(PROC, xpd, "Creating BRI_INFO file\n"); - priv->bri_info = create_proc_read_entry(PROC_BRI_INFO_FNAME, 0444, xpd->proc_xpd_dir, proc_bri_info_read, xpd); - if(!priv->bri_info) { - XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_BRI_INFO_FNAME); - ret = -ENOENT; - goto err; - } - priv->bri_info->owner = THIS_MODULE; - XPD_DBG(PROC, xpd, "Creating registers file\n"); - priv->regfile = create_proc_entry(PROC_REGISTER_FNAME, 0644, xpd->proc_xpd_dir); - if(!priv->regfile) { - XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_REGISTER_FNAME); - goto err; - } - priv->regfile->owner = THIS_MODULE; - priv->regfile->write_proc = proc_xpd_register_write; - priv->regfile->read_proc = proc_xpd_register_read; - priv->regfile->data = xpd; -#endif - priv->t1 = HFC_TIMER_OFF; - ret = run_initialize_registers(xpd); - if(ret < 0) - goto err; - XPD_DBG(PROC, xpd, "done\n"); - priv->initialized = 1; - return 0; -err: - clean_proc(xbus, xpd); - XPD_ERR(xpd, "Failed initializing registers (%d)\n", ret); - return ret; -} - -static int BRI_card_remove(xbus_t *xbus, xpd_t *xpd) -{ - struct BRI_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - XPD_DBG(GENERAL, xpd, "\n"); - clean_proc(xbus, xpd); - return 0; -} - -static int BRI_card_zaptel_preregistration(xpd_t *xpd, bool on) -{ - xbus_t *xbus; - struct BRI_priv_data *priv; - xpp_line_t tmp_pcm_mask; - int tmp_pcm_len; - unsigned long flags; - int i; - - BUG_ON(!xpd); - xbus = xpd->xbus; - priv = xpd->priv; - BUG_ON(!xbus); - XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off"); - if(!on) { - /* Nothing to do yet */ - return 0; - } - xpd->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_CCS; - xpd->span.deflaw = ZT_LAW_ALAW; - BIT_SET(xpd->digital_signalling, 2); /* D-Channel */ - for_each_line(xpd, i) { - struct zt_chan *cur_chan = &xpd->chans[i]; - - XPD_DBG(GENERAL, xpd, "setting BRI channel %d\n", i); - snprintf(cur_chan->name, MAX_CHANNAME, "XPP_%s/%02d/%1d%1d/%d", - xpd->xproto->name, xbus->num, - xpd->addr.unit, xpd->addr.subunit, i); - cur_chan->chanpos = i + 1; - cur_chan->pvt = xpd; - if(i == 2) { /* D-CHAN */ - cur_chan->sigcap = BRI_DCHAN_SIGCAP; - cur_chan->flags |= ZT_FLAG_BRIDCHAN; - cur_chan->flags &= ~ZT_FLAG_HDLC; - - /* Setup big buffers for D-Channel rx/tx */ - cur_chan->readchunk = priv->dchan_rbuf; - cur_chan->writechunk = priv->dchan_tbuf; - priv->dchan_r_idx = 0; - priv->txframe_begin = 1; - - cur_chan->maxbytes2transmit = MULTIBYTE_MAX_LEN; - cur_chan->bytes2transmit = 0; - cur_chan->bytes2receive = 0; - } else - cur_chan->sigcap = BRI_BCHAN_SIGCAP; - } - xpd->offhook = BIT(0) | BIT(1); /* 2*bchan */ - - /* - * Compute PCM lentgh and mask - * We know all cards have been initialized until now - */ - tmp_pcm_mask = 0; - if(xpd->addr.subunit == 0) { - int line_count = 0; - - for(i = 0; i < MAX_SUBUNIT; i++) { - xpd_t *sub_xpd = xpd_byaddr(xbus, xpd->addr.unit, i); - if(sub_xpd) { - tmp_pcm_mask |= PCM_SHIFT(sub_xpd->wanted_pcm_mask, i); - line_count += 2; - } - } - tmp_pcm_len = RPACKET_HEADERSIZE + sizeof(xpp_line_t) + line_count * ZT_CHUNKSIZE; - } else - tmp_pcm_len = 0; - spin_lock_irqsave(&xpd->lock, flags); - xpd->pcm_len = tmp_pcm_len; - xpd->wanted_pcm_mask = xpd->offhook; - priv->card_pcm_mask = tmp_pcm_mask; - xpd->span.spanconfig = bri_spanconfig; - xpd->span.chanconfig = bri_chanconfig; - xpd->span.startup = bri_startup; - xpd->span.shutdown = bri_shutdown; - spin_unlock_irqrestore(&xpd->lock, flags); - return 0; -} - -static int BRI_card_zaptel_postregistration(xpd_t *xpd, bool on) -{ - xbus_t *xbus; - struct BRI_priv_data *priv; - - BUG_ON(!xpd); - xbus = xpd->xbus; - priv = xpd->priv; - BUG_ON(!xbus); - XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off"); - return(0); -} - -static int BRI_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig) -{ - LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig)); - return 0; -} - -/* - * LED managment is done by the driver now: - * - Turn constant ON RED/GREEN led to indicate NT/TE port - * - Very fast "Double Blink" to indicate Layer1 alive (without D-Channel) - * - Constant blink (1/2 sec cycle) to indicate D-Channel alive. - */ -static void handle_leds(xbus_t *xbus, xpd_t *xpd) -{ - struct BRI_priv_data *priv; - unsigned int timer_count; - int which_led; - int other_led; - int mod; - - BUG_ON(!xpd); - if(IS_NT(xpd)) { - which_led = RED_LED; - other_led = GREEN_LED; - } else { - which_led = GREEN_LED; - other_led = RED_LED; - } - priv = xpd->priv; - BUG_ON(!priv); - timer_count = xpd->timer_count; - if(xpd->blink_mode) { - if((timer_count % DEFAULT_LED_PERIOD) == 0) { - // led state is toggled - if(priv->ledstate[which_led] == BRI_LED_OFF) { - DO_LED(xpd, which_led, BRI_LED_ON); - DO_LED(xpd, other_led, BRI_LED_ON); - } else { - DO_LED(xpd, which_led, BRI_LED_OFF); - DO_LED(xpd, other_led, BRI_LED_OFF); - } - } - return; - } - if(priv->ledstate[other_led] != BRI_LED_OFF) - DO_LED(xpd, other_led, BRI_LED_OFF); - if(priv->dchan_alive) { - mod = timer_count % 1000; - switch(mod) { - case 0: - DO_LED(xpd, which_led, BRI_LED_ON); - break; - case 500: - DO_LED(xpd, which_led, BRI_LED_OFF); - break; - } - } else if(priv->layer1_up) { - mod = timer_count % 1000; - switch(mod) { - case 0: - case 100: - DO_LED(xpd, which_led, BRI_LED_ON); - break; - case 50: - case 150: - DO_LED(xpd, which_led, BRI_LED_OFF); - break; - } - } else { - if(priv->ledstate[which_led] != BRI_LED_ON) - DO_LED(xpd, which_led, BRI_LED_ON); - } -} - -/* Poll the register ST/Up-State-machine Register, to see if the cable - * if a cable is connected to the port. - */ -static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd) -{ - struct BRI_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - if(!priv->initialized || !xbus->self_ticking) - return 0; - if(poll_interval != 0 && (priv->tick_counter % poll_interval) == 0) { - // XPD_DBG(GENERAL, xpd, "%d\n", priv->tick_counter); - priv->poll_counter++; - xpp_register_request(xbus, xpd, 0, 0, 0, A_SU_RD_STA, 0, 0, 0); - - if(IS_NT(xpd) && nt_keepalive && - !test_bit(HFC_L1_ACTIVATED, &priv->l1_flags) && - !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) { - XPD_DBG(SIGNAL, xpd, "Kick NT D-Channel\n"); - xpd_activation(xpd, 1); - } - } - /* Detect D-Channel disconnect heuristic */ - priv->dchan_notx_ticks++; - priv->dchan_norx_ticks++; - priv->dchan_alive_ticks++; - if(priv->dchan_alive && (priv->dchan_notx_ticks > DCHAN_LOST || priv->dchan_norx_ticks > DCHAN_LOST)) { - /* - * No tx_dchan() or rx_dchan() for many ticks - * This D-Channel is probabelly dead. - */ - dchan_state(xpd, 0); - } else if(priv->dchan_rx_counter > 1 && priv->dchan_tx_counter > 1) { - if(!priv->dchan_alive) - dchan_state(xpd, 1); - } - /* Detect Layer1 disconnect */ - if(priv->reg30_good && priv->reg30_ticks > poll_interval * REG30_LOST) { - /* No reply for 1/2 a second */ - XPD_ERR(xpd, "Lost state tracking for %d ticks\n", priv->reg30_ticks); - priv->reg30_good = 0; - layer1_state(xpd, 0); - dchan_state(xpd, 0); - } - handle_leds(xbus, xpd); - tx_dchan(xpd); - /* Detect T1 timer expiry on NT */ - if(IS_NT(xpd) && !nt_keepalive) { - if (priv->t1 > HFC_TIMER_OFF) { - if (--priv->t1 == 0) { - XPD_DBG(SIGNAL, xpd, "T1 Expired. Deactivate NT\n"); - priv->t1 = HFC_TIMER_OFF; - clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); - write_state_register(xpd, STA_DEACTIVATE); - } - } - } - priv->tick_counter++; - priv->reg30_ticks++; - return 0; -} - -static int BRI_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg) -{ - BUG_ON(!xpd); - if(!TRANSPORT_RUNNING(xpd->xbus)) - return -ENODEV; - switch (cmd) { - case ZT_TONEDETECT: - /* - * Asterisk call all span types with this (FXS specific) - * call. Silently ignore it. - */ - LINE_DBG(SIGNAL, xpd, pos, "BRI: Starting a call\n"); - return -ENOTTY; - default: - report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd); - return -ENOTTY; - } - return 0; -} - -static int BRI_card_close(xpd_t *xpd, lineno_t pos) -{ - struct zt_chan *chan = &xpd->span.chans[pos]; - - /* Clear D-Channel pending data */ - chan->bytes2receive = 0; - chan->eofrx = 0; - chan->bytes2transmit = 0; - chan->eoftx = 0; - return 0; -} - -/* - * Called only for 'span' keyword in /etc/zaptel.conf - */ -static int bri_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) -{ - xpd_t *xpd = span->pvt; - const char *framingstr = ""; - const char *codingstr = ""; - const char *crcstr = ""; - - /* framing first */ - if (lc->lineconfig & ZT_CONFIG_B8ZS) - framingstr = "B8ZS"; - else if (lc->lineconfig & ZT_CONFIG_AMI) - framingstr = "AMI"; - else if (lc->lineconfig & ZT_CONFIG_HDB3) - framingstr = "HDB3"; - /* then coding */ - if (lc->lineconfig & ZT_CONFIG_ESF) - codingstr = "ESF"; - else if (lc->lineconfig & ZT_CONFIG_D4) - codingstr = "D4"; - else if (lc->lineconfig & ZT_CONFIG_CCS) - codingstr = "CCS"; - /* E1's can enable CRC checking */ - if (lc->lineconfig & ZT_CONFIG_CRC4) - crcstr = "CRC4"; - XPD_DBG(GENERAL, xpd, "[%s]: span=%d (%s) lbo=%d lineconfig=%s/%s/%s (0x%X) sync=%d\n", - IS_NT(xpd)?"NT":"TE", - lc->span, - lc->name, - lc->lbo, - framingstr, codingstr, crcstr, - lc->lineconfig, - lc->sync); - /* - * FIXME: validate - */ - span->lineconfig = lc->lineconfig; - return 0; -} - -/* - * Set signalling type (if appropriate) - * Called from zaptel with spinlock held on chan. Must not call back - * zaptel functions. - */ -static int bri_chanconfig(struct zt_chan *chan, int sigtype) -{ - DBG(GENERAL, "channel %d (%s) -> %s\n", chan->channo, chan->name, sig2str(sigtype)); - // FIXME: sanity checks: - // - should be supported (within the sigcap) - // - should not replace fxs <->fxo ??? (covered by previous?) - return 0; -} - -/* - * Called only for 'span' keyword in /etc/zaptel.conf - */ -static int bri_startup(struct zt_span *span) -{ - xpd_t *xpd = span->pvt; - struct BRI_priv_data *priv; - struct zt_chan *dchan; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - if(!TRANSPORT_RUNNING(xpd->xbus)) { - XPD_DBG(GENERAL, xpd, "Startup called by zaptel. No Hardware. Ignored\n"); - return -ENODEV; - } - XPD_DBG(GENERAL, xpd, "STARTUP\n"); - // Turn on all channels - CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 1); - write_state_register(xpd, 0); /* Enable L1 state machine */ - xpd_activation(xpd, 1); - if(SPAN_REGISTERED(xpd)) { - dchan = &span->chans[2]; - span->flags |= ZT_FLAG_RUNNING; - /* - * Zaptel (wrongly) assume that D-Channel need HDLC decoding - * and during zaptel registration override our flags. - * - * Don't Get Mad, Get Even: Now we override zaptel :-) - */ - dchan->flags |= ZT_FLAG_BRIDCHAN; - dchan->flags &= ~ZT_FLAG_HDLC; - } - return 0; -} - -/* - * Called only for 'span' keyword in /etc/zaptel.conf - */ -static int bri_shutdown(struct zt_span *span) -{ - xpd_t *xpd = span->pvt; - struct BRI_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - if(!TRANSPORT_RUNNING(xpd->xbus)) { - XPD_DBG(GENERAL, xpd, "Shutdown called by zaptel. No Hardware. Ignored\n"); - return -ENODEV; - } - XPD_DBG(GENERAL, xpd, "SHUTDOWN\n"); - // Turn off all channels - CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 0); - if(IS_NT(xpd)) - xpd_activation(xpd, 0); - return 0; -} - -static void BRI_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpp_line_t wanted_lines, xpacket_t *pack) -{ - byte *pcm; - struct zt_chan *chans; - unsigned long flags; - int i; - int subunit; - xpp_line_t pcm_mask = 0; - - - BUG_ON(!xbus); - BUG_ON(!xpd); - BUG_ON(!pack); - pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm); - for(subunit = 0; subunit < MAX_SUBUNIT; subunit++) { - xpd_t *tmp_xpd; - - tmp_xpd = xpd_byaddr(xbus, xpd->addr.unit, subunit); - if(!tmp_xpd || !tmp_xpd->card_present) - continue; - spin_lock_irqsave(&tmp_xpd->lock, flags); - chans = tmp_xpd->span.chans; - for_each_line(tmp_xpd, i) { - if(IS_SET(wanted_lines, i)) { - if(SPAN_REGISTERED(tmp_xpd)) { -#ifdef DEBUG_PCMTX - if(pcmtx >= 0 && pcmtx_chan == i) - memset((u_char *)pcm, pcmtx, ZT_CHUNKSIZE); - else -#endif - memcpy((u_char *)pcm, chans[i].writechunk, ZT_CHUNKSIZE); - // fill_beep((u_char *)pcm, tmp_xpd->addr.subunit, 2); - } else - memset((u_char *)pcm, 0x7F, ZT_CHUNKSIZE); - pcm += ZT_CHUNKSIZE; - } - } - pcm_mask |= PCM_SHIFT(wanted_lines, subunit); - XPD_COUNTER(tmp_xpd, PCM_WRITE)++; - spin_unlock_irqrestore(&tmp_xpd->lock, flags); - } - RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = pcm_mask; -} - -static void BRI_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack) -{ - byte *pcm; - xpp_line_t pcm_mask; - unsigned long flags; - int subunit; - int i; - - /* - * Subunit 0 handle all other subunits - */ - if(xpd->addr.subunit != 0) - return; - if(!SPAN_REGISTERED(xpd)) - return; - pcm = RPACKET_FIELD(pack, GLOBAL, PCM_READ, pcm); - pcm_mask = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines); - for(subunit = 0; subunit < MAX_SUBUNIT; subunit++, pcm_mask >>= SUBUNIT_PCM_SHIFT) { - xpd_t *tmp_xpd; - - if(!pcm_mask) - break; /* optimize */ - tmp_xpd = xpd_byaddr(xbus, xpd->addr.unit, subunit); - if(!tmp_xpd || !tmp_xpd->card_present || !SPAN_REGISTERED(tmp_xpd)) - continue; - spin_lock_irqsave(&tmp_xpd->lock, flags); - for (i = 0; i < 2; i++) { - xpp_line_t tmp_mask = pcm_mask & (BIT(0) | BIT(1)); - volatile u_char *r; - - if(IS_SET(tmp_mask, i)) { - r = tmp_xpd->span.chans[i].readchunk; - // memset((u_char *)r, 0x5A, ZT_CHUNKSIZE); // DEBUG - // fill_beep((u_char *)r, 1, 1); // DEBUG: BEEP - memcpy((u_char *)r, pcm, ZT_CHUNKSIZE); - pcm += ZT_CHUNKSIZE; - } - } - XPD_COUNTER(tmp_xpd, PCM_READ)++; - spin_unlock_irqrestore(&tmp_xpd->lock, flags); - } -} - -/*---------------- BRI: HOST COMMANDS -------------------------------------*/ - -static /* 0x0F */ HOSTCMD(BRI, XPD_STATE, bool on) -{ - BUG_ON(!xpd); - XPD_DBG(GENERAL, xpd, "%s\n", (on)?"ON":"OFF"); - xpd_activation(xpd, on); - return 0; -} - -static /* 0x0F */ HOSTCMD(BRI, RING, lineno_t chan, bool on) -{ - XPD_ERR(xpd, "%s: Unsupported\n", __FUNCTION__); - return -ENOSYS; -} - -static /* 0x0F */ HOSTCMD(BRI, RELAY_OUT, byte which, bool on) -{ - XPD_ERR(xpd, "%s: Unsupported\n", __FUNCTION__); - return -ENOSYS; -} - -static /* 0x33 */ HOSTCMD(BRI, SET_LED, enum bri_led_names which_led, enum led_state to_led_state) -{ - int ret = 0; - xframe_t *xframe; - xpacket_t *pack; - struct bri_leds *bri_leds; - struct BRI_priv_data *priv; - - BUG_ON(!xbus); - priv = xpd->priv; - BUG_ON(!priv); - XPD_DBG(LEDS, xpd, "%s -> %d\n", - (which_led)?"RED":"GREEN", - to_led_state); - XFRAME_NEW_CMD(xframe, pack, xbus, BRI, SET_LED, xpd->xbus_idx); - bri_leds = &RPACKET_FIELD(pack, BRI, SET_LED, bri_leds); - bri_leds->state = to_led_state; - bri_leds->led_sel = which_led; - XPACKET_LEN(pack) = RPACKET_SIZE(BRI, SET_LED); - ret = send_cmd_frame(xbus, xframe); - priv->ledstate[which_led] = to_led_state; - return ret; -} - -static int write_state_register(xpd_t *xpd, byte value) -{ - int ret; - - XPD_DBG(REGS, xpd, "value = 0x%02X\n", value); - ret = xpp_register_request(xpd->xbus, xpd, - 0, /* chipsel */ - 1, /* writing */ - 0, /* do_subreg */ - A_SU_WR_STA, /* regnum */ - 0, /* subreg */ - value, /* data_low */ - 0 /* data_high */ - ); - return ret; -} - -/*---------------- BRI: Astribank Reply Handlers --------------------------*/ -static void su_new_state(xpd_t *xpd, byte reg_x30) -{ - xbus_t *xbus; - struct BRI_priv_data *priv; - su_rd_sta_t new_state; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - xbus = xpd->xbus; - if(!priv->initialized) { - XPD_ERR(xpd, "%s called on uninitialized AB\n", __FUNCTION__); - return; - } - new_state.reg = reg_x30; - priv->reg30_ticks = 0; - priv->reg30_good = 1; - if((!IS_NT(xpd) && new_state.bits.v_su_sta == ST_TE_ACTIVATED) || - (IS_NT(xpd) && new_state.bits.v_su_sta == ST_NT_ACTIVATED)) { - if(!priv->layer1_up) { - layer1_state(xpd, 1); - update_xpd_status(xpd, ZT_ALARM_NONE); - } - } else { - /* - * Layer 1 disconnected - */ - if(priv->layer1_up) { - layer1_state(xpd, 0); - dchan_state(xpd, 0); - } - /* - * Do NOT notify Zaptel about the disconnection. - * If we do, Asterisk stops transmitting on the D-channel and - * we can't reactivate layer-1. - * Without the notification, Asterisk thinks that we are active - * (although the PSTN stopped layer-1) and on call setup, sends - * us D-channel data, which triggers the layer-1 activation. - */ -#if 0 - update_xpd_status(xpd, ZT_ALARM_RED); -#endif - } - if (priv->state_register.bits.v_su_sta == new_state.bits.v_su_sta) - return; /* same same */ - DBG(SIGNAL, "%02X ---> %02X\n", priv->state_register.reg, reg_x30); - XPD_DBG(SIGNAL, xpd, "%s%i\n", IS_NT(xpd)?"G":"F", new_state.bits.v_su_sta); - - if(!IS_NT(xpd)) { - /* disable T3 ? */ - if ((new_state.bits.v_su_sta <= ST_TE_DEACTIVATED) || (new_state.bits.v_su_sta >= ST_TE_ACTIVATED)) { - XPD_DBG(SIGNAL, xpd, "Disable T3 ?\n"); - priv->t3 = HFC_TIMER_OFF; - } - switch (new_state.bits.v_su_sta) { - case ST_TE_DEACTIVATED: /* F3 */ - XPD_DBG(SIGNAL, xpd, "State ST_TE_DEACTIVATED (F3)\n"); - if (test_and_clear_bit(HFC_L1_ACTIVATED, &priv->l1_flags)) - priv->t4 = HFC_TIMER_T4; - break; - case ST_TE_SIGWAIT: /* F4 */ - XPD_DBG(SIGNAL, xpd, "State ST_TE_SIGWAIT (F4)\n"); - break; - case ST_TE_IDENT: /* F5 */ - XPD_DBG(SIGNAL, xpd, "State ST_TE_IDENT (F5)\n"); - break; - case ST_TE_SYNCED: /* F6 */ - XPD_DBG(SIGNAL, xpd, "State ST_TE_SYNCED (F6)\n"); - break; - case ST_TE_ACTIVATED: /* F7 */ - XPD_DBG(SIGNAL, xpd, "State ST_TE_ACTIVATED (F7)\n"); - if (priv->t4 > HFC_TIMER_OFF) - priv->t4 = HFC_TIMER_OFF; - clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); - set_bit(HFC_L1_ACTIVATED, &priv->l1_flags); - update_xpd_status(xpd, ZT_ALARM_NONE); - break; - - case ST_TE_LOST_FRAMING: /* F8 */ - XPD_DBG(SIGNAL, xpd, "State ST_TE_LOST_FRAMING (F8)\n"); - priv->t4 = HFC_TIMER_OFF; - break; - default: - XPD_NOTICE(xpd, "Bad TE state: %d\n", new_state.bits.v_su_sta); - break; - } - - } else if(IS_NT(xpd)) { - switch (new_state.bits.v_su_sta) { - case ST_NT_DEACTIVATED: /* G1 */ - XPD_DBG(SIGNAL, xpd, "State ST_NT_DEACTIVATED (G1)\n"); - clear_bit(HFC_L1_ACTIVATED, &priv->l1_flags); - priv->t1 = HFC_TIMER_OFF; - break; - case ST_NT_ACTIVATING: /* G2 */ - XPD_DBG(SIGNAL, xpd, "State ST_NT_ACTIVATING (G2)\n"); - xpd_activation(xpd, 1); - break; - case ST_NT_ACTIVATED: /* G3 */ - XPD_DBG(SIGNAL, xpd, "State ST_NT_ACTIVATED (G3)\n"); - clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags); - set_bit(HFC_L1_ACTIVATED, &priv->l1_flags); - priv->t1 = HFC_TIMER_OFF; - break; - case ST_NT_DEACTIVTING: /* G4 */ - XPD_DBG(SIGNAL, xpd, "State ST_NT_DEACTIVTING (G4)\n"); - priv->t1 = HFC_TIMER_OFF; - break; - default: - XPD_NOTICE(xpd, "Bad NT state: %d\n", new_state.bits.v_su_sta); - break; - } - } else - XPD_ERR(xpd, "%s: Unknown xpd type %d\n", __FUNCTION__, xpd->type); - priv->state_register.reg = new_state.reg; -} - -static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) -{ - unsigned long flags; - struct BRI_priv_data *priv; - int ret; - - spin_lock_irqsave(&xpd->lock, flags); - priv = xpd->priv; - BUG_ON(!priv); - if(REG_FIELD(info, do_subreg)) { - XPD_DBG(REGS, xpd, "RS %02X %02X %02X\n", - REG_FIELD(info, regnum), REG_FIELD(info, subreg), REG_FIELD(info, data_low)); - } else { - if (REG_FIELD(info, regnum) != A_SU_RD_STA) - XPD_DBG(REGS, xpd, "RD %02X %02X\n", - REG_FIELD(info, regnum), REG_FIELD(info, data_low)); - } - if(info->multibyte) { - XPD_DBG(REGS, xpd, "Got Multibyte: %d bytes, eoframe: %d\n", - info->bytes, info->eoframe); - ret = rx_dchan(xpd, info); - if (ret < 0) { - priv->dchan_rx_drops++; - if(atomic_read(&xpd->open_counter) > 0) - XPD_NOTICE(xpd, "Multibyte Drop: errno=%d\n", ret); - } - goto end; - } - if(REG_FIELD(info, regnum) == A_SU_RD_STA) { - su_new_state(xpd, REG_FIELD(info, data_low)); - } - - /* Update /proc info only if reply relate to the last slic read request */ - if( - REG_FIELD(&priv->requested_reply, regnum) == REG_FIELD(info, regnum) && - REG_FIELD(&priv->requested_reply, do_subreg) == REG_FIELD(info, do_subreg) && - REG_FIELD(&priv->requested_reply, subreg) == REG_FIELD(info, subreg)) { - priv->last_reply = *info; - } - -end: - spin_unlock_irqrestore(&xpd->lock, flags); - return 0; -} - -static xproto_table_t PROTO_TABLE(BRI_NT) = { - .owner = THIS_MODULE, - .entries = { - /* Table Card Opcode */ - }, - .name = "BRI_NT", - .type = XPD_TYPE_BRI_NT, - .xops = { - .card_new = BRI_card_new, - .card_init = BRI_card_init, - .card_remove = BRI_card_remove, - .card_zaptel_preregistration = BRI_card_zaptel_preregistration, - .card_zaptel_postregistration = BRI_card_zaptel_postregistration, - .card_hooksig = BRI_card_hooksig, - .card_tick = BRI_card_tick, - .card_pcm_fromspan = BRI_card_pcm_fromspan, - .card_pcm_tospan = BRI_card_pcm_tospan, - .card_ioctl = BRI_card_ioctl, - .card_close = BRI_card_close, - .card_register_reply = BRI_card_register_reply, - - .RING = XPROTO_CALLER(BRI, RING), - .RELAY_OUT = XPROTO_CALLER(BRI, RELAY_OUT), - .XPD_STATE = XPROTO_CALLER(BRI, XPD_STATE), - }, - .packet_is_valid = bri_packet_is_valid, - .packet_dump = bri_packet_dump, -}; - -static xproto_table_t PROTO_TABLE(BRI_TE) = { - .owner = THIS_MODULE, - .entries = { - /* Table Card Opcode */ - }, - .name = "BRI_TE", - .type = XPD_TYPE_BRI_TE, - .xops = { - .card_new = BRI_card_new, - .card_init = BRI_card_init, - .card_remove = BRI_card_remove, - .card_zaptel_preregistration = BRI_card_zaptel_preregistration, - .card_zaptel_postregistration = BRI_card_zaptel_postregistration, - .card_hooksig = BRI_card_hooksig, - .card_tick = BRI_card_tick, - .card_pcm_fromspan = BRI_card_pcm_fromspan, - .card_pcm_tospan = BRI_card_pcm_tospan, - .card_ioctl = BRI_card_ioctl, - .card_close = BRI_card_close, - .card_register_reply = BRI_card_register_reply, - - .RING = XPROTO_CALLER(BRI, RING), - .RELAY_OUT = XPROTO_CALLER(BRI, RELAY_OUT), - .XPD_STATE = XPROTO_CALLER(BRI, XPD_STATE), - }, - .packet_is_valid = bri_packet_is_valid, - .packet_dump = bri_packet_dump, -}; - -static bool bri_packet_is_valid(xpacket_t *pack) -{ - const xproto_entry_t *xe_nt = NULL; - const xproto_entry_t *xe_te = NULL; - // DBG(GENERAL, "\n"); - xe_nt = xproto_card_entry(&PROTO_TABLE(BRI_NT), XPACKET_OP(pack)); - xe_te = xproto_card_entry(&PROTO_TABLE(BRI_TE), XPACKET_OP(pack)); - return xe_nt != NULL || xe_te != NULL; -} - -static void bri_packet_dump(const char *msg, xpacket_t *pack) -{ - DBG(GENERAL, "%s\n", msg); -} -/*------------------------- REGISTER Handling --------------------------*/ - -static int proc_bri_info_read(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - unsigned long flags; - xpd_t *xpd = data; - struct BRI_priv_data *priv; - - DBG(PROC, "\n"); - if(!xpd) - return -ENODEV; - spin_lock_irqsave(&xpd->lock, flags); - priv = xpd->priv; - BUG_ON(!priv); - len += sprintf(page + len, "%05d Layer 1: ", priv->poll_counter); - if(priv->reg30_good) { - len += sprintf(page + len, "%-5s ", (priv->layer1_up) ? "UP" : "DOWN"); - len += sprintf(page + len, "%c%d %-15s -- fr_sync=%d t2_exp=%d info0=%d g2_g3=%d\n", - IS_NT(xpd)?'G':'F', - priv->state_register.bits.v_su_sta, - xhfc_state_name(xpd->type, priv->state_register.bits.v_su_sta), - priv->state_register.bits.v_su_fr_sync, - priv->state_register.bits.v_su_t2_exp, - priv->state_register.bits.v_su_info0, - priv->state_register.bits.v_g2_g3); - } else - len += sprintf(page + len, "Unkown\n"); - if(IS_NT(xpd)) - len += sprintf(page + len, "T1 Timer: %d\n", priv->t1); - len += sprintf(page + len, "Tick Counter: %d\n", priv->tick_counter); - len += sprintf(page + len, "Last Poll Reply: %d ticks ago\n", priv->reg30_ticks); - len += sprintf(page + len, "reg30_good=%d\n", priv->reg30_good); - len += sprintf(page + len, "D-Channel: TX=[%5d] RX=[%5d] BAD=[%5d] ", - priv->dchan_tx_counter, priv->dchan_rx_counter, priv->dchan_rx_drops); - if(priv->dchan_alive) { - len += sprintf(page + len, "(alive %d K-ticks)\n", - priv->dchan_alive_ticks/1000); - } else { - len += sprintf(page + len, "(dead)\n"); - } - len += sprintf(page + len, "dchan_notx_ticks: %d\n", priv->dchan_notx_ticks); - len += sprintf(page + len, "dchan_norx_ticks: %d\n", priv->dchan_norx_ticks); - len += sprintf(page + len, "LED: %-10s = %d\n", "GREEN", priv->ledstate[GREEN_LED]); - len += sprintf(page + len, "LED: %-10s = %d\n", "RED", priv->ledstate[RED_LED]); - len += sprintf(page + len, "\nDCHAN:\n"); - len += sprintf(page + len, "\n"); - spin_unlock_irqrestore(&xpd->lock, flags); - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; -} - -/* - * - * Direct/Indirect - * | - * | Reg# - * | | - * | | Data (only in Write) - * | | | - * | | +-+-+ - * v v v v - * FF WD 06 01 05 - * ^ ^ - * | | - * | Write/Read - * | - * Chan# - * - */ -static int handle_register_command(xpd_t *xpd, char *cmdline) -{ - unsigned chipsel; - unsigned data = 0; - unsigned xdata1 = 0; - unsigned xdata2 = 0; - char op; /* [W]rite, [R]ead */ - char reg_type; /* [D]irect, [S]ubregister */ - int reg_num; - int subreg; - int elements; - bool writing; - char *p; - reg_cmd_t regcmd; - xbus_t *xbus; - int ret = -EINVAL; - struct BRI_priv_data *priv; - byte buf[MAX_PROC_WRITE]; - - BUG_ON(!xpd); - xbus = xpd->xbus; - BUG_ON(!xbus); - priv = xpd->priv; - BUG_ON(!priv); - if((p = strchr(cmdline, '#')) != NULL) /* Truncate comments */ - *p = '\0'; - if((p = strchr(cmdline, ';')) != NULL) /* Truncate comments */ - *p = '\0'; - for(p = cmdline; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */ - ; - if(*p == '\0') - return 0; - - if(!XBUS_GET(xbus)) { - XBUS_DBG(GENERAL, xbus, "Dropped packet. Is shutting down.\n"); - return -EBUSY; - } - memset(buf, 0, MAX_PROC_WRITE); - elements = sscanf(cmdline, "%d %c%c %x %x %x %x %x", - &chipsel, - &op, ®_type, ®_num, - &subreg, - &data, &xdata1, &xdata2); - XPD_DBG(PROC, xpd, "'%s': %d %c%c %02X %02X %02X\n", cmdline, chipsel, op, reg_type, reg_num, subreg, data); - if(elements < 3) { // At least: chipsel, op, reg_type, reg_num - ERR("Not enough arguments: (%d args) '%s'\n", elements, cmdline); - goto out; - } - if(!VALID_CHIPSEL(chipsel)) { - ERR("Bad chip select number: %d\n", chipsel); - goto out; - } - REG_FIELD(®cmd, chipsel) = chipsel; - switch(op) { - case 'W': - writing = 1; - break; - case 'R': - writing = 0; - break; - default: - ERR("Unkown operation type '%c'\n", op); - goto out; - } - if( - (op == 'W' && reg_type == 'D' && elements != 5) || - (op == 'W' && reg_type == 'S' && elements != 6) || - (op == 'R' && reg_type == 'D' && elements != 4) || - (op == 'R' && reg_type == 'S' && elements != 4) - ) { - ERR("Bad number of elements: '%s' (%d elements): %d %c%c %02X %02X %02X\n", - cmdline, elements, - chipsel, op, reg_type, reg_num, subreg, data); - goto out; - } - switch(reg_type) { - case 'S': - REG_FIELD(®cmd, do_subreg) = 1; - REG_FIELD(®cmd, regnum) = reg_num; - REG_FIELD(®cmd, subreg) = subreg; - REG_FIELD(®cmd, data_low) = data; - break; - case 'D': - REG_FIELD(®cmd, do_subreg) = 0; - REG_FIELD(®cmd, regnum) = reg_num; - REG_FIELD(®cmd, subreg) = 0; - REG_FIELD(®cmd, data_low) = subreg; - break; - case 'M': /* Multi without eoftx */ - case 'm': /* Multi with eoftx */ - if(!writing) { - ERR("Read multibyte is not implemented\n"); - goto out; - } - elements -= 3; - REG_XDATA(®cmd)[0] = reg_num; - REG_XDATA(®cmd)[1] = subreg; - REG_XDATA(®cmd)[2] = data; - REG_XDATA(®cmd)[3] = xdata1; - REG_XDATA(®cmd)[4] = xdata2; - ret = send_bri_multibyte(xpd, REG_XDATA(®cmd), elements, (reg_type == 'm')); - goto out; - default: - ERR("Unkown register type '%c'\n", reg_type); - goto out; - } - regcmd.bytes = sizeof(regcmd) - 1; - REG_FIELD(®cmd, read_request) = writing; - REG_FIELD(®cmd, data_high) = 0; - priv->requested_reply = regcmd; - if(print_dbg) - dump_reg_cmd("BRI", ®cmd, 1); - ret = xpp_register_request(xpd->xbus, xpd, - REG_FIELD(®cmd, chipsel), - writing, - REG_FIELD(®cmd, do_subreg), - REG_FIELD(®cmd, regnum), - REG_FIELD(®cmd, subreg), - REG_FIELD(®cmd, data_low), - REG_FIELD(®cmd, data_high)); -out: - XBUS_PUT(xbus); - return ret; -} - -static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data) -{ - xpd_t *xpd = data; - char buf[MAX_PROC_WRITE]; - char *p; - int i; - int ret; - - if(!xpd) - return -ENODEV; - for(i = 0; i < count; /* noop */) { - for(p = buf; p < buf + MAX_PROC_WRITE; p++) { /* read a line */ - if(i >= count) - break; - if(get_user(*p, buffer + i)) - return -EFAULT; - i++; - if(*p == '\n' || *p == '\r') /* whatever */ - break; - } - if(p >= buf + MAX_PROC_WRITE) - return -E2BIG; - *p = '\0'; - ret = handle_register_command(xpd, buf); - if(ret < 0) - return ret; - msleep(1); - } - return count; -} - - -static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - unsigned long flags; - xpd_t *xpd = data; - reg_cmd_t *info; - struct BRI_priv_data *priv; - - if(!xpd) - return -ENODEV; - priv = xpd->priv; - BUG_ON(!priv); - spin_lock_irqsave(&xpd->lock, flags); - info = &priv->last_reply; - len += sprintf(page + len, "# Writing bad data into this file may damage your hardware!\n"); - len += sprintf(page + len, "# Consult firmware docs first\n"); - len += sprintf(page + len, "#\n"); - if(REG_FIELD(info, do_subreg)) { - len += sprintf(page + len, "#CH\tOP\tReg.\tSub\tDL\n"); - len += sprintf(page + len, "%2d\tRS\t%02X\t%02X\t%02X\n", - REG_FIELD(info, chipsel), - REG_FIELD(info, regnum), REG_FIELD(info, subreg), REG_FIELD(info, data_low)); - } else { - len += sprintf(page + len, "#CH\tOP\tReg.\tDL\n"); - len += sprintf(page + len, "%2d\tRD\t%02X\t%02X\n", - REG_FIELD(info, chipsel), - REG_FIELD(info, regnum), REG_FIELD(info, data_low)); - } - spin_unlock_irqrestore(&xpd->lock, flags); - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; -} - -int __init card_bri_startup(void) -{ - DBG(GENERAL, "\n"); - - INFO("revision %s\n", XPP_VERSION); - xproto_register(&PROTO_TABLE(BRI_NT)); - xproto_register(&PROTO_TABLE(BRI_TE)); - return 0; -} - -void __exit card_bri_cleanup(void) -{ - DBG(GENERAL, "\n"); - xproto_unregister(&PROTO_TABLE(BRI_NT)); - xproto_unregister(&PROTO_TABLE(BRI_TE)); -} - -MODULE_DESCRIPTION("XPP BRI Card Driver"); -MODULE_AUTHOR("Oron Peled "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(XPP_VERSION); -MODULE_ALIAS_XPD(XPD_TYPE_BRI_NT); -MODULE_ALIAS_XPD(XPD_TYPE_BRI_TE); - -module_init(card_bri_startup); -module_exit(card_bri_cleanup); diff --git a/xpp/card_bri.h b/xpp/card_bri.h deleted file mode 100644 index a7b69de..0000000 --- a/xpp/card_bri.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef CARD_BRI_H -#define CARD_BRI_H -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "xpd.h" - -enum bri_opcodes { - XPROTO_NAME(BRI, SET_LED) = 0x33, -}; - -#endif /* CARD_BRI_H */ diff --git a/xpp/card_fxo.c b/xpp/card_fxo.c deleted file mode 100644 index cbe953b..0000000 --- a/xpp/card_fxo.c +++ /dev/null @@ -1,1218 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include "xpd.h" -#include "xproto.h" -#include "xpp_zap.h" -#include "card_fxo.h" -#include "zap_debug.h" -#include "xbus-core.h" - -static const char rcsid[] = "$Id$"; - -DEF_PARM(int, print_dbg, 0, 0644, "Print DBG statements"); -DEF_PARM(uint, poll_battery_interval, 500, 0644, "Poll battery interval in milliseconds (0 - disable)"); -DEF_PARM(uint, poll_power_denial_interval, 40, 0644, "Power denial detection poll interval in milliseconds (0 - disable)"); -#ifdef WITH_METERING -DEF_PARM(uint, poll_metering_interval, 500, 0644, "Poll metering interval in milliseconds (0 - disable)"); -#endif -DEF_PARM(int, ring_debounce, 50, 0644, "Number of ticks to debounce a false RING indication"); - -/* Signaling is opposite (fxs signalling for fxo card) */ -#if 1 -#define FXO_DEFAULT_SIGCAP (ZT_SIG_FXSKS | ZT_SIG_FXSLS) -#else -#define FXO_DEFAULT_SIGCAP (ZT_SIG_SF) -#endif - -enum fxo_leds { - LED_GREEN, -}; - -#define NUM_LEDS 1 -#define DELAY_UNTIL_DIALTONE 3000 - -#define POLREV_THRESHOLD 1000 /* minimum duration for polarity reversal detection (in ticks) */ -#define BAT_THRESHOLD 3 -#define BAT_DEBOUNCE 1000 /* compensate for battery voltage fluctuation (in ticks) */ - -/* Shortcuts */ -#define DAA_WRITE 1 -#define DAA_READ 0 -#define DAA_DIRECT_REQUEST(xbus,xpd,chipsel,writing,reg,dL) \ - xpp_register_request((xbus), (xpd), (chipsel), (writing), 0, (reg), 0, (dL), 0) - -#define VALID_CHIPSEL(x) (((chipsel) >= 0 && (chipsel) <= 7) || (chipsel) == ALL_CHANS) - -/*---------------- FXO Protocol Commands ----------------------------------*/ - -static /* 0x0F */ DECLARE_CMD(FXO, XPD_STATE, bool on); -static /* 0x0F */ DECLARE_CMD(FXO, RING, lineno_t chan, bool on); -static /* 0x0F */ DECLARE_CMD(FXO, RELAY_OUT, byte which, bool on); - -static bool fxo_packet_is_valid(xpacket_t *pack); -static void fxo_packet_dump(const char *msg, xpacket_t *pack); -static int proc_fxo_info_read(char *page, char **start, off_t off, int count, int *eof, void *data); -#ifdef WITH_METERING -static int proc_xpd_metering_read(char *page, char **start, off_t off, int count, int *eof, void *data); -#endif -static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data); -static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data); -static int handle_register_command(xpd_t *xpd, char *cmdline); - -#define PROC_REGISTER_FNAME "slics" -#define PROC_FXO_INFO_FNAME "fxo_info" -#ifdef WITH_METERING -#define PROC_METERING_FNAME "metering_read" -#endif - -#define DAA_REG_RING 0x05 -#define DAA_REG_METERING 0x11 /* 17 */ -#define DAA_REG_CURRENT 0x1C /* 28 */ -#define DAA_REG_VBAT 0x1D /* 29 */ - -#define POWER_DENIAL_CURRENT 3 -#define POWER_DENIAL_TIME 80 /* ticks */ - -struct FXO_priv_data { - struct proc_dir_entry *regfile; -#ifdef WITH_METERING - struct proc_dir_entry *meteringfile; -#endif - struct proc_dir_entry *fxo_info; - uint poll_counter; - signed char battery_voltage[CHANNELS_PERXPD]; - xpp_line_t battery; - ushort battery_debounce[CHANNELS_PERXPD]; - xpp_line_t polarity; - ushort polarity_counter[CHANNELS_PERXPD]; - ushort current_counter[CHANNELS_PERXPD]; - xpp_line_t ledstate[NUM_LEDS]; /* 0 - OFF, 1 - ON */ - xpp_line_t ledcontrol[NUM_LEDS]; /* 0 - OFF, 1 - ON */ - int led_counter[NUM_LEDS][CHANNELS_PERXPD]; - atomic_t ring_debounce[CHANNELS_PERXPD]; -#ifdef WITH_METERING - uint metering_count[CHANNELS_PERXPD]; - xpp_line_t metering_tone_state; -#endif -}; - -/* - * LED counter values: - * n>1 : BLINK every n'th tick - */ -#define LED_COUNTER(priv,pos,color) ((priv)->led_counter[color][pos]) -#define IS_BLINKING(priv,pos,color) (LED_COUNTER(priv,pos,color) > 0) -#define MARK_BLINK(priv,pos,color,t) ((priv)->led_counter[color][pos] = (t)) -#define MARK_OFF(priv,pos,color) do { BIT_CLR((priv)->ledcontrol[color],(pos)); MARK_BLINK((priv),(pos),(color),0); } while(0) -#define MARK_ON(priv,pos,color) do { BIT_SET((priv)->ledcontrol[color],(pos)); MARK_BLINK((priv),(pos),(color),0); } while(0) - -#define LED_BLINK_RING (1000/8) /* in ticks */ - -/*---------------- FXO: Static functions ----------------------------------*/ - -/* - * LED control is done via DAA register 0x20 - */ -static int do_led(xpd_t *xpd, lineno_t chan, byte which, bool on) -{ - int ret = 0; - struct FXO_priv_data *priv; - xbus_t *xbus; - - BUG_ON(!xpd); - xbus = xpd->xbus; - priv = xpd->priv; - which = which % NUM_LEDS; - if(IS_SET(xpd->digital_outputs, chan) || IS_SET(xpd->digital_inputs, chan)) - goto out; - if(chan == ALL_CHANS) { - priv->ledstate[which] = (on) ? ~0 : 0; - } else { - if(on) { - BIT_SET(priv->ledstate[which], chan); - } else { - BIT_CLR(priv->ledstate[which], chan); - } - } - LINE_DBG(LEDS, xpd, chan, "LED: which=%d -- %s\n", which, (on) ? "on" : "off"); - ret = DAA_DIRECT_REQUEST(xbus, xpd, chan, DAA_WRITE, 0x20, on); -out: - return ret; -} - -static void handle_fxo_leds(xpd_t *xpd) -{ - int i; - unsigned long flags; - const enum fxo_leds color = LED_GREEN; - unsigned int timer_count; - struct FXO_priv_data *priv; - - BUG_ON(!xpd); - spin_lock_irqsave(&xpd->lock, flags); - priv = xpd->priv; - timer_count = xpd->timer_count; - for_each_line(xpd, i) { - if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i)) - continue; - if(xpd->blink_mode || IS_BLINKING(priv,i,color)) { - int mod_value = LED_COUNTER(priv, i, color); - - if(!mod_value) - mod_value = DEFAULT_LED_PERIOD; /* safety value */ - // led state is toggled - if((timer_count % mod_value) == 0) { - LINE_DBG(LEDS, xpd, i, "ledstate=%s\n", (IS_SET(priv->ledstate[color], i))?"ON":"OFF"); - if(!IS_SET(priv->ledstate[color], i)) { - do_led(xpd, i, color, 1); - } else { - do_led(xpd, i, color, 0); - } - } - } else if(IS_SET(priv->ledcontrol[color], i) && !IS_SET(priv->ledstate[color], i)) { - do_led(xpd, i, color, 1); - } else if(!IS_SET(priv->ledcontrol[color], i) && IS_SET(priv->ledstate[color], i)) { - do_led(xpd, i, color, 0); - } - } - spin_unlock_irqrestore(&xpd->lock, flags); -} - -static void update_zap_ring(xpd_t *xpd, int pos, bool on) -{ - zt_rxsig_t rxsig; - - BUG_ON(!xpd); - if(on) { - BIT_CLR(xpd->cid_on, pos); - rxsig = ZT_RXSIG_RING; - } else { - BIT_SET(xpd->cid_on, pos); - rxsig = ZT_RXSIG_OFFHOOK; - } - pcm_recompute(xpd, 0); - /* - * We should not spinlock before calling zt_hooksig() as - * it may call back into our xpp_hooksig() and cause - * a nested spinlock scenario - */ - if(SPAN_REGISTERED(xpd)) - zt_hooksig(&xpd->chans[pos], rxsig); -} - -static void mark_ring(xpd_t *xpd, lineno_t pos, bool on, bool update_zap) -{ - struct FXO_priv_data *priv; - - priv = xpd->priv; - BUG_ON(!priv); - atomic_set(&priv->ring_debounce[pos], 0); /* Stop debouncing */ - /* - * We don't want to check battery during ringing - * due to voltage fluctuations. - */ - priv->battery_debounce[pos] = 0; - if(on && !xpd->ringing[pos]) { - LINE_DBG(SIGNAL, xpd, pos, "START\n"); - xpd->ringing[pos] = 1; - MARK_BLINK(priv, pos, LED_GREEN, LED_BLINK_RING); - if(update_zap) - update_zap_ring(xpd, pos, on); - } else if(!on && xpd->ringing[pos]) { - LINE_DBG(SIGNAL, xpd, pos, "STOP\n"); - xpd->ringing[pos] = 0; - if(IS_BLINKING(priv, pos, LED_GREEN)) - MARK_BLINK(priv, pos, LED_GREEN, 0); - if(update_zap) - update_zap_ring(xpd, pos, on); - } -} - -static int do_sethook(xpd_t *xpd, int pos, bool to_offhook) -{ - unsigned long flags; - xbus_t *xbus; - struct FXO_priv_data *priv; - int ret = 0; - byte value; - - BUG_ON(!xpd); - BUG_ON(xpd->direction == TO_PHONE); // We can SETHOOK state only on PSTN - xbus = xpd->xbus; - priv = xpd->priv; - BUG_ON(!priv); - if(!IS_SET(priv->battery, pos)) { - LINE_DBG(SIGNAL, xpd, pos, "WARNING: called while battery is off\n"); - } - spin_lock_irqsave(&xpd->lock, flags); - mark_ring(xpd, pos, 0, 0); // No more rings - value = (to_offhook) ? 0x09 : 0x08; /* Bit 3 is for CID */ - LINE_DBG(SIGNAL, xpd, pos, "SETHOOK: value=0x%02X %s\n", value, (to_offhook)?"OFFHOOK":"ONHOOK"); - if(to_offhook) - MARK_ON(priv, pos, LED_GREEN); - else - MARK_OFF(priv, pos, LED_GREEN); - ret = DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, DAA_REG_RING, value); - if(to_offhook) { - BIT_SET(xpd->offhook, pos); - } else { - BIT_CLR(xpd->offhook, pos); - BIT_CLR(xpd->cid_on, pos); - } -#ifdef WITH_METERING - priv->metering_count[pos] = 0; - priv->metering_tone_state = 0L; - DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, DAA_REG_METERING, 0x2D); -#endif - spin_unlock_irqrestore(&xpd->lock, flags); - return ret; -} - -/*---------------- FXO: Methods -------------------------------------------*/ - -static xpd_t *FXO_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table, byte subtype, byte revision) -{ - xpd_t *xpd = NULL; - int channels; - - if(subtype == 2) - channels = min(2, CHANNELS_PERXPD); - else - channels = min(8, CHANNELS_PERXPD); - xpd = xpd_alloc(sizeof(struct FXO_priv_data), proto_table, channels); - if(!xpd) - return NULL; - xpd->direction = TO_PSTN; - xpd->revision = revision; - xpd->type_name = proto_table->name; - return xpd; -} - -static void clean_proc(xbus_t *xbus, xpd_t *xpd) -{ - struct FXO_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - XPD_DBG(PROC, xpd, "\n"); -#ifdef CONFIG_PROC_FS - if(priv->regfile) { - XPD_DBG(PROC, xpd, "Removing xpd DAA file\n"); - remove_proc_entry(PROC_REGISTER_FNAME, xpd->proc_xpd_dir); - priv->regfile->data = NULL; - } -#ifdef WITH_METERING - if(priv->meteringfile) { - XPD_DBG(PROC, xpd, "Removing xpd metering tone file\n"); - priv->meteringfile->data = NULL; - remove_proc_entry(PROC_METERING_FNAME, xpd->proc_xpd_dir); - priv->meteringfile = NULL; - } -#endif - if(priv->fxo_info) { - XPD_DBG(PROC, xpd, "Removing xpd FXO_INFO file\n"); - remove_proc_entry(PROC_FXO_INFO_FNAME, xpd->proc_xpd_dir); - priv->fxo_info = NULL; - } -#endif -} - -static int FXO_card_init(xbus_t *xbus, xpd_t *xpd) -{ - struct FXO_priv_data *priv; - int ret = 0; - int i; - - BUG_ON(!xpd); - priv = xpd->priv; -#ifdef CONFIG_PROC_FS - XPD_DBG(PROC, xpd, "Creating FXO_INFO file\n"); - priv->fxo_info = create_proc_read_entry(PROC_FXO_INFO_FNAME, 0444, xpd->proc_xpd_dir, proc_fxo_info_read, xpd); - if(!priv->fxo_info) { - XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_FXO_INFO_FNAME); - ret = -ENOENT; - goto err; - } - priv->fxo_info->owner = THIS_MODULE; -#ifdef WITH_METERING - XPD_DBG(PROC, xpd, "Creating Metering tone file\n"); - priv->meteringfile = create_proc_read_entry(PROC_METERING_FNAME, 0444, xpd->proc_xpd_dir, - proc_xpd_metering_read, xpd); - if(!priv->meteringfile) { - XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_METERING_FNAME); - ret = -ENOENT; - goto err; - } - priv->meteringfile->owner = THIS_MODULE; -#endif - XPD_DBG(PROC, xpd, "Creating DAAs file\n"); - priv->regfile = create_proc_entry(PROC_REGISTER_FNAME, 0644, xpd->proc_xpd_dir); - if(!priv->regfile) { - XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_REGISTER_FNAME); - ret = -ENOENT; - goto err; - } - priv->regfile->owner = THIS_MODULE; - priv->regfile->write_proc = proc_xpd_register_write; - priv->regfile->read_proc = proc_xpd_register_read; - priv->regfile->data = xpd; -#endif - ret = run_initialize_registers(xpd); - if(ret < 0) - goto err; - // Hanghup all lines - for_each_line(xpd, i) { - do_sethook(xpd, i, 0); - } - XPD_DBG(GENERAL, xpd, "done\n"); - for_each_line(xpd, i) { - do_led(xpd, i, LED_GREEN, 0); - } - for_each_line(xpd, i) { - do_led(xpd, i, LED_GREEN, 1); - msleep(50); - } - for_each_line(xpd, i) { - do_led(xpd, i, LED_GREEN, 0); - msleep(50); - } - pcm_recompute(xpd, 0); - return 0; -err: - clean_proc(xbus, xpd); - XPD_ERR(xpd, "Failed initializing registers (%d)\n", ret); - return ret; -} - -static int FXO_card_remove(xbus_t *xbus, xpd_t *xpd) -{ - struct FXO_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - XPD_DBG(GENERAL, xpd, "\n"); - clean_proc(xbus, xpd); - return 0; -} - -static int FXO_card_zaptel_preregistration(xpd_t *xpd, bool on) -{ - xbus_t *xbus; - struct FXO_priv_data *priv; - int i; - - BUG_ON(!xpd); - xbus = xpd->xbus; - BUG_ON(!xbus); - priv = xpd->priv; - BUG_ON(!priv); - XPD_DBG(GENERAL, xpd, "%s\n", (on)?"ON":"OFF"); - for_each_line(xpd, i) { - struct zt_chan *cur_chan = &xpd->chans[i]; - - XPD_DBG(GENERAL, xpd, "setting FXO channel %d\n", i); - snprintf(cur_chan->name, MAX_CHANNAME, "XPP_FXO/%02d/%1d%1d/%d", - xbus->num, xpd->addr.unit, xpd->addr.subunit, i); - cur_chan->chanpos = i + 1; - cur_chan->pvt = xpd; - cur_chan->sigcap = FXO_DEFAULT_SIGCAP; - } - for_each_line(xpd, i) { - MARK_ON(priv, i, LED_GREEN); - msleep(4); - } - return 0; -} - -static int FXO_card_zaptel_postregistration(xpd_t *xpd, bool on) -{ - xbus_t *xbus; - struct FXO_priv_data *priv; - int i; - - BUG_ON(!xpd); - xbus = xpd->xbus; - BUG_ON(!xbus); - priv = xpd->priv; - BUG_ON(!priv); - XPD_DBG(GENERAL, xpd, "%s\n", (on)?"ON":"OFF"); - for_each_line(xpd, i) { - MARK_OFF(priv, i, LED_GREEN); - msleep(2); - // MARK_OFF(priv, i, LED_RED); - msleep(2); - } - return 0; -} - -static int FXO_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig) -{ - struct FXO_priv_data *priv; - - priv = xpd->priv; - BUG_ON(!priv); - LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig)); - BUG_ON(xpd->direction != TO_PSTN); - /* XXX Enable hooksig for FXO XXX */ - switch(txsig) { - case ZT_TXSIG_START: - break; - case ZT_TXSIG_OFFHOOK: - do_sethook(xpd, pos, 1); - break; - case ZT_TXSIG_ONHOOK: - do_sethook(xpd, pos, 0); - break; - default: - XPD_NOTICE(xpd, "Can't set tx state to %s (%d)\n", - txsig2str(txsig), txsig); - return -EINVAL; - } - pcm_recompute(xpd, 0); - return 0; -} - -static int FXO_card_open(xpd_t *xpd, lineno_t chan) -{ - struct FXO_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - /* - * We pretend to have battery. If this is really the case - * than next calls to update_battery_status() won't change it. - * If we don't have battery, than on the next calls to - * update_battery_status() a battery_debounce[] cycle would start. - * Than, if no-battery is persistent, asterisk would be notified. - */ - BIT_SET(priv->battery, chan); - return 0; -} - -static void poll_battery(xbus_t *xbus, xpd_t *xpd) -{ - int i; - - for_each_line(xpd, i) { - DAA_DIRECT_REQUEST(xbus, xpd, i, DAA_READ, DAA_REG_VBAT, 0); - } -} - -static void poll_current(xbus_t *xbus, xpd_t *xpd) -{ - int i; - - for_each_line(xpd, i) { - if (IS_SET(xpd->offhook, i)) - DAA_DIRECT_REQUEST(xbus, xpd, i, DAA_READ, DAA_REG_CURRENT, 0); - } -} - -#ifdef WITH_METERING -static void poll_metering(xbus_t *xbus, xpd_t *xpd) -{ - int i; - - for_each_line(xpd, i) { - if (IS_SET(xpd->offhook, i)) - DAA_DIRECT_REQUEST(xbus, xpd, i, DAA_READ, DAA_REG_METERING, 0); - } -} -#endif - -static void handle_fxo_ring(xpd_t *xpd) -{ - struct FXO_priv_data *priv; - int i; - - priv = xpd->priv; - for_each_line(xpd, i) { - if(atomic_read(&priv->ring_debounce[i]) > 0) { - /* Maybe start ring */ - if(atomic_dec_and_test(&priv->ring_debounce[i])) - mark_ring(xpd, i, 1, 1); - } else if (atomic_read(&priv->ring_debounce[i]) < 0) { - /* Maybe stop ring */ - if(atomic_inc_and_test(&priv->ring_debounce[i])) - mark_ring(xpd, i, 0, 1); - } - } -} - -static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd) -{ - struct FXO_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - if(poll_battery_interval != 0 && (priv->poll_counter % poll_battery_interval) == 0) - poll_battery(xbus, xpd); - if(poll_power_denial_interval != 0 && (priv->poll_counter % poll_power_denial_interval) == 0) - poll_current(xbus, xpd); -#ifdef WITH_METERING - if(poll_metering_interval != 0 && (priv->poll_counter % poll_metering_interval) == 0) - poll_metering(xbus, xpd); -#endif - handle_fxo_leds(xpd); - handle_fxo_ring(xpd); - priv->poll_counter++; - return 0; -} - -/* FIXME: based on data from from wctdm.h */ -#include -/* - * The first register is the ACIM, the other are coefficient registers. - * We define the array size explicitly to track possible inconsistencies - * if the struct is modified. - */ -static const char echotune_regs[sizeof(struct wctdm_echo_coefs)] = {30, 45, 46, 47, 48, 49, 50, 51, 52}; - -static int FXO_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg) -{ - int i,ret; - unsigned char echotune_data[ARRAY_SIZE(echotune_regs)]; - - BUG_ON(!xpd); - if(!TRANSPORT_RUNNING(xpd->xbus)) - return -ENODEV; - switch (cmd) { - case WCTDM_SET_ECHOTUNE: - XPD_DBG(GENERAL, xpd, "-- Setting echo registers: \n"); - /* first off: check if this span is fxs. If not: -EINVALID */ - if (copy_from_user(&echotune_data, (void __user *)arg, sizeof(echotune_data))) - return -EFAULT; - - for (i = 0; i < ARRAY_SIZE(echotune_regs); i++) { - XPD_DBG(REGS, xpd, "Reg=0x%02X, data=0x%02X\n", echotune_regs[i], echotune_data[i]); - ret = DAA_DIRECT_REQUEST(xpd->xbus, xpd, pos, DAA_WRITE, echotune_regs[i], echotune_data[i]); - if (ret < 0) { - LINE_NOTICE(xpd, pos, "Couldn't write %0x02X to register %0x02X\n", - echotune_data[i], echotune_regs[i]); - return ret; - } - msleep(1); - } - - XPD_DBG(GENERAL, xpd, "-- Set echo registers successfully\n"); - break; - case ZT_TONEDETECT: - /* - * Asterisk call all span types with this (FXS specific) - * call. Silently ignore it. - */ - LINE_DBG(GENERAL, xpd, pos, - "ZT_TONEDETECT (FXO: NOTIMPLEMENTED)\n"); - return -ENOTTY; - default: - report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd); - return -ENOTTY; - } - return 0; -} - -/*---------------- FXO: HOST COMMANDS -------------------------------------*/ - -/* 0x0F */ HOSTCMD(FXO, XPD_STATE, bool on) -{ - int ret = 0; - struct FXO_priv_data *priv; - - BUG_ON(!xbus); - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off"); - return ret; -} - -/* 0x0F */ HOSTCMD(FXO, RING, lineno_t chan, bool on) -{ - BUG_ON(!xbus); - BUG_ON(!xpd); - LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on) ? "on" : "off"); - return DAA_DIRECT_REQUEST(xbus, xpd, chan, DAA_WRITE, 0x40, (on)?0x04:0x01); -} - -/* 0x0F */ HOSTCMD(FXO, RELAY_OUT, byte which, bool on) -{ - return -ENOSYS; -} - -/*---------------- FXO: Astribank Reply Handlers --------------------------*/ - -HANDLER_DEF(FXO, SIG_CHANGED) -{ - xpp_line_t sig_status = RPACKET_FIELD(pack, FXO, SIG_CHANGED, sig_status); - xpp_line_t sig_toggles = RPACKET_FIELD(pack, FXO, SIG_CHANGED, sig_toggles); - unsigned long flags; - int i; - struct FXO_priv_data *priv; - - if(!xpd) { - notify_bad_xpd(__FUNCTION__, xbus, XPACKET_ADDR(pack), cmd->name); - return -EPROTO; - } - priv = xpd->priv; - BUG_ON(!priv); - XPD_DBG(SIGNAL, xpd, "(PSTN) sig_toggles=0x%04X sig_status=0x%04X\n", sig_toggles, sig_status); - spin_lock_irqsave(&xpd->lock, flags); - for_each_line(xpd, i) { - int debounce; - - if(IS_SET(sig_toggles, i)) { - if(!IS_SET(priv->battery, i)) { - LINE_DBG(SIGNAL, xpd, i, "SIG_CHANGED while battery is off.\n"); - // FIXME: allow dialing without battery polling... - // continue; - } - /* First report false ring alarms */ - debounce = atomic_read(&priv->ring_debounce[i]); - if(debounce) - LINE_NOTICE(xpd, i, "debounced false ring (only %d ticks)\n", debounce); - /* - * Now set a new ring alarm. - * It will be checked in handle_fxo_ring() - */ - debounce = (IS_SET(sig_status, i)) ? ring_debounce : -ring_debounce; - atomic_set(&priv->ring_debounce[i], debounce); - } - } - spin_unlock_irqrestore(&xpd->lock, flags); - return 0; -} - -#ifndef ZT_GET_PARAMS_V1 -#define zt_alarm_channel(a,b) zt_qevent_lock(a,( (b)==ZT_ALARM_NONE )? \ - ZT_EVENT_NOALARM : ZT_EVENT_ALARM) -#endif -static void update_battery_status(xpd_t *xpd, byte data_low, lineno_t chipsel) -{ - struct FXO_priv_data *priv; - byte bat = abs((signed char)data_low); - byte pol = IS_SET(data_low, 7); - int msec; - - - priv = xpd->priv; - BUG_ON(!priv); - priv->battery_voltage[chipsel] = data_low; - if(bat < BAT_THRESHOLD) { - /* - * Check for battery voltage fluctuations - */ - if(IS_SET(priv->battery, chipsel)) { - int milliseconds; - - milliseconds = priv->battery_debounce[chipsel]++ * - poll_battery_interval; - if(milliseconds > BAT_DEBOUNCE) { - LINE_DBG(SIGNAL, xpd, chipsel, "BATTERY OFF voltage=%d\n", bat); - BIT_CLR(priv->battery, chipsel); - if(SPAN_REGISTERED(xpd)) - zt_alarm_channel(&xpd->chans[chipsel], ZT_ALARM_RED); - } - - } - } else { - priv->battery_debounce[chipsel] = 0; - if(!IS_SET(priv->battery, chipsel)) { - LINE_DBG(SIGNAL, xpd, chipsel, "BATTERY ON voltage=%d\n", bat); - BIT_SET(priv->battery, chipsel); - if(SPAN_REGISTERED(xpd)) - zt_alarm_channel(&xpd->chans[chipsel], ZT_ALARM_NONE); - } - } - /* - * Handle reverse polarity - */ - if(IS_SET(priv->polarity, chipsel) == pol) { - /* same, same, nothing to see here, move on */ - priv->polarity_counter[chipsel] = 0; - return; - } - /* - * Track polarity reversals and debounce spikes. - * Only reversals with long duration count. - */ - msec = priv->polarity_counter[chipsel]++ * poll_battery_interval; - if (msec >= POLREV_THRESHOLD) { - LINE_DBG(SIGNAL, xpd, chipsel, "Polarity is %s\n", - (pol)?"Positive":"Negative"); - priv->polarity_counter[chipsel] = 0; - if (pol) - BIT_SET(priv->polarity, chipsel); - else - BIT_CLR(priv->polarity, chipsel); - /* polarity reversal during offhook should be reported to zaptel */ - if(IS_SET(xpd->offhook, chipsel)) { - /* Inform Zaptel */ - LINE_DBG(SIGNAL, xpd, chipsel, "Send ZT_EVENT_POLARITY\n"); - zt_qevent_lock(&xpd->chans[chipsel], ZT_EVENT_POLARITY); -#if 0 - /* - * These two lines hangup the channel (by sending a message to - * the firmware), and inform Zaptel that the line has been hung-up. - * They are not needed if Asterisk does the hangup after receiving - * a notification from Zaptel (which is sent by the above zt_qevent_lock(). - * Asterisk does that if it has "hanguponpolarityswitch=1" in zapata.conf. - */ - do_sethook(xpd, chipsel, 0); - update_line_status(xpd, chipsel, 0); - pcm_recompute(xpd, 0); -#endif - } - } -} - -static void update_power_denial(xpd_t *xpd, byte data_low, lineno_t chipsel) -{ - struct FXO_priv_data *priv; - - priv = xpd->priv; - BUG_ON(!priv); - if (IS_SET(xpd->offhook, chipsel) && data_low < POWER_DENIAL_CURRENT) { - /* Current dropped */ - priv->current_counter[chipsel]++; - if (priv->current_counter[chipsel] * poll_battery_interval >= POWER_DENIAL_TIME) { - LINE_DBG(SIGNAL, xpd, chipsel, "Power Denial Hangup\n"); - priv->current_counter[chipsel] = 0; - do_sethook(xpd, chipsel, 0); - update_line_status(xpd, chipsel, 0); - pcm_recompute(xpd, 0); - } - } else - priv->current_counter[chipsel] = 0; -} - -#ifdef WITH_METERING -#define BTD_BIT BIT(0) - -static void update_metering_state(xpd_t *xpd, byte data_low, lineno_t chipsel) -{ - struct FXO_priv_data *priv; - bool metering_tone = data_low & BTD_BIT; - bool old_metering_tone; - - priv = xpd->priv; - BUG_ON(!priv); - old_metering_tone = IS_SET(priv->metering_tone_state, chipsel); - LINE_DBG(SIGNAL, xpd, chipsel, "METERING: %s [dL=0x%X] (%d)\n", - (metering_tone) ? "ON" : "OFF", - data_low, priv->metering_count[chipsel]); - if(metering_tone && !old_metering_tone) { - /* Rising edge */ - priv->metering_count[chipsel]++; - BIT_SET(priv->metering_tone_state, chipsel); - } else if(!metering_tone && old_metering_tone) - BIT_CLR(priv->metering_tone_state, chipsel); - if(metering_tone) { - /* Clear the BTD bit */ - data_low &= ~BTD_BIT; - DAA_DIRECT_REQUEST(xpd->xbus, xpd, chipsel, DAA_WRITE, DAA_REG_METERING, data_low); - } -} -#endif - -static int FXO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) -{ - struct FXO_priv_data *priv; - lineno_t chipsel; - - priv = xpd->priv; - BUG_ON(!priv); - chipsel = REG_FIELD(info, chipsel); - switch(REG_FIELD(info, regnum)) { - case DAA_REG_VBAT: - update_battery_status(xpd, REG_FIELD(info, data_low), chipsel); - break; - case DAA_REG_CURRENT: - update_power_denial(xpd, REG_FIELD(info, data_low), chipsel); - break; -#ifdef WITH_METERING - case DAA_REG_METERING: - update_metering_state(xpd, REG_FIELD(info, data_low), chipsel); - break; -#endif - } - LINE_DBG(REGS, xpd, chipsel, "%c reg_num=0x%X, dataL=0x%X dataH=0x%X\n", - ((info->bytes == 3)?'I':'D'), - REG_FIELD(info, regnum), - REG_FIELD(info, data_low), - REG_FIELD(info, data_high)); - /* Update /proc info only if reply relate to the last slic read request */ - if( - REG_FIELD(&xpd->requested_reply, regnum) == REG_FIELD(info, regnum) && - REG_FIELD(&xpd->requested_reply, do_subreg) == REG_FIELD(info, do_subreg) && - REG_FIELD(&xpd->requested_reply, subreg) == REG_FIELD(info, subreg)) { - xpd->last_reply = *info; - } - return 0; -} - - -static xproto_table_t PROTO_TABLE(FXO) = { - .owner = THIS_MODULE, - .entries = { - /* Prototable Card Opcode */ - XENTRY( FXO, FXO, SIG_CHANGED ), - }, - .name = "FXO", - .type = XPD_TYPE_FXO, - .xops = { - .card_new = FXO_card_new, - .card_init = FXO_card_init, - .card_remove = FXO_card_remove, - .card_zaptel_preregistration = FXO_card_zaptel_preregistration, - .card_zaptel_postregistration = FXO_card_zaptel_postregistration, - .card_hooksig = FXO_card_hooksig, - .card_tick = FXO_card_tick, - .card_pcm_fromspan = generic_card_pcm_fromspan, - .card_pcm_tospan = generic_card_pcm_tospan, - .card_ioctl = FXO_card_ioctl, - .card_open = FXO_card_open, - .card_register_reply = FXO_card_register_reply, - - .RING = XPROTO_CALLER(FXO, RING), - .RELAY_OUT = XPROTO_CALLER(FXO, RELAY_OUT), - .XPD_STATE = XPROTO_CALLER(FXO, XPD_STATE), - }, - .packet_is_valid = fxo_packet_is_valid, - .packet_dump = fxo_packet_dump, -}; - -static bool fxo_packet_is_valid(xpacket_t *pack) -{ - const xproto_entry_t *xe; - - //DBG(GENERAL, "\n"); - xe = xproto_card_entry(&PROTO_TABLE(FXO), XPACKET_OP(pack)); - return xe != NULL; -} - -static void fxo_packet_dump(const char *msg, xpacket_t *pack) -{ - DBG(GENERAL, "%s\n", msg); -} - -/*------------------------- DAA Handling --------------------------*/ - -static int proc_fxo_info_read(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - unsigned long flags; - xpd_t *xpd = data; - struct FXO_priv_data *priv; - int i; - - if(!xpd) - return -ENODEV; - spin_lock_irqsave(&xpd->lock, flags); - priv = xpd->priv; - BUG_ON(!priv); - len += sprintf(page + len, "\t%-17s: ", "Channel"); - for_each_line(xpd, i) { - if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) - len += sprintf(page + len, "%3d ", i % 10); - } - len += sprintf(page + len, "\n\t%-17s: ", "ledstate"); - for_each_line(xpd, i) { - if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) - len += sprintf(page + len, "%3d ", IS_SET(priv->ledstate[LED_GREEN], i)); - } - len += sprintf(page + len, "\n\t%-17s: ", "blinking"); - for_each_line(xpd, i) { - if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) - len += sprintf(page + len, "%3d ", IS_BLINKING(priv,i,LED_GREEN)); - } - len += sprintf(page + len, "\n\t%-17s: ", "battery"); - for_each_line(xpd, i) { - len += sprintf(page + len, "%3d ", IS_SET(priv->battery, i)); - } - len += sprintf(page + len, "\n\t%-17s: ", "polarity"); - for_each_line(xpd, i) { - len += sprintf(page + len, "%3d ", IS_SET(priv->polarity, i)); - } - len += sprintf(page + len, "\n\t%-17s: ", "polarity_counter"); - for_each_line(xpd, i) { - len += sprintf(page + len, "%3d ", priv->polarity_counter[i]); - } - len += sprintf(page + len, "\n\t%-17s: ", "battery_voltage"); - for_each_line(xpd, i) { - len += sprintf(page + len, "%3d ", priv->battery_voltage[i]); - } -#ifdef WITH_METERING - len += sprintf(page + len, "\n\t%-17s: ", "metering"); - for_each_line(xpd, i) { - len += sprintf(page + len, "%3d ", priv->metering_count[i]); - } -#endif - len += sprintf(page + len, "\n"); - spin_unlock_irqrestore(&xpd->lock, flags); - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; -} - -/* - * - * Direct/Indirect - * | - * | Reg# - * | | - * | | Data (only in Write) - * | | | - * | | +-+-+ - * v v v v - * FF WD 06 01 05 - * ^ ^ - * | | - * | Write/Read - * | - * Chan# - * - */ -static int handle_register_command(xpd_t *xpd, char *cmdline) -{ - unsigned chipsel; - unsigned data_low = 0; - char op; /* [W]rite, [R]ead */ - char reg_type; /* [D]irect */ - int reg_num; - int elements; - bool writing; - char *p; - reg_cmd_t regcmd; - xbus_t *xbus; - int ret = -EINVAL; - - BUG_ON(!xpd); - xbus = xpd->xbus; - if((p = strchr(cmdline, '#')) != NULL) /* Truncate comments */ - *p = '\0'; - if((p = strchr(cmdline, ';')) != NULL) /* Truncate comments */ - *p = '\0'; - for(p = cmdline; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */ - ; - if(*p == '\0') - return 0; - - if(!XBUS_GET(xbus)) { - XBUS_DBG(GENERAL, xbus, "Dropped packet. Is shutting down.\n"); - return -EBUSY; - } - elements = sscanf(cmdline, "%d %c%c %x %x", - &chipsel, - &op, ®_type, ®_num, - &data_low); - XPD_DBG(PROC, xpd, "'%s': %d %c%c %02X %02X\n", cmdline, chipsel, op, reg_type, reg_num, data_low); - if(elements < 4) { // At least: chipsel, op, reg_type, reg_num - ERR("Not enough arguments: (%d args) '%s'\n", elements, cmdline); - goto out; - } - if(!VALID_CHIPSEL(chipsel)) { - ERR("Bad chipsel number: %d\n", chipsel); - goto out; - } - REG_FIELD(®cmd, chipsel) = chipsel; - REG_FIELD(®cmd, do_subreg) = 0; - switch(op) { - case 'W': - writing = 1; - break; - case 'R': - writing = 0; - break; - default: - ERR("Unkown operation type '%c'\n", op); - goto out; - } - switch(reg_type) { - case 'D': - REG_FIELD(®cmd, regnum) = reg_num; - REG_FIELD(®cmd, subreg) = 0; - break; - default: - ERR("Unkown register type '%c'\n", reg_type); - goto out; - } - if( - (op == 'W' && reg_type == 'D' && elements != 5) || - (op == 'R' && reg_type == 'D' && elements != 4) - ) { - ERR("%s: '%s' (%d elements): %d %c%c %02X %02X\n", __FUNCTION__, - cmdline, elements, - chipsel, op, reg_type, reg_num, data_low); - goto out; - } - regcmd.bytes = sizeof(regcmd) - 1; - REG_FIELD(®cmd, data_low) = data_low; - REG_FIELD(®cmd, data_high) = 0; - REG_FIELD(®cmd, read_request) = writing; - xpd->requested_reply = regcmd; - if(print_dbg) - dump_reg_cmd("FXO", ®cmd, 1); - ret = DAA_DIRECT_REQUEST(xpd->xbus, xpd, REG_FIELD(®cmd, chipsel), writing, REG_FIELD(®cmd, regnum), REG_FIELD(®cmd, data_low)); -out: - XBUS_PUT(xbus); - return ret; -} - -static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data) -{ - xpd_t *xpd = data; - char buf[MAX_PROC_WRITE]; - char *p; - int i; - int ret; - - if(!xpd) - return -ENODEV; - for(i = 0; i < count; /* noop */) { - for(p = buf; p < buf + MAX_PROC_WRITE; p++) { /* read a line */ - if(i >= count) - break; - if(get_user(*p, buffer + i)) - return -EFAULT; - i++; - if(*p == '\n' || *p == '\r') /* whatever */ - break; - } - if(p >= buf + MAX_PROC_WRITE) - return -E2BIG; - *p = '\0'; - ret = handle_register_command(xpd, buf); - if(ret < 0) - return ret; - msleep(1); - } - return count; -} - -static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - unsigned long flags; - xpd_t *xpd = data; - reg_cmd_t *info; - byte regnum; - - if(!xpd) - return -ENODEV; - spin_lock_irqsave(&xpd->lock, flags); - info = &xpd->last_reply; - regnum = REG_FIELD(info, regnum); - len += sprintf(page + len, "# Writing bad data into this file may damage your hardware!\n"); - len += sprintf(page + len, "# Consult firmware docs first\n"); - len += sprintf(page + len, "#\n"); - len += sprintf(page + len, "#CH\tD/I\tReg.\tDL\n"); - len += sprintf(page + len, "%2d\tRD\t%02X\t%02X\n", - REG_FIELD(info, chipsel), - regnum, REG_FIELD(info, data_low)); - spin_unlock_irqrestore(&xpd->lock, flags); - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; -} - -#ifdef WITH_METERING -static int proc_xpd_metering_read(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - unsigned long flags; - xpd_t *xpd = data; - struct FXO_priv_data *priv; - int i; - - if(!xpd) - return -ENODEV; - priv = xpd->priv; - BUG_ON(!priv); - spin_lock_irqsave(&xpd->lock, flags); - len += sprintf(page + len, "# Chan\tMeter (since last read)\n"); - for_each_line(xpd, i) { - len += sprintf(page + len, "%d\t%d\n", - i, priv->metering_count[i]); - } - spin_unlock_irqrestore(&xpd->lock, flags); - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - /* Zero meters */ - for_each_line(xpd, i) - priv->metering_count[i] = 0; - return len; -} -#endif - -int __init card_fxo_startup(void) -{ - if(ring_debounce <= 0) { - ERR("ring_debounce=%d. Must be positive number of ticks\n", ring_debounce); - return -EINVAL; - } - INFO("revision %s\n", XPP_VERSION); -#ifdef WITH_METERING - INFO("FEATURE: WITH METERING Detection\n"); -#else - INFO("FEATURE: NO METERING Detection\n"); -#endif - xproto_register(&PROTO_TABLE(FXO)); - return 0; -} - -void __exit card_fxo_cleanup(void) -{ - xproto_unregister(&PROTO_TABLE(FXO)); -} - -MODULE_DESCRIPTION("XPP FXO Card Driver"); -MODULE_AUTHOR("Oron Peled "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(XPP_VERSION); -MODULE_ALIAS_XPD(XPD_TYPE_FXO); - -module_init(card_fxo_startup); -module_exit(card_fxo_cleanup); diff --git a/xpp/card_fxo.h b/xpp/card_fxo.h deleted file mode 100644 index 4d0bd25..0000000 --- a/xpp/card_fxo.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef CARD_FXO_H -#define CARD_FXO_H -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "xpd.h" - -enum fxo_opcodes { - XPROTO_NAME(FXO, SIG_CHANGED) = 0x06, -/**/ - XPROTO_NAME(FXO, DAA_WRITE) = 0x0F, /* Write to DAA */ - XPROTO_NAME(FXO, XPD_STATE) = 0x0F, /* Write to DAA */ - XPROTO_NAME(FXO, CHAN_CID) = 0x0F, /* Write to DAA */ - XPROTO_NAME(FXO, RING) = 0x0F, /* Write to DAA */ - XPROTO_NAME(FXO, LED) = 0x0F, /* Write to DAA */ - XPROTO_NAME(FXO, RELAY_OUT) = 0x0F, /* Write to DAA */ -}; - - -DEF_RPACKET_DATA(FXO, SIG_CHANGED, - byte type; /* unused -- we have it from DEV_DESC */ - xpp_line_t sig_status; /* channels: lsb=1, msb=8 */ - xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */ - ); - -#endif /* CARD_FXO_H */ diff --git a/xpp/card_fxs.c b/xpp/card_fxs.c deleted file mode 100644 index f2251e0..0000000 --- a/xpp/card_fxs.c +++ /dev/null @@ -1,1620 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include "xpd.h" -#include "xproto.h" -#include "xpp_zap.h" -#include "card_fxo.h" -#include "zap_debug.h" -#include "xbus-core.h" - -static const char rcsid[] = "$Id$"; - -DEF_PARM(int, print_dbg, 0, 0644, "Print DBG statements"); /* must be before zap_debug.h */ -DEF_PARM(uint, poll_digital_inputs, 1000, 0644, "Poll Digital Inputs"); -DEF_PARM_BOOL(reversepolarity, 0, 0644, "Reverse Line Polarity"); -DEF_PARM_BOOL(vmwineon, 0, 0644, "Indicate voicemail to a neon lamp"); -DEF_PARM_BOOL(dtmf_detection, 0, 0644, "Do DTMF detection in hardware"); - -#ifdef ZT_VMWI -DEF_PARM_BOOL(vmwi_ioctl, 0, 0644, "Asterisk support VMWI notification via ioctl"); -#else -#define vmwi_ioctl 0 /* not supported */ -#endif - -/* Signaling is opposite (fxo signalling for fxs card) */ -#if 1 -#define FXS_DEFAULT_SIGCAP (ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS) -#else -#define FXS_DEFAULT_SIGCAP (ZT_SIG_SF | ZT_SIG_EM) -#endif - -#define LINES_DIGI_OUT 2 -#define LINES_DIGI_INP 4 - -enum fxs_leds { - LED_GREEN, - LED_RED, - OUTPUT_RELAY, -}; - -#define NUM_LEDS 2 - -/* Shortcuts */ -#define SLIC_WRITE 1 -#define SLIC_READ 0 -#define SLIC_DIRECT_REQUEST(xbus,xpd,chipsel,writing,reg,dL) \ - xpp_register_request((xbus), (xpd), (chipsel), (writing), 0, (reg), 0, (dL), 0) -#define SLIC_INDIRECT_REQUEST(xbus,xpd,chipsel,writing,reg,dL,dH) \ - xpp_register_request((xbus), (xpd), (chipsel), (writing), 1, 0x1E, (reg), (dL), (dH)) - -#define VALID_CHIPSEL(x) (((chipsel) >= 0 && (chipsel) <= 7) || (chipsel) == ALL_CHANS) - -/* Values of SLIC linefeed control register (0x40) */ -enum fxs_state { - FXS_LINE_OPEN = 0x00, /* Open */ - FXS_LINE_ACTIVE = 0x01, /* Forward active */ - FXS_LINE_OHTRANS = 0x02, /* Forward on-hook transmission */ - FXS_LINE_TIPOPEN = 0x03, /* TIP open */ - FXS_LINE_RING = 0x04, /* Ringing */ - FXS_LINE_REV_ACTIVE = 0x05, /* Reverse active */ - FXS_LINE_REV_OHTRANS = 0x06, /* Reverse on-hook transmission */ - FXS_LINE_RING_OPEN = 0x07 /* RING open */ -}; - -#define FXS_LINE_POL_ACTIVE ((reversepolarity) ? FXS_LINE_REV_ACTIVE : FXS_LINE_ACTIVE) -#define FXS_LINE_POL_OHTRANS ((reversepolarity) ? FXS_LINE_REV_OHTRANS : FXS_LINE_OHTRANS) - -/* - * DTMF detection - */ -#define SLIC_REG_DTMF 0x18 /* 24 */ -#define SLIC_REG_VOLTAGE 0x42 /* 66 */ - -/*---------------- FXS Protocol Commands ----------------------------------*/ - -static /* 0x0F */ DECLARE_CMD(FXS, XPD_STATE, bool on); -static /* 0x0F */ DECLARE_CMD(FXS, RING, lineno_t chan, bool on); -static /* 0x0F */ DECLARE_CMD(FXS, RELAY_OUT, byte which, bool on); - -static bool fxs_packet_is_valid(xpacket_t *pack); -static void fxs_packet_dump(const char *msg, xpacket_t *pack); -static int proc_fxs_info_read(char *page, char **start, off_t off, int count, int *eof, void *data); -#ifdef WITH_METERING -static int proc_xpd_metering_write(struct file *file, const char __user *buffer, unsigned long count, void *data); -#endif -static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data); -static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data); -static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos); - -#define PROC_REGISTER_FNAME "slics" -#define PROC_FXS_INFO_FNAME "fxs_info" -#ifdef WITH_METERING -#define PROC_METERING_FNAME "metering_gen" -#endif - -struct FXS_priv_data { - struct proc_dir_entry *regfile; -#ifdef WITH_METERING - struct proc_dir_entry *meteringfile; -#endif - struct proc_dir_entry *fxs_info; - xpp_line_t ledstate[NUM_LEDS]; /* 0 - OFF, 1 - ON */ - xpp_line_t ledcontrol[NUM_LEDS]; /* 0 - OFF, 1 - ON */ - xpp_line_t search_fsk_pattern; - xpp_line_t found_fsk_pattern; - xpp_line_t update_offhook_state; - xpp_line_t want_dtmf_events; /* what zaptel want */ - xpp_line_t want_dtmf_mute; /* what zaptel want */ - int led_counter[NUM_LEDS][CHANNELS_PERXPD]; - int ohttimer[CHANNELS_PERXPD]; -#define OHT_TIMER 6000 /* How long after RING to retain OHT */ - enum fxs_state idletxhookstate[CHANNELS_PERXPD]; /* IDLE changing hook state */ - enum fxs_state lasttxhook[CHANNELS_PERXPD]; -}; - -/* - * LED counter values: - * n>1 : BLINK every n'th tick - */ -#define LED_COUNTER(priv,pos,color) ((priv)->led_counter[color][pos]) -#define IS_BLINKING(priv,pos,color) (LED_COUNTER(priv,pos,color) > 0) -#define MARK_BLINK(priv,pos,color,t) ((priv)->led_counter[color][pos] = (t)) -#define MARK_OFF(priv,pos,color) do { BIT_CLR((priv)->ledcontrol[color],(pos)); MARK_BLINK((priv),(pos),(color),0); } while(0) -#define MARK_ON(priv,pos,color) do { BIT_SET((priv)->ledcontrol[color],(pos)); MARK_BLINK((priv),(pos),(color),0); } while(0) - -#define LED_BLINK_RING (1000/8) /* in ticks */ - -/*---------------- FXS: Static functions ----------------------------------*/ -static int linefeed_control(xbus_t *xbus, xpd_t *xpd, lineno_t chan, enum fxs_state value) -{ - struct FXS_priv_data *priv; - - priv = xpd->priv; - LINE_DBG(SIGNAL, xpd, chan, "value=0x%02X\n", value); - priv->lasttxhook[chan] = value; - return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, 0x40, value); -} - -static int do_chan_power(xbus_t *xbus, xpd_t *xpd, lineno_t chan, bool on) -{ - int value = (on) ? 0x06 : 0x00; - - BUG_ON(!xbus); - BUG_ON(!xpd); - LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on) ? "up" : "down"); - return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, SLIC_REG_VOLTAGE, value); -} - -/* - * LED and RELAY control is done via SLIC register 0x06: - * 7 6 5 4 3 2 1 0 - * +-----+-----+-----+-----+-----+-----+-----+-----+ - * | M2 | M1 | M3 | C2 | O1 | O3 | C1 | C3 | - * +-----+-----+-----+-----+-----+-----+-----+-----+ - * - * Cn - Control bit (control one digital line) - * On - Output bit (program a digital line for output) - * Mn - Mask bit (only the matching output control bit is affected) - * - * C3 - OUTPUT RELAY (0 - OFF, 1 - ON) - * C1 - GREEN LED (0 - OFF, 1 - ON) - * O3 - Output RELAY (this line is output) - * O1 - Output GREEN (this line is output) - * C2 - RED LED (0 - OFF, 1 - ON) - * M3 - Mask RELAY. (1 - C3 effect the OUTPUT RELAY) - * M2 - Mask RED. (1 - C2 effect the RED LED) - * M1 - Mask GREEN. (1 - C1 effect the GREEN LED) - * - * The OUTPUT RELAY (actually a relay out) is connected to line 0 and 4 only. - */ - -// GREEN RED OUTPUT RELAY -static const int led_register_mask[] = { BIT(7), BIT(6), BIT(5) }; -static const int led_register_vals[] = { BIT(4), BIT(1), BIT(0) }; - -/* - * pos can be: - * - A line number - * - ALL_LINES. This is not valid anymore since 8-Jan-2007. - */ -static int do_led(xpd_t *xpd, lineno_t chan, byte which, bool on) -{ - int ret = 0; - struct FXS_priv_data *priv; - int value; - xbus_t *xbus; - - BUG_ON(!xpd); - BUG_ON(chan == ALL_LINES); - xbus = xpd->xbus; - priv = xpd->priv; - which = which % NUM_LEDS; - if(IS_SET(xpd->digital_outputs, chan) || IS_SET(xpd->digital_inputs, chan)) - goto out; - if(chan == ALL_CHANS) { - priv->ledstate[which] = (on) ? ~0 : 0; - } else { - if(on) { - BIT_SET(priv->ledstate[which], chan); - } else { - BIT_CLR(priv->ledstate[which], chan); - } - } - LINE_DBG(LEDS, xpd, chan, "LED: which=%d -- %s\n", which, (on) ? "on" : "off"); - value = BIT(2) | BIT(3); - value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[which]); - if(on) - value |= led_register_vals[which]; - ret = SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, 0x06, value); -out: - return ret; -} - -static void handle_fxs_leds(xpd_t *xpd) -{ - int i; - const enum fxs_leds colors[] = { LED_GREEN, LED_RED }; - int color; - unsigned int timer_count; - struct FXS_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - timer_count = xpd->timer_count; - for(color = 0; color < ARRAY_SIZE(colors); color++) { - for_each_line(xpd, i) { - if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i)) - continue; - if(xpd->blink_mode || IS_BLINKING(priv, i, color)) { // Blinking - int mod_value = LED_COUNTER(priv, i, color); - - if(!mod_value) - mod_value = DEFAULT_LED_PERIOD; /* safety value */ - // led state is toggled - if((timer_count % mod_value) == 0) { - LINE_DBG(LEDS, xpd, i, "ledstate=%s\n", (IS_SET(priv->ledstate[color], i))?"ON":"OFF"); - if(!IS_SET(priv->ledstate[color], i)) { - do_led(xpd, i, color, 1); - } else { - do_led(xpd, i, color, 0); - } - } - } else if(IS_SET(priv->ledcontrol[color], i) && !IS_SET(priv->ledstate[color], i)) { - do_led(xpd, i, color, 1); - } else if(!IS_SET(priv->ledcontrol[color], i) && IS_SET(priv->ledstate[color], i)) { - do_led(xpd, i, color, 0); - } - - } - } -} - -static void restore_leds(xpd_t *xpd) -{ - struct FXS_priv_data *priv; - int i; - - priv = xpd->priv; - for_each_line(xpd, i) { - if(IS_SET(xpd->offhook, i)) - MARK_ON(priv, i, LED_GREEN); - else - MARK_OFF(priv, i, LED_GREEN); - } -} - -#ifdef WITH_METERING -static int metering_gen(xpd_t *xpd, lineno_t chan, bool on) -{ - byte value = (on) ? 0x94 : 0x00; - - LINE_DBG(SIGNAL, xpd, chan, "METERING Generate: %s\n", (on)?"ON":"OFF"); - return SLIC_DIRECT_REQUEST(xpd->xbus, xpd, chan, SLIC_WRITE, 0x23, value); -} -#endif - -/*---------------- FXS: Methods -------------------------------------------*/ - -static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table, byte subtype, byte revision) -{ - xpd_t *xpd = NULL; - int channels; - int regular_channels; - - if(subtype == 2) - regular_channels = min(6, CHANNELS_PERXPD); - else - regular_channels = min(8, CHANNELS_PERXPD); - channels = regular_channels; - if(unit == 0) - channels += 6; /* 2 DIGITAL OUTPUTS, 4 DIGITAL INPUTS */ - xpd = xpd_alloc(sizeof(struct FXS_priv_data), proto_table, channels); - if(!xpd) - return NULL; - if(unit == 0) { - XBUS_DBG(GENERAL, xbus, "First XPD detected. Initialize digital outputs/inputs\n"); - xpd->digital_outputs = BITMASK(LINES_DIGI_OUT) << regular_channels; - xpd->digital_inputs = BITMASK(LINES_DIGI_INP) << (regular_channels + LINES_DIGI_OUT); - } - xpd->direction = TO_PHONE; - xpd->revision = revision; - xpd->type_name = proto_table->name; - return xpd; -} - -static void clean_proc(xbus_t *xbus, xpd_t *xpd) -{ - struct FXS_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; -#ifdef CONFIG_PROC_FS - if(priv->regfile) { - XPD_DBG(PROC, xpd, "Removing xpd SLIC file\n"); - priv->regfile->data = NULL; - remove_proc_entry(PROC_REGISTER_FNAME, xpd->proc_xpd_dir); - priv->regfile = NULL; - } -#ifdef WITH_METERING - if(priv->meteringfile) { - XPD_DBG(PROC, xpd, "Removing xpd metering tone file\n"); - priv->meteringfile->data = NULL; - remove_proc_entry(PROC_METERING_FNAME, xpd->proc_xpd_dir); - priv->meteringfile = NULL; - } -#endif - if(priv->fxs_info) { - XPD_DBG(PROC, xpd, "Removing xpd FXS_INFO file\n"); - remove_proc_entry(PROC_FXS_INFO_FNAME, xpd->proc_xpd_dir); - priv->fxs_info = NULL; - } -#endif -} - -static int FXS_card_init(xbus_t *xbus, xpd_t *xpd) -{ - struct FXS_priv_data *priv; - int ret = 0; - int i; - - BUG_ON(!xpd); - priv = xpd->priv; -#ifdef CONFIG_PROC_FS - XPD_DBG(PROC, xpd, "Creating FXS_INFO file\n"); - priv->fxs_info = create_proc_read_entry(PROC_FXS_INFO_FNAME, 0444, xpd->proc_xpd_dir, proc_fxs_info_read, xpd); - if(!priv->fxs_info) { - XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_FXS_INFO_FNAME); - ret = -ENOENT; - goto err; - } - priv->fxs_info->owner = THIS_MODULE; -#ifdef WITH_METERING - XPD_DBG(PROC, xpd, "Creating Metering tone file\n"); - priv->meteringfile = create_proc_entry(PROC_METERING_FNAME, 0200, xpd->proc_xpd_dir); - if(!priv->meteringfile) { - XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_METERING_FNAME); - ret = -ENOENT; - goto err; - } - priv->meteringfile->owner = THIS_MODULE; - priv->meteringfile->write_proc = proc_xpd_metering_write; - priv->meteringfile->read_proc = NULL; - priv->meteringfile->data = xpd; -#endif - XPD_DBG(PROC, xpd, "Creating SLICs file\n"); - priv->regfile = create_proc_entry(PROC_REGISTER_FNAME, 0644, xpd->proc_xpd_dir); - if(!priv->regfile) { - XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_REGISTER_FNAME); - ret = -ENOENT; - goto err; - } - priv->regfile->owner = THIS_MODULE; - priv->regfile->write_proc = proc_xpd_register_write; - priv->regfile->read_proc = proc_xpd_register_read; - priv->regfile->data = xpd; -#endif - for_each_line(xpd, i) { - priv->idletxhookstate[i] = FXS_LINE_POL_ACTIVE; - } - ret = run_initialize_registers(xpd); - if(ret < 0) - goto err; - /* - * Setup ring timers - */ - /* Software controled ringing (for CID) */ - ret = SLIC_DIRECT_REQUEST(xbus, xpd, ALL_CHANS, SLIC_WRITE, 0x22, 0x00); /* Ringing Oscilator Control */ - if(ret < 0) - goto err; - XPD_DBG(GENERAL, xpd, "done\n"); - for_each_line(xpd, i) { - do_led(xpd, i, LED_GREEN, 0); - do_led(xpd, i, LED_RED, 0); - } - for_each_line(xpd, i) { - do_led(xpd, i, LED_GREEN, 1); - msleep(50); - } - for_each_line(xpd, i) { - do_led(xpd, i, LED_GREEN, 0); - msleep(50); - } - restore_leds(xpd); - pcm_recompute(xpd, 0); - return 0; -err: - clean_proc(xbus, xpd); - XPD_ERR(xpd, "Failed initializing registers (%d)\n", ret); - return ret; -} - -static int FXS_card_remove(xbus_t *xbus, xpd_t *xpd) -{ - struct FXS_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - XPD_DBG(GENERAL, xpd, "\n"); - clean_proc(xbus, xpd); - return 0; -} - -static int FXS_card_zaptel_preregistration(xpd_t *xpd, bool on) -{ - xbus_t *xbus; - struct FXS_priv_data *priv; - int i; - - BUG_ON(!xpd); - xbus = xpd->xbus; - BUG_ON(!xbus); - priv = xpd->priv; - BUG_ON(!priv); - XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off"); - for_each_line(xpd, i) { - struct zt_chan *cur_chan = &xpd->chans[i]; - - XPD_DBG(GENERAL, xpd, "setting FXS channel %d\n", i); - if(IS_SET(xpd->digital_outputs, i)) { - snprintf(cur_chan->name, MAX_CHANNAME, "XPP_OUT/%02d/%1d%1d/%d", - xbus->num, xpd->addr.unit, xpd->addr.subunit, i); - } else if(IS_SET(xpd->digital_inputs, i)) { - snprintf(cur_chan->name, MAX_CHANNAME, "XPP_IN/%02d/%1d%1d/%d", - xbus->num, xpd->addr.unit, xpd->addr.subunit, i); - } else { - snprintf(cur_chan->name, MAX_CHANNAME, "XPP_FXS/%02d/%1d%1d/%d", - xbus->num, xpd->addr.unit, xpd->addr.subunit, i); - } - cur_chan->chanpos = i + 1; - cur_chan->pvt = xpd; - cur_chan->sigcap = FXS_DEFAULT_SIGCAP; - } - for_each_line(xpd, i) { - MARK_ON(priv, i, LED_GREEN); - msleep(4); - } - return 0; -} - -static int FXS_card_zaptel_postregistration(xpd_t *xpd, bool on) -{ - xbus_t *xbus; - struct FXS_priv_data *priv; - int i; - - BUG_ON(!xpd); - xbus = xpd->xbus; - BUG_ON(!xbus); - priv = xpd->priv; - BUG_ON(!priv); - XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off"); - for_each_line(xpd, i) { - MARK_OFF(priv, i, LED_GREEN); - msleep(2); - MARK_OFF(priv, i, LED_RED); - msleep(2); - } - restore_leds(xpd); - return 0; -} - -/* - * Called with XPD spinlocked - */ -static void __do_mute_dtmf(xpd_t *xpd, int pos, bool muteit) -{ - LINE_DBG(SIGNAL, xpd, pos, "%s\n", (muteit) ? "MUTE" : "UNMUTE"); - if(muteit) - BIT_SET(xpd->mute_dtmf, pos); - else - BIT_CLR(xpd->mute_dtmf, pos); -} - -static int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig) -{ - struct FXS_priv_data *priv; - int ret = 0; - struct zt_chan *chan = NULL; - enum fxs_state txhook; - unsigned long flags; - - LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig)); - priv = xpd->priv; - BUG_ON(xpd->direction != TO_PHONE); - if (IS_SET(xpd->digital_inputs, pos)) { - LINE_DBG(SIGNAL, xpd, pos, "Ignoring signal sent to digital input line\n"); - return 0; - } - if(SPAN_REGISTERED(xpd)) - chan = &xpd->span.chans[pos]; - switch(txsig) { - case ZT_TXSIG_ONHOOK: - spin_lock_irqsave(&xpd->lock, flags); - xpd->ringing[pos] = 0; - BIT_CLR(xpd->cid_on, pos); - BIT_CLR(priv->search_fsk_pattern, pos); - BIT_CLR(priv->want_dtmf_events, pos); - BIT_CLR(priv->want_dtmf_mute, pos); - __do_mute_dtmf(xpd, pos, 0); - __pcm_recompute(xpd, 0); /* already spinlocked */ - spin_unlock_irqrestore(&xpd->lock, flags); - if(IS_SET(xpd->digital_outputs, pos)) { - LINE_DBG(SIGNAL, xpd, pos, "digital output OFF\n"); - ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 0); - return ret; - } - if (priv->lasttxhook[pos] == FXS_LINE_OPEN) { - /* - * Restore state after KEWL hangup. - */ - LINE_DBG(SIGNAL, xpd, pos, "KEWL STOP\n"); - linefeed_control(xbus, xpd, pos, FXS_LINE_POL_ACTIVE); - if(IS_SET(xpd->offhook, pos)) - MARK_ON(priv, pos, LED_GREEN); - } - ret = CALL_XMETHOD(RING, xbus, xpd, pos, 0); // RING off - if (!IS_SET(xpd->offhook, pos)) - start_stop_vm_led(xbus, xpd, pos); - txhook = priv->lasttxhook[pos]; - if(chan) { - switch(chan->sig) { - case ZT_SIG_EM: - case ZT_SIG_FXOKS: - case ZT_SIG_FXOLS: - txhook = priv->idletxhookstate[pos]; - break; - case ZT_SIG_FXOGS: - txhook = FXS_LINE_TIPOPEN; - break; - } - } - ret = linefeed_control(xbus, xpd, pos, txhook); - break; - case ZT_TXSIG_OFFHOOK: - txhook = priv->lasttxhook[pos]; - if(xpd->ringing[pos]) { - BIT_SET(xpd->cid_on, pos); - pcm_recompute(xpd, 0); - txhook = FXS_LINE_OHTRANS; - } - xpd->ringing[pos] = 0; - if(chan) { - switch(chan->sig) { - case ZT_SIG_EM: - txhook = FXS_LINE_POL_ACTIVE; - break; - default: - txhook = priv->idletxhookstate[pos]; - break; - } - } - ret = linefeed_control(xbus, xpd, pos, txhook); - break; - case ZT_TXSIG_START: - xpd->ringing[pos] = 1; - BIT_CLR(xpd->cid_on, pos); - BIT_CLR(priv->search_fsk_pattern, pos); - pcm_recompute(xpd, 0); - if(IS_SET(xpd->digital_outputs, pos)) { - LINE_DBG(SIGNAL, xpd, pos, "%s digital output ON\n", txsig2str(txsig)); - ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 1); - return ret; - } - ret = CALL_XMETHOD(RING, xbus, xpd, pos, 1); // RING on - break; - case ZT_TXSIG_KEWL: - LINE_DBG(SIGNAL, xpd, pos, "KEWL START\n"); - linefeed_control(xbus, xpd, pos, FXS_LINE_OPEN); - MARK_OFF(priv, pos, LED_GREEN); - break; - default: - XPD_NOTICE(xpd, "%s: Can't set tx state to %s (%d)\n", - __FUNCTION__, txsig2str(txsig), txsig); - ret = -EINVAL; - } - return ret; -} - -/* - * Private ioctl() - * We don't need it now, since we detect vmwi via FSK patterns - */ -static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg) -{ - struct FXS_priv_data *priv; - xbus_t *xbus; - int val; - unsigned long flags; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - xbus = xpd->xbus; - BUG_ON(!xbus); - if(!TRANSPORT_RUNNING(xbus)) - return -ENODEV; - if (pos < 0 || pos >= xpd->channels) { - XPD_NOTICE(xpd, "Bad channel number %d in %s(), cmd=%u\n", - pos, __FUNCTION__, cmd); - return -EINVAL; - } - - switch (cmd) { - case ZT_ONHOOKTRANSFER: - if (get_user(val, (int __user *)arg)) - return -EFAULT; - LINE_DBG(SIGNAL, xpd, pos, "ZT_ONHOOKTRANSFER (%d millis)\n", val); - BUG_ON(pos == ALL_CHANS); - if (IS_SET(xpd->digital_inputs | xpd->digital_outputs, pos)) - return 0; /* Nothing to do */ - BIT_CLR(xpd->cid_on, pos); - if(priv->lasttxhook[pos] == FXS_LINE_POL_ACTIVE) { - priv->ohttimer[pos] = OHT_TIMER; - priv->idletxhookstate[pos] = FXS_LINE_POL_OHTRANS; - BIT_SET(priv->search_fsk_pattern, pos); - pcm_recompute(xpd, priv->search_fsk_pattern); - } - if(!IS_SET(xpd->offhook, pos)) - start_stop_vm_led(xbus, xpd, pos); - return 0; - case ZT_TONEDETECT: - if (get_user(val, (int __user *)arg)) - return -EFAULT; - LINE_DBG(SIGNAL, xpd, pos, "ZT_TONEDETECT: %s %s (dtmf_detection=%s)\n", - (val & ZT_TONEDETECT_ON) ? "ON" : "OFF", - (val & ZT_TONEDETECT_MUTE) ? "MUTE" : "NO-MUTE", - (dtmf_detection ? "YES" : "NO")); - if(!dtmf_detection) { - spin_lock_irqsave(&xpd->lock, flags); - if(IS_SET(priv->want_dtmf_events, pos)) { - /* Detection mode changed: Disable DTMF interrupts */ - SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x17, 0); - } - BIT_CLR(priv->want_dtmf_events, pos); - BIT_CLR(priv->want_dtmf_mute, pos); - __do_mute_dtmf(xpd, pos, 0); - __pcm_recompute(xpd, 0); /* already spinlocked */ - spin_unlock_irqrestore(&xpd->lock, flags); - return -ENOTTY; - } - /* - * During natively bridged calls, Asterisk - * will request one of the sides to stop sending - * dtmf events. Check the requested state. - */ - spin_lock_irqsave(&xpd->lock, flags); - if(val & ZT_TONEDETECT_ON) { - if(!IS_SET(priv->want_dtmf_events, pos)) { - /* Detection mode changed: Enable DTMF interrupts */ - LINE_DBG(SIGNAL, xpd, pos, - "ZT_TONEDETECT: Enable Hardware DTMF\n"); - SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x17, 1); - } - BIT_SET(priv->want_dtmf_events, pos); - } else { - if(IS_SET(priv->want_dtmf_events, pos)) { - /* Detection mode changed: Disable DTMF interrupts */ - LINE_DBG(SIGNAL, xpd, pos, - "ZT_TONEDETECT: Disable Hardware DTMF\n"); - SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x17, 0); - } - BIT_CLR(priv->want_dtmf_events, pos); - } - if(val & ZT_TONEDETECT_MUTE) { - BIT_SET(priv->want_dtmf_mute, pos); - } else { - BIT_CLR(priv->want_dtmf_mute, pos); - __do_mute_dtmf(xpd, pos, 0); - __pcm_recompute(xpd, 0); - } - spin_unlock_irqrestore(&xpd->lock, flags); - return 0; - case ZT_SETPOLARITY: - if (get_user(val, (int __user *)arg)) - return -EFAULT; - /* Can't change polarity while ringing or when open */ - if (priv->lasttxhook[pos] == FXS_LINE_RING || priv->lasttxhook[pos] == FXS_LINE_OPEN) { - LINE_ERR(xpd, pos, "ZT_SETPOLARITY: %s Cannot change when lasttxhook=0x%X\n", - (val)?"ON":"OFF", priv->lasttxhook[pos]); - return -EINVAL; - } - LINE_DBG(SIGNAL, xpd, pos, "ZT_SETPOLARITY: %s\n", (val)?"ON":"OFF"); - if ((val && !reversepolarity) || (!val && reversepolarity)) - priv->lasttxhook[pos] |= FXS_LINE_RING; - else - priv->lasttxhook[pos] &= ~FXS_LINE_RING; - linefeed_control(xbus, xpd, pos, priv->lasttxhook[pos]); - return 0; -#ifdef ZT_VMWI - case ZT_VMWI: /* message-waiting led control */ - if (get_user(val, (int __user *)arg)) - return -EFAULT; - if(!vmwi_ioctl) { - LINE_NOTICE(xpd, pos, "Got ZT_VMWI notification but vmwi_ioctl parameter is off. Ignoring.\n"); - return 0; - } - /* Digital inputs/outputs don't have VM leds */ - if (IS_SET(xpd->digital_inputs | xpd->digital_outputs, pos)) - return 0; - if (val) - BIT_SET(xpd->msg_waiting, pos); - else - BIT_CLR(xpd->msg_waiting, pos); - return 0; -#endif - default: - report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd); - } - return -ENOTTY; -} - -static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos, int on) -{ - int ret = 0; - BUG_ON(!xbus); - BUG_ON(!xpd); - - LINE_DBG(SIGNAL, xpd, pos, "%s%s\n", (on)?"ON":"OFF", (vmwineon)?"":" (Ignored)"); - if (!vmwineon) - return 0; - if (on) { - /* A write to register 0x40 will now turn on/off the VM led */ - ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16, 0xE8, 0x03); - ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15, 0xEF, 0x7B); - ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14, 0x9F, 0x00); - ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x19); - ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x4A, 0x34); - ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0xE0); - ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x01); - ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0xF0); - ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x05); - ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D, 0x00, 0x46); - } else { - /* A write to register 0x40 will now turn on/off the ringer */ - ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16, 0x00, 0x00); - ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15, 0x60, 0x01); - ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14, 0xF0, 0x7E); - ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x00); - ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x4A, 0x34); - ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0x00); - ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x00); - ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0x00); - ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x00); - ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D, 0x00, 0x36); - } - - return (ret ? -EPROTO : 0); -} - -static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos) -{ - struct FXS_priv_data *priv; - bool on; - - BUG_ON(!xpd); - if (IS_SET(xpd->digital_outputs | xpd->digital_inputs, pos)) - return; - priv = xpd->priv; - on = IS_SET(xpd->msg_waiting, pos); - LINE_DBG(SIGNAL, xpd, pos, "%s\n", (on)?"ON":"OFF"); - set_vm_led_mode(xbus, xpd, pos, on); - do_chan_power(xbus, xpd, pos, on); - linefeed_control(xbus, xpd, pos, (on) ? FXS_LINE_RING : priv->idletxhookstate[pos]); -} - -static int FXS_card_open(xpd_t *xpd, lineno_t chan) -{ - struct FXS_priv_data *priv; - bool is_offhook; - - BUG_ON(!xpd); - priv = xpd->priv; - is_offhook = IS_SET(xpd->offhook, chan); - LINE_DBG(GENERAL, xpd, chan, "(is %shook)\n", (is_offhook)?"off":"on"); - /* - * Delegate updating zaptel to FXS_card_tick(): - * The problem is that zt_hooksig() is spinlocking the channel and - * we are called by zaptel with the spinlock already held on the - * same channel. - */ - BIT_SET(priv->update_offhook_state, chan); - return 0; -} - -static int FXS_card_close(xpd_t *xpd, lineno_t chan) -{ - struct FXS_priv_data *priv; - - BUG_ON(!xpd); - LINE_DBG(GENERAL, xpd, chan, "\n"); - priv = xpd->priv; - priv->idletxhookstate[chan] = FXS_LINE_POL_ACTIVE; - return 0; -} - -/* - * INPUT polling is done via SLIC register 0x06 (same as LEDS): - * 7 6 5 4 3 2 1 0 - * +-----+-----+-----+-----+-----+-----+-----+-----+ - * | I1 | I3 | | | I2 | I4 | | | - * +-----+-----+-----+-----+-----+-----+-----+-----+ - * - */ -static int input_channels[] = { 6, 7, 2, 3 }; // Slic numbers of input relays - -static void poll_inputs(xpd_t *xpd) -{ - int i; - - BUG_ON(xpd->xbus_idx != 0); // Only unit #0 has digital inputs - for(i = 0; i < ARRAY_SIZE(input_channels); i++) { - byte pos = input_channels[i]; - - SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_READ, 0x06, 0); - } -} - -static void handle_linefeed(xpd_t *xpd) -{ - struct FXS_priv_data *priv; - int i; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - for_each_line(xpd, i) { - if (priv->lasttxhook[i] == FXS_LINE_RING) { - /* RINGing, prepare for OHT */ - priv->ohttimer[i] = OHT_TIMER; - priv->idletxhookstate[i] = FXS_LINE_POL_OHTRANS; - } else { - if (priv->ohttimer[i]) { - priv->ohttimer[i]--; - if (!priv->ohttimer[i]) { - priv->idletxhookstate[i] = FXS_LINE_POL_ACTIVE; - if (priv->lasttxhook[i] == FXS_LINE_POL_OHTRANS) { - enum fxs_state txhook = FXS_LINE_POL_ACTIVE; - /* Apply the change if appropriate */ - BIT_CLR(xpd->cid_on, i); - BIT_CLR(priv->search_fsk_pattern, i); - pcm_recompute(xpd, 0); - linefeed_control(xpd->xbus, xpd, i, txhook); - } - } - } - } - } -} - -/* - * Optimized memcmp() like function. Only test for equality (true/false). - * This optimization reduced the detect_vmwi() runtime by a factor of 3. - */ -static inline bool mem_equal(const char a[], const char b[], size_t len) -{ - int i; - - for(i = 0; i < len; i++) - if(a[i] != b[i]) - return 0; - return 1; -} - -/* - * Detect Voice Mail Waiting Indication - */ -static void detect_vmwi(xpd_t *xpd) -{ - struct FXS_priv_data *priv; - xbus_t *xbus; - static const byte FSK_COMMON_PATTERN[] = { 0xA8, 0x49, 0x22, 0x3B, 0x9F, 0xFF, 0x1F, 0xBB }; - static const byte FSK_ON_PATTERN[] = { 0xA2, 0x2C, 0x1F, 0x2C, 0xBB, 0xA1, 0xA5, 0xFF }; - static const byte FSK_OFF_PATTERN[] = { 0xA2, 0x2C, 0x28, 0xA5, 0xB1, 0x21, 0x49, 0x9F }; - int i; - - BUG_ON(!xpd); - xbus = xpd->xbus; - priv = xpd->priv; - BUG_ON(!priv); - for_each_line(xpd, i) { - struct zt_chan *chan = &xpd->span.chans[i]; - byte *writechunk = chan->writechunk; - - if(IS_SET(xpd->offhook | xpd->cid_on | xpd->digital_inputs | xpd->digital_outputs, i)) - continue; -#if 0 - if(writechunk[0] != 0x7F && writechunk[0] != 0) { - int j; - - LINE_DBG(GENERAL, xpd, pos, "MSG:"); - for(j = 0; j < ZT_CHUNKSIZE; j++) { - if(print_dbg) - printk(" %02X", writechunk[j]); - } - if(print_dbg) - printk("\n"); - } -#endif - if(unlikely(mem_equal(writechunk, FSK_COMMON_PATTERN, ZT_CHUNKSIZE))) - BIT_SET(priv->found_fsk_pattern, i); - else if(unlikely(IS_SET(priv->found_fsk_pattern, i))) { - BIT_CLR(priv->found_fsk_pattern, i); - if(unlikely(mem_equal(writechunk, FSK_ON_PATTERN, ZT_CHUNKSIZE))) { - LINE_DBG(SIGNAL, xpd, i, "MSG WAITING ON\n"); - BIT_SET(xpd->msg_waiting, i); - start_stop_vm_led(xbus, xpd, i); - } else if(unlikely(mem_equal(writechunk, FSK_OFF_PATTERN, ZT_CHUNKSIZE))) { - LINE_DBG(SIGNAL, xpd, i, "MSG WAITING OFF\n"); - BIT_CLR(xpd->msg_waiting, i); - start_stop_vm_led(xbus, xpd, i); - } else { - int j; - - LINE_NOTICE(xpd, i, "MSG WAITING Unexpected:"); - for(j = 0; j < ZT_CHUNKSIZE; j++) { - printk(" %02X", writechunk[j]); - } - printk("\n"); - } - } - } -} - -static int FXS_card_tick(xbus_t *xbus, xpd_t *xpd) -{ - struct FXS_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); -#if POLL_DIGITAL_INPUTS - if(poll_digital_inputs && xpd->xbus_idx == 0) { - if((xpd->timer_count % poll_digital_inputs) == 0) - poll_inputs(xpd); - } -#endif - handle_fxs_leds(xpd); - handle_linefeed(xpd); - if(priv->update_offhook_state) { /* set in FXS_card_open() */ - int i; - - for_each_line(xpd, i) { - if(!IS_SET(priv->update_offhook_state, i)) - continue; - /* - * Update LEDs and zaptel with current state of line. - */ - if(IS_SET(xpd->offhook, i)) { - LINE_NOTICE(xpd, i, "Already offhook during open. OK.\n"); - MARK_ON(priv, i, LED_GREEN); - update_line_status(xpd, i, 1); - } else { - MARK_OFF(priv, i, LED_GREEN); - update_line_status(xpd, i, 0); - } - BIT_CLR(priv->update_offhook_state, i); - } - } - if(SPAN_REGISTERED(xpd)) { - if(vmwineon && !vmwi_ioctl) - detect_vmwi(xpd); /* Detect via FSK modulation */ - } - return 0; -} - -/*---------------- FXS: HOST COMMANDS -------------------------------------*/ - -/* 0x0F */ HOSTCMD(FXS, XPD_STATE, bool on) -{ - int i; - enum fxs_state value = (on) ? FXS_LINE_POL_ACTIVE : FXS_LINE_OPEN; - unsigned long flags; - struct FXS_priv_data *priv; - - BUG_ON(!xbus); - BUG_ON(!xpd); - priv = xpd->priv; - spin_lock_irqsave(&xpd->lock, flags); - XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off"); - for_each_line(xpd, i) - linefeed_control(xbus, xpd, i, value); - if(on) { - MARK_ON(priv, ALL_CHANS, LED_GREEN); - } else { - MARK_OFF(priv, ALL_CHANS, LED_GREEN); - } - spin_unlock_irqrestore(&xpd->lock, flags); - return 0; -} - -/* 0x0F */ HOSTCMD(FXS, RING, lineno_t chan, bool on) -{ - int ret = 0; - struct FXS_priv_data *priv; - enum fxs_state value = (on) ? FXS_LINE_RING : FXS_LINE_POL_ACTIVE; - - BUG_ON(!xbus); - BUG_ON(!xpd); - LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on)?"on":"off"); - priv = xpd->priv; - set_vm_led_mode(xbus, xpd, chan, 0); - do_chan_power(xbus, xpd, chan, on); // Power up (for ring) - ret = linefeed_control(xbus, xpd, chan, value); - if(on) { - MARK_BLINK(priv, chan, LED_GREEN, LED_BLINK_RING); - } else { - if(IS_BLINKING(priv, chan, LED_GREEN)) - MARK_BLINK(priv, chan, LED_GREEN, 0); - } - return ret; -} - -/* 0x0F */ HOSTCMD(FXS, RELAY_OUT, byte which, bool on) -{ - int value; - int relay_channels[] = { 0, 4 }; - - BUG_ON(!xbus); - BUG_ON(!xpd); - XPD_DBG(SIGNAL, xpd, "RELAY_OUT: which=%d -- %s\n", which, (on) ? "on" : "off"); - which = which % ARRAY_SIZE(relay_channels); - value = BIT(2) | BIT(3); - value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[OUTPUT_RELAY]); - if(on) - value |= led_register_vals[OUTPUT_RELAY]; - return SLIC_DIRECT_REQUEST(xbus, xpd, relay_channels[which], SLIC_WRITE, 0x06, value); -} - -/*---------------- FXS: Astribank Reply Handlers --------------------------*/ - -HANDLER_DEF(FXS, SIG_CHANGED) -{ - xpp_line_t sig_status = RPACKET_FIELD(pack, FXS, SIG_CHANGED, sig_status); - xpp_line_t sig_toggles = RPACKET_FIELD(pack, FXS, SIG_CHANGED, sig_toggles); - struct FXS_priv_data *priv; - int i; - unsigned long flags; - - BUG_ON(!xpd); - BUG_ON(xpd->direction != TO_PHONE); - priv = xpd->priv; - XPD_DBG(SIGNAL, xpd, "(PHONE) sig_toggles=0x%04X sig_status=0x%04X\n", sig_toggles, sig_status); -#if 0 - Is this needed? - for_each_line(xpd, i) { - if(IS_SET(sig_toggles, i)) - do_chan_power(xpd->xbus, xpd, BIT(i), 0); // Power down (prevent overheating!!!) - } -#endif - spin_lock_irqsave(&xpd->lock, flags); - for_each_line(xpd, i) { - if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i)) - continue; - if(IS_SET(sig_toggles, i)) { - xpd->ringing[i] = 0; /* No more ringing... */ -#ifdef WITH_METERING - metering_gen(xpd, i, 0); /* Stop metering... */ -#endif - MARK_BLINK(priv, i, LED_GREEN, 0); - if(IS_SET(sig_status, i)) { - LINE_DBG(SIGNAL, xpd, i, "OFFHOOK\n"); - MARK_ON(priv, i, LED_GREEN); - update_line_status(xpd, i, 1); - } else { - LINE_DBG(SIGNAL, xpd, i, "ONHOOK\n"); - MARK_OFF(priv, i, LED_GREEN); - update_line_status(xpd, i, 0); - } - } - } - __pcm_recompute(xpd, 0); /* in a spinlock */ - spin_unlock_irqrestore(&xpd->lock, flags); - return 0; -} - -static void process_digital_inputs(xpd_t *xpd, const reg_cmd_t *info) -{ - int i; - bool offhook = (REG_FIELD(info, data_low) & 0x1) == 0; - xpp_line_t lines = BIT(REG_FIELD(info, chipsel)); - - /* Map SLIC number into line number */ - for(i = 0; i < ARRAY_SIZE(input_channels); i++) { - int channo = input_channels[i]; - int newchanno; - - if(IS_SET(lines, channo)) { - newchanno = xpd->channels - LINES_DIGI_INP + i; - BIT_CLR(lines, channo); - BIT_SET(lines, newchanno); - xpd->ringing[newchanno] = 0; // Stop ringing. No leds for digital inputs. - if(offhook && !IS_SET(xpd->offhook, newchanno)) { // OFFHOOK - LINE_DBG(SIGNAL, xpd, newchanno, "OFFHOOK\n"); - update_line_status(xpd, newchanno, 1); - } else if(!offhook && IS_SET(xpd->offhook, newchanno)) { // ONHOOK - LINE_DBG(SIGNAL, xpd, newchanno, "ONHOOK\n"); - update_line_status(xpd, newchanno, 0); - } - } - } -} - -static const char dtmf_digits[] = { - '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '*', '#', 'A', 'B', 'C', 'D' -}; - -/* - * This function is called with spinlocked XPD - */ -static void process_dtmf(xpd_t *xpd, xpp_line_t lines, byte val) -{ - int i; - byte digit; - bool is_down = val & 0x10; - struct FXS_priv_data *priv; - - if(!dtmf_detection) - return; - priv = xpd->priv; - val &= 0xF; - if(val <= 0) { - if(is_down) - XPD_NOTICE(xpd, "Bad DTMF value %d. Ignored\n", val); - return; - } - val--; - digit = dtmf_digits[val]; - for_each_line(xpd, i) { - if(IS_SET(lines, i)) { - int event = (is_down) ? ZT_EVENT_DTMFDOWN : ZT_EVENT_DTMFUP; - bool want_mute = IS_SET(priv->want_dtmf_mute, i); - bool want_event = IS_SET(priv->want_dtmf_events, i); - - if(want_event) { - LINE_DBG(SIGNAL, xpd, i, - "DTMF digit %s (val=%d) '%c' (want_mute=%s)\n", - (is_down)?"DOWN":"UP", val, digit, - (want_mute) ? "yes" : "no"); - } else { - LINE_DBG(SIGNAL, xpd, i, - "Ignored DTMF digit %s '%c'\n", - (is_down)?"DOWN":"UP", digit); - } - /* - * FIXME: we currently don't use the want_dtmf_mute until - * we are sure about the logic in Asterisk native bridging. - * Meanwhile, simply mute it on button press. - */ - if(is_down && want_mute) - __do_mute_dtmf(xpd, i, 1); - else - __do_mute_dtmf(xpd, i, 0); - __pcm_recompute(xpd, 0); /* XPD is locked */ - if(want_event) - zt_qevent_lock(&xpd->chans[i], event | digit); - break; - } - } -} - -static int FXS_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) -{ - unsigned long flags; - struct FXS_priv_data *priv; - byte regnum; - bool indirect; - - spin_lock_irqsave(&xpd->lock, flags); - priv = xpd->priv; - BUG_ON(!priv); - indirect = (REG_FIELD(info, regnum) == 0x1E); - regnum = (indirect) ? REG_FIELD(info, subreg) : REG_FIELD(info, regnum); - XPD_DBG(REGS, xpd, "%s reg_num=0x%X, dataL=0x%X dataH=0x%X\n", - (indirect)?"I":"D", - regnum, REG_FIELD(info, data_low), REG_FIELD(info, data_high)); - if(!SPAN_REGISTERED(xpd)) - goto out; - /* - * Process digital inputs polling results - */ - if(xpd->xbus_idx == 0 && !indirect && regnum == 0x06) - process_digital_inputs(xpd, info); - if(!indirect && regnum == SLIC_REG_DTMF) { - byte val = REG_FIELD(info, data_low); - xpp_line_t lines = BIT(REG_FIELD(info, chipsel)); - -#if 0 - XPD_DBG(SIGNAL, xpd, "DTMF result lines=0x%04X val=%d\n", - lines, val); -#endif - process_dtmf(xpd, lines, val); - } -out: - /* Update /proc info only if reply relate to the last slic read request */ - if( - REG_FIELD(&xpd->requested_reply, regnum) == REG_FIELD(info, regnum) && - REG_FIELD(&xpd->requested_reply, do_subreg) == REG_FIELD(info, do_subreg) && - REG_FIELD(&xpd->requested_reply, subreg) == REG_FIELD(info, subreg)) { - xpd->last_reply = *info; - } - spin_unlock_irqrestore(&xpd->lock, flags); - return 0; -} - -static xproto_table_t PROTO_TABLE(FXS) = { - .owner = THIS_MODULE, - .entries = { - /* Prototable Card Opcode */ - XENTRY( FXS, FXS, SIG_CHANGED ), - }, - .name = "FXS", - .type = XPD_TYPE_FXS, - .xops = { - .card_new = FXS_card_new, - .card_init = FXS_card_init, - .card_remove = FXS_card_remove, - .card_zaptel_preregistration = FXS_card_zaptel_preregistration, - .card_zaptel_postregistration = FXS_card_zaptel_postregistration, - .card_hooksig = FXS_card_hooksig, - .card_tick = FXS_card_tick, - .card_pcm_fromspan = generic_card_pcm_fromspan, - .card_pcm_tospan = generic_card_pcm_tospan, - .card_open = FXS_card_open, - .card_close = FXS_card_close, - .card_ioctl = FXS_card_ioctl, - .card_register_reply = FXS_card_register_reply, - - .RING = XPROTO_CALLER(FXS, RING), - .RELAY_OUT = XPROTO_CALLER(FXS, RELAY_OUT), - .XPD_STATE = XPROTO_CALLER(FXS, XPD_STATE), - }, - .packet_is_valid = fxs_packet_is_valid, - .packet_dump = fxs_packet_dump, -}; - -static bool fxs_packet_is_valid(xpacket_t *pack) -{ - const xproto_entry_t *xe; - - // DBG(GENERAL, "\n"); - xe = xproto_card_entry(&PROTO_TABLE(FXS), XPACKET_OP(pack)); - return xe != NULL; -} - -static void fxs_packet_dump(const char *msg, xpacket_t *pack) -{ - DBG(GENERAL, "%s\n", msg); -} - -/*------------------------- SLIC Handling --------------------------*/ - -static int proc_fxs_info_read(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - unsigned long flags; - xpd_t *xpd = data; - struct FXS_priv_data *priv; - int i; - int led; - - if(!xpd) - return -ENODEV; - spin_lock_irqsave(&xpd->lock, flags); - priv = xpd->priv; - BUG_ON(!priv); - len += sprintf(page + len, "%-8s %-10s %-10s %-10s\n", - "Channel", - "idletxhookstate", - "lasttxhook", - "ohttimer" - ); - for_each_line(xpd, i) { - char pref; - - if(IS_SET(xpd->digital_outputs, i)) - pref = 'O'; - else if(IS_SET(xpd->digital_inputs, i)) - pref = 'I'; - else - pref = ' '; - len += sprintf(page + len, "%c%7d %10d %10d %10d\n", - pref, - i, - priv->idletxhookstate[i], - priv->lasttxhook[i], - priv->ohttimer[i] - ); - } - len += sprintf(page + len, "\n"); - for(led = 0; led < NUM_LEDS; led++) { - len += sprintf(page + len, "LED #%d", led); - len += sprintf(page + len, "\n\t%-17s: ", "ledstate"); - for_each_line(xpd, i) { - if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) - len += sprintf(page + len, "%d ", IS_SET(priv->ledstate[led], i)); - } - len += sprintf(page + len, "\n\t%-17s: ", "ledcontrol"); - for_each_line(xpd, i) { - if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) - len += sprintf(page + len, "%d ", IS_SET(priv->ledcontrol[led], i)); - } - len += sprintf(page + len, "\n\t%-17s: ", "led_counter"); - for_each_line(xpd, i) { - if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) - len += sprintf(page + len, "%d ", LED_COUNTER(priv,i,led)); - } - len += sprintf(page + len, "\n"); - } - spin_unlock_irqrestore(&xpd->lock, flags); - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; -} - -/* - * - * Direct/Indirect - * | - * | Reg# - * | | - * | | Data (only in Write) - * | | | - * | | +-+-+ - * v v v v - * FF WD 06 01 05 - * ^ ^ - * | | - * | Write/Read - * | - * Chan# - * - */ -static int handle_register_command(xpd_t *xpd, char *cmdline) -{ - unsigned chipsel; - unsigned data_low = 0; - unsigned data_high = 0; - char op; /* [W]rite, [R]ead */ - char reg_type; /* [D]irect, [I]ndirect */ - int reg_num; - int elements; - bool writing; - char *p; - reg_cmd_t regcmd; - xbus_t *xbus; - int ret = -EINVAL; - - BUG_ON(!xpd); - xbus = xpd->xbus; - if((p = strchr(cmdline, '#')) != NULL) /* Truncate comments */ - *p = '\0'; - if((p = strchr(cmdline, ';')) != NULL) /* Truncate comments */ - *p = '\0'; - for(p = cmdline; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */ - ; - if(*p == '\0') - return 0; - if(!XBUS_GET(xbus)) { - XBUS_DBG(GENERAL, xbus, "Dropped packet. Is shutting down.\n"); - return -EBUSY; - } - elements = sscanf(cmdline, "%d %c%c %x %x %x", - &chipsel, - &op, ®_type, ®_num, - &data_low, - &data_high); - XPD_DBG(REGS, xpd, "'%s': %d %c%c %02X %02X %02X\n", cmdline, chipsel, op, reg_type, reg_num, data_low, data_high); - if(elements < 4) { // At least: chipsel, op, reg_type, reg_num - ERR("Not enough arguments: (%d args) '%s'\n", elements, cmdline); - goto out; - } - if(!VALID_CHIPSEL(chipsel)) { - ERR("Bad chipsel number: %d\n", chipsel); - goto out; - } - REG_FIELD(®cmd, chipsel) = chipsel; - switch(op) { - case 'W': - writing = 1; - break; - case 'R': - writing = 0; - break; - default: - ERR("Unkown operation type '%c'\n", op); - goto out; - } - switch(reg_type) { - case 'I': - REG_FIELD(®cmd, do_subreg) = 1; - REG_FIELD(®cmd, regnum) = 0x1E; // FIXME: card dependent... - REG_FIELD(®cmd, subreg) = reg_num; - break; - case 'D': - REG_FIELD(®cmd, do_subreg) = 0; - REG_FIELD(®cmd, regnum) = reg_num; - REG_FIELD(®cmd, subreg) = 0; - break; - default: - ERR("Unkown register type '%c'\n", reg_type); - goto out; - } - if( - (op == 'W' && reg_type == 'D' && elements != 5) || - (op == 'W' && reg_type == 'I' && elements != 6) || - (op == 'R' && reg_type == 'D' && elements != 4) || - (op == 'R' && reg_type == 'I' && elements != 4) - ) { - ERR("%s: '%s' (%d elements): %d %c%c %02X %02X %02X\n", __FUNCTION__, - cmdline, elements, - chipsel, op, reg_type, reg_num, data_low, data_high); - goto out; - } - regcmd.bytes = sizeof(regcmd) - 1; - REG_FIELD(®cmd, data_low) = data_low; - REG_FIELD(®cmd, data_high) = data_high; - REG_FIELD(®cmd, read_request) = writing; - xpd->requested_reply = regcmd; - if(print_dbg) - dump_reg_cmd("FXS", ®cmd, 1); - ret = xpp_register_request(xpd->xbus, xpd, - REG_FIELD(®cmd, chipsel), - writing, - REG_FIELD(®cmd, do_subreg), - REG_FIELD(®cmd, regnum), - REG_FIELD(®cmd, subreg), - REG_FIELD(®cmd, data_low), - REG_FIELD(®cmd, data_high)); -out: - XBUS_PUT(xbus); - return ret; -} - -static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data) -{ - xpd_t *xpd = data; - char buf[MAX_PROC_WRITE]; - char *p; - int i; - int ret; - - if(!xpd) - return -ENODEV; - for(i = 0; i < count; /* noop */) { - for(p = buf; p < buf + MAX_PROC_WRITE; p++) { /* read a line */ - if(i >= count) - break; - if(get_user(*p, buffer + i)) - return -EFAULT; - i++; - if(*p == '\n' || *p == '\r') /* whatever */ - break; - } - if(p >= buf + MAX_PROC_WRITE) - return -E2BIG; - *p = '\0'; - ret = handle_register_command(xpd, buf); - if(ret < 0) - return ret; - msleep(1); - } - return count; -} - -static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - unsigned long flags; - xpd_t *xpd = data; - reg_cmd_t *info; - byte regnum; - bool indirect; - - if(!xpd) - return -ENODEV; - spin_lock_irqsave(&xpd->lock, flags); - info = &xpd->last_reply; - indirect = (REG_FIELD(info, regnum) == 0x1E); - regnum = (indirect) ? REG_FIELD(info, subreg) : REG_FIELD(info, regnum); - len += sprintf(page + len, "# Writing bad data into this file may damage your hardware!\n"); - len += sprintf(page + len, "# Consult firmware docs first\n"); - len += sprintf(page + len, "#\n"); - len += sprintf(page + len, "#CH\tD/I\tReg.\tDL DH\n"); - len += sprintf(page + len, "%2d\tR%c\t%02X\t%02X %02X\n", - REG_FIELD(info, chipsel), - (indirect)?'I':'D', - regnum, REG_FIELD(info, data_low), REG_FIELD(info, data_high)); - spin_unlock_irqrestore(&xpd->lock, flags); - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; -} - -#ifdef WITH_METERING -static int proc_xpd_metering_write(struct file *file, const char __user *buffer, unsigned long count, void *data) -{ - xpd_t *xpd = data; - char buf[MAX_PROC_WRITE]; - lineno_t chan; - int num; - int ret; - - if(!xpd) - return -ENODEV; - if(count >= MAX_PROC_WRITE - 1) { - XPD_ERR(xpd, "Metering string too long (%lu)\n", count); - return -EINVAL; - } - if(copy_from_user(&buf, buffer, count)) - return -EFAULT; - buf[count] = '\0'; - ret = sscanf(buf, "%d", &num); - if(ret != 1) { - XPD_ERR(xpd, "Metering value should be number. Got '%s'\n", buf); - return -EINVAL; - } - chan = num; - if(chan != ALL_CHANS && chan > xpd->channels) { - XPD_ERR(xpd, "Metering tone: bad channel number %d\n", chan); - return -EINVAL; - } - if((ret = metering_gen(xpd, chan, 1)) < 0) { - XPD_ERR(xpd, "Failed sending metering tone\n"); - return ret; - } - return count; -} -#endif - -int __init card_fxs_startup(void) -{ - INFO("revision %s\n", XPP_VERSION); -#ifdef POLL_DIGITAL_INPUTS - INFO("FEATURE: with DIGITAL INPUTS support (polled every %d msec)\n", - poll_digital_inputs); -#else - INFO("FEATURE: without DIGITAL INPUTS support\n"); -#endif -#ifdef ZT_VMWI - INFO("FEATURE: ZT_VMWI\n"); -#else - INFO("FEATURE: NO ZT_VMWI\n"); -#endif -#ifdef WITH_METERING - INFO("FEATURE: WITH METERING Generation\n"); -#else - INFO("FEATURE: NO METERING Generation\n"); -#endif - xproto_register(&PROTO_TABLE(FXS)); - return 0; -} - -void __exit card_fxs_cleanup(void) -{ - xproto_unregister(&PROTO_TABLE(FXS)); -} - -MODULE_DESCRIPTION("XPP FXS Card Driver"); -MODULE_AUTHOR("Oron Peled "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(XPP_VERSION); -MODULE_ALIAS_XPD(XPD_TYPE_FXS); - -module_init(card_fxs_startup); -module_exit(card_fxs_cleanup); diff --git a/xpp/card_fxs.h b/xpp/card_fxs.h deleted file mode 100644 index 6a89228..0000000 --- a/xpp/card_fxs.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef CARD_FXS_H -#define CARD_FXS_H -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "xpd.h" - -enum fxs_opcodes { - XPROTO_NAME(FXS, SIG_CHANGED) = 0x06, -/**/ - XPROTO_NAME(FXS, XPD_STATE) = 0x0F, /* Write to SLIC */ - XPROTO_NAME(FXS, CHAN_POWER) = 0x0F, /* Write to SLIC */ - XPROTO_NAME(FXS, CHAN_CID) = 0x0F, /* Write to SLIC */ - XPROTO_NAME(FXS, RING) = 0x0F, /* Write to SLIC */ - XPROTO_NAME(FXS, LED) = 0x0F, /* Write to SLIC */ - XPROTO_NAME(FXS, RELAY_OUT) = 0x0F, /* Write to SLIC */ -}; - - -DEF_RPACKET_DATA(FXS, SIG_CHANGED, - byte type; /* unused -- we have it from DEV_DESC */ - xpp_line_t sig_status; /* channels: lsb=1, msb=8 */ - xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */ - ); - -#endif /* CARD_FXS_H */ diff --git a/xpp/card_global.c b/xpp/card_global.c deleted file mode 100644 index 05f4008..0000000 --- a/xpp/card_global.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include "xdefs.h" -#include "xpd.h" -#include "xpp_zap.h" -#include "xproto.h" -#include "zap_debug.h" -#include "xbus-core.h" -#include "parport_debug.h" - -static const char rcsid[] = "$Id$"; - -DEF_PARM(charp,initdir, "/usr/share/zaptel", 0644, "The directory of card initialization scripts"); - -extern int print_dbg; - -/*---------------- GLOBAL Protocol Commands -------------------------------*/ - -static bool global_packet_is_valid(xpacket_t *pack); -static void global_packet_dump(const char *msg, xpacket_t *pack); - -/*---------------- GLOBAL: HOST COMMANDS ----------------------------------*/ - -/* 0x04 */ HOSTCMD(GLOBAL, DESC_REQ, int xpd_num) -{ - int ret = 0; - xframe_t *xframe; - xpacket_t *pack; - - if(!xbus) { - DBG(GENERAL, "NO XBUS\n"); - return -EINVAL; - } - XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, DESC_REQ, xpd_num); - XBUS_DBG(GENERAL, xbus, "to %1d%1d\n", XBUS_UNIT(xpd_num), XBUS_SUBUNIT(xpd_num)); - ret = send_cmd_frame(xbus, xframe); - XBUS_COUNTER(xbus, DESC_REQ)++; - return ret; -} - -int xpp_register_request(xbus_t *xbus, xpd_t *xpd, - byte chipsel, bool writing, bool do_subreg, byte regnum, byte subreg, byte data_low, byte data_high) -{ - int ret = 0; - xframe_t *xframe; - xpacket_t *pack; - reg_cmd_t *reg_cmd; - - if(!xbus) { - DBG(REGS, "NO XBUS\n"); - return -EINVAL; - } - XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx); - LINE_DBG(REGS, xpd, chipsel, "%c%c R%02X S%02X %02X %02X\n", - (writing)?'W':'R', - (do_subreg)?'S':'D', - regnum, subreg, data_low, data_high); - reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd); - reg_cmd->bytes = sizeof(*reg_cmd) - 1; // do not count the 'bytes' field - reg_cmd->eoframe = 0; - reg_cmd->multibyte = 0; - REG_FIELD(reg_cmd, chipsel) = chipsel; - REG_FIELD(reg_cmd, reserved) = 0; /* force reserved bits to 0 */ - REG_FIELD(reg_cmd, read_request) = (writing) ? 0 : 1; - REG_FIELD(reg_cmd, do_subreg) = do_subreg; - REG_FIELD(reg_cmd, regnum) = regnum; - REG_FIELD(reg_cmd, subreg) = subreg; - REG_FIELD(reg_cmd, data_low) = data_low; - REG_FIELD(reg_cmd, data_high) = data_high; - ret = send_cmd_frame(xbus, xframe); - return ret; -} - -/* - * The XPD parameter is totaly ignored by the driver and firmware as well. - */ -/* 0x19 */ HOSTCMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift) -{ - xframe_t *xframe; - xpacket_t *pack; - const char *mode_name; - - BUG_ON(!xbus); - if((mode_name = sync_mode_name(mode)) == NULL) { - XBUS_ERR(xbus, "SYNC_SOURCE: bad sync_mode=0x%X\n", mode); - return -EINVAL; - } - XBUS_DBG(SYNC, xbus, "%s (0x%X), drift=%d\n", mode_name, mode, drift); - XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, SYNC_SOURCE, 0); - RPACKET_FIELD(pack, GLOBAL, SYNC_SOURCE, sync_mode) = mode; - RPACKET_FIELD(pack, GLOBAL, SYNC_SOURCE, drift) = drift; - send_cmd_frame(xbus, xframe); - return 0; -} - -/* 0x23 */ HOSTCMD(GLOBAL, RESET_SYNC_COUNTERS) -{ - xframe_t *xframe; - xpacket_t *pack; - - BUG_ON(!xbus); - //XBUS_DBG(SYNC, xbus, "\n"); - XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, RESET_SYNC_COUNTERS, 0); - RPACKET_FIELD(pack, GLOBAL, RESET_SYNC_COUNTERS, mask) = 0x10; - send_cmd_frame(xbus, xframe); - return 0; -} - -/*---------------- GLOBAL: Astribank Reply Handlers -----------------------*/ - -HANDLER_DEF(GLOBAL, NULL_REPLY) -{ - XBUS_DBG(GENERAL, xbus, "got len=%d\n", XPACKET_LEN(pack)); - return 0; -} - -HANDLER_DEF(GLOBAL, DEV_DESC) -{ - struct card_desc_struct *card_desc; - - BUG_ON(!xbus); - if((card_desc = KZALLOC(sizeof(struct card_desc_struct), GFP_ATOMIC)) == NULL) { - XBUS_ERR(xbus, "Card description allocation failed.\n"); - return -ENOMEM; - } - card_desc->magic = CARD_DESC_MAGIC; - INIT_LIST_HEAD(&card_desc->card_list); - card_desc->xbus = xbus; - card_desc->type = RPACKET_FIELD(pack, GLOBAL, DEV_DESC, type); - card_desc->subtype = RPACKET_FIELD(pack, GLOBAL, DEV_DESC, subtype); - card_desc->rev = RPACKET_FIELD(pack, GLOBAL, DEV_DESC, rev); - card_desc->xpd_addr = RPACKET_FIELD(pack, GLOBAL, DEV_DESC, head.addr); - card_desc->line_status = RPACKET_FIELD(pack, GLOBAL, DEV_DESC, line_status); - XBUS_DBG(GENERAL, xbus, "XPD=%d%d type=%d.%d rev=%d line_status=0x%04X\n", - card_desc->xpd_addr.unit, - card_desc->xpd_addr.subunit, - card_desc->type, - card_desc->subtype, - card_desc->rev, - card_desc->line_status); - xbus_poller_notify(xbus, card_desc); - return 0; -} - -HANDLER_DEF(GLOBAL, REGISTER_REPLY) -{ - reg_cmd_t *reg = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REPLY, regcmd); - - if(!xpd) { - XBUS_NOTICE(xbus, "%s: received %s for non-existing unit (%1d%1d)\n", - __FUNCTION__, cmd->name, - XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack)); - return -EPROTO; - } - return CALL_XMETHOD(card_register_reply, xbus, xpd, reg); -} - -HANDLER_DEF(GLOBAL, SYNC_REPLY) -{ - byte mode = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, sync_mode); - byte drift = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, drift); - const char *mode_name; - - BUG_ON(!xbus); - if((mode_name = sync_mode_name(mode)) == NULL) { - XBUS_ERR(xbus, "SYNC_REPLY: bad sync_mode=0x%X\n", mode); - return -EINVAL; - } - XBUS_DBG(SYNC, xbus, "%s (0x%X), drift=%d\n", mode_name, mode, drift); - //dump_packet("SYNC_REPLY", pack, print_dbg & DBG_SYNC); - got_new_syncer(xbus, mode, drift); - return 0; -} - -#define TMP_NAME_LEN (XBUS_NAMELEN + XPD_NAMELEN + 5) - -HANDLER_DEF(GLOBAL, ERROR_CODE) -{ - byte errorcode = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, errorcode); - reg_cmd_t *bad_cmd; - char tmp_name[TMP_NAME_LEN]; - static long rate_limit; - - BUG_ON(!xbus); - if((rate_limit++ % 5003) > 200) - return 0; - if(!xpd) { - snprintf(tmp_name, TMP_NAME_LEN, "%s(%1d%1d)", xbus->busname, - XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack)); - } else { - snprintf(tmp_name, TMP_NAME_LEN, "%s/%s", xbus->busname, xpd->xpdname); - } - NOTICE("%s: FIRMWARE: %s CODE = 0x%X (rate_limit=%ld)\n", - tmp_name, cmd->name, errorcode, rate_limit); - switch(errorcode) { - case 1: - bad_cmd = &RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, info.bad_spi_cmd); - dump_packet("FIRMWARE: BAD_SPI_CMD", pack, 1); - break; - case 0xAB: - dump_packet("FIRMWARE: BAD_PACKET_LEN", pack, 1); - break; - default: - NOTICE("%s: FIRMWARE: %s UNKNOWN CODE = 0x%X\n", tmp_name, cmd->name, errorcode); - dump_packet("PACKET", pack, 1); - } - /* - * FIXME: Should implement an error recovery plan - */ - return 0; -} - - -xproto_table_t PROTO_TABLE(GLOBAL) = { - .entries = { - /* Prototable Card Opcode */ - XENTRY( GLOBAL, GLOBAL, NULL_REPLY ), - XENTRY( GLOBAL, GLOBAL, DEV_DESC ), - XENTRY( GLOBAL, GLOBAL, SYNC_REPLY ), - XENTRY( GLOBAL, GLOBAL, ERROR_CODE ), - XENTRY( GLOBAL, GLOBAL, REGISTER_REPLY ), - }, - .name = "GLOBAL", - .packet_is_valid = global_packet_is_valid, - .packet_dump = global_packet_dump, -}; - -static bool global_packet_is_valid(xpacket_t *pack) -{ - const xproto_entry_t *xe; - - //DBG(GENERAL, "\n"); - xe = xproto_global_entry(XPACKET_OP(pack)); - return xe != NULL; -} - -static void global_packet_dump(const char *msg, xpacket_t *pack) -{ - DBG(GENERAL, "%s\n", msg); -} - -#define MAX_ENV_STR 40 -#define MAX_PATH_STR 60 - -int run_initialize_registers(xpd_t *xpd) -{ - int ret; - xbus_t *xbus; - char busstr[MAX_ENV_STR]; - char xpdstr[MAX_ENV_STR]; - char unitstr[MAX_ENV_STR]; - char subunitstr[MAX_ENV_STR]; - char typestr[MAX_ENV_STR]; - char revstr[MAX_ENV_STR]; - char connectorstr[MAX_ENV_STR]; - char init_card[MAX_PATH_STR]; - char *argv[] = { - init_card, - NULL - }; - char *envp[] = { - busstr, - xpdstr, - unitstr, - subunitstr, - typestr, - revstr, - connectorstr, - NULL - }; - - BUG_ON(!xpd); - xbus = xpd->xbus; - if(!initdir || !initdir[0]) { - XPD_NOTICE(xpd, "Missing initdir parameter\n"); - return -EINVAL; - } - snprintf(busstr, MAX_ENV_STR, "XPD_BUS=%s", xbus->busname); - snprintf(xpdstr, MAX_ENV_STR, "XPD_NAME=%s", xpd->xpdname); - snprintf(unitstr, MAX_ENV_STR, "XPD_UNIT=%d", xpd->addr.unit); - snprintf(subunitstr, MAX_ENV_STR, "XPD_SUBUNIT=%d", xpd->addr.subunit); - snprintf(typestr, MAX_ENV_STR, "XPD_TYPE=%d", xpd->type); - snprintf(revstr, MAX_ENV_STR, "XPD_REVISION=%d", xpd->revision); - snprintf(connectorstr, MAX_ENV_STR, "XBUS_CONNECTOR=%s", xbus->busdesc); - if(snprintf(init_card, MAX_PATH_STR, "%s/init_card_%d_%d", - initdir, xpd->type, xpd->revision) > MAX_PATH_STR) { - XPD_NOTICE(xpd, "Cannot initialize. pathname is longer than %d characters.\n", MAX_PATH_STR); - return -E2BIG; - } - if(!XBUS_GET(xbus)) { - XBUS_ERR(xbus, "Skipped register initialization. XBUS is going down\n"); - return -ENODEV; - } - XPD_DBG(GENERAL, xpd, "running '%s' for type=%d revision=%d\n", - init_card, xpd->type, xpd->revision); - ret = call_usermodehelper(init_card, argv, envp, 1); - /* - * Carefully report results - */ - if(ret == 0) - XPD_DBG(GENERAL, xpd, "'%s' finished OK\n", init_card); - else if(ret < 0) { - XPD_ERR(xpd, "Failed running '%s' (errno %d)\n", init_card, ret); - } else { - byte exitval = ((unsigned)ret >> 8) & 0xFF; - byte sigval = ret & 0xFF; - - if(!exitval) { - XPD_ERR(xpd, "'%s' killed by signal %d\n", init_card, sigval); - } else { - XPD_ERR(xpd, "'%s' aborted with exitval %d\n", init_card, exitval); - } - ret = -EINVAL; - } - XBUS_PUT(xbus); - return ret; -} - -EXPORT_SYMBOL(sync_mode_name); -EXPORT_SYMBOL(run_initialize_registers); -EXPORT_SYMBOL(xpp_register_request); diff --git a/xpp/card_global.h b/xpp/card_global.h deleted file mode 100644 index 250f4f4..0000000 --- a/xpp/card_global.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef CARD_GLOBAL_H -#define CARD_GLOBAL_H -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "xdefs.h" -#include "xbus-pcm.h" - -enum global_opcodes { - XPROTO_NAME(GLOBAL, DESC_REQ) = 0x04, - XPROTO_NAME(GLOBAL, DEV_DESC) = 0x05, - XPROTO_NAME(GLOBAL, REGISTER_REQUEST) = 0x0F, - XPROTO_NAME(GLOBAL, REGISTER_REPLY) = 0x10, -/**/ - XPROTO_NAME(GLOBAL, PCM_WRITE) = 0x11, - XPROTO_NAME(GLOBAL, PCM_READ) = 0x12, -/**/ - XPROTO_NAME(GLOBAL, SYNC_SOURCE) = 0x19, - XPROTO_NAME(GLOBAL, SYNC_REPLY) = 0x1A, -/**/ - XPROTO_NAME(GLOBAL, ERROR_CODE) = 0x22, - XPROTO_NAME(GLOBAL, RESET_SYNC_COUNTERS) = 0x23, - XPROTO_NAME(GLOBAL, NULL_REPLY) = 0xFE, -}; - -DEF_RPACKET_DATA(GLOBAL, NULL_REPLY); -DEF_RPACKET_DATA(GLOBAL, DESC_REQ); -DEF_RPACKET_DATA(GLOBAL, DEV_DESC, - byte rev; /* Revision number */ - byte type:4; /* LSB: 1 - to_phone, 0 - to_line */ - byte subtype:4; /* default 0 */ - xpp_line_t line_status; /* hook/ring status, depending on unit */ - ); -DEF_RPACKET_DATA(GLOBAL, REGISTER_REQUEST, - reg_cmd_t reg_cmd; - ); -DEF_RPACKET_DATA(GLOBAL, PCM_WRITE, - xpp_line_t lines; - byte pcm[PCM_CHUNKSIZE]; - ); -DEF_RPACKET_DATA(GLOBAL, PCM_READ, - xpp_line_t lines; - byte pcm[PCM_CHUNKSIZE]; - ); -DEF_RPACKET_DATA(GLOBAL, SYNC_SOURCE, - byte sync_mode; - byte drift; - ); -DEF_RPACKET_DATA(GLOBAL, SYNC_REPLY, - byte sync_mode; - byte drift; - ); -DEF_RPACKET_DATA(GLOBAL, REGISTER_REPLY, - reg_cmd_t regcmd; - ); -DEF_RPACKET_DATA(GLOBAL, RESET_SYNC_COUNTERS, - byte mask; - ); -DEF_RPACKET_DATA(GLOBAL, ERROR_CODE, - byte errorcode; - union { - reg_cmd_t bad_spi_cmd; - } info; - ); - -/* 0x04 */ DECLARE_CMD(GLOBAL, DESC_REQ, int xpd_num); -/* 0x19 */ DECLARE_CMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift); -/* 0x23 */ DECLARE_CMD(GLOBAL, RESET_SYNC_COUNTERS); - -int xpp_register_request(xbus_t *xbus, xpd_t *xpd, - byte chipsel, bool writing, bool do_subreg, byte regnum, byte subreg, byte data_low, byte data_high); -extern xproto_table_t PROTO_TABLE(GLOBAL); -int run_initialize_registers(xpd_t *xpd); - -#endif /* CARD_GLOBAL_H */ diff --git a/xpp/card_pri.c b/xpp/card_pri.c deleted file mode 100644 index e055953..0000000 --- a/xpp/card_pri.c +++ /dev/null @@ -1,1673 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * Parts derived from Cologne demo driver for the chip. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include "xpd.h" -#include "xproto.h" -#include "xpp_zap.h" -#include "card_pri.h" -#include "zap_debug.h" -#include "xpd.h" -#include "xbus-core.h" - -static const char rcsid[] = "$Id$"; - -DEF_PARM(int, print_dbg, 0, 0644, "Print DBG statements"); /* must be before zap_debug.h */ -DEF_PARM(uint, poll_interval, 500, 0644, "Poll channel state interval in milliseconds (0 - disable)"); -#ifdef DEBUG_PCMTX -DEF_PARM(int, pcmtx, -1, 0644, "Forced PCM value to transmit (negative to disable)"); -DEF_PARM(int, pcmtx_chan, 0, 0644, "channel to force PCM value"); -#endif - -#define PRI_LINES_BITMASK BITMASK(31) -#define PRI_DCHAN_SIGCAP ( \ - ZT_SIG_EM | \ - ZT_SIG_CLEAR | \ - ZT_SIG_FXSLS | \ - ZT_SIG_FXSGS | \ - ZT_SIG_FXSKS | \ - ZT_SIG_FXOLS | \ - ZT_SIG_FXOGS | \ - ZT_SIG_FXOKS | \ - ZT_SIG_CAS | \ - ZT_SIG_SF \ - ) -#define PRI_BCHAN_SIGCAP ZT_SIG_CLEAR - - -/*---------------- PRI Protocol Commands ----------------------------------*/ - -static bool pri_packet_is_valid(xpacket_t *pack); -static void pri_packet_dump(const char *msg, xpacket_t *pack); -static int proc_pri_info_read(char *page, char **start, off_t off, int count, int *eof, void *data); -static int proc_pri_info_write(struct file *file, const char __user *buffer, unsigned long count, void *data); -static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data); -static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data); -static int pri_startup(struct zt_span *span); -static int pri_shutdown(struct zt_span *span); - -#define PROC_REGISTER_FNAME "slics" -#define PROC_PRI_INFO_FNAME "pri_info" - -#define VALID_CHIPSEL(x) ((x) == 0) - -enum pri_protocol { - PRI_PROTO_0 = 0, - PRI_PROTO_E1 = 1, - PRI_PROTO_T1 = 2, - PRI_PROTO_J1 = 3 -}; - -static const char *pri_protocol_name(enum pri_protocol pri_protocol) -{ - static const char *protocol_names[] = { - [PRI_PROTO_0] = "Unknown", - [PRI_PROTO_E1] = "E1", - [PRI_PROTO_T1] = "T1", - [PRI_PROTO_J1] = "J1" - }; - return protocol_names[pri_protocol]; -} - -static int pri_num_channels(enum pri_protocol pri_protocol) -{ - static int num_channels[] = { - [PRI_PROTO_0] = 0, - [PRI_PROTO_E1] = 31, - [PRI_PROTO_T1] = 24, - [PRI_PROTO_J1] = 0 - }; - return num_channels[pri_protocol]; -} - -static const char *type_name(enum pri_protocol pri_protocol, bool is_nt) -{ - static const char *names[2][4] = { - /* TE */ [0] = { - [PRI_PROTO_0] = "Unknown_TE", - [PRI_PROTO_E1] = "E1_TE", - [PRI_PROTO_T1] = "T1_TE", - [PRI_PROTO_J1] = "J1_TE" - }, - /* NT */ [1] = { - [PRI_PROTO_0] = "Unknown_NT", - [PRI_PROTO_E1] = "E1_NT", - [PRI_PROTO_T1] = "T1_NT", - [PRI_PROTO_J1] = "J1_NT" - } - }; - int term = (is_nt) ? 1 : 0; - - return names[term][pri_protocol]; -} - -static int pri_linecompat(enum pri_protocol pri_protocol) -{ - static const int linecompat[] = { - [PRI_PROTO_0] = 0, - [PRI_PROTO_E1] = - /* coding */ - ZT_CONFIG_CCS | - // CAS | - ZT_CONFIG_CRC4 | - /* framing */ - ZT_CONFIG_AMI | ZT_CONFIG_HDB3, - [PRI_PROTO_T1] = - /* coding */ - // ZT_CONFIG_D4 | - ZT_CONFIG_ESF | - /* framing */ - ZT_CONFIG_AMI | ZT_CONFIG_B8ZS, - [PRI_PROTO_J1] = 0 - }; - - DBG(GENERAL, "pri_linecompat: pri_protocol=%d\n", pri_protocol); - return linecompat[pri_protocol]; -} - -#define PRI_DCHAN_IDX(priv) ((priv)->dchan_num - 1) - -enum pri_led_state { - PRI_LED_OFF = 0x0, - PRI_LED_ON = 0x1, - /* - * We blink by software from driver, so that - * if the driver malfunction that blink would stop. - */ - // PRI_LED_BLINK_SLOW = 0x2, /* 1/2 a second blink cycle */ - // PRI_LED_BLINK_FAST = 0x3 /* 1/4 a second blink cycle */ -}; - -enum pri_led_selectors { - TE_RED_LED = 0, - TE_GREEN_LED = 1, - NT_RED_LED = 2, - NT_GREEN_LED = 3, -}; - -#define NUM_LEDS 4 - -struct pri_leds { - byte state:2; /* enum pri_led_state */ - byte led_sel:2; /* enum pri_led_selectors */ - byte reserved:4; -}; - -#define REG_FRS0 0x4C /* Framer Receive Status Register 0 */ -#define REG_FRS0_RRA BIT(4) /* Receive Remote Alarm: T1-YELLOW-Alarm */ -#define REG_FRS0_LFA BIT(5) /* Loss of Frame Alignment */ -#define REG_FRS0_AIS BIT(6) /* Alarm Indication Signal: T1-BLUE-Alarm */ -#define REG_FRS0_LOS BIT(7) /* Los Of Signal: T1-RED-Alarm */ - -#define REG_FRS1 0x4D /* Framer Receive Status Register 1 */ - -#define REG_LIM0 0x36 -#define REG_LIM0_MAS BIT(0) /* Master Mode, DCO-R circuitry is frequency - synchronized to the clock supplied by SYNC */ -#define REG_LIM0_RTRS BIT(5) /* - * Receive Termination Resistance Selection: - * integrated resistor to create 75 Ohm termination (100 || 300 = 75) - * 0 = 100 Ohm - * 1 = 75 Ohm - */ -#define REG_LIM0_LL BIT(1) /* LL (Local Loopback) */ - -#define REG_FMR0 0x1C -#define REG_FMR0_E_RC0 BIT(4) /* Receive Code - LSB */ -#define REG_FMR0_E_RC1 BIT(5) /* Receive Code - MSB */ -#define REG_FMR0_E_XC0 BIT(6) /* Transmit Code - LSB */ -#define REG_FMR0_E_XC1 BIT(7) /* Transmit Code - MSB */ - -#define REG_FMR1 0x1D -#define REG_FMR1_XAIS BIT(0) /* Transmit AIS toward transmit end */ -#define REG_FMR1_SSD0 BIT(1) -#define REG_FMR1_ECM BIT(2) -#define REG_FMR1_XFS BIT(3) -#define REG_FMR1_PMOD BIT(4) /* E1 = 0, T1/J1 = 1 */ -#define REG_FMR1_EDL BIT(5) -#define REG_FMR1_AFR BIT(6) - -#define REG_FMR2 0x1E -#define REG_FMR2_E_ALMF BIT(0) /* Automatic Loss of Multiframe */ -#define REG_FMR2_T_EXZE BIT(0) /* Excessive Zeros Detection Enable */ -#define REG_FMR2_E_AXRA BIT(1) /* Automatic Transmit Remote Alarm */ -#define REG_FMR2_T_AXRA BIT(1) /* Automatic Transmit Remote Alarm */ -#define REG_FMR2_E_PLB BIT(2) /* Payload Loop-Back */ -#define REG_FMR2_E_RFS0 BIT(6) /* Receive Framing Select - LSB */ -#define REG_FMR2_E_RFS1 BIT(7) /* Receive Framing Select - MSB */ -#define REG_FMR2_T_SSP BIT(5) /* Select Synchronization/Resynchronization Procedure */ -#define REG_FMR2_T_MCSP BIT(6) /* Multiple Candidates Synchronization Procedure */ -#define REG_FMR2_T_AFRS BIT(7) /* Automatic Force Resynchronization */ - -#define REG_FMR4 0x20 -#define REG_FMR4_FM1 BIT(1) - -#define REG_XSP_E 0x21 -#define REG_FMR5_T 0x21 -#define REG_XSP_E_XSIF BIT(2) /* Transmit Spare Bit For International Use (FAS Word) */ -#define REG_FMR5_T_XTM BIT(2) /* Transmit Transparent Mode */ -#define REG_XSP_E_AXS BIT(3) /* Automatic Transmission of Submultiframe Status */ -#define REG_XSP_E_EBP BIT(4) /* E-Bit Polarity, Si-bit position of every outgoing CRC multiframe */ -#define REG_XSP_E_CASEN BIT(7) /* Channel Associated Signaling Enable */ - -#define REG_RC0 0x24 -#define REG_RC0_SJR BIT(7) /* T1 = 0, J1 = 1 */ - - -struct PRI_priv_data { - bool is_nt; - struct proc_dir_entry *regfile; - struct proc_dir_entry *pri_info; - enum pri_protocol pri_protocol; - int deflaw; - unsigned int dchan_num; - bool initialized; - bool local_loopback; - reg_cmd_t requested_reply; - reg_cmd_t last_reply; - uint poll_noreplies; - uint layer1_replies; - byte reg_frs0; - byte reg_frs1; - bool layer1_up; - byte dchan_tx_sample; - byte dchan_rx_sample; - uint dchan_tx_counter; - uint dchan_rx_counter; - bool dchan_alive; - uint dchan_alive_ticks; - enum pri_led_state ledstate[NUM_LEDS]; -}; - -static xproto_table_t PROTO_TABLE(PRI); - -DEF_RPACKET_DATA(PRI, SET_LED, /* Set one of the LED's */ - struct pri_leds pri_leds; - ); - - -static /* 0x33 */ DECLARE_CMD(PRI, SET_LED, enum pri_led_selectors led_sel, enum pri_led_state to_led_state); - -#define DO_LED(xpd, which, tostate) \ - CALL_PROTO(PRI, SET_LED, (xpd)->xbus, (xpd), (which), (tostate)) - -/*---------------- PRI: Methods -------------------------------------------*/ - -static int query_subunit(xpd_t *xpd, byte regnum) -{ -#if 0 - XPD_DBG(GENERAL, xpd, "(%d%d): REG=0x%02X\n", - xpd->addr.unit, xpd->addr.subunit, - regnum); -#endif - return xpp_register_request( - xpd->xbus, xpd, - 0, /* chipsel */ - 0, /* writing */ - 1, /* do_subreg */ - regnum, - xpd->addr.subunit, /* subreg */ - 0, /* data_L */ - 0); /* data_H */ -} - - -static int write_subunit(xpd_t *xpd, byte regnum, byte val) -{ - XPD_DBG(REGS, xpd, "(%d%d): REG=0x%02X dataL=0x%02X\n", - xpd->addr.unit, xpd->addr.subunit, - regnum, val); - return xpp_register_request( - xpd->xbus, xpd, - 0, /* chipsel */ - 1, /* writing */ - 1, /* do_subreg */ - regnum, - xpd->addr.subunit, /* subreg */ - val, /* data_L */ - 0); /* data_H */ -} - -static xpd_t *PRI_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table, byte subtype, byte revision) -{ - xpd_t *xpd = NULL; - struct PRI_priv_data *priv; - int channels = min(31, CHANNELS_PERXPD); /* worst case */ - - XBUS_DBG(GENERAL, xbus, "\n"); - xpd = xpd_alloc(sizeof(struct PRI_priv_data), proto_table, channels); - if(!xpd) - return NULL; - priv = xpd->priv; - xpd->revision = revision; - priv->pri_protocol = PRI_PROTO_0; /* Default, changes in set_pri_proto() */ - priv->deflaw = ZT_LAW_DEFAULT; /* Default, changes in set_pri_proto() */ - xpd->type_name = - type_name(priv->pri_protocol, 0); /* Default, changes in set_nt() */ - return xpd; -} - -static void clean_proc(xbus_t *xbus, xpd_t *xpd) -{ - struct PRI_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - XPD_DBG(PROC, xpd, "\n"); -#ifdef CONFIG_PROC_FS - if(priv->regfile) { - XPD_DBG(PROC, xpd, "Removing registers file\n"); - priv->regfile->data = NULL; - remove_proc_entry(PROC_REGISTER_FNAME, xpd->proc_xpd_dir); - } - if(priv->pri_info) { - XPD_DBG(PROC, xpd, "Removing xpd PRI_INFO file\n"); - remove_proc_entry(PROC_PRI_INFO_FNAME, xpd->proc_xpd_dir); - } -#endif -} - -static bool valid_pri_modes(const xpd_t *xpd) -{ - struct PRI_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - if( - priv->pri_protocol != PRI_PROTO_E1 && - priv->pri_protocol != PRI_PROTO_T1 && - priv->pri_protocol != PRI_PROTO_J1) - return 0; - return 1; -} - -/* - * Set E1/T1/J1 - * May only be called on unregistered xpd's - * (the span and channel description are set according to this) - */ -static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto) -{ - struct PRI_priv_data *priv; - int deflaw; - unsigned int dchan_num; - byte fmr1 = - REG_FMR1_AFR | - REG_FMR1_XFS | - REG_FMR1_ECM; - byte rc0 = 0; /* FIXME: PCM offsets */ - - BUG_ON(!xpd); - priv = xpd->priv; - if(SPAN_REGISTERED(xpd)) { - XPD_NOTICE(xpd, "Registered as span %d. Cannot do setup pri protocol (%s)\n", - xpd->span.spanno, __FUNCTION__); - return -EBUSY; - } - switch(set_proto) { - case PRI_PROTO_E1: - deflaw = ZT_LAW_ALAW; - dchan_num = 16; - break; - case PRI_PROTO_T1: - deflaw = ZT_LAW_MULAW; - dchan_num = 24; - fmr1 |= REG_FMR1_PMOD; - break; - case PRI_PROTO_J1: - /* - * Check all assumptions - */ - deflaw = ZT_LAW_MULAW; - dchan_num = 24; - fmr1 |= REG_FMR1_PMOD; - rc0 |= REG_RC0_SJR; - XPD_NOTICE(xpd, "J1 is not supported yet\n"); - return -ENOSYS; - default: - XPD_ERR(xpd, "%s: Unknown pri protocol = %d\n", - __FUNCTION__, set_proto); - return -EINVAL; - } - priv->pri_protocol = set_proto; - xpd->channels = pri_num_channels(set_proto); - xpd->pcm_len = RPACKET_HEADERSIZE + sizeof(xpp_line_t) + xpd->channels * ZT_CHUNKSIZE; - xpd->wanted_pcm_mask = BITMASK(xpd->channels); - priv->deflaw = deflaw; - priv->dchan_num = dchan_num; - xpd->type_name = type_name(priv->pri_protocol, priv->is_nt); - XPD_DBG(GENERAL, xpd, "%s, channels=%d, dchan_num=%d, deflaw=%d\n", - pri_protocol_name(set_proto), - xpd->channels, - priv->dchan_num, - priv->deflaw - ); - write_subunit(xpd, REG_FMR1, fmr1); -#ifdef JAPANEZE_SUPPORT - if(rc0) - write_subunit(xpd, REG_RC0, rc0); -#endif - return 0; -} - -/* - * Normally set by the timing parameter in zaptel.conf - * If this is called by ztcfg, than it's too late to change - * zaptel sync priority (we are already registered) - * There are two workarounds to mitigate this problem: - * 1. So we set *our* sync master at least. - * 2. And we try to call it with a sane default from set_nt() - * which is called before zaptel registration. - */ -static int set_master_mode(const char *msg, xpd_t *xpd, bool is_master_mode) -{ - struct PRI_priv_data *priv; - byte lim0 = 0; - byte xsp = 0; - - BUG_ON(!xpd); - priv = xpd->priv; - lim0 |= (priv->local_loopback) ? REG_LIM0_LL : 0; - if(is_master_mode) - lim0 |= REG_LIM0_MAS; - else - lim0 &= ~REG_LIM0_MAS; - if(priv->pri_protocol == PRI_PROTO_E1) - { - lim0 |= REG_LIM0_RTRS; /* Receive termination: Integrated resistor is switched on (100 Ohm || 300 Ohm = 75 Ohm) */ - xsp |= REG_XSP_E_EBP | REG_XSP_E_AXS | REG_XSP_E_XSIF; - } else if(priv->pri_protocol == PRI_PROTO_T1) { - lim0 &= ~REG_LIM0_RTRS; /* Receive termination: Integrated resistor is switched off (100 Ohm, no internal 300 Ohm) */; - xsp |= REG_FMR5_T_XTM; - } - XPD_DBG(SIGNAL, xpd, "%s(%s): %s\n", __FUNCTION__, msg, (is_master_mode) ? "MASTER" : "SLAVE"); - write_subunit(xpd, REG_LIM0 , lim0); - write_subunit(xpd, REG_XSP_E, xsp); - return 0; -} - -static int set_nt(const char *msg, xpd_t *xpd, bool is_nt) -{ - struct PRI_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - if(SPAN_REGISTERED(xpd)) { - XPD_NOTICE(xpd, "Registered as span %d. Cannot do %s(%s)\n", - xpd->span.spanno, __FUNCTION__, msg); - return -EBUSY; - } - priv->is_nt = is_nt; - xpd->type_name = type_name(priv->pri_protocol, is_nt); - xpd->direction = (is_nt) ? TO_PHONE : TO_PSTN; - XPD_DBG(SIGNAL, xpd, "%s(%s): %s %s\n", __FUNCTION__, msg, xpd->type_name, (is_nt) ? "NT" : "TE"); - set_master_mode(msg, xpd, is_nt); /* by default set master-mode from NT/TE */ - return 0; -} - -static int set_localloop(const char *msg, xpd_t *xpd, bool localloop) -{ - struct PRI_priv_data *priv; - byte lim0 = 0; - byte xsp = 0; - - BUG_ON(!xpd); - priv = xpd->priv; - if(SPAN_REGISTERED(xpd)) { - XPD_NOTICE(xpd, "Registered as span %d. Cannot do %s(%s)\n", - xpd->span.spanno, __FUNCTION__, msg); - return -EBUSY; - } - lim0 |= (localloop) ? REG_LIM0_LL : 0; - if(priv->is_nt) - lim0 |= REG_LIM0_MAS; - else - lim0 &= ~REG_LIM0_MAS; - if(priv->pri_protocol == PRI_PROTO_E1) - { - lim0 |= REG_LIM0_RTRS; /* Receive termination: Integrated resistor is switched on (100 Ohm || 300 Ohm = 75 Ohm) */ - xsp |= REG_XSP_E_EBP | REG_XSP_E_AXS | REG_XSP_E_XSIF; - } else if(priv->pri_protocol == PRI_PROTO_T1) { - lim0 &= ~REG_LIM0_RTRS ; /* Receive termination: Integrated resistor is switched off (100 Ohm, no internal 300 Ohm) */; - xsp |= REG_FMR5_T_XTM; - } - priv->local_loopback = localloop; - XPD_DBG(SIGNAL, xpd, "%s(%s): %s\n", __FUNCTION__, msg, (localloop) ? "LOCALLOOP" : "NO"); - write_subunit(xpd, REG_LIM0 , lim0); - write_subunit(xpd, REG_XSP_E, xsp); - return 0; -} - -#define VALID_CONFIG(bit,flg,str) [bit] = { .flags = flg, .name = str } - -static const struct { - const char *name; - const int flags; -} valid_spanconfigs[sizeof(unsigned int)*8] = { - /* These apply to T1 */ -// VALID_CONFIG(4, ZT_CONFIG_D4, "D4"), FIXME: should support - VALID_CONFIG(5, ZT_CONFIG_ESF, "ESF"), - VALID_CONFIG(6, ZT_CONFIG_AMI, "AMI"), - VALID_CONFIG(7, ZT_CONFIG_B8ZS, "B8ZS"), - /* These apply to E1 */ - VALID_CONFIG(8, ZT_CONFIG_CCS, "CCS"), - VALID_CONFIG(9, ZT_CONFIG_HDB3, "HDB3"), - VALID_CONFIG(10, ZT_CONFIG_CRC4, "CRC4"), -}; - -/* - * Called only for 'span' keyword in /etc/zaptel.conf - */ - -static int pri_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) -{ - xpd_t *xpd = span->pvt; - struct PRI_priv_data *priv; - const char *framingstr = ""; - const char *codingstr = ""; - const char *crcstr = ""; - byte fmr0 = 0; /* Dummy initilizations to */ - byte fmr2 = 0; /* silense false gcc warnings */ - byte fmr4 = 0x0C; - unsigned int bad_bits; - int i; - - BUG_ON(!xpd); - priv = xpd->priv; - /* - * validate - */ - bad_bits = lc->lineconfig & pri_linecompat(priv->pri_protocol); - bad_bits = bad_bits ^ lc->lineconfig; - for(i = 0; i < ARRAY_SIZE(valid_spanconfigs); i++) { - unsigned int flags = valid_spanconfigs[i].flags; - - if(bad_bits & BIT(i)) { - if(flags) { - XPD_ERR(xpd, - "Bad config item '%s' for %s. Ignore\n", - valid_spanconfigs[i].name, - pri_protocol_name(priv->pri_protocol)); - } else { - /* we got real garbage */ - XPD_ERR(xpd, - "Unknown config item 0x%X for %s. Ignore\n", - BIT(i), - pri_protocol_name(priv->pri_protocol)); - } - } - if(flags && flags != BIT(i)) { - ERR("%s: BUG: i=%d flags=0x%X\n", - __FUNCTION__, i, flags); - // BUG(); - } - } - if(bad_bits) - goto bad_lineconfig; - if(lc->span != xpd->span.spanno) { - XPD_ERR(xpd, "I am span %d but got spanconfig for span %d\n", - xpd->span.spanno, lc->span); - return -EINVAL; - } - /* - * FIXME: lc->name is unused by ztcfg and zaptel... - * We currently ignore it also. - */ - if(priv->pri_protocol == PRI_PROTO_E1) - fmr2 = REG_FMR2_E_AXRA | REG_FMR2_E_ALMF; /* 0x03 */ - else if(priv->pri_protocol == PRI_PROTO_T1) - fmr2 = REG_FMR2_T_SSP | REG_FMR2_T_AXRA; /* 0x22 */ - else if(priv->pri_protocol == PRI_PROTO_J1) { - XPD_ERR(xpd, "J1 unsupported yet\n"); - return -ENOSYS; - } - if(priv->local_loopback) - fmr2 |= REG_FMR2_E_PLB; - /* framing first */ - if (lc->lineconfig & ZT_CONFIG_B8ZS) { - framingstr = "B8ZS"; - fmr0 = REG_FMR0_E_XC1 | REG_FMR0_E_XC0 | REG_FMR0_E_RC1 | REG_FMR0_E_RC0; - } else if (lc->lineconfig & ZT_CONFIG_AMI) { - framingstr = "AMI"; - fmr0 = REG_FMR0_E_XC1 | REG_FMR0_E_RC1; - } else if (lc->lineconfig & ZT_CONFIG_HDB3) { - framingstr = "HDB3"; - fmr0 = REG_FMR0_E_XC1 | REG_FMR0_E_XC0 | REG_FMR0_E_RC1 | REG_FMR0_E_RC0; - } - /* then coding */ - if (lc->lineconfig & ZT_CONFIG_ESF) { - codingstr = "ESF"; - fmr4 |= REG_FMR4_FM1; - fmr2 |= REG_FMR2_T_AXRA | REG_FMR2_T_MCSP | REG_FMR2_T_SSP; - } else if (lc->lineconfig & ZT_CONFIG_D4) { - codingstr = "D4"; - } else if (lc->lineconfig & ZT_CONFIG_CCS) { - codingstr = "CCS"; - /* do nothing */ - } - /* E1's can enable CRC checking */ - if (lc->lineconfig & ZT_CONFIG_CRC4) { - crcstr = "CRC4"; - fmr2 |= REG_FMR2_E_RFS1; - } - XPD_DBG(GENERAL, xpd, "[%s] lbo=%d lineconfig=%s/%s/%s %s (0x%X) sync=%d\n", - (priv->is_nt)?"NT":"TE", - lc->lbo, - framingstr, codingstr, crcstr, - (lc->lineconfig & ZT_CONFIG_NOTOPEN)?"YELLOW":"", - lc->lineconfig, - lc->sync); - span->lineconfig = lc->lineconfig; - xpd->timing_priority = lc->sync; - if(fmr0 != 0) { - XPD_DBG(GENERAL, xpd, "%s: fmr0(0x%02X) = 0x%02X\n", __FUNCTION__, REG_FMR0, fmr0); - write_subunit(xpd, REG_FMR0, fmr0); - } - XPD_DBG(GENERAL, xpd, "%s: fmr4(0x%02X) = 0x%02X\n", __FUNCTION__, REG_FMR4, fmr4); - write_subunit(xpd, REG_FMR4, fmr4); - XPD_DBG(GENERAL, xpd, "%s: fmr2(0x%02X) = 0x%02X\n", __FUNCTION__, REG_FMR2, fmr2); - write_subunit(xpd, REG_FMR2, fmr2); - set_master_mode("spanconfig", xpd, xpd->timing_priority == 0); - elect_syncer("PRI-master_mode"); - return 0; -bad_lineconfig: - XPD_ERR(xpd, "Bad span configuration. Abort\n"); - return -EINVAL; -} - -/* - * Set signalling type (if appropriate) - * Called from zaptel with spinlock held on chan. Must not call back - * zaptel functions. - */ -static int pri_chanconfig(struct zt_chan *chan, int sigtype) -{ - DBG(GENERAL, "channel %d (%s) -> %s\n", chan->channo, chan->name, sig2str(sigtype)); - // FIXME: sanity checks: - // - should be supported (within the sigcap) - // - should not replace fxs <->fxo ??? (covered by previous?) - return 0; -} - -static int PRI_card_init(xbus_t *xbus, xpd_t *xpd) -{ - struct PRI_priv_data *priv; - int ret = 0; - xproto_table_t *proto_table; - - BUG_ON(!xpd); - XPD_DBG(GENERAL, xpd, "\n"); - xpd->type = XPD_TYPE_PRI; - proto_table = &PROTO_TABLE(PRI); - priv = xpd->priv; - xpd->xops = &proto_table->xops; -#ifdef CONFIG_PROC_FS - XPD_DBG(PROC, xpd, "Creating PRI_INFO file\n"); - priv->pri_info = create_proc_entry(PROC_PRI_INFO_FNAME, 0644, xpd->proc_xpd_dir); - if(!priv->pri_info) { - XPD_ERR(xpd, "Failed to create proc '%s'\n", PROC_PRI_INFO_FNAME); - ret = -ENOENT; - goto err; - } - priv->pri_info->owner = THIS_MODULE; - priv->pri_info->write_proc = proc_pri_info_write; - priv->pri_info->read_proc = proc_pri_info_read; - priv->pri_info->data = xpd; - XPD_DBG(PROC, xpd, "Creating registers file\n"); - priv->regfile = create_proc_entry(PROC_REGISTER_FNAME, 0644, xpd->proc_xpd_dir); - if(!priv->regfile) { - XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_REGISTER_FNAME); - ret = -ENOENT; - goto err; - } - priv->regfile->owner = THIS_MODULE; - priv->regfile->write_proc = proc_xpd_register_write; - priv->regfile->read_proc = proc_xpd_register_read; - priv->regfile->data = xpd; -#endif - /* Assume E1, changes later from user space */ - ret = set_pri_proto(xpd, PRI_PROTO_E1); - if(ret < 0) - goto err; - ret = run_initialize_registers(xpd); - if(ret < 0) - goto err; - /* - * initialization script should have set correct - * operating modes. - */ - if(!valid_pri_modes(xpd)) { - XPD_NOTICE(xpd, "PRI protocol not set\n"); - goto err; - } - XPD_DBG(GENERAL, xpd, "done\n"); - for(ret = 0; ret < NUM_LEDS; ret++) { - DO_LED(xpd, ret, PRI_LED_ON); - msleep(20); - DO_LED(xpd, ret, PRI_LED_OFF); - } - priv->initialized = 1; - return 0; -err: - clean_proc(xbus, xpd); - XPD_ERR(xpd, "Failed initializing registers (%d)\n", ret); - return ret; -} - -static int PRI_card_remove(xbus_t *xbus, xpd_t *xpd) -{ - struct PRI_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - XPD_DBG(GENERAL, xpd, "\n"); - clean_proc(xbus, xpd); - return 0; -} - -static int PRI_card_zaptel_preregistration(xpd_t *xpd, bool on) -{ - xbus_t *xbus; - struct PRI_priv_data *priv; - int i; - - BUG_ON(!xpd); - xbus = xpd->xbus; - priv = xpd->priv; - BUG_ON(!xbus); - XPD_DBG(GENERAL, xpd, "%s (proto=%s, channels=%d, deflaw=%d)\n", - (on)?"on":"off", - pri_protocol_name(priv->pri_protocol), - xpd->channels, - priv->deflaw); - if(!on) { - /* Nothing to do yet */ - return 0; - } - xpd->span.linecompat = pri_linecompat(priv->pri_protocol); - xpd->span.deflaw = priv->deflaw; - for_each_line(xpd, i) { - struct zt_chan *cur_chan = &xpd->chans[i]; - bool is_dchan = i == PRI_DCHAN_IDX(priv); - - XPD_DBG(GENERAL, xpd, "setting PRI channel %d (%s)\n", i, - (is_dchan)?"DCHAN":"CLEAR"); - snprintf(cur_chan->name, MAX_CHANNAME, "XPP_%s/%02d/%1d%1d/%d", - xpd->type_name, xbus->num, xpd->addr.unit, xpd->addr.subunit, i); - cur_chan->chanpos = i + 1; - cur_chan->pvt = xpd; - if(is_dchan) { /* D-CHAN */ - cur_chan->sigcap = PRI_DCHAN_SIGCAP; - //FIXME: cur_chan->flags |= ZT_FLAG_PRIDCHAN; - cur_chan->flags &= ~ZT_FLAG_HDLC; - } else - cur_chan->sigcap = PRI_BCHAN_SIGCAP; - } - xpd->offhook = xpd->wanted_pcm_mask; - xpd->span.spanconfig = pri_spanconfig; - xpd->span.chanconfig = pri_chanconfig; - xpd->span.startup = pri_startup; - xpd->span.shutdown = pri_shutdown; - return 0; -} - -static int PRI_card_zaptel_postregistration(xpd_t *xpd, bool on) -{ - xbus_t *xbus; - struct PRI_priv_data *priv; - - BUG_ON(!xpd); - xbus = xpd->xbus; - priv = xpd->priv; - BUG_ON(!xbus); - XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off"); - return(0); -} - -static int PRI_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig) -{ - LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig)); - return 0; -} - -static void dchan_state(xpd_t *xpd, bool up) -{ - struct PRI_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - if(priv->dchan_alive == up) - return; - if(!priv->layer1_up) /* No layer1, kill dchan */ - up = 0; - if(up) { - XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel RUNNING\n"); - priv->dchan_alive = 1; - } else { - byte *pcm; - - if(SPAN_REGISTERED(xpd)) { - pcm = (byte *)&xpd->span.chans[PRI_DCHAN_IDX(priv)].readchunk; - pcm[0] = 0x00; - pcm = (byte *)&xpd->span.chans[PRI_DCHAN_IDX(priv)].writechunk; - pcm[0] = 0x00; - } - XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel STOPPED\n"); - priv->dchan_rx_counter = priv->dchan_tx_counter = 0; - priv->dchan_alive = 0; - priv->dchan_alive_ticks = 0; - priv->dchan_rx_sample = priv->dchan_tx_sample = 0x00; - } -} - -/* - * LED managment is done by the driver now: - * - Turn constant ON RED/GREEN led to indicate NT/TE port - * - Very fast "Double Blink" to indicate Layer1 alive (without D-Channel) - * - Constant blink (1/2 sec cycle) to indicate D-Channel alive. - */ -static void handle_leds(xbus_t *xbus, xpd_t *xpd) -{ - struct PRI_priv_data *priv; - unsigned int timer_count; - int which_led; - int other_led; - enum pri_led_state ledstate; - int mod; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - if(priv->is_nt) { - which_led = NT_RED_LED; - other_led = TE_GREEN_LED; - } else { - which_led = TE_GREEN_LED; - other_led = NT_RED_LED; - } - ledstate = priv->ledstate[which_led]; - timer_count = xpd->timer_count; - if(xpd->blink_mode) { - if((timer_count % DEFAULT_LED_PERIOD) == 0) { - // led state is toggled - if(ledstate == PRI_LED_OFF) { - DO_LED(xpd, which_led, PRI_LED_ON); - DO_LED(xpd, other_led, PRI_LED_ON); - } else { - DO_LED(xpd, which_led, PRI_LED_OFF); - DO_LED(xpd, other_led, PRI_LED_OFF); - } - } - return; - } - if(priv->ledstate[other_led] != PRI_LED_OFF) - DO_LED(xpd, other_led, PRI_LED_OFF); - if(priv->dchan_alive) { - mod = timer_count % 1000; - switch(mod) { - case 0: - DO_LED(xpd, which_led, PRI_LED_ON); - break; - case 500: - DO_LED(xpd, which_led, PRI_LED_OFF); - break; - } - } else if(priv->layer1_up) { - mod = timer_count % 1000; - switch(mod) { - case 0: - case 100: - DO_LED(xpd, which_led, PRI_LED_ON); - break; - case 50: - case 150: - DO_LED(xpd, which_led, PRI_LED_OFF); - break; - } - } else { - if(priv->ledstate[which_led] != PRI_LED_ON) - DO_LED(xpd, which_led, PRI_LED_ON); - } -} - -static int PRI_card_tick(xbus_t *xbus, xpd_t *xpd) -{ - struct PRI_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - if(!priv->initialized || !xbus->self_ticking) - return 0; - /* - * Poll layer1 status (cascade subunits) - */ - if(poll_interval != 0 && - ((xpd->timer_count % poll_interval) == 0)) { - priv->poll_noreplies++; - query_subunit(xpd, REG_FRS0); - //query_subunit(xpd, REG_FRS1); - } - if(priv->dchan_tx_counter >= 1 && priv->dchan_rx_counter > 1) { - dchan_state(xpd, 1); - priv->dchan_alive_ticks++; - } - handle_leds(xbus, xpd); - return 0; -} - -static int PRI_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg) -{ - BUG_ON(!xpd); - if(!TRANSPORT_RUNNING(xpd->xbus)) - return -ENODEV; - switch (cmd) { - case ZT_TONEDETECT: - /* - * Asterisk call all span types with this (FXS specific) - * call. Silently ignore it. - */ - LINE_DBG(SIGNAL, xpd, pos, "PRI: Starting a call\n"); - return -ENOTTY; - default: - report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd); - return -ENOTTY; - } - return 0; -} - -static int PRI_card_close(xpd_t *xpd, lineno_t pos) -{ - //struct zt_chan *chan = &xpd->span.chans[pos]; - dchan_state(xpd, 0); - return 0; -} - -/* - * Called only for 'span' keyword in /etc/zaptel.conf - */ -static int pri_startup(struct zt_span *span) -{ - xpd_t *xpd = span->pvt; - struct PRI_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - if(!TRANSPORT_RUNNING(xpd->xbus)) { - XPD_DBG(GENERAL, xpd, "Startup called by zaptel. No Hardware. Ignored\n"); - return -ENODEV; - } - XPD_DBG(GENERAL, xpd, "STARTUP\n"); - // Turn on all channels - CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 1); - return 0; -} - -/* - * Called only for 'span' keyword in /etc/zaptel.conf - */ -static int pri_shutdown(struct zt_span *span) -{ - xpd_t *xpd = span->pvt; - struct PRI_priv_data *priv; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - if(!TRANSPORT_RUNNING(xpd->xbus)) { - XPD_DBG(GENERAL, xpd, "Shutdown called by zaptel. No Hardware. Ignored\n"); - return -ENODEV; - } - XPD_DBG(GENERAL, xpd, "SHUTDOWN\n"); - // Turn off all channels - CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 0); - return 0; -} - -/*! Copy PCM chunks from the buffers of the xpd to a new packet - * \param xbus xbus of source xpd. - * \param xpd source xpd. - * \param lines a bitmask of the active channels that need to be copied. - * \param pack packet to be filled. - * - * On PRI this function is should also shift the lines mask one bit, as - * channel 0 on the wire is an internal chip control channel. We only - * send 31 channels to the device, but they should be called 1-31 rather - * than 0-30 . - */ -static void PRI_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, xpacket_t *pack) -{ - struct PRI_priv_data *priv; - byte *pcm; - struct zt_chan *chans; - unsigned long flags; - int i; - int physical_chan; - int physical_mask = 0; - - BUG_ON(!xbus); - BUG_ON(!xpd); - BUG_ON(!pack); - priv = xpd->priv; - BUG_ON(!priv); - pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm); - spin_lock_irqsave(&xpd->lock, flags); - chans = xpd->span.chans; - physical_chan = 0; - for_each_line(xpd, i) { - if(priv->pri_protocol == PRI_PROTO_E1) { - /* In E1 - Only 0'th channel is unused */ - if(i == 0) { - physical_chan++; - } - } else if(priv->pri_protocol == PRI_PROTO_T1) { - /* In T1 - Every 4'th channel is unused */ - if((i % 3) == 0) { - physical_chan++; - } - } - if(IS_SET(lines, i)) { - physical_mask |= BIT(physical_chan); - if(SPAN_REGISTERED(xpd)) { - if(i == PRI_DCHAN_IDX(priv)) { - if(priv->dchan_tx_sample != chans[i].writechunk[0]) { - priv->dchan_tx_sample = chans[i].writechunk[0]; - priv->dchan_tx_counter++; - } else if(chans[i].writechunk[0] == 0xFF) - dchan_state(xpd, 0); - } -#ifdef DEBUG_PCMTX - if(pcmtx >= 0 && pcmtx_chan == i) - memset((u_char *)pcm, pcmtx, ZT_CHUNKSIZE); - else -#endif - memcpy((u_char *)pcm, chans[i].writechunk, ZT_CHUNKSIZE); - // fill_beep((u_char *)pcm, xpd->addr.subunit, 2); - } else - memset((u_char *)pcm, 0x7F, ZT_CHUNKSIZE); - pcm += ZT_CHUNKSIZE; - } - physical_chan++; - } - RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = physical_mask; - XPD_COUNTER(xpd, PCM_WRITE)++; - spin_unlock_irqrestore(&xpd->lock, flags); -} - -/*! Copy PCM chunks from the packet we recieved to the xpd struct. - * \param xbus xbus of target xpd. - * \param xpd target xpd. - * \param pack Source packet. - * - * On PRI this function is should also shift the lines back mask one bit, as - * channel 0 on the wire is an internal chip control channel. - * - * \see PRI_card_pcm_fromspan - */ -static void PRI_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack) -{ - struct PRI_priv_data *priv; - byte *pcm; - struct zt_chan *chans; - xpp_line_t physical_mask; - unsigned long flags; - int i; - int logical_chan; - - if(!SPAN_REGISTERED(xpd)) - return; - priv = xpd->priv; - BUG_ON(!priv); - pcm = RPACKET_FIELD(pack, GLOBAL, PCM_READ, pcm); - physical_mask = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines); - spin_lock_irqsave(&xpd->lock, flags); - chans = xpd->span.chans; - logical_chan = 0; - for (i = 0; i < CHANNELS_PERXPD; i++) { - volatile u_char *r; - - if(priv->pri_protocol == PRI_PROTO_E1) { - /* In E1 - Only 0'th channel is unused */ - if(i == 0) - continue; - } else if(priv->pri_protocol == PRI_PROTO_T1) { - /* In T1 - Every 4'th channel is unused */ - if((i % 4) == 0) - continue; - } - if(logical_chan == PRI_DCHAN_IDX(priv)) { - if(priv->dchan_rx_sample != pcm[0]) { - if(print_dbg & DBG_PCM) { - XPD_INFO(xpd, "RX-D-Chan: prev=0x%X now=0x%X\n", - priv->dchan_rx_sample, pcm[0]); - dump_packet("RX-D-Chan", pack, 1); - } - priv->dchan_rx_sample = pcm[0]; - priv->dchan_rx_counter++; - } else if(pcm[0] == 0xFF) - dchan_state(xpd, 0); - } - if(IS_SET(physical_mask, i)) { - r = chans[logical_chan].readchunk; - // memset((u_char *)r, 0x5A, ZT_CHUNKSIZE); // DEBUG - // fill_beep((u_char *)r, 1, 1); // DEBUG: BEEP - memcpy((u_char *)r, pcm, ZT_CHUNKSIZE); - pcm += ZT_CHUNKSIZE; - } - logical_chan++; - } - XPD_COUNTER(xpd, PCM_READ)++; - spin_unlock_irqrestore(&xpd->lock, flags); -} - -/*---------------- PRI: HOST COMMANDS -------------------------------------*/ - -static /* 0x0F */ HOSTCMD(PRI, XPD_STATE, bool on) -{ - BUG_ON(!xpd); - XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off"); - return 0; -} - -static /* 0x0F */ HOSTCMD(PRI, RING, lineno_t chan, bool on) -{ - XPD_ERR(xpd, "%s: Unsupported\n", __FUNCTION__); - return -ENOSYS; -} - -static /* 0x0F */ HOSTCMD(PRI, RELAY_OUT, byte which, bool on) -{ - XPD_ERR(xpd, "%s: Unsupported\n", __FUNCTION__); - return -ENOSYS; -} - -/* 0x33 */ HOSTCMD(PRI, SET_LED, enum pri_led_selectors led_sel, enum pri_led_state to_led_state) -{ - int ret = 0; - xframe_t *xframe; - xpacket_t *pack; - struct pri_leds *pri_leds; - struct PRI_priv_data *priv; - - BUG_ON(!xbus); - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - XPD_DBG(LEDS, xpd, "led_sel=%d to_state=%d\n", led_sel, to_led_state); - XFRAME_NEW_CMD(xframe, pack, xbus, PRI, SET_LED, xpd->xbus_idx); - pri_leds = &RPACKET_FIELD(pack, PRI, SET_LED, pri_leds); - pri_leds->state = to_led_state; - pri_leds->led_sel = led_sel; - XPACKET_LEN(pack) = RPACKET_SIZE(PRI, SET_LED); - ret = send_cmd_frame(xbus, xframe); - priv->ledstate[led_sel] = to_led_state; - return ret; -} - -/*---------------- PRI: Astribank Reply Handlers --------------------------*/ -static void layer1_state(xpd_t *xpd, byte subunit, byte data_low) -{ - struct PRI_priv_data *priv; - int alarms = 0; - - BUG_ON(!xpd); - priv = xpd->priv; - BUG_ON(!priv); - if(xpd->addr.subunit != subunit) { - XPD_NOTICE(xpd, "layer1_state got wrong subunit=%d. Ignored.\n", subunit); - return; - } - priv->poll_noreplies = 0; - if(data_low & REG_FRS0_LOS) - alarms |= ZT_ALARM_RED; - if(data_low & REG_FRS0_AIS) - alarms |= ZT_ALARM_BLUE; - if(data_low & REG_FRS0_RRA) - alarms |= ZT_ALARM_YELLOW; - priv->layer1_up = alarms == 0; - if(!priv->layer1_up) - dchan_state(xpd, 0); - if(SPAN_REGISTERED(xpd) && xpd->span.alarms != alarms) { - char str1[MAX_PROC_WRITE]; - char str2[MAX_PROC_WRITE]; - - alarm2str(xpd->span.alarms, str1, sizeof(str1)); - alarm2str(alarms, str2, sizeof(str2)); - XPD_NOTICE(xpd, "Alarms: 0x%X (%s) => 0x%X (%s)\n", - xpd->span.alarms, str1, - alarms, str2); - xpd->span.alarms = alarms; - zt_alarm_notify(&xpd->span); - } - priv->reg_frs0 = data_low; - priv->layer1_replies++; - XPD_DBG(REGS, xpd, "subunit=%d data_low=0x%02X\n", subunit, data_low); -} - -static int PRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info) -{ - unsigned long flags; - struct PRI_priv_data *priv; - - spin_lock_irqsave(&xpd->lock, flags); - priv = xpd->priv; - BUG_ON(!priv); -#if 1 - if(print_dbg) - dump_reg_cmd("PRI", info, 0); -#endif - if(info->multibyte) { - XPD_NOTICE(xpd, "Got Multibyte: %d bytes, eoframe: %d\n", - info->bytes, info->eoframe); - goto end; - } - if(REG_FIELD(info, regnum) == REG_FRS0 && REG_FIELD(info, do_subreg)) - layer1_state(xpd, REG_FIELD(info, subreg), REG_FIELD(info, data_low)); - if(REG_FIELD(info, regnum) == REG_FRS1 && REG_FIELD(info, do_subreg)) - priv->reg_frs1 = REG_FIELD(info, data_low); - /* Update /proc info only if reply relate to the last slic read request */ - if( - REG_FIELD(&priv->requested_reply, regnum) == REG_FIELD(info, regnum) && - REG_FIELD(&priv->requested_reply, do_subreg) == REG_FIELD(info, do_subreg) && - REG_FIELD(&priv->requested_reply, subreg) == REG_FIELD(info, subreg)) { - priv->last_reply = *info; - } - -end: - spin_unlock_irqrestore(&xpd->lock, flags); - return 0; -} - -static xproto_table_t PROTO_TABLE(PRI) = { - .owner = THIS_MODULE, - .entries = { - /* Table Card Opcode */ - }, - .name = "PRI_xx", /* xpd->type_name is set in set_nt() */ - .type = XPD_TYPE_PRI, - .xops = { - .card_new = PRI_card_new, - .card_init = PRI_card_init, - .card_remove = PRI_card_remove, - .card_zaptel_preregistration = PRI_card_zaptel_preregistration, - .card_zaptel_postregistration = PRI_card_zaptel_postregistration, - .card_hooksig = PRI_card_hooksig, - .card_tick = PRI_card_tick, - .card_pcm_fromspan = PRI_card_pcm_fromspan, - .card_pcm_tospan = PRI_card_pcm_tospan, - .card_ioctl = PRI_card_ioctl, - .card_close = PRI_card_close, - .card_register_reply = PRI_card_register_reply, - - .RING = XPROTO_CALLER(PRI, RING), - .RELAY_OUT = XPROTO_CALLER(PRI, RELAY_OUT), - .XPD_STATE = XPROTO_CALLER(PRI, XPD_STATE), - }, - .packet_is_valid = pri_packet_is_valid, - .packet_dump = pri_packet_dump, -}; - -static bool pri_packet_is_valid(xpacket_t *pack) -{ - const xproto_entry_t *xe_nt = NULL; - const xproto_entry_t *xe_te = NULL; - // DBG(GENERAL, "\n"); - xe_nt = xproto_card_entry(&PROTO_TABLE(PRI), XPACKET_OP(pack)); - return xe_nt != NULL || xe_te != NULL; -} - -static void pri_packet_dump(const char *msg, xpacket_t *pack) -{ - DBG(GENERAL, "%s\n", msg); -} -/*------------------------- REGISTER Handling --------------------------*/ -static int proc_pri_info_write(struct file *file, const char __user *buffer, unsigned long count, void *data) -{ - xpd_t *xpd = data; - struct PRI_priv_data *priv; - char buf[MAX_PROC_WRITE]; - char *p; - char *tok; - static const char *msg = "PROC"; /* for logs */ - int ret = 0; - bool got_localloop = 0; - bool got_nolocalloop = 0; - bool got_te = 0; - bool got_nt = 0; - bool got_e1 = 0; - bool got_t1 = 0; - bool got_j1 = 0; - - if(!xpd) - return -ENODEV; - priv = xpd->priv; - if(count >= MAX_PROC_WRITE) { /* leave room for null */ - XPD_ERR(xpd, "write too long (%ld)\n", count); - return -E2BIG; - } - if(copy_from_user(buf, buffer, count)) { - XPD_ERR(xpd, "Failed reading user data\n"); - return -EFAULT; - } - buf[count] = '\0'; - XPD_DBG(PROC, xpd, "PRI-SETUP: got %s\n", buf); - /* - * First parse. Act only of *everything* is good. - */ - p = buf; - while((tok = strsep(&p, " \t\v\n")) != NULL) { - if(*tok == '\0') - continue; - XPD_DBG(PROC, xpd, "Got token='%s'\n", tok); - if(strnicmp(tok, "LOCALLOOP", 8) == 0) - got_localloop = 1; - else if(strnicmp(tok, "NOLOCALLOOP", 8) == 0) - got_nolocalloop = 1; - else if(strnicmp(tok, "NT", 2) == 0) - got_nt = 1; - else if(strnicmp(tok, "TE", 2) == 0) - got_te = 1; - else if(strnicmp(tok, "E1", 2) == 0) - got_e1 = 1; - else if(strnicmp(tok, "T1", 2) == 0) - got_t1 = 1; - else if(strnicmp(tok, "J1", 2) == 0) { - got_j1 = 1; - } else { - XPD_NOTICE(xpd, "PRI-SETUP: unknown keyword: '%s'\n", tok); - return -EINVAL; - } - } - if(got_e1) - ret = set_pri_proto(xpd, PRI_PROTO_E1); - else if(got_t1) - ret = set_pri_proto(xpd, PRI_PROTO_T1); - else if(got_j1) - ret = set_pri_proto(xpd, PRI_PROTO_J1); - if(priv->pri_protocol == PRI_PROTO_0) { - XPD_ERR(xpd, - "Must set PRI protocol (E1/T1/J1) before setting other parameters\n"); - return -EINVAL; - } - if(got_localloop) - ret = set_localloop(msg, xpd, 1); - if(got_nolocalloop) - ret = set_localloop(msg, xpd, 0); - if(got_nt) - ret = set_nt(msg, xpd, 1); - if(got_te) - ret = set_nt(msg, xpd, 0); - return (ret) ? ret : count; -} - - -static int proc_pri_info_read(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - unsigned long flags; - xpd_t *xpd = data; - struct PRI_priv_data *priv; - int i; - - DBG(PROC, "\n"); - if(!xpd) - return -ENODEV; - spin_lock_irqsave(&xpd->lock, flags); - priv = xpd->priv; - BUG_ON(!priv); - len += sprintf(page + len, "PRI: %s %s%s (deflaw=%d, dchan=%d)\n", - (priv->is_nt) ? "NT" : "TE", - pri_protocol_name(priv->pri_protocol), - (priv->local_loopback) ? " LOCALLOOP" : "", - priv->deflaw, priv->dchan_num); - len += sprintf(page + len, "%05d Layer1: ", priv->layer1_replies); - if(priv->poll_noreplies > 1) - len += sprintf(page + len, "No Replies [%d]\n", - priv->poll_noreplies); - else { - len += sprintf(page + len, "%s\n", - ((priv->layer1_up) ? "UP" : "DOWN")); - len += sprintf(page + len, - "Framer Status: FRS0=0x%02X, FRS1=0x%02X ALARMS:", - priv->reg_frs0, priv->reg_frs1); - if(priv->reg_frs0 & REG_FRS0_LOS) - len += sprintf(page + len, " RED"); - if(priv->reg_frs0 & REG_FRS0_AIS) - len += sprintf(page + len, " BLUE"); - if(priv->reg_frs0 & REG_FRS0_RRA) - len += sprintf(page + len, " YELLOW"); - len += sprintf(page + len, "\n"); - } - len += sprintf(page + len, "D-Channel: TX=[%5d] (0x%02X) RX=[%5d] (0x%02X) ", - priv->dchan_tx_counter, priv->dchan_tx_sample, - priv->dchan_rx_counter, priv->dchan_rx_sample); - if(priv->dchan_alive) { - len += sprintf(page + len, "(alive %d K-ticks)\n", - priv->dchan_alive_ticks/1000); - } else { - len += sprintf(page + len, "(dead)\n"); - } - for(i = 0; i < NUM_LEDS; i++) - len += sprintf(page + len, "LED #%d: %d\n", i, priv->ledstate[i]); - spin_unlock_irqrestore(&xpd->lock, flags); - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; -} - -/* - * - * Direct/Indirect - * | - * | Reg# - * | | - * | | Data (only in Write) - * | | | - * | | +-+-+ - * v v v v - * FF WD 06 01 05 - * ^ ^ - * | | - * | Write/Read - * | - * Chan# - * - */ -static int handle_register_command(xpd_t *xpd, char *cmdline) -{ - unsigned chipsel; - unsigned data = 0; - unsigned xdata1 = 0; - unsigned xdata2 = 0; - char op; /* [W]rite, [R]ead */ - char reg_type; /* [D]irect, [S]ubregister */ - int reg_num; - int subreg; - int elements; - bool writing; - char *p; - reg_cmd_t regcmd; - xbus_t *xbus; - int ret = -EINVAL; - struct PRI_priv_data *priv; - byte buf[MAX_PROC_WRITE]; - - BUG_ON(!xpd); - xbus = xpd->xbus; - priv = xpd->priv; - BUG_ON(!priv); - if((p = strchr(cmdline, '#')) != NULL) /* Truncate comments */ - *p = '\0'; - if((p = strchr(cmdline, ';')) != NULL) /* Truncate comments */ - *p = '\0'; - for(p = cmdline; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */ - ; - if(*p == '\0') - return 0; - if(!XBUS_GET(xbus)) { - XBUS_DBG(GENERAL, xbus, "Dropped packet. Is shutting down.\n"); - return -EBUSY; - } - memset(buf, 0, MAX_PROC_WRITE); - elements = sscanf(cmdline, "%d %c%c %x %x %x %x %x", - &chipsel, - &op, ®_type, ®_num, - &subreg, - &data, &xdata1, &xdata2); - XPD_DBG(PROC, xpd, "'%s': %d %c%c %02X %02X %02X\n", cmdline, chipsel, op, reg_type, reg_num, subreg, data); - if(elements < 3) { // At least: chipsel, op, reg_type, reg_num - ERR("Not enough arguments: (%d args) '%s'\n", elements, cmdline); - goto out; - } - if(!VALID_CHIPSEL(chipsel)) { - ERR("Bad chip select number: %d\n", chipsel); - goto out; - } - REG_FIELD(®cmd, chipsel) = chipsel; - switch(op) { - case 'W': - writing = 1; - break; - case 'R': - writing = 0; - break; - default: - ERR("Unkown operation type '%c'\n", op); - goto out; - } - if( - (op == 'W' && reg_type == 'D' && elements != 5) || - (op == 'W' && reg_type == 'S' && elements != 6) || - (op == 'R' && reg_type == 'D' && elements != 4) || - (op == 'R' && reg_type == 'S' && elements != 5) - ) { - ERR("Bad number of elements: '%s' (%d elements): %d %c%c %02X %02X %02X\n", - cmdline, elements, - chipsel, op, reg_type, reg_num, subreg, data); - goto out; - } - switch(reg_type) { - case 'S': - REG_FIELD(®cmd, do_subreg) = 1; - REG_FIELD(®cmd, regnum) = reg_num; - REG_FIELD(®cmd, subreg) = subreg; - REG_FIELD(®cmd, data_low) = data; - XPD_DBG(PROC, xpd, "SUBREG\n"); - break; - case 'D': - REG_FIELD(®cmd, do_subreg) = 0; - REG_FIELD(®cmd, regnum) = reg_num; - REG_FIELD(®cmd, subreg) = 0; - REG_FIELD(®cmd, data_low) = subreg; - XPD_DBG(PROC, xpd, "DIRECT\n"); - break; - default: - ERR("Unkown register type '%c'\n", reg_type); - goto out; - } - regcmd.bytes = sizeof(regcmd) - 1; - REG_FIELD(®cmd, read_request) = writing; - REG_FIELD(®cmd, data_high) = 0; - priv->requested_reply = regcmd; - if(print_dbg) - dump_reg_cmd("PRI", ®cmd, 1); - ret = xpp_register_request(xpd->xbus, xpd, - REG_FIELD(®cmd, chipsel), - writing, - REG_FIELD(®cmd, do_subreg), - REG_FIELD(®cmd, regnum), - REG_FIELD(®cmd, subreg), - REG_FIELD(®cmd, data_low), - REG_FIELD(®cmd, data_high)); -out: - XBUS_PUT(xbus); - return ret; -} - -static int proc_xpd_register_write(struct file *file, const char __user *buffer, unsigned long count, void *data) -{ - xpd_t *xpd = data; - char buf[MAX_PROC_WRITE]; - char *p; - int i; - int ret; - - if(!xpd) - return -ENODEV; - for(i = 0; i < count; /* noop */) { - for(p = buf; p < buf + MAX_PROC_WRITE; p++) { /* read a line */ - if(i >= count) - break; - if(get_user(*p, buffer + i)) - return -EFAULT; - i++; - if(*p == '\n' || *p == '\r') /* whatever */ - break; - } - if(p >= buf + MAX_PROC_WRITE) - return -E2BIG; - *p = '\0'; - ret = handle_register_command(xpd, buf); - if(ret < 0) - return ret; - msleep(1); - } - return count; -} - - -static int proc_xpd_register_read(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - unsigned long flags; - xpd_t *xpd = data; - reg_cmd_t *info; - struct PRI_priv_data *priv; - - if(!xpd) - return -ENODEV; - priv = xpd->priv; - BUG_ON(!priv); - spin_lock_irqsave(&xpd->lock, flags); - info = &priv->last_reply; - len += sprintf(page + len, "# Writing bad data into this file may damage your hardware!\n"); - len += sprintf(page + len, "# Consult firmware docs first\n"); - len += sprintf(page + len, "#\n"); - if(REG_FIELD(info, do_subreg)) { - len += sprintf(page + len, "#CH\tOP\tReg.\tSub\tDL\n"); - len += sprintf(page + len, "%2d\tRS\t%02X\t%02X\t%02X\n", - REG_FIELD(info, chipsel), - REG_FIELD(info, regnum), REG_FIELD(info, subreg), REG_FIELD(info, data_low)); - } else { - len += sprintf(page + len, "#CH\tOP\tReg.\tDL\n"); - len += sprintf(page + len, "%2d\tRD\t%02X\t%02X\n", - REG_FIELD(info, chipsel), - REG_FIELD(info, regnum), REG_FIELD(info, data_low)); - } - spin_unlock_irqrestore(&xpd->lock, flags); - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; -} - -int __init card_pri_startup(void) -{ - DBG(GENERAL, "\n"); - - INFO("revision %s\n", XPP_VERSION); - xproto_register(&PROTO_TABLE(PRI)); - return 0; -} - -void __exit card_pri_cleanup(void) -{ - DBG(GENERAL, "\n"); - xproto_unregister(&PROTO_TABLE(PRI)); -} - -MODULE_DESCRIPTION("XPP PRI Card Driver"); -MODULE_AUTHOR("Oron Peled "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(XPP_VERSION); -MODULE_ALIAS_XPD(XPD_TYPE_PRI); - -module_init(card_pri_startup); -module_exit(card_pri_cleanup); diff --git a/xpp/card_pri.h b/xpp/card_pri.h deleted file mode 100644 index dbe83c0..0000000 --- a/xpp/card_pri.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef CARD_PRI_H -#define CARD_PRI_H -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "xpd.h" - -enum pri_opcodes { - XPROTO_NAME(PRI, SET_LED) = 0x33, -}; - - -#endif /* CARD_PRI_H */ diff --git a/xpp/firmwares/FPGA_1141.hex b/xpp/firmwares/FPGA_1141.hex deleted file mode 100644 index 512df60..0000000 --- a/xpp/firmwares/FPGA_1141.hex +++ /dev/null @@ -1,658 +0,0 @@ -# -# $Id: FPGA_1141.hex 5122 2007-12-12 10:07:59Z dima $ -# -:020000040000FA -:80000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6AD6FF4000782C0A006AD6FF4000782C0A006AD6FF4000782C0A0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4455544455557475577775577675577775577765566665563625523235D2E37C2B5111155111155111155111C4 -:80008000155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111000000000000000000000000000000000000002552222552222552220025522225522200000000001AA1111AA1110025522200001AA1111AA111001AA11100001AA1111AA11100001AA1111AA1111AA113 -:80010000110000002552222552222F21F112122F21F112122552222552222552222552220000001AA111255222255222255222255222255222255222255222255222255222255222000000002F21F112122F21F1121200002552222552221AA1111AA1112552222F21F1121200001AA1112F21F1121200002F21F112122F21F112121AA100 -:80018000110025522225522200000000002552220000000025522225522200000000002552220000FFF9F99F9F7F78F8878700000000000000000000000000000000000000000000000000000000002552220000000025522225522200002552222552222552222552222552222552222552222552222552220025522200000000004F44D4 -:80020000F444444F44F44444000000004F44F444444F44F44444004F44F4444400004F44F444444F44F444440000004F44F444446F64F446466F64F44646000000004F48F884846F69F996962F21F11212000000CAACCC2F2DFDD2D22F21F112124F48F884842F21F11212004F4CFCC4C46F6DFDD6D62F21F1121200006F6DFDD6D66F6DF0 -:80028000FDD6D66F6DFDD6D6000000008AA8882F29F992922F21F112120000004F4CFCC4C46F6DFDD6D62F21F112128AA8882F21F11212004F4CFCC4C46F6DFDD6D62F21F1121200006F6DFDD6D6CFC5F55C5CBFBEFEEBEB006F6DFDD6D66F6DFDD6D6000000008F8CFCC8C8AFACFCCACA255222000000CFC4F44C4CCFC4F44C4C008F8C66 -:80030000FCC8C825522200CFC4F44C4CCFC4F44C4C000000CFC4F44C4CCFC4F44C4CCFC4F44C4C00000000CFCCFCCCCCCFCCFCCCCC000000008F84F44848AFA4F44A4A255222CFCCFCCCCC0000CFC4F44C4CEFE4F44E4E2552220000EFE4F44E4EEFE4F44E4EEFE4F44E4E00000000CFC8F88C8CCFC8F88C8C000000008F84F44848AFA4A9 -:80038000F44A4A255222CFC8F88C8C0000CFC4F44C4CEFE4F44E4E2552220000EFE4F44E4EEFE4F44E4EEFE4F44E4E00000000CFC8F88C8CCFC8F88C8C000000008F8CFCC8C8AFACFCCACA255222CFC8F88C8C0000CFCCFCCCCCEFECFCCECE2552220000EFECFCCECEEFECFCCECEEFECFCCECE00000000CFC8F88C8CCFCBFBBCBC3AA33379 -:800400000000008F8CFCC8C8AFADFDDADA2F21F11212CFC8F88C8C3AA33300CFCCFCCCCCEFEDFDDEDE2F21F112120000AFA9F99A9AFFFEFEEFEF00EFEDFDDEDEEFEDFDDEDEEFEDFDDEDE000000008AA888BAABBB3AA333000000CFCCFCCCCCEFEEFEEEEE2F22F222228AA8883AA33300CFCCFCCCCCEFEEFEEEEE2F22F222220000EFEEFEFD -:80048000EEEEEFEEFEEEEEEFEEFEEEEE000000004AA4441F14F44141155111000000CFCCFCCCCCFFFFFFFFFF3F33F333334AA44415511100CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000008F84F448489F95F559591F11F11111000000CFCCFCCCCCFFFEFEEFEF3F32F223238F84F448481F11AF -:80050000F1111100CFCCFCCCCCFFFEFEEFEF3F32F223230000FFFEFEEFEFFFFEFEEFEFFFFEFEEFEF00000000CFC4F44C4CFFF4F44F4F3553330000008F8CFCC8C8BFBFFFFBFB3F33F33333CFC4F44C4C35533300CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004554444F42F224242AA2220092 -:8005800000008F8CFCC8C8BFBFFFFBFB3F33F333334554442AA22200CFCCFCCCCCFFFFFFFFFF3F33F33333008F81F118189F9EFEE9E90000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004AA4446AA6662AA222000000CFCCFCCCCCFFFFFFFFFF3F33F333334AA4442AA22200CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFF8D -:80060000FFFFFFFFFFFFFFFFFF00000000CFC4F44C4CCFC6F66C6C2AA2220000008F8CFCC8C8BFBFFFFBFB3F33F33333CFC4F44C4C2AA22200CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F48F884846F68F886862552220000008F8CFCC8C8BFBFFFFBFB3F33F333334F48F884842552221B -:80068000008F8CFCC8C8BFBFFFFBFB3F33F333330000BFBFFFFBFBBFBFFFFBFBBFBFFFFBFB000000004F48F884846F68F88686255222000000CFCCFCCCCCFFFFFFFFFF3F33F333334F48F8848425522200CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F48F884846F68F8868625522200009B -:8007000000CFCCFCCCCCFFFFFFFFFF3F33F333334F48F8848425522200CFCCFCCCCCFFFFFFFFFF3F33F33333EAAEEE7F75F55757000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F44F444447F75F557573F31F11313000000CFC8F88C8CDFDBFBBDBD1F13F331314F44F444443F31F1131300CFC8F88C8CDFDBFBBDBD1F13F33105 -:80078000310000DFDBFBBDBDDFDBFBBDBDDFDBFBBDBD000000004F44F444445F55F555551F11F111110000008F8CFCC8C88F8FFFF8F83AA3334F44F444441F11F11111008F8CFCC8C88F8FFFF8F83AA33300008F8FFFF8F88F8FFFF8F88F8FFFF8F8000000004F44F444444F47F774743AA333000000CFCCFCCCCCDFDEFEEDED1F12F221F9 -:80080000214F44F444441F13F3313100CFCCFCCCCCCFCEFEECEC2AA2220000CFCEFEECECCFCEFEECECCFCEFEECEC000000004F44F444445F57F775751F13F33131000000CFCCFCCCCCCFCFFFFCFC3AA3334F44F444441F13F3313100CFCCFCCCCCCFCFFFFCFC3AA3330000CFCFFFFCFCCFCFFFFCFCCFCFFFFCFC00000000000000000000AE -:800880000000000000000000FFFBFBBFBF7F77F7777700008001000000000000000000000000004001000000000000000000000000DF8D07480000000000000000000000000000000000000000000000000000000000BE4E000000000000000000000000000000000000000000000000000000000000FFE40F480080010000000000000066 -:8009000000000000000040010000000000000000000000002F820C0000000000000000000000000000000000000000000000000000000000F04FFE8002004001008004148002800414800200008002800400002148400100800400002148000010F2A6CE000000000000000000000000000000000000000000000000000000000000FFE44F -:800980000F0000000000000000000000000000000000000000000000000000000000F04FFE80840180020000001002000010024001002100140000000028000014882880080088280028009A0F0080840100002001000000000000001200004001000040010000400100000000009F31094818148002800414182810820416012810A2115B -:800A000040012810A2414001002B11484001280048408188022148008828108204F05C6580840180020000001002000010024001002100140000000028000014882800008088020000EFF80F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000000000008827 -:800A800028000000280000F0B32B00002002000000100200002400000024120018000000002800000000000088000000FFA60A0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000200100000000000000000000000000F07CBE0000000000000000000000000000120039 -:800B00000000000000000020080000000000004F330B000000000000000000000000001002000000000022000000000000000000F04F4A000000000000002100000000000000000000000000000000220000000000005F2E060000000000000000000000000000000000000000000000000000000000F04FFE0000200200000000000000CE -:800B8000210000000000000000000000000000002028020000AF950C000000000000000000000000000000004002000000000000880000000000F09CC320010000002400000000800400000000400200220000200100000000008002004200EFDE0D00000000240000000000000000000010024002000000000000000080020000F0A3BEEA -:800C0000800100000000000000004800000000000000220000200100000088000000004800BF170E00000000A0110000000000000088008001000080010000000000000000002008F0AD1A000000000000000000000082000000000000000000000000000000000000A0430000800200000020040000000000002002800200000082000069 -:800C800000000000000000F0B25B8001382001002088021240022200828081024200200442000000282222800200200482002004200448F0A82C002002120000008001242002000000480000002200008002820000004200008004200442F01C39800118200200202802800400008220810200004A0242000000802202220000008200008A -:800D0000000000FFA70400000022108224020000200880022800000000000000000000220000000000800228F0293700000010013288000080218201482008000000001280028280022800008002200800000020045E4500000000902220020000800848000000000080012200000000000000000000800200FF150D000000190212C20098 -:800D8000008081220120222802000000000080082820020028200220080000002006DF770F800428000080014A01222002280082211218882816220880010080011200188800242004284200000042227016018004120060222800002A040000221002182120280318001828182448200380022024086214004800481002289F280328007D -:800E0000001800000000181800000000002200002242000000200A240000002800000000B0520C00A0210080322200588024A112800222001224001818202121A21422122420A112A0212A08C04288484214422004002004F0D53F20020020010012000000000088008028823222000000800100200810020000000080048022726D0620A5 -:800E80000448000000000000008002008008210000009021824210022028820200004002000000F01E712002208101800128800180088232882004A82024020082800182200480011812002200000000800400F0A19C0028000000280022980020010026820A28002200002022288908800A8800002100000028002A04008F2208208184F3 -:800F000002288001184A01208122010000182C01002082888128218802002004680022002800880080048004F084B6000000200800D2000000B2008800000000C882003081200A18202808800200A08400000000683FFA0D1220012800000012800288002800200820020000A21280828284042212800220020000282228228002E03C0480 -:800F800022111122184001002084011280018800222A04288081A4818001001848A04224182800240029020021103242488004F056742021210122002002002A04208804808202002824280018A04280022840222202280024220000280028200214F03CF700221C84011E2100A01200A0212021081A02121022820188290100241400244A -:80100000A0428001C042800424A0282424240011481002BF5A041AA1121A8185220200202185212102A0112A0A4A81CA822088022901488083A82A1D216A8A86E225A1212AA29228222B222822200820022213A2224A4481F441CB80A22115013A8112012AA21258223280A1881AA822182A2222A2682AA224A023A088008A248328AB4898 -:8010800082808AA1882012C242212121602840B2220248204221F27568209241A0233011A011A0214A88218C21A811CA812808A82921032226128226A1999A682300982442263222225A218884022228004A782212022B64424A04002BA5002601260126012021820400120028122848281A848204290518800198800100212004460200D2 -:801100002400820000142004F06C9DA0233AE313F221211F110A1F11818183A399187A051AA2185AA5A9AA28A29DFAAB335A24A626184AA4884A85E124B482A8B91F16E625BFA20A1AA145BAEA28BE2266242944B22202A0442F22B222F222222B222AA6426A066AF6F722A0333AA7331F13D3112AA211003AA199185A07A0995AA5AAAA09 -:801180000AFABBF2AB777A25A6BC184A8CA844F041632BA8BEB11F16E627B7E22AA2175AA5EF8EE22B624A82062AA222E024F6222225722232221B626E622B62B062F65AD9A0231F13B731031AD211A211121AA2319AA9444AA611189AA155AAABBB229ABDA2A866382AA4A25AB412A1995AAC895E532B912AFA71711F31B3A28EE223B3BB -:8012000012A1F7AAEB26B262E22216E2229222824E422F22B222F222222B222A22B662066AF67216A0331F13F131311AA1311F12F211111AA1313AA3991AA1551AA1111AA9551AA39B2AA2FB3AA3336AA7423AAA452B199AA9551AE137B732B321F271711F33B3A28EA2337AA5BBAAEB267242F2226227222F229222826E422F2252222FB1 -:801280002232222AA6662B26246AF65C1620022280010000000000200800820000280088200288422A082200A0922002000024C02280820400F0E1F900120022110022128084012088210280220322400200002A0822C011001082020030220080082C028084820422AFB3062AB41122B21122B611324219B26291212B961B682B9413B86D -:801300004229F24291222F142BF242B13AE414EB2AE414EA2264152F22E419E22264192CA4292CBC91C2521B29241B292B841B6923B481364219B64298212B8413B84228B24228B24228B242A842882E429776A0421AE612A42166A1212F14B11132621B282B921B692BA41B692B84322D811AF442A1B22DB123D312EA28C1B12E821CD8A6 -:8013800022E118E22261183CC1212DD21B29581B6929B88192921B2925B2810219F2428219A2A41B282928B24228B24228B24318B242EA22E4EB0A20080000800200210000000000000000004001008004000000008002000000501214EF760B2840014001402101C6024882002282281262284280220129880188222A01880000008200A0 -:80140000228800242280A428008082F418A520A138803111181E21294802A812240028190811180012008002202641622920120221100220062220420242C021148022866814702D0118CA1101121CA12121008AC2C222002819289281382C2122A34120A81230824A011328A2210042000020062228A2228024021488284E22882601CF97 -:80148000D8072228204101148234122041828408000080040022002022412219829282100221008200002440021C828402004248BBC50080013420822222010000000080034200A0242250222829010080220200002C8804482C080000002800702E0D228002282218121062121818888021024A8B21A4121220042021820128A012200284 -:80150000008A0228622A040000304228482880A8242A84F2476B0080022C022081828102128800001A0C1A04188004482002242880020028200822622C0200002442224228002A8406CF660B2220011428322824108101001222808221A22142002022032721281820012828002800A04842208418020000800A20F277792001000028265B -:801580008122016820224182820148322100160112D28800280040022082064800428A2222924240222224A2844221006FB7041C024222120010820420A882422800001002281A08602880A21214C2241901A0182981812102290240022A0822004800212242EDBC00001C010000800121001280321128822022A442102302122024012245 -:8016000092220020028008000000420000A880F2DB36902100262101220012184602A0411A8282036892002AA48230126888321242582419813122122383A12142A082802812A24820B22204488248A880F2F6918001200100193222488082280810021C012880024601142C0180222208288848882006221082240224000048284800283E -:8016800048471210218102002002001200C02212200212208208242846033063A01822A8304224280082190C42808442020040021002F081C9001100281100248A0210221882011221108281042082A812E818822A054001146886011411002440010022211002202404DFC60D808262132001160113A118802181210182221A82A2421832 -:801700004229A284422024028221C2200C9220E822A848224228482842800442806622482220F219EB000000282124121022220228002812409211211922081882184812800200B2001400000010424101200600002CF4D6C88081031828182C02350221204102A02100244280C112100200904228421A42C222D02222942220420223821D -:80178000220220042200C021282260FE8012818122112121820228280020021812002222221842183238321982044001160114902220A28214C0418084020010028004AF1C05114001001400889898102281081342E218222124088219210288881829010000001041411121140140018004000010F2248E008211002219D21231112A01BF -:80180000400200002412001022024246024810226421200E20241C02A048258204283022004800001426F2161F8002488008002820820838102102006210021823820800886011C800B0120C31240014002024440122A024226248211CF4873DA0219A33111E31923E312C622124188A6223C0121838A0B11AE112A9142F11A516222B226D -:8018800025B152A133BAAB132CA24F2B858AC482822D41BAB842A488248A82B2438622A4624A52311480E4246626224AA4622681F25172601217182A22A2221113E212B11121A882B81A232922A112268252223A862231C2885A8E542123A4642A8C21E22428A2443A19421191223D412681888466142A24B46246A2248084026014F0EBF3 -:80190000971411221400241691232F12F232A32B1182242123F121821A4261221A122286EA316228222AA24C4886F2D3112982A53315E1225A212CF321822F34F2218188196C383726311502481128228052222A32422CE426F4E1E414400100146032402201122C2881081C083C0A1C28C1212114400142218A028A028A12A228218A4291 -:801980002208400200200822000042003F4C06281B11A033221B13D021B332E32ABA828BA91B23B89213E11BFAB1B11F1B99323F3AF9A1911F11F5B2423F18F861711F13E311E413F5E1B316A2A9BA2B2FFA41E32BBB173B23FA41C1AA2AFCE1233D812A7243A12217121F28F8C3C1284A26A264C0426AA6442F36F67F5B143AB3F1B7112B -:801A0000A3733AB131B311F133323B112F28B892A12B9EB223B882B1B1E91B2BA2333F3AFAA3B12BAB1AF5A1533F3AA8EE7AE317E71DFDF1F38E8237121AEF14EF2AFAE3432F25FF11B33F2AFAE1612D822BA61F3EFAE3613F16F663216A56111F38F8E3C12AA2462AE226E422A2242B662AE222F62614B011F331713AA3333AF131113E1D -:801A8000323F31F332322F2BBB82ABB38AD322B812B181E913A3321E323F1ABB22B332A3DC1F36F5C2E22BC45AB151F5F1D23F3CFCB39326A1A55AFB41411F3EF413F33F315B223F1ED622B862FEE1632F16EE26F263211F16D61152111F14A44462624E626E426AB422A6666E624F6F41F131311F1BF711317AA3331F13F311113F33F372 -:801B000013312F2ABA92A93B9E822F2199121B33BEB11F18EA23D322F3A3911F13A7CD6E423F3EFE61E17AB171F7B1F23F3FFB33132F19AF541B5F1F3EF443E33F31F5B113373A1F14FC23222B6E1F3EFEE3633F36F263211F16764151111F14A4644AA6666E426E624AA6262AE632F66CFA2002222002200182002001112812301130816F -:801B8000281100421180A824208401218001001440010024481400400200002FCD0C260126019021261221223122800121321C21CB13224A0138484A3222142CA12C989012402244022440024240820448002304802424220442F01452C0411B21141B2146B311726293212F34B111F242931B212F2439112F2429F24293222F3429D21255 -:801C0000AB431CE922C4A12F2264112F22641D2E4296F122C29AF222C21B292EC21B292F22B891F262821B292B841B282F2498212F2498212B84112F2428F242A2222BA4222B842A84E822C4E4C0511B611CB511E23631112F3691216E1313E134B891E224BA91F24292824EB3222F3429CAB12B432D91AAC5B13DC21AFA23429237221248 -:801C80002F326C112F222CF122C11AF42281122F3238116E8219F26282282F3688E234BA816224E0240A4A2AB242B822B4426A22BF8A0A2088040000000010020000000000800800001C080000000000002280020000004001CF540A8AE112611211182D12281902200B2001628048A2824222388880321120242101182C2102290A92210D -:801D00003A082A0488484848428092424822288004346F160622821228800850221904664262244082818202A242802486344223828982288422A2412B248082A252422C8388CC22200824488A042223842422C2212AF42A9914A03C1361121286222212C241B86222460228200223E2288422238D229412A81A8C8239416022784A324236 -:801D8000288E1248882888C88842C24824684E2242424222244A6212286F4C042A112102241210410200252201482921882288820420246214218001A0211810A22880A2121AC6126880120280048220922248280048EFCA0C14001122602230420048000042320042481800210028181288A0821223022A0126022C882206800600484225 -:801E000020040020E23D0C1A021B922021D21201A08211360200212381880322286880242202182C64262A812101C2282032827682A248822B4228002924C882284890422A248402CFDE08289011A0212CA22121A028113221400223A5922820064A014222282063254E328A038220288281622820BA82A6482924A2241022682422004803 -:801E8000224200CF830C19018A120110012904200400008001A042220021000000122A213162800223C2720022280080048842484602482022627910012800240090123828488004800220B142222224A12423A4292242001800400282482148884082062220840A0022622100AFC90D222240012A812232220010224222128204281002E5 -:801F00002CA24320212C3812A248B042822684260821002C82840220024082020030C28846F25D38800111280080010014808881012921080000000000122848001821180014008842A02421480048424002800456091C0328116021222229024023041E42260278882212626022484823812328A581621842682C248281184201A223C4DA -:801F80006268248024843862002C22A2844846F2E3E80068142880021224122A81028220410200002848282242482821282034228001290C4602428008800600228004200488F052EF8002168183D2128102382218241800211288187032028022040000A012002424226022001A02620000B022042128422902212828CF2B0F1812280034 -:802000004042028228822088212228028282A23A04822C8184010000292202D0220A42880000232222041002202234224820F4E6D81412008012322211100126012511121262280028128014A224189082A8122D12282C458285044022824102282200002822102284222204DF430E902140012818282830820000182280A812002412580E -:80208000002A0412230212280080A281A0412128004248800200000010027FE20240611242114091321218322128000038120028284200220000002024A2A420042004200400000000284200F0971F2082A141180021008A0222801202210000804422024222008A8402240000368202268222140228482810220822002200E7E1100148D0 -:80210000806112404201148E1212128A8102008A820420080092C824808C984220189282880020A4280000000042000022703701800662132191111220112201202428282108200122C04238108264210020A32440824402002442808402002A8402004234422F1C431101481100401141718102821A0212382121128A8114022C2382882F -:80218000642100822F1221A9481A0848A0246E92708282C82248108202282120044830421C52851415F12121181AE52171316321255112E038681A888E1216E2210280A823AAA84A5E422CA24428A0189224A0389632422B6C27244221299622882E128222216280040021C042262224C2214AF42BFEA0325200171229F321212CA2138E47 -:80220000221B11233132271198236822249AA188282381A2842318B212E22294822B688A3132183A42A2C148AAA8886E42CAA3252CC2824A84062342427222A2A4A024A022294481F2652C2081F131211F16820229B13191211F13B922C2B21830422AB192ABBB212CA15138222AA5226E526AA52548122F23C4C22B222C2DA33A2F2AC2FE -:80228000227E12F032422123B6C2E62212A26642808622E22622A264484AA2462722EF264501000000344001200882000000202804422084080029081890820048244002244880044002800400006FCA09181F12721111D121F82322311B312B111F2BB9922942F292922F2CB682BAA2E229B9B2AB339E12EAAFD82F27B622E626B762E462 -:8023000027B692A9DD9AE926AEB35E722F28F812922AAAA8BEB27AA7772B648ABAA20A2B646632224AA464CABE42A6226AE416E62284A4662D224FB90F19F161611F13B1317311B23333333B233B131F3BB9B2AA222AEA28F9D2522F2BB992E129B8B2AB335AB5F2AFDD2C94427EB22B753EE22BDDEAAEFF1F35C5B25E712DA22DA22CA6A7 -:80238000A8BEB22B155E622B452BC62B8A2CB262E62692224AA444EEC22B646AA6461B666AB462A46626F289D314381D711E2119D321D323B233F131332F21F2B3323BB93ACBB22F29F1D2D22F28B8A2AABB2BABBAA99B2B5FDAE12CADE82EC22F26F672723AA3FFAAEB36BEE2EF25F7A2922F21B982A4A81E322BEE2BEF2B67AEA22BAAAE -:80240000212B622E222B644A042B8A2B6422666222222B446AE222F48CA5141F12F321711F13F131311F2BF2333337233F33F333333F3BFA33B13ADB22FA82122F2DFDB2B22B89BABBB2A3BBFAAE7FDAE526A2421E222F27F7F272FAEF26A6FE4E532F2EFF53722F22FB22F22F2ABAA2EA23F3C2C22F2FFE52422F26FCC2822F22B24266C5 -:80248000262B444A44F2A2822B646AE626E626A6666AA6226E42DF5E0E14C011400222122622290220412249228902200182102204002818100222302280082A0800008044020028A02400D04505902190212E12D0320114D032888201211022822281A34242002E424229A1282B42B02224652280042430421A9212482304216800004AE0 -:80250000082448A042008F240D1CB411021B21421B21272419F2421119F2429119F24291112F1429F24291222F3429D212A9424E912E424E812E4256E12264192EC296C1429AD222B491C2521B2925B29162241B6927241B28272419B24298612F2498412F2428F24282222B842A94822A84E82274560F1CB511061B21421B21272419F224 -:802580004213284E918AF242318AD212012F142BF24293A21CB1A2D412C1521CABC21E81272216E1226D112EC316D122BC81C2D21B612D821B292E121369241B282F2698212C98212C9A214E82222F2422D222288298422BA426F279920082480000000000288004000000800100000014000000000000008002800400001424D30218009C -:802600002E111602181542012583220400289A02A024000048002904702282C6421A8403001290220000208484E42802C0A228004826F242C2001B1A002092221AC6121C02242411E028220516A282A04912622904122712884E12488081098820126214221880A4A4298404882440022D4124424001EF4D06181B3C6013182D2218181286 -:802680002603232206C082328021682252125223240C26812854221912622D52124200182232002C28042282422C0AA02829C2424081F2EF860000002092612503145022112022244B2222240822001225228421045A02A08260226014100242688024844402243043100242245FFE0A18001100242002A04124488004009242000022C0FB -:802700004230228229012A81A2828220018200002282000000218242AA04486F570A19021C2342A2121C8845A2812C831A2349220168181984A818224A02422982015622212282988260212A11B2228123012E828282808428242886A2A4220028F01E7A80012219022A6118212220B182139192200162B04101122800228045E22261214A -:802780002A81A2A182A2182C229112B2128088282A2824088828282B84008A8482E49A091C021C0124004A41A218222C04422448001888C888A042C042222420240840820286820128006022000080044880222A2402F09578002280A1421448250200428008A84A082C4102232221081022C82280042C212226812201202802291802B0B3 -:80280000620820081120880880F82E9A00803121200200102112621200A0120028290420A1A4121220211181040048190AA014A0242084822402482A04209422902228F0AA16A014902100202382210220085810324248200848A0841420022082820800001221800100000000881C0800424242AF580E5860113260122229222142A142C4 -:802880008280853842281642828A8401481932121A428201228A15822281E2128811A214222282218004006A8888889422824A2226F4D9270068221162A014100200211B2820C2821A240420222488880480025A022022048005208881148224022B84200400200800827E850022601226D112911252214691422012128221C8929229329F -:80290000822818254202002901A028888E118082A2121812222200800800000080222804F0CF12803411008024044229A281A08420D22388024213A8240019A88211111391211823294102272824248A94822C0821502210022D821002211082180260221F5B0C0000422214200114428027011C2442012681C5812B421480010020AA128D -:8029800028130219011324341152114AB28122948142A08400000000827F4108140010010000002921288882810800000042202728044221C26014828022A248148A024081048822802482040082F0677D8022848224A2241A448213028A01A0212240028A0420220C2001220020280188281A1A8289A828882002200248000088682100A5 -:802A00008FEE0F42121A04100223061E421A084A982210022901218002182C0B108201002460282224A08120028008008002008002821002BF7A090048200400004880018218221400888621810214141414188622210200420020012100101201860286028824200CD01C05288228426011348096216028281A0C2424221AAC4210220269 -:802A800000212240022129012981B8820128228088820A20080000203221484021F8DE7300221C352100002001528002A01820022028084A21A4844223A4244A2164144AA22452C04150122081C4410020A8688088A4C2484828822D82486F934121621D2AC1412A7211B351E52432626E414AA4411AE824CC821B1A2ABA2203AEC2CAA857 -:802B000014382B85230452382B16225AB82228D712B242B282A18B2BAA288EE22CAA622CEA1A4692418692C12C2C7E8282E828041D426A021423F818A9A0448A2331212CB44247B312E421A5111146F2A26223A139282B111CF852C23B24242AE228A828243F3444F26143284E5282CE7238FE52126EC24AA3113A61121813186224882032 -:802B80000482004A14A2E68224CA6418A8BF810D1922C2214A7241210280D223B292A9984AA1182227211F2864291B38B021E21838311B421BAAD01121F11181122D12122F2888E83A98212543F3C2812B11F6A191AE41882E21822D81A602C8002A022ABA828C8888F4354610810120084800000000144001144814481C02000000000092 -:802C00001110011123161112314211230421100221D0120200F03E26141F14B411621222A0135E523E324AA1A81F1CED24FC42128E928E9233B1C1ACDF1F1431611F28AC641F151FB141E634F143511F35FD13416E624AA4645E722B771F35B2C2E434F8A2833F12B251F6F3F33F3FF923633B4637323F34F442423F16D822F442E227288C -:802C80002B8CCE622F2CBC42A68248F0C2C2DF6C0E4AB471E712B221E226F271322CE527A7161F1EFF8191242B3518243B331BDF1F17FD411113BE81FCE1611F1FBF13B141F4C1833F34F563D33F13E426A7DD1F15E624FF42C11F3DF2C3415EF32F3AF323611B232F21B372F3A1E11BC42F2AB8827881A1A42F28BCC22CE82CF8E2422F4C -:802D00002EFC6261EEA22B44A0CC9F630D6AB411E611F1212115F111111F31E123A3571F17F6C1D32F219CF28AED287912A12A1F1BE827E238A8AE3DE11AE91CED14F441C33F15F421633F17A667CAEC1DEB25B372E72DF6E3612E623F2ABAB1E333A1BB2BBF1B622E23EABE82081F3CAAC82B8882CEC22B6EEAEC2EB222BAC2084AFCABDE -:802D80005FF061411B73141F12F261A11F13F311517E727AF571713F387912B252A55C182F12A31AAAF86361AEE1EA8ADE31E814FD42613F34FC53433F3BB653E427A75DDE217EB21B771F3DA66E2E621F2AB2E1EB32A3463F3FB2A3EE38A8EE3F38F8C341CE828AFC828223A8CCEE422BCECE222BCA2BCC88CAFCFC7E2002002602182026 -:802E0000A248A049241A04122089A2482812288210028002800988800988909280092A08200882200800824200824F38032001286611714202181351220010022DB2482410029826023D424211122C242422F1224242A02121282220020088000048A0484A022882003FDC041CB511C2111B21421B212394612B1419B24299212B94112B89 -:802E80009413F2429113F2429113F242911B424E911F22C4A12E4216E12264192F226C192CA4292CB491C2431B29341B2966B3917642B381764293612F3498612F3498412F2428F24282222F242892A22A84E822F488B3C051681CB11122B4111292212B1419F24292112BB413B84231212939212B9413B24239232B941F2281E922CC811C -:802F00002B5296D1226C193CE419C2421AC2C39AC6439A62329A44A3684683E63488E6349A614E82224E82224E8222A82B4229A8428FA60220080000004001008002000010021800000040010080040000000000200400100225015F960E901180036E12421641013602808818022CA88480842304001002821A12A2122282822A088601D4 -:802F8000880046A2428200802848A24280260242243F4F0B46A12832A04240212284A38420612160216A016022009213128282810222800858298202AE112C12A1218002004288002822204CC281E018A242AF310430D120234482C4211C24A396212296C28230222C884402381A3C1221821800201221E314B22288AAA48AF22142A01A57 -:803000002022A4248820028800284AC82214C0412D221F14011C84A21220A261141200001800124A01882242001302223022A0821229081800C011821400400280840820CA224880840AA848EA0F226012005022112C0120D1228144012008114220840433021B4228881229810212212814120026020022400124A02422288A84024A0242 -:803080007F334181210180A22122222812180014C2142A94222306808A0200D02281042AA44227214A02221230822B822F2A1161262A143281298C14C24142802484222402228F710F00190220211223028011021C48A12429386220042A84042712242E114A022AA512382386112213512282299A2123A62421139A4213146224424A82BA -:80310000A242AA842602225EED14321200282C02281829210116621448002810012A0800002C0482242C040022001A886221002100880011004800004A024F1B0518481C218302801201190252141880848309282902C28A22022C4102800423020086220B2AA182000048C220C8A2E82C8484120200EF8701114800003012422180122280 -:8031800002212B82004223110224001A04880022529021482A84014800283944A2820048200400002908281FEA08100100142280A224520048002024028842480042112848184A010048C0120022008082042400008008002200EF5E051111162183422192221C84A261281A440120A2348A012B1A4A82C442A0241A847182822125C4120B -:8032000030414826822828A421A828622CA4824223842428B882C2824826028820F2221C8001000020612248141082C612B0420828480020880A142242002242222820C1521A22020025010088002A2484040022003F8F0C100148C0218003000020224102111001142411004A020048282C41A312113811001021022110420280322228B3 -:80328000422200504F004011111102002819C121100321181CB21252120000802401130115029682220340632412218220083022828038220010820480745B0A0000802101212400272124107182820110028002150220028A41020021A8212A0488882C8A081001110040A284282180049F440B80040010024A61154242222085420100D5 -:803300001220110222141602242008002C228484011E224A0242A82C0800400221002002F01996A0121120F2211222200222112A012CD1218289434282011C0120024826012024032331121221111280085021002214D01204224082044240F3E4A210010010210200211413024A01001382D2210129210221224810410100001B2482B0C9 -:803380001102808A220400800800282C0200485FE30C201241010018161201001420061C8241110200140010814142028A8202824814213823850480022100282100208482021F9F02190228808131112024A114181110111101008042012392211B4380212421018200400200183148222B840021000000004870BB0A00481228242800FB -:803400002100183840822A01001911924118803811221682A8848E2140611416828422022054124222111119120120924200902222AB3E001942D111F221223B12182C21913313810215D231B513E221C3213F317122D1310119A1221D221B226AC7212A61211D8229F822122F2BF333112CA3261591212383B11262382BE42E42282225CA -:8034800041E218283222242B6A00484E214AF44F7BB01182140116E121B222A221582693421B111AE211B112E22671A1F131122A9211121F13214122225413199123589AE529260830121A74A2F23212189EA24AA8A215A124E2250114212C82B22262242F24A224282A043FF804264121A241181416216224524E1166F3211321621C98BA -:8035000082214012023419541214127A64111425A114A8882CE212F48383184E411D22228E521B44A229D822D82172811271410224002A94422260227E7300000024200200224083440224400200000000100221100221100280044800000000000000F08FAB141A61122A7231513115B222A2326AF731311F12F351511F31513115E33365 -:80358000F31113257111E33252332A022F160617121D511F17F721314AD511A15C2B2229E221B373F721133B111F12A3112F29B392E5163222EAEE2CFC232335F181831F2C5C2225E22282A4224AA442A0448D2E141B116E612AF231111B221B133A82A3761F37F771711F15F511311731141F39F98181371117111F1353113B22E017E722 -:8036000022F2A3911F17F651F11F12F351513F18F9C1512B991E113E321B661F3AFF91913F12F321112F29BB72A76E2B6EAEE22F2CDE33F223211F38F8C1E3272225E222B242A4264E422B464AF662628B41141AA1422A723151311D132F12A3136AF751511B776E711F31D33351333F37F793933F32F223233E32212B23F0615117323F25 -:8036800012FA71717AE712F351511F18E933F3B2222F2BFA33333F37F7A3F33F13F121311D132F2AFB7272EEE22F2ABA22A2EE3F32D21352333F1CDC225222257222E222B242B6228684F455B6141B112AE612F2311115F331132F1382A1761F35F573717AB7115131357131F393813F127223E32313A232F061711F32F233A11B771F1F29 -:80370000E712F351533F1CED3637921F297811F371631F3AFB31133F12F321132F2BF3B272EEA22F26F6A2E22F2C5C323D2135F3E3C12F2252222E2223E222B242B662E624E626F6D797A0120080012E1112220048144032812412301110018012830210012A012A09002F12093C012E82601248224003340000A02420043F4F0E001428D8 -:8037800034194221612611182818112981843321002180414201563121D021214C2241022E1113410222D02281D422082C0824130880022B243042224073A90C481B21B01162241B21272619B24291212F2699212F2419F142932AF44293222F3429D212A9421CE922E414E82264112F2264192F2264192D429AD222B491D222B4915222B1 -:803800001B2923B49132421B682394612B841B282B84112B84222B84A22B842229A842882E425E5880B411061B2146B2116224114A91212F2419F142B2C0932AF44293224E93221CB922D412E922C1912AE811F8224296712262192D439E2129B49112B29156221B2923B49132421B2823942129B881B24292212B84222B84A22B84222921 -:80388000B82294822E421FCF0500000000000000002100000080018800004001000000000000002800000000003FE90A180012C011298162122812240000111932C2108322A2424022912129682220A12126A22180082824114042022CA268008004A29022298202F0CF5C0026210180021C014260125880512280911123040086220C428C -:8039000012800120240162181022498231A1602800408284820462422044019FDC0D184E2180018031218024012302122111169181294403A085828229652282260219810122424A08221234128A022D82224222244862808A94422D222A04F0EDF6008001B011122261122890214A010021222B1410228262224200190118004AE222210A -:80398000212241022C08101102248A02002004282200007F2C06000000002A812212011A04902200124200484200130200200C402101122C210120042100108204224248280022DF8242818222022AD121A21222109112868201183888384AC22213A2410020E414C242682984948228281AA6422818202A86C462282A044223044A0888A5 -:803A000088A280044A0A1FE603002280429132221AC22121191802002B8238808204808484844283964200882033211820012B42002222602400824280AA864248808AF2F28C14222200182200001A021252181A02A0422CC1214A010060142A04C04282682848422212A03818426823C442004224488008002820047F880B11488A21025A -:803A80002100208402203242488880288231421AA44812E02204221810210800002800C8A0484228282088248806008004885F370512481118002138282302A0812601222842003022001A0600824091211812808C050082306240024222212002208C0221003FBE070088001400008002008004000000001118A042C84821224A010018B1 -:803B00002823012400004242000022000048AF9F061901132102142118222302804101684A028800424280022A04A0421C2C94821A82A14800322818C8468224044A622448208A02A2004220F435F920082041028002482228883042808804221822188A24041429A128182022014220810424822428883022008A22044220240200821FEC -:803B80007107002812122A110200000000282028822202002682028001282024040042288A02004800000000001002F09F870000008002000000800A1C8241113141100100482242304100A82004C042808462221448C04200802422024800F0D53614821422280080020011001A02821A88022220A8348818001800202682210400400284 -:803C00002C0824222C024622C42240A2242C82A22400BF550214124800826200288002000030410090128880042880220800481480A6250014002200000000000000DFBE01384800202304222200140080084280082A8104220000802208A0488A0412200800284822280020248204004826F1EE550080042280014280034218800800883E -:803C8000203142282220120262224214141818200820810280040020240600484200F0184800800110022800100180012219328111111C08209441306138121388084882808204120029A82C1110024002240024A02428F06D2A80220962402201002002182002A0212224426221C81002002280260216022400000020020080040080028F -:803D00002C047F1B0392281C05280048282002800200928004A2238888038800001948218882088E612246014A22C28100002800002004902248FFC5072AA32D2A02282F22A1418002800280A18822321BD2E8A0AA3AA614226E21210080A8482219AA281A88A2882A418228A6AAAE8168222002B0220228226842E01684F4946C1412866B -:803D800021012A21A1222A26840222421A012A021F180A171230419062CA26A1222E61226A051BA64A24A2478E12482C82E21744926125E22442A2642E2248244AC4424A54224246A2424A82028E311081C1112A07282B142022A23215110132A0A818DE21F021A31CA59C1B8A882C4422A4311AE21A42A1284A84B941246C125A04B20053 -:803E00007061012124422004226890222B4230223FB90D1100204882040000000000480020410146116214400100423041221118112111211002211082140221100200F096D8141F1AB32162122A83A128006A26A2311D216A8481232272A1B181F1A1A11F1ABA61EC12B881B8E1A4661F16541117137AF481814AAEE6EAAE65BE622D815D -:803E8000AEA33F12B241F693B33F3C7C83728251223F3656222125F242422F26B262E622F222222B222A2622E222B6DC0E221B6326A13218BAA3212AA244283AF321214A8681A322881F12F1A1311F1A28F262411F1AB8A1BBE1F8E1E11F1686A8134AF4A1A16AAEE61BEE1F11F4B1E32D418E8335B141F692B22BCC1BA246D122F24361FF -:803F0000A0662F24B442A2666E622F22D22292222CB662A64248DD5CA0321B7314E02892222A82A466A0112AA26420A1888AF8B1A11F19F9A1E11BCC3BDFAE812EB14AF461C16E422B664AF46141EAE616A6A2AAFEC1B11F38B422FEA1A23B225E535AB5C2BCC1643815F163616AE624A6442B442AE624B462A6222C92222B66222AF68AB9 -:803F80008570A1B13163122AA2223AA3312AA6442AA21115F14141183AA1AA2AFA21B11F18F9A1C14AE416F481812EE14AACE61F16F6E1617AF75151EAAEE66AAEEEBAEB29BC22F281A23B224E435AF5C3C33BC64EA31D213F34B642E624A6442F22B462A6444E622B242E222B222B662A84F4C16CA0120000200200220012208822883225 -:804000008128124A0242008002282A082A0818800818A082200226010000288082840242D0E40B001828002B14000040010020418144A14800A82E4280240542208804C8200280242408484220840448800420042814DFB1011CB41142B11162241B292394612B1419B24299212B94112B94222F1429F242912AD412B931C4911F22E414B7 -:80408000F8214256F1234296F1214296C142DAC2421B2D3CB49142B391E234B1917242B381724293212F2498212F2418F142822AF44282222F242892822A84E822F41F4FC0411AC64119E226311190612B121B612B9419B2429B612B94222F1429F242912AD412B933D412F821521CF921821E81372296F1214296C1439E21249AE212A4E9 -:804100006925A3292F3621E834A1284693214E8219E2249A214E82224E82224E8222882B4229A842B78D0082200800000000280000000028008008410022144002000000000000280000000021F03C830024181400211124A888C04180014321612A882088A482284A2204468224020023AA418A810880820610228404294102438226081C -:80418000802248F23A4D008604324D220089081211A81082B8AA812802132684221201A0121A8201C8299342382088323481C281122E484883032200528B2D0020C444481CA4249F8C4201433C12142604218D81242886011B4220B8A2A1182A61224AC84288481A2AA24A2AA5121820382120A3829AA41438A0848CA21600268884622220 -:8042000080F422D8008830444A829442CF3A0600A02124000092A028248041480488130222281100004229A4242D124224008A92848400C068462201482081014CA24280048028F2DE9310140140922120119661214001290100181218000000100860229A322410A2212E11281400206481002100C0829242228812003645C311284CE8FC -:8042800022D11411B815C449508210121228548249492224C2442021F64AA2222D5523B216F4422412294482A112418880B144622313248992224E2232482D4246A21248282E8A8A11246A88225F93093114413821814C944860124012015602490952124304124AA28623B24411524A292601A84303441211902532130400422A314240FC -:8043000022219C822C8CCB841A3288228F7E4931142288C01527121C911161A7242400842181002128180024812411225844242C6621C032A082322A8144029868A3831242622442222063820082001F340830441042C421105284251C01259614411044948830148A82B28864C140281448143248252C91142136440456084002304828E2 -:80438000278244418A12E482A1828504288C21F1F49D00482D288C81C4148140018074288484682858428004214C04124C0C80C128484128211548044A020048221D94A0818C042044946224809222E3644212EFDF4F021045012528025810480814161802C01481A922C418440046C21844582228002A8401128C02C91114081280A141D9 -:804400006081400858608900416E35004141279141AD1185021F24111C2814DA43E568012381D44888B41C824C344445984446384A85642328CD22C3129265612E141A2222149444226928618866AA415084472A28842B58CCB232E8840241B7B21002A71220C42422100C1484008182461484411822B2486388008021D184248404181215 -:8044800018104498181608841C014A219128414A01874432281018D448031F85040085410340021001004145484C4804202404400120C8444C246C44230415440400444241C03289041984024902222342342844604184AF150A1240C4144901138101811819118311921221104A1C118A1474421298461602120028224216A8214C023EE7 -:8045000048000044840068182280C41888222280F1831720544210021229D422014484188021941800160543154481242464445684411225911465C2425240D2242281411806212400541024A14128441A48388849F2A44410814104465841403118105642131123011285012440A1211018941184411961818100381044C81810044A51A8 -:8045800084811348082888401204004C2802BF7F4122588211274418814311088593112440625213428801181123D114017094010084502843B2580254583024604412C0480010B142012244C0828D14800114FDE680459218951264541054182110084651284464A0412001101814028004514418104438242E44002991444112003028A1 -:804600004CC21218604218884B212818448D181004806194904819941400808582011C01255261C048485100160112414A010016884608124904220082A0420017424304508442290841D0A1021424001562844110161411183444004416412101118400118450821018429812282200502280114241C413C08181B08281280152814C81C9 -:8046800028F85BF64048A84181800148172440424482023490284502491204117911084002884051241115082C04118411161824C888150C2D31201404222290882962824F510816748868D187812D545F21D134F4414247A551164162212447C1856751F04C115439018341D4417458B44851488334522B44463A3A4B22A9716111C82867 -:804700002931444B451C22D4487184C81A3B44D091512422417AF3342829723A446452283F95031F1411145B14E084A41416D158414F36125C31531B12239316A75111A3D134569B1F1654A4473447886F41E424F912549CD1C909C01A5E254975447424A2214C51424E1A67C143D3485811942E8243B4A19224246D4489E88CA928CF83D2 -:80478000E389524C7787242CD422D124F14316D7B5857518D44A1113DA83D19831434D55AD425D1885F8211A27614D1256F4445449714151823551111241457494711EF444362F41F425421E243A43742CF6324B8C71148461B429B48898289D212F41E441F1D2541EA4C014CF4394948A9894AE18FFAD071100140000001200000060829B -:8048000060824604800448800558A042200218118111A11912922123843242304230423042100200812FFA447181734153398F21F558D97F11FC4A4E7F71F1535115F115131E125E545F35F11212BF23F3181AEFF3F25E56AF21B352F218197E7897A59FA4744CFA525A6FA5F55652CF64F5D7D76FE5F1363EE7E56F65F112111F11F319B8 -:804880001F2F7163F33FF1F67B763FB2D22BF267227E73BFBCFC6B4BEF64F544662F6FFFD4562F24B4C6BD54F79C98CDA849F116A45FA8447115F71D4E17711E568F45F5DF45EFE4751FFF5F59D5F111171F21B173F75551EFA1F33F35DFA1F13B398F35F51C367F31F369294FD5F5495BBFA4F4CE5A2FA5F596CE6F65F51C56EFEDFD5FB9 -:804900005F6FE3F37A3FAFF3F376141F57F7191FAFF3F3325B7FD1F35B567F94D4EBF3EBAF7F67F3CBC9BFE4F24E567F75F1F2F66F6DF172746FAEFB5EF8CFABF93EBC8F82D966FA449C7045D775D57D51648FE5F51356B5FE1717BF95F51919BFF1711BFB53716F65F11216BF22F31A1AFF91F1747B6F61F13D5D7F51E197F749191F24A1 -:80498000D4C9F8585CCFE1F55656BF71F5D1D38FB3F3763CEFE5F7165C1B314D643E16AFE1F33312BB35AF7555D2AFF6F147645E1FBF9EFE4A2AAB5457342F4F7CF4B646F6CED2EBFFCB99AF8AA89ACFCAFBCD2634777DDF61F113134765AFECF51B1EFFE4F11C1FFF95F51C159F31F11B123B757F35F43F1BFF73F3171EBF91E1B7F7140B -:804A000016FF93F137754FD5F54D4DDFB4F45E8DCFC5F59C1E6F65F51E16DFFDFD682F2FE7F37F7E3FE3F316644CF63C1E2F63F37716FF41F378776FD4F4681FBFFCFE1196BF8E5EACFF74F515172F6FED6BF176744FAEFB7EEAEF4BF9BE9CCFEAF9ACACBF7B052901618421484D1184452241424883441101154804301181001185048500 -:804A80001403413022501460125014501450140040414821890264828D24824482BEBA4042C41215885181211B412115182241013C31142041024E154118404528011224446D188B252456041A42428481A41412E08854188410044120421284618240F93A87C0421F4152281F417248F11124A3D441B24AF11124AB9419B24A19F54A92AA -:804B00004F82F44A9343F24A914782AF14F924484E954FA2E414F8264A56F1264AD6E1A2655D2EDA9E242E4A1F49C2421F49D228F1912C83F4912CA3F4812CAB141D24AB9419B24A3995AB9443B24A39342B94478229F9344889F9244A4F4D06ACF411648D421E24C7141F41324A1D24AB141F41F64A941D24ABB451AF64D984F448B341EF -:804B80008F149944AF1419F242954F82E114F926885E8167A2D6E1A261542E9B9E252E4A1FC9C24A1F49C6521FC92276913C6217C8AB161741AF467881B46AB195B24A3924AB9443BB4A792498926F83949A4F22F53DEB402808008200000080820100000021008008000014008400000000004400001002308400B0F40340C21415E21162 -:804C0000C4184601481994481A043018008C5428C181410026282471444282C13610C2882816046C81A2828C0417822AC99A70823141C08880C8281823840140F492EE10B1812312CC288615D4415112441885C1482584CC15178941C04219285448874411257A41041504118C83224235C2148445A2414712484148481222188E142124A3 -:804C8000434186B88CD24A041C44F8EA5B10E18C9314D43B43C961145D12194411DC812142E4816C111B8185447A4CC28A43142455298994414918237121B611028C52144B854679147A24A2C14D614845A16856522426A1524489483294EC2258486D1A0084CBAA0011230281191804C0444A81744802101488044001814588426241481C -:804D0000442112A428882821002042088C826188188214922100C012AA240442413F9D0C222861805141403844008A44234824C11412292302000010081229014B52838421BC2241941240D241A2148424484248241220422601002A04482727241691142601469418453115126AC1A13210981185C2E12618D822E1C8644F844398AC2725 -:804D80001616445484B042018A922822441A82D848F3A41810B6124A84888181042522B122FC4428274C238A0A7024F26BB930222215044415041C911412A28A1411D24181F112811A323823914C4A02402202444412124C87E481E2222C82911243512C2CC2148B2141C2002418A012224D6A8A14026860664FEE0919311429021AC4187B -:804E000015148CA424142A018308844916188232824B81814CB88C9241160C16189242E0820860412684C828B251422308214A818544424292C42911A4282A08007B4350424A811224A4821614423C8C1068C14126C2142948228A311429121428293425440048248C614247A2464234584931128818206821412412234208121884221019 -:804E8000827438E45201244A321818320020021D1813624A18412618081244291A0E7014D814CA12D081B138A42119522489440812427044B82821F42C128C8244584230284848408A418211C224127F840422108212E41831286011003042A116081243518440088486041088021062412280042228804214085048929884821883912226 -:804F000041008C286281F01C99244C82B31892144B211C1108167D88C411341A544249F12A16922CA1184423CB2C448D84C113321963321836AA42222E16C143869424842C61844B12421884437598C2828321B818C4421AD268112822288211B8D4068602212842284F22012210C828896881811018D44822514810088849C42440812451 -:804F8000D12411A8425022122A41B424618889C12C2B82842112248460810018901AF0482443F2B17420922418008121A426212201141820092088413AAC82003818A85048449024C0284228A02412299218A9328441128489428221022284221004429F350A848141441B41489180215112892111A8121914228881288441024282304119 -:805000008362241A7221886164182E12240022830882128B128008381012A41C4120849224F0EC8320088721100814004008846C04448210B2642889084410141224234242140A40044C81112801448482812E824440849112812361888E128440F8EE8800106121B08401442487414014111A984289110484211118A418910000284200B4 -:8050800044144CC14244D0484405A28180A418C99228499428411084248421FAD139304516084A81410A4008140010688100100A442200302C18450860880042239118254804418001481812821218002048048034129F3F0C1200504100B06101442D1C800180C8182041943882848445224408121A981134C412240012301240588441F8 -:805100002880210441241088252111048D4E00C0481098124E161821200148008247A1D042048490481004602252A18304181A460444282412888A31A22081080000444200A04232F07FCE203184502630829014244D2800A74146A414A514D24A414A140236480684224B144262A1235122102A8404A512048634145022222F2204257233 -:80518000A8642482A4A01444189489F4CB881001198632844124404492482504286180842221A418112111890198002321644485012C44144805850181482AA14A4004680000289128C4292CBA7F06137388E813219481A72125D882E121F1283AC1F0411521D029B84ED842E129816184C11E882544D848DA82D541D82497162F2B71268E -:805200007C286864278341472343E18344783844EA4A23E84218C26216A25147224F2443B84A029F8186F448488D174AE665055C74A4548D16D62491941667611B2245E425B11A11FA5416A7C56F81C112C783426F6C3A923F53AB484532424512E42667816E484B641CD124D182D624F1724227C48161AD1186D845098D8C5E68AC638E02 -:805280002D98242BB14467418654424D84CAF332144E21BE884BAE8021419236AFD1C44C1314744E3112354968818D482CE34C64898612FE1848C969888B329518CC193A721438688F2152889F2D341243F148441D1489D172C21647236B9483F91EC84F23B38CA183984B288744858CA4821E4A8F81AA141694244BC3817FBB0D139414A3 -:805300001143924110111411140148644854124448441A041A44854481410114800289021992141902193242282304632468246024602422462212280810F89EFD141F12E296F2393F1D13FFD4F454559F14F41911BF95F53A37FFB555BABFD4D48CD1A8F3189BAF91F178F8AFA17988E8A8F449C88F9EFE524B3D418FA2F673733F27F7BA -:8053800013725FB7F59F9BCF89BB34F3323EBF72F251633FB3F32F2CC5F55C6BEFEEF6FF6FE764EAB6F2B3DCB988F4DAD88FCDF95A1CED4C8F8EFE7CB84F8FF9B5D48FE8FB3C7C4BBB2F8EFEAF37141F12F2656D9FF3F31152FFF4F45F55FF55B51BF15B5BBFF3F35B5FBD19BFB3538E8FA1F71AD3EFF9F972FAEFC17D18F88C4EAF96FDF0 -:8054000039398D1B7D4DDFFAF77777FFEFFF5774DFB4F71F3BFF69FB34367F61F116162F24F6232D9FA1F16E67CFB1F2AF2DAFAFF6DE9EEFCBF73E448F45B7D8F39AFCCFC8FD5E7CEFC7F394DA6F83FFF4D84FDFF9D8BCEFC7B7B4EBA7FC85E5F065453AF4393F5F61F35F1D4F45F15959FD1CFFF6F43A16BFF5F51A1BBF95F74C1AEFE4D8 -:80548000F59F9EB781CFE6FF1298CFC8F9D898FFC1FD38B9DD1E37A4FFF4BA12F374472FA5F5745EEFEAF8BE854F41F3525A65FE76467D668FB1F11A12F762EFCB714FFFAEF48FA3F7BA78AFEBFB7A382F21FF86D4EFC17146F68AC8CFE1FED6ACCF43F55434AFC7F6B8BCEEF81B34145F53F53C559FF3F35636FFD5F15E1BFFD5F51E1CD6 -:80550000FFF5F53A3FBFB5D493F15B3B6FA5F17E5EFFE9FD9F9EEFE6FE56DCCFC5FDDC9CEDDD9F975FED77E4EFE5F85351CFFFF75A78CFE5F71E3EEF5BDDCCF27E7E6F61F57353FD24AFF3F35A16FFE3F1FFDD8FE5F9AAFECFE3F3FA3CAFADF9BA78EFA9F9CE9CEFC7F11656EFEBFB5EAE6FCDFEFC9C4F4DFB7C7CCFCBED82FD457F2002AD -:8055800000000020412201122482444024482449041092282189921283948442219014100218844909224042486281404864812001124A02EFF40C438802446D121E486041C024A140425848418971141812847124481144312287512154E05192824424444890184421446049454248A2282443114818528421848F44381481226FEF0559 -:805600004D421F41522C1FC132481F41364E1D24EB141D24AB9419F24A9251AF443935AF5439A42F547934F842B54F83E414F9244A4E854FA264114FA265192E4A96E5A2E449E2A2F491244F32F491248F32F1912487161F49766AF1816CEB141D64AF249961AF249945AF24B934F44AB24B42ABB44F8A94B24F8294984FA2B4630845D22E -:8056800081D624F1114483F41164E5D2C1961619D64AF91164ADA213D1483A35AF44B9A4D45AF334482F54FB36488F14F926528F54E922EC54E8A2615D266A592E4B8E252E528F49F2244B9E648F32E5497268E1497662F1816CEB1419764AD641F66A825B68AF24B9A4F448224B4A8BB44B4AA9BBA6941A4F22F5E9C440080000000000BE -:80570000000000000000008800800214008480048008220000800200000040017F514A2294112411404544C8481D121986791108D449245224124F832443082220B212D28441024881272230821F288431812584C22620116B882A019E42888484884528A14112430849F29E557011248831282ADD2233584712308440294485C41283C811 -:80578000488A4222B864886188214480F212888416A48210C8122230382C78942831144422434198228001267441289822144483C125819FDB0F4671410880FC16214CC521425B1867168D11264954944B4129189C828CF3A2128C82F1388260621AB218C898251894212185C2821B8427848F38428481229114B145383C28D2239828853F -:8058000024183C1246C112811428DBF69016122CD181A212104A1C0820A81411429028483849044B48000070240220C58828211222121882EB8216140622922400122072482188224134944C52847F3C071410420884831481C148244021482103C02113CA34221014080012238242428401401416911A4480324C00820042478142206456 -:8058800082444301A2BF680C6B341226E922C129715302423B128B25B28252427016781A61814C3148462422048B2449334AC14E1890582024BA44A13816E181C8421678974204A92C2415AAC11C216888282A38124A2884042BCFC05412111602A575480452130100582092142D188C61184A21044884A01221C128281800A21886240100 -:805900008C91122338244598C8428E12804C41C8882882A142002AD8AF4D3221702298289C02131201A3E6A285CB81881C642181111CB214322C438212042E48448C64211E48C04A445890443865F181182354844D13201402488112529624044AA22149B8442104BF6D031C31442C9228160B182225183213228F497282022144124728B1 -:80598000241688064243312449420410B221810184882626288125082021914428228200121E426A412458825216F2F932504242214014481464112850B2444C0389C22840B84C81D84A982824568A48022D98C3C1121165F28864C425158254C22120124E449214AC31381E448C0126180C242AD1424128B522040050214844100A100830 -:805A00004049C816102621220418818810489824400800122820C121C0284788188449042048281818064489012844F0E6E2C015442342F91E429014E962B12C12D881B21A78830E6C514823C18827C41AF484288361A44394264D22859638856281124C916A43F1268129A281671123E588C22CC116E841844598928E4C98818B21C38539 -:805A8000D568818863C4B03E0D21408242410C10023C01205128268812C41432A988840289088160484901272290840044218C02C082124110A2218112815042D04202384588C1425F72064210198924C1488CB2184408833124608649416845481428456821200448224A8882C48550A424881129211182021A0820294182718488C18657 -:805B00004B124301422212888FB20C8C022D224A02938201A082242211450884A2882D124482801804C40081867884022028483284438822018410442402490122230800224004121FF70600008420021004A4400228120026820140180645180200842E8421C42042823818881012144202648041040040280442DFD806A490411021589C -:805B8000221C1113B11A0CC92121281886866881140080682248A48C4502258284012041582410044394184A1288024B242034184210220110F2AD7E3081124126485C282084023C0224002722C032168282341248C04216084440826641408204849018A442808204428A0486948460C421478C8304214528F163CFC0288430422E4280C8 -:805C0000444AC2188C0840A81248128C2832892885447488040012120080112151827012018008834128416441A021308A30142001169412483FD50540E28204001890442AAC142A64848A92488C211862448008009810023084430121C444459214822141818841208862820090140000128882885F75071D442830112428C041404201DD -:805C80002B1898214C08218810A2614BC11002B06861484A02B08424E588222418282814DA28641CE0411418A8428A9448428004004004EFCC08A4814880825121C0321745281DC42449223842106C8243D88504848A8491448949028428894501488485811408428881308A2C684482192261828A01E025028221228E9CA0468788B53C8F -:805D0000536490528D122E54812DC12F26F214BE27A8AE884B9238AB138B486552388741C7412534866085268AC8222744944C58C94D2A21B7D12B112B835624428855648C6188A9C386511632AA122F4183A8222D124F4441A212DB9EC021C0238F82F448682F23633417962D286F2D7881DA89541A8D84A9F4122A29E8A4F44492A6BC58 -:805D800092DC84856D8848A4ED424B618F48F4A8CC48242F2BC4528B4964A6F2888A47A818CF84B8C878C77C18E84FF448222243F7421483A445CFE8B94424741228A5284D1CDAFCD6D250252F2122C2211352981E28297451F2217D8B3792424B114E328F4C7494FA84A42B239DB11F462222DC2CEC24F81C6490182F85014F23FA1ED447 -:805E000043B414F84284C849199518A5BA8244B2182A94864B835EC8A0C94FC8DBC4290447C14A4588A881F0AD1850414044418441440100002041840412004220044218422084218421044200184C14C2442148214823A248214821482148290240082F2D4DF161475FF5515D5F51F5484AEFF1731A5B9BAF83F12B19FF11F589321F5F77 -:805E80003D98EFCCF4DC1C8F8D7B68F85848CF27FDBA98CF4AFA8C88ED8629D8A831128F26F21612AFA6F2A6A4AF88D924F9CA8AAF2BEB2878165C158F69FC869665E628F4BFB7DE9AEFA1F936322F2BEB63D533D12AF63AB28FA1F95216AF89FD3C3DCFE7B754FDDCD8AFA7F64747F061657F43D799E281F56C4EEFF3F37A73AB73EF457B -:805F0000F5FBD1BF5BF9A932BFDFEFA8F88E8C8D1889B328F35CECCF26746BFABCB4CFCDF91E162B8CCFC849F838AA6FA9F9A2A26F4CF88A8F2D96AFE8F9F6BE6F68A8CDCF28F988C68F29D92A7C8AF2AFB72FE8F98A9CAFEAFFAAB22D327F51F81E926F62D3AE99166B98DFE3F37674EFC4ACD56E72EFFB0F5F32F4115795F31311CFE4A7 -:805F8000F45B7BFFD7F37F3FAF83F33F3D9F4DF591323F1DDF64F1DEDECFCEF2F8B8CFCEF8D858CFE3F9B89CEFCEFE1C5CCFC8FD84C48FA2FE366E2FA7B636FF785A6F63FD18CB6F21F5DECE2FABF3C2C21A5D848761AFACDD82F8C44EBF17F3D89AEF8DFDF2D6AF8FEF2577C3F5CAC6AF86FA5CDE2F45F1DAD8CFE1F13E7C2BD1DAED221F -:80600000F39FC9F065633F63D3FDF253391F96F47F7FFFF7F73F7DFFD5F5BDFD9F9BF1B13AFF9DFF1C1E6FCDFDECACCFCEFBECBCEFCDFFBCBEAFCFFDEEFCCFE4F54C5E2F2CFC7EEE6FE3F6F26A6F83FFFCDE2BD5EFE5FD1656AFEDFDF6766F6CFC16D4CFA8795AF6CEDE2FA4FCCC4EBF37F3DC9EEFCDFDF8FAAF2BEB2DFDD715CF2DFD6610 -:80608000AECFA4FD56144F6DFD5E5E6F43F61CDCCFC5AD229D2A200261702641782403260326016088A0482C22898204820010022181698102908210042908988440882828420812400800124E248281F01C8F204804283412904141134842581241853214105422224C391420082144218A52248241502244490818860882208148040023 -:806100008244C01441814121844604EFAC042CF4112485F2112C87161F41B24AD141F24A111D24AB9619B24A19B54A3924AF5439342F147B24D812F924481CF9244A8D814FA27418F1244A96E1A27498E5A2F49824ACF491242E421F49722CF29124EB161F49324E1F48B26AD141B26A9921AB9451AB9443B24A7924B8427B2498B24F82F8 -:8061800084FB244ACFE20CACD141D628D141D618E141F442111D2C65D1C1D24A3881AD2553F148A443D2527914F84A855782AF447926F848B12FA2E114F824925EA52E12D661A2C6E532E15CF224129F4DE2A2E149F42C4113B92CB191362E1B69E7121FC1F42A841F41962A59D61A99442D344B4929BA2494326F81D442FA344A7F5204DD -:806200008480040000008100280048002004210080080000140084800400000040040000000040016F1807800144232194322A018B4222390D488074C4C182902820E584014825423414884334841628822231141AA8822349289988842200204522082922B8124A0A4846A848FE271418A67121783229C2215036224531122608160E8A74 -:8062800062814C827384821544D428022E442883860224F012488165820218478220A61247221845484818C8844A614A8C5D48145AC888819E21C1EFE447014E29AC52781AE21462214F3201C73249B22321721C8222F881584C0A8F2862214B1483242334E2F01468824CD4247811CA48836221124E982C3284A018884D2A22C18481874E -:8063000046641A6C422F8A514819C3882532488F11CC845F360F1812141A023022208284E1880448A0424490324142C014A450244C022800A02124444302981E2881688B12800100188220282498821A948880C2485F5B034110022215681244411124150800304284288488100840E21112E21402C018200225024B82284AA128E0810298 -:806380003048908210284204A04144436244F03D5E804284421131122C912124B0A2248251628420D242225842222A34118396242F9254484425F44224361634544314C41412848612488A84285684218C25E4418488416885260C8CAA1420F69C7600442114143D18224C0214E8281245420870222C1824AA248381C424A4164E64422713 -:8064000044284CE1412444644140A482836428A01A28C4A3848198448112816082100842229F11074C02282002165112645022942400306260228400142648E21432212419846261819024249012890A236182488142008C344212822844834524E542B8241584F4E7C980240545014D1890188420C82244815642095982421841982122D9 -:8064800021184200282942841241A8484440982AC18489024E124F88021618088B24223022109842A025DFE50D2034184008414071440291C41F280300AC014502690841448A11931241005024918CC22442899122521AA22424160849A18260430045188421012F422164A1CF9F0800C0281A0228432211081A04211190144028120445C0 -:806500000846420C8D64214A51848421441880024100124501804408481212421A1208523024D0714D81041638212E18CC014C43C844884E1AD02128146A414FB221624221504143D262145423CC11A4252D288421C42AB1248892182D2889C2385E28556281242E9826C8188D14B058926C2646882165414996483F36068212400C302419 -:80658000841C411892218562811C1101104848758498280084422E420044414C1202484440B44241048C021A242408481800123810A84220F24ADEA01221209112872389C12C818592A883322880124808288128188012082180022148614125124404108202830441A9010040044B1238181885042B121F5A04C42830C844C024122823E8 -:806600000216062902127024187222144241410416042200844483821128C228A4800118184E148B1800F0C1221812188622846282A012F02EC7601B46429224161C24110860220041102242C124188C8282410884408802A4403818301600221612A441443042005800180022200840F8C97340C814110048003502414C440283322411E8 -:80668000219140544940D248820218848C42140840440318C440480184400584428424422548420228005F7B05404C225128430141288110088184000000220040682200842222004902840040449824610000849028442A0118C0184964124FE20C4121848C3222899224000028440010440400402282111202412722424984621200413D -:80670000252412042283241324031859A22144284444306C44321AF439720000410081248001006C0185551881120050128901224185044180014412840024004C045028818C1801242C0810D248022810D84408848A1202118825018122911001420026123C281284122400262206413829C11624C012181869018C1104846890288CC24B -:806780001284C04821C9014C0141F027BD40981848A02800290448212546840225023111120025042E128008258A61442814844048C2455094220046110244488C622290144042024221F0CA63A022CB68F03E1426EC214978187823B82862A8813C120C491266822E3526A43236C11785382C2C5126CFA2B42C7224E865B414B218524836 -:8068000025EA423114456461497112B448A4411CF48E22B301118D412E221E124F21E5227318D4847134C4282E212E284FB40455A61AA1A4871828CD2744D0A2A5225E288425C42AD426D24F128F5384911361222D2A2D24282942586225C84423F212224F416221A762212A721AD584F21134C3B41EE3458493A88B4547AC1A312CA37637 -:8068800016542236F28848C9F414141AF129EDA01127E11582B616736EBC32F124428D22505A27226584316AA3519934A487A1C02CE04102878222122489B32CB26A51C45D181047E8B1110E8312C42C464E484CE8823111A5D8424834884B722992322E1448A9F47BB8100111102114A114114A1181012C012C0118403214100541001202 -:80690000218001188011811181119112151812811881082C088880080000F0B247141F39F3622C1E1ADFF3F3FC795F65FF5B781F54F31B799F81B739F348599FD1F11E1EAF25F522329F93F33C3BDFB2F22E3E6F427215F53D39E7C24FC2722AFA3616AFA7EFA3F22E1A474219846291CB322AF2242345F527219F83F22D2917353F13F348 -:8069800051123F37FB9581AAFAD99DDFD1F991936F6AFB8A9AAFA3FB36BAEFE2F172543E187AF57A6A4FE44DE162F363659F91F12F3D8FB3FB1736BF47F76935AFA1F52B6ABFC6F62839BFD353CE8F84F421399F93F33D3B7FB2F22222A7A27751DF93F33A182B22EF6A1AF26AE8CFC3F22C3ECFE4F42C3D4D248FD2F22B273F72F26C6B08 -:806A0000CD1FFFF2F62926AFE2F26A6EFF53F37D3EAFE7FBB6A41F12F27878DFD1F991936F62F23A3A6F63F932BAEFE3F3565E6FC7A711AFA6F7CB31144B334F63F7353FCFF3F31912EF61F97E3B5F73963A8F84D2D8F2584B3D3165F64E4637319D199FB2F23B39AF82F33A38EF93F331358D18A42FA2782EFE6A6A87A3EFE2F136162F10 -:806A800031F41C3E16F835391F11F214763F63F2333687F1EFC3735CFC79722D5BEFEBF31A9C8F83F359395FF9D5AAE922D3AEF1EA7A4FABF33E1EAF47F53E18CFC6F4687ABF29075F7BF33676CFE3F33E3F9FA3F35E7EEF76F33C66BD19AFA7F34A698FB1D29FF31E1EEFE4F4332B7FD2F3292B7FD3F1363CEFC3F33F391F73F3281A6FB7 -:806B0000E2F226AEA5FAFA7AEFE3F22E3E6FE5F5727E1E36DFC3F3343E2F61F31E76BFE3F37B3E8F51F1383C9FD7F73D36EFF6F7FA3EBFD3FBB9B18F85F79D5F2D926F6AFA3E3A6F6FF7B63EEFE3F35C5CEF87F71C1E8F86F614ED40016F12012501144001140040044C125128803211280080125248B04812062120022170220245022202 -:806B80008C240280444348028D22200485044FD709221504118B1213011D24A7221518C828A10010382420912284408242082240428481E2A241846141C024896141238412421408890121433248224C31241826082E433F65022CF4112485F2112483F41124A3D4C1B26AF18124AB9419B24A19B54A7924F84A9143F2429347822D955FCA -:806C000082C4954FA2C4854FA2E451F2244A96E1A2E459E2A2E449C24A1F49C2421F4952281FC932481F49324A1F48B24AD141B24A9921AF2419B54A3934AB9443B242F9A44829FB2448B84FA2F4944CC04A1F4146F2116CC11B21811D24E11318DE41B24A1AB548BA25B44838244E8147821CF92748986FA2C5814DDA4E81478286C14A39 -:806C800096C54B96D5A4F491283CF4916C3CF4912CC7141B29E7141B29A7141F417248D541F24A3353F14A2443B24A21D242F1844829F91648886FA3F4D69340280800000000448082810200000080010000000040080000000040042800000000004F9C01223011842E5268302124998442094021328883844454488042C8421449A6240B -:806D00006228488C815128801184511886088921C48DCB285883084C018984B28421A11228844D2846F259B480F18314F0A612818218F0128849C8881219E45804868492A484424A62865D488828472281C721843024A827463AB824A42822886148C3964216A41248A92287210C4C32984841462435C41C44F4FA6580F2C619F0861A5E18 -:806D800028230E1123584322112655411CA28282C31628542C50948349627A4CE443344AB04472919816A400478424C18CB4241482748469224F8421A21258288D6489694116C4242E522042F6BA5F80011C8102808192188E48896881428A044189222814A4242E484A024A028942882202224AA2924E242A8982198148B84861412AE1DD -:806E0000C824E28904430880A248A041F084488744484EA6004001830289912121482284000021002044080045021812AC2404128002100481000020C2288112004A21181284118442F82AB9242443C3182332522269842454248CE819244402418B144B289A522C4044346C90481C849482493314C396266314043902287244C3922462A1 -:806E80004B288308184CD484312422288A24322C891204A77C4002182992422458683044C041001024B1842258482304604460C4480049036230464C020020044400A28388220100622C820C83122C12F8DFF624E044430989235284142304A33A9846C422002D48A02100E14426082C61181E4298469A5445EA41028424266144288B12FD -:806F00004426C82462444312382843751864421282302416342244187F74012AA112400289824661842C231A084054432A819328814B21881A042C0230181880082306498182C28289223121C821301C944A82B4822484814224083260447072061012844108800188804108008224422A286442224441469444409858800248A0844100FF -:806F80000020030020086082921A040020014F6D0611100900124031488448109A488B84C1901400002800264A140422001A02206141888C128802004A224858481084142862C24508005FE20617231A0212A1811290412C6B8A8110C244B74C8B382E128F4132A81A868292244722C04887418321218282841324341486C4A82E18208CD8 -:807000000285C441488678C42814A425C1828574180418F0A55D00501C0028621311C848A0418184814004424034844A0190444C1242C44882242848122A88C212001D282622011283A22846026083881A8422820246041FC906250200211008222002200884881082042220084800800420089A1284820122002002188011042220C21407 -:80708000414C722448A4422F520F16C424B0128201304400202C290100208429048248504812444844443220422412C22432009024802A28010044C01468488924815484EFB7072442208301812002284A48840800108281848228044985014248412800322604438122020022A24988A1124100203314424C8202812F2D07ED188F46A4A3 -:807100004425020046045044444BB22A2312880848C2242552229AA1118B888A68484004132188D28C58A88B646AA414009024004D14444B2228224C02442A4464A4E7212D463E54FFE8020000002002200100008185042008006042000020042002008222000000002028042021420440F4621310781288840400A0140041CC228302002A -:8071800012002502211898828800264431211C4298288C644448000082004144222800000025C22429B1D8098424481800000040048C0200000010021880684244442042410484284841A028000088442A888284880420044421288FE902298144021218000044800300000010061880080020414104860C482200000050448002004004E6 -:80720000201802186F1B0C001210222101000000480000000000800200004042042604228200000000000020040084411605A5384C12422244000041B024E28222023088124052222412A08B8A22082218131231218538188B44CA24248802800C4514382420220100401252281AF3367340D2888484140200524044544CA0220000001094 -:8072800092122A81018A0800411414508484224A0400820044444584A22242200880382421212E2C40041022018418001200100884002800000010044441C02220222201448008000088842044820430440028F0B3FF001280018001141210084820010000000000284820021004002008448002888820280400001004008F6C4442061AD9 -:8073000041321200B051011A112861848001841A010000224C226242702424A1224562222812124B2249AA82002004821028044A810480E44828D2C812F456EE10B2121182011A212182040030184250888D840082440000104404266444C0244F4288022028E84208008880A8882004802895244004D0360C18442423814394181880013E -:80738000508810080020020000222828489034A0224160422E248244A028A0288A088881008AA448234404424141222E24BF64042F22D222A2122B111229012C512329F812131F11B189F991898F84F888418F842454911148955C884E488F44F424444B242E24222E2480524445A6222F227212C2122B191AB88228E828592229F81213E8 -:807400001F11B188E999F848888B488F8424E4840448855C884AF68D8DF0262625A2123A2111021C5122213CF1111119ED897818F88841CA2464941501848588F4484445B444A22622448052424584F3262625A2321AA1812B8982502229C81B1B1119E889F818888B48CA244408405888483FA90100141100000000000000000000000028 -:807480000000401808000000848100000000000000F07D9C0040110100000000004042024002255222250240424202008481000081810000000000000000005F7A0E0014110000000010024002502224000024250885020040588840180810080081000000000000005F180D00141100000000400210020021240010028518080040085001 -:8075000088000010181808000000000000F0746C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000E7 -:8075800000005022212100240000002125021012020000008100000000000000000000EF7B0F0014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000CF -:80760000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000E7 -:80768000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C0040110100000000000000000000000000008481000000401808000000DB -:8077000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C0040110100000000000000000000EB -:8077800000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07DF4 -:807800009C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F540800141100000000000000000000000000004018FF -:8078800008000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F5408001411005D -:8079000000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C0040110100000000000000004042420200000040180800000084A4 -:8079800000000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C0040110100000000000000AE -:807A000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC70900141100000000000000000000000000004018080000008481000000000000DE -:807A800000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000068 -:807B000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC70900A7 -:807B800014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C0040110100000000000000000000000000008481000011 -:807C00000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C0040110100000086 -:807C80000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000000000000000000000401808000000848100005C -:807D00000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000002424400221212140020000400881008100000000000000000000FF680700141100000000000000A3 -:807D800000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000020 -:807E000000009F54080014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000021212140020000002163 -:807E8000210081240000100800001008000000000000002F75090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000404242020000004018080000008400000000000000009F54080014110000000000002421404202004012425828000010088481001018088100000085 -:807F0000000000001FEF0D001411000000004002100200212400100285180800400850880000008181000000000000006F47080014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000073 -:807F8000000024242400002400401808001008818400000000000000009FC8050014110000000000002125120224210010120221A10000841048080000818100000000000000DFFB090014110000000000000000000000000000401808000000848100000000000000F07D9C0040110100000000000000004042420200000040180800008A -:80800000008400000000000000009F54080014110000000000002421404202004012425828000010088481008181101808000000000000F076DA00401101000000002400210010420200215088810000840085080000101808000000000000F07684004011010000000000000000000000000000848100000040180800000000000000DFCA -:80808000C7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000024242400002400004042020081818400000000841008000000000000F0731D004011010000000000002121002100002121840000100881840000101808000000000000F0BB1A00401101000000002512120200EB -:80810000240000002481240000818100810000841008000000000000F07EB60040110100000000000025022100000025028100008400848100000000000000000000F02C44004011010000000000401202240000502240185A220081008184810000848100000000000000F0BFA7004011010000000024242421000024000021855A2A24E1 -:8081800025020000818110181818181808000000000000D0840E0014110000000000000000000000000000401808000000848100000000000000F07D9C00401101000000002400002125121212121202A48548425A828484854808008100001008000000000000F04E9E0040110100000000004052222421251202002552222502A552227B -:80820000000081008100008400000000000000F0162A004011010000000024241012120221000050228184A542020000818400000000000000000000F0C431004011010000000000000000404242020000004018080000008400000000000000009F5408001411000000001002000021000000250A0000845088400800004018080000008B -:80828000000000F0573600401101000000000050220021250200502240180A00401808848100840000000000000000002FEB09001411000000000000100200212502240081002502100885480800000000000000000000F05C8D004011010000000000000000000000000000848100000040180800000000000000DFC709005011400100FC -:80830000000000000000000000000000848100000040180800000000000000DFD10A0010010000000024000040021012120224814002008481001008000081000000000000009FE707001411000000000000400240420200100210020084008100001048180800000000000070C50F001411000000000000000000000000000040180800CA -:808380000000848100000000000000F07D9C004011010000000024242400000024000040022400840081000040181808000000000000F042F400401101000000000040120224240000244058280000100810080040181808000000000000F0B857004011010000000024002100104202002150888140024008508800001018080000000014 -:808400000000004DEA004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C000015414101000000000000000000000000008481000000401808000000000000008F5A0200141100000000000000000024242453 -:80848000000000008481000000400800000000000000F04985004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000040424202000040020000244002400810080000848181000000000000002F440F001411000000000000242140420200400284850224001008100800401808000021 -:8085000000000000008F1C0D00104141010000002400210010420200215088810000840085080000811008000000000000F0D343004011010000000000000000000000000000848100000040180800000000000000DFC7090014110000000000000000000000000000401808000000848100000000000000F07D9C004011010000000000A2 -:80858000000000000000000000848100000040180800000000000000DFC7090010011400000040424202000000000000008181840081000040180800000000000000AFC8030050111400000000000000000000000000008481000000401808000000000000008F410C0014110000000000000000000000000000401808000000848100005B -:808600000000000000F07D9C004011010000000021000000100200000000005088000000401808000000000000008E3B004011010000000000000000404242020000004018080000008400000000000000009F5408001411000000000000244042020000244002000084000000008400000000000000008FBF040014100100000010024070 -:80868000022424242100400240420A40480800000040180800000000000000FFDA07001411000000000000250210020000212440180A008400401808008400000000000000004DCD0040110100000000240025022110022502002481104202000000000085088100000000000000BFD14B0116410148488C34242028225858442884805244 -:80870000482001128282A290928001224C282414420882C0482A1184240282202884C224C483A129892209126F6E061964848146591C45D824324866946417413832869884433224C921A329E8988E425646C2523830922388ED4489C484412AA4248146F8984441C364862AB814C4242A8112C4A443043A3424481A088F2CD148BC520C20 -:8087800011994531415443D428E6421484641120018800842822422044041E2226420218A0124B480080028884B0283128A0212200822200462821440842F074B700100800008088A281918948342C2828818A01181852A0480082201804444522464828B49404004A082009414CAC243034848222188378C8B452040040C84810148884AB -:8088000012044084020000288888860221181218211200C8000081802414243244412002000080810124241FBF09420000840022412092240010C4144C019800218200828028A48400428004004548240400220040342430242888881218AFDE0300180000000000004002000000000000004800000000002008000000000000E038043045 -:808880001181138134618C322881CC223E68C0114A08E01102218E48268818844C4A88832414626492A2121A44A282897318048AB41242B844822A88080000001648942442CF99054A031684C222168C1534442181141A143A18121A44A64387441644C4444224221846F5822CC042284902A0280044683624422408114281C3044AA818C8 -:80890000C0346A81B4288584F27EA9A0141883012E424B241E68492214AAC219866481CA21A14136B5127642EC8861C2434464242C82F12156868454224E242F482188A187B022382C874549A148234368442E8182888C044288208234182E1462628FC20B2211411B2170110884C14C1248C8121181000060448088844818088B242004DA -:808980002822000012222822448828801418048218C01432428C44041F7A0224001A02001181824E811962140043210420029028222002002081280144C800001084322848220012004A228122C22482001FA10A18542313F622182CC1348D441D1249E38201844898888328E2821164162AE44148E48482D48456846F8403E9C42243A678 -:808A000042222E144F11024983384422432538248A61368144D81E2C8CD142B244981448284348F4ABD600F01222228C021A120423C98128008A41B44888120819A4241241201614588224468C4824C62449E912014C024443A2168C4A2462161024381C5249A2844B21624014D4A20E18716041236121441784871143E2841371488104EE -:808A80001A0880332428B08C223268E08442B4240512282B25004A4204128842400462922481124A21722822312440A48282F07916206124200210542511818CA1144CC2854E1492181284A0812F4804C9048A156242A0144181A28241812212322882241C13E224210810028A41E82835144C22B1840423F1C2F260424A220241210020E9 -:808B000033822244280000284D484CC22220E843A4284A3218A8108232442601A31884028441004E8889528428208224820428424128482F81F2B347001014028B122688C228000081214E28CDA214800300508284444210488A84011A2284012011922420418404528B4884850210A8180080F46677302428433222806382599228A49878 -:808B800058C087424AB2188A2162C196840AC3B842A2242742CC222855422D284B243034484CA3212A4112C4242CC288244A8822358242A284CA31383624C1C4488B24DFF4091810024542180425A121812840C81496481611A84228490448854428848542188824A982908200B028214832114AE1C11608C0488116384250428A442402EF -:808C0000F011D7202101002444000010042800267124210121C31422A4614186180446244804402402008D44422E445110081046982490449044102412F22CD7C022C022322828208102221280021AA8824880C68400844430288004902489044C84448862424F2104C120748204AC12E4AC425628608889041012B854F295520050414490 -:808C800015C414442022020020840290241843225284904410044148488A240400448041A4C21031810040024304422141622002F09E6640810600481410814481120883822802001848214800888A054302812848D0840200004002602442830424002C444222224404CFD20F18182001E08182440884488004288848800480840428804A -:808D000024220210982842100800A8A8A0611002844822400822220020F814AD1052821E2848A1000041002228140000A0184800281200008100412004490281204412240280D12882C14244841A04422238F0FC6E2044840420814404184A02174418000012A8001008418860844880040084002810483241904690880080881404826554 -:808D8000088A24F299B840210221C02416814221440114402104004410044C02002800C90849821404004100908600188004484C2283424464434440F446D240081C8542012024046046A024430446644242882210021887248841901890181480422882044220088842264A2682228244424202484823A484AF1F4DC2438B41172147245C -:808E0000114B121CA1458714267429A14455A5446681AA2C424AB3E4614323143846425A058BC648448784878A424E444E44448B22442E244E128B44844E428AA4282A7528428EF4222A222149F44A4629FC46246249B2C4F8924680018B3240813251441158421200288A04193221688A09F028482E44848120E48426B844D14844084873 -:808E80004122188D4486A84437581D876F444488B86A65AC4D444D6A8D6287A449716462824992982AF739A830312F4243B53273286465CD24282A2284A2226688D1C124E342B82454441A982449F6444C10F424224D24437924AC124D44C84F828292244B24842841414BA24F283A246B34502A2784504A4AF142844B14274A224C82D5F9 -:808F000042A44625E41F08174410011190414991411819849141184118484C9141850444400444604120810888810000188421C081C082800888804888488848884808AFDC43736757B3B5FA1233E7D21F14D588F53421979357528F83E713F2314115F451554B67BE2417569F91F178984B914AC44C2A16F4286E2F81E3C6D688F52878ED -:808F80004F41F4A874CF48FA84C42AE246E242D244D244C3142F4AD24254677F75F9E624BE32AF22F29ADCE788EFADF52E2E2B9F6F6AF2D61AE7E4EF89FFACAC5E58CFC7F4947C246F62F15353FFE3F31736EFD6D455F129291B2387815F51F5393D13E143E251E145B574E64B7A21F139398F83A3B82B4485F84858428FA6FB12387EF879 -:809000002AF36C7C4F41F4297D4F48FAA4E54FC2D644F4646C45F424744D546FCAF6E2267F66F277776F4AF2F47E2FAEFEFABEE7ECEFEDF1EEAE6F6FF9A62E6FEBF78EAE6F69FFE6E44FC1F5283A7F8E4BB262F63566E5FD1436FFC3F375749FD5F564348F86F675349FD6A6364AB651F145414BB6EE644F57F144414F47B114B126F224D2 -:80908000244F4213F42CEEE5F83C3CC5F83C2C4F4BFA8C7DCFC4724CFC242C47444F42D644F214344F67F7EC2E4F62FEA6A66F21F926A42FE3F1AA8AAFA1D74CF81E14EF6AFA3E7EEF62FE5E166FECF836746F42F2DCD44FC6FDAF72243F16F73477EFF3F31636FFC7F73435CFC6F664749F96F664658F87A7745F14E614B454B544EB4EA7 -:80910000FE74554F56F6F4F44F49FB2424CFC6F64C4C4F44F47C6EEFC1F1AC2C4F46F67C6C4F4FFACCFD4FC4F66D6C4F46F64444CF4256447AF37C7E4FEEF2E4E67F6EFEF7F76F66FE3A1EA7A2CF8DFF4CCEEF65F56E66EFEFFF6EEEEF67F7642EEFCBFF6664CF4BFDA4EC8FE806230221B026012A01000000A048000042200442B0480279 -:80918000008B24224243222402430200240048C048248C0484244880840200CF1A0B48124722440042446220064200A02443621443881304414C02857424084882100844004180C1684AB8812202221002836482A180022324227424F16A75C0521F417228F2112487241F41324A1D24AB141D24AB9419B24A5985AB944782AF1439252F43 -:80920000147B24D812FB24481CF9244A1CF8244A16F1244A96E1A26459ACE449C24A1F49C2421F497228F291248B141F49324A1FC8F24A111D24AB9419B24A19B54A3924AB9443B2427924B842F92448984FA2F48EA4C04A1E64241ECC241E2C428CB24EC1282F44C9282F445B84ABB44782AF1419B14249D812F922482DB12E528D812E22 -:80928000D216F122CA87192E4216C1439E212CF4912C2CF491688D4217484AB19122E481F24A111B21A7441B21AF443311AB34322324B3426183297132086D585FEE050049040000004004280000000028008008800100000048200200004004280000000021F031A7808101263122812082A21828182034482A289A54608A00222088C4F1 -:809300001141100820D248A242322C1224826232458802180020110242223034802224FABE47241420238121A621992115222814928900A0828852288E4CA0422C243228802286222D2444220C28A0488CA1841A28A4242A0420088C0142228118C8A6018FE304184A2162222280024A233924462262148C822A9A74A09226C288221AE664 -:8093800024A8482E1144200611684E2C89266D26002226212C8AA414412082992218A04250842482489AC2F75012803111188C86F11128248028018628042088C848904400201208288428D80030223024284A6881E112802206004028042832182A840ACF1B0F2215044CA2161A8201218C168AA2849018842009928111814889082042DF -:809400004468412A6148808261410026028002168421A184008218806288428608AE4A7B9190142A81C21182A18062A14CE128E33184511AC84AE3A4C822A2224B2142824988424C9248624A92622B482AA1284443248ABA84B212D424A3529AB4C8E388A486AA049DC4C28CA5284B188A810149E244034FB60541132292214A2203C018FC -:80948000A18E1219821C31188CC482A28A2228013084884508262864842F2204448A322441A2884CE2224194428826684142BA04481088292122811424622C6FB504384C014CA181252821126247A9A24123112AAC2189841122732498418C88648240829424284CA1E13A08A0141624622848321AA252D24E882A09C2C7184A882D328466 -:809500009886088E284B1426F8FC6F202404284A3228F01622426C014662442181298802134A1892A650484886282192241E28CA2298228C62848230D8814889C8161C22847194C112984608881A2628B348032842F08819244CA12416161824C128C098C028284CA14820C21812001221A029412A1C1898124470280148458824614450E9 -:8095800024C06800224304209284284308890812460212DB2E8002301400108828020081602148144901838A01008042441802441882282100281222820042200880A114B01802E0822888086F9E052A84028B12421E282638262F84612222682B142784843AA84213A138842B124B2190A84984E281524827831E2450481AE28822228C71 -:809600003198284725824FA82582A4428A41220949A8C2F2A21EA889321862C8F078A6F08618D024413424001608161408204802A9015490888210048C04224425A82C2E82806444211044088C221201124621098C8421416481A041A882009F360942200128200284422448482184288A2502429A722228D882882831240084008668180B -:80968000AC842228682A82830200818128202102828128829A842228F817B500224142834543688142238104411C1101001A0823241108222284292212648421291296822424414002301824223018803248818180C822801188F4348560885284008A02230228C02841420021424284810022800424814A12480883044210088410082609 -:80970000088284C638488200224842483024F01674501200181489E114421152281225470816066028200620014280E444C14420288494122088032F8401499514415084424400444212818F22918826248481F15D8E008002224A01004A08002C0100282C0200282012D2280222840080140210120200280044200222A80000882324E823 -:8097800018F17D7EA06110C8512F8104121C02272246440700AC58481844894884480C4C08440020C2218718282A842428A32849A1212800A8824444280018204902882904CE9D40CC2A0049C821C148133614284C73585381141840B288C41220013A1C4202848042C24421825042608816A22800C4414C012F486428122410883242401D -:809800002802F08F3524228728C0220080840288008146882A88418268498C280A41224242898404008440222142B82801008182818A1214A841422A088410242824F2BFFD00C04140E1286435400936484481622183E141847838048422274181244288264484912289C361008C0158101474148A248284C4448002824044324818F0120A -:8098800024481FAF493222A69A2A182F48F588412E613E288B448B83424810F949198F8811A2182F86F882622F85B39AC32CAD2886B422C56A66D888926C8B86248BA4A14E282CF112822AD122FA142A8C72147214ECC252CC8E888B2444122A12A22184AB93CAE24129F56415CAD477025A3288145A5681248D1E271415937249C8333738 -:80990000942F9561212CBA84A185CF68A59447488843AA43496624439262656482ACD2437522B81446A24A2A11F8681823F234144C8242A2DA4B441E884B4883A414AA94184B22AC12528490482AF86C2AD04184D78451218F17B27133531D422E2846F63A72B3D26C056123F358C42E221A52888968828B918E822E8228874447416AE462 -:8099800024018F86E228E4BC98C22744826FA92AF98894428D1889148812B8A2E482D882F184484E888E8881CAD4A8FCE242AAAEA91AB1BF4452412444148604441844404802244110044190449044100621830116146241604140044400230427149012901248211618022141100445087F364E7181F15716EFB3F33D6A3F21F2BF2DDFCA -:809A0000D7F23C249F83F224348F88EF21F11B1815F151532F6A53EA6596662FE3FBF2B4CFCEBA24EAEEFEA2266F2AF23274CD26EF6293364F81E5A5F694B64F21F9BEA2AEB26FEBBABEBA94F8E4E4E761AF61F43D675F54F196FEEFAFFF62B22F44ED25744E7E2ABA3AEB2AFA666CEFD6F6A8284E448F4DF57CE6ED79246F65F11D3CCF14 -:809A800093F31F58DFE6F2FF3D9F96F439611F37F6A6A62F4A5E13BFB75755DF55F7A632AFEDF41696EF26FEEEAA2F6EFA6EBCCDA84F8FEE4EEE49E943F71C96EFE4F546584FA1F5574F4FCAFAEEE2CFA3F266766F63BEBEFABCE84F4FFF7E76EF62F63D67DF56D3EEFE6A6CEAF7E8F2EF65741AF868C88BB3AEAAEFC6D6CDD864F82E88E6 -:809B00008F45FD7CE42F3547D246B411E473F2392AFFF7F67363BFB7F2683ACFE6A7748FCFEF25F15A7AFF54F54D4FAFAAFBEEF84F24FD521E2FACBA96FFA6A8EEE48FAAFB86A26F22EA62F27C744FC2E6E3E627F6467FAF2CFEC2CCFEEA4F68FF82F2AFE8FA1294EFE8FA4C4CE5F476244E1A4FC8FEEAE45AECA1F29298CF4C38A88FAB99 -:809B8000FBA6A48FAFFF6E6AEFCFB3E2F6E4784BF6CF810D1F1DF71D262F53F25B189FAEF63F3FFFC6F62979DFF6F3EAAAAF8E7E41F1597B1D13AF37F5AABAEF8FCF962FE5F9C2AAEF88FEA2ACFEE48FAAFBE6E25EE6AFE7F7CA4C45ECE7F67862AFB4F5AEEC8FEBEFAFFE82F26F69FB98AE2F6DFBCEEECF81F33E3C6FC7F26C3ECFC9FFE7 -:809C0000EAE2AF8DF4D8E8CFEDFDDAD2ABC68FA3FBA6AC8FAFF9EAAE2BBBAF8AFAE4F86EB48FDC022A012E1180013C8124E2812402E081442149A2412CA24889220100A0241008830481002B82B022016941484228420886484208482C6281288242924282BFDA07000080062881122C8804842186C8A2102A08A2888688820443022A041B -:809C80002602C828488240B828283124100480220481800842260822001D16C0421F4152281F41B248F11124AB141F41B24AD141F24A9219B24A19B54A3924AF1439242F147924D812F924481CF9244A1CF8244A16F1245A96E1A265592EDA9E24ACF591242CF5912485F2912483F49124A3F48124AB161D24AB9419B24A9945AB94478305 -:809D0000AB9443BA42792498924F8284F9244AEFC90E1CB411068C66141D28A3C428A71419F242968CF248A559F24A924B422F1479A4F84211478A27146F82E414F9265A1CF824DA8D816F2264182FA26458BC6C48BCF4812CACF491648D421F497248F2916483E448F64A121D448D1619D648BB95F44AA247838B84222F246183882B43FD -:809D800029A8527FF60E848248100200004024C82400000000001800000040010000000000004480020080010025012FDC0B4800215281489053204CE2813488848E1200E08801008982E24402222A044008820012888281828922E3820846A842884820A448002BA52002C8DF3402B08201182832188820222282084521A44A43128202F3 -:809E00004A18040000602284802281E21132228116422492840049A882124281480022178C80A88414F0C4EB2074D208215289A2418813259284222BC340AC814A88021EA82440648328C60420820215282239282E124A8328018AE288028A32844F84A224A2484A2224042CA4E124E214884F990C00202122011002621068881448291231 -:809E80001402A048002002224224810000141028180E411A12088812428400882299088800484B88002008880080080000000000000000000000000000000000000000110010011400775E200231181285C4216228846B121C74118238828CB234A1483CB82151421A82F8854854428542A8241A047368488F82A5A400311816D148B441DD -:809F000088021E287F128144C2846B28841AA14A29484204A89E488D25B02242D281A141894864144C12C4282F1281F491828421839154422E87116B381A782838844E45221D228D18124A2C1803188F42822814C71412896A18669C249127121AF588828423A44149239282248E148B818C223818002008200880080000000000000000F7 -:809F8000000000000000000000000000110010011400FFF4024840031C0100002302148688A84229218881841181B32504000026285182441880410400484B12008281102841228812C4140082C04815071F22D124A3128D12282AA14247824E22C38721B448011C04221E6828A28AE682A448001CA4241E224A2335244CA4242249C2E49C -:80A00000803A248B526B1A8843B9549222D223280546D14825BC12BE4898448849644149B28902582229C1121322834604251C22D481918819280216084888622A2C0213A44216A2168B244C13CC241A42A486448810B882C2A4982E14218A31828304F04284422339844130844C41FCFF47302163C12381180026A8243A84034280C442C0 -:80A0800032AAA412A82A45299145008002122448428032148062424AB314241124249A488021C14189A1824B248C858488044AD27D4F2241B1483218C018000042322C082081681431CC4298426014228001112810012280588414144602830113214224024608284F82A814808101E084F3F22C004810A21420221301100C2283A98200C0 -:80A100008C01908211884230248800D081A28600128C8603D048248806444448AA21880400890B23622218187F8605280049021048982838964802C24C0484818A22A14800840042A8419011421882220088122832481800588D110020911200284200F07A68001128A3A21481848341889398835322488B49328908B67818A4484A48C133 -:80A18000884820051110A1245A2A0A9243E2139811284381244241041786888C28C4328F42286481B012862231486FA8062B121068412021826212200488824482D08154122281001984024C22422422410880020060248C96981A8481A214121848001812A8320020F2961D304218201208422501424B1442228911D212228421822808EE -:80A20000882348021C0240E1618829484104200820E421222228028018A282A04100420024427F7A0F12288142248082410A2822C8298888C1822E821224421C082822001126244801184B288A3185821123F811448A124534412741193222188A820422214901008249F2F6778001001334188180352881009028800122809182108806AA -:80A2800020242A04120020A421001200828C01A818688200880018188A8481F15D8F008014A8282830280024248901524048E4288458414212484C3842122812002100899221A113212198162220081810011828224C9142814880045F2B04868162114212211A8201124321C644424E1219E889B44988A1148021528120440286228884CF -:80A30000C242208821A2284A51411A34C14289832F1802601182423024E8828042B17846622280A2212086641481422A18A8182C018D1228180011280011A02412174416D141A848223A24044B41492402602118748411E8D012240A109288800112481F370FC012484008102202848E14A48DA18D814810422192221411005014114004EB -:80A38000004D814443082D42499842403424424142604880342444414884220044AF7E0E1120414801A04262818001C02122002084098A21022001124381011212121860414821A288004A48A818440025C288322028A22148E0A20784F021482094481088A1122C542880028308266E281880716A14A19428C82B52482904601821688CF4 -:80A40000948248002180210212444AA134148218248301002382F285A3241E22928B122A5421A9E7A2E2110483F1241C4AD22872DAF2313B2D91A6F254812B9A6E52221B128D2421493242472219E161A2884C18E221F18244445F48E944B984E844E724B414FE819627427E144F4A3A9829D14408AEA1B02E4894828D9820E2157442F413 -:80A480002E9F90127011E985D28824A6443B168F23A454E83E122B49118A3CB11ED8AFEAA241927D112719FA7949E11A041B71482EC12D511E531A84AE924F88EE2196221F41E129B81731824322C4EA2B112A8BA81C13F411524BA8CA7234F25844A23A042A91648F4F0217142E3228815E2184128D284E382E288725ADC84F84C998A3EC -:80A50000F44828A384C12329A88D4A48E18AE224A84246F172214B1C574553A8B8825F11A2174671B8C2232186A5165E214BB197188B441734FAF211622BC942221E5229F124184A84AB858AA2129F150E11100184211042180200144834400110045181450245021502241004101114111411121152812111211221504212002001002FDF -:80A580009B4DF3212337A1BF12F211319F364212D839F3637B6E7A8F2CD922135A33BF9111F321226F62F813113F3ABAE2FA6184EEE45F7EF482815F52F657753F76FCD643475C6F71F146C64F4BBAC27C74F575667565512E211F26F253136E472F7AFAE1B27F66D2ADF153631F75F4C3C29E822B57EFE4F4A2B26FC4F148885AA7CFFAD0 -:80A60000FE24426FB34ED231D113F421291E799FB5E581F17A5ABFB6F67B332E22CFAEF8E2FACB768D8A8F88E818F8D1DB7FF6F4A2E27F79FDE6263F57E14EFCF4766F7CFEA3F31F15F466E62F6CE774F5C4C54F56FEA6346F18F3E1E9EE633F2EBF33F2B1A17E773F68F8E3C23F7FFED2F37F79F2EA5F2F2EFEE3F73DC23F31B872F74ACD -:80A68000EA4F2AFA7C6C8F82EA2EBE72A4476F23F7B4C8243F32F23262B5F111119F96F272785E122B24BF96F66A682FEDDD22F39AAA1F3CF59B13AF37FF28BAFF76FDD6967F7EFBF7F53BD6DF13FF21534D873F12EE25F761474F1DF4C6455751DEC3BAFA46444FC7FD44C77F69FC97862F6BFBE4A77F4FFB51462D844F75F86A388D9F0A -:80A700003F15F7D1F33B54DABDF2FD5C5E6F6EFF4E1C8F84A8752BCEBAFB2412FFCD4BF221333B239F92F258399F97F732388F87F5383A9F17B732F5FADEAF2AFBDAFA5ED3AF89F93B38BFAEFF7E565F7FFF53D33F1FF77351DF1BFD24742F14FE31E14F65F4F5353F5DFF56D54F7DBDF2BFB2B397F3F4F51F6FF7B6766F3BF2B2A77F67C1 -:80A78000F7B636FE572F7EFFD1D27F69F3E9DA2F26FE45F33F24F5D1D16F4FFF5CFC4F6EFF7C7C8F83ABBB2B8AFED24B723F1B0B2A0121204288E18144E18144E28944820417892C124126282488228802421842514288424929A412A092F02481F02481481C08221A049224482CA2418922091228F01383602812A1281848C02880220252 -:80A800006089460242B6082A84014A410819A424224219290128B0418208256141632401928B86441C292884044198604422A048C0415D7BC0521F4152281F4132481FC1326A1D24AB141D2CAB9619B24A19F54A914B42AF1439242F147B24D852F924488D954FA2E454FA244A16F5244A9E252E4A96C54A9E242E4A1F49C2421F49522833 -:80A880001F4932481F49364A1F48B24AD1C1B66AB911B24A19B54A3934ABB443B242F9344829F92448984FAAF49941C04A1F4156281F4126F4112C8354414AF1812C8F4411F14AB441AF14BB24F44A91412F1469822D912F82949829C5912E881E818C24E98264599CE449C24B17C9ACB49156281B69811F49324A1B28A9D1C1F2429417F1 -:80A9000081AF441AB54A2BB14A79249812478329F9264829E9A8B58304000000200282400428000000002180018800004001008004000000400428200100008121F04CEF0022802102284602288C081B142B84608246327119826A581B421A0449B2235481D018A2241828B6084A3222188492824B41200148882212881008A2122908AEF1 -:80A9800018184AF2E528E024B2848121C2421E221485E181F282114A018219614810C8828E584E11528841682308902A00178449C84220A9182AA821431231222128632AA84352C8811E81882A28216886238E4401FF960E4E22560412482C233248A128C9041F2229BD848242E225BAA8B411FC8146CA9254122B283B288181850115F8D1 -:80AA000081248B69B0282CA2248CC274344E32806348C84B69222A25983182A28A4262822DE24EB81823F7CD4800281828260214112E121389094211403848111C218211012A4484443122282A2405102291929218828844002302A041888488842081A9480000BF360B2400280049410800122182241260820090418044914114A0212055 -:80AA8000C11280242402271220242982324213A89282244301003288AA84290A708E0928186F2291188363228CA63462278A228CC851844B491DAC602919EB1A21B724611887122844688594481F82C424C84E24282E141B8449C1884D128B82432218E419B228944113832CD881AC422A35844A12A44249E4443A245F480424100218242A -:80AB00002E481222238232981C0186140A831141013E44822E411C5214224100222002284092214D1246684A1024C9A819A1928869D88128A642824A9224C2412AC8249E732082B114D282C3282849E184829488002934881AB4A5012AB882A3387814148420C441848B529396149AD442A4424B411BC249C188A082122A88B24332416A3E -:80AB80004821848104184323A8842A216E44F0BDF90060C5843283AA21CA0210011614884422EE242221022180081CC1488B840088912AE581422164A280044A884A913112860400248938844A22018C3222A28BC1FF7E438104421C2304848741282E8884844C882931888444E210B14209224B4289034C691A42161141823C448284A0CC -:80AC0000482A01202328C21412601248205741421282292881F3DCF330120021808924D88204380011901412855181421284480000225289026844A02128111A9835800248A97444028384C8824112841422684304004544A31450482F122196188CF7244284898A021A98981847882F8659689E284A223198488A028094289E614AC28160 -:80AC8000814931882E514217221845818288E82522F1241240088611D48228E344A24178E8A2828B248F13090018841828608162D0184108114212B0216414408104E04472211898544028A1424AB22245A48280A829186822118F168884A941883042128F44082850488023D8D30E60888021C34184122A849448AC8221C9C8C02181224F -:80AD0000263181394291228219460188914E9898822184329C9221348C42248484C26142624448824921220148222098421F3A0A4842808244024210C222B04828042C24444262A400003127814222840048100100301280C31230419084E0228408C84A0942828800886F1508208941081A22120821120020A182812A98891480240A00C2 -:80AD800000184E21402822822106001A04A02100320018838502228A01802684FAAADD00100115085828801233422004800A48800190482220924800144021842A91888042242892829082114498001A18248122828108846FF30248442890281924840281228A010022800416082248828004888188848018810100160142008880888C70 -:80AE00000181812008928001F034490012A0124A01914A81420290848884844E812419EA6428230C8D11230430481B281628860AC22814282E428213521886882482828422842C882222820C1A2A3622F014E5001410012400294181454282111231122224221304178890812D224E8A262281126181460114401101218A2125083C8111AB -:80AE800002C042435428002C0400421F960430828942888801218184888AE224018888004A81088828C24A022860228A25C22222888024042289342882121812280000845A0818130227414E11F0A3DF40085800A219422824024C042816321D201C28A184304A1902908800B082014E1128881518C2485014481119228848C184823812DE -:80AF000000882001B02208EF910E4E4286882183A2E22B63812396433AED24F892425AE981E51BB222A1448AF527282A2CA6E21B8D2E228B542E62A03317381E596E889A14A198526E811C62224F11E286EE1423ACE89A292D0A4AA89CEBC382AA28B68168224B828E21486F9F0CE049311885283B11116AD628D1A8022B284D1829C482C1 -:80AF8000D5E888E6A868B68F1D3D418A1E0819582293E42246A9E383E621A3A62A8EF221738912E818914953A1811A87E11294E3E84AAA48E0CCA34621923A27A9712E11CAF821FF0019B42192319F84E5347148EB818126F2432A2E584A28388A2CFC41812A92AB242F191173C1F92A6B2F1CB4214278C8B888F84A181BA88308271C1734 -:80B0000083508117223B2127C68B188F28B423681239E25231429E561AF11848B01CAB31D842292BA4C4A9F2C3A8001C41480100241E48140040020000000000100211421100004222200243824423612248228A14022584148294220012F0BBC64052571AD119E42EF26323BF34B642A623BF17F3BEB28F23F382822F28F95A184FE4B324 -:80B0800032EB22F273F16FE4B482E51AF621A98FB37C2272617121E122F8715B2F23F3B2318FA1F1A2A21AF359518EA22559B92BDB8B159F8BF189C92D412B541F3EFC83A329E821CD525E182E22AFA1F24242211F28FFC2D24F46A6542BC41F34044E426FC41418E824F35332B7342181AB15AF6DF91A122F42AA98DEB84FE4B332EB2A19 -:80B10000F27BB9E5FE92922F12F669A98FA1F482C21F1AFD61432F26FC715BAFBBF3B2B18FB1F2C2225E511F85F581822F1454B92B888F85F119D89F95E11AA3541F1CEC4CE924F4F2B22CF9D89A2F2CF88A886AAE841F28FCD2D26F46A5DEDAFDB46BE024F417451AF139193AF2797ABF25F75A782B67BF96F2F2D62F26F682A22F21B860 -:80B1800042FC44742FA7DBA2F852DA6FE6FEB2712B6A8F9AFE29D9AE813B861B422CE42DFDD2E22B798F31FF82E21AF7F1F9CEF22B628D2B2BBBEF85F3ED389F9EFFE3E13BBD1F3FFA93A62BFFDABFC2F5C81A2B62CFC5A6662E222BF6EAFDA684BAADD8C6094E42FF517419F939391F1DF5597ABF249462AF87F569293F3DF992926BF52D -:80B200002DD22BD74F5EFF32BA2FAAFA5AF8EFF2FED3912B648F9EFE285A2F2CFC71C235F2E24A8FADFDFAFA2F1DEF25FFC2221BFF1BFF1F2EFE22619FB2B2B3FB78389F8F7FC9FBB3B33F27FB73A22BBF7E722BBD2B918F8DE927F75AFA2BEE4E922BEEEAFE3614BAA9D8CF7C05002A014028C248221A64228608009E4824842813A8244E -:80B280001142A02411288082A824188028044001148C848984A84800A04140088A0448004282FF360B481214E016D181921280311180A414124A38312C82F44A821220885221880048D08125E882044819828822024302223042282F12A14920084B4388A218B2422A8408AF92042CF511248D121F4132481F41324A1D24AB141D64AB9492 -:80B3000019B24A5985AB9443F24A9143F2429147822D914F82C4914FA2D418F8244A16F1244AD6F1214A96C54A9E24ACF4D1242E421F49F228821F49B26CF19124A3F48164AB161D24AB961B68AB9459B44A3924AF44B924B442F9244829FB244889F9244A1FEC0149D581D622F5112483F41124A7241D2446D241F648141D242BB45D289B -:80B38000AF2439248F5439342F1469822D856F82D418F926521CF824DA87114BC2D6F1224896D4B2E449D2B2F5C12C2AF4914CAF227C91B46C789114EA48366A15F42A941F49943859B64829F248944B42984D48B86F82D448D826F595330082000000000080020000009022800100000000008001000000842200000000002501ED982470 -:80B400000026A8218426488864411284002341028CA242871123229C18984A4A28126184A0212892841E8482221028216445428A6212122182181A0C3243A48482B28458AA61828FBF0112B200482B84121A42084AA214890442A28E1130248822480000A021161808682B28260A4416A221235824861128210D1C3248894891C8E01108A8 -:80B480004E1820224AA1487F4E04A02D843246E8882481751884B1242461A6802478B88146398266321888F28182B028C41884221F2946C8AC8908522D288A61443749421AA818245382B82839818988E318246484B8244A49A1C13F21022901224082128802108804122422004C2382888401204281012A01A0282C0143022C01801488C3 -:80B50000621612C048A04142C0148298902822B826F8FDD80000100800000018304800201404800100142200004028011902162404000081000000000000482F3A0220021C0212005220098B84A08122132922490268209221488044219481802204301400601248A04114292882091A049828C200436641F0AF150000191208000098C093 -:80B5800098200C1C09CA4114228621C22142142811421C082842001C034C219421488011118A22014200200890444C011FA30420020012004A010042608122200200000000480000108801410000004820088220011A8882048002422F180F2001001242001800800182000000200222000020220200400122180000008001302C00A0148E -:80B600002200BF590E00288122260318814A482824044181841A264284242204848004204502422220288202002CDA140436A22800008812000082A0824FF40F14004112810012001218000000521888001140840141008004000081830618004812008200421002201AF8382E0012102863824820A1C1202101448280034CA11488482818 -:80B6800081288001430580820400260189E283A4284C012602180088604142248025826A8AAD6C4001224430112112811088242401848148284820024001460400302242228088020040924120A186001220982800008200EFB9010000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000046 -:80B70000000000000000000000000000000000000000000000FFE40F8004000000400428000000002180018800004001400848000000004480020000001002183F5F0B0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F24 -:80B780000000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFDE -:80B80000E40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000069 -:80B8800000FFE40F00002200008800000000000000000088000041000000000000008200000000005EC28001003048000000B04821918840088800000024602240280128484C428208250400002200000082A0840020F83D22400125418202160240081E42101211418498241826080010480840241222040044124031488055141A0889C3 -:80B9000008C24160680021898288046FE70D19410280220400842011A21416918840188408000040082602221848224240A6811002004418228908C24410240829280220F816F400400121842C0100804442081144822812890200400821101418020043020045C148A04114820000002C088014282804BDDC4002212866410810882206A7 -:80B9800081200442844A618228000090288442489014822021024084114121382882462201482089128401444382089FE24401121E23812148D0820181982210889891B044011290411A8A4222041324C821493448661C1434844B811082321246F446121E4612284A880443044C25282C228401889F9E0F801132224248200126280A813C -:80BA000084821321044088220400409848C02143044648941449C8141046223141C8362288048014842921A841904418005B1240021C43CA218424848420250220840847854A8103119A8202292412A14842F01448490A808208A01211412D146D4818222BC14280042E444188223024882CF8B9C10022141A344821282006902826044078 -:80BA80007424B848A112481229068141142283442102342082B12174482402228B42622541981496048227128081028024912281127F5A095082802402840078490822008C010024226112428081A912002814124885212104281024410A4A420412108432122800B0820442DFE94C810100402881410187110029648400408102000020E5 -:80BB000004008C2112040000142304208108200260A4804CC4382281121A14F86DE4002342018952828C2321A2141181244289D44891281A64116823E24482114844A1412608228B122849A12414134184D221223264621825E8428488225912AC84A2B4418B122283A1E18CD128F4B7DF800120210400468192982800004484288001809A -:80BB80000480824501400220A142002044C8121588288101284024112202480042F0814600000014F022484210280400191341080022408184021210512800890141282002000048542161A0242445781262485084848242FF21412244022384018110020000008005002002110000408482050012144AE1110254542141400428144112D0 -:80BC00008800224B182A21F2D9A7A0122301188C022C12110842000014810014001C011021028001271141501410145441814508288303128011544248400444121A8804CF2402C021C0224262009028504842000022202201400184200200C02118180048301112001111214C0211122880A11422222221411F630D236822008C6412A0FB -:80BC800012A0120080014904196682121304844008111B241045C8444088420414448504471400260450144120514821414C4804441CF2341F00110010084262004E11802204892411012072111218E1818808000048411C812102142241C01125C411250340210100425820C222D0710A480012180000480028200228201188611421A031 -:80BD00001420042224468422016012180024382189044818001AC421441248802218147284F2FB17302100206281178620222404114211621942814201120084142814284414458802801101003998188120011431124684146224A04900430DEF4E0FA4C04215024200A1814064441C020000124810021848C810014812541944C4284426 -:80BD80004818440043E4540240A4144A021242492201230121218F18081E42335A222C24C4214682A14426084A0420467128C838264181E11152215081850178144144255844D054B111732444C44549D24E72422152C6283542F242142CD154D62422F1A6544C253C2E813CC8A21F3344722241012B1129B73884F24229AF82B248810475 -:80BE000026011453734131513813A1412A6411118F14F491282A14A1221761CD434D6158859C21B011015352B81B1985F44516321F2461413362115744724E44C52E24D944A5113E944B5843F6B84DA0242C0313723878417828E92204684698194E4419054A86E21244C83846018C4309484E2126011446E843A1271E511247422815A17F -:80BE8000111F430159D198F441214F51C41110E51194111AB142612163A4A34CBA84E24752423F5A4B0114002082E4220118481C011C0138190413011142001142115211121142001440011440C348344826023448800448248A041008F0FC51F023223D2B211F3114D818F219538D6AAF86F258785AB54134615E115A83D34CF528183A2E -:80BF0000F318181E11222A528A85D988E311A3922A52646F61D1CCF11454CFC7F7141447414FC4A2335F53A7132B9B4F43F32D272352252B322AE24151114F2152464D14AFA2BA12F924266D944D144F45E54EFED86CF023223FB656223F31F5685887129F33F53A5AAF87B368F65C5C9F81F1513446A1156AF56C548F92F2292987811F91 -:80BF8000317163F12828BF917148F8A8B81F17E312F331314F71F1471F6FD3F27474CFC7F71C1C57515D6D1B333AF71D1CFFDBFB3534CFE3B713F115462F63F323213B335D454F65F646144D16CFE2FF46D44F2FB292F936344F47F7D6D4AF914BF323221F32561317315AF449619F35F51272AF86F268688FC1F519591B6415A1151AF27E -:80C000005C4C8F96F731318F91E115B572F721318D188D498F92EE12E317F621211E173F71F14C5D8FC3F57C7C157924F431551B115F51F138183F5AF94946BF71F156366F267213F511133B7555F414466F21F45E1AEF8FBB92FD2466EF41983E4B554F64F529A5143F26F62B63357353E387F269219F37F76262AF86F238388F8454997B -:80C080005B441F1121A467CFD7F638399F93F319191F11F173719FB2D399F149491F97FE61717E611F1242F3475F6FC7F66C5CCFC7F7151D5F53F23D355F417155F51D1E7F7AFB4B4AFFF5F577767F76F713133F11B153F745545F77F54616AFA4F5FEFE4F4DFDC432EF49DB4CE226FAC4965FD30900001884228422846081200112400843 -:80C10000120028100880818201184249012290148001181200002041022001822021043F22078A9121008006B0420118484200481C22122881118142482182024012082800140040C12820D112215112101201481890822A941822421CF4519FC0421F41F228131F41326A1F41726AD241F24A111D24AB9419B64A19B54A3925AF143B245B -:80C180002F147924D812FB24481CF9254A1CF8244A16F1244A96E1A26459ACE449C24A1F49C2431F4952281F497248F19124A7241F48F24A131D2CAF249921AF2419B54AB924F44AB243BA42F92448A9F92448984FA2F4ACC450A24C762AF21144A3C624AF26D141B248D141D24AC92CABB449B24A19D1427B25F8428157822F145B861C19 -:80C20000FA275A4AF8259A5E8157A296F1254A871D45FB98252E4A86DCB4F491648D4396744CF1112C4F12E888F42E111D6CAF467911D41A9B45AF448BD44AD984F442142E48AD942F82C4142D582F83028400008400000000000000000018800800000000000000000044000000000000DB818022210118121019984148008C5414118469 -:80C28000188008138492412842109824108C92242B14511A7421C22424424121AC44812B28111125012118868212AC4960826E3DC041237822084551217460112B821331212F316418007A081A02848B8381846924D218014602582384118454424410D4680A1642F4882446D538A24A8502C7244B16668A2A12AC244187588AF44933A015 -:80C3000042569228C01416131461212A7414613272191445B13888218158286222567142249A11C042D084954149F14214C149F5412228644B424522C14459DA41CF88322614F1481443952A8A825A424FA2A48543A841DFB30834800114404358181328043486082004280017898184284881844C023022283041214441D028082484A1C4 -:80C3800060328A543841242246220126084181A6F842F60000122411240080014A8104450813081381028111541312984128844448874180A282440025014116080048904100303481B0482102487FD20B422912322283A541815A92581A28D4825422802D39888CA28129E8C1E41C82048E28482B42C0181A344A892AB4448848A4214932 -:80C400003288C2871140E241EC6B1401101A8D9C4C8243EE4894848E44448CFA682B0022A0218B1423012180A11400A08486088E29983969432E4140C12448C041382C258484644C2841384488111830186B1462314800416084E084088449042AF4EF6CC0422410021C14A861568848C24A4A31421249918800904888890487183CB2286F -:80C48000048181C48E288D1420884A2412B842184904888E1400D08344291C94B44392C45E842A18C48896064260218081C2244C224288925847222C24048A4144F11224102244A9281C83C5144393382A28C2781621A516563A11004110084004B028448C240180880152E02B0624263241226608A43489344411F02844842022648116CC -:80C5000008182912110418A221001412448712118887428AC241C088842D2184164604926128230262822384082223F1D3EA0012848140814428611212139282008A018042A842C014C8424085140356488808000041269422924A01308184C08100A8C3111238484A4138A83FFC0C24249991288346B14C523826D849021E29A51218A290 -:80C58000828A6181364A8886C245CB84CA82E236A11467138B211F83C818AAC11813853334294A3124A283A94240C481811259042288CD1282A99CC84AE18192A84F4202481A42021828244CA214482E11484A882424211444313418801101114441004222874422800C1C4144424C7211182811022C6888858684A342001820042F24082C -:80C600004821100A0000830148708A028014180490128185C1881189548481430811418440241854144450414410848181C254800149818801184308CF49020084242C460416022C0612100483012022250124481C4428E212B42264122B4820311429819411825021588B141A24813885908100490C882426028184F035F30040210222A9 -:80C680000010C88400104184882204205A18138A22E28214C18142450182904C1014014241418C04114211421880080041E0420481CFDE0D1428008C1278424B68246084814B24A8830810342452A0149824D02244012A54C2222F884421241802588281110048001081820C8A0524C0821084F8A15FA0282221222144A021A049A02188A1 -:80C70000C1863814820000B30222481782804388C745498148140448411100466141C121138441C844A64414C412C034418BC28C42F9FACC80042C0442800429042B8429DC220400837488A44800907212192181484251298481182480E4888104930881001112484C91821820014C45A82818007F9F072410184808814200844411584042 -:80C78000480412A0584286028C0114008800C9C4488A210188416015122158D228218A8462241A84242E88088008FF7E058004002210480811828410024428818608136816202208848890884908110015044248441008004A02C02480184404160812F03C4F40488226411148224403400C782800002004218418803852901290128714BF -:80C80000002F8801198588180810C454400528004448C08243821882F8765B002F2812D12262A22285E825521A2C581229B24938582902C9A8224C2B2144C8A1A7859D2115817448B64AF2A9AA257D847CD4F8444267414AEC14C1844F48543144571484446B585CE214B2C443B444B31645A45A8AD186C834A9DA14B188F85587A064626A -:80C88000856A824641344181B0287488AC8D69D6264818684888428E481AE111F818181968888B2585D811C2494511A4948D94818A9814D18288CF84F844481E14653414441B4519159816AAC884124D8467442CA3828664CAF0D9155021302283916ACD2A2CD482E524F452184ADC8845E2C8B589F8141C4A54CCCB424AC1C23B7E1F2E76 -:80C90000E412F26242A6F863212F83F5A1822F45F5E9C2A71148DCC15A23E149F8151115A1481F11D188B458B548F551818A31121DC15ACC44C24BDC522C684BE3E887958884AF180C1304111031221118158811815181188041C834000010682881B01882381800000000002184213022302212211221902292200192F0EBAE141553B3B9 -:80C98000A5F21233EF54D65F724AF232632731BF34B1DBFD7161171BC5F61939124B89CBCE8F47A591DED287837E71FECB2FBEFE4B4B1F17F773432FAEFD2A3BFF33DE4EF594CCCFF9F956D66F45F5551547414F58584CFF75715B7B4EF67664DFFEFFC3D23F32F38BCD4D166F687846F646444F64FDCACA6D966F4CF424344FC8D8A8F83A -:80CA0000A5CAE026F6434BB5F3123BEF54D457523B2FB3F242513F3CF9DFD48F23FEC2F47F71F59A1843B184A9EC8B9D1AA9DDBF82FA6169FEF89F1EFEE9EB1F97F75263AFBDF4E27FFF7EFFCE55CFC9FC989E2F85FD56545F49FD95144758CF44F45F57BF95D1C4F16476FFFEFFC39446F1C8CA6F64F44624CAB9C4FD4442EFA4F4A2A2BC -:80CA80006F265E46CFC8F818989F4C07242B629FB2B212F34D668F24F6494B2F22F34B4ABF29F88ADD6E388F8CF2DC94DD954F48F9CCC88B9B8B461AA9DDAF9FEF1FFF68788F82E6A2FC71212F26B5EAF4BA6EAF67F64251CFC1F1DCDE6FE9F9D2545F51F511915F48F8494E5F55B15AF548585E56AFC4EC44F9E1B19FBDBF46B194FD5446 -:80CB0000844F69B9E2FFD8DA6F62FBDEDC6F8CF59C188D18FFD20A1F36F629638FA2E2A1F36D4E1FB6F6484A6E7ABFA4F49B8AAF5DFC68F2FFBCFC8FCFEF49F88C98CF8CFCBCB88F4EA8D5DAFC28E98F9AFEA9F99FBEFE6AE38F96F76373BFBEF4FB673F7CED4CFD585C8FEDFDC6D62F4DF595941F49F981859FF4FC55543FA5D5CA81F590 -:80CB8000DDCF3F3DF9F3B19F8DFD54562F2FFD56844F2DF97674CFE5F53616CF8FFD565CCFC1F188988FF40E001410C4488004402308008480048A04824A028B2420048384A82400884200880048188C44220140A248A04900200800F048F5601A2042488146417842232854812449C481C084A2852421048901882281807222224818C820 -:80CC0000428218122018082522018A240429080021482D822242806A985F8D0C2CF4112485F2112487261F41324A1D24AB161D24AB9419B24A19B54A3924AF1439242F547B24D812F924488D914FAAD418F8264A87116FA2F498252ECA96C54A9E24ACF491242CF4912485F2912483F49124A3F4812CAB141D24AB9419B24A19B54A39248B -:80CC8000AB9443BA427B2498924F8A84F9A44A8FD201941E64AD414CF26A111E24A716442716CCF26E81282F34DA85B24838242F1458842F547A24F84A935782AD915F2A55185FA29D885D428D255FA26C584D4B9E214D4A1F89D2A4F49164CD431B29C7349E24C7341FC8F244121D288F7669418F347A11F848A6228D944B492F44A24338 -:80CD00002D846B4B25F4A458CF260B84000000000014000000000021800118000040010080040000004004280000000021F07C4F6022004303842881248C621494258201611748468861828318048C942C00138614082124831454218815480122856421876284821048698541428608C8888604F05C8B3044A6214241224324946D828CC0 -:80CD80008821CC8C18282438190219249289102134418186815441863844443C98A422412624430C3D444A7114315813874914A11430141A761A420446D984D4EC084E2413063641828142E882B482924D85239E161269D22498781393288AC4249C785298258A147141C8418314D181483448871819B8424A9821C024812D158B21E5F198 -:80CE0000448811835384941A2494884AF142824D824C18F814484FBA03242042048C1284541484881260880014005018001008422282401422144634265014442A411884344612181A8618A11441301428160820044F5F0326022712306811A3828661888042318181484604852462448032814200224A02824981824404110014E0244106 -:80CE8000D82A21818184A848348244602420348480F41D9430421483712A92158CD46184D168C2613C22492A3411242823288334384A22312886641449B712C4141CB46C8136884BA1581D241A7226F128824C933713A28243B22408254258428698482E12174243884484128CF89BF8A042111D38285F841179212C127C8281A22115924D -:80CF0000411941A224B02C21E4460190A144114582A24313A42D90284B841A44E1129125841431482998221E8410D282388484AB846C02869442412A4888D8190E254202252A229442298533683482818884484429082284683884C8485A22150485B42485A821412644028E221E244CC3318CD2489122184830428601124D214220144439 -:80CF80002474490A482044314251B0467332184811614323012937842E132A1132518D2210C4986D81812171D0A5E811964821818E42421F8162311E421C71A85418293E44441CC218E810182298821886280429F117C51092421E2183830248904143243828471A48128881002844231465144A918830648A0110C8841CC1214446180471 -:80D0000044A6A4412312A1212504482290822822168806887012F227439014288440084902001212814008008118224008284A62411884804124E1C2041218208202001022E2242158C246088A2124022391181E48812FAF082F4491228CC3192D28544C86B238D44864188B1287112321B162C18C3CC2182259A624156414CE287D688D34 -:80D0800016667497084718C3E441781A64124B412941C4124D328E3541AD221C784222A2122B856D88891482A3842B183A24213D1885F272B50040812204241E44250118118848818220C122121884814100800130182B1283A44280088F12912142B0681921E6410219148804869882228902A94828046F5A0A2D22811439C422C0220004 -:80D10000698881E3210824224B82374490185608828D2168484129C1C122282144C144444479082D28414413984246DC82081FA438848C12245862684604C450485FFC064021010046081212888128460400184220E21402002E881848418624894281041518A81200315048CC02484821422C0142C0888429048684F47FE220C422C9120C -:80D180003444517022041114001216288184088880511C4842124241487C146444C0141126242141048CE3421448043481904841301400800828F02BD4C02856049028280048406841902288411218122A61328412218814262222018CC4189E41111215B889E248240910AA24A0240011B0225828200222A0422432CC0D8A011825C8421B -:80D20000846081422944C2880018CC0248B24964188B4220112C14DC14B78431428A22848164181824114C41218845F221488388084821202975248282342844812AF896DE2490111447228016022188218004A542D1222492421C0214E880410270228841A4289C02402A84C462267C221108106244444110012470842838844841F08C8C -:80D28000810000148444478244008424848444D041130110089021001188148811000020814421C1142412121623A18592121602290824478112301285F4214F80C44281101649242361520044844489018283621C00830110B848413828A44287581028012230424424B031041260A18413418D0100294A8C6284F08EBD402212140842FC -:80D3000048812064182748981E24281100118418122B2446D88131212A0824131108D411C48C728184041C11D8214214C18485D14308C912928C41C84E1418228CB822A8C1FF3608246F991153414F86D683344638211DC5A7288A38CA18EB194931C22F41B87881F8282989A336228CD2387434B2C4F511A92F94E44218FA14AC4B44CFB8 -:80D38000486131CF424AE6219419AF58F21C212FC2BA62758CC4122F88E82C7944C4344F686129228AF9F22298CF8AD228A14B9FED043A9641CD27ED28218D218B22E5E42531D616911A4C7118C828A5ED51D6119162414A31321ECA5E61422AE21425E26EB184E214230F165111221E114F11B945F334284F82B122F41451281FA7BDC5CF -:80D40000FC58125D413F2961312B814AFD8664224DCC4E284CE4CCD244BB944632426E221E183C54684746EC648348281D8836E821DA4644B631F22412EAC4819F9FB711F84149D35889CF18F451888D2C2FF1924C1F61F98E485DEC8955C9125D2417AC33CA8425771162E49724D51D529A19548A8D48F78A85584624EFE49618C74A4240 -:80D480004B828784EFB50220024150246022502412A04124126C1241120141301410053901001901188001290125011C010014000000001A5418128112F0D9CA242F24F4131BDFB3F32226FF12D659B24AD44832125F525A3985F23AD88F81B11AB338F15255AAFBC2788E294F5BFF74443E384FC352448FE2F354594FE6B7A6D22AF24409 -:80D500002F2F46F424248FC4F49D941F62F275355F79F11564C763EF7BF96A68FFB7F61317FF61D1AAF11B5BBFF7F447D7EF81D966F146C26F67F9BE964F6BFB6C74CF43F764E44F44FC2DDE241E323F36F23B32211F12F623212B466D342B157F72FE83872729AF41FF1A182F81F132243F15F5E2A13F9FEF9BFABCFDEFD7F77C5D8F9245 -:80D580005319CFE2FA51574FE7F5D61EAFE1F1C5CFEFDEFE7C7CCFC4F4848D4F62F2B5675F79F115278763AF7AFA6E6EFFF3F73F3FFF7BF75AD6AF35F55BFBFFE5F91FBEEFE8F1C6D66F67BBF2BFACFF6C78EFC3F768E8EF86E62F4BF262421F33F4392B3F32F22B691F32F24F4D4F66F716547F76F38B9F2CF95AF88FA5B11AF138136FDD -:80D6000014E73EFBCB794FCEF3F9F93F9EFF75756E5997968FF2FA16595FF7F636B4EF71F88E8FAFD6F468648FC5F5919C1F62F232D51F38B117F32D2E7F7BFB4F4CFFF5F61237BF61FB8B1EBFB9F5DB6B7FB5FD1E9A6D1A6F2DF4E6E66FEFF9C4B6CF47F7EE6C4FCFFF6CBCCF22084E223F32F63F2395FF6D6BBFF6F26F4FEFE6F7565443 -:80D680006F76F78B9BAFA9F95ED2EFA4F11A1AFF33F353732F3FFBFBF95FDFFFF9F94FDFEF13F72849D7D2DFF2F273577FF7F5B79FBFF9F8DF5FEFCFF77C7CCFC5F595955F63F3B7B73F79F11737BFB3F3BFBF5FC7F71F3FFFD1F39DB7BF3DFD92139FBDFD5FDEDFE3D9EEF9D6D66F2EFEF4D27FEBFFFA78CF8CF6FCFACFCEF249A500505A -:80D700001484438224020014000040A448A048288242A024101831488092920080011C0824800124482486488144234102202804003F2C0B8A8502280042A01496049098D04821032289034E15225C0144481E244342C59228A0211021321100898112B81102288B94841812218242A2872422818A84C2482FF3024F22F41124C5F211243D -:80D78000C3F41124A3D641B24EF11124AB961B21AB9453B94A39A4AF543B242F547924D812F934481CF9A44A1CF8244A16F1245A96E1A26459ACE549C2DA1F49C2521F49D228F191248B841F49F24A111F48B24AD9C1B24A9921AB9453B84A3924AB9443B24AF92448A9F93448984FA2F46B65F0224A19965A1B21A7341E28E72617C1AFA7 -:80D8000026B111F26A8617818F64BA95764A32A1AF343B112F147B24D81AB936D41AF8A5528D115F22CC816F8261197FA27588F524138F58D224D9C1D2A4FD8164ED1213F94E9186D83ED941B246D9C1F24A951D242BB457882F447324F84A94322F64A8432D842B434CF8225ABFA30646084818000000000000400800100240040000404D -:80D8800001400800000000400428001008005012F0F4A4C041400C8C344C8CE2414281A8A133C158942B48582352822B48ADA42788264C044C8412B112C2218A94148D5425E244A22112C0144CC27C2C91288B244CC1128E4828601186D822384418206188784148EF7A4C52241B28135384195312165318624912228AD8425128814E81D6 -:80D900004C313114430748483449C4182C34544137222AC8181A3845A243C82814883782C84F18F14822471C20018924A1412AE8463846E384D148F838C185F4FB54244635634D29C9747142ED82D185034D224B1227127E825D1AC81AF423828761197C8BE2AE41344452518E44BCA1614D714C9C11AF44D3A2C1255922E3C478386412F5 -:80D98000CB25A9726238B5C14DD3C3282292188E124E92624F228D344616BA8875946941ADC2008001814834601682889281502884428033244426082034224002244C8208D852880044881381C8486E122024011914084C0844168838244AC2483F250249044100008C0212241E283440241102003014508142415484168465482C25A1C3 -:80DA000082174100004D81402311028503818285321430240089528442F099FC50124531232815B81994844887714EA88F190230118611E8C27598E588743B34944211A286954A122D158F241AA4126962424905572126126C412B164E184C94414B691A82A11423C4484C48B86C18C23E6496843A1C8CF89D6B7041044D2128818D114382 -:80DA8000886681CAC198320044833116824844414905143C441C545A560E9AB22284A2C111182881E018024429818BC11921814092182E882836584227412E888981F891152440071021048155322819124AD112C181C0681D1C89B82B810911833A84421981216A45444721433124495114254294146B4189954146D14224024A31428BEF -:80DB000084861C64446141608A414314F83D9D0010210248235182282E5C2814413125D414021D284100212A6432981912684540041C82216122901A1D1414816B282813C41166486425A0144423216924222422002F81F47DB250414B1410684325491835586038124B424969812C011098221AB28244044A0152252282D2412851842704 -:80DB800012181283042E84688490144845420C8449A214888118C219341489342429F187BF20820290411849020081892609A084560412204848112412263228A014296184284031C12052221216214842188129E22811082628164838234A08001F2C0F4D2149028076421B5C428B1466D4217221A84147314781CE221E4485512C2832FC -:80DC00008968424932E22D253AF41668214E246D11844FA1A2211C73418231247728721E898AC24616F149268E1826E228911C522F812A6324E22D421EC4424912F8413E0012148CD21421A1121528628189A8412C2808530122188088641411809888808221A852009092C0112885C22430118304A041814844B04868818122288480F4D4 -:80DC8000411D10044412812C1464929B211984B2894511083CB82484C4446022146A8881082154268418141204250444114338812C21C414221815683A41860427412CA818442AF188644B1C8A34842F22498206183041814A614542200441432802601880080028681024043A842181C1242C6441184C38424470818412010088B04408BE -:80DD00002843A2A4250210047F29063504C460114244403144184E18003044848C91148081A52114601442241854604528141609841684C3548811521116C4248844981110B4121834148C218281F86F1840288221022D3C818502248490182055122082021488241068431212412C0100482458880028002CE861243452181880C1120073 -:80DD80001288801142F8E76AA038388400902810A42928110044241B421411A0421302428841C119240220A2212244A01226816214432891244A2868541442244B1420012229B22421D228076F8B0B840017420000388100001828C04421496511008814800211281052141604190290112061442400216413113228868222121214624822 -:80DE00003018FFEC02002884222880032041721421810444002641048E4828220044002E4420041C068288802886228822024880024CA28400A0481002DBE320518410C81A14130200841008008422680012156218841348218851142511212491128E21511882281110616141122284590100201101819C02BFE506461881248106211589 -:80DE800094444C816442B0141236461881121442482D188021A2A4832224A4344B8414C8608480162481A421428813846A44822813881494448A8404482998661D7B4034814C8211D88BF52844CCD551C276284871442B2473E8967465D9147644A1121F12FC78181D118D291CD21654D576C5136E111A83A4533C8242F481A13F48D5117B -:80DF0000B581F231451394C146D2176418E13B193D1249ADA282641EC14F8AD484F8B8D1E3F93AA9B04262C287818FC1E283F464224D2195E28334588CF558211A7194781462362594482B131B1A4714421C882E36E54AA3C149B175DC26B446F474244D827FC1B55735151AB134F2D4844E564B244F287FD294947EA41B84174D49E84E28 -:80DF80004436C24F42BDF4F424325E847E24542ECCFF984AB235A5214931211F34032D184F13B244D11438781F8851D8184CC544C9A33846041B612B118E6223AA881664C26229C2241E241D84181F4422E412B8887B2484A8221A8869434F32F313648CE1228749F41C81324D162B21295B42A9A3584E2AB03A47014901452148810412B1 -:80E000002A082A0888801AC184114C2A8112215481D081C12419219811C2188222601240012E81400126018044012840020081A0246F564AB266F62521CFC2E212F268782B777F47F76D649FD4F4587C8F8DFDD91B33C9922BEC6B4CAF1DC5862F497984F5C1416A6594124E49CF8C559CC0954F41F994954F4EF634F44F61FD85664F419D -:80E08000FC85B44F4AF2A5F447445F4CFAE4667F6FFF92925F63A1111F38F89A9C1F68F98ABA67624F6DF9F4F62BBB6F54F48C84C5F48484474BBF5443B272F675758F43F228758F96F7787ABFC7F56D7D9FD5F5F8BC8FCDFFF97B2F4BC3822BFD4F7EF6FA594F74FCD3D1BE311F1EF4E2F18F1CF8A8918F1CFCE4C855F128AD2E811E9201 -:80E100007F7DED5EE645FD54D67FCFF715E45F4DBFB1FA85F41F44F2D5B54F6FF6F7F72F69F9B1B61B37CE42EF8AFA8585CFA8FB26364E124F6FFFB2B26F74F786B4EFC1FB14D46F4EFDBBF3F064645F53F734245F52B269F62172FFC6F37D3DDFD4F6D8FC8FC4F779F3BF91E3A8B142F864A2BF1771CCDF57F824A43AB922F4F1D9CAF569 -:80E1800049814F94F844418F86F665514F587594F526E54F43E728F7D7795EC55F5BFFB4A45F53FA54845F46F271727BFD1F2AF571532F63F18383AF8DFF9196BF8DFD24444F6FE927BFB2FF5652AF83F18EBC4BE8EEF47F9A4BF371515F53F7382C9FD4F169F19FA6F56F3CDFD6F371757E748F8DFF69FBEF81F3941A2BD75F72FA3F1DEA -:80E20000CFFBF153D15F57FF35951F13F3F9B197181F94F84585DF95F5B5711F16F4A1573F7DB522FE3474FE767F5FF771E55F5BFFB1A51F5FF3F1755F57F371277F5BFBF5F75F7EFF71733F3DFDDBF95D85DF9FBD24F7E4B26F2FFDA2F26F66F6B2B4CD7C4F21F7E4EE2FAE0F2220022C0141481486088240482648848422089200004616 -:80E280000442984A3222420029082A081820022420021440820400924A2288027F5D0D222042E822210128188041C81192244881821848188A04A2A04280410490922898D0122501822049A24120D9220829012182A04342100289033F3C032CF4112485F21124C3F41124A7241F41F64A121D24AF149921AB9451AB9443F24A9143F242F1 -:80E300009147832D914F82C4914FA2C4814FA264116FA265592FA2655DACE549C25A1F49C2421F4952281F49724AF29124AB841F48B24AD141B24AD981B24A19F54A9443B24A39242B94478229F92448984FA2F44B1750A61D64CD431E24141E68211FC116B881D458B181F4483453B8483195A714578A4E15178925D487D418F927128D7A -:80E38000915BC28D811945F125DA144D9B1CD2A47D11DCA4FD9144CD111B29C57391F44E811D24ED9115D45AF9812CA97395784A6581AF4438A44E1426D84AF926484CF986183D9D4028080000000000280000008A04000000000014000041000000004480024800000014F0DF2B243845331884554A48115C68822CE48144E2884102870B -:80E40000428A6182508280C381478281481AE28116E284D14241644243B242D82408A62681B8227C31C4A7D38395824012FC12C4281AAC164C384441C024ADEA90458A8252216046499322224D1196886889901C42112D2496B541E849A21C4820D843E4C25142714394212CBA483312001C6292188A74127C1411222128E2121571928D78 -:80E4800041225168452824FA2811B6C548BF8A0743239C229552942FC2C4374C42988743B15A688212161852694CF38518C6F21C8242621B81874A86BC243524578227441D4217414D6850288AF444212D284F29A248A748CE142D149E278DB52CE2137821D45271164224B34CB12EA5842E828D151EA116F47571D012D4419218000084E7 -:80E500004322B148082C6988444828822811289218003914D82221058B212E82126B124C028214802171229121004A81048618A849218210644422442E487FE80B2D4100128B141014612216A41280015C082C2882311481A214400110227422082EC2282AA8218812490110B144C14C221E48102184F44281D04231243024100448DDB734 -:80E5800080921663D34A1211C42949118A42312B3CF818811AD41AD9C183DDC23E82B6816182E24628E4D2C142CCFB148121004E1449941614114F28F228148D241119F3188543A221423016418CC54882C38664424AD384CA24FF2A042D6116C414496395302819C1282D244098118C4897191FC3B8123C424C91312A6882288C04164F93 -:80E600007288F2249121C68232A443A11890156C981422A016899B7C38002488124E1C2A188C84826282F034A140422252824054414121121F223121882D114A2908228F6A21388812148A448184823474812002524A123611806282853555855541001324B416C445831412843624414B4149B82474780E224B439125284204288429B1FB -:80E680001212322441183018412788A7422829136C88455828D2848845885114C48219826184108412225858148764442889E484820580AA4241C9D5424224F5F43C002CA4211E23702A9148D4292212312943421192212728462901912112809944812121124126AB1A1094232F8471322122E455C2222094821504211C0A2A28E2E4C17A -:80E7000088838292C2221E228F340141211084819412601190884200514C0C40048634482214481444422024022489222114C4828184A485E4212228220816134452244800008981044F41054127221E221CC32297621E489D249C22929931506149F14422AC188C392ACCE8846241844D881D4218AC243848444D224D128B2836F6116236 -:80E78000F01322C183F45C234D821636812A2848C21A8F14C8522686B43CA4A42638285E284CC242FF3F0322165418C4298104D0222131228C064031811819544A411C2291281328D4847848140249A121848B281001168488622230281D2846C24C2581621441208822181AE444318442221FCD0900213011258292211800244021742215 -:80E800009A2426A584A02143122424B82C142424618283414164884290824921E44A143814450848400881A0212800304800F038FBC0221817410060811200A8221890820030142644143818158844820800202589820212818504186200121244142003610010C444221AF49AC71041613149634119130133C42881002061417424100895 -:80E8800021282C629282418C5292A048A4800220D22401504889A24211118111415124442AC824846B422913086CF2979200228C14018128004581419184414183A89281203187822DC6001112888882008415426184001CD14862288814C04646646189A4212180842104C5823324F0378630A23440424882456224824A6921A4004503DA -:80E90000864206890420531210D2843322901125C284290421822188A1274444118B42604A1304C98491246928C48430428504845F5E0960832E4214004068425652418694818D122A088111888221178112884AC1C80040024B82128800122A983C8812814C8111445848002298004220218401D77DC01842404801812810815249124C7E -:80E980000A8008144180748A110110188191410048181A66124021E41441621110847152012714281420C4242812004249F65515901225240241895121811A8208885018812870880480982424C18A0298704198182849148801228D21003022482A051C022847A83C21082CC112CB21628023049FAF0A008CE4A18652414014943481C489 -:80EA000014A843919113012219B818C49123A2848951141B86132C62188A84C86100460B9B42204111012506144604683C0420046781221062212F7B081F23B2B25317C1241C711A61526B4223912483B21251436D144597AE4D822D21A1814F81D134FAF4638F9C52E14E244F343212841E928B28CED28B582CD221622BD5F18A5A5F28F7 -:80EA800095223F929211C5F4544455588119CC1A194B2488A2527E1289A6446A84F7AA9C3421918FA383B63161A11F8621E141F345B1BF8578817181F18C9A8B488E381D112F88E241C4267F41FEA824CC958313F284616B11AE889F94D118AB687C1DBE21621490A136EC51F23884CF842134143F245331ABA18F34513E9F5424F61692A6 -:80EB00002F2237544F44D8466241AF81913443F6924E806174F0331BE57529C4228D2A1374A8A41AAC998C143E829B83B654594B885B98CE183DC1835B8829BC4848B919A4A21F28744831441E2C1AB832E416D482A13843E484F21186CF49E5D606384E5568463C1427312AF244842E54AD2A8CF466184F4202167E3B0D400140582440E0 -:80EB8000420840628174164846481241264114111842941390121001214288501200601280A84100200148200112810012F01971343F31F1161CCF23F335211B33FF12F241417D159F94F448CABF9DFE91B33F13F11C923FD1B3264AD44CF28CAD9FBBF3FB3D8F84D858F16CEEBB889FB2712AFD65673B766E2A2F96EEE6B6E226F6B1B134 -:80EC00001F3AFAE3B9DFDAFAB56D1F14F49DA49F9CFCCDD7AFAEBE43F493913E322FCFDDFFF5C3E14F4CEC2BF826364F4AFA24262D564D344D24CFE3F2E4AB342F21F11556CF22F33D3B1F13F323319F14D54EF1486ABFBCFFEFFDBE333F13AB111F11FB22212EA26F48D2DDFAB93D9F97776AFC79D1CFEFBDA2FCE1C727125F77F76BF9FA -:80EC80008FA6FAE36B2FD2F65CDC8FAFF8B29B2F1AFAA1E9DFEAFA1FFF3F1CFC7D6E9FC7F4C9C7AFEAFE27753F1AEB32F2CEE8FFE4F5D3E14B446F28F826264F4EFA7C662F63D34682F23C6EA7A61417316F42F52C3E7F53F33B1DF772BF84D6F7F113111F3CFCF367BF33F39BB99F39F99B19AF2AFA8A38CF72F2A6A51EB3EF95FBDA89E9 -:80ED00004F1CF5C4D6BF3CFC2BABFFB3F32F6F3F3FF5D22BAF95FEE8EF2F86E6A7F5333B3D233BE8DFEAFABE2EAF44F759619F84F54C5EEFA3F34743BFFCF86B2BAFACFE4F1F7F58F9C4D42F2BFD26168F8FFD2C1E2E546D744F43F32C1E1F71457331F32516DFE2F33517DFD3712FFF6B797D1FBFB5F7FBFFBFFFFF3B33BFB8F89F1BBF22 -:80ED8000DAF8AF2BBFF8FAAFAF3F72F216B3AF1C7ED5F1F9D1CFECFDABC3EFB6FE3B3BFFF3F7F3F33FBDFADB6BAFEAFADEDEAFAFF833333D63BF2AFA2F2AFFF5FBEBFDDFFFFEDBDD9FF1F57A7E7F77F7F3BBBFB3F3DADAFFF4F1B7954BDD6F2BFD76724F8FF96C5E6F42F5167C4F41F36C7ADFC20C146012C011E0124108484008402541B8 -:80EE0000041041245148009028114A8218A81281001490145014200222204248A14174822C8204484A0200DFE104822849416822282412E0489212D02221C812C083431268822D112A844AC2A14D42811887112B42C22722A012C22501A3624125012991613011902142512148002143C1244F82041C74D7092CF41124A5F3112487241FFB -:80EE800041724AD241B24AD141F24A921B21AF243915AF74B924F44A9743F342934F83D452F924488D954FA2C4816FA264516FA265192FA265594D4A9E242D4A1F49C2421F49522A1F4932481F49324E1F48B24AD141B24AB911B24A19B54A3924AF4439242B94478229F92448984FA2F44AB7D022E441D63AF41124E3F4112CA11D642F21 -:80EF000014D141F22A951B618F547214D81AD884F44A91578327144F83541A7B428D916F82D118B9A5044F8261181FA265594D4B1E25A41FC8C2DA1E6485F3112460C165F3112C4F24F1812CAD961F48B2427A85B84A3134AF4429FB4A96478229F9364829E922F5AF184008000000008002280000000000008800004001008848000000AC -:80EF80000044800200000000F0B731244843416433441CD1220289C118BCC1A113F8884124844728628717B0489148C04A8C1234162269548226343242860221248621C828D081C48489B834B4121602484B842D84812186D88218E8C1022CE46F0F411348113C21637614E182016DA200842D148634D41864449F42B824C8258DC48286CF -:80F0000034498C9411801102882D1444D6852852268E1274499B38277240897248518421428E2443C224442B48484561429FA50B4456157414C8215C16B512C218C93217A82E89DBC14358C243986267924C78C47A2CA1485A78827884F244182E122485722412416248A5B645E824C822862259629F48E46338A543E62402268CE424C8D9 -:80F08000844C1274A49A8C2C3C187054E24C07290414195226122B1284249285124102A04918414A712188835448844CD28104114684012A218C0118C081448312A112848522D11A816214455842488D822200A14B424422DF3209002501105112A014281CB1114201180000409441442200D021344848A04282E041120298130100442023 -:80F1000081282124E1247814080012890220A23214611D2441818D122E188B1C1117A2C44221A44D424E84412E81C9E4A158488F1894248B49A0A487444D58C09285E226418261244AA8282483B28A028D11337699022FC294428C2411086084AD512C6A4CF014488148CF214502401418B822A148118522622413532146C2D44100981057 -:80F18000982412A0482005248C1462241A88748422082A38133019421E89D02A81C8581860244C4188C4A249014E148428AFE34E41C42525011215381BC071C11301814400197A444858C2C69541C32C82924C85D421B45808762202B0122602A9C1A8409221412143260442898148C8428D11203C288480F434361419C34A1312120C4017 -:80F200001112011245C218234282668820117442A124722C024881CC4202469238D41C04422B212B2124124890422C78884482028416C444244B388668CD2931144CF8CCE35042688351142C622287216217A3228E415042142A412448413C4831A5443114C48126E84601478185B412022D1116B483668413084D184A62286282381448E0 -:80F280008E24402424A1180021403812BD5600108403912200432151181886048641040016081009411480810644488002105824403126830142188C4A4888712202222005A800AF634972246122CF2132356C6232183B241E2827429E4116185249184532C419486C24165C85229B4243024698248D148B4345EA21F648124CD11436433A -:80F3000060224CD268E131C2448B342B48CE228CA8C2254868C15AE244C1128AB2487116A828164C76820F1840018184830225311110C112922113884208164881641441816D881CC258284502412884122A08AD911221482E8200121C418808244121A24C21A8841220F8B1660000280000400884405218164668A12A0400488C110410EB -:80F380001862822064448C74220800448722268232421E228C018D428B1C428100622062214816085F5A0512449413011E242972128432818072143888429142A216484962128486216A1924112214851244180141182442402804422813845341A11B1422400A12288420F29FFB208102100800130123012100000054A11440814289719E -:80F40000828141C1148582011824410040482A24724212011574110223440A00220048AFF10A2113818104209121A5C424840014122001222091482D88AA14C242A012C0C284004C81C481A0412A81C8141661422548948C00484C48A21481124004005FEC054440094781C04E158266428002608481424508844840028447288904488497 -:80F4800040F824482608224440240248260A2E122830588448200212100824F0D15A0080145822A4225028840024491241542840088014014821109421484E22002D41108212A2242428008884B0484142110888528828A0121870F44301460214100100A0128CA812816982092CC11120285842604842888314982445111402224724B0F8 -:80F50000240441F084281810240440028118208281012D2870780586348118C9C114124C0100280010A442800422484144E3344A608488424421003044004440081028018426010022AC8681424208148CF2ECB640684148205848405414245041841C220180025081833892221941180184184AA294142A18C218C0D98114241812851183 -:80F58000214304282C41584226425481C0182D2470DD42021F3E911846F48814224A333127444B2A22818343BA28F11144E083F41A28F44ADC122AF4C821418D9114DF18E216447B685884E544E9448281B11CE8867488742A72D89242142D281B1E8CF619128FB4749222B22AB238A7321A7122A81185A5264F23091E1486549189618151 -:80F600003D168743744F92529A382E821867182FC1F42C128CD4226312132211F58C9D57A22F72FE814AAB448C982899D27294584E628F6348E24856262865C42945F823544F86D3223764A57D19C24519C1592F84C21A27A427412E214953821649D8450441432171311B741C58266193417612D881421C7945C18883358C588185F9C834 -:80F680004824297DC83844ACB112D482F1E45449F342868CB141F6225855C2245C816322388C721872B8F81916686A71C418324C85E2450C88848331682E3224AFAB4D0234402148021C014D9280087C081C083C0888114411443110211121192119329821131C3281308124174824443412140041244110441104418187291416D6A2118F -:80F70000721D57539731EF85A6216F85C4A62BB91F19EB49F91496AF4DFDE5E49F8CFC44D63F9BA9AA1B445F88FC5CDCCFACFCC7C4C7641B154FD6A6BAAE925F4BEDA9F472FC5ED27F5DEC26F762A51CF889C1D7627F7AF8CFC51B669E91CD258F81D498E684F415145F55F73414EBDD2D442F48F82C3EA72226F4181C45FE8CDC3467410E -:80F780001E4816721F55DD1711CFE7E633F2524889FA9C949F13F3183C8F81B9D8FD756C9F85F464F41F9BB9A89A48AF88FCD8D88F8FADCECFECF41A58EFCBE582F1283EABDD2FD9E4C6FE48C19F9DFE81953EE54F53FA8DC59F2A781AF23A48DFCFFF7859EF46D6CAF218388FC6F711129F11F33416EF8DFD72742F4AF82C3EEFE271229A -:80F80000E443F314364FA9457316D45555884D167D15DD17EFC6F62437AF86E42BD1C2F81119284F69F14AC4CF52D74CF5E5772F81E993F3D9D9FF9CFC9CDDCFBEFFCFE5CF747C4BF17C7D9F92E237F2B76D4DDB6FC6E6ACF4564C5F3EFF36741F49F13934CFFBFB3636AF85F76168EFDDFF4979BFC7D591F651789F11F5111169F2DAF4A9 -:80F88000AB746BB98FA2F12E1CAF82518C2E1A8FB6457114F41D17BFA1F11E1CDFF1F91F1FEFC7F62437EFA6F6BA36AFC2FAB9B9C5FA9F16EF44FCBCFDCF61F5EF6F2F81F839399F9DFDCDCDDF59F5ED7FFFFCFE4FCFBF91F52D6D1F96F2F9AFFFDBC6DE2FE2F6FB7A3FBFFE42162F63B2B3F2FDB48FB3F3182AFFDFFEE9F8CFD4F75B79A7 -:80F90000BF97F71939DF94F74D45DF73F12E22AFEFFF6A786B9BDFE2F32A38AF82F13C38CFE2939A9014C011844D118443022284228400148C048C94280082819028009028418121831404223024844028628122482216081A44A341281E482890288002FF940F000024122411254204128502002C0118601415081588D82254182944B1D8 -:80F980002124144214026190128426222104255281508185821428011002188001DF9A082E421F417228F3112487361F41324A1F41F24E131F49F24A931B28AF243985AF3439A4AF3439A42F34F9A4482D954F82C4B14FA2C4816FA264114FA265192FA26D59ACFD98242DDA1F49D222FD9124AD821F49F24E821F49F24E821F48F24E9278 -:80FA00001F48F24A921B28AB9453F84A9243B24A39242B9447822B944F82A4944FA2F47ABAF0224B1E44EF2224316A1741A7141E6C811F41764A95218F54B314F24A14128F5433242D114F8384F336484EB46FA2C5942EC8442E58442E58442E5B8D242E5315ECA2F1116489F111248B141B218B1419B248A129CD828E24ABB45B28AF44FB -:80FA800031A48F4431A4AF447924E844F926488F44F9265ABFBD0F86280800000000000000002400001880080000140000580000000044800200000040015FB90D21411678215422CD111E21284482850140594A60421221814211414880042598421F64A3242904A82888F084128169D8A492A42C8232224A4238124844A88A028E2C8901 -:80FB0000D4C2058B4889F257D1144571A2F181248CC121227014D881622222279114983CD8840220A241C05C814181A34284431418C4382AB41614941126342843D229012CF114881E8140A1258115068CD12A55581880624616016F550B4433FE15A81829625328102DD28612236289F398224902214846721418944484AE18248992447A -:80FB80002E496F229429622E94C3621843B698D226629822AA31A6130813C22A8F424155422AE88D42F414A883F4245A6664941E289F5A042541041D2C34841CE1C122224861811411508420816281904181002944C412901480052904181044D824411C66812F228122A44180041658221508100298245FCB0E2081012211424822110082 -:80FC00004A8824042304428001284870264204008004248241000044818A5222008298480088220088268818F494E9144815062D2142A762502B91266628848411303412495412418631448241628418431322544222850426A741889031181862C041F08A428129C48687481A9248246265024810F8B8EC20440129229222608425216269 -:80FC8000288442004CA114481441924904442C342416440424442281C027180013216141680025E228C488884C4C040028104208449FA6078156861121544927241126181512C488662124121234421011A282481A62A8E0210248804444628843A448200240A8283304844123072D88384E88222D424488232648FAB1CF107512C126845A -:80FD00002824424513C4220081233144904821278C80480400001028C2828189020021453228804AD82A2128480A30128483B858322A2D2841A3C1444428EFD10230241130141605122218502240021022248291118C048002818301C02442006905280028004484C502808484842108008280C7442F720900701402284303209491819850 -:80FD80000012001841812842812400282E860020194802160224122112200500128141008240888401F06B1350411826C11436F4152243D114C12426A281A4832191442C1128B4921424C16842842240B818D2840A263248AE18815820018982A1281867818E4884108235588564882A94A821A416C81436B424F443E440D2415224842144 -:80FE00002006211A44032C082160249028128D8141001002002362480024442582522670220281901286140A242024D128098912A4844842F0F25D000000001120098221504250280000004128004528342410228128114214044384020000008240C882C01249941800242F81091141211694111F21024034428250288331188821C028E0 -:80FE800042842280044144188E247042284A6223100410823182232238422C480283088091188129080048F0791F00008021010023040029911200212014382220240244414141800A2D12400424002221822188212184880092841280110224FBCC50988F44B442345414260311448A7184D444B82EE28262C28642088902242512E2410D -:80FF0000A1114B898A38982A8CD22A1481817A185A88CB444E44424E16822220044554444B2A2A226281A49082274485522223A411EFD20B000021104202800481814210020082001004100422000000800100212C0A800424248100000000F022B910D882A414480000244014C62422280020012012D24221A1928A8208001C14416188CD -:80FF8000818C24A44182441800506241CC228202212001002129F1197B4008482941428421021042042800004842242421800188104488021400848084088200004004890280442824842812025FC44702581001000040042C0225282404001002188008244002140084A04100000000448002200400002180D18D040010014042020010B8 -:020000040001F9 -:800000000800218100000080020028180000000000002C08404208460821000000418B662485B848A41442001012014556446B222222180080440245A2111AE349282808001111118558888B44424AC1A20000504445B424322822428488002450241A9148405288A04420014002004544A82242408404002121411A018A080040511200DE -:800080008528A84420C118218840125844422B22000000212121C7C3001245224102840010020048109888000010046082492204000080014188801822080000001810084800001F930B12003022901200008180548280040000000000442002000012180000100200000010040000F064BC40224154132532122F2121120100217048A84C -:8001000044428CA8454800104404004C2402420020018A81887882022938822424A124850858295484480000F0E6F6248001122845025022259242A1854208904281200428004122261814022B2300800812208822216128888004A13042420012208802411F31022311E221C11200812502400284872429C4128141008210442492242873 -:80018000261494280024008061411A219884A92142020084465288248189084A041004E764F026222F21E222B11221B112012C512329F812131F31B189E989F848888F18F44848421F941481548985F844488F44F424444B244F4222E24202284556442E246F22F212222AA1191AB89229E828592229F812131F31B188E999F848888B48EF -:800200008F8424E48404488558884F84F43632F0262265A2123A211102142512D232F1111119F8918887818F18A44C42141501848588F44844C5B444A226220050424584F2262265E222A1131AB88228082512D232B11191819E8887818B48CA240400848588F4851800000000000000000000000000000000000000000000000000000097 -:80028000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000000000000000A0 -:800300000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000000000001F -:8003800000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000000000009F -:80040000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000001E -:800480000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000009E -:8005000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000001D -:80058000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000009D -:800600000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000001C -:8006800000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000009C -:80070000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000001B -:800780000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000009B -:8008000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000001A -:80088000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE009A -:800900000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04F17 -:80098000FE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000D8 -:800A0000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000000000000000000000000000018 -:800A80000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000098 -:800B000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000000000000000017 -:800B8000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000000000000000097 -:800C00000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000016 -:800C800000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000096 -:800D0000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000015 -:800D80000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000095 -:800E000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000014 -:800E8000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000094 -:800F00000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000013 -:800F800000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000093 -:80100000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000012 -:801080000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0092 -:8011000000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE420 -:801180000F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000000000000000000000000074 -:80120000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000000000000000000000000010 -:801280000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE142044C9481CD484042A1434142302440000F018261287248282842748822981D14811862132488364446084188041088C143414221222822C424442C4249A02128331161F980B2D419D1240110C4786AD162CB6C1721421E2123830 -:80130000845F246A4269D26A032EC22A297118C294482B436C62288283E982FC14C8882E8283A24210D828C4CE46346C1E262CA686442241C4412E4A49C2321225223B8A8AE484F832391032480044850444214B841820084621624284818246280888445200472141186E18822E8249829648004304498211329200418222438242042853 -:801380006089888CF464C814201162848190482B124C321335041482A82100322944225128CC21A48226241812A824490846C84800128D428A1102E0442246840181608400328E122821469A844F71024214001C044C02422822100441408213A2211200100220C18882841008000040684410044400004002231112820112F09AD3400196 -:80140000911120048C04002822411014421404290A8A01882582110218822004001008106884660880222242542440244204820012AFA20F000000000000000000000000000000200800000000000000000000000000B739D0214412282301A12D21169128A3C4A84224644D482B42416230824A82E19842024941E3818A21F51842001A8D -:801480004AA48183684919F48822422AC81418428A81114882283134822C8838442A1564E92410245362818B211744242810011440C82130328A6141260C9044814C04844562C42A388224C448A200265868449382254C988124882CE844312C21299C1662842841A47E6870430227221A321A38412D21292222A48200A5D4823422226A6C -:8015000049B2888286F1812885222451388F49D2846525830184CA12A418828BA1C3F48A249B245AE24431184E818229318823B52698124391822AD482A8424C43F227C8004489410484A714C01184A5416814005362244301434104904410440410A2282C0C61122A0881441410228808208108448424AAC41482102454849F9E022302C0 -:8015800060412144204102A0412C082111008148141518588544001008122210022200122C28081AB24C0822122724304284103442800181229DC1144532112F525112172119E2118256413C511825C9119486E149E288222BD268A1144CC6E490288561851CC4246F86C828161CB854B841C8112E94544C621366CB46C0228981A44817CB -:80160000818C81487418B2884118DA84922C4281AF1902211CD1124201221152443951288384412188031038141324624851843048195428A63418CC426A4990212210A428254984E1821808822724A488448143582881406484F094A4146C026C6141273145218312012531113C481863588B822A89628423D11CB44812C8249112302469 -:801680008984220148C681319454321CE128C6422846941262589C812144C81287214270343828C0285FA70C1C02902250481116C23842801284C51411A8424D42841421441C1604218D248613880283F3281122452125012883814161814014087144436144444187424008219F18434164411342140E2922622434114243185182901A52 -:80170000BC611147229821608182D42C81A521222503494841263A4245592343E142388224502480C61C228721850288812444284C3612DFCC0529C1224361918011545214811213115882100622288044581820024022048339681042A114282B822210D248528413A229190321822082723882088C01A0488FF50A7961431F4192362171 -:80178000C391226D218D613518E112417851921465B228D138371449B28244486C924C4A692136F48352223D982E48322943B32515328E39A2124F88938E154EE94268138B428CD1146881AD122A7488D6846842AD14898264241F7B0722105281C150141229819412482C48181881084E23841C011448184D82888C84428812728844C8D3 -:8018000024881AE2120165022A012A2111022502444342240384004C22F8CA6A80A421246CC12424221816682122248240084A08422241118B34004302A249014D68C941280112232121B188D32231185048883618E8814434142488A400AB2189D22818F8CE511014069112830181282882830181414311125C1480888DE8A20C14A81407 -:801880002088612882821A021C048C088B48803182280014A160838031441248004B242F4B02494203281C13012002609244551814488122183C29008013217248220A800500122817214548E24412544810644E81008C440400280081245F5B0100142446C4248092421608884601398802422110E2C2488101A487144511612711A21EF2 -:801900002D8400828382220C222902186012211682988A836142824C8168441E44F09F744001C038428C2524014444488004004D814068241E281012E888122108845284442244004149221188C134841784002DA48608490680A12CD0420885F169178004811124174281C344223868448602A430428126624841142F8881229842002056 -:801980001819C3B1124E11C81284302AD0820800400149422411848312B2182C1112D28B05244412003022108816D24102182113CAA11246C54292491484080070416814100489882812044842884882C886E4817C52E42124345280B188C4C445129448A0243F48021932112501850120262508428304821481682A280440112A84810410 -:801A000022200860164280021A0838448D41188C02294C082C08AB484129C288A01A4186F4E96C1484281A14024818008C244814E158124188C2818130485042903BC08846E8883111216214206282B0241403112220220536041E21814843820C00B092047FA70C46E14252282F916112763B284E785E184E4CA968B414C61CB528C86154 -:801A80005D1C1D2468C5A44B8D218FA463921D492D488D2C1A45F142384F8313F838A81741484C49F8242C5AF56CD244BF83026AE1A1F3D2118189F95E4876F494184F8929F212946B654A7488BB46B426064B627133D125D24DD6478261638932224B2C1BC3DB843553422D25A3E6129E88A3F42312496B452AF84222832266143F4AAAA8 -:801B0000E8CD43974C2D38584A87E311F429122F21F9A88833F16E184F28B544F1194C8F4CD888366675CA962D1AAB848F44B2C26DA8ACE8CAA314874A1BED1415E631C11183B25291582B24812AF498B22289A248C9F1888917A11B88872C4F1ED4E4E88C7C49FD859A2398888E349D211BC885F9511A1389FCB48486212ABB22F21424AB -:801B800093CC228E289A42F4A8884BA82A7421E2B16D4582C9CE242E424D244B268B18CB814F41CC2ADE9A006D118425415834840024841C41C817822C41C814C016001130828041140131202204C011100222488812224001444082442241048110681C24694408A14B649D273D41CD5418CF61B282B198AACDCF2CF49294172133F1489D -:801C0000A19EB54FEBFB26642E38C2DE8A3F14E482E593F13CBD5FCA7A91F383818D64FAAEA85F5DAEC95F5CFAA9A33F5B26FD81A18F8AFE21358AF84125CB241F14F9818955D188F5A4A42BBA4D122D82AFA2B26AA6B28F82F32C2CBF5543D222F4465A259242421D611D414F46D788F1ECF44F49AF21FAAE5D8F89FB99881B8DDEB5DE99 -:801C8000F14FCFFB2C6CBF8AFF51197E381F96E68AFD3159DFD7FFB5BD9F9DFC81518F9AF774EC8D38DFD5A6A84FC8FEACA85F537258F83161EF6BFE2B23AF8CFCD1B5CFC5F361B11F9FFF9D9FAFCCFDACAEABBB4F64F842C2AFABBB72BFEEF2A8B8CFC3D3D1091E161D4185BA2AF268688F22D39BD44CF458684F6DF28A1C9F1AFB88A8BE -:801D00009F2DBD8AD828F1CB888BBDCF98FEA4EEEFCBFF6229FE518FACF7CBC11F82EC14F4292D1FDFFFA1833F8FF93865BEB88F88FAD5EDBAFE34748F63719BF5C828BF9DFB82B23F7AFF1E38DFD4FAF8B44E899F99FB4545CFC9BDFEF9A2B26F2CF51692AFA4FF62F82B728D18CF42F7BF4C141E12BD76AD1ABF87726CFA2A3EBD69CF68 -:801D8000C6F7787A6F66FB3AFC9F8AFBC8EAFFBCFCBA9E3F22F1EBE8DF8CFEF9FB6FECF81A5CDF86F6F9D98FACFFCBCB3F83FC29498FDCF6D1FC9FBEFCF35BEFCBF634BC8F8AFB557DAAFB2D359FF1F11B1FABBEBF1FFFAEBEFFFBBFDEF74DB58FEEEF96FAD9F9DFDCFCDEDEE726EFEBFBB6F66F67FDCEECFAFFF468CF89F96C7C5B9A9003 -:801E00001460122082E412A1412220A24880446488008524B8480289028B24A024118D243048412022840100C0484D1284411260881484448AC4268022F948249244826F6E068683E22211C112152404E0881402341308F042A1821CA248253495422442118180D22189A29281988280E23269C82E12808832288266A24818922542886365 -:801E80008864C024228344D1FF074D421F41D23EF11124E7341F41724AD341F24A121D24AF249921AF343985AF743924AF7439242F747925D852F925481CF9244A1CF8264A16F5274A96F5274A96F5224A9E242D4A1F49C2421F49D23AF19124E3F69124A3F48124AB161D24AB9419F24A9151AF643924AF2439242B944782AD944F82940F -:801F0000984FA2F47CDDD082C464581E2C421E2C23D4C1B248D141F242948CE244FB8428AB1443F2429147824E91178229F92748987FA2C5814F826D111F82641D57A296E592645D4D4A9E2C9C94618DD39E24C71696744AE149762AC144AF549921ADB519F64A9343F24A924B4329A84229F92648986F22B5680A8480040010010000283C -:801F8000000000000000000000004008480000008281000000000000F0ED71403412257328021901802152821A0290516E845E8249B2146A8218284E14828502411D2C50216C4344C8188222206A58935941548984B48426220850484D828249A486CF220841004FF34791221B282E1411484644849125511A421158C182100884601C93D2 -:802000001471410428460832478489E482C8444AE21224F4811481A4688394421D2481842B48BB34831186941881A800E08864984CF21525C0265E22119722485C1484912145129C112255B811E8446AAC4CB21C18C8434E281E41D641229A442062142FE27581CC448B21992834C183988C1B49745483048F42986699BE2811944C8919CD -:8020800068468A92282592C8E021F2281F1012F124120012004991212A81120842800128229811444181107825285184201288A42422162412312A8C24D4413248482C28410210948282424308418918F4329E2002201118C11210A44981802808C026C081A084114E2530488428E044C21880311841822C4894929092004C8448186281B8 -:8021000040A814498482144A882A0241AB2614D052E22241C67164193214267A2428E91148C857C6644490988163C424488668C4863442E1393219284F82084B86837942942488C992281726882E9289A8424B162A24662198359C1812882E449A120C4C4CF8A2EC1424442E1249D18155412301C9B24AA98119091D142B844024892824D2 -:80218000028D814688984884222E1936684A124F8886A1484968488B81601923E823688CCA92444278241E82CB144528A284C386210A4344F8FF1F8032214022023CC214C02481C088C841436422849542B44498416644744C022D2425C144100812CD8241264262428332620041B0183222811884141A844102A6182C2218F4A84C30143C -:8022000022118042C1A42A5142111314B18441CC6840223212285124D41240140594286021488F117264B14251826400121074440826D818C8142442AF420132224890824078BF0511415A72220427814039284225281244815384230A11A012ACA2141D5440282124082A41184403303883C1624C938389128962224C8804221608C1A7C4 -:80228000648426C4184C012B298F3204105286301441824440C43284002428304822101204A0242621723412042004211810049110C814285084111821614180094B81122283944C485F380D5311E6C17222E421120185544A43B4587222085416D28432228D42141011D4149544685413B114728788A212484D42F01661182D2483712AF4 -:8023000051422D918991298147828718872912244F8174129418AF645284762421C54CE6F868440028250141163C241B212211251181493848C0822238222D342618180126C8244800C01AE08201292411042A413824444306239241244160824C28810B89728408F0AA5D00434224020084488D24004354A2A021190440F1A8114211408B -:80238000140400412342143644121A1211F1211411E044684A282022C218482939448E684100182082F26B24E045C2111009834424846224488140C444858431482C363410E46812082121006648A2412A5421482082064A2201818218C6C21282511488A094622088231CF435F55024244511E4228484042684042420840827222041082E -:8024000081414228621C04282148498834224C4612149848204C1CC888422024C488444A0242824A2254484644F8C86C00000032812654820022818C02002228242002430281442E489460694001111A14480220128221C5141012044224182222004A01428F5303CA820200115604184148800649C411424981A4921C44014041444804D1 -:802480008342818101A5420280123812804A8822088A14A248E0846888424182618225F1A31F24182301D1466881224242805248A028222598194608248C8A12411804904A421122424C4224C24C49C228124C032F1842614484120043041A18A4121A28212212026FA10F00120024241648DA28422454282888424140324144C1E68AC415 -:80250000422C8202214443811202141D2810460200481288811E84181C110118008890882382F8BDA61042622100282844212521A2422142800428914CB4440184262404282218B042880A6218004094422B86998144642C48135C822F8178220840088B69848A4424FC27DA4048944822244416AA21008125048E268722176241189088FE -:80258000904123042981F4448A8024048114A164D4D042142A51414A32145048C0248032144313040032901243F255B2E0426558355298812E4C4F81F1184E6CD422E42442784A4CEC6CF8562A2AF4384883344C2F57F6286CC8C7444B448D4233964E42C7E26B817E54242E211E211D41702824F12A4286F2CAC5DB53CF85A8418BD229D6 -:80260000F8488A1D564929A8299A810589A8854EE168ED1E244B2165A21119C262B9F322626B12239224228722226994269D11A71169023D1A495814CFD85282222D24CD6CA436EA14E45AD624D242F4424E3F46F53626455632AF2662514E84414644F4483C211F259516C71D914F25D684F548A44A6A852E628D5C4742C11D857042A2D5 -:8026800033C5742424247548A4248F8473699C4E4AC6428F2CB828E442F445144AE133E65BFE8918137461E222463764246A9241284E122F88B87412542C4AF12A214D284D1D4AB333F721388EA8AAB584682CAAA2492D882F5DE642F948842E48A24BFA9AB1A4E228E14EF872E600671284434248024100840044844048022840044421FD -:802700000010820200400100004018042041424803002001504812F0D78CD024F2213DFF3252422CFC1D15CF67F42E142D4815B128A266A3B648FC8AE42B444E42EF64F42321BF16BE922CE248A8631D452B322B224FC4E423538A9AFD984C3E52CD4ED5F5514327222E225F53F37D6F6F7BFAAF299FDEEA4FE76AF94ACA3F38FA1A9C9F80 -:802780009CFD491943B6D4A834CAF8CC9C8FAEF5CCE84E548E815F210C281F94F7313329E426F66767EF45F46C74CF65F54D674F42A266AD22AF4CAC882B442F27D766F323319F1CFFA2F8AF82B4E4B872F72161AEF42F46F26CAE2F27F34A281F1DF7B8BD7E56E5FF5D1F1F36F26242A15F71F51B5B6F59FC48899F9EFA28E88F6ADCCE36 -:80280000F481F1AFC2F3C9D99D394BDE4F49A964AAFAECFC8FA6F58AA86AA6D9BB242429F621719F32F22A289F96FE3F37EF65F426542F84D475F228648F86D428B2C2BC8EF87B7B8F85F57C141F13F7C3F12F89FDEB8D1F18AE721D412B8645FC444E2B516AA4D98FD1FD32568D4C1FD1F155455F42F421225F43F37D7E6F7BF2BBF99FFD -:802880001EF3E8FC8F6AF97A7E3F3ADA8AF6CDC9FFD5F8E4344F4EAB345AF9CC8C8F82B39AABD44F4CBB8844D224F22874EFA3F36A2C9FB656FFEFE5F424588F85D5FDF2282C8F8656A86F8CFC8888FFB6F76A7BEFE6F323331F3CFFA6F9DF9EEC3AEE82D711F472E4E7C4EFEEF21A5AAFA6F651F58FCBFB7256FD2C7E3D1F56F2254495E1 -:80290000F27B16BF83F516C5CF9DFF79BD8FCBFFB8D6AFC3F7B3F1EF81F3CCD7FFD3F1E4744FCAAB7DBAFBFCEC8F87B7DEEF47F7C4D56F470F43026302226022844502260224864822818254289285044C0242801212180129082302185012F0261190844888004022412188220812460142F0581700110046014148C14C06004188510063 -:802980002843C821481CD88484024426082A4404401201204208448322018C2202A9010018842082528420F2984EF024421F41F22E131F4132481F41B24ED141B24AD141B24A9921AB9451AF443924AF1439242F147924D812FB24485CF9244A8D855FA264155FA264192E4ADE252E4ADE24ACF4D1242E431F4952281F4932481F49364EAA -:802A00001FC8B24AD141F64A9219F64A9255F84A934B42AB944B422F44FB2448A9F924488DB44FA2F44B2950A24CC65217C1421D2CAF14B111B24AD141D252D981D64A9B4529FB24482F147935D812D984D412F926481CF923588D915FA2EC1578256A182E5AC6F5241383DCB4F1D12847321F89D42CB49152289E6C2B141F48D23EB19198 -:802A800056421B685CB381D658E182D448B91494A24B4A29B19684F2A25ABDA9608882480000008200100200000010021880080000000080040020020000280000000014A02C4046410324411453A241001B821281144962212A34814031287028528528253744212830162C12342212212240682262288C648830884608484942341488D3 -:802B0000248120E41478EE07429E227014828402401111921860652C4401805162384880044624122826146484818984192252A143A2244481887041825412241516AC818C3C68B04C0143C68183F2853B7044B2C151234381942680021512D4182AC25619D4528291228E1125C21289021A12E2480246B82224445441848D428F216221C9 -:802B80002889D2426686288B2428488861392854244E28AAB188B43C2468A1A42E441CA883FEFB002800214051414E1100121884008004411C82048C54582CC4256120022D58286182001400442182811D484284851241144404904400428CB4450E430241195222151408241142400100211188114A0210110844204418488202402201B1 -:802C000060221618420828805412704A4108001068824A02DF3E0F112607614712421C331C30443601D018A4184819461CE422114818584826C225814964421C322481842A141207167988014681416221C28502A400C82D882F385184D68A8201F0B89120524110121201CC41324452406114802412C8841F2261828484C100412002286D -:802C800084A9A242212524416818608112809162A448A13043C22D881C41A8C1842200AF7F01512C42D441C2274674310810611200819224191405200440C12A4D218143C44499120C001011C211812833144218820840038484308261A4228CA124F066E980648245186442115481480050C29128E12361440060613014C4141800406820 -:802D000052616D28255442814782002189166C11842121868C08A1811006418301219EC43016654901421800544604661184946250489179D28664128552818B21224146D248618289522185C12840C112812D112E411E281C218851822186082524324882104848088881A9D2BE0F00218D321400432212F111288100C9A1120000000069 -:802D800000512C4442044800200450241024C1214842C01118A14160228A2189B1188C0244BF634F62413742B01CF22244194135244C54411E288D238074520C83411BC5441008890254196585A722CC42638426185A5256062119D282D314B198763CE191C44A84312F881148CC8822AB818648688D8C0245F84BDF8004E5011400842686 -:802E00008144811458812447832594442C42C821435118418D244014061078244234241002CF1241440200250288122482460281D0422141241928E2E101200234114962211400A484220048001048914419C52814918086342A906A0041441825C1114E2813F1482210C8124A0883042024223444844100F01D7E1422C02222121024223E -:802E8000243646228502142830242CC7212A24C226C048281A44C824186811801491410042208421044220243A4282908800428289948848AEC75021C44008124844811414A14820060028E08441887444022D124651141E484242A021150480020068800640C668211C9C42439E424282C8100412BFA50942111116242404212004002C6F -:802F00001251422B41123414212100844C44022603160B00125021910024504342818119018100908A182443840826D87906464402214E2480011220011A4408304414531444410427274800421321144181044944450100212D44454121848CC2C380542248D08412120282282F8E0222442210E24122C42C2814892244041254124904DE -:802F80002C8442C821144F12F12441100494008181288422100100602410683844240020028486022582F83D75141200001425440144C026A44E21A041143012001314440440014112208262228422813260122E113224200A001111222800412848A324B4A90E43691A2011144861841422100143A44228444844680000280000144018D1 -:803000007844014240228204445081242018018288442CB848A1280044F0116B5081C041412220022306624644C12A2081C23100841312128101A81C528210229442221C64A249A1524001A01222825042818A1211928844006882239488EF450612473826C2116E11223E16A126C8212E2289D23A51843B722E161E2426741231269F8165 -:8030800026443422651894312A52BCAD21BCF443488D182E258D24157511F63321484813F4241A75742298A8A3B82251319F3878820144E14B424B844B2281C48D48CFDE0C1754A215712A56421F857146D141F24261172446485884B5423144414E315F22E13422D498D611F21C6599F42844501517421D581B34344AC4481B542E42853E -:8031000081D11152812926413141426CD828DA8A12622426A284222785A9E424AC888E422E32BE37144B72BD24284391644D24484F9284E142D449B563A4644A24F412614E515B414E649974227127F4744217246E231F15F242438F64A47556028B222A724552144B242A438AE116E233F142647AD618F492424E481F1CB4C4AC4419FC30 -:80318000C2E4AF8AA6CC8F4861AA27484E448B84CAF83E97004302C1302C4003404843480300441224400428504800298112120830249016200218D02441A81284188418008464128D250010F8D1981455D377F22E2F6F63D284F8352E7FF3F32C251F15F34444DF93F329488FA3F14F463F25F367173F55F544762F655576BD495D4D5F70 -:8032000056E432F46A68D7F6777627148F95F712288D688D6A2B664E6A2F46A4641B321F2132224AF271332F23F635629F83F428D83E72BFBBFF98DAAFA5B512F7E462C7A2AFA4F47A36AFA4B2A2F484C4CD8C8FAAFCEEB9145F71F14667E7F2EFE3F466CC5FE5F53F3D4FD2F251315D25DFF1F129288FA5F74F4E2B154F47F151555F71C9 -:80328000F147576F66F46A48F5FC45452E1267E66FFEF867472F16F878699F91F34161AFA2B262F6486A7FD6F465611B773F21B322E422F273732B725F63F63B482E52AFEBFF2B6BBFBAFE13D22B116F26F62E284AFC18988FACFEA2866F4CF44C8C8FAEE59543F144477D677F72F23B2A7F45F53D363FF3D77CB252F345259FF7F56B4B32 -:80330000AFA1D3EFF453127F71F1535147757F77F72647BF92F62F6D5F54D631F162223F167A656524BF95F52A7B3F32F622632B26EC7222FC24277F73F7123223E226F273236B517F12F522422F23FE22763F34FC82E23F38AC884F6EFEA6E66F6DFDFABEEFE4F2A6846B88CDC88FAAFF5BF6145F57D755F62D2F3F27F27774DF65F53BC3 -:803380007F2D2F2B375F56F2515F9FB6F25A5AF5FE51126F65F553554F77F377677F72F669699FD2F24565267262FA62AA77763F7EF26B7BAFB3F36361AFA2B222F22C2E7F56F225237F52F733232B261F22F263736F41F56577BFB2F4F2E2AFAAFF13D3AFB8DE33BC82F864E6EFCAFAD4D6EFE9F96F6E2F4EBE46D484FC286A8785C01148 -:803400003026D01281F4241248268144C24880440220810281114C024431442189921210020000290114A0124022280214402208922882205848F0D55DF02441404238681604C422702801403842C0354924342121002285014C1204224088424844C124001428214489011896182A81188442485684802444F88332F024421F41522C1FE5 -:8034800041326C1F41324A1D24AF34D1C1B24AD981F24A9255B84A3924AF143934AF747934F842914F83D458F9244A8DA14FA27418F5245A96E1A2F5D825ACE549D2A4F591242CF591248D121FC9B248F1916CEF14F1812CAB141D2CAB941D28AB9455B84A3924AB944783AB944F82949A4F8294984FA2F4B9A3C04A1AD638B411324813C2 -:803500007148F21124E3F4112C4E961E282F547A14F848A543F24A9113F3489147834E9527838F14D8A6F148912E828F14F8251AD6F1231A875C2D11CE254F8271D1D8A4F19164AF1275819C189E6CED131F88E612D1C1D442D9C1D622DB84D618B92494924F83D4429844ADB46F8284F926523F5F0D2088040000000048000000000000A7 -:8035800080080000140000480000000000280000000014F0EE990010080040110881200500185110054240112194291722148C2241420442421181002014354880088211820018430860841283F4ABE64032812424B025812288021110582120120949446811001014044400142002002250523C6251250460323021403648308841812C0A -:8036000002281428750A204C4A0249232298285084B0281411229219144354143448301111C66482542120114144314842134298435012695414466832493821A264830C8849D184C822248CC6111E28F7F440120100111001400118000041408801004440214261821424280000406412160400000011008100000048AEB1001604100625 -:803680005041222824110000100541004243428484022820842804001942214841081D48211100000024102211084241BF9F044032216B21197224A12821244028638145420291218C14D181145184904225C4443D448054812122811304003C91442C441D92414B242C24841808428484495448181588C928CF64054012512217424C82E8 -:803700001284121278123118412110581284418904CC94244842412504423C84280419041411114489449C48424AC24242002044189242164C08C845F8ECB2004C8162431021180322200200211141421414140025544268132402812012088002982D412415421153410088840040180418158821F216B550A42642712384042800210003 -:8037800015442201236824A641488802839482C0884A410865521820924410082592284400282608C8648200809821480010F294220080048434142884443129120428225082410024458801A082450828141400112C9428814C24048110018041EC12012522138404841281AD127735004480010010922832244051182012042334840033 -:803800004410180400220030224004405412282004860180040084112841824C046FC803442312D252C248142822A4441D22282551211361228A427A81028128402408C1CC4488722201C022114810584247861422204238818A054E11002B1287484862804144F27E4100441412002501218C92120010082449C4248CC4845048AC048481 -:80388000281800442508E04442C2240025421408468102502882240080028524384884DFF6090000903200212400101202200215022014120800101201000089C11244812100000010848404000000E0A94B01408141C141218024081611A42800A2C8822292C812228632A42215044D1245280242584343848401000026724502482414FF -:803900002124A02486820482D0220C8002282004289024800200222242002A24021C6412486248422A044848400800484220041002110000008888200448A788105118241118004414100415021282103212121480048100288188001444448C0C00190828888B844440228804A02422218B42868202E0B70600004042010000000000286F -:80398000220081220060182410020048000048000042002460820042000000CFE707288082C122C0221428C02800143B426120582141305122240081282851222905230255022400454283048024549440C44281C0420080045FAA021688211194812E1512188021842804121112281A6C1811301120FC2281881642014D48005843219161 -:803A0000142D312C219252C2868262222844D021623820982226C8292BA48302289B9814824B28C0212200282428C021002012128202222200134212092052218044050040020046044281144246C444002C04004214485D8D6096112A0518E032053342224244814221294C4622B1122C912A1CA4144C8484E48294414AC28285C188C06E -:803A80004824C8004818F061822068463582022004852284022304FF640A1AF688241A8323F241233E313D322E218E2289824216111324FAC2222C027AA8476A632497A222484E4487126E41BFC676221228051F21D524C1824D12861A32828AF862A36D42AB644E619552277908A304CE421FA4AEA62AE41884F41AC71422862112E21971 -:803B000062423724412C8431221E81428642E118922222BA98A21901141CE614FC42A1666122464A42218484E841210E23314239061B54A048405421C2428D4223E422AC428C121A426814F0B6DD501113437131D521B112052231436244135211217AB132E82499C42F14F135132F18E618F3184833A2284F68D488F29121687F48532455 -:803B80001A6C244D6D4F845444169C3112425E44282F4444A8263C086D414C645648F04222A322AA482B2460266F52060084A048001C019880091C081448340000825082448412352859849A42A828411B28611B28B081429221100120025440020085010028EF75081F16F6353D9F93F23C3C1F25F357173F17B623F23131BAF3FE782A38 -:803C0000F3C1D22F29F1C2415F79F382924F45F9E3C17F72F2A3D11F17F729316AD628F2ED676FC1F558D88F1BFD7C622FB3FB7A9AAF2AFC96581F5BFBF4944F6AF891133F3AEA2BFF36243F3DF9C7873F28FE21228FBC7C4153BB7724EFECBE42F4AAEA2AF2686AAFAEB2A2FC48486AA666AE6B141F16F6757D9F93F33C7C1F3B7327F7DD -:803C800063612B333AA32AEFCEF6A1B11F3EFF92132F3CF6B6B63F18F994B41F1EFE37351F3BFB73317E38AB378CF4AD5FFF5264982F9BFDB8AAFF32FE62C98F2BF9E2291F97F775155F5EEC2BF323633F15F5D5857E327F5EFA81C21F24F48CCF15F36B2B7764FFCCAE668FA8BC62D6A8F6AAAA2F2A5C8A6AE625F5AC56B061F4155516B6 -:803D0000F135151F11F716572F17B413513129F84A4C9AF851633B913F15FDB4B62BFE5F59ADDF5F53B331F553F19F11E92ECF2B1F32DA4EE4A6F6134B1F7CDD1AE4B8F6824AABF317915F75F386463EB23F31F1531367452F2BFF26A72F38FE23228FFCFC6223AD6B7774CFE83842AFAAFE2222AFA6F6CB8A2BC8AF86A62218AF4B4AF159 -:803D80005151DF51E511F155151F37F677572F1555333F33B112F96A4C17111F3DFE13933F37FDB7B72F2CFDD5F52BFF5F53F391913F15E9A5F9E8B38F36F679E37D4D1F33F3BBE39D333D4F9AE7A9B54FEC47F7D4B66F29F413932F27F3F2B26F6DF853536F5CE83AFE6362AFFAFE2323AFB47647F7AF8F2F22F28ACA2F26F62A6A8F2A88 -:803E0000BAA2FE2A282AE2267317061440011C012412000014400228130812281301138812011828188021941280011420022682840824408104C022800200008DCF0000122011022480210110021C082D82C08100201484024062442210845214289021904110011902004100006082212200AEAAC0421F4152281F41326A1F41324E1D0E -:803E800024EB141F48B64AB981B24A3985AB9443F24A9343F242B147822F14F924484E914FA2C4814FA264554FA2645D4FA26C59ACEC49D2A4FCD1244DC21F49D22CF891248B841FC9B24AF88124EB141D6CAB941B68AB9451AF443924AB944B4AAB944F82B442F9A448984FA2F474F47024D2C1B4287411382C4C742ED141F42E111F41EC -:803F00007422B411D44AB215561A3AD41AB814C4A54F82F4429565F848B16B128D912A7C583125874535F218253C7418C5421FC54298418915F148121D2CAB141F48D22AF181488D141F88F44A3686D838F3A448A9F1A44829B184B44231862B144FA8F1C4E6402808000000000028000000000018800800001400004800000000002800F8 -:803F80000000002501EFD404400400282128400200002400C2282100280080024A1204000021008092420000804411084082440244002C012008820000008002140000400822001100000024401802008044012004420020044200004814B0810C30C40080022800412810814202A084AC4222021A4221082820425421401A480280249404 -:804000002121003044A0421008400224244C4421F1E19800008200210010020000000000000000800400000000004220040010210442200400004F9901504100008002002800000010044004400284004002240000002004000000424100002002F043CB002A0114001001248420010040040000812146040000832402450121212821007F -:8040800000000000400890281008F0D5F50016051400601200A12218000041400400A4D024048400C0482902354402201202420000002014040026088C02D0840120020000000000000000004004000000000000100200000000000081000000F0D821800200400114210000820050140000100410880100000000002800404888088182B0 -:804100000080040000F05CA1002614080000484242810000001002000011410000001004004901184228000000400400002218F0C5E3000020020000140080110410040084000000000020040000000000001008000000008F41022244818042011121420000400415441402400840112401000080040043210248228484824008814420DA -:8041800004002200AFE3098002000020044641088218000000004100810000004004000012000000200800000080017F9D0B000000400800400100000000000000000000000000228840082800000080010012F0E1FC00000000000000001004000000000000000000000000000000000000000070AC01140000000000000000000082007D -:80420000000000000000000000000000000000000070F303110000000000000040040000000000000000000000000000000000000000F0184D000000000000000000000082000000000000000000000000000000000000A043000000000000000000000000000000000000000000000000000000380000E0EB0F0010084088044100000092 -:804280004400240000000020010000800100840000000000000000006FC60B0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000002400008840020000000000000000000000007B9C001001AB -:80430000000000000000000000400400000000000000000000000000000000009F7F070000000000000000000000000000000000000000000000000000000000F04FFE0040410800421004000010040000000000200188002180010084000000000000280000F0A8C500000040080000000000002100440010020000000000000000000091 -:804380000000180000B06C0E0000000000000000000000000000000000000000000000000000000000F04FFE0040010080045400004840040021004400100218808802218001884008000028840000800200009FD2010014000048405588281082044480022100448002214818808802214818448828842148408481421882041E14800244 -:80440000211A01445C0300000000000014000000000000000000000028000080080000002884000000001B72004001008004540000484084041002400400218001882810021880088400008042080000280000F0E2D1000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000D2 -:8044800000000000000000000000000000000000F04FFE0010020000000000281002008002000080028004000080044480022148400400214840040021EFA20A0000000000000000000000000000000000000000000000000000000000F04FFE000000000000400100000000000000000028000000008800000080420800000070820E0053 -:8045000000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000008002000000000000000000000000F07F4D00000000000040010000000000000000000000000080080000002884000000002FDBFBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF63 -:11458000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3B -:00000001FF diff --git a/xpp/firmwares/FPGA_1151.hex b/xpp/firmwares/FPGA_1151.hex deleted file mode 100644 index 5ecab69..0000000 --- a/xpp/firmwares/FPGA_1151.hex +++ /dev/null @@ -1,664 +0,0 @@ -# -# $Id: FPGA_1151.hex 5128 2007-12-13 14:30:31Z dima $ -# -:020000040000FA -:80000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6AD6FF400038460A006AD6FF400038460A006AD6FF400038460A0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4455544455557475577775577675577775577765566665563625523235D2E37C2B511115511115511115511136 -:80008000155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111000000000000000000000000000000000000002552222552222552220025522225522200000000001AA1111AA1110025522200001AA1111AA111001AA11100001AA1111AA11100001AA1111AA1111AA113 -:80010000110000002552222552222F21F112122F21F112122552222552222552222552220000001AA111255222255222255222255222255222255222255222255222255222255222000000002F21F112122F21F1121200002552222552221AA1111AA1112552222F21F1121200001AA1112F21F112121AA111002F21F112122F21F11212EF -:800180001AA11100255222255222000000000025522200000000255222255222000000000025522200001F1BFBB1B1755777000000000000000000000000001AA1111AA11100000000000000000000000000002552220000000025522225522200002552222552222552222552222552222552222552222552222552220025522200000066 -:8002000000004F44F444444F44F44444000000004554444F41F114141AA1114F44F4444400004F44F444444F44F444440000004F44F444446F64F446466F64F44646000000004F48F884846F69F996962F21F112120000004AA4442F25F552522F21F112124F48F884846F61F116164554444AA4446F65F556566F61F116164F41F1141411 -:800280004554446F65F556566F65F556566F65F55656000000008AA8882F29F992922F21F112120000004F44F444446F65F556562F21F112128AA8882F21F11212004F4CFCC4C46F6DFDD6D62F21F112122F21F11212006F6DFDD6D68AA888255222006F6DFDD6D66F6DFDD6D6000000008F8CFCC8C8AFACFCCACA255222000000455444CE -:80030000455444008F8CFCC8C8255222004F44F444444F44F444440000004F44F444444F44F444444F44F4444400000000CFCCFCCCCCCFCCFCCCCC000000008F88F88888AFA8F88A8A255222CFCCFCCCCCC55CCCC55CCCCAACCCEFECFCCECEE55EEEC55CCCC55CCCEFECFCCECEEFECFCCECEEFECFCCECE00000000CFC8F88C8CCFC8F88CB8 -:800380008C000000008F84F44848AFA4F44A4A255222CFC8F88C8CC55CCCC55CCCCAACCCEFECFCCECEE55EEEC55CCCC55CCCEFECFCCECEEFECFCCECEEFECFCCECE00000000CFC8F88C8CCFC8F88C8C000000008F84F44848AFA4F44A4A255222CFC8F88C8CC55CCCC55CCCCAACCCEFECFCCECEE55EEEC55CCCC55CCCEFECFCCECEEFECFCE8 -:80040000CECEEFECFCCECE00000000CFC8F88C8CCFCBFBBCBC3AA3330000008F84F44848AFA5F55A5A2F21F11212CFC8F88C8CCFC3F33C3CC55CCCCAACCCEFEDFDDEDEEFE1F11E1ECFC1F11C1CC55CCC4F4CFCC4C48F8BFBB8B800EFEDFDDEDEEFEDFDDEDEEFEDFDDEDE000000008AA8889AA9991AA111000000CFC4F44C4CEFE6F66E6E1A -:800480002F22F222228AA8883AA33300CFCCFCCCCCEFECFCCECE2552220000EFECFCCECEEFECFCCECEEFECFCCECE000000004AA4441F14F44141155111000000CFC8F88C8CFFFBFBBFBF3F33F333334AA44415511100CFCCFCCCCCFFFFFFFFFF3F33F3333315511100FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000008F84F448489F95F51A -:8005000059591F11F11111000000CFC8F88C8CFFFAFAAFAF3F32F223238F84F448489F91F119198558884F4CFCC4C4FFFEFEEFEFBFB2F22B2B955999855888FFFEFEEFEFFFFEFEEFEFFFFEFEEFEF00000000CFC4F44C4CFFF4F44F4F3553330000008F88F88888BFBBFBBBBB3F33F33333CFC4F44C4CF55FFFC55CCCCAACCCFFFFFFFFFF9E -:80058000FFF3F33F3FD55DDDC55CCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004554444F42F224242AA2220000008F8CFCC8C8BFBFFFFBFB3F33F333334554444F42F224244554448F8CFCC8C8FFFFFFFFFF7F73F337374F42F224244AA4446F6CFCC6C600455444FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004AA4446AA6662AB6 -:80060000A222000000CFC8F88C8CFFFBFBBFBF3F33F333334AA4442AA22200CFCCFCCCCCFFFFFFFFFF3F33F333332AA22200FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000CFC4F44C4CCFC6F66C6C2AA2220000008F88F88888BFBBFBBBBB3F33F33333CFC4F44C4CCFC2F22C2CC55CCCCAACCCFFFFFFFFFFFFF3F33F3FCFC2F22C2CC571 -:800680005CCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F48F884846F68F886862552220000008F84F44848BFB7F77B7B3F33F333334F48F88484255222008F8CFCC8C8BFBFFFFBFB3F33F333330000BFBFFFFBFBBFBFFFFBFBBFBFFFFBFB000000004F48F884846F68F88686255222000000CFC4F44C4CFFF7F77F7F3F33F33333C3 -:800700004F48F8848425522200CFCCFCCCCCFFFFFFFFFF3F33F333330000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F48F884846F68F88686255222000000CFC4F44C4CFFF7F77F7F3F33F333334F48F884846556664554448F8CFCC8C8FFFFFFFFFF7F73F337375F59F9959585588800655666455444FFFFFFFFFFFFFFFFFFFFFFC6 -:80078000FFFFFFFF000000004F44F444447F75F557573F31F11313000000CFC8F88C8CCFCBFBBCBC3AA3334F44F444443F31F1131300CFC8F88C8CCFCBFBBCBC3AA3330000CFCBFBBCBCCFCBFBBCBCCFCBFBBCBC000000004F44F444445F54F445451551110000008F8CFCC8C88F8FFFF8F83AA3334F44F444441F15F551514AA4448F88ED -:80080000F888888F8EFEE8E86AA6664AA4444AA4448F8EFEE8E88F8EFEE8E88F8EFEE8E8000000004F44F444444F47F774743AA333000000CFCCFCCCCCDFDEFEEDED1F12F221214F44F444441F17F771714AA444CFC8F88C8CCFCEFEECEC6AA6664AA4444AA444CFCEFEECECCFCEFEECECCFCEFEECEC000000004F44F444444F47F774740C -:800880003AA3330000008F8CFCC8C89F9FFFF9F91F13F331314F44F444441F17F771714AA4448F88F888888F8FFFF8F87AA7774AA4444AA4448F8FFFF8F88F8FFFF8F88F8FFFF8F80000000000000000000000000000000000008F8FFFF8F88F8DFDD8D800008001000000000000000000000000004001000000000000000000000000DF75 -:800900008D07480000000000000000000000140000000000000000000000000000000000F07472000000000000000000000000000000000000000000000000000000000000FFE40F48008001000000000000000040010000000014000000000000000000000000F0E6F40000000000000000000000000000000000000000000000000000D7 -:8009800000000000FFE40F2800001400004840012800484001280000002800480000108204140000484001002148000010F26B52000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE80840180020000001002000010024082 -:800A000001002100140000000028000080880200008828002800FF9C030080840100002001000000000000402101000014000000140000001400000000007028034818148002800414182810820416012810A21140012810A2414001002B11484001280048408188022148008828108204F05C65808401800200000010020000100240016A -:800A80000021001400000000280000808802000088280000F04EFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000210000002100180000000000000000000000280000F0994D000020020000002400000000000000180000000000200200008228000080080000D0C10C00000A -:800B0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000008001800100000000000000000000000000F0A149000080020000002400000024000000000000000000000000200800000000000078 -:800B8000EF8A0C000000000000000000000000002400000000000000000020020000000000D015020000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000002200000000000088280000F09AEA00000000000000000000000000240000000000000000000000009C -:800C000000000000F06646000000000000480000000000002002000025220200220000000000002008200200002F940C000000000000000000000000000000002100000000000000000000220000F0855400000000000048000000000000C022000010220200280000000000008008000000F0D59C0018000000002001009800000000405E -:800C80000118001100000080010000000000000000820067E5000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00400100240000180024000020011200002002000000000000000000004002000000CFE10500000000005F -:800D000080010000002001120000000000000000000000000000000000007DE10040010024000000400200000000000028000000000000000000000024000000F0CAFE000020820420824402002400000020040010210410020000008004000000000080024200F0823100200200184002200100400200000048A0240080040010020034F9 -:800D8000000000C20000280042004A22F8D8D9000000481800000040020000000000000042004002004003000000000000800400F03C270020022800C0224230120000240000800442204681042400000000200400008A040080022220046282EF214881040000200223011032220000006022008001420040010048004800002162200427 -:800E00000028280040410248CF2F0800A01248004041011301482880022200241120018002001C024001284212002800002602000000002480F8D4F5000014002224001248004082046022002004400100184800400200000048000000100280128104D06703420013022082427112814102480068800221281148002002000010012200EC -:800E8000002220A42460240020820280024220F8813700001242001002B011440200210022000000144800122A04002C04200100100280020010020000C0431FB80912800228A024112842288082040000201202182382210622264202C022808202201481229442138802800882008800A22A94828F8D0C10011902001224002B61250159 -:800F00004812222006004222482C04808484840490411118581122484A018012232408244227244A0242C800481F87041838002222002346021420042A1422020042200412800620026014222A140162208222022094218028A4822A0842288084C281CF3D05481021212481A3248022041304004818122A0540022002180010228203000D -:800F80002A01A0141002800800291802212182002C28F258BDA04211121842424828482C22324300000020020080A24226022248904100281CA424C0212800102232C100484A082304238402292A28F21AEF00222222000025022002210021480062484268482121482904290446818404C04160140020860842420042A084200430424804 -:80100000CF2C0C00001800005840021800622828000024004800222002002001001218428024220800202822026200F03D44001800806221420048C0427062220400425840022400220000000090214021020019042800200280082240017FAF0E001C05121A0400000028800252520010021880180218282AC1614081118104002D422863 -:801080002800828868002282228888422114F7C620041B3212621AA7567E622AA2622F22063521A444802681A232282344B24281A6216A662668222D4220A2262D61384A11F12121112E111E622B22F041A319AAA4A0888A784222B242282AA444486E218AE6CC021AE71341E11282244242219412F032632C8454226E420032A056484A45 -:80110000E42266242E429062422C26B423A7441B4113F261411681036A86226424428AE41C641860244E42AAA8A42CA4C42AAA82AAE818AC86AFA502902112181A23A421D02264244213A4242981A22123A6764AA544000023B242512212224AA122422820041B22362144A1452B12482B6222222AA48C4880F68242AA92228AE428A2242C -:8011800024217FDE0F4001000018C012C0138001180000122001211022011221122041011440010024400100002440020000D07E01821F1283A2324AA2231E222B232B212AB252F33123567242B2522327A3137AA1223AA1151AA1272B46423E526E622B562E125A25A1115AB15184B111F111311996413E1223C5222B441386A446A0844B -:801200004AE824B422E8247482E116A4C248C814DDDA80B47127A1525AA4534E422B472B457E122B552B433B272F25B11221A3477AA117284AB452A1554E224E429EB22B731EB22B542E127E525E216AA6261B671CB57137112E21687E722B552986B261C8A14AAEEE4A88BA62A48A6ABEA2BC6186BC22A6C46AFAF617A0551F11A4213A38 -:80128000A3246AE224F262322D622B732B241F36C3622F21B142C432583AA5117A273242E026F36242882E427E722B463E225AF6223120F471612AA3731E111119E621B37261262B441F1EA288EA8C2224E82CB622EC249EA3CA24B8A2A66AAAF24A2FA06F1B6317117A21A5175E522F22B14264262F25F163133B6427242B556E726AA5A0 -:80130000275AA7755A25A4444E224E421EA22F23F782222B4476E22794326AA6351F15C6311B711B331F1292615E722B372F2692221F1EE21AAAE6CAAE84AAF8E2622F2AB862BE22A8EEEAAACEEA6C1EAF160E1880011848184880044880044820818204000000008002200222A012601220822422280220088228821182288228823D2F67 -:801380000011008048022502244001250229820400000021100200230200144001002C01001482002400D012028004F02FC980B41162121B2166B11132621B212F36B111F262921B212F1439112B94322F1429F24291222F14AB424E912E421CFA22425E212F22E519E22265192D52DAC2521B292D531B29341B2946B1917642B381724267 -:8014000092612F1498212F3418F14282222F2428B2422892822AA4842E42CFCD0F2AA4412AB41122B6113262282B1619B26299214A9B214A29F24291222F1429F342A12B434E812AE514AAC25EA12E42DE212E42D6C143DE2148DAC2439AC6431B2946B19166141B282384E61498612DA119B642A8422B842AA4842A94822B424AE8226407 -:8014800012008248000000000028800400000090128008000000008004488001000080020000004001DF4B07820020042400004003A01242108304128004002200282C0200800200294102488200002426022848008048F28CBA20A42980012E1220C2422AD4222432428682542111284822132202226842001110832402271242290121A2 -:8015000060124E11264122A28426C18224C2003081282044A1245F7B4921A43C80012A01298224964222394482E6211281C241282C8203322A240828113023172422702221A4219042242E111A74228194228A64122A08239C2221E0188442021C88F2D1670000200421400224402208114210824401800448000020020024000040012013 -:80158000084002002002004880F4F3730020020000424821134102210082000000100121100100003C0814004800000034000000800842F09A76200220E2240228002130C2200C8002308128800242A0428022482282020028181642021180223C8100004A022800424228F0DCFD200228282C062200219093308221000011000042E0224F -:80160000048048222202708182321118101201803481100120040080042A046FA80300000000484821488004808208822820021001801201000000400242002888001002282002802804C0DB002212280028122C04C0420012488004224002184280A48486014081A821C01218822601A02100225021004888820024422420724C03008022 -:801680000480041448181420022280010046022C0110820800268104800411C84200501200E2224800428008884E22A0842F8C0500400100210024002100880020080082000012000000000000800400004002000082007FEF022002110022230129C412172400182A24880422884240824C8284C481180048001A94121C98A142200248BA -:80170000226014004888290882304282A0486E2F008081022004460100240000120000000000002022A81200000080012501A028214800420080A84260129F250B1222102121B21222922222002131882901282246118232812C44C123C0224821582800181419811201198922C46110011C84084222004248422229F4EEAE10010011137C -:8017800044210446024211422096229081008004800888110020A82920042B41002011024840011082084A2882188108F0566200140024000020B8120212002200182004222014218585021118421001001C02282440210421482024220442006234DF840D1100281142204422041314211422C48142214A120100B88048A12848800412C4 -:801800000030114248305125118108881188428842884288248880F84CB8A0343220A121321F25A212683248000000282A04258122B31244B112225222004A28A224268122828282022880862224A6244A0823282204A2222A2C263822AF15040038140040028880022908290288002A0821A82901802228220220280400110082000000E8 -:801880002100800200004817B80000000000242810422208210014001304581400E0281481044814000021C84200000020040042000024CF4A04228212226215021120880848886814424A2988C2421CC42288A2121CC6410028000022002012011448192ACA818004200800286014886F5D0400682008002420420128001111112128100D -:801900004281D5228408132208C0D1214229849141208435812400800428000000002114CF480A1F12242801171E15A2142D42422CADA41B1235C1428AD821A6248E82822C9421421F1CB6C2D823E421D912B2413222212A2502181344C1113F1243011F11F8211333A442114846812C988280268A0288C04142FFAF44A111968162111893 -:801980002F11342211232228DA32042D112B242333A11381DA11E11408181F23A4863714172426A3E44E82C6A1244AB6518EB663A42112286AA46C1AC4631C62146EA11D22461182A44E62A042EAA424A22E21229F6F03282AA2121B221AA2261F11A2362CB26212A22446A28C244225A16617366A7222B2216622288E212A26A2C11F1888 -:801A0000A16A281CA499238A81027041922118CA0A33A4E8A0C8114EC24288884AAC84882AB442EC24F882C2EDDE144218C011481C8184818481C411482CA1482C8184818401180000008840022E926022E0220122A092603220226812822088228822C821822882286FA2032A220319A7221D112AF211113A23E829F912322B11A0911E0D -:801A80002137111F18BB31FB31323F1DED14F43171EAFE21811F18E416E637FFE341281F3C5C22272B1E42171235723222712113F23181121B461B4415D11124E224744292624A8604424AA64428482CF253DA142E21CA84C2612E233D422F22F223432B229AED2BD933F622231ED22F21EF31F231211F18BDB1DB31F4E3C12F14F43171F3 -:801B00008E921F3AC8E32F37F742432F1EA4A21F3C5C322F28E128F4414135F3534315D313A444171D17384E433D411F12F481411F1CE412622C29A24C48CA84E21CA444238824FC8885A0671AA5121B317AF671132B6717342B66FAA9EC1F24B243B6D2B1C2F841712F14F4D1811F1EFF63213F18F853111F12E63EEF1EF841833F16F672 -:801B80003173EE43CE223F1ECC612BAF2BA51F32B641B633B613E22292221F1FBE91B662B662B681CAE11BA21F2CFE42822B886AAECA2AAA8A6AAECE2BA2AAEC22BEA14FF171719AA5331F15F371711F25F573711F35B562A6CC2F2FFF53732F34E624FC72D23F34F762611F1DFCE1F13F17F7A3811F15F321618E83EEC11F24F473711D64 -:801C0000431F3EE42AFAE3C12AB2F2B7F2F621631F16B633F723323F16F261611F1FF3A1326E633F12B6A1EE1AFEE1E18EA32F2CB8A2A8EEAAAEEEAAAAEEEAAEAEAAEE2EFE89AE00004002240082000010011348022800114231423110022004005012400114004001000000000000CE42400122400186210112211A5212122928511212A2 -:801C800030114212148210219451C0822820D1221881244102141B412C180140114102210000002004FF740E1CB41142B11162141B21271419B24291212B9419F2429313F84293A22F342BF24291222D91AAE414E922C4A12E4216E122E419E2226D192CA5292CBD91C2521B292CB19122B491F242921B28271419F6428219F6428119B4B9 -:801D00004228B242A8422B842229A842882E428F6A0A2A91415819A212482B1219B4229141298986AB68981B482DB1482DB1AAD412B182E414CB121CCAC21EA11D424AF2218256E13268192EC213E922B481E422349162112F12A84826B18134228AC4211B68218A94228A94228AB4423282288E422FC90E20880400000000800200000011 -:801D800000000028000000008004000024001480022800000014F08AD5200A1200282902000042000000130300221C984100822400222119022B288021858234414240021C04000048002860222BCF00822A08141414282234964181410230532CA6212416A1251A8414021C0118281965241842208401148819082C02828A34A129486220 -:801E0000242C048A04A814421C08EF324201C218001C32228042032044824222C52232267311021A249783C2190198283B1413D422210446A238E011846512A0424880C4212B8630422420842452214A4221B2C90C22A08240011428001C19810100144820013A04001100000028902100008882421121822C28480124482008820088F0D2 -:801E8000E8220000281420924124124612613400001A04120020021100000080082A08804281C48200008288102288082008A024F034AE200232124868112AC141004A018AA1844A93411488424882488842486810C12214224821484A211242011429828284480121404202482220C44100AF910E228001116819A2143C840118158221DB -:801F00008841A114881848884282408104142C0222482328A41400115021A22100C082002488002288481448F02F9500808223049021004239242428A42442142004002242422200100100A08228212811422022244801821042828804004222F0C8F6A0142218680013023021200388800240014022818B028008001400228210828C02A3 -:801F80002848004031424820081081022C0A48FF6701008024042001290420A8420023880422602480A584A041888228141C3242002422C22024012448A20082200462000046022CF2EDDD0000000028001210021061140000000000000042A02818001100008200880000240014200822D0D30912281222426012222419260188C85021E9 -:802000001B480022208481AAC2A04120881241820438249083884A82014A3842A8881582842404220020888642F24545800400002001001A120220024814000048000000A042A08280880200200200008800822304200282A042EF9D0F48721081C1110050121220582200922192211A2201E0280218808991916898B0410A4A83820C98BB -:802080002882281CA4821002828E2222282280226232F0546F8002282280024A82A4288002282002702201A0824022240A2200622004400200422011018821484800200482C0C28084B8540740218184044248008248482004424220922229046219924214001906222848006022284021822286220440032088280480C42123F49C2800F1 -:8021000000120012003042002002208202C8800800208404000048480011602242240080820800222022068288281F330800209121322822281B8228A2258224A8212A9C8324005E212AA9851CC461222822C22848628A8662188230218223C141213042468106212018024888802484BA83051800284290410042130800200818E0280398 -:802180008246D112A2182C41A194882246011C88818812218138211C0400110080B44218828814010000571C20228112014200240000102224011220094002A0148001181118148084018024828982E8280288800842483081800420F44F8120041240110120042120880410B2212488081410020000000028C02100800225D1226C28805A -:80220000084A088002A8808428CA81F0A829808182042242322022A44242422842C228241100906280014A0A288820410114208204B0820480042048A268200448601A0021F0436520A2511AA125A0412A05F042426A88082D42A0842B48211CCAB2281BC8682F21D2222A9441A0381CACA422A213671A623B6A22271A2212E6E222BE62C8 -:80228000AC62398C2A88384290A28AE21CEA12A4442BAA469322AFF6094A47A1222E11261121056E4213B88204272CA086C0224ED38632A28ADC12612C6AF4814125A3245A848422228488841A0190C14AE4249C418240226422482420A6466A044AA28848AEE162AF240A122A02111B746E3119A266282EA11B216A862C9442AAA7971B7A -:80230000223B13B032A1272E911C28A6E33E11AAA283EAF1115119A7758AB241E418A6111A82F281223F1AF3123125E128F2C381A2CAE424F8C2418AF882E282882AA4882842A0C8F501004021080040220840022048124122089210020088000040010000344002248200240000402108002F450B5AA2261219A62717161F16A2462A2217 -:80238000B4E24A12028AE821B162AE7726A1B34A64111F1BAAAA3F1A6A2C3F16A691AAAA5417131AA1CADAADE88AF8A1813AD311A6CC4AB433B382A2CC1712371AAA8EA8842F247822B262A4C66E41A0486A8444F1C53B20A5531AB121B2F1D611A1374AA42217342BE68E822BEE2F24B4C2EA2DB972F3D3B23B992F23B3D2FF53E11F137D -:80240000F6E1F31F36F441F33F17A751EAF641711F17E613A3FF7AF5E1E1CEA11F1FAF331F1AFAA1813F1BF8B3B1AEA22BAE3F16BA62ACEEAA6A242B2CEEC22BA82AA4CE4A2CB862A8EE4AA835A0642A26F311313E3115F13131E02626B2E2EA26F4C2A246A2CC4E422F26EE22E23AE822AAEE2F14F4F1B11F1EFB83811F34F86361A0BBFC -:802480001F11F131417E61AAA88C1BC81B881F1A0E1F18FAC1E3FEF23B112F2CFAE2E217323F1EA2EECEE229F8428227222BCE6AACA819A2C82BCC482AF27758A0553A21B331B371F751511F17A3446E62CEC22BE6242BEC25B2E2EC29BBF2FB13333F19F932322BFD1F15FDB1F11F3EFEA3C33F34F473711AA37F1F1DFF31617AA6FFFAC9 -:80250000FF6161CE811F1BAF331F1AFA81A12F1BFE3231EEA22BEE3F1AFAE3E1EAAEEC4EC22F2EF862C22928B2C18CAE886AAAEE6EA1FF4F0318800118C011480014004880044820A824132824A82411004220044200000000184888482248A048208802A0482800826F4102009021421180243481232408102228B4811402210015820837 -:8025800000804881A428C88AC28128B0814282E232084682E214082C080021800A208208EF8F032AB41142B11162141B212394212F24B191B24299212F2419B14229FA429313F242B3A22D91AAC4912E421CF8224216E12264192EC29E212CAC292CB4D1C2431B2925B2917242B2917242B3817242B381F2428219F24282112F1428B2426C -:8026000028F24281A22B842AA4842E427F6A092AA441481B2162122316B16231912316A1B41B282B94924EB113F142B1B22D112B491CAA521C89EC15CA521E212CED11C2D39E212CA52D3CB491C6D11B29421B6927148A62141B282394214A8AD212A8424AA84A2B84A22334224A6822AF4A012008000000000028180000000000000000FC -:8026800000000048000000000028004800004001AFCD0A20020038241C8154215AE81823084223C291208804422A2182080086A12400284248C02182210098A08410220200240048200240F2F7DB20611820098044220200482038812344826422260182108214022810A141107223E2340880A8482E82142C02804881D4214481022008D1 -:80270000821414A0E21412130C00184662212815A2142E8188A028E01C41A248241D2248823229A848214081061180744222240229AC48222B1822C224822222002C028004244001FF540480029280021142802821044632A121002A04800300008A021458282119C283118800821410021021944125010088804A01B0A509A021222002DE -:802780002240A2412001100210810828C021209441008024842144A2212428002901260200228200200848888008005F390E4A02185021D0212482A28214C224821C8C88A28121581420641C28282B244A8392212890822A01230E8800211908D0121C312270C2612C488A04228848428A84F4A4F42022A32180024200290DD8001488409F -:80280000031001281442222984031422208882622C00101292812110122108212400422A28082004EF3D06480040031D2222282814402238C2202289A8412260148A2492412248282A24C41248162231222882800122001B482C82028E414AA8844A0800C8428848DFAD0118002811002800C2285280C51242420040220192002C083240A5 -:80288000C11280210C12260218002022641286218C04210080C82240F23777000048420042245200880068801121244202A021808128880414201241021448428800002842000000A2002442229FAB0F001001001200121A1402000012002A2824148202280018428A2408128082810228242C04002100A048884082A2480067EA2001606F -:80290000121C04A02410A2816AA141A0412A95424A31118022AA14468282828132824A2281A41CA2111A08112AA1249228242C8422225612C80048204A22A86842249F2C0700000020011A24042908000080040080080080010021122C042A01210000201481084290828200280026F18926800211800142281021140124924A082492A000 -:802980001430813021E024421221A281806824428008003A0434482008800C284282000010F2986D00118002602311221023921280C4122C01002248482221240020082C248502428004222400280029840C0088422004800A5F250A4A02C011281C8102001800182021042280B212222104A043001200222D11A81128342248200620A27E -:802A000024222119042480024A62284A022E412F384D01280012200129810688C800A88820841202002C8142A18492820000188212200100828215024240220C209CC20000704C061A841221324119C64222258231412001487041A24227214229248812A24222162281862404422C02298242823212304100821082988311C28822242A9B -:802A800028084622F89E4500802201123100802284C881D022A2838A81A8121228C8348088C821860118111C018A0280820418218A868292432C2A04828012210262884072AA04004001002012011200200400008001142400122022028025810180820450221C0400002800000022E055011182280000A0412823A2384218002242421266 -:802B000088482C028004582023C41280011220A1181914022384388214404232414A082182292824C68188EF820F4081041382044A014800802A1902822C02201962162C2181180180226612429062800412222800200880028046B2214403822924F6C3F114621F18621213837111E1245312281B22327E82881622B122ADC12D128E521B -:802B80002B235AA1582225E22282B4533761BE51A21A8381AD11EE726A2382E124A2645AA7428E428ADC319A824A2AACC8422220AA2826014886E126322DE011221A8132314A32122223C2121F14A638181989E12DE212A28E294AB22238729E924A12A212242B1111582A94212B242C8218825B21A23623F24222464132E24E4125C2C29D -:802C000035E21888EE28A4241D42282BCC826E21887B3C8004281CE11482B521E421A6152F141442A14D82CEC2F0C21248724A8186BA41F621411D412F2822E21894821AAA846E4236B26134121B4912282B11182411A82B22F081222A14621439642C6ACAC22B862BCC222BA62CBC82F42A4B0014408104400214001220490124822400EE -:802C8000821001211001000021111811100100400124400200100100007F444C8194212AB221267A61F363212AA2445E132B55EAACCC1F14C4923F19B8E2A8932B574AA6AC6AA14426F24243CE425E324AE818A8884AC4622D222F24F1B1E18AA82315F18183317E321F15A5EC2BCCEEE11F16E22EAECC4823A4AE8AA8C4211B662BEA2A41 -:802D0000A8CE4AF4DD7D144AB461B621B231B631FB11232F2531222B241F25B113A1CEEAFF41D12CFB83832F2EBC52E72FBF72B7D2BB42AEEC6E132F36B422B972A3261F1CAD886AC4432F2632421F3FFF53111F15A4221F1BBF11F751735AA5C82BCE1F2CB661B2E2BE62C6422B64EAA8CA4AFE23E21F26BEA2BE62EA14A4CCDF3A4CB162 -:802D800041D61146F121116E511F36F163316E622B541F15B151A7E4CA7E81E129F922A23F1CACD72B574E622BEF2BDF4AF421723F34F442C25E521F15E119A8814A4513E226F491F11F1AAA732AE219487142F25353CEE223A822112F28F882E2299482E024E824BC62AAEE2BC829AC88AEE26E1A141B661B62111B151B771F35F75333E0 -:802E00002B662F24F343223B66EAAEFD1F11E927FDE2A23F3EFEC2E22F2BBB72B7F2AFE6EAEE36F6626327212F27A2271F1DAD8B6AE526F662622F24F4D2F22B9F3AF72121FEB13E713F36F65252CEC22BCC3F2CB663B6C2BCC2DE21B4A2A8AAEEE26EE22F26EE2EBEA2AEE6EEE18EC22B41A01240012E11E0128144A2411448A0410028CA -:802E80008022A1241228A024800242884218422220020029012A81A48240A248240048248E4128A02420045F6D0E1C0422004021512228228218A094122DA18A3442304280C8424641021B521280E22224453291204183523219C21240B2810428421188224E82602482208208B71980B41142B11162141B21272419F2421119F242931B31 -:802F0000212F3439912B94222F3429FA4293222D911B4A1CF921421CF8214216F1234296F1224296C1C29AC2C21B2D2D421B292CB99122B49136421B28271419F2428319F24282112F2428B24228B2422892822A84E822F4E58780B41186B411021A3642284A81B242B911A2B41B294A29F24291B22714A21CB1A384F921521CF921C21A00 -:802F8000B82164192E4216C1C39E212CBCD142B211C6D21B29881B6923A428271419F2428119A2A419B24228A284222B842229B82284E822E48F0D208804000000008002000000008004000000000080040000000021280000000014E06B0400108114011A22E1312821011220012142142A8921024262200222C022202222228321284852 -:8030000042014211C08288802C024282002028F4B963A014A68101322B8148002820AA41002C0618212C324122124A18032A418289B521218521C44146022816C142184A811422B8220C460221904180A4828691411CA2823E6820651E005E22118003199212226200282112C023CE122832123924A821282B184AB221B1411122C66122F2 -:803080001A22E1198494122B412442112B48822B82244A288284A4482AC8821344A1C29F13040018112029041892208921011A440223041C22018A042A040018202201C042200288408104822260240040010011800A8E8800002822112503292188A94820010050128242002014022200C22C04002440011428241002230424824240022D -:8031000088800880F4469E002222142412321848212962218286028AA3D298A04122424A2214314111B041888222A2812CA4848A81A18226823A1286A1244E813B8228E2420024288A8284024242F01DE20020C22124302212482988A385E02801824A8148218C86043041218042014A82062C04181041022333812133DC32A824824221BA -:8031800042242823880C824200E78C0028002813D1210129418208290880836A212001A04248904111A0482882248A018AC482122A88B28102800628A0248008002220028024F4B4C580250248502180417112023812A025304221268102821C8112229442C822424041A2424A212422042880021180262422044A08682024442284F26976 -:803200001F1001A05242804403111C02A08428220080044248482818923290321B521C0288283012528821188220C88282200A0000221042826824AF810322804201000042000020081A02A08180028A0414000042003188001480082024021400002120088282006F7105262102114234400233912118128A24612AA02114481282182473 -:803280002A28B413A412B05212A124242A7C2281A4211819089288806422E8148248C08280A228304220C4422E918005221A02203411144821280042602480228288E414A24242004828A0250020C58200302220021C280848008004488084288828F272BB8083A221C012281824242C6224244225420240426222402122149222212221D4 -:80330000282511E222E81812328221803162008A04001308860248290888482142A2485FB50900001904214A230480A281D88005408121212121021118E0120118005213A44122114200120040012123048A02000000F09DEE002081024001001814A01448000000280011001A041A280221192288A8411001114800C042202428A48422EC -:80338000822924040070D6030020011148122004420088222D41A0522B41141A34210048140000480000112400400142118280028820140200230AF0525E80011420D42184633446224192A12124822C244102260200207412120123848214238AD8220812299142A0422014C14100821502004800422240F14F83C06100421821102221A5 -:8034000088021239A8212301271218A041A04148406122828280A1121C01182C0411160229210100113413344228280080084820F2988C00186800000000188002224A223141804201C0118081044001208124232222C221200222228882806224000028A8C082887F1C02200200624A3222A0A423088E4120045012004828111D2280045E -:80348000A8B08124840248400140011C0428A0841062120021233C2288200480F494FB0080A41280010020220128002212002830428085E222084824225214601222342A0448A042113302A042008220E2248804281002C778B02104A03442230123C212E23AE82132122B448AB122312123A34236A26116218432433642A2C84A22D21224 -:8035000011A18923F89241DE621B12282D121976529141198C52113C54124A7482622C8A6E22C8290C2A0486A3846F5B0F38121A22031D431F269751808F7441E114BC81A8462C0218159112621943D121C44119E61132421994E11B254229B241E2244AC141121122192425044A042C84B8412C6226CA6A24424EC24A9822A0424F9F0DC8 -:80358000122AB221011E536A32125E222B4425D222B222E928E121D122A8452F2457312F25A1243921B63127467242B123E123B28261292E422B73223ED3112B922F217223E3153642282A83F223418AB281B881FA232390C2212934A28222286A8C0A2F9203111811001800120000200112100100000011000080092A091400B02201239B -:8036000002146032820024C022000080F23668501117142AB211C6413F32322237322B722F2C3CA23F39F9D3D2173429FB22222B662F23F352412F21B172A7666AE626F66362CE132F21E323B1D2E529FD33224E22DE624E422F31C8223F27E322F232521AE521F262423F1EEE1EAAA61BE64E436AFC4141288AF862E2EEE2EAAECC4AA623 -:8036800066AAAACC47F8145AF441411F12B311E635F53333373135F372722F2CFC82823F39F9F3B23F3CF492B22F22F372722F33F372732F25F5327229A4462F27F763622F24FD13132F23B9D2ED2DFF73322F34E225EF24FC32932F2AF633723F22F232323F31F532723F34F4E3E11F1EFC61E16ABE43B463F44141C82CF8E2E22BEE2B15 -:80370000EE4A24B4A2AAAAEEE2FF85031AF211711F1212E136F6333337373D132F26F7F2F22F2BF113133F3DFFC3932F28DD22F372723F27F753532F25B552B762E612C6133F36F642C33F31F172722F2FF792D33F33F252632F29F272623F39F873623F32F622233F33F142623F31B252F661632F16F6616119FCA1631BAC1F1444A28AB7 -:803780002BE26AA644CAAC642BEEEAACEEDF760B1F15A6113AB351E237F733333F35F413132F27F7E2E22F2EFCD3D33F3DFAD3932F2BF922322F27F772732F37F752522B673F16E632C7533F36F652423F31F1E2622F2EFEC2C33F37F652622F2BFBF2F23F3BFBF3723F23F323223F33F363611F17F771311F36F663411F16C6C23F2ABE69 -:80380000C3FE41412F24E42AFAE2E22B6E29A44442EAAACEEAFEBDB70000808164124822004814004810011200002811002800220040011480018024021440810482288200282024F82D2CC0411922122182542220249812282D928A6424220029219322C0112E4214260258922722168124D82234C1262201197242024613418162240051 -:80388000822724C08220248AAA424214571280B411021B21421B212394212B1419B24299212B94112B9413F2429113F2429113D212A9421CE922C4811F2264111F2264192E4296C1429AC2C21B292CBC9142B39122B49132421B282394212F3698212F1418F14282222F2428F242822229A842882E423F1F05481B61181B21421B212384B2 -:80390000724291212B941B282BB4112F1428D21228D2122BF2429129D412E922C5812E82122E42922E8296C1438AE222BC81C2C21B69241B29421B28230621282726824A12F14282222D82F042A222882B4A29E822F4DCD4008004000000008002000000100218000000000000480000000000280000000000AF8B032002224216214503A7 -:8039800086A221000030510048008A0220041810A28124201202142028222A04424001820000422088222424F6FB42145811005022190215822248611C824819268898C11B8313242681786291221904115A188102C88842404181CC114081388229248244C1422400C6C242822814F08DA380E4140222481721194211D3228801AA0448C2 -:803A0000221384B881A4841D422832123D22C213245121B081D1210268884213048681641840012C8884A2C214482400822C682A2A84E424F256BC80010024A01400282A18412108198409303180842828240200D800C0820040012AA82142E0240814004002806424480000AF5A030080220200A0212008B042010042824200002210019A -:803A800000482830110000182800800482421124602410020020F2248D144A2102111819018091816800230C8A81E419841131B1D28286A12800781981A986AA01A0822AA88234C0813C0C272A2C0814218058122CA48288202CAC8428B0B208001081C21100122E812888002182421448A034000022A02119210138001B1288101142915C -:803B000021218A1282042928348125714222160248800824AF8F0D1A8402281800001242002B484A21015A8831811CA81C8813A882001C0488AA848C028222A8001AA84824C08240010000822C08884A282482F283A6A0240048002002298124842884828288222E94112868808C311188208444014001003A84840824244602268302802A -:803B80000880C422402288F8EEEC14001A82A624182200A01820C18268200400001391A280011A2A0811142C2C22A22128422480818812212208822A08280082002C02E0F20D00800124004842100180C1122024012A0880042002804102005888212880024880044882304140020020082A045F56432106281A22C412200229A1494292CD -:803C00002C8881A1844AA24BB0A18102E288C01132824A9141808892711A22022C028A8144C242222B48152298C1A02800482C0200887FD90882800122200242481001484222210048004E312004280000214221C0822022210688281448A028000021800888224A0AEF350B90116014102102280000122002481308001302134281A2216F -:803C80001442D800228004A21A28442102248E22A0243041004221200C48AA04AFD507122022011200800828A8002711C023A08414146018825021146012209C82252105293811008A34911C962100822188118A04AA14120221008FFA078A0100001158A04200008014210C8028023200008282262102A042001C12212224044A0830420C -:803D000080C44188282304282A0428488A041480248804242890114A98118081024218E024018888002A1422250300141E621110E1212C22019A828802C811808A480288801C0221243FE90928802284C321180020860800222200220000221A4821220413042888181200132408400182000022682128422302001CF2D8EF140018304138 -:803D800000801621C841C82182001502864211813211181188133812112928C8811121882160211440011420822844210800400288005FC70120810424426800211C0119011820082A01184800D829B412944224405221142124208104423A08482024C422800221882400808288F8C61B202428110100005A0200200480091200200200D3 -:803E0000C0610000200800E81C0280222832228008002880088008884F6F0982224832A041142800242A052880C44128134CA184223981B44121A284001A24A12416212D92D219881432821442824248822122A024200400A2482129F4D4F2141A6519E014944114112A21F482114AF9219118181813A1448E5319A1991F14C1C113E81100 -:803E800031611F1126E511A48286E11EA4A816A2C2DA9182171116B162B911EA11B691E2149421CEC28ABC82021113F822422ABA8254228EA2298CE81282E81C08118A22A231423B356A324228621D421A223812246A021BA78AA844821982B28184043D633B3C1E51194222B48238D12F32A44523582186A246C24E1113E814A822226E0C -:803F00004180AC668A68242C22A4442223A6842726FEA38082A131111A82641128221B618AA2441BA4A086481F1208271617222928E212A1228EA3E60226F241224E521B911F2284D23283E22881A8BA1F11768291812AACA2AE42F042222CB862681C1C2894426A883822288A24A8482F6E0142222022581248211A142211A241211A1406 -:803F800022019A842209924282421901190819089800A012C081A092C0810040A24814482882248A04822880F27FC320A836181D611F36F6C342213E322F21F382822BCD2F2CFC72422F24B4927A13F1B2A33F1AFAF1E32B446E311B4415F191811F38BEE2F7227329E824B472E723BB72A7E44AE42FBFF2FF21B33F28F883422B111F1834 -:80400000B9812AA88827282F22F42242C81BC8CAEC24B482A8222B842B8829A2CCCAAC447FC646F141411A051F11A5E61F17EF25F512122B751F1EF8E1E13F3CFCC3E14AA4CC3F17F2B2A32F1AFEA1A32B4CEEA33F1656113F39FA83E16EE23F36F643623F36F673723F3BFB72716AEE2DE42ABDF2F7A1E32F2AFAB3D21B111F1CF841A135 -:804080001F1CEC1CFC4242212BA229B881F861E2272429B822FA42C227222B222BC4CAEC24FC8EAB147AA6512AF231111F17B751F541632B224AF641B1DED21F1EBF92AB54DED21F34F1A1F33F3AFF33F32F21BC52F963411F11E11EFD81633F32FA52732F15E435F472716EE32F1FA7A86E62BEF22F2DFD93D33F2BFAB3332F11FBF131B3 -:804100001F19BA81F8E12227282B4C2B628ABEC1EC3CFCE2E22F2EEC24B4C2E82CBA82BA22AA8A6EA2FF2844A15D1A011F15F131733F17A7441E122F25F763B1FEB21F1EFF92922B54DED21F34F1A1F33F38FDF3F32F2DB4D2F9E3C11F39F9E1F33F18E626F653733F25F4D3C33F29FD83C32F2FA7ABFE628EC22F2DF593933F3BF2D392A8 -:804180003BB31F1FFBD1C11F1CEC3EFCC2422B4C2BAA2B881BCC1F1EEC26BE62BAC2FCC2C22F26BE22AAE6AAEA26FA97FA0080012E13C01340023440834412818204114211102114221402184A021002001C082901226022822400828044022880222804BF6C0D14008081B62201228246B18104480014221C081C280A24A8C02122468122 -:8042000068182A2188A428481122114A38811081082210120110022C022148C041FF2C01581B21141B21421B21271419B24291212B9419B24219B14229F34291A22F1429DA12A94A1CE92AE414F8214216F1214296F121C296C1C29AC2C21B293CB49142B291E216B891B242B881F2428119F2428219F24281112F14A8422F242AB242285E -:8042800092822A84EA22F4E9E120A26126B11122B49152121912B211B26239912F24BB91C212A24623EB34218BBBA2D412E12A41E122E811A852122B82922DC31A82AC292BC21B492D121B214AB8119292282998212D82199222112F24A84224222522022B4229E822F4EFBD0082480000000000280000004410021800000000000000000A -:80430000000000800200000000B07E0B5424005222111361238C282481054428003061442884C2800418822826A842224C988123A32120B821A1280088800C0080016880022A812AF27A3D24129A0228471AA02822808113889819005D8219E1C823E811A2851986328100504121138441828484440593A2482C81816B24871B2426A84823 -:8043800024C0A2002824444081F48DEF3015CA1122E2418C32A11962211628C318EA911844221D841621C92115A668147A388182805141D0819621288E44172C3A745401141BA4221232423E894883A28610E2210A28404202224AF278131082026012001222824200110024D048A24838128B2400480082230258100280028E281892218B -:80440000822C082C080000808422422483089F25010080C21219468102200260880088800838A2004420642280288828850880021024A882008222821486880820812A0100824FF10F211681C2125B427012C4482E124A38813BA4271930149CA414888F41A2485324A428AE418E422C5641424B4B4E2156DA24046D223EC147341E812988 -:8044800089088713238488082328245C12468109E8D02212A8148B24F0F5242420218272728432128C26318219E82498818818871498881624082A883221462416E422A4184AA248006B282B184384A281824189212E08A028C813448808A0852210229568D0E90C1001183413541480228432231884448004898AE4542384888C18D21231 -:80450000046634818C91C62B41B0411271921102F0812200888221C0821C68149820C2822A410820F8B8F7001212190749011682D424842265483E448022C8121148612C82E124211C88C294801444B1820282002AB1ADA425924148A31814688444882822CA024932146024284CFA39149018200400182128129215A441228C0441448106 -:80458000322224CC84819221484A8891242114301A99218401488502002A3418602144800A800A28882CB21844E21C0D2C1414045A22024342018428800812320020284501450215428208A0412008000010648222008822200420210410624144421FC40A184C118482A512126722281E422E98001A0412B664611426B28422D71C843438 -:8046000062A115C254296924415288251821042A31848B2149712468228C1288E884034882284AAA2CC014604689C246BE31C042803111224420611444B011A6944338482200811A0480014C38214A023024408282290912D08162248280A48416140821820018C024222928E14421FAFD2F244A02A11428150824244826026C08001C52C0 -:80468000144225621446211864844E114631424678427441B4422888B8411287088E24835C185C84C44468C848811031842A9448884D8245688290246F510114952481818801C1441288424282461884312A124321CA28C0930018821B81002C81B22101E86B149012008CD24211082123024227A228A931244D284A22828408BFF90180F8 -:80470000224248281628C1423A64348C6A214C2422B28824B48862826800281964428954424827828C9412480029018A914820048384698C8D1216A252962838C8824212128D948021F5ACFC5021124829224474531411988484604212822480581200881446E86841886882202838882CC148C8442884A018A694222C0A440000522901E9 -:804780008248200250221F320BC612518140482214B1420184000029318231141D88A119D418840215088C34124508851208124E81864248129C1186D942322A27412342B81814E19102811285C4441A28816D585F82021A92241AA4211D2689022243C2222828828270286443436144524122328B4881AAE41288328822224814428A0229 -:80480000002044C8444004824C88084280446C15820021484FFE0A440041121184A11184A0142901A90D81830228884110220200803112112899092810042820812101412841004426042A382A484E8822F06A57144180C249416B14644604458194884241244246A418CCF241845CC19862A0284116180452228044022411212351424468 -:8048800012A02499B158C2129018882C0338D022218423042F5D0416A84148008021C12888196841A0254008422B8140082D8845D21441A282008282E098011184228A34E42AA1288288A0825048800A0000002398228B82AF5F0A3F72768495138F8143EC123654CD42CFC2B258A668814E8458216D4413D6187488F649E1EF98F2A82109 -:804900008F8484E9886A189B1322848F61B1248A59882E596A7265921486BA74D1C4BD8C62A32D328E246FA1F1442287834E988E5819FCA2B46394884B711AD262E783E518E822F461F430442B268F82D212F43922FFE1D121D5113241374A83B2F2BB863616ACE522728834436EE1A664421B44AE819B6A97525F2646734472C8B2246E84 -:80498000AD85A26A9345C24519D842F88A842364834F1CB82CB464F5A184BAC8F22B4119E81631182AF4343C66FAA4C88789421E424B24AFBF47A1111F81217121944442A5FC121C2D5249F9438B8CE421E14CB8E8D888F116FA4FEBFB17184FA1B141FD14881D3247E46F24D4C8E184D6CABE117DC298413F8DF452928E821F19BC92FA82 -:804A0000A26283C1628B2B1F74D849E74D781AB848D68A15922C87218FA97244F298284AF488842F64B164B888AA368E9C4FFE4D0100002400402249022412200882309120098210032908290922702201002A084D1190841004000024C02450282004F09A7F1447246F65F1141C9F93F39D17FF7B53CCDFF6F244141F37F63D218F2AAB4A -:804A8000D54F6DF884C4CF62F2286CF5BB39F1A697ED9C9F96F6ADCDDFBAFA838323F81E154F469E424F46F626646E72AF89F118383B91FEB41F58A222AA0A5B3BFE724F2DFBD2D27FB3DA8AF49A8A2BDE1F81F4D1614F46BE424EB458F132A4AAFF78E88DA86E644F924DF16563EFEBF71D2D8F81F15D15FF555ADFDFF6D357F1ED6C1FE4 -:804B0000DEBAF8EB4DFF8484CFC8FC3C348FE2F6BFEF3FD1F9AABAFF9CFD4348DFD2FCFFCFBFFEFC6BF85FC7F76C6C8F8DFD7CFC4F4EF6E8EBAFADF1DA788F99FDA4E55FDBF73EBC6F4AF6181C9FCEF4F87F2F6FFFDADEBF56FD18D4AF88F85A789F19F4891B6F4FFDD8D8CF8EBC5CF16E646FC7F7E2D88F81E165FEE67E344F21F51777FB -:804B80006F41F131311F1AF63B7157D41F16F24D3D1F74FD2BBD8FA5BFD2FFC4562BDDCF67F1F2FC5F73F3B3976F73F9FFBDBF97F7ADDDCFF8D97BF866866F55F17476EF4AF2E4426BBB8FB7F6FA3AAFA7FFB3F84F6FFFB7F58F81F1A4A62F42F2B53D8F87F7A4A22F2DFC87C18FE6F68A882BFD1B559F9DADF62BD44D4CCF8FFB26A6CF0A -:804C00008FFD6AE88D884DF44A4EF23577FF7BF317351F13F37979BF55F65F1FBF76F34F3FFFEFF7B3BBAFAFFBD6D26F6DFDDADAEF67F3EEEEFF7FFF5B9FAFEAFBDFDD9F9FFF25DFCFFEFEA3EDDFF7F67F7FEFE7F7F6FEEFE7FEF676AFAFFFE2388FAFFFB3FB7F7AF6BFB7AFA1F9F626AFCFFFD9C5CFF7FF6674EFEDFDDFDFAFAFFD8A8A9C -:804C8000AF85F5D9D99FBCFD66F6EFC4BDECFDECB8EFE6FEF6FCFEF88F8DDD44FFA6260030228440583448268144410840E68904135128401401110085048D24410000B0240129016981542490841608926081A048608144124C22A124F0BCEC4031111081E1411402E08864148028480430842324480188136844654811048844884A929B -:804D0000921B242A08888E24D081E2220888282D82282B841114439212803224A98804471A4FC1063CF4112485F21124A7241F41324A1D24AB141F48B24AB911B24A19B54A79A5F84A9143FA4291578A2D914F8AE414F9A44A1CF8254A16F1254A96F121CA96E5A2EC49E2A2F491243CF4912487221F49F24C821F49724EF18124EB941D8A -:804D800024AB9419F24A9251AF243924AB9443F242B64F82F442914F8284F9244AC7F3E0B2F41164CD421B21A7261F413262157C4AF2812487661B218DB259A684478A2D334F8AF44231478AAD212B4AAD254F2AC5214F828CFA2648F022C88D242DC38F4992C29E2C2D4A1F49C2C217C1CF24F8812443F41128EB84282D961D6CAF243BF2 -:804E0000854E324782AB9443F84216224E94678AA9F1A452BFE704848248000000004400000084000048180000002100401884040000000000A011000000008E39108452C12014342400866818AB42884491281B21B024B81876C1C43114444C24022D7811C02429081634812304212A884446784412881202C810084028088F446148891A -:804E800008DF930B2722922884CC48325868AB8645334840682892184634214224B04428811663445C02888B86888CD142A2426B166C021143116488C8892A741431482F1A0170C211E884A118386888583641F2177A24608D4D29B08444B61C2632489D847F8438222E8845C218326E1126E148C232741F4132117279A46811278313C894 -:804F0000282E861338224B25BB432E44211149CE444728B068384A4D2343E4122106390C12818AA1244D4A411648F2924B7024820284810048230AC04820C8814004428CA4848A044110C42448800C8C4104861402211240B84848041285228808818483248902989A840A6FA107100180C1242A41581C682A28814188081C6A8810111873 -:804F800001480016D52604488304B02408410028A02826E281044821908A1984419882484A2202412848BFE1064B24A0121882256324124812123B82244A41240130B498BAA4161F88342128212F8214B12DB4242122E98368252EC24A82CA3295B2942265882CA8A486A925214260141902891884E841221528F27FB1C06411208198243F -:805000002E42124588C1221818838508190A4B8219E98124C2884824E033642489C4242E48189E284B782F288426AA2199E24AA13484A31D32C82B24212D48008501424B42822818009FBE03002A011231294198412A84B92148024412308812A0821395411C8202A554414D21522008801204502220A882A086111880C8411C85328289D6 -:80508000082849C1448C22F6F76B50484883011A04282422951494180041A21219C428181A44428C49021AA283A9850316218DA2292F8A91128AD1812E81311447222A048052428E181E68981302422D44822E428E34A85F840A8015020089941140222862412F42A14131491A48A124E02128C1122A04807881024043628145410881486B -:80510000246024301416A2818344C44128A041200828EC08581FF7094A0140485848D04A222124118108109848418A01002024184431484443342468228200400446644A8A022006200800144301100200AFEE0758128C018C15A4428D15324681C128C0144391298B4987549B186858C0144E828E424416C158CE192A8582B52264884D08 -:8051800083127018448894844F28D6242261239828219CB51824A834162468442AF844A84B38888FED0C430821844058282821C42938112C094622C8248022019281800228264214462422B922A1212E8212881B284D121A82014386048C8428081200460221002E417F2C020020C24185D218028489CE881129524212250C101105178116 -:8052000044002D1E83820820951450848072282158410084188921AA21118152804396440084004E282FCB09800117443041245142C012200822002240CA448848888E411148A1C88121811A5412E81298A021884668431B248846084288848C22648CC0884324082E1412DF1B0E8280821134C428221256081018812848081A021741D0EA -:8052800041014420512200205142256241604422824B214C030011281E220010846122202223A242145F150544288014391219012524180270121218D81289149682C84B428A94442CA4421C88D485A448A4482E41488C84044820242CE444A88446344846A43428528B84304A4628548400F08661001614248111449218224440B84201BA -:8053000064004140146A43E0410884431604124A0912842100841840644118301C19044B81898402E2284C48088481C0F1A0422812284210C2224A81A21811E0441A410413B38931111911312315D28179A1D481B911348124E082441D41944281188382286188906C22407548014245022002109282482DC1200124442187194548041077 -:80538000880181882C314C840088882400008418430411862101B8888200A840088288CC0228A0218011621218226483F258CEA012824C41220149154804608115981143218121B124341880A4384004404114486422A01418823880684320449414C01418008C888812A4422012C449F0DC7A400C8C46918C2180C128004422CA120286C5 -:8054000014113842101292418921948410388485028712205A82A061424280C888101168C854284098188638112088311288EF1C032A61491AF221121F41D81358854B11C14C582895F2621A211B18448A911415D112F1474C9EE557451B4447741B4C2D6B7F91F45188DE469E5A6F21F578224B44EAA2154F183938824741EAF61848AED2 -:80548000C49AEC828EF5A9724B844A94C88BDA2E44A76E1CEC9296A82E284731E09A0949A21A641E4467844F45F52A2285F8627846A8111E11E015B814CA12EFC17818E362F314848E91C3C64147719DC845355C812D41854894288CD511D122BD82FC182882CBE22A66814B92CF15F148344E155F832AD5590226A824A781688146B43489 -:805500001164D2623ED5E04184B22CF144218D5385EA55F1222716F4A8728E88848F18F28D5625FE1E8813B461F25C889D4A169211AEB28A28F82A381F42A184C74849384A17866748A7A147C12AA242B81E11CAD944694C8445388D8344E9897518A82547C1CEB24D186F8E03862AB148FF8878AFAF0A100465C14845012410240848444C -:8055800084248A44144124480485140111441110040023022A088884002A08419214001200241028514890289F1A0C4AA61485FA15729FE5F14D1EBB641AA1158ABA8CD833F15B4E3F74F58AA88F88F8DAD885A8CE5F5CF88F89DFDFFE9D99CFC4542EEF2EE421F518D817985E5A4FC8FD145CCF6BF96C766F48A8CE9AA8888AED84EF8B33 -:80560000FB74544F4BF96CFC4F83F34161AAFAE8885E188BFD4763EF4CF8DE146F5FFF35344F43F13434BADD18F869D6B054A673CFE2F215768FA5F15E4F5E622B336B37DAF38C84B5F323447F71F53F1F8FA8F898989F92F2E8C5DFDCF88BC8FFCFFCB999DFF5FD888BFFB6FC7677AF917588FCC84ACFCDFD1C5DCFCBF97C7C6FE9B8F254 -:80568000AFEABAFAA8884F86EF87F37C5C4FCBF978F85FD3F379FD1F8AFAC9B95E588F8DFD84AEEFECFEDE3E9BEE4F43F33C346F43F3B8F88F87FD83F6E044C65487E15F61F35B4CDFE4B143E621F1525CCEE48D8E3D13BFB5F657D7FF91F99888AF8DFD1C185FBFFCD78DFF98F8FFFD5F19FDC4D4FD4B6F26FC53536F85F58541CF25FD22 -:80570000C4C6AF75F788FA6E726F83AFCE9AACABBABB78BFA8B3FCF7FCB48F85FD7D399F57FFE9218F8CFE5848DEC86E8A2FC4F8D6946FCFFFF4BC4FC2F2363CAEFC8F82FB9658F054644F43F33C2E7F75F35E5FFF75F553722F43F36E7C4F4DFF989EB5FB4F6BFFF9FD979F6FA8B852F57D7DCF5EFDDF8D7F55F4E5C55F5FF545D7CFFCD0 -:80578000FC6F4BEFB7F7464D5F5CF4CCC64F6DFD7876AFAFFF7A786BEFFAADA3BAF8B8888B7F8BFFCFCFFFF4FC8F8FFF75759F97FFE1789F9CAD45DEC86EEA2FC6FEF6F4CFCEFEF9F88F82F23C3CCFCAFF68D9B7FB0080012C810412204142482349012011180113080021812911881818044100A0828443028884001486080086C82416AB -:8058000048240880028D9B200841503415981E10A24818D02811D42A3884181508D04A094C61285451009601F02212E02221091A0280684149E841A2821741902120018021123234209118226F65082E521F41722CF21124C7141FC1766AD341F26A131F48B24AB981B24A19F54A96578AAF3439252F147BA4D852F924485CFB254A5CF868 -:80588000254A1E215FA264192FA26459ACE449E2A2F491246F22F49124CD831F49F248811F49326A1F48F24E911F41F24A9219F24A9153B14A3924AF2439242B94478329F924488B944FA2F41776F0244A1B4143E2C154141FC1722AD341F46C131788AF44F18124A9B385F24296478AAD138AE444F3A4482F5451862F54FBA41A4E844DB3 -:80590000825AEAA2645D2FA26814BCED4582F8D12C65F21144CDC21F4192881F49968A1D4469E941566A1AB642B395D42AB224D428B92494184B43A9B8A2B44AF1A41A1F5B0C00000000000080028008000028800100440000008480042200000000000084000014E04301402602678295942230184C81812401818148802252482AA5A4B7 -:805980004142604283245284AB242001520012182A91411221C82F81041C22045086424944481828B448918CEF9A05F0A211842D18242A95141F2249041324423A146042843088427651148092284C120280C6148B284686A42826E212018D84C014E0822831A42482196988C042A02138116A7134C821286F54072453C7222C017B123295 -:805A0000139A1849914522163816282281A0824247B34F12A5424B212AB484322242288F44B22211C116428B522413048741325601232ABD2C11C421B601244394424E341618C17249C251CBA16DBB00104A382C8C14261106184800814528048122428008814044087048E482280482221A822108441884248A442228648840088042184E -:805A8000E881942870FE05410000110081901880118428C181414C214251844A08812AC4240040C412004218448860241E244A082364812098981028110200448444F0C8E2E022815226842783A5522583028223B821018CD92C512426BA38388149618232494208904348848CBB2221A4254C2402222684484868422946A4242266018A08 -:805B000005808181C851481A2485B67F082E12226542C2329502210089292181D82408318D241C99349126EC461808221448C0124961211A044A02908482421E248A06290440C18812001212821B4144844422AFF905410081815041831228183221701864814CC1A8294904281800842CC46410688A2242224604124C2202854248A624AF -:805B8000418B5222CA22A148812C010080A4141A24F4EA661088448AE281562A3418218439D1A1014F82012088A4412840E28304235182278826A221449D1483212888C4416082481662428E4800241A444A0C2883222814684A44666281F0138400298501008C14883114001634A2521002001256028B1420A44820688440D241E2812270 -:805C000041A8521682C84400188A02A0141604A82021031236C116882E145F12080015441122822112994122001018480820441808800612001888801442821A82280180015628042282002D12812001134808B0A80810C2182CC2782CF218411A12F11148C019124CE9811458820040A814424824899442228AB244C18D167AA4021A7423 -:805C8000E2A1122E982928C5248B41188B2980C43200A012824068483634448C28F288D30012451341424842981A442F12012542088088A4142A84419838A44A02834122412801422E9840022051248008424829C14889092C48981A3A842183688318415F560945021042081504442228184098488141814C44A84142224A013044221879 -:805D000042442084018823054241810048008A01441982144C08402401F0625400001110C13A84108805482C0424199C11008413C3182C48021518F824489487388B848688284A41A4418E1C8890688122A24068948718908812828488180012E90B20226222A01222228C0122262201A0428B2122182828008C82820280848202120000E7 -:805D80001648428C02184004202101420018201442A2846FFE0B28480012101208118425289219120098198811124808194832182C0416C2189230C81218C04222821838488C018F14131892288C51A6002141001A04F6048284B04141311180814281C1125022C0120029226214184E2100814A224801420016A884481A02C80048006870 -:805E00002422230111244118004480015F8A054604414141CF2442344243512C11204164C12D841644DCE1014D18426381189441694864C12259014E186214842185128C7428042849C498444C0888421A88D22A48881898188C023EB900E08104843011002981842424A442158884847441487221082D49142110084424200228283444CF -:805E80002832104198284028514911008420010082F022A1006022224C110218800210184224042210420441262228482204648800E08401C0441281000056C412004418411225240481428984D492098CC1244C042842816CC4282341C1448002989B824826D82405412914951443B211086081428186210216682448E012214188D114F5 -:805F0000418842043884124280428C06218CF8EB8280A1484415D244714851962F87E1412112A1161E1229B41EF41A71CF4831514B422B5666F428684E461B783D812C9451891264C3AF6E4DA8818B43D81C1CD188E14648147848384885A58E13D122F917114B81526FC978429C82C084850C4A25F42CC440B428F22C223625F231348F10 -:805F80004313782CF8192C4E39872129764443B844E8173A2C19D338F216421711CB116E8947682F8272449C4429B7484218A27C8C1288B214034F81E697429C41184B73CD288D1A89528886DD98E324751CD224E18121B854F612482E88C89FDF0A495642122B2497A12C54214CD422D212B132944283D488E14661A83D488C7FDA7F1411 -:80600000D898B144E192522C224718A713278C87D55D1257118B8D85A89C1B2F1E122F247416F68A12CB983AA3231E2846E841B524668948991111A8128788AB2445081887218E183F3E045241B024014714844184454108400444402458681185145148214450481181718902400122151854811815287211988415A88284888488222C1E -:80608000289388228B8432818FD90E4AB524F2383A3D318FA1F63373AF95D2AE56AAB5AA644AE664744AB212F561832F86FC51122B143FD7F711595F92F629789D4D1D839FF6D633F433791F13F3313D9FB9F99818AAEE8AE21BA15D3E329FF3F383C11F4EF63D351F91F331111B355F56FA81A1273A33CA818F88FAAC284F8EF634B43B33 -:80610000DFDF48A22C2AA2D88BE8DB77A0327AF72C2A3D333F75F22362AD6BAD7AEFA3F12B2B6F44E624F752742F25F512363F3CFDD3DD1FA5F5725E3FB7B772F62B318F82F3F9F31F3AFA68EA3F32F27BF99F53F72977DFBBDF99B4F8FF78218F9BE7299452BF73F38781DFC6F634348B319F17F55D544B919EB4373AADA11F11F9D9F9CE -:80618000C7ECABC4EF43BBF2FD84248BE42B22BEF178AF2B065E444D448FE3D373711FFB77338FC7F22E7EAFE153EB1F76F662722B75EF25F55C1A7FB6F3FFF95F3FFFDFF1FFD7F714587FD2F7687DDFDCF5A7A2CFE4FC5F517F95B714F3313CAFFDFDE8E99AED8BFAB1B95E523F31F53A3C1F4AFAE8CDCF43E385B731E115F7E4744EE4E0 -:806200007EC33B754F4CC58AED8EEFE4F5BC162F84DE987864F8C2982E388F88FDAE61E047F63474CFE2F21737EFE1F177361E7EED7E6FE3F32F3FAFC1F7487A6B556F65F556567F7EFFFFFDDFF7F7777F5FF7F65549DFD2D3D9F3EDFF7F3AFA6C6EFF13F35F7DCFC5F7797EEFF9ED9AFED8D89F8FFAB1F92E623F33F33A36FFEBFAEEED2E -:806280004F43F369699F87E717B6A4F3F17B3F36FE42415F5CF5F9598FA4B96AF7BE142F9DD7CCF86C488F8FEF95D588FC18A600A01210023440224162812448241B4180044800100100218B240022812200C0113026400100200100484412000000EFAB05822012413311A1405281805428008481122C48A81426088450224028141518E0 -:8063000022A142C092502A4C0216180818CC1208A1604416D82262821084228221F22E92C0421F41722AF2112483F49124A7141D2CAB141D2CAF14D981B24A19F54A9143F24A9143FA4A934782AF14F924488D914FA2C4816FA27418F1244A87197FA27498D5A2E44DC24A1F49D224F49124C5F2912C83F4912CAB141FC9B24ED1C1B24A57 -:80638000D981B24A5985AB944782AF2439342B94478329F93448984FA2F4FA48F024481B6167221EC84F12D1817226F111286B161D282F56D9C1B24AAB21AF5428FA4AB713FA4A3613D24A3B33AD94AAF148B53F22DC48BA217188B427F588242D939E25ACE8C952B413DD2664C94E911FC8B622E1C9521616F86217CCE614F314482F141C -:806400007324F84A124B41A7444B41A33436A3D424F5F79C008004000024004400000000000000000000000080040000002001280000000014F0339130142514044661422210048C85C4181844002444844413444442141445012826448264424216815812901A0024E08481C528192425210484E9F21228CB2541C044BBE71420E8A24186 -:80648000415882D12C41C82110081062924A218269226280C2491D282212222741811849243148444ABA12D284311828295182308445322860210028001A48061AC411F08DA614444364A21415D848422151C21C325483B4282111362158222959282446019B4137824B28441163116843158295688364337A781289F5281212254862483C -:80650000857444C8283E41422004818F2158A42E1E181C2175FF062C0149014602C30200810000840044224E24C02440041621022290441044840C41842100001AB4220124121822002D2432424904418BFE8081022002241D448110889288844088016C1284028184001A12D14812012011044100840081C42112188221000020242934A9 -:80658000844A82F49CC62441642284D11624420AA32266111C51424A8142346488144964122826344484004881C562644344D2140151163422C042113B41B0240C4628A4811CA1B484988C08AD1410044BCD10868242C82900178481B02844E19118AA148118222225E142C42181C1460422148C44586880012711108111022C443848A057 -:80660000871288481A28A18284888288C18842F0565C805124004449612245423228200341801294448644042082028418302411C0442D44444441444183021071121542048C1402114A011846283152412684F46E86201444988A1828001412C844C8122419082116C814282CE44164121A06CE182191804194212140B822083C0C2C06BA -:806680004182244AA2248748811A02808403922480F5C3F47028B1220480180623721698485048E02288218234418240C81211AC28018200529490451813618810A44110384880954881857112D416C42425424808608285A228F01D922001A08282B48481002828A5C144810010210240280428C016100C52000024182081080049218111 -:8067000001C048890800100444F0DFEDB031144658821265092C6291124A4232486C4138A346621486C1142688D158F4488228404816B1144429E1421412012D824C1121D1288A04124D528382338267144B418358824628022E84848684F4E85F2088022880522A84418C84C8281CA848180090182280843121422252291148289144802F -:806780002181880292214881444A48A8141D4889415828008001890128B0850E002180028400100444488100200120044891888034234200D0429442C01140190600425180544110648888508400428443B57F4E111741140100D084210880A22818802128322C1B188282132828440C122244266111113024400A10450420810D21842A8D -:806800005122452231124282121E84F083682482224140841244110412004044488842840428281244800500324240941848001820914213045825284804218001894C2201006FD50484442321154A24C11490118119810180011011123284182312189D81B648820845C2411215C4A33034468A081E2890242012B188718C318890214CB8 -:806880000940042884AEFBB02424044413018444604840088228004D48002002490412418042040014460284202282120800208601A08118004608424814CF1A0580028096283048201489044C123845312222852402611382023021A0424042440244484810082144881032120061452818187482A4411086F4A976004148213014001017 -:80690000818128018088414128988E15A484881C58481C08234418448811982180110115041348381130819081303100488A8181388283788AF44AFF14308889C1118D848818810014882210844808242828841068424602868424084180044883220226126412E02264481FA2244102408244C64212004282AFF1078C9112400281442054 -:8069800001400428004058584254397443041813810D242082E414084048D41C7C4244810183529422186C18B8816288188480622868451802BF854981671D4146F6F4248241D4121F48D8D90132C826681425187418E424F482222E41472351937849F211458693134E242AF22448003447422B154CD882F684263C328A447447292FB161 -:806A0000FCC2321D828576A2548C8243656927AD25024D858AF823FB503247EA1E121E1115783CB418115C8446014E8128434814088426FA22A44B815FC842E41CE1125AD4CB14CB244E624840E74DF1454A5F84A36C8D2197828724371247411F92C6295B6646B521A28185C8884F21E82198886C989449A4B85AF4A8428D1CEBB52445A9 -:806A800084524A11A18C42AC144C8121B188C114301C4B988F11F1E8215D21C57821AD84CEC12EE845ACD1A083222F8AD8442194422751291441FC14235C1188311483B48881B3C8C1416F597181D189A3182F679118AF8486B954D48468854F24F4CDDA2084016186A8148442124F1428A184124E84844A28E14408642004441088012148 -:806B0000004A92148A1234814B1217886332812A7181281221321126628160812003328526422403EBC3341F28D16451E81F11F551514F48F34C444F44E44131811B5D4AA49DC2CF8CF644463F197981F1E541AEC2225F5CBC81F869C95F18F8C5437F11F524C6828F887824F46C4A2F23F188CA2BAA1F14F215951D883F68782EFF9597FB -:806B80007F887825F4989B3F1BB9D3BD93F992936F28F88D81AF6BFBD6D46D266F84F6E6A42BCACF8AAEEACF62D8FA4CD343E16652A81F31E54EC624CFC454444AE41CF44CCC8AA88EC28F86FC8D8F2BCC1F1EF6A1412BAE2B88FF9EFEA5E19F9AFDA1A8DFF4DC13F424462EE2CFC67624F4684B2722CFACFCA7EB2B8C5CFC288B5F78F8CA -:806C0000898A346F94F4CDC59FE5F5D2D52F7FF9D3939FE9FB8E86DF58FAB2B6EFCFFF46666D24AAB2A2F9CECC8EC8CFEE7D7245F341533E7687E17F51F111115EF48F45544C1E145F44FC595C8F88A8B14DC4CF84F48C8EBF11F945C55F16FCA2C23F1EFCE7E11B88DFCAF9CDC1DF34FC171957F2371CEFCCF864448FF4F6D6D6EFE25643 -:806C8000F76F4CFE34758E2D8F62F2ADAE6F71F34E694F46F6D9FA2F3BFB5AFD3BFF2F39F38F8FFF79F99A966F6FFF86866FC6F4EE8C2BE8ED584BD84F62F978EF341F5EE761F5181E7F75F13B355E74CFC1F15C5C1E145F51F9191C8F85A5394DC4C5F85D5FAB19DF52BA24FCE6A83F1CFCEDE95F1CF4EDCD5F9EFE4D4B3F85F5745E2E23 -:806D0000E2CFC6F66444CFE4F6D6D6EFE3F786C63F56E643F3BD3EDF6AFA282F2F23F3FFF8DF4EFE787F6F6FFF7BA83F1FFB9D8AEF68F8BF1F2FEBFBDE4E6F6CFCE6DECFEEBD82FB4C5C4FC2F7ECCE6FAB03230221808114C4488004488004190448904130814411100100410042214221008424108444820482249264400620088281F0DB -:806D80002618001E2410110C1816041301160810280184708418A2424282144D48422C61142004901420022E122843022B128422122128A901A19242802119228841F34485C0421F4152381F4132681FC1324A1FC1F24A111FC1F24A911B21AF143915AB944783AF1439342F347B34F842B54F83C4914FA2D418FA244A16F1245A9E212FAE -:806E0000A2E55DC25A9E244D5A1F49C2531F49D23AF1912CAF14F19124AF14F1812CAF14F19124AF34B911F24A915781AB944783AB9443F3429247822B944F83A4944FA2F4169940DA41561C1FC13668153C4A1D2CEF14D1C1F24A1528AF149325276426F84811512F6442C8A163D21AD8A4D558FA24D816D122DC18D2A2F48825B48F1968 -:806E8000D2A4F4812C3CB491543A1F88744A71917C4A7191FC4A1117812F74B111F448B14781AF147B34B84229F34A122E484A39322B944FA2714901208804000000008002000000000080480100400100001800000000800200000000F0FB32002841248744E094C242412E1883820387148128A02C4140142816C4444C229444424A4A65 -:806F0000853414222C642120028944A582A0872C31C81483088A219484430929018281874C6F48092753137832884A4294141E2826231411581A881694184F21028B2429A42428862CC428211C332128618B61274146D88281422598128424484181F42E482041024664812C914887458C28C4484E15F08E962430E144A8464CE415E22264 -:806F800045E48451842C11D881882303624D4A482483A2C212C3644A19B44422A22C4D43428361918364214A880383148512F888248D32C94CB12808C2A0184D182C4148B24898185AB8DD0A4F1201AB125022104C68322826C12814488544C8368228E0440285944428211A122114B61892144634222865012184244849084E1348204157 -:80700000024CE18144A64887449242604445F8AE7C00000020024228189018000080418802809428A0211852480040022400402141018304220000802802410042F0A898200122382843021662411088018081311C2142202117880248C063D028022481899424728AC182186888284826022B418081840C524082A241418A21F21FA100A6 -:807080008082824224622112001800800100842268844280842281D4280610D82844A4248200288228904825820118480098401284158425F234549018001280029044228D1430182212D068015880311280E28102124E2312002440C128182B148223C14112144822C06400A06820240222102208BF7E0F212A0140044112222A618212CF -:807100001E421E881818701209811168CC4288442184C22883A642852494224F24011A028138A024401118220414C0288C06102C048442AFCA0918008440440221232411518241100360882692288812422822000084902800008D218210110422422220416CA42001248022A1244197FC144501442800001400000026481C1404400444B3 -:807180000089022001100231B611524228252C0114841001841880110220084800BF230B65A121448441444562212C8266831458AB81164258A44D1983382815E84492148D4422148B2490282AB42854842722D0342533226561AA166C1144149187242242836181837412B83804C0884858626CF4A9CE800180020040210112A14130315C -:8072000000449022828902422220028C01304826021C28312820026220021400512012022441281008BF260F260120810100180040010014800128122822001248003024004424001180024001100148421018040048A0425FFC041228213C02382587312489013012401482222222113844002262264C2162422248833412001C31142494 -:8072800049914412190211850283141288140424369848414C069F150C1810823212001841180020420414A012106841222023922848222022263412004243010012141411008D42A0244844443018202424F6E431D089B2480213012E12150638844554447B232826022228806122272425A2131AA148164401430215559111855CA88FE7 -:8073000015A4441469B144022200455C474B222A1608810029724852622D261AF1C815240000000000168101110000800242800444221004230100000080020040010010080020022242F0759910C848422C044302802141144424820200120025825242386A29880800461141411868824848100422004441441C82420284005022D042C3 -:80738000716708A4800440010000442A810224180000108292148028028100264102AC22A44410220280041C4424A222000000484221485F720B80060000181041042A0280010000218001881100282814008C02480000000044902800000000218071380526022228000040210120110140040000420042000000002121220022000040D2 -:807400004118180140040000F026BF90228324240400005044C5B424022220011240D222642243019282824C86825111151153A887818344220400001145544443826482000060242542B614F196DF404888C44280022200107114E411B2210300008052242981A11288A8008026D2110250884CC4410000110050442868008412004012F6 -:80748000F287A8001014020018141214002100000000404104844400280024280022282110280200842494140000002084F4A7CB2001280000800180010000008004422240040000000000000000001400001008008004F099B9242821260460122021414111082581412201180022484F5202437241082E4489A2114A02A0222311420461 -:807500008002224811481184A71484105884004200445FB4092723222C022128001112181B111A11410100808204414A84A224B024028082840225622280823222228100501181508100001880044849F4AB1800002C0241808391111301A0111112184112004AA422504444281024322260222C02206222150241801241011008971424D5 -:80758000100828A0644324F4B4B4F0362225C2122B111221C0122592832F31F119111B98179987818F18F44848D09154111C548985F844688F44D444B444F22424224C02284554642E246F23D222E222B132A1812B88C0922592832F31F111119B98179987848B488F84244408488558884F84F423B4F0262265A2321A21210118259282DC -:80760000BCF1111319E989588889242444511148155889488F44D44CB444A226220028444584F326226D222AA1111A282988512229C8131F3191C19E888598484A24240448848588F67E1A000000848100000000000000000000000000000000000000000000000000009F820F0000401808000000000000000000000000000000000000F8 -:8076800000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F00004018080000000000000000000000003E -:8077000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F0000401808000000000000BD -:8077800000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F00004018083D -:8078000000000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F822B -:807880000F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F80000008481000000000000000000000000000000000000000000005D -:80790000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000BB -:80798000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F80000008481000000000000000000003B -:807A0000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000BA -:807A8000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F80000003F -:807B0000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000CA -:807B8000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F00004018080000000000000000000000000000000000000039 -:807C0000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000B8 -:807C8000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F00004018080000000000000038 -:807D0000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800B7 -:807D8000000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F97 -:807E0000000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F800000084810000000000000000000000000000000000000000000000E6 -:807E80000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F80000008481000000000000000000000000000000000036 -:807F00000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F800000084810000000000000000000000B5 -:807F80000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F80000008481000000000035 -:808000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F80000008435 -:808080008100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F0D9 -:8081000029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F00004018080000000000000000000000000000000000000000A3 -:808180000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F0000401808000000000000000000000000000033 -:808200000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F00004018080000000000000000B2 -:808280000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F0000401808000032 -:808300000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F0011 -:80838000000081848400000000000000000000000000000000000000000000000000BF46070000008100000000000000000000000000000000000000000000000000003F5A07000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000051 -:8084000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F80000008481000000000000000000000000000000000000B0 -:8084800000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F80000005088848400000000000000000000000000000000000000000000000000EF9805000040180800000000000000000000000000000000000000000000000000F029F800000084810000000000000000000000F9 -:808500000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000000854808000000000000000000000000000000000000000000000000005F530700004018080000000037 -:80858000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F800000010480800000000000000000000000000000000000000000000000000DE5800000050DE -:80860000884008000000000000000000000000000000000000000000000000F0FD74000000848100000000000000000000000000000000000000000000000000009F820F000040180800000000000000000000000000000000000000000000000000F029F8000000848100000000000000000000000000000000000000000000000000001E -:808680009F820F000040180800000000000000000000000000000000000000000000000000F029F800000084001008000000000000000000000000000000000000000000000000AF8A08000040180800000000000000000000000000000000000000000000000000F029F80000008481000000000000000000000000000000000000000086 -:808700000000000000009F824F0184001445C8184538242200005440442461218B2412100213820218B18B245951488144204441C94384438204200240642484409628282C0210F641A9902114154859C2C0262602174161284D38417026C2221B212D2E1362318189E124117452D221611125C91413E18422D4213649195481814845C879 -:80878000448D4247826F2492645132D912D81472249224A342662484818344F8FB4310014008C032261C92114410048002188391112E4840A2142446D1221101112822411B420089048064446CD224C226408131288016081008216024842FDB09280024448100442C02C01810114246012125C118844024322190184C2165448485C244AB -:8088000000141014020020224211181502AD22904226184818B4990300840041450800002241402202282212200100001421141901404801848C14111808486604404404302280022400F0A7121450181411150800284120021014046C120424002480011602848181481081440111848094480041000049424414840200F087BB00002094 -:808880000200008400000000000000000000200800800100140000000000001800001F180700443524022280E14182421801211A741398A5282825488C81820221B0428202A041813A840110C8114D121049518523342813642440020098491104F05F34B0149215188C12F4542924841052221800A4459824301247944C25142118A22432 -:808900004A518243013B254C31281E421144512AC11348298204AE4829484B01434892A4584B2426D8489242281E48287FFF09411D14188752281F440140323428161801A14994181F22A8126C02C344C12222222B41842367223611A412A43A0415A42187213C654248818DC2D4A523324188212D2423C46490BC29848281B2740B2A0147 -:808980004502418C622284185022004062812D2541D081F4481480210848104204421883841591140011201112611282421508490482189028C0144183049F8F0A00902100230223022240A34129810416088002448C942800230200482820A1122800242841B04208818224488140068D24002084F495AC9026282F1182712A22D281E477 -:808A00008225018CD18204844643785439824B25444791836C83502183A212483829D2A242EC8411C62523B48191163645C819842951843AA84832488CA8844AC8489E28245AF284488385A2821F3C0749829221135282213D284638328082041819041781122E444413022A21042032221A028D22488B416114529A12521470181124D1EF -:808A800042A418200184C248E4B281214B481248C83FC349023012122822421A0260A1811127842D1283D424948812901C4E88851468B28C2281042722504828604329426141388582121832882883AC2842231C28881438246A11C84828222FFC47D281D24205A02149D2A211D442424268C481830211469824885021181A025682184289 -:808B000088382429447422042227814A018A0113CA821210220200388812288319383689A812211FCF0416C841009011C02124114308122A2821420400410021128C08282C2101221384C844608436081244108838285301C048285042004124008CE2B904007024D11C148804141816012145C24882212503360885048924229248100304 -:808B80001812D0828201100141D08402214088218448B644215424200146C444484E3224126160124D4845D1A2742154341D1298106A481A34A18D441D22C02814443884422D288344EA113836214722228A32442981B111A281415B828E2EAC8198229C82210416F244924944B688D168C114CCC41446F8A94460121301442E111E281844 -:808C0000302250188C8441180A2512842841648180844202220052184654821A0210081800008418008E48448021028022A8242217D600C0212D428C1408004601284800C08800E0820100A889420412CC944420346C4B5844417062084B123024124322028C110285044A480442400C1FD30D902100111C044118601882819902682227EC -:808C80008849318242151814724218044180A881220000812E888841D01608220026021082811104481212002F4E04409423223183D282C42284901121106E818091266388024932148C420100651A0484CC1104412E5240428E188411042812104A885148000046C814F02219C042C018119042113024CA024229A1242191304830C8A327 -:808D000012918210081282190860494800AC04281A041C148808249698C880A8144AA824884A21014B814AC2483EE2104441C628004904400491846042E01204222220C2212E12430227C28410981C1082C4252A840290289021442C12110288182B86812325B14241A814488C08CF270DA4221001418CA21490282384214891816E1280B6 -:808D800012C818130800188D1412004200208161218816180A006081430824001240084148844420F1ACD380028149E4410421200181A2408404490186024186C8C8C188211CE841240414E04801426011448888194AC821A021160240450C824810440418F0C8BB004444848514611241C41150281B4224831204645024002810A421000D -:808E0000254442480C84005042004522024140223218124352423016004508005F94024E3C9042002144226882824C2481541484C4489B24481644548280012A08AC08824009404884D414D22208A0C182C88296058B682048048A2291228229C448DFDD056E1655343A2D28AFA1F4694227524E223A23044AD8187C41588D6E612F6E72F8 -:808E8000E8A8876E884A7829E588782898AB442E3147898D488C74147CAC46984859847684544A9BB44F887884C5814CC1144722ACD82268819BC14F24E4C1E824B9D4684446D88294D48F4468857E15002F12D2E1F2214515444108F021659B8C26EA8441E2130A4D1945F28C262972168CD254847244383440B485B94EF848811249041F -:808F00004A682419C1228421293A27492A92F1281B258869313AC3D44CC4444B514B118B2483A543F019A8906424457148724451C2DB644F42714CBC887812B18B3732ED452744CD1883D1425692CF28F528314D888B236721A6D6A87314CC422546A618848F4D7174EC417314F4326A4F83F8A2468D261F26D1C8B2B1B41C7A82B4B2B165 -:808F8000A8D12A61A8CCAB18278318298AF4141486D48491483FB305122011441844081A14C4486089C048441F810448441A149841448A1488058880A82418422A011800200442124220240882200AA2200AA2811F540D5AB412F11818CB228F85754DD98AF248488F81F1C98A2F28FC2322BFF7F5CBCA21AE82EF8BFD8CA85DC92B8A7FFA -:809000003DB96412E44CFCC88887A435F14CCA2F88E8ACFC93D12E42AFCFFD48481F1DADCC1F1D79A87AA1F548481F5AFA8BC95F1BF7D8F817546AF671738F8DD1D9F5C8624F2FF71A182F61FB1A38BEB6AFABF93C784F8BE383F21A12F054625F6256B93F33579A97B4FD288F82D28CF2A9AA7FE8B823FA49CFFFFCFC22251F38FC8A8ADA -:80908000EF8AF823892672C3F167288F8CFCEAF88FACF8EEAAFD29CFA5ED8CFCC4CEFFD9FDADCBAFCA68D41FDCEC6CFCA3EFE7285778CFA6F6E5E7BFDAFEB175CFEDFE7335CFE2F22B3BAFC5D3FDD4AEF2747EAFC3F31636AF85F7F4F6EF2BF91A448F81F57278FF52036E527F7254A87D249FA7F3676DAF94F464648F87F5ED8FAF7CFCC7 -:809100006BA2BFBDFFC78E31DF36F65F59CFEEFAE3C1CF8CF8B5F17F5AF8C1C14FEAF92A688FA2F87755C5FE828CECF8C3858F3CFADEFCCFC4F6757D4F66F297D58FAA72A3F52A2CBFDEF68BACDFDDFBD8B85F72FEAAACBFB3FBDABABFF1FCCACA4FADFD7EB8AFE5FCFE987E56AB65EB914F8DF9E898DFBC0B4E725F62F23D3F5F75F36CB2 -:809180002DDFF6F64F4D4F47F75C7C5F66FECBCEBFA7FFDFDBFFCCBC61F4347E7FF7F7EECCBFBEFC7E7E7F5BF7A4859F3AFAECCEEFE2F626AEFFD5F79C1E8E82AD8AFFDDF9DCB3EFC9FB19385F57E723F3BDB7CF2951FD8FC6F6AB2DBFD8FAD9BD8FADFBA7E7AFE8FADBDBEF8DF98FC5EFAEFCE4FAEF8DFDDEDEEF8FF97456EF84F6DEDCDF -:80920000CFABFFE8D88FB60C417022415832484184404801248C44454842480628C0248002287048141618141804430221844F22084150241220416281241E484440243148124482EF1E0F220084406812844A812224110A42A034224284892118489288604120081288128C2484214182020080A1212C889288860812881A94881E48603D -:80928000818B8486F16921C0421F4152281F4132481FC1724AF2112CAB141F41B26AB911B24A7915B84A7934F84A9147832F147934D81AF934481CF9A54A8D814FA264115FA265192EDA96C5CADE24ACF591242CF591248D121F49B248F19124AB141F49B24AD141B24A9921AB9451AB9443B24A39242B9447822D914F8294984FA2F4991A -:8093000015E0A2F41164C5F211644376117C22D2C1F22E121D24AF4258C12F14D385522257824C732598225782AD14778229F8251A85F4259A83F1278AF02148442D4B1E252D4A16CC4B1E64C5A36814C4A561C9A5C12C2D15CCD21A03AF743324AF247124F8421226C8946F82B44AF124525FFF0500492408000000002800200800008041 -:809380000484000000000000002002004480020000001022F4CCA31460428144400149624219220281830425486C82C91208874A9904C0248C142C42A2418F240121521243522485C48828001621028181442184844D4840D84864814628F222E57024424204C189628184844288110025A82430842361424F120970644842C21425C2C148 -:8094000084262C4AC48444222002224136C81488F08228189293281824012F881224B98466188974FF45016B248441849C4228C22C28490281C02821456882C183C2234F827848B13804276A8D4224A6416AC51F284146D44824B144421442684281601130AC83618ACC2818247148224878D4B234E888E485F226BD302410064180410C74 -:80948000198418018C14E28204439832414C0910046041452804282E488028210222C42A082A6141882821801111421818942841818C04F0B1178001418C52241638428C1604204801004400104888210A254881042A64440000002120420890881281114200602412284F8B04228921F2E653204601218302533A14896381232122114881 -:80950000341C8C91A836B68CF182444CC42446B825A4244F85322887644D18282D44C1421CB546E118120517C162DE222C4523B691727288984C83B422919443944450485842428F3A0C2A4401A14592181183D448C218A082191108439118895A2483388A842E14425125D8184458482D2426C244813011441414609326289E1282294111 -:80958000D183A148814238182985D648091A9218425F9D021810846282246E841E241224120010144804324C61444604A688A6422E142A24E481C4441084C4424A612A4140842461241528B6A8A142304481214B8441442A54484248226EB4344D184944140945522462214658942829860423A249241781C0214241CF24818A084049D866 -:809600008201842532512661841132A3328B424542D126611882A3914869024002150A248904BFC50E8C82150200141200418012181854824F1562422484890820918AC0688084C44921960884429811425082184AE284CA28160459A82440B81442354240C81423F44397001008419B42008B212504160821188904008302100140742CFC -:809680000292800888201222411C0428C0211608904900D022344410418102308CEFB5094C821152184122E021C22825088C21344A10FA82484E147782850284444C245A4A47228C16C942894942D828914126015D981B1221882D4819F122412F26C1888531124DC1630446284374422A1288918C1758B08241140CD0C1543648184C54D9 -:8097000018282190184B4218138221D218B2825412A40081204928C4488229A8212112407468D281024C9218866C129A1448488254424121007048C442AF45032084022002141181242218448608604840C428434AC284824827914110024282621220041284832842E2881648088460950000180080F4342300150422260450842083C8F7 -:809780001111902282830B212B8224142D282881458106A13CB4412802107832128112210B100A1348112B32892289028241005240F82FB73081004160484548A82447A822188800290228408202002121800126012100100225D2848804A1880014460290221218421884004A41F2BE2F402882240448421008182C18A428501423422194 -:809800007888819148271A9C84712188D41824480820440A19044840011304130843041304008336344290128440E4AB0124100813022400180000134208212450284846232224721851424314621628182F840268198812A1288C841284D2838411011111A9042D28CC14820484145FB646419C21152442040013048C18494804105484C4 -:8098800036889145844781431C0441848C38A884C088200970882411C8862489951A002142810081414018F2284422F0ECFD00C042800884148D16C0124091218388288868188922681888811568A400188089082441001486244401114241212E8200803812202149882108BE4CC02147881014082314D26242042622012147821421C0FE -:8099000012100400124482410086420A4882411C2804800400808441024100C044121038185F970845084D411C1491844144201C6248828972114211CE21A354144C012D44342ED425C4823C31418A64228CD4140414150C4C4418A1149388183142814485E1443258290527A4812181307242DF5C0E15F4814C87624AC22443784846D581 -:8099800029D468A4113B834F18D984E882AA829E8189A89C8E88C9D38B38AC446D2815F64D428D18476513AA8E26887842E22111E418E442F896598F145481211B88A961D825D132D411D1141493285088218CB91A041E21841ECE50144358142A34A9442D486127D26B8B2CE2180315B281F1842BCF42E23A32284F51D1E2F4C4654E67CA -:809A00006F9AF2C84665C92D4F1588EC14C6492F2CF648428C76C3B4611BB18992818CF348C41B664E181F82B24BC4461D886897887A7742E883B562D28C341EB07CC1886CD4314F61222E2111555414624195B844C318AB8885321B44A5534B255A4725FB2B223E81D081F949C21CB868B7125163A798AD883F218268C98342D812546263 -:809A80004551481B8A96D2B8586ACEC3D089A124A7842485BB145D2A4F48E565C1428CC1488B5683D58D05302450141044480240088414841001114413480446146144401421044229A82414288828804681C2811AC682288880A8412C28C18213918890A812F08644E02AF226288D2A6D6187E82B4C8FA4F449495E34DAB796A999AF4B9B -:809B00005974EFC9FB28289FA2F886865F49E9C6F43B188FD4A4998FCFFE81884E68CF81D5E8FC11522E431E528F82F41436224F5AF9D4744B2687C28F42B558F73CBFAF8AF8A68D8F84F6AC2E8F8B5328AFCDFD9C1EAF8DF374368F8FFBF83ADE12EFD5F19298CF4BAB511CF41CE7F024267F42D2EDD246F64C6E6DA48F84F449485E345D -:809B80008B64AFC2B3A2FB8BA44F68F89EBEA7A22B8A45F4B434CFCEF68E1CEF56F4349D6FEEFB8E8EFFFCFB155DCFA1FC14D28FAAFA1A5ABF92F87C5C8796EFC8FBD6767F2276ABFC893C9F89FF3CBEAF8EFCCEEC2F81F7AD2CDFCFB7C9FCDBF85FE9F19B18CF4FBBF8FBFC3CCF6DF1DE9EAFADFDDEDC3AF342529F320D2E267D6495FFDC -:809C0000272587EA6F46F4484AB5B853F5D4D49E963E31AF39533BEFC1F128893F32F8A2A1DFFBFB664FFF9BD9CEB294FB645757124FD6FE3E1AAD1D9FB9F5284B2F33F72A496F69DB8AF685CF7F6BD526F68AA98F41F1785BFFF9FBCBE8DFD8F86948DDAEBFD5F1EBA8BFB5F34686AF95F1D48EAF81F138BA2FB7F79F8EAF81F17E7CBAE9 -:809C8000AD54AF5842F1A5277D24D5FE6725DFF6F626248FA454E37F47F7E4F6AFAAFB3BB9FF39F88B83FFFBF9A6893F1AE81AFAB5B5EFDEFEDFFDDFD6F6BDFFCFF6F4AD47EFF7FE7E5FEFFDF597DF1FBEFE3BFBAFB6FCF6DE3F84F687CF7F6B7527F38FAD9FD9F9F9DBFFFFF9CBEAFFF9F1FB5AFFE6F85B1CBF86F2DB9A7F74F85B5BEF44 -:809D0000E7F3FAFAEFE6FE7E7AEFE1F1D2D8EF47E52BEAB4F43F58100414000084148A2422412348424846C82490281358488210131812181308800849012541C811C08284002484141648410816482221241108DF7E08224440444204C4C522412208504A0040668144604440D484041844482829048C0C290841808114220848145028ED -:809D8000A0148033248190128C24042F39096F22F41124C5F21124C3F41124A3D4C1B64AD141B24A9921AB9451AB944783AF1439242F147924D852F924484E954FA2E454F8244A16F5244AD6E5A2645DACE44DC2CA1F49C2421F4952281F49324A1F49364A1F48B24AD941B64A9921AB9453B14AB934B44A3934AB944782A9F93448984F21 -:809E0000A27497066D491B41E3F21168E7361F81522A1FC1A2161D2C2F44D9C1B2427B15F84AB15781AB145393121F82F4421436F842B51FA2E544EBA2EC55F2258AD6E4A26D554D594E216DDADE28B41F41D628F41124E3E489D61EA1616F34F81168AD941F4196BA1B41AF64AB43AD964B43A9A942AD942F81D442EB82F5F52520228824 -:809E80000400840000000000000000000000008814008400180000000080020000200825018FE80D22260194A149422231142283180AA4709468811391C3D34124C484C14CC24590212248482116E882014D8118244110A142221F42042342111228C11242100C304840F84BA300436882308184158CC6884728144078815485269245500F -:809F0000842632C18D24288A12C2228C11D4861894888B42212412482F483214884140388A102C2D1208484972141288210D41144847DF80625E2658A19C184488411C542481264858818D161E4514AB48BCF384438F423424369C244F18548247128CC84446D22916B8183218112F468951424041D882B84552244B3C26638281184C2261 -:809F800001168C41C248148B413F43010000C028458386A928AD8100535842A281125441008886022212244C028308122490C41024180462284008002024714246088A044100CFF607008280080088000000000000000000000000000000000000000010010011400170E705211E221D1885148442218652A243C24119016D82C44A05BE56 -:80A000008218A5E58188A24C144554212E29811A1431C2C016C9B4620A118F4151848A4A230625F82421198441F44E8A4818E02B88514A1E8828828FD10723628411859414A834622952814712488E128C28B41A9414E01A58212584F8183843C8454217221E298911A1882914C8184E242F220C11E042BD4C6218506684183E619F284874 -:80A0800028B412148421026C2981D284F44ECE00200880088008000000000000000000000000000000000000000011001001140097725024002863020014122A41082084C4124041180A00004484424001800D48001224200487243048804988891462888843220400CDB13043264544D481D42861D4118F4134C129A8419601DC98A325C6 -:80A1000078D8A4483245D194936883E4444288213129493168A82E1A41291814223385141064C314E0286282231451228931581098428448562CF668FF244642014932228C314A1149E538A118848830C9394CAA811C0C31431188946400811D2849410916684C90448091840046648224608C84D8842999488C1118784284044E14226FFF -:80A18000F60B54491204D3041504158824A2411C01412229914C6083C493A2428410C814184220A68228272182248032111502301499042C8212424122914282882284428448EF1A0C85225486441A042046280215423C220000821883028E142A21C88148128420420948880058411021C8161426440228E1C1F04214428460888028F46D -:80A200007AE780F24428101212085422248426E841D214048651842C84043F2108221C01883220381413E15114A218A5A2482C924C21A0184021081948E34122883122004C120481502A4F5805232401003410821424210120A11248182C614280088D421054214825010018100480A8121628624100804348981100809142244860424463 -:80A28000EFBB0C23362285148655389023891684E1A211784681C1A120A1C14C739A019AE2849282511B25482368411E218391125849384222CC381683C111406418E0284218FA118885642256E42441487482088E24C5F2848E0016140221004C0428A11118001287444825022882251401002951180049042C0888901228A02849391135 -:80A30000214CC21115C412412C01004E242044188274A30D4111405418110010010000A81244228C02894498848D814C4101608242488302001564811901508260448116044D128481A91248288404819042BF610D221280428204444D222094421840082A24020070220120824422222C01008604008212314242230800311002238832D3 -:80A3800082844E198848F06F7B0041141C35818902204124021004880016416481008313628481840043444814082200C14828100847888CD8491208001002002121817307248004604421902682232916420245022460241410081810A24812212541424112512212103288003088190100290249080000888812BFD70B8E241528721101 -:80A40000A4121D14001A048422184141418688A821B08442942121452884860610A12483548122308110A12481006548848112448601224508C088405812ADE3800141218504444901108131A4283A8811A412811B12902944112D42100425381120418105204109162165A6200214441C1848021280B848028042F4CFA400288C042032D0 -:80A48000282184200480130229145442400240082C82088A642480E8110200242428842302221220020082834208480068004FDD080080240643810214190200288001478411C511011564324185041A1489810228002814811440C288901145D11808206228A6A28200001881DF460C42444C2442042800414044AA28450245222C582CF9 -:80A500002A219482224941885882242288279827181440084812214CB4121204228342148A42084082014058821A72BC054F42E21851415C52E18F511444F418144D848F2AA2628723246F22F384862F217C24B222582865794888F88C3E43586AE3F6CA421AD1283243A722CD2812345035855A9BA7814AD2A851284849C224854A12DEF6 -:80A58000A261422BA8C1C2811E888894C3D1780D1A144EB224B57832644C92224726A04580D944C18C284B344CB21563921D141CD4B542D11B92541D4CA0284E414B59482A54188828281981F2C122346829F28C381E1155E818D2874818D82252A827A88846283422622D18FFF20AD041922C1355141D228B124D12281553114E1241823E -:80A600008051488A7D48FC45348F233A25833221ECE4860226F8424A3F8348F1D1A823F9214869022B19144B911CF53A4423E6C8D442D8C9F8B8111372184582FA88882AA12229A542818F88F4881262EFCA073024108414042112671282211220C12492A049441381124134810028989091400224A0120000A082601282144002002800A3 -:80A68000B048028B243FFA056E641F1252B96D448FA2F61D1DAFA1F22222AFC5F58787EFB848F2989C6F21F992B26D26AFA9F722622F25FFAA82EFA5F52C2CCFC8F8A8A4AFAAFA6A6AAF82D68AF83818AEE38FB9F1CAEAAF8CFE587A2F2252465F78781AF13B63BF97F67C3E8785E5FC9C1C5D1C9D32BF389A8AE5E68969A23AE12AFA5C61 -:80A700009C8F8A4A88AC95EF47F24A1EF064645FD2F62D2B7D45CFA4F61D3DAF83A222CFC4F682A7BFFCE824F4A8AC6D862F28D866F28A6E2F22D6A2F2AFAEFF7454CF1F98F8A7B45FDEEEAEFE4A48AFA4FC2848AEE285FB6A6BAF8DBF18F328284F62F2C7CD9791BF3BFEFBE94F65F17A2AE5FE3E345F4AFB98BEBF28D8AA5A6EAFA97BAA -:80A780002ABA1AF3A8AACFC5F9E8E885D88AFC78B8E7C41FDD036E645F5256E875F5787F5F57F71B292AF25C7A5D25B7C62B66AFA9FB1692EF89F92E2EEFAFB722FA5AD2EF5AFA5C59EFD6F68C854F52FB6CCBAFA6FE2A62AF86F4BA188FBEFEBA3B2F1AFEE8EAAF85E782021F397D1BF3ABA33F1EFE3636AF85F2CE6CCFC9F9A5BC9F6848 -:80A80000FB9BB18FA15BEE2F89E922F238388F8AFAFCFCBAEB81F52A685E58CFC6F7583FF064445F52F22D2F7F57F35C7FDFD1F33B2B2F43F35C7E5BA8BF9EBA72F79EBA6D86EFC9F9BEBEEFEFBF36FB7AFAFFCBFB5D5DFFC6F4A98B5FC2FA65CDCFA6FE6A6AAFAEB4F2F5F1F2BFBFB7B2EF2FBF1AE3A2F22222BF1B7F19FBFBBBBF8EFEC0 -:80A880007476AFA7F2CC668FCBF3A5BD8FB8FA9BB89F9159EE8FABB92AB218F9A8AACFCFAFBB8F81F5A8E88FAFFF6C6CAB4C00400100410000000000000000828F4412E2440281B04802420000144001C0484048220800844008008281F0F1B2308410044712601290141188C01240245162438271115842154854814C028125229411F0A9 -:80A9000022188304001224842CC1488D12009644414803242224A02484811048B16A0C4D421F41D22EF11124C7241FC1724AF21124EF24F19124AF34B911B24A19B54A3934AF543B352F147935D852F925481CF9A54A5CF8254A16F1244A96F1255A96D5A4E549D2A6F491242DC31F49D22EF1912483F49124A7141F48B24AF18164AF1451 -:80A980009921AF3419B54A3924AF4439242BB44782A9F924488B944FA2F4FAC4508419B62CF111484D121D288D121D2CC72217C98F6251C18B245789AB3484ADA5478A2968882F447286D842E3AA45F424DA16D1A4CC212E4A86C14B9AF222DA16D8A2B481F42AC21B218B8413394A13B14AD141F46A141B212BB41789ABB443F34A1212B5 -:80AA00004A71B4983A6B418B944D1257BC400800000000008002000000100200000000004008000000220000000000121008F02473144941941736C8244114871241830884488B94524126184BC48421424C1845AD4255D84A0415084124184492221A085C2144311481B66811521C185448AD26124A414408905826F8B3E7244AB28101ED -:80AA80002112154824F441222287286283110589511428B611BA54B2242881944220856221229746255884C1C04618C44CB12874311492C1184661821C8204214A318888298292148C4C9144FF6B4CC244472416F112281E24454114796164824D88266881479D4AD384712D8232112CE823644412635116E247348D2416722871215A85FC -:80AB000045D84811C8C26A514818CF11747411739411E896D985E111B2A144562CCB1623A114418942061E4847214F9D0A2A311141008414682482244842000015C8A6454824CA841934483018480046041042941480492402808401224800008928982280E188042E484F91092D1250228001221224B0689121188410411211021822288A -:80AB800000415022408852249249012A010081842440425C2811424042086064122840044FF50F193214448F41D242D2C211158531242D812542019CC13283C1782E482FBAC4415C416C162F486212E9942889312483B412C22A2C861E96224D23C952272E124923823111221A688833718441D248C22C284E2516A4A5124F82F88F291036 -:80AC0000711206AF21A2218911116121228A5312404848417852A1426213742441C4214414848400E0616283412D229022144154A31232222C51580083D812C18125423C284F24924141F26048DB2C3032401414544249C21410744368221901168193128C52A21788232191282CA4286C62442D228371247868022CA8168AB4140247225C -:80AC8000872281181E24001889D21229044484284160432A014961828B3C7048245541444C188814141204524C924858A121850224131454488D12248C9491160410C245A4005084425048418324022602422829012C6881362C01484149057FE34F422814482203008354221B18312F41F616829011C01482C012488031241188106485F1 -:80AD00004361122B42CC91914C64828314248401202884D218E2429884902A8830A4001210F26F57A0214124118E4222278129118101400881D08404452305842222484044622300C0848223542112182810E8421152124400108134144C5422814D2ACCC228A0824FC441C2544464344F2432282F8114141334813B1425DAA4C158918950 -:80AD8000544882421481818125C2491671146243561826944425BC43685412838122D448A14322232814A242D0168194ACE42E1A83CA2E26982C122A78D201221285418401241287241229014AA148241225245172122B1449D44222E244024400211247228B289812244C0244C1502C40C12422158C284822B14219C4146044122744F09A -:80AE00006D33243081B02291298012010042483042204483024028141A831111D1480222100840B228019E21C220133881278241244447249681088800008691D26F2D065883B1184475144274461882614810029238618423485982AC0644C0262081424242A4412E8446094902240088884E242F82119148A984094485C428428002280F -:80AE80001648586800C20042271211804431538121008412002001140012217012C5181884214004104A04188504502C2A4804122619484424481444C445F07F6A241602418100284914068162804608250430842318849E8483946C904CC0840016898262845988048420969144429013891441829AD2008042782842F4D3BD4042084AE7 -:80AF00000228841420030024220020110C00178114134431448C214221048582128422924C2140189822244490442143C422488A0200238221F8752F4028217115321414418412518480018C44844429044121842118218344012012465141922210081448426011614004001800008812D084F56F21604641A120868484922124482AD882 -:80AF800024C424412DA2506241214813448464482816D4228812424CC98182801484042A34A8824288004283E18C928230A883E48C11394881003F8C0B4486022502C21420120210241424810111484415189881502141A1110045229222400230492D211840112CA23426026908444100824C424401AF7E0884224C149888643044150442 -:80B000001941042800C140440244271144294184280247A4812948B5441844C88268295284C314941400C014D081522818124518992481426322F2179FB044A54985F274324AF142A1F7449F14E221B684724A0843A444874785F648189127444D488F4114E83224D91262249CE19E321887224CD1E1B186A28A4C121444D8D2CAA84CF86D -:80B0800028788F52D8A8F84E284E287082D6F8F878828D92CBC24B828F18685A4DA8784515B861022F41F28A2A4C51816F187621E2324276218561318F248A3582453212672125D32D82F88222D4D354C84DC82F4237162119F312486F121208ED44414E662F32D2283264F3B6C8D344E885942626552227B5CD48CA54C16F819232448CE8 -:80B1000011C444C5E89BE687F952BA24245C7116585A87E34D448C944449517119A5424447212D684B824C34841C516A4394478E1C7DC315761DD161D46D74267F8454A86BC48FC2F9412BB2228E9C23D229C5411E48C25D121F5B41F2A454785A91176718A664CD8F8C24C428872226D428F186442FC50A100421008426022A48C882C0F1 -:80B1800084842C68826C382124A242132234821002318A820141200221D0120822501448806422400180440485214124A1247E2C2456F27331F7D16F63F7781BFFB6F24A4A37247F53F124A51F38FC82822BDF4AE928FB8696CFEEFF62E22F27F9A2822BA8CF46F21C5CC7FAFFF8F24F4F7F75F56A692F2FFF8E8E77F96F27FEE6E66F6C4E -:80B20000F69EB42E22EEAAAD2AAFAAFEAE8CFE844F6DF6C6A48FEBF92A288F83F32A2A2B117FA1F95BD8C59C94CF42F214954F4FFF1C98CFC6A413CF55F437652447643F75F51F1FEFE2F37A7FFFF2D233F262226F41F114959ED6AFA4F412344F44F984B2CD1E6F66F764E37F77F9A6866BA8EF52F23D3DDFFAF1C7657F54FC5757EFF6E3 -:80B28000FE6762A5FA932FEFF7FEE6E26F6CFE96BC2AF2A2EAAF82F2ABEB7F4EE84FF8BCAEBFDFFBB5B64FE2F2181E8FA1F1323A65FFCAE84FC8F85ED8CF4EFA159C8F9FFF1C9CE5EC86B6CEFD29D9244F65F13276AF23F332322F67F16B2CAFA4F671335F77F5E765AFE34FE225F7D616EFA5FD2626EFE5F58723EFED53E463F26F6CDFC3 -:80B30000C3F7A5D77F54F647C65F77F736376F97F72E2E7FDFF55ADD6F6AFAC6E26FC9E926F6A2E68FAAFAA62FE75E8F4FFBACAEEF6EF2AB3DCFCAEAEFFBA2A8AF2CDBA7F84FCCCF82F36CD88B664FC1F9ECEC49FAE2ECBADBCCE392437256F61256EF43F33A365E549FC2D2ABF2783E7E523F5EF63AFA8FACBC14F1D416EFA7FDAAAEEFB8 -:80B38000E5F58E2BFFFDF3868E6BCECF94F45D5D9F7AFCCFEFFF94F43D3FEFFBF35F7BAFABFBF77FEFC5FDAAA66F6CFE96B46E66AF4AB8AAFAE527DFCAF2F8BC8FEAFAEFBFFFEEFFE6EE2FADFBE2BA8FAC5FF7FF4EFCB6B4EFC7BFE8FA149CCFCEDECCF8B49C4FAFFDAC8D9DD190129016844B125014501400400280C4244881828D24C046 -:80B40000241189125148118D244901224261422290848440B8246881434248628124845416C8244820180889021EBB002002A503244418D0120121A0141229312121482111004614223122D022014B527022485424702C024F1468414244A503830442800121490414444180F4BB8FC0421F4152281F41324A1F41764AD2C1B64AD141F2C6 -:80B480004A921D68AB9459F44A924782AF347925F84293478B2D915F8AC4914FA2C4816FA264117FA264192FA264594D5A9E242E5A1F49C2421F49D23AF19124AF14F99124E3F48124AF14D141F24A9319F64A9153F84A9143BA4AB9A4F44294478229F934484E944FAAD4A30A26BA11D62CF41124811F4116DA41B44CF18144AF42B9815E -:80B50000D648BA81B44A3BA48F1429EA1478A44871A658184B1A144F82ED117A2428C9CA8F49C2CB4CE2A25CC1ACFC8164811D648B841F49324A1992988E24AF4429B84A3B84A933A4A9618A2933342B842F8A8479B4FA36E360888248000000004400000080040000000000001840080000000000000048000040018F7407441341711A39 -:80B5800005124CA242478189E211568224194184522111150C3217828C8124468441381A63314248701422522424C503316E86862752382800884260C426881142744254844C39442FEC4D22748422011508C88448218C58214890422531422044481904A441244D4A00844B1283A24188152624024B12281110054B18312283145482243F -:80B60000CA2142984119018D41287FEA022564F816C15D1130248445085B213538621721463422195412DC1478217228417818A24286F644188485C21846B44182D52498292D444E22158E92212EC127483952812DA645018B82431442B84289116824455248C71962FF5F0B4812241028218CE624C1288B844002101102008911848144FF -:80B680000450221245A22184804144026041214414442001284210984489221252141B142014D4FA0500800228100110020000002184100400002440024004000000860400008008000021411004484F63098002250415022481C018C0189018285681822C6219481241D0A48621820118A01221121243012902112120018A0481808182C3 -:80B70000442451286084437824F88F330040C224C021211121100A00001981B2424818210444209612301220014B2100184C418202172800004A080020224482518450844CC8486FC20820020000400812608160812848002292441200C18002100210220100004100180030888001400424800426F49E46000044418CC24144800400135E -:80B780000800118810210400212820810141818200000080088800004004200112108402CFA8021460313012000000424002C44121008100800446422882022012642460222864441200000080088C08E0883448A0818481CF880300100825811108001800309200200110080084004821382112200244818002000088000000414449063F -:80B8000042F0D6551001508627419C6215850448800186012F480111821885810400214608324A134222822904205268800180088008884184004DC887444C1404E0E50C001C01240000004800218464000010084280528200B02411180423821206412888000000008220011228928B24841FFC0D0000000000000000000000000000006C -:80B880000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F8004000000400428000000002180018800004001400848000000004480020000001002183F5F0B0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000058 -:80B900000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000069 -:80B9800000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000E9 -:80BA0000000000000000000000000000000000000000000000000000000000FFE40F00800100000000000000000000000000000000400181000000000000008200F0B5C800004004100880024008890100C0481243042284002001402282043011000080020000004412204408001FE30F290280024216043082800C82100282268E150422 -:80BA8000403144118410048C220200230244221881111800348904000084450800847024020080420441812480820884301A00008C24314460420040040024222C840212201118812102304800004412414008009F6D0D230200808401200848200800828D261A44041021548181001889220200004581020000400300004018880410089D -:80BB00002F670B108141180200002160140011290880541884106144A490412002008002444014088D1113112208110000201202008304DF340665C224A51204284184411A8831D881834864C8514E2985D42838145199111448911C4146187C41C8228332844C48C5217494302141C0898715608B181D1A49CC16B04451488146242152FA -:80BB800048AF170141105824804244088602828008131821048297414481444100C0484C22241262484C12C521514548186151136118142001348664214012044418818574E704213D2423110A00408481315887148141E449D881123C4821941C41C1489467815C04818501260888400431804208A18B58F08128188C8114044B52818486 -:80BC000042A042E0CC0A125234006415260114404A548416881268411440382420684949288283514818460150411845C84812282A010041121D92648904281A24018824429289F8D4C3406A444009000041426062861184240800649018A04188318002244581C288100848602482004641084024B24801008A011042046783341906F01E -:80BC80002412A411811424800181008081229118404814048424434408116044209662804801417024020020880816181208384048081FA70933D64201354A1A143A1350144A5128A4591828C418360400265C4849684C44146B1281811C3142288147344A41840824430341001234608C83A4215283818908818668A87FE7051840E141CF -:80BD000002114501240000844C2182081C618185041800A428481A12044146848822028113212608282714C420C98228188421003280C414F05C9DC04628242880028C010084008362822046280A26044DC880111134181004896182008C1148941CE02401220014A5A44818800142188B818C149848BFBF0C2200142246981C549C7198F6 -:80BD8000A5812B21C02114128018446A185843011528021EA82829C2524A18D412D441895442207443C22141367442221818E22412482804968A614C424120F8EC35144004100480C2244008400441408419440400304820141C8814088014040060242608188142003823861882282204181244CF2B0A148041447818C412002A09854491 -:80BE0000186812149C424201001B24288A96149892002541511244008032332841444038212120082034C841821822828A22F815133082154414084C1488052D44A04228497488D484449141414840488448841204E0210422100180022A881802212829451802218C082181189084407A1471CA0648904A0090242200841088025048827C -:80BE800085220846841851181D484820618815C88C8118111C08180017828531484A18A114A01400102804104804F013C44084C4212412271150941518281301190900830130129812418221893A2222413E82F09241212C894501AC7118044800289088888A42420829110421800C1F3F0624A451A354820080018848888120048188CC2E -:80BF0000C48480C44841D0C1248428488444C4484C44441448048744201E8801CA01184A51844945044490181821AEBEC01180444404804484064445C26245421354343C026882211C825314888514D4144218C4414911D28199122A14A342181352484018410C2820284AE248046C210884DF9845E14475C43417253E1E71897223953470 -:80BF800067118E2A2E28248D418F42C241E5DDCCF1128BCB488A78449481815D814B2746B298FB1C182EC27F76D4266CC14F24A1C44F25B4122252186F24F7594583249B68BE292CF498C28AC1486A9D464ED887482B11484B8C47498F3858C25F870B43722142B32C44E483D144C11895F928C88B819B41811125C92411195A482C9A350B -:80C000009EA86E541F54E2E8D291E41265442E2445DC8861542F28544847311D1184843E1287CB67A21D45AD66C6B243714858824E482D1284878C2368844A6C49188F84A94283EC5845523125D8484261828F446481CB6516E44C8321E4C2F8449C5D82D78522CE435B2827C427445843F1A4C88B428D14D5FC244882BB29928F88B24CEA -:80C08000F133491F48E148D845F118227F484681F2243A47843658281C41C1A69A38182CF818246F2179A4B444713A0E1E184B81CF7C031A021A12843246304630463042E04421E84421EA44312118222008244654218008882880428102800829012190823022102218220222A042A042812F560C7E431AE3E1F128288F23F53F572F4540 -:80C10000F4652FBFB1D4EEBD5E7D53F18AD6CF68FC52536FDFFA82D32B42DFA5F338FA8F82A81D7AF32163FF16563867312FA1B228F26A64AF61F5226AABBBAF41F3B9B63B2315D722F225671F32F231239F14F2E6BEAF28FB31B39F97FF7AF2AFEBF8C89A8B144F26FAEAC2AFAFBFE6EB27FBD6148F8EFAB4BC4F6EE65A45F17146AFE4BC -:80C18000F6272E6FC3736EF83D5DCF25F56F2FF794CFCAEF477F53F1EAB6CF61F55A56EFCFFAE3BFEFDBF51C7F8FABFF288A2BBF5AF127377FA6F64EDC5F46F264EE4FC3F3EAEEAFE3D7F6F89E962F65F3BEBF2BFB1FB4F42A2AFFF3F7DBB93F73F26B22CF8EBB2AF37BEBFFF7BFF8FFBAACAFACF94A32EF8EFAE8CAEFE9B9C6ED23FBF67D -:80C2000038CE88CFEDFDFAEAAE65F044734D462E2EDFD2F2193DDF55F3541E3FD1F539355F56FAD99F1FB3E628FBDC9E6FADD9D7F52F236F6DF9FF9A8EEA8F89BFD2A57BDFDCFBA9ABEFD2FA14414F63F6A828AFEFF73BF2AFB1FD9AC62F47F451FE7F65FD3777EFE3F3A7A75FC6F667699FB3F6A4BCABFE3F1BF3D156DAB9DABECAF91885 -:80C2800092EF8EF898BAAFA8F886844D166F4AFE86944FCDFDAC9E7F8A47F34772ED467FE1F1171DFD2FFF55F33C7CDFB3F71E1F7F5FFBB9FB9FB3F684B24764EFE8FC2F7DF5FFCF8FFFFAFC8CEAAF89BFF6EE29FD6DAF3F9AFA7C6D5FF7F3F67A4F8BF3FAFEFFEBF7FEFEAF6DFC62463FBDFB5756FF32F63E3EFFFFFAFFFEDFF2F6796D81 -:80C30000EFCEFB68729FBFF6D95CAF8DF9DCE28F2CB9E8FCEC8AAF8DFF9C9E6F4FF77476EF897C8CFCBCAECFEEFDDBBD100425415824E022012623490240081548042008128314A1242144218D24318B246B128163024B929014842941581484881A44E181041A0496C824484CA2494C221128F89BD2202811241144182C1144A882840060 -:80C380005C185158518160444044D84828625584B02141842804421430241584C844A0682A180180490849D4280198102892884712C77CE032F41124C7221F41326E1F41324E1D24EB141D24AB941B21AB9453F14A9443F34AB553F342B557832DB15F82C4B14FA2E414F8254A16F5244A96E1A26459ACE449C24A1F49C2431F4952281FD7 -:80C40000497248F29124A7241F49F24A121D2CAF249921AF3419F54A9243B24A39242B9447822B944F82B448F9244A7502BCD541941C48ED1112E5F11124E582D278E949D23833118D36128D97126C7114989869D412F1245A1CE1A268514FA26C152E4A16E5B244E4827D91FC22489E44A5F2116487261748AF24F19124A724CCF24A16F7 -:80C480004CF24AB251AF241BB44A1BF442B245885B86ADB44D125F7D0F8480040000000080020000001002188008000041008488000000004004280000000021F03CD224400495041E4441644CB592469848188A4424A14158150440094784190800448303484E8C8426022081A8818E12621220981823318810181814A841288152C12CBB -:80C50000F855BA20318341901E911FA28133291480014483E4C8441424C81C62C0240021224531481164446041202588E24144088C41A2C2122998481AB48821E441A4349A242201856412F07DD7142D1257844485361856C43469D141F28221450830444F84B28481B544C181496124949048248A2142849418443354488130524628A2D3 -:80C5800081830926C8128AC682C97112E84A351842C14483A521403814478229D85A0B00101154818581B24AA141E0818421088C4404448428C024411C08105148130241C249810282184420B94201208188142818A8414A232824038C04F0A14100100C411100419082848840844414411101004146342444137248850824824084081407 -:80C60000281811102102A0412001400229A148201208BF130F25042A31111C042D458B128F3144091391422398C11419E424C1688D14174226B4C9611284D018049011578489C1485248296112B8541942C8318344E212F488221415588625A248848B3483321428414449FAF1F4100281204422049F644109184622B84568145364344230 -:80C680005D182611C488224528D28494218114942CB1482805181922922438113213041982181158C22442F0224A818E1410446C485F660941E0423111454151413608248815988200001217824084E2141125444401174492431408D02424081E8114148414812C82942823456121201828A11242282220E2DA042D4810880422007042FB -:80C70000140244A51284D884F442228A1162A2415D58814914E42802241046014249244408481612A868416022D084118818882182C1841216BA484848F464BE148444D012840418411D28141608C42A15D8828201198443230400308543223A4414762112D881D2421212A442460418004A28189422121228C4238401864604F04B54204F -:80C7800062221514941241156881005081C084190100818100E04402814242400800410032811181184126D81A0400120088524480082004CD2600282415A614C018811153144201CE1643B182C24CF081582B21178243B419D44806441B2443224A428502CC7441842252842671484448846214248812A321C118A262189890884E8C4024 -:80C80000B6CA0F2B4244E501C0241416742802894158288C5218842CA142218400446044844429046D48808502286D4212002C21A196C4A18A0684A02820D168914444924C0183043FDC094140551424104224113211A4181427414312981247111831202844AA422C116C8490494A1168212001004E112551288054181414C18C8C840288 -:80C880002A946840988882D0240B0084A121001C413181C3228812041110044142848484148400905C40285185682A141184312820010018E026181128248CA18142183828F025243014100400404228112257488912081B8181852241827C5851620014181816824112281481810180210186129814200881281800C0288400814FC70EA7 -:80C90000315B14A024B1280060441009822810420113081681024845628222142A4848012248880000422744518018420440148801004C2825C1228FD7028A62431100902843E4451225040023B14881081410041C081018044904521248244012488211410148830152148400880080080025F1452D4008324004411200110012008129A7 -:80C98000420415084114114870440340811412182102114078125221844D429304302148822212622881908828389F7D0B40C24A816042800280B3223812284E8411411200D80084C1008908135422850411125411282018AC122012143122A028460226028B4816022281F09459800100002744006A112211981240884114425486C38408 -:80CA00007141C244472249B1213814008021440212004248942C444402821EC10081C880012A0998248E3D4019A141439221009024502815045912B8641805982880181284032E8818110029488108178490511C0881431444222C6844803218822604442024544A84BFA74B039E239D182362222E22238451249E432F4462A96D128D1208 -:80CA8000848F2452A1816B11242D51F088484D424D242F64F62B14B967144F24D49AF45218811D482F16541385011A1159C84E722D462CC4195AA148CCA4489052DA092A812EDC8851D82AF2DDBB30154D442C72445CC30045C32D574415FA222189721474427481D854F82611116B83C3F4C6414B82D484835284AE87C11E111285E5818D -:80CB0000D51C3911AE329011822CC45215394CCD38BF485813F0A9A18F84A8D48F8AA2422B655ECC85B814A86DB662213F87095C931147518D231444CD245E247A81F338119B9416D811B83CF924558B1916C48D5CD1C1D888F9111393F44B4145A82147811F41B588F241122C1CE224025E441B114D2311FE193715E7411C7842F444429D -:80CB8000883DA14E1214C782884C22B28882D18AA382B885B87D4A02400800702481B42488446288448A04840081A24222441146044411861462482186641244144C82C824800228349A0210328429B214143294A1413014F0A8E1242B221F36F22B23BD4E55F42626AF84F4212117523DC37D922F22FA2B9D75F747414F44DC88F8A7A384 -:80CC0000A5F82C2A7FB5F4A5ADCF4A7A2EFE462BA67A32EA24BC9BF88CC27FB8E8ACF416866D8AFD52AE826F51F224227BEA8B24FF52F663276F46F2121E5FEAF2327237189FBF59EC8BFD8F62FA92966F68FCD6C8CFE2F23674CF47FFB498E7422FCF064F63B352F41C12BFF252136F62F24A4C5F55F531117F73D9EAF97A7A3F12F3972D -:80CC800093FFD1D38CF814923F7ADB73F1A2B63F91F5C78D9F1DFD34172D27CD9A67E3CFF5FD1A15CF25F5979B6FFDF416866FA6FEB7BA5F65F6776C55D217D598F73775FFF5714CFC7E3E7FE6F222651F38F8FBFFC7E4CF65F5AAA62F4CF8E4E4CF8FEEAAFAB2F8EF4EFEBCA8AF83F3B8F9143E244F63F63A33FFF2D277D266F24E485B0E -:80CD0000331F6676C7F7DA7E9F32FA1BBB65F6DBDD8BF78F88F8B7A33F315126EF8FFE179D5D85DFA6D577F226862F23F16E6BF7958FE1F58212EDD58F25F5AA363FA2F7E6C73F11F611163B994F47F45161E57D44F47C7E7FE4FC93D63F1ABAD99BC2CF6DB9E2BA94BD24F7F896AF8EA846EF8FFFB8BC8FA2F16241243F63F316444F23E4 -:80CD8000F32F2F3D236D26AFC4F465741F26F7E766AFADF5EBE3BFB9FB8A9EFFDEFD7CB4CFF9F9BFAFFFF1F18F9FFF1BFB55D51F1FFF685FED2FEFA3F23616EFFEF65A1D9FFDFDD35BAF81FC5C5EAFEEF7B3B23F35F63F641F63F3D391CFFFFC5B69FFD2F64C4CCFE5F5B7BE3F19FDA1A3FF9DFF46C48F85E9AFFBD6F26B768FEFBB7AF1D2 -:80CE0000F4DCCF8EEFEBFB2832D7F810041C012302A041204122011648210812441351489242001098114C123148188314021C0114C01150144800204801400812801408005FE70E47181054812641140445112146D818588489389585518130819044145538484189028384411102182848122068341618082344FC421148428442A034D9 -:80CE800012892A8309382679EF072CF4112485F2112C83F4112CE7241D24EF14D1C1F24A9219B24A5985AF643924AF147924F8429147822F14F924481CF9254A4E855FA264515FA264592E4A9E252D4A9E242FA2F491243CF4912485F3912483F49124A3F48124AF34F91124AF149921AB9451AF143934ABB44B4BAB94478229F9344898F5 -:80CF00004FA2F45439F0224A1F417422F2114CC7241F81726E42F86C131D4CAF64D941E2245385AF6411E4347B84F84A3343F242112F82D452F9245A4E956FA268456F827C98D486E459D296E449D2A67491DC86E449964E1F41324E1F49324A1F41F24E929AF248861F41F24AB243F94A2643D16AB8B4F44A8643F242946F8BD442F8248F -:80CF80005AAFAD0A000028000000180000000000001800000000002608001004000044008400000000F07616604100702244FA1528209481A962811CC4486B48A22A041C1188222464246044CD220050626292638423855128100A11842301A8421588148104B0280836044901FEA18072A45148004B429058224382018CC19483D184B1C9 -:80D000008C61C14312C45447912295C4418332414662428984C694301820581243E111A238808562828E421A94884A389160291AA821E028812C6E14CCF2C8F56041461548C22483F211241848471A6781837168D128945C4CB86818D814117864D21C05876514478ED12C048C34621D44301A8B121E4246417812628230418CE28142323E -:80D080007489F468811311813482188C4AE262A824128F41F26CBB20821204C044A18C2402228031948836C81443811284014A1221044A12C22440B422299944802891141982091810A2488882A04820892102924A216844F05946200218901C4422151414411261140012888028D118130400240044200144221004207124410820E481A6 -:80D10000021B41814003242AD44822039246046F8B0716062555A480324422562825233118C9C184895449D15B4294A024481C72440A1E4916C41276714188518216A812882352C28A82D126624963062B481314223483E08184921C82428B92488648F86FEE400431818564424916654142221C31484182811C18DD144C391828601245D0 -:80D1800058224649440484188082022125845861830200C81934128C3482305A7012B8288895284882F091A8A0122143512412002883C4112C011C9118411A54488082611246840442808121F132414E112485C41818498842282343E641D842867432081C04141480B2444224822969C484EBAA40A8124084443452413A44C198246483C6 -:80D200008244814431824E2C1224388A81C48890248480084C0120250148008C4822248466846CA41284484B8400448F41C8682A14F81A2450822195A443818414A30281118D214CB124096112840045C248414A4192842A05A2463C228311A11A1C2362E2F022489014103189448C014CB88884F42482106118D0220412281D93E01211E4 -:80D280000430121C1228416841281894141228E041220222400989824234481230144362824442008420052880023011001216889211A50100C444CF7B0D382F4211C83423C4252795C98344A9388D31A571162184A2418B2182842E147024098722812A352C26688423DA84F224182A91213A841228024391A8113B2C4CA46184B08AB12C -:80D3000048A1D22BC22C414874DAA4242E58C1EF6F0A25014501894148028B121654188061882C11055129B224048C84A14842434284241964411890845260412542A814001008811B414A8A044548048800844422AF980E4114459848C1224931285B123218001004C541F81441841C110180064219644140041840440291830444241693 -:80D380002442042315C8481044B81804412004445F83074A02114022440185328185A124184C3428150A2830254542286282418C2441088484448D444200114054222C041018B122010023140822412418845882FFE50EC024494104448118448420240432C1444461101424150410244828218181420800A04318388181A02881225012E3 -:80D400008CB2C2216181420018006FFB0100C0214C72182131442846144414288424A21200800421488C7122C4C84C021DC4842842448981288114E344084664221E448128215210D1282214961290448012F842F4A02800001422841004200241415084C048218534241E488081021088048C01000084222848233418181068C3000048BF -:80D480004082288814B8C14F429428D0480212001041490812800128811038622125841185C8480018C0211800134199148C542A1838302131184219032064488501120049F43415C04900141301109211202192D2288034121C214B8408A1B044418888010000811812C0521082B1880228004C0489220100E0830481C082BF13094041C8 -:80D5000008897224C82813022800C180A1128230482800183902A2181A084644B42815464424813214224C416442466C644C042A4822189854412258491484A481F09756C019442A041400100842C410944A4826882122E48201E90C8C21E54298228C3122C081141929C268801C81021210024E1885042C22022D180080241102AFCE0BFD -:80D580006E355F185288C13E232E598782D3C21C8F4FD2D11138584B14521F6221D248F2346C4416782BFC386845D488E6877554D488487428B918F4342A8F42D288A1311AD512C2893E46BAA251FE282E622FA164123377A278149A419D182DAA2B442FE28AE182A4118CA455483F1D429241874254174230184B2121261304484C0DA9F9 -:80D6000031142D94479189D881524649D424B158624487482AB4D121F152444D1419B414E44558C4A21B111A519CAF44F12E24AD5446EC44D165C12A8189C51223F214448D18C3C448474449A81522826F96064130349C56CD5D241CE184B31D521183E5867222C8444FC2F64868DF81E222B141B16CD4290F4E843F8254244D218CF32299 -:80D68000648D18434888E984511400502D3B344D422445B21EB12C92E889A17562A798688B1416A45156C4122F44948888CD8E3F4844214121013042704201698894820084001412540040416214241460181882200C821882188224100488482C08888028C18211880022B0EE0E7E651FD3F119151F52F459728F23B714F22C223F24F655 -:80D70000E173DB186E22AFCDFD585A2FA5F76F7EAF9A59151F1CF97837EFBE3C218F9AFC24273F16F4697D2B47AFF7FEE9EDF5FD25A98FC6FEB8FEEFD9F5B4B4DAEF8E7B88EC4AFA8686EFE5F1EEEC2F63F37E5A6D648F86B2A2F3FADC2DC2AFA5FFDED4CFACF96E32EFA5F5E7E4CD4CEAFEA8B84F4AEE4245F272641FD656591F53F56936 -:80D7800067CF62F7746AEF27F73632DFFEF781156E62AF8BFD585EAFE7F76F7EAF1B0B4F4DF97C7FEFDEFC6D44CFF8FE647B7F36F466E8FF97F67A2F9FDFFF9E94CFC7FF79EDFEB667CD8FC3A3751BFB8FC9F1387CE7A16F6DFB662E6F66F17E5EFFDBFF8CAC8F8FF3F8FCADCABFB4FC5E5EEFADF9BEB26F2DF9FABCCFE4B442F5C8D96F9D -:80D800004FFB6445343B764B6285F9212D5F93B777F32927BF56F6787D3F56FE59572F8FFB58784F65F54E4AFF82F7A8BBEFA2B1CAFD7D76FFCF7F2FF8BC991F86F7296AEFC6FE7C7ADFE7F65D5CEFCCFC343C8F9FF7FC3EEFC5F9343C5E722F2BB71AF811154F45F17E2EEFEBFA3636EFE5F5CDED9F77E327FBD8789F1CF45852EF65F53D -:80D88000D6944F4FFB787B7F62F2D6D4AF8DAC98CFEAEDAB4DF36335CF42F61C19DFD7F3296DFF46F3292D9F72F23F39FFD6FE595BAF8FFF58784F65F57E5AFF87F7BCBFFFF3F3FEFC9FE7F7FFF8DFC6F498B95FE6F6676C5F96F67C7ADFE7F7DDDCFFD4F47D7D8F9FF6D43E6FC5F9243CDEF23F3BF31A999FD5F1DE8E6F6FFB5E5E6F652B -:80D90000F75E5EDFD7F75836AF25FBDE7ABF3CD4BBF49EDEEFE5F53E762F27F33E3E6F4DFD7A78EEF3CFEE79EA01411004418C84C1480000E0814406401828112841048504449028202422048001225032008420486188A048148E48248608822001825FAE038211C0284304460189419418901812811A441484216144124E214548814466 -:80D98000D18525817418051644480419C212C42A6141C064C38694928A622484984198AA44944429098849F47E59C0421F4152381F417248F21124A7241D24EF24D141F26A9219B24A19B54A7925F84A9153F3429157822D954F82C4914FA2E414F8264A16F1264A96F1224A96C55ADE24ACF491242CF491248D121F49F248121F49324EB0 -:80DA00001F48B24AD141B24A9921AB9451AB9443F34AB243B242792498924F8284F9244A8FD40B3CC44C87324C76487111344C44CF14018F52D941F648B251ABB45788AF2431B52D2217882D14678A1CD184E514D88469112EC896E5A2E458C259DE252E4A1FCD42FA8164AD121F48C2121FC9724CB28132481D24AD9619F648A6518F24C2 -:80DA80003B348F243B248B844782B95B86A9D984F5BF19302280040000000080020000008821008008000014008400000080020000000000001470CB4A0241181504837112088524384A8E311602457A1438E8502443C824684392444A023041E3E18128B128212506C8182A89D8481994C8814E8892802421E188E4219244839A28842235 -:80DB0000281A82F4CECD4021487118C229637244514A56128452228D415B481448544B412283B21824688584304247228D242C6214222304832118312484161A2102494482C24212602824402A1124BC4841D418449CF62460441285D582B22471441866C44D8245825A82614912E85618447482D42484B218321C2C240C993636871C16AB -:80DB8000E28384D418928846E145321889311C2284904828430422888A8433481A08812E4226649187459F15021440214143D81241C812306813E114B18154384B41811A84628289A348468484024C121698122820810588A082822D81444AC84C2C2849A2411812A5022566828D248A9418A024F0E52920C2246144008002482642088453 -:80DC000040882282082061441008818C01414A9212420000000049C1444260221A044002884138304800D09604154421127A3E32482E844412218DC10018812F55D21484742C314887544E2483C2242B864222441F4522412182229742228023A921CE222CE221883298C082888E18111E66478129C448A2A29E48844CD8CB0E4992212964 -:80DC800042342C81430880E48442088C4132751524E6820899A4436822298284921446256114328027840200322216E44439228C09822100412D18486880E28108B0370B144444A5622148224C2211621821008184685041461814548441830C8181384122216824008083094E82282148C02258888B18142B2549584283A128838C14C817 -:80DD000084BFFB0E46C8112D2A8C449414003862100248848229041F81882121449812225C88044448848160C119850919818401801408848444B048811C048C88840144A9DADF0B4781444148D0180218100422442B12A021B024014A02211981118828013608108121046081812A3448138286A1610013C224290523E288C4242A81C2CE -:80DD8000848242219FB407280080455284914082410841141548583244448482414A022932212B2424004B2542002A4484981290188A0120C111420000201564812200F0492E40D425C124A1481655821C21F34422122942224468AB422697812812428D142810A64168C3314284C924D44824A12C3088290328F84AB11826419929A041EA -:80DE00004E1AA8C24B34478889238A18C4A8EEE5A052100849C12841840040084341115128128D144B41818214488932211C128202A0121218138461411C018B1417810000184824288054488083C4142044D18903244904428428400C00008442122816C9453024004B122881411256140123011268182820049A848104800419011B144C -:80DE80001A12042AA1828BA445483A24BFAE0B1A2411286124184CA2142C6448806421431448614410B841031485914124148111008181818922C129D01855420046C9281908DCC1A8601C00842E1883041882AA21F8FCBCC014140010442C3118263118228418302115381C90442422404911B5411141120880241441011681012612010C -:80DF00008B142200812884C0142410082904945F550425083048498224820280044880D148048A64819C41B1888401582B4222CB49803C1129240180ED418424A2940012A0141988210E114921048C981126881182B13A0A8200401845384849E2448114413848498882094C09884888422A0812211242992225010044844341280883082D -:80DF800080223844880032A80042A820746F0F420044161228C12112004E141021018144429064442C6442A0424908491481444891248426C86828460842892614420246222914C22200622A180226A8821FD90540A24100124221482618148A1A4442444583824A4801402888880281402342E8140121242642010019048483121101843B -:80E000008489010000B0D10C498281022A11C81290281281321818000022442984230148442242222218001084042A440281229018A04812858401842282828440C841818F410584269C589B124C840241414218444882C332888002811210228881A18425042180488198228412C88413850222A034184C04288B1C414890111981C9547E -:80E080002B18247F764EC2544FF94328F1283643E48481D48476A4F1144883A14185E8C1B247524866ECC4C51D5F44928D11874C288F5CF1454417416485C818258A65621F42B621E246E312F814481B182A2C24E21128B2D9AC332F4C28B953912CE5A4A8DE711BA8A351848F9B926A6A033248811B6412BB111E267D288F67715834487A -:80E100001993884749896C1219FB1C81ABA1DBE12F82A8638BC11CB221BC2782F2CC5149B342C442899128988F15A14DCB41997262A2458291CE688C21D45261841B711DC1C83E18621608814EF82BCA1CC91ACB793044213AD1C8F144482E2CC3F278148087B162E4A6B141951487C94D49193125625827142CB12565A4488F2331225ADD -:80E1800074A17139B1512CF14828C013E0A1D148531A4E3A2E7989B14BA4718CB2885C9C428549E481F728128F82E88321FA581442AE843FCC4E02002018861402690829485842822117882182149214864861A814A414A48220282208823081100111881110010092002011088141F025CF342B67AC52AAFFF3F45A665F57763A5CFFAFDA -:80E20000C6F726A2AFA8F8C3C32D5C7F74FC1E3AFFE1FA5E51DF34B743F47D7BF7845F53B379F75DC775F66D7BDF11F27E332F38FAB8BB8F1DFDEA6AAF81F818B22BE93E632BA54F41D811F6D9C99F1EFFC9D99D6BBF9FF7D193FF9DF969ABBFD1D821F942513E32EF8717E895F4981B2F21F13C349AFDF6CF8BB3147E662F457318FA2FD6 -:80E2800057EFC6F663776FE6F26D2FCFC5F72EAEEFC8F8D9D98F87F54FD3EFC4F75CECCFC5F5E5F3BF16F6ADEB7716DFDFFB7973FD85F5FDBFFBEF33B77CF74264AFB7F7FAF39FBAF35AC88F25FF9EEDBEE22F11FF2C8D9B8A9F94B4E9FFC9D99FA3F3FB791F29F9C3DD9FA4F96BF94E522B744F23F37E588F8AB9D9FD383B2F81F1BE140C -:80E30000BE58EEDA8FB54EF174644D66AFA1713FBF3EF27F6D4FE5D4FDF16C3ECFCBF37AFC9F94E5ACFF45D5AFC8F93CACCF6BDB5BF2C1CCDFB7F7FAC87F53E38DFC45D5AF88F867C14D4B5F52F61B792F33F7D851AF34FC3A389E3A2F81F291C26F517788D94DF2D9C99B9D1F97F7D1F2BF99F1591ABFDDF969BBBF95F3C89AAF8DF53CF2 -:80E380003AEF87F7A8388F87E6A3B172F7FAF84FC9EDA4F58D51342F23F6167487A1FFF7F17EEE5F17F7766CFFD7F7787ECF8AF26ABEBF95F5D8FA9FD4FDEEDE7FC7FEFCFF7FDEFFEDEDDFBFBEF7FCFDFD1FADFC65C51F2CFC3DCB2E486F52F6183FFEF3BFBFF748CBAF87E7ADF5E7AC7E627F51F3A92BCF4AFA59498BDD9F95F5F8F2BF5E -:80E400009DF5181ABF1FFF69FABF94DFA9F97AD14F23F37E688F8AFBD8F88F22F172788F83F5B4CC6E6BA72CA012008441001241844008404448844404002880024440941100B02421E412012200A08248E08824C248E081440140982812288228F03EA6904412242889A1418144A041421242168828E8546288188648A44198438A8204A3 -:80E480004B1214581AC21812841014C11284188C344812881288821882701488628120081E488148B7A8D022F41124A5F31124C7241F41724AD241F24E121D24AF349921AF245985AF64B925F44A9357822F147935D81AF925488D915FA2D418F8274A8F15F2264A87192FA264592D4ADE24ACF491242CF4912485F2912487241F49324A6C -:80E500001F48B24AD141B24A9921AB9453B14AB924F44A924B43AB944F82949A4F82C4944FA2F417F5D092F41164E5B311764C3311A543D43E01AF7441F4423384AF74BB35F44A9255D8227915988839F44A941F22D548D9273C186F227818F1224256F522491E2525F8112C2D481F45D22EF41124872617498F24F18124AF265141AF6452 -:80E58000D941F248B25B218D1243D22A3134A53224A9B122D442E982F5AFF3008248000000000028000000002180011908000000188480040000004004280000000014E0D401421443411408832361D21A689816381844C3318400448A024664428A022992246442284D7800244870117411164492288F242A2114381870828281B854E22D -:80E600002A04C0188118438274310216652A222474413028C024382D22344A681883711884321841C3A61220648446843118498101AD424E2C8B2119218502AC121811025FA10A2D822E5842821C0499A1348B49112A3941871187224D599044133A244D42814128831245F4358A8C322A4CB41C981C4981C21C4CEA22B45482A285842793 -:80E680004A43D2680118833649A992383B144A713458248B42257822A88429615A81AB1887222E44888A94241F85A852CE18182E925661115E2A6F5D0D1C0129014503892131289A02123C21482118080085044422424812604522161462440010C1114410312AF0481240A2412C2841A1412C024019088D24F02DAC80014100A012008007 -:80E7000001290818924C08AD2260442200004E2141802194148308282A082215084001221281820083044C088D84124018088F88044C522716D18642046489F426526A8182211548944428A149C42C224909854444C41412CC289228826AF128125694541812C0781E69389C541884822E49189C24A141A3B31C8C834888A14283E623069C -:80E78000641118A1001E24A0251A04121A18C814444948A842C9A224445084004C2521084212E81869B4A424214118E88184021598183048109818C02884CC8A08184A6282FF1D06324465C12444002D4A642238304200D82225526840A49200444126115448388932848991281A820128117819C2111D48223088132A6114425269E94178 -:80E800002C2141484888F4C771248418608260425012182602467888A48249048B18118228822CD441412302800A28302270848181E1C1928848E028A23425419C1415542138813088A021800292904EAF4B018444803448402182C2448042F4261220022D2424248C921822A11887483608B018242281442164448490494221863848002F -:80E880004400A2E022242984018951848C13F218FD000010025A1208218C010018251824011200420010043548848144180823021B2118164414A412008328014694184008200520047F7F082141C02A42282A94211A726432188322D824B14421F284182752822A91224A11458352841250815E242229C248862C6447223698195282ECC7 -:80E900009A58C11634881429E1C864812E48278128A0128971189438C3B4490B20011048C41384240048852248420812249088844A4308D048622240288105201162411C0845C2242B1419024021010082881A8481048242F034270043024322840246225484422824122B142678C294144285648428188584528421381222291102A01A79 -:80E9800020890100168C018841320010A8120012A08440F839FDC0421824808294280010AC414E1820D24105224538415B8316140182224824A414281008448246A448008902481885911A304282203182800888817084F2C6FD00000081424942182801221284831104222A1484012800200581820084801998982884843034844B12628D -:80EA0000184B21C048228182E08221913620F44A5E008484902844001E241A0212414C8A081681E891480148811001195118111E4115B228240311141148990113E113948900110014118094480022B04281F3759D2008248B24844285641410040085C114828100304840A421A280E44204624548116884260816840242418110020040A5 -:80EA80008261880029018C0418481F310521280044642C02A14221287044122822284584014D2842828F4401003200184681216484288044A8414448C048488C8289B12884A38122484A82490488BFC3073880050080018091484280140445C8116012601241406CC18100008880088820A8212848C024A88308421B8482808401002E88A3 -:80EB0000C352482B5C24108152814C0441C41A94211009844C085884C8CC014832895C484E228188288C0118411C034410B8240500008041081240048F410820845424F0AA93E0849214584100421AC2244A114824A124002262288001AF4804190549081544B289E182C471804428C421811E214223C2246E154714E0540868201C888407 -:80EB800038482508278A22F942A1248E341E123982342C2F44F642442F81F614742D481D485AB614F182EC5119B714B4919E5417484B3319A5A94F92DC84C4148C32281F83F18A81218E482AE4123D144D853E188F54314846F91E444D8546F1C81D8B358F2A32144AB142B834D2889918C28538928E1889CC586B44242B41318446F42899 -:80EC00002C30241D22CD149558488B14ACF141868B148DDE4F4198A845E141725CE944E4957A28BCC1C226B9B47C7811A4641D1C97868B26144B248ABC58B4888AC6118F4337611AE683D124CE4C1AA5B41126D8A82CE8860C3A85B92AA811CB82972A20323C22C78243E44454884F832126A6113A12D48834143A32C86E1C8FC67149A916 -:80EC80007284C742495448837254C8512D31A5E321A2711E148F813188118A43618B3E28C0388B166D241392811588E4199C598AA1654399924AF268484F44F6242C2F4CB2C50D00008400004008120014400181000000002128290100100115081150810020090082400882002029E417094F41D5D5F13C34DF7276427444764AFC6D3535 -:80ED00008D5CDF72941E1D118F467159F5DAE8D7C19F89BD88F8859187924FB3F4696D1F9FFE656DDF16F66C7E6F42F674223FF3F37B4B77713B444F4EEF96F779717AE7D5F138115F53B7C9FC4D5FFF96F6E5C22F5FADCEC7841F95C5D41D13AF8DF16C6C8B56CF64F57AB8FEF22F25F5ECEC85F832A8EFE6024F43F55575CFC3F32D6FF8 -:80ED8000EFC4F24C2EE5FE4F27EFC7F76D4FAF45F559598F847719FDD2C8DFC1F14958CFCBFBE1D95F97F37D7BFFD6F7B5F17F55F7296DCFEEBE36F73CCA27E3AFB77416FD71694F4BEF86F731791F17E751D118F23D6D9F8DFC4C2EAF86F4E5C22F1FFDF5358FC7F359591AE929F9DA38CFC7F668D84F65F5FAF8FEF22B77AF87FD141895 -:80EE00004E5C5E51A0515D558FA3D3FF7266742C5ECEDFF4D2CEF43D3FAF46F359118FA4F3DD9BEF8D7958F93C489F12F6B4988FD3F23469FF96B7C4FFE5F9CFCEF66DEB7F31F5266297F39FB7F4A4A64E414F4FAD77CE681F1EFE94D49F8BFB25248F9CFC5C5EEFC7F765662F56F7F5F59FDCFC79795AFB4153AF8DFD6C748B76CF6CBD8F -:80EE8000F2FBF8EA2BFF6FCFFFE8C88F82BB6C0C2AF635658FA3F34F2FEFC6F26C2EE5FC7D3FEFC5F52D2FAB379F95F1485ADFF4F5DE9CC7D5CF86F5EDED4FCFFD757DCF87F76F794F2AFFC175CFC8F66DEB7F31F5A74B9FF3F2784B4F5BEA96F4B4D48F86F791F1FAFF94149B89DFC7F3D8D9CFE5F13B79DFE7F762795FDFF3F8F89F97BF -:80EF0000A7D51F3DFDFBD9CFCFFFA8F84FEDBDF2FFF8FAAF8BFF74FCCF8FFD4CCCD50C00228461001A14C44820019E486089444844400485249828400489820118A01210042A014098141A2462816089006088288A049228D04822F88CBE3086282A413422C4C128611A2246881194824889228378310816E81402444342D48245712302EE -:80EF80008C088492412888841828C028C1408122341100389608148148189CF4EAD8C0531F41522A1F4132481FC1324A1D24AB141D24AB941F81B24A19F54A9253F24A9153F24A91478A2F14F924481CF9244A1CF8244A16F1244AD6F1224ADE252FA2E549D2A4F491243CF4912485F3912C87141F49726AF1812CAF34F11124AF249921E5 -:80F00000AB9451AF243924AB94478A2BB4478229F934484AF9244A1F350A4D5B1A563E1B6187321FC1724AD241F24A131D242F54E9C1F24AA349F24A9353B24A3925A939242F147926F842915FA2E514F925CA1E215F826C5D65E85CF2261BDE254D4ADE282E4BD6D43CE489724CA3698736CCF248931F41F64A171D64AF349B25AF34B17B -:80F0800024E4646982AF64F3244829F9364823F424182F88040000004400004400000010010000000000400100800400000000800200000000704F0B444D222244AF11342441948711813C51A119440840A84372330296688C4628C224478113C22C8C119426124906416C514918276143682250841AC8C922A36421C860E14D728E222EE9 -:80F100008243241494443743142C2668318C41C418114B242C721481288331128D118618160A4483644222228242901C1A3C64996281448911A2142212A042188F41A84986420C89E12178487418C22400438105856497F0CFBDF02442472438E14CB528117424D18153875961A2663112160884A12CD514C24A1EAC4E881A26684A89C14E -:80F180003DCB294E3417C2CC22D1B414684443D25AC1424B616B18C9B25248F41884578C2E127E884C414814DC22E74893E26724C9B4347454D2120A804221511A44148C04122C38111884148658423A84020028842848442044082941A412802101120098D028084048C2482F2429821104120081F0F5DB50244C921A0048458114241124 -:80F200000234501840213948A2288042684448812A54484112254224022A4C94169018488042028B1480080042848B243048438811E4C34102C0A54D1816F4221232C1831204C018814512042A248244C8189984A428444D7280658C4E2846A824238815021C1218012E14214C76889522C8422358248F219C286349B2842182B16818F860 -:80F28000B731106242DC5248809214CC54846C014048480D80232608C04889241AF4481222414DC88C7642682482302270261138114210C242152E064A3882418B418B244098168CA2188BE1F011FB5024909218433152271280020013110261148A142836288C61126044424982648520012D24221AA484441840083684C224888C810CB1 -:80F3000040C282D0C2292628140445F842B6400C282C14C1238481222D128A11514862A04843C1228301602445E814D1868812CC182AC81884848C0480C4281AD284A52518412E8423014C22261408E722112041B328C18890226F754342287319D412D64884A14200830228444712842230452002458A8303A02124817016E14235228E23 -:80F380002138172284512A0C81842170A40845AA211442882E88802461282281F0D824404204180047117B1248460489011258244810019B4A00444A4229C42420440224842112000022004E28480088218C011E4144C025A01482487F324E027035B82261C416D1927716A1242FA1068C0244182A98422604229368844C41A442224B2125 -:80F400002CE18832585CE1253228A123E116819224C442288514F21248C82828D21484E9F27288A0416CE388E38463884AE2F50D45E2410211258112C42840843911811B418384C41419D41A014A1294281F22D448D881B84878240824816528A4822824C0119AA21216088E2422CC028C5422844A21084100200870C3022442160210C44E -:80F4800029204391114A811484054E142A811414AC148424104464453C0120033244C04481448741444481C02422A2D0A444412401108452841441DF8602221001411B21414440840889011392218800107224B111341322930A268854818A44440D1200144A2204208C32422118839482842B8420244222844108DF41034015080040683F -:80F50000A21826284196111054413011844C6181846E8441488C4182A242902A18464841220112182913C82448706841081C68414228256481811A021425F8CFE52064821A942C8110A22180120210188E912844216A012121841306531401241F41244148031C440100008F142101181418211424450862408285A9947DB1200441224921 -:80F58000212212048DE24C18A91424422448801192688021024D42A0811218212412481858C41042044961284F18D2480A172490111018E2442184016088E0940E2C1141022064D11485141168428082C1848249C4248421468C440E8302A415C8483AA848C28CC244450828852412386830482183843148B048216984869114C9D8821966 -:80F600002412F45A4B24404241021C0148124180041041088941091011048501144260120060410011446220061504128018411C120281C041419044842F6B032F18215886137412298461221008854249440884284666422200108848D814081211811084F41422624F828441F8148236823214866121891281111448C41A4581450E25E7 -:80F6800015F231444008484482450842415A284124E211128429012112522271484C054A09002882460181842C810568480013480A4C84810243A112880060882B12244BEA3052C71A658412F661198351414D144B44298B8655452995191D14247F64352CCF44B124D2119199489D2A484B6911BFA1B424F228421A34551447411E64CD74 -:80F70000213283F56624521F8EF24565AF8898213A784A798C7246C49A8F461238214661442B1D87D2AD824FED4A62323F28D431D127645945F624284A518A8FDA7B88F8191825091755453414323659223E28AF15558845F64E25C6F45C198D922F82C131188CA31C2E14EF45A1127941F44C144D748371269E8C2F2B981427A6997211DD -:80F78000E251E52171DCE481F192986FC1F11CDECF8151C44F397644F437538005878187428D181AD651B12CA6233721471142C3F71A13CD289AFAEAC8CF44035E3C2954C14F45F4626817824BC21574416D15623F3DBC94588C8D68481F247448F1221A6826A85889C35589F121668B51CE59583D88959942614F44A464F022A281988C0B -:80F80000F18444A02520012044384420042200408144010044008200801108284128182840088418200288806881888028832882A842A04B814F2A4CF333122FB6F13A3A2F32F71CD8CF17E751F55557AFA5F546ECCF99FD797BBFE7F54643AF84F545C6EFDAEB63F31311186D52CFD3F714117FD456FD7F2AF757514FE5FD544727263F5D -:80F880003FFCE6266FCBFF3435DF17D471F4711F7F63F336644AF6D4E2AD68BF6CBCB2FFE9E1EF8BFBA2A2ABCD5BDD3B49EEF2AAFEFCFE3F2FFB36354FE7F34C243EA44F2576BD45F333123F33F53F3AEFB3F35E5CDF57F76D79DFF7F77A3EAFECFCDACD9FB4F47B68DFB5F54B58DFEFFE9E9D8FE7F77B794B76CF82F36F69DFD1F4755594 -:80F90000DFF6F42F66FFD5F574F6DFF7765AF8D1D37F7EFE96F4CFD7F7746C5E461F73F51F3EEFC3F2485AEFEDFF6A68FF6FFFBBD78F6FFF7EFCBFBEFF7BFF5FADFDD6F4AFEEFD72FEAFAFFC72B27F47F5FCBCEFC6F374FDCFEEFFF41B343F25C763AFE1F12E3FAF83F37C794F41F1797FAFA5F1CBEB3FD9FD797BBFA557BAEFC5D5FCF1E7 -:80F980006E7EFFB2B276E642D386F436751F53F7657EF7B23FF2FE73715FF6F6787B6E52BFBFFCE2B72FC8FF24245FD5F561531F72F7393F6F43F3484C4F2DBE36F7F3F76BFFDF5FFF72B4BF2EFB5BA85F4DFD1B58CF2EBD28FEFCDAEFB7FB3616AFCBFF8E9CCF47DE6CF13593343F25D733F31B1EEFF3F3BA78DFD7F71C7CDFB5F72E2E30 -:80FA0000FFFEFEFBF99FB7F75B7AF5FF5F5CCFF2F34E5AFFF7F77E7CCFC2F126187E75DFD3F7EDDEFFFEFC2B6FBF97F7EC3E9FB7F7787ABFADFDE2F7AFC9FD7D7C4F47F574525F72F33D3FEFC3D3E8F5DEFE6B77FFF7FFFEF2CF6FFF7274BF3AF95E3A5FFDFDFA59EF6DFD7A7EEFEDFD76366F6DFCB6FCCF48FB34BDCFECFE1739002042A6 -:80FA80006812804108841484341648A541A041850485044A0228902811811890168118901400901440021C486832841412348424128112200882AF320F145014107811044CA2128614024A0181418D823A24241232141445581861144B5210C2218C2801C04228148C62241E284342D824A12142288D124130148141819082168869887FE6 -:80FB00007B034F22F4112485F3112487241F41324E1D2CAB141D24AB9419B24A19F54A9153F24AB15B422F147924F842914F82C4954FAAE414F8244A16F1244A87194FA265594D4ADE24ACF491242D531F4952281FC932481FC9B26AF18124AF24D141B24AB911F24A9255F84A9243B34A39242B944F82B442F9B4488B944FAAF4CCAFF065 -:80FB800026481E44AD411F41724AF21124C7241D288B141F41F26A961D24ABB449D63A9945ABB45B4229F934482D916F82D452F9A45A1CF124CA1E816FA274C8F1241AD655949E216DCA8E282D5B1F4D925C1F8932421FC8B22AF98144AD121D648F44F911242DA25D688D924B4389B824B44269822F64698BAF44E12AB18C0B828200000D -:80FC0000000000800200000000008008001240010080040000000048000000005012F062D314164146098022C22425318C80384841486B6127222602854434181A1824021818444598162C0898A021166119D021C22CC3A28184A04823F2528889814904107818A28486A84A22EE5F2032B3384799671116151BE344F22251232182D818B8 -:80FC80007491041B49128B122AF5211826618281114C024B2413212422C214C44D312150C245420856D214A2428F68444849E228D4A4048B828F223481448052584978BD0F126F2CE381321525E412511A4427522D8D612850143C6F461BC32D3212467C31FE2811863818136248121E645361E42038128E19CF3221019B18491451421EA4 -:80FD0000644D814864CF28C4232A88715A04A8A48609248CC8C12721CD47601211148CC81144269221421A8621B848C848441221902832003841200200E0412242140422131106A3C22885A22183E28804848F24E188C48241812A0447812B84228D2443FA34DB001A0284224003426014A084008488222100004800812001802408860445 -:80FD80000082881504400200850214840010844808F0EB1D104511085863010000911522D4120C1144818AD24822020042274289E12228941883024812204288F12458988C128204A72880212414F218C241861218242208B778102402A0212110220410612424C28414248160C22800008400218480280400849018128421406228400828 -:80FE0000422186022484448100B7DA103111818924341414006054811B824814803824200A002905C8274283A12948121D6800478980029AB46438852820144218E422814441E8844184188488823812BD453023100A4461D022C23285212A0421840046C61580E844C841644582420820C488212B42001100C0282301200162A0412D886C -:80FE80008122C062B08841B8448142F276710080410414004042088214302112182229912200C0481012C42844271260814115C2124151214142126130481824000021A0249062821E44888FF90A80011502811214150811172294814825081481628418000024226400121028228242381980088125080084444C4408848122184008DF00 -:80FF0000E24A312318A34105411217221611BA8862162D8885815483D0617418C1328B284A8154244D4A103224C7224217A21889514826C1216952848711A0C11245628146A834701258428D442210E884E2A8C278437C2488F81C4C00005026154802831251124003812218126C820443480120121802452248A22400290134702C02244E -:80FF800084000042860884212A142201124A01BF3E0D004008440000140000000012200200000010082888000012244022180840185281002400840040F2E1B110D1520123111111011D2810185181450820684824001021627410084924112422082B1843D1124861288830122860212411244001883014304888C122EFEA0C3011241807 -:020000040001F9 -:80000000100510011400008018040022141849844808204104222C081282400220811A28512285111213010018848140582257EE5089AF44A444831401143028504C55B42DF228242200882412242552221AC3139AA888C04440D811D211187198588CAF14B441A49482254202004554444B228B2222801842042C348265A213CF210B3053 -:800080001200214C0100004001141012080000000040040000000000000010010000000000008F2705818C2484041021024014E448722881224808005022102291142AC88400181413486188818C2484041220024016C424378228008112002490122F1F0E84E02144018011518114924480220800002012129414828E810081284041029E -:80010000A48004214112002450418052810000001002EF770380040000004044810281000020180218800A280021140084804422013410120244800221100800100218BF1D062100180020011113080084000080080000000000001002002410082400145021424008000000F75B10B8482424041100004555444F822A26060000242542EB -:8001800026019604430822501111118558888B4452420010420245544C4B222A362100004002241AF1CC95008D184C8404000082805844112A0281840000242981A1112A88080040521121508848C8240010020045042A4202442002212512F29876241800000014004019111A01C084120000112828000022200140024C1882C2120011C7 -:8002000011114018080000004044F474F8002001238261110012000000000000401404812244000040020024000040022121102801810000002FD50F21001012412143482119718111234402410000004742441382022229031200106249822D2223816122100381214008814112220000DF5A49228121711203410014118881401128584B -:80028000888C08A0880045014B226042100840022121405222C012A11003213181467B4A012508000010F448610023C11480A2111B1115019815C18189784878810910880180124404C028414504228048C2822400185014242124241543411219810185080010042FEC0A6F22F212222E122B11122B11C0132592822F31F111119B888E32 -:80030000898F84F888418F8424F4414915C1419558884F84F448444F42B444F22424222E2480524445E642F326222D222E122B191AB88229C8122592831E111F11B189F991898F84B888F44848424E4880548885F844484FF6046F2252262AA1131200182592823CF1111319EC89D988B888A44C4214158154819588F44844C5B444A22291 -:800380002200405444286F22D226A8123AA1812B8882822592823CF1131119EC897818B888A4444200405888483F810B48420000008024040000000000000000000000000000000000000000000000F09359802484240420240400000000000000000000002024042084A4444200202424040000000000002FB80B484A04484200420020A4 -:800400000400000000000000008004428024240400A044004200000080088200004DB1800480040000424242000000000000000000A04400800442004A040000000000A088820000330948420000008024040000000000000000000000000000000000000000000000F09359802404000000484200000000000000000000000000000000CC -:8004800000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F093590000004200000000000000000000004848000042000080842404484800000088820000E0A40648420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000006D -:800500000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F09359808C -:80058000240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000B6 -:80060000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B484200000080240400000000000000D9 -:8006800000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B484200000001 -:800700008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F0935980240442000080040000000000000000000000000020240400000000000022 -:80078000000000B50B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F093598024044200008004000000000000000000000000A0 -:8008000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F0935980240442000080040000D7 -:800880000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F09359C5 -:80090000802404420000800400000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F9905484200000080240400000000000000000000000000000000B2 -:8009800000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F9905484200000080240400000000000056 -:800A00000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F9905484200007D -:800A8000008024040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F093598024040000004842000000000000000000000000000000000000000000BC -:800B00000000003F990548420000008024040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000D4 -:800B8000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420054 -:800C000000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F0935980044A0420040000000000000000000000000042422084840400420000000000000000FFBF07484200000080240400000000000000000000000000000000000000000000AA -:800C800000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B484200000080240400000000000000000000000053 -:800D00000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000000000000000000F0935900000000002004000000000000000048480020040000A0444800004200008008200800BFAE0548420000008024E4 -:800D8000040000000000000000000000000000000000000000000000F09359802404420000800400000000000000000000000000202404000000000000000000B50B200448420020240442000000000000000000004A0420240400A04400420000000088820000EF5B074800480000004242000000000000000000A04400800442004A0442 -:800E00000000000000A0888200001FBE0548420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548422004200442480000000000000000000000000000424200002004000000000000FFFB0C80048004000042420033 -:800E800000000000000000008084A444004A04004A8404484800000000008200F03D2980240400000048420000000000000000000000000000000000000000000000003F9905484220040000480000000000000000000000000000424200000000000000000050BB00428024042024044242000000000000000000004A0420240400A044BA -:800F0000004200000000888200001FEE014800480000004242000000000000000000A04400800442004A040000000000A0888200001FBE0548420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548000000004820B2 -:800F8000040000000000000000424200002004000042420000000020080082828FDA0720048004000042420000000000000000000048480048002084840400000000008800009FAC0E4242004200004820040000000000000080840442002004000020044200000080280800009FA904480048420000000000000000000000000080248418 -:801000000400008024040000000000820000DFC506004248420000484200000000000000000000A0440042000048428084240400000088820020F8912C0000200442424242424200000000000000002024A444000020042084044A24A444420000008A280800F03C62802404000000484200000000000000000000000000000000000000CD -:8010800000000000003F99054A848404200400004200000000000000000048428084A444484848002004424A040000008A0888888888EFF7070042004200004800000000000000000000A044424A84A4440080A4444A2484A44442000000008200F05A1800008004000000000000000000000020044A8484044800004248428024240400C8 -:801100000020882808001F4807484220040000480000000000000000000000000000424200000000000000000050BB004A044800000048420000000000000000004800800400008024040000000088000080B8590148428024048004000000000000000000000048428084240400484280040000000088820000BFA20142A0444A0400009C -:8011800000000000000000000000004248008004A04400008024040000000000E0AF0A48420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F9905484248004200002004000000000000000000420020044848002004202D -:8012000004000000820000B0B50148000000004248420000000000000000000020042024042084048004000000000000B0750E48420000008024040000000000000000000000000000000000000000000000F093598004200400004842420000000000000000202404000000004200200442000000820000D0530820042004008024240470 -:80128000000000000000000000A044004242000042004200000000888200007FAA0C4800480000202404000000000000000000A04400800442004A040000420000008A280800F0CEE580240400000048420000000000000000000000000000000000000000000000003F990548420000008024040000000000000000000000000000000013 -:8013000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F9905484220040000480000000000000000000000000000424200000000000000000050BB80240400000048420000000000000000000000000000000000000000000000003F9905480042000080242404000000000098 -:801380000000004242000000002004004220040000200800003D85004200420000484200000000000000000000A04400424200004200422004000080280800F0FA2F8004800400004220040000000000000000004A0400482004A0440000000000008A280800F0D49B802404000000484200000000000000000000000000000000000000B7 -:8014000000000000003F990548420000008024040000000000000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F990548000000004842000000000000000000424200000000200400000000002008008282AFDF0F4842000000802404000000000000FD -:801480000000000000000000000000000000000000F0935980240400000048420000000000000000000000000000000000000000000000003F9905A044000000802404000000000000000000000000480000000000000080080000F04BB2802404420000800400000000000000000000000000202404000000000000000000B50B480000FA -:801500000000480000000000000000000000422024040000422004000000000000002F57044800000000484200000000000000000000200442424A0400200420240400008008800880F8F4F78004004842008004000000000000000000004842800400004820044800000000802808008B7A0080240400004A0442000000000000000000C1 -:80158000A04442488004000020044820040000200800009F9D4D0184008CC1484149E422247824214861484C0A282C22E121120820083121883121889881882042490184484548B82638A41400C4C0224C420624122051828FB20D1416D381D129D4411464862648F424418092348415D22542341E57A2881B1AAB1896F8421249A81A1E13 -:801600002533F118849F48B129C12986446BD2113632189DC25C1CAC4A4B5242296443325C2378615684248B121E2E6AF12842894128F56AB80000800148842C2268128A3221601841C01854239111848341022822147D8282119312480A80820121806821464284020028E4008D24304A218981F193A14061211941924800483041448085 -:80168000D14808112C2212082528082B41411004124321A28144112685C211218998880049C484821C819111896814284489122207890189D4AB084001994411C42826440400000061641A826A221282408249B11248581882004048011142C04C8924022841C0244110024418200124E0E60E4018084483140448260440044D222200009F -:8017000082008882152201008C018288008484111744302481224880021004268201212200247B6F000000000000000000000000000000000000280000400800000000000000005F2B0F19414261C2114E2114154421C48129224102302820220216042C728428022E18872286D842C412224CD421210418162C94192495145484261852F7 -:8017800028701802296224248C0849A4812CF82A38108441522148831178421A9828121421256814441381721258225C059241482443562298E082482821812212022642189241AA219261923C117114938420118601182284412FB44111612115C22D13F42148248754A18394812229119243411782D022211263418828274C28418D1224 -:80180000872287288B48802321C14200ECC242181394A74145E88211538363D1864982624429110A43B61888D86D044901002112850114282C11018400182289024E1480111448A2242322094CC21A90441932228021115881608122198628011124C01200821800412FAE0900003411181004188424009260888112101108608242211E7E -:80188000242144222888122B8211002D12160448002412872480015084420010088F840A1B423D1218B014C2187C72249A58AE581C24C2898351141558C12981D84178212883C2814732001E24821E2127832741848903186C7821988C194A6844C3F1D4222E188C240A1221A3E122C832433248424982064E49805612002289D125119418 -:801900001CC6A814C08812411E89159882833894841484824483024C32942F31922C412688092B1A74118522628148813E828C2104462A512200209648404408EFA604141223014D131422AC22A421118C42434801448C01111C828342C121212C242102122B129028188068824CF8811241411E44468412B8820380C1188E2247832504F4 -:80198000422268F0BB1FC0287C02482424182100122244E3561A1C8228216121111008278E284184222002184311B122E4846282144C5424B04463924C616919C12200002722D04A41CC648185F2688A508212111B41008416044C948142CE1422580046582B2082A4122901458191661D86100100002784001221C421902244C68A429836 -:801A00001290428008288448221F34064830182841CC9141911C4288844141012444612012D884080084141212168251825082414711241D84120028944B4124284008812FC11204C921128201883FA34E0336158201C57241C219114628A8218E52142D48308487443D1828931214088C42751463C19E27B02351822C3114644B412259C0 -:801A80008AB1145426415C34251AE22A21181A7A1298364CC42216BC1662423889648ABEAAA042D0189121452291184422444E1148144D481C31212522412211E2888443A2842E88882A04180040186132101A017028E281F2481244211F8104008425028884A14D48005FAD0B200100205248448068883088151824382886F411882D81D2 -:801B0000448215144818413811824012088064229C324485C238D0826324264851821800448C43C81881282280F2F1DF0011E045420481001E84130110C584880028224119140218439812240016011A88243311A124152892818308178848C111000024009012458811F46D1600615012501428135281182119A3818814211CD124618180 -:801B80004400181001005018C04800111AA81813B18802102118411102402101801288014048F899FD80829248504812449042148B242426044941022531218249712851213E42411C01A6C182428C084A1218484881021B2410D22101B0414996480028C01821288004242FFB0F118140C831005C220211149441282484824D831181C6B1 -:801C00006889458118C81200200250821414248142208121341800272184111442002250188041E1D90E16A8242C2704288523018078822C8221212A31241212211833A28242400122184364A180A338221800244D212B822D21282C238184C12820E12221120212898122F2C9B400904800212180C12A49241412938815E8180200008062 -:801C800011082061184A88111288784222042C4882880482883D888280820528820022224810F8A88B209313288436681148184225412AC281122C02601824818B81232892481C8618B2188C52188B481A223A32412221001528981143942212281316648114128120215182286021CFE60A94441AE4111241140584C4184C84042194283F -:801D0000409824112A5122244447144B84671243A12125A1481CA1484098A1C82E814A088304488289C414484AA21448001028283122708B0E266247167241117112E4C2525683D44871C458A19E816D886DA1B7421DA18C7838FE87283B9128AC3B144F44F21C81124D611AD131E8F461A3ACB15AB421062E331F22028F36F6A284841EC7 -:801D8000E2242AF331883914F818511B1128A8278236C8322DA8878236E922F2D373141E21B12AB216E1129325F021222CA4211DD1299A27174199C1831823B285C994B48C651B2D383924D813F19A981F6AF838488B4BA0A82E2896F1311112AF18B84EB281F851393F397221F84B299D43A7484E3A3E181784E041F1381281A1853838F8 -:801E0000527018F82D3890114D318D188F82761CCC11F7141E185D3857B8AF21F2E85183E61861EB8638BA5F78C3218733C7489F5F18F161C78D891D4E4636212D21CA91818BD4AB438E92ECE12CF6838816F8A1CB84248B942F5CA1DA2F89E83465112F440446A146842C832183C17438447F69040000008441200200440000102808400C -:801E80000400000000420000C048C048220084200148208102002021F4FCD4143E123F97F3193B2F12F62C2FBFB3F17B5197128F63F241C14F1EFF6121BFF6F48A118F18EA13F33A19BE989E963F92F347D9BABBB1F9E1E33F18FA81135F15F561A15F17F451415F76F36AE22F2AB36AF6BCA62F3AE8925A11288F2CD46EB8DBFC5DD73FF4 -:801F000083F72361FF33F12B23BF57F441111D612AF7A882A1242F22B392E986A7667E62AD17143E323F13F7393B2F13F23C2FBF93F37977EF62F1121E4EC98FFEFF696BBFB4D47FF1173B1FB3F33A3B2FABFBBEBF3FA2F2D7DE3BBB9F8BFBF5E77D299FB1FC55433F37FA77733F36F6773F3FB7FE3232AFB1F2564F2F3FEF22F61A181F26 -:801F800012F62923EF63F31B81DF53F21179AB62AF67F129339F1757911F11A1328FABFB22222F21F13A32AF29BB4AA7772F26F52151F034362F22F73B3B3F33F22F2F2722BF77F52F2FEF67F65343AFD7FE4941BFB4F68E95CF18E812F23A9B2FEBF1B297BFB2D357F1FBF81B775F7AFBAFA3BD82DFD4F46122FFBBB253F47537AF37E225 -:80200000A1331A4FE9F8E2E21F1256198FA2F24A6AEF6FBFEAFA9D9FBF97FF21318FF7F56A72BF91F2415146A176AEA2212E222B329AF922382AA232AF71074F63F33232BFB3F3332BAFF3B223F27977FFF2F37E7EBFB7F77AFB8FB7F75BDBFF78F1BE9B8FB2FABABB6FEAFABEBF3FA2F21F9DBF8FF779685F7AFB272ABD4BDFF5F5F333FF -:80208000FFB3F36363FFF7F77A6B2FA1F31B2A67612F2FEF23F31A12BFB6F22A2BEF63FB69E1DFD7F67B798B33AFA3FD6872BF95F711191F15A5778FABFB3A382F23F32A388F89F93A383E328FA2F235AE4001186012844D13843492266189248214960817816C224834818113A8245048118129384823123822422D81C0118414C093600C -:80210000221E4826031416080012002800F04D82A0181F4152221638241082B244C128241A52184026C123860845581892206254354A84644413A225A025214280D222086AC848218CE214891288828144013826186281A3A4432894BF78072D421F41522C1F4132481F41324E1D2CAB141D24AF249921AB9453F14A9643F24A9543F24A16 -:8021800091478B2DB14F82C4954FA2C4854FA264116FA264192E5A96C54ADE24ACF491242CF59124E5F2912483F4916CA3F6812CAB141D24AB941F81B24A19B54A3934AF4439242BB4478229F934484CF9244A7F34056D4A1F41762CB21134481F41324E1D2CAB1615D44AD941B668B915F24A84228F543924AF147994D812D282C4B56F12 -:80220000A2C5954F8AC481ACE558F2245A96C14BDE2545FA81288CF59164C7221B29411FC9362E17C8AB141F48F242141FC1B24A9A25A93934AF4419B4427B2498922F83F442844FA2F564E1008004000000008002000000100218000000400100000000000000000000001002BF7B07114712111213110385D4254321289111B0826161B6 -:80228000461884E8C88241284C18214204AB61CC22011A48F812222071221808861148C3482C011542181592428A054981048190284F9E08288A012641584815022192601881E511814243122811014D18412442811F42412554A12E882C021442142486025223A183982718001A0412248125022D2A26486411242FB30D136246C031993A -:802300001101213D2411411C9111141ACA341518C688264442881942B18213E441723CE144D281B181221B1A297441421A083C011B2929C19161342A051821A94492148F24C22284128721CFA60330111440424C41CC12928882855284250123042196C81170485484801458214284508240A22121122282218A9418F04882001018158259 -:80238000C4924002814120F2CFB7200265032C01182814111C01A048141002850130144251104304814528044241422C8802440063B28114283848923440264104899244188022F2D3FC244411165885D411508116A2858988D1127112711438124498641AEA9885244978840810924429493C3223B3E211B44462112A817283081427430B -:802400002E8622241314FA188213688427A24F261174A262424901F0EA97D04212811143066012B0833511183C21512424A08184B8481A8415348C140049341C89C4122AB5B4C44448222264871890234E148D2680244421514152442B144CB2A224818122F233F100505AC1934181113811C08810C2C19921410454218F1118845818242F -:80248000101452288844230221604A3381210240B48322A828843F2811388A23582A89C224A164264404F0B247401812591484101C08890121168418F8188190128229140148188128A112118440D4410128222518594200C25410C8828C824231421882C0141622E288445428DF720746C9142D2421502813246882B048114834241682A2 -:8025000024C82412282168382D121024C1442C4852181211002146AC281C6244430222132224018B24444024952C882824288A81F29F47301200364254141A62482714618213012111104203832182488C34248C04303248224058484100002B212901304221110048122312E22408818904005F6947B3414154C25C431CB13754481782BD -:8025800087418C5C1A124181C8803382AD321382FE1844469224837412E8413493AC6492439118854404448C127642342670258224244918D814D422141492AC2978280283C49489B29A01241A643210421C08272480214122C81317812D82511848002810B824880828210044807222021C98212A21A1846032843428428021A394484C92 -:8026000021B148220AD0F40C401442744801118C0480114201141CC1128460138A0142484B2C4B4812211820482882028AA11231430C9048884C34441BE142009741006301804118B42871C80B1312814423025034184400223881441482D08244911421008429886284244CE4444368848A2614E181321A44411222890190A2C88F440844 -:802680001863012AC428422218823FA90A25C212D02244012D4918000040840144C48905001961428002188B82178A89018F4438811684418461821EC816CA24008184008448CC914C28274100418516F456C720A424911A021902A952481952492D634414222E4189722212543280D2284488052C9844804421488101001124444A024422 -:8027000041131202AB1200228001450248C0423EDB60284840088C119441F0831840081C08241214A082418122BC082A28E412384244321014A82110081111141115B4832188E4115821883902188400438182E112F8F579409418121524015230114582111121911584141218421418211849C9428470144188642118228AF44428118C1E -:80278000A421288A02004682A924841A046C2892E270428A62412342B67E0348444C0200222002E02208218008421344982288203221212800224CD88242114482281484088085C3284951218008104218342812002914F8C3561012512818490485865118100812816161C114C48031221F8861148001142C381515082CF844138445A2C2 -:80280000290011C11902118F19029011111281304829A1282C0281216BC660C1504181846C04442D4481D0481198648100168612C488412532841880D88448240848262118441884542246682564982C06C01646826284230660C463150421F01D44244F243492474149B1126421DB614D514511F411141592225C6C3143741A6A141E4566 -:802880004AB692A182167A12ED1AC2442B1245E544588A5AB14CA1A2EF15B448F8C4721AD368B124F219245E427F25C2843F81227282F1A1A21DC22F4C5C432BD287C3C5D2E885E7269224C752497B674261428557A2177485595884521FC5D35341E81498117B119FC2711881F119142B14C7324F22F814181F12B18DC4868B2A481B2E1C -:802900004F1B7541B526E8A832842E12824034333B9165F925142E4D4B1B4F72C4861E4821A791197118D92452242F423236E7872B112E141E4A86FCDA84D012B165D519723A38652A7442772B1EFA2888A5F23A28C54118D6417A25F5862ACD2A3F8158194CB248EC26BA44E42449FA128A85B8A4FB894F3AF4184C1FC8FA34761E84D7E3 -:802980001E948FA8A44C8F888291218B1CDF9DF761925AA53C85E82675189C525ED84A626845344818A7266DCB8092142849810228803244284A084A48A8842288118120241808104194118110088100228426416812404108122641486181A88488908848A81A043FCF4AF243213E3BAFB2F23B7E8FE8F22F6F3FD7F77374BFA4F4AAA6B3 -:802A0000FF96F6CBD8BFEDFD53185F4DFFE7F6ABBAFF869DBABB143F9CFD6D6D1F1CF971A14F7EFAC3133F11E121F9CB829FBDF88B97A5F6DEE68F8EF4A8A62F29F8B2AA8FB1E2B9E9A1F1A6BB6F62F2E2F32E263F5ED233F35293AF8B7984F845EA4FE6B6C6E827B192EDE8F2A2444F4EFEC4C44FF774814CF241255F7652B9F7E4BD2F9B -:802A8000FFE3F753541F71F17A7C9FF3F3BBBD9D1BAFA7F7C39BEFC8D8EEF14A58CFA2B912FBA8B27FFCFD4F4D17149F3CFBE7A73F36F2595B4F6DFDE6E25F7FFE5347AF77F6F6F6EEF32FEEFFD2C62F6DDD75F216145E5A6F2CFD22262F2EEFEAFF73757F78E72CED69BF16FDD6DA4F6DFDC68C6BBF2F8BFFA62C6F6AB4D6FD9C94CF6A62 -:802B0000E13E45F273566F7157EABF61F12A4C5F64F653543F45F12B3AEFECFC1A1CBF82F35B3A3F89FD191C65F61A18BFDEF58A3DBF98F8B3B9FFD3F3D4D41F1AEB7EDE22B862F66467FF3DFDF9E9DFDAFFECCFEF6FFECCE84FA1FE56427F7ADEFDF2B5BF9FCCF8F9EF7F67F6A7B71F4FFA23B43F74F33333BF81FF951DDDCCCFCAFB9409 -:802B8000D44F6AFF56748FE4BB72F326644F41F1A41E3FF84AF273565F71F73C3EFFE1F1B3555F65F773345FF1F11E1CDFF6F69B999F3EFF5A3A3D4BEFC8F8CECEEF87F7AD1F7F58F3E9AB7FDBFB3F3D4F4BFBC9CB7F7AF862628FA7F7F577FF37FFF9EB7F69FDFEFEEF6BFBEDFE6F6BFFF6627F7BFF1D3F7FDBFBBDFD5F7BFB73773F7A84 -:802C0000F9F9FD6F43F543F71F33FF1FDB7FD1F99FDF4F62F37E3C6F47F3AEFCEFC3BB72F33674CFC7F7AC8F3B96C0119016D022014D111E4824400134400744122008112048143248902861422B92816B823026302250249014124522098260890044128584440444F09E9610169118D01CE1414422511CD0280189018D1412348485971D -:802C8000448DB1128F5432A146048B216B4214D88D21411A02A0D211472296681215088A521A1966221B41421125E688D428234A220B823886F85FC4F024421F41F22C121F41F268111F41726AD241F26E111F48F66A921B68AF14B985F44A914F8AF44AB34B4AAF347B24D812F924488D914FA2D418F8244A16F5264A87592E5A8759ACF0 -:802D0000F49824ACF491242E421F497228F2912CA3F6912CA3F4812CAB141FC1B26AD981B24A7915B84A7924F84AB24782AF247924B84AF934484AFB244A6F5D044FA2B411F42C5212CB1613316A44CB121F49F42A848E4489BB84969A5F8994AA4B488BB447838D8563DA58F1265A8D914BC28D852E5A87482E528759BCF49824341FC91A -:802D8000E2A2F411642AE9C932281E2C29E8C8B24AF1112C2F46C82C2BB44F81B24A5984A97B24B8487924B8487916A8A46FA2B1CC048282480000000000280000000021008008002840010080040000004004000000005012E01F0BC0221508531601804181112128840112A48D838110C4644014880600243024844436C29288174100D1 -:802E0000C022002022880183622143180200D01CF2EB5190411B18242A014C91442501248420411FE8485381208192818922113481415991281911D84139282B81D0123142405C8230361608C06927888044064F2814382818C542286411F063AF10B1E141A8211D6419C144141814C34101C7348B21281651281E81A95221C9B224751289 -:802E80003485C3B825C12813011B8199B23648D82F21B54258862D15F012248428218B246388A24A4D12D02422318A18A4244216311A972D800425034044020021800930948110088800002004404814020022128884001800118100008E488143121214083024EF97082011021C11011A62141B411812A51104122D144838120042220045 -:802F0000444021B2D86282CA3222C01200108A1608216822122484004222188221A24624F2AF196051436213188934244F9162644002230685D1147444885C182094458A5284948B4822A3B428D148391460418484211B28248885A521008D4130128823162244E2C568822D882F22C428CBC36082E0490B15043B21301844DCA314141BCF -:802F800014244A111A1121A48183044A1124C244268144022A7195086668418C1E0A1902502D8C23041304422AA81440088B94A48F22A8122D882A8DA842222F9404184C0312469121D0248204298112514849341C6914810319841848C88822C914082E148A312860228059228800228481212B1270224282046162206422C122C1F0C99D -:8030000044D084016C028C426244921C021042B429218101478400800498200248460248118341943311453811280040048B12AA146849147048146C248420618840F65B7D248914417934210400524C9431484443465412440089611289189C18844328A5211148231392210012AC51482C2921018531118091224C02C126022280512262 -:80308000482604AFFE0F1922016041254598A400400888E088C24212124410248612444804188341C8448044A2420025010028210048212504008514040081C88F8145925119C1221D14464C57842E141661441A52827094011C42B21C2441044314B4284854484AA1211C51288B1225E48182342133741452283C2321014D2111181A969E -:803100006A2349558426144A5248182331488CC286CF74024382541C282E122004624081048CC4169668440016C82186B8480281224C8824945242485024122A81D4142108008429C128884002C048444F820400824448D7F16044492222149438291298122835481142312281211016180210086458647048022C42448201182642448864 -:803180001478120200A02180A1184784188A1188E882210AED7200218C84020028708104008A024346280A13122402130232882688342412004906004430448429044518621410588485440420024248E0A2F47C730018128345112101448C850E88800A491894814188844AA841008034882088A25893214821085024C42284528D42206B -:8032000024C441001092482A2411742408BF360613035014A1859428464508181E24422893149961100410942480014902121A0815482152144A08108808541684021400504180C112414184182C81F874BF2420C322868491121042982210022110022184A9110810084082C142403A1C246024004B212C2404255822420080D1844108F5 -:8032800041801898222240F8FF32008004C12C022C42512440A6242C864402C73440021008409C42882311983211A585147264280125C42842109488244244212081B422448401449012F04CDD50244C544811001001002A1888018885012008548200190811224C14051444841845880400C2421614020000812024C2141A2818C244DFAB -:803300005C0C828601408244024582F4441240924124D02464818512048181008091829012812112A1702304814227224449422832848504C430428422424CA452816141F085331484D041B4183221450130318C814214C528901140912190283046483890844A410880C8491B81534548810C14004091481A7262C5412F1112112651222A -:803380008129684286D82A28E23644A221A285D6617228F322282C127615F3B24416B222C24237842439D279F4162D24291BC82446B44882C2356E46AF48E226B4426221AB2256F622388512E641B1244AF6AA24AF84246E211E536CD41581E6C45544434464A427218F820D5E168F8D989466E2A94811F5C11449F2344115F41955256803 -:8034000086A554946F1C8639AA8E113B6E87D1633C49778815FC822CC14B8A8C0524414ED38B81CFE18459A1CD984E825DC517188885126C9441D1C9F12E2C212904149F11519B526F43A454474547C5ADA84F42A12229761F0146B61662938F8471145824321D232E188F24E3824163542C44C8C22668288D25C502948D48117084B8120F -:8034800021D182A118A7D21E8529F41D452B157E649116B442D42444D6E276422C7CC878683241AF2162841E16C78838412F28B2A837A42887E9CD886F990A8001004A0142800888800998224C299298228D952285214AA51214228691148B28A028A028499121B081021F8802199284288816088C44244A04801488048F5F4E53131F31C0 -:80350000512B39F6C86EBF75F3434B35EA25F383677F3DF55372BF6EFCDA5A3F39F166337F3FFFBA22373BBD2E2F99FBA1A115F198A91F18FAAD3B1F31F56222BFBAFF4B4B2F22FA2AAAAFAFFFE862EF4AFEE6E457DACFE27A26F36A677F5EFAEAEE6F72F3A2B1AE219F8DF7C383BB8875F74A786F26BF72AFAE2BEE6F74B122FF54544F19 -:803580004D4DF2BCE6342B331FF6762BF23B3BAFF5F74B2F3FB4F6436B2FB5F7C33F3F7EF7C3E2BF297BCA7A8AF2CF93DFB9F9BE2677BBBFC9FB9ABBEFCABA6CF6CAF91F18FAACAA6F27F643C33F3DFCB7E7AB91AFA2FACAEAFFAEF6577F3B771F1FF72CAEEFFAFEEEA55F54F6696DCEFB6F56F7C361EFDDF7C3C3BF8EFE4F4FEFC1F12E28 -:80360000962F67EF2AFCE2A46FF6F722FAEFC5F4D4D44F61F1E82F346F64F437773D22BF817348FE3B7FAFA6F67B7AAFA5F12BE23F61F1F3F1BF14F64BCBB734BF3DFC4353EFF6DD3EF29F9E2792EFC1F1F4B89D5826D1ECF872723F34B44AF1CECE3FF3F3BA3B6F6DF762E27FF5F767654F49F53DBD6F68F8E7E66D64FFD6F64A64BF4F1F -:80368000DB5CFE797C3F34B65B771FFA4B5C2FA6B472A267EFCFFF2E4A2F8FFB3EE84F49E92EFFD829346F61F13F773F21F31B3FA7FCFFD3F71A1ABFB3F35A5BBF67FB11123F36F6DB93BFB57D4BF35F437F3EFF2D9FFD2BF5FEBA99FFD3F3DC9A9D4826F12DAF6F61F4D2123F3FFF7636BFF1F1AA2A2F2CF562B27F75F5E3E44F4BF52DFF -:80370000AFE7E6FF62F64745EFCEFED8DCBF47D355FC7A7D3F34F65B78F7B1FF9555EA2F63F66446AFCAFE7E5E2F8FFB3E7C4F4BF9647E97F8C011C011842941E81241186481144081041D4844848504441287440060443048004181180000108454244880442248A14120011A44A448852448046B8120E241322216F44E111A7242128128 -:80378000813622482D1219D422014A11D1220118844200241210182251A2812C3441581285022542180889012B84288B14112544584210628229219838223F8D052CF411248D121F417248F11124EB141D24AF14F18124AB941F88B24A3985AB9443FA4AB143FA4AB5478AADB14F8AD458FB244A1CFA244A8F51F2245A9E252ECA8F59C214 -:80380000DA9E24ACFC91242CFC91248D931F497248F19124A7141FC8F24A111D24AF14B911B24A5985AB944782AF647924B8427924B84AF924484AF9244A8F3C05A41D648F22E14136481D24EB144CB24AF181242F46F9812C2BB45F88B24A3984AF142BF84AB54788A9BB82D44AFB845289D324DC48C2529E24ACFD88243CED49C2CB1F18 -:80388000C8C2DA1F48D624F9916C83F4912423F4812CEB141F41F24A841F81F24AB45D28A96982AF447124A8144782AB9463A2946FA2F12EE30082480000000000280000000021008008800140010080040000000000000000002501BF7B0E1001502818803242822C0134207428041800100400000023049024604A1822281489C1242021 -:8039000022018C21B2480142A622043028208C21F281281033A23016485D2881805114111B8184130480918410047270484432441285240216282411C811424068212C049C0446C8434820082144001A449684875214641F7706312F1C026331484D288032425938141B818511A124898291140024723054244328918C28231438412281BC -:8039800097425262264891482992412218116D4828AA05424C82044A61E245F22844167112F61C3A0000403211818001344082044120084110048480040020011604920020911244813048481810082182210080388120F2DF6A10421406005041004A286814004188C0838A44212804100410080040021844A0282C088144250200400809 -:803A00008421848100828564885F510B4E25331151121042B14211718201462378C2D11418528323184CA2181068C88618420241216D288800A8C082822C21643188A18C2881A482C014216381C8828281B04481082E532424572134004072544141A1848288884C584284884C187212014884240021A4248400200880282A341323186CEA -:803A80002812480064504280988200988398882F75021D641014012111408208137443C24111241D8210A9848882844C9888410044302482408222C186809182400AA1002A088C018D1282848181C04444F0E5BA60C4501484688042820220C48480820200248881800844491544C228200100401802448A321821100824861C02B0416286 -:803B0000C1809142493484F098B68002283504001110A868C04442288F2138882008A08238298108002212006082124827848144123084850110014449210841214604A428C01AAFB6051164842444141218142001212C084224852182024444904400840085128411120400001440140238200118813100880048F0A5B9144E25644D2837 -:803B8000B542440116C1218468B08244028B2186581A0082C3E241024B84A014C42682421884D1829214482512084CC1A1C5521410B811022F88311610B824544A496429E04402D0830880C4414462A01210029848A048A04821802A12220882908444008C01290100004004804918020000981022013048E04448F8E2BF00460C4088146B -:803C000048042F110C0048E06884048024422852862942024140489288240000829088182140081018088018082484301820F8E23114006125240210080021481CB28204208846220400428022A82441211230848384215424002001822181250200001082280440F8ED5440010000000041100400000024002100248120091002248810F9 -:803C8000480280289882000024004440040024F0225A1012134211626422104386C242001121D024028C02490220A22860220028002418460220044810022D82D042140444C82129082D82448841F0247400004110146211244184882480020000811008400841001008830824008048C81800000084004008008301F05A676044508448DC -:803D00005110694469848844020080022C021008C18088481214182A180A4810E8280484008608004C482808400884100821126F86010028144001208204211480880862A1A228A2290686022A8422224262441012E2410448100441004508E4002100424011022924D88C0563388100860214001400460213042120141808812221502207 -:803D800010281808814022280424408A484808444042480460888440065C01AFCD0F22274448A35487400441241454881C022100812502100249818228110422400118848004200148E0A814C88441E8002504448481708202D54E9242231CF2474147284191463842344634422DC23561222514A222842BA283E4427228722282A2882D13 -:803E000022418147A2A7828954288829B4C20D8E8827244C4898828486221804C0484442214608144696185489F8A7DB1415F68145C506444E424D29645D24535418114344222408648F2406212D8848457842C42822235246822427482538844216324224100A44AD8288894CAA84A542022C18B88258C8AC58861AD8143D12FF310C43F6 -:803E800052A428E4B79215149215242F49DC22C28211481F18CCC22A243C228D4A2E28818C52482E822682D468AB268B8128AC0925EAA14194484160888F25B198A1488558E2A1A7A845BC88182658C4855224A318484822F87D4DA024C028412843848281969468880000800888488848A848802481E449822408860486048604862444A8 -:803F00002444A484844A084A18A484418841884994884B41F0E21234777A7776243FA2766A7A61E194F471732B333BFA7F18F18B891D471F28D82134826EE22F2E74AAD88AB4EAF8C8888F8AB848E66CFA6A282B336F67FEF6BCFE943E864F6CFD888ACF88B81EFDD2D26FC8B88438862FACFC96944F49FC84C4CAFC4E84ABCC2B4CAFAC77 -:803F8000FC488E6F4CF4C446E7888FC4FC888CF7C8236C444F48F8C442CF2D0E4762FFF2F422267FF2F66A4F5F52E482F2616335F5C7D43F5AFBEAEA3F38FE838329B622EA2CFCE242AF8AE2AAFEEAAAAF86F268688FA5F7C2A6AF8EB352F7D4666FCEE26EF8BA8E9FBC7D84FE8C8B6FADFDD6D6674C4B886B8C4F6CFC56D49ED2AF28B4E1 -:80400000C27CCCDECAD8A8F86AEAC7AC2BA84D86EFAC7C8EDACAD8EDF8C68EEF8CA854DEC4EF444DF347673D47BFF2526FAD2E7D47EFB6F64B432F44F497C43F47F62B291F14B6C1F8C1C2272C2F22BA227868F8CAC8AD48A5F848488F8A8BF628AA2F27F62636AFEAB6A6F874624F787988FA888C2F84F5D4D62F28F4828625F2868EAF68 -:804080002DFD929227246F4CB882D4CAD882F84AA88E4A25D22658E2AFACD48ED886D8C6F48A885AF584127FEF44F1C567F557DBFF76F24A2F7774E5FA7B733F56F6D7C63B4DAFACFC43433F3CB8E2BC62FAC2C22BC687868FA6F6AAE8AF8AFA28288FACDF22F63AAA2B234F66F72E6E6F2BF97EC28FB859E69FE8B852ED2DD966F4828688 -:8041000023E82CFC16966F69794AF2C6842C5C8A8FACF44A288DCA676A2F6CF4CA4EAD8AE57888FE8248A5F89494CED6BF8D0326011440022623412161124002244800240000002128299128291108810021100225424842088200248224822482200882003FF90A24442415044C1444484244128128482142024018088141001004002DA2 -:8041800012400858000012008D821008A908008110082184009F780D2CF41124C5F21124C7141FC1324A1D24EB141D24AF249921AB9451AF1439A4AF5439A42F7479A4F842914F8AE454F9A44A4EA14FA27458F1244AD6E1A2645D2D4A9E24ACF491242CF4912485F2912C83F49164A3F48164AF24D141F64A921D68AB9459B44AB924B4A1 -:804200004AB924F442924782A9F9244889F9244A7F480FA41F45F22C421E28C3F61128A3F41124E3B211D642D8C1B6489B64AB9443FA4A154B4A2F54F3A4481C73A6C8356FA8D118F3248A8D814F2261182E189E25B49E21ACF49128ACB49146F29128811B29A11B28A991214CD981D2489B25A93924A939242B9447828B946B438B846F3B -:80428000AAF55C724028880400000000A028000000002180018800004001008004000000400428000000002501BFB70D82001110114201248810082502218008005048211002009800804806000000000000000000888440F29FC5008200000082190211004A08002141000000C02600210010028810028200880000200494200118402140 -:80430000D1984C01C608144003144012142102290A2124104402301A218230244082180124812442240000200841200200850112C0928114216FFD0D00000000821982088160240080080010042440022001008241820020080000002004000000007F6B01000000421048840121000010020014000000000000400444290840240429018E -:80438000210000100200007F6107100114001004002880241884089840048281400222144218008441120000800100200242211022020000844FA60410011100424481410021801824082B1800908184002122114812004084410464880044002110C242002110020040F81339000000000020810248000000410000000000008400000011 -:804400008001482021020000220000002F650700000000000000293188002100000000000000000000000000C048000000424800005FA307201208218121250800811011218454422A2408280080020040544221000028404481D84202200200008018140880013F3D060000000010E222040000001008008A0200400100000000000000B8 -:804480000010080000000000EFE206008110121812480268214031138608412A94888002A8000011000000002200118228009048840000884914088001476E002800002400008400806424100200002002004054260000001004244400220000000048000027DE00000014008400000000000000000000000080080000009028200200C092 -:804500002800180000F063DF000000000000000000000000000000000000000000000000000000000000FFE40F000000002400000000000000000000000000400200000000000000000010081F4406000000000000000000000000000000000000100200000000000000000000CFDC09000000002400000000000000000000000000000006 -:8045800000000000000000000081F063C50000840000000000000040020041000000000000000000000000000080020000DBC40000001008000000484004000000000000000000120040080000000000800100004F54030000000000000000000000000000000000000000000000000000000000F04FFE0000000000440000000000000054 -:804600000000000000000000000000000000000000F0634900000000000000000000000000400220018200000000000000000000000000F0EF63000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000210000000000000000000000004759000000400840040080B8 -:804680000441001002400400218001820000120000000000000000280000E0280E00400800000000000000000000000000001002000084000000000000180000F09536000000000000000000000000000000000000000000000000000000000000FFE40F000000004005008004440010024004002180018828100218800884000080420853 -:804700000000280000B014010014000048405588281082044480022100448002214818808802214818448828842148408481421882041E148002211A01445C03000040010080041400000000000000000000002800008008000000288400000000BF7405000000004005008004440010024004002180018828908280018840080000288492 -:804780000000800200003F6A0C0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0021001400004800800221000028000000280048000000484004281082044400108204440010F2448D0000000000000000000000000060 -:804800000000000000000000000000000000000000FFE40F00000000000014000000000000000000800200000080080080020084000000002F3A0A0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000008002000000000000280000000000004F7D0200000000000014E6 -:494880000000000000000000000000000000880000000084000000009FA3F7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD8 -:00000001FF diff --git a/xpp/firmwares/FPGA_FXS.hex b/xpp/firmwares/FPGA_FXS.hex deleted file mode 100644 index 1321a53..0000000 --- a/xpp/firmwares/FPGA_FXS.hex +++ /dev/null @@ -1,648 +0,0 @@ -# -# $Id: FPGA_1131.hex 5122 2007-12-12 10:07:59Z dima $ -# -:020000040000FA -:80000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6AD6FF4000F8030A006AD6FF4000F8030A006AD6FF4000F8030A0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4455544455557475577775577675577775577765566665563625523235D2E37C2B5111155111155111155111BF -:80008000155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111155111000000000000000000000000000000000000002552222552222552220025522225522200000000001AA1111AA1110025522200000000001AA1110000000000000000000000002552222552222F21F11211 -:80010000122F21F112122552222552222552222552220000001AA111255222255222255222255222255222255222255222255222255222255222000000002F21F112122F21F1121200002552222552221AA1111AA1112552222F21F1121200001AA1112F21F112121AA111002F21F112122F21F112121AA111002552222552220000000087 -:800180000025522200001AA1111AA111255222255222000000000025522200005F51F115151F1AFAA1A1000000000000000000000000001AA1111AA11100000000000000000000000000002552220000000025522225522200002552222552222552222552222552222552222552222552222552220025522200000000004AA4444AA44402 -:80020000000000004F44F444445F55F555551F11F111114F44F4444400004AA4444AA4440000004AA4442F24F442422F24F44242000000004554446F61F116162F21F11212000000CAACCC2F2DFDD2D22F21F112124F48F884846F61F116164554444AA4446F65F556566F61F116166F61F116164554446F65F556566F65F556566F65F559 -:80028000565600000000002F21F112122F21F112120000004F4CFCC4C46F6DFDD6D62F21F112128AA8882F21F11212004F44F444446F65F556562F21F112122F21F11212006F65F556563553336F6DFDD6D6006F65F556566F65F5565600000000CAACCC2F2CFCC2C2255222000000CFCCFCCCCCCFCCFCCCCC008F8CFCC8C8255222004FD0 -:800300004CFCC4C44F4CFCC4C40000004F4CFCC4C44F4CFCC4C44F4CFCC4C400000000CFC4F44C4CCFC4F44C4C000000008F8CFCC8C8AFACFCCACA255222CFCCFCCCCCC55CCCC55CCC4AA444EFE4F44E4EE55EEEC55CCCC55CCCEFE4F44E4EEFE4F44E4EEFE4F44E4E00000000CFC8F88C8CCFC8F88C8C000000008F8CFCC8C8AFACFCCAE0 -:80038000CA255222CFC8F88C8CC55CCCC55CCCCAACCCEFECFCCECEE55EEEC55CCCC55CCCEFECFCCECEEFECFCCECEEFECFCCECE00000000CFC8F88C8CCFC8F88C8C000000008F8CFCC8C8AFACFCCACA255222CFC8F88C8CC55CCCC55CCCCAACCCEFECFCCECEE55EEEC55CCCC55CCCEFECFCCECEEFECFCCECEEFECFCCECE00000000CFC8F85E -:800400008C8CCFCBFBBCBC3AA3330000008F8CFCC8C8AFADFDDADA2F21F11212CFC8F88C8CCFC3F33C3CC55CCCCAACCCEFEDFDDEDEEFE1F11E1ECFC1F11C1CC55CCC455444BFB7F77B7B00EFEDFDDEDEEFEDFDDEDEEFEDFDDEDE000000008AA8889AA9991AA111000000CFCCFCCCCCEFEEFEEEEE2F22F222228AA8883AA33300CFCCFCCC28 -:80048000CCEFECFCCECE2552220000EFECFCCECEEFECFCCECEEFECFCCECE000000004AA4441F14F44141155111000000CFCCFCCCCCFFFFFFFFFF3F33F333334AA44415511100CFCCFCCCCCFFFFFFFFFF3F33F3333315511100FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000008F84F448489F95F559591F11F11111000000CFCCFCCCCCFF9B -:80050000FEFEEFEF3F32F223238F84F448489F91F119198558884F4CFCC4C4FFFEFEEFEFBFB2F22B2B955999855888FFFEFEEFEFFFFEFEEFEFFFFEFEEFEF00000000CFC4F44C4CFFF4F44F4F3553330000008F8CFCC8C8BFBFFFFBFB3F33F33333CFC4F44C4CF55FFFC55CCCCAACCCFFFFFFFFFFFFF3F33F3FF55FFFC55CCCFFFFFFFFFF03 -:80058000FFFFFFFFFFFFFFFFFFFF000000004554444F42F224242AA2220000008F8CFCC8C8BFBFFFFBFB3F33F333334554444F42F224244554448F8CFCC8C8FFFFFFFFFF7F73F337374554444AA44435533300455444FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004AA4446AA6662AA222000000CFCCFCCCCCFFFFFFFFFF3F33F33333ED -:800600004AA4442AA22200CFCCFCCCCCFFFFFFFFFF3F33F333332AA22200FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000CFC4F44C4CCFC6F66C6C2AA2220000008F8CFCC8C8BFBFFFFBFB3F33F33333CFC4F44C4CCFC2F22C2CC55CCCCAACCCFFFFFFFFFFFFF3F33F3FCFC2F22C2CC55CCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000F1 -:80068000004F48F884846F68F886862552220000008F8CFCC8C8BFBFFFFBFB3F33F333334F48F88484255222008F8CFCC8C8BFBFFFFBFB3F33F333330000BFBFFFFBFBBFBFFFFBFBBFBFFFFBFB000000008AA8882F28F88282255222000000CFCCFCCCCCDFDFFFFDFD1F13F331314F48F88484255222008F8CFCC8C89F9FFFF9F91F13F35E -:80070000313100009F9FFFF9F99F9FFFF9F99F9FFFF9F9000000004F48F884846F68F88686255222000000CFCCFCCCCCFFFFFFFFFF3F33F333334F48F884846556664554448F8CFCC8C8FFFFFFFFFF7F73F337374F4FFFF4F4BFB2F22B2B00455444455444FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000004F44F444447F74F4474735530B -:8007800033000000CFC8F88C8CDFDBFBBDBD1F13F331314F44F444447F71F117174554448F88F88888DFDAFAADAD5F52F22525455444455444DFDAFAADADDFDAFAADADDFDAFAADAD000000004F44F444445F54F44545155111000000CFCCFCCCCCEFEFFFFEFE2F23F332324F44F444441F11F1111100CFCCFCCCCCCFCEFEECEC2AA222002A -:8008000000CFCEFEECECCFCEFEECECCFCEFEECEC000000004F44F444445F57F775751F13F33131000000CFCCFCCCCCFFFCFCCFCF3553334F44F444441F17F771714AA444CFC8F88C8CDFDCFCCDCD1F14F441414AA4444AA444DFDCFCCDCDDFDCFCCDCDDFDCFCCDCD000000004F44F444445F57F775751F13F33131000000CFCCFCCCCCDFF0 -:80088000DDFDDDDD1F11F111114F44F444441F17F771714AA444CFC8F88C8CDFDDFDDDDD1F15F551515AA5554AA444DFDDFDDDDDDFDDFDDDDDDFDDFDDDDD0000000000000000000000000000000000001F19F99191DFDBFBBDBD00008001000000000000000000000000004001000000000000000000000000DF8D0748000000000000000E -:8009000000000000000000000000000000000080020000000000F01B24000000000000000000000000000000000000000000000000000000000000FFE40F48008001000000000000000000000000004001000000000080020000000000F089A2000000000000000000000000000000000000000000000000000000000000FFE40F28000013 -:8009800014000048400128004840012800000028004800001082040000800400002148000010F2BA5E000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE80840180020000001002000010024001002100140000001480028E -:800A00000040818802000088280000F04CBE0000481800000012000000000000002001000014000000000000008002000000003F84054818148002800414182810820416012810A21140012810A2414001002B11484001280048408188022148008828108204F05C65808401800200000010020000100240010021001400000014800200F6 -:800A800040818802000088280000F04CBE000000000000000000000000000000000000000000000000000000000000FFE40F0000280000000021000000000000100280010000400100004081080000000000002F6D020000000000000000004002001100800100000000002200000000000082280000F0293D000000000000000000000095 -:800B000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000110000000000000000000000000000000000F0726D0000000000000000000000000000000000000011000000110000008088020000AFED030000000000009B -:800B80000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000230120010000008002000088000000000000F036AD00002002000000100200001002000000000000000000000000000000000000F0DB150000000040020000000000000000000000000000002002000014000000800842F03E -:800C00003C89000012000040020020C41212000000000000000000000000100100000000000000F07CB2000018000000210000901200000000000000000000000040010040010000008880045F960900000000100200208401000000000000000000000000280000000000000000E03A0F8001000000000000000000000000000000000034 -:800C8000000000280000400100002008F0C63F000000000000000000000000000000000000000000000000000000000000FFE40F000000000000200800000000000000000000000000000020040000000000B0440A001800000000000000820042000000001200008002290100002200000000008800008FF30A0000000000000000000062 -:800D00004200000000120000800200000000000000000000009F3901001800000000008200200800000000000000000029010000220048000000200800E0980D000000002240020030110020080020040000100200002100000000000000000000E0DA0B00188001002C0800000000000000000000000048A2000080022004480000000033 -:800D80004200F09C7F0020010000880000001800000000420000400200800A000022000042000000004800F09B5200002001002C02240000110080080000000000002004240000002004000000000000F06BB7800380220100001122230280081282249082C0110080140200800800200180082824002800008004005022EFA80E800200CB -:800E0000000080013A0812308200002180018001882011012002488880040000002848000000240070A40A0000001828000000800110A1280018480048808401A021004800880022000028000000000020F4653A80830200000010C1221A0812988218822221202104206524C21812802188220488884280024002220000004200002CF42B -:800E8000FE550000281880810280010000214021088210018888000080020000120088200200800400000000F0A33220822102000000000000280000214200880038220022003440A21200002268800400220000004248FF110B000000281C02291882188288031880111222082722242C8128822428250C82200882460128240000008043 -:800F0000020024808404F04D86000028002800A8000028222082288204100212180048000022800220080000800648224200808204007FD60C800212000010828182810218003082188821118E528028010012000012122001000000800200220000009FFF0FA021282001000016021200201201008004114213042A8484A428284081420E -:800F8000828A82220442800414000022002022041CD45D0F00000000800118800200002C020080210882110000001002000000280080020000002004AF420822112002001114001988C22182800114400121121800428098114820081B841B1211002286C28182002082022840022200002F520D0018800180021825820100180088884278 -:80100000001002A0810020030022303220238488060000004228008002006FFF0B00481C01001001400228802A8808800839188109982800001420018084018200210024E01412420200100221147FCD079011181382010024A21AA1883A21888201E031288A1462342C02211AA123484AAA113A2A82081BCA211BAB2B42B22830418262BF -:801080000020848284022180021442F7E4000038002A12011E92242B1110A182128814C0A223A48830122D415848988044A1140011303129418121A4888A02001B462111A0268002224A04006FAA062AA2232A222101E0125211212117222120A12A3AA32882211E81805C118E829A58128AE41623A8448A842228C3232C031A83A24A242A -:801100002934226800224823022302242823A2444A84F4E6DF0022A012000080082C08888022011180048A0419041828208821088214822B128218A08660246024601420042800C0220020E4A8012817111AF311218880F2212115B312B892F191119AD9112828AA8A171815F122A23F14A4CC1F14EC2CF842428215A1C61F1EACC41F1594 -:80118000AC6EAA8AE811F9C1411F19A22ABAAAC84AA4C43F1EEE2AFE42622B441F347443F141432B444E422124212382A44448F08DC580F251611AD11187012AF2212115F392122B993F31B912DB1128A8299A798141F222A23F1C9C421F14E42CFD42432BC41F11A1921F1C24FCC1D11F16AF2A86A1991F36FCE2D22AAB72EAADE64AF813 -:801200006161EEE22F2436421F34F443611F3494426E6229421292224E622B444829F4459980F231511AF31121002AF2212115F292122F21F111831A7B8181A81AAAF981811D832F22FA63612BC81F14EC28F98383297811A147171A8217116EE1A2821B111F14FC13612B82BAAAA8CAE62CF8E1E32BAA6A26E424D413F241432B446E42B2 -:801280002342522226B242B4428424F4F52D80F231713AF171311A092AF2212115F312922B193F39B112718181A82BBAA9881D832F22FAE3E18AF8C1C1CE823F3C1CF21111AAD31182F81191BE712A92811F11F9E1632F2BA73B7AA3DBEAEE28F863632BEA6A064E4237141F3494426E62294252222E222B662B442CA444860D0000002215 -:80130000402201922008000000002004422084282402888008260100000000000000004200D0AE0522122A0118004022480200208102248002001002182800980060221288A01200A08228000000280080024214EF14042AB41122B211A2141B212394212B1619F2629219B24239112B94322F142BF342B1322D912AC4912E421CEA2264A2 -:80138000112F22E519E222E519C2529AE222B4D1E222B491D222B191F262111B2923B481324219B26298212B84112B84222BA4222BA42229AA424AE822F4D42580B411C4411361141B212394212F1491212B9419F242B1112F1429FA428113B84238A129B8A384F1A152881B4A881D42821F2224C9439E212C244DB39186A4294631112F9C -:8014000024A828273419E224082F340A2F34082F24082F242892822B42296822BF6C0D2088040000240000000000000000800800000000800400000000000000000021F05EA100008082522248002400003200822800000021112001246A0828008002002200004200000028A04240F1A17E009200000020040024000040A22122824A0214 -:80148000422081A1241901202428840180A428488820880400004280040014F0E43F00D200C02280044210224202180082266223228272602C00186A11512120842824054848A848888088042A040042808442A224002BAF00002002240000000022000000000090110012A02C8002002800800200000000000000F0EC580000A01200123E -:80150000000000003081000000000028190818008008001800008A0240010000002820049FD608288002001800881200820022002100000018160200006A0138A012800228200820220400000000008FEC042880021A021200880000002814000000000022142001002880031A020082009041000000200248F0DBF8000000001200180082 -:8015800082008048020000001816028800A043800900002200A280020000000000D0710522002081082800002280018001002180010062409221200100001200820024282228140000002200F088A88001A02180010000A0820022822800212928C1130012240010012391218024080000000028002200001002F0D7FC000000824002009E -:8016000020010000922872000000008001000020012008280000000000000000AF67031A028001002221002001208208822223031824001268001B1200121902001880280800292202142002000000F078ED000028181200000088800120830142821001884002240012210080090080020000000000800200BF310CA0210000802202000A -:801680002430228880582200000023010029088800822225F1228100118828220028000020020000F0E21D8002148082C211180000181218111800004002423031824A081A08208482A1A40080080040410111004848200200F09EA900002004001828122C0121221022012522818101248260292C0100880040028288001012021002217A -:8017000021002110120270E20F00122820218101820080022A01221200822D8224822602001081A92428E01C028002484081C86300480024002A0400004FC10D1100800400281882882812002280810100122001009211008800A03823884142022824404202404202400200224E148002002001002001800A0000001002182813240214A8 -:8017800000000025011C0200248082621248281100000000E03107A012001902001440011CC1221120410114234491428813082A193182004282484248A2000012111411114228482280242434420000BF9A0920880120020088200100000018120000001800000082880000140000004021020028004001573B00800488000022800828E2 -:80180000802202204222911282291181081941A181E01421AA2414800486810848002C8444C16211002C02190410022FDF0928BA2221A2282AA2113A2122182121422251211286021400A0811C9821122C3812868181A8844AA64CAE61489AA882863181401331221D216E42141512512260222B262D431042013FB9062282002AA4111419 -:801880003011B8E02889B112B8232208141AF1321258988A04272C2A9132B234121F1908BAA48A224AD832C823821A481112A228172427241C3222230410B2428684120214F0DE5D1081C1113041008022A291701182012AA3323824701262111E122728B012F821411CA19C39089A0480DA21B1A1322219024AA8811B4223C22110A144CE -:801900001CF42221A04400420020F2443110A1121130812A110111221130112C081C0A1C083C8844A141142984820529044800122212271212141223044A088004000080020000F0DCA41415D1111151111F14F45161111F11F111111F13A99117181D9129F183911B821B998217183F1AFAD3D14AD411F1C1C3CE821326E126EE25F151B2 -:801980009115A144A0391E11172917321F3BFBB2B1CA54312F21DD22F423233F16F66163212F34F442423512E224F46242251202002E22CFCD06281F173611486AF45171111AA1311F11F39191988AFB81912B981B821B9B17181718BEB29AF983811F1DFDC1D3CAB8E1A8657E621F15F951111F11F151D1C29E911F1FE71DFED3F11F38EC -:801A0000FAB2B1DAFD515329FC81C33F1EDE11F261632B222F14E62414024AE426F462422F24542221A0223FB904221B531601881B671E111AA1312AFA1191921ABB82F88381AE21A81D81B022B312F113114AC5121DC31F12FA51512E321E5217181B55145AA5EC6E311D321F22E63AF2B3311E122BC41F197941F323232F36F663613F9E -:801A800012F643611D433553222B446E6229820421A022CF1A031D211B6316217421B1714781D111F311319A89F981931F31B112E11BA1931A59113F32B352051F11E124F483C13F12FA11217E623F19F512111F156518DABDC1FC61714E733F28E63BFBA3A14E422B911F187841F363633F32F263613F12F243411F34543325B242E42203 -:801B0000F462422F241412022AF2E348004001144001144021492149210982308142121001208401192884099880092A08001C0926814401800400480000002F5F0A26210120A24120212288012011228122812191120082108292111229410120022A082D11122C0800008002000022000040F1B17EA0421B212AB11122B611B262912115 -:801B80002B1619F242921B212F2419F14292222F342BF242B3222D913AC4912E421CF822421E212F2265192F2264192E429AE222B491E222B49152321B29421B2923B681324219B24298212B84112B84222B84222BA42229AA42882E4247B4809461481B2142133142112B14112B8419A2B4114A39212B94112B84222D913B424AA1124E99 -:801C0000811D82122A6C1C2662193C641D24D2349AC4419A42B191562219662419C282684EA3E03428E22428C2822A84B82294822CF48A29008248008001000000000000000000880000000000480000000000000000001002AF1B0A0000002001822081018800002882280000000018800100322822A0282002000000000000426012AF49 -:801C8000950960188082C1A2182822225A088214001260212412200129181211022C91A1800A820010120280280228008642822402142C880214F0BD6300C6012280022A81A28292204A2108128061221E82221212248211009083111A08882007230228800A8002222424422810C182244200BF7A0800001888290100421218000040023A -:801D0000004082081002181A022800002210220820020020080000800220F239E740010000206122820088008081041A040000001502210080010025011400000000820000002800481C012800808204421200182088888102822C0A2028021122800928802A82080082239822804802482100200888208804005F1A082800800220C43228 -:801D800082000082181820A8580000002214160200802108241182133822800880042008000088280048CFFB051100004280010012888200224280120288224001248220028A22020040020040021002008880088004008FFF0F000000002583A11200821800281824108282810280222891211142212200804202000048000022888840E9 -:801E0000821802F0AE48A0140020040000602200200220089082C01288200100108141022820018001100100000000001002245D5900000000200488004800140020040000110020012200980000000000220000000000002B9680040042008094123A682280842112810224800824882021820819022E429022382081422201400142226C -:801E80000000880024820024BFED0E1848000000250100200800800942800228881400181220018008000000000000200282000000CF9D0B402162140080220400004800202228110225020040020024001800202124021001008008002C0200007D33009041000000CA02282008222148250220880180918124001126621824288092A1B6 -:801F00001A1222938128A082190A11881120220282A800288F4203002004008001182110018005D02222083022E029022112241200005021502348141001002240012200002400F0DE1900001218122480022800101162225AA218003083D0210112008824E01102182121000014808848118108000088220021F079F50011281100281823 -:801F8000422B16200200180020A212821818222222860212221212282128002800800280028088082260224002009FD2071240010020022001400120018800100129010020021C421101120080210224288028C88240810888C0820021B08C040020410200008008004682248A8281681121141824001002108289012122601A004001009F -:8020000011240000002A0800EBF700002820012021010040222182311200000033088011A11280222802228001000028A0280020022820024021F21B4E200148800100288002C02213240600001123289211902100502388863111001429042601001C0A0090228088888848011012F265C92051112214009032128AA51128002D42187A40 -:80208000E1212ABA82A1911D111F2119029022D0223112381F2132122531223022222429E2128468121C42312182118200A82824142440015FCF0A00B051032901226A27A1222908171815B17284249412260220885231A6420212221622A2129E822C61212429F812118E51181100AA88E8122A48E118A8A8008828824081F28ADF8001AA -:802100001D21481A218102B062022200422C92222B521EA228A22B88143633223BB11F1261287081722391828A9A311A82D311C2212A3231282681B2A388E218023C9882312222AAA82A2B8A2BA2213022CF8F0D0000001002290829082908240012000010020020180200200813883181308110011110010000822400008F6F0912D01177 -:80218000F211611E822B11E023F352722BF79AEB2AFA82823D8119E822A3574AA49888F081811F18F821213551213593829AF9B1B317181E922B88AAA2AA8A98812EA33F3B38431B8C86F181233BA21B2226F121211592832F18A8228240F2A281AA0820F2C911A0114E4115F13171821E1225F212122B777EF22F2BFB22222F22D213F85E -:8022000041A12B332F27F7C2922B982BB3213F19F981811D131573A1523327282B111F3371A1E332BA82EA2BFAA2A22BAA1BE62EA39EC3FEA11F1C38818EA32F18D21192811CE212F283813BA8828AAAA28EA223AA8A002B222DA5A01119D411D21152312B111E122F23B372A77E3EB22F229222173837182F23B372632529A1AA3ADB13BC -:80228000F811111F3253221F223823241AF1212333F82283AE82AE2221E01276817212F3C2F16A9E8186D312AA22112E213CB283F882812A22A82270A231822120F269D9A0111D4115F171311F11E121B132A3223E722B7F3AABAA281738371A2B332B373E122B98BAAB911F19B911F921231F32F221823552221AF1B193172A2EA2BEB266 -:80230000BE222B232E222E611F2AF2F2A23B751BE61CE828B883B221EA18A82219FA83813B8AAAA2882AE2227A22B2A20220F22EF100601240022E120000400224122492200913091128212800213022B022012B82A082A092A0820020220800822880220800F03C62801121224121A112C012682E12000048382AC42290328009282410B1 -:802380002221021882888001250280048280820800880082200200F0868D80B411021B21421B212394212B141B282B941B282B9413F84293222F1429F34291222D912AC4912E421CF8224216E12265192EC296D122AC292CB491C2421B29341B294E111B292F14B181724291212F1498212F1418F14281222B84A22B842229A842882E420A -:80240000FF2E07481B61B01126B411324219B242B181B242B181B242A3282F1421E21429F24291222D912B421CA9521CB8218CE82264111F222CC1C39E212CB491C2421B693CB49162141B2827341B284691212F1498212F349A212F1428B2422872422282B82294822E422FCA078282000000000080020000000000800800001400004838 -:802480000000000000280000000025012F240C182800423342012448420000002001004002009042001888120080213912186024280000000000200420B2490D228A8111814882A14280C23142400210018224A0242042C22280029032888058121214882712196C120024242248402198212C02828882194201BFFB0612CA03A0482C2297 -:8025000021022B24284222240011204942A2242011A2282128002B211282142521611460191CC5116024220042221488190200E024C82114226FAA032280114112418104E01401000000000020022140220480089800C092282988024002230200002C0288820000BFF10700000022200400000088482880020010010000218088028001CF -:802580000024200210810800002C020000DFA80E48808202301218C082822118253281422022080080280821809622380022184022225212122322080021240023082008682022F241D68004282240A22112428288212C411221044A220222000011218012220120A821002828212C012928021041028008801A8202006F560D0000000015 -:802600000021008008888008002088080048282602200200230114200200242008240000200422223EE500002800000082200321888642221802292881188212018001008214002100004880042008000000212422F0F928800100800200001C2202200240012121002A0182320010010000482094120000000024280080042602F04685AC -:8026800000000000000010928200001200000000000042100224001002008800000000002800003D6980012002000020D8214202A08282256228100212882042810118003082110021202401428848000020020022212200EFC70A8084048002000080211802001C0120082428802802004800400200250200000088400200800480025FE7 -:80270000870B20044280B21104008221822008820000004022038008882488248880081C0829088830422410120200000000F0E6FC0000001821182110012A219812880029011812002188282240820420021840022A110120042A8404008004290400003F4C0E20812405002200212C02204202000022122902C0822400808202800218A6 -:802780002800808202820000220020221202F0D8B60028000000122811002800220010221102402204A082100218284E822800A82848002280820400302200200222FFBB021822208312322128200A2100004221122188A092242C28B222012382020040021128241002001002100200000000227F9C01A04158206112806421200112308F -:80280000120020025A0221000080040028281302288002288082A868102204212228282002C022F071DA0000001223850116012C0929031218128011A228230448002290122280040000001AA41A4248A0A44820044200280010023FC9041282003821800400000010412214022022080023281212020024220021002180020000000000D6 -:80288000424021E4BF0F228004002280022112802202200112101212820188000098144A182204C800802604002290614880042A44012221F0221D00B2A0352821722A26E2221131122124A0184A512246129282882E12282CD422B222C4222AC2222128E022C6226811A82722A228F2222A02A823842424242214A246146240011FC20187 -:8029000032CA24812412D113A2111063282C29A918234B22AA11212C6123184890822AC122882DC2126A8881AC81882B1A29488248F2328129A6842C84F422422A62242914022A840200296212F0E61A808103E021E1238365241A81DA12218213820314A01312583AA2A127288028312230A224882B223023422A22C12138428026ACA671 -:80298000C22C0411A0246022282A0222242AF6BC740000002603228028C18280088822204A8284A248B0828482A42148924892201922099220C81282002400400200001448800497DCA0225A032A062E113160212D232B998AB892C9822B999AF1F1732F2BBAD24DA2FF7AA5994AB4C2E42CF532126E422F2DED2DBD92AD495AED21FBF18C -:802A0000F1121F11E921F9928229F1E2E2AAA846EABEC25E222D2223F44343A0442E222F2616A2662AA6666A9622DFC40E3AA2711AA1231AD21293633A62213F38BA82B812B112E321B992A92A1F3DF5B2B22BFF2B332B992B137AE5256528AEB22F25F562C227222F22B292FDB1616AEE36FEF1F3BAF841C12CF892C22BDC2D222AA2EE1C -:802A80004AB4427622F222222B663F34A4646AE622F26262216E612E622B666AA622AFEB012AA273A0231E323E233B23183AE3385A222C91329AA1911AF951D32B337AD722B1A2BB32A3FD2CF982822EA22F26F432322D2221D24E916A66283F17B6E2FF2161863212AAF97272624AA4AC2F24D622D222B242F64343A0444AA4464AA444A5 -:802B00006A3242A0663F14082AA233A0331AF313313F11A3333E323F31B392B982D922F192122B91881F37FF12122B552B322BDC32BAE924ED2CEC235A222F2FF562422F2979D2F262B16AF6F1521F3FAE741D61BE322F2DF862522F23B3D2AFEC4AF642622B2429F242623F34B462A4664E422F26B642A6666A32422AA266BDB900008081 -:802B800001184002240000402201A024200442214229219412422200A01220022A8124022248800448002800800242D0CF07AAA121182002211A220221009012122812292311A24218002220022E12282A012E128001183042000000280020420228202402F0EC4980B411021B2166B211726292212B141B282F26B981B24239812F242989 -:802C0000FA4291222F3429D212A9421CEB22C4A12F22E411E222E419E2226C192CAC292DC21B292DC21B292D821B294E811B292F14B881B24298212B8419B24218B14228B24228B2422892822A84E822F4994D80B4118634114212259161421B282B8413B8423A812B8413AA84AAF44211AAC4812B4A1C89C5812C6D112EC2D6E122681CAB -:802C80001CE81CC282DAC2838AC6C39AE234A8281CB881F642821B284692212F248AC2812A94822A94822A94822B42882E4237D2008004000000002008000000008001880000000000480000000000280000000025017F5D09820018800116420112120088A08480250800001002004262000000292808808408000024240000280070C247 -:802D000008202A014082016012A04288122124221D22199831302190212128800224801102232212222A52212218200225222208002200288661141C64268FDC01200418C012002113022222248224A22C82854982021A12E22802A8002314110221304210022220240821222200242800C082144681F26F8D0028180080214101181A8443 -:802D800028012014C18113021110010000002A058022022AA8283C08182002248008240000221C82042CF4F89920028042021C813222122001200428121C32312100002400A092901200402209008008200800400100002800F059FA00262101A0522839016602483011C011C0A2004820023121301200322830724818F0128125E21108E9 -:802E00001E21888A02400200004268284800482F1D0C2828124082671139818217A241601142192182691218210050210018A02926A221301242182123113292601B88A20000400100228006006FD40D4001280028282100000000222113820428244002210012002A0420C9814001002008100200208484020042DFAE4A011480020024B8 -:802E800013018021228421020028191982C142183011248800803642C042200142000020840280048008882100F08613200142200500108201220088008E110021208801802202282008221200219012400242400129022200001002428EC5000014000048000040010000800400001280810140028001182008800C000000480028000029 -:802F0000AFEF064001281A040027212001200422001B18281C01184A084081818A81032446228294121229819492002304200220848284082E820080E4D906188014010060140012001C2108008088042480A881260200A02C0018484800008088241441020000000040F2D19B141130211860221890113021181200140027112601C8C074 -:802F800082281382B221844221210420052008341E212230832115021431140021A0240000DF6B0D120028001418408101288228001308201442E11481288108881A8888810811208C048810410114C02200000021002280F489126011141400400100271822805122101101183192882214C0111414100100884812909100188219288828 -:803000000224482088240400422228CF650DA02520041601199242284200281824122A0120011288C082882412484082438252212882282E8286022880D2239841422420823822420000F0DF2D0013011418338803286602008012110226110314601421141C014601484A6224D02182E22184811701131281122108111114202A02800212 -:8030800040D14B09228082218201128081821102202101182001122220282229220100180000000028000000000080222412022F1704001A840210124122288868212880080024C280148282218482288868288228428880021226020024402244023042200A2908001F8944218224012A1102C052200124181012414202111C04601800C6 -:803100008A810519042C82C212112C8A82841221018002142004222024022842005F2A01808204800228C011A0828032521230222001122F34082C81820880042A68114A918222211A94811818488222C82228822880880242C0421022F22988F01121F011113228371311321C353135A11229011AC311211F12B212C111984AE814B5425E -:80318000B82108211F1428088A85C1623AF2921213E428A22A19C4811AB212417181C2211B223CD23214022224422A2A82246212428DD320C251B04122031C92214E22292888C822232816D2310117322135F181111B881D4186B1B2C941BAB2128558112EC2AA081F166C3A2B921A21A22915D211F281822E811F226C184288171421A86F -:803200008A8606482B824A0424CB1814181B272A82C1122CB312C113124E333AAF29121E1225F21182128E12F011225AB4126421AE3229D211B23183F161A11B5D4AA82C2B112D522829A24529E81DFB21122F1229A62228822D823332412C5411822B8627224A84E22482022AF2CAFD140020023440214101228088C4828008880080027F -:803280002880028001214229012100C0122004460224400200240000004E2814387AA2111F11A1223B333B323E217AF733332BCCCE422B8127282B1929B191B9A3B2A2D222F1939119AD991F29FA82832F18A111988AFD91D11F18E92EEB27E72FEE28EC33E72EAA2A8E819E923D222F14B6A1EA1AFE21E2AEA11F14A6CC2C54122EA22B5E -:80330000EE4AA2AA2E222BEA4A0424BFC2041B221F16B231F131712AF33133E012E221F1B3B23BCE6EF22F297B8232822B993F19B9B27382F212123BD92BD9DAED38FBA2832B225AB7F1AFF51F1DFD81511F3CA911BEB3CAEC2DADDCAAABD9BEB23F21B251B681BA81FCA1C21BEE1D212BEE2B4429E228B8C2BE42B4A2EA22F2E2C22B44D9 -:8033800040B24748A1321F12F611311F11A3313B333B321F13F231323F3ABA82EA28F312B22D822B452F29A9112EA33F33F392923B512F1DFD91D1EEF32F38B821F871511F17F521511F19BD91E93FEF2FEF2FFFF1D31F2FEF2BAFAB1BA81F31F1A3B23B881BEE1BAA3F2EBAA3B841E61CFE4143312E222F26E624A4AA6E222BCC2B66E02C -:8034000022F24677141F13F321611B131F17A3323F33F333311F12F221323F3BFAA3812EB22F29D922B842F412122B991F33FB33332F29F913511F1DFD91D1EEE3273A1F12F25171FE711F14F3D1D11BD9FED32B993F2FFFD3D13F3DBDB2BDB27AD1F191133F2BBB93BA41BE81F8C3823BCC1D21CEE23F34742341F242422F24B4A2EA26E4 -:80348000B2E2BC42042E22AF1A0A2A01001800402109400230112412241242822008214218421880088842888008002A0124000048002448004A0228B04C0F14111428A021271212628A5212281880012521521240216914A64231213021821928C582C012823C0198121C8852128214C08128250314800842000014DF470D1CB41122B2F3 -:803500001162241B2127341B212F1491212F16B981B24239812F24A94A2F1429FA4291A22DB12AC4912E421CEA22E411F222429E212F2264192CA5292D421B292D521B2925B29162241B292F24B181724292212F2498212F2418B14228F24282222B842229A8424AE822F4767EC0411986A14146A12127145012282D9113A8B413B842A987 -:803580004A4E91A22F1429DA12B922C4912E521CC8D21E812C64192E4286E11264192213A9421369221B4946B211E224B881662619E42498614E2219E224084EA2E02422022B4229A8423F2E090048000000000000000000000080080000140000481800000000800200000000F0D8284011014001143682410228140028002128802164D5 -:80360000241021110320AC1421B08181021C01483A08400134282C44815422008A020022F0881B14200218481200000020810112230223C181481211150211122D912329011848A04111221C8102212121140011100220284482021422BF6A4D11A124004218111821100222802162212221235221521AE4311461181971123192181ABC3B -:80368000119412C091484621C211622A0925021430221B4235622400A0C224240028AD5300112041018082018042210100001288000021001429080048A012C0110010021440010000218200288002F7F500000000004826020088400200200800000011B0222809200218C091702201290821501240022008202428044F7C0C111432140B -:8037000032182E112312B22128180140012248221B42230128142D6220042988A18618301212190140012D112C08109221008211208284922222808278C30C1120438183C11228C0A1A2140000282022048840A22421006011CA222821012601001123D112088225120111101182A28426820200828F950B4001009021242004210019088F -:803780009042D02182012211004824824022632820210112111A4821121202281022080000208628064F5F0E188001241221200130221A04282200255122122002AE12200425A241200490514002240040821402130429829442284822006602F0FC4500480000008002002A0400280022211888182A44018230211C02242818128A0480ED -:803800006123400120322200228250223022212848BF64081400000028000000C012901200001100502262000048280000120080228808000000000000E01A0A1C011840821122020021424860230031211A021C818832622581220811288092421800002021724281083C42024823224A420223822602FF1C0982000000808102281800D9 -:80388000402203100228808828D4220429858224041B2120918212211226022C08800400488084020080F4383B40011212800520041448001848138224041811C8488012118102228084140100141602200A2280CA228E42282B2822002728248A0426F21ECB00141420110162601A29322248CA0210A22123813262C8141A0224C84E2244 -:80390000001C2424422286062410131113A1484A9842462204424821208C0400C29F890DAA2101282A2132231227226023240080021419021962122290215A08112822000012241A0222113819084021120142002006002004B7B8202402004248200120A4121422A0120000008001126011880012001021C21220880200828282148028CE -:803980006428800810024FA84F8104004021C121800228460280D2120415224231C24228422826612E1110A124421811233411211200C021E824C82414141C04A22868008042E17508001128000040030010314224720000214800880021800848200200800A0010014886821882142208824A0848BF530F002A01245022482924C4119889 -:803A00003041C01188806414482A414181C1414218E012A12C181222481D12821B8119E22221011093C290422400420021422A240282CFA904288A03122C2641032084842141C252182411236124808101421829824112018822382302222B8221223428601228C0210060228088228202A622F21F782019A14200281A26E121820124900D -:803A800022118001222001290A2E111CC8922081812143011602800500928224C02220881201904240029042F0AE34141AA32A1B232063126A86A724924AA2211AF242411B112B212B3425E11231623A21E21645A146CE411B112662131921A9B24AA51316029683FB113160281F18092622484291411F2C8C4282FA62C2248229081CBCCF -:803B0000827C930C1CB48141A1322CA25416335126F2224225F142C22F24348127326A64231B641B25482F24F64161A02419F221326E613F15D423E113E214A6451246A2562B472A718222F212313B8229B221B241F662413BCE3F26F4C282141BC4CA7E62A228EAE4268CB2A2AC244E22CF220562168121A1143F21921327222B511F143E -:803B8000F231122A8101423CD111E82391423C52119AB981AA52141A18A23828233821822A82D613D221922313532217221E31228E812F18C8A2288A8A125232238204290A2A242422E2FE0200004800001C88C482C0811A8488040012000000100200001880010000002440022482200840220882F0CC9C14AAF6212111782AFA61B317FE -:803C0000141F32A235CE222F28F162322F28FC93111B286E32AAFB611317362B334AF421A11F14A1471F12F421731F36F762A327313F1BF8D1D19A81A4652F247442F28282921F3161213F38F993311F3252333F36FC43211F16E624F842433D222F24BE42F462422B866E4282A8482CF68C95141AF551712A82A7B31F3AF3715137322B1E -:803C800026172C2F2AF1A2822F2EBE9331832F22F3B3B13D133F26F212323F347623F161414AA5628E626E623F18F292B33F13F2D1711F1AA3115E733F3515F2E3619E221F33E721F283B33F197921F323232F268CFAC1412F267A8242F242622B222B4A2B826E422AB262A6462CFA81D6B021F631611B112AA3462F2431421F3287E72140 -:803D0000FB52522F2FFA12723F15B951A5AE1F167761F131513AF751513984F16151226EE37E631F337313F3A3811F1FED1DA3665AF473712B333F182EAB1213F3B1B11F19FB21233F34F862C22B286AE62CFA43833F18ACE42B8C27262B882F26BCC29CA28AEC28F6EE8CB0B1F711611F11A1367AF741531B571F33A5772F25F972522B52 -:803D8000472F2DFF53913F35F5E2F23F37F553533F37F752723F15F723211F12A6442AE622FE71631F31F393B327131F1FE518A3371F27F673732B333F19E729F2613313F2B2B33F197921F323222F26BC82FAC141CEA22F2CB882B8C2FEE2A22F2EB282FAE2C22BEEEAAECE8EA28BB920022A01220040A241241280041210418204132814 -:803E00000442808201188021240222A09220021C0988820014480024480000002FE30500144002244818121450221301D02213C112122122184041421123312282A02124120025321121000011252208501200222C080060385F7E09581B21B091A2141B212B1619B262B181F262931B282B9413F94291A22F1429F242B1322DB12AC49138 -:803E80002E421CEA2264112E429E212F226C192CA4292CB491C2521B292CB19122B49132621B28272619F2628219F24282112B84222BA4222F242892822AA4842E421F410F581B61481B21181B612F1681F262118AF222131B684AA32825B1A194122AF442B113B2423B222D912E521CEA22ED1528E211F223C2D2349E212CA42D348AC612 -:803F0000431B2946B2917262A2282693612E8219E624BA8142A24A2B24222D828AA42423B842E222F4155E00824800000000148002000000000080080000140000480040080000800200000080022F520F80021480128586818111421188110A2123921111428052831190322901922D42A44211184094112941212402C0229200002228F7 -:803F80002031224A1224FA8DADD01261491681612182B01A1892C87038014249242792218A41A234A2C5010030411432114132203741281A0811708282C1228B82A04270C1C8912C064668242084E11488F4A1592413B1E42181218118F5528A9098200246C8266E187022A3821D1224C8441E22852148A21200135843A322641356218411 -:80400000C11240B182A421228B82222B8320B49102232222642126222588FA18A80040114182022818482C711148014A012880014E3122850110011D4216A1121248122142809284111C0124400280041788A042C0482420246244481FAD08480000402241C248250114001228112001A0244828002011012A0148005012002042081225A4 -:804080001201110020010000481FD406002713858251224194422A812225DC822148098041118801601C28B012442115282482239425200136D228C6191662228A043214863844482880C672A0144A82D8330C48F022118450221043E2821182A484A1881C214201148112008E41400219410162007021443211002994118C41221142410F -:80410000318149242402484A12822124F4A3B300003012103418424213221121018400121800624822222005588118223A240400A0218722830229A248B022018100208182014222825F650A1D2222382065211140312149D2810289A5242F4221A4212228412148804631338880266314842D182A24344444214C66222C02222741511189 -:80418000844842251882012448288CB448D23905804468822184408112489812442625082225229112812334184A0121482978120861411190116084402AC11448301188C301A0282022042828304222F0CDC100142112431201182031112001848440480122100141400800B480240441002200123C0242A0124221A0148C28242101C096 -:8042000014F0F16B4051128B213828161B011C12B9185292184E148E4826847212AA21293128428C014125915B24838152C14914B8429151414144244E244C923239826144182E1146280C322328A1121E22A02443B148F2556620821242B846013011A021141A021548628142221422446014484A022821C0421A122244888204248C8296 -:8042800021210427329285012460248C3448480042B048029F72440112188148842814008C24011692184088040018260128484818224A4204208421445112111001423228181C011502002A84A3421A028249F2691B200110418134188904C6092C048699412E122882188120048481803248001C42858E121145044341A8844EA4168C74 -:80430000044C14324938488222100420324848DFE90718118051189A12021C0240981400141048082B1226D12841118882611100304448112664211820284442C1282244118C1222A1122250262061221810F8F9B80028810020A42489141251438140314A1605130200A01214408148018042048888A8124E222682426234241502214C98 -:804380000110A481002D8288A012F0E9BF3084A021608214123400492624848421628442C041212100101102290114000022434192141CC1424400929886822C48612128C24968848008C6F1F1F11012042021028190486051002A2401100280133248108803240000492211010042848C021424260811810048812260418001EDF9201228 -:80440000414129D482A4422848004C08A7112188281C018A2224B482041B4260842B24229044708401148038A300824A6841421984E4110490428AA4816C8101C8428C4CF2BFE58024C121122812A130216082844588241221A12189041902931101589111C04400239244284828C06128D480024A6212A881948A2112FCA2182043840261 -:804480004CA2AD7021288284622140038427227022662128818C5423942E118324459142284A9121888413942242681421421E28314BC270112A1251211D121A08CC04295A214C052034842038228CF8D922141E451F48D11111A85684129344EB88D42484D4A861252B421F12F163119C91124AE81504581D1117122E225E421519A1425A -:80450000112CD244BA64A4815B48182F1832548B4487648A528466F164811F11FAC2D217248D82114A6D288F41BA12F382A23EB4A28F1AB564FC88DB242A42E183C238289B342B522E488B62F021281FB13B543B588F91714852847A74117928F822221F16F511A180764151118F2CE42112D454E4522448F424112CF387A72CD8716392FB -:804580003DE1375637272C94512F4625B314F811112F15DC44D242DA22A5824B414388A1A185D24E04183A02171197B12F23F4482B1C3243AF14324AA3544285B941F212E88F2132898B263C84A12187A48F827648C8588F82A31366B142A22443A44639B24162173253A3C21F21638AC9DC58B713F3922285D299D29A64882E12B28B1787 -:80460000478E47446E1848296E848E2C3D82200460128008246032E012888428C1A4482C8AC4A412880010180221280061800800210084450224860882200848448A44020083F4678614BE315F5363111D51173E3F35711A5112357381D199F883833F38C9822BE85FF8F89E952B922F28F986867F58EC11B5D8FF494946E936B452744154 -:80468000E135F5214157144F26F6A48246F4E1C51F7CF8D4B24F49F134752CF286A63F28F23A322F24F633723F35F57B13BF11F14A4A3F24F572A68F83F9382E2723EFA2F276546AE483D3EC74C54BF336355FD67638F929799FB57D8BF35A493F16D41BF6A1619FF4FA6323BF3187F8C8AAB7B4A7922F86F8B393EFE2F626462F15F5D977 -:80470000F89F9541E112EA14F459B95E531F1254155F72E268F82424DFDFED5DF995F85F59F934759D286F58FA81A67F65F153633F2DF5733737368F9AF2CA5B3F247752F6F8D267A56F2F754EFEF6D62B888F8BFF9C7E6784342B775F537739F92939B43F91F17863BF12F24B613F3EF243E7AF27F643311F2CF442C23F34F14B53BF1E16 -:80478000F64AC3AF86F231513F1CFD58589F967541F968EBBB6717343F35F5222457546E638E826F48F8754D5F57F697D76F48E87152BA6FECFE8FABFF33F342723F37FFDBDFBF3FF85BE3AF24FCD3936F67F27C488FCFFA72C2EFAEFBE6C42B448F8AFA4CDE4F3F4CF3F674DF5264931F96F3595BBF14F47A2BBF96F24B632F2EF24AEAD6 -:80480000AF2BFA5B519F3CF4629A6F7DF97E77BF1FF372F3AF8EAE533F1DFD59588F9663948FB6F67B798FBDE735E5427245F564678E866F4AFAF5DD5F5EFEBFB67F7BFB5227BFB3F1A6E7BFD8FA1D163F35B7D3FCFBFABF3FF9DBFB2FBDFDF3D36F6DB9FCFDD69C6F4FFD4C9C4F47BD12F978F8CFECBD730E410084264128C24800C0481E -:8048800014404208118113011183044A1211888112250442490898D012011C41D814A841141220011A442341648164924492008FA107239221100148211146518110D128011CA1421816480221124A42082A2404B02444914400B02444044C4282065022482410082058480000484294DE17C0421F41D228F111248F14F11124AB141D24B4 -:80490000AB141D24AF149921AF143915AB9443F24AB143F2429147832D914F82C4914FA2C4814FA264114FA264192E4A9E254D4A9E242E4A1F49C2C21F4952281F49B248F89124E7261F48F26E121D24AB9619B24A19B54A3924ABB443F242B6478229FB24488B944FA2D4580EBCC1648D53448F14C124AF14D141B2486148AF5429D81A4D -:80498000BB85B44A289ABA4B481CE988D412F8A6481CF9245A89F824C21E814FA224E8A2E459F2244996E4A27411DCB4BC11D628F81124CB841B29672617C8CF2661486E1417C8AF34B385B24811D42A2BD8685384B86D48ABB44F88D5520D8482480082200100008100000000210000000040016084800400000000800200000000F06BC0 -:804A0000B5902213638115841141D64866225028110014208384C22419912484304D001C22012F8104924210466241112180088311825222189C81A128482B82C9C9328184B246F275B1207182225282A01C89089564A26082185C119888428D22122422521228222211D043A414114324C222471212222241124D51A01468494438384A32 -:804A8000C844C820829442444A815A1443B2E34D22F3C2138B21A584C1418938225C421A7C28217314118188D628226162244A21215381A2112652414217851D44AA61268712446692244523C111884A91686149322A2B4816848AAA24222F88F414221E4289BA94B214724E0F800211A08141CC54282824001048888184021C332481E047 -:804B000044021021C512000044290118004C048081142881D181A41440A2484C0181002CF47B231002251251181118200481101A111A01113412208132212800134285211104221B2141111C41C8821222602400001D481484449022222800249F3B0E1C82E342012952828289613289912282205941367A219C2222872881A21100342221 -:804B8000188CC225812F222184058E2324283B8129217212A816884E812B82271129084823882246B44221A1484902CF520339822201118031181352A28482841958C122430214218003222810221148C51825067219D16142A21282243602002581D22201842484412A042B43122042D2510C60214722159228A581084818221082119245 -:804C000019353823228F211888C82111108132211D243820230422821414B72192C038788A243C8211821CC4418222244302228A1404AF560F1C248182A221354852857088A221E71112230329828142C824216911A412C288524283724802214D421008560434188460821AD22211C428844E389E48606C466242211261899118CF45075D -:804C8000D014241113420212154441382481848B2100A180042932288909CB828502008343039028414260414E2218122113441424214B04842082CC82896228442CB334014C111228014484D02A02004014911442642A8191288344018414264114221141481838112A21824208448CA44120A44111006024402881812804F06D4540D139 -:804D000014C13A1722188504455A2D868283124864214158CD22838195288745853488835849BC1414E28471315882E1A1122A912470146827C381E484E313248474183118CC814D9AC48B242F28662820941C2CF2A138F0845200122612512A13215281857211C812165818322480322421221C222224A221488942022004191224211271 -:804D800011028D1240624129818288148844024C2191B84308849734802211082818442F148222844601141014C42820223118439AA2211946922129C14214122CC24123C24149022D26844D221683022A48C122196228426512C41241282781228843F45D510024162242E2842202118B1A812C44A8182414B44A91684D825140117484C5 -:804E0000819923C0282052228484441211002880C28220A4281C48140388814B82184928841184F8C4771423182203188504810018121818A012436944100841108844018022822204411244400488408821113514181810A4A418902440C8444289F23712402802974189048344765892484481648041014081B1448254221CC412008461 -:804E8000141E8812114418111012B14111120154888314423441618E12200400488CE12201DFFC41012800A12041130140A142144880048844881E41114C04121480D1421204859428122302221621424204682064289216022CC12C252A882102848CF164FEC01E508200608212204182046818482CC218896482818C2A8C0290A8867977 -:804F0000421841810221219C4108411991428722485116041148202822A848200800E2DFF80122002D113C248C9442004888251858828881A228272C002584C8944A8A0811811622015094901400009611012D82190290841100801112848818E4960A1A7498010024121A6281241682522146084E22A2240050140021800410068C8681CA -:804F800003499822472128182B24484E34351828912280C1241AA416A302123AA82426013F1407254CA442872213280185C442004C818122329414C0131E4193032B14124611B2182827344121881CA284682D6811E84219341190883E821B12824C011CE61144044CC462535242867812086F7449C14282A3D212312369947887466A24BF -:805000007C72DE1161164E588B344F4DA8248F41D282F15448557D41BDC57F24A4442B493668A815BA15F421234E618FE2E262E13431114CC2922B64237111E169E111782BF1285E16A281255444CAB154F434D4EB814F62F112811AE2C4FF18198BC1DD11242E24AE3616381D8E418B9127811E519721AB51184E82EFA1719831121F1287 -:80508000F2268B2AF549412F42BA12B324042D635F78B841334919B638716A4C2411C4A93E242EB717111F42A2111563229CF2A7185E16271C1714172A16F2138259CC26A1EC82E262722434B8AE814FC4D2E4066B1137812CE3A272586A8647267D2A2D192688B41A0631245897492F84E822FA89128BC28B91748B8D212E812D21AF122A -:80510000F142618E232B112F823912AB45F16B44E3127425E78EB346366B4E668ABA15FAA2B41CF341F18E512F71B2A2E9A4A24E2B854B18AF840D6C662A1FE80F424008602284002C48888884884486442211088524010090283088208821088241826182184880041A049A44240182A04914828112812FEB45F134267FF363812F33D763 -:805180002882F3541C15F4682AAFABB3B67331F2AA841F19F18B1B1B89DB8B422465F6475549E21AFA25A14F4CEC2AE627F731E93F99FB727F6F57FE3888CFCEFEA81ABF37FD73B51FFDF8B3352F48BCC2FA61619F9CFEE8689F88DF4FD723FB33B33F11F555D15F14A7368F8EF518785AE544C6283AA7B14F23F2989A1427627F7666A1C1 -:805200009F3397698CF74C3C3F61F27B228FAAE36FF3F382AF8BFA9153BFB9F1B5D1DF3BF9AAA2AD2A6FAEF4DFDD6F8CEE5AFAA7A75F58EC2BF7787B1F1BF6B1F3EF6DFF57C59FA3F8E6EEB79A5FF7FD73A11F79FEB3312E462B753F38D89BF2DCDC9F88798FDC62DB33F133716F25FDD6544D24E7C5EF6DF376745F4DF656782F8BE78DF0 -:80528000FF8E3E2F444AF375675F737738FA2223AF16F66A326D5CDD458D6A2FA1FF7276FED2AB745E98BF95FDD397FFBDEDA6F37373EFF5F14655FFD8ABBB5F5AFBA5A52CFA72722FA3F6333A2FDAFA342587BA8FAFF57CCE4FF7E76FF792463F735B622F14F27372EFE9FEAFE5AF89FD69721F6CFF23B31F1DFF46D27B914F42FBE8D862 -:80530000EFE5BF92B844FFE4F8AF41FF18B4CF22FB4A3C341F74F42767A7A1AF37F37A73AFA6F34E7EFF75F44B6B8FA5FF7A7AAFA3F1DAF85EDABF95FDF757EF2FFDFAF2BFB777C6FFDCDD5FD9FBB1B75F7AFEA7A72F23F27B7BAFB3F6B3BBEFE1F115158FBAF1FA7ABFA7FD75575F2F7797F737B147642BFC3F39F95A7BFF7CFCBFBDFFE9 -:80538000FFF6D2F33F39B9D1FF53D33F59B986FBDED8EFADBFB6BAD6FED6F88FC2EFE1FB8CAAEFCE0314004001418C64121A64221E48141230812813883291448032814C028001714269111802185012D012811404471240012482141244844412004604EF3E0E27284425C228218C064CB22821012850811812852412A842A1484625A8DE -:805400008422832432582A0480924442408441642410688960C82911B1423114422004184885A44A89018F3C042CF51124CD121FC1326C1F41324A1D2CAB141F48B24AF98128AB9453B84A3924AF543934AF547924D81AF934488D954FA2C4814FA27418F1244A8F19F221CA96C5CA9E24ACFC91244DC21F49D22CF89124EB861FC9B26A3D -:80548000F98124AB141F41B26AB911B24AB915F44A9443B24A3B342BB44782A9F9344889F9244ADF4A094D181F41D636D5C1B26E7111A4141D2C8B141D244E141D2CA99345182E488D952E488F543924AD912B4A8D954F82C5815F823C185D4A8B211FA27418C4435CE282E4C1F2244B1B61C7221B21E3E6C17262F3912C89F11124AF427E -:80550000F89124A9B215F24A8643FA483243EB2472A498386B43A9F8A45ADFF20F00481E1200000000000000000000188008000014000000200800901800280000000025015FBB0212142123410A2D3816284211480112A4444588B282024228A028442190620041814981012D6290211119F221140000E01241984413B414822132122041 -:8055800009422AF4E3F210A1283628180270216495181C21E28401B028C1611644F11224004D584419248442848382336222C14444228921018149654329F1284425198804849062471119741814B24C6318815F990E111F24A2212D1250228362421D6819911C222A01242A511C441CD2424382C25C1EA44631C2604432224B21B364427F -:80560000165128482B24818092384426267168561C838224B441C2241249C31160298B341483F5227780018188818071118801141183241158844A2293822004004480322200202251844443022E11134151414A2101001311181428B142123142478121414A28F2ECCD108202901212801402B0119498164841C814415410CA48422004E7 -:8056800000890212650200241024612280410800864822F14814C01222187048348442223F5E477131542154D01852281D1C16081B4189322200414B81142E588CA2241601228461812D4C1144CB2481D048E1423184430218301436CA4C23631329E928A452488C8498D22B248D1248ABA52A081E2870960D262452528042781285116223 -:805700001580248141151CE4C4529442848904A44C048C0426B848C21224124361484C12820136D48213B82881830829048C0523A8213668244A6888882A81F2E6961439110170132811C848008D22139388812099111828263211A0240085124411144418442C020041124062651031128AB4188A14B2CCA1412D4224188B12434694480D -:80578000F09F69108401851274281104482941D1246111C3428421220218B22C6112C71321825662418CA114611281C512081860834220275283244C68848169132282C122411A0224B044F141C2A012488992224240480284845508228140981800602481124C8418A442412052124C2613084B841200A4814130684CA412233341582135 -:80580000828904648648C214188F7E0E48400100182962C2481240882441221484332C81C44142008400C088841880E221024120C11410AA25000000A490121210C44884842F8E072A811138284226911830662F84518140C844C1246289A1124483D24851849902D0A4E145C2145827C884844302324B1843A12148A42C15E8138482E42E -:805880008453822CC1128123D822024C42C448C9D148F4F8DB90446032104658242881807111D812418821113824608398481CD22464442004818092125E24AC8142024088614183C224A18C9482C01259242482E181C41412A908009E15244096154932498F440270482126028442A02142C03842A90118412C0240828153828420062690 -:80590000044146CA1C2921117A28246162818D82C954848B242288418849212414F4268C200124811210B14201B041414814382100220020522832218AC24200401204C03680138102441116848412C124130111301C212A08228A212AF43976242031191820054A8101842015288211C84423B4280146088141901A205218830144322038 -:80598000121491121820012A61812A810884444422842B214C428AA214284FD545D1A11401111414997121421111E15214413159C0128901003021901119342142801491455A424AD812048C120427228D41294212744A6341250223DD2221C424422FA128481C42D88A47217824312424811290285880128882048C2264428143A21283B1 -:805A0000018F22840442244168004144124C21410811226604130400904418224B94588E44B0440888F0BEA1F05428502841434329022819042E14B01192484222A014488914114204882006202381420180C8148C722204904869A148A12449844211082544482882312418FF530B004008200424A44D4AD02241420227812012480218B7 -:805A80001126011418480048149044100820E444111814084284119290C4800842200888AFE80B17628428181014082002469148189881282512842122220244896181820028121816248661422241228022022218328E142C28880118A3D14212B848D224A1A4CFEF0C84124828274480434818084C41820248C0580042131403581386DE -:805B0000321C411113446814482146082C85410125A484144324C8C422388C3482C04880044121F0374B1437668E256F41E1D1734D79647D39E21134411F92F63B2146D1815418BF82A8161E2A2CD648E6A4E1852512D8AAD251B221726179328AB121D1887312A8211B2529B214D344D294D148D6427326E6127682DC1AF31A361F11F2BE -:805B800012BA37B1A5F68483AFA2AA83CD248F81F326264CF422E89AB872E2BA051E617B111D28A7222F41B4194191281E68A14AD48BD422D182A5352D286AB5463112497428C2281C81B524F482D12B7149B422A46417178F14B46455484F25B54234988F43F2221A47314A7243B45C62444AF8424A484F4CE88CC9544B1947642F8DFD5F -:805C000064848F8C6D824B144F42C4442FF34B92148487324138484E386E1A8D114245A833874713C5418B41A187C36E188B23289F14B531722435424618A894455418214D14444F2265C217422A5121437161A811CFA1A1425F83B424F4289483AA124B41B7854E448C47F28242B09C7A98A4348F28F8A5790018844018844442480324C0 -:805C80001648022412201128011246041002181002001811981118111815C882130115081B414008802211281108702F49F215325FC3721CD667F41B189FC1B131B73BF27B389F9652149D132F465111DEE86AA672C57614F424348F82F339391F13731C5A37BFBCF5415B4FC4EC62F222231FB7F278284B234F62F21F451F56F6958D8F69 -:805D0000AAF83A5B2F17F735176F63F31415BEB51F3AB82A43F34B4DDFA4F4C3716D846F64F462762B76ED256B668E88BA73B4F22554245F63F36575C5D7D7F45D599FC5F539383F12F37B7B3F92D2D8D211F25822B5E9A9F82222AF87774EF4561CCFC6E2A2F33B391F13D3F95133BFBCF41143CFC3F224263F32F2792B9FD7E246E746F1 -:805D8000C74E4F47F7D5C5DFFBF83F762F16F77577BFF3F33B148FFBFB8787BF5AFBA3982F8BFB5249AF8CBD2EBFFAFF6EE66F8B7A86FCEE6C6F44F4B4346F28B93247F154766F43761A761FF65B1C1FD5F1787ABF27B31BF1282BA5FD4933BD7939B5CBFD7872AF84F34616EB45CF42F72838BF93F331395FB45535BFB4FC435B6FE4F43C -:805E000072663F37F66B7BAFD67214F424266FC3E442F295C49FB2F33E2E7B777B337FF6F3D4DE9F83F6DDDEBFD6E621F5CAE8DFA4F5C7DF6FE3F87E4EAFEEF7E232ED876BEE6F84B724E228F17D5A245F67F73775F771DFE4F27D7C9FC3F3796A3F27F57B7ABFB6D69AD231F35A52BF95F59A9AAFA2F67A386F44F17658CFC3F61838BF12 -:805E800093F521285FF4F42543BFA4FE1353EFE3F736263F37F65B7BAFD7E245E523F717571F57F7B4C58FE3F37A3C7F45F77477AFA7F7DED6BF87F6D4D7AF8FCFDABF91FF5C5FEFCCFD6EF4AF6DFD4EB6EF89FB1E9CEF8FFF4C5C3AF3C4824FC90B6130260048008004008C0448241A14A84189220100002142311002184218104408483D -:805F0000400882E0880484448E48208922089246043F9101828041188C921828294148C1681880418841C8242242130355887221321841282C018CA5240021E022012A01181A0216081281924432812A344284188420F85B71C0421F41D228F1112CC3F4912CA7241D24AB141FC1F24A911B21AB9455B84A3934AF143934AF347934D812CC -:805F8000F934481CF9244A5CF8244A16F1264A87192E5A96D5A2F49824ACF491242CF591248D121F49B248F1912CAB141FC9B24AD941B24AF91128AB9451AB944782AB9443F34AB44783A9F9244889F9244ACFE30FBCD541C4511FC1F246111F81521A1D6C2F16E1C1F24A851FC1F242A15788AF147914F84A8143F34A8547835CF836489D -:806000001CF8261A8D954B8216E1A271888565594D4B8F49F2244B8E284FA2C5648D128E244F24E1C8D22EE181722CC2242F66E9C1D22ABA14F24A9236F84A9443F14AA643D34A7A2698BA4F22759607108204000000008002000000000080080000140000480000000044000000000014F0C56F0000415028151844F814288341214581B7 -:8060800084D42821A125214C3361542490418B212E110049114818025A92921425012C9121004321612300122694162E541A522428434334442FF1025A32A2C011896557181B122B1411A0128150482C420481C902494188E212446424C0488F111268434A11E84611C32490244F8992848C911812A29C38481A286158141028189888420C -:806100008641D83B0E7622041C81E42221F1142189551C4568138B431181684D12128C962A64471295A4213374C491482E1146D81843943989018D262E416BB424411E8C643628012E849999682F4289919528211E4CA2D022E24166581E4CFFF10F80024489D1C1541810A22118006044100A1841381A0480021A12023018414225288506 -:8061800001141922224941882101120050144C21825184890800CFD20C2001442631112400682C318114400140C8224342742428148102508228481A82410410022B12280000811A6424128B14123441242200A90888ACF4F438244A032D232810028312D8B48122721238181A142FF14294218925278822C24A142D154224FC427264225A -:8062000022EC4231251B820027512963534212A1382214463894A021124C341462D28B42F0CE1CB0120613322213024008D3B122417113C818184581E16C81321E1A82822682462211022528B1125242484313E318022CC21123128184F142184218871190942128184C8491C29810F815F71480114204330129128846220AC04384508203 -:80628000803644478840115812548C24D24136224C24820843022B124024C13410081E222242894541C41222406482488B2C428FF20930248C52232444C02284441A0227412644C88141E4105A9424942E18A0284146D24821D12441A114108162252849425848481242811524542A48188200436483404218F8D34BC057485048121410C6 -:8063000092214220446C32512C02604124E024818251841748BC141421144241449818274146041C08AAC1144008874821824F184102182C8109C14622C2525F620D2051412885512844CC0189028400102851121C32640012822A4402830328839228A122412420C118122180A2214400401848048C0A428A419444608AD0147412D4210E -:8063800052498551A64436DC828282532818454371894256851F22714854964AD18121D248C2262CF4542A8751788C51281883D261C114274130351628CA54286E1884954242DA1CC4184C8861AA4A298211C42485F27C72A01828C1282911410214CC044881504822185042220028862814515800244C322287440022B022618824160C09 -:8064000012408488842849022041E481D448883448486DC4601413029142304213840428D04141181901111001112810011230431111001854111646213122452142011CB29154124829C8810022230846021A58282FAA0126444231128139811282714118261532426024B04612344410845138106824894152248744496264285024C058 -:8064800014B594142225582641582588084361C449D8427282A4248860486688F48BF96018400924C012182549D8281851188941E584C113182541110214142210438171421158A22825221111110A2842112253911415827411429111800718A88128442D24CF440D2C4184021248224C02222885041C921228002A816112602620242261 -:80650000A28462200512E0882284026848126223944886082C02822138200443250148828F1F0521241210322810083502469188482C1E41914143CC6819115114100515021144491234541C7228110414A9521E14411C41C821C0816011442CC884C0246382288442F17DBF00190284005428481816A1122124502400160280331280517A -:806580001220014A811849415424422136388156220826C222A04B44008E42C042418240848191446F124BA1421844E0146221421914280620912400401408441028118895584602108116820480011880028448426081442C0446082A08A0148C08B03C0A20285221165C8155481C82D181548248148C91284B582C6132444E22490410A1 -:80660000140313888303218220982214284011624412282568422C216844182306122305632242C2285F9D08AC014D4A4392818E4412100140041A624212282281244410D62C82512888890285026012640044484240548344166148842E441B412884410041128149318282CF570317134F28721BD1D9D2945A316C2236418D138628717E -:806680004956189BB267152F21F116214E8B4D14344D51AC1259D295429A58562173A24192122E241D9622411B128E424E3115F2222A93736AF881828C9C1B29FC17818CF548722F22F884A23AC4A41E34A81E918F64F64FB1803282AC8231422F84F937511D2CA3F163481D31AF9482E9857146A4321D254E16737342BB2421B225653119 -:806700004F2284B451F4E2832E421774CB449FC2F614221572AE78417111D78C721EF12A422F4AF141416CD151F4726C1B315EE21B156C7583B226A841212F443312CF84BC86E424B6A278364BF344521713474225F219528F413648ED539CA421A7661D5227915D4216D9A9A4841B428D341B423F44524116752418F112292F127111985C -:80678000336D581D1E61EE4469C5216D462B1227311F867315F44421C5F446214F21D31C71EC631A4523FC5C8586F4442476B484B8E411E2C331AC45F845550000430288200280248244A441A041A041890228A024A02480028120044288001044080000008200200800828304F0E145141F18F4212395F319735F7FF321269F86F2393FF3 -:806800003F17B721F3111A3F35F3BA915714AF193B445F59F96412DF7AFB7A1A2F1424F65D596F1454FC8FACF45B5BAF967D1AB922F2A5A38CB4D6FC52511F2CFC41463FB5B132E31BFF585EBFACFE43649D2EDD2EF5FEABBA9FA3DB23F54546CFA1F92AAA6F247426D622F826A26B2285D888FD2A6A6FC14FF171533F96F41937FF71F7B9 -:8068800077F71F69F5572CFFF3F37B711B335FA1F13A3BAFD95B54AF985B347F78F936377F7BFA3F1F6F17F576355F51F12537E5DFABF85B5BBFB7793AF967327F3858366BCD2F61F1CBC67F74F41757BFA3F3B9FBFD3FFFE8FA6F6DFFE7F75B1BBD1ABFFAFB31321F72F75556FFF1FB3E1E6F67F5E4666F68F826244F427686FCDCDCCF0F -:80690000EFF7B3EF243F41F42167644F73F377373F67F31F6E9FE3F77B3239F1597C1F35F2DAF3D734EF3D7D6FF3D7D57F76F1E7DFFFF7F347457F57F135154F32F34F4FBD8BBFB5F572733731AFB3F2EFE7A7B46F6DFD56527FFCFC87A65F71F73D337F3BFB5F5F7F7EFE4F4C9FF7F655767F74FE7B3E9FB7FBC3E27F7CF59B1BEFE3FBF2 -:80698000F6F66F66FC62D66F26FEDEE8AF85DCC4FD2C9E6FA641E169D56BF43B3E7F76F36F371F75F1776EFFF6F66A223F35F57B78BF97F7DFDBDFF5F5EFDDCFB7F5C7D76F76F7EFEFDFF7F777754F57F335355F725277BF92F27B7BBFBFF77361FFF7F38F87ED2E6F4DFD56127FFCFE87A77F51F32D1ADFBFFB3F3D7F7EFE6F6DFFF7F68B -:806A00005F59FF55FDFB9BBFBBFB93F35F7CFDF795EFEBFBF6F66F66FE66F66F4AEA89FF74CC4FC5FD6CFE2FC30243021884418449E18164221A048424844048044C2201128504004A122204002022A48220422882041245E289242201820020C122800200EFB2072905181321C42422848100122001322001433142414018281288012A9A -:806A800001262811044828496181008302412822844212E08304802801124CCA493F8B0A2CF4112485F2112483F41124A3D641B24AF18124AB9419B24A3915AB9443F34A9143F3429147822D914F82C4914FA2C4854FA2E411F2244A87192E4A96C55A9E24ACF491242CFD9124C5F2912483F49124AF24F18124AB141D24AB9419B24A1909 -:806B0000B54A3924AB9443B242792498924F8284F9244ABB23C04B1E64AD4313714AF2112487364CF24A111F48D27AA1488DB19AD43AB8B5D42AB8B5948A5994927D482B945D5A4E947FA2EC11D28538987F22644D6DD99E252D8A1E2C6D599E64E5B391F246839E2CED938E24AF14C124AD978E248F3493248F7439B4A536242D94478A24 -:806B80002F44312629F924583F6E04848248820000004014020000000021000000004001400848000000000028800400001002EF4C4B121403288418361CD88182023018161428112C25044601C02C8C0425012691141C52244D281622C28217421292411E252088912C18119812CA8126844284824804C3E21646A1524B18A32181613856 -:806C000082961172927122E811223888174815883281A52425722194C8241C5241421821D04AE182211564512E11824D216D2A6E11244F11E2817264C9421CE2814891441445AA218D422021061685F88B2A9042274D811284922F81D21898211B1269C2212249C1891843822524E4320460C12088441261611353418321B12B21B866888D -:806C8000624363741423A2288F41C42E43C381AA11044AB242512844282A48042769DFF60A4B121129818211918412A52218289198864854818113584A1230258B8426F24821554281810285E4A2E1441244E41211D13461882E11284D1116681248141648A1414E914588A2422021044C61822FCA0C1001001123423448008200000000A0 -:806D0000000042A41001118048448242013450182881442C0100AD9112002901880041C0424F36062440021054819013404271130818911A142342611414414712111B2442898218584184226041308484416021430450249122001C08484848832281664828F76200400210548241A301C0821C014009212214421440052E4821944049B0 -:806D8000348844B016126148154214C8224C142441548128990182200442838231248624F244FC00350800111C021C0464118C0212A0411400142444225661184228821041810284004608141284400221708224430123212408C0426024DF820E002485042250164562228418160250422E1827628015A484004622C4141820442415120B -:806E000004202182084218250110A248508170220818899128844241E05A4691141445081341038512C1D110028111001820220813122C481902121240280439E2480350282AC4184412150484218C41628144480030142042FCCE765021241902604100848140111101008C880183321820128C62A6493229C09222104212712222D81415 -:806E800001288224000025120440181824058400E792002563C2C1F02112502E45EBA2082711195183116132872818522E84831421F248821B24A3C7342A81B414888744641226D522233A152846C814172144508227282C51688351424688D148812141684285724C014D1140031C410411B0111408000085323420122889528444844482 -:806F000021858101250A25022909608823A4212C081400488111608240082E48858404412F3B091440014008110018008481410014221C02400220B1220422444828002415148802400221100A240000220060824224AF22091002122C8152420016D18308212C48C181215C48024411814601150C184912058846B48241C281C0121D1829 -:806F80001F2822F28118452812E8140125213111454808A41E48484840E817070011407228020020490288944D81D01448231244424802822C814404C041200888154468128601131802904300211144200248F0482240727507953A482021014114D02151D445B424E2A222420200C0232513B251A1118F59A88838284712441D814D61CB -:80700000395188B5BA48A4542F846122228951842942D84C51644F12A23232848410981A46522229B418F1A5BD0018100341120025022100200884121100400480420226028008000000241100800440210400120000441F1E0A818C2484041002214014E4E862828A12110800190821292181818808812810414118E881A414482400284F -:80708000212444618D24222842400800282129F12A7E50828004200122810044C0224002141140D22112024931248800001116014008481901411211842140042C1208230480041002BF52058004000000C084800200140000218041810800001D41008480040000211114441428400100001002185F620300121602180000408248020058 -:8071000000000014140044410000000000000000211424840000000010F4E7C5301883246424221002205844C5B42C2222021144114002241A3114921482005011105388818B5442422840020045544C6B222662860020042440A2114FC30B50884848000031200845042A12010000146121284B912E8888442200141501128588A85424D0 -:8071800011401102004514A92240480800216121CF570C211249010018210024008420116A88008800412002224200200800604188C012184002145018000044800400D08F06004001210000200810084001110011000000800200000000100110410280045622040000009F2E0321124414212150222180881858A8A18295518550118002 -:8072000012147424240210322823224402001816A41828E03151232558310084152244B24804A0440041F09F1C2400121270140250A18882D0A208823C518285210113180111114039244904000020018A61112455024012D223145228948D49008112000044CF380B121818358282B11221022424A18200118058118048414144D144A2A5 -:8072800022408482028A090012003012312641015019318314A25421452804800241CF6B016F22F212222E122B11122B11C0123592822F31F111139B989E888D888F18F44848D0915411488558884F84F448444F42B444F22424222E2480526445E442F226222F21A2129AA1812B99823C512229F812131F31B189699987848B488F8424CF -:80730000E48404488558884F84F47C3BF0262265A2123A211102142592822D131F1191811F89F818888F18242C44511150918588F44844C5B444A226220050424584F226226D822E123AA1812B8882822592822D131F1191819E88878189A444420040588848FFAA0A00000000000000000000000000000000000000000000000000000068 -:807380000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000000000000000000002F -:8074000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000AE -:80748000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000002E -:807500000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000000000000AD -:8075800000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000000000000000002D -:80760000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000AC -:807680000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000002C -:8077000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000AB -:80778000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000002B -:807800000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000AA -:8078800000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000002A -:80790000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000A9 -:807980000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0029 -:807A000000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE4B7 -:807A80000F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000000000000000000000000000000B -:807B0000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000000000000000000000000A7 -:807B80000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000027 -:807C000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000A6 -:807C8000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000000000000026 -:807D00000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000000000A5 -:807D800000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000000025 -:807E0000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000000000000000000000000A4 -:807E80000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000024 -:807F000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000A3 -:807F8000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000023 -:808000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000A2 -:8080800000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000000022 -:80810000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE00000000A1 -:808180000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000021 -:8082000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFEA0 -:80828000000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F06D -:808300004FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F000000000000000000000000000000000000000000000000000000008F -:8083800000F04FFE000000000000000000000000000000000000000000000000000000000000FFE44F4181C21880412802301441E042210844D021A22186824228092398521111818188008D8246242241C1418C0547821E4848430212890180420280C222162825F13F7E242816495129D14485942E6362221AA221178845D824322163B0 -:8084000072124C37311F89B48241B8560817281626F912812B811F84B149E98428742198419C16988851468C65426D22422D24282655484E2745D842B234F42612522901842D4C5FA207211601301A4445481284810286880861403137142884810000881282828840021138C088874160C52C210422104128D4420267242052229018525D -:80848000EEB720C22818910010022C2281C115C1902126742804D08394828692C429B88164412131811218807424281641014242808452422132C30111842604452204812C44ECFB0A110000008422440022000000381200002311C211008501C8890840182804415048446800004C42022A81012812001FC30700150815148832240044F8 -:808500002800434202230129882881810110018C3812428D41816014800411118128280044204204002022810140F21E4800000000000000000000000000000000000000000014000000808101000000F0AA3820C122C3011881442A11821288921885238111E14132112C428994484188004428004C1462821D341211828664414826815B -:80858000621481A3C43810088110141408C024418D5234221601871187125C7212C84122257182C219103488E4008285A45811822A149248874527228C6D85212628084A58142830384044D8488882024287144644592400123604C11248EFCB4A21E13172144891188D214D1826031483681389511829111CE241E2183128278C4883DCAF -:8086000024028416022BA18C04469C8226F83184160482A816C444938238418C324A6AC14849141908444100452813F4243730220016681244211A642228254208418928410110C411118084887448342483C41220022044912160C100C02C2200841484101402184783004448FF48072228000000250140080012241114320060824211E8 -:808680004231109128003081241AC21160121121153828100214004100008800F0FAC6001695140042AB1290188D1127925260B18958349C02844D439CC2218D14148220614483C318882B1283A3212014942811211694184902104182886194AC14C48862A4184901F0D4F7001F4211044082033195020024824551831414163121148460 -:80870000850114481C8441312860811211468291191001215528023110011C4418122812B8824104F03BC120021800488190181817828B1470184128612240686684221624820C2C1134281628B81282822208262412912217418C814208402228416844418848001200FF88029584911148481440614410243518891154488814B3127AD4 -:8087800021088145091B18C02819211168138303288C018C048418102481014D11128084110C848183C1128C11F88BAD24814C0229051049042441002E4150124480018244430223A2181724008421110031848014229484B81C0240314484C02A80220162C042A042BFE64BA11200818C311A20018C92192800208121044B12C0881150CC -:808800008484201408131118B22821210290310081231149088C028C880148210000008F3848D14322C312818C651181433144892221C1181E41442196C4431781897321388855582C22942C841499183D182E18A93218312A01C0318143E883B82731188C41414938884E121883241118188825C168CF1606184414122484141100A58153 -:808880000684701508C02241884128118504142628010012221A0250282024014001A0611810086C02A0421810083F110312282232104208182884230600C0311C218192311C4109406B851CA4211412811088311119D21802D0818202221140010081200200202272CB0B428141811608008482004D488E4848850182004188188841181E -:8089000045210A40088430218A02008A022021281A28010043618449141804309C825FA601121008A0242142208401001098481C94411200C08A002400811118200440C4222A014484B0188828015270180212A041208102414F8F0E1400421044111414446164490187422290182240C48822D04109104981084001B0910220348810B1A5 -:8089800084020081840000208242240882CF41072022922822008021A2122884202182220283922980082184812A883249848B42848122482294238A44882232482211008908100280021A2282F2E98640088C24010018004004400184508400361835417042018114180000008810381222402802001100108808200221F01B2CC0644211 -:808A000048901C50488428128CC48C13A424481B8400904182144098881004818001482200208181823818001880488441888834580096081212DFE703000060220028302424008180C1482E4114890122148440018301141818193281102111491861158410418918810888C088002602006FC30A8C021C04263144414954144905C48026 -:808A8000024C6514C01C58002D14C01324884820012A68164A8841888104121841490800D4CCC4284004224C0230842728F0D3A1006A82C2281E284D2444811CF394245992289741207631A143121CF171383E948F89C9949718FF7848724C3D288B1289D518014A1498111BBA13117952A29D1922B198A88413484151518C18084AB428FA -:808B00009128A0A249A18A96F4DA1AA04640B83871282556874B1445A4548F84A18661CE481889F649281F96F44564484942F11D212C44984119F1C1811F117211018B33808A621126E1B33281267834716C18F488282E9115A889CB448260C825E84C6A424CD2A481D24883F2AEE4F0113484C712422CC142814C64832236C24A4E48D0AA -:808B80008DF444881CB18871384851991322C288D09A51228C46688817818CFC18286E49B681B48482F12838897288D811E3C2228332189568818961816B8183C1481A2422A18A122B825F9F0D1504150411421142118819841881088841A84188412843084100008220084288008008000098808984092C9944984588490884F0EAAF14E3 -:808C00001F1454D5D14711CFD5F44B2B6D444F51E554F28545CB4DBF34F4CBC5C2DF5DB768F5B5D54F4C71C5E846F4A594457D94F158444D846F2454476AB4B1E815A4819F84AE794EE88BA11B441BAD85F23B8B2B441F1BFA4C44474B8F84F79818CB1919F1D8DCDAEDA9D146F1D8D84BFD8F49514C4F6BD9C8B8B8F9B8A26D11F04464A7 -:808C80005F5616FD3C39CFD4F64F2FF7D4CFD1F514555F5AF78915AF2ABAEAFEC5458B7D8F1CFFDCDDCFCAF3E559CF94F68893EF42F23511FF2CF5838AAFF45D232F14EE99F8D8C91E895ED18F8FE716FE19381B441F899F389FB3B44AF799B9CFC4F7B4848F847F89D948F889918F4FBF48C4A84F48F9D8D84F86F62884818FABF98AAC06 -:808D00008B8A8BBB8EC6246F4796418FD2E2427265F62E6EF5FD5414DFC5D3CCFC796FAFAEBE4AF648C8DF55F5FCD48F83F524F11FC7A4CF13F326B8BE8C8FB4F58B8B6F24DC77F422489783CEC11B118F9CA67D4EE8BEA95F4EF794C495F3BBBBEFCCF495848F44F4B4AC4AF529A895F591888DB98F8454A8AB89CFC4BD287424F8B4B436 -:808D8000C5FCA284BE984F48F952FA343F15F225648D2D1E345F61D7FF56CE4B15DFC3F73DFD5E72AFA4F2CBE1DFD4AC53DF57F7F9D18F56FF715D9F9FFF3D1DBFDAFBB19F8FB4F4878DAFF5D4BBF4AB691F9BF948591F91F1C8488F8FF769E81F9BFBE5F4DF5BDB39F3F3B1CF4EFFBDBC9FD4F7B4AC6AF739B8957119F98C398F8D7D2814 -:808E00007A1AF2CE5C8F8F7D24A8BB2AF2BABCBE984F6AFB3A7B800122001004200100486081F01148209128128182813100899211811881002A012641A812844712842A081484C04840088C840228824C027FBB0A8002844D1228811241288302A100198402421508C081C081219043000042221308008221008604840014001002000011 -:808E80001886F19F93C0421F4152281F4932481F41324A1D24AB141D24AB941B21AB9451AB9443F24A9143F2429147822D914F82C4914FA2C4814FA264114FA265192E4A96C54ADE24ACF491242CF4912485F2912483F49124A3F49124AB141F41B24AB911B24AB915B44A3934AF44B934F442944F83D442F92448984FA2F4F343D0A2E4B5 -:808F00004156281E64811E2CA1CC921ACCF24A941AF24AB44781AB9413F24A91F04A9117822D913D482F14F1215A4E912E8A87115F226D1D2E4AD6E5B2645DACF5512C45DA41D628E541521C1D64AB141F49364A1F41764AF41124AF14B215364A32A7443A54423E4825F43648986F82F54B7B40084904001800004480024002000021005A -:808F80009088000040014008000000004004280000000021429F770919812221512490749028152821818164148C041D18442D184611C11184C21584814129D421840252143824848C8191412826414AC32889E11801482884002E144432C3A2284F2B0F22502422420084182B124E2860281628082C028C01211A021B4260821417A41ADB -:809000005C488C91482C0838418A514121CC829218200842130212811210240212421C24F4D4BB90114E28122B2144211A140822CB43209B1813240483C1182137241C32111A843C8419C1528DC14D4817211D4888428D212A6124554A782834418361128652212AC4211743124228814122124D126A118CFA9643200241200443028F22AA -:8090800071110812244888842C12416481200117827021081528018324022921112409121828221008811688088112003024004A82E4720A6302004722484110C2488302810084283289A8424A0800461402224614042622086022822144201934110020088414001220491484012F820318903281A9C1168AD18441218348C81216082DAF -:8091000016C5011594141D141411418242668B648212CC2631342B42460412A8296B129038268881082C315188614E9CC488224B2426889428445FA74D6243303230244212816087A880C11840564140849554004445021C1242644180839142008A81E8429121128362811288A081428958424C488C084A8A0210F4C8AA00008562A116A3 -:80918000968416160184818121248361822A918943C2811411A0484883243668F0244830A628492452222C8208821694210040C2111031582081C214C44CB418026E5560214112214840842802C11018E441329883822682D181984244469828821285342128425C0221442A588480C51483618441413014142C122C04811002803C888466 -:809200001F6E012604C0681608C02483111C051880228204002821802164C8800246186291200181A0422142800122831424288113888141242124420418BF1B0F13C4122216342449628183880412224848008061412823816191005049488444002281181A14826182C02480611120A24220840188185048108821F85852E011D642A128 -:8092800021A3E2C16442C1228150812289954443A11A83A625411819A11416C9486240EC423421CC82941822A1122A19A6212781524C02411741421A621A80B5180483C816188744284A1888F855993084106241228041AC16C418000084003822A90A44105884164118C842302480418404801264818B1412228480C41245081218000070 -:80930000458849F8E33D80042081018504404428538200890144404408006022220040184118010000484410280181821A14A1412004802807001F290118418D241008504230883A044282430441AA24044486041748004192484210088C2101208182B8491118C4614E34D081024214B02831282847821028A8429F54462208616280024A -:80938000100244842245084C1252128423082200254444384425C92211003024644111E484848009811800890143018083014C3818C4FF6D0E122922422631840083210400301E118C24341162134808008400121968212485048014414401501411000040448102C480B884829424F0517D00411850845828282228122116885422303887 -:8094000020023AC88416F82D822211182A24122422921400112A0118139A44302486118483010000800490284814AFF90E800241008041C4188418212921C11C41168C81012D18290224484CA28113018416081E282081E4A304121412812A8418C82C46A1284C812882D148080020F8A3E33024803428A28F48820100624A2804422AC85E -:809480004122536442D1284421142819148864871D144400192902206244801241B411541411C4460100004189240589F4884C008A41981221901850844830281048082485419C820089082A584184608211802402282251144788842A31288A2111081828C901A0144381014C61493844FEE970644A8245982484E04491324941624424E7 -:80950000380029829122839122123D249014214A18041686A283144C4864E1244946A21260514088E2144264112820422812A4128308A74C22AF220F6892A5F828262F89013845C61483D848C1324E6A2443F52C122CF22B545F94F2F2181D298B122C7884F42281226F8434142F86F431413D35442D28CB118A322525F533158E2A9F4305 -:8095800084322113684389BF3172887914F1494453212262424FC1E342B9E4E945F45C31CF86F41EA930348E242CF114184D244F82781488B63AA2243AA68621274C4CC128AB444D28A5843A8A478926752141521689E2C2991847A485CA41819C2863255384524421871484CD999D1145589C1B3113D48489C4A4124D1820D148D4844954 -:809600004CF41E97244E1667224F432234288F4552281A51844FC165A4AF8194188F81D18AF412854FD2611D3E5245F424964CDA8CC38A4D249D6436A54C1F11E24823F338B84741285D144CA321C57238E18CFB155CCF51E341A26C17474A21B22865111C81F148788B216AB88CE28132A8AA8CBAE70DA012A012A094200488C082122C21 -:8096800008A813810A89228122093388921181B08802822A0114A01284490922204288088884888088840854E04402424D5D70847626F41E2E6FA1F452C88F86744CFC6E2E2B644F48E68CE624A7CC8F2CB482F264563F5CFCEE473719BF3E15F2249455EDB2BA66545557528B615F5AFB29476F749CA24748CF43FAE4E41F74546216FA89 -:8097000023279F9D56D5515F58F885DC5F53F148681B18CE9857545D149AEB8CBC24B294A9E4CF88FD8C888F88F82868BFC2084F61F2466EE5FC366E6FC5DE88F26C3CEFE7D28A76CCFCDC4E2F2CBCE2BED4748EFAEECE6F6CFEAF4F7F3CF66747AD28E7C25D25CFE3B344B424DB4484FED5955F7EF85FF55D954748CD8CCFCFFF61476F16 -:80978000F4D475D233D2DFD4DDF42D1C5FD8F884E55F4BFAD8E49B2A1BBE5F48F885841AF1D8D8C742CFCBF97DFCCFEAF8CAD84F4DFBBEDCFB28246D266F43F7142665F652744F436261EFE2F652781EF48FC4F4E8F24E788D8A2F25F5EED6FF56F56EC72F17FDEFDF7F5AF92E945FDAF925BF7BCE5D855757DFD5F625259FFAFC7757EFBC -:80980000D8F2B4244BA3BEBC5D372F61761AFABAA6CFCDF63C3CCD2D5F59FB59185F5CF848441B919F8DB3D1F915143AA3DD4BCFCFC1F1484849B5B6F9A8488F82C5BA242F2DF61876EFC3F26E2EAD2CCFCDE763F33E7E2F81F75C9C8FE3B772F798BAAF81F9525AEFE7F5FFFFFFF7FD7FFFFFB7FDB7B18FCBF9B5B5CFFAFBC4C36F53F2BE -:809880003D7DDFD9F7DDDDDFF7F57F7FEFD8F2BC3CCF83FBB1BD5F72F23F77FFF1F19FB7FFD9FB3D3DDFC3F3B5B4CFCDFE7D7C8B759BA29F8DF71D5C5741BAFB7878CF4F7C2CF878FC8F4FFDEEFC4FEFFFA4DCEF3C072B123026844184221E484302800448248CC42419C42413D848024411286044A02419912849111804182002618440B7 -:80990000E81228286288A0494482289E488922812228045FE30A65022542A4165028C4428CF2281210082D141088D422011C28C284864834221041110421204204446182811B416041411A041118008081444458481A5448F03E26E022F4112487221F41B248F11124A3D441B24AD141F24A9219F24A9251AB9443F24AB143F242B147820F -:809980002DB14F82C4B14FA2D418F8264A1E216FA264192FA2E459C24A9E242D4A1F49C2421F49522C1F4932481F49324A1F48B24AD141B24A9921AB9451AB944B42AF44B924B4427924F842944F82E444F9244ACFE30747A21B418F22D141B448F11124AB141D24AB141D24AF64F91124AF249A258B9443F34AA143D21A7B34D812FA17DF -:809A00004829F224588F1491C68D216FA27D98F5224ADE252E4B8E242D5B5E2C4FB2A468CD53CCF268111F49326A1F48B24AC12CAD951D64ABB45D28A9A943AD842AF442944F82F44A1463F242B44FA2F56527402888040000004004400100000000188008000014202182080000000000000000005012F06BEB10022B1218244C022220E4 -:809A800041284201852521628119C22480926811405832428CB22401232104224A4145C821189014424115484838488C2484842168424014C824829EFC20A5285028812C24A1818314848441C88C21264C2882085218802204408D7842C82124004200100288A0218A2219C1111854144CC2A8541844424031449FB30852E6A22184212805 -:809B0000122A1118D4842462128728512E148183C281C0521A324832488728D0439488C426321121102874444128021024C6249445012E5884193464823034444D428426E54974940621001285C2442188421220111814488822813224002811001484282B521420044A820124111882181288928117819045008933850000004F440D00D0 -:809B80008280080088000000000000000000000000000000000000000010010011400170E705502219214114CC21624115BC22C161128E822518B85415E322486148841A9B4947586AC122129493C44823584C18284A2C92178FC184A82E145044250A2AC611859AA24AB42411E2210887481E18A8CAF42D2A90226638114C312C28544214 -:809C00004125AA1148268178821A98144827238A48A5114E289BC814444542B818031F943482812E1649928252196148499828146614648129A342348A184298148AA4832425A4112845F8AC72002008880080080000000000000000000000000000000000000000110010011400775E0012100111421781604122111001004814800398A3 -:809C800015081181209114404A342400822D111098411830421280144218A8494058484181924A48F8D5893426042642FC18248584212211A841A3E581745C021218169C888B161D48196114444110C24D91284364422A3112184616443428294112881B91818011691113152891922229A221428441DBDB34260428414902122270188424 -:809D00009212701102187048748831488B24A094851114110A9CA1124289024C026068118123612480098E11205581939159898481C1264942A8584E8844FF510D204112C9189524941912A01493B448C14C00181880C31119411104009744101444343629217144024C2142189118282D41001002A081D08218082A0110F8CE5F002394D2 -:809D800028806441301830481C17CD12001810044418CE12125681464168848C4428C141460228AF4423043880220118848481440028209414451218528483F1B8F120A225001828842200302400168822842202294872245128242A69210024404984028148812014082441447024820248108801006112127F960B4840C128103914E05B -:809E00008412428811CA4480186484122A114108000041200580024400401108002AA41418588004122002424880A484EF330C2229238282741954482A61862D481D488D21833146892109CB241828314E18112C0425911861608412812221446906841B128122002B614684A1142180840178431114028D548C78B7094850188418281842 -:809E800084002A21110220624480321498824C53814A22028C34482C0148462482820100428418106481818C02482012088034484180E46D08411100811412405841840091CC014061415E218489023445D8288142028522014508120015247411480224118148241005901444634288223148F0613D20011011C418488922025844410010 -:809F00004782C018284400240040A24A8D16408A215281242800329018008324911400200423C88820311A8140F25B5A0000498204701891162850811008100820818194148941280684A042404CC84260448415082810482441182A082480688400448694441282DFFB061128932214D14852818624021128CC8501814931284260844199 -:809F800023E252841184420480226411602484444846841482049012005821984400C81842308242FF21038A03109C34411A2202890228180022482621A2242A614248C302A2248F216222368224A44100224441188984C4386012428442444A8194442094748384B31684E414F182A74038244412004441811480854404462443041508CB -:80A000001429014342D48408001829018F1104800210A12144893248288281004C8121240222803816A3F273CF14411448260113270400284008468401101404120042421248C18420C2210084B0284488013304002120241801418AC18810082D88D021084A2234288168802204A0248C0112008024049052538224428224210342001230 -:80A08000425884400414184A210252884014A438184304410024889F4B0A84003018400C0083614480C21848C30214C021859142E01411D88448048032244D41241284112A3421289025D120048744821D228230881281203C882504CB31145B42821538115B368D389742148185F161288B34421CE145D188353885F82445283CB211D15D -:80A100001412C8255845F81A6229325223B142D644F211415823D2896242DD14683B341FD1D149A2442B312181D02371C3A4829A782488E1A271146A898FBD28F2BAA8C0241F561218C44C625AF7247284418B1136694143116C464D184F12A4247E158F82E59266434B2226686487244F8268E2848F24F3281487868B1427245845D484B0 -:80A18000A24442163A4A4D4A9558A88F81E888A881444935C44CC592C7488183C8844D54DEC8FFF5091A012E248FD6321857514558C83E241B224848CD58854898244E241B21125D4812C7444AF5435DEB44CF8AF232244E14CB118F22A24243A151A4124E2450193AF23919B02426E113A2444E544E424B444F14A8811E16C784DE446E7E -:80A20000E847456ABF4C0525F27938144245011C41480100140040840484441110011110012181290829010021422601146032601260221A4421488204800228009028DFE84F21D451D2CCD2DDE7C4F44165C7424F4254881F12F25C583A31184AB41CF164244FC6B654F138184F43F1341C4FC3B114312441CFE2D2ECF148228EAAAA3A57 -:80A280004AE3D54454288B5558474245F41444817E526F95F56C5C89F1482AEB8917141551357F11A3888F43FB1C344CF19CBC9AF95CD48E182CF2EC49E044E244D2CCD2CC66424F44564CCD6445F42424CF45B718F73834CB45CF81E243F374745B35CF837135F4545C77834B351B568782CFCAFE161487279E9AAFAAFA5852AF15C4489A -:80A300008FB4F45258588C54DCCF817418A1554F84F544544E19428F4CFCC9491F1EFEC5C14BECCAFDF8F4CF45ECCDFDC4CC4FC9F9DEDC4F88ED89F5DCD5147AF425658D28DFD1F35C4CDF56F66C2C4F4656CC5F53F3585C8F83F158784AF45C1C4FC6F65C7CC75797934F53F131116FD7F53551CFD2D111E2E2DEECF5686A2E228F83738B -:80A3800048F84C494544E285B512F72161D5FC111519F1717BBF95F579399F83E5A6F39A9C8F88A86455F393914B88CBFA4F43E346F528284F4AF94EC4CFC4E426FF74D7145F55D65556555FD7F3794DDFD7764DFD5C78CFC1F31D3D9F57B738F35C78CFC5F57C1C4F42F65C5CDFD7727DFD35359F15F77D5D5F57F76D4D9F92F224CEEF2C -:80A40000E3F57C481AF13A1A8FA7F55A58CFC4F7494A2B552B319F1252DD1F15F371733FB7F77B78DFD7F37153AF27F3DAD88F88EC2CFE17173F5BF9C4D4CF4EFFF4A4CFCFFD2C2C4FCAFC9CDCCFC1F9E8FA2FC60E221044382484436281002216081A0412281A84028922E1440289028744D048028324022014042280C148181E4820010F -:80A480004820482449A44885042049048F9A0C86112112011781202152C1183048109844C0481C2141954181411448286D12A0121225385820110214150C48251181E181941A001A54122A041290444A01C0417F330A3CF4112485F3112487141FC1764AD341F24A111D24AF149921AF1419F54A9143F24A9147822F147924D812F9244828 -:80A500001CF9244A1CF8264A87116FA2641D2FA264592D5A9E24ACF4D1242D421F4952281F497248F29124A7241F48F24A121F41F24A921B61AF2419F54A924B42AF2439242F2479A4989A4F8284F9244A6FAB0CACB11156281D64181FC1522A4C92181D24AF44A921AF448BB24A39242F14698229392429F9364829F9245A986F827C183F -:80A58000F126C85671226A586D5B9E24BCF4D12C2F22E44954289E64836649EB1686B4687191544A1F41B2489325AB944B424A19A4B4848D346F8284D926D5A60200480000008240042800000000000088008100140000000000004004280000000020F4B49C30240020449A1C19642324C0488CC1144283A4411243883815C04C44002850 -:80A60000228129641149042B424602248061CA2220F1211418304280A4484D5A87414B41A997488D249018F0A5AE003F28624181841F42018516189C1822406A211C01158885260622C028A0144508851412A2414D182D14523287424D234A11F4122487428984288521A418148022084301411483F4FA8D40661623113848851344C32AAC -:80A68000C12062C2CD124A31484883614C2ADC340566244128A843818146581253846482A394426A21E24162CC261462C35B25984725582A2431418CD1C2C1928B164E1847A2448483F513AB200241001E2489C14C18901A8C840124138111810128101884023024102611229156168401E1112B12B024018100008A84984428490441006C -:80A7000018F0824B4092214054224062C12244002C01188414843021142688C24842111261460581604D8052241A0240020080048008814B491812892368441A44048F984BD1526141828962838D41C4D05AD118D48272623A481D164631138C6E64C0444781B0C101112674227138223248636561224E122440C1324331242E4244242403 -:80A780001F22F1881118B9D121C145248F42044974422CD384C81850EFD04131228849F21A2248106692E42846784252241215F84128460A4E214D11284E218314012B21E3E1443248482C812474224282211242C22241004E111818881C1188D98482F1483489BC14E241484CF2747F10D241018110496C81693141812992181CC14129D9 -:80A8000021180441818198809425112C1241321C41432B01412681C1144C2204502228A718249C01671446B412042441428924015FA745E244622516182C4424012041A824124698141C0148243265682241818051218C1822A21216810448200438AC4104886A28024D1860844887241014082658824C81F1E79B004A027022048324612E -:80A880009128008243410147818484204A42C81226C88822128441501818D081A2215211812324C1644611284118844284018842182814294828E14A05400412103A24240040180A818448121A0420844144C44418481A024140240121C0140028882C62112011210820911C8C81041C0820F4AC8624441E2421C9D142524A8F41C41212EA -:80A90000328428A971541868818CE481C44232678268C445CA24C9D42123C138224181411866A1211853D128735802AE44823F83A4210082C3A4417012D448351822848200EFE20E2A0489014220028501C04888C015114C0189018880018100AC04411A822105100200E0410219860889711108001E48890842804AD84881749C0D5964F9 -:80A98000181844895494114FB21414141108644485851424140520044A026241480022004604412243241402290C2112884261182D426A88942280120A4D1A1F290C004008184418281800521321110226518129010068414D42200916021628C12220031210088305AB244C28049858001288800418009FF3042048342800421842148C1F -:80AA00006812811008111200A0410028002290522004004240041842210080881C6224C01441A086450243A4814AF8E798203124813143219618484C8282618121002633184601AC4261C210042688C842004604C064202182044C02162482239822400442302800A0921A28027FCA024C240112100441608480324252100AC1111304B040 -:80AA8000442A22448494142314843818288006C028188C94248448483880820C4CE142042A44B4289814228423F2AFF400282AC1226850840049828204604416148222D682612210924A4448002242268452144004800110012C213144184C11180420881188812C8424F4977E1429021032881A826482481961A500C018F0182400224914 -:80AB0000840400242848800200408282024400232242040040028284808D04818885F49BD4A0128222200222200100844180024822B011826241418092142818801301802184013024181004402401202C1104848E1180E81281F8E85E5082444D486412C681018148E041248102122E411818437442941C290218818821412410424102C8 -:80AB800025084C8422812406442CA12444182840A2414901418504A502FF554DB15434A42A3212AB91493134C741429B54848F86F21848407634341287128572116A142E444AE4C6E246242684013E528E448B15442E224E641A0318682E284CE282A5444E685AA371388B1145064B462B234E424786176896F4224C3EA14F82F4DB47249A -:80AC000027428E2147E11CA2264EC1CC85D348F534254A42A1144751CD18A5BB4C7345B42195385F623348451694248D4C1AF676C43A64443AD28202424311A221C321714C64258F4562624F43D16438A2DE82C24AB45489F84C5C188A949458DAE998D522F9E1F2C031169418C7E2CCF4312C87146E4B4B22F098112F2115E22421953181 -:80AC80001F92A4714E216F5694424F81A3B248D0247222C4222764103621384425A24643E24252441E52195422B825223844D0242CD122E461A188439BB87E48CBA2818572C8F483C714800118400120410100002400122412200100184218800122A0124218B024012E124002472212224082C4224828C024800228EF35470122CB212EAF -:80AD0000628414C5DC44D2CCF224258B4424AF84E444F44444A5B1220247448FA441F42C4CAAFA386844CFA4F126266F211C62236F68F81928454453461A64848F8112A44495FB1C4CC5BE145164008F84F48496684D528F8CFD54146E889788A285F81898CFC4F42AF314126E44CB22CF62F6645C6E414FC4F44434C784CFD2F26C248F7A -:80AD8000A6F26A6C4F44F44C6C2AF26F6D9F93F26464ED2C3F54F26E48FAFA7818F02CBA6F66D226BC62F664666F685A99457424764E9E428C54C84CE44651FD8558EC6AF414866EC48AF868A84F68D94446F29CEC188F84FD9C5C4BDCAF84A4FD4F8DFDACE41419A543CFA1F232288F85D419F22D48CF83F75C7C5F16F6494C2AF24868EF -:80AE000085FC4C4CA712BF96F664455FD7F3611B9D5DEFC1A5AA8F82D7C8F46CCE6F43B272A6414F63F49E8CAF91D244D264F2162C2B451AF418284B338F84F61B2BEFC57446B616F3C2762F49A3748F8DF786966F41F52652AF86F5FC1CEE888F9EF8B4942F8EAC924D36EF1A41B313A773CF21F37A32EFC7F17D255FC6E486F36C38DFCE -:80AE800092F2693E2F26F24E788FC4F4685E4762FFD6F374155FF7F3723BAFD1F73C7CFAFF6C5CCFC6F67C4E6F47F3F2722F23F37676EFCDFF7A794F42F224266FE7A3558B31CFC1F374348FC7F37F7FAF85F556762B772F6FBFF2AFFF8F8DFBC6D66F47F5E6B6EFCFFFE8388F8EFBFC3C4BFE7E78EEF84F2EFF3DBE10022210C44843C2F7 -:80AF000048221E4826A241C0484416C8248CC4261904A0246044A0242014221402201402004110A441800482A041449A041A442439489220D8F20A824C1248342213010015344828001811215150848B2441205248411086722402004014820244418C148612A64929818401215042862854844248C04A96083CF4112485F3112487141F04 -:80AF800041724AD341F24A111F48F24A9119F24A9351AF343924AF1439242F347924D812F924481CF9244A1CF8244A56F1244A96E1A26459ACE44DC25A1F4DD224F49124C5F2912487241F49724AF28124EF24F9112CAF249921AF2419F54A924B42AF24B924F4429247822D944F82C4944FA2F4D3E4C05A4CD628C5248B141F41724AE2A0 -:80B000004132481FC8F24A144CF24AB24D28AF24B925B4483935AF2438342D816F8B541A4F22C5914FA2EC14F8245A86E1A255586F326D5D2E1817CC6D5A1F48F6245217886A7181FC42111FC8B2667911F86A8415A4B45F88921A4994BA49A4B445C8B42D484CDBA6D52F0D004800001200400428000000000000000000140000000000CE -:80B08000002002280000008240017F2F028234128CF22B144C81D184124C92180050525E28841D5882124152899C44426042428991144B242089848211141638744C92424D411B121A2C52821221430C44C8A24482C04841AFDB43832208234112C9A8002014384889C142148052842E44844998111C024224180084428CC228200422266F -:80B1000004840040A41C428883084A0844838121012661848FD209297241226181275327518B21261C0C4945287618524137868193918478A44B414E915B43A048B0121448346819A4288C96281A644428C44A7328844434114E944F222464238938448841436482412C099CF21844FFC50B00242881848200100A812024012A141844240D -:80B18000180842C0242081410483010010861204211924029884888088048298120042246F4E0718000044000018000020041400000000840000001180020012000000800400000047828074170600004211A1112508A348480840460110C4114116140810028014C242430223813114A45912481102944121000080442244084282C4BF5D -:80B20000AF04000048340081241E888181004413041441131144440824100846020024111812814942981121501844008004008004C06860445F390E18000041841502000000240000001200000000486902183024241100004002000080440281402418D84B04112200212004805228001002840018804208424840081800000000002869 -:80B2800042121A28122808840044001008007F1A08001A0240080000001800120020230481840000490418208104A0210018184028A44842004888202102121A02229F290B0000004028012001104401400A002288008441002228000000804208842889010000204108002006CB9E4081020084480022800112448001241832628486187F -:80B30000284448084C0412208104A021208281048AC278C20080044183810289812284F22B8400A01210024088018502002111811008002820041004182822000000008C8261818901818A0484208801002081022FFA0B0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000015 -:80B380000000000000000000000000000000000000FFE40F8004000000400428000000002180018800004001400848000000004480020000001002183F5F0B0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000A8 -:80B4000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00006E -:80B48000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40FEE -:80B5000000000000000000000000000000000000000000008400002001000010084200F0D12E604100221290248904180011811210048111480080028041E618810400E041020011420044882800004A218841880940086E3F24284100100880120A8180150128830542260822800428A04260222200241084011082335822188001892825 -:80B5800041088820840200DF140C164404221230248C2402101841C811001038412A0428A0240018641CA92400001E244400118033484922212201838821212808422200F0DFCF302200008400241608001A04C0241E480081000080024A0230220010021840820412200800008C041281920081D09808408461412211411B410021124099 -:80B600008801211281820046618210840228002904418081824128628140282629A2410018480089084C51848141AF18022816424828018913C82C1AD428420211814C3121872449D6245594188460C4211C341219A4218B242E1284812223220800424C818421048890441C5848281E4C2A91588C26BC4401BFA606222031180084004662 -:80B68000022901141210622489A24815880183724802241828282A241448042282188480112424A2488004448884224A913848362888019EC2006C41488413E142F111484D281289022184814391211698444311069C0444414E21304118842B2121842829810280924818841A248122094819C144108C38184C7444D84844D4E54501428A -:80B7000083A112D08162812A018071248223041846081820C1421184221CF14812188924048394648430282367212A91448998882846382C28412A018341A2144A61881018C218129766202444044844405228260841891238141004840047281242B0A285028280422101288961448484102202224212C12200228D24C0342210021AF46A -:80B78000844FA012184012042A04284126480851001004493322840000400683212102211800004004000080C48448200820248802846E58A0251841244C1469842692286D288371281268941604CC44248121D1849811602266C122418183A4218B422A15222102D0820249E88822B22824A42181428624C122C924B184A3248C0840F8AF -:80B80000E2590090181A024CA21212002280110412008143922248C0480083C512C218004484282CE14192181247248400C02C00183048808B14082092182CF46DE680014C323149C12811441AA22100411142B01C9218818441212843048B42128302160884281E68208122A22162001B1431D0480C27448081041288188302003F1F0B85 -:80B88000242C1228044845181832420000182E182032144100841411000000200100901800444285C4584081216991260890844820014622F61BB4001810D2C1B2111411C8284127A1181884130221412440C8282280846182A024421842005E28480010881238420012A34608481008100C4141F0675900804208002004C08C6B8418A12E -:80B9000084402802290124154808112C840113044200301814000012C021400400824A2982210381008DC32018042001201164838036182021A11244896411328C02C4003048400820A12120850228004210018C018C024816280286584881806114AF17072E189012122143C14A402284022EC228B02114044400C048008004814818221A -:80B98000001A02A04112324840A842846218E084122892884AE14482C4248248F0528A0023433422422648249442244244210044811901C3524240011110C121111C11C118284840210184118D211041881681621486014858268401824120F25A4F80061851A9022449854188A11490118084240218005242801208220042000000814022 -:80BA00000810022210828408207428240600F06E2750848004111120421C042D8424282304003248841002CC35482A081618011A42410884428C048B414885118263D4704225A128608822008091882388F1A118C0328E226D188F32743AC4448794C7A5484AD222B2486B4814488B4447C1CD2449E39271380C265AD187848B42814E4802 -:80BA80007049E91191581A95283618A121818C13098558281782848FD16422921691288CB5C8A97543088B2343C891127FB30C2212F012145B348B1715D242A336AF21C518122F21F51A123F81E1A2A2221679282491162AA24490411E282E682E212D381A112181E28785A251833231221AB548A6446F95A4558B641B14BB648CE5842474 -:80BB000034282E2847424CF35C288885A4442B2225014B412F42E1639221941D294584741E7E242CF58242CB8611624F11B148A11256D86E04A5D818B34C4425D41111F8384148486E28228025A4148C31186E2857823419D11A7221E52AA211B7469B881EC8CAA841828F87EC42D584C188414AD4C702B0220161481C8144224122019E9B -:80BB80004824125C22410114128501000042208401222032411001842200122220022009C02480022098283F790F4F25F674141E221F13F355195F55F51913EF66F74C4C4E546B262F24F87ADC3F14B458F349551F57F528249FD6F5692B3F13E382F231191F9114D49155881F16041F14F419198F81F238288F827239A1661F97D299A212 -:80BC0000221F14B22152313F34D513F37D349FA5F76B7BB7168F81F1511126F8B8F8CF82FB6CDCCFCEEE8151888F89F96A68AF440C4F26F67476C7A29FB3F73D3DDF53F31D14EF47F37E5C6F47F77A7CAFA3FA52F41F35F453116E645E541F53F24175CFA7F21E14AB221F97F34959C9F4A1F98B229F92F829398D199F95F459598F82F382 -:80BC800068791D391F12A37789F2392187859B2697B437243F11F57D3D9FF5F5697BAB771AFD59112E288F8EFE2CA8CF84F9ECEC1E3A65FC1818AF83F3DC92F074626F43F73E2AFF91F257115F56F655596B76CF61D76CF77A3CAF84F95A783D13BF11D14CF1785CD7528F47B768A3333F92E287F3455D46F469E995F969691AF159411FF8 -:80BD000011F148798F87A6663E281F16A6418F83F338381F15F729689714B7B4BF95F37D351D66BFB6F65B719DD91D9926A8F78F86F3E8DC8F8EEF82D1C6F894D42AF781F2F054724F63F53C3E9FF7F15C3DDFD4F65919EF47F33E1C6F47F77A7AAFA3FB5ED89FB1F15B59DFD7F77C7C8FC1F27177FFF7F31E1C9F92E287F345458D459F64 -:80BD800093FC69419F9EF659599F15D411F178798F83B371F771717AA7519F12F239318F86B2697249734BFB7B79DFD7F361633F36B65AD799FD4991FEB87AFF3C38CF8AFBACE44FC3D3C6E825AD76AFA60F4110423822844D12844302400812701108118113D148028304830483048912210483A412C01140011C81048C44A14114160824 -:80BE00001A048A0484200100E0DB094B1A122A711104174120C1121E48229A76422241A1428921C1349032C02141812200285881182826282422018C22C24824B0280124684038484889B314A4A4412841464471CA072E521F41D22AF11124A3F41124AF34F11124AF24F11124AB941B29AF24B915F44A9243F34AB143F242914783AD91C3 -:80BE80004F82C4914FA2C4814FA264154FA2651D2FA264592E5A9E242E4A1F4DC2421F4952281F49326C1FC9324E1F49B26AF18124AB961B28AB9453B14A3924AB9443F242B4478229FB2448984FA2D4EF022E1A1F41D62AB11116CA24A7321F41724AF21124AF6638918F64F215688F2428D318BA24F442911F8194AA7F8394825FA285AF -:80BF0000F925CA4AF8255AD227A287592E539E25AC74D14CFA91648D421F4932649E28E7141F49326E1B28AF46E148F24A3143794A3124AB9422AF443BA429BB3684F1A65ACFCB0F000000000040040000000000000000004001000000000000000000000000F0456B800189418181815114182628B38804874484836188841D18280081E9 -:80BF800020025311889312588B522842424850422826C8186266180C13440A444528317848412A190CCA82F434773024B228459A48158822833214208205458122A341418C9114832AC1212006430228214112268C32262A61821240420852C198584A2189014149CA38462CA1831629F245CF9014522A51148904324C23923C4B218B86D3 -:80C000006A415C4189B288C1184391384D128483A12122AA044CA2122F21827171A412418934644A1126932812A984B64C11F414C116B82241741408833764CCF118C4A42AB198A4255F4E0422288184297111081118000048811228488501200A11001645082044082E48282128830240284208848024240912448228224C2188029F6615 -:80C080000A244400230218442110A82180144808845C22081242260855088042082228220011C1122268810012A0412150228002288648648142A41F13063624B21412CC148C7441BA69E11364A12800160B36C3C512421A24B6446213C027222B523899B4448195184626252664432826B11C14B454D224D585828406819A14282591640A -:80C1000098522B4144124AF2BC6F902425841254426085336414831182018D11211911143824808201283C62C218182847816083284268484C22024A11B44C92442D2CA02412252808482262AA8114548418F098B11418284911889348118F4231326082222044782832C1181CA41C484E246E118444112B4228998424054D423800135149 -:80C18000841E21262C268141810548E0244198121841C09A4A8121B428F4BE6AC02442455241C01B2880012227823885C318141221422260441223C4288951824D482842181E4920018B34623860814488804802492202422C4328248121428821F118F940E144018B12424048818231184981A2184128C3224521C188281461498431118F -:80C20000881A0870240122103844004412224142809E442A81C814212290684A129842481A669C80051D28402422A112800424844410086081422282490200204108460826044A02004042985860814160188004202C038180322483F81514C0214487427528E492911A8081C4282D18214D938901260E1324648A4B244711496442843741 -:80C280008149A592423058438202122228701C32182E58448845821C01C845028B42781E288944B84842C4A85EA9905412141A1204221B212212184C921884441782181A941832208802830488848130584302184AA2424418004488B04801228A86014A219382202483022B34486FDB0D00122004321004812A8121114818732418410146 -:80C30000004A020080024800482A818302920000444244484812418AA11600444781283622F2C5FF00C9024E28401488D228E1288265242C623818C0488651282602704A02485668148601911A28C4D11C984225810100004CC4414429018241144342C884412880280CEFCE0D0085124488810200000020A12100004898004C22711421C9 -:80C380008204114228812280026A182402008022012A0120220444C04242FE5700120090284C2481240148811A0259021100301211121812800622001C02424291481D28B021611422189C224C1104C200849260284618027F7B069222A415081048C82C8D84412284201112440890218005422C3844218062112282902120014982240115 -:80C40000423624051A0619614148A012281822258863127FD7068C06182C82162541842182220100C10041222B4100408224C24889042812C042608180A418124852192154221A021A8202824392444321E4814404F033A100604241840048808494821A04A08219819441218628241293138584014146882C8C6118A48400000028206817 -:80C4800014008E244004824820281802BFF30C32302420420822C0181200844130640080221324021CD21482420180038001484420422482C12200003048C0441A04432124041AF4B14240888104212A21C458683028449024892615CA4418424851332884012C38148D4420826812008C6412484896C168188470B4C1815C41A12888686F -:80C500009880386822282308DF2A011847898FE1E34214B814A2362E182AE22891244E32844D124285CB319D2D8511919243E127D132E424F448181AC2212811AE4142881F24B418E512E61182E212A15B47152A95441C644498121A61411CB8E4E48386AC831E188F2AB224E81813B2AC0F2828D08B92222E141E448D64ECA4278D482A23 -:80C58000A83496D988D242735E24941426628619914942145F697465F243D4475485A8111ED16AA2883D281218A0E1468132512E385E16CF3377D1C1314F1A14B4FC014E8443A6184D444F81D488E623A467ED2EA0432A312445E28654898528B55CD1C8A8172B418721E041B134FC21484B48172429C6612B468E852A032AC25547838F13 -:80C6000082A4664AAA2A9AC52166B2423169418748A82E5C2813B524B283D842B661041B984CE4419A148F49F344446AE24439C24A086F5E01800122482A012200B02228918248A81288848815089628048001809211802144012A113128199418488501458204408584A24900850428A0242F27064F41F114148D24AD4CDF74F65777EF78 -:80C68000C47264FC5C768F4AF212B2AFAAF9FAD82D88EF89FBD8EAAF8AD889F8D1DAAFBCF85A5A8F99F9B1AC25F82828477A7D178F917C49A1661B8A1B5BAAEE3FF712532B551F17F33838CF99FD984983F511195E192AF32FBB3F16374113E259F8D8DC7AF2D8D8C784CF8EEF4FDA88F43C7C1AA5ADCFB6034F41F15454CD36CF62F44D7F -:80C700004F7F77B522F36C3C4FE6F72CBC6F4AFB38388FC4D782F98E9A6FA6F62F299DC81FBDFDCA8B2F25F5F2F11FCAEFA4F52B294F7CFC7737FF91FD69696AB4F1EA1FACCEBEF3AF16B762F539713AF3B4B18F9FFD79617E187E298FE4F3E1E73F5EBA71B721F21491CFC4B434F65C788FC3F678E84BDDC5F87E345AA7DF8E9DA0333AAD -:80C78000F714262D2E9F34F6173F6F47F2743C4F67E74FF77ABC8F87F6587A8FA9F15C9ABFB6F6272557589F35FD422B3F1BBF12F1F9B58B368F86F62DCB7F31F5387957526E611F18EE1AAEAEEEE23FB7B753A7621F13B3B4FBDDF44E681F11F749311F22F3AFB83F5EEF13B711F391819F8DF974F4CFCFF9ECE84BFE8FCFFDA8C8EFCB23 -:80C80000AFCEEAFF6D1FA0313AF71C36CF66F2496B7FF3B352F37C1C4FE7F73CBCAFEDFFFAD8CFA5F4981ACFA5F9DFEF77525FDCF45DD52FB6F2FBF92B779F5BFF6862BF96F62DEB7F76F7BF695F56E414F6B1E1BAAEEE1F2EFA636B3B772AF23131CF8BFBBDD41F97A2579F16F26D7E7F7EFFA1E17E611B215F18F88DCC4F47AFF34F47B7 -:80C88000BF74FFFCFCCF4AFE7CF4AAAEBEAF2D042A010045024184800484400811448444A02480122114C224902800002A28840149014B124800A0482001001A8462894482890228F0BE3DB084819218CC726A6241A021E0C1021A12281128431141024E2119A4B490282084E144F221485222422C9121A0212280082AB1112466412382BF -:80C9000044015C014CA242B014048C84C341CBC7C0521F41F228121F4132681F41B66AD141F24A121D24AF26B911F24A9251AF143934AF143B24AF147B24D81AF9B4488F14F9244A1CF8244A16F1245A96E1A2E459C25ADE24ACF591242E421F49F228131FC97248F1916CEF14F1816CEF24D1C1B24AB981B64A9945AF44B934B44ABB249E -:80C98000B4427924D842F924484AFB244ABFFC04241F41F628121F4136281E64AB1215F44A121D248F62D941D2288BD2483924ADB143D212BB2594922B484E256D121CFA25CA125F222CF9214A4CD2A1EC5CC24A9E2C2E431F48C6421749421F4836468AF6461128AD951D64AB3449F442154B42A9BA24B44A69832D946F82E444F3845A1D -:80CA00007F190B0000000000400400000000100200000000140084002002000011000000000000C0270044384B128C41C933A012D081321812A0142A5C2848842823348480422882812282276142CCA8B48022210280A3821B21478218B042081348728428C9284028A1124149F2AD6F6042860240821102C42829E12812D8485141259919 -:80CA8000818117484C34852A44C8441B48A9A4241014A486482290242924029021172400584DE129A1128485B441A12444241AE64A84344C871346F83575106424B0140225E13102C1F0261189322A43C1438332814817884D621F4894A4846B2193E888222592241E64884C1668178582A6162830214E22282A91644B3443A1A126C88CFC -:80CB0000248B824B1885A216CE2424CB14225E24EF9E0A22442A0189618121A01228819218844CB181542884440048802494422800A025E04882C824000030118811893181258204114E1149042240A814228D1484FFB20B40D42201008901209198193448D048014A31258542482162144578481182021E2121005024C05240421408222B -:80CB80004800A028002C48C8A448008B84A084246FC246C2241280F2324215021F2224F1228630224014D22864822D4A4B42646694141A823222481E4841A9C42CA381324422488AA212260C3F4483D642E188922486DD22661483DC5818EC486181928E6C4A92244DE816C8242F2A0C6116446222722583218621F81882488124490166BB -:80CC0000581AC1211426C451C49C32428C048F13342284224228482A24618241278490164A0894B041C2C859586885F414885A984848882AACC126B241062224180010185122361432214241818934122E442946FC224418222682041A5224402E014164602928450253A3422889C224433862290884881A28022E8428665C848141EF1906 -:80CC8000021C012C028416119129846C52C1A38152624528144401284309847B842118809518008561848C028922748128415861281884C42A11240AA741828344469164849014843BED40384216658149D22202605100B042538124222301A99812B04403A9028CE1882402128CD414524288004AC122A02481163424203288CB61C098D3 -:80CD0000281622A1142A8101290644150120011C02002C011220220820C1481822642200902C004430482081391222604241890288008041816884210088C041004088E4CC083C81F111243D18C12F314271211823137232E22154784582654511212CE349B2444118342E80946416B84811D82CD148318822303449C2388B2415381436C6 -:80CD800014F824188CBA183AC8A9588298ABC14721124E34844AD28441E459090080220220911C44854588088122A1128DA24120021F8A0484898801202422BC224128028D830086342200C0114820C11400484A0200218CD41B0D502424201292122D12812784282308236484AF28042D12682911021002002C84215124502240022422F6 -:80CE0000482280A62180614A488941A481984227414A93141280085FD6030084812117818B24913081C0242302211D2483182C9141128C2258218400820000442250A444400C81402482828158221821B0222194828244102AF4A54C800440688283222122642222D01824044280322C8C2602100881009088A182228428442A8402814535 -:80CE80000823C14444202288188481088028188464484F3B41522114141C4211440110C841110022A0420082828821228800281002848424448890481AC2822C02822B81D82324080028A012242C022A2442F2FD76A02C100A183028182901244004C8888091128180A11824812100902480024100141088C22441410088581008222098E4 -:80CF00001838448021F495D400446021000028004410181808448001A121230980242201424C4431214058840081202284128602C11604822E988026248A0921CED4000010880148C044428004008894422812261182228809808281423824508400004420A828004A3122986021000060812100E30A450200482880A2422800440010288C -:80CF8000120421821008A98282342845486412501422C02881184440049AA442006088401404100418A2416FA84B4389C2422800484001412645C12841004028280A218240820C4042184499884008C82240622446522486024480C2840022822C24A22423048D646014675885420185B81867242F14E6283441D091A244C81F64BCA8186C -:80D00000E841A252BEA222A0218318A82420A11165986844518942F42A44883AE1487228F68262414F64E942AB518A0B4D884B882B988A84ACBC4D962F42A284EAA8448F144F93622C12117A536A1317A42E3126FA28254F227223734456A8265288A44F127362F289A8218A6128218812482AB8227384861442F82AA4274223588525D8B7 -:80D080008C44588266F4C2923AF654422B8226D28C7188C6143E228F21EB62A14123DDA4E841D72846F4B28E502550823E2A8B224D322216886184488A820487C48A8264E1CD585682D1988AF9A98A257AA20A4A56288782874257CAEB22944141288B2228C39224413E64233882CE242B449E821A211164421A62822AA61922184D825FD8 -:80D10000620A000040124132112C48C882C08240023482344001140020048221822182232238268220080030244840584210022184148440087F2E045F4656559FB2F219119F15371AAF84F43839AD41EF48F68F298F84EC5EB886F84A643BE62F1AFAB5B57F9DE911F9B3919D899F9BFBB8A92F9AEAAA9122688F8958A84FCEFE81828E6E -:80D18000AA86E62AEA2AFAE5A78AE288AEB94F22F28286AEA4CAF566246E722B268FA3516CE06BFB9ADA2CF788DAA5EC25FC68788BFA8B44AFE94CF345475FF6F62B2BAF81F548683F12F34B598F92F24A41FF5C768EFC6BE93F18BE867842FCC388AF18B8BCFBD6D88F9BFFB391AF89F9B8B88F9AEA9AEAAB99622EC2AFABF9AAAEF06CDF -:80D200006F4FEA7AA8FA2C2E2E221F7AFEA8288F82F2383EAFEA7A42F2E6B26F6EFDF6E22F4CE924F62AA2CD1A9EB22F6BFB3ADA2E52EE926F24FA4EEAAF86B4F8F95E56FF4748F222267D4595FB393BBF35F53B23B5F3183A3F23D266FC4367EE628F24DE2EF4CAC63F2EFEAAAB4FE37156F2F9BAAF99F9AAA89AF929BA3F28F828822B15 -:80D28000244E62AFA1F1828A6FC656BA6F6AD2EAFA262E2F22F2874729A83185F22E222F4CEC4DADFC4F46EE67BFA2F698386FC9E829F8B2B48F8FBB42F342427F6CF19E982B764E588CE5774AE374F42C66A5FA7B399F34F43A32AF27F7586ABFA7F26FEF2F64F4E363BFA47C4EFACACEBFAAFAAAAB57F36F67F2F9BAAF99F8B9B99AF9E3 -:80D30000A9AA3FA8F83A8A29E62AF6BABA2FE25246AFEEFEA226AFA2FA262E6F6A7A83D78AB838F3ACAE6F6AFA42446F6AF9E2F24F27B6B2ED2FF792B8ED984F43E96AFBFA982BBEAFAFFB76B26BB1AF8EECADFDC49E4FE10D00250126012AC148228C2422088A048C0416882281221908810090284908881004222002418443A2412A2807 -:80D3800029A2482009924C228122099228828FAE0247180084A9012110022B84501A10229822412B14269892126022004224C01250A48B2826A22826624840A88282250266C2242001450880084E824128489044BFAF012CF4112485F21124C7241F41724AF31124AF34D141F24A9319F24A9251AF243924AF74B924F4429347822D914FEE -:80D4000082C4914FA2C4814FA264154FA264192E4A96D5A2E449F2224A1F49F226421F49522E1F4932481F49324A1F48B26ED141F24A9219F64A9255F84A9643F24A9243F24294478229F924484CF9244A8FEA0B2E4A1F41F628421F4112FC116487141F41724EF181244E151F88F24A341B288B14418DB54B422F147924D81AF926481CF1 -:80D48000FB86581CF324CA5E214FA268112ECA5E259CEC41E292FC112C4BC21AD43CFC11248B941F41B24AF88124EB1619D26AD941E6249B218F6439244E924B424E9443B24239262D944F22758D0E84000000000000280000000000188008002044410400000000002002000000200825014F4103512D324181001C61211E211811848AD1 -:80D5000041028372A28C219482200426084902A0288444418830228092122C62822E843C0581C018814241122C4F8421A1C284C028A8BFE202484718831162218D112422902C2110A814811112C18434482A3848C04881E344412A13A1166481800228904100225B824981A882208918A881224141484B125C08C7AD504146532881701204 -:80D580006111382D314D1245416882588489B28E41C8422C48220E324668E848E088125A411F4116542A898222B62241E21482CA434085919C8328C214188B4286A41243B1444A2AD31438B25FE90A2CE441921480414802C0280098101281321481114230488420524811A012008200008012488481B22848042842828892290100424187 -:80D6000089023F4F0A80120481842140028044412814D1123821508444501820944610020040240218001150412C912149080020014026089088008AF46A7D903534847042C6116C0144472116D18241824169C1C4E979119451111800441038444C991620831474143147226189D24285F2C124128B2465C23160A18662148E5262148937 -:80D6800032944C93188B21227F51011524124A4298122901412D1412895421166814908427C253B14801181430444954284964492120818462214C81128422C124EE1423811242018100D24A120386C42C8C412874960A32114430449141210025230140D8C151921909454105840021009014201244544146012115D842141131214F8822 -:80D7000044B422011823D9120461828322A18120A3822FC208222A44140A0041680043224391142004430249412451C2824342A8128082611480448B24D541D218624282B02204450A88C28842257824280246A8412084F485C9109244A30200874216612124863814839A8484412608D048418829125282CA21034C21018333B125142C16 -:80D7800022542240081A02800725418414942418478800210024DF21094A11024116452415180628008100252491112260844842488448101B1808848C223211250418D01C41143C61B08801814100244AC1180060C1F0638FA04243D2C21266414489D2B4D12445628A20D148381C44C322816183C14D58188536C84E24841A721E618186 -:80D800001638288728C3722431717023668126184116942145FA188290884C84544289F1422818463812A0412CF46E21D022014048014B142002A0218918013042C0254118824A8204845A022002581A820425624190214196AC128C26A461308142824426C8244319084221A5045FA6084246044914084A1108182304C094433488141DD1 -:80D880008819C48824928E2840028C223422230C4C3218192928181198220092400CA82412442D1480048428412200FF8F07320020644220A252448001101281018C18810411848C1525418804221CC42400002E148524A124E0140380410142424A02522816A4845022F0267340024502181018842268418458C01849D1E21494126460F0 -:80D900004C48883448151C821134118210484484051B81884CC1448AE1488482040000182842848121812678860F0048186021801402812E82A0182221281820E81318A121248824281860284110C242112C6C489220348186C8442048242244411184089880419882415FE8018E1424244582528252161804248091446094183C44529462 -:80D9800042001C21628400201421C2281604172290238D421F4146841628420419A2411848414924921880432482F81AD9400200441100124F2481016512C1181008841880012364141B18884430124C12224102201288010000802221C8844422224341648110429422D77D10022041F82452902424302800104424684818424C01C4C0BB -:80DA0000844414842E542410C48600804134248035111111280014488084A1849024448148C1DF8804481441A03423446424424A0A60464246A21424524E824221418886180210124284C1920070221414122208851584A88188180082182684880822601A886FE34B421C840444108811042662CA002190428022A1281374131295242402 -:80DA8000881024011150C24115081C4C521428282238301244E0116211100210012821F0493D9016330869745C7E43324A4F8715F28414AD682B895823782E58814B552F249C118F48B58168418BA19FA8C4A53745C78283F4222456D626E122BB12731892842D841EE19EA86F16F214B44953418D31CCAA298A41120145246748BAF28C01 -:80DB000068124E2E8147B28D249F464FE226C442C0122AB32C0189F264442F21EA630127461F64285528BD888E1816F855885A96D417321A38498E4A3C11A41548157485648ACC41F5C4222D14C18FC1F8C2412E44CF97E5463C814CB812C4314AF845D41B944C36544A84D1D892142AC2E188AF2501165444456641481E644F8145A631F9 -:80DB80004A048FA232144B516CF5D655267215F5CAE225B32671C3F1845865F1A64245912327A14D426B983E2146516C6F1418722151243F72C112115E818A3A154B52222EA413A35116E31114B42297941AB824215B8682678A1FEB074A02008A044880D4240888482C88C4812A44A542142242A22022240222C221008230813081B08179 -:80DC0000048E48002008488004482048810448F0AB44C0263F7452622F61F41E2C7F13761A546C2B124F4ABF9CA1988E841F78BD8AF93EF7BF93F325241F8BF9A46F26F1A5451D311F3E762EF66E4E2D22CFC2B2B4E92FFD17B59EB22F437B18D256F8A6A53F15FA89A6AFB9EF5FBF21FAECEDDFDBFB9DBD8FE8923238CEC625F242514FD3 -:80DC800022B166F5B4144F42712CA842CFC6F66444CF8EF69848F044267D6D2465F4AC2CFFD7D64A7414F632726F4BFF98948E98C85F59FD38F27F61FD1E5D6F72F2B399DFC4FE45647F56F7ED5C9FA5DE7BF6EDFE6F63F11E3E4F6DB2F2FEB1911F2BFB36B49FE1F18B8D7F4AFAB5EC8E83FFF9F3F3F45F5BFFCDFCDFDDF399AD8FE8F25B -:80DD000086141AE12FFF96C66F44D764F746544F4EF1B818CFC3F22868EFC67428F8BE3CDE172427223F524432123AF63177CF61F12E362F42F1F4F6AFC1A199A81F7CDC6AF9DFD66FF17924F594FC7FE1F7D7347F54FC351D8FA4F7CE26FFF47C27DECEB294F7E1C73F51FBA4B5BEBE8F6159E27F6ADA23E67AFAAA3A3BCC1B37CED59FB7 -:80DD8000DBFF9595BEA62F41A122CA2EA45566B276F594D44FC37324784CFCAEECC7C2CF88FB5572E026742F55646741CFC6F67F7FEFE4F4363E2F27F7F6F6AF89E189FB42427F7CFC7E5E6FFCFD76FE7F62F8C7FE6FF4F466D55F57F55DFD8FA4F56AC6FFF7FC1F3FEFE1F176567F7EFEB7972F3AFBB6BE8FE1D9F2F8A2A7EF63FAB7A680 -:80DE0000EFF3F3F6F55F57FFC1D45F5FE74BEA6BFAB2B43AF3D1F1DEC44F47E526F676544F4DFDB8B8DFC27248F8ACEC8FA6F6ACBCFF250729010018842A4108122642081A44E28104160892301110111803219012A01290143026A012B022014B1212148422402149052812002880028F130A244465024582448294121E4421C01241208E -:80DE8000582849D422C8484282D084A484844028140463022D8A4426421446084C04CC049E2400184829B814048A9438C0148028F87556E022F4112485F2112483F41164A3D441F64E121D64AB9419F64A9259B44AB925F44AB15B422F54FB25482F14FBA4481CFB244A4EA14FA2E415F2245ADE212E4ADE252D4ADE24ACF4D1243CFC91A4 -:80DF0000248D831F49F248811F49F64A811FC8B64AF98164AF249961AB9459B44AB9A4B44AB9A4B442F9A4482B944F82A4944FAAD4350926EA41D638F4112483E641744ED141B62A91418D9419D64A9B658D915B42AF44BB2194B25F82E4447BA6E854F3265A4EB14FA2E854FA241ADE251F82E45D42EB5D42EAC5C28B1E648DC31E248F24 -:80DF800014E841D612D8C1F64A921FC8F648961F48F648B25B68AF24B9A49418AAF442944F8AB44AE18AF44A944FAAF56D1A4028081400000000800200000000800100000014000000000000402484020000220014F08173802413181229F34C226081421648029042244641028934843014106122144CE14861210030428E112308354201 -:80E00000B442820A482002818921981842C3E88411A82828488644F8DE3FD0426128444D9241D012D12401C52288815442478141854294141E244A514826410E2073428212F624122A7132C41426B445B222280285C6156822521288222C98194C981CC021CA42C8844116C1242F250B43210E4959182E121D7869618143949C162256423A -:80E0800044448110326C4F211494148502AA31121E424B82165442222B212751CD116E83CE22222127441E84286812324181328D9143795488F848112E88A66828449631149F260E2924512E1006411042180200AB14704213C4141288841C1244011C122611A221294184A4286140417428922142200488288D821008852422044C8244A1 -:80E1000064823FC70D2200284110C26C27221A0400001280C4A241442004422682024E242A84F2244812187024020000904122408212420848444825A448308428825FEA0841181E24A5D218C11C5606844581A212149662244B8441641364241304111059821374221A59823721B08692242614032D242C2A8232141252C68C2D29552440 -:80E180004328D8283A182A0528904C26F8AB27400426145A5A44584B248446242241819142183044299444230442904822682632482722122684E14122824242240210A4144249A4418A3142812148CC22E44204806884A23FCC0122181228181658422578229211200282244B4841E012184205144051A214A126354826C34A4B28405639 -:80E2000061808238222812142A918886228211C484828827A1184A2812942481BD2924222C44810215A8421214A0826110471418182288619810344A2F8952421200F08222854524518446A124CC12CE24B04402400211244849612143A1144034124C06222FFB0448690484A33426441421444A81D442830819E24214044149220421B02E -:80E280008901181C04441C22822292184E148062848C86114188248883044028048A345830125624F96485002218290110518256A814111E2842818C7412028991188C82C1AC121C42048322128611A81418821E4224204102448247812A911832841A3818208A3824006800847E8DE022942416F1221246382E5C54A38981611F252255BA -:80E30000C2481D186F8214BC1868821F8AD18492148D2343525289013112A5922828821A26B1143218A146986C5E2459C13818237938A1581698141A98422E4482442B21433544A6D89D082110420811221246C144E081061358682224123014448A0448894888A21246048E244965412A41D4320443C22463028884C0482240820426C89E -:80E380009412421E48422218F02EE42460412146A221444A524821428422C04284207228343226023024C0224C8804237142924426C22C44442D448C01224800C04812002011222128618230442A04841F810815240410284424A1412B181B81C09812B02411028554858E42163898151844186888821628EA812418222A3282874182A56C -:80E40000A448A14084024820082149228211820245083FF24B211402122D42361A982A7022E3244281044218C9164802382245A2242522143224001214124D3825024D2860444004262481812D2298141845820250688C1CE481C824A7381001AD4244004C22C128121110223D8481186044009A2402410048800A123041848840468888CB -:80E4800042014187481400A04829E24411E4449822184084F1B5486028C01A8418C01800481200C042418C8182014C1404430210B42424014384542860446844004220022844214A0120A885920043A121812845F8924714400180944430441826058041848102232512044AA21400002988624224444881006229062210A441818001805C -:80E500004C41028634282C0210025B4F001241302C1842404402268848C88842481420C98814002518A1841181902181298104100228258424081842488A12111484022840082B38004F8E0900181C41561824200228182D4410944241210049018004502410022480240220414224C2144442284A8A88D8822C84948480C8840049888A93 -:80E58000F1FFDD00C044412032124A924640584A848B282181214614229222822F28041845820840064C48B51198228490E21440A82436CC41814084814284040012803412286FFA0A426B488D1C2B414724550A4D184FA6B68191128F3282B1CCF18C824F22F424222FC47428B428A2738B14CE22A144CF549844CD4416382A4D24E5B504 -:80E6000042B51502242B126F8268424F8C624686BC24C2411AB34324B4C1B11489B824DC42A3214B631AF2E2324D884FC8D2A8F13ED414357111024D162F4272487438722AF212142F31F4212116D842C8884C754AB858F4283149D145F8C4882B228BD32CD22202E01E3A224D2423E48164E28FF4FC262A6B4C4B24281B2422121962C5A6 -:80E680004F43B18C2CA15A814666612F28B2943CA485526A1E44EAA1114CF2FACF5024186721918F81B532F7467C5E64E046F2984A218F8DE4217442E841D3C251242B612D1225F494C145B465548425724A562298CE122ED36E92CB812B124CAC228FE1C816ED822D444DCA4386F5482866AC98A829A8485B4C5E14224CE8C8F8241884E6 -:80E700004CB6283834DF2804000040020049082C08002C022484148446454841484168142568182528981282200882A11B48811110011B483081002008820020084FBD4651475F75F11E1EFFD1F51A38DFD1B236F21E14CF81F11D9B7F1AABBA29F18494CF8DFD3818EF43D3D9526EF5B293F998DC9F19F91F263B22C55E5D9F12F22737AC -:80E780008FAAF8C9C9EE663AFB1C8EEF4EEE24F4C21AEDAE4F48FE252D5FD3B3C8CE2945F531372B951F32F25BD94B111F31F136166F417934F4148623F25E18CFC7F73CBCAFA2D22D4651575F71751CFE1F1FEFC5F16D3F6FC2F22434CF87F77FF8FFD9FB82B8AF46F79494CF4DEF61F3465C8FE4547FFF6BFBBBF8BFDBFFB9B5DF21F33C -:80E800002D2A9FF8D939B46AF6AEBE87E2FFDDEE3FF674F64F64FC848EEEE22F2AD7AEF88C8E5F9EFEF5BD975447D2141F31F857D52E22AFCEFA81918AFB36B62F41F934248FA9FA3A3AEFA5F176348FCBF9382A2B47141F71F113576F61711FFF1A1EBFD1F112346F61B356F39735BFF9E122B292FB8496EFADF51A1CEFE7F23B3D6FE323 -:80E88000F196B18FC9F9F7D54F89FD247785DA75D8C6F46464CFE37337F3E412AFF4FF12389E7E4FE4E66CFC32722729BF9AAAEC8B35DF5EEE82F315341E3E3F5FEB26FA5AF84B111F31F932122BB84B934FA3792AFA5A28AF86FE38B88F22F3EF51141F71F111171E167F71F17E3EFF72F342266F61F356547F5FF79B1FAFA2B2D6FB94F4 -:80E9000096EFEFFD7A3EEFE4F46A6E3FF3F3B6972F4FFF6CDC5FD9F9247345F21C8E7D4F7F54F43436BFFBF8F676EFE5FF5E7EEFEFF7E4E64E642F21F3BA2A3F32B262F6F9B187444FC3F17D3C9FFAFBF2F4EEE2FF9CFA9591FE922F2ABB82BBB4F9B89AAFA3F25A682BEE8F8AFA283ABFFC0969012901418CB424412802221648E2880432 -:80E980001244846C0244924A0228200444A02422200243022A0122482248229628A248A041249220D9480285248802DFC20886016041214C724262414E1213412201478181482F240218C0B44800442542642290145269052D58442D42442C41044C024449810480118498442850284128488D1445E1FA0C2CF4112485F2112C87241F41CF -:80EA0000324A1D24AB141FC8F24A921B68AF1419F54A9243F24AB343F24A914F82F44A914F82D418F9244A8F14F8244A87154FA274D8F122CA87592DCA9E242DDA1F49C2C21F49D228F8912CAF24F8916CAB841FC8B24AF18124AB941B68AF2419B54A39B4AB944B4A2B944F8B94924F8A84F9A44A7FCC0FACE441C6431E2C87341E2487EA -:80EA8000141D242B141D28AD16688F549325AF2419F448B343F248914B42AF1439268D956F22F548914F227C58B1247858B1227418D512C4242D5B1FC1C24A1F4186E4C152221E6C4AE1C8F24A128E248D968E648F24D384B24839B4AB844B4A2B144F8B94826F8A94124FAAF51ADA40081800000000440000002200001400880000400139 -:80EB00004008000000004004280000000081F084DA403211144C4111C27322445602A11C91924889128202214C82022440544A4244295142472422984840828181514219628224222C1428714428F12488884508004608F0331A146714A2AC022AE442115E14871425A4412242C14D18133518C3C1441335525311384485822632141242DB -:80EB80002C0124839212644D11702612B418C2524D1216188828821CD22444C2442224C9A718436299F04F3424423B249121190433372347A446F61442281F22B48491188B2427812248486727446041212D66458879142285714502A98A15F4421923E16142963C1A64828C113284A3A21AC3C4548C9A4285042E4C8E1287428A61215D0E -:80EC000024501412221664221E24C14414124088416844130147816413011313881408284904244421282C014044021860321614C2284260244012C484222412801408EFBF064D114429014088110184181062810029030060824284408A420A8444244C02000040012011240160148200400884288444F048F740028816D12254241485A8 -:80EC8000321445022215882401845624A1411242C024230487244446A22483242211D442C414284C93864332141722E082E4489281188C3914DD124344E849A4822A5484131C48F45BB750618068314825381215C2144421109A1800844E14008022441442C22264304241221224444381C21282114111184C4614011B8188191144C8444E -:80ED0000822226048544F4D8282041941200441484102821128184012B1280A114184608262844C84884488C628424491284049024444C22612240A892881883C414458A049628C24884178C007F8B02859654858412082E1418212524B224289249488A01181048384A8442260C4160821284421E448B24412084912448441E444302E024 -:80ED8000481128D18601441E48B0824408231404BFAC45B228C442901A2210688816082D18A48743188423A242421044152215084D992100831441512A822E1385E424423218818110188142040018AA4134442052122184845F2B48212102901245028644810140512200C47014888301205822608258214469342800A02400602100E059 -:80EE00008104484A02118184881281421144181049E146F11422C1A7231A12D48471146A81298171A80216CA482AC9440045D84911288158C23598265829B218D41234284721839A254384622149522885241144081281183D1C8CA182D86C21E88412125484F0D4F9502200100823021444A3028D1319440289A2418D14328034488C84A5 -:80EE8000121408814185C44283842431221062814A0143C4284E11284A88060047818584344800481884CB1B400400421E284130182001008146043448800441480018481846945681382A9458903880054A0320012A044841E042C8248022218202286FB3083A448C822401223684421488218481C11141901C87122AD11815480150181A -:80EF0000140026828414081914814234414048140811288484818100004E821832F0E2FF00401882014082042324042400210000152441082C028100000000482420022180040012003068442384088882F071F5408884961C84C1A304282022321A4442141A020010024B2141C4C034608228002C414442C454280046841342C4940020CB -:80EF800004298882B82C21131812FC175660241048C128484800148C0489014249042119044C0400002A14018034220068008042212424384882482810C4148288A018203814A2F0A12460C14100481116140400009112301843C1142021840400800441444220024A022820042A2102908242214048981C82200600385F470400444362DD -:80F0000048430128448041084C9124504111845D188147821D2619C228261424D24826048183C4484001142001810081141044882484346866184898288C14E84E018286018480041444001400002400100142102121020000C424112C9221414160424141400130182441430200141840015B2D40084984912428120041C04C80420400E3 -:80F080002902002B2180031D84441F44C212A0121C524164CC4186142102228041084E14800248C0488143182E781A42F23E9C50448A3428718CF835484C25F3244815C4281386D441C1184C545845D112C4394F9417E234E454312426A4628B444658286A34224E4C2CA2441D12701504724E444D648A81011B44205148E1A6CC184C0827 -:80F100009BA8CAB128E8193328AFDB082A75811CC43C49C33647861D265024895128857814C24447144B1121C304E044F42C2481104CD554E212C224E08425A24115A4441F4282F22664196222224D268CD48DE84928421844C4C2C74885BAE87C6438288E188D4127C1EF81085612C42C8B418F47344812411E24A0451E481A11387417C7 -:80F180002126D221E1C1132D713DA9111B229C82931F13D344B544D566932889736CD986F326216D592392111C8473582832587022A165E945E884B54CA2E66AC6381E142FC1BA16E282C822EFF602280022480018A012482200001302112811281144150884121528452801121412204121010040010080044800A048A048F09E7E145E5B -:80F20000623F9452441D45474E57515AF625351E141F11A1269F1282F115155E544B26CF827326F746648F82F265664B448B616FC2762DFC2D2D4FC5F578F88F83F11C4E6D568D18CFC5F124266F66F546776B3575F534545AD544F41414CFC808346B8856F21A14C5F21E18AABAD8038F85F54D56EDDECFC6E486FD5A4A6F9345F15466AC -:80F280007D65C7C25D15CF867355AD655F52A3135F53F164649F12D2C8D355D14453418D1A2F63F1567CCFC3F37474BF84F41C444FC3F724245F1AFA646C9F96FE34344F65D466F52B39CFC7F7747FEFE4F746767F11F7171547421F16F6747445F49CBC8548FA424416F23A3885B25AB768E285E78AFA7878CFE4F486CCEFC6F6B8A88FEC -:80F30000A2F13E49146E423F12F42C2CDFD2F26C4CDFD3A1665F57E642F325258FC57151A131DFD1F144544F55F41D1F67727F55F768495F57F56E799F17E596F721215F52FA2D255F96E613D664D7EEF21221CFC2F23C3E3FC2F457477F72F617115F12B241F664648FC3F3E8EC8B119F3CFCC3E47E32AB31C5B652B5C4B8DCA9AE8F87C7 -:80F38000F548EEEFC5FB2ECC8D988FA8F9FC2B144F667423D54CF23D35CFCEF7757D7AF77165385D258FC7F77969CF81F11D1D4F427111F5393B37727F55F76D4D5F57F16D7DDF53F7257DDFD2F22585DF56F4F579CFD7F66476EFA6F21221CFC3F32D2E3FD4F677677F73535717121B754F475788CFCDFF18181FB4F443613E32AB31C5B5 -:80F40000F67E5CCF86F258788F8EFE78788FF9FBFEBCCFCAFFF8F88FA858AB800140884128024120420884804404008D246044400442002004202214062302002216080012004088628828124C0228F03C5C00002084828104202401A014C011112B14844E11C01111202214042E424422C0484CE2121401446220C44483A44846811218EF -:80F4800024348442A08480288128F89C35D022F4112485F21124A7241F41764AF2112CAF24F1116CAF269961AF249945AF247924F84A9143F2429147822DB14F82D418F9244A8D854FA27418F1265A871D2E5A8759ACE549C25A1F49C2521F49D228F19124AF24F19124AF24F18124EB141F41B24A9921AB9459F44A924B42AF24B924F4E2 -:80F500004294478A29F9A448984FA2F4871D7026F91164EF1224714EB3117644E3C17662F3114CAF72D841F44AB3688F747924B8427B24D842DB8494B26D48A9CB528DB4C88DA46D528B2C2E1287584D538E24BCE5C8C25A1F4896588E24EF34B181F248121D64CD921AF64A961D248F24BB15F648924B43AD924B43AF6438A48B146B4A2D -:80F58000AF44F1A4521F18018A240800000000000000000000800188000040011884000000000000280000000014F0E34C002220814121341448AB411440111C98821211221884130415121401372214C28503E04443C4214014449A2860424894CE19123911081812C08216088061424772E012B486511284E71285541421260121233150 -:80F600008223645184281246084E2410848442048B144C9214254424041A6441274238224A81742422D46881483248248864C9F288268161282246C42546F8A1ADC042D60481AD14809414502A51213B82CCD4A58188C1112812458A14C441218E15F0124135245D1C15044CA1145D224E281A92248314C2244E24C494D97918E21201605D -:80F6800083CB8270822461224364131AB61B0F26815212122651C1450366A14120410240880283044A1201C02400268852241022A4424418444180C16824E0242168244824864816C412842426084054847301002D1150124042180A2440031800400140084800D02324010000000028C50200201148081124C082C014008048F85491C024 -:80F700004212812D1140914143614121501881441001263442490143044048098111241223C6142081220245812682B426F81242248223C212004F81C248448E48288481122CF6F4CD806421191113413141A11221405181001120121204488004403241211022C614002800224C122224288591822782120027818C18B284048181888DAB -:80F7800042D50B248C442811029014E14042C826411800411C84415284008C51814068118051120089014A021594482870220621450824130226841464812210222172ED0A2820425182221280031142D094115812122C2292182034214CC2420000622508298412148401101282420385044E119088814321C2428218404848FA94ED24F2 -:80F8000049411441042501121185122802001241891109A9041830288419048301100216880200A302811004000018502281848420014901DF5208110084108814481822611131211018484114441414180828644400414A22012D420060410048781321044048A44120014884498801E0E145231194215508A7121A3418AC0183B1411297 -:80F88000521E81A711818D125D28814D4860838CC22289924444844E2290621289B3444204244783408874646111C1204458488C2531188182E041C81812F0124970240100A1006012842521412101C0141302431192441441830414211250482442241022015022202211820413019224412982344A16085048845FC10510110414001247 -:80F90000008502000018008418110000008100210000104A04204208009012100200000081229FE30B11001721106111100111C011259119210084440048100460C14181C024000012142443135612272130922100210084109C124412007787100140022081015029C0112111211800841021044400814048C22500001214242A5142507C -:80F980008221291802702202000023111442084F8C0F85B849E444E4144141410111504445B424E212B2280100844116522225A2111A210943518400154111518885F848424E4843440427121820514445B436A2220084504840921225A2139FEF0E00240000000000814002000000000000000000000070120414A124008485020000006B -:80FA000000F0AB6A10C848424800000054514C22820200005022901216949482880000111484818C24841402182210411644848202812001400229F196512484804411420410084044C821110020010021800188104408111C424242888144014011021041458202008420021002BF9603904200001001114480028400810010024901883D -:80FA800000004001C028242A44024002004004280000000021C014DFD7032001001001110040010000000010044411440000000060230018002400000000000000B02B04A18B4420041400004554444B2226712801400C40522225A2111A2129280800112811851AB84824A51410020050444534244822128141002440A2114FB60F5088B6 -:80FB00004C8414021100100155B44882020000002421111A818818021240D111021285984448002C014002D0C4828202100800212512F2C66A801102000014400110080081000040044922420800004022021200282400001481001C042100200841446FFC0300100200000091240018000000000000410028240024001002801212434291 -:80FB8000028542080020020070C906230144140040011100157848589924818100000000004420012228234282C11427212C42427122512200101A384140588812800840F417AE00124002411511414801911435010045280100414554544059241008282C0224233122260230140040513214401A02A141800200418F614E42124212129D -:80FC000012014001154111088001000000207224041004004082021212142129F112122C42582311A1A442811800200210048FCE0C6F22F212222E122B111221C0132592822F31F111119B98D659888F18F44848421F945411488558884F84F448444F42B444F22424222E2480524445E642F226222F21E222B112A1812B99C0932592828D -:80FC80001E111F11B189E999F848888B488F8424E48404488558884F84F4F1CFF0262265A2121A212101502229C8131F3191C19E8887818D414A2444511148155988688F44544C4B242A220280425444286F22D226A2123AA1812328082592823CF1131119EC897818B888A444420048848588F6C5B400000000004842282200000080228D -:80FD000002000000000000000000000000000000000000EF6E09000000008024842202002222220000000000000042422084A4444A2404004242000000000000E0F70400002002004842282A82220200220020020000480048208424240400004A0442000000000000006F220B0000282200802484022800000022222200000042004A0462 -:80FD800080044200A0440000000000000000F09854000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000002097 -:80FE0000024842000022000000000000484A840400000000808424848404000000000000AF910F0000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E0900000000802484220200000028220000000000000000B9 -:80FE800000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248467 -:80FF000022020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE960000000000484228220000008022020000000000000000000000000006 -:80FF80000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000801C -:020000040001F9 -:800000002202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F04F -:80008000EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F9309000000008024842202000000282200000000E7 -:800100000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000C -:800180000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE9600000000004842282200000080020000000000000000424242F1 -:800200000000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE9600000000004842282200BD -:800280000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000003D -:800300000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E0900000000802484220200000028220074 -:800380000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E098A -:800400000000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000D9 -:80048000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE9600000000004823 -:80050000422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F930900000000802484220200000028220000000000000000000000002E -:80058000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE960000000022802484022220020000000000000000200442484848002004000000000000005F2901000000008024842202D8 -:800600000000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE9600000000004842282200000080020000000000000000424242000000000000B8 -:800680000000005F93090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE960000002002802404000000002002000021 -:800700008084840400420000004A840400420000000000001F65080000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822000000800200000000000000004242420000000000000000005F9309000028220080240422282200002222200200000000A04420240400004A044200006A -:8007800000000000006FEA030000282200802484022800000020220200002004A04400482004004A040000000000000000BE44000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000000048422822003D -:8008000000222082020000000000000000424242000042000000000000F0533E000000A022004842800228000000222200000000808424044A0400A04448484800000000000000BE7F000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002800000000000000002024E6 -:8008800024040000000000000000F0359900008022020048422082220200222220220200000000A04420240400004A0442000000000000009F41030000282200802484022800000020220200002004A04400482004004A040000000000000000BE44000000000048422822000000802202000000000000000000000000000000000000EFEC -:800900006E090000000080248422020000002822000000000000000000000000000000000000F0EE9600000000002A248602002002002820020000202424040020040000200400000000000000CF420B000080820280240422808202000022220000000000480048000042480000000000000000DF1A01000000008024242202220000802C -:800980000222000080A4444820042004000000424200000000000000AFCF010000200200484228802202000000000000000080A44400000080240400000000000000DF4A020000282200802406A02222000080220200000000004A04420000802484842404000000000000ADB800008022020048420020022222222222222200000042421E -:800A0000424A0400200400424848424A24040000000000F0784A000000000048422822000000802202000000000000000000000000000000000000EF6E0900002880828282A6242A820220020000200200002004484280A44448484848002024A444000000000000F0594600000020220248420022A022220000280000000000A0444A8423 -:800A8000A4440000484A2484A44442000000000000BF6C02000080A2220048420080020000000000002024044A8404480000208424842424040000000000F05B8A000000000048422822000000800200000000000000004242420000000000000000005F93090000000080A424A022280000008022020000480048004800000080240400F1 -:800B0000000000000000FFF70C00002822008024842282220200280000000000008024848424040080248404000000000000008FAE0200000000802424022A020000000000000000208404808424044A04008024040000000000F0AEC2000000000048422822000000802202000000000000000000000000000000000000EF6E09000000D4 -:800B80008084044228220000008022020000000000000000000000000000000000005FA70A0000000000422822002200000022000000420042004280848404004220040000000000003E98000000000048422800000000222822000000000020044242002084044800000000000000CF2F08000000008024842202000000282200000000FD -:800C00000000000000000000000000000000F0EE96000000000048422800000000282222000000424242000000420042004220040000000000F0D521000080220200484220022200008022220200000000A0442024040000422004000000000000F091F90000802202004842288002000020220200000042004A0480044200A04400004270 -:800C80000000000000006B8E000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE96000000004848A0442822000000802202000000000000000000000000000000000000FFCA0600000000802484220200000096 -:800D0000280000000000000000202424040000000000000000F03599000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248402000000802222020000202424040000200420042004420000000000005F1D020000282200802404222002000028220000000000A04420240400004220AD -:800D80000442000000000000FFDE02000028228004A044288002000020022200000042004A0480044200A0440000000000000000F09DF4000000000048422822000000802202000000000000000000000000000000000000EF6E090000000080248422020000002822000000000000000000000000000000000000F0EE9600000000004843 -:800E0000422822000000802202000000000000000000000000000000000000EF6E0900000080042262280000000028220000002024240400000000420000000000000000F0C1530000000080044A8422020000002822000000000000000000000000000000000000F03447000000000048422822000000802202000000000000000000000D -:800E80000000000000000000EF6E09000000008024042A02000000282200000048000000800400000000000000000000F03547000000000048422822000000800200000000000000004242420000000000000000005F930900000020024842280000220080020000000000200442000000420000000000000000FF9A0E000000A022A044B2 -:800F000028280000000028220000004800004220A444000020044242000000000000B02C04000080220280248402802202008002000000000048424800000048208404000000000000C0220000008002802404000000002A022200000042004A24044880240400208404420000000000006F4F044001482D5900849044610000112CE24135 -:800F80006241304812200110835143A1990181850225C12184808124628148484712804144C22424448761288902009F860A118C51839144C9D468E444D142341214D05811D441D24A5242153A282F25E22211C81243147232C1121483C1153019411C5281401AD118944DC48D546F22D4249224122297428143467822F41862282C612157 -:80100000122C7154F21D4A40811148E28164448440224104851144412142638221812D18D042042001418001C4223125912184111A044E3428295242110060446144504818250800BF3F051011924841002721441003181014082648A4142A04006033301111C480018501400281002418412023D218110885024628220212D024643D00D6 -:801080008414003044898494440044002952248001001212100224204111014008811140598450484862410000282449022122211682F17663000014118110040000804206160422290100215021C01A1181810000004844488442000026442402281823011200304900001400000000000000280000000000000000100400000000000027 -:8011000000000000F0F6F200400900D05242519484848B148185142C05126902440000241D181018022CC412200444812502002816688848004004416648028450844FE5084D42205212843D241605842A9151501250122114672294850220014115120113021A422813C411866412701201265184343024466112D02441E828022812CC2B -:80118000229124A2288773101462A240C225416511C93D8F140129445248411B144C7212792204440044002D18109832846662411691C41424160B2651481428366C846601109A2490248C819212C92282F23F498004141181C011280040D81841484348024018021800154211C12100204102801204240010021C0830142018024A52840E -:80120000008845F88E410040012552412184216012121C013014400816480100400821444522054441282111414082020000A01412250225026400128902CF760B11121818458951411A92248905508250A58CD48222D12C0281528B434042D24111044226781804184381C23218A5521485C4148B428CBA1202883082491168CA844618EC -:8012800018049E4487444F9D03141811505225122532244E1814183110816482188C124808360810C8154014648444444432213410522683321448100220D4223814212D8C21422141D04862448B5700202111D84101161802289018107C1E0284412311A1144840022512042CA4128C0118442838494148410489B2888203881812108800 -:801300004258848120A1C1816F4F02512B2415361448402882812212AC21128120123118418148521421841688B248224242019022B3922400122D242C41011884848331221608C41882008909125FD20D200484810000C4114B422800114A2141145834C122001D144348421198121CA121290181482021C241842850281923042644D651 -:8013800028A118402801618412AFE1470244205242A505100118000025028722002051489024904185044883028100001110180800414022C8918002414C01926044848D555025494254A44954522002411B218B42124052214AC2392781C484414914815218C37424382189342220321222114420E181D21442982290141352281612C574 -:8014000014AB12CC48A41820215148811FD9092140A321818481C0118C0200128180014440E5819438244441164132482283911283410223824201248C84110184A9819488928190121285248178842804DFC80F412C0224998212B2124481098865B2183842005C28C144408118C484548114288410094022493218901420496841818BBA -:8014800012001688424802890158C048F0337F14172214C041448591488551481C82521881548A121141229423222032110090140081320088400810C8148CC282400285826838118E1640022F28011AB81448F4E5137024011121284C8442865424872A28886081828B81C0848975820840482C68428C013084406811101212425424AC17 -:80150000281A1444041028418808C1440000846F550D8444584A8204800600448002C7222222006C214222022302222043180250861444100240111808148091262A013800874830442842FFD30510141216184812CC428D82818D9184A30812242E14882712401464528844C08481884100888019088C029E228082C82829C1281200187C -:801580008A4101184A412844F1D987241038242400C9013041402488322400C02881803112000040442462415022004436042244446C2842242614024311044100C1446144BF99088480041624822441240120B2146288137481440343884A91A2001188114098818249186448008490128001000019E85842111824481888886981F09CE8 -:801600001614200228603400812518041814586245588285043028102812088342A41200D058018420028425182461811284128460485084124B18418004481F840B8C51824880140426024942C2242128256468188025D8E28111028C819284218CD84284C28C94218184215C14DE120281C02100448002101288026C022918F8DF1314E8 -:801680005D11E7121E246E252B419F56744AFC3C1763F45C2D2F8A722B417C1AE983B2A47828FE21242E4CCFB8F48C8259A3321CD248D251025B2341BA66428F9A78883496A410922445D226D282B8187118DE1262211D2887A51B188E163E28AC5162160ACD1EC49AC4114D4C2FAE0A4CC22A10D2C4D284022D2885ED2848E288FB281250 -:801700005D862DD41F444361984F24B823D3423222004B882A5844869128A9D12C92145041A32818ECA351C21E1DC3F925884147CBC11A012391821D11C3B1148858EC124F24AE148F8F24E4EF4362224435C2428716241E624AC4423B12C1242B888A31CC8D437B996D12AB194E843E1816F98482DFC2415A8483D2CA61C845EC986841EF -:80178000A4BCD144F81392E4A5952883C2362F48A2A889C12CA386D2887815D944E848B828514C1AAB881AD1C4D84458285F6D0E1220011241800118800100608120412141011424142416416211241A0212301188132112612211221321329122122009A22003A220027F2A4691344FC1F324245F43F37958DF72F25E1CDF67F33B389FB3 -:801800001FFF9CB8BD21AFEAF89B93EF8DEF36F62321DF52F26467DD44D7C8C5F48D9DDFCAFAA9A4CD1C7FD3F337373FA3F3F8FE3FF8F31A3AEFE1F398988B994F69F982998FB9DB7BF51134FF51F19B99DF78B893FA89833F1DFE8882B791D79995F1A832EFCBF32E282B8B6D3C6F49A3334B118FA1F269A990155F91F731335F62F66934 -:80188000289FF3F34E4C9FA5F52F3EBFF7D7CAF1193BAFA8FA9B1BEF85FD7DBF75F33E367FE6F21D9ECFF8F83D2D9FBBFBB9BEAFFAFAAFAD7FD3F23632EFFBFA7C7CDFDBFB18BB8F49FA1A1A37795F71F9DAD98FB9F91F5FBF81F19812EFCBF98D8FF7C18F68F89E8C9F38F81A2EF5DF9BF29C1A6FC9F1AAA86F4BF81A386F25F7FE7C7E1D -:80190000784E721FFF457316D457F615177F72F24B6BFFF2F23F3DDFD3D799F1BDBDBFDAFB3B39BFB8FA1D1FBFB5F5EB6BFFD3535D6F37DF5EFC9C9CFF58D8DCF1A4B7E762FFD2FA342B4FE3733CFCFBF9C7C88FBB713EFE9C9A77B17F71D164F41D3EBFE2F31235EF43FB9ABEBFE2F31233EF62F35276AF2AFB9BBB77B8FFF8F89A1EEF3D -:80198000E9F92E1AAFA9FB961E6F4BF996944BBBCD1E4F814BF11527FF51F321237F56F25D5FBFF3F36F2FDFF7F74D4FBFFF778BFB3BBBBFB9F19F1FFFF5FCFFFFFFB3F33E327FA7FF3ADFEFC9F99E8C9F81F3A4B5C7C2CF82FA252A5FB3F3AC8CBF97F7A8BAAFABF9A884EFA17186F61496ED56BFA3F37F3EEFD3B3A8FBB9BBBFAAFB3E52 -:801A00003FAF62F33B3FBF3AFB9E9A6FF8F8AB8BEFE9F9B6BEEFEAF996B6EFE9B176F9FEFC9EC8CFE4F4B6AA302200302620C248438224022440A2492049269928128D24828504850410044918081004411006492891841220098444402449048324714804CB9F602815041564241187224414865832118931818911414228048D241200CB -:801A8000814128504880028140948210C228241AC2828AC2121A42A2682C29C8135028C092E044084234DDABC0421F4152281F41324C1F41324A1D24AB141D24AB9419B24A19B54A3934AF147934F84A9147832D914F82C4914FA2C4816FA264116FA264192FA264592D4A9E242D4A1F49C2421F4952281F497248F2912CA3F49124AB1454 -:801B00001FC1B24AF91128AB9453B14A3924AB9443B342792498924F8284F9244AFF6D0B2CF4116C85F21144411B21A3D441B24AD141F242941D24AB3451AF443B14AF547834F8428147832D816F82C4116D581CF924C816D1846415267898C5411E24BCF49824ACE441D62864498724962464C9AB1416F44A9416B44A3B152B244782A3C5 -:801B80003434AB944782216F8294124FA2752B090048008400000080020000001002428008000014008480040018000044800200000000F099480031151255144440CC11C22114188604257812342481261C26B241028998244144004412248480084410684181214C09200818002449D1229148D28A8124F4FB972446258A01A1224868BD -:801C0000290491281D48218631649944D24101824328C9882542022982D148C2A8A39292C0813012842120124114112C0118672880644110C4142688D41819F4D11F304513265141C5818244CA514E8241282E494C082786BD546440666826641D8379822A4A44247124E822D881F31282C0818246582C108812594243588441882A318464 -:801C80002120D142C1128B142CA1858C39543BF5502240032144C064008511C112C0814120D25861822088025024302200850440082412006041001C011840220148445042418BA42004FF1F0D004901008521411121224182142288118182D4180A0050228180D2227118C418800929084D131114B0421851220013581882244800441241 -:801D00004A212844F87ACF702112C521141351268A5322B0521A011216C9421415CABA24D44CC11142341548841122358817268E244885041594242598343E8C12B06A21153C12A911D24A11B18831184A31382662C2422828E79BD021428142211162191890A11100B4241C58218D1123D29434A81621042144A911A2431889948C48475D -:801D8000885016809121892A2138111210B212581829117112981842841283852804FFAA0340D4140114648C1252231A848221B142810489814A0216054051A10040C28A2E1523031880C82475CA1417413042A72648E11295028748200C124B12282D2442228CF23FA810241411C24A3011D01261846034B821C0149250848C11B14891FF -:801E00004447248C2872D8024200144682028934560010A82130122280624A6311D8427184E8460128800683F154EF80F1214400400481412417814382122C6122844C03442D16C011812692112348642828701A118441921842D3C8812224501242844189A143881820041212E1A420F53DE92415424234212002610040081058120019B2 -:801E8000018400800490482588C149000000122B2150168984818201008D413048212484800180F274C550412D24501248274211E5624184189922584216E8527192C8344062818CB14561442558122D488534C21290184582438251429391132815CA68241A64821088E81588F148148E4864160823A124A0242F980829115116288180F9 -:801F0000011448A5C14429414802008D154781544840A8A42212291438228714214200481249A82824442C31112212A0214E1245582850423A0432854408847D1A8002208432382281421305C02442230226521C138484A1421811302800482724A2800A40C2246903800390242024884422042E42A012F2208444F2ECA12420116481811B -:801F80001054224144816C81A421C88AC4484830822A84C18145F24182D0210231A251444324A124118814433A41860124200A12124B2C442C084349144212DC42A148FFD60410439823104188028C82824238142223E221425824C312023022101292242284E024088800C024212100881A02D0A2421442CA24121602000028AFDA4D225F -:802000002602814008548118491882C821154816A14229014841004904806C8811002C04144800141034412A614449812124228412181828542212222C24F8A75420582884240010123C84002841401A04C012202292442902442D5410064180312488858209C048234546810218008012040000841CF26B4F001A82A2612054481F84D249 -:8020800021444184928A28901440D183A6420021A2188521048812282C0100CC115221465141412C88044E884B42441289384888182988C3488021016F5647C11C002092162081A242309846B4826484CA324841800841331C41C1441C02481022061F42247422118124A842214413C2C2004C084C118484124424E9C4732834A4F0E13F00 -:802100004012512214A122214012B88204908100411828C11182442339842248181922012911641229A8124324984443488168841014024384817244422C04490220027F920F460848004601583302842D8C809281211929AA18C092422903181188861378649181282E812185412C0A24A04B4591821C0822660428122120924270428472 -:8021800054A287441FA846A3219718841CD288F2592465A2259FA2747218D2222AE21428B884E9527414B55176A8F212234B2B2C647A1D448CF645624F4448F123C21CF826764A84F621224AF28A2216B144DC11364D1EC16E7E6B482B9843F5D2724D14AD822AB3C82CA2C34AB6D2A8524E481E312B8CAF8B05212723701B02266142D5AF -:802200007144D15CFD88A88AF188887D428F94DE28B25998622F92F84214C846E441988665722431221B793F24D85831A250662F42E15C64494D843F6273A117D65274C212E2167A6CA4422A28E449D1A844F61C186C91124D6823F52234ACCC48FF7D086E4638ED226E5823D28255882FA2D5429221476487836F44E6497121F262446D93 -:802280003A97AE4D124DE84A81F4A1311B61EE81B11425F2A8684B255922ADAA1739815F3231614B88214E84BA5B451B881741282912A8614B4447446B222D66E37834E62251C4C1C7464F22F22A5400400C862404188001188001200912819220016044200112881288522041018190185018D01828918880688188800A888008817B2761 -:80230000347F76F63333CFA2F22D6B2F21D557F67D39DF83F77A6E1FDFFFB5B17AFF72C2AFB4FD4EFC1F1CF2C2427F5EFE61F3FFFEA26A4DE41D914F42FA6AAAEFC4B351F154754FE9FBD4FB7F19B972E767F33636AF3ABB13E1C6FB11361F38F2EB6A3F5E7684E9A3F3F95B3F51FBD9998F88A91FCD8C4F4DFDE466CFCBF336844F4CFC52 -:8023800088882F4CF57C58CFC9F9548A6F524DF341637FF1F72E2ADFB2E627F12767BFF3F73B7DAFF7F7FBFFFFBAEB27F75676BFB4FC4FCE9FB6B676F5E3E96EF37F7EF2B2326F44DC11F975F7BFB6DA9B38536F77FFB6A6FEF32F1BF8F6F55E264F5FFBF4FE7F7FEF47EB49F9C545DFBEF6DF1F7FDCF4B6FEFFF7FF1B9F7F7FF97232AF21 -:80240000A7F956866F4F7EEEBE36F922862F6E5CCEEFE5FD7E584F5AFCD4D21EDC346F64F43373BFF3F319137FF1F15B39CFC7F31D7CAFE6F6793D8F4AABD5AF84FEDC5DCFC5FDD5F17DC37F7FFF23B3FFF3BD22FE37515F1AFB8496AFA6F667C53AA2334FEBFA14FF67517E732F67F636763FAAFC13523F6AF73B3F9FBAF263E3BFD2F26C -:80248000D5D19F22F68183AFCAE264F852122F25F7CE4EEFC5FD74F6CF87F3E6244F44F82828AFC7F7FAF8CFC1F1C49A9F4C43E325F51F37BFF3F3793B7F73F97B3BEFE3F71F75AFF7F6FFDFAFEAEA2FFF1E4AFFFCF5CF5E5F3FFFF7D17F5DFF6BFBFFF7B9F2FF77715F1AFB6473FFBEFE27651F16E22FF7AEAECFF77F26F574766E665F14 -:8025000047F5A5D77F7BFDB376AFFBFBED2FFFB6FEB7F77F55F5BFF7FFF5FDF2762F6FF3FABAAFA5F7D256EFCFF57EDEEF85F1EE2E2F6EF6AEACEFC5F5FEB8CFD3F7C4DA2FF2062D11004042C811844722864861882484441F810480A2414213891201114A02426110024322A4822002254388A1412CA841008004124448004E2412008F9B -:80258000950B2C9421850214121870464148028314C11212467114D832688120C1858E4244A410912820C8828E2430812722442E81C44384929416B84AC124266281C048A514D44A032504213244F0ACB9C0421F4152281FC132681F41724AD241F24A111D24AF249921AB9451AF343934AF143B34AF147934D852F934481CF9244A1CF824 -:80260000244A16F1244A96F1224ADE254DCA9E24ACFC91244D421F49522C1F49324C1F49F26A121F48B24EF11124AB9419B24A19F54A924782AF2439242F24792498924F82A4944FA2F4C459C0421FC17622F2114C83F41124E3068B141D24AF4299418B9649B24A29734825F34A8513D142F236481CD8A685EBA26C512E4887592E4A56D4 -:80268000C48B1AC2CB1FC9C24A9A56281B6983A428AF1661488B1419F24A9419F24AB4512BB447828B9447828B944393986F8294986F22F56544A02882480000000044800200000010020000000014000048000000004480020010080025015FB40F5023441A1221045522C121100113112A836241251204164C042143341A004904214475 -:80270000238421921484004508850449230142200442181034C82840F1AB3214205881418113122302441A088711805128248D21126229812201A22312D4245128368232486810A41829382423116A22182881908221248504450221A1846044167144A8711424C2256C43201632252341211961411189C32A282C6221267412A212412399 -:8027800071A2624A4941022B14221904239418F01284EC82150823110C4CB316186264442830422C41484CCA44167156F8511C00111450181114004C0250181221122457818004458801C04281491178240225E84402442A090021CC02288100008442412400A0842200AF960826011450144001145012102A58128002A942E8440185041B -:8028000040088042082BC20020021812248429488C212122088444C03284448242861828D2584F228151846522014B216C6141C9011800814E28C4181AA44128442844416CC2241871182A68C1C01416921414442D218249C11418C188F012482498841E8CA149BC38941A8982C26481FDDC200285554251E01112341487410025881842BF -:8028800068821829B548A142414C4204444124264528D8860941D04212217122214862488C41848892C8C088414938224B84498248888826F262D124192101241240C4121124141200914A120489024C018440648229220112222A04121818408441D2488141C41812241830128189D12811C85A838166828544F8D3F9001A8401842412D1 -:80290000C03121822138AD14840047241810948818850449E32224022244812A042312686600423228004412608345018041028421894828F16E3924186CC4241321044009416014A81420E284084144130249022AC85840240818100C902A4282A1009011122484622A9448482302218006244C61217F3A0528111022514110029011817F -:802980000021120000C24484244200104224A821820012004912184218420813420821188582684200820048CF5B4221D361819212565825501A1E21415092182D11A1128C4C6641444F12DC48481498C2CC26042388A28189E2820C283826044D28843284394108948962818904288A6162C04A82814C21D4820A21901411001840021C8D -:802A000089845884200248000089138402286302414418442410022D826024200218442B12484612E52441582200222018081F21052912C522A444484481404C089081003840142401B8810016C82418C382088881408418043022201224012221842120B22818042392124C021F9706460200000011001C1811A441430481188140180496 -:802A800081444112000045082008008008928A41C42880822292184082A1818A018C01AF540780014355121586C2221C41028622C84288242648022E121004222112A110829126882170820CE141216441844425040010042247238604A22001A49DFA80221268128741234218173822182392282D883022486D1828218CA2A400862242E0 -:802B000002261AD4280124C22CA2281E222AC4262810028A82321230188932288546288138447064786832841FDF09440000844110844421010000100416044181402402800244C42018840448804224283114001004490240041A0240F832950081E484810083E481C21816482811210281411200200118901440040010341418801404F1 -:802B8000809914488218988048C6128280C11244C118F0E369248C5414484C21E2410211400140014122484881C4484C048889080018400448482284800490884042024E28000020042B8244881096245F840543698960123C01172126443224246028C016C012282C8292248C82A81228290121412528D1C222388A106282212A54424466 -:802C00000000209222284130144C82847244884422F5EABE4082C24420528129026110F34134214932A2412148A118238418622818A488876460212A6828664106A44CE9280681161A24022821449022212110222204904286F271D8246F44F19E3C85FA621815D881F4243117148D181F82D198018A7BCCB524D144E68412A41226A4420C -:802C80008D24188B82E0816281284F42019EBC2E8C8F885488444F41B8A88808C147A316E8487912A4222B2624241064E22FC10A4F4DE82229B148F5744483F37F171468134A7418F31C374743648782155348248BB1A4118626F228422A65611A33444F8438948AA2882961426D48122D1C10E644B2C638A4214D3429F2246425B28258E6 -:802D00004643B184DA62A8112A3B12C554428983E16282F3D424E74863C11845DAB602264231245D2423D23A52826D266F41F2462233F1A34335D122B8125E222B11A7E4ED28E5FA123CAAC4A416DAAA5264ED126C51A2CF23722662286D826CF412AA8E2227A5476227244CD24822E822A2144B1185082E28ACE8A2321647266F8839225A -:802D8000486ACB2C8D222F48FC2AD1000000422004422004800400000000100881001008000000840000888008888008800400004FD444F2576375FB2F2FFFE1F6EB6A8FA3771AFF3B1BFFB6F64F49A794AFA6FAE3D27F74FC96366D26EF67F762622D2AAD2A29F13C9C4F4AFA188AAF28DA2251226FE7F63636E5FE1212AFE8F2A6EEEF79 -:802E00008CF4B2B26F6BF3F63E65D66654666FE9F912162F2BFBF6726F42F358789E92AF2B594CC9F2ACA24B554F49F9D614EEB3AF89F97C3CCFC6F7ACE47F6548F25763FFB6F4272FFD7FEFEEF73E7EAF77F67B72FFA6F63B3BE7E4BFBFDBEBF9CFCF6F49DB66F25E7EAFE6F63A3EAFA2F22A3AEF8BB924FA8A9A2F28FAA2A22FA2B272DC -:802E8000FE3A3AEFE2F1B2127D27EFEEFECECFAF2BF3A6A66FCB57664F6252464F6BFB82822F2BF3F2F22F2BFBDEDC2E22AFE8FA8C8CCFC8F88EBA6F25F7B4B66F4BE92BF9BA9AEFC6F26C7CCF4F7E3446F157654D66FFF3F33F2EBFA2F67B33B7F1BFB7F7767AFFB2F23A3FAFAAF6C3F23F7DFDD1932F26F27E768F23D7AAF23E2EE7C17A -:802F0000EFCBF3B4B48FAAF9A2AAAD8E2FA1F1544EE7E1EFA2F212B2AFB9EBAEFECACA2FABFB36B26F6BFF26A66D26EFC2F2BAB4EFE9F9AEBC4BF74F48F9487EAFA1F19ABAEFE858CECD1ACF4DFD9C942F6EFED2932BDD6FC7F7686CCF6AFFCD15347F15F22C66BF93F37B3FAFA3F77B1FBFF3F23B3ECFA3F37F7B2F63F3BBFBFFA8F15FE4 -:802F8000DF3F3FF16222EFE7F77E7EAFC3F33E3EAFC3F3BEF8BE328FAAF8AAA8ED8E2FA1F1F66EAFE3F22E3E8FA9FB1ABBAFA6FECBCA2FA3FB8686EF6BFB26A66D22EFC2F2BCBCAFA8F83AB84F2FFF3636AFE7F7BABAEFA151EEE5FC2E3AEF2FFFB8B62F6FFDB6B66BF76FC6F46C4CCFEEFFFA93100661846D1148458114C448148E48149D -:8030000082544084442441240800400444189084800888B02408229084C0828226628924822008C02682850442826FC20122128501811A56221E68141E4823A24125024A01A5042D1200434124885822120023624125825224C012864442041E24252201860482184308922D26802101411826FAA132C0421F4152281F417248F11124A348 -:80308000D441B24AD141B24A9921AF145985AB944B43AF1439242F147924D812F924488D914FA2C4A14FA264114FA264192E4A96C54A8F49E2A2F491242CF491248D121F4932481F49326A1F48B24AD141B24A9921AB9451AF243924AF2439242B94478229FB2448984FA274DD032CF4116C85E24136481F41324A1F41B24AF11124AF4452 -:80310000E941B24A5B85ABB44B41AF1438342F1419F4429163D312D924D518D924FC18814D5A96E1227498C543DE252417C92E521FC8D628F19164421FC9B24A7181BC6AD141F24A841D242B9659B24239248B944782184D4829792688F3265A8D2B4028080000000044800200000010021880084200400140084800000000448002000015 -:80318000005012E017042417221014C81146049045248180441802C0124160C200002002401492346041002011C1329024200810084012B8148261820040F8834A1420887812012504110082152218B2810100482008184110044188221A088880088890A4C1880090240040145841440044D0484211F457AF0017AE2C68418444480046C1 -:80320000358491230A1002A0142186428C11048A01268428C282112A0888E08408491989084902491A0484412815044418264462C21425F2924A400210413211411100244082D418090010042200100400604160416041008012A421210000001008A52403840050841F59034054122002250224100288165818122903200222208202005B -:8032800010021810840290142800100190180000400400888281F0E491108501141118163911901812233111000012964228B1443114002542A241C0422C42041818602180711294122C0324821002C0164C5228A8208104A8F01A75101144112102351802242C01191108122B1200250844440010124222441204180010042C212151125C -:80330000244008001861818800C83028F04178406421001418181C01A9011888129100189822186A8121C222005200298201411A021229E121120422008218210044286422800182883092004284100210820190411001237242082A054168400218002400002410021022017022928412008931228051142C145828400424EF750528427E -:80338000110022485C2122C419284C02000045022480014F22882149180812400460110016040018101404E042092C2891284180612420C17E0000144043089445022400000000230200004230224002C240044400100200248648022410121184040000DFFC0A0015084083C4119C512413C1610020C248801422A22418C0822041782250 -:803400000A0041401441042301002B12446C3188508229082918F2482240820140D2890C220011212885422482140821112410024C03250440C2242004001221C224901200442C010029080018431122C114418744849044009FD20D8002121414110029011612281122110840C4140000000000124400C0240021004400214014020041C1 -:80348000210040043B73001410010000130894118E216082216728412880120220080044242200122812302280024034344004004400000021F0C7B5000010110821000040180850820000241800200112240000006021442100442001412428100400125024F0D13E0090114A02008F21022480010081800218241838800120084C1802A5 -:8035000000211A0812A08145021002400200803212121042845224AF170E002200000040010000001848180000224002000000008001002400004084012100000044AF94430100201122011100001C42212184810444000090820040240144124004000044005042800221400212801402EFDC04318004400210721202888716182888841C -:8035800000200840028008002100182828008012240850421220820343810840C41480019F9B0B8286011880011140080024840000008001B08201180000800121220020020040060000416100212114E0D7099C039994218211182903115041212814222124284428502280012E82408201885488448412495C422606210021401482427D -:80360000242821A12131684C5122F0A86A341882124213581334181113092417141E113302242C23C4144C8903001820012C51422241444412414B8144B6522482414512562420C21226B482D1425942244D1121C015F09D7960128215B131021229B133022D1B211D89853881811E18878421902449023A5122602A280012242901982B91 -:80368000212B2A2A434252462F42124244642212242512845144414981015E224974245124DFEF0411171289C21116112851282502111A31228542F928A22187482D3442122124189082F082127086041A4824810116042B1328002421168411524400602216B21242921416445242AD5F2001100889018901890998800998224CA9424C9C -:8037000028031200001220099A028A82218821882108000000122001322002222003BFF944D21393218F81A1519FA151AAA7913F117112FA921ABF19E1A1F1DBCA2B199F99F11812AF8FFFA624674A284F490B2A6221212B322B131E122F29F914161E961AFBA4B44F4BF386842B884F487884F694928EA4442F2858662546A6112B111E20 -:80378000124F2151444F2AB2B6FB34342F23D154F214744B67412CF2926B243D311F9557981F11B51141529A9FB1F1131B3FB9F18F151FB9F9F3F62B199F88F1989A2BFE4F6AF2B6144F44F684A62B221AC112212B2A23E329F192829E962F41F811B14F4BEB1BF31E1C23F2D4DC476869C4226F4A5A2265562265F616142F21F13232452F -:80380000526467682B884F436323284F61F776642AF21436DB4BA0231B621AF1181815F213133F13F21B1925F21A92AD162FA9F94B6A3F31D9BBF1BABAAF84B526B816A3884B132B113AC312212BA223E3217112F2949616F6B4154F48F314966FE3F316344F4BF714964F214144F486866544C4144C11C22265F216144F29B186F83414D0 -:803880006F6153666F42B446B53483B11B4EF233219F13E712F259191B119FB1F13B391F317113F31B9395F7131BFFADFE1B9AB5FA3A3AAF8CFC3C9A6B754BDD4B132B221A4112B2223A221E122F28E86151424F5BF194341F21F9363E6F4AFABC744D866B15BEB26F4A5A666544D266D14251222D226F21F116166F69B1B2FB34146F6187 -:80390000F312136F43F566741AD164F1157330226012843C416812841484348424404308001220010021282110064110046B1280012E121004241224400264001244124200F0111A60180000122400101211080085024C1184210100000024000012808261416128002144000000441012140244F052DAC0421F4152381F417248F11124C2 -:80398000A7241D24AB141F48B24AB981F24A9153B84A39A4AF343BA42F547BB4D852FB34481CFB244A1CF8244A16F1244A96E1A26C592DCA9E24ACFC91242CFD91248F22F99124EF24F99124AB841F48B26ED141F24A9219B24A19B54A3924AF4439242B94478229F924484CF9244AFF9706ACC464241E6C421FC132421D2C4AD1C1F24A8F -:803A0000144CB24A9365AB1441AF1483C43516D852F316481CFA265A1CF924CA16F1244A16E1826451BC6451AC54C1ACD54196581F41B248B11132481F48B24A9121AF44B911F248A453B14A2AB94A18B442598429F91248886D5A1EFA4008480000000000280000000021008008000014008480040000004004000000005012F0E9176002 -:803A80002822000084140018001121008001000000400200000000000021222141001200004C020000418FBB0E30818948011400181110010080010000000000002741800100188008180000000040023011440014F0192F00133688111001140043110114290218004002301220081042624111008120058220110221414160430010C25B -:803B000024131144021423F11D7E400200008180110100000080010000000000001200000000800200000000000000413FFA053011000081000000000022108401000000004002000000005041002100008028020000F0EC7C400200120015024140010000000000000041000043428801181012188421020018400418002122182841F03F -:803B800053684002001840082141100100002240840100001004009026840012240044121742002118400418882200122244E0BC0BC011000040010000000000000000000000008001001008000000000000212800007F760E00000000000000401802520000000010084100000000000000002C01008180088100F0A4551001004011027D -:803C00000080040021000021000000218004212100800100221004800800000040048218F0D636200200001100200200000041100484000000810000002100818400000000001200001800CF5B0411000010020028480050280049040084000000890421004002008428100480080000008840888101EFBD06220000111400000040020030 -:803C8000185042000000218140440200200100840000002C01008901100482007F5A0C0010040081000014000044100400001004000000200200008800A0120000840018004008BFE70F0000000000000000000000000000000000000000000000000000000000F04FFE0000000000000000000000000000000000000000000000000000D4 -:803D000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F00000000000000000000210000002180010000000040080000000000800100006FB70E00000000000000000000000000000000002100000041 -:803D80000000000000000000004759000084008400000000000000000000000000000000000000000000000000001A0E0000000000000000000000000000000000000000000000000000000000F04FFE000000000000000000000000000000000000200100000000000000200200006F8C0800000000000000000000000000000000000070 -:803E00000000000000000000000000F04FFE000000000000000000000000000000000000000000000000000000000000FFE40F0040080000000000000000000000218001001002180040080000000000000000F05C4B00000040080000000000002100000000000000000000000000000000380000F05672000000000000000000000000C7 -:803E8000000000000000000000000000000000000000FFE40F000000004005000040040021004400100218808802218001884008000028840000800200004FB1070014000048405588281082044480022100448002214818808802214818448828842148408481421882041E148002211A01445C03000040010080045400004840040000D9 -:803F000040040000008002000088000000804208000000F0469900000000005400000044001002400400218001882810021880088400008042080000280000F0147B000000000000000000000000000000000000000000000000000000000000FFE40F0000000000000000000000000000000000000000000000000000000000F04FFE0044 -:803F80001002400100800400281082040028000000280048000000484004281082044400108204440010F28F41000000000000000000000000000000000000000000000000000000000000FFE40F0000000000005400400400000000440000800200000080080000002884000000002FDD0E000000000000000000000000000000000000BC -:804000000000000000000000000000F04FFE00000000000000004004000000000000002800000000000000000000000000BFF20A00000000000054000000000000400400000000000080080000002884000000006FCBFBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08 -:01408000FF40 -:00000001FF diff --git a/xpp/firmwares/LICENSE.firmware b/xpp/firmwares/LICENSE.firmware deleted file mode 100644 index b9bb89f..0000000 --- a/xpp/firmwares/LICENSE.firmware +++ /dev/null @@ -1,37 +0,0 @@ -The firmware files (*.hex) in this directory are software for the -Astribank itself and not intended to run on the Linux system itself. -They are generally freely distriributable (see exact terms below). - -/****************************************************************************/ -/* Copyright (c) 2004-2006 Xorcom Inc. All Rights Reserved. */ -/* Redistribution and use of the microcode software ( Firmware ) is */ -/* permitted provided that the following conditions are met: */ -/* */ -/* 1. Firmware is redistributed verbatim without any modification; */ -/* 2. Any reproduction of Firmware must contain the above */ -/* copyright notice, this list of conditions and the below */ -/* disclaimer in the documentation and/or other materials */ -/* provided with the distribution; and */ -/* 3. The name of Xorcom may not be used to endorse or promote */ -/* products derived from this Firmware without specific prior */ -/* written consent. */ -/* */ -/* Disclaimer: Xorcom provides this firmware "as is" with no warranties */ -/* or indemnities whatsoever. Xorcom expressly disclaims any express, */ -/* statutory or implied warranties, including, but not limited to, the */ -/* implied warranties of merchantability, fitness for a particular */ -/* purpose and non-infringement. In no event shall Xorcom be liable for */ -/* any direct, indirect, incidental, special, exemplary, or consequential */ -/* damages (including, but not limited to, procurement of substitute */ -/* goods or services; loss of use, data, or profits; or business */ -/* interruption) however caused and on any theory of liability, whether */ -/* in contract, strict liability, or tort (including negligence or */ -/* otherwise) arising in any way out of the use of this firmware, even */ -/* if advised of the possibility of such damage. User acknowledges and */ -/* agrees that the purchase or use of the firmware will not create or */ -/* give grounds for a license by implication, estoppel, or otherwise in */ -/* any intellectual property rights (patent, copyright, trade secret, */ -/* mask work, or other proprietary right) embodied in any other Xorcom */ -/* hardware or firmware either solely or in combination with the firmware. */ -/****************************************************************************/ - diff --git a/xpp/firmwares/README b/xpp/firmwares/README deleted file mode 100644 index e423aa6..0000000 --- a/xpp/firmwares/README +++ /dev/null @@ -1,19 +0,0 @@ -This distribution includes the firmware files required by the Xorcom[tm] -Astribank[tm]. - -This distribution inlcudes just the firmware files. Be sure to use a -zaptel distribution/package of a matching version. - -INSTALLATION -"""""""""""" -run "make install" as root. (which will simply copy all the *.hex files -to /usr/share/zaptel ) - -USAGE -""""" -When the firmware files are in place everything should work -automagically. Consult the xpp documentation included in the package -zaptel (or the debian package zaptel) that you use for further information. - - -For further information contact support@xorcom.com http://xorcom.com diff --git a/xpp/firmwares/USB_FW.hex b/xpp/firmwares/USB_FW.hex deleted file mode 100644 index 01f7ce9..0000000 --- a/xpp/firmwares/USB_FW.hex +++ /dev/null @@ -1,223 +0,0 @@ -# -# $Id:$ -# -:100600001201000200000040E4E451110000010268 -:1006100003010A0600020000004001000902370041 -:1006200002010080320904000002FF0000040705F7 -:100630000202000200070586020002000904010010 -:1006400002FF0000050705040200020007058802FA -:100650000002000902370002010080320904000094 -:1006600002FF0000040705020240000007058602A1 -:100670004000000904010002FF0000050705040214 -:100680004000000705880240000004030904160327 -:1006900058006F00720063006F006D0020004C0076 -:1006A0005400440014034100730074007200690098 -:1006B000620061006E006B001203490053004E009F -:1006C00075006D006200650072000A03460050006C -:1006D000470041002A034D0061006E006100670081 -:1006E00065006D0065006E0074002000500072000F -:1006F0006F0063006500730073006F0072000000FC -:0B0B6C00C2B675B5C4120B18D2B62239 -:100A6300E4901010F07A107B107D017F50120A9FE2 -:100A73007F501208567A107B007D107F50020A8344 -:1008F8007F031209EBEF2402FFE43EFEE516C394E2 -:1009080008501F74082516F582E43410F583E0FDBD -:100918008F828E8375F002E5161205E8EDF0051654 -:0209280080DA73 -:01092A0022AA -:10092B00E50B240AFDE4350AFC901003E02FFF0DC4 -:10093B00EDAA0470010C14F5828A83EFF090100479 -:10094B00E08D828C83F0D20512099090E680E05402 -:02095B00F7F0B3 -:01095D002277 -:1007000090E600E054E74410F090E60174C0F090E9 -:10071000E6107420F000000090E611F00000009058 -:10072000E6047480F0000000740FF0000000E4F0B4 -:1007300000000090E6187410F0000000E490E61944 -:10074000F000000090E61A7408F0000000E490E663 -:100750001BF000000090E6497482F0000000F000F9 -:10076000000090E6247402F0000000E490E625F01A -:1007700000000090E6957480F0000000F00000009A -:0407800043AF012260 -:040B18007F327E00AA -:100B1C007C007D181205D6EF1FAC0670011E4C70C0 -:020B2C00F622AF -:0A0784008E188F198B1A8A1B891C2E -:10078E00E4F51DF51EC3E51E9519E51D95185033AC -:10079E00AB1AAA1BA91C851E82851D83120587FF15 -:1007AE00E4FEC2B2EF1392B7EFC313FFD2B20EBE86 -:1007BE0008F0C2B220B002C322051EE51E70C605A7 -:0407CE001D80C2D3F5 -:0107D2002204 -:10029200E4901010F0F516F517C204E5AA54846034 -:1002A200030203F990F400E024FE700302036524C4 -:1002B200FA700302038724F870030203B324F07078 -:1002C200030203BD24E070030203D824C0700302BA -:1002D20003D8247F60030203CC75160075170490BF -:1002E200FC007401F090F401E090FC01F090F40243 -:1002F200E090FC02F090F401E07017A3E07013307C -:10030200B01090E60174C0F0C2B6120B18D2B61249 -:100312000B1820B00330B44390E694E0FE90E695CB -:10032200E07C002400FFEC3ECF24FCCF34FFFE7BB8 -:10033200017AF47904120784501990FC0330B40D49 -:100342007408F07FE87E03120B1C0203D87404F0D9 -:100352000203D890FC037402F0807B90FC037401CA -:10036200F0807375160075170490FC007402F0E4B7 -:10037200A3F0A3F030B406A37410F0805990FC03EC -:100382007420F0805175160075171190FC007408E6 -:10039200F0E4FF74002FF582E43410F583E0FE747C -:1003A200012FF582E434FCF583EEF00FBF10E480F8 -:1003B2002590E6017403F07F02800A90E60174C082 -:1003C200F0C2B6E4FF12092B800C751600751701F6 -:1003D20090FC0074AAF0E51745166012E51690E647 -:1003E2009CF0000000E51790E69DF000000090E60A -:0703F200957480F00000008B -:0103F90022E1 -:020AFD00D32202 -:080B8C0090E6BAE0F528D3223F -:100AEB0090E740E528F0E490E68AF090E68B04F07E -:020AFB00D32204 -:080B940090E6BAE0F527D32238 -:100B5A0090E740E527F0E490E68AF090E68B04F00F -:020B6A00D32294 -:100A160090E6B9E0242F600D04701990E604E0FF1B -:100A2600430780800890E604E0FF53077F0000003C -:070A3600EFF08002D322C3A0 -:010A3D002296 -:100ABB00C0E0C083C082D2015391EF90E65D740118 -:080ACB00F0D082D083D0E032AC -:100B2E00C0E0C083C0825391EF90E65D7404F0D0B4 -:060B3E0082D083D0E032FA -:100B4400C0E0C083C0825391EF90E65D7402F0D0A0 -:060B540082D083D0E032E4 -:10088E00C0E0C083C08285100C85110D850D828558 -:10089E000C83A37402F085080E85090F850F8285DF -:1008AE000E83A37407F05391EF90E65D7410F0D0B1 -:0608BE0082D083D0E0327D -:100AD300C0E0C083C082D2035391EF90E65D7408F7 -:080AE300F0D082D083D0E03294 -:10081900C0E0C083C08290E680E030E72085080C04 -:1008290085090D850D82850C83A37402F085100E50 -:1008390085110F850F82850E83A37407F05391EFFD -:0D08490090E65D7420F0D082D083D0E032C4 -:0A0B8200000102020303040405054C -:10050200C203C200C202C201120B6C120700120B1C -:100512009C120A63750A06750B0075120675131292 -:1005220075080675091C7510067511537514067544 -:10053200158AD2E843D82090E668E04409F090E6B4 -:100542005CE0443DF0D2AF1208F87F0112092B5350 -:100552008EF8C203120292300105120070C20130FD -:1005620003F2C203120A3E20001690E682E030E750 -:1005720004E020E1EF90E682E030E604E020E0E4EF -:050582001209BF80CF4B -:0B0B770090E50DE030E402C322D32221 -:1000700090E6B9E0700302012F1470030201A4247A -:10008000FE700302021F24FB700302012914700397 -:1000900002012314700302011714700302011D24CE -:1000A00005600302027E120AFD400302028A90E606 -:1000B000BBE024FE602714603824FD601114602723 -:1000C00024067050E50A90E6B3F0E50B803C120B75 -:1000D00077503EE51290E6B3F0E513802DE50C90E5 -:1000E000E6B3F0E50D8023E50E90E6B3F0E50F8072 -:1000F0001990E6BAE0FF1209EBAA06A9077B01EA0C -:10010000494B600DEE90E6B3F0EF90E6B4F00202DA -:100110008A020279020279120B5A02028A120B94A5 -:1001200002028A120B8C02028A120AEB02028A90E5 -:10013000E6B8E0247F601514601924027063A20001 -:10014000E43325E0FFA202E4334F8041E490E7402E -:10015000F0803F90E6BCE0547EFF7E00E0D39480C8 -:100160007C0040047D0180027D00EC4EFEED4F24BA -:1001700082F582740B3EF583E493FF3395E0FEEF46 -:1001800024A1FFEE34E68F82F583E0540190E7402E -:10019000F0E4A3F090E68AF090E68B7402F002029D -:1001A0008A02027990E6B8E024FE60162402600319 -:1001B00002028A90E6BAE0B40105C20002028A0295 -:1001C000027990E6BAE0705590E6BCE0547EFF7E7E -:1001D00000E0D394807C0040047D0180027D00EC2F -:1001E0004EFEED4F2482F582740B3EF583E493FFBF -:1001F0003395E0FEEF24A1FFEE34E68F82F583E035 -:1002000054FEF090E6BCE05480131313541FFFE03B -:10021000540F2F90E683F0E04420F0806D805A90D8 -:10022000E6B8E024FE60192402704E90E6BAE0B40D -:100230000104D200805490E6BAE06402604C803938 -:1002400090E6BCE0547EFF7E00E0D394807C0040CA -:10025000047D0180027D00EC4EFEED4F2482F5828C -:10026000740B3EF583E493FF3395E0FEEF24A1FF8A -:10027000EE34E68F82F583800D90E6A08008120AA6 -:1002800016500790E6A0E04401F090E6A0E044801C -:01029000F07D -:01029100224A -:03003300020BA419 -:040BA40053D8EF3201 -:03004300020B00AD -:03005300020B009D -:100B0000020ABB00020B4400020B2E00020AD300B3 -:080B100002088E000208190022 -:1009BF0090E682E030E004E020E60B90E682E03043 -:1009CF00E119E030E71590E680E04401F07F147EF6 -:0C09DF00001207D390E680E054FEF022E6 -:1009900030050990E680E0440AF0800790E680E0A8 -:1009A0004408F07FDC7E051207D390E65D74FFF00B -:0F09B00090E65FF05391EF90E680E054F7F0226D -:080B9C00E4F526D2E9D2AF22F4 -:10085600AD0790E678E020E6F9C2E990E678E04454 -:1008660080F0ED25E090E679F090E678E030E0F96A -:1008760090E678E04440F090E678E020E6F990E6ED -:0808860078E030E1D6D2E9224E -:10095E00AC0790E678E020E6F9E526702390E6787D -:10096E00E04480F0EC25E090E679F08D21AF03A90C -:10097E00077522018A238924E4F525752601D322E1 -:02098E00C32282 -:1008C400AC0790E678E020E6F9E526702590E67816 -:1008D400E04480F0EC25E0440190E679F08D21AF0E -:1008E40003A9077522018A238924E4F525752603C3 -:0408F400D322C32226 -:03004B000203FAB3 -:1003FA00C0E0C083C082C085C084C086758600C044 -:10040A00D075D000C000C001C002C003C006C0073A -:10041A0090E678E030E2067526060204E490E67873 -:10042A00E020E10CE526640260067526070204E472 -:10043A00E52624FE605F14603624FE70030204D5AC -:10044A0024FC70030204E1240860030204E4AB22E2 -:10045A00AA23A924AF2505258F8275830012058753 -:10046A0090E679F0E52565217070752605806B9018 -:10047A00E679E0AB22AA23A924AE258E82758300F1 -:10048A001205B4752602E5216401704E90E678E003 -:10049A004420F08045E52124FEB5250790E678E062 -:1004AA004420F0E52114B5250A90E678E04440F0AE -:1004BA0075260090E679E0AB22AA23A924AE258E00 -:1004CA00827583001205B40525800F90E678E04412 -:1004DA0040F075260080037526005391DFD007D0BF -:1004EA0006D003D002D001D000D0D0D086D084D09C -:0804FA0085D082D083D0E032EE -:0209EB00A9075A -:1009ED00AE14AF158F828E83A3E064037017AD0133 -:1009FD0019ED7001228F828E83E07C002FFDEC3E7D -:080A0D00FEAF0580DFE4FEFFEF -:010A150022BE -:100A83001208C4E52624FA600E146006240770F3E6 -:0C0A9300D322E4F526D322E4F526D3227A -:100A9F0012095EE52624FA600E146006240770F32F -:0C0AAF00D322E4F526D322E4F526D3225E -:100A3E0090E682E044C0F090E681F043870100002A -:040A4E000000002282 -:1007D3008E188F1990E600E054187012E519240161 -:1007E300FFE43518C313F518EF13F519801590E6D8 -:1007F30000E05418FFBF100BE51925E0F519E518C3 -:1008030033F518E5191519AE18700215184E600561 -:06081300120A5280EE22E1 -:100A52007400F58690FDA57C05A3E582458370F9B7 -:010A62002271 -:030000000205F402 -:0C05F400787FE4F6D8FD7581280205022E -:10058700BB010CE58229F582E5833AF583E0225029 -:1005970006E92582F8E622BBFE06E92582F8E22273 -:0D05A700E58229F582E5833AF583E493228D -:1005B400F8BB010DE58229F582E5833AF583E8F07D -:1005C400225006E92582C8F622BBFE05E92582C829 -:0205D400F22211 -:1005D600EF8DF0A4A8F0CF8CF0A428CE8DF0A42E39 -:0205E600FE22F3 -:0C05E800A42582F582E5F03583F583221E -:00000001FF - \ No newline at end of file diff --git a/xpp/init_card_3_29 b/xpp/init_card_3_29 deleted file mode 100755 index 43dbb54..0000000 --- a/xpp/init_card_3_29 +++ /dev/null @@ -1,189 +0,0 @@ -#! /bin/sh -# -# Written by Oron Peled -# Copyright (C) 2006, Xorcom -# -# All rights reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# See the file LICENSE in the top level of this tarball. -# - -# -# $Id$ -# -# Data format: -# - A comment start with ';' or '#' until the end of line -# - Blank lines are ignored -# - Fields are whitespace separated (spaces or tabs) -# -# The fields are (in command line order): -# 1. SLIC select in decimal (range 0-7). -# 31 is a special value which means ALL SLICS (only some registers -# accept settings for ALL SLICS). -# 2. Command word: -# - RD Read Direct register. -# - RI Read Indirect register. -# - WD Write Direct register. -# - WI Write Indirect register. -# 3. Register number in hexadecimal. -# 4. Low data byte in hexadecimal. (for WD and WI commands). -# 5. High data byte in hexadecimal. (for WI command only). -# -# - -# ----------------------------------==== 8-channel FXS unit initialization ===----------------------------------------- - -set -e - -me=`basename $0` -INIT_DIR=`dirname $0` -XPP_BASE=/proc/xpp -export XPP_BASE -LOGGER="logger -s -t $me" - -ZAPTEL_BOOT_DEBIAN=${ZAPTEL_BOOT_DEBIAN:-/etc/default/zaptel} -ZAPTEL_BOOT_FEDORA=${ZAPTEL_BOOT_FEDORA:-/etc/sysconfig/zaptel} - -# read default configuration from /etc/default/zaptel -if [ -r $ZAPTEL_BOOT_DEBIAN ]; then . $ZAPTEL_BOOT_DEBIAN; fi -if [ -r $ZAPTEL_BOOT_FEDORA ]; then . $ZAPTEL_BOOT_FEDORA; fi - -if [ "$DEBUG_CALIBRATION"=1 ]; then - LOGGER=":" -fi - -# Always redirect stderr somewhere, otherwise the shell script will die -# when it tries to do I/O related stuff on closed file descriptor. -# Our default is to throw it down the bit-bucket. -exec 2> /dev/console -## If you wish to trace this script: -#exec 2> /tmp/xpp_init_$XPD_NAME -## Altenativly, if you have multiple XBUS'es: -#exec 2> /tmp/xpp_init_$XBUS_NAME_$XPD_NAME -#set -x - -# redirect script output to the "slics" (registers command) file: -exec 1> "$XPP_BASE/$XPD_BUS/$XPD_NAME/slics" - -$LOGGER -p kern.info "$XPD_BUS/$XPD_NAME: Calibrating '$0'" - -"$INIT_DIR/calibrate_slics" - -$LOGGER -p kern.info "$XPD_BUS/$XPD_NAME: Continue '$0'" - -echo " -# Change SLICs states to "Open state"s (Off,all transfers tristated to avoid data collision), Voltage sense -31 WD 40 00 - -# Flush out energy accumulators -31 WI 58 00 00 -31 WI 59 00 00 -31 WI 5A 00 00 -31 WI 5B 00 00 -31 WI 5C 00 00 -31 WI 5D 00 00 -31 WI 5E 00 00 -31 WI 5F 00 00 -31 WI 61 00 00 -31 WI 58 00 00 -31 WI C1 00 00 -31 WI C2 00 00 -31 WI C3 00 00 -31 WI C4 00 00 -31 WI C5 00 00 -31 WI C6 00 00 -31 WI C7 00 00 -31 WI C8 00 00 -31 WI C9 00 00 -31 WI CA 00 00 -31 WI CB 00 00 -31 WI CC 00 00 -31 WI CD 00 00 -31 WI CE 00 00 -31 WI CF 00 00 -31 WI D0 00 00 -31 WI D1 00 00 -31 WI D2 00 00 -31 WI D3 00 00 - -# Setting of SLICs offsets -# New card initialization -0 WD 02 00 -0 WD 04 00 -1 WD 02 08 -1 WD 04 08 -2 WD 02 10 -2 WD 04 10 -3 WD 02 18 -3 WD 04 18 -4 WD 02 20 -4 WD 04 20 -5 WD 02 28 -5 WD 04 28 -6 WD 02 30 -6 WD 04 30 -7 WD 02 38 -7 WD 04 38 -31 WD 03 00 -31 WD 05 00 - -# Audio path. (also initialize 0A and 0B here if necessary) -31 WD 08 00 -31 WD 09 00 - -# Automatic/Manual Control: defaults - Cancel Power Alarm -31 WD 43 1E - -# Loop Closure Debounce Interval -31 WD 45 0A - -# Ring Detect Debounce Interval -31 WD 46 47 - -# Battery Feed Control: Battery low (DCSW low) -31 WD 42 00 - -# Loop Current Limit -31 WD 47 00 - -31 WD 6C 01 - -31 WI 23 00 80 -31 WI 24 20 03 -31 WI 25 8C 08 -31 WI 26 00 01 -31 WI 27 10 00 - -#------ Metering tone -31 WI 17 61 15 # Amplitue Ramp-up -31 WI 18 61 15 # Max Amplitude -31 WI 19 FB 30 # Frequency -31 WD 2C 00 # Timer dL -31 WD 2D 03 # Timer dH - -# ------------------------------------- Initialization of direct registers -------------------------------------------- - -# Mode(8-bit,u-Law,1 PCLK ) setting, Loopbacks and Interrupts clear - -31 WD 01 29 -#31 WD 0E 00 - -#31 WD 15 00 -#31 WD 16 03 - -# Clear pending interrupts -31 WD 12 FF -31 WD 13 FF -31 WD 14 FF - -#31 WD 4A 34 -#31 WD 4B 10 -" | sed -e 's/[;#].*$//' -e '/^[ ]*$/d' - -$LOGGER -p kern.info "$XPD_BUS/$XPD_NAME: Ending '$0'" -exit 0 diff --git a/xpp/init_card_4_29 b/xpp/init_card_4_29 deleted file mode 100755 index 5dda0b2..0000000 --- a/xpp/init_card_4_29 +++ /dev/null @@ -1,165 +0,0 @@ -#! /bin/sh -# -# Written by Oron Peled -# Copyright (C) 2006, Xorcom -# -# All rights reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# See the file LICENSE in the top level of this tarball. -# - -# -# $Id$ -# -# Data format: -# - A comment start with ';' or '#' until the end of line -# - Blank lines are ignored -# - Fields are whitespace separated (spaces or tabs) -# -# The fields are (in command line order): -# 1. DAA select in decimal (range 0-7). -# 31 is a special value which means ALL DAAs (only some registers -# accept settings for ALL DAAs). -# 2. Command word: -# - RD Read Direct register. -# - WD Write Direct register. -# 3. Register number in hexadecimal. -# 4. Data byte in hexadecimal. (for WD command). -# - -# ----------------------------------==== 8-channel FXO unit initialization ===----------------------------------------- - -set -e - -opermode='FCC' - -me=`basename $0` -INIT_DIR=`dirname $0` -XPP_BASE=/proc/xpp -export XPP_BASE -LOGGER="logger -s -t $me" - -ZAPTEL_BOOT_DEBIAN=${ZAPTEL_BOOT_DEBIAN:-/etc/default/zaptel} -ZAPTEL_BOOT_FEDORA=${ZAPTEL_BOOT_FEDORA:-/etc/sysconfig/zaptel} - -# read default configuration from /etc/default/zaptel -if [ -r $ZAPTEL_BOOT_DEBIAN ]; then . $ZAPTEL_BOOT_DEBIAN; fi -if [ -r $ZAPTEL_BOOT_FEDORA ]; then . $ZAPTEL_BOOT_FEDORA; fi - -if [ "$DEBUG_CALIBRATION"=1 ]; then - LOGGER=":" -fi - -# Always redirect stderr somewhere, otherwise the shell script will die -# when it tries to do I/O related stuff on closed file descriptor. -# Our default is to throw it down the bit-bucket. -exec 2> /dev/console -## If you wish to trace this script: -#exec 2> /tmp/xpp_init_$XPD_NAME -## Altenativly, if you have multiple XBUS'es: -#exec 2> /tmp/xpp_init_$XBUS_NAME_$XPD_NAME -#set -x - -# redirect script output to the "slics" (registers command) file: -exec 1> "$XPP_BASE/$XPD_BUS/$XPD_NAME/slics" - -$LOGGER -p kern.info "$XPD_BUS/$XPD_NAME: Initializing '$0'" - -# Several countries (South Africa, UAE, anybody else) -# require a shorter delay: -case "$opermode" in -SOUTHAFRICA|UAE) echo 31 WD 17 2B;; -esac - -# Remove empty lines and commets. Not strictly necessary -# but works around some limitations of the proc interface: -echo " - - -31 WD 21 28 -31 WD 18 99 -31 WD 06 00 - -# ----------- DAA PCM start offset ---------- - -0 WD 22 00 -0 WD 23 00 -0 WD 24 00 -0 WD 25 00 - -1 WD 22 08 -1 WD 23 00 -1 WD 24 08 -1 WD 25 00 - -2 WD 22 10 -2 WD 23 00 -2 WD 24 10 -2 WD 25 00 - -3 WD 22 18 -3 WD 23 00 -3 WD 24 18 -3 WD 25 00 - -4 WD 22 20 -4 WD 23 00 -4 WD 24 20 -4 WD 25 00 - -5 WD 22 28 -5 WD 23 00 -5 WD 24 28 -5 WD 25 00 - -6 WD 22 30 -6 WD 23 00 -6 WD 24 30 -6 WD 25 00 - -7 WD 22 38 -7 WD 23 00 -7 WD 24 38 -7 WD 25 00 - -# ----------- DAA ONHOOK -------------------- -31 WD 05 00 - -# Set tip to ring voltage to 3.5 volts while off-hook -# instead of default of 3.1 -31 WD 1A C0 -" | sed -e 's/[;#].*$//' -e '/^[ ]*$/d' - -# Turning off red LEDs -# Warning: do not send WD 31 20 A0 ! -for i in `seq 0 7`; do - echo "$i WD 20 A0" -done - -# based on fxo_modes from wctdm.c . -reg16=00; reg26=00; reg30=00; reg31=20; ring_osc=; ring_x=; -mode="$opermode" -if [ -r $INIT_DIR/init_fxo_modes ]; then - . $INIT_DIR/init_fxo_modes -fi -# Our register numbers are HEXADECIMAL! -echo " -31 WD 10 $reg16 -31 WD 1A $reg26 -31 WD 1E $reg30 -31 WD 1F $reg31 -" -# for the FXS: -#if [ "$ring_osc" != '' ]; then -# /bin/echo "31 WI __ $ring_osc" -#fi -#if [ "$ring_x" != '' ]; then -# /bin/echo "31 WI __ $ring_x" -#fi -$LOGGER -p kern.info "$XPD_BUS/$XPD_NAME: Ending '$0'" -exit 0 diff --git a/xpp/init_card_6_29 b/xpp/init_card_6_29 deleted file mode 100755 index 0da1f61..0000000 --- a/xpp/init_card_6_29 +++ /dev/null @@ -1,434 +0,0 @@ -#! /usr/bin/perl -w -use strict; - -# -# $Id$ -# - -# -# Written by Oron Peled -# Copyright (C) 2006, Xorcom -# -# All rights reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# See the file LICENSE in the top level of this tarball. -# - -# This script is run from the xpp kernel module upon detection -# of a new XPD. -# -# Expects the following environment variables to be set: -# XPD_BUS - bus name -# XPD_NAME - xpd name -# XPD_UNIT - xpd unit number -# XPD_SUBUNIT - xpd subunit number -# XPD_TYPE - xpd type number (from protocol reply): -# 3 - FXS -# 4 - FXO -# 6 - BRI_TE -# 7 - BRI_NT -# XPD_REVISION - xpd revision number -# -# Output data format: -# - An optional comment start with ';' or '#' until the end of line -# - Optional Blank lines are ignored -# - Fields are whitespace separated (spaces or tabs) -# -# The fields are (in command line order): -# 1. CHIP select in decimal (ignored, taken from 3 LSB's of subunit number) -# 2. Command word: -# - RD Read Direct register. -# - RS Read Sub-register. -# - WD Write Direct register. -# - WS Write Sub-register. -# 3. Register number in hexadecimal. -# 4. Subregister number in hexadecimal. (for RS and WS commands). -# 5. Data byte in hexadecimal. (for WD and WS commands only). -# - -package main; -use File::Basename; - -my $program = basename("$0"); -my $init_dir = dirname("$0"); -my $unit_id; - -sub logit { - print STDERR "$unit_id: @_\n"; -} - -# Arrange for error logging -if (-t STDERR) { - $unit_id = 'Interactive'; - logit "Interactive startup\n"; -} else { - $unit_id = "$ENV{XPD_BUS}/$ENV{XPD_NAME}"; - open (STDERR, "| logger -t $program -p kern.info") || die; - logit "Non Interactive startup\n"; -} - -package BRI; - -sub gen { - my $fmt = shift; - $| = 1; - printf "$fmt\n", @_; -} - -package BRI::Port; - -sub new { - my $pack = shift; - my $port = { @_ }; - bless $port, $pack; -} - -# zap_xhfc_su.c:995 -sub init_su { - my $port = shift; - my $portnum = $port->{PORT_NUM}; - my $port_mode_up = $port->{PORT_MODE_UP}; - my $port_mode_exch = $port->{PORT_MODE_EXCH}; - my $bri_nt = $port->{BRI_NT}; - #logit "init_su(portnum=$portnum, port_mode_up=$port_mode_up, bri_nt=$bri_nt)"; - - # Setting PLL - # R_PLL_CTRL = 0 (V_PLL_M = 0, Reset PLL, Disable PLL_ - # R_CLK_CFG = 05 (PLL clock as system clock, output it to CLK_OUT pin) - # R_PLL_P = 1 - # R_PLL_N = 6 - # R_PLL_S = 1 - # R_PLL_CTRL = 1 (V_PLL_M) - - BRI::gen "#--------------------------- init_su($portnum, $bri_nt, $port_mode_up, $port_mode_exch)"; - BRI::gen "0 WD 02 04"; - BRI::gen "0 WD 50 00"; # disable PLL - BRI::gen "0 WD 51 02"; - BRI::gen "0 WD 52 06"; - BRI::gen "0 WD 53 04"; - BRI::gen "0 WD 50 01"; # Enable PLL - BRI::gen "0 WD 02 05"; # Enable PLL - - su_sel($portnum); # select port - if ("$port_mode_up" == 1) { - $port->{CTRL3} = 0x01; # A_ST_CTRL3: V_ST_SEL = 1 - $port->{CTRL0} = 0x10; # A_SU_CTRL0: V_ST_SQ_EN = 1 - BRI::gen "0 WD 34 0F"; # A_MS_TX: - # (multiframe/superframe transmit register) - } else { - $port->{CTRL3} = 0x00; # A_ST_CTRL3: V_ST_SEL = 0 - $port->{CTRL0} = 0x00; # A_SU_CTRL0: V_ST_SQ_EN = 0 - } - if ("$bri_nt" == 1) { - $port->{CTRL0} |= 0x04; # V_SU_MD - } - # ((V_SU_EXCH)?0x80:00) (change polarity) - if($port_mode_exch) { - $port->{CTRL2} = 0x80; - } else { - $port->{CTRL2} = 0x00; - } - BRI::gen "0 WD 35 %02X", $port->{CTRL3}; # A_ST_CTRL3 - BRI::gen "0 WD 31 %02X", $port->{CTRL0}; # A_SU_CTRL0 - BRI::gen "0 WD 35 F8"; # A_ST_CTRL3 = set end of pulse control to 0xF8 - BRI::gen "0 WD 32 08"; # A_SU_CTRL1 = Ignore E-channel data - BRI::gen "0 WD 33 %02X", $port->{CTRL2}; # A_SU_CTRL2 - - # zap_xhfc_su.c:1030 in init_su() - # A_SU_CLK_DLY - my $clk_dly; - if ("$bri_nt" == 1) { - $clk_dly = 0x6C; - } else { - $clk_dly = 0x0E; - } - #logit "clk_dly=$clk_dly"; - BRI::gen "0 WD 37 %02X", "$clk_dly"; -} - -sub su_sel { - if (@_ != 1 ) { - main::logit "ERROR: su_sel() called with " . scalar(@_) . " parameters"; - exit 1; - } - my $portnum = shift; - BRI::gen "0 WD 16 %02X", $portnum; # R_SU_SEL -} - -# zap_xhfc_su.c:281 -sub xhfc_selfifo { - if (@_ != 1 ) { - main::logit "ERROR: xhfc_selfifo() called with " . scalar(@_) . " parameters"; - exit 1; - } - my $fifonum = shift; - #logit "xhfc_selfifo($fifonum)"; - BRI::gen "0 WD 0F %02X", $fifonum; - # --> WAIT UNTIL (R_STATUS & M_BUSY) == 0 -} - -# zap_xhfc_su.c:295 -sub xhfc_resetfifo() { - #logit "xhfc_resetfifo()"; - # A_INC_RES_FIFO = M_RES_FIFO | M_RES_FIFO_ERR - BRI::gen "0 WD 0E 0A"; - # --> WAIT UNTIL (R_STATUS & M_BUSY) == 0 -} - -# zap_xhfc_su.c:1040 -# Initialize fifo (called for each portnum, channel, direction) -sub setup_fifo { - my $port = shift; - my $chan = shift; - my $direction = shift; - my $conhdlc = shift; - my $subcfg = shift; - my $fifoctrl = shift; - - my $portnum = $port->{PORT_NUM}; - my $port_mode_up = $port->{PORT_MODE_UP}; - my $port_mode_exch = $port->{PORT_MODE_EXCH}; - my $bri_nt = $port->{BRI_NT}; - - BRI::gen "#--------------------------- setup_fifo($portnum, $chan, $direction)"; - # my $fifonum = 0x80 | ($portnum << 3) | ($chan << 1) | ($direction); # # MSB first - my $fifonum = ($portnum << 3) | ($chan << 1) | ($direction); # # MSB first - my $r_slot = ($portnum << 3) | ($chan << 1) | ($direction); - - # channel order workaround, swap odd and even portnums in $r_slot for PCM (chan 0, 1) only - if ("$chan" == 0 || "$chan" == 1) { - $r_slot = $r_slot ^ 0x08; - } - - my $short_portnum = $portnum & 0x03; - my $a_sl_cfg = (0x80 | ($short_portnum << 3) | ($chan << 1) | ($direction)); # receive data from STIO2, transmit to STIO1 - - #logit "setup_fifo($fifonum)"; - xhfc_selfifo $fifonum; - # A_CON_HDLC: transparent mode selection - BRI::gen "0 WD FA %02X", $conhdlc; - # A_SUBCH_CFG: subchnl params - BRI::gen "0 WD FB %02X", $subcfg; - # A_FIFO_CTRL: FIFO Control Register - BRI::gen "0 WD FF %02X", $fifoctrl; - xhfc_resetfifo; - xhfc_selfifo $fifonum; # wait for busy is builtin in this command - BRI::gen "0 WD 10 %02X", $r_slot; # R_SLOT - BRI::gen "0 WD D0 %02X", $a_sl_cfg; # A_SL_CFG - - #system("/bin/echo \"----=====TE\" \"short_portnum=\"$short_portnum \"portnum=\" $portnum \"chan=\" $chan\"======----\n\" >>/root/xortel/test_init"); -} - -# zap_xhfc_su.c:1071 -sub setup_su { - my $port = shift; - my $bchan = shift; - my $portnum = $port->{PORT_NUM}; - my $port_mode_exch = $port->{PORT_MODE_EXCH}; - my $bri_nt = $port->{BRI_NT}; - - BRI::gen "#--------------------------- setup_su($portnum, $bchan)"; - #logit "setup_su(portnum=$portnum, bchan=$bchan, port_mode_exch=$port_mode_exch, bri_nt=$bri_nt)"; - $port->{CTRL0} |= (1 << $bchan) | $bri_nt; - $port->{CTRL2} |= ($port_mode_exch << 7) | (1 << $bchan); - su_sel($portnum); # Select port - BRI::gen "0 WD 31 %02X", $port->{CTRL0}; # A_SU_CTRL0: V_B1_TX_EN | V_SU_MD | (NT/TE) - BRI::gen "0 WD 33 %02X", $port->{CTRL2}; # A_SU_CTRL2: V_B1_RX_EN -} - -sub xhfc_ph_command { - my $port = shift; - my $cmd = shift; - my $portnum = $port->{PORT_NUM}; - #logit "xhfc_ph_command(portnum=$portnum)"; - if ("$cmd" eq "HFC_L1_ACTIVATE_TE") { - su_sel($portnum); # Select port - BRI::gen "0 WD 30 60"; # A_SU_WR_STA = (M_SU_ACT & 0x03) - # (set activation) - } elsif ("$cmd" eq "HFC_L1_FORCE_DEACTIVATE_TE") { - su_sel($portnum); # Select port - BRI::gen "0 WD 30 40"; # A_SU_WR_STA = (M_SU_ACT & 0x02) - # (set deactivation) - } elsif ("$cmd" eq "HFC_L1_ACTIVATE_NT") { - su_sel($portnum); # Select port - BRI::gen "0 WD 30 E0"; # A_SU_WR_STA = (M_SU_ACT & 0x03) | 0x80 - # (set activation + NT) - } elsif ("$cmd" eq "HFC_L1_DEACTIVATE_NT") { - su_sel($portnum); # Select port - BRI::gen "0 WD 30 40"; # A_SU_WR_STA = (M_SU_ACT & 0x02) - # (set deactivation) - } -} - - -sub zthfc_startup { - my $port = shift; - my $portnum = $port->{PORT_NUM}; - my $port_mode_exch = $port->{PORT_MODE_EXCH}; - my $bri_nt = $port->{BRI_NT}; - #logit "zthfc_startup(portnum=$portnum, port_mode_exch=$port_mode_exch, bri_nt=$bri_nt)"; - - # PCM <-> ST/Up Configuration - foreach my $chan ( 0, 1 ) { - $port->setup_fifo($chan, 0, 0xFE, 0, 0);# Transparent mode, FIFO EN, ST->PCM - $port->setup_fifo($chan, 1, 0xFE, 0, 0);# Transparent mode, FIFO EN, ST->PCM - $port->setup_su($chan); # zap_xhfc_su.c:194 - } - - # Zaptel chan 2 used as HDLC D-Channel - $port->setup_fifo(2, 0, 0x05, 2, 0); # D-TX: zap_xhfc_su.c:205 - $port->setup_fifo(2, 1, 0x05, 2, 0); # D-RX: zap_xhfc_su.c:206 - # E-chan, Echo channel is ignored - - - # enable this port's state machine - su_sel($portnum); # Select port - # A_SU_WR_STA: reset port state machine - BRI::gen "0 WD 30 00"; - if ("$bri_nt" == 0) { - $port->xhfc_ph_command("HFC_L1_ACTIVATE_TE"); - } else { - $port->xhfc_ph_command("HFC_L1_ACTIVATE_NT"); - } -} - - -package main; -use Getopt::Std; - -my %opts; -getopts('o:', \%opts); - -$ENV{XPP_BASE} = '/proc/xpp'; -my $cmd = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/command"; -my $output; -if ($opts{o}) { - $output = $opts{o}; -} else { - $ENV{XPD_BUS} || die "Missing XPD_BUS environment variable\n"; - $ENV{XPD_NAME} || die "Missing XPD_NAME environment variable\n"; - $ENV{XPD_TYPE} || die "Missing XPD_TYPE environment variable\n"; - $ENV{XPD_REVISION} || die "Missing XPD_REVISION environment variable\n"; - $output = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/$ENV{XPD_NAME}/slics"; -} - -open(REG, ">$output") || die "Failed to open '$output': $!\n"; -select REG; - -logit "Starting '$0'"; - -#------------------------------------------- Instance detection - -# zap_xhfc_su.c:895 -sub init_xhfc() { - #logit "init_xhfc()"; - BRI::gen "#--------------------------- init_xhfc"; - BRI::gen "0 WD 0D 00"; # r_FIFO_MD: 16 fifos, - # 64 bytes for TX and RX each (FIFO mode config) - - # software reset to enable R_FIFO_MD setting - BRI::gen "0 WD 00 08"; # R_CIRM = M_SRES (soft reset) - # --> WAIT 5u - BRI::gen "0 WD 00 00"; # R_CIRM = 0 (zero it to deactivate reset) - - # amplitude - BRI::gen "0 WD 46 80"; # R_PWM_MD: (PWM output mode register) - # PWM push to zero only - BRI::gen "0 WD 39 18"; # R_PWM1: (modulator register for PWM1) - # set duty cycle - - BRI::gen "0 WD 0C 11"; # R_FIFO_THRES: (FIFO fill lvl control register) - # RX/TX threshold = 16 bytes - - # --> Wait until (R_STATUS & (M_BUSY | M_PCM_INIT)) - # M_BUSY status will be checked after fifo selection - BRI::gen "0 WD 0F 80"; - # set PCM !master mode - BRI::gen "0 WD 14 08"; # R_PCM_MD0 = PCM slave mode, F0IO duration is 2 HFC_PCLK's - - # (C4IO, F0IO are inputs) - - # set pll adjust - # WD 14 90 # R_PCM_MD0: Index value to select - # the register at address 15 - # WD 15 2C # R_PCM_MD1: V_PLL_ADJ (DPLL adjust speed), C4IO is 16.384MHz(128 time slots) - # in the last slot of PCM frame - BRI::gen "0 WS 14 98 20"; # R_PCM_MD1: V_PLL_ADJ - # (DPLL adjust speed) in the - # last slot of PCM frame - - BRI::gen "0 WD 4C 03"; # GPIOGPIO function (not PWM) on GPIO0 and GPIO1 pins - BRI::gen "0 WD 4A 03"; # Output enable for GPIO0 and GPIO1 pins -} - -my %port_type = ( - 6 => { 'BRI_NT' => 0 }, - 7 => { 'BRI_NT' => 1 } - ); - -# zap_xhfc_su.c:175 -sub main() { - #logit "main(): XPD_TYPE=$ENV{XPD_TYPE}"; - - $ENV{XPD_TYPE} || die "Missing XPD_TYPE environment variable\n"; - my $type = $port_type{$ENV{XPD_TYPE}}; - die "Bad XPD_TYPE=$ENV{XPD_TYPE}\n" unless $type; - die "Missing XPD_SUBUNIT information\n" unless defined($ENV{XPD_SUBUNIT}); - - # We must first turn off packet reception. - # - # Otherwise we mess with registers while the FPGA firmware tries to - # send us packets. - BRI::gen "0 Wm"; - - # Common initialization - if(($ENV{XPD_SUBUNIT} % 4) eq '0') { - # Turn off multi-byte packet reception before initialization started - my $chipnum = ($ENV{XPD_SUBUNIT} & 0x04) << 3; # Max 2 XHFC chips - for my $subunit (0 .. 3) { # 4 subunits per XHFC chip - my $addr = $chipnum | ($subunit << 3); - my $str = sprintf("0A 00 0F %02X C0 00 00 00 00 00\n", $addr); - open(CMD, ">$cmd") || die "Failed to open '$cmd': $!\n"; - print CMD $str; - close CMD; - } - init_xhfc; # zap_xhfc_su.c:1173 in setup_instance() - } - - # Port initialization - my $p = BRI::Port->new( - 'PORT_NUM' => $ENV{XPD_SUBUNIT}, - 'BRI_NT' => $type->{BRI_NT}, - 'PORT_MODE_UP' => 0, - 'PORT_MODE_EXCH' => 0 - ); - # zap_XHfc_su.c:1186 in setup_instance() - $p->init_su; - - $p->zthfc_startup; - - if(($ENV{XPD_SUBUNIT} % 4) eq 3) { - # Turn on multi-byte packet reception when ports initialization finished - my $chipnum = ($ENV{XPD_SUBUNIT} & 0x04) << 3; # Max 2 XHFC chips - for my $subunit (0 .. 3) { # 4 subunits per XHFC chip - my $addr = $chipnum | ($subunit << 3); - my $str = sprintf("0A 00 0F %02X 80 00 00 00 00 00\n", $addr); - open(CMD, ">$cmd") || die "Failed to open '$cmd': $!\n"; - print CMD $str; - close CMD; - } - } -} - -main; - -logit "Ending '$0'"; - -close REG; -close STDERR; -exit 0; diff --git a/xpp/init_card_7_29 b/xpp/init_card_7_29 deleted file mode 100755 index 255d50e..0000000 --- a/xpp/init_card_7_29 +++ /dev/null @@ -1,434 +0,0 @@ -#! /usr/bin/perl -w -use strict; - -# -# $Id$ -# - -# -# Written by Oron Peled -# Copyright (C) 2006, Xorcom -# -# All rights reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# See the file LICENSE in the top level of this tarball. -# - -# This script is run from the xpp kernel module upon detection -# of a new XPD. -# -# Expects the following environment variables to be set: -# XPD_BUS - bus name -# XPD_NAME - xpd name -# XPD_UNIT - xpd unit number -# XPD_SUBUNIT - xpd subunit number -# XPD_TYPE - xpd type number (from protocol reply): -# 3 - FXS -# 4 - FXO -# 6 - BRI_TE -# 7 - BRI_NT -# XPD_REVISION - xpd revision number -# -# Output data format: -# - An optional comment start with ';' or '#' until the end of line -# - Optional Blank lines are ignored -# - Fields are whitespace separated (spaces or tabs) -# -# The fields are (in command line order): -# 1. CHIP select in decimal (ignored, taken from 3 LSB's of subunit number) -# 2. Command word: -# - RD Read Direct register. -# - RS Read Sub-register. -# - WD Write Direct register. -# - WS Write Sub-register. -# 3. Register number in hexadecimal. -# 4. Subregister number in hexadecimal. (for RS and WS commands). -# 5. Data byte in hexadecimal. (for WD and WS commands only). -# - -package main; -use File::Basename; - -my $program = basename("$0"); -my $init_dir = dirname("$0"); -my $unit_id; - -sub logit { - print STDERR "$unit_id: @_\n"; -} - -# Arrange for error logging -if (-t STDERR) { - $unit_id = 'Interactive'; - logit "Interactive startup\n"; -} else { - $unit_id = "$ENV{XPD_BUS}/$ENV{XPD_NAME}"; - open (STDERR, "| logger -t $program -p kern.info") || die; - logit "Non Interactive startup\n"; -} - -package BRI; - -sub gen { - my $fmt = shift; - $| = 1; - printf "$fmt\n", @_; -} - -package BRI::Port; - -sub new { - my $pack = shift; - my $port = { @_ }; - bless $port, $pack; -} - -# zap_xhfc_su.c:995 -sub init_su { - my $port = shift; - my $portnum = $port->{PORT_NUM}; - my $port_mode_up = $port->{PORT_MODE_UP}; - my $port_mode_exch = $port->{PORT_MODE_EXCH}; - my $bri_nt = $port->{BRI_NT}; - #logit "init_su(portnum=$portnum, port_mode_up=$port_mode_up, bri_nt=$bri_nt)"; - - # Setting PLL - # R_PLL_CTRL = 0 (V_PLL_M = 0, Reset PLL, Disable PLL_ - # R_CLK_CFG = 05 (PLL clock as system clock, output it to CLK_OUT pin) - # R_PLL_P = 1 - # R_PLL_N = 6 - # R_PLL_S = 1 - # R_PLL_CTRL = 1 (V_PLL_M) - - BRI::gen "#--------------------------- init_su($portnum, $bri_nt, $port_mode_up, $port_mode_exch)"; - BRI::gen "0 WD 02 04"; - BRI::gen "0 WD 50 00"; # disable PLL - BRI::gen "0 WD 51 02"; - BRI::gen "0 WD 52 06"; - BRI::gen "0 WD 53 04"; - BRI::gen "0 WD 50 01"; # Enable PLL - BRI::gen "0 WD 02 05"; # Enable PLL - - su_sel($portnum); # select port - if ("$port_mode_up" == 1) { - $port->{CTRL3} = 0x01; # A_ST_CTRL3: V_ST_SEL = 1 - $port->{CTRL0} = 0x10; # A_SU_CTRL0: V_ST_SQ_EN = 1 - BRI::gen "0 WD 34 0F"; # A_MS_TX: - # (multiframe/superframe transmit register) - } else { - $port->{CTRL3} = 0x00; # A_ST_CTRL3: V_ST_SEL = 0 - $port->{CTRL0} = 0x00; # A_SU_CTRL0: V_ST_SQ_EN = 0 - } - if ("$bri_nt" == 1) { - $port->{CTRL0} |= 0x04; # V_SU_MD - } - # ((V_SU_EXCH)?0x80:00) (change polarity) - if($port_mode_exch) { - $port->{CTRL2} = 0x80; - } else { - $port->{CTRL2} = 0x00; - } - BRI::gen "0 WD 35 %02X", $port->{CTRL3}; # A_ST_CTRL3 - BRI::gen "0 WD 31 %02X", $port->{CTRL0}; # A_SU_CTRL0 - BRI::gen "0 WD 35 F8"; # A_ST_CTRL3 = set end of pulse control to 0xF8 - BRI::gen "0 WD 32 08"; # A_SU_CTRL1 = Ignore E-channel data - BRI::gen "0 WD 33 %02X", $port->{CTRL2}; # A_SU_CTRL2 - - # zap_xhfc_su.c:1030 in init_su() - # A_SU_CLK_DLY - my $clk_dly; - if ("$bri_nt" == 1) { - $clk_dly = 0x6C; - } else { - $clk_dly = 0x0E; - } - #logit "clk_dly=$clk_dly"; - BRI::gen "0 WD 37 %02X", "$clk_dly"; -} - -sub su_sel { - if (@_ != 1 ) { - main::logit "ERROR: su_sel() called with " . scalar(@_) . " parameters"; - exit 1; - } - my $portnum = shift; - BRI::gen "0 WD 16 %02X", $portnum; # R_SU_SEL -} - -# zap_xhfc_su.c:281 -sub xhfc_selfifo { - if (@_ != 1 ) { - main::logit "ERROR: xhfc_selfifo() called with " . scalar(@_) . " parameters"; - exit 1; - } - my $fifonum = shift; - #logit "xhfc_selfifo($fifonum)"; - BRI::gen "0 WD 0F %02X", $fifonum; - # --> WAIT UNTIL (R_STATUS & M_BUSY) == 0 -} - -# zap_xhfc_su.c:295 -sub xhfc_resetfifo() { - #logit "xhfc_resetfifo()"; - # A_INC_RES_FIFO = M_RES_FIFO | M_RES_FIFO_ERR - BRI::gen "0 WD 0E 0A"; - # --> WAIT UNTIL (R_STATUS & M_BUSY) == 0 -} - -# zap_xhfc_su.c:1040 -# Initialize fifo (called for each portnum, channel, direction) -sub setup_fifo { - my $port = shift; - my $chan = shift; - my $direction = shift; - my $conhdlc = shift; - my $subcfg = shift; - my $fifoctrl = shift; - - my $portnum = $port->{PORT_NUM}; - my $port_mode_up = $port->{PORT_MODE_UP}; - my $port_mode_exch = $port->{PORT_MODE_EXCH}; - my $bri_nt = $port->{BRI_NT}; - - BRI::gen "#--------------------------- setup_fifo($portnum, $chan, $direction)"; - # my $fifonum = 0x80 | ($portnum << 3) | ($chan << 1) | ($direction); # # MSB first - my $fifonum = ($portnum << 3) | ($chan << 1) | ($direction); # # MSB first - my $r_slot = ($portnum << 3) | ($chan << 1) | ($direction); - - # channel order workaround, swap odd and even portnums in $r_slot for PCM (chan 0, 1) only - if ("$chan" == 0 || "$chan" == 1) { - $r_slot = $r_slot ^ 0x08; - } - - my $short_portnum = $portnum & 0x03; - my $a_sl_cfg = (0x80 | ($short_portnum << 3) | ($chan << 1) | ($direction)); # receive data from STIO2, transmit to STIO1 - - #logit "setup_fifo($fifonum)"; - xhfc_selfifo $fifonum; - # A_CON_HDLC: transparent mode selection - BRI::gen "0 WD FA %02X", $conhdlc; - # A_SUBCH_CFG: subchnl params - BRI::gen "0 WD FB %02X", $subcfg; - # A_FIFO_CTRL: FIFO Control Register - BRI::gen "0 WD FF %02X", $fifoctrl; - xhfc_resetfifo; - xhfc_selfifo $fifonum; # wait for busy is builtin in this command - BRI::gen "0 WD 10 %02X", $r_slot; # R_SLOT - BRI::gen "0 WD D0 %02X", $a_sl_cfg; # A_SL_CFG - - #system("/bin/echo \"----=====NT\" \"short_portnum=\"$short_portnum \"portnum=\" $portnum \"chan=\" $chan\"======----\n\" >>/root/xortel/test_init"); -} - -# zap_xhfc_su.c:1071 -sub setup_su { - my $port = shift; - my $bchan = shift; - my $portnum = $port->{PORT_NUM}; - my $port_mode_exch = $port->{PORT_MODE_EXCH}; - my $bri_nt = $port->{BRI_NT}; - - BRI::gen "#--------------------------- setup_su($portnum, $bchan)"; - #logit "setup_su(portnum=$portnum, bchan=$bchan, port_mode_exch=$port_mode_exch, bri_nt=$bri_nt)"; - $port->{CTRL0} |= (1 << $bchan) | $bri_nt; - $port->{CTRL2} |= ($port_mode_exch << 7) | (1 << $bchan); - su_sel($portnum); # Select port - BRI::gen "0 WD 31 %02X", $port->{CTRL0}; # A_SU_CTRL0: V_B1_TX_EN | V_SU_MD | (NT/TE) - BRI::gen "0 WD 33 %02X", $port->{CTRL2}; # A_SU_CTRL2: V_B1_RX_EN -} - -sub xhfc_ph_command { - my $port = shift; - my $cmd = shift; - my $portnum = $port->{PORT_NUM}; - #logit "xhfc_ph_command(portnum=$portnum)"; - if ("$cmd" eq "HFC_L1_ACTIVATE_TE") { - su_sel($portnum); # Select port - BRI::gen "0 WD 30 60"; # A_SU_WR_STA = (M_SU_ACT & 0x03) - # (set activation) - } elsif ("$cmd" eq "HFC_L1_FORCE_DEACTIVATE_TE") { - su_sel($portnum); # Select port - BRI::gen "0 WD 30 40"; # A_SU_WR_STA = (M_SU_ACT & 0x02) - # (set deactivation) - } elsif ("$cmd" eq "HFC_L1_ACTIVATE_NT") { - su_sel($portnum); # Select port - BRI::gen "0 WD 30 E0"; # A_SU_WR_STA = (M_SU_ACT & 0x03) | 0x80 - # (set activation + NT) - } elsif ("$cmd" eq "HFC_L1_DEACTIVATE_NT") { - su_sel($portnum); # Select port - BRI::gen "0 WD 30 40"; # A_SU_WR_STA = (M_SU_ACT & 0x02) - # (set deactivation) - } -} - - -sub zthfc_startup { - my $port = shift; - my $portnum = $port->{PORT_NUM}; - my $port_mode_exch = $port->{PORT_MODE_EXCH}; - my $bri_nt = $port->{BRI_NT}; - #logit "zthfc_startup(portnum=$portnum, port_mode_exch=$port_mode_exch, bri_nt=$bri_nt)"; - - # PCM <-> ST/Up Configuration - foreach my $chan ( 0, 1 ) { - $port->setup_fifo($chan, 0, 0xFE, 0, 0);# Transparent mode, FIFO EN, ST->PCM - $port->setup_fifo($chan, 1, 0xFE, 0, 0);# Transparent mode, FIFO EN, ST->PCM - $port->setup_su($chan); # zap_xhfc_su.c:194 - } - - # Zaptel chan 2 used as HDLC D-Channel - $port->setup_fifo(2, 0, 0x05, 2, 0); # D-TX: zap_xhfc_su.c:205 - $port->setup_fifo(2, 1, 0x05, 2, 0); # D-RX: zap_xhfc_su.c:206 - # E-chan, Echo channel is ignored - - - # enable this port's state machine - su_sel($portnum); # Select port - # A_SU_WR_STA: reset port state machine - BRI::gen "0 WD 30 00"; - if ("$bri_nt" == 0) { - $port->xhfc_ph_command("HFC_L1_ACTIVATE_TE"); - } else { - $port->xhfc_ph_command("HFC_L1_ACTIVATE_NT"); - } -} - - -package main; -use Getopt::Std; - -my %opts; -getopts('o:', \%opts); - -$ENV{XPP_BASE} = '/proc/xpp'; -my $cmd = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/command"; -my $output; -if ($opts{o}) { - $output = $opts{o}; -} else { - $ENV{XPD_BUS} || die "Missing XPD_BUS environment variable\n"; - $ENV{XPD_NAME} || die "Missing XPD_NAME environment variable\n"; - $ENV{XPD_TYPE} || die "Missing XPD_TYPE environment variable\n"; - $ENV{XPD_REVISION} || die "Missing XPD_REVISION environment variable\n"; - $output = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/$ENV{XPD_NAME}/slics"; -} - -open(REG, ">$output") || die "Failed to open '$output': $!\n"; -select REG; - -logit "Starting '$0'"; - -#------------------------------------------- Instance detection - -# zap_xhfc_su.c:895 -sub init_xhfc() { - #logit "init_xhfc()"; - BRI::gen "#--------------------------- init_xhfc"; - BRI::gen "0 WD 0D 00"; # r_FIFO_MD: 16 fifos, - # 64 bytes for TX and RX each (FIFO mode config) - - # software reset to enable R_FIFO_MD setting - BRI::gen "0 WD 00 08"; # R_CIRM = M_SRES (soft reset) - # --> WAIT 5u - BRI::gen "0 WD 00 00"; # R_CIRM = 0 (zero it to deactivate reset) - - # amplitude - BRI::gen "0 WD 46 80"; # R_PWM_MD: (PWM output mode register) - # PWM push to zero only - BRI::gen "0 WD 39 18"; # R_PWM1: (modulator register for PWM1) - # set duty cycle - - BRI::gen "0 WD 0C 11"; # R_FIFO_THRES: (FIFO fill lvl control register) - # RX/TX threshold = 16 bytes - - # --> Wait until (R_STATUS & (M_BUSY | M_PCM_INIT)) - # M_BUSY status will be checked after fifo selection - BRI::gen "0 WD 0F 80"; - # set PCM !master mode - BRI::gen "0 WD 14 08"; # R_PCM_MD0 = PCM slave mode, F0IO duration is 2 HFC_PCLK's - - # (C4IO, F0IO are inputs) - - # set pll adjust - # WD 14 90 # R_PCM_MD0: Index value to select - # the register at address 15 - # WD 15 2C # R_PCM_MD1: V_PLL_ADJ (DPLL adjust speed), C4IO is 16.384MHz(128 time slots) - # in the last slot of PCM frame - BRI::gen "0 WS 14 98 20"; # R_PCM_MD1: V_PLL_ADJ - # (DPLL adjust speed) in the - # last slot of PCM frame - - BRI::gen "0 WD 4C 03"; # GPIOGPIO function (not PWM) on GPIO0 and GPIO1 pins - BRI::gen "0 WD 4A 03"; # Output enable for GPIO0 and GPIO1 pins -} - -my %port_type = ( - 6 => { 'BRI_NT' => 0 }, - 7 => { 'BRI_NT' => 1 } - ); - -# zap_xhfc_su.c:175 -sub main() { - #logit "main(): XPD_TYPE=$ENV{XPD_TYPE}"; - - $ENV{XPD_TYPE} || die "Missing XPD_TYPE environment variable\n"; - my $type = $port_type{$ENV{XPD_TYPE}}; - die "Bad XPD_TYPE=$ENV{XPD_TYPE}\n" unless $type; - die "Missing XPD_SUBUNIT information\n" unless defined($ENV{XPD_SUBUNIT}); - - # We must first turn off packet reception. - # - # Otherwise we mess with registers while the FPGA firmware tries to - # send us packets. - BRI::gen "0 Wm"; - - # Common initialization - if(($ENV{XPD_SUBUNIT} % 4) eq '0') { - # Turn off multi-byte packet reception before initialization started - my $chipnum = ($ENV{XPD_SUBUNIT} & 0x04) << 3; # Max 2 XHFC chips - for my $subunit (0 .. 3) { # 4 subunits per XHFC chip - my $addr = $chipnum | ($subunit << 3); - my $str = sprintf("0A 00 0F %02X C0 00 00 00 00 00\n", $addr); - open(CMD, ">$cmd") || die "Failed to open '$cmd': $!\n"; - print CMD $str; - close CMD; - } - init_xhfc; # zap_xhfc_su.c:1173 in setup_instance() - } - - # Port initialization - my $p = BRI::Port->new( - 'PORT_NUM' => $ENV{XPD_SUBUNIT}, - 'BRI_NT' => $type->{BRI_NT}, - 'PORT_MODE_UP' => 0, - 'PORT_MODE_EXCH' => 0 - ); - # zap_XHfc_su.c:1186 in setup_instance() - $p->init_su; - - $p->zthfc_startup; - - if(($ENV{XPD_SUBUNIT} % 4) eq 3) { - # Turn on multi-byte packet reception when ports initialization finished - my $chipnum = ($ENV{XPD_SUBUNIT} & 0x04) << 3; # Max 2 XHFC chips - for my $subunit (0 .. 3) { # 4 subunits per XHFC chip - my $addr = $chipnum | ($subunit << 3); - my $str = sprintf("0A 00 0F %02X 80 00 00 00 00 00\n", $addr); - open(CMD, ">$cmd") || die "Failed to open '$cmd': $!\n"; - print CMD $str; - close CMD; - } - } -} - -main; - -logit "Ending '$0'"; - -close REG; -close STDERR; -exit 0; diff --git a/xpp/init_card_9_29 b/xpp/init_card_9_29 deleted file mode 100755 index dd3b0a5..0000000 --- a/xpp/init_card_9_29 +++ /dev/null @@ -1,358 +0,0 @@ -#! /usr/bin/perl -w -use strict; - -# -# $Id$ -# - -# -# Written by Oron Peled -# Copyright (C) 2007, Xorcom -# -# All rights reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# See the file LICENSE in the top level of this tarball. -# - -# This script is run from the xpp kernel module upon detection -# of a new XPD. -# -# Expects the following environment variables to be set: -# XPD_BUS - bus name -# XBUS_CONNECTOR - bus connector id string -# XPD_NAME - xpd name -# XPD_UNIT - xpd unit number -# XPD_TYPE - xpd type number (from protocol reply): -# 3 - FXS -# 4 - FXO -# 6 - BRI_TE -# 7 - BRI_NT -# 8 - PRI_TE -# 9 - PRI_NT -# XPD_REVISION - xpd revision number -# -# Output data format: -# - An optional comment start with ';' or '#' until the end of line -# - Optional Blank lines are ignored -# - Fields are whitespace separated (spaces or tabs) -# -# The fields are (in command line order): -# 1. CHIP select in decimal (ignored, taken from 3 LSB's of subunit number) -# 2. Command word: -# - RD Read Direct register. -# - WD Write Direct register. -# 3. Register number in hexadecimal. -# 4. Subregister number in hexadecimal. (for RS and WS commands). -# 5. Data byte in hexadecimal. (for WD and WS commands only). -# - -package main; -use File::Basename; - -my $program = basename("$0"); -my $init_dir = dirname("$0"); -my $unit_id; - -sub logit { - print STDERR "$unit_id: @_\n"; -} - -# Arrange for error logging -if (-t STDERR) { - $unit_id = 'Interactive'; - logit "Interactive startup\n"; -} else { - $unit_id = "$ENV{XPD_BUS}/$ENV{XPD_NAME}"; - open (STDERR, "| logger -t $program -p kern.info") || die; - logit "Non Interactive startup\n"; -} - -package PRI; - -sub gen { - my $fmt = shift; - $| = 1; - printf "$fmt\n", @_; -} - -package PRI::Port; - -sub new { - my $pack = shift; - my $port = { @_ }; - bless $port, $pack; -} - -package main; -use Getopt::Std; -BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/zconf"); } -use Zaptel::Config::Defaults; - -my %opts; -getopts('o:', \%opts); - -$ENV{XPP_BASE} = '/proc/xpp'; -#my $cmd = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/command"; -my $output; -if ($opts{o}) { - $output = $opts{o}; -} else { - $ENV{XPD_BUS} || die "Missing XPD_BUS environment variable\n"; - $ENV{XPD_NAME} || die "Missing XPD_NAME environment variable\n"; - $ENV{XPD_TYPE} || die "Missing XPD_TYPE environment variable\n"; - $ENV{XPD_REVISION} || die "Missing XPD_REVISION environment variable\n"; - $ENV{XBUS_CONNECTOR} || die "Missing XBUS_CONNECTOR environment variable\n"; - $output = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/$ENV{XPD_NAME}/slics"; -} - -sub write_pri_info { - my $pri_type = shift || die "Missing pri_type parameter"; - my $pri_proto = shift || die "Missing pri_proto parameter"; - my $info = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/$ENV{XPD_NAME}/pri_info"; - - open(INFO, ">$info") || die "Failed to open '$info': $!\n"; - print INFO "$pri_type $pri_proto\n" || die "Failed writing to '$info': $!\n"; - close INFO || die "Failed during close of '$info': $!\n"; -} - -my @PRI_SETUP; - -sub set_defaults { - my @pri_specs; - my $match; - my $setup; - # For lab tests - my $labfile = "${0}.setup"; - - # Source default files - $ENV{ZAPTEL_DEFAULTS} = "$labfile" if -r "$labfile"; - my $setup_var = 'XPP_PRI_SETUP'; - my $setup_string; - my ($default_file, %source_defaults) = - Zaptel::Config::Defaults::source_vars($setup_var); - $setup_string = $source_defaults{$setup_var}; - $setup_string =~ s/^\s+//; # trim - $setup_string =~ s/\s+$//; # trim - $setup_string =~ s/\s+/\n/g; # cannonical spaces - logit "From $default_file: $setup_var=\n$setup_string\n"; - @pri_specs = split(/\s+/, $setup_string); - push(@pri_specs, 'NUM/*=TE,E1'); # Fall back default (last) - logit "pri_specs: @pri_specs"; -SPEC: - for(my $i = 0; $i < @pri_specs; $i++) { - my $spec = $pri_specs[$i]; - ($match, $setup) = split(/=/, $spec); - next unless defined $match and defined $setup; - # Convert "globs" to regex - $match =~ s/\*/.*/g; - $match =~ s/\?/./g; - #logit "match: $match"; - my @patlist = ( - "CONNECTOR/$ENV{XBUS_CONNECTOR}/$ENV{XPD_NAME}", - "NUM/$ENV{XPD_BUS}/$ENV{XPD_NAME}" - ); - foreach my $pattern (@patlist) { - #logit "testmatch: $pattern =~ $match"; - if($pattern =~ $match) { - logit "MATCH($i): '$match' setup=$setup"; - last SPEC; - } - } - } - die "No setup matching $ENV{XPD_BUS}/$ENV{XPD_NAME}\n" unless defined $setup; - @PRI_SETUP = split(/,/, $setup); - die "Bad setup string '$setup'\n" unless @PRI_SETUP; -} - -set_defaults; - -open(REG, ">$output") || die "Failed to open '$output': $!\n"; -select REG; - -logit "Starting '$0'"; - -PRI::gen "#--------------------------- start"; - -# only one of the following loopbacks can be activated in the same time -my $LIM1_RL = 0 << 1; # RL (Remote Loopback) -my $lim1 = 0xB0 | $LIM1_RL; - -my $subunits_num = 4; -my $subunit = $ENV{XPD_SUBUNIT}; - -if($subunit eq 0) { - # Tuning of clocking unit to the 16.384 MHz reference frequence - # by setting Global Clock Mode registers (GCM[1:8]), same for E1 and T1/J1 - PRI::gen "0 WD 92 00"; # GCM1 - PRI::gen "0 WD 93 18"; # GCM2 - PRI::gen "0 WD 94 FB"; # GCM3 - PRI::gen "0 WD 95 0B"; # GCM4 - PRI::gen "0 WD 96 01"; # GCM5 - PRI::gen "0 WD 97 0B"; # GCM6 - PRI::gen "0 WD 98 DB"; # GCM7 - PRI::gen "0 WD 99 DF"; # GCM8 - - for(my $i = 0; $i < $subunits_num; $i++) { - PRI::gen "0 WS 26 $i BD"; # XPM0: Pulse Shape Programming for R1=18Ohms (0x54) - PRI::gen "0 WS 27 $i 03"; # XPM1: ...3V Pulse Level at the line (0x02) - PRI::gen "0 WS 28 $i 00"; # XPM2: ~XLT (transmit line is not in the high impedance state) - - # if (unchannelized) - #PRI::gen "0 WS 1F $i 22"; # LOOP (Channel Looback): - # ECLB (Enable Channel Loop-Back) - # CLA (Channel Address) - PRI::gen "0 WS 2B $i EF"; # IDL (Idle): - # If channel loopback is enabled than transmit this code on the outgoing - PRI::gen "0 WS 1F $i 00"; # LOOP (Channel Looback): - #if($i eq 0){ - # PRI::gen "0 WS 1F $i 00"; # LOOP (Channel Looback): - # # channels (XL1/XL2) - #}else { - # PRI::gen "0 WS 1F $i 20"; # LOOP (Channel Looback): - #} - - PRI::gen "0 WS 37 $i %02X", $lim1; - # LIM1: ~RL (Remote Loop bit 0x02), - # ~DRS (Dual Rail Select, latch receive data while trasmit), - # RIL1, RIL0 (Receive Input Treshold 0.62 V), - # CLOS (Clear data in case of LOS) - PRI::gen "0 WS 3A $i 20"; # LIM2: SLT1, SLT0 = 01 - # (Receiver Slicer Threshold, the receive slicer - # generates a mark (digital one) if the voltage at - # RL1/2 exceeds 50% of the peak amplitude, - # default, recommended in E1 mode). - - PRI::gen "0 WS 38 $i 0A"; # PCD: (Pulse Count Detection, LOS Detection after 176 consecutive 0s) - PRI::gen "0 WS 39 $i 15"; # PCR: (Pulse Count Recovery, LOS Recovery after 22 ones in PCD interval) - - # Configure system interface - PRI::gen "0 WS 3E $i C2"; # SIC1: SSC1 (System clock ) is 8.192 Mhz, - # SSD1 (System Data rate) is 8.192 Mbit/s, - # ~BIM (Byte interleaved mode), - # XBS (Transmit Buffer Size) is 2 frames - PRI::gen "0 WS 40 $i 04"; # SIC3: Edges for capture, Synchronous Pulse Receive @Rising Edge - PRI::gen "0 WS 41 $i 04"; # CMR4: RCLK is 8.192 MHz - PRI::gen "0 WS 43 $i 04"; # CMR5: TCLK is 8.192 MHz - PRI::gen "0 WS 44 $i 34"; # CMR6: Receive reference clock generated by channel 1, - # RCLK is at 8.192 Mhz dejittered, Clock recovered from the line - # TCLK is at 8.192 MHz is de-jittered by DCO-R to drive a6.176 MHz - # clock on RCLK.*/ - - PRI::gen "0 WS 20 $i 9F"; # XSW: XSIS (Spare Bit For International Use fixed to 1), - # XY0, XY1, XY2, XY3, XY4 (Y0, Y1 and Y3-Bits fixed to 1) - - # cas = 0x1c; - # if (!(lineconfig & ZT_CONFIG_CCS)) - # cas |= 0x40; - - PRI::gen "0 WS 22 $i 00"; # XC0: (Transmit Counter Offset = 497/T=2) - PRI::gen "0 WS 23 $i 04"; # XC1: - - PRI::gen "0 WS 24 $i 00"; # RC0: (Receive Counter Offset = 497/T=2) - PRI::gen "0 WS 25 $i 05"; # RC1: - - my $sic2 = sprintf("%x", 0x00 | ($i << 1)); - - PRI::gen "0 WS 3F $i $sic2"; # SIC2: No FFS, no center receive elastic buffer, data active at phase ($sic >> 1) - - # enable the following interrupt sources - PRI::gen "0 WS 16 $i 00"; # IMR2 (Interrupt Mask Register2): Enable ALL - - PRI::gen "0 WS 17 $i 3F"; # IMR3 ~ES, ~SEC (Enable ES and SEC interrupts) - PRI::gen "0 WS 18 $i 00"; # IMR4: Enable ALL - - PRI::gen "0 WS 08 $i 04"; # IPC: SYNC is 8 Khz - - PRI::gen "0 WS 02 $i 51"; # CMDR (Command Register): RRES, XRES, SRES (Receiver/Transmitter reset) - PRI::gen "0 WS 02 $i 00"; # CMDR - - - # Configure interrupts - PRI::gen "0 WS 46 $i 40"; # GCR: Interrupt on Activation/Deactivation of AIX, LOS - - PRI::gen "0 WS 45 $i 00"; # CMR2: External sources for SYPR, SCLKR, SYPX, SCLKX for TX and RX. - #PRI::gen "0 WS 22 $i 00"; # XC0: Normal operation of Sa-bits - #PRI::gen "0 WS 23 $i 04"; # XC1: X=4 => T=4-X=0 offset - #PRI::gen "0 WS 24 $i 00"; # RC0: 0 offset - #PRI::gen "0 WS 25 $i 00"; # RC1: Remaining part of RC0 - - # Configure ports - PRI::gen "0 WD 85 80"; # GPC1 (Global Port Configuration 1): - #PRI::gen "0 WD 85 00"; # GPC1 (Global Port Configuration 1): - # SMM (System Interface Multiplex Mode) - PRI::gen "0 WS 80 $i 00"; # PC1: SYPR/SYPX provided to RPA/XPA inputs - - PRI::gen "0 WS 84 $i 31"; # PC5: XMFS active low, SCLKR is input, RCLK is output (unused) - PRI::gen "0 WS 86 $i 03"; # PC6: CLK1 is Tx Clock output, CLK2 is 8.192 Mhz from DCO-R - PRI::gen "0 WS 3B $i 00"; # Clear LCR1 - Loop Code Register 1 - - # printk("TE110P: Successfully initialized serial bus for card\n"); - - # Initialize PCM and SIG regs - PRI::gen "0 WS A0 $i 00"; # TSEO (Time Slot Even/Odd Select) - PRI::gen "0 WS A1 $i FF"; # TSBS (Time Slot Bit Select)- only selected bits are used for HDLC channel 1 - # in selected time slots - PRI::gen "0 WS 03 $i 89"; # Mode Register: - # MDS (Mode Select) = 100 (No address comparison) - # HRAC (Receiver Active - HDLC channel 1) - # RFT2 (HDLC Receive FIFO is 64 byte deep) - PRI::gen "0 WS 09 $i 18"; # CCR1 (Common Configuration Register1) - # EITS (Enable Internal Time Slot 0 to 31 Signalling) - # ITF (Interframe Time Fill) - PRI::gen "0 WS 0A $i 04"; # CCR2 (Common Configuration Register2) - # RCRC (enable CRC - HDLC channel 1enable CRC - HDLC channel 1) - PRI::gen "0 WS 0C $i 00"; # RTR1 (Receive Time Slot register 1) - PRI::gen "0 WS 0D $i 00"; # RTR2 (Receive Time Slot register 2) - PRI::gen "0 WS 0E $i 00"; # RTR3 (Receive Time Slot register 3), TS16 (Enable time slot 16) - PRI::gen "0 WS 0F $i 00"; # RTR4 (Receive Time Slot register 4) - - PRI::gen "0 WS 10 $i 00"; # TTR1 (Transmit Time Slot register 1) - PRI::gen "0 WS 11 $i 00"; # TTR2 (Transmit Time Slot register 2) - PRI::gen "0 WS 12 $i 00"; # TTR3 (Transmit Time Slot register 3), TS16 (Enable time slot 16) - PRI::gen "0 WS 13 $i 00"; # TTR4 (Transmit Time Slot register 4) - - # configure the best performance of the Bipolar Violation detection for all four channels - PRI::gen "0 WS BD $i 00"; # BFR (Bugfix Register): ~BVP (Bipolar Violations), - # use Improved Bipolar Violation Detection instead - } - PRI::gen "0 WD BB FF"; # REGFP - PRI::gen "0 WD BC AC"; # REGFD - PRI::gen "0 WD BB 2B"; # REGFP - PRI::gen "0 WD BC 00"; # REGFD - PRI::gen "0 WD BB AB"; # REGFP - PRI::gen "0 WD BC 2A"; # REGFD - PRI::gen "0 WD BB FF"; # REGFP - PRI::gen "0 WD BC AA"; # REGFD - PRI::gen "0 WD BB 29"; # REGFP - PRI::gen "0 WD BC FF"; # REGFD - PRI::gen "0 WD BB A9"; # REGFP - PRI::gen "0 WD BC 28"; # REGFD - PRI::gen "0 WD BB 00"; # REGFP - PRI::gen "0 WD BC A8"; # REGFD - PRI::gen "0 WD BB 27"; # REGFP - PRI::gen "0 WD BC FF"; # REGFD - PRI::gen "0 WD BB A7"; # REGFP - PRI::gen "0 WD BC 00"; # REGFD - -# PRI::gen "0 WS 80 00 00"; # PC1 (Port configuration 1): RPB_1.SYPR , XPB_1.SYPX - PRI::gen "0 WS 81 00 0B"; # PC2 (Port configuration 2): RPB_1.GPOH (ResetID ), XPB_1.GPOL (MUX_SEL0) - PRI::gen "0 WS 82 00 9B"; # PC3 (Port configuration 3): RPC_1.GPI (nConfig0), XPC_1.GPOL (MUX_SEL1) - PRI::gen "0 WS 83 00 9B"; # PC4 (Port configuration 4): RPD_1.GPI (nConfig1), XPD_1.GPOL (MUX_SEL2) -} - - -#------------------------------------------- Instance detection - -logit "Ending '$0'"; - -close REG; - -write_pri_info @PRI_SETUP; - -close STDERR; -exit 0; diff --git a/xpp/param_doc b/xpp/param_doc deleted file mode 100755 index 5848728..0000000 --- a/xpp/param_doc +++ /dev/null @@ -1,40 +0,0 @@ -#! /usr/bin/perl -w -use strict; -# -# Extract parameter documentation from *.ko files. -# Assumes that parameter description include the default -# value in the format we use in our DEF_PARM() macro -# - -@ARGV || die "Usage: $0 module.ko....\n"; - -my $modinfo = '/sbin/modinfo'; -my @mod_params; - -foreach my $file (glob "@ARGV") { - undef @mod_params; - print "$file:\n"; - open(F, "$modinfo '$file' |") || die; - while() { - chomp; - next unless s/^parm:\s*//; - my ($name, $description) = split(/:/, $_, 2); - # Extract type - $description =~ s/\s*\(([^)]+)\)$//; - my $type = $1; - # Extract default value - $description =~ s/\s*\[default\s+([^]]+)\]$//; - my $default = $1; - push(@mod_params, { - NAME => $name, - TYPE => $type, - DEFVAL => $default, - DESC => $description, - }); - } - # Print sorted list - foreach my $p (sort { $a->{NAME} cmp $b->{NAME} } @mod_params) { - printf "\t%-8s %-22s = %-20s %s\n", $p->{TYPE}, $p->{NAME}, $p->{DEFVAL}, $p->{DESC}; - } - close F || die; -} diff --git a/xpp/parport_debug.c b/xpp/parport_debug.c deleted file mode 100644 index 93049ef..0000000 --- a/xpp/parport_debug.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2007, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -# warning "This module is tested only with 2.6 kernels" -#endif - -#include -#include -#include -#include "parport_debug.h" - -static struct parport *debug_sync_parport = NULL; -static int parport_toggles[8]; /* 8 bit flip-flop */ - -void flip_parport_bit(unsigned char bitnum) -{ - static unsigned char last_value; - spinlock_t lock = SPIN_LOCK_UNLOCKED; - unsigned long flags; - unsigned char mask; - unsigned char value; - - if(!debug_sync_parport) { - if(printk_ratelimit()) { - printk(KERN_NOTICE "%s: no debug parallel port\n", - THIS_MODULE->name); - } - return; - } - BUG_ON(bitnum > 7); - mask = 1 << bitnum; - spin_lock_irqsave(&lock, flags); - value = last_value & ~mask; - if(parport_toggles[bitnum] % 2) /* square wave */ - value |= mask; - last_value = value; - parport_toggles[bitnum]++; - spin_unlock_irqrestore(&lock, flags); - parport_write_data(debug_sync_parport, value); -} -EXPORT_SYMBOL(flip_parport_bit); - -static void parport_attach(struct parport *port) -{ - printk(KERN_INFO "%s: Using %s for debugging\n", THIS_MODULE->name, port->name); - if(debug_sync_parport) { - printk(KERN_ERR "%s: Using %s, ignore new attachment %s\n", - THIS_MODULE->name, debug_sync_parport->name, port->name); - return; - } - parport_get_port(port); - debug_sync_parport = port; -} - -static void parport_detach(struct parport *port) -{ - printk(KERN_INFO "%s: Releasing %s\n", THIS_MODULE->name, port->name); - if(debug_sync_parport != port) { - printk(KERN_ERR "%s: Using %s, ignore new detachment %s\n", - THIS_MODULE->name, debug_sync_parport->name, port->name); - return; - } - parport_put_port(debug_sync_parport); - debug_sync_parport = NULL; -} - -static struct parport_driver debug_parport_driver = { - .name = "parport_debug", - .attach = parport_attach, - .detach = parport_detach, -}; - -int __init parallel_dbg_init(void) -{ - int ret; - - ret = parport_register_driver(&debug_parport_driver); - return ret; -} - -void __exit parallel_dbg_cleanup(void) -{ - parport_unregister_driver(&debug_parport_driver); -} - -MODULE_DESCRIPTION("Use parallel port to debug drivers"); -MODULE_AUTHOR("Oron Peled "); -MODULE_LICENSE("GPL"); -MODULE_VERSION("$Id:"); - -module_init(parallel_dbg_init); -module_exit(parallel_dbg_cleanup); diff --git a/xpp/parport_debug.h b/xpp/parport_debug.h deleted file mode 100644 index 138af99..0000000 --- a/xpp/parport_debug.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PARPORT_DEBUG_H -#define PARPORT_DEBUG_H -/* - * Written by Oron Peled - * Copyright (C) 2007, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifdef DEBUG_SYNC_PARPORT -void flip_parport_bit(unsigned char bitnum); -#else -#define flip_parport_bit(bitnum) -#endif - -#endif /* PARPORT_DEBUG_H */ diff --git a/xpp/utils/Makefile b/xpp/utils/Makefile deleted file mode 100644 index 437b359..0000000 --- a/xpp/utils/Makefile +++ /dev/null @@ -1,136 +0,0 @@ -PEDANTIC = -ansi -pedantic -std=c99 - -RANLIB = ranlib -INSTALL = install -INSTALL_DATA = install -m 644 - -ZAPTEL_DIR ?= ../.. - --include $(ZAPTEL_DIR)/makeopts - -INSTALL_DATA = $(INSTALL) -m 644 - -# In 1.4 those are provided by autoconf through makeopts -prefix ?= /usr -datadir ?= $(prefix)/share -mandir ?= $(datadir)/man -INSTALL ?= install - -INSTALL_DATA = $(INSTALL) -m 644 - -SBINDIR = $(prefix)/sbin -DATADIR = $(datadir)/zaptel -MANDIR = $(mandir)/man8 -HOTPLUG_USB_DIR = /etc/hotplug/usb -UDEV_RULES_DIR = /etc/udev/rules.d -PERLLIBDIR := $(shell eval `perl -V:sitelib`; echo "$$sitelib") -PERL_DIRS := $(shell cd zconf; find * -name '[A-Z]*' -type d| xargs) -PERL_MODS_PAT := *.pm $(PERL_DIRS:%=%/*.pm) -PERL_MODS := $(shell cd zconf; echo $(PERL_MODS_PAT)) - -XPD_FIRMWARE = $(wildcard ../firmwares/*.hex) -XPD_INIT_DATA = $(XPD_FIRMWARE) init_fxo_modes -XPD_INIT = $(wildcard ../init_card_?_*) ../calibrate_slics xpp_fxloader - -# Variables that should be defined above, but need sane defaults: -# FIXME: Are those values really sane? -HOSTCC ?= $(CC) - -ifeq (,$(PBX_LIBUSB)) -# No PBX_LIBUSB? Maybe we compile against zaptel-1.2 -# Let's make a poor man detection of libusb -PBX_LIBUSB = $(shell if [ -r /usr/include/usb.h ]; then echo 1; else echo 0; fi) -endif - -WCTDM=$(ZAPTEL_DIR)/wctdm.c - -CFLAGS = -g -Wall $(EXTRA_CFLAGS) - -%.8: % - pod2man --section 8 $^ > $@ || $(RM) $@ -PERL_SCRIPTS = \ - zt_registration \ - xpp_sync \ - lszaptel \ - xpp_blink \ - zapconf \ - zaptel_hardware \ - # - -PERL_MANS = $(PERL_SCRIPTS:%=%.8) - -TARGETS = init_fxo_modes print_modes perlcheck -PROG_INSTALL = genzaptelconf -MAN_INSTALL = $(PROG_INSTALL:%=%.8) -ifeq (1,$(PBX_LIBUSB)) -TARGETS += libhexfile.a fpga_load test_parse -PROG_INSTALL += fpga_load -endif -ifneq (,$(PERLLIBDIR)) -PROG_INSTALL += $(PERL_SCRIPTS) -TARGETS += $(PERL_MANS) -endif - -all: $(TARGETS) - -docs: $(PERL_MANS) - -install: all - $(INSTALL) -d $(DESTDIR)$(SBINDIR) - $(INSTALL) $(PROG_INSTALL) $(DESTDIR)$(SBINDIR)/ - $(INSTALL) -d $(DESTDIR)$(DATADIR) - $(INSTALL_DATA) $(XPD_INIT_DATA) $(DESTDIR)$(DATADIR)/ - $(INSTALL) $(XPD_INIT) $(DESTDIR)$(DATADIR)/ - $(INSTALL) -d $(DESTDIR)$(MANDIR) - $(INSTALL_DATA) $(MAN_INSTALL) $(DESTDIR)$(MANDIR)/ - $(INSTALL) -d $(DESTDIR)$(HOTPLUG_USB_DIR) - $(INSTALL_DATA) xpp_fxloader.usermap $(DESTDIR)$(HOTPLUG_USB_DIR)/ - # for backward compatibility and for hotplug users: - ln -sf $(DATADIR)/xpp_fxloader $(DESTDIR)$(HOTPLUG_USB_DIR)/ - $(INSTALL) -d $(DESTDIR)$(UDEV_RULES_DIR) - $(INSTALL_DATA) xpp.rules $(DESTDIR)$(UDEV_RULES_DIR)/ -ifneq (,$(PERLLIBDIR)) - $(INSTALL) -d $(DESTDIR)$(PERLLIBDIR) - for i in $(PERL_DIRS); \ - do \ - $(INSTALL) -d "$(DESTDIR)$(PERLLIBDIR)/$$i"; \ - done - for i in $(PERL_MODS); \ - do \ - $(INSTALL_DATA) "zconf/$$i" "$(DESTDIR)$(PERLLIBDIR)/$$i"; \ - done -endif - -libhexfile.a: hexfile.o - $(AR) cru $@ $^ - $(RANLIB) $@ - -fpga_load: fpga_load.o libhexfile.a - $(CC) -L. -o $@ $@.o $(EXTRA_LIBS) -lhexfile -lusb - -fpga_load.o: CFLAGS+=-D_GNU_SOURCE # We use memrchr() - -hexfile.o: hexfile.c hexfile.h - $(CC) $(CFLAGS) $(PEDANTIC) -c $< - -test_parse.o: test_parse.c hexfile.h - $(CC) $(CFLAGS) $(PEDANTIC) -c $< - -test_parse: test_parse.o libhexfile.a - $(CC) -L. -o $@ $@.o $(EXTRA_LIBS) -lhexfile -lusb - -print_modes: print_modes.c wctdm_fxomodes.h - $(HOSTCC) -o $@ $(CFLAGS) $< - -wctdm_fxomodes.h: $(WCTDM) - perl -n -e 'print if (/^static struct fxo_mode {$$/ .. /};$$/)' $(WCTDM) >$@ - -init_fxo_modes: print_modes - ./$< >$@ - -perlcheck: $(PERL_SCRIPTS) - for i in $^; do perl -I./zconf -c $$i || exit 1; done - touch $@ - -clean: - $(RM) *.o $(TARGETS) diff --git a/xpp/utils/astribank_hook b/xpp/utils/astribank_hook deleted file mode 100755 index 351cd93..0000000 --- a/xpp/utils/astribank_hook +++ /dev/null @@ -1,53 +0,0 @@ -#! /bin/sh - -# This is an example of an Astribank device hook. The xpp.rules file -# calls /usr/share/zaptel/astribank_hook after a new Astribank is ready -# and after and old Astribank device has been destroyed. -# -# This example script sets the sync source, and thus makes the call to -# xpp_sync in the init.d script unnecessary. - -set -e - -xpp_sync="/usr/sbin/xpp_sync" - -me=`basename $0` -INIT_DIR=`dirname $0` -XPP_BASE=/proc/xpp -export XPP_BASE -LOGGER="logger -s -t $me" -XPP_SYNC='auto' - -ZAPTEL_BOOT_DEBIAN=${ZAPTEL_BOOT_DEBIAN:-/etc/default/zaptel} -ZAPTEL_BOOT_FEDORA=${ZAPTEL_BOOT_FEDORA:-/etc/sysconfig/zaptel} - -# read default configuration from /etc/default/zaptel -if [ -r $ZAPTEL_BOOT_DEBIAN ]; then . $ZAPTEL_BOOT_DEBIAN; fi -if [ -r $ZAPTEL_BOOT_FEDORA ]; then . $ZAPTEL_BOOT_FEDORA; fi - -if [ "$ASTRIBANK_HOOK_DISABLED" != '' ]; then - $LOGGER -p kern.info "Exiting... ASTRIBANK_HOOK_DISABLED" - exit 0 -fi - -# Always redirect stderr somewhere, otherwise the shell script will die -# when it tries to do I/O related stuff on closed file descriptor. -# Our default is to throw it down the bit-bucket. -#exec 2> /dev/console -## If you wish to trace this script: -#exec 2> "/tmp/astribank_hook_$XBUS_NAME" - -$LOGGER -p kern.info "$ACTION: $*. Setting sync to $XPP_SYNC." - -case "$ACTION" in -add) - "$xpp_sync" $XPP_SYNC - ;; -remove) - "$xpp_sync" $XPP_SYNC - ;; -*) - ;; -esac - -"$xpp_sync" | $LOGGER -p kern.info diff --git a/xpp/utils/example_default_zaptel b/xpp/utils/example_default_zaptel deleted file mode 100644 index f60b651..0000000 --- a/xpp/utils/example_default_zaptel +++ /dev/null @@ -1,31 +0,0 @@ -# Disables hotplug firmware loading -#XPP_HOTPLUG_DISABLED=yes -# -# Disables udev hook called when an astribank is added and ready -# or removed. -#ASTRIBANK_HOOK_DISABLED=yes - -# Setup for XPP PRI. This allows to have fixed settings: -# 1. The variable XPP_PRI_SETUP contains a whitespace separated list of -# port specifications. -# 2. Each port specification contains a match expression, a '=' and -# a setting string. -# 2. Match expressions may be: -# - CONNECTOR/usb..../XPD-nn To identify by physical connector -# - NUM/XBUS-mm/XPD-nn To identify by bus number -# 4. Match expressions may contain "wildcards" (which are translated -# internally to regular expressions): -# * matches zero or more characters. -# ? matches one charater -# 5. The list of matches is scanned from beginning to end. First match wins. -# 6. The list implicitly contains an 'NUM/*=TE,E1' catch all default, appended -# to its end. -# 7. The setting string is composed of comma separated settings. Valid -# settings are: -# - NT or TE -# - E1 or T1 or J1 -# -XPP_PRI_SETUP=' - CONNECTOR/usb-0000:00:1d.7-1/XPD-01=NT,E1 - NUM/*/XPD-03=NT,E1 - ' diff --git a/xpp/utils/fpga_load.8 b/xpp/utils/fpga_load.8 deleted file mode 100644 index 412a839..0000000 --- a/xpp/utils/fpga_load.8 +++ /dev/null @@ -1,86 +0,0 @@ -.TH "FPGA_LOAD" "8" "16 April 2006" "" "" - -.SH NAME -ztcfg \- reads and loads zaptel.conf -.SH SYNOPSIS - -.B fpga_load -[\fB-g\fR] [\fB-r\fR] [\fB-v\fR] \fB-D \fR{/proc/bus/usb|/dev/bus/usb}/\fIBUS/DEV\fR - -.B fpga_load -[\fB-g\fR] [\fB-v\fR] \fB-D \fR{/proc/bus/usb|/dev/bus/usb}/\fIBUS/DEV\fR \fB-I \fIfirmware.hex\fR [\fB-b \fIdump.bin\fR] [\fB-i\fR] - -.B fpga_load -h - -.SH DESCRIPTION -.B fpga_load -loads the FPGA firmware to the Xorcom Astribank device. -The syntax resembles that of fxload(8). - -.SH OPTIONS -.B -b -.I dump.bin -.RS -Before writing firmware, bump the processed binary file to -.I dump.bin\fR. -.RE - -.B -D -.I DEVICE -.RS -Required. The device to read from/write to. On modern UDEV-based system -this is usually /dev/bus/usb/\fIbus_num\fR/\fIdevice_num\fR, -where \fIbus_num\fR and \fIdevice_num\fR are the first two numbers in the -output of lsusb(8). -On older systems that use usbfs, it is usually -/proc/bus/usb/\fIbus_num\fR/\fIdevice_num\fR. -.RE - -.B -r -.RS -Reset the Astribank and renumerate its USB connection to power on product ID. -.RE - -.B -g -.RS -Dump all eeprom data to standard output. -.RE - -.B -I -.I fireware_file -.RS -The firmware file to write to the device. -.RE - -.B -i -.RS -Show information about the firmware file (valid only with \fB-I\fR option). -Example: -.PP - ./FPGA_1151.hex: Version=3297 Checksum=58270 - -In particular, the calculated checksum should match the output of \fIsum(1)\fR -on the binary firmware file generated by the \fB-b\fR option. -.RE - -.B -v -.RS -Increase verbosity. May be used multiple times. -.RE - -.B -h -.RS -Displays usage message. -.RE - -.SH SEE ALSO -fxload(8), lsusb(8) - -.SH AUTHOR -This manual page was written by Tzafrir Cohen . -Permission is granted to copy, distribute and/or modify this document under -the terms of the GNU General Public License, Version 2 any -later version published by the Free Software Foundation. - -On Debian systems, the complete text of the GNU General Public -License can be found in /usr/share/common-licenses/GPL. diff --git a/xpp/utils/fpga_load.c b/xpp/utils/fpga_load.c deleted file mode 100644 index 3d6bdbe..0000000 --- a/xpp/utils/fpga_load.c +++ /dev/null @@ -1,1003 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "hexfile.h" - -static const char rcsid[] = "$Id$"; - -#define ERR(fmt, arg...) do { \ - if(verbose >= LOG_ERR) \ - fprintf(stderr, "%s: ERROR (%d): " fmt, \ - progname, __LINE__, ## arg); \ - } while(0); -#define INFO(fmt, arg...) do { \ - if(verbose >= LOG_INFO) \ - fprintf(stderr, "%s: " fmt, \ - progname, ## arg); \ - } while(0); -#define DBG(fmt, arg...) do { \ - if(verbose >= LOG_DEBUG) \ - fprintf(stderr, "%s: DBG: " fmt, \ - progname, ## arg); \ - } while(0); - -static int verbose = LOG_WARNING; -static char *progname; -static int disconnected = 0; - -#define MAX_HEX_LINES 10000 -#define PACKET_SIZE 512 -#define EEPROM_SIZE 16 -#define LABEL_SIZE 8 -#define TIMEOUT 5000 - - -/* My device parameters */ -#define MY_EP_OUT 0x04 -#define MY_EP_IN 0x88 - -#define FPGA_EP_OUT 0x02 -#define FPGA_EP_IN 0x86 - -/* USB firmware types */ -#define USB_11xx 0 -#define USB_FIRMWARE_II 1 - -#define TYPE_ENTRY(t,ni,n,ne,out,in,...) \ - [t] = { \ - .type_code = (t), \ - .num_interfaces = (ni), \ - .my_interface_num = (n), \ - .num_endpoints = (ne), \ - .my_ep_in = (in), \ - .my_ep_out = (out), \ - .name = #t, \ - .endpoints = { __VA_ARGS__ }, \ - } - -static const struct astribank_type { - int type_code; - int num_interfaces; - int my_interface_num; - int num_endpoints; - int my_ep_out; - int my_ep_in; - char *name; - int endpoints[4]; /* for matching */ -} astribank_types[] = { - TYPE_ENTRY(USB_11xx, 1, 0, 4, MY_EP_OUT, MY_EP_IN, - FPGA_EP_OUT, - MY_EP_OUT, - FPGA_EP_IN, - MY_EP_IN), - TYPE_ENTRY(USB_FIRMWARE_II, 2, 1, 2, MY_EP_OUT, MY_EP_IN, - MY_EP_OUT, - MY_EP_IN), -}; -#undef TYPE_ENTRY - -enum fpga_load_packet_types { - PT_STATUS_REPLY = 0x01, - PT_DATA_PACKET = 0x01, -#ifdef XORCOM_INTERNAL - PT_EEPROM_SET = 0x04, -#endif - PT_EEPROM_GET = 0x08, - PT_RENUMERATE = 0x10, - PT_RESET = 0x20, - PT_BAD_COMMAND = 0xAA -}; - -struct myeeprom { - uint8_t source; - uint16_t vendor; - uint16_t product; - uint8_t release_major; - uint8_t release_minor; - uint8_t reserved; - uint8_t label[LABEL_SIZE]; -} PACKED; - -struct fpga_packet_header { - struct { - uint8_t op; - } PACKED header; - union { - struct { - uint16_t seq; - uint8_t status; - } PACKED status_reply; - struct { - uint16_t seq; - uint8_t reserved; - uint8_t data[ZERO_SIZE]; - } PACKED data_packet; - struct { - struct myeeprom data; - } PACKED eeprom_set; - struct { - struct myeeprom data; - } PACKED eeprom_get; - } d; -} PACKED; - -enum fpga_load_status { - FW_FAIL_RESET = 1, - FW_FAIL_TRANS = 2, - FW_TRANS_OK = 4, - FW_CONFIG_DONE = 8 -}; - -struct my_usb_device { - struct usb_device *dev; - usb_dev_handle *handle; - int my_interface_num; - int my_ep_out; - int my_ep_in; - char iManufacturer[BUFSIZ]; - char iProduct[BUFSIZ]; - char iSerialNumber[BUFSIZ]; - char iInterface[BUFSIZ]; - int is_usb2; - struct myeeprom eeprom; - const struct astribank_type *abtype; -}; - -const char *load_status2str(enum fpga_load_status s) -{ - switch(s) { - case FW_FAIL_RESET: return "FW_FAIL_RESET"; - case FW_FAIL_TRANS: return "FW_FAIL_TRANS"; - case FW_TRANS_OK: return "FW_TRANS_OK"; - case FW_CONFIG_DONE: return "FW_CONFIG_DONE"; - default: return "UNKNOWN"; - } -} - -/* return 1 if: - * - str has a number - * - It is larger than 0 - * - It equals num - */ -int num_matches(int num, const char* str) { - int str_val = atoi(str); - if (str_val <= 0) - return 0; - return (str_val == num); -} - -struct usb_device *dev_of_path(const char *path) -{ - struct usb_bus *bus; - struct usb_device *dev; - char dirname[PATH_MAX]; - char filename[PATH_MAX]; - const char *p; - int bnum; - int dnum; - int ret; - - assert(path != NULL); - if(access(path, F_OK) < 0) { - perror(path); - return NULL; - } - /* Find last '/' */ - if((p = memrchr(path, '/', strlen(path))) == NULL) { - ERR("Missing a '/' in %s\n", path); - return NULL; - } - /* Get the device number */ - ret = sscanf(p + 1, "%d", &dnum); - if(ret != 1) { - ERR("Path tail is not a device number: '%s'\n", p); - return NULL; - } - /* Search for a '/' before that */ - p = memrchr(path, '/', p - path); - if(p == NULL) - p = path; /* Relative path */ - else - p++; /* skip '/' */ - /* Get the bus number */ - ret = sscanf(p, "%d", &bnum); - if(ret != 1) { - ERR("Path tail is not a bus number: '%s'\n", p); - return NULL; - } - sprintf(dirname, "%03d", bnum); - sprintf(filename, "%03d", dnum); - for (bus = usb_busses; bus; bus = bus->next) { - if (! num_matches(bnum, bus->dirname)) - //if(strcmp(bus->dirname, dirname) != 0) - continue; - for (dev = bus->devices; dev; dev = dev->next) { - //if(strcmp(dev->filename, filename) == 0) - if (num_matches(dnum, dev->filename)) - return dev; - } - } - ERR("no usb device match '%s'\n", path); - return NULL; -} - -int get_usb_string(char *buf, unsigned int len, uint16_t item, usb_dev_handle *handle) -{ - char tmp[BUFSIZ]; - int ret; - - if (!item) - return 0; - ret = usb_get_string_simple(handle, item, tmp, BUFSIZ); - if (ret <= 0) - return ret; - return snprintf(buf, len, "%s", tmp); -} - -void my_usb_device_cleanup(struct my_usb_device *mydev) -{ - assert(mydev != NULL); - if(!mydev->handle) { - return; /* Nothing to do */ - } - if(!disconnected) { - if(usb_release_interface(mydev->handle, mydev->abtype->my_interface_num) != 0) { - ERR("Releasing interface: usb: %s\n", usb_strerror()); - } - } - if(usb_close(mydev->handle) != 0) { - ERR("Closing device: usb: %s\n", usb_strerror()); - } - disconnected = 1; - mydev->handle = NULL; -} - -static void show_device_info(const struct my_usb_device *mydev) -{ - const struct myeeprom *eeprom; - uint8_t data[LABEL_SIZE + 1]; - - assert(mydev != NULL); - eeprom = &mydev->eeprom; - memset(data, 0, LABEL_SIZE + 1); - memcpy(data, eeprom->label, LABEL_SIZE); - printf("USB Firmware Type: [%s]\n", mydev->abtype->name); - printf("USB iManufacturer: [%s]\n", mydev->iManufacturer); - printf("USB iProduct: [%s]\n", mydev->iProduct); - printf("USB iSerialNumber: [%s]\n", mydev->iSerialNumber); - printf("EEPROM Source: 0x%02X\n", eeprom->source); - printf("EEPROM Vendor: 0x%04X\n", eeprom->vendor); - printf("EEPROM Product: 0x%04X\n", eeprom->product); - printf("EEPROM Release: %d.%03d\n", eeprom->release_major, eeprom->release_minor); - printf("EEPROM Label: HEX(%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X) [%s]\n", - data[0], data[1], data[2], data[3], - data[4], data[5], data[6], data[7], data); -} - -void dump_packet(const char *msg, const char *buf, int len) -{ - int i; - - for(i = 0; i < len; i++) - INFO("%s: %2d> 0x%02X\n", msg, i, (uint8_t)buf[i]); -} - -int send_usb(const char *msg, struct my_usb_device *mydev, struct fpga_packet_header *phead, int len, int timeout) -{ - char *p = (char *)phead; - int ret; - - if(verbose >= LOG_DEBUG) - dump_packet(msg, p, len); - if(mydev->my_ep_out & USB_ENDPOINT_IN) { - ERR("send_usb called with an input endpoint 0x%x\n", mydev->my_ep_out); - return -EINVAL; - } - ret = usb_bulk_write(mydev->handle, mydev->my_ep_out, p, len, timeout); - if(ret < 0) { - /* - * If the device was gone, it may be the - * result of renumeration. Ignore it. - */ - if(ret != -ENODEV) { - ERR("bulk_write to endpoint 0x%x failed: %s\n", mydev->my_ep_out, usb_strerror()); - dump_packet("send_usb[ERR]", p, len); - } else { - disconnected = 1; - my_usb_device_cleanup(mydev); - } - return ret; - } else if(ret != len) { - ERR("bulk_write to endpoint 0x%x short write: %s\n", mydev->my_ep_out, usb_strerror()); - dump_packet("send_usb[ERR]", p, len); - return -EFAULT; - } - return ret; -} - -int recv_usb(const char *msg, struct my_usb_device *mydev, char *buf, size_t len, int timeout) -{ - int ret; - - if(mydev->my_ep_in & USB_ENDPOINT_OUT) { - ERR("recv_usb called with an output endpoint 0x%x\n", mydev->my_ep_in); - return -EINVAL; - } - ret = usb_bulk_read(mydev->handle, mydev->my_ep_in, buf, len, timeout); - if(ret < 0) { - ERR("bulk_read from endpoint 0x%x failed: %s\n", mydev->my_ep_in, usb_strerror()); - return ret; - } - if(verbose >= LOG_DEBUG) - dump_packet(msg, buf, ret); - return ret; -} - -#ifdef XORCOM_INTERNAL -int eeprom_set(struct my_usb_device *mydev, const struct myeeprom *eeprom) -{ - int ret; - int len; - char buf[PACKET_SIZE]; - struct fpga_packet_header *phead = (struct fpga_packet_header *)buf; - - DBG("%s Start...\n", __FUNCTION__); - assert(mydev != NULL); - phead->header.op = PT_EEPROM_SET; - memcpy(&phead->d.eeprom_set.data, eeprom, EEPROM_SIZE); - len = sizeof(phead->d.eeprom_set) + sizeof(phead->header.op); - ret = send_usb("eeprom_set[W]", mydev, phead, len, TIMEOUT); - if(ret < 0) - return ret; - ret = recv_usb("eeprom_set[R]", mydev, buf, sizeof(buf), TIMEOUT); - if(ret <= 0) - return ret; - phead = (struct fpga_packet_header *)buf; - if(phead->header.op == PT_BAD_COMMAND) { - ERR("Firmware rejected PT_EEPROM_SET command\n"); - return -EINVAL; - } else if(phead->header.op != PT_EEPROM_SET) { - ERR("Got unexpected reply op=%d\n", phead->header.op); - return -EINVAL; - } - return 0; -} -#endif - -int eeprom_get(struct my_usb_device *mydev) -{ - int ret; - int len; - char buf[PACKET_SIZE]; - struct fpga_packet_header *phead = (struct fpga_packet_header *)buf; - struct myeeprom *eeprom; - - assert(mydev != NULL); - eeprom = &mydev->eeprom; - DBG("%s Start...\n", __FUNCTION__); - phead->header.op = PT_EEPROM_GET; - len = sizeof(phead->header.op); /* warning: sending small packet */ - ret = send_usb("eeprom_get[W]", mydev, phead, len, TIMEOUT); - if(ret < 0) - return ret; - ret = recv_usb("eeprom_get[R]", mydev, buf, sizeof(buf), TIMEOUT); - if(ret <= 0) - return ret; - phead = (struct fpga_packet_header *)buf; - if(phead->header.op == PT_BAD_COMMAND) { - ERR("PT_BAD_COMMAND\n"); - return -EINVAL; - } else if(phead->header.op != PT_EEPROM_GET) { - ERR("Got unexpected reply op=%d\n", phead->header.op); - return -EINVAL; - } - memcpy(eeprom, &phead->d.eeprom_get.data, EEPROM_SIZE); - return 0; -} - -int send_hexline(struct my_usb_device *mydev, struct hexline *hexline, int seq) -{ - int ret; - int len; - uint8_t *data; - char buf[PACKET_SIZE]; - struct fpga_packet_header *phead = (struct fpga_packet_header *)buf; - enum fpga_load_status status; - - assert(mydev != NULL); - assert(hexline != NULL); - if(hexline->d.content.header.tt != TT_DATA) { - DBG("Non data record %d type = %d\n", seq, hexline->d.content.header.tt); - return 0; - } - len = hexline->d.content.header.ll; /* don't send checksum */ - data = hexline->d.content.tt_data.data; - phead->header.op = PT_DATA_PACKET; - phead->d.data_packet.seq = seq; - phead->d.data_packet.reserved = 0x00; - memcpy(phead->d.data_packet.data, data, len); - len += sizeof(hexline->d.content.header); - DBG("%04d+\r", seq); - ret = send_usb("hexline[W]", mydev, phead, len, TIMEOUT); - if(ret < 0) - return ret; - ret = recv_usb("hexline[R]", mydev, buf, sizeof(buf), TIMEOUT); - if(ret <= 0) - return ret; - DBG("%04d-\r", seq); - phead = (struct fpga_packet_header *)buf; - if(phead->header.op != PT_STATUS_REPLY) { - ERR("Got unexpected reply op=%d\n", phead->header.op); - dump_packet("hexline[ERR]", buf, ret); - return -EINVAL; - } - status = (enum fpga_load_status)phead->d.status_reply.status; - switch(status) { - case FW_TRANS_OK: - case FW_CONFIG_DONE: - break; - case FW_FAIL_RESET: - case FW_FAIL_TRANS: - ERR("status reply %s (%d)\n", load_status2str(status), status); - dump_packet("hexline[ERR]", buf, ret); - return -EPROTO; - default: - ERR("Unknown status reply %d\n", status); - dump_packet("hexline[ERR]", buf, ret); - return -EPROTO; - } - return 0; -} - -//. returns > 0 - ok, the number of lines sent -//. returns < 0 - error number -int send_splited_hexline(struct my_usb_device *mydev, struct hexline *hexline, int seq, uint8_t maxwidth) -{ - struct hexline *extraline; - int linessent = 0; - int allocsize; - int extra_offset = 0; - unsigned int this_line = 0; - uint8_t bytesleft = 0; - - assert(mydev != NULL); - if(!hexline) { - ERR("Bad record %d type = %d\n", seq, hexline->d.content.header.tt); - return -EINVAL; - } - bytesleft = hexline->d.content.header.ll; - // split the line into several lines - while (bytesleft > 0) { - int status; - this_line = (bytesleft >= maxwidth) ? maxwidth : bytesleft; - allocsize = sizeof(struct hexline) + this_line + 1; - // generate the new line - if((extraline = (struct hexline *)malloc(allocsize)) == NULL) { - ERR("Not enough memory for spliting the lines\n" ); - return -EINVAL; - } - memset(extraline, 0, allocsize); - extraline->d.content.header.ll = this_line; - extraline->d.content.header.offset = hexline->d.content.header.offset + extra_offset; - extraline->d.content.header.tt = hexline->d.content.header.tt; - memcpy( extraline->d.content.tt_data.data, hexline->d.content.tt_data.data+extra_offset, this_line); - status = send_hexline(mydev, extraline, seq+linessent ); - // cleanups - free(extraline); - extra_offset += this_line; - bytesleft -= this_line; - if (status) - return status; - linessent++; - } - return linessent; -} - -int match_usb_device_identity(const struct usb_config_descriptor *config_desc, - const struct astribank_type *ab) -{ - struct usb_interface *interface; - struct usb_interface_descriptor *iface_desc; - - if(config_desc->bNumInterfaces <= ab->my_interface_num) - return 0; - interface = &config_desc->interface[ab->my_interface_num]; - iface_desc = interface->altsetting; - - return iface_desc->bInterfaceClass == 0xFF && - iface_desc->bInterfaceNumber == ab->my_interface_num && - iface_desc->bNumEndpoints == ab->num_endpoints; -} - -const struct astribank_type *my_usb_device_identify(const char devpath[], struct my_usb_device *mydev) -{ - struct usb_device_descriptor *dev_desc; - struct usb_config_descriptor *config_desc; - int i; - - assert(mydev != NULL); - usb_init(); - usb_find_busses(); - usb_find_devices(); - mydev->dev = dev_of_path(devpath); - if(!mydev->dev) { - ERR("Bailing out\n"); - return 0; - } - dev_desc = &mydev->dev->descriptor; - config_desc = mydev->dev->config; - for(i = 0; i < sizeof(astribank_types)/sizeof(astribank_types[0]); i++) { - if(match_usb_device_identity(config_desc, &astribank_types[i])) { - DBG("Identified[%d]: interfaces=%d endpoints=%d: \"%s\"\n", - i, - astribank_types[i].num_interfaces, - astribank_types[i].num_endpoints, - astribank_types[i].name); - return &astribank_types[i]; - } - } - return NULL; -} - -int my_usb_device_init(const char devpath[], struct my_usb_device *mydev, const struct astribank_type *abtype) -{ - struct usb_device_descriptor *dev_desc; - struct usb_config_descriptor *config_desc; - struct usb_interface *interface; - struct usb_interface_descriptor *iface_desc; - struct usb_endpoint_descriptor *endpoint; - int ret; - int i; - - assert(mydev != NULL); - usb_init(); - usb_find_busses(); - usb_find_devices(); - mydev->dev = dev_of_path(devpath); - if(!mydev->dev) { - ERR("Bailing out\n"); - return 0; - } - mydev->handle = usb_open(mydev->dev); - if(!mydev->handle) { - ERR("Failed to open usb device '%s/%s': %s\n", mydev->dev->bus->dirname, mydev->dev->filename, usb_strerror()); - return 0; - } - if(usb_claim_interface(mydev->handle, abtype->my_interface_num) != 0) { - ERR("usb_claim_interface: %s\n", usb_strerror()); - return 0; - } - dev_desc = &mydev->dev->descriptor; - config_desc = mydev->dev->config; - interface = &config_desc->interface[abtype->my_interface_num]; - iface_desc = interface->altsetting; - endpoint = iface_desc->endpoint; - mydev->is_usb2 = (endpoint->wMaxPacketSize == 512); - for(i = 0; i < iface_desc->bNumEndpoints; i++, endpoint++) { - if(endpoint->bEndpointAddress != abtype->endpoints[i]) { - ERR("Wrong endpoint 0x%X (at index %d)\n", endpoint->bEndpointAddress, i); - return 0; - } - if(endpoint->bEndpointAddress == MY_EP_OUT || endpoint->bEndpointAddress == MY_EP_IN) { - if(endpoint->wMaxPacketSize > PACKET_SIZE) { - ERR("Endpoint #%d wMaxPacketSize too large (%d)\n", i, endpoint->wMaxPacketSize); - return 0; - } - } - } - mydev->abtype = abtype; - mydev->my_ep_in = abtype->my_ep_in; - mydev->my_ep_out = abtype->my_ep_out; - ret = get_usb_string(mydev->iManufacturer, BUFSIZ, dev_desc->iManufacturer, mydev->handle); - ret = get_usb_string(mydev->iProduct, BUFSIZ, dev_desc->iProduct, mydev->handle); - ret = get_usb_string(mydev->iSerialNumber, BUFSIZ, dev_desc->iSerialNumber, mydev->handle); - ret = get_usb_string(mydev->iInterface, BUFSIZ, iface_desc->iInterface, mydev->handle); - INFO("ID=%04X:%04X Manufacturer=[%s] Product=[%s] SerialNumber=[%s] Interface=[%s]\n", - dev_desc->idVendor, - dev_desc->idProduct, - mydev->iManufacturer, - mydev->iProduct, - mydev->iSerialNumber, - mydev->iInterface); - if(usb_clear_halt(mydev->handle, mydev->my_ep_out) != 0) { - ERR("Clearing output endpoint: %s\n", usb_strerror()); - return 0; - } - if(usb_clear_halt(mydev->handle, mydev->my_ep_in) != 0) { - ERR("Clearing input endpoint: %s\n", usb_strerror()); - return 0; - } - return 1; -} - -int renumerate_device(struct my_usb_device *mydev, enum fpga_load_packet_types pt) -{ - char buf[PACKET_SIZE]; - struct fpga_packet_header *phead = (struct fpga_packet_header *)buf; - int ret; - - assert(mydev != NULL); - DBG("Renumerating with 0x%X\n", pt); - phead->header.op = pt; - ret = send_usb("renumerate[W]", mydev, phead, 1, TIMEOUT); - if(ret < 0 && ret != -ENODEV) - return ret; -#if 0 - /* - * FIXME: we count on our USB firmware to reset the device... should we? - */ - ret = usb_reset(mydev->handle); - if(ret < 0) { - ERR("usb_reset: %s\n", usb_strerror()); - return -ENODEV; - } -#endif - return 0; -} - -/* - * Returns: true on success, false on failure - */ -int fpga_load(struct my_usb_device *mydev, const struct hexdata *hexdata) -{ - unsigned int i; - unsigned int j = 0; - int ret; - int finished = 0; - const char *v = hexdata->version_info; - - v = (v[0]) ? v : "Unknown"; - assert(mydev != NULL); - INFO("FPGA_LOAD (version %s)\n", v); - /* - * i - is the line number - * j - is the sequence number, on USB 2, i=j, but on - * USB 1 send_splited_hexline may increase the sequence - * number, as it needs - */ - for(i = 0; i < hexdata->maxlines; i++) { - struct hexline *hexline = hexdata->lines[i]; - - if(!hexline) - break; - if(finished) { - ERR("Extra data after End Of Data Record (line %d)\n", i); - return 0; - } - if(hexline->d.content.header.tt == TT_EOF) { - DBG("End of data\n"); - finished = 1; - continue; - } - if(mydev->is_usb2) { - if((ret = send_hexline(mydev, hexline, i)) != 0) { - perror("Failed sending hexline"); - return 0; - } - } else { - if((ret = send_splited_hexline(mydev, hexline, j, 60)) < 0) { - perror("Failed sending hexline (splitting did not help)"); - return 0; - } - j += ret; - } - } - DBG("Finished...\n"); - return 1; -} - -#include - -void usage() -{ - fprintf(stderr, "Usage: %s -D {/proc/bus/usb|/dev/bus/usb}// [options...]\n", progname); - fprintf(stderr, "\tOptions:\n"); - fprintf(stderr, "\t\t[-r] # Reset the device\n"); - fprintf(stderr, "\t\t[-b ] # Output to \n"); - fprintf(stderr, "\t\t[-I ] # Input from \n"); - fprintf(stderr, "\t\t[-H ] # Output to ('-' is stdout)\n"); - fprintf(stderr, "\t\t[-i] # Show hexfile information\n"); - fprintf(stderr, "\t\t[-g] # Get eeprom from device\n"); - fprintf(stderr, "\t\t[-v] # Increase verbosity\n"); -#ifdef XORCOM_INTERNAL - fprintf(stderr, "\t\t[-C srC byte] # Set Address sourCe (default: C0)\n"); - fprintf(stderr, "\t\t[-V vendorid] # Set Vendor id on device\n"); - fprintf(stderr, "\t\t[-P productid] # Set Product id on device\n"); - fprintf(stderr, "\t\t[-R release] # Set Release. 2 dot separated decimals\n"); - fprintf(stderr, "\t\t[-L label] # Set label.\n"); -#endif - exit(1); -} - -static void parse_report_func(int level, const char *msg, ...) -{ - va_list ap; - - va_start(ap, msg); - if(level <= verbose) - vfprintf(stderr, msg, ap); - va_end(ap); -} - -#ifdef XORCOM_INTERNAL -static void eeprom_fill(struct myeeprom *myeeprom, - const char vendor[], - const char product[], - const char release[], - const char label[], - const char source[]) -{ - // FF: address source is from device. C0: from eeprom - if (source) - myeeprom->source = strtoul(source, NULL, 0); - else - myeeprom->source = 0xC0; - if(vendor) - myeeprom->vendor = strtoul(vendor, NULL, 0); - if(product) - myeeprom->product = strtoul(product, NULL, 0); - if(release) { - int release_major = 0; - int release_minor = 0; - - sscanf(release, "%d.%d", &release_major, &release_minor); - myeeprom->release_major = release_major; - myeeprom->release_minor = release_minor; - } - if(label) { - /* padding */ - memset(myeeprom->label, 0, LABEL_SIZE); - memcpy(myeeprom->label, label, strlen(label)); - } -} -#endif - -int main(int argc, char *argv[]) -{ - const struct astribank_type *abtype; - struct my_usb_device mydev; - const char *devpath = NULL; - const char *binfile = NULL; - const char *inhexfile = NULL; - const char *outhexfile = NULL; - struct hexdata *hexdata = NULL; - int opt_reset = 0; - int opt_info = 0; - int opt_read_eeprom = 0; - int opt_output_width = 0; - int output_is_set = 0; -#ifdef XORCOM_INTERNAL - int opt_write_eeprom = 0; - char *vendor = NULL; - char *source = NULL; - char *product = NULL; - char *release = NULL; - char *label = NULL; - const char options[] = "rib:D:ghH:I:vw:C:V:P:R:S:"; -#else - const char options[] = "rib:D:ghH:I:vw:"; -#endif - int ret = 0; - - progname = argv[0]; - assert(sizeof(struct fpga_packet_header) <= PACKET_SIZE); - assert(sizeof(struct myeeprom) == EEPROM_SIZE); - while (1) { - int c; - - c = getopt (argc, argv, options); - if (c == -1) - break; - - switch (c) { - case 'D': - devpath = optarg; - if(output_is_set++) { - ERR("Cannot set -D. Another output option is already selected\n"); - return 1; - } - break; - case 'r': - opt_reset = 1; - break; - case 'i': - opt_info = 1; - break; - case 'b': - binfile = optarg; - if(output_is_set++) { - ERR("Cannot set -b. Another output option is already selected\n"); - return 1; - } - break; - case 'g': - opt_read_eeprom = 1; - break; - case 'H': - outhexfile = optarg; - if(output_is_set++) { - ERR("Cannot set -H. Another output option is already selected\n"); - return 1; - } - break; - case 'I': - inhexfile = optarg; - break; -#ifdef XORCOM_INTERNAL - case 'V': - vendor = optarg; - break; - case 'C': - source = optarg; - break; - case 'P': - product = optarg; - break; - case 'R': - release = optarg; - break; - case 'S': - label = optarg; - { - const char GOOD_CHARS[] = - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789" - "-_."; - int len = strlen(label); - int goodlen = strspn(label, GOOD_CHARS); - - if(len > LABEL_SIZE) { - ERR("Label too long (%d > %d)\n", len, LABEL_SIZE); - usage(); - } - if(goodlen != len) { - ERR("Bad character in label number (pos=%d)\n", goodlen); - usage(); - } - } - break; -#endif - case 'w': - opt_output_width = strtoul(optarg, NULL, 0); - break; - case 'v': - verbose++; - break; - case 'h': - default: - ERR("Unknown option '%c'\n", c); - usage(); - } - } - - if (optind != argc) { - usage(); - } - if(inhexfile) { -#ifdef XORCOM_INTERNAL - if(vendor || product || release || label || source ) { - ERR("The -I option is exclusive of -[VPRSC]\n"); - return 1; - } -#endif - parse_hexfile_set_reporting(parse_report_func); - hexdata = parse_hexfile(inhexfile, MAX_HEX_LINES); - if(!hexdata) { - ERR("Bailing out\n"); - exit(1); - } - if(opt_info) { - printf("%s: Version=%s Checksum=%d\n", - inhexfile, hexdata->version_info, - bsd_checksum(hexdata)); - } - if(binfile) { - dump_binary(hexdata, binfile); - return 0; - } - if(outhexfile) { - if(opt_output_width) - dump_hexfile2(hexdata, outhexfile, opt_output_width); - else - dump_hexfile(hexdata, outhexfile); - return 0; - } - } -#ifdef XORCOM_INTERNAL - else if(vendor || product || release || label || source ) { - if(outhexfile) { - FILE *fp; - - if(strcmp(outhexfile, "-") == 0) - fp = stdout; - else if((fp = fopen(outhexfile, "w")) == NULL) { - perror(outhexfile); - return 1; - } - memset(&mydev.eeprom, 0, sizeof(struct myeeprom)); - eeprom_fill(&mydev.eeprom, vendor, product, release, label, source); - gen_hexline((uint8_t *)&mydev.eeprom, 0, sizeof(mydev.eeprom), fp); - gen_hexline(NULL, 0, 0, fp); /* EOF */ - return 0; - } - } -#endif - if(!devpath) { - ERR("Missing device path\n"); - usage(); - } - DBG("Startup %s\n", devpath); - if((abtype = my_usb_device_identify(devpath, &mydev)) == NULL) { - ERR("Bad device. Does not match our types.\n"); - usage(); - } - INFO("FIRMWARE: %s (type=%d)\n", abtype->name, abtype->type_code); - if(!my_usb_device_init(devpath, &mydev, abtype)) { - ERR("Failed to initialize USB device '%s'\n", devpath); - ret = -ENODEV; - goto dev_err; - } - ret = eeprom_get(&mydev); - if(ret < 0) { - ERR("Failed reading eeprom\n"); - goto dev_err; - } -#ifdef XORCOM_INTERNAL - if(vendor || product || release || label || source ) { - eeprom_fill(&mydev.eeprom, vendor, product, release, label, source); - opt_write_eeprom = 1; - opt_read_eeprom = 1; - } -#endif - if(opt_read_eeprom) { - show_device_info(&mydev); - } - if(hexdata) { - if (!mydev.is_usb2) - INFO("Warning: working on a low end USB1 backend\n"); - if(!fpga_load(&mydev, hexdata)) { - ERR("FPGA loading failed\n"); - ret = -ENODEV; - goto dev_err; - } - ret = renumerate_device(&mydev, PT_RENUMERATE); - if(ret < 0) { - ERR("Renumeration failed: errno=%d\n", ret); - goto dev_err; - } - } -#ifdef XORCOM_INTERNAL - else if(opt_write_eeprom) { - if(abtype->type_code == USB_FIRMWARE_II) { - ERR("No EEPROM burning command in %s. Use fxload for that\n", - abtype->name); - goto dev_err; - } - ret = eeprom_set(&mydev, &mydev.eeprom); - if(ret < 0) { - ERR("Failed writing eeprom: %s\n", strerror(-ret)); - goto dev_err; - } - printf("------- RESULTS -------\n"); - show_device_info(&mydev); - } -#endif - if(opt_reset) { - DBG("Reseting to default\n"); - ret = renumerate_device(&mydev, PT_RESET); - if(ret < 0) { - ERR("Renumeration to default failed: errno=%d\n", ret); - goto dev_err; - } - } - DBG("Exiting\n"); -dev_err: - my_usb_device_cleanup(&mydev); - return ret; -} diff --git a/xpp/utils/genzaptelconf b/xpp/utils/genzaptelconf deleted file mode 100755 index 1435e9f..0000000 --- a/xpp/utils/genzaptelconf +++ /dev/null @@ -1,1195 +0,0 @@ -#! /bin/bash - -# genzaptelconf: generate as smartly as you can: -# /etc/zaptel.conf -# /etc/asterisk/zapata-channels.conf (to be #include-d into zapata.conf) -# update: -# With '-M' /etc/modules (list of modules to load) -# -# Copyright (C) 2005 by Xorcom -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# -# If you have any technical questions, contact -# Tzafrir Cohen -# - -# The script uses a number of bash-specific features -# TODO: either ditch them or convert to perl -# Don't override variables here. -# Override them in /etc/default/zaptel (debian) or /etc/sysconfig/zaptel -# (redhat/centos) - -# /etc/default/zaptel may override the following variables -VERSION=0.5.10 -rcsid='$Id$' -lc_country=us -# set to: ls, ks or gs for (Loopstart, Kewlstart and GroundStart) -# on FXS channels (FXO signalling). -fxs_default_start=ks -base_exten=6000 -# If set: no context changes are made in zapata-channels.conf -#context_manual=yes -context_lines=from-pstn # context into which PSTN calls go -context_phones=from-internal # context for internal phones calls. -# The two below apply to input and output ports of the Xorcom Astribank: -context_input=astbank-input -context_output=astbank-output # useless, but helps marking the channels :-) -# TODO: what about PRI/BRI? -# If set: no group changes are made in zapata-channels.conf -#group_manual=yes -group_phones=5 # group for phones -group_lines=0 # group for lines -# Set fxs_immediate to 'yes' to make all FXS lines answer immediately. -fxs_immediate=no - -ZAPCONF_FILE=${ZAPCONF_FILE:-/etc/zaptel.conf} -ZAPCONF_FILE_SYSTEM=$ZAPCONF_FILE -ZAPATA_FILE=${ZAPATA_FILE:-/etc/asterisk/zapata-channels.conf} -ZAPSCAN_FILE=${ZAPSCAN_FILE:-/etc/asterisk/zapscan.conf} -ZAPTEL_BOOT_DEBIAN=${ZAPTEL_BOOT_DEBIAN:-/etc/default/zaptel} -ZAPTEL_BOOT_FEDORA=${ZAPTEL_BOOT_FEDORA:-/etc/sysconfig/zaptel} -MODLIST_FILE=/etc/modules -MODLIST_FILE_FEDORA=/etc/sysconfig/zaptel -exten_base_dir=/etc/asterisk/extensions-phones.d -exten_defs_file=/etc/asterisk/extensions-defs.conf -# perl utilities: -xpp_sync=/usr/sbin/xpp_sync -zt_registration=/usr/sbin/zt_registration -# how long to wait for /dev/zap/ctl to appear? (seconds) -DEVZAP_TIMEOUT=${DEVZAP_TIMEOUT:-20} -ZTCFG=${ZTCFG:-/sbin/ztcfg} -# BRI/PRI spans will be in an additional per-span group whose number -# is SPAN_GROUP_BASE + span-number -SPAN_GROUP_BASE=10 -# set to "yes" to make BRI NT spans set overlapdial (handy for ISDN phones -# and other devices). -brint_overlap=no - -# a temporary directory to store whatever we need to remember. -# -# The main loop of genconf is run in a sub-process. -tmp_dir= - -# A list of all modules: -# - the list of modules which will be probed (in this order) if -d is used -# - The module that will be deleted from /etc/modules , if -d -M is used -ALL_MODULES="wct4xxp wcte12xp wcte11xp wct1xxp wanpipe tor2 torisa qozap vzaphfc zaphfc ztgsm wctdm24xxp wctdm opvxa1200 wcfxo pciradio wcusb xpp_usb" - -# The name of the variable in /etc/sysconfig/zaptel into which to set -# the list of detected modules. -modules_var=MODULES -# On SuSE with the rpm package: -#modules_var=ZAPTEL_MODULES - -# What signalling to give to ZapBRI channels? -# bri: bri_net; bri_cpe (Bristuffed Asterisk. No multi- support) -# bri_ptmpi: bri_net_ptmp; bri_cpe_ptmp (Bristuffed Asterisk, multi- support) -# pri: pri_net; pri_cpe (Recent Asterisk. Experimental) -#ZAPBRI_SIGNALLING=bri -ZAPBRI_SIGNALLING=bri_ptmp -#ZAPBRI_SIGNALLING=pri -zapconf_def_termtype=te - -# A command to stop / start asterisk. Must support parameters "start" -# and "stop" . This is the executable: -ZAPCONF_ASTERISK_SCRIPT=/etc/init.d/asterisk -# -# Should you need to pass extra arguments: -ZAPCONF_ASTERISK_CMD=$ZAPCONF_ASTERISK_SCRIPT - -# read default configuration from /etc/default/zaptel -if [ -r $ZAPTEL_BOOT_DEBIAN ]; then . $ZAPTEL_BOOT_DEBIAN; fi -if [ -r $ZAPTEL_BOOT_FEDORA ]; then . $ZAPTEL_BOOT_FEDORA; fi - -if [ ! -x "$ZTCFG" ]; then - # Work around a bug in the rpm package: ztcfg should be in - # /sbin as it may be required for starting a network interface - if [ -x /usr/sbin/ztcfg ]; then - ZTCFG=/usr/sbin/ztcfg - else - echo >&2 "ztcfg is not on found, do you have zaptel properly installed?" - exit_cleanup 1 - fi -fi - -XPP_SYNC=auto # sync mode. can be set to '0' or '1' or HOST explicitly. - -# it is safe to use -c twice: the last one will be used. -ztcfg_cmd="$ZTCFG -c $ZAPCONF_FILE" - -# work around a bug (that was already fixed) in the installer: -if [ "$lc_country" = '' ]; then lc_country=us; fi - -force_stop_ast=no -do_detect=no -do_unload=no -do_module_list=no -verbose=no -do_restart=yes -fxsdisable=no -do_gen_zapscan=no - -span_te_timing_counter=1 - -case "$ZAPBRI_SIGNALLING" in -bri) ZAPBRI_NET=bri_net; ZAPBRI_CPE=bri_cpe ;; -pri) ZAPBRI_NET=pri_net; ZAPBRI_CPE=pri_cpe ;; -bri_ptmp) ZAPBRI_NET=bri_net_ptmp; ZAPBRI_CPE=bri_cpe_ptmp ;; -*) - die "Incorrect value for ZAPBRI_SIGNALLING ($ZAPBRI_SIGNALLING). Abortring" - ;; -esac - -die() { - echo "$@" >&2 - exit_cleanup 1 -} - -say() { - if [ "$verbose" = no ]; then - return - fi - echo "$@" >&2 -} - -# exit (exit value is the optional $1), and clean up after us -exit_cleanup() { - if [ -d "$tmp_dir" ]; then - # don't fail but don't hide error if directory is not - # empty - rmdir "$tmp_dir" || : - fi - exit $1 -} - -# Wait for udev to generate /dev/zap/ctl, if needed: -wait_for_zapctl() { - # if device file already exists, or if zaptel has failed to load: - # no point waiting. - if [ -c /dev/zap/ctl ] || ! grep -q zaptel /proc/modules ; then - return - fi - say "Waiting for /dev/zap/ctl to be generated" - devzap_found=0 - for i in `seq $DEVZAP_TIMEOUT`; do - sleep 1 - if [ -c /dev/zap/ctl ]; then - devzap_found=1 - break - fi - done - if [ "$devzap_found" != 1 ]; then - say "Still no /dev/zap/ctl after $devzap_timeout seconds." - echo >&2 "No /dev/zap/ctl: cannot run ztcfg. Aborting." - fi -} - -run_ztcfg() { - # Run ztcfg itself - if [ "$verbose" = no ]; then - $ztcfg_cmd "$@" - else - say "Reconfiguring identified channels" - $ztcfg_cmd -vv "$@" - fi -} - -update_module_list_debian() { - say "Updating Debian modules list $MODLIST_FILE." - del_args=`for i in $ALL_MODULES ztdummy - do - echo "$i" | sed s:.\*:-e\ '/^&/d': - done` - add_args=`for i in $* - do - echo "$i" | sed s:.\*:-e\ '\$a&': - done` - - sed -i.bak $del_args "$MODLIST_FILE" - for i in $* - do - echo "$i" - done >> "$MODLIST_FILE" -} - -update_module_list_fedora() { - say "Updating modules list in zaptel init config $MODLIST_FILE_FEDORA." - sed -i.bak -e "/^$modules_var=/d" "$MODLIST_FILE_FEDORA" - echo "$modules_var=\"$*\"" >> "$MODLIST_FILE_FEDORA" -} - -update_module_list() { - if [ -f "$MODLIST_FILE" ]; then - update_module_list_debian "$@" - elif [ -f "$MODLIST_FILE_FEDORA" ]; then - update_module_list_fedora "$@" - else - die "Can't find a modules list to update. Tried: $MODLIST_FILE, $MODLIST_FILE_FEDORA. Aborting" - fi -} - - - -zap_reg_xpp() { - if [ ! -d /proc/xpp ]; then return; fi - - # Get a list of connected Astribank devices, sorted by the name of - # the USB connector. That order is rather arbitrary, but will not - # change without changes to the cabling. - xbusses=`sed -e '/STATUS=connected/!d' -e 's/ *STATUS=.*//' -e 's/ *CONNECTOR=//' /proc/xpp/xbuses | sort -t: -k 2 | cut -d: -f1` - say "Zaptel registration order:" - say "$xbusses" - - # get a list of XPDs that were not yet registered as zaptel spans. - # this will be the case if you set the parameter zap_autoreg=0 to - # the module xpp - # Append /dev/null to provide a valid file name in case of an empty pattern. - xbusses_pattern=`echo $xbusses| sed -e 's|XBUS-[0-9]*|/proc/xpp/&/XPD-*/zt_registration|g'`' /dev/null' - xpds_to_register=`grep -l 0 $xbusses_pattern` - for file in $xpds_to_register; do - echo 1 >$file - done -} - -# Initialize the Xorcom Astribank (xpp/) -xpp_startup() { - # do nothing if the module xpp was not loaded, or if no - # Astribanks connected: - if [ ! -d /proc/xpp ]; then return 0; fi - if ! grep -q 'STATUS=connected' /proc/xpp/xbuses; then return 0; fi - - echo "Waiting for Astribank devices to initialize:" - cat /proc/xpp/XBUS-[0-9]*/waitfor_xpds 2>/dev/null || true - - # overriding locales for the above two, as perl can be noisy - # when locales are missing. - # No register all the devices if they didn't auto-register: - LC_ALL=C $zt_registration on - - # this one could actually be run after ztcfg: - LC_ALL=C $xpp_sync "$XPP_SYNC" -} - - - -usage() { - program=`basename $0` - - echo >&2 "$program: generate zaptel.conf and zapata.conf" - echo >&2 "(version $VERSION, $rcsid)" - echo >&2 "usage:" - echo >&2 " $program [-sRdv] [-m k|l|g] [-c ] [-e ] [-F]" - echo >&2 " $program [-sRdv] -l" - echo >&2 " $program -su" - echo >&2 " $program -h (this screen)" - echo >&2 "" - echo >&2 "Options:" - echo >&2 " -c CODE: set the country code (default: $lc_country)" - echo >&2 " -e NUM: set the base extension number (default: $base_exten)" - echo >&2 " -F: Don't print FXSs in zapata.conf" - echo >&2 " -l: output a list of detected channels instead of zaptel.conf" - echo >&2 " -d: Perform hardware detection" - echo >&2 " -u: Unload zaptel modules (will not restart Asterisk)." - echo >&2 " -v: verbose" - echo >&2 " -s: Stop Asterisk before running, and start it at the end." - echo >&2 " -R: Don't restart asterisk in the end." - echo >&2 " -z: also generate zapscan.conf for the asterisk GUI." -} - -# print /etc/asterisk/zapscan.conf for the Asterisk-GUI -# $1: port type. Currently only fxs/fxo . Note that this is the type, and -# not the signalling (which would be the fxo fir an fxs port. -# $2: port number. Probably a range of ports is also allowed. -print_zapscan_port () { - if [ "$do_gen_zapscan" != 'yes' ]; then return 0; fi - - echo " -[$2] -port=$1 -" >>$zapscan_file -} - -# $1: channel number -print_pattern() { - local astbank_type='' - local reset_values="" - OPTIND=1 - while getopts 'a:' arg - do - case "$arg" in - a) case "$OPTARG" in input|output) astbank_type=$OPTARG;;esac ;; - esac - done - shift $(( $OPTIND-1 )) - - - local chan=$1 - local sig=$2 #fxs/fxo - local mode=$3 - local method - - if [ "$sig" = 'fxs' ]; then - # Coutries in which we need to use busydetect: - # United Arab Emirats, Israel, Slovenia - case "$lc_country" in - ae|il|si) - method=ls - ;; - *) - method=ks - ;; - esac - else - method="$fxs_default_start" - fi - case "$sig" in - fxs) sig_name=FXO;; - fxo) sig_name=FXS;; - esac - case "$mode" in - list) - echo $chan $sig_name $astbank_type;; - files) - # sadly, both input ports and output ports go into the same span as - # the FXS ports. Thus we need to separate between them. See also - # the zapata.conf section: - - echo ";;; line=\"$line\"" >> $zapata_file - - if [ "$astbank_type" != '' ]; - then echo "# astbanktype: $astbank_type" >>$zaptel_file; - fi - echo "${sig}$method=$chan" >>$zaptel_file - # zap2amp will rewrite those from zaptel.conf and hints there - if [ "$fxsdisable" = 'yes' ] && [ "$sig" = 'fxo' ]; then return; fi - - echo "signalling=${sig}_$method" >>$zapata_file - if [ "$sig" = 'fxo' ] - then - # to preconfigure channel 1's extension to 550, set - # chan_1_exten=550 - # in, e.g, /etc/default/zaptel - var_name=`echo chan_${chan}_exten` - cfg_exten=`echo ${!var_name} | tr -d -c 0-9` - var_name=`echo chan_${chan}_vmbox` - cfg_vmbox=`echo ${!var_name} | tr -d -c 0-9` - var_name=`echo chan_${chan}_cntxt` - cfg_cntxt=`echo ${!var_name} | tr -d -c 0-9` - - if [ "$cfg_exten" = '' ] - then # No extension number set for this channel - exten=$(($chan+$base_exten)) - else # use the pre-configured extension number - exten=$cfg_exten - fi - # is there any real need to set 'mailbox=' ? - if [ "x$cfg_vmbox" = x ] - then # No extension number set for this channel - vmbox=$exten - else # use the pre-configured extension number - vmbox=$cfg_vmbox - fi - echo "callerid=\"Channel $chan\" <$exten>" >> $zapata_file - reset_values="$reset_values callerid" - echo "mailbox=$exten" >> $zapata_file - reset_values="$reset_values mailbox" - if [ "$group_manual" != "yes" ] - then - echo "group=$group_phones" >> $zapata_file - reset_values="$reset_values group" - fi - if [ "$context_manual" != "yes" ] - then - if [ "$astbank_type" != '' ]; - then - context_var_name=context_$astbank_type - echo context=${!context_var_name} >> $zapata_file - else - echo "context=$context_phones" >> $zapata_file - fi - reset_values="$reset_values context" - fi - else # this is an FXO (trunk/phone: FXO signalling) - # we have may have set it. So reset it: - echo "callerid=asreceived" >> $zapata_file - if [ "$group_manual" != "yes" ] - then - echo "group=$group_lines" >> $zapata_file - fi - if [ "$context_manual" != "yes" ] - then - echo "context=$context_lines" >> $zapata_file - reset_values="$reset_values context" - fi - if [ "$lc_country" = 'uk' ] - then - echo "cidsignalling=v23" >> $zapata_file - case $line in - *WCFXO*) echo "cidstart=history" >> $zapata_file;; - *) echo "cidstart=polarity" >> $zapata_file;; - esac - reset_values="$reset_values cidsignalling cidstart" - fi - case "$line" in - *XPP_FXO*) - if [ "$xpp_fxo_rxgain" != '' ]; then - echo "rxgain=$xpp_fxo_rxgain" >> $zapata_file - reset_values="$reset_values rxgain" - fi - ;; - esac - # if kewlstart is not used, busydetect has to be employed: - if [ "$method" = 'ls' ] - then - echo 'busydetect=yes' >> $zapata_file - reset_values="$reset_values busydetect" - fi - fi - - if [ "$astbank_type" = 'input' ] || \ - ( [ "$fxs_immediate" = 'yes' ] && [ "$sig" = "fxo" ] ) - then - echo 'immediate=yes' >> $zapata_file - reset_values="$reset_values immediate" - fi - echo "channel => $chan" >> $zapata_file - reset_zapata_entry $zapata_file $reset_values - echo "" >> $zapata_file - - print_zapscan_port "$sig" "$chan" - ;; - esac - -} - -# the number of channels from /proc/zaptel -# must always print a number as its output. -count_proc_zap_lines() { - # if zaptel is not loaded there are 0 channels: - if [ ! -d /proc/zaptel ]; then echo '0'; return; fi - - ( - for file in `echo /proc/zaptel/* |grep -v '\*'` - do sed -e 1,2d $file # remove the two header lines - done - ) | wc -l # the total number of lines -} - -load_modules() { - say "Test Loading modules:" - for i in $ALL_MODULES - do - lines_before=`count_proc_zap_lines` - args="${i}_args" - eval "args=\$$args" - # a module is worth listing if it: - # a. loaded successfully, and - # b. added channels lines under /proc/zaptel/* - if /sbin/modprobe $i $args 2> /dev/null - then - check=0 - case "$i" in - xpp_usb) check=`grep 'STATUS=connected' 2>/dev/null /proc/xpp/xbuses | wc -l` ;; - *) if [ $lines_before -lt `count_proc_zap_lines` ]; then check=1; fi ;; - esac - if [ "$check" != 0 ] - then - probed_modules="$probed_modules $i" - say " ok $i $args" - else - say " - $i $args" - rmmod $i - fi - else - say " - $i $args" - fi - done -} - -# recursively unload a module and its dependencies, if possible. -# where's modprobe -r when you need it? -# inputs: module to unload. -# returns: the result from -unload_module() { - module="$1" - line=`lsmod 2>/dev/null | grep "^$1 "` - if [ "$line" = '' ]; then return; fi # module was not loaded - - set -- $line - # $1: the original module, $2: size, $3: refcount, $4: deps list - mods=`echo $4 | tr , ' '` - # xpp_usb keeps the xpds below busy, and hence must be removed - # before them: - case "$module" in xpd_*) mods="xpp_usb $mods";; esac - for mod in $mods; do - # run in a subshell, so it won't step over our vars: - (unload_module $mod) - # TODO: the following is probably the error handling we want: - # if [ $? != 0 ]; then return 1; fi - done - rmmod $module -} - -unload_modules() { - say "Unloading zaptel modules:" - unload_module zaptel - say '' -} - -# sleep a while until the xpp modules fully register -wait_for_xpp() { - if [ -d /proc/xpp ] - then - # wait for the XPDs to register: - # TODO: improve error reporting and produce a messagee here - cat /proc/xpp/XBUS-*/waitfor_xpds 2>/dev/null >/dev/null || true - fi -} - -detect() { - unload_modules - temporary_zapconf save - load_modules - temporary_zapconf restore - modlist="$probed_modules" - modlist="$(echo $modlist)" # clean spaces - if [ "$do_module_list" = yes ] - then - update_module_list "$modlist" - fi - if echo $modlist | grep -q xpp_usb; then wait_for_xpp; fi -} - -# The module configuration generated by zaptel includes a totally useless -# automatic run of ztcfg after modules loading. As a workaround for that, -# we provide an empty zaptel.conf temporarily. -# -# At hardware detection time we shouldn't really touch zaptel.conf . So we -# must keep a copy of it somewhere. -# -# I use ZAPCONF_FILE_SYSTEM rather than ZAPCONF_FILE, as the bogus modprobe -# entries will not be initiated by us. -# -# ZAPCONF_FILE_TMP is a "global", as it needs to be preserved between the -# call to 'save' and to 'restore' -ZAPCONF_FILE_TMP= -temporary_zapconf() { - case "$1" in - save) - say "Temporarily moving zaptel.conf aside to work around broken modprobe.conf" - ZAPCONF_FILE_TMP=`mktemp /tmp/genzaptelconf-zaptel.conf-XXXXXX` || die "Error creating temporary zaptel.conf" - if [ -f $ZAPCONF_FILE_SYSTEM ]; then - cp -a $ZAPCONF_FILE_SYSTEM $ZAPCONF_FILE_TMP - fi - echo -n >$ZAPCONF_FILE_SYSTEM - ;; - restore) - # restore original zaptel.conf: - if [ "$ZAPCONF_FILE_TMP" = '' ]; then return; fi - mv $ZAPCONF_FILE_TMP $ZAPCONF_FILE_SYSTEM - ZAPCONF_FILE_TMP='' - ;; - esac -} - -# run after the channel's entry. Used to reset all the values -reset_zapata_entry() { - conf_file="$1"; shift - - for arg in "$@"; do - case "$arg" in - busydetect) echo "$arg=no" >>$conf_file;; - context) echo "$arg=default" >>$conf_file;; - immediate) echo "$arg=no" >>$conf_file;; - overlapdial) echo "$arg=no" >>$conf_file;; - rxgain) echo "$arg=0" >>$conf_file;; - txgain) echo "$arg=0" >>$conf_file;; - *) echo "$arg=" >>$conf_file;; - esac - done -} - - -# we need to preserve the permissions of existing configurations files. -# However we also don't want to be left with incomplete configurations in -# case we are stopped in the middle. Thus we create a temporary file and -# mv it to the original file only when done. -# -# This function gives the temporary file the permissions of the original, -# or some sane defaults. -# -# The temporary file is generated here, and ths its name is passed through -# a variable whose name is passed as a parameter (new_var). -# -# $1: orig_cfg_file -# $2: new_var -gen_tmp_conf() { - orig_cfg_file=$1 - new_var=$2 - - # assign to new_var by reference: - eval $new_var=`mktemp /tmp/genzaptelconf-conf-XXXXXX` \ - || die "Unable to create temporary config file for $orig_cfg_file" - if [ -r "$orig_cfg_file" ]; then - chown --reference="$orig_cfg_file" ${!new_var} 2>/dev/null - chmod --reference="$orig_cfg_file" ${!new_var} 2>/dev/null - else - chmod 644 ${!new_var} - fi -} - -# Extract information from one digital channel (one line in a /proc/zaptel -# file). Information is saved to $tmp_dir/span_foo variables. -# FIXME: detection should move to when we know the number of channels -# and hence can tell between an E1 and a T1. -detect_digital_channel() { - line="$1" - chan_num="$2" - span_num="$3" - - # PRI/BRI channel - # Rather than identifying cards by the header line, we identify - # them by the channel names. This is shorter. - # This also allows us to count the channel numbers and check if - # we have a E1 span, a T1 span or a BRI span. - - # span_lastd is always the one before last - # channel. span_bchan is the last: - echo $chan_num >$tmp_dir/span_end - - if [ "`cat $tmp_dir/span_begin`" != "-1" ] - then - return #we already configured this span. - fi - - # Now we need to give initial configuration to the span - echo $chan_num >$tmp_dir/span_begin - echo $span_num >$tmp_dir/span_num - - case "$line" in - *ZTHFC*/* | *ztqoz*/* | *XPP_BRI_*/*) - # BRI channel - echo 'ccs' >$tmp_dir/span_framing - echo 'euroisdn' >$tmp_dir/span_switchtype - if [ "`cat $tmp_dir/span_termtype`" = 'nt' 2>/dev/null ] - then - echo $ZAPBRI_NET >$tmp_dir/span_signalling - else - echo $ZAPBRI_CPE >$tmp_dir/span_signalling - fi - ;; - *ztgsm*/*) - # Junghanns's GSM cards. - echo 'ccs' >$tmp_dir/span_framing - #Does this mean anything? - echo 'gsm' >$tmp_dir/span_signalling - ;; - *TE[24]/* | *WCT1/* | *Tor2/* | *TorISA/* | *WP[TE]1/* | \ - *R[124]T1/* | *XPP_[TEJ]1_*) - # FIXME: handle cwain around here. - # name: *cwain[12]/* . Always E1. - - # PRI span (E1/T1) - echo 'esf' >$tmp_dir/span_framing - echo 'b8zs' >$tmp_dir/span_coding - echo 'national' >$tmp_dir/span_switchtype - if [ "`cat $tmp_dir/span_termtype`" = 'nt' 2>/dev/null ] - then - echo pri_net >$tmp_dir/span_signalling - else - echo pri_cpe >$tmp_dir/span_signalling - fi - # an example of country-specific setup. This is probably not accurate - # Contributions are welcome - case "$lc_country" in - nl) - # (Just an example for per-country info) - echo 'ccs' >$tmp_dir/span_framing - echo 'ami' >$tmp_dir/span_coding - #echo 'crc4' >$tmp_dir/span_yellow - #echo 'euroisdn' >$tmp_dir/span_switchtype - #echo 'pri_cpe' >$tmp_dir/span_signalling - ;; - il|de|au) - echo 'ccs' >$tmp_dir/span_framing - echo 'hdb3' >$tmp_dir/span_coding - echo 'crc4' >$tmp_dir/span_yellow - echo 'euroisdn' >$tmp_dir/span_switchtype - ;; - cl) - echo 'ccs' >$tmp_dir/span_framing - echo 'hdb3' >$tmp_dir/span_coding - #echo 'crc4' >$tmp_dir/span_yellow - echo 'national' >$tmp_dir/span_switchtype - ;; - esac - ;; - esac -} - -# read information from the $tmp_dir/span_foo files and generate -# configuration for the span and its channels. -write_digital_config() { - # if the current file we checked was not of a digital span, we have - # nothing to do: - if [ "`cat $tmp_dir/span_begin`" = -1 ]; then return; fi - - # read files to variables: - for suffix in num begin end timing lbo framing \ - coding switchtype signalling yellow termtype - do - eval span_$suffix=`cat $tmp_dir/span_$suffix 2>/dev/null` - done - - # exactly the same logic is used in asterisk's chan_zap.c. - # also not that $(( )) is bash-specific - case "$((1+ $span_end - $span_begin))" in - 2|3|24) #ztgsm, BRI or T1 - dchan=$span_end - bchans="$span_begin-$(($span_end-1))" - ;; - 31) #E1 - dchan="$(($span_begin+15))" - bchans="$span_begin-$(($span_begin+14)),$(($span_begin+16))-$span_end" - if [ "$span_framing" = 'esf' ]; then - # don't leave an E1 span with defective defaults: - span_framing=ccs - span_coding=hdb3 - span_switchtype=euroisdn - span_yellow=crc4 - fi - ;; - esac - if [ "$span_yellow" != '' ]; then span_yellow=",$span_yellow"; fi - # Let's assume that a TE span should get the clock from the remote unit, - # and NT spans should provide timing. Just as a sane default. - # If we have several TE spans, the first will have priority 1, - # second: 2, etc. - case "$span_signalling" in *_cpe*) - span_timing=$span_te_timing_counter - span_te_timing_counter=$(($span_te_timing_counter + 1)) - ;; - esac - case "$mode" in - files) - echo span=$span_num,$span_timing,$span_lbo,$span_framing,$span_coding$span_yellow >> $zaptel_file - # leave a comment in zaptel.conf that allows to tell if - # this span is TE or NT: - if [ "$span_termtype" != '' ] - then echo "# termtype: $span_termtype" >>$zaptel_file - fi - - echo bchan=$bchans >>$zaptel_file - echo dchan=$dchan >>$zaptel_file - if [ "$fxsdisable" = 'yes' ] && [ "$span_termtype" = 'nt' ]; then return; fi - # You should not send content to zapata.conf below this line - - span_group=$(($SPAN_GROUP_BASE + $span_num)) - - if [ "$span_termtype" != '' ] - then - # an ISDN card's span that we know if it is in NT mode or TE mode. - # NT is the same as FXS for us and TE is the same as FXO - if [ "$span_termtype" = 'nt' ] - then - echo "callerid=\"Channels $span_begin - $span_end\" <$span_begin>" >> $zapata_file - reset_values="$reset_values callerid" - #echo "mailbox=$exten" - if [ "$brint_overlap" = 'yes' ] - then - echo "overlapdial=yes" >> $zapata_file - reset_values="$reset_values overlapdial" - fi - if [ "$group_manual" != "yes" ] - then - echo "group=$group_phones,$span_group" >> $zapata_file - reset_values="$reset_values group" - fi - if [ "$context_manual" != "yes" ] - then - echo "context=$context_phones" >> $zapata_file - fi - else - #echo "mailbox=" - if [ "$group_manual" != "yes" ] - then - echo "group=$group_lines,$span_group" >> $zapata_file - reset_values="$reset_values group" - fi - if [ "$context_manual" != "yes" ] - then - echo "context=$context_lines" >> $zapata_file - reset_values="$reset_values context" - fi - fi - fi - echo "switchtype = $span_switchtype" >> $zapata_file - echo "signalling = $span_signalling" >> $zapata_file - echo "channel => $bchans" >> $zapata_file - reset_zapata_entry $zapata_file $reset_values - reset_values= - ;; - list) - echo "### BRI/PRI: $span_termtype" - echo "$bchans Data" - echo "$dchan Control" - #echo BRI/PRI: chans: $bchans, control: $dchan - ;; - esac -} - -# This is where the actual detection configuration detection work happens. -genconf() { - local mode=$1 - local reset_values="" - -# spanlist=`echo /proc/zaptel/* | grep -v '\*'` -# spanlist=$(for i in `for i in /proc/zaptel/*; do if [ -f $i ]; then echo $i | cut -f 4 -d / ; fi; done | sort -n`; do echo -n "/proc/zaptel/$i "; done) -# spanlist=(cd /proc/zaptel; ls | sort -n | sed 's|^|/proc/zaptel/|') - spanlist=`ls /proc/zaptel/ 2>/dev/null | sort -n | sed 's|^|/proc/zaptel/|'` - - #if [ "$spanlist" == "" ]; then - # die "No zapata interfaces in /proc/zaptel" - #fi - - - case "$mode" in - files) - if [ "$do_gen_zapscan" = 'yes' ]; then - gen_tmp_conf "$ZAPSCAN_FILE" zapscan_file - cat <$zapscan_file -; zapscan.conf: information about detected zaptel channels -; (currently: analog only) -; -; Automatically generated by $0 -- Please do not edit. - -EOF - fi - gen_tmp_conf "$ZAPTEL_FILE" zaptel_file - gen_tmp_conf "$ZAPATA_FILE" zapata_file - cat <$zaptel_file -# Autogenerated by $0 -- do not hand edit -# Zaptel Configuration File -# -# This file is parsed by the Zaptel Configurator, ztcfg -# - -# It must be in the module loading order - -EOF - cat <$zapata_file -; Autogenerated by $0 -- do not hand edit -; Zaptel Channels Configurations (zapata.conf) -; -; This is not intended to be a complete zapata.conf. Rather, it is intended -; to be #include-d by /etc/zapata.conf that will include the global settings -; -EOF - ;; - esac - - # For each line in the spanlist: see if it represents a channel. - # if it does, test that the channel is usable. - # we do that by configuring it (using ztcfg with a 1-line config file) - # and then trying to read 1 byte from the device file. - # - # The '<(command)' syntax creates a temporary file whose content is is the - # output of 'command'. - # - # Another problem with such an approach is how to include an existing - # configuration file. For instance: how to include some default settings. - # - # Maybe an 'include' directive should be added to zaptel.conf ? - #cat $spanlist | - for procfile in $spanlist - do - span_num=`basename $procfile` - # the first line is the title line. It states the model name - # the second line is empty - title=`head -n 1 $procfile` - # stuff that needs to be remembered accross lines (for PRI/BRI support) - case "$mode" in - list) echo "### $title";; - files) - echo "" >>$zaptel_file - echo "# $title" >>$zaptel_file - echo "" >>$zapata_file - echo "; $title" >>$zapata_file - ;; - esac - echo '-1' >$tmp_dir/span_begin - echo '-1' >$tmp_dir/span_end - echo '0' >$tmp_dir/span_timing - echo '0' >$tmp_dir/span_lbo - echo '' >$tmp_dir/span_framing - echo 'ami' >$tmp_dir/span_coding - echo '' >$tmp_dir/span_switchtype - echo '' >$tmp_dir/span_signalling - if [ "$zapconf_def_termtype" != '' ] - then - echo "$zapconf_def_termtype" >$tmp_dir/span_termtype - fi - - # Check if ZapBRI cards are in TE or NT mode - if echo $title | egrep -q '((quad|octo)BRI PCI ISDN Card.* \[NT\]\ |octoBRI \[NT\] |HFC-S PCI A ISDN.* \[NT\] |Xorcom .* (BRI|T1|E1)_NT)' - then - echo 'nt' >$tmp_dir/span_termtype - elif echo $title | egrep -q '((quad|octo)BRI PCI ISDN Card.* \[TE\]\ |octoBRI \[TE\] |HFC-S PCI A ISDN.* \[TE\] |Xorcom .* (BRI|T1|E1)_TE)' - then - echo 'te' >$tmp_dir/span_termtype - fi - - # The rest of the lines are per-channel lines - sed -e 1,2d $procfile | \ - while read line - do - # in case this is a real channel. - chan_num=`echo $line |awk '{print $1}'` - case "$line" in - *WCTDM/* | *\ WRTDM/* | *OPVXA1200/*) - # TDM400P/2400P and similar cards (Sangoma A200, OpenVox A1200) - # this can be either FXS or FXO - maybe_fxs=0 - maybe_fxo=0 - $ztcfg_cmd -c <(echo fxoks=$chan_num) &>/dev/null && maybe_fxs=1 - $ztcfg_cmd -c <(echo fxsks=$chan_num) &>/dev/null && maybe_fxo=1 - if [ $maybe_fxs = 1 ] && [ $maybe_fxo = 1 ] - then - # An installed module won't accept both FXS and FXO signalling types: - # this is an empty slot. - # TODO: I believe that the Sangoma A20x will reject both and thus - # print nothing here. - echo "# channel $chan_num, WCTDM, no module." >> $zaptel_file - continue - fi - - if [ $maybe_fxs = 1 ]; then print_pattern $chan_num fxo $mode; fi - if [ $maybe_fxo = 1 ]; then print_pattern $chan_num fxs $mode; fi - ;; - *WCFXO/*) - # X100P - print_pattern $chan_num fxs $mode || \ - echo "# channel $chan_num, WCFXO, inactive." >>$zaptel_file - ;; - *WCUSB/*) - print_pattern $chan_num fxo $mode - ;; - *XPP_FXO/*) - # Astribank FXO span - print_pattern $chan_num fxs $mode - ;; - *XPP_FXS/*) - # Astribank FXS span (regular port) - print_pattern $chan_num fxo $mode - ;; - *' FXO'/*) - # FXO module (probably Rhino) - print_pattern $chan_num fxs $mode - ;; - *' FXS'/*) - # FXS module (probably Rhino) - print_pattern $chan_num fxo $mode - ;; - *' ---'/*) - # no module (probably Rhino) - continue - ;; - *XPP_OUT/*) - # Astribank FXS span (output port) - print_pattern -a output $chan_num fxo $mode - ;; - *XPP_IN/*) - # Astribank FXS span (input port) - print_pattern -a input $chan_num fxo $mode - ;; - *ZTHFC*/* | *ztqoz*/* |*ztgsm/* |*TE[24]/* | \ - *WCT1/*|*Tor2/* | *TorISA/* | \ - *XPP_BRI_*/* | *WP[TE]1/* | *R[124]T1/* | \ - *XPP_[TE]1*/* ) - detect_digital_channel "$line" "$chan_num" "$span_num" - ;; - '') ;; # Empty line (after span header) - *) - case "$mode" in - list) echo "# ??: $line";; - files) - echo "# ??: $line" >>$zaptel_file - echo "; ??: $line" >>$zapata_file - esac - ;; - esac - done - # end of part in sub-process. - - write_digital_config - done - - if [ "$mode" = 'files' ] - then - cat <> ${zaptel_file} - -# Global data - -loadzone = $loadzone -defaultzone = $defaultzone -EOF - fi - - if [ "$mode" = 'files' ]; then - mv ${ZAPCONF_FILE} ${ZAPCONF_FILE}.bak 2>/dev/null - mv $zaptel_file ${ZAPCONF_FILE} - mv ${ZAPATA_FILE} ${ZAPATA_FILE}.bak 2>/dev/nullk - mv $zapata_file ${ZAPATA_FILE} - if [ "$do_gen_zapscan" = 'yes' ]; then - mv $ZAPSCAN_FILE $ZAPSCAN_FILE.bak 2>/dev/null - mv $zapscan_file $ZAPSCAN_FILE - fi - - zapata_file_name=`basename $ZAPATA_FILE` - if ! grep -q "^#include.*$zapata_file_name" \ - /etc/asterisk/zapata.conf - then - say "Note: generated $ZAPATA_FILE not included in zapata.conf" - say "To fix: echo '#include $zapata_file_name' >>/etc/asterisk/zapata.conf" - fi - fi -} - -while getopts 'c:de:Fhlm:MRsuvz' arg -do - case "$arg" in - e) # guarantee that it is a number: - new_base_exten=`echo $OPTARG | tr -d -c 0-9` - if [ "x$new_base_exten" != x ]; then base_exten=$new_base_exten; fi - ;; - c) lc_country=`echo $OPTARG | tr -d -c a-z` ;; - d) do_detect=yes ;; - F) fxsdisable=yes;; - u) do_unload=yes ; force_stop_ast=yes ;; - v) verbose=yes ;; - l) mode='list' ;; - M) do_module_list=yes; do_detect=yes ;; - s) force_stop_ast=yes ;; - R) do_restart=no ;; - z) do_gen_zapscan=yes ;; - h) usage; exit 0;; - *) echo >&2 "unknown parameter -$arg, Aborting"; usage; exit 1;; - esac -done -shift $(( $OPTIND-1 )) -if [ $# != 0 ]; then - echo >&2 "$0: too many parameters" - usage - exit 1 -fi - -tmp_dir=`mktemp -d /tmp/genzaptelconf-dir-XXXXXX` || \ - die "$0: failed to create temporary directory. Aborting" - - -case "$lc_country" in - # the list was generated from the source of zaptel: - #grep '{.*[0-9]\+,.*"[a-z][a-z]"' zonedata.c | cut -d'"' -f 2 | xargs |tr ' ' '|' - us|au|fr|nl|uk|fi|es|jp|no|at|nz|it|gr|tw|cl|se|be|sg|il|br|hu|lt|pl|za|pt|ee|mx|in|de|ch|dk|cz|cn):;; - *) - lc_country=us - echo >&2 "unknown country-code $lc_country, defaulting to \"us\"" - ;; -esac -# any reason for loadzone and defaultzone to be different? If so, this is -# the place to make that difference -loadzone=$lc_country -defaultzone=$loadzone - -# make sure asterisk is not in our way -if [ "$force_stop_ast" = 'yes' ] -then - $ZAPCONF_ASTERISK_CMD stop 1>&2 -else - # if asterisk is running and we wanted to detect modules - # or simply to unload modules, asterisk needs to go away. - if ( [ "$do_unload" = yes ] || [ "$do_detect" = yes ] ) && \ - pidof asterisk >/dev/null - then - echo >&2 "Asterisk is already running. Configuration left untouched" - echo >&2 "You can use the option -s to shut down Asterisk for the" - echo >&2 "duration of the detection." - exit_cleanup 1 - fi -fi - -if [ "$do_unload" = yes ] -then - unload_modules - exit_cleanup $? -fi - -if [ "$do_detect" = yes ] -then - detect -fi - -if [ "$zapconf_use_perl" = yes ]; then - #redefine genconf to use perl utilities: - genconf() { - case "$1" in - list) zaptel_hardware ;; - files) zapconf ;; - esac - } -fi - -if [ "$mode" = list ]; then - genconf list -else - #zap_reg_xpp - xpp_startup - wait_for_zapctl - say "Generating '${ZAPCONF_FILE} and ${ZAPATA_FILE}'" - genconf files - run_ztcfg -fi - -if [ "$tmp_dir" != '' ] -then - rm -rf "$tmp_dir" -fi - -if [ "$force_stop_ast" != 'yes' ] || [ "$do_restart" != 'yes' ] -then - exit_cleanup 0 -fi - -if [ -x "$ZAPCONF_ASTERISK_SCRIPT" ] -then - $ZAPCONF_ASTERISK_CMD start 1>&2 -fi - -# if in verbose mode: verify that asterisk is running -if [ "$verbose" != 'no' ] - then - say "Checking channels configured in Asterisk:" - sleep 1 # give it some time. This is enough on our simple test server - if [ -x ast-cmd ] - then - ast-cmd cmd "zap show channels" - else - asterisk -rx "zap show channels" - fi -fi - -# vim:ts=8: diff --git a/xpp/utils/genzaptelconf.8 b/xpp/utils/genzaptelconf.8 deleted file mode 100644 index c3f6f73..0000000 --- a/xpp/utils/genzaptelconf.8 +++ /dev/null @@ -1,326 +0,0 @@ -.TH GENZAPTELCONF 8 "July 18th, 2005" "Xorcom Rapid Asterisk" "Linux Programmer's Manual" -.SH "NAME" -.B genzaptelconf --- generates zaptel configuration (TDM adaptors) -.SH SYNOPSIS -.PP -.B genzaptelconf -[-sRdvzF] [-c ] [-e ] - -.B genzaptelconf -[-sRdv] -l -- only list to standard output - -.B genzaptelconf --su -- only unload zaptel modules - -.B genzaptelconf --h -- Help screen - -.SH DESCRIPTION -.B genzaptelconf -is a script to detect zaptel devices (currently mostly TDM cards are -supported). It generates both -.I /etc/zaptel.conf -and -.I /etc/asterisk/zapata-channels.conf - -.I PRI -and -.I BRI -(with ZapBRI) cards are basically identified as well. However the span -configiration is a default that I only hope is sane. Looking for feedback - -.SH OPTIONS -.B -c -.I country_code -.RS -A two-letter country code. Sets the country-code for the zonezone -entries in -.I zaptel.conf -, The default is the value of -.I lc_country -from -.I /etc/default/zaptel -and failing that, "us". -.RE - -.B -d -.RS -Also try to detect modules. Unloads all zaptel modules and loads them -one by one. Considers a module useful if it loaded successfully and if -loading it has generated at least one zapata channel. - -The list of detected modules is written as the value of -.I ZAPTEL_MODS -in -.I /etc/default/zaptel -.RE - -.B -e -.I base_exten_num -.RS -Configure channel -.I i -as extension -.I exten_num -+ -.I i - . This is mostly for the caller-id values. Crude, but may be good enough. -See also -.I -r -.RE - -.B -F -.RS -Disable writing FXS extensions in zapata.conf -.RE - -.B -l -.RS -Only list deceted channels and their signalling. Don't write -configuration files. Note, however that -.I -ld -will still rewrite the modules line in -.I /etc/default/zaptel -(see -.I -d -above). -.RE - -.B -M -.RS -Update -.I /etc/modules -with a list of our modules, thereby -triggers their loading via modprobe on the next boot. - -This triggers the -.I -d -option as well. -.RE - -.B -R -.RS -Don't restart asterisk even if it was stopped using -.I -s - . -.RE - -.B -s -.RS -Stop asterisk for the duration of the test. The detection will only -work if nobody uses the zaptel channels: - -* To allow unloading of modules - -* to allow reading configuration files. - -This option tells the script to stop asterisk (if it was running) and to -try to start it after the end of the test. -.RE - -.B -v -.RS -Be verbose. lists the detected modules if -.I -d -is used. Lists detected channls. In the end tries to connect to asterisk -to get a list of configured zaptel channels. -.RE - -.B -z -.RS -emulate the operation of zapscan.bin: generate -.I /etc/asterisk/zapscan.conf -with the results of the scan. -.RE - -.SH CONFIGURATION -Look at the beginning of the script for a number of variables that can -be overriden through the configuraion file. Some variables can also be -overriden through the environment. The configuration file is sourced by -bash but for compatibility expected to have only 'var=VALUE' lines and -comments or empty lines. - -The configuration will first be read from -.I /etc/default/zaptel -if it exists, and -.I /etc/sysconfig/zaptel -otherwise (But those file names may be overriden, see -.I ZAPTEL_BOOT_DEBIAN -and -.I ZAPTEL_BOOT_FEDORA -below). Variables set in those files will override the default settings -and setting rom the environment. - -The following variables may be set from the environment: -ZAPCONF_FILE, ZAPATA_FILE, ZAPTEL_BOOT_DEBIAN, ZAPTEL_BOOT_FEDORA, -DEVZAP_TIMEOUT, ZTCFG - -.RS -.I lc_country -.RS -The default country. Can be also overriden by the option -c -.RE - -.I base_exten -.RS -The base number used for automatic numbering -.RE - -.I context_manual -.RS -If set to 'yes', no context changes are made in zapata-channels.conf -.RE - -.I context_lines -.RS -The context into which calls will go from zaptel trunks. -.RE - -.I context_phones -.RS -The context into which calls will go from zaptel phones. -.RE - -.I context_manual -.RS -If set to 'yes', no group settings are made in zapata-channels.conf -.RE - -.I group_lines -.RS -The group number for zaptel trunks. -.RE - -.I group_phones -.RS -The group number for zaptel phones. -.RE - -.I ALL_MODULES -.RS -modules list. Used for unloading and modules detection. The order of modules -is the same for both. -.RE - -.I ZAPCONF_FILE -.RS -ztcfg's configuration file. The sane default is /etc/zaptel.conf . -.RE - -.I ZAPATA_FILE -.RS -The generated partial zapata.conf snippet. Default: -/etc/asterisk/zapata-channels.conf . -.RE - -.I ZAPTEL_BOOT_DEBIAN -.RS -The Debian Zaptel defaults file. Normally -.I /etc/default/zaptel -. -.RE - - -.I ZAPTEL_BOOT_FEDORA -.RS -The Zaptel defaults file on various other distributions. Normally -.I /etc/sysconfig/zaptel - . -.RE - -.I DEVZAP_TIMEOUT -.RS -Maximal number of seconds to wait for /dev/zap to be initializaed by -udev. -.RE - -.I ZTCFG -.RS -The full path to the ztcfg tool. Default: -.I /sbin/ztcfg -genzaptelconf will also explicitly test for -.I /usr/sbin/ztcfg -as a last resort. -.RE -.RE - -.SH FILES -.I /etc/zaptel.conf -.RS -The configuration file used by -.I ztcfg -to configure zaptel devices. re-written by -.I genzaptelconf - . A backup copy is saved to -.I /etc/zaptel.conf.bak - . -.RE - -.I /etc/asterisk/zapata.conf -.RS -The configuration file of Asterisk's -.I chan_zap. -Not modified directly by -.I genzaptelconf. -If you want genzaptelconf's setting to take effect, add the following -line at the end of -.I zapata.conf: -.RS -#include "zapata-channels.conf" -.RE -.RE - -.I /etc/asterisk/zapata-channels.conf -.RS -This is the snippet of -.I chan_zap -configuration file that -.I genzaptelconf generates. - . A backup copy is saved to -.I /etc/asterisk/zapata-channels.conf.bak - . -.RE - -.I /etc/default/zaptel -.RS -This file holds configuration for both -.I genzaptelconf -and -.I /etc/init.d/zaptel . -It is sourced by both scripts and can thus be used to override settings -of variables from those scripts. -.RE - -.I /etc/modules -.RS -A debian-specific list of kernel modules to be loaded by modprobe at -boot time. When the option -.I -d -(detect) is used, genzaptelconf will write in this file zaptel modules -to be loaded. If you want to use a different file, set -.I MOD_FILELIST - . If it is rewritten, a backup copy is saved to -.I /etc/modules.bak - . -.RS -The backup copy of -.I /etc/modules -.RE - -.SH "SEE ALSO" -ztcfg(8) asterisk(8). - -.SH BUGS -If you override a configuration variable both through the environment -and through the configuration file, the value from the configuration -file wins. - -.SH "AUTHOR" -This manual page was written by Tzafrir Cohen -Permission is granted to copy, distribute and/or modify this document under -the terms of the GNU General Public License, Version 2 any -later version published by the Free Software Foundation. - -On Debian systems, the complete text of the GNU General Public -License can be found in /usr/share/common-licenses/GPL. diff --git a/xpp/utils/hexfile.c b/xpp/utils/hexfile.c deleted file mode 100644 index 2a01b3f..0000000 --- a/xpp/utils/hexfile.c +++ /dev/null @@ -1,567 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include "hexfile.h" - -static const char rcsid[] = "$Id$"; - -static parse_hexfile_report_func_t report_func = NULL; - -parse_hexfile_report_func_t parse_hexfile_set_reporting(parse_hexfile_report_func_t rf) -{ - parse_hexfile_report_func_t old_rf = report_func; - report_func = rf; - return old_rf; -} - -static void chomp(char buf[]) -{ - size_t last = strlen(buf) - 1; - while(last >= 0 && isspace(buf[last])) - buf[last--] = '\0'; -} - -static int hexline_checksum(struct hexline *hexline) -{ - unsigned int i; - unsigned int chksm = 0; - int ll = hexline->d.content.header.ll; - - for(i = 0; i <= sizeof(hexline->d.content.header) + ll; i++) { - chksm += hexline->d.raw[i]; - } - return chksm & 0xFF; -} - -int dump_hexline(int recordno, struct hexline *line, FILE *fp) -{ - uint8_t ll; - uint16_t offset; - uint8_t tt; - uint8_t old_chksum; - uint8_t new_chksum; - uint8_t *data; - unsigned int i; - - ll = line->d.content.header.ll; - offset = line->d.content.header.offset; - tt = line->d.content.header.tt; - fprintf(fp, ":%02X%04X%02X", ll, offset, tt); - data = line->d.content.tt_data.data; - for(i = 0; i < ll; i++) { - fprintf(fp, "%02X", data[i]); - } - old_chksum = data[ll]; - data[ll] = 0; - new_chksum = 0xFF - hexline_checksum(line) + 1; - data[ll] = old_chksum; - fprintf(fp, "%02X\n", new_chksum); - if(new_chksum != old_chksum) { - if(report_func) - report_func(LOG_ERR, "record #%d: new_chksum(%02X) != old_chksum(%02X)\n", - recordno, new_chksum, old_chksum); - return 0; - } - return 1; -} - -struct hexline *new_hexline(uint8_t datalen, uint16_t offset, uint8_t tt) -{ - struct hexline *hexline; - size_t allocsize; - - allocsize = sizeof(struct hexline) + datalen + 1; /* checksum byte */ - if((hexline = malloc(allocsize)) == NULL) { - if(report_func) - report_func(LOG_ERR, "No more memory\n"); - return NULL; - } - memset(hexline, 0, allocsize); - hexline->d.content.header.ll = datalen; - hexline->d.content.header.offset = offset; - hexline->d.content.header.tt = tt; - return hexline; -} - -static int append_hexline(struct hexdata *hexdata, char *buf) -{ - int ret; - unsigned int ll, offset, tt; - char *p; - struct hexline *hexline; - unsigned int i; - - if(hexdata->got_eof) { - if(report_func) - report_func(LOG_ERR, "Extranous data after EOF record\n"); - return -EINVAL; - } - if(hexdata->last_line >= hexdata->maxlines) { - if(report_func) - report_func(LOG_ERR, "Hexfile too large (maxline %d)\n", hexdata->maxlines); - return -ENOMEM; - } - ret = sscanf(buf, "%02X%04X%02X", &ll, &offset, &tt); - if(ret != 3) { - if(report_func) - report_func(LOG_ERR, "Bad line header (only %d items out of 3 parsed)\n", ret); - return -EINVAL; - } - switch(tt) { - case TT_DATA: - break; - case TT_EOF: - if(ll != 0) { - if(report_func) - report_func(LOG_ERR, - "%d: Record %d(EOF): Bad len = %d\n", - hexdata->last_line, tt, ll); - return -EINVAL; - } - if(offset != 0) { - if(report_func) - report_func(LOG_ERR, - "%d: Record %d(EOF): Bad offset = %d\n", - hexdata->last_line, tt, offset); - return -EINVAL; - } - hexdata->got_eof = 1; - break; - case TT_EXT_SEG: - if(ll != 2) { - if(report_func) - report_func(LOG_ERR, - "%d: Record %d(EXT_SEG): Bad len = %d\n", - hexdata->last_line, tt, ll); - return -EINVAL; - } - if(offset != 0) { - if(report_func) - report_func(LOG_ERR, - "%d: Record %d(EXT_SEG): Bad offset = %d\n", - hexdata->last_line, tt, offset); - return -EINVAL; - } - break; - case TT_START_SEG: - if(ll != 4) { - if(report_func) - report_func(LOG_ERR, - "%d: Record %d(START_SEG): Bad len = %d\n", - hexdata->last_line, tt, ll); - return -EINVAL; - } - if(offset != 0) { - if(report_func) - report_func(LOG_ERR, - "%d: Record %d(START_SEG): Bad offset = %d\n", - hexdata->last_line, tt, offset); - return -EINVAL; - } - break; - case TT_EXT_LIN: - if(ll != 2) { - if(report_func) - report_func(LOG_ERR, - "%d: Record %d(EXT_LIN): Bad len = %d\n", - hexdata->last_line, tt, ll); - return -EINVAL; - } - if(offset != 0) { - if(report_func) - report_func(LOG_ERR, - "%d: Record %d(EXT_LIN): Bad offset = %d\n", - hexdata->last_line, tt, ll); - return -EINVAL; - } - break; - case TT_START_LIN: /* Unimplemented */ - if(ll != 4) { - if(report_func) - report_func(LOG_ERR, - "%d: Record %d(EXT_LIN): Bad len = %d\n", - hexdata->last_line, tt, ll); - return -EINVAL; - } - if(offset != 0) { - if(report_func) - report_func(LOG_ERR, - "%d: Record %d(EXT_LIN): Bad offset = %d\n", - hexdata->last_line, tt, ll); - return -EINVAL; - } - break; - default: - if(report_func) - report_func(LOG_ERR, "%d: Unimplemented record type %d: %s\n", - hexdata->last_line, tt, buf); - return -EINVAL; - } - buf += 8; /* Skip header */ - if((hexline = new_hexline(ll, offset, tt)) == NULL) { - if(report_func) - report_func(LOG_ERR, "No more memory for hexfile lines\n"); - return -EINVAL; - } - p = buf; - for(i = 0; i < ll + 1; i++) { /* include checksum */ - unsigned int val; - - if((*p == '\0') || (*(p+1) == '\0')) { - if(report_func) - report_func(LOG_ERR, "Short data string '%s'\n", buf); - return -EINVAL; - } - ret = sscanf(p, "%02X", &val); - if(ret != 1) { - if(report_func) - report_func(LOG_ERR, "Bad data byte #%d\n", i); - return -EINVAL; - } - hexline->d.content.tt_data.data[i] = val; - p += 2; - } - if(hexline_checksum(hexline) != 0) { - if(report_func) { - report_func(LOG_ERR, "Bad checksum (%d instead of 0)\n", - hexline_checksum(hexline)); - dump_hexline(hexdata->last_line, hexline, stderr); - } - return -EINVAL; - } - hexdata->lines[hexdata->last_line] = hexline; - if(hexdata->got_eof) - return 0; - hexdata->last_line++; - return 1; -} - -void free_hexdata(struct hexdata *hexdata) -{ - if(hexdata) { - unsigned int i; - - for(i = 0; i < hexdata->maxlines; i++) - if(hexdata->lines[i] != NULL) - free(hexdata->lines[i]); - free(hexdata); - } -} - -int dump_hexfile(struct hexdata *hexdata, const char *outfile) -{ - FILE *fp; - unsigned int i; - - if(report_func) - report_func(LOG_INFO, "Dumping hex data into '%s'\n", outfile); - if(!outfile || strcmp(outfile, "-") == 0) - fp = stdout; - else if((fp = fopen(outfile, "w")) == NULL) { - perror(outfile); - exit(1); - } - for(i = 0; i <= hexdata->last_line; i++) { - struct hexline *line = hexdata->lines[i]; - if(!line) { - if(report_func) - report_func(LOG_ERR, "Missing line at #%d\n", i); - return -EINVAL; - } - if(!dump_hexline(i, line, fp)) - return -EINVAL; - } - return 0; -} - -int dump_hexfile2(struct hexdata *hexdata, const char *outfile, uint8_t maxwidth) -{ - FILE *fp; - uint8_t tt; - unsigned int i; - struct hexline *line; - - if(report_func) - report_func(LOG_INFO, - "Dumping hex data into '%s' (maxwidth=%d)\n", - outfile, maxwidth); - if(!outfile || strcmp(outfile, "-") == 0) - fp = stdout; - else if((fp = fopen(outfile, "w")) == NULL) { - perror(outfile); - exit(1); - } - if(maxwidth == 0) - maxwidth = UINT8_MAX; - for(i = 0; i <= hexdata->last_line; i++) { - int bytesleft = 0; - int extra_offset = 0; - int base_offset; - uint8_t *base_data; - - line = hexdata->lines[i]; - if(!line) { - if(report_func) - report_func(LOG_ERR, "Missing line at #%d\n", i); - return -EINVAL; - } - bytesleft = line->d.content.header.ll; - /* split the line into several lines */ - tt = line->d.content.header.tt; - base_offset = line->d.content.header.offset; - base_data = line->d.content.tt_data.data; - while (bytesleft > 0) { - struct hexline *extraline; - uint8_t new_chksum; - unsigned int curr_bytes = (bytesleft >= maxwidth) ? maxwidth : bytesleft; - - /* generate the new line */ - if((extraline = new_hexline(curr_bytes, base_offset + extra_offset, tt)) == NULL) { - if(report_func) - report_func(LOG_ERR, "No more memory for hexfile lines\n"); - return -EINVAL; - } - memcpy(extraline->d.content.tt_data.data, base_data + extra_offset, curr_bytes); - new_chksum = 0xFF - hexline_checksum(extraline) + 1; - extraline->d.content.tt_data.data[curr_bytes] = new_chksum; - /* print it */ - dump_hexline(i, extraline, fp); - /* cleanups */ - free(extraline); - extra_offset += curr_bytes; - bytesleft -= curr_bytes; - } - } - if(tt != TT_EOF) { - if(report_func) - report_func(LOG_ERR, "Missing EOF record\n"); - return -EINVAL; - } - dump_hexline(i, line, fp); - return 0; -} - -void process_comment(struct hexdata *hexdata, char buf[]) -{ - char *dollar_start; - char *dollar_end; - const char id_prefix[] = "Id: "; - char tmp[BUFSIZ]; - char *p; - int len; - - if(report_func) - report_func(LOG_INFO, "Comment: %s\n", buf + 1); - /* Search for RCS keywords */ - if((dollar_start = strchr(buf, '$')) == NULL) - return; - if((dollar_end = strchr(dollar_start + 1, '$')) == NULL) - return; - /* Crop the '$' signs */ - len = dollar_end - dollar_start; - len -= 2; - memcpy(tmp, dollar_start + 1, len); - tmp[len] = '\0'; - p = tmp; - if(strstr(tmp, id_prefix) == NULL) - return; - p += strlen(id_prefix); - if((p = strchr(p, ' ')) == NULL) - return; - p++; - snprintf(hexdata->version_info, BUFSIZ, "%s", p); - if((p = strchr(hexdata->version_info, ' ')) != NULL) - *p = '\0'; -} - -struct hexdata *parse_hexfile(const char *fname, unsigned int maxlines) -{ - FILE *fp; - struct hexdata *hexdata = NULL; - int datasize; - char buf[BUFSIZ]; - int line; - int dos_eof = 0; - int ret; - - assert(fname != NULL); - if(report_func) - report_func(LOG_INFO, "Parsing %s\n", fname); - datasize = sizeof(struct hexdata) + maxlines * sizeof(char *); - hexdata = (struct hexdata *)malloc(datasize); - if(!hexdata) { - if(report_func) - report_func(LOG_ERR, "Failed to allocate %d bytes for hexfile contents\n", datasize); - goto err; - } - memset(hexdata, 0, datasize); - hexdata->maxlines = maxlines; - if((fp = fopen(fname, "r")) == NULL) { - if(report_func) - report_func(LOG_ERR, "Failed to open hexfile '%s'\n", fname); - goto err; - } - for(line = 1; fgets(buf, BUFSIZ, fp); line++) { - if(dos_eof) { - if(report_func) - report_func(LOG_ERR, "%s:%d - Got DOS EOF character before true EOF\n", fname, line); - goto err; - } - if(buf[0] == 0x1A && buf[1] == '\0') { /* DOS EOF char */ - dos_eof = 1; - continue; - } - chomp(buf); - if(buf[0] == '\0') { - if(report_func) - report_func(LOG_ERR, "%s:%d - Short line\n", fname, line); - goto err; - } - if(buf[0] == '#') { - process_comment(hexdata, buf); - continue; - } - if(buf[0] != ':') { - if(report_func) - report_func(LOG_ERR, "%s:%d - Line begins with 0x%X\n", fname, line, buf[0]); - goto err; - } - if((ret = append_hexline(hexdata, buf + 1)) < 0) { - if(report_func) - report_func(LOG_ERR, "%s:%d - Failed parsing.\n", fname, line); - goto err; - } - } - fclose(fp); - if(report_func) - report_func(LOG_INFO, "%s parsed OK\n", fname); - return hexdata; -err: - free_hexdata(hexdata); - return NULL; -} - -void dump_binary(struct hexdata *hexdata, const char *outfile) -{ - FILE *fp; - unsigned int i; - size_t len; - - if(report_func) - report_func(LOG_INFO, "Dumping binary data into '%s'\n", outfile); - if((fp = fopen(outfile, "w")) == NULL) { - perror(outfile); - exit(1); - } - for(i = 0; i < hexdata->maxlines; i++) { - struct hexline *hexline = hexdata->lines[i]; - - if(!hexline) - break; - switch(hexline->d.content.header.tt) { - case TT_EOF: - if(report_func) - report_func(LOG_INFO, "\ndump: good EOF record"); - break; - case TT_DATA: - if(report_func) - report_func(LOG_INFO, "dump: %6d\r", i); - len = hexline->d.content.header.ll; - if(fwrite(hexline->d.content.tt_data.data, 1, len, fp) != len) { - perror("write"); - exit(1); - } - break; - case TT_EXT_SEG: - case TT_START_SEG: - case TT_EXT_LIN: - case TT_START_LIN: - if(report_func) - report_func(LOG_INFO, - "\ndump(%d): ignored record type %d", - i, hexline->d.content.header.tt); - break; - default: - if(report_func) - report_func(LOG_ERR, "dump: Unknown record type %d\n", - hexline->d.content.header.tt); - exit(1); - } - } - if(report_func) - report_func(LOG_INFO, "\nDump finished\n"); - fclose(fp); -} - -void gen_hexline(const uint8_t *data, uint16_t addr, size_t len, FILE *output) -{ - struct hexline *hexline; - - if(!data) { - fprintf(output, ":%02X%04X%02XFF\n", 0, 0, TT_EOF); - return; - } - if((hexline = new_hexline(len, addr, (!data) ? TT_EOF : TT_DATA)) == NULL) { - if(report_func) - report_func(LOG_ERR, "No more memory\n"); - return; - } - if(data) - memcpy(&hexline->d.content.tt_data, data, len); - dump_hexline(0, hexline, output); - free(hexline); -} - -/* - * Algorithm lifted of sum(1) implementation from coreutils. - * We chose the default algorithm (BSD style). - */ -int bsd_checksum(struct hexdata *hexdata) -{ - unsigned int i; - size_t len; - int ck = 0; - - for(i = 0; i < hexdata->maxlines; i++) { - struct hexline *hexline = hexdata->lines[i]; - unsigned char *p; - - if(!hexline) - break; - if(hexline->d.content.header.tt == TT_EOF) - continue; - len = hexline->d.content.header.ll; - p = hexline->d.content.tt_data.data; - for(; len; p++, len--) { - ck = (ck >> 1) + ((ck & 1) << 15); - ck += *p; - ck &= 0xffff; /* Keep it within bounds. */ - } - } - return ck; -} diff --git a/xpp/utils/hexfile.h b/xpp/utils/hexfile.h deleted file mode 100644 index f8bf6a9..0000000 --- a/xpp/utils/hexfile.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef PARSE_HEXFILE_H -#define PARSE_HEXFILE_H - -#include - -/* - * Some portability workarounds - */ -#ifdef _WINDOWS - -#include /* for UCHAR USHORT */ -typedef UCHAR uint8_t; -typedef USHORT uint16_t; -#define PACKED -#define sscanf sscanf_s -#define ZERO_SIZE 1 - -/* From /usr/include/syslog.h */ -#define LOG_EMERG 0 /* system is unusable */ -#define LOG_ALERT 1 /* action must be taken immediately */ -#define LOG_CRIT 2 /* critical conditions */ -#define LOG_ERR 3 /* error conditions */ -#define LOG_WARNING 4 /* warning conditions */ -#define LOG_NOTICE 5 /* normal but significant condition */ -#define LOG_INFO 6 /* informational */ -#define LOG_DEBUG 7 /* debug-level messages */ - -#ifdef __cplusplus -# define __BEGIN_DECLS extern "C" { -# define __END_DECLS } -#else -# define __BEGIN_DECLS -# define __END_DECLS -#endif - -#elif __GNUC__ - -#include -#include -#define PACKED __attribute__((packed)) -#define ZERO_SIZE 1 - -#else - -#error "Cannot compile on this platform" - -#endif - -/* Record types in hexfile */ -enum { - TT_DATA = 0, - TT_EOF = 1, - TT_EXT_SEG = 2, - TT_START_SEG = 3, - TT_EXT_LIN = 4, - TT_START_LIN = 5, - TT_NO_SUCH_TT -}; - -#pragma pack(1) -struct hexline { - union { - uint8_t raw[ZERO_SIZE]; - struct content { - struct header { - uint8_t ll; /* len */ - uint16_t offset; /* offset */ - uint8_t tt; /* type */ - } PACKED header; - struct tt_data { - uint8_t data[ZERO_SIZE]; - } tt_data; - } PACKED content; - } d; -} PACKED; -#pragma pack() - -struct hexdata { - unsigned int maxlines; - unsigned int last_line; - int got_eof; - char version_info[BUFSIZ]; - struct hexline *lines[ZERO_SIZE]; -}; - - -__BEGIN_DECLS - -typedef void (*parse_hexfile_report_func_t)(int level, const char *msg, ...); - -parse_hexfile_report_func_t parse_hexfile_set_reporting(parse_hexfile_report_func_t rf); -void free_hexdata(struct hexdata *hexdata); -struct hexdata *parse_hexfile(const char *fname, unsigned int maxlines); -int dump_hexfile(struct hexdata *hexdata, const char *outfile); -int dump_hexfile2(struct hexdata *hexdata, const char *outfile, uint8_t maxwidth); -void dump_binary(struct hexdata *hexdata, const char *outfile); -void gen_hexline(const uint8_t *data, uint16_t addr, size_t len, FILE *output); -int bsd_checksum(struct hexdata *hexdata); -__END_DECLS - -#endif diff --git a/xpp/utils/lszaptel b/xpp/utils/lszaptel deleted file mode 100755 index a836d98..0000000 --- a/xpp/utils/lszaptel +++ /dev/null @@ -1,108 +0,0 @@ -#! /usr/bin/perl -w -# -# Written by Oron Peled -# Copyright (C) 2007, Xorcom -# This program is free software; you can redistribute and/or -# modify it under the same terms as Perl itself. -# -# $Id$ -# -use strict; -use File::Basename; -BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/zconf"); } - -use Zaptel; -use Zaptel::Span; -use Zaptel::Xpp; -use Zaptel::Xpp::Xbus; -use Zaptel::Xpp::Xpd; - -my @xbuses = Zaptel::Xpp::xbuses("SORT_CONNECTOR"); -my @xpds = map { $_->xpds } @xbuses; - -foreach my $span (Zaptel::spans()) { - my $spanno = $span->num; - my $xpd = $span->xpd; - my @lines; - my $index = 0; - - @lines = @{$xpd->lines} if defined $xpd; - printf "### Span %2d: %s %s\n", $span->num, $span->name, $span->description; - foreach my $chan ($span->chans()) { - my %type_map = ( - OUT => 'Output', - IN => 'Input' - ); - my ($type) = map { $type_map{$_} or $_ } $chan->type || ("unknown"); - my $batt = ""; - $batt = "(battery)" if $chan->battery; - printf "%3d %-10s %-10s %s %s\n", - $chan->num, $type, $chan->signalling, $chan->info, $batt; - $index++; - } -} - -__END__ - -=head1 NAME - -lszaptel - List all zaptel channels with their types and spans. - -=head1 SYNOPSIS - -lszaptel - -=head1 DESCRIPTION - -Example output: - - ### Span 1: WCTDM/0 "Wildcard TDM400P REV E/F Board 1" - 1 FXO FXOLS (In use) - 2 FXS FXSKS - 3 FXS FXSKS - 4 FXS FXSKS - ### Span 2: XBUS-00/XPD-00 "Xorcom XPD #00/00: FXO" - 5 FXO FXSKS (In use) - 6 FXO FXSKS (In use) (no pcm) - 7 FXO FXSKS (In use) (no pcm) - 8 FXO FXSKS (In use) (no pcm) - 9 FXO FXSKS (In use) (no pcm) - 10 FXO FXSKS (In use) (no pcm) - 11 FXO FXSKS (In use) (no pcm) - 12 FXO FXSKS (In use) (no pcm) - ### Span 3: XBUS-00/XPD-10 "Xorcom XPD #00/10: FXO" - 13 FXO FXSKS (In use) (no pcm) - 14 FXO FXSKS (In use) (no pcm) - 15 FXO FXSKS (In use) (no pcm) - 16 FXO FXSKS (In use) (no pcm) - 17 FXO FXSKS (In use) (no pcm) - 18 FXO FXSKS (In use) (no pcm) - 19 FXO FXSKS (In use) (no pcm) - 20 FXO FXSKS (In use) (no pcm) - - ... - - ### Span 6: XBUS-01/XPD-00 "Xorcom XPD #01/00: FXS" - 37 FXS FXOLS (In use) - 38 FXS FXOLS (In use) (no pcm) - 39 FXS FXOLS (In use) (no pcm) - 40 FXS FXOLS (In use) (no pcm) - 41 FXS FXOLS (In use) (no pcm) - 42 FXS FXOLS (In use) (no pcm) - 43 FXS FXOLS (In use) (no pcm) - 44 FXS FXOLS (In use) (no pcm) - 45 Output FXOLS (In use) (no pcm) - 46 Output FXOLS (In use) (no pcm) - 47 Input FXOLS (In use) (no pcm) - 48 Input FXOLS (In use) (no pcm) - 49 Input FXOLS (In use) (no pcm) - 50 Input FXOLS (In use) (no pcm) - -The first column is the type of the channel (port, for an analog device) -and the second one is the signalling (if set). - -=head1 FILES - -lszaptel is a somewhat glorified 'cat /proc/zaptel/*' . Unlike that -command, it sorts the spans with the proper order. It also formats the -output slightly differently. diff --git a/xpp/utils/print_modes.c b/xpp/utils/print_modes.c deleted file mode 100644 index 6312bd1..0000000 --- a/xpp/utils/print_modes.c +++ /dev/null @@ -1,44 +0,0 @@ -#include - -#include "wctdm_fxomodes.h" - -int main() { - size_t i; - - printf("case \"$mode\" in\n"); - for (i=0; i<(sizeof(fxo_modes)/sizeof(struct fxo_mode)); i++) { - if (fxo_modes[i].name == NULL) break; - int reg16=0, reg26=0, reg30=0, reg31=0x20; - char ring_osc[BUFSIZ]="", ring_x[BUFSIZ] = ""; - - reg16 |= (fxo_modes[i].ohs << 6); - reg16 |= (fxo_modes[i].rz << 1); - reg16 |= (fxo_modes[i].rt); - - reg26 |= (fxo_modes[i].dcv << 6); - reg26 |= (fxo_modes[i].mini << 4); - reg26 |= (fxo_modes[i].ilim << 1); - - reg30 = (fxo_modes[i].acim); - - reg31 |= (fxo_modes[i].ohs2 << 3); - - if (fxo_modes[i].ring_osc !=0 ) { - snprintf(ring_osc, BUFSIZ, "; ring_osc=\"%02X %02X\"", - (fxo_modes[i].ring_osc)>>8, - (fxo_modes[i].ring_osc)&&0xFF - ); - } - if (fxo_modes[i].ring_x !=0 ) { - snprintf(ring_x, BUFSIZ, "; ring_x=\"%02X %02X\"", - (fxo_modes[i].ring_x)>>8, - (fxo_modes[i].ring_x)&&0xFF - ); - } - - printf("%s)\treg16=%02X; reg26=%02X; reg30=%02X; reg31=%02X%s%s;;\n", - fxo_modes[i].name, reg16, reg26, reg30, reg31, ring_osc, ring_x); - } - printf("esac\n"); - return 0; -} diff --git a/xpp/utils/test_parse.c b/xpp/utils/test_parse.c deleted file mode 100644 index 8ac2023..0000000 --- a/xpp/utils/test_parse.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include -#include "hexfile.h" - -static void default_report_func(int level, const char *msg, ...) -{ - va_list ap; - - va_start(ap, msg); - vfprintf(stderr, msg, ap); - va_end(ap); -} - -int main(int argc, char *argv[]) -{ - struct hexdata *hd; - int i; - - if(argc < 2) { - fprintf(stderr, "Usage: program hexfile...\n"); - return 1; - } - parse_hexfile_set_reporting(default_report_func); - for(i = 1; i < argc; i++) { - hd = parse_hexfile(argv[i], 2000); - if(!hd) { - fprintf(stderr, "Parsing failed\n"); - return 1; - } - fprintf(stderr, "=== %s === (version: %s)\n", argv[i], hd->version_info); - dump_hexfile2(hd, "-", 60 ); - free_hexdata(hd); - } - return 0; -} diff --git a/xpp/utils/xpp.rules b/xpp/utils/xpp.rules deleted file mode 100644 index 794a9f0..0000000 --- a/xpp/utils/xpp.rules +++ /dev/null @@ -1,13 +0,0 @@ -BUS!="usb", ACTION!="add", GOTO="xpp_usb_add_end" -KERNEL=="*_ep*", GOTO="xpp_usb_add_end" -KERNEL=="[0-9]*", GOTO="xpp_usb_add_end" - -# Load firmware into the Xorcom Astribank device: -SYSFS{idVendor}=="e4e4", SYSFS{idProduct}=="11[345][01]", \ - RUN+="/usr/share/zaptel/xpp_fxloader udev $sysfs{idVendor}/$sysfs{idProduct}/$sysfs{bcdDevice}" - -LABEL="xpp_usb_add_end" - -# Hotplug hook for Astribank up/down -KERNEL=="xbus*" RUN+="/usr/share/zaptel/astribank_hook udev $kernel $sysfs{status} $sysfs{connector}" - diff --git a/xpp/utils/xpp_blink b/xpp/utils/xpp_blink deleted file mode 100755 index 8a96502..0000000 --- a/xpp/utils/xpp_blink +++ /dev/null @@ -1,130 +0,0 @@ -#! /usr/bin/perl -w -# -# Written by Oron Peled -# Copyright (C) 2007, Xorcom -# This program is free software; you can redistribute and/or -# modify it under the same terms as Perl itself. -# -# $Id$ -# -use strict; -use File::Basename; -BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/zconf"); } - -use Zaptel; -use Zaptel::Span; -use Zaptel::Xpp; -use Zaptel::Xpp::Xbus; - -sub usage { - die "Usage: $0 {on|off|bzzt} {span | xpd [] | label /dev/null 2>&1 &)& -} - -init_astribank() { - wait_for_xpp - zap_reg_xpp - fix_asterisbank_sync - run_adj_clock -} - -xpp_do_blink() { - val="$1" - shift - for xbus in $* - do - for xpd in /proc/xpp/XBUS-"$xbus"/XPD-* - do - echo "$val" > "$xpd/blink" - done - done -} - -xpp_blink() { - xbuses=`grep STATUS=connected /proc/xpp/xbuses | sed -e 's/^XBUS-//' -e 's/:.*$//'` - num=`echo $1 | tr -c -d 0-9` - case "$num" in - [0-9]*) - shift - xpp_do_blink 1 $xbuses - sleep 2 - xpp_do_blink 0 $xbuses - ;; - *) - shift - echo 1>&2 Enumerating $xbuses - xpp_do_blink 0 $xbuses - for i in $xbuses - do - echo "BLINKING: $i" - xpp_do_blink 1 "$i" - sleep 2 - xpp_do_blink 0 "$i" - done - ;; - esac -} - -# The current Debian start function. -# The function is not responsible for loading the zaptel modules: -# they will be loaded beforehand. -debian_start() { - wait_for_xpp - zap_reg_xpp - fix_asterisbank_sync - wait_for_zapctl - - if [ -r /etc/fxotune.conf ] && [ -x $FXOTUNE ]; then - $FXOTUNE -s - fi - - # configure existing modules: - $ZTCFG -} - - -# run_fxotune: destroy all FXO channels and run fxotune. -# This allows running fxotune without completly shutting down Asterisk. -# -# A simplistic assumption: every zaptel channel in the context from-pstn -# is a FXO ones. -# or rather: all tunable FXO channels are in the context from-pstn are -# not defined by zaptel. -run_fxotune() { - zap_fxo_chans=`asterisk -rx "zap show channels" | awk "/$FXO_CONTEXT/{print \$1}"` - xpp_fxo_chans=`cat /proc/zaptel/* | awk '/XPP_FXO/{print $1}'` - for chan in $xpp_fxo_chans $zap_fxo_chans; do - asterisk -rx "zap destroy channel $chan" - done - $FXOTUNE -i - asterisk -rx "zap restart" -} - - -# recursively unload a module and its dependencies, if possible. -# where's modprobe -r when you need it? -# inputs: module to unload. -unload_module() { - set +e - module="$1" - line=`lsmod 2>/dev/null | grep "^$module "` - if [ "$line" = '' ]; then return; fi # module was not loaded - - set -- $line - # $1: the original module, $2: size, $3: refcount, $4: deps list - mods=`echo $4 | tr , ' '` - # xpd_fxs actually sort of depends on xpp: - case "$module" in xpd_*) mods="xpp_usb $mods";; esac - for mod in $mods; do - # run in a subshell, so it won't step over our vars: - (unload_module $mod) - done - rmmod $module || true - set -e -} - -unload() { - unload_module zaptel -} - -# sleep a while until the xpp modules fully register -wait_for_xpp() { - if [ -d /proc/xpp ] && \ - [ "`cat /sys/module/xpp/parameters/zap_autoreg`" = 'Y' ] - then - # wait for the XPDs to register: - # TODO: improve error reporting and produce a messagee here - cat /proc/xpp/XBUS-*/waitfor_xpds 2>/dev/null >/dev/null || true - fi -} - -############################################################################# -##### -##### Hardware detection functions -##### - -load_modules() { - say "Test Loading modules:" - for i in $ALL_MODULES - do - lines_before=`count_proc_zap_lines` - args="${i}_args" - eval "args=\$$args" - # a module is worth listing if it: - # a. loaded successfully, and - # b. added channels lines under /proc/zaptel/* - if /sbin/modprobe $i $args 2> /dev/null - then - check=0 - case "$i" in - xpp_usb) check=`grep 'STATUS=connected' 2>/dev/null /proc/xpp/xbuses | wc -l` ;; - # FIXME: zttranscode will always load, and will never - # add a span. Maybe try to read from /dev/zap/transcode . - zttranscode) : ;; - *) if [ $lines_before -lt `count_proc_zap_lines` ]; then check=1; fi ;; - esac - if [ "$check" != 0 ] - then - probed_modules="$probed_modules $i" - say " ok $i $args" - else - say " - $i $args" - rmmod $i - fi - else - say " - $i $args" - fi - done -} - -update_module_list_debian() { - say "Updating Debian modules list $MODLIST_FILE_DEBIAN." - del_args=`for i in $ALL_MODULES ztdummy - do - echo "$i" | sed s:.\*:-e\ '/^&/d': - done` - add_args=`for i in $* - do - echo "$i" | sed s:.\*:-e\ '\$a&': - done` - - sed -i.bak $del_args "$MODLIST_FILE_DEBIAN" - for i in $* - do - echo "$i" - done >> "$MODLIST_FILE_DEBIAN" -} - -update_module_list_redhat() { - say "Updating modules list in zaptel init config $MODLIST_FILE_REDHAT." - sed -i.bak -e '/^MODULES=/d' "$MODLIST_FILE_REDHAT" - echo "MODULES=\"$*\"" >> "$MODLIST_FILE_REDHAT" -} - -update_module_list() { - if [ -f "$MODLIST_FILE_DEBIAN" ]; then - update_module_list_debian "$@" - elif [ -f "$MODLIST_FILE_REDHAT" ]; then - update_module_list_redhat "$@" - else - die "Can't find a modules list to update. Tried: $MODLIST_FILE_DEBIAN, $MODLIST_FILE_REDHAT. Aborting" - fi -} - - - - - - -# unless we wanted to use this as a set of functions, run -# the given function with its parameters: -if [ "$ZAPHELPER_ONLY_INCLUDE" = '' ]; then - "$@" -fi diff --git a/xpp/utils/zaptel_drivers b/xpp/utils/zaptel_drivers deleted file mode 100755 index d7904c0..0000000 --- a/xpp/utils/zaptel_drivers +++ /dev/null @@ -1,9 +0,0 @@ -#! /usr/bin/perl -w -use strict; -use File::Basename; -BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/zconf"); } - -use Zaptel::Hardware; - -my $hardware = Zaptel::Hardware->scan; -print join("\n", $hardware->drivers),"\n"; diff --git a/xpp/utils/zaptel_hardware b/xpp/utils/zaptel_hardware deleted file mode 100755 index 004a44b..0000000 --- a/xpp/utils/zaptel_hardware +++ /dev/null @@ -1,164 +0,0 @@ -#! /usr/bin/perl -w -# -# Written by Oron Peled -# Copyright (C) 2007, Xorcom -# This program is free software; you can redistribute and/or -# modify it under the same terms as Perl itself. -# -# $Id$ -# -use strict; -use File::Basename; -use Getopt::Std; -BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/zconf"); } - -use Zaptel; -use Zaptel::Span; -use Zaptel::Xpp; -use Zaptel::Xpp::Xbus; -use Zaptel::Hardware; - -sub usage { - die "Usage: $0 [-v][-x]\n"; -} - -our ($opt_v, $opt_x); -getopts('vx') || usage; -@ARGV == 0 or usage; - -my $hardware = Zaptel::Hardware->scan; -my @spans = Zaptel::spans; - -sub show_xbus($) { - my $xbus = shift or die; - my @xpds = $xbus->xpds; - my $label = '[' . $xbus->label() . ']'; - my $connector = ($xbus->status eq 'CONNECTED') ? $xbus->connector : "MISSING"; - printf " LABEL=%-20s CONNECTOR=%-20s\n", $label, $connector; - foreach my $xpd (@xpds) { - my $reg = $xpd->zt_registration; - my $span; - my $spanstr; - if($reg && @spans) { - ($span) = grep { $_->name eq $xpd->fqn } @spans; - $spanstr = ($span) ? ("Span " . $span->num) : ""; - } else { - $spanstr = "Unregistered"; - } - my $master = ''; - #$master = "XPP-SYNC" if $xpd->is_sync_master; - $master .= " ZAPTEL-SYNC" if defined($span) && $span->is_zaptel_sync_master; - printf "\t%-10s: %-8s %s %s\n", $xpd->fqn, $xpd->type, $spanstr, $master; - } -} - -my %seen; -my $format = "%-20s %-12s %4s:%4s %s\n"; - -sub show_disconnected(%) { - my %seen = @_; - - my $notified_lost = 0; - foreach my $xbus (Zaptel::Xpp::xbuses('SORT_CONNECTOR')) { - if(!$seen{$xbus->name}) { - print "----------- XPP Spans with disconnected hardware -----------\n" - unless $notified_lost++; - printf($format, $xbus->name, '', '', '', "NO HARDWARE"); - show_xbus($xbus) if $opt_v; - } - } -} - -foreach my $dev ($hardware->device_list) { - my $driver = $dev->driver || ""; - my $xbus; - my $loaded; - if($dev->is_astribank) { - $xbus = $dev->xbus; - } - $loaded = $dev->loaded; - warn "driver should be '$driver' but is actually '$loaded'\n" - if defined($loaded) && $driver ne $loaded; - $driver = "$driver" . (($loaded) ? "+" : "-"); - my $description = $dev->description || ""; - printf $format, $dev->hardware_name, $driver, $dev->vendor, $dev->product, $description; - if(!defined $xbus || !$xbus) { - next; - } - $seen{$xbus->name} = 1; - show_xbus($xbus) if $opt_v; -} - -show_disconnected(%seen) if $opt_x; - -__END__ - -=head1 NAME - -zaptel_hardware - Shows Zaptel hardware devices. - -=head1 SYNOPSIS - -zaptel_hardware [-v][-x] - -=head1 OPTIONS - -=over - -=item -v - -Verbose ouput - show spans used by each device etc. Currently only -implemented for the Xorcom Astribank. - -=item -x - -Show disconnected Astribank unit, if any. - -=back - -=head1 DESCRIPTION - -Show all zaptel hardware devices. Devices are recognized according to -lists of PCI and USB IDs in Zaptel::Hardware::PCI.pm and -Zaptel::Hardware::USB.pm . For PCI it is possible to detect by -sub-vendor and sub-product ID as well. - -The first output column is the connector: a bus specific field that -shows where this device is. - -The second field shows which driver should handle the device. a "-" sign -marks that the device is not yet handled by this driver. A "+" sign -means that the device is handled by the driver. - -For the Xorcom Astribank (and in the future: for other Zaptel devices) -some further information is provided from the driver. Those extra lines -always begin with spaces. - -Example output: - -Without drivers loaded: - - usb:001/002 xpp_usb- e4e4:1152 Astribank-multi FPGA-firmware - usb:001/003 xpp_usb- e4e4:1152 Astribank-multi FPGA-firmware - pci:0000:01:0b.0 wctdm- e159:0001 Wildcard TDM400P REV H - -With drivers loaded, without -v: - usb:001/002 xpp_usb+ e4e4:1152 Astribank-multi FPGA-firmware - usb:001/003 xpp_usb+ e4e4:1152 Astribank-multi FPGA-firmware - pci:0000:01:0b.0 wctdm+ e159:0001 Wildcard TDM400P REV E/F - -With drivers loaded, with -v: - usb:001/002 xpp_usb+ e4e4:1152 Astribank-multi FPGA-firmware - LABEL=[usb:123] CONNECTOR=usb-0000:00:1d.7-1 - XBUS-00/XPD-00: FXS Span 2 - XBUS-00/XPD-10: FXS Span 3 - XBUS-00/XPD-20: FXS Span 4 - XBUS-00/XPD-30: FXS Span 5 - usb:001/003 xpp_usb+ e4e4:1152 Astribank-multi FPGA-firmware - LABEL=[usb:4567] CONNECTOR=usb-0000:00:1d.7-4 - XBUS-01/XPD-00: FXS Span 6 XPP-SYNC - XBUS-01/XPD-10: FXO Span 7 - XBUS-01/XPD-20: FXO Span 8 - XBUS-01/XPD-30: FXO Span 9 - pci:0000:01:0b.0 wctdm+ e159:0001 Wildcard TDM400P REV E/F - diff --git a/xpp/utils/zconf/Zaptel.pm b/xpp/utils/zconf/Zaptel.pm deleted file mode 100644 index a7e7d6c..0000000 --- a/xpp/utils/zconf/Zaptel.pm +++ /dev/null @@ -1,68 +0,0 @@ -package Zaptel; -# -# Written by Oron Peled -# Copyright (C) 2007, Xorcom -# This program is free software; you can redistribute and/or -# modify it under the same terms as Perl itself. -# -# $Id$ -# -use strict; -use Zaptel::Span; - -=head1 NAME - -Zaptel - Perl interface to Zaptel information - -This package allows access from Perl to information about Zaptel -hardware and loaded Zaptel devices. - -=head1 SYNOPSIS - - # Listing channels in analog spans: - use Zaptel; - # scans system: - my @xbuses = Zaptel::spans(); - for my $span (@spans) { - next if ($span->is_digital); - $span->num. " - [". $span->type ."] ". $span->name. "\n"; - for my $chan ($span->chans) { - print " - ".$chan->num . " - [". $chan->type. "] ". $chan->fqn". \n"; - } - } -=cut - -my $proc_base = "/proc/zaptel"; - -=head1 spans() - -Returns a list of span objects, ordered by span number. - -=cut - -sub spans() { - my @spans; - - -d $proc_base or return (); - foreach my $zfile (glob "$proc_base/*") { - $zfile =~ s:$proc_base/::; - my $span = Zaptel::Span->new($zfile); - push(@spans, $span); - } - @spans = sort { $a->num <=> $b->num } @spans; - return @spans; -} - -=head1 SEE ALSO - -Span objects: L. - -Zaptel channels objects: L. - -Zaptel hardware devices information: L. - -Xorcom Astribank -specific information: L. - -=cut - -1; diff --git a/xpp/utils/zconf/Zaptel/Chans.pm b/xpp/utils/zconf/Zaptel/Chans.pm deleted file mode 100644 index b02bf24..0000000 --- a/xpp/utils/zconf/Zaptel/Chans.pm +++ /dev/null @@ -1,187 +0,0 @@ -package Zaptel::Chans; -# -# Written by Oron Peled -# Copyright (C) 2007, Xorcom -# This program is free software; you can redistribute and/or -# modify it under the same terms as Perl itself. -# -# $Id$ -# -use strict; -use Zaptel::Utils; - -=head1 NAME - -Zaptel::Chans - Perl interface to a Zaptel channel information - -This package allows access from perl to information about a Zaptel -channel. It is part of the Zaptel Perl package. - -=head1 battery() - -Returns 1 if channel reports to have battery (A remote PBX connected to -an FXO port), 0 if channel reports to not have battery and C -otherwise. - -Currently only wcfxo and Astribank FXO modules report battery. For the -rest of the channels - -=head1 fqn() - -(Fully Qualified Name) Returns the full "name" of the channel. - -=head1 index() - -Returns the number of this channel (in the span). - -=head1 num() - -Returns the number of this channel as a Zaptel channel. - -=head signalling() - -Returns the signalling set for this channel through /etc/zaptel.conf . -This is always empty before ztcfg was run. And shows the "other" type -for FXS and for FXO. - -=head1 span() - -Returns a reference to the span to which this channel belongs. - -=head1 type() - -Returns the type of the channel: 'FXS', 'FXO', 'EMPTY', etc. - -=cut - -sub new($$$$$$) { - my $pack = shift or die "Wasn't called as a class method\n"; - my $span = shift or die "Missing a span parameter\n"; - my $index = shift; - my $line = shift or die "Missing an input line\n"; - defined $index or die "Missing an index parameter\n"; - my $self = { - 'SPAN' => $span, - 'INDEX' => $index, - }; - bless $self, $pack; - my ($num, $fqn, $rest) = split(/\s+/, $line, 3); - $num or die "Missing a channel number parameter\n"; - $fqn or die "Missing a channel fqn parameter\n"; - my $signalling = ''; - my $info = ''; - if(defined $rest) { - if($rest =~ s/^\s*(\w+)\s*//) { - $signalling = $1; - } - if($rest =~ s/(.*)//) { - $info = $1; - } - } - $self->{NUM} = $num; - $self->{FQN} = $fqn; - $self->{SIGNALLING} = $signalling; - $self->{INFO} = $info; - my $type; - if($fqn =~ m|\bXPP_(\w+)/.*$|) { - $type = $1; # An Astribank - } elsif ($fqn =~ m{\bWCFXO/.*}) { - $type = "FXO"; # wcfxo - x100p and relatives. - # A single port card. The driver issue RED alarm when - # There's no better - $self->{BATTERY} = !($span->description =~ /\bRED\b/); - } elsif ($fqn =~ m{\bFXS/.*}) { - $type = "FXS"; # likely Rhino - } elsif ($fqn =~ m{\bFXO/.*}) { - $type = "FXO"; # likely Rhino - } elsif ($fqn =~ m{\b---/.*}) { - $type = "EMPTY"; # likely Rhino, empty slot. - } elsif ($fqn =~ m{\b(TE[24]|WCT1|Tor2|TorISA|WP[TE]1|cwain[12])/.*}) { - # TE[24]: Digium wct4xxp - # WCT1: Digium single span card drivers? - # Tor2: Tor PCI cards - # TorISA: ISA ones (still used?) - # WP[TE]1: Sangoma. TODO: this one tells us if it is TE or NT. - # cwain: Junghanns E1 card. - $type = "PRI"; - } elsif ($fqn =~ m{\b(ZTHFC%d*|ztqoz\d*)/.*}) { - # ZTHFC: HFC-s single-port card (zaphfc/vzaphfc) - # ztqoz: qozap (Junghanns) multi-port HFC card - $type = "BRI"; - } elsif ($fqn =~ m{\bztgsm/.*}) { - # Junghanns GSM card - $type = "GSM"; - } elsif(defined $signalling) { - $type = 'FXS' if $signalling =~ /^FXS/; - $type = 'FXO' if $signalling =~ /^FXO/; - } else { - $type = undef; - } - $self->type($type); - $self->span()->type($type) - if ! defined($self->span()->type()) || - $self->span()->type() eq 'UNKNOWN'; - return $self; -} - -=head1 probe_type() - -In the case of some cards, the information in /proc/zaptel is not good -enough to tell the type of each channel. In this case an extra explicit -probe is needed. - -Currently this is implemented by using some invocations of ztcfg(8). - -It may later be replaced by ztscan(8). - -=cut - -my $ztcfg = $ENV{ZTCFG} || '/sbin/ztcfg'; -sub probe_type($) { - my $self = shift; - my $fqn = $self->fqn; - my $num = $self->num; - my $type; - - if($fqn =~ m:WCTDM/| WRTDM/|OPVXA1200/:) { - my %maybe; - - undef %maybe; - foreach my $sig (qw(fxo fxs)) { - my $cmd = "echo ${sig}ks=$num | $ztcfg -c /dev/fd/0"; - - $maybe{$sig} = system("$cmd >/dev/null 2>&1") == 0; - } - if($maybe{fxo} and $maybe{fxs}) { - $type = 'EMPTY'; - } elsif($maybe{fxo}) { - $type = 'FXS'; - } elsif($maybe{fxs}) { - $type = 'FXO'; - } else { - $type = 'EMPTY'; - } - } else { - $type = $self->type; - } - return $type; -} - -sub battery($) { - my $self = shift or die; - my $span = $self->span or die; - - return undef unless $self->type eq 'FXO'; - return $self->{BATTERY} if defined $self->{BATTERY}; - - my $xpd = $span->xpd; - my $index = $self->index; - return undef if !$xpd; - - # It's an XPD (FXO) - my @lines = @{$xpd->lines}; - my $line = $lines[$index]; - return $line->battery; -} - -1; diff --git a/xpp/utils/zconf/Zaptel/Config/Defaults.pm b/xpp/utils/zconf/Zaptel/Config/Defaults.pm deleted file mode 100644 index 360ca0a..0000000 --- a/xpp/utils/zconf/Zaptel/Config/Defaults.pm +++ /dev/null @@ -1,56 +0,0 @@ -package Zaptel::Config::Defaults; -# -# Written by Oron Peled -# Copyright (C) 2007, Xorcom -# This program is free software; you can redistribute and/or -# modify it under the same terms as Perl itself. -# -# $Id$ -# -use strict; - -# Use the shell to source a file and expand a given list -# of variables. -sub do_source($@) { - my $file = shift; - my @vars = @_; - my @output = `env -i sh -ec '. $file; export @vars; for i in @vars; do eval echo \$i=\\\$\$i; done'`; - die "$0: Sourcing '$file' exited with $?" if $?; - my %vars; - - foreach my $line (@output) { - chomp $line; - my ($k, $v) = split(/=/, $line, 2); - $vars{$k} = $v if grep /^$k$/, @vars; - } - return %vars; -} - -sub source_vars { - my @vars = @_; - my $default_file; - my %system_files = ( - "/etc/default/zaptel" => 'Debian and friends', - "/etc/sysconfig/zaptel" => 'Red Hat and friends', - ); - - if(defined $ENV{ZAPTEL_DEFAULTS}) { - $default_file = $ENV{ZAPTEL_DEFAULTS}; - } else { - foreach my $f (keys %system_files) { - if(-r $f) { - if(defined $default_file) { - die "An '$f' collides with '$default_file'"; - } - $default_file = $f; - } - } - } - if (! $default_file) { - return ("", ()); - } - my %vars = Zaptel::Config::Defaults::do_source($default_file, @vars); - return ($default_file, %vars); -} - -1; diff --git a/xpp/utils/zconf/Zaptel/Hardware.pm b/xpp/utils/zconf/Zaptel/Hardware.pm deleted file mode 100644 index 5af22f7..0000000 --- a/xpp/utils/zconf/Zaptel/Hardware.pm +++ /dev/null @@ -1,60 +0,0 @@ -package Zaptel::Hardware; -# -# Written by Oron Peled -# Copyright (C) 2007, Xorcom -# This program is free software; you can redistribute and/or -# modify it under the same terms as Perl itself. -# -# $Id$ -# -use strict; -use Zaptel::Hardware::USB; -use Zaptel::Hardware::PCI; - -sub device_detected($$) { - my $dev = shift || die; - my $name = shift || die; - die unless defined $dev->{'BUS_TYPE'}; - $dev->{IS_ASTRIBANK} = 0 unless defined $dev->{'IS_ASTRIBANK'}; - $dev->{'HARDWARE_NAME'} = $name; -} - -sub device_removed($) { - my $dev = shift || die; - my $name = $dev->hardware_name; - die "Missing zaptel device hardware name" unless $name; -} - -sub device_list($) { - my $self = shift || die; - my @types = @_; - my @list; - - @types = qw(USB PCI) unless @types; - foreach my $t (@types) { - @list = ( @list, @{$self->{$t}} ); - } - return @list; -} - -sub drivers($) { - my $self = shift || die; - my @devs = $self->device_list; - my @drvs = map { $_->{DRIVER} } @devs; - # Make unique - my %drivers; - @drivers{@drvs} = 1; - return sort keys %drivers; -} - -sub scan($) { - my $pack = shift || die; - my $self = {}; - bless $self, $pack; - - $self->{USB} = [ Zaptel::Hardware::USB->devices ]; - $self->{PCI} = [ Zaptel::Hardware::PCI->scan_devices ]; - return $self; -} - -1; diff --git a/xpp/utils/zconf/Zaptel/Hardware/PCI.pm b/xpp/utils/zconf/Zaptel/Hardware/PCI.pm deleted file mode 100644 index 45173d4..0000000 --- a/xpp/utils/zconf/Zaptel/Hardware/PCI.pm +++ /dev/null @@ -1,204 +0,0 @@ -package Zaptel::Hardware::PCI; -# -# Written by Oron Peled -# Copyright (C) 2007, Xorcom -# This program is free software; you can redistribute and/or -# modify it under the same terms as Perl itself. -# -# $Id$ -# -use strict; -use Zaptel::Utils; -use Zaptel::Hardware; - -our @ISA = qw(Zaptel::Hardware); - -# Lookup algorithm: -# First match 'vendor:product/subvendor:subproduct' key -# Else match 'vendor:product/subvendor' key -# Else match 'vendor:product' key -# Else not a zaptel hardware. -my %pci_ids = ( - # from wct4xxp - '10ee:0314' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE410P/TE405P (1st Gen)' }, - 'd161:0420/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE420 (4th Gen)' }, - 'd161:0410/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE410P (4th Gen)' }, - 'd161:0405/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE405P (4th Gen)' }, - 'd161:0410/0003' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE410P (3rd Gen)' }, - 'd161:0405/0003' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE405P (3rd Gen)' }, - 'd161:0410' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE410P (2nd Gen)' }, - 'd161:0405' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE405P (2nd Gen)' }, - 'd161:0220/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE220 (4th Gen)' }, - 'd161:0205/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE205P (4th Gen)' }, - 'd161:0210/0004' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE210P (4th Gen)' }, - 'd161:0205/0003' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE205P (3rd Gen)' }, - 'd161:0210/0003' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE210P (3rd Gen)' }, - 'd161:0205' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE205P ' }, - 'd161:0210' => { DRIVER => 'wct4xxp', DESCRIPTION => 'Wildcard TE210P ' }, - - # from wctdm24xxp - 'd161:2400' => { DRIVER => 'wctdm24xxp', DESCRIPTION => 'Wildcard TDM2400P' }, - 'd161:0800' => { DRIVER => 'wctdm24xxp', DESCRIPTION => 'Wildcard TDM800P' }, - 'd161:8002' => { DRIVER => 'wctdm24xxp', DESCRIPTION => 'Wildcard AEX800' }, - 'd161:8003' => { DRIVER => 'wctdm24xxp', DESCRIPTION => 'Wildcard AEX2400' }, - - # from pciradio - 'e159:0001/e16b' => { DRIVER => 'pciradio', DESCRIPTION => 'PCIRADIO' }, - - # from wcfxo - 'e159:0001/8084' => { DRIVER => 'wcfxo', DESCRIPTION => 'Wildcard X101P clone' }, - 'e159:0001/8085' => { DRIVER => 'wcfxo', DESCRIPTION => 'Wildcard X101P' }, - 'e159:0001/8086' => { DRIVER => 'wcfxo', DESCRIPTION => 'Wildcard X101P clone' }, - 'e159:0001/8087' => { DRIVER => 'wcfxo', DESCRIPTION => 'Wildcard X101P clone' }, - '1057:5608' => { DRIVER => 'wcfxo', DESCRIPTION => 'Wildcard X100P' }, - - # from wct1xxp - 'e159:0001/6159' => { DRIVER => 'wct1xxp', DESCRIPTION => 'Digium Wildcard T100P T1/PRI or E100P E1/PRA Board' }, - - # from wctdm - 'e159:0001/a159' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard S400P Prototype' }, - 'e159:0001/e159' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard S400P Prototype' }, - 'e159:0001/b100' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV E/F' }, - 'e159:0001/b1d9' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV I' }, - 'e159:0001/b118' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV I' }, - 'e159:0001/b119' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV I' }, - 'e159:0001/a9fd' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, - 'e159:0001/a8fd' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, - 'e159:0001/a800' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, - 'e159:0001/a801' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, - 'e159:0001/a908' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, - 'e159:0001/a901' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, - #'e159:0001' => { DRIVER => 'wctdm', DESCRIPTION => 'Wildcard TDM400P REV H' }, - - # from wcte11xp - 'e159:0001/71fe' => { DRIVER => 'wcte11xp', DESCRIPTION => 'Digium Wildcard TE110P T1/E1 Board' }, - 'e159:0001/79fe' => { DRIVER => 'wcte11xp', DESCRIPTION => 'Digium Wildcard TE110P T1/E1 Board' }, - 'e159:0001/795e' => { DRIVER => 'wcte11xp', DESCRIPTION => 'Digium Wildcard TE110P T1/E1 Board' }, - 'e159:0001/79de' => { DRIVER => 'wcte11xp', DESCRIPTION => 'Digium Wildcard TE110P T1/E1 Board' }, - 'e159:0001/797e' => { DRIVER => 'wcte11xp', DESCRIPTION => 'Digium Wildcard TE110P T1/E1 Board' }, - - # from wcte12xp - 'd161:0120' => { DRIVER => 'wcte12xp', DESCRIPTION => 'Wildcard TE12xP' }, - - # from tor2 - '10b5:9030' => { DRIVER => 'tor2', DESCRIPTION => 'PLX 9030' }, - '10b5:3001' => { DRIVER => 'tor2', DESCRIPTION => 'PLX Development Board' }, - '10b5:D00D' => { DRIVER => 'tor2', DESCRIPTION => 'Tormenta 2 Quad T1/PRI or E1/PRA' }, - '10b5:4000' => { DRIVER => 'tor2', DESCRIPTION => 'Tormenta 2 Quad T1/E1 (non-Digium clone)' }, - - # Cologne Chips: - # (Still a partial list) - '1397:08b4/b556' => { DRIVER => 'qozap', DESCRIPTION => 'Junghanns DuoBRI ISDN card' }, - '1397:08b4' => { DRIVER => 'qozap', DESCRIPTION => 'Junghanns QuadBRI ISDN card' }, - '1397:16b8' => { DRIVER => 'qozap', DESCRIPTION => 'Junghanns OctoBRI ISDN card' }, - '1397:30b1' => { DRIVER => 'cwain', DESCRIPTION => 'HFC-E1 ISDN E1 card' }, - '1397:2bd0' => { DRIVER => 'zaphfc', DESCRIPTION => 'HFC-S ISDN BRI card' }, - '1397:f001' => { DRIVER => 'ztgsm', DESCRIPTION => 'HFC-GSM Cologne Chips GSM' }, - - # Rhino cards (based on pci.ids) - '0b0b:0105' => { DRIVER => 'r1t1', DESCRIPTION => 'Rhino R1T1' }, - '0b0b:0205' => { DRIVER => 'r4fxo', DESCRIPTION => 'Rhino R14FXO' }, - '0b0b:0206' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB4FXO 4-channel FXO analog telphony card' }, - '0b0b:0305' => { DRIVER => 'r1t1', DESCRIPTION => 'Rhino R1T1' }, - '0b0b:0405' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino R8FXX' }, - '0b0b:0406' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB8FXX 8-channel modular analog telphony card' }, - '0b0b:0505' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino R24FXX' }, - '0b0b:0506' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB24FXS 24-Channel FXS analog telphony card' }, - '0b0b:0605' => { DRIVER => 'rxt1', DESCRIPTION => 'Rhino R2T1' }, - '0b0b:0705' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino R24FXS' }, - '0b0b:0706' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB24FXO 24-Channel FXO analog telphony card' }, - '0b0b:0906' => { DRIVER => 'rcbfx', DESCRIPTION => 'Rhino RCB24FXX 24-channel modular analog telphony card' }, - - # Sangoma cards (based on pci.ids) - '1923:0040' => { DRIVER => 'wanpipe', DESCRIPTION => 'Sangoma Technologies Corp. A200/Remora FXO/FXS Analog AFT card' }, - '1923:0100' => { DRIVER => 'wanpipe', DESCRIPTION => 'Sangoma Technologies Corp. A104d QUAD T1/E1 AFT card' }, - '1923:0300' => { DRIVER => 'wanpipe', DESCRIPTION => 'Sangoma Technologies Corp. A101 single-port T1/E1' }, - '1923:0400' => { DRIVER => 'wanpipe', DESCRIPTION => 'Sangoma Technologies Corp. A104u Quad T1/E1 AFT' }, - ); - -$ENV{PATH} .= ":/usr/sbin:/sbin:/usr/bin:/bin"; - -sub pci_sorter { - return $a->priv_device_name() cmp $b->priv_device_name(); -} - -sub new($$) { - my $pack = shift or die "Wasn't called as a class method\n"; - my $self = { @_ }; - bless $self, $pack; - Zaptel::Hardware::device_detected($self, - sprintf("pci:%s", $self->{PRIV_DEVICE_NAME})); - return $self; -} - -my %pci_devs; - -sub readfile($) { - my $name = shift || die; - open(F, $name) || die "Failed to open '$name': $!"; - my $str = ; - close F; - chomp($str); - return $str; -} - -sub scan_devices($) { - my @devices; - - while() { - m,([^/]+)$,,; - my $name = $1; - my $l = readlink $_ || die; - $pci_devs{$name}{PRIV_DEVICE_NAME} = $name; - $pci_devs{$name}{DEVICE} = $l; - $pci_devs{$name}{VENDOR} = readfile "$_/vendor"; - $pci_devs{$name}{PRODUCT} = readfile "$_/device"; - $pci_devs{$name}{SUBVENDOR} = readfile "$_/subsystem_vendor"; - $pci_devs{$name}{SUBPRODUCT} = readfile "$_/subsystem_device"; - my $dev = $pci_devs{$name}; - grep(s/0x//, $dev->{VENDOR}, $dev->{PRODUCT}, $dev->{SUBVENDOR}, $dev->{SUBPRODUCT}); - $pci_devs{$name}{DRIVER} = ''; - } - - while() { - m,^(.*?)/([^/]+)/([^/]+)$,; - my $prefix = $1; - my $drvname = $2; - my $id = $3; - my $l = readlink "$prefix/$drvname/module"; - # Find the real module name (if we can). - if(defined $l) { - my $moduledir = "$prefix/$drvname/$l"; - my $modname = $moduledir; - $modname =~ s:^.*/::; - $drvname = $modname; - } - $pci_devs{$id}{LOADED} = $drvname; - } - foreach (sort keys %pci_devs) { - my $dev = $pci_devs{$_}; - my $key; - # Try to match - $key = "$dev->{VENDOR}:$dev->{PRODUCT}/$dev->{SUBVENDOR}:$dev->{SUBPRODUCT}"; - $key = "$dev->{VENDOR}:$dev->{PRODUCT}/$dev->{SUBVENDOR}" if !defined($pci_ids{$key}); - $key = "$dev->{VENDOR}:$dev->{PRODUCT}" if !defined($pci_ids{$key}); - next unless defined $pci_ids{$key}; - - my $d = Zaptel::Hardware::PCI->new( - BUS_TYPE => 'PCI', - PRIV_DEVICE_NAME => $dev->{PRIV_DEVICE_NAME}, - VENDOR => $dev->{VENDOR}, - PRODUCT => $dev->{PRODUCT}, - SUBVENDOR => $dev->{SUBVENDOR}, - SUBPRODUCT => $dev->{SUBPRODUCT}, - LOADED => $dev->{LOADED}, - DRIVER => $pci_ids{$key}{DRIVER}, - DESCRIPTION => $pci_ids{$key}{DESCRIPTION}, - ); - push(@devices, $d); - } - @devices = sort pci_sorter @devices; - return @devices; -} - -1; diff --git a/xpp/utils/zconf/Zaptel/Hardware/USB.pm b/xpp/utils/zconf/Zaptel/Hardware/USB.pm deleted file mode 100644 index a2dc08f..0000000 --- a/xpp/utils/zconf/Zaptel/Hardware/USB.pm +++ /dev/null @@ -1,116 +0,0 @@ -package Zaptel::Hardware::USB; -# -# Written by Oron Peled -# Copyright (C) 2007, Xorcom -# This program is free software; you can redistribute and/or -# modify it under the same terms as Perl itself. -# -# $Id$ -# -use strict; -use Zaptel::Utils; -use Zaptel::Hardware; -use Zaptel::Xpp; -use Zaptel::Xpp::Xbus; - -our @ISA = qw(Zaptel::Hardware); - -my %usb_ids = ( - # from wcusb - '06e6:831c' => { DRIVER => 'wcusb', DESCRIPTION => 'Wildcard S100U USB FXS Interface' }, - '06e6:831e' => { DRIVER => 'wcusb2', DESCRIPTION => 'Wildcard S110U USB FXS Interface' }, - '06e6:b210' => { DRIVER => 'wc_usb_phone', DESCRIPTION => 'Wildcard Phone Test driver' }, - - # from xpp_usb - 'e4e4:1130' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-8/16 no-firmware' }, - 'e4e4:1131' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-8/16 USB-firmware' }, - 'e4e4:1132' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-8/16 FPGA-firmware' }, - 'e4e4:1140' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-BRI no-firmware' }, - 'e4e4:1141' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-BRI USB-firmware' }, - 'e4e4:1142' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-BRI FPGA-firmware' }, - 'e4e4:1150' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-multi no-firmware' }, - 'e4e4:1151' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-multi USB-firmware' }, - 'e4e4:1152' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-multi FPGA-firmware' }, - 'e4e4:1160' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-modular no-firmware' }, - 'e4e4:1161' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-modular USB-firmware' }, - 'e4e4:1162' => { DRIVER => 'xpp_usb', DESCRIPTION => 'Astribank-modular FPGA-firmware' }, - ); - - -$ENV{PATH} .= ":/usr/sbin:/sbin:/usr/bin:/bin"; - -my @xbuses = Zaptel::Xpp::xbuses('SORT_CONNECTOR'); - -sub usb_sorter() { - return $a->hardware_name cmp $b->hardware_name; -} - -sub xbus_of_usb($) { - my $priv_device_name = shift; - my $dev = shift; - - my ($wanted) = grep { - defined($_->usb_devname) && - $priv_device_name eq $_->usb_devname - } @xbuses; - return $wanted; -} - -sub new($$) { - my $pack = shift or die "Wasn't called as a class method\n"; - my $self = { @_ }; - bless $self, $pack; - my $xbus = xbus_of_usb($self->priv_device_name); - if(defined $xbus) { - $self->{XBUS} = $xbus; - $self->{LOADED} = 'xpp_usb'; - } else { - $self->{XBUS} = undef; - $self->{LOADED} = undef; - } - Zaptel::Hardware::device_detected($self, - sprintf("usb:%s", $self->{PRIV_DEVICE_NAME})); - return $self; -} - -sub devices($) { - my $pack = shift || die; - my $usb_device_list = "/proc/bus/usb/devices"; - return unless (-r $usb_device_list); - - my @devices; - open(F, $usb_device_list) || die "Failed to open $usb_device_list: $!"; - local $/ = ''; - while() { - my @lines = split(/\n/); - my ($tline) = grep(/^T/, @lines); - my ($pline) = grep(/^P/, @lines); - my ($sline) = grep(/^S:.*SerialNumber=/, @lines); - my ($busnum,$devnum) = ($tline =~ /Bus=(\w+)\W.*Dev#=\s*(\w+)\W/); - my $devname = sprintf("%03d/%03d", $busnum, $devnum); - my ($vendor,$product) = ($pline =~ /Vendor=(\w+)\W.*ProdID=(\w+)\W/); - my $serial; - if(defined $sline) { - $sline =~ /SerialNumber=(.*)/; - $serial = $1; - #$serial =~ s/[[:^print:]]/_/g; - } - my $model = $usb_ids{"$vendor:$product"}; - next unless defined $model; - my $d = Zaptel::Hardware::USB->new( - IS_ASTRIBANK => ($model->{DRIVER} eq 'xpp_usb')?1:0, - BUS_TYPE => 'USB', - PRIV_DEVICE_NAME => $devname, - VENDOR => $vendor, - PRODUCT => $product, - SERIAL => $serial, - DESCRIPTION => $model->{DESCRIPTION}, - DRIVER => $model->{DRIVER}, - ); - push(@devices, $d); - } - close F; - @devices = sort usb_sorter @devices; -} - -1; diff --git a/xpp/utils/zconf/Zaptel/Span.pm b/xpp/utils/zconf/Zaptel/Span.pm deleted file mode 100644 index 380dc7f..0000000 --- a/xpp/utils/zconf/Zaptel/Span.pm +++ /dev/null @@ -1,160 +0,0 @@ -package Zaptel::Span; -# -# Written by Oron Peled -# Copyright (C) 2007, Xorcom -# This program is free software; you can redistribute and/or -# modify it under the same terms as Perl itself. -# -# $Id$ -# -use strict; -use Zaptel::Utils; -use Zaptel::Chans; -use Zaptel::Xpp::Xpd; - -my $proc_base = "/proc/zaptel"; - -sub chans($) { - my $span = shift; - return @{$span->{CHANS}}; -} - -sub by_number($) { - my $span_number = shift; - die "Missing span number" unless defined $span_number; - my @spans = Zaptel::spans(); - - my ($span) = grep { $_->num == $span_number } @spans; - return $span; -} - -my @bri_strings = ( - 'BRI_(NT|TE)', - '(?:quad|octo)BRI PCI ISDN Card.* \[(NT|TE)\]\ ', - 'octoBRI \[(NT|TE)\] ', - 'HFC-S PCI A ISDN.* \[(NT|TE)\] ' - ); - -my @pri_strings = ( - '(E1|T1|J1)_(NT|TE)' - ); - -our $ZAPBRI_NET = 'bri_net'; -our $ZAPBRI_CPE = 'bri_cpe'; - -our $ZAPPRI_NET = 'pri_net'; -our $ZAPPRI_CPE = 'pri_cpe'; - -sub new($$) { - my $pack = shift or die "Wasn't called as a class method\n"; - my $num = shift or die "Missing a span number parameter\n"; - my $self = { NUM => $num }; - bless $self, $pack; - $self->{TYPE} = "UNKNOWN"; - my @xpds = Zaptel::Xpp::Xpd::xpds_by_spanno; - my $xpd = $xpds[$num]; - if(defined $xpd) { - die "Spanno mismatch: $xpd->spanno, $num" unless $xpd->spanno == $num; - $self->{XPD} = $xpd; - } - open(F, "$proc_base/$num") or die "Failed to open '$proc_base/$num\n"; - my $head = ; - chomp $head; - $self->{IS_DIGITAL} = 0; - $self->{IS_BRI} = 0; - $self->{IS_PRI} = 0; - foreach my $cardtype (@bri_strings) { - if($head =~ m/$cardtype/) { - $self->{IS_DIGITAL} = 1; - $self->{IS_BRI} = 1; - $self->{TERMTYPE} = $1; - $self->{TYPE} = "BRI_$1"; - $self->{DCHAN_IDX} = 2; - $self->{BCHAN_LIST} = [ 0, 1 ]; - last; - } - } - foreach my $cardtype (@pri_strings) { - if($head =~ m/$cardtype/) { - $self->{IS_DIGITAL} = 1; - $self->{IS_PRI} = 1; - $self->{PROTO} = "$1"; - $self->{TERMTYPE} = $2; - $self->{TYPE} = "$1_$2"; - if($self->{PROTO} eq 'E1') { - $self->{DCHAN_IDX} = 15; - $self->{BCHAN_LIST} = [ 0 .. 14, 16 .. 30 ]; - } elsif($self->{PROTO} eq 'T1') { - $self->{DCHAN_IDX} = 23; - $self->{BCHAN_LIST} = [ 0 .. 22 ]; - } else { - die "'$self->{PROTO}' unsupported yet"; - } - last; - } - } - die "$0: Unkown TERMTYPE [NT/TE]\n" - if $self->is_digital and !defined $self->{TERMTYPE}; - ($self->{NAME}, $self->{DESCRIPTION}) = (split(/\s+/, $head, 4))[2, 3]; - $self->{IS_ZAPTEL_SYNC_MASTER} = - ($self->{DESCRIPTION} =~ /\(MASTER\)/) ? 1 : 0; - $self->{CHANS} = []; - my @channels; - my $index = 0; - while() { - chomp; - s/^\s*//; - s/\s*$//; - next unless /\S/; - my $c = Zaptel::Chans->new($self, $index, $_); - push(@channels, $c); - $index++; - } - close F; - @channels = sort { $a->num <=> $b->num } @channels; - $self->{CHANS} = \@channels; - $self->{YELLOW} = undef; - $self->{CRC4} = undef; - if($self->is_bri()) { - $self->{CODING} = 'ami'; - $self->{DCHAN} = ($self->chans())[$self->{DCHAN_IDX}]; - $self->{BCHANS} = [ ($self->chans())[@{$self->{BCHAN_LIST}}] ]; - # Infer some info from channel name: - my $first_chan = ($self->chans())[0] || die "$0: No channels in span #$num\n"; - my $chan_fqn = $first_chan->fqn(); - if($chan_fqn =~ m(ZTHFC.*/|ztqoz.*/|XPP_BRI_.*/)) { # BRI - $self->{FRAMING} = 'ccs'; - $self->{SWITCHTYPE} = 'euroisdn'; - $self->{SIGNALLING} = ($self->{TERMTYPE} eq 'NT') ? $ZAPBRI_NET : $ZAPBRI_CPE ; - } elsif($chan_fqn =~ m(ztgsm.*/)) { # Junghanns's GSM cards. - $self->{FRAMING} = 'ccs'; - $self->{SIGNALLING} = 'gsm'; - } - } - if($self->is_pri()) { - $self->{DCHAN} = ($self->chans())[$self->{DCHAN_IDX}]; - $self->{BCHANS} = [ ($self->chans())[@{$self->{BCHAN_LIST}}] ]; - if($self->{PROTO} eq 'E1') { - $self->{CODING} = 'hdb3'; - $self->{FRAMING} = 'ccs'; - $self->{SWITCHTYPE} = 'euroisdn'; - $self->{CRC4} = 'crc4'; - } elsif($self->{PROTO} eq 'T1') { - $self->{CODING} = 'b8zs'; - $self->{FRAMING} = 'esf'; - $self->{SWITCHTYPE} = 'national'; - } else { - die "'$self->{PROTO}' unsupported yet"; - } - $self->{SIGNALLING} = ($self->{TERMTYPE} eq 'NT') ? $ZAPPRI_NET : $ZAPPRI_CPE ; - } - return $self; -} - -sub bchans($) { - my $self = shift || die; - - return @{$self->{BCHANS}}; -} - -1; diff --git a/xpp/utils/zconf/Zaptel/Utils.pm b/xpp/utils/zconf/Zaptel/Utils.pm deleted file mode 100644 index 8d13ad7..0000000 --- a/xpp/utils/zconf/Zaptel/Utils.pm +++ /dev/null @@ -1,52 +0,0 @@ -package Zaptel::Utils; - -# Accessors (miniperl does not have Class:Accessor) -our $AUTOLOAD; -sub AUTOLOAD { - my $self = shift; - my $name = $AUTOLOAD; - $name =~ s/.*://; # strip fully-qualified portion - return if $name =~ /^[A-Z_]+$/; # ignore special methods (DESTROY) - my $key = uc($name); - my $val = shift; - if (defined $val) { - #print STDERR "set: $key = $val\n"; - return $self->{$key} = $val; - } else { - if(!exists $self->{$key}) { - #$self->xpp_dump; - #die "Trying to get uninitialized '$key'"; - } - my $val = $self->{$key}; - #print STDERR "get: $key ($val)\n"; - return $val; - } -} - -sub xpp_dump($) { - my $self = shift || die; - printf STDERR "Dump a %s\n", ref($self); - foreach my $k (sort keys %{$self}) { - my $val = $self->{$k}; - $val = '**UNDEF**' if !defined $val; - printf STDERR " %-20s %s\n", $k, $val; - } -} - -# Based on Autoloader - -sub import { - my $pkg = shift; - my $callpkg = caller; - - #print STDERR "import: $pkg, $callpkg\n"; - # - # Export symbols, but not by accident of inheritance. - # - die "Sombody inherited Zaptel::Utils" if $pkg ne 'Zaptel::Utils'; - no strict 'refs'; - *{ $callpkg . '::AUTOLOAD' } = \&AUTOLOAD; - *{ $callpkg . '::xpp_dump' } = \&xpp_dump; -} - -1; diff --git a/xpp/utils/zconf/Zaptel/Xpp.pm b/xpp/utils/zconf/Zaptel/Xpp.pm deleted file mode 100644 index 8a2a6eb..0000000 --- a/xpp/utils/zconf/Zaptel/Xpp.pm +++ /dev/null @@ -1,183 +0,0 @@ -package Zaptel::Xpp; -# -# Written by Oron Peled -# Copyright (C) 2007, Xorcom -# This program is free software; you can redistribute and/or -# modify it under the same terms as Perl itself. -# -# $Id$ -# -use strict; -use Zaptel::Xpp::Xbus; - -=head1 NAME - -Zaptel::Xpp - Perl interface to the Xorcom Astribank drivers. - -=head1 SYNOPSIS - - # Listing all Astribanks: - use Zaptel::Xpp; - # scans hardware: - my @xbuses = Zaptel::Xpp::xbuses("SORT_CONNECTOR"); - for my $xbus (@xbuses) { - print $xbus->name." (".$xbus->label .", ". $xbus->connector .")\n"; - for my $xpd ($xbus->xpds) { - print " - ".$xpd->fqn,"\n"; - } - } -=cut - - -my $proc_base = "/proc/xpp"; - -# Nominal sorters for xbuses -sub by_name { - return $a->name cmp $b->name; -} - -sub by_connector { - return $a->connector cmp $b->connector; -} - -sub by_label { - my $cmp = $a->label cmp $b->label; - return $cmp if $cmp != 0; - return $a->connector cmp $b->connector; -} - -=head1 xbuses([sort_order]) - -Scans system (/proc and /sys) and returns a list of Astribank (Xbus) -objects. The optional parameter sort_order is the order in which -the Astribanks will be returns: - -=over - -=item SORT_CONNECTOR - -Sort by the connector string. For USB this defines the "path" to get to -the device through controllers, hubs etc. - -=item SORT_LABEL - -Sorts by the label of the Astribank. The label field is unique to the -Astribank. It can also be viewed through 'lsusb -v' without the drivers -loaded (the iSerial field in the Device Descriptor). - -=item SORT_NAME - -Sort by the "name". e.g: "XBUS-00". The order of Astribank names depends -on the load order, and hence may change between different runs. - -=item custom function - -Instead of using a predefined sorter, you can pass your own sorting -function. See the example sorters in the code of this module. - -=back - -=cut - -sub xbuses { - my $optsort = shift || 'SORT_CONNECTOR'; - my @xbuses; - - -d "$proc_base" or return (); - my @lines; - local $/ = "\n"; - open(F, "$proc_base/xbuses") || - die "$0: Failed to open $proc_base/xbuses: $!\n"; - @lines = ; - close F; - foreach my $line (@lines) { - chomp $line; - my ($name, @attr) = split(/\s+/, $line); - $name =~ s/://; - $name =~ /XBUS-(\d\d)/ or die "Bad XBUS number: $name"; - my $num = $1; - @attr = map { split(/=/); } @attr; - my $xbus = Zaptel::Xpp::Xbus->new(NAME => $name, NUM => $num, @attr); - push(@xbuses, $xbus); - } - my $sorter; - if($optsort eq "SORT_CONNECTOR") { - $sorter = \&by_connector; - } elsif($optsort eq "SORT_NAME") { - $sorter = \&by_name; - } elsif($optsort eq "SORT_LABEL") { - $sorter = \&by_label; - } elsif(ref($optsort) eq 'CODE') { - $sorter = $optsort; - } else { - die "Unknown optional sorter '$optsort'"; - } - @xbuses = sort $sorter @xbuses; - return @xbuses; -} - -sub xpd_of_span($) { - my $span = shift or die "Missing span parameter"; - return undef unless defined $span; - foreach my $xbus (Zaptel::Xpp::xbuses('SORT_CONNECTOR')) { - foreach my $xpd ($xbus->xpds()) { - return $xpd if $xpd->fqn eq $span->name; - } - } - return undef; -} - -=head1 sync([new_sync_source]) - -Gets (and optionally sets) the internal Astribanks synchronization -source. When used to set sync source, returns the original sync source. - -A synchronization source is a value valid writing into /proc/xpp/sync . -For more information read that file and see README.Astribank . - -=cut - -sub sync { - my $newsync = shift; - my $result; - my $newapi = 0; - - my $file = "$proc_base/sync"; - return '' unless -f $file; - # First query - open(F, "$file") or die "Failed to open $file for reading: $!"; - while() { - chomp; - /SYNC=/ and $newapi = 1; - s/#.*//; - if(/\S/) { # First non-comment line - s/^SYNC=\D*// if $newapi; - $result = $_; - last; - } - } - close F; - if(defined($newsync)) { # Now change - $newsync =~ s/.*/\U$&/; - if($newsync =~ /^(\d+)$/) { - $newsync = ($newapi)? "SYNC=$1" : "$1 0"; - } elsif($newsync ne 'ZAPTEL') { - die "Bad sync parameter '$newsync'"; - } - open(F, ">$file") or die "Failed to open $file for writing: $!"; - print F $newsync; - close(F) or die "Failed in closing $file: $!"; - } - return $result; -} - -=head1 SEE ALSO - -For the documentation of xbus objects, see L. For -information about XPD objects, see L. - -General documentation can be found in the master package L. - -=cut - -1; diff --git a/xpp/utils/zconf/Zaptel/Xpp/Line.pm b/xpp/utils/zconf/Zaptel/Xpp/Line.pm deleted file mode 100644 index e3e04f0..0000000 --- a/xpp/utils/zconf/Zaptel/Xpp/Line.pm +++ /dev/null @@ -1,59 +0,0 @@ -package Zaptel::Xpp::Line; -# -# Written by Oron Peled -# Copyright (C) 2008, Xorcom -# This program is free software; you can redistribute and/or -# modify it under the same terms as Perl itself. -# -# $Id$ -# -use strict; -use Zaptel::Utils; - -my $proc_base = "/proc/xpp"; - -sub new($$$) { - my $pack = shift or die "Wasn't called as a class method\n"; - my $xpd = shift or die; - my $index = shift; - defined $index or die; - my $self = {}; - bless $self, ref($xpd); - $self->{XPD} = $xpd; - $self->{INDEX} = $index; - return $self; -} - -sub create_all($$) { - my $pack = shift or die "Wasn't called as a class method\n"; - my $xpd = shift || die; - my $procdir = shift || die; - local $/ = "\n"; - my @lines; - for(my $i = 0; $i < $xpd->{CHANNELS}; $i++) { - my $line = Zaptel::Xpp::Line->new($xpd, $i); - push(@lines, $line); - } - $xpd->{LINES} = \@lines; - my ($infofile) = glob "$procdir/*_info"; - die "Failed globbing '$procdir/*_info'" unless defined $infofile; - my $type = $xpd->type; - open(F, "$infofile") || die "Failed opening '$infofile': $!"; - while () { - chomp; - if($type eq 'FXO') { - if(s/^\s*battery\s*:\s*//) { - my @batt = split; - foreach my $l (@lines) { - die unless @batt; - $l->{BATTERY} = shift @batt; - } - die if @batt; - } - } - } - close F; -} - - -1; diff --git a/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm b/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm deleted file mode 100644 index a5fcf1e..0000000 --- a/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm +++ /dev/null @@ -1,117 +0,0 @@ -package Zaptel::Xpp::Xbus; -# -# Written by Oron Peled -# Copyright (C) 2007, Xorcom -# This program is free software; you can redistribute and/or -# modify it under the same terms as Perl itself. -# -# $Id$ -# -use strict; -use Zaptel::Utils; -use Zaptel::Xpp::Xpd; - -my $proc_base = "/proc/xpp"; - -sub xpds($) { - my $xbus = shift; - return @{$xbus->{XPDS}}; -} - -sub by_number($) { - my $busnumber = shift; - die "Missing xbus number parameter" unless defined $busnumber; - my @xbuses = Zaptel::Xpp::xbuses(); - - my ($xbus) = grep { $_->num == $busnumber } @xbuses; - return $xbus; -} - -sub by_label($) { - my $label = shift; - die "Missing xbus label parameter" unless defined $label; - my @xbuses = Zaptel::Xpp::xbuses(); - - my ($xbus) = grep { $_->label eq $label } @xbuses; - return $xbus; -} - -sub get_xpd_by_number($$) { - my $xbus = shift; - my $xpdid = shift; - die "Missing XPD id parameter" unless defined $xpdid; - my @xpds = $xbus->xpds; - return $xpds[$xpdid]; -} - -sub new($$) { - my $pack = shift or die "Wasn't called as a class method\n"; - my $self = {}; - bless $self, $pack; - while(@_) { - my ($k, $v) = @_; - shift; shift; - # Keys in all caps - $k = uc($k); - # Some values are in all caps as well - if($k =~ /^(STATUS)$/) { - $v = uc($v); - } - $self->{$k} = $v; - } - # backward compat for drivers without labels. - if(!defined $self->{LABEL}) { - $self->{LABEL} = '[]'; - } - $self->{LABEL} =~ s/^\[(.*)\]$/$1/ or die "$self->{NAME}: Bad label"; - # Fix badly burned labels. - $self->{LABEL} =~ s/[[:^print:]]/_/g; - $self->{NAME} or die "Missing xbus name"; - my $prefix = "$proc_base/" . $self->{NAME}; - my $usbfile = "$prefix/xpp_usb"; - if(open(F, "$usbfile")) { - my $head = ; - chomp $head; - close F; - $head =~ s/^device: +([^, ]+)/$1/i or die; - $self->{USB_DEVNAME} = $head; - } - @{$self->{XPDS}} = (); - foreach my $dir (glob "$prefix/XPD-??") { - my $xpd = Zaptel::Xpp::Xpd->new($self, $dir); - push(@{$self->{XPDS}}, $xpd); - } - @{$self->{XPDS}} = sort { $a->id <=> $b->id } @{$self->{XPDS}}; - return $self; -} - -sub pretty_xpds($) { - my $xbus = shift; - my @xpds = sort { $a->id <=> $b->id } $xbus->xpds(); - my @xpd_types = map { $_->type } @xpds; - my $last_type = ''; - my $mult = 0; - my $xpdstr = ''; - foreach my $curr (@xpd_types) { - if(!$last_type || ($curr eq $last_type)) { - $mult++; - } else { - if($mult == 1) { - $xpdstr .= "$last_type "; - } elsif($mult) { - $xpdstr .= "$last_type*$mult "; - } - $mult = 1; - } - $last_type = $curr; - } - if($mult == 1) { - $xpdstr .= "$last_type "; - } elsif($mult) { - $xpdstr .= "$last_type*$mult "; - } - $xpdstr =~ s/\s*$//; # trim trailing space - return $xpdstr; -} - -1; diff --git a/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm b/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm deleted file mode 100644 index 326aafd..0000000 --- a/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm +++ /dev/null @@ -1,123 +0,0 @@ -package Zaptel::Xpp::Xpd; -# -# Written by Oron Peled -# Copyright (C) 2007, Xorcom -# This program is free software; you can redistribute and/or -# modify it under the same terms as Perl itself. -# -# $Id$ -# -use strict; -use Zaptel::Utils; -use Zaptel::Xpp; -use Zaptel::Xpp::Line; - -my $proc_base = "/proc/xpp"; - -sub blink($$) { - my $self = shift; - my $on = shift; - my $result; - - my $file = "$proc_base/" . $self->fqn . "/blink"; - die "$file is missing" unless -f $file; - # First query - open(F, "$file") or die "Failed to open $file for reading: $!"; - $result = ; - chomp $result; - close F; - if(defined($on) and $on ne $result) { # Now change - open(F, ">$file") or die "Failed to open $file for writing: $!"; - print F ($on)?"1":"0"; - if(!close(F)) { - if($! == 17) { # EEXISTS - # good - } else { - undef $result; - } - } - } - return $result; -} - -sub zt_registration($$) { - my $self = shift; - my $on = shift; - my $result; - - my $file = "$proc_base/" . $self->fqn . "/zt_registration"; - die "$file is missing" unless -f $file; - # First query - open(F, "$file") or die "Failed to open $file for reading: $!"; - $result = ; - chomp $result; - close F; - if(defined($on) and $on ne $result) { # Now change - open(F, ">$file") or die "Failed to open $file for writing: $!"; - print F ($on)?"1":"0"; - if(!close(F)) { - if($! == 17) { # EEXISTS - # good - } else { - undef $result; - } - } - } - return $result; -} - -sub xpds_by_spanno() { - my @xbuses = Zaptel::Xpp::xbuses("SORT_CONNECTOR"); - my @xpds = map { $_->xpds } @xbuses; - @xpds = grep { $_->spanno } @xpds; - @xpds = sort { $a->spanno <=> $b->spanno } @xpds; - my @spanno = map { $_->spanno } @xpds; - my @idx; - @idx[@spanno] = @xpds; # The spanno is the index now - return @idx; -} - -sub new($$) { - my $pack = shift or die "Wasn't called as a class method\n"; - my $xbus = shift || die; - my $procdir = shift || die; - my $self = {}; - bless $self, $pack; - $self->{XBUS} = $xbus; - $self->{DIR} = $procdir; - local $/ = "\n"; - open(F, "$procdir/summary") || die "Missing summary file in $procdir"; - my $head = ; - chomp $head; # "XPD-00 (BRI_TE ,card present, span 3)" - # The driver does not export the number of channels... - # Let's find it indirectly - while() { - chomp; - if(s/^\s*offhook\s*:\s*//) { - my @offhook = split; - @offhook || die "No channels in '$procdir/summary'"; - $self->{CHANNELS} = @offhook; - last; - } - } - close F; - $head =~ s/^(XPD-(\d\d))\s+// || die; - $self->{ID} = $2; - $self->{FQN} = $xbus->name . "/" . $1; - $head =~ s/^.*\(// || die; - $head =~ s/\) */, / || die; - $head =~ s/\s*,\s*/,/g || die; - my ($type,$present,$span,$rest) = split(/,/, $head); - #warn "Garbage in '$procdir/summary': rest='$rest'\n" if $rest; - if($span =~ s/span\s+(\d+)//) { # since changeset:5119 - $self->{SPANNO} = $1; - } - $self->{TYPE} = $type; - $self->{IS_BRI} = ($type =~ /BRI_(NT|TE)/); - $self->{IS_PRI} = ($type =~ /[ETJ]1_(NT|TE)/); - $self->{IS_DIGITAL} = ( $self->{IS_BRI} || $self->{IS_PRI} ); - Zaptel::Xpp::Line->create_all($self, $procdir); - return $self; -} - -1; diff --git a/xpp/utils/zt_registration b/xpp/utils/zt_registration deleted file mode 100755 index 3bdc642..0000000 --- a/xpp/utils/zt_registration +++ /dev/null @@ -1,125 +0,0 @@ -#! /usr/bin/perl -w -# -# Written by Oron Peled -# Copyright (C) 2007, Xorcom -# This program is free software; you can redistribute and/or -# modify it under the same terms as Perl itself. -# -# $Id$ -# -use strict; -use File::Basename; -BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/zconf"); } - -use Zaptel; -use Zaptel::Span; -use Zaptel::Xpp; -use Zaptel::Xpp::Xbus; - -sub usage { - die "Usage: $0 [on|off|1|0]\n"; -} - -@ARGV == 0 or @ARGV == 1 or usage; -my $on = shift; -my $verbose = 0; -my $should_output = 1; - -if(defined($on)) { # Translate to booleans - $on = uc($on); - $on =~ /^(ON|OFF|1|0)$/ or usage; - $on = ($on eq 'ON') ? 1 : 0; - $should_output = 0 unless $verbose; -} - -sub state2str($) { - return (shift)?"on":"off"; -} - -sub myprintf { - printf @_ if $should_output; -} - -my @spans = Zaptel::spans; - -foreach my $xbus (Zaptel::Xpp::xbuses('SORT_CONNECTOR')) { - myprintf "%-10s\t%s\t%s\n", $xbus->name, $xbus->label, $xbus->connector; - next unless $xbus->status eq 'CONNECTED'; - foreach my $xpd ($xbus->xpds()) { - my $prev = $xpd->zt_registration($on); - if(!defined($prev)) { # Failure - printf "%s: Failed %s\n", $xpd->fqn, $!; - next; - } - myprintf "\t%-10s: ", $xpd->fqn; - if(!defined($on)) { # Query only - my ($span) = grep { $_->name eq $xpd->fqn } @spans; - my $spanstr = ($span) ? ("Span " . $span->num) : ""; - myprintf "%s %s\n", state2str($prev), $spanstr ; - next; - } - myprintf "%3s ==> %3s\n", state2str($prev), state2str($on); - } -} - -__END__ - -=head1 NAME - -zt_registration - Handle registration of Xorcom XPD modules in zaptel. - -=head1 SYNOPSIS - -zt_registration [on|off] - -=head1 DESCRIPTION - -Without parameters, show all connected XPDs sorted by physical connector order. -Each one is show to be unregistered (off), or registered to a specific zaptel -span (the span number is shown). - -All registerations/deregisterations are sorted by physical connector string. - -Span registration should generally always succeed. Span unregistration may -fail if channels from the span are in use by e.g. asterisk. In such a case -you'll also see those channels as '(In use)' in the output of lszaptel(8). - -=head2 Parameters - -off -- deregisters all XPD's from zaptel. - -on -- registers all XPD's to zaptel. - -=head2 Sample Output - -An example of the output of zt_registration for some registered -Astribanks: - - $ zt_registration - XBUS-02 [] usb-0000:00:1d.7-4 - XBUS-00/XPD-00: on Span 1 - XBUS-00/XPD-10: on Span 2 - XBUS-00 [usb:00000126] usb-0000:00:1d.7-2 - XBUS-02/XPD-00: on Span 3 - XBUS-02/XPD-10: on Span 4 - XBUS-02/XPD-20: on Span 5 - XBUS-02/XPD-30: on Span 6 - XBUS-01 [usb:00000128] usb-0000:00:1d.7-1 - XBUS-01/XPD-00: on Span 7 - XBUS-01/XPD-10: on Span 8 - XBUS-01/XPD-20: on Span 9 - XBUS-01/XPD-30: on Span 10 - -=head1 FILES - -=over - -=item /proc/xpp/XBUS-nn/XPD-mm/zt_registration - -Reading from this file shows if if the if the specific XPD is -registered. Writing to it 0 or 1 registers / unregisters the device. - -This should allow you to register / unregister a specific XPD rather -than all of them. - -=back diff --git a/xpp/xbus-core.c b/xpp/xbus-core.c deleted file mode 100644 index 790c12a..0000000 --- a/xpp/xbus-core.c +++ /dev/null @@ -1,1798 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -# warning "This module is tested only with 2.6 kernels" -#endif - -#include -#include -#include -#include -#ifdef PROTOCOL_DEBUG -#include -#endif -#include -#include -#include /* for msleep() to debug */ -#include "xpd.h" -#include "xpp_zap.h" -#include "xbus-core.h" -#ifdef XPP_DEBUGFS -#include "xpp_log.h" -#endif -#include "zap_debug.h" - -static const char rcsid[] = "$Id$"; - -/* Defines */ -#define INITIALIZATION_TIMEOUT (60*HZ) /* in jiffies */ -#define PROC_XBUSES "xbuses" -#define PROC_XBUS_SUMMARY "summary" -#define PROC_XBUS_WAITFOR_XPDS "waitfor_xpds" - -#ifdef PROTOCOL_DEBUG -#define PROC_XBUS_COMMAND "command" -static int proc_xbus_command_write(struct file *file, const char __user *buffer, unsigned long count, void *data); -#endif - -/* Command line parameters */ -extern int print_dbg; -DEF_PARM(uint, poll_timeout, 1000, 0644, "Timeout (in jiffies) waiting for units to reply"); -DEF_PARM_BOOL(rx_tasklet, 0, 0644, "Use receive tasklets"); - -static int xbus_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data); -static int xbus_read_waitfor_xpds(char *page, char **start, off_t off, int count, int *eof, void *data); -static void transport_init(xbus_t *xbus, struct xbus_ops *ops, ushort max_send_size, void *priv); -static void transport_destroy(xbus_t *xbus); - -/* - * Encapsulate all poll related data of a single xbus. - */ -struct xbus_poller { - /* - * Bus scanning - */ - uint xbus_num; - struct workqueue_struct *wq; - bool is_polling; - atomic_t count_poll_answers; - struct list_head poll_results; - wait_queue_head_t wait_for_polls; - - struct work_struct xpds_init_work; - - atomic_t count_xpds_to_initialize; - atomic_t count_xpds_initialized; - wait_queue_head_t wait_for_xpd_initialization; - struct proc_dir_entry *proc_xbus_waitfor_xpds; -}; - -/* Data structures */ -static spinlock_t xbuses_lock = SPIN_LOCK_UNLOCKED; -static int bus_count = 0; -static struct proc_dir_entry *proc_xbuses = NULL; - -static struct xbus_desc { - xbus_t *xbus; - atomic_t xbus_refcount; - wait_queue_head_t can_release_xbus; -} xbuses_array[MAX_BUSES]; - -static void init_xbus(uint num, xbus_t *xbus) -{ - struct xbus_desc *desc; - - BUG_ON(num >= ARRAY_SIZE(xbuses_array)); - desc = &xbuses_array[num]; - desc->xbus = xbus; - atomic_set(&desc->xbus_refcount, 0); - init_waitqueue_head(&desc->can_release_xbus); -} - -int refcount_xbus(uint num) -{ - BUG_ON(num >= ARRAY_SIZE(xbuses_array)); - return atomic_read(&xbuses_array[num].xbus_refcount); -} - -xbus_t *get_xbus(uint num) -{ - struct xbus_desc *desc; - - if(num >= ARRAY_SIZE(xbuses_array)) - return NULL; - desc = &xbuses_array[num]; - atomic_inc(&desc->xbus_refcount); - if(!desc->xbus) - atomic_dec(&desc->xbus_refcount); - return desc->xbus; -} - -void put_xbus(xbus_t *xbus) -{ - struct xbus_desc *desc; - int num; - - BUG_ON(!xbus); - num = xbus->num; - BUG_ON(num >= ARRAY_SIZE(xbuses_array)); - desc = &xbuses_array[num]; - BUG_ON(desc->xbus != xbus); - if(atomic_dec_and_test(&desc->xbus_refcount)) { - static int rate_limit; - - if((rate_limit++ % 1003) == 0) - XBUS_DBG(DEVICES, xbus, - "wake_up(can_release_xbus) (%d)\n", rate_limit); - wake_up(&desc->can_release_xbus); - } -} - -bool __must_check wait_for_xbus_release(uint xbus_num) -{ - xbus_t *xbus; - int ret; - - xbus = get_xbus(xbus_num); - if(!xbus) { - ERR("%s: xbus #%d is already removed. Skip.\n", - __FUNCTION__, xbus_num); - return 0; - } - put_xbus(xbus); - DBG(DEVICES, "Waiting... refcount_xbus=%d\n", refcount_xbus(xbus_num)); - ret = wait_event_interruptible(xbuses_array[xbus_num].can_release_xbus, - refcount_xbus(xbus_num) == 0); - if(ret) { - ERR("%s: waiting for xbus #%d interrupted!!!\n", - __FUNCTION__, xbus_num); - } else - DBG(DEVICES, "Waiting for refcount_xbus done.\n"); - return 1; -} - -static void initialize_xbuses_array(void) -{ - int i; - - for(i = 0; i < ARRAY_SIZE(xbuses_array); i++) - init_xbus(i, NULL); -} - -static void finalize_xbuses_array(void) -{ - int i; - - for(i = 0; i < ARRAY_SIZE(xbuses_array); i++) { - if(xbuses_array[i].xbus != NULL) { - ERR("%s: xbus #%d is not NULL\n", __FUNCTION__, i); - BUG(); - } - } -} - -/*------------------------- Debugfs Handling -----------------------*/ -#ifdef XPP_DEBUGFS - -#define DEBUGFS_BUFSIZ 4096 /* must be power of two, otherwise POS_IN_BUF will have to use '%' instead of '&' */ -#define POS_IN_BUF(x) ((x) & (DEBUGFS_BUFSIZ-1)) - -struct debugfs_data { - spinlock_t lock; - xbus_t *xbus; - char buffer[DEBUGFS_BUFSIZ]; - unsigned long head, tail; /* reading and writing are performed at position (head % BUF_SIZ) and (tail % BUF_SIZ) */ - wait_queue_head_t queue; -}; - -static unsigned long add_to_buf(struct debugfs_data *d, unsigned long tail, const void *buf, unsigned long len) -{ - unsigned long count = min(len, (unsigned long)(DEBUGFS_BUFSIZ - POS_IN_BUF(tail))); - memcpy(d->buffer + POS_IN_BUF(tail), buf, count); /* fill starting at position tail */ - memcpy(d->buffer, (u_char *)buf + count, len - count); /* fill leftover */ - return len; -} - -int xbus_log(xbus_t *xbus, xpd_t *xpd, int direction, const void *buf, unsigned long len) -{ - unsigned long tail; - unsigned long flags; - struct debugfs_data *d; - struct log_header header; - int ret = 0; - - BUG_ON(!xbus); - BUG_ON(!xpd); - BUG_ON(sizeof(struct log_header) + len > DEBUGFS_BUFSIZ); - d = xbus->debugfs_data; - if (!d) /* no consumer process */ - return ret; - spin_lock_irqsave(&d->lock, flags); - if (sizeof(struct log_header) + len > DEBUGFS_BUFSIZ - (d->tail - d->head)) { - ret = -ENOSPC; - XPD_DBG(GENERAL, xpd, "Dropping debugfs data of len %lu, free space is %lu\n", sizeof(struct log_header) + len, - DEBUGFS_BUFSIZ - (d->tail - d->head)); - goto out; - } - header.len = sizeof(struct log_header) + len; - header.time = jiffies_to_msecs(jiffies); - header.xpd_num = xpd->xbus_idx; - header.direction = (char)direction; - tail = d->tail; - tail += add_to_buf(d, tail, &header, sizeof(header)); - tail += add_to_buf(d, tail, buf, len); - d->tail = tail; - wake_up_interruptible(&d->queue); -out: - spin_unlock_irqrestore(&d->lock, flags); - return ret; -} - -static struct dentry *debugfs_root = NULL; -static int debugfs_open(struct inode *inode, struct file *file); -static ssize_t debugfs_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos); -static int debugfs_release(struct inode *inode, struct file *file); - -static struct file_operations debugfs_operations = { - .open = debugfs_open, - .read = debugfs_read, - .release = debugfs_release, -}; - -/* - * As part of the "inode diet" the private data member of struct inode - * has changed in 2.6.19. However, Fedore Core 6 adopted this change - * a bit earlier (2.6.18). If you use such a kernel, Change the - * following test from 2,6,19 to 2,6,18. - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -#define I_PRIVATE(inode) ((inode)->u.generic_ip) -#else -#define I_PRIVATE(inode) ((inode)->i_private) -#endif - -static int debugfs_open(struct inode *inode, struct file *file) -{ - xbus_t *xbus = I_PRIVATE(inode); - struct debugfs_data *d; - struct log_global_header gheader; - - BUG_ON(!xbus); - XBUS_DBG(GENERAL, xbus, "\n"); - if (xbus->debugfs_data) - return -EBUSY; - d = KZALLOC(sizeof(struct debugfs_data), GFP_KERNEL); - if (!d) - return -ENOMEM; - try_module_get(THIS_MODULE); - spin_lock_init(&d->lock); - d->xbus = xbus; - d->head = d->tail = 0; - init_waitqueue_head(&d->queue); - file->private_data = d; - - gheader.magic = XPP_LOG_MAGIC; - gheader.version = 1; - d->tail += add_to_buf(d, d->tail, &gheader, sizeof(gheader)); - - xbus->debugfs_data = d; - return 0; -} - -static ssize_t debugfs_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) -{ - struct debugfs_data *d = file->private_data; - size_t len; - - BUG_ON(!d); - BUG_ON(!d->xbus); - XBUS_DBG(GENERAL, d->xbus, "\n"); - while (d->head == d->tail) { - if (wait_event_interruptible(d->queue, d->head != d->tail)) - return -EAGAIN; - } - len = min(nbytes, (size_t)(d->tail - d->head)); - if (copy_to_user(buf, d->buffer + POS_IN_BUF(d->head), len)) - return -EFAULT; - d->head += len; - /* optimization to avoid future buffer wraparound */ - if (d->head == d->tail) { - unsigned long flags; - spin_lock_irqsave(&d->lock, flags); - if (d->head == d->tail) - d->head = d->tail = 0; - spin_unlock_irqrestore(&d->lock, flags); - } - return len; -} - -static int debugfs_release(struct inode *inode, struct file *file) -{ - struct debugfs_data *d = file->private_data; - - BUG_ON(!d); - BUG_ON(!d->xbus); - XBUS_DBG(GENERAL, d->xbus, "\n"); - d->xbus->debugfs_data = NULL; - kfree(d); - module_put(THIS_MODULE); - return 0; -} -#endif - -/*------------------------- Frame Handling ------------------------*/ - -void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize, void *priv) -{ - memset(xframe, 0, sizeof(*xframe)); - INIT_LIST_HEAD(&xframe->frame_list); - xframe->priv = priv; - xframe->xbus = xbus; - xframe->packets = xframe->first_free = buf; - xframe->frame_maxlen = maxsize; - atomic_set(&xframe->frame_len, 0); - do_gettimeofday(&xframe->tv_created); - xframe->xframe_magic = XFRAME_MAGIC; -} - -/* - * Return pointer to next packet slot in the frame - * or NULL if the frame is full. - * - * FIXME: we do not use atomic_add_return() because kernel-2.6.8 - * does not have it. This make this code a little racy, - * but we currently call xframe_next_packet() only in the - * PCM loop (xbus_tick() etc.) - */ -xpacket_t *xframe_next_packet(xframe_t *frm, int len) -{ - int newlen = XFRAME_LEN(frm); - - newlen += len; -// DBG(GENERAL, "len=%d, newlen=%d, frm->frame_len=%d\n", len, newlen, XFRAME_LEN(frm)); - if (newlen > XFRAME_DATASIZE) { - return NULL; - } - atomic_add(len, &frm->frame_len); - return (xpacket_t *)(frm->packets + newlen - len); -} - -static spinlock_t serialize_dump_xframe = SPIN_LOCK_UNLOCKED; - -static void do_hexdump(const char msg[], byte *data, uint16_t len) -{ - int i; - int print_dbg = DBG_ANY; /* mask global print_dbg */ - - for(i = 0; i < len; i++) - DBG(ANY, "%s: %3d> %02X\n", msg, i, data[i]); -} - -void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe) -{ - const uint16_t frm_len = XFRAME_LEN(xframe); - xpacket_t *pack; - uint16_t pos = 0; - uint16_t nextpos; - int num = 1; - bool do_print; - unsigned long flags; - - if(xframe->xframe_magic != XFRAME_MAGIC) { - XBUS_ERR(xbus, "%s: bad xframe_magic %lX\n", - __FUNCTION__, xframe->xframe_magic); - return; - } - spin_lock_irqsave(&serialize_dump_xframe, flags); - do { - if(pos >= xbus->transport.max_send_size) { - if(printk_ratelimit()) { - XBUS_NOTICE(xbus, "%s: xframe overflow (%d bytes)\n", - msg, frm_len); - do_hexdump(msg, xframe->packets, frm_len); - } - break; - } - if(pos > frm_len) { - if(printk_ratelimit()) { - XBUS_NOTICE(xbus, "%s: packet overflow pos=%d frame_len=%d\n", - msg, pos, frm_len); - do_hexdump(msg, xframe->packets, frm_len); - } - break; - } - pack = (xpacket_t *)&xframe->packets[pos]; - if(XPACKET_LEN(pack) <= 0) { - if(printk_ratelimit()) { - XBUS_NOTICE(xbus, "%s: xframe -- bad packet_len=%d pos=%d frame_len=%d\n", - msg, XPACKET_LEN(pack), pos, frm_len); - do_hexdump(msg, xframe->packets, frm_len); - } - break; - } - nextpos = pos + XPACKET_LEN(pack); - if(nextpos > frm_len) { - if(printk_ratelimit()) { - XBUS_NOTICE(xbus, "%s: packet overflow nextpos=%d frame_len=%d\n", - msg, nextpos, frm_len); - do_hexdump(msg, xframe->packets, frm_len); - } - break; - } - do_print = 0; - if(XPACKET_OP(pack) != XPROTO_NAME(GLOBAL,PCM_READ) && - XPACKET_OP(pack) != XPROTO_NAME(GLOBAL,PCM_WRITE)) - do_print = 1; - else if(print_dbg & DBG_PCM) { - static int rate_limit; - - if((rate_limit++ % 1003) == 0) - do_print = 1; - } - if(do_print) { - if(num == 1) { - XBUS_DBG(ANY, xbus, "%s: frame_len=%d. %s\n", - msg, frm_len, - (XPACKET_IS_PCM(pack)) - ? "(IS_PCM)" - : ""); - } - XBUS_DBG(ANY, xbus, " %3d. DATALEN=%d pcm=%d slot=%d OP=0x%02X XPD-%d%d (pos=%d)\n", - num, XPACKET_LEN(pack), - XPACKET_IS_PCM(pack), XPACKET_PCMSLOT(pack), - XPACKET_OP(pack), - XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack), - pos); - dump_packet(" ", pack, print_dbg); - } - num++; - pos = nextpos; - if(pos >= frm_len) - break; - } while(1); - spin_unlock_irqrestore(&serialize_dump_xframe, flags); -} - -bool xbus_ready(const xbus_t *xbus, const char msg[]) -{ - if(!xbus) { - ERR("null xbus: %s\n", msg); - return 0; - } - if (!TRANSPORT_RUNNING(xbus)) { - XBUS_ERR(xbus, "%s -- hardware is not ready.", msg); - return 0; - } - if(!xbus->transport.ops) { - XBUS_ERR(xbus, "%s -- hardware is gone.", msg); - return 0; - } - return 1; -} - -/** - * - * Frame is freed: - * - In case of error, by this function. - * - Otherwise, by the underlying sending mechanism - */ -int send_pcm_frame(xbus_t *xbus, xframe_t *xframe) -{ - struct xbus_ops *ops; - int ret = -ENODEV; - - BUG_ON(!xframe); - if(!xbus_ready(xbus, "Dropped a pcm frame")) { - ret = -ENODEV; - goto error; - } - ops = transportops_get(xbus); - BUG_ON(!ops); - ret = ops->xframe_send_pcm(xbus, xframe); - transportops_put(xbus); - if(ret) - XBUS_COUNTER(xbus, TX_BYTES) += XFRAME_LEN(xframe); - return ret; - -error: - FREE_SEND_XFRAME(xbus, xframe); - return ret; -} - -static int really_send_cmd_frame(xbus_t *xbus, xframe_t *xframe) -{ - struct xbus_ops *ops; - int ret; - - BUG_ON(!xbus); - BUG_ON(!xframe); - BUG_ON(xframe->xframe_magic != XFRAME_MAGIC); - if(!xbus_ready(xbus, "Dropped command before sending")) { - FREE_SEND_XFRAME(xbus, xframe); - return -ENODEV; - } - ops = transportops_get(xbus); - BUG_ON(!ops); - ret = ops->xframe_send_cmd(xbus, xframe); - transportops_put(xbus); - if(ret == 0) { - XBUS_COUNTER(xbus, TX_CMD)++; - XBUS_COUNTER(xbus, TX_BYTES) += XFRAME_LEN(xframe); - } - return ret; -} - -int xbus_command_queue_tick(xbus_t *xbus) -{ - xframe_t *frm; - int ret = 0; - - frm = xframe_dequeue(&xbus->command_queue); - if(frm) { - BUG_ON(frm->xframe_magic != XFRAME_MAGIC); - ret = really_send_cmd_frame(xbus, frm); - if(ret < 0) - XBUS_ERR(xbus, - "Failed to send from command_queue (ret=%d)\n", - ret); - XBUS_PUT(xbus); - } else - wake_up(&xbus->command_queue_empty); - return ret; -} - -static void xbus_command_queue_clean(xbus_t *xbus) -{ - xframe_t *frm; - - XBUS_DBG(DEVICES, xbus, "count=%d\n", xbus->command_queue.count); - xframe_queue_disable(&xbus->command_queue); - while((frm = xframe_dequeue(&xbus->command_queue)) != NULL) { - FREE_SEND_XFRAME(xbus, frm); - XBUS_PUT(xbus); - } -} - -static int xbus_command_queue_waitempty(xbus_t *xbus) -{ - int ret; - - XBUS_DBG(DEVICES, xbus, "Waiting for command_queue to empty\n"); - ret = wait_event_interruptible(xbus->command_queue_empty, - xframe_queue_count(&xbus->command_queue) == 0); - if(ret) { - XBUS_ERR(xbus, "waiting for command_queue interrupted!!!\n"); - } - return ret; -} - -int send_cmd_frame(xbus_t *xbus, xframe_t *xframe) -{ - static int rate_limit; - const char *msg = ""; - int ret = 0; - - - BUG_ON(xframe->xframe_magic != XFRAME_MAGIC); - if(!xbus_ready(xbus, "Dropped command before queueing")) { - ret = -ENODEV; - goto err; - } - if(!XBUS_GET(xbus)) { - msg = "Dropped command xframe. Is shutting down."; - ret = -ENODEV; - goto err; - } - if(!xframe_enqueue(&xbus->command_queue, xframe)) { - XBUS_PUT(xbus); - msg = "Dropped command xframe. Cannot enqueue."; - ret = -E2BIG; - goto err; - } - return 0; -err: - if((rate_limit++ % 1003) == 0) { - XBUS_ERR(xbus, "%s\n", msg); - dump_xframe("send_cmd_frame", xbus, xframe); - } - FREE_SEND_XFRAME(xbus, xframe); - return ret; -} - -/*------------------------- Receive Tasklet Handling ---------------*/ - -static void xframe_enqueue_recv(xbus_t *xbus, xframe_t *xframe) -{ - int cpu = smp_processor_id(); - - BUG_ON(!xbus); - xbus->cpu_rcv_intr[cpu]++; - if(!xframe_enqueue(&xbus->receive_queue, xframe)) { - static int rate_limit; - - if((rate_limit++ % 1003) == 0) - XBUS_ERR(xbus, "Failed to enqueue for receive_tasklet (%d)\n", rate_limit); - FREE_RECV_XFRAME(xbus, xframe); /* return to receive_pool */ - return; - } - tasklet_schedule(&xbus->receive_tasklet); -} - -/* - * process frames in the receive_queue in a tasklet - */ -static void receive_tasklet_func(unsigned long data) -{ - xbus_t *xbus = (xbus_t *)data; - xframe_t *xframe = NULL; - int cpu = smp_processor_id(); - - BUG_ON(!xbus); - xbus->cpu_rcv_tasklet[cpu]++; - while((xframe = xframe_dequeue(&xbus->receive_queue)) != NULL) { - xframe_receive(xbus, xframe); - } -} - -void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe) -{ - BUG_ON(!xbus); - if(rx_tasklet) { - xframe_enqueue_recv(xbus, xframe); - } else { - if (likely(TRANSPORT_RUNNING(xbus))) - xframe_receive(xbus, xframe); - else - FREE_RECV_XFRAME(xbus, xframe); /* return to receive_pool */ - } -} - -/*------------------------- Bus Management -------------------------*/ -xpd_t *xpd_of(const xbus_t *xbus, int xpd_num) -{ - if(!VALID_XPD_NUM(xpd_num)) - return NULL; - return xbus->xpds[xpd_num]; -} - -xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit) -{ - if(unit > MAX_UNIT || subunit > MAX_SUBUNIT) - return NULL; - return xbus->xpds[XPD_IDX(unit,subunit)]; -} - -int xbus_register_xpd(xbus_t *xbus, xpd_t *xpd) -{ - unsigned int xpd_num = xpd->xbus_idx; - unsigned long flags; - int ret = 0; - - xbus = get_xbus(xbus->num); /* until unregister */ - BUG_ON(!xbus); - XBUS_DBG(DEVICES, xbus, "XPD #%d (xbus_refcount=%d)\n", - xpd_num, refcount_xbus(xbus->num)); - spin_lock_irqsave(&xbus->lock, flags); - if(!VALID_XPD_NUM(xpd_num)) { - XBUS_ERR(xbus, "Bad xpd_num = %d\n", xpd_num); - ret = -EINVAL; - goto out; - } - if(xbus->xpds[xpd_num] != NULL) { - xpd_t *other = xbus->xpds[xpd_num]; - - XBUS_ERR(xbus, "xpd_num=%d is occupied by %p (%s)\n", - xpd_num, other, other->xpdname); - ret = -EINVAL; - goto out; - } - xbus->xpds[xpd_num] = xpd; - xpd->xbus = xbus; - xbus->num_xpds++; -out: - spin_unlock_irqrestore(&xbus->lock, flags); - return ret; -} - -int xbus_unregister_xpd(xbus_t *xbus, xpd_t *xpd) -{ - unsigned int xpd_num = xpd->xbus_idx; - unsigned long flags; - int ret = -EINVAL; - - spin_lock_irqsave(&xbus->lock, flags); - XBUS_DBG(DEVICES, xbus, "XPD #%d (xbus_refcount=%d)\n", - xpd_num, refcount_xbus(xbus->num)); - if(!VALID_XPD_NUM(xpd_num)) { - XBUS_ERR(xbus, "%s: Bad xpd_num = %d\n", __FUNCTION__, xpd_num); - goto out; - } - if(xbus->xpds[xpd_num] == NULL) { - XBUS_ERR(xbus, "%s: slot xpd_num=%d is empty\n", __FUNCTION__, xpd_num); - goto out; - } - if(xbus->xpds[xpd_num] != xpd) { - xpd_t *other = xbus->xpds[xpd_num]; - - XBUS_ERR(xbus, "%s: slot xpd_num=%d is occupied by %p (%s)\n", - __FUNCTION__, xpd_num, other, other->xpdname); - goto out; - } - xbus->xpds[xpd_num] = NULL; - xbus->num_xpds--; - xpd->xbus = NULL; - put_xbus(xbus); /* we got it in xbus_register_xpd() */ - ret = 0; -out: - spin_unlock_irqrestore(&xbus->lock, flags); - return ret; -} - -/* - * This must be called from synchronous (non-interrupt) context - * it returns only when all XPD's on the bus are detected and - * initialized. - */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) -static void xbus_poll(struct work_struct *work) -{ - struct xbus_poller *poller = container_of(work, struct xbus_poller, xpds_init_work); -#else -static void xbus_poll(void *data) -{ - struct xbus_poller *poller = data; -#endif - int id; - int ret = 0; - unsigned long flags; - struct list_head *card; - struct list_head *next_card; - struct list_head removal_list; - struct list_head additions_list; - int count_removed; - int count_added; - xbus_t *xbus; - - BUG_ON(!poller); - xbus = get_xbus(poller->xbus_num); - if(!xbus) { - XBUS_ERR(xbus, "Aborting poll. XBUS #%d disappeared.\n", - poller->xbus_num); - return; - } - msleep(2); /* roundtrip for older polls */ - spin_lock_irqsave(&xbus->lock, flags); - XBUS_DBG(DEVICES, xbus, "\n"); - poller->is_polling = 1; - if(!XBUS_GET(xbus)) { - XBUS_ERR(xbus, "Aborting poll. Is shutting down.\n"); - goto out; - } - /* - * Send out the polls - */ - for(id = 0; id < MAX_XPDS; id++) { - if(!TRANSPORT_RUNNING(xbus)) - break; - XBUS_DBG(DEVICES, xbus, "Polling slot %d\n", id); - spin_unlock_irqrestore(&xbus->lock, flags); - ret = CALL_PROTO(GLOBAL, DESC_REQ, xbus, NULL, id); - spin_lock_irqsave(&xbus->lock, flags); - if(ret < 0) { - XBUS_ERR(xbus, "Failed sending DESC_REQ to XPD #%d\n", id); - goto out; - } - } - spin_unlock_irqrestore(&xbus->lock, flags); - /* - * Wait for replies - */ - XBUS_DBG(DEVICES, xbus, "Polled %d XPD's. Waiting for replies max %d jiffies\n", MAX_XPDS, poll_timeout); - ret = wait_event_interruptible_timeout(poller->wait_for_polls, atomic_read(&poller->count_poll_answers) >= MAX_XPDS, poll_timeout); - if(ret == 0) { - XBUS_ERR(xbus, "Poll timeout. Continuing anyway.\n"); - /* - * Continue processing. Maybe some units did reply. - */ - } else if(ret < 0) { - XBUS_ERR(xbus, "Poll interrupted %d\n", ret); - goto out; - } else - XBUS_DBG(DEVICES, xbus, "Poll finished in %d jiffies.\n", poll_timeout - ret); - /* - * Build removals/additions lists - */ - spin_lock_irqsave(&xbus->lock, flags); - INIT_LIST_HEAD(&removal_list); - INIT_LIST_HEAD(&additions_list); - count_removed = 0; - count_added = 0; - list_for_each_safe(card, next_card, &poller->poll_results) { - struct card_desc_struct *card_desc = list_entry(card, struct card_desc_struct, card_list); - byte type = card_desc->type; - xpd_t *xpd; - - BUG_ON(card_desc->magic != CARD_DESC_MAGIC); - /* - * Return the refcount we got in xbus_poller_notify() - * We are still protected by the refcount taken in - * the beginning of xbus_poll(). - */ - put_xbus(xbus); - xpd = xpd_byaddr(xbus, card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit); - - if(xpd && type == XPD_TYPE_NOMODULE) { /* card removal */ - list_move_tail(card, &removal_list); - count_removed++; - } else if(!xpd && type != XPD_TYPE_NOMODULE) { /* card detection */ - if(card_desc->rev != XPP_PROTOCOL_VERSION) { - XBUS_NOTICE(xbus, "XPD at %d%d: type=%d.%d has bad firmware revision %d.%d\n", - card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit, - card_desc->type, card_desc->subtype, - card_desc->rev / 10, card_desc->rev % 10); - list_del(card); - kfree(card_desc); - continue; - } - XBUS_INFO(xbus, "Detected XPD at %d%d type=%d.%d Revision %d.%d\n", - card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit, - card_desc->type, card_desc->subtype, - card_desc->rev / 10, card_desc->rev % 10); - list_move_tail(card, &additions_list); - count_added++; - } else { /* same same */ - list_del(card); - kfree(card_desc); - } - } - poller->is_polling = 0; - /* - * We set this *after* poll is finished, so wait_for_xpd_initialization can - * tell we already know how many units we have. - */ - atomic_set(&poller->count_xpds_to_initialize, count_added); - spin_unlock_irqrestore(&xbus->lock, flags); - XBUS_INFO(xbus, "Poll results: removals=%d additions=%d\n", count_removed, count_added); - /* - * Process removals first - */ - list_for_each_safe(card, next_card, &removal_list) { - struct card_desc_struct *card_desc = list_entry(card, struct card_desc_struct, card_list); - xpd_t *xpd; - - list_del(card); - xpd = xpd_byaddr(xbus, card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit); - if(xpd) - xpd_disconnect(xpd); - kfree(card); - } - /* - * Now process additions - */ - list_for_each_safe(card, next_card, &additions_list) { - struct card_desc_struct *card_desc = list_entry(card, struct card_desc_struct, card_list); - - list_del(card); - /* FIXME: card_detected() should have a return value for count_xpds_initialized */ - card_detected(card_desc); - atomic_inc(&poller->count_xpds_initialized); - } - /* Device-Model */ - if((ret = xbus_sysfs_create(xbus)) < 0) { - XBUS_ERR(xbus, "%s: xbus_sysfs_create() failed: %d\n", __FUNCTION__, ret); - goto out; - } - /* - * Now request Astribank to start self_ticking. - * This is the last initialization command. So - * all others will reach the device before it. - */ - xbus_request_sync(xbus, SYNC_MODE_PLL); - elect_syncer("xbus_poll(end)"); /* FIXME: try to do it later */ -out: - poller->is_polling = 0; /* just for safety */ - XBUS_PUT(xbus); - wake_up(&poller->wait_for_xpd_initialization); - put_xbus(xbus); - return; -} - -void xbus_poller_notify(xbus_t *xbus, struct card_desc_struct *card_desc) -{ - struct xbus_poller *poller; - unsigned long flags; - - BUG_ON(!xbus); - poller = xbus->poller; - BUG_ON(!poller); - if(!poller->is_polling) { - XBUS_NOTICE(xbus, "%d%d replied not during poll. Ignore\n", - card_desc->xpd_addr.unit, - card_desc->xpd_addr.subunit); - kfree(card_desc); - return; - } - spin_lock_irqsave(&xbus->lock, flags); - if(card_desc->type == XPD_TYPE_NOMODULE) - XBUS_COUNTER(xbus, DEV_DESC_EMPTY)++; - else - XBUS_COUNTER(xbus, DEV_DESC_FULL)++; - atomic_inc(&poller->count_poll_answers); - list_add_tail(&card_desc->card_list, &poller->poll_results); - spin_unlock_irqrestore(&xbus->lock, flags); - /* - * Reference counting for the xbus. - * Would be returned in xbus_poll() - */ - xbus = get_xbus(xbus->num); - BUG_ON(!xbus); - /* - * wake_up only after exiting our critical section. - * We suspect that otherwise a spinlock nesting may occur - * and cause a panic (if spinlock debugging is compiled in). - */ - wake_up(&poller->wait_for_polls); - return; -} - -static void poller_destroy(struct xbus_poller *poller) -{ - xbus_t *xbus; - - if(!poller) - return; - xbus = get_xbus(poller->xbus_num); - if(xbus) { -#ifdef CONFIG_PROC_FS - if(xbus->proc_xbus_dir && poller->proc_xbus_waitfor_xpds) { - XBUS_DBG(PROC, xbus, "Removing proc '%s'\n", PROC_XBUS_WAITFOR_XPDS); - remove_proc_entry(PROC_XBUS_WAITFOR_XPDS, xbus->proc_xbus_dir); - poller->proc_xbus_waitfor_xpds = NULL; - } -#endif - XBUS_DBG(DEVICES, xbus, "detach poller\n"); - xbus->poller = NULL; - } - if (poller->wq) { - DBG(DEVICES, "XBUS #%d: destroy workqueue\n", poller->xbus_num); - flush_workqueue(poller->wq); - destroy_workqueue(poller->wq); - poller->wq = NULL; - } - put_xbus(xbus); - KZFREE(poller); -} - -/* - * Allocate a poller for the xbus including the nessessary workqueue. - * May call blocking operations, but only briefly (as we are called - * from xbus_new() which is called from khubd. - */ -static struct xbus_poller *poller_new(xbus_t *xbus) -{ - struct xbus_poller *poller; - - BUG_ON(xbus->busname[0] == '\0'); /* No name? */ - BUG_ON(xbus->poller); /* Hmmm... overrun pollers? */ - XBUS_DBG(DEVICES, xbus, "\n"); - poller = KZALLOC(sizeof(*poller), GFP_KERNEL); - if(!poller) - goto err; - poller->xbus_num = xbus->num; - xbus->poller = poller; - /* poll related variables */ - atomic_set(&poller->count_poll_answers, 0); - atomic_set(&poller->count_xpds_to_initialize, 0); - atomic_set(&poller->count_xpds_initialized, 0); - INIT_LIST_HEAD(&poller->poll_results); - init_waitqueue_head(&poller->wait_for_polls); - init_waitqueue_head(&poller->wait_for_xpd_initialization); - poller->wq = create_singlethread_workqueue(xbus->busname); - if(!poller->wq) { - XBUS_ERR(xbus, "Failed to create poller workqueue.\n"); - goto err; - } -#ifdef CONFIG_PROC_FS - if(xbus->proc_xbus_dir) { - poller->proc_xbus_waitfor_xpds = create_proc_read_entry( - PROC_XBUS_WAITFOR_XPDS, 0444, - xbus->proc_xbus_dir, - xbus_read_waitfor_xpds, - xbus); - if (!poller->proc_xbus_waitfor_xpds) { - XBUS_ERR(xbus, "Failed to create proc file '%s'\n", PROC_XBUS_WAITFOR_XPDS); - goto err; - } - poller->proc_xbus_waitfor_xpds->owner = THIS_MODULE; - } -#endif - return poller; -err: - poller_destroy(poller); - return NULL; -} - -/* - * Sends an xbus_poll() work to the poller workqueue of the given xbus. - */ -static int poller_dispatch(xbus_t *xbus) -{ - struct xbus_poller *poller = xbus->poller; - - if(!poller) { - XBUS_ERR(xbus, "missing poller\n"); - return 0; - } - /* Initialize the work. (adapt to kernel API changes). */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) - INIT_WORK(&poller->xpds_init_work, xbus_poll); -#else - INIT_WORK(&poller->xpds_init_work, xbus_poll, poller); -#endif - /* Now send it */ - if(!queue_work(poller->wq, &poller->xpds_init_work)) { - XBUS_ERR(xbus, "Failed to queue xpd initialization work\n"); - return 0; - } - return 1; -} - -int xbus_activate(xbus_t *xbus) -{ - struct xbus_ops *ops; - struct xbus_poller *poller; - - BUG_ON(!xbus); - ops = transportops_get(xbus); - BUG_ON(!ops); - poller = xbus->poller; - BUG_ON(!poller); - /* Sanity checks */ - BUG_ON(!ops->xframe_send_pcm); - BUG_ON(!ops->xframe_send_cmd); - BUG_ON(!ops->alloc_xframe); - BUG_ON(!ops->free_xframe); - xpp_timing_init(&xbus->timing, xbus->busname); - /* - * We start with timer based ticking - */ - xbus_set_command_timer(xbus, 1); - xbus->transport.transport_running = 1; /* must be done after transport is valid */ - XBUS_INFO(xbus, "[%s] Activating\n", xbus->label); - /* - * Make sure Astribank knows not to send us ticks. - */ - xbus_request_sync(xbus, SYNC_MODE_NONE); - /* Poll it */ - poller_dispatch(xbus); - return 0; -} - -void xbus_disconnect(xbus_t *xbus) -{ - int i; - - BUG_ON(!xbus); - XBUS_INFO(xbus, "[%s] Disconnecting\n", xbus->label); - xbus_set_command_timer(xbus, 1); - xbus_request_sync(xbus, SYNC_MODE_PLL); /* no more ticks */ - for(i = 0; i < MAX_XPDS; i++) { - xpd_t *xpd = xpd_of(xbus, i); - if(!xpd) - continue; - if(xpd->xbus_idx != i) { - XBUS_ERR(xbus, "BUG: xpd->xbus_idx=%d != i=%d\n", xpd->xbus_idx, i); - continue; - } - xpd_disconnect(xpd); - } - XBUS_DBG(DEVICES, xbus, "Deactivating\n"); - tasklet_kill(&xbus->receive_tasklet); - xframe_queue_clear(&xbus->receive_queue); - xbus_command_queue_clean(xbus); - xbus_command_queue_waitempty(xbus); - del_timer_sync(&xbus->command_timer); - xframe_queue_clear(&xbus->send_pool); - xframe_queue_clear(&xbus->receive_pool); - xframe_queue_clear(&xbus->pcm_tospan[0]); - xframe_queue_clear(&xbus->pcm_tospan[1]); - transportops_put(xbus); - transport_destroy(xbus); - elect_syncer("disconnect"); - XBUS_DBG(DEVICES, xbus, "Deactivated (refcount_xbus=%d)\n", refcount_xbus(xbus->num)); - if(atomic_dec_and_test(&xbus->xbus_ref_count)) { - XBUS_DBG(DEVICES, xbus, "Going to remove XBUS\n"); - xbus_remove(xbus); - } -} - -static xbus_t *xbus_alloc(void) -{ - unsigned long flags; - xbus_t *xbus; - int i; - - xbus = KZALLOC(sizeof(xbus_t), GFP_KERNEL); - if(!xbus) { - ERR("%s: out of memory\n", __FUNCTION__); - return NULL; - } - spin_lock_irqsave(&xbuses_lock, flags); - for(i = 0; i < MAX_BUSES; i++) - if(xbuses_array[i].xbus == NULL) - break; - if(i >= MAX_BUSES) { - ERR("%s: No free slot for new bus. i=%d\n", __FUNCTION__, i); - kfree(xbus); - return NULL; - } - /* Found empty slot */ - xbus->num = i; - init_xbus(i, xbus); - xbus = get_xbus(i); - bus_count++; - spin_unlock_irqrestore(&xbuses_lock, flags); - return xbus; -} - - -static void xbus_free(xbus_t *xbus) -{ - unsigned long flags; - uint num; - - if(!xbus) - return; - spin_lock_irqsave(&xbuses_lock, flags); - num = xbus->num; - BUG_ON(!xbuses_array[num].xbus); - BUG_ON(xbus != xbuses_array[num].xbus); - spin_unlock_irqrestore(&xbuses_lock, flags); -#ifdef XPP_DEBUGFS - if(xbus->debugfs_dir) { - if(xbus->debugfs_file) { - XBUS_DBG(GENERAL, xbus, "Removing debugfs file\n"); - debugfs_remove(xbus->debugfs_file); - } - XBUS_DBG(GENERAL, xbus, "Removing debugfs directory\n"); - debugfs_remove(xbus->debugfs_dir); - } -#endif - poller_destroy(xbus->poller); -#ifdef CONFIG_PROC_FS - if(xbus->proc_xbus_dir) { - if(xbus->proc_xbus_summary) { - XBUS_DBG(PROC, xbus, "Removing proc '%s'\n", PROC_XBUS_SUMMARY); - remove_proc_entry(PROC_XBUS_SUMMARY, xbus->proc_xbus_dir); - xbus->proc_xbus_summary = NULL; - } -#ifdef PROTOCOL_DEBUG - if(xbus->proc_xbus_command) { - XBUS_DBG(PROC, xbus, "Removing proc '%s'\n", PROC_XBUS_COMMAND); - remove_proc_entry(PROC_XBUS_COMMAND, xbus->proc_xbus_dir); - xbus->proc_xbus_command = NULL; - } -#endif - XBUS_DBG(PROC, xbus, "Removing proc directory\n"); - remove_proc_entry(xbus->busname, xpp_proc_toplevel); - xbus->proc_xbus_dir = NULL; - } -#endif - spin_lock_irqsave(&xbuses_lock, flags); - /* - * Return to xbus reference counts: - * - One from our caller: transport disconnect or xpp_close() - * - One from xbus_alloc() - */ - put_xbus(xbus); - put_xbus(xbus); - if(!wait_for_xbus_release(xbus->num)) - BUG(); /* Let's see what happens next... */ - bus_count--; - XBUS_DBG(DEVICES, xbus, "Going to free... refcount_xbus=%d\n", refcount_xbus(num)); - BUG_ON(refcount_xbus(num) != 0); - init_xbus(num, NULL); - spin_unlock_irqrestore(&xbuses_lock, flags); - KZFREE(xbus); -} - -xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, void *priv) -{ - int err; - xbus_t *xbus = NULL; - struct xbus_poller *poller; - - BUG_ON(!ops); - XBUS_DBG(GENERAL, xbus, "allocate new xbus\n"); - xbus = xbus_alloc(); - if(!xbus) - return NULL; - transport_init(xbus, ops, max_send_size, priv); - spin_lock_init(&xbus->lock); - atomic_set(&xbus->xbus_ref_count, 1); /* a single ref */ - snprintf(xbus->busname, XBUS_NAMELEN, "XBUS-%02d", xbus->num); - init_waitqueue_head(&xbus->command_queue_empty); - init_timer(&xbus->command_timer); - atomic_set(&xbus->pcm_rx_counter, 0); - xbus->min_tx_sync = INT_MAX; - xbus->min_rx_sync = INT_MAX; - - xbus->num_xpds = 0; - xbus->sync_mode = SYNC_MODE_NONE; - init_rwsem(&xbus->in_use); - xbus_reset_counters(xbus); -#ifdef CONFIG_PROC_FS - XBUS_DBG(PROC, xbus, "Creating xbus proc directory\n"); - xbus->proc_xbus_dir = proc_mkdir(xbus->busname, xpp_proc_toplevel); - if(!xbus->proc_xbus_dir) { - XBUS_ERR(xbus, "Failed to create proc directory\n"); - err = -EIO; - goto nobus; - } - xbus->proc_xbus_summary = create_proc_read_entry(PROC_XBUS_SUMMARY, 0444, xbus->proc_xbus_dir, - xbus_read_proc, (void *)(xbus->num)); - if (!xbus->proc_xbus_summary) { - XBUS_ERR(xbus, "Failed to create proc file '%s'\n", PROC_XBUS_SUMMARY); - err = -EIO; - goto nobus; - } - xbus->proc_xbus_summary->owner = THIS_MODULE; -#ifdef PROTOCOL_DEBUG - xbus->proc_xbus_command = create_proc_entry(PROC_XBUS_COMMAND, 0200, xbus->proc_xbus_dir); - if (!xbus->proc_xbus_command) { - XBUS_ERR(xbus, "Failed to create proc file '%s'\n", PROC_XBUS_COMMAND); - err = -EIO; - goto nobus; - } - xbus->proc_xbus_command->write_proc = proc_xbus_command_write; - xbus->proc_xbus_command->data = xbus; - xbus->proc_xbus_command->owner = THIS_MODULE; -#endif -#endif -#ifdef XPP_DEBUGFS - xbus->debugfs_dir = debugfs_create_dir(xbus->busname, debugfs_root); - if(!xbus->debugfs_dir) { - XBUS_ERR(xbus, "Failed to create debugfs directory\n"); - goto nobus; - } - xbus->debugfs_file = debugfs_create_file("dchannel", S_IFREG|S_IRUGO|S_IWUSR, xbus->debugfs_dir, xbus, &debugfs_operations); - if(!xbus->debugfs_file) { - XBUS_ERR(xbus, "Failed to create dchannel file\n"); - goto nobus; - } -#endif - xframe_queue_init(&xbus->command_queue, 10, 200, "command_queue", xbus); - xframe_queue_init(&xbus->receive_queue, 10, 50, "receive_queue", xbus); - xframe_queue_init(&xbus->send_pool, 10, 200, "send_pool", xbus); - xframe_queue_init(&xbus->receive_pool, 10, 50, "receive_pool", xbus); - xframe_queue_init(&xbus->pcm_tospan[0], 5, 10, "pcm_tospan[0]", xbus); - xframe_queue_init(&xbus->pcm_tospan[1], 5, 10, "pcm_tospan[1]", xbus); - tasklet_init(&xbus->receive_tasklet, receive_tasklet_func, (unsigned long)xbus); - /* - * Create poller after /proc/XBUS-?? so the directory exists - * before /proc/XBUS-??/waitfor_xpds tries to get created. - */ - poller = poller_new(xbus); - if(!poller) { - ERR("Failed to allocate poller\n"); - xbus_free(xbus); - return NULL; - } - return xbus; -nobus: - xbus_free(xbus); - return NULL; -} - -void xbus_remove(xbus_t *xbus) -{ - int i; - - BUG_ON(TRANSPORT_RUNNING(xbus)); - down_write(&xbus->in_use); - - XBUS_INFO(xbus, "[%s] Removing\n", xbus->label); - xbus_sysfs_remove(xbus); /* Device-Model */ - for(i = 0; i < MAX_XPDS; i++) { - xpd_t *xpd = xpd_of(xbus, i); - - if(xpd) { - if(xpd->xbus_idx != i) { - XBUS_ERR(xbus, "BUG: xpd->xbus_idx=%d != i=%d\n", xpd->xbus_idx, i); - continue; - } - XBUS_DBG(DEVICES, xbus, " Removing xpd #%d\n", i); - xpd_remove(xpd); - } - xbus->xpds[i] = NULL; - } - xbus_free(xbus); -} - -/*------------------------- Proc handling --------------------------*/ - -void xbus_reset_counters(xbus_t *xbus) -{ - int i; - - XBUS_DBG(GENERAL, xbus, "Reseting counters\n"); - for(i = 0; i < XBUS_COUNTER_MAX; i++) { - xbus->counters[i] = 0; - } -} - -#if CONFIG_PROC_FS - -static int xbus_fill_proc_queue(char *p, struct xframe_queue *q) -{ - int len; - - len = sprintf(p, - "%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02ld.%ld ms\n", - q->name, - q->steady_state_count, - q->count, - q->max_count, - q->worst_count, - q->overflows, - q->worst_lag_usec / 1000, - q->worst_lag_usec % 1000); - xframe_queue_clearstats(q); - return len; -} - -static int xbus_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - xbus_t *xbus; - struct xbus_poller *poller; - unsigned long flags; - int len = 0; - int i = (int)data; - struct timeval now; - - - xbus = get_xbus(i); - if(!xbus) - goto out; - spin_lock_irqsave(&xbus->lock, flags); - do_gettimeofday(&now); - poller = xbus->poller; - - len += sprintf(page + len, "%s: CONNECTOR=%s LABEL=[%s] STATUS=%s\n", - xbus->busname, - xbus->busdesc, - xbus->label, - (TRANSPORT_RUNNING(xbus)) ? "connected" : "missing" - ); - len += sprintf(page + len, "POLLS: %d/%d\n", - atomic_read(&poller->count_poll_answers), MAX_XPDS); - len += sprintf(page + len, "XPDS_READY: %d/%d\n", - atomic_read(&poller->count_xpds_initialized), - atomic_read(&poller->count_xpds_to_initialize)); - len += sprintf(page + len, "\nxbus_ref_count=%d\n", - atomic_read(&xbus->xbus_ref_count) - ); - len += xbus_fill_proc_queue(page + len, &xbus->send_pool); - len += xbus_fill_proc_queue(page + len, &xbus->receive_pool); - len += xbus_fill_proc_queue(page + len, &xbus->command_queue); - len += xbus_fill_proc_queue(page + len, &xbus->receive_queue); - len += xbus_fill_proc_queue(page + len, &xbus->pcm_tospan[0]); - len += xbus_fill_proc_queue(page + len, &xbus->pcm_tospan[1]); - if(rx_tasklet) { - len += sprintf(page + len, "\ncpu_rcv_intr: "); - for_each_online_cpu(i) - len += sprintf(page + len, "%5d ", xbus->cpu_rcv_intr[i]); - len += sprintf(page + len, "\ncpu_rcv_tasklet: "); - for_each_online_cpu(i) - len += sprintf(page + len, "%5d ", xbus->cpu_rcv_tasklet[i]); - len += sprintf(page + len, "\n"); - } - len += sprintf(page + len, "self_ticking: %d\n", xbus->self_ticking); - len += sprintf(page + len, "xbus: pcm_rx_counter = %d, frag = %d\n", - atomic_read(&xbus->pcm_rx_counter), xbus->xbus_frag_count); - len += sprintf(page + len, "max_rx_process = %2ld.%ld ms\n", - xbus->max_rx_process / 1000, - xbus->max_rx_process % 1000); - xbus->max_rx_process = 0; - len += sprintf(page + len, "\nTRANSPORT: max_send_size=%d refcount=%d\n", - MAX_SEND_SIZE(xbus), - atomic_read(&xbus->transport.transport_refcount) - ); - len += sprintf(page + len, "\nSYNC: [%d] %-14s: DRIFT=%d %3ld sec ago\n", - xbus->sync_mode, sync_mode_name(xbus->sync_mode), xbus->sync_adjustment, - (xbus->pll_updated_at == 0) ? 0 : now.tv_sec - xbus->pll_updated_at); - len += sprintf(page + len, - "tick timing: avg = %3d usec stddev = %4d usec (count=%ld)\n", - xbus->timing.tick_avg, xbus->timing.tick_stddev, xbus->timing.timing_count); - len += sprintf(page + len, - "sync_offset_usec=%ld\n", xbus->sync_offset_usec); - len += sprintf(page + len, "PCM Metrices:\n"); - len += sprintf(page + len, "\tPCM TX: min=%ld max=%ld\n", - xbus->min_tx_sync, xbus->max_tx_sync); - len += sprintf(page + len, "\tPCM RX: min=%ld max=%ld\n", - xbus->min_rx_sync, xbus->max_rx_sync); - len += sprintf(page + len, "COUNTERS:\n"); - for(i = 0; i < XBUS_COUNTER_MAX; i++) { - len += sprintf(page + len, "\t%-15s = %d\n", - xbus_counters[i].name, xbus->counters[i]); - } - len += sprintf(page + len, "<-- len=%d\n", len); - /* reset statistics */ - xbus->min_tx_sync = INT_MAX; - xbus->max_tx_sync = 0; - xbus->min_rx_sync = INT_MAX; - xbus->max_rx_sync = 0; - spin_unlock_irqrestore(&xbus->lock, flags); - put_xbus(xbus); -out: - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; - -} - -static int xbus_read_waitfor_xpds(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - unsigned long flags; - xbus_t *xbus = data; - struct xbus_poller *poller; - int ret; - - if(!xbus) - goto out; - /* first handle special cases */ - if(!count || off) - goto out; - /* - * poller is created before /proc/XBUS-?? - * So by now it exists and initialized. - */ - poller = xbus->poller; - BUG_ON(!poller); - XBUS_DBG(DEVICES, xbus, - "Waiting for card initialization of %d XPD's max %d seconds\n", - atomic_read(&poller->count_xpds_to_initialize), INITIALIZATION_TIMEOUT/HZ); - /* - * when polling is finished xbus_poll(): - * - Unset poller->is_polling - * - Sets poller->count_xpds_to_initialize. - * So we wait until polling is finished (is_polling == 0) and: - * - No poll answers from Astribank (e.g: defective firmware). - * - Or no units to initialize (e.g: mini-AB with only main card). - * - Or we finished initializing all existing units. - * - Or A timeout passed. - */ - ret = wait_event_interruptible_timeout(poller->wait_for_xpd_initialization, - !poller->is_polling && ( - atomic_read(&poller->count_poll_answers) == 0 || - atomic_read(&poller->count_xpds_to_initialize) == 0 || - atomic_read(&poller->count_xpds_initialized) >= - atomic_read(&poller->count_xpds_to_initialize)), - INITIALIZATION_TIMEOUT); - if(ret == 0) { - XBUS_ERR(xbus, "Card Initialization Timeout\n"); - return ret; - } else if(ret < 0) { - XBUS_ERR(xbus, "Card Initialization Interrupted %d\n", ret); - return ret; - } else - XBUS_DBG(DEVICES, xbus, - "Finished initialization of %d XPD's in %d seconds.\n", - atomic_read(&poller->count_xpds_initialized), - (INITIALIZATION_TIMEOUT - ret)/HZ); - spin_lock_irqsave(&xbus->lock, flags); - len += sprintf(page + len, "XPDS_READY: %s: %d/%d\n", - xbus->busname, - atomic_read(&poller->count_xpds_initialized), - atomic_read(&poller->count_xpds_to_initialize)); - spin_unlock_irqrestore(&xbus->lock, flags); -out: - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; - -} - -#ifdef PROTOCOL_DEBUG -static int proc_xbus_command_write(struct file *file, const char __user *buffer, unsigned long count, void *data) -{ - char *buf; - xbus_t *xbus = data; - char *p; - byte *pack_start; - byte *q; - xframe_t *xframe; - size_t len; - const size_t max_len = xbus->transport.max_send_size; - const size_t max_text = max_len * 3 + 10; - - if(count > max_text) { - XBUS_ERR(xbus, "%s: line too long (%ld > %d)\n", __FUNCTION__, count, max_len); - return -EFBIG; - } - /* 3 bytes per hex-digit and space */ - buf = kmalloc(max_text, GFP_KERNEL); - if(!buf) - return -ENOMEM; - if(copy_from_user(buf, buffer, count)) { - count = -EINVAL; - goto out; - } - buf[count] = '\0'; - XBUS_DBG(GENERAL, xbus, "count=%ld\n", count); - /* - * We replace the content of buf[] from - * ascii representation to packet content - * as the binary representation is shorter - */ - q = pack_start = buf; - for(p = buf; *p;) { - int val; - char hexdigit[3]; - - while(*p && isspace(*p)) // skip whitespace - p++; - if(!(*p)) - break; - if(!isxdigit(*p)) { - XBUS_ERR(xbus, "%s: bad hex value ASCII='0x%X' at position %ld\n", - __FUNCTION__, *p, (long)(p - buf)); - count = -EINVAL; - goto out; - } - hexdigit[0] = *p++; - hexdigit[1] = '\0'; - hexdigit[2] = '\0'; - if(isxdigit(*p)) - hexdigit[1] = *p++; - if(sscanf(hexdigit, "%2X", &val) != 1) { - XBUS_ERR(xbus, "%s: bad hex value '%s' at position %ld\n", - __FUNCTION__, hexdigit, (long)(p - buf)); - count = -EINVAL; - goto out; - } - *q++ = val; - XBUS_DBG(GENERAL, xbus, "%3d> '%s' val=%d\n", q - pack_start, hexdigit, val); - } - len = q - pack_start; - xframe = ALLOC_SEND_XFRAME(xbus); - if(!xframe) { - count = -ENOMEM; - goto out; - } - if(len > max_len) - len = max_len; - atomic_set(&xframe->frame_len, len); - memcpy(xframe->packets, pack_start, len); /* FIXME: checksum? */ - dump_xframe("COMMAND", xbus, xframe); - send_cmd_frame(xbus, xframe); -out: - kfree(buf); - return count; -} -#endif - - -static int read_proc_xbuses(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - unsigned long flags; - int i; - - spin_lock_irqsave(&xbuses_lock, flags); - for(i = 0; i < MAX_BUSES; i++) { - xbus_t *xbus = get_xbus(i); - - if(xbus) { - len += sprintf(page + len, "%s: CONNECTOR=%s LABEL=[%s] STATUS=%s REFCOUNT=%d\n", - xbus->busname, - xbus->busdesc, - xbus->label, - (TRANSPORT_RUNNING(xbus)) ? "connected" : "missing", - refcount_xbus(i) - 1 - ); - put_xbus(xbus); - } - } -#if 0 - len += sprintf(page + len, "<-- len=%d\n", len); -#endif - spin_unlock_irqrestore(&xbuses_lock, flags); - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; - -} -#endif - -static void transport_init(xbus_t *xbus, struct xbus_ops *ops, ushort max_send_size, void *priv) -{ - BUG_ON(!xbus); - BUG_ON(!ops); - BUG_ON(!ops->xframe_send_pcm); - BUG_ON(!ops->xframe_send_cmd); - BUG_ON(!ops->alloc_xframe); - BUG_ON(!ops->free_xframe); - xbus->transport.ops = ops; - xbus->transport.max_send_size = max_send_size; - xbus->transport.priv = priv; - spin_lock_init(&xbus->transport.lock); - atomic_set(&xbus->transport.transport_refcount, 0); - init_waitqueue_head(&xbus->transport.transport_unused); -} - -void transport_destroy(xbus_t *xbus) -{ - int ret; - - BUG_ON(!xbus); - xbus->transport.transport_running = 0; - XBUS_INFO(xbus, "Waiting... (transport_refcount=%d)\n", - atomic_read(&xbus->transport.transport_refcount)); - ret = wait_event_interruptible(xbus->transport.transport_unused, - atomic_read(&xbus->transport.transport_refcount) == 0); - if(ret) - XBUS_ERR(xbus, "Waiting for transport_refcount interrupted!!!\n"); - xbus->transport.ops = NULL; - xbus->transport.priv = NULL; -} - -struct xbus_ops *transportops_get(xbus_t *xbus) -{ - struct xbus_ops *ops; - - BUG_ON(!xbus); - atomic_inc(&xbus->transport.transport_refcount); - ops = xbus->transport.ops; - if(!ops) - atomic_dec(&xbus->transport.transport_refcount); - /* fall through */ - return ops; -} - -void transportops_put(xbus_t *xbus) -{ - struct xbus_ops *ops; - - BUG_ON(!xbus); - ops = xbus->transport.ops; - BUG_ON(!ops); - if(atomic_dec_and_test(&xbus->transport.transport_refcount)) - wake_up(&xbus->transport.transport_unused); -} - -/*------------------------- Initialization -------------------------*/ -static void xbus_core_cleanup(void) -{ - finalize_xbuses_array(); -#ifdef XPP_DEBUGFS - if(debugfs_root) { - DBG(GENERAL, "Removing xpp from debugfs\n"); - debugfs_remove(debugfs_root); - } -#endif -#ifdef CONFIG_PROC_FS - if(proc_xbuses) { - DBG(PROC, "Removing " PROC_XBUSES " from proc\n"); - remove_proc_entry(PROC_XBUSES, xpp_proc_toplevel); - proc_xbuses = NULL; - } -#endif -} - -int __init xbus_core_init(void) -{ - int ret = 0; - - initialize_xbuses_array(); -#ifdef PROTOCOL_DEBUG - INFO("FEATURE: with PROTOCOL_DEBUG\n"); -#endif -#ifdef XPP_DEBUGFS - INFO("FEATURE: with XPP_DEBUGFS support\n"); -#endif -#ifdef CONFIG_PROC_FS - proc_xbuses = create_proc_read_entry(PROC_XBUSES, 0444, xpp_proc_toplevel, read_proc_xbuses, NULL); - if (!proc_xbuses) { - ERR("Failed to create proc file %s\n", PROC_XBUSES); - ret = -EFAULT; - goto err; - } - proc_xbuses->owner = THIS_MODULE; -#endif -#ifdef XPP_DEBUGFS - DBG(GENERAL, "Creating debugfs xpp root\n"); - debugfs_root = debugfs_create_dir("xpp", NULL); - if(!debugfs_root) { - ERR("Failed to create debugfs root\n"); - ret = -EFAULT; - goto err; - } -#endif - if((ret = register_xpp_bus()) < 0) - goto err; - return 0; -err: - xbus_core_cleanup(); - return ret; -} - - -void __exit xbus_core_shutdown(void) -{ - int i; - - for(i = 0; i < MAX_BUSES; i++) { - xbus_t *xbus = get_xbus(i); - - if(xbus) { - xbus_remove(xbus); - } - } - BUG_ON(bus_count); - unregister_xpp_bus(); - xbus_core_cleanup(); -} - -EXPORT_SYMBOL(xpd_of); -EXPORT_SYMBOL(xpd_byaddr); -EXPORT_SYMBOL(get_xbus); -EXPORT_SYMBOL(put_xbus); -EXPORT_SYMBOL(xbus_new); -EXPORT_SYMBOL(xbus_remove); -EXPORT_SYMBOL(xbus_activate); -EXPORT_SYMBOL(xbus_disconnect); -EXPORT_SYMBOL(xbus_receive_xframe); -EXPORT_SYMBOL(xbus_reset_counters); -EXPORT_SYMBOL(xframe_next_packet); -EXPORT_SYMBOL(dump_xframe); -EXPORT_SYMBOL(send_pcm_frame); -EXPORT_SYMBOL(send_cmd_frame); -EXPORT_SYMBOL(xframe_init); -EXPORT_SYMBOL(transportops_get); -EXPORT_SYMBOL(transportops_put); -EXPORT_SYMBOL(xbus_poller_notify); -EXPORT_SYMBOL(xbus_command_queue_tick); -#ifdef XPP_DEBUGFS -EXPORT_SYMBOL(xbus_log); -#endif diff --git a/xpp/xbus-core.h b/xpp/xbus-core.h deleted file mode 100644 index de6e859..0000000 --- a/xpp/xbus-core.h +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#ifndef XBUS_CORE_H -#define XBUS_CORE_H - -#include -#include /* for tasklets */ -#include "xpd.h" -#include "xframe_queue.h" -#include "xbus-pcm.h" - -#define MAX_BUSES 32 -#define XFRAME_DATASIZE 512 - -/* forward declarations */ -struct xbus_poller; -#ifdef XPP_DEBUGFS -struct debugfs_data; -#endif - -#ifdef __KERNEL__ - -struct xbus_ops { - int (*xframe_send_pcm)(xbus_t *xbus, xframe_t *xframe); - int (*xframe_send_cmd)(xbus_t *xbus, xframe_t *xframe); - xframe_t *(*alloc_xframe)(xbus_t *xbus, gfp_t gfp_flags); - void (*free_xframe)(xbus_t *xbus, xframe_t *xframe); -}; - -/* - * XBUS statistics counters - */ -enum { - XBUS_N_DESC_REQ, - XBUS_N_DEV_DESC_FULL, - XBUS_N_DEV_DESC_EMPTY, - XBUS_N_TX_XFRAME_PCM, - XBUS_N_RX_XFRAME_PCM, - XBUS_N_TX_PACK_PCM, - XBUS_N_RX_PACK_PCM, - XBUS_N_TX_BYTES, - XBUS_N_RX_BYTES, - XBUS_N_TX_PCM_FRAG, - XBUS_N_TX_CMD, -}; - -#define XBUS_COUNTER(xbus, counter) ((xbus)->counters[XBUS_N_ ## counter]) - -#define C_(x) [ XBUS_N_ ## x ] = { #x } - -/* yucky, make an instance so we can size it... */ -static struct xbus_counters { - char *name; -} xbus_counters[] = { - C_(DESC_REQ), - C_(DEV_DESC_FULL), - C_(DEV_DESC_EMPTY), - C_(TX_XFRAME_PCM), - C_(RX_XFRAME_PCM), - C_(TX_PACK_PCM), - C_(RX_PACK_PCM), - C_(TX_BYTES), - C_(RX_BYTES), - C_(TX_PCM_FRAG), - C_(TX_CMD), -}; - -#undef C_ - -#define XBUS_COUNTER_MAX ARRAY_SIZE(xbus_counters) - -struct xbus_transport { - struct xbus_ops *ops; - void *priv; - ushort max_send_size; - bool transport_running; /* Hardware is functional */ - atomic_t transport_refcount; - wait_queue_head_t transport_unused; - spinlock_t lock; -}; - -#define MAX_SEND_SIZE(xbus) ((xbus)->transport.max_send_size) -#define TRANSPORT_RUNNING(xbus) ((xbus)->transport.transport_running) -#define TRANSPORT_EXIST(xbus) ((xbus)->transport.ops != NULL) - -struct xbus_ops *transportops_get(xbus_t *xbus); -void transportops_put(xbus_t *xbus); - -/* - * Allocate/Free an xframe from pools of empty xframes. - * Calls to {get,put}_xframe are wrapped in - * the macros bellow, so we take/return it - * to the correct pool. - */ -xframe_t *get_xframe(struct xframe_queue *q); -void put_xframe(struct xframe_queue *q, xframe_t *xframe); - -#define ALLOC_SEND_XFRAME(xbus) get_xframe(&(xbus)->send_pool) -#define ALLOC_RECV_XFRAME(xbus) get_xframe(&(xbus)->receive_pool) -#define FREE_SEND_XFRAME(xbus, xframe) put_xframe(&(xbus)->send_pool, (xframe)) -#define FREE_RECV_XFRAME(xbus, xframe) put_xframe(&(xbus)->receive_pool, (xframe)) - -xbus_t *get_xbus(uint num); -void put_xbus(xbus_t *xbus); - -/* - * An xbus is a transport layer for Xorcom Protocol commands - */ -struct xbus { - char busname[XBUS_NAMELEN]; /* set by xbus_new() */ - - /* low-level bus drivers set these 2 fields */ - char busdesc[XBUS_DESCLEN]; - char label[LABEL_SIZE]; - struct xbus_transport transport; - - int num; - struct xpd *xpds[MAX_XPDS]; - - struct xframe_queue command_queue; - wait_queue_head_t command_queue_empty; - - struct xframe_queue send_pool; /* empty xframes for send */ - struct xframe_queue receive_pool; /* empty xframes for receive */ - - /* tasklet processing */ - struct xframe_queue receive_queue; - struct tasklet_struct receive_tasklet; - int cpu_rcv_intr[NR_CPUS]; - int cpu_rcv_tasklet[NR_CPUS]; - - bool self_ticking; - enum sync_mode sync_mode; - struct timer_list command_timer; - unsigned int xbus_frag_count; - struct xframe_queue pcm_tospan[2]; /* double buffer */ - struct xpp_timing timing; - atomic_t pcm_rx_counter; - unsigned int global_counter; - long sync_offset_usec; - - /* Device-Model */ - struct device astribank; -#define dev_to_xbus(dev) container_of(dev, struct xbus, astribank) - - spinlock_t lock; - atomic_t xbus_ref_count; /* How many need this struct? */ - - /* PCM metrics */ - struct timeval last_tx_sync; - struct timeval last_rx_sync; - unsigned long max_tx_sync; - unsigned long min_tx_sync; - unsigned long max_rx_sync; - unsigned long min_rx_sync; - unsigned long max_rx_process; /* packet processing time (usec) */ - - struct xbus_poller *poller; - - /* - * Sync adjustment - */ - int sync_adjustment; - int sync_adjustment_offset; - long pll_updated_at; - - struct rw_semaphore in_use; -#define XBUS_GET(xbus) down_read_trylock(&(xbus)->in_use) -#define XBUS_PUT(xbus) up_read(&(xbus)->in_use) - - int num_xpds; - -#ifdef XPP_DEBUGFS - struct dentry *debugfs_dir; - struct dentry *debugfs_file; - struct debugfs_data *debugfs_data; -#endif -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *proc_xbus_dir; - struct proc_dir_entry *proc_xbus_summary; -#ifdef PROTOCOL_DEBUG - struct proc_dir_entry *proc_xbus_command; -#endif -#endif - - /* statistics */ - int counters[XBUS_COUNTER_MAX]; -}; -#endif - -#define XFRAME_MAGIC 123456L - -struct xframe { - unsigned long xframe_magic; - struct list_head frame_list; - atomic_t frame_len; - xbus_t *xbus; - struct timeval tv_created; - struct timeval tv_queued; - struct timeval tv_submitted; - struct timeval tv_received; - /* filled by transport layer */ - size_t frame_maxlen; - byte *packets; /* max XFRAME_DATASIZE */ - byte *first_free; - void *priv; -}; - -void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize, void *priv); - -#define XFRAME_LEN(frame) atomic_read(&(frame)->frame_len) - -int xbus_core_init(void); /* Initializer */ -void xbus_core_shutdown(void); /* Terminator */ - -#ifdef XPP_DEBUGFS -/* Debugfs handling */ -int xbus_log(xbus_t *xbus, xpd_t *xpd, int direction, const void *buf, unsigned long len); -#endif - -/* Frame handling */ -void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe); -int send_cmd_frame(xbus_t *xbus, xframe_t *xframe); - -/* - * Return pointer to next packet slot in the frame - * or NULL if the frame is full. - */ -xpacket_t *xframe_next_packet(xframe_t *xframe, int len); - -/* XBUS handling */ - -/* - * Map: unit+subunit <--> index in xbus->xpds[] - */ -#define XPD_IDX(unit,subunit) ((unit) * MAX_SUBUNIT + (subunit)) -#define XBUS_UNIT(idx) ((idx) / MAX_SUBUNIT) -#define XBUS_SUBUNIT(idx) ((idx) % MAX_SUBUNIT) - -xpd_t *xpd_of(const xbus_t *xbus, int xpd_num); -xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit); -xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, void *priv); -void xbus_remove(xbus_t *xbus); -int xbus_activate(xbus_t *xbus); -void xbus_disconnect(xbus_t *xbus); -void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe); - -void xbus_poller_notify(xbus_t *xbus, struct card_desc_struct *card_desc); -int xbus_register_xpd(xbus_t *xbus, xpd_t *xpd); -int xbus_unregister_xpd(xbus_t *xbus, xpd_t *xpd); - -/* sysfs */ -int register_xpp_bus(void); -void unregister_xpp_bus(void); -int xbus_sysfs_create(xbus_t *xbus); -void xbus_sysfs_remove(xbus_t *xbus); - -#endif /* XBUS_CORE_H */ - diff --git a/xpp/xbus-pcm.c b/xpp/xbus-pcm.c deleted file mode 100644 index 0b1e5d1..0000000 --- a/xpp/xbus-pcm.c +++ /dev/null @@ -1,1168 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2004-2007, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -# warning "This module is tested only with 2.6 kernels" -#endif - -#include -#include -#include "xbus-pcm.h" -#include "xbus-core.h" -#include "xpp_zap.h" -#include "zap_debug.h" -#include "parport_debug.h" - -static const char rcsid[] = "$Id$"; - -extern int print_dbg; -#ifdef XPP_EC_CHUNK -#include "supress/ec_xpp.h" -DEF_PARM_BOOL(xpp_ec, 0, 0444, "Do we use our own (1) or Zaptel's (0) echo canceller"); -#endif -#ifdef OPTIMIZE_CHANMUTE -DEF_PARM_BOOL(optimize_chanmute, 1, 0644, "Optimize by muting inactive channels"); -#endif - -DEF_PARM(int, disable_pcm, 0, 0644, "Disable all PCM transmissions"); -#ifdef DEBUG_PCMTX -DEF_PARM(int, pcmtx, -1, 0644, "Forced PCM value to transmit (negative to disable)"); -DEF_PARM(int, pcmtx_chan, 0, 0644, "channel to force PCM value"); -#endif -DEF_PARM_BOOL(pcm_tasklet, 0, 0644, "Handle PCM in a tasklet (lower interrupt load)"); -#define PCM_TASKLET_DEPRECATION "\n" \ - "====================================================================\n" \ - "CONFIGURATION ERROR: 'pcm_tasklet' module parameter is deprecated!!!\n" \ - "====================================================================\n" - -static xbus_t *syncer; /* current syncer */ -static struct xpp_timing ref_sync; -static atomic_t xpp_tick_counter; -static const struct xpp_timing *global_ticker; /* increment xpp_tick_counter */ -static bool zaptel_syncer = 0; - -#define PROC_SYNC "sync" -#define BIG_TICK_INTERVAL 1000 -#define SYNC_ADJ_MIN (-30) /* minimal firmware drift unit */ -#define SYNC_ADJ_MAX 30 /* maximal firmware drift unit */ -#define SYNC_ADJ_FACTOR(x) ((x) / 30) /* average usec/drift_unit */ - -#ifdef ZAPTEL_SYNC_TICK -static unsigned int zaptel_tick_count = 0; -#endif - -/*------------------------- SYNC Handling --------------------------*/ - - -const char *sync_mode_name(enum sync_mode mode) -{ - static const char *sync_mode_names[] = { - [SYNC_MODE_AB] "SYNC_MODE_AB", - [SYNC_MODE_NONE] "SYNC_MODE_NONE", - [SYNC_MODE_PLL] "SYNC_MODE_PLL", - [SYNC_MODE_QUERY] "SYNC_MODE_QUERY", - }; - if(mode >= ARRAY_SIZE(sync_mode_names)) - return NULL; - return sync_mode_names[mode]; -} - -static void xpp_set_syncer(xbus_t *xbus, bool on) -{ - if(syncer != xbus && on) { - XBUS_DBG(SYNC, xbus, "New syncer\n"); - syncer = xbus; - } else if(syncer == xbus && !on) { - XBUS_DBG(SYNC, xbus, "Lost syncer\n"); - syncer = NULL; - } else - XBUS_DBG(SYNC, xbus, "ignore %s (current syncer: %s)\n", - (on)?"ON":"OFF", - (syncer) ? syncer->busname : "NO-SYNC"); -} - -void xpp_timing_init(struct xpp_timing *timing, const char *name) -{ - memset(timing, 0, sizeof(*timing)); - do_gettimeofday(&timing->timing_val); - spin_lock_init(&timing->lock); - timing->name = name; -} - -#define XPP_TIMING_SAMPLES 50 -#define XPP_TIMING_TICKS 100 -#define XPP_TIMING_MAX_STDDEV 500 - -static void xpp_timing_tick(struct xpp_timing *timing, const struct timeval *val) -{ - long usec; - int diff_sec; - int diff_usec; - unsigned long flags; - - spin_lock_irqsave(&timing->lock, flags); - if((timing->timing_count % XPP_TIMING_TICKS) != 0) - goto out; - diff_sec = val->tv_sec - timing->timing_val.tv_sec; - diff_usec = val->tv_usec - timing->timing_val.tv_usec; - timing->timing_val = *val; - /* ignore first batch of samples */ - if(timing->timing_count < (XPP_TIMING_TICKS * XPP_TIMING_SAMPLES)) - goto out; - if(abs(diff_sec) > 2) { - static int rate_limit; - - if((rate_limit++ % 1003) == 0) - NOTICE("TIMING(%s): bad timing: diff_sec=%d\n", - timing->name, diff_sec); - goto out; - } - usec = diff_sec * 1000000 + diff_usec; - if(usec) - timing->tick_rate = XPP_TIMING_TICKS * 1000000 / usec; - usec -= 1000 * XPP_TIMING_TICKS; /* normalize */ - - timing->accumulated_usec += usec; - timing->accumulated_usec_sqr += usec * usec; - if((timing->timing_count % (XPP_TIMING_TICKS * XPP_TIMING_SAMPLES)) == 0) { - int avg; - int stddev; - - avg = timing->accumulated_usec / XPP_TIMING_SAMPLES; - stddev = (timing->accumulated_usec_sqr / XPP_TIMING_SAMPLES); - stddev = int_sqrt(stddev); - timing->accumulated_usec = 0; - timing->accumulated_usec_sqr = 0; - if(stddev > XPP_TIMING_MAX_STDDEV) { - static int rate_limit; - - if((rate_limit++ % 1003) == 0) - NOTICE("TIMING(%s): bad timing: stddev=%d avg=%d\n", - timing->name, stddev, avg); - goto out; - } - timing->tick_avg = avg; - timing->tick_stddev = stddev; - } -out: - timing->timing_count++; - if(timing == global_ticker) - atomic_inc(&xpp_tick_counter); - spin_unlock_irqrestore(&timing->lock, flags); -} - -void xbus_command_timer(unsigned long param) -{ - xbus_t *xbus = (xbus_t *)param; - struct timeval now; - - BUG_ON(!xbus); - do_gettimeofday(&now); - xbus_command_queue_tick(xbus); - if(!xbus->self_ticking) - mod_timer(&xbus->command_timer, jiffies + 1); /* Must be 1KHz rate */ -} - -void xbus_set_command_timer(xbus_t *xbus, bool on) -{ - XBUS_DBG(SYNC, xbus, "%s\n", (on)?"ON":"OFF"); - if(on) { - if(!timer_pending(&xbus->command_timer)) { - XBUS_DBG(SYNC, xbus, "add_timer\n"); - xbus->command_timer.function = xbus_command_timer; - xbus->command_timer.data = (unsigned long)xbus; - xbus->command_timer.expires = jiffies + 1; - add_timer(&xbus->command_timer); - xbus->self_ticking = 0; - } - } else if(timer_pending(&xbus->command_timer)) { - xbus->self_ticking = 1; - XBUS_DBG(SYNC, xbus, "del_timer\n"); - del_timer(&xbus->command_timer); - } -} - -/* - * Called when the Astribank replies to a sync change request - */ -void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift) -{ - unsigned long flags; - - XBUS_DBG(SYNC, xbus, "%s (%d), drift=%d (pcm_rx_counter=%d)\n", - sync_mode_name(mode), mode, drift, atomic_read(&xbus->pcm_rx_counter)); - spin_lock_irqsave(&xbus->lock, flags); - xbus->sync_adjustment = (signed char)drift; - if(xbus->sync_mode == mode) { - XBUS_DBG(SYNC, xbus, "Already in %s. Ignored\n", sync_mode_name(mode)); - goto out; - } - switch(mode) { - case SYNC_MODE_AB: - xbus->sync_mode = mode; - xbus_set_command_timer(xbus, 0); - xpp_set_syncer(xbus, 1); - break; - case SYNC_MODE_PLL: - xbus->sync_mode = mode; - xbus_set_command_timer(xbus, 0); - xpp_set_syncer(xbus, 0); - break; - case SYNC_MODE_NONE: /* lost sync source */ - xbus->sync_mode = mode; - xbus_set_command_timer(xbus, 1); - xpp_set_syncer(xbus, 0); - break; - case SYNC_MODE_QUERY: /* ignore */ - break; - default: - XBUS_ERR(xbus, "%s: unknown mode=0x%X\n", __FUNCTION__, mode); - } -out: - spin_unlock_irqrestore(&xbus->lock, flags); -} - -void xbus_request_sync(xbus_t *xbus, enum sync_mode mode) -{ - BUG_ON(!xbus); - XBUS_DBG(SYNC, xbus, "sent request (mode=%d)\n", mode); - CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, mode, 0); -} - -static void reset_sync_counters(void) -{ - int i; - - //DBG(SYNC, "%d\n", atomic_read(&xpp_tick_counter)); - for(i = 0; i < MAX_BUSES; i++) { - xbus_t *xbus = get_xbus(i); - - if(!xbus) - continue; - if (TRANSPORT_RUNNING(xbus)) { - if(XBUS_GET(xbus)) { - /* Reset sync LEDs once in a while */ - CALL_PROTO(GLOBAL, RESET_SYNC_COUNTERS, xbus, NULL); - XBUS_PUT(xbus); - } else { - static int rate_limit; - - if((rate_limit++ % 1003) == 0) - XBUS_DBG(GENERAL, xbus, - "Dropped packet. Is shutting down. (%d)\n", rate_limit); - } - } - put_xbus(xbus); - } -} - -static void send_drift(xbus_t *xbus, int drift) -{ - struct timeval now; - const char *msg; - - BUG_ON(drift < SYNC_ADJ_MIN || drift > SYNC_ADJ_MAX); - do_gettimeofday(&now); - if(drift > xbus->sync_adjustment) - msg = "up"; - else - msg = "down"; - XBUS_DBG(SYNC, xbus, "DRIFT adjust %s (%d) (last update %ld seconds ago)\n", - msg, drift, now.tv_sec - xbus->pll_updated_at); - CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_PLL, drift); - xbus->pll_updated_at = now.tv_sec; -} - -#ifdef ZAPTEL_SYNC_TICK -int zaptel_sync_tick(struct zt_span *span, int is_master) -{ - xpd_t *xpd = span->pvt; - struct timeval now; - static int redundant_ticks; /* for extra spans */ - - if(!zaptel_syncer) - goto noop; - BUG_ON(!xpd); - /* - * Detect if any of our spans is zaptel sync master - */ - if(is_master) { - static int rate_limit; - - if(xpd->xbus != syncer && ((rate_limit % 1003) == 0)) { - XPD_ERR(xpd, - "Zaptel master, but syncer=%s\n", - xpd->xbus->busname); - } - if((rate_limit % 5003) == 0) - XPD_NOTICE(xpd, "Zaptel master: ignore ZAPTEL sync\n"); - rate_limit++; - goto noop; - } - /* Now we know for sure someone else is zaptel sync master */ - if(syncer) { - static int rate_limit; - - if((rate_limit++ % 5003) == 0) - XBUS_DBG(SYNC, syncer, - "Already a syncer, ignore ZAPTEL sync\n"); - goto noop; - } - /* ignore duplicate calls from all our registered spans */ - if((redundant_ticks++ % total_registered_spans()) != 0) { -#if 0 - static int rate_limit; - - if((rate_limit++ % 1003) < 16) - XPD_NOTICE(xpd, "boop (%d)\n", zaptel_tick_count); -#endif - goto noop; - } - do_gettimeofday(&now); - xpp_timing_tick(&ref_sync, &now); - zaptel_tick_count++; - flip_parport_bit(1); - return 0; -noop: - return 0; /* No auto sync from zaptel */ -} -#endif - - -static void sync_rate_adjust(xbus_t *xbus) -{ - int offset; - - xbus->sync_offset_usec = xbus->timing.tick_avg - ref_sync.tick_avg; - /* Calculate required PLL fix */ - offset = SYNC_ADJ_FACTOR(xbus->sync_offset_usec); - if(offset < SYNC_ADJ_MIN) - offset = SYNC_ADJ_MIN; - if(offset > SYNC_ADJ_MAX) - offset = SYNC_ADJ_MAX; - xbus->sync_adjustment_offset = offset; - if(xbus != syncer && xbus->sync_adjustment != offset) - send_drift(xbus, offset); -} - -/* - * called from elect_syncer() - * if new_syncer is NULL, than we move all to SYNC_MODE_PLL - * for ZAPTEL sync. - */ -static void update_sync_master(xbus_t *new_syncer) -{ - const char *msg = (zaptel_syncer) ? "ZAPTEL" : "NO-SYNC"; - int i; - - DBG(SYNC, "%s => %s\n", - (syncer) ? syncer->busname : msg, - (new_syncer) ? new_syncer->busname : msg); - if(new_syncer) { - XBUS_DBG(SYNC, new_syncer, "pcm_rx_counter=%d\n", - atomic_read(&new_syncer->pcm_rx_counter)); - zaptel_syncer = 0; - global_ticker = &new_syncer->timing; - xbus_request_sync(new_syncer, SYNC_MODE_AB); - } else - global_ticker = &ref_sync; - DBG(SYNC, "stop unwanted syncers\n"); - /* Shut all down except the wanted sync master */ - for(i = 0; i < MAX_BUSES; i++) { - xbus_t *xbus = get_xbus(i); - if(!xbus) - continue; - if(TRANSPORT_RUNNING(xbus) && xbus != new_syncer) { - if(xbus->self_ticking) - xbus_request_sync(xbus, SYNC_MODE_PLL); - else - XBUS_DBG(SYNC, xbus, "Not self_ticking yet. Ignore\n"); - } - put_xbus(xbus); - } -} - -void elect_syncer(const char *msg) -{ - int i; - int j; - uint timing_priority = 0; - xpd_t *best_xpd = NULL; - xbus_t *the_xbus = NULL; - - for(i = 0; i < MAX_BUSES; i++) { - xbus_t *xbus = get_xbus(i); - if(!xbus) - continue; - if(!the_xbus) - the_xbus = xbus; - if (TRANSPORT_RUNNING(xbus)) { - for(j = 0; j < MAX_XPDS; j++) { - xpd_t *xpd = xpd_of(xbus, j); - - if(!xpd) - continue; - if(xpd->timing_priority > timing_priority) { - timing_priority = xpd->timing_priority; - best_xpd = xpd; - } - } - } - put_xbus(xbus); - } - if(best_xpd) { - the_xbus = best_xpd->xbus; - XPD_DBG(SYNC, best_xpd, "%s: elected with priority %d\n", msg, timing_priority); - } else if(the_xbus) { - XBUS_DBG(SYNC, the_xbus, "%s: elected\n", msg); - } else - DBG(SYNC, "%s: No more syncers\n", msg); - if(the_xbus != syncer) - update_sync_master(the_xbus); -} - -/* - * This function is used by FXS/FXO. The pcm_mask argument signifies - * channels which should be *added* to the automatic calculation. - * Normally, this argument is 0. - * - * The caller should spinlock the XPD before calling it. - */ -void __pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask) -{ - int i; - int line_count = 0; - - /* Add/remove all the trivial cases */ - pcm_mask |= xpd->offhook; - pcm_mask |= xpd->cid_on; - pcm_mask &= ~xpd->digital_signalling; /* No PCM in D-Channels */ - pcm_mask &= ~xpd->digital_inputs; - pcm_mask &= ~xpd->digital_outputs; - for_each_line(xpd, i) - if(IS_SET(pcm_mask, i)) - line_count++; - /* - * FIXME: Workaround a bug in sync code of the Astribank. - * Send dummy PCM for sync. - */ - if(xpd->addr.unit == 0 && pcm_mask == 0) { - pcm_mask = BIT(0); - line_count = 1; - } - xpd->pcm_len = (line_count) - ? RPACKET_HEADERSIZE + sizeof(xpp_line_t) + line_count * ZT_CHUNKSIZE - : 0L; - xpd->wanted_pcm_mask = pcm_mask; -} - -/* - * A spinlocked version of __pcm_recompute() - */ -void pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask) -{ - unsigned long flags; - - spin_lock_irqsave(&xpd->lock, flags); - __pcm_recompute(xpd, pcm_mask); - spin_unlock_irqrestore(&xpd->lock, flags); -} - -void fill_beep(u_char *buf, int num, int duration) -{ - bool alternate = (duration) ? (jiffies/(duration*1000)) & 0x1 : 0; - int which; - u_char *snd; - - /* - * debug tones - */ - static u_char beep[] = { - 0x7F, 0xBE, 0xD8, 0xBE, 0x80, 0x41, 0x24, 0x41, /* Dima */ - 0x67, 0x90, 0x89, 0x90, 0xFF, 0x10, 0x09, 0x10, /* Izzy */ - }; - static u_char beep_alt[] = { - 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, /* silence */ - }; - if(alternate) { - which = num % ARRAY_SIZE(beep_alt); - snd = &beep_alt[which]; - } else { - which = num % ARRAY_SIZE(beep); - snd = &beep[which]; - } - memcpy(buf, snd, ZT_CHUNKSIZE); -} - -#ifdef XPP_EC_CHUNK -/* - * Taken from zaptel.c - */ -static inline void xpp_ec_chunk(struct zt_chan *chan, unsigned char *rxchunk, const unsigned char *txchunk) -{ - int16_t rxlin; - int x; - unsigned long flags; - - /* Perform echo cancellation on a chunk if necessary */ - if (!chan->ec) - return; - spin_lock_irqsave(&chan->lock, flags); - for (x=0;xec, ZT_XLAW(txchunk[x], chan), rxlin); - rxchunk[x] = ZT_LIN2X((int)rxlin, chan); - } - spin_unlock_irqrestore(&chan->lock, flags); -} -#endif - -static void do_ec(xpd_t *xpd) -{ - struct zt_chan *chans = xpd->span.chans; - int i; - -#ifdef WITH_ECHO_SUPPRESSION - /* FIXME: need to Echo cancel double buffered data */ - for (i = 0;i < xpd->span.channels; i++) { - if(unlikely(IS_SET(xpd->digital_signalling, i))) /* Don't echo cancel BRI D-chans */ - continue; -#ifdef XPP_EC_CHUNK - /* even if defined, parameterr xpp_ec can override at run-time */ - if (xpp_ec) - xpp_ec_chunk(&chans[i], chans[i].readchunk, xpd->ec_chunk2[i]); - else -#endif - zt_ec_chunk(&chans[i], chans[i].readchunk, xpd->ec_chunk2[i]); - memcpy(xpd->ec_chunk2[i], xpd->ec_chunk1[i], ZT_CHUNKSIZE); - memcpy(xpd->ec_chunk1[i], chans[i].writechunk, ZT_CHUNKSIZE); - } -#endif -} - -#if 0 -/* Okay, now we get to the signalling. You have several options: */ - -/* Option 1: If you're a T1 like interface, you can just provide a - rbsbits function and we'll assert robbed bits for you. Be sure to - set the ZT_FLAG_RBS in this case. */ - -/* Opt: If the span uses A/B bits, set them here */ -int (*rbsbits)(struct zt_chan *chan, int bits); - -/* Option 2: If you don't know about sig bits, but do have their - equivalents (i.e. you can disconnect battery, detect off hook, - generate ring, etc directly) then you can just specify a - sethook function, and we'll call you with appropriate hook states - to set. Still set the ZT_FLAG_RBS in this case as well */ -int (*hooksig)(struct zt_chan *chan, zt_txsig_t hookstate); - -/* Option 3: If you can't use sig bits, you can write a function - which handles the individual hook states */ -int (*sethook)(struct zt_chan *chan, int hookstate); -#endif - -int xpp_echocan(struct zt_chan *chan, int len) -{ -#ifdef XPP_EC_CHUNK - if(len == 0) { /* shut down */ - /* zaptel calls this also during channel initialization */ - if(chan->ec) { - xpp_echo_can_free(chan->ec); - } - return 0; - } - if(chan->ec) { - ERR("%s: Trying to override an existing EC (%p)\n", __FUNCTION__, chan->ec); - return -EINVAL; - } - chan->ec = xpp_echo_can_create(len, 0); - if(!chan->ec) { - ERR("%s: Failed creating xpp EC (len=%d)\n", __FUNCTION__, len); - return -EINVAL; - } -#endif - return 0; -} - -static bool pcm_valid(xpd_t *xpd, xpacket_t *pack) -{ - xpp_line_t lines = RPACKET_FIELD(pack, GLOBAL, PCM_READ, lines); - int i; - int count = 0; - uint16_t good_len; - - BUG_ON(!pack); - BUG_ON(XPACKET_OP(pack) != XPROTO_NAME(GLOBAL, PCM_READ)); - /* - * Don't use for_each_line(xpd, i) here because for BRI it will - * ignore the channels of the other xpd's in the same unit. - */ - for (i = 0; i < CHANNELS_PERXPD; i++) - if(IS_SET(lines, i)) - count++; - /* FRAMES: include opcode in calculation */ - good_len = RPACKET_HEADERSIZE + sizeof(xpp_line_t) + count * 8; - if(XPACKET_LEN(pack) != good_len) { - static int rate_limit = 0; - - XPD_COUNTER(xpd, RECV_ERRORS)++; - if((rate_limit++ % 1000) <= 10) { - XPD_ERR(xpd, "BAD PCM REPLY: packet_len=%d (should be %d), count=%d\n", - XPACKET_LEN(pack), good_len, count); - dump_packet("BAD PCM REPLY", pack, 1); - } - return 0; - } - return 1; -} - - - -static inline void pcm_frame_out(xbus_t *xbus, xframe_t *xframe) -{ - unsigned long flags; - struct timeval now; - unsigned long usec; - - spin_lock_irqsave(&xbus->lock, flags); - do_gettimeofday(&now); - if(unlikely(disable_pcm || !TRANSPORT_RUNNING(xbus))) - goto dropit; - if(XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) { - usec = usec_diff(&now, &xbus->last_tx_sync); - xbus->last_tx_sync = now; - /* ignore startup statistics */ - if(likely(atomic_read(&xbus->pcm_rx_counter) > BIG_TICK_INTERVAL)) { - if(abs(usec - 1000) > TICK_TOLERANCE) { - static int rate_limit; - - if((rate_limit++ % 5003) == 0) - XBUS_DBG(SYNC, xbus, "Bad PCM TX timing(%d): usec=%ld.\n", - rate_limit, usec); - } - if(usec > xbus->max_tx_sync) - xbus->max_tx_sync = usec; - if(usec < xbus->min_tx_sync) - xbus->min_tx_sync = usec; - } - } - spin_unlock_irqrestore(&xbus->lock, flags); - /* OK, really send it */ - if(print_dbg & DBG_PCM ) - dump_xframe("TX_XFRAME_PCM", xbus, xframe); - send_pcm_frame(xbus, xframe); - XBUS_COUNTER(xbus, TX_XFRAME_PCM)++; - return; -dropit: - spin_unlock_irqrestore(&xbus->lock, flags); - FREE_SEND_XFRAME(xbus, xframe); -} - -/* - * Generic implementations of card_pcmfromspan()/card_pcmtospan() - * For FXS/FXO - */ -void generic_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, xpacket_t *pack) -{ - byte *pcm; - struct zt_chan *chans; - unsigned long flags; - int i; - - BUG_ON(!xbus); - BUG_ON(!xpd); - BUG_ON(!pack); - RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = lines; - pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm); - spin_lock_irqsave(&xpd->lock, flags); - chans = xpd->span.chans; - for (i = 0; i < xpd->channels; i++) { - if(IS_SET(lines, i)) { - if(SPAN_REGISTERED(xpd)) { -#ifdef DEBUG_PCMTX - if(pcmtx >= 0 && pcmtx_chan == i) - memset((u_char *)pcm, pcmtx, ZT_CHUNKSIZE); - else -#endif - memcpy((u_char *)pcm, chans[i].writechunk, ZT_CHUNKSIZE); - // fill_beep((u_char *)pcm, xpd->addr.subunit, 2); - } else - memset((u_char *)pcm, 0x7F, ZT_CHUNKSIZE); - pcm += ZT_CHUNKSIZE; - } - } - XPD_COUNTER(xpd, PCM_WRITE)++; - spin_unlock_irqrestore(&xpd->lock, flags); -} - -void generic_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack) -{ - byte *pcm; - xpp_line_t pcm_mask; - unsigned long flags; - int i; - - pcm = RPACKET_FIELD(pack, GLOBAL, PCM_READ, pcm); - pcm_mask = RPACKET_FIELD(pack, GLOBAL, PCM_READ, lines); - spin_lock_irqsave(&xpd->lock, flags); - if(!SPAN_REGISTERED(xpd)) - goto out; - for (i = 0; i < xpd->channels; i++) { - volatile u_char *r = xpd->span.chans[i].readchunk; - - if(!IS_SET(xpd->wanted_pcm_mask, i)) { - if(IS_SET(xpd->silence_pcm, i)) - memset((u_char *)r, 0x7F, ZT_CHUNKSIZE); // SILENCE - continue; - } - pcm_mask &= ~xpd->mute_dtmf; - if(IS_SET(pcm_mask, i)) { - // memset((u_char *)r, 0x5A, ZT_CHUNKSIZE); // DEBUG - // fill_beep((u_char *)r, 1, 1); // DEBUG: BEEP - memcpy((u_char *)r, pcm, ZT_CHUNKSIZE); - pcm += ZT_CHUNKSIZE; - } else { - memset((u_char *)r, 0x7F, ZT_CHUNKSIZE); // SILENCE - } - } -out: - XPD_COUNTER(xpd, PCM_READ)++; - spin_unlock_irqrestore(&xpd->lock, flags); -} - -static int copy_pcm_tospan(xbus_t *xbus, xframe_t *xframe) -{ - byte *xframe_end; - xpacket_t *pack; - byte *p; - int ret = -EPROTO; /* Assume error */ - - if(print_dbg & DBG_PCM) - dump_xframe("RX_XFRAME_PCM", xbus, xframe); - /* handle content */ - - p = xframe->packets; - xframe_end = p + XFRAME_LEN(xframe); - do { - int len; - xpd_t *xpd; - - pack = (xpacket_t *)p; - len = XPACKET_LEN(pack); - /* Sanity checks */ - if(unlikely(XPACKET_OP(pack) != XPROTO_NAME(GLOBAL,PCM_READ))) { - static int rate_limit; - - if((rate_limit++ % 1003) == 0) { - XBUS_NOTICE(xbus, - "%s: Non-PCM packet within a PCM xframe. (%d)\n", - __FUNCTION__, rate_limit); - dump_xframe("In PCM xframe", xbus, xframe); - } - goto out; - } - p += len; - if(p > xframe_end || len < RPACKET_HEADERSIZE) { - static int rate_limit; - - if((rate_limit++ % 1003) == 0) { - XBUS_NOTICE(xbus, - "%s: Invalid packet length %d. (%d)\n", - __FUNCTION__, len, rate_limit); - dump_xframe("BAD LENGTH", xbus, xframe); - } - goto out; - } - xpd = xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack)); - if(unlikely(!xpd)) { - static int rate_limit; - - if((rate_limit++ % 1003) == 0) { - notify_bad_xpd(__FUNCTION__, xbus, XPACKET_ADDR(pack), "RECEIVE PCM"); - dump_xframe("Unknown XPD addr", xbus, xframe); - } - goto out; - } - if(!pcm_valid(xpd, pack)) - goto out; - if(SPAN_REGISTERED(xpd)) { - XBUS_COUNTER(xbus, RX_PACK_PCM)++; - CALL_XMETHOD(card_pcm_tospan, xbus, xpd, pack); - } - } while(p < xframe_end); - ret = 0; /* all good */ - XBUS_COUNTER(xbus, RX_XFRAME_PCM)++; -out: - FREE_RECV_XFRAME(xbus, xframe); - return ret; -} - -static void xbus_tick(xbus_t *xbus) -{ - int i; - xpd_t *xpd; - xframe_t *xframe = NULL; - xpacket_t *pack = NULL; - size_t pcm_len; - bool sent_sync_bit = 0; - - /* - * Update zaptel - */ - for(i = 0; i < MAX_XPDS; i++) { - xpd = xpd_of(xbus, i); - if(xpd && SPAN_REGISTERED(xpd)) { -#ifdef OPTIMIZE_CHANMUTE - int j; - xpp_line_t xmit_mask = xpd->wanted_pcm_mask; - - xmit_mask |= xpd->silence_pcm; - xmit_mask |= xpd->digital_signalling; - for_each_line(xpd, j) { - xpd->chans[j].chanmute = (optimize_chanmute) - ? !IS_SET(xmit_mask, j) - : 0; - } -#endif - /* - * calls to zt_transmit should be out of spinlocks, as it may call back - * our hook setting methods. - */ - zt_transmit(&xpd->span); - } - } - /* - * Fill xframes - */ - for(i = 0; i < MAX_XPDS; i++) { - if((xpd = xpd_of(xbus, i)) == NULL) - continue; - pcm_len = xpd->pcm_len; - if(SPAN_REGISTERED(xpd)) { - if(pcm_len && xpd->card_present) { - do { - // pack = NULL; /* FORCE single packet frames */ - if(xframe && !pack) { /* FULL frame */ - pcm_frame_out(xbus, xframe); - xframe = NULL; - XBUS_COUNTER(xbus, TX_PCM_FRAG)++; - } - if(!xframe) { /* Alloc frame */ - xframe = ALLOC_SEND_XFRAME(xbus); - if (!xframe) { - static int rate_limit; - - if((rate_limit++ % 3001) == 0) - XBUS_ERR(xbus, - "%s: failed to allocate new xframe\n", - __FUNCTION__); - return; - } - } - pack = xframe_next_packet(xframe, pcm_len); - } while(!pack); - XPACKET_INIT(pack, GLOBAL, PCM_WRITE, xpd->xbus_idx, 1, 0); - XPACKET_LEN(pack) = pcm_len; - if(!sent_sync_bit) { - XPACKET_ADDR_SYNC(pack) = 1; - sent_sync_bit = 1; - } - CALL_XMETHOD(card_pcm_fromspan, xbus, xpd, xpd->wanted_pcm_mask, pack); - XBUS_COUNTER(xbus, TX_PACK_PCM)++; - } - } - } - if(xframe) /* clean any leftovers */ - pcm_frame_out(xbus, xframe); - /* - * Receive PCM - */ - i = atomic_read(&xbus->pcm_rx_counter) & 1; - while((xframe = xframe_dequeue(&xbus->pcm_tospan[i])) != NULL) { - copy_pcm_tospan(xbus, xframe); - if(XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) { - struct timeval now; - unsigned long usec; - - do_gettimeofday(&now); - usec = usec_diff(&now, &xbus->last_rx_sync); - xbus->last_rx_sync = now; - /* ignore startup statistics */ - if(likely(atomic_read(&xbus->pcm_rx_counter) > BIG_TICK_INTERVAL)) { - if(abs(usec - 1000) > TICK_TOLERANCE) { - static int rate_limit; - - if((rate_limit++ % 5003) == 0) - XBUS_DBG(SYNC, xbus, "Bad PCM RX timing(%d): usec=%ld.\n", - rate_limit, usec); - } - if(usec > xbus->max_rx_sync) - xbus->max_rx_sync = usec; - if(usec < xbus->min_rx_sync) - xbus->min_rx_sync = usec; - } - } - } - for(i = 0; i < MAX_XPDS; i++) { - xpd = xpd_of(xbus, i); - if(!xpd || !xpd->card_present) - continue; - if(SPAN_REGISTERED(xpd)) { - do_ec(xpd); - zt_receive(&xpd->span); - } - xpd->silence_pcm = 0; /* silence was injected */ - xpd->timer_count = xbus->global_counter; - /* - * Must be called *after* tx/rx so - * D-Chan counters may be cleared - */ - CALL_XMETHOD(card_tick, xbus, xpd); - } -} - -void do_tick(xbus_t *xbus, struct timeval tv_received) -{ - int counter = atomic_read(&xpp_tick_counter); - - xbus_command_queue_tick(xbus); - xpp_timing_tick(&xbus->timing, &tv_received); - if(syncer == xbus) { - xpp_timing_tick(&ref_sync, &tv_received); - if((counter % BIG_TICK_INTERVAL) == 0) - reset_sync_counters(); - } - if((atomic_read(&xbus->pcm_rx_counter) % BIG_TICK_INTERVAL) == 0) { - if(xbus->sync_mode == SYNC_MODE_PLL) - sync_rate_adjust(xbus); - } - if(likely(xbus->self_ticking)) - xbus_tick(xbus); - xbus->global_counter = counter; -} - -void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe) -{ - int which = atomic_read(&xbus->pcm_rx_counter) & 1; - - if(!xframe_enqueue(&xbus->pcm_tospan[which], xframe)) { - static int rate_limit; - - if((rate_limit++ % 1003) == 0) - XBUS_DBG(SYNC, xbus, - "Failed to enqueue received pcm frame. (%d)\n", - rate_limit); - FREE_RECV_XFRAME(xbus, xframe); - } - /* - * The sync_master bit is marked at the first packet - * of the frame, regardless of the XPD that is sync master. - * FIXME: what about PRI split? - */ - if(XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) { - do_tick(xbus, xframe->tv_received); - atomic_inc(&xbus->pcm_rx_counter); - } else - xbus->xbus_frag_count++; -} - -#ifdef CONFIG_PROC_FS -int proc_sync_read(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - struct timeval now; - unsigned int counter = atomic_read(&xpp_tick_counter); - unsigned long usec; - - do_gettimeofday(&now); - len += sprintf(page + len, "# To modify sync source write into this file:\n"); - len += sprintf(page + len, "# ZAPTEL - Another zaptel device provide sync\n"); - len += sprintf(page + len, "# SYNC=nn - XBUS-nn provide sync\n"); - len += sprintf(page + len, "# QUERY=nn - Query XBUS-nn for sync information (DEBUG)\n"); - if(!syncer) { - if(zaptel_syncer) - len += sprintf(page + len, "ZAPTEL\n"); - else - len += sprintf(page + len, "NO-SYNC\n"); - } else - len += sprintf(page + len, "SYNC=%02d\n", syncer->num); -#ifdef ZAPTEL_SYNC_TICK - if(zaptel_syncer) { - len += sprintf(page + len, - "Zaptel Reference Sync (%d registered spans):\n", - total_registered_spans()); - len += sprintf(page + len, "\tzaptel_tick: #%d\n", zaptel_tick_count); - len += sprintf(page + len, "\ttick - zaptel_tick = %d\n", - counter - zaptel_tick_count); - } else { - len += sprintf(page + len, - "Zaptel Reference Sync Not activated\n"); - } -#endif - usec = usec_diff(&now, &ref_sync.timing_val); - len += sprintf(page + len, "\ntick: #%d\n", counter); - len += sprintf(page + len, - "tick rate: %4d/second (measured %ld.%ld msec ago)\n", - ref_sync.tick_rate, - usec / 1000, usec % 1000); - if(pcm_tasklet) - len += sprintf(page + len, PCM_TASKLET_DEPRECATION); - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; -} - -static int proc_sync_write(struct file *file, const char __user *buffer, unsigned long count, void *data) -{ - char buf[MAX_PROC_WRITE]; - int xbus_num; - int xpd_num; - xbus_t *xbus; - xpd_t *xpd; - - // DBG(SYNC, "%s: count=%ld\n", __FUNCTION__, count); - if(count >= MAX_PROC_WRITE) - return -EINVAL; - if(copy_from_user(buf, buffer, count)) - return -EFAULT; - buf[count] = '\0'; - if(strncmp("ZAPTEL", buf, 6) == 0) { - DBG(SYNC, "ZAPTEL\n"); - zaptel_syncer=1; - update_sync_master(NULL); - } else if(sscanf(buf, "SYNC=%d", &xbus_num) == 1) { - DBG(SYNC, "SYNC=%d\n", xbus_num); - if((xbus = get_xbus(xbus_num)) == NULL) { - ERR("No bus %d exists\n", xbus_num); - return -ENXIO; - } - update_sync_master(xbus); - put_xbus(xbus); - } else if(sscanf(buf, "QUERY=%d", &xbus_num) == 1) { - DBG(SYNC, "QUERY=%d\n", xbus_num); - if((xbus = get_xbus(xbus_num)) == NULL) { - ERR("No bus %d exists\n", xbus_num); - return -ENXIO; - } - CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_QUERY, 0); - put_xbus(xbus); - } else if(sscanf(buf, "%d %d", &xbus_num, &xpd_num) == 2) { - NOTICE("Using deprecated syntax to update %s file\n", - PROC_SYNC); - if(xpd_num != 0) { - ERR("Currently can only set sync for XPD #0\n"); - return -EINVAL; - } - if((xbus = get_xbus(xbus_num)) == NULL) { - ERR("No bus %d exists\n", xbus_num); - return -ENXIO; - } - if((xpd = xpd_of(xbus, xpd_num)) == NULL) { - XBUS_ERR(xbus, "No xpd %d exists\n", xpd_num); - put_xbus(xbus); - return -ENXIO; - } - update_sync_master(xbus); - put_xbus(xbus); - } else { - ERR("%s: cannot parse '%s'\n", __FUNCTION__, buf); - count = -EINVAL; - } - return count; -} - -static struct proc_dir_entry *top; - -#endif - -int xbus_pcm_init(struct proc_dir_entry *toplevel) -{ - int ret = 0; -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *ent; -#endif - -#ifdef OPTIMIZE_CHANMUTE - INFO("FEATURE: with CHANMUTE optimization (%sactivated)\n", - (optimize_chanmute)?"":"de"); -#endif -#ifdef WITH_ECHO_SUPPRESSION - INFO("FEATURE: with ECHO_SUPPRESSION\n"); -#else - INFO("FEATURE: without ECHO_SUPPRESSION\n"); -#endif - if(xpp_ec) - INFO("FEATURE: with XPP_EC_CHUNK\n"); - else - INFO("FEATURE: without XPP_EC_CHUNK\n"); -#ifdef ZAPTEL_SYNC_TICK - INFO("FEATURE: with sync_tick() from ZAPTEL\n"); -#else - INFO("FEATURE: without sync_tick() from ZAPTEL\n"); -#endif -#ifdef CONFIG_PROC_FS - top = toplevel; - ent = create_proc_entry(PROC_SYNC, 0644, top); - if(!ent) { - ret = -EFAULT; - goto err; - } - ent->read_proc = proc_sync_read; - ent->write_proc = proc_sync_write; - ent->data = NULL; -#endif - if(pcm_tasklet) - ERR(PCM_TASKLET_DEPRECATION); - xpp_timing_init(&ref_sync, "REF-SYNC"); -err: - return ret; -} - -void xbus_pcm_shutdown(void) -{ -#ifdef CONFIG_PROC_FS - DBG(GENERAL, "Removing '%s' from proc\n", PROC_SYNC); - remove_proc_entry(PROC_SYNC, top); -#endif -} - - -EXPORT_SYMBOL(xbus_request_sync); -EXPORT_SYMBOL(got_new_syncer); -EXPORT_SYMBOL(elect_syncer); -EXPORT_SYMBOL(xpp_echocan); -#ifdef ZAPTEL_SYNC_TICK -EXPORT_SYMBOL(zaptel_sync_tick); -#endif -EXPORT_SYMBOL(__pcm_recompute); -EXPORT_SYMBOL(pcm_recompute); -EXPORT_SYMBOL(generic_card_pcm_tospan); -EXPORT_SYMBOL(generic_card_pcm_fromspan); - diff --git a/xpp/xbus-pcm.h b/xpp/xbus-pcm.h deleted file mode 100644 index 79d0078..0000000 --- a/xpp/xbus-pcm.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2004-2007, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* - * This source module contains all the PCM and SYNC handling code. - */ -#ifndef XBUS_PCM_H -#define XBUS_PCM_H - -#include "xdefs.h" -#include -#include - -#ifdef __KERNEL__ - -enum sync_mode { - SYNC_MODE_NONE = 0x00, - SYNC_MODE_AB = 0x01, /* Astribank sync */ - SYNC_MODE_PLL = 0x03, /* Adjust XPD's PLL according to HOST */ - SYNC_MODE_QUERY = 0x80, -}; - -/* - * A generic timing source. Encapsulates all sampling - * logic, average and standard deviation computation, - * tick_rate computation. - * - * Each xbus has embedded instance. - * Also there is a global instance for external reference - * syncing (e.g: from zaptel) - */ -struct xpp_timing { - const char *name; - struct timeval timing_val; - unsigned long timing_count; - long accumulated_usec; - long accumulated_usec_sqr; - int tick_avg; - int tick_stddev; - spinlock_t lock; - unsigned int tick_rate; -}; - -void xpp_timing_init(struct xpp_timing *timing, const char *name); - -static inline long usec_diff(const struct timeval *tv1, const struct timeval *tv2) -{ - long diff_sec; - long diff_usec; - - diff_sec = tv1->tv_sec - tv2->tv_sec; - diff_usec = tv1->tv_usec - tv2->tv_usec; - return diff_sec * 1000000 + diff_usec; -} - - -int xbus_pcm_init(struct proc_dir_entry *top); -void xbus_pcm_shutdown(void); -int send_pcm_frame(xbus_t *xbus, xframe_t *xframe); -void pcm_recompute(xpd_t *xpd, xpp_line_t tmp_pcm_mask); -void __pcm_recompute(xpd_t *xpd, xpp_line_t tmp_pcm_mask); /* non locking */ -void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe); -void generic_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, xpacket_t *pack); -void generic_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack); -void fill_beep(u_char *buf, int num, int duration); -const char *sync_mode_name(enum sync_mode mode); -void xbus_set_command_timer(xbus_t *xbus, bool on); -void xbus_request_sync(xbus_t *xbus, enum sync_mode mode); -void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift); -int xbus_command_queue_tick(xbus_t *xbus); -void xbus_reset_counters(xbus_t *xbus); -void elect_syncer(const char *msg); -int xpp_echocan(struct zt_chan *chan, int len); -#ifdef ZAPTEL_SYNC_TICK -int zaptel_sync_tick(struct zt_span *span, int is_master); -#endif - -#ifdef XPP_EC_CHUNK -extern int xpp_ec; -#else -#define xpp_ec 0 -#endif - -#endif /* __KERNEL__ */ - -#endif /* XBUS_PCM_H */ - diff --git a/xpp/xbus-sysfs.c b/xpp/xbus-sysfs.c deleted file mode 100644 index d45058e..0000000 --- a/xpp/xbus-sysfs.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -# warning "This module is tested only with 2.6 kernels" -#endif - -#include -#include -#include -#include -#ifdef PROTOCOL_DEBUG -#include -#endif -#include -#include -#include /* for msleep() to debug */ -#include "xpd.h" -#include "xpp_zap.h" -#include "xbus-core.h" -#ifdef XPP_DEBUGFS -#include "xpp_log.h" -#endif -#include "zap_debug.h" - -static const char rcsid[] = "$Id$"; - -/* Command line parameters */ -extern int print_dbg; - - -/* Kernel versions... */ -/* - * Hotplug replaced with uevent in 2.6.16 - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) -#define OLD_HOPLUG_SUPPORT // for older kernels -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) -#define DEVICE_ATTR_FUNC(name,dev,buf) \ - ssize_t name(struct device *dev, struct device_attribute *attr, char *buf) -#else -#define DEVICE_ATTR_FUNC(name,dev,buf) \ - ssize_t name(struct device *dev, char *buf) -#endif - -/*--------- Sysfs Bus handling ----*/ -static int xpp_bus_match(struct device *dev, struct device_driver *driver) -{ - DBG(GENERAL, "dev->bus_id = %s, driver->name = %s\n", dev->bus_id, driver->name); - return 1; -} - -#ifdef OLD_HOPLUG_SUPPORT -static int xpp_bus_hotplug(struct device *dev, char **envp, int envnum, char *buff, int bufsize) -{ - xbus_t *xbus; - - if(!dev) - return -ENODEV; - xbus = dev_to_xbus(dev); - envp[0] = buff; - if(snprintf(buff, bufsize, "XBUS_NAME=%s", xbus->busname) >= bufsize) - return -ENOMEM; - envp[1] = NULL; - return 0; -} -#else - -#define XBUS_ADD_UEVENT_VAR(fmt, val...) \ - do { \ - int err = add_uevent_var(envp, num_envp, &i, \ - buffer, buffer_size, &len, \ - fmt, val); \ - if (err) \ - return err; \ - } while (0) - -static int xpp_bus_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) -{ - xbus_t *xbus; - int i = 0; - int len = 0; - - if(!dev) - return -ENODEV; - xbus = dev_to_xbus(dev); - DBG(GENERAL, "bus_id=%s xbus=%s\n", dev->bus_id, xbus->busname); - XBUS_ADD_UEVENT_VAR("XBUS_NUM=%02d", xbus->num); - XBUS_ADD_UEVENT_VAR("XBUS_NAME=%s", xbus->busname); - envp[i] = NULL; - return 0; -} -#endif - -static void xpp_bus_release(struct device *dev) -{ - DBG(GENERAL, "\n"); -} - -static void xpp_dev_release(struct device *dev) -{ - xbus_t *xbus; - - BUG_ON(!dev); - xbus = dev_to_xbus(dev); - XBUS_DBG(GENERAL, xbus, "\n"); -} - -static struct bus_type xpp_bus_type = { - .name = "astribanks", - .match = xpp_bus_match, -#ifdef OLD_HOPLUG_SUPPORT - .hotplug = xpp_bus_hotplug, -#else - .uevent = xpp_bus_uevent, -#endif -}; - -static struct device xpp_bus = { - .bus_id = "xppbus", - .release = xpp_bus_release -}; - -static struct device_driver xpp_driver = { - .name = "xppdrv", - .bus = &xpp_bus_type, -#ifndef OLD_HOPLUG_SUPPORT - .owner = THIS_MODULE -#endif -}; - -int register_xpp_bus(void) -{ - int ret; - - if((ret = bus_register(&xpp_bus_type)) < 0) { - ERR("%s: bus_register failed. Error number %d", __FUNCTION__, ret); - goto failed_bus; - } - if((ret = device_register(&xpp_bus)) < 0) { - ERR("%s: registration of xpp_bus failed. Error number %d", - __FUNCTION__, ret); - goto failed_busdevice; - } - if((ret = driver_register(&xpp_driver)) < 0) { - ERR("%s: driver_register failed. Error number %d", __FUNCTION__, ret); - goto failed_driver; - } - return 0; -failed_driver: - device_unregister(&xpp_bus); -failed_busdevice: - bus_unregister(&xpp_bus_type); -failed_bus: - return ret; -} - -void unregister_xpp_bus(void) -{ - driver_unregister(&xpp_driver); - device_unregister(&xpp_bus); - bus_unregister(&xpp_bus_type); -} - -/*--------- Sysfs Device handling ----*/ -static DEVICE_ATTR_FUNC(connector_show, dev, buf) -{ - xbus_t *xbus; - int ret; - - xbus = dev_to_xbus(dev); - ret = snprintf(buf, PAGE_SIZE, "%s\n", xbus->busdesc); - return ret; -} - -static DEVICE_ATTR_FUNC(label_show, dev, buf) -{ - xbus_t *xbus; - int ret; - - xbus = dev_to_xbus(dev); - ret = snprintf(buf, PAGE_SIZE, "%s\n", xbus->label); - return ret; -} - -static DEVICE_ATTR_FUNC(status_show, dev, buf) -{ - xbus_t *xbus; - int ret; - - xbus = dev_to_xbus(dev); - ret = snprintf(buf, PAGE_SIZE, "%s\n", (TRANSPORT_RUNNING(xbus))?"connected":"missing"); - return ret; -} - -static DEVICE_ATTR(connector, S_IRUGO, connector_show, NULL); -static DEVICE_ATTR(label, S_IRUGO, label_show, NULL); -static DEVICE_ATTR(status, S_IRUGO, status_show, NULL); - -void xbus_sysfs_remove(xbus_t *xbus) -{ - struct device *astribank; - - BUG_ON(!xbus); - XBUS_DBG(GENERAL, xbus, "\n"); - astribank = &xbus->astribank; - BUG_ON(!astribank); - device_remove_file(&xbus->astribank, &dev_attr_status); - device_remove_file(&xbus->astribank, &dev_attr_label); - device_remove_file(&xbus->astribank, &dev_attr_connector); - device_unregister(&xbus->astribank); -} - -int xbus_sysfs_create(xbus_t *xbus) -{ - struct device *astribank; - int ret = 0; - - BUG_ON(!xbus); - astribank = &xbus->astribank; - BUG_ON(!astribank); - XBUS_DBG(GENERAL, xbus, "\n"); - device_initialize(astribank); - astribank->bus = &xpp_bus_type; - astribank->parent = &xpp_bus; - snprintf(astribank->bus_id, BUS_ID_SIZE, "xbus-%02d", xbus->num); - astribank->driver_data = NULL; /* FIXME: add some usefull data */ - astribank->release = xpp_dev_release; - ret = device_register(astribank); - if(ret) { - XBUS_ERR(xbus, "%s: device_add failed: %d\n", __FUNCTION__, ret); - goto out; - } - ret = device_create_file(astribank, &dev_attr_connector); - if(ret) { - XBUS_ERR(xbus, "%s: device_create_file failed: %d\n", __FUNCTION__, ret); - goto out; - } - ret = device_create_file(astribank, &dev_attr_label); - if(ret) { - XBUS_ERR(xbus, "%s: device_create_file failed: %d\n", __FUNCTION__, ret); - goto out; - } - ret = device_create_file(astribank, &dev_attr_status); - if(ret) { - XBUS_ERR(xbus, "%s: device_create_file failed: %d\n", __FUNCTION__, ret); - goto out; - } -out: - return ret; -} diff --git a/xpp/xdefs.h b/xpp/xdefs.h deleted file mode 100644 index 2aec497..0000000 --- a/xpp/xdefs.h +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef XDEFS_H -#define XDEFS_H -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "xpp_version.h" - -#ifdef __KERNEL__ - -#include -#include - -#else - -/* This is to enable user-space programs to include this. */ - -#include -typedef uint8_t __u8; -typedef uint32_t __u32; - -#include - -#define DBG(fmt, ...) printf("DBG: %s: " fmt, __FUNCTION__, ## __VA_ARGS__) -#define INFO(fmt, ...) printf("INFO: " fmt, ## __VA_ARGS__) -#define NOTICE(fmt, ...) printf("NOTICE: " fmt, ## __VA_ARGS__) -#define ERR(fmt, ...) printf("ERR: " fmt, ## __VA_ARGS__) -#define __user - -struct list_head { struct list_head *next; struct list_head *prev; }; - -#endif - -#define PACKED __attribute__((packed)) - -#define ALL_LINES ((lineno_t)-1) - -#define BIT(i) (1 << (i)) -#define BIT_SET(x,i) ((x) |= BIT(i)) -#define BIT_CLR(x,i) ((x) &= ~BIT(i)) -#define IS_SET(x,i) (((x) & BIT(i)) != 0) -#define BITMASK(i) (((u64)1 << (i)) - 1) - -#define MAX_PROC_WRITE 100 /* Largest buffer we allow writing our /proc files */ -#define CHANNELS_PERXPD 32 /* Depends on xpp_line_t and protocol fields */ - -#define MAX_SPANNAME 20 /* From zaptel.h */ -#define MAX_SPANDESC 40 /* From zaptel.h */ -#define MAX_CHANNAME 40 /* From zaptel.h */ - -#define XPD_NAMELEN 10 /* must be <= from maximal workqueue name */ -#define XPD_DESCLEN 20 -#define XBUS_NAMELEN 20 /* must be <= from maximal workqueue name */ -#define XBUS_DESCLEN 40 -#define LABEL_SIZE 20 - -#define UNIT_BITS 3 /* Bit for Astribank unit number */ -#define SUBUNIT_BITS 3 /* Bit for Astribank subunit number */ - -#define MAX_UNIT BIT(UNIT_BITS) /* 1 FXS + 3 FXS/FXO | 1 BRI + 3 FXS/FXO */ -#define MAX_SUBUNIT BIT(SUBUNIT_BITS) /* 8 port BRI */ - -/* - * Compile time sanity checks - */ -#if MAX_UNIT > BIT(UNIT_BITS) -#error "MAX_UNIT too large" -#endif - -#if MAX_SUBUNIT > BIT(SUBUNIT_BITS) -#error "MAX_SUBUNIT too large" -#endif - -#define MAX_XPDS (MAX_UNIT*MAX_SUBUNIT) - -#define VALID_XPD_NUM(x) ((x) < MAX_XPDS && (x) >= 0) - -#define CHAN_BITS 5 /* 0-30 for E1, 31 = ALL_CHANS */ -#define ALL_CHANS BITMASK(CHAN_BITS) -#define MAX_CHAN (ALL_CHANS - 1) -#define VALID_CHAN_NUM(x) ((x) < MAX_CHAN) - -typedef char *charp; -typedef unsigned char byte; -#ifdef __KERNEL__ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -#define KMEM_CACHE_T kmem_cache_t -#else -#define KMEM_CACHE_T struct kmem_cache -#endif - -#define KZALLOC(size, gfp) my_kzalloc(size, gfp) -#define KZFREE(p) do { \ - memset((p), 0, sizeof(*(p))); \ - kfree(p); \ - } while(0); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -typedef int bool; -#endif -#else -typedef int bool; -#endif -typedef struct xbus xbus_t; -typedef struct xpd xpd_t; -typedef struct xframe xframe_t; -typedef struct xpacket xpacket_t; -typedef struct xops xops_t; -typedef __u32 xpp_line_t; /* at most 31 lines for E1 */ -typedef byte lineno_t; - -#endif /* XDEFS_H */ diff --git a/xpp/xframe_queue.c b/xpp/xframe_queue.c deleted file mode 100644 index 23dee0e..0000000 --- a/xpp/xframe_queue.c +++ /dev/null @@ -1,258 +0,0 @@ -#include "xframe_queue.h" -#include "xbus-core.h" -#include "zap_debug.h" - -static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags); -static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe); - -void xframe_queue_init(struct xframe_queue *q, unsigned int steady_state_count, unsigned int max_count, const char *name, void *priv) -{ - memset(q, 0, sizeof(*q)); - spin_lock_init(&q->lock); - INIT_LIST_HEAD(&q->head); - q->max_count = XFRAME_QUEUE_MARGIN + max_count; - q->steady_state_count = XFRAME_QUEUE_MARGIN + steady_state_count; - q->name = name; - q->priv = priv; -} - -void xframe_queue_clearstats(struct xframe_queue *q) -{ - q->worst_count = 0; - //q->overflows = 0; /* Never clear overflows */ - q->worst_lag_usec = 0L; -} - -static bool __xframe_enqueue(struct xframe_queue *q, xframe_t *xframe) -{ - int ret = 1; - - if(q->count >= q->max_count) { - q->overflows++; - ret = 0; - goto out; - } - if(++q->count > q->worst_count) - q->worst_count = q->count; - list_add_tail(&xframe->frame_list, &q->head); - do_gettimeofday(&xframe->tv_queued); -out: - return ret; -} - -bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&q->lock, flags); - ret = __xframe_enqueue(q, xframe); - spin_unlock_irqrestore(&q->lock, flags); - return ret; -} - -xframe_t *__xframe_dequeue(struct xframe_queue *q) -{ - xframe_t *frm = NULL; - struct list_head *h; - struct timeval now; - unsigned long usec_lag; - - if(list_empty(&q->head)) - goto out; - h = q->head.next; - list_del_init(h); - --q->count; - frm = list_entry(h, xframe_t, frame_list); - do_gettimeofday(&now); - usec_lag = - (now.tv_sec - frm->tv_queued.tv_sec)*1000*1000 + - (now.tv_usec - frm->tv_queued.tv_usec); - if(q->worst_lag_usec < usec_lag) - q->worst_lag_usec = usec_lag; -out: - return frm; -} - -xframe_t *xframe_dequeue(struct xframe_queue *q) -{ - unsigned long flags; - xframe_t *frm; - - spin_lock_irqsave(&q->lock, flags); - frm = __xframe_dequeue(q); - spin_unlock_irqrestore(&q->lock, flags); - return frm; -} -void xframe_queue_disable(struct xframe_queue *q) -{ - q->max_count = 0; -} - -void xframe_queue_clear(struct xframe_queue *q) -{ - xframe_t *xframe; - xbus_t *xbus = q->priv; - int i = 0; - - xframe_queue_disable(q); - while((xframe = xframe_dequeue(q)) != NULL) { - transport_free_xframe(xbus, xframe); - i++; - } - XBUS_INFO(xbus, "%s: finished queue clear (%d items)\n", q->name, i); -} - -uint xframe_queue_count(struct xframe_queue *q) -{ - return q->count; -} - -/*------------------------- Frame Alloc/Dealloc --------------------*/ - -static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags) -{ - struct xbus_ops *ops; - xframe_t *xframe; - unsigned long flags; - - BUG_ON(!xbus); - ops = transportops_get(xbus); - if(unlikely(!ops)) { - XBUS_ERR(xbus, "Missing transport\n"); - return NULL; - } - spin_lock_irqsave(&xbus->transport.lock, flags); - //XBUS_INFO(xbus, "%s (transport_refcount=%d)\n", __FUNCTION__, atomic_read(&xbus->transport.transport_refcount)); - xframe = ops->alloc_xframe(xbus, gfp_flags); - if(!xframe) { - static int rate_limit; - - if((rate_limit++ % 3001) == 0) - XBUS_ERR(xbus, - "Failed xframe allocation from transport (%d)\n", - rate_limit); - transportops_put(xbus); - /* fall through */ - } - spin_unlock_irqrestore(&xbus->transport.lock, flags); - return xframe; -} - -static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe) -{ - struct xbus_ops *ops; - unsigned long flags; - - BUG_ON(!xbus); - ops = xbus->transport.ops; - BUG_ON(!ops); - spin_lock_irqsave(&xbus->transport.lock, flags); - //XBUS_INFO(xbus, "%s (transport_refcount=%d)\n", __FUNCTION__, atomic_read(&xbus->transport.transport_refcount)); - ops->free_xframe(xbus, xframe); - transportops_put(xbus); - spin_unlock_irqrestore(&xbus->transport.lock, flags); -} - -static bool xframe_queue_adjust(struct xframe_queue *q) -{ - xbus_t *xbus; - xframe_t *xframe; - int delta; - unsigned long flags; - int ret = 0; - - BUG_ON(!q); - xbus = q->priv; - BUG_ON(!xbus); - spin_lock_irqsave(&q->lock, flags); - delta = q->count - q->steady_state_count; - if(delta < -XFRAME_QUEUE_MARGIN) { - /* Increase pool by one frame */ - //XBUS_INFO(xbus, "%s(%d): Allocate one\n", q->name, delta); - xframe = transport_alloc_xframe(xbus, GFP_ATOMIC); - if(!xframe) { - XBUS_ERR(xbus, "%s: failed frame allocation\n", q->name); - goto out; - } - if(!__xframe_enqueue(q, xframe)) { - XBUS_ERR(xbus, "%s: failed enqueueing frame\n", q->name); - transport_free_xframe(xbus, xframe); - goto out; - } - } else if(delta > XFRAME_QUEUE_MARGIN) { - /* Decrease pool by one frame */ - //XBUS_INFO(xbus, "%s(%d): Free one\n", q->name, delta); - xframe = __xframe_dequeue(q); - if(!xframe) { - XBUS_ERR(xbus, "%s: failed dequeueing frame\n", q->name); - goto out; - } - transport_free_xframe(xbus, xframe); - } - ret = 1; -out: - spin_unlock_irqrestore(&q->lock, flags); - return ret; -} - -xframe_t *get_xframe(struct xframe_queue *q) -{ - xframe_t *xframe; - xbus_t *xbus; - - BUG_ON(!q); - xbus = (xbus_t *)q->priv; - BUG_ON(!xbus); - xframe_queue_adjust(q); - xframe = xframe_dequeue(q); - if(!xframe) { - static int rate_limit; - - if((rate_limit++ % 3001) == 0) - XBUS_ERR(xbus, "%s STILL EMPTY (%d)\n", q->name, rate_limit); - return NULL; - } - BUG_ON(xframe->xframe_magic != XFRAME_MAGIC); - atomic_set(&xframe->frame_len, 0); - xframe->first_free = xframe->packets; - do_gettimeofday(&xframe->tv_created); - /* - * If later parts bother to correctly initialize their - * headers, there is no need to memset() the whole data. - * - * ticket:403 - * - * memset(xframe->packets, 0, xframe->frame_maxlen); - */ - //XBUS_INFO(xbus, "%s\n", __FUNCTION__); - return xframe; -} - -void put_xframe(struct xframe_queue *q, xframe_t *xframe) -{ - xbus_t *xbus; - - BUG_ON(!q); - xbus = (xbus_t *)q->priv; - BUG_ON(!xbus); - //XBUS_INFO(xbus, "%s\n", __FUNCTION__); - BUG_ON(!TRANSPORT_EXIST(xbus)); - if(unlikely(!xframe_enqueue(q, xframe))) { - XBUS_ERR(xbus, "Failed returning xframe to %s\n", q->name); - transport_free_xframe(xbus, xframe); - return; - } - xframe_queue_adjust(q); -} - - -EXPORT_SYMBOL(xframe_queue_init); -EXPORT_SYMBOL(xframe_queue_clearstats); -EXPORT_SYMBOL(xframe_enqueue); -EXPORT_SYMBOL(xframe_dequeue); -EXPORT_SYMBOL(xframe_queue_disable); -EXPORT_SYMBOL(xframe_queue_clear); -EXPORT_SYMBOL(xframe_queue_count); -EXPORT_SYMBOL(get_xframe); -EXPORT_SYMBOL(put_xframe); diff --git a/xpp/xframe_queue.h b/xpp/xframe_queue.h deleted file mode 100644 index 5612d65..0000000 --- a/xpp/xframe_queue.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef XFRAME_QUEUE_H -#define XFRAME_QUEUE_H - -#include -#include -#include "xdefs.h" - -#define XFRAME_QUEUE_MARGIN 10 - -struct xframe_queue { - struct list_head head; - unsigned int count; - unsigned int max_count; - unsigned int steady_state_count; - spinlock_t lock; - const char *name; - void *priv; - /* statistics */ - unsigned int worst_count; - unsigned int overflows; - unsigned long worst_lag_usec; /* since xframe creation */ -}; - -void xframe_queue_init(struct xframe_queue *q, - unsigned int steady_state_count, unsigned int max_count, - const char *name, void *priv); -__must_check bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe); -__must_check xframe_t *xframe_dequeue(struct xframe_queue *q); -void xframe_queue_clearstats(struct xframe_queue *q); -void xframe_queue_disable(struct xframe_queue *q); -void xframe_queue_clear(struct xframe_queue *q); -uint xframe_queue_count(struct xframe_queue *q); - -#endif /* XFRAME_QUEUE_ */ diff --git a/xpp/xpd.h b/xpp/xpd.h deleted file mode 100644 index 3187227..0000000 --- a/xpp/xpd.h +++ /dev/null @@ -1,223 +0,0 @@ -#ifndef XPD_H -#define XPD_H - -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "xdefs.h" -#include "xproto.h" - -#ifdef __KERNEL__ -#include -#include -#include -#include -#include -#ifdef XPP_DEBUGFS -#ifndef CONFIG_DEBUG_FS -#warning kernel does not include CONFIG_DEBUG_FS, canceling XPP_DEBUGFS support -#undef XPP_DEBUGFS -#else -#include -#endif -#endif -#endif /* __KERNEL__ */ - -#include - -#ifdef __KERNEL__ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) -/* also added in RHEL kernels with the OpenInfiniband backport: */ -#if LINUX_VERSION_CODE != KERNEL_VERSION(2,6,9) || !defined(DEFINE_SPINLOCK) -typedef unsigned gfp_t; /* Added in 2.6.14 */ -#endif -#endif - -/* - * FIXME: Kludge for 2.6.19 - * bool is now defined as a proper boolean type (gcc _Bool) - * but the command line parsing framework handles it as int. - */ -#define DEF_PARM_BOOL(name,init,perm,desc) \ - int name = init; \ - module_param(name, bool, perm); \ - MODULE_PARM_DESC(name, desc " [default " #init "]") - -#define DEF_PARM(type,name,init,perm,desc) \ - type name = init; \ - module_param(name, type, perm); \ - MODULE_PARM_DESC(name, desc " [default " #init "]") - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) -/* - * Old 2.6 kernels had module_param_array() macro that receive the counter - * by value. - */ -#define DEF_ARRAY(type,name,count,init,desc) \ - unsigned int name ## _num_values; \ - type name[count] = { [0 ... ((count)-1)] = (init) }; \ - module_param_array(name, type, name ## _num_values, 0644); \ - MODULE_PARM_DESC(name, desc " ( 1-" __MODULE_STRING(count) ")") -#else -#define DEF_ARRAY(type,name,count,init,desc) \ - unsigned int name ## _num_values; \ - type name[count] = {[0 ... ((count)-1)] = init}; \ - module_param_array(name, type, &name ## _num_values, 0644); \ - MODULE_PARM_DESC(name, desc " ( 1-" __MODULE_STRING(count) ")") -#endif -#endif // __KERNEL__ - -#define CARD_DESC_MAGIC 0xca9dde5c - -struct card_desc_struct { - struct list_head card_list; - u32 magic; - xbus_t *xbus; - byte rev; /* Revision number */ - byte type; /* LSB: 1 - to_phone, 0 - to_line */ - byte subtype; - struct xpd_addr xpd_addr; - xpp_line_t line_status; /* Initial line status (offhook) */ -}; - -typedef enum xpd_direction { - TO_PSTN = 0, - TO_PHONE = 1, -} xpd_direction_t; - -#ifdef __KERNEL__ - -/* - * XPD statistics counters - */ -enum { - XPD_N_PCM_READ, - XPD_N_PCM_WRITE, - XPD_N_RECV_ERRORS, -}; - -#define XPD_COUNTER(xpd, counter) ((xpd)->counters[XPD_N_ ## counter]) - -#define C_(x) [ XPD_N_ ## x ] = { #x } - -/* yucky, make an instance so we can size it... */ -static struct xpd_counters { - char *name; -} xpd_counters[] = { - C_(PCM_READ), - C_(PCM_WRITE), - C_(RECV_ERRORS), -}; - -#undef C_ - -#define XPD_COUNTER_MAX (sizeof(xpd_counters)/sizeof(xpd_counters[0])) - -/* - * An XPD is a single Xorcom Protocol Device - */ -struct xpd { - char xpdname[XPD_NAMELEN]; - struct zt_span span; - struct zt_chan *chans; - int channels; - xpd_type_t type; - const char *type_name; - byte subtype; - byte revision; /* Card revision */ - xpd_direction_t direction; /* TO_PHONE, TO_PSTN */ - xpp_line_t no_pcm; /* Temporary: disable PCM (for USB-1) */ - xpp_line_t offhook; /* Actual chip state: 0 - ONHOOK, 1 - OFHOOK */ - xpp_line_t cid_on; - xpp_line_t msg_waiting; /* Voice Mail Waiting Indication */ - xpp_line_t digital_outputs; /* 0 - no, 1 - yes */ - xpp_line_t digital_inputs; /* 0 - no, 1 - yes */ - xpp_line_t digital_signalling; /* BRI signalling channels */ - uint timing_priority; /* from 'span' directives in zapata.conf */ - - /* maintained by card drivers */ - uint pcm_len; /* allocation length of PCM packet (dynamic) */ - xpp_line_t wanted_pcm_mask; - xpp_line_t silence_pcm; /* inject silence during next tick */ - xpp_line_t mute_dtmf; - - bool ringing[CHANNELS_PERXPD]; - - xbus_t *xbus; /* The XBUS we are connected to */ - - spinlock_t lock; - atomic_t zt_registered; /* Am I fully registered with zaptel */ - atomic_t open_counter; /* Number of open channels */ - - int flags; - bool blink_mode; /* for visual identification */ -#define DEFAULT_LED_PERIOD (1000/8) /* in tick */ - -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *proc_xpd_dir; - struct proc_dir_entry *proc_xpd_summary; - struct proc_dir_entry *proc_xpd_ztregister; - struct proc_dir_entry *proc_xpd_blink; -#endif - - int counters[XPD_COUNTER_MAX]; - - const xproto_table_t *xproto; /* Card level protocol table */ - const xops_t *xops; /* Card level operations */ - void *priv; /* Card level private data */ - bool card_present; - reg_cmd_t requested_reply; - reg_cmd_t last_reply; - - unsigned long last_response; /* in jiffies */ - unsigned xbus_idx; /* index in xbus->xpds[] */ - struct xpd_addr addr; - struct list_head xpd_list; - unsigned int timer_count; - /* Echo cancelation */ - u_char ec_chunk1[CHANNELS_PERXPD][ZT_CHUNKSIZE]; - u_char ec_chunk2[CHANNELS_PERXPD][ZT_CHUNKSIZE]; -}; - -#define for_each_line(xpd,i) for((i) = 0; (i) < (xpd)->channels; (i)++) -#define IS_BRI(xpd) ((xpd)->type == XPD_TYPE_BRI_NT || (xpd)->type == XPD_TYPE_BRI_TE) -#define TICK_TOLERANCE 500 /* usec */ - -#ifdef DEBUG_SYNC_PARPORT -void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1); -#else -#define xbus_flip_bit(xbus, bitnum0, bitnum1) -#endif - -static inline void *my_kzalloc(size_t size, gfp_t flags) -{ - void *p; - - p = kmalloc(size, flags); - if(p) - memset(p, 0, size); - return p; -} - -#endif - -#endif /* XPD_H */ diff --git a/xpp/xpp_log.h b/xpp/xpp_log.h deleted file mode 100644 index 322b7f0..0000000 --- a/xpp/xpp_log.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef XPP_LOG_H -#define XPP_LOG_H -/* - * Written by Alexander Landau - * Copyright (C) 2004-2007, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifdef __KERNEL__ - -#include -#include - -#else - -/* This is to enable user-space programs to include this. */ - -#include "xdefs.h" - -#endif - -#define XPP_LOG_MAGIC 0x10583ADE - -struct log_global_header { - __u32 magic; - __u32 version; -} __attribute__((packed)); - -struct log_header { - __u32 len; - __u32 time; - __u8 xpd_num; - __u8 direction; -} __attribute__((packed)); - -#endif diff --git a/xpp/xpp_usb.c b/xpp/xpp_usb.c deleted file mode 100644 index 785e713..0000000 --- a/xpp/xpp_usb.c +++ /dev/null @@ -1,1085 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include /* for udelay */ -#include -#include -#include -#include -#include -#include -#include "xpd.h" -#include "xproto.h" -#include "xbus-core.h" -#include "xframe_queue.h" -#ifdef DEBUG -#include "card_fxs.h" -#include "card_fxo.h" -#endif -#include "parport_debug.h" - -static const char rcsid[] = "$Id$"; - -DEF_PARM(int, print_dbg, 0, 0644, "Print DBG statements"); /* must be before zap_debug.h */ -DEF_PARM(int, usb1, 0, 0644, "Allow using USB 1.1 interfaces"); -DEF_PARM(uint, tx_sluggish, 2000, 0644, "A sluggish transmit (usec)"); -DEF_PARM(uint, drop_pcm_after, 6, 0644, "Number of consecutive tx_sluggish to drop a PCM frame"); - -#include "zap_debug.h" - - -#define XUSB_PRINTK(level, xusb, fmt, ...) \ - printk(KERN_ ## level "%s-%s: xusb-%d (%s) [%s]: " fmt, #level, \ - THIS_MODULE->name, (xusb)->index, xusb->path, xusb->serial, ## __VA_ARGS__) - -#define XUSB_DBG(bits, xusb, fmt, ...) \ - ((void)((print_dbg & (DBG_ ## bits)) && XUSB_PRINTK(DEBUG, xusb, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))) -#define XUSB_ERR(xusb, fmt, ...) XUSB_PRINTK(ERR, xusb, fmt, ## __VA_ARGS__) -#define XUSB_NOTICE(xusb, fmt, ...) XUSB_PRINTK(NOTICE, xusb, fmt, ## __VA_ARGS__) -#define XUSB_INFO(xusb, fmt, ...) XUSB_PRINTK(INFO, xusb, fmt, ## __VA_ARGS__) - -/* FIXME: A flag that was deprecated at some point, and rather useless */ -/* anyway. Only used in the code or-ed to other flags */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) -# define URB_ASYNC_UNLINK 0 -#endif -/* Get a minor range for your devices from the usb maintainer */ -#define USB_SKEL_MINOR_BASE 192 - -#ifdef CONFIG_PROC_FS -#define PROC_USBXPP_SUMMARY "xpp_usb" -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -# warning "This module is tested only with 2.6 kernels" -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) -# undef USB_FIELDS_MISSING -#else -# define USB_FIELDS_MISSING - -# define USB_MAX_STRING 128 -# define USB_GET_STRING(udev,field,buf) \ - do { \ - if((udev)->descriptor.field) { \ - char tmp[USB_MAX_STRING]; \ - if(usb_string((udev), (udev)->descriptor.field, tmp, sizeof(tmp)) > 0) \ - snprintf((buf), USB_MAX_STRING, "%s", tmp); \ - } \ - } while(0); -# define USB_GET_IFACE_NAME(udev,iface,buf) \ - do { \ - if((iface)->desc.iInterface) { \ - char tmp[USB_MAX_STRING]; \ - if(usb_string((udev), (iface)->desc.iInterface, tmp, sizeof(tmp)) > 0) \ - snprintf((buf), USB_MAX_STRING, "%s", tmp); \ - } \ - } while(0); -#endif - -#ifdef DEBUG_PCM_TIMING -static cycles_t stamp_last_pcm_read; -static cycles_t accumulate_diff; -#endif - -struct xusb_model_info; - -struct xusb_endpoint { - int ep_addr; - int max_size; - usb_complete_t callback; -}; - -enum xusb_dir { - XUSB_RECV = 0, - XUSB_SEND = 1, -}; - -static int xframe_send_pcm(xbus_t *xbus, xframe_t *xframe); -static int xframe_send_cmd(xbus_t *xbus, xframe_t *xframe); -static xframe_t *alloc_xframe(xbus_t *xbus, gfp_t flags); -static void free_xframe(xbus_t *xbus, xframe_t *frm); - -static struct xbus_ops xusb_ops = { - .xframe_send_pcm = xframe_send_pcm, - .xframe_send_cmd = xframe_send_cmd, - .alloc_xframe = alloc_xframe, - .free_xframe = free_xframe, -}; - -enum { - XUSB_N_RX_FRAMES, - XUSB_N_TX_FRAMES, - XUSB_N_RX_ERRORS, - XUSB_N_TX_ERRORS, - XUSB_N_RCV_ZERO_LEN, -}; - -#define XUSB_COUNTER(xusb, counter) ((xusb)->counters[XUSB_N_ ## counter]) - -#define C_(x) [ XUSB_N_ ## x ] = { #x } - -static struct xusb_counters { - char *name; -} xusb_counters[] = { - C_(RX_FRAMES), - C_(TX_FRAMES), - C_(RX_ERRORS), - C_(TX_ERRORS), - C_(RCV_ZERO_LEN), -}; - -#undef C_ - -#define XUSB_COUNTER_MAX ARRAY_SIZE(xusb_counters) - -#define MAX_PENDING_WRITES 100 - -static KMEM_CACHE_T *xusb_cache = NULL; - -typedef struct xusb xusb_t; - -/* - * A uframe is our low level representation of a frame. - * - * It contains the metadata for the usb stack (a urb) - * and the metadata for the xbus-core (an xframe) - * as well as pointing to the data (transfer_buffer, transfer_buffer_length) - * directionality (send/receive) and ownership (xusb). - */ -struct uframe { - unsigned long uframe_magic; -#define UFRAME_MAGIC 654321L - struct urb urb; - xframe_t xframe; - size_t transfer_buffer_length; - void *transfer_buffer; /* max XFRAME_DATASIZE */ - xusb_t *xusb; -}; - -#define urb_to_uframe(urb) container_of(urb, struct uframe, urb) -#define xframe_to_uframe(xframe) container_of(xframe, struct uframe, xframe) -#define xusb_of(xbus) ((xusb_t *)((xbus)->transport.priv)) - -#define USEC_BUCKET 100 /* usec */ -#define NUM_BUCKETS 15 -#define BUCKET_START (500/USEC_BUCKET) /* skip uninteresting */ - -/* - * USB XPP Bus (a USB Device) - */ -struct xusb { - uint xbus_num; - struct usb_device *udev; /* save off the usb device pointer */ - struct usb_interface *interface; /* the interface for this device */ - unsigned char minor; /* the starting minor number for this device */ - uint index; - char path[XBUS_DESCLEN]; /* a unique path */ - - struct xusb_model_info *model_info; - struct xusb_endpoint endpoints[2]; /* RECV/SEND endpoints */ - - int present; /* if the device is not disconnected */ - atomic_t pending_writes; /* submited but not out yet */ - struct semaphore sem; /* locks this structure */ - int counters[XUSB_COUNTER_MAX]; - - /* metrics */ - struct timeval last_tx; - unsigned int max_tx_delay; - uint usb_tx_delay[NUM_BUCKETS]; - uint sluggish_debounce; - bool drop_next_pcm; /* due to sluggishness */ - atomic_t pcm_tx_drops; - atomic_t usb_sluggish_count; - -#ifdef USB_FIELDS_MISSING - /* storage for missing strings in old kernels */ - char manufacturer[USB_MAX_STRING]; - char product[USB_MAX_STRING]; - char serial[USB_MAX_STRING]; - char interface_name[USB_MAX_STRING]; -#else - const char *manufacturer; - const char *product; - const char *serial; - const char *interface_name; -#endif - -}; - -static spinlock_t xusb_lock = SPIN_LOCK_UNLOCKED; -static xusb_t *xusb_array[MAX_BUSES] = {}; -static unsigned bus_count = 0; - - -/* prevent races between open() and disconnect() */ -static DECLARE_MUTEX (disconnect_sem); - -/* - * AsteriskNow kernel has backported the "lean" callback from 2.6.20 - * to 2.6.19 without any macro to notify of this fact -- how lovely. - * Debian-Etch and Centos5 are using 2.6.18 for now (lucky for us). - * Fedora6 jumped from 2.6.18 to 2.6.20. So far luck is on our side ;-) - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -#define USB_PASS_CB(u) struct urb *u, struct pt_regs *regs -#else -#define USB_PASS_CB(u) struct urb *u -#endif - -static void xpp_send_callback(USB_PASS_CB(urb)); -static void xpp_receive_callback(USB_PASS_CB(urb)); -static int xusb_probe (struct usb_interface *interface, const struct usb_device_id *id); -static void xusb_disconnect (struct usb_interface *interface); -static int xusb_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data); - -/*------------------------------------------------------------------*/ - -/* - * Updates the urb+xframe metadata from the uframe information. - */ -static void uframe_recompute(struct uframe *uframe, enum xusb_dir dir) -{ - struct urb *urb = &uframe->urb; - xusb_t *xusb = uframe->xusb; - struct usb_device *udev = xusb->udev; - struct xusb_endpoint *xusb_ep = &xusb->endpoints[dir]; - unsigned int ep_addr = xusb_ep->ep_addr; - usb_complete_t urb_cb = xusb_ep->callback; - unsigned int epnum = ep_addr & USB_ENDPOINT_NUMBER_MASK; - int pipe = usb_pipein(ep_addr) - ? usb_rcvbulkpipe(udev, epnum) - : usb_sndbulkpipe(udev, epnum); - - BUG_ON(uframe->uframe_magic != UFRAME_MAGIC); - usb_fill_bulk_urb(urb, udev, pipe, uframe->transfer_buffer, uframe->transfer_buffer_length, urb_cb, uframe); - urb->transfer_flags = (URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK); -} - -static xframe_t *alloc_xframe(xbus_t *xbus, gfp_t gfp_flags) -{ - struct uframe *uframe; - xusb_t *xusb; - void *p; - int size; - static int rate_limit; - - BUG_ON(!xbus); - xusb = xusb_of(xbus); - BUG_ON(!xusb); - if(!xusb->present) { - if((rate_limit++ % 1003) == 0) - XUSB_ERR(xusb, - "abort allocations during device disconnect (%d)\n", rate_limit); - return NULL; - } - size = min(xusb->endpoints[XUSB_SEND].max_size, xusb->endpoints[XUSB_RECV].max_size); - uframe = kmem_cache_alloc(xusb_cache, gfp_flags); - if(!uframe) { - if((rate_limit++ % 1003) == 0) - XUSB_ERR(xusb, "frame allocation failed (%d)\n", rate_limit); - return NULL; - } - usb_init_urb(&uframe->urb); - p = usb_buffer_alloc(xusb->udev, size, gfp_flags, &uframe->urb.transfer_dma); - if(!p) { - if((rate_limit++ % 1003) == 0) - XUSB_ERR(xusb, "buffer allocation failed (%d)\n", rate_limit); - kfree(uframe); - return NULL; - } - uframe->uframe_magic = UFRAME_MAGIC; - uframe->transfer_buffer_length = size; - uframe->transfer_buffer = p; - uframe->xusb = xusb; - xframe_init(xbus, &uframe->xframe, uframe->transfer_buffer, uframe->transfer_buffer_length, uframe); - return &uframe->xframe; -} - -void free_xframe(xbus_t *xbus, xframe_t *xframe) -{ - struct uframe *uframe = xframe_to_uframe(xframe); - struct urb *urb = &uframe->urb; - - BUG_ON(xbus->transport.priv != uframe->xusb); - //XUSB_INFO(uframe->xusb, "frame_free\n"); - usb_buffer_free(urb->dev, uframe->transfer_buffer_length, - urb->transfer_buffer, - urb->transfer_dma); - memset(uframe, 0, sizeof(*uframe)); - kmem_cache_free(xusb_cache, uframe); -} - -/*------------------------------------------------------------------*/ - -/* - * Actuall frame sending -- both PCM and commands. - */ -static int do_send_xframe(xbus_t *xbus, xframe_t *xframe) -{ - struct urb *urb; - xusb_t *xusb; - int ret = 0; - struct uframe *uframe; - static int rate_limit; - - BUG_ON(!xframe); - BUG_ON(xframe->xframe_magic != XFRAME_MAGIC); - xusb = xusb_of(xbus); - BUG_ON(!xusb); - if(!xusb->present) { - if((rate_limit++ % 1003) == 0) - XUSB_ERR(xusb, - "abort do_send_xframe during device disconnect (%d)\n", rate_limit); - ret = -ENODEV; - goto failure; - } - /* - * If something really bad happend, do not overflow the USB stack - */ - if(atomic_read(&xusb->pending_writes) > MAX_PENDING_WRITES) { - static int rate_limit; - - if((rate_limit++ % 5000) == 0) - XUSB_ERR(xusb, - "USB device is totaly stuck. Dropping packets (#%d).\n", - rate_limit); - ret = -ENODEV; - goto failure; - } - uframe = xframe->priv; - BUG_ON(!uframe); - BUG_ON(uframe->uframe_magic != UFRAME_MAGIC); - uframe_recompute(uframe, XUSB_SEND); - urb = &uframe->urb; - BUG_ON(!urb); - /* update urb length */ - urb->transfer_buffer_length = XFRAME_LEN(xframe); - do_gettimeofday(&xframe->tv_submitted); - ret = usb_submit_urb(urb, GFP_ATOMIC); - if(ret < 0) { - static int rate_limit; - - if((rate_limit++ % 1000) < 5) - XUSB_ERR(xusb, "failed submit_urb: %d\n", ret); - ret = -EBADF; - goto failure; - } -// if (print_dbg) -// dump_xframe("USB_FRAME_SEND", xbus, xframe); - atomic_inc(&xusb->pending_writes); - return 0; -failure: - XUSB_COUNTER(xusb, TX_ERRORS)++; - FREE_SEND_XFRAME(xbus, xframe); /* return to pool */ - return ret; -} - -/* - * PCM wrapper - */ -static int xframe_send_pcm(xbus_t *xbus, xframe_t *xframe) -{ - xusb_t *xusb; - - BUG_ON(!xbus); - BUG_ON(!xframe); - xusb = xusb_of(xbus); - BUG_ON(!xusb); - if(xusb->drop_next_pcm) { - FREE_SEND_XFRAME(xbus, xframe); /* return to pool */ - xusb->drop_next_pcm = 0; - return -EIO; - } - return do_send_xframe(xbus, xframe); -} - -/* - * commands wrapper - */ -static int xframe_send_cmd(xbus_t *xbus, xframe_t *xframe) -{ - BUG_ON(!xbus); - BUG_ON(!xframe); - //XBUS_INFO(xbus, "%s:\n", __FUNCTION__); - return do_send_xframe(xbus, xframe); -} - -/* - * get a urb from the receive_pool and submit it on the read endpoint. - */ -static bool xusb_listen(xusb_t *xusb) -{ - xbus_t *xbus = get_xbus(xusb->xbus_num); - xframe_t *xframe; - struct uframe *uframe; - int ret = 0; - - BUG_ON(!xbus); - xframe = ALLOC_RECV_XFRAME(xbus); - if(!xframe) { - XBUS_ERR(xbus, "Empty receive_pool\n"); - goto out; - } - uframe = xframe_to_uframe(xframe); - uframe_recompute(uframe, XUSB_RECV); - ret = usb_submit_urb(&uframe->urb, GFP_ATOMIC); - if(ret < 0) { - XBUS_ERR(xbus, "Failed to submit a receive urb\n"); - FREE_RECV_XFRAME(xbus, xframe); - goto out; - } - ret = 1; -out: - put_xbus(xbus); - return ret; -} - -/*------------------------- XPP USB Bus Handling -------------------*/ - -enum XUSB_MODELS { - MODEL_FPGA_XPD -}; - -static const struct xusb_model_info { - const char *desc; - int iface_num; - struct xusb_endpoint in; - struct xusb_endpoint out; -} model_table[] = { - [MODEL_FPGA_XPD] { - .iface_num = 0, - .in = { .ep_addr = 0x86 }, - .out = { .ep_addr = 0x02 }, - .desc = "FPGA_XPD" - }, -}; - -/* table of devices that work with this driver */ -static const struct usb_device_id xusb_table [] = { - { USB_DEVICE(0xE4E4, 0x1132), .driver_info=(kernel_ulong_t)&model_table[MODEL_FPGA_XPD] }, // FPGA_FXS - { USB_DEVICE(0xE4E4, 0x1142), .driver_info=(kernel_ulong_t)&model_table[MODEL_FPGA_XPD] }, // FPGA_1141 - { USB_DEVICE(0xE4E4, 0x1152), .driver_info=(kernel_ulong_t)&model_table[MODEL_FPGA_XPD] }, // FPGA_1151 - { USB_DEVICE(0xE4E4, 0x1162), .driver_info=(kernel_ulong_t)&model_table[MODEL_FPGA_XPD] }, // FPGA_1161 - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, xusb_table); - - -/* usb specific object needed to register this driver with the usb subsystem */ -static struct usb_driver xusb_driver = { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) - .owner = THIS_MODULE, -#endif - .name = "xpp_usb", - .probe = xusb_probe, - .disconnect = xusb_disconnect, - .id_table = xusb_table, -}; - -/* - * File operations needed when we register this driver. - * This assumes that this driver NEEDS file operations, - * of course, which means that the driver is expected - * to have a node in the /dev directory. If the USB - * device were for a network interface then the driver - * would use "struct net_driver" instead, and a serial - * device would use "struct tty_driver". - */ -static struct file_operations xusb_fops = { - /* - * The owner field is part of the module-locking - * mechanism. The idea is that the kernel knows - * which module to increment the use-counter of - * BEFORE it calls the device's open() function. - * This also means that the kernel can decrement - * the use-counter again before calling release() - * or should the open() function fail. - */ - .owner = THIS_MODULE, -}; - -/* - * usb class driver info in order to get a minor number from the usb core, - * and to have the device registered with devfs and the driver core - */ -static struct usb_class_driver xusb_class = { - .name = "usb/xpp_usb%d", - .fops = &xusb_fops, -/* FIXME: The sysfs class interfase seems to have chaged around here */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) - .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, -#endif - .minor_base = USB_SKEL_MINOR_BASE, -}; - -/* - * Check that an endpoint's wMaxPacketSize attribute is 512. This - * indicates that it is a USB2's high speed end point. - * - * If it is 64, it means we have a USB1 controller. By default we do not - * support it and just fail the probe of the device. However if the user - * has set usb1=1, we continue and just put a notice. - * - * Returns true if all OK, false otherwise. - */ -static int check_usb1(struct usb_endpoint_descriptor *endpoint) -{ - const char *msg = (usb_pipein(endpoint->bEndpointAddress))?"input":"output"; - - if(endpoint->wMaxPacketSize >= sizeof(xpacket_t)) - return 1; - - if(usb1) { - NOTICE("USB1 endpoint detected: USB %s endpoint 0x%X support only wMaxPacketSize=%d.\n", - msg, endpoint->bEndpointAddress, endpoint->wMaxPacketSize); - return 1; - } - NOTICE("USB1 endpoint detected. Device disabled. To enable: usb1=1, and read docs. (%s, endpoint %d, size %d).\n", - msg, endpoint->bEndpointAddress, endpoint->wMaxPacketSize); - return 0; -} - -/* - * set up the endpoint information - * check out the endpoints - * FIXME: Should be simplified (above 2.6.10) to use usb_dev->ep_in[0..16] and usb_dev->ep_out[0..16] - */ -static int set_endpoints(xusb_t *xusb, struct usb_host_interface *iface_desc, struct xusb_model_info *model_info) -{ - struct usb_endpoint_descriptor *endpoint; - struct xusb_endpoint *xusb_ep; - int ep_addr; - int i; - -#define BULK_ENDPOINT(ep) (((ep)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) - - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - ep_addr = endpoint->bEndpointAddress; - - if(!BULK_ENDPOINT(endpoint)) { - DBG(DEVICES, "endpoint 0x%x is not bulk: mbAttributes=0x%X\n", - ep_addr, endpoint->bmAttributes); - continue; - } - if(usb_pipein(ep_addr)) { // Input - if(ep_addr == model_info->in.ep_addr) { - if (!check_usb1(endpoint)) - return 0; - xusb_ep = &xusb->endpoints[XUSB_RECV]; - xusb_ep->ep_addr = ep_addr; - xusb_ep->max_size = endpoint->wMaxPacketSize; - xusb_ep->callback = xpp_receive_callback; - } - } else { // Output - if(ep_addr == model_info->out.ep_addr) { - if (!check_usb1(endpoint)) - return 0; - xusb_ep = &xusb->endpoints[XUSB_SEND]; - xusb_ep->ep_addr = ep_addr; - xusb_ep->max_size = endpoint->wMaxPacketSize; - xusb_ep->callback = xpp_send_callback; - } - } - } - if (!xusb->endpoints[XUSB_RECV].ep_addr || !xusb->endpoints[XUSB_SEND].ep_addr) { - XUSB_ERR(xusb, "Couldn't find bulk-in or bulk-out endpoints\n"); - return 0; - } - DBG(DEVICES, "in=0x%02X out=0x%02X\n", xusb->endpoints[XUSB_RECV].ep_addr, xusb->endpoints[XUSB_SEND].ep_addr); - return 1; -} - -/** - * xusb_probe - * - * Called by the usb core when a new device is connected that it thinks - * this driver might be interested in. - */ -static int xusb_probe(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct usb_host_interface *iface_desc = usb_altnum_to_altsetting(interface, 0); - xusb_t *xusb = NULL; - struct xusb_model_info *model_info = (struct xusb_model_info*)id->driver_info; - struct proc_dir_entry *procsummary = NULL; - xbus_t *xbus = NULL; - unsigned long flags; - int retval = -ENOMEM; - int i; - - DBG(DEVICES, "New XUSB device MODEL=%s\n", model_info->desc); - if(iface_desc->desc.bInterfaceNumber != model_info->iface_num) { - DBG(DEVICES, "Skip interface #%d != #%d\n", - iface_desc->desc.bInterfaceNumber, model_info->iface_num); - return -ENODEV; - } - - /* The USB stack before 2.6.10 seems to be a bit shoddy. It seems that when being called - * from the probe we may already have the lock to udev (the Usb DEVice). Thus we call - * the internal __usb_reset_device instead. */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - if((retval = __usb_reset_device(udev)) < 0) { -#else - if((retval = usb_reset_device(udev)) < 0) { -#endif - ERR("usb_reset_device failed: %d\n", retval); - goto probe_failed; - } - if (!model_info) { - ERR("Missing endpoint setup for this device %d:%d\n", - udev->descriptor.idVendor,udev->descriptor.idProduct); - retval = -ENODEV; - goto probe_failed; - } - - /* allocate memory for our device state and initialize it */ - xusb = KZALLOC(sizeof(xusb_t), GFP_KERNEL); - if (xusb == NULL) { - ERR("xpp_usb: Unable to allocate new xpp usb bus\n"); - retval = -ENOMEM; - goto probe_failed; - } - init_MUTEX (&xusb->sem); - atomic_set(&xusb->pending_writes, 0); - atomic_set(&xusb->pcm_tx_drops, 0); - atomic_set(&xusb->usb_sluggish_count, 0); - xusb->udev = udev; - xusb->interface = interface; - xusb->model_info = model_info; - - if(!set_endpoints(xusb, iface_desc, model_info)) { - retval = -ENODEV; - goto probe_failed; - } -#ifndef USB_FIELDS_MISSING - xusb->serial = udev->serial; - xusb->manufacturer = udev->manufacturer; - xusb->product = udev->product; - xusb->interface_name = iface_desc->string; -#else - USB_GET_STRING(udev, iSerialNumber, xusb->serial); - USB_GET_STRING(udev, iManufacturer, xusb->manufacturer); - USB_GET_STRING(udev, iProduct, xusb->product); - USB_GET_IFACE_NAME(udev, iface_desc, xusb->interface_name); -#endif - INFO("XUSB: %s -- %s -- %s\n", - xusb->manufacturer, xusb->product, xusb->interface_name); - - /* allow device read, write and ioctl */ - xusb->present = 1; - - /* we can register the device now, as it is ready */ - usb_set_intfdata (interface, xusb); - retval = usb_register_dev (interface, &xusb_class); - if (retval) { - /* something prevented us from registering this driver */ - ERR ("Not able to get a minor for this device.\n"); - goto probe_failed; - } - - xusb->minor = interface->minor; - - /* let the user know what node this device is now attached to */ - DBG(DEVICES, "USB XPP device now attached to minor %d\n", xusb->minor); - xbus = xbus_new(&xusb_ops, min(xusb->endpoints[XUSB_SEND].max_size, xusb->endpoints[XUSB_RECV].max_size), xusb); - if(!xbus) { - retval = -ENOMEM; - goto probe_failed; - } - spin_lock_irqsave(&xusb_lock, flags); - for(i = 0; i < MAX_BUSES; i++) { - if(xusb_array[i] == NULL) - break; - } - spin_unlock_irqrestore(&xusb_lock, flags); - if(i >= MAX_BUSES) { - ERR("xpp_usb: Too many XPP USB buses\n"); - retval = -ENOMEM; - goto probe_failed; - } - usb_make_path(udev, xusb->path, XBUS_DESCLEN); // May trunacte... ignore - snprintf(xbus->busdesc, XBUS_DESCLEN, "%s", xusb->path); - if(xusb->serial && xusb->serial[0]) - snprintf(xbus->label, LABEL_SIZE, "usb:%s", xusb->serial); - xusb->index = i; - xusb_array[i] = xusb; - XUSB_DBG(DEVICES, xusb, "GOT XPP USB BUS: %s\n", xbus->busdesc); - -#ifdef CONFIG_PROC_FS - DBG(PROC, "Creating proc entry " PROC_USBXPP_SUMMARY " in bus proc dir.\n"); - procsummary = create_proc_read_entry(PROC_USBXPP_SUMMARY, 0444, xbus->proc_xbus_dir, - xusb_read_proc, xusb); - if (!procsummary) { - XBUS_ERR(xbus, "Failed to create proc file '%s'\n", PROC_USBXPP_SUMMARY); - // FIXME: better error handling - retval = -EIO; - goto probe_failed; - } - procsummary->owner = THIS_MODULE; -#endif - bus_count++; - xusb->xbus_num = xbus->num; - xusb_listen(xusb); - xbus_activate(xbus); - return retval; -probe_failed: - ERR("Failed to initialize xpp usb bus: %d\n", retval); - usb_set_intfdata (interface, NULL); - if(xusb) { - if(xusb->minor) // passed registration phase - usb_deregister_dev(interface, &xusb_class); - kfree(xusb); - } - if(xbus) { - if(procsummary) { - XBUS_DBG(PROC, xbus, "Remove proc_entry: " PROC_USBXPP_SUMMARY "\n"); - remove_proc_entry(PROC_USBXPP_SUMMARY, xbus->proc_xbus_dir); - procsummary = NULL; - } - xbus_disconnect(xbus); // Blocking until fully deactivated! - } - return retval; -} - -/** - * xusb_disconnect - * - * Called by the usb core when the device is removed from the system. - * - * This routine guarantees that the driver will not submit any more urbs - * by clearing dev->udev. It is also supposed to terminate any currently - * active urbs. Unfortunately, usb_bulk_msg(), used in xusb_read(), does - * not provide any way to do this. But at least we can cancel an active - * write. - */ -static void xusb_disconnect(struct usb_interface *interface) -{ - xusb_t *xusb; - xbus_t *xbus; - int minor; - int i; - - DBG(DEVICES, "CALLED\n"); - /* prevent races with open() */ - down (&disconnect_sem); - - xusb = usb_get_intfdata (interface); - xbus = get_xbus(xusb->xbus_num); - - /* find our xusb */ - for(i = 0; i < MAX_BUSES; i++) { - if(xusb_array[i] == xusb) - break; - } - BUG_ON(i >= MAX_BUSES); - xusb_array[i] = NULL; - -#ifdef CONFIG_PROC_FS - if(xbus->proc_xbus_dir) { - XBUS_DBG(PROC, xbus, "Remove proc_entry: " PROC_USBXPP_SUMMARY "\n"); - remove_proc_entry(PROC_USBXPP_SUMMARY, xbus->proc_xbus_dir); - } -#endif - /* - * put_xbus() would be called during xbus_disconnect() - */ - xbus_disconnect(xbus); // Blocking until fully deactivated! - xusb->present = 0; - usb_set_intfdata (interface, NULL); - - down (&xusb->sem); - minor = xusb->minor; - - /* give back our minor */ - usb_deregister_dev (interface, &xusb_class); - - up (&xusb->sem); - DBG(DEVICES, "Semaphore released\n"); - kfree(xusb); - - up (&disconnect_sem); - XUSB_INFO(xusb, "now disconnected\n"); -} - -static void xpp_send_callback(USB_PASS_CB(urb)) -{ - struct uframe *uframe = urb_to_uframe(urb); - xframe_t *xframe = &uframe->xframe; - xusb_t *xusb = uframe->xusb; - xbus_t *xbus = get_xbus(xusb->xbus_num); - struct timeval now; - long usec; - int writes = atomic_read(&xusb->pending_writes); - int i; - - if(!xbus) { - XUSB_ERR(xusb, "Sent URB does not belong to a valid xbus anymore...\n"); - return; - } - //flip_parport_bit(6); - atomic_dec(&xusb->pending_writes); - do_gettimeofday(&now); - xusb->last_tx = xframe->tv_submitted; - usec = usec_diff(&now, &xframe->tv_submitted); - if(usec > xusb->max_tx_delay) - xusb->max_tx_delay = usec; - i = usec / USEC_BUCKET; - if(i >= NUM_BUCKETS) - i = NUM_BUCKETS - 1; - xusb->usb_tx_delay[i]++; - if(unlikely(usec > tx_sluggish)) { - atomic_inc(&xusb->usb_sluggish_count); - if(xusb->sluggish_debounce++ > drop_pcm_after) { - static int rate_limit; - - if((rate_limit++ % 1003) == 500) /* skip first messages */ - XUSB_NOTICE(xusb, - "Sluggish USB. Dropping next PCM frame (pending_writes=%d)\n", - writes); - atomic_inc(&xusb->pcm_tx_drops); - xusb->drop_next_pcm = 1; - xusb->sluggish_debounce = 0; - } - } else - xusb->sluggish_debounce = 0; - /* sync/async unlink faults aren't errors */ - if (urb->status && !(urb->status == -ENOENT || urb->status == -ECONNRESET)) { - static int rate_limit; - if((rate_limit++ % 1000) < 10) - XUSB_ERR(xusb, - "nonzero write bulk status received: %d (pending_writes=%d)\n", - urb->status, writes); - XUSB_COUNTER(xusb, TX_ERRORS)++; - } else - XUSB_COUNTER(xusb, TX_FRAMES)++; - FREE_SEND_XFRAME(xbus, xframe); - if(!xusb->present) - XUSB_ERR(xusb, "A urb from non-connected device?\n"); - put_xbus(xbus); -} - -static void xpp_receive_callback(USB_PASS_CB(urb)) -{ - struct uframe *uframe = urb_to_uframe(urb); - xframe_t *xframe = &uframe->xframe; - xusb_t *xusb = uframe->xusb; - xbus_t *xbus = get_xbus(xusb->xbus_num); - size_t size; - bool do_resubmit = 1; - bool is_inuse = 0; - - //flip_parport_bit(7); - if(!xbus) { - XUSB_ERR(xusb, "Received URB does not belong to a valid xbus anymore...\n"); - return; - } - if (urb->status) { - DBG(GENERAL, "nonzero read bulk status received: %d\n", urb->status); - XUSB_COUNTER(xusb, RX_ERRORS)++; - goto err; - } - if(!XBUS_GET(xbus)) { - XUSB_ERR(xusb, "Dropping urb. Is shutting down.\n"); - do_resubmit = 0; - goto err; - } - is_inuse = 1; - if(!xusb->present) { - XUSB_ERR(xusb, "A packet from non-connected device?\n"); - do_resubmit = 0; - goto err; - } - size = urb->actual_length; - if(size == 0) { - static int rate_limit; - - if((rate_limit++ % 5003) == 0) - XUSB_NOTICE(xusb, "Received a zero length URBs (%d)\n", rate_limit); - XUSB_COUNTER(xusb, RCV_ZERO_LEN)++; - goto err; - } - atomic_set(&xframe->frame_len, size); - do_gettimeofday(&xframe->tv_received); - -// if (print_dbg) -// dump_xframe("USB_FRAME_RECEIVE", xbus, xframe); - XUSB_COUNTER(xusb, RX_FRAMES)++; - /* Send UP */ - xbus_receive_xframe(xbus, xframe); -end: - if(is_inuse) - XBUS_PUT(xbus); - if(do_resubmit) - xusb_listen(xusb); - put_xbus(xbus); - return; -err: - FREE_RECV_XFRAME(xbus, xframe); - goto end; -} - - -/*------------------------- Initialization -------------------------*/ - -static void xpp_usb_cleanup(void) -{ - if(xusb_cache) { - kmem_cache_destroy(xusb_cache); - xusb_cache = NULL; - } -} - -int __init xpp_usb_init(void) -{ - int ret; - //xusb_t *xusb; - - INFO("revision %s [sizeof(uframe)=%d]\n", XPP_VERSION, sizeof(struct uframe)); - xusb_cache = kmem_cache_create("xusb_cache", - sizeof(xframe_t) + XFRAME_DATASIZE, - 0, 0, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) - NULL, -#endif - NULL); - if(!xusb_cache) { - ret = -ENOMEM; - goto failure; - } - - /* register this driver with the USB subsystem */ - ret = usb_register(&xusb_driver); - if (ret) { - ERR("usb_register failed. Error number %d\n", ret); - goto failure; - } - return 0; -failure: - xpp_usb_cleanup(); - return ret; -} - - -void __exit xpp_usb_shutdown(void) -{ - DBG(GENERAL, "\n"); - /* deregister this driver with the USB subsystem */ - usb_deregister(&xusb_driver); - xpp_usb_cleanup(); -} - - - -#ifdef CONFIG_PROC_FS - -static int xusb_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - unsigned long flags; - int i; - //unsigned long stamp = jiffies; - xusb_t *xusb = data; - uint usb_tx_delay[NUM_BUCKETS]; - const int mark_limit = tx_sluggish/USEC_BUCKET; - - if(!xusb) - goto out; - // TODO: probably needs a per-xusb lock: - spin_lock_irqsave(&xusb_lock, flags); - len += sprintf(page + len, "Device: %03d/%03d\n", - xusb->udev->bus->busnum, - xusb->udev->devnum - ); - len += sprintf(page + len, "USB: manufacturer=%s\n", xusb->manufacturer); - len += sprintf(page + len, "USB: product=%s\n", xusb->product); - len += sprintf(page + len, "USB: serial=%s\n", xusb->serial); - len += sprintf(page + len, "Minor: %d\nModel Info: %s\n", - xusb->minor, xusb->model_info->desc); - len += sprintf(page + len, "Endpoints:\n" - "\tIn: 0x%02X - Size: %d)\n" - "\tOut: 0x%02X - Size: %d)\n", - xusb->endpoints[XUSB_RECV].ep_addr, - xusb->endpoints[XUSB_RECV].max_size, - xusb->endpoints[XUSB_SEND].ep_addr, - xusb->endpoints[XUSB_SEND].max_size - ); - len += sprintf(page + len, "\npending_writes=%d\n", atomic_read(&xusb->pending_writes)); - len += sprintf(page + len, "max_tx_delay=%d\n", xusb->max_tx_delay); - xusb->max_tx_delay = 0; -#ifdef DEBUG_PCM_TIMING - len += sprintf(page + len, "\nstamp_last_pcm_read=%lld accumulate_diff=%lld\n", stamp_last_pcm_read, accumulate_diff); -#endif - memcpy(usb_tx_delay, xusb->usb_tx_delay, sizeof(usb_tx_delay)); - len += sprintf(page + len, "usb_tx_delay[%d,%d,%d]: ", - USEC_BUCKET, BUCKET_START, NUM_BUCKETS); - for(i = BUCKET_START; i < NUM_BUCKETS; i++) { - len += sprintf(page + len, "%6d ", - usb_tx_delay[i]); - if(i == mark_limit) - len += sprintf(page + len, "| "); - } - len += sprintf(page + len, "\nPCM_TX_DROPS: %5d (sluggish: %d)\n", - atomic_read(&xusb->pcm_tx_drops), - atomic_read(&xusb->usb_sluggish_count) - ); - len += sprintf(page + len, "\nCOUNTERS:\n"); - for(i = 0; i < XUSB_COUNTER_MAX; i++) { - len += sprintf(page + len, "\t%-15s = %d\n", xusb_counters[i].name, xusb->counters[i]); - } -#if 0 - len += sprintf(page + len, "<-- len=%d\n", len); -#endif - spin_unlock_irqrestore(&xusb_lock, flags); -out: - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; - -} - -#endif - - - -MODULE_DESCRIPTION("XPP USB Transport Driver"); -MODULE_AUTHOR("Oron Peled "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(XPP_VERSION); - -module_init(xpp_usb_init); -module_exit(xpp_usb_shutdown); diff --git a/xpp/xpp_zap.c b/xpp/xpp_zap.c deleted file mode 100644 index edaedf9..0000000 --- a/xpp/xpp_zap.c +++ /dev/null @@ -1,1049 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2004, Xorcom - * - * Derived from ztdummy - * - * Copyright (C) 2002, Hermes Softlab - * Copyright (C) 2004, Digium, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -# warning "This module is tested only with 2.6 kernels" -#endif - -#include -#include -#include -#include -#include -#include /* for udelay */ -#include -#include -#include -#include "xbus-core.h" -#include "xproto.h" -#include "xpp_zap.h" -#include "parport_debug.h" - -static const char rcsid[] = "$Id$"; - -#ifdef CONFIG_PROC_FS -struct proc_dir_entry *xpp_proc_toplevel = NULL; -#define PROC_DIR "xpp" -#define PROC_XPD_ZTREGISTER "zt_registration" -#define PROC_XPD_BLINK "blink" -#define PROC_XPD_SUMMARY "summary" -#endif - -#define MAX_QUEUE_LEN 10000 -#define DELAY_UNTIL_DIALTONE 3000 - -DEF_PARM(int, print_dbg, 0, 0644, "Print DBG statements"); -DEF_PARM_BOOL(zap_autoreg, 0, 0644, "Register spans automatically (1) or not (0)"); -DEF_PARM_BOOL(prefmaster, 0, 0644, "Do we want to be zaptel preferred sync master"); -// DEF_ARRAY(int, pcmtx, 4, 0, "Forced PCM values to transmit"); - -#include "zap_debug.h" - -#ifdef DEBUG_SYNC_PARPORT -/* - * Use parallel port to sample our PCM sync and diagnose quality and - * potential problems. A logic analizer or a scope should be connected - * to the data bits of the parallel port. - * - * Array parameter: Choose the two xbuses Id's to sample. - * This can be changed on runtime as well. Example: - * echo "3,5" > /sys/module/xpp/parameters/parport_xbuses - */ -static int parport_xbuses[2] = { 0, 1 }; -unsigned int parport_xbuses_num_values; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) -module_param_array(parport_xbuses, int, &parport_xbuses_num_values, 0577); -#else -module_param_array(parport_xbuses, int, parport_xbuses_num_values, 0577); -#endif -MODULE_PARM_DESC(parport_xbuses, "Id's of xbuses to sample (1-2)"); - -/* - * Flip a single bit in the parallel port: - * - The bit number is either bitnum0 or bitnum1 - * - Bit is selected by xbus number from parport_xbuses[] - */ -void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1) -{ - int num = xbus->num; - - if(num == parport_xbuses[0]) - flip_parport_bit(bitnum0); - if(num == parport_xbuses[1]) - flip_parport_bit(bitnum1); -} -EXPORT_SYMBOL(xbus_flip_bit); -#endif - -static atomic_t num_registered_spans = ATOMIC_INIT(0); - -int total_registered_spans(void) -{ - return atomic_read(&num_registered_spans); -} - -static int zaptel_register_xpd(xpd_t *xpd); -static int zaptel_unregister_xpd(xpd_t *xpd); -static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data); -static int proc_xpd_ztregister_read(char *page, char **start, off_t off, int count, int *eof, void *data); -static int proc_xpd_ztregister_write(struct file *file, const char __user *buffer, unsigned long count, void *data); -static int proc_xpd_blink_read(char *page, char **start, off_t off, int count, int *eof, void *data); -static int proc_xpd_blink_write(struct file *file, const char __user *buffer, unsigned long count, void *data); -static void xpd_free(xpd_t *xpd); - -static void xpd_free(xpd_t *xpd) -{ - xbus_t *xbus = NULL; - - if(!xpd) - return; - xbus = xpd->xbus; - if(!xbus) - return; - XPD_DBG(DEVICES, xpd, "\n"); -#ifdef CONFIG_PROC_FS - if(xpd->proc_xpd_dir) { - if(xpd->proc_xpd_summary) { - XPD_DBG(PROC, xpd, "Removing proc '%s'\n", PROC_XPD_SUMMARY); - remove_proc_entry(PROC_XPD_SUMMARY, xpd->proc_xpd_dir); - xpd->proc_xpd_summary = NULL; - } - if(xpd->proc_xpd_ztregister) { - XPD_DBG(PROC, xpd, "Removing proc '%s'\n", PROC_XPD_ZTREGISTER); - remove_proc_entry(PROC_XPD_ZTREGISTER, xpd->proc_xpd_dir); - xpd->proc_xpd_ztregister = NULL; - } - if(xpd->proc_xpd_blink) { - XPD_DBG(PROC, xpd, "Removing proc '%s'\n", PROC_XPD_BLINK); - remove_proc_entry(PROC_XPD_BLINK, xpd->proc_xpd_dir); - xpd->proc_xpd_blink = NULL; - } - XPD_DBG(PROC, xpd, "Removing proc directory\n"); - remove_proc_entry(xpd->xpdname, xbus->proc_xbus_dir); - xpd->proc_xpd_dir = NULL; - } -#endif - xbus_unregister_xpd(xbus, xpd); - if(xpd->xproto) - xproto_put(xpd->xproto); - xpd->xproto = NULL; - KZFREE(xpd); -} - - -/*------------------------- XPD Management -------------------------*/ - -/* - * Synchronous part of XPD detection. - * Called from xbus_poll() - */ -void card_detected(struct card_desc_struct *card_desc) -{ - xbus_t *xbus; - xpd_t *xpd = NULL; - byte type; - byte subtype; - int unit; - int subunit; - byte rev; - const xops_t *xops; - const xproto_table_t *proto_table; - - - BUG_ON(!card_desc); - BUG_ON(card_desc->magic != CARD_DESC_MAGIC); - xbus = card_desc->xbus; /* refcount held by xbus_poll() */ - type = card_desc->type; - subtype = card_desc->subtype; - unit = card_desc->xpd_addr.unit; - subunit = card_desc->xpd_addr.subunit; - rev = card_desc->rev; - BUG_ON(!xbus); - xpd = xpd_byaddr(xbus, unit, subunit); - if(xpd) { - if(type == XPD_TYPE_NOMODULE) { - XBUS_NOTICE(xbus, "XPD at %d%d removed\n", - unit, subunit); - BUG(); - goto out; - } - XPD_NOTICE(xpd, "XPD at %d%d already exists\n", - unit, subunit); - goto out; - } - if(type == XPD_TYPE_NOMODULE) { - XBUS_NOTICE(xbus, "XPD at %d%d Missing\n", - unit, subunit); - goto out; - } - proto_table = xproto_get(type); - if(!proto_table) { - XBUS_NOTICE(xbus, "XPD at %d%d: missing protocol table for type=%d. Ignored.\n", - unit, subunit, - type); - goto out; - } - xops = &proto_table->xops; - BUG_ON(!xops); - xpd = xops->card_new(xbus, unit, subunit, proto_table, subtype, rev); - if(!xpd) { - XBUS_NOTICE(xbus, "card_new(%d,%d,%d,%d,%d) failed. Ignored.\n", - unit, subunit, proto_table->type, subtype, rev); - xproto_put(proto_table); - goto err; - } - xpd->addr = card_desc->xpd_addr; - xpd->xbus_idx = XPD_IDX(unit,subunit); - snprintf(xpd->xpdname, XPD_NAMELEN, "XPD-%1d%1d", unit, subunit); - xpd->subtype = card_desc->subtype; - xpd->offhook = card_desc->line_status; - - /* For USB-1 disable some channels */ - if(MAX_SEND_SIZE(xbus) < RPACKET_SIZE(GLOBAL, PCM_WRITE)) { - xpp_line_t no_pcm; - - no_pcm = 0x7F | xpd->digital_outputs | xpd->digital_inputs; - xpd->no_pcm = no_pcm; - XBUS_NOTICE(xbus, "max xframe size = %d, disabling some PCM channels. no_pcm=0x%04X\n", - MAX_SEND_SIZE(xbus), xpd->no_pcm); - } - xbus_register_xpd(xbus, xpd); -#ifdef CONFIG_PROC_FS - XPD_DBG(PROC, xpd, "Creating proc directory\n"); - xpd->proc_xpd_dir = proc_mkdir(xpd->xpdname, xbus->proc_xbus_dir); - if(!xpd->proc_xpd_dir) { - XPD_ERR(xpd, "Failed to create proc directory\n"); - goto err; - } - xpd->proc_xpd_summary = create_proc_read_entry(PROC_XPD_SUMMARY, 0444, xpd->proc_xpd_dir, - xpd_read_proc, xpd); - if(!xpd->proc_xpd_summary) { - XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_XPD_SUMMARY); - goto err; - } - xpd->proc_xpd_summary->owner = THIS_MODULE; - xpd->proc_xpd_ztregister = create_proc_entry(PROC_XPD_ZTREGISTER, 0644, xpd->proc_xpd_dir); - if (!xpd->proc_xpd_ztregister) { - XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_XPD_ZTREGISTER); - goto err; - } - xpd->proc_xpd_ztregister->owner = THIS_MODULE; - xpd->proc_xpd_ztregister->data = xpd; - xpd->proc_xpd_ztregister->read_proc = proc_xpd_ztregister_read; - xpd->proc_xpd_ztregister->write_proc = proc_xpd_ztregister_write; - xpd->proc_xpd_blink = create_proc_entry(PROC_XPD_BLINK, 0644, xpd->proc_xpd_dir); - if (!xpd->proc_xpd_blink) { - XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_XPD_BLINK); - goto err; - } - xpd->proc_xpd_blink->owner = THIS_MODULE; - xpd->proc_xpd_blink->data = xpd; - xpd->proc_xpd_blink->read_proc = proc_xpd_blink_read; - xpd->proc_xpd_blink->write_proc = proc_xpd_blink_write; -#endif - if(CALL_XMETHOD(card_init, xbus, xpd) < 0) - goto err; - //CALL_XMETHOD(XPD_STATE, xbus, xpd, 0); /* Turn off all channels */ - xpd->card_present = 1; - CALL_XMETHOD(XPD_STATE, xbus, xpd, 1); /* Turn on all channels */ - XPD_INFO(xpd, "Initialized: %s\n", xpd->type_name); - - if(zap_autoreg) - zaptel_register_xpd(xpd); -out: - KZFREE(card_desc); - return; -err: - xpd_free(xpd); - goto out; -} - - -#ifdef CONFIG_PROC_FS - -/** - * Prints a general procfs entry for the bus, under xpp/BUSNAME/summary - * @page TODO: figure out procfs - * @start TODO: figure out procfs - * @off TODO: figure out procfs - * @count TODO: figure out procfs - * @eof TODO: figure out procfs - * @data an xbus_t pointer with the bus data. - */ -static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - xpd_t *xpd = data; - xbus_t *xbus; - int i; - - if(!xpd) - goto out; - - xbus = xpd->xbus; - len += sprintf(page + len, "%s (%s ,card %s, span %d)\n" - "timing_priority: %d\n" - "timer_count: %d span->mainttimer=%d\n" - , - xpd->xpdname, xpd->type_name, - (xpd->card_present) ? "present" : "missing", - (SPAN_REGISTERED(xpd)) ? xpd->span.spanno : 0, - xpd->timing_priority, - xpd->timer_count, xpd->span.mainttimer - ); - len += sprintf(page + len, "Address: U=%d S=%d\n", xpd->addr.unit, xpd->addr.subunit); - len += sprintf(page + len, "Type: %d.%d\n\n", xpd->type, xpd->subtype); - len += sprintf(page + len, "pcm_len=%d\n\n", xpd->pcm_len); - len += sprintf(page + len, "wanted_pcm_mask=0x%04X\n\n", xpd->wanted_pcm_mask); - len += sprintf(page + len, "mute_dtmf=0x%04X\n\n", xpd->mute_dtmf); - len += sprintf(page + len, "STATES:"); - len += sprintf(page + len, "\n\t%-17s: ", "output_relays"); - for_each_line(xpd, i) { - len += sprintf(page + len, "%d ", IS_SET(xpd->digital_outputs, i)); - } - len += sprintf(page + len, "\n\t%-17s: ", "input_relays"); - for_each_line(xpd, i) { - len += sprintf(page + len, "%d ", IS_SET(xpd->digital_inputs, i)); - } - len += sprintf(page + len, "\n\t%-17s: ", "offhook"); - for_each_line(xpd, i) { - len += sprintf(page + len, "%d ", IS_SET(xpd->offhook, i)); - } - len += sprintf(page + len, "\n\t%-17s: ", "cid_on"); - for_each_line(xpd, i) { - len += sprintf(page + len, "%d ", IS_SET(xpd->cid_on, i)); - } - len += sprintf(page + len, "\n\t%-17s: ", "msg_waiting"); - for_each_line(xpd, i) { - len += sprintf(page + len, "%d ", IS_SET(xpd->msg_waiting, i)); - } - len += sprintf(page + len, "\n\t%-17s: ", "ringing"); - for_each_line(xpd, i) { - len += sprintf(page + len, "%d ", xpd->ringing[i]); - } - len += sprintf(page + len, "\n\t%-17s: ", "no_pcm"); - for_each_line(xpd, i) { - len += sprintf(page + len, "%d ", IS_SET(xpd->no_pcm, i)); - } -#if 1 - if(SPAN_REGISTERED(xpd)) { - len += sprintf(page + len, "\nPCM:\n | [readchunk] | [writechunk] | W D"); - for_each_line(xpd, i) { - struct zt_chan *chans = xpd->span.chans; - byte rchunk[ZT_CHUNKSIZE]; - byte wchunk[ZT_CHUNKSIZE]; - byte *rp; - byte *wp; - int j; - - if(IS_SET(xpd->digital_outputs, i)) - continue; - if(IS_SET(xpd->digital_inputs, i)) - continue; - if(IS_SET(xpd->digital_signalling, i)) - continue; - rp = chans[i].readchunk; - wp = chans[i].writechunk; - memcpy(rchunk, rp, ZT_CHUNKSIZE); - memcpy(wchunk, wp, ZT_CHUNKSIZE); - len += sprintf(page + len, "\n port %2d> | ", i); - for(j = 0; j < ZT_CHUNKSIZE; j++) { - len += sprintf(page + len, "%02X ", rchunk[j]); - } - len += sprintf(page + len, " | "); - for(j = 0; j < ZT_CHUNKSIZE; j++) { - len += sprintf(page + len, "%02X ", wchunk[j]); - } - len += sprintf(page + len, " | %c", - (IS_SET(xpd->wanted_pcm_mask, i))?'+':' '); - len += sprintf(page + len, " %c", - (IS_SET(xpd->mute_dtmf, i))?'-':' '); - } - } -#endif -#if 0 - if(SPAN_REGISTERED(xpd)) { - len += sprintf(page + len, "\nSignalling:\n"); - for_each_line(xpd, i) { - struct zt_chan *chan = &xpd->span.chans[i]; - len += sprintf(page + len, "\t%2d> sigcap=0x%04X sig=0x%04X\n", i, chan->sigcap, chan->sig); - } - } -#endif - len += sprintf(page + len, "\nCOUNTERS:\n"); - for(i = 0; i < XPD_COUNTER_MAX; i++) { - len += sprintf(page + len, "\t\t%-20s = %d\n", - xpd_counters[i].name, xpd->counters[i]); - } - len += sprintf(page + len, "<-- len=%d\n", len); -out: - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; - -} - -#endif - -/* - * xpd_alloc - Allocator for new XPD's - * - */ -xpd_t *xpd_alloc(size_t privsize, const xproto_table_t *proto_table, int channels) -{ - xpd_t *xpd = NULL; - size_t alloc_size = sizeof(xpd_t) + privsize; - int type = proto_table->type; - - DBG(DEVICES, "type=%d channels=%d (alloc_size=%d)\n", - type, channels, alloc_size); - if(channels > CHANNELS_PERXPD) { - ERR("%s: type=%d: too many channels %d\n", - __FUNCTION__, type, channels); - goto err; - } - - if((xpd = KZALLOC(alloc_size, GFP_KERNEL)) == NULL) { - ERR("%s: type=%d: Unable to allocate memory\n", - __FUNCTION__, type); - goto err; - } - xpd->priv = (byte *)xpd + sizeof(xpd_t); - spin_lock_init(&xpd->lock); - xpd->xbus = NULL; - xpd->xbus_idx = -1; - xpd->channels = channels; - xpd->chans = NULL; - xpd->card_present = 0; - xpd->offhook = 0x0; /* ONHOOK */ - xpd->type = proto_table->type; - xpd->xproto = proto_table; - xpd->xops = &proto_table->xops; - xpd->digital_outputs = 0; - xpd->digital_inputs = 0; - - atomic_set(&xpd->zt_registered, 0); - atomic_set(&xpd->open_counter, 0); - - xpd->chans = kmalloc(sizeof(struct zt_chan)*xpd->channels, GFP_KERNEL); - if (xpd->chans == NULL) { - ERR("%s: Unable to allocate channels\n", __FUNCTION__); - goto err; - } - return xpd; -err: - if(xpd) { - if(xpd->chans) - kfree((void *)xpd->chans); - kfree(xpd); - } - return NULL; -} - -/* FIXME: this should be removed once digium patch their zaptel.h - * I simply wish to avoid changing zaptel.h in the xpp patches. - */ -#ifndef ZT_EVENT_REMOVED -#define ZT_EVENT_REMOVED (20) -#endif - -void xpd_disconnect(xpd_t *xpd) -{ - unsigned long flags; - - BUG_ON(!xpd); - - spin_lock_irqsave(&xpd->lock, flags); - XPD_DBG(DEVICES, xpd, "(%p)\n", xpd->xproto); - if(!xpd->card_present) /* Multiple reports */ - goto out; - xpd->card_present = 0; - if(SPAN_REGISTERED(xpd)) { - int i; - - update_xpd_status(xpd, ZT_ALARM_NOTOPEN); - /* TODO: Should this be done before releasing the spinlock? */ - XPD_DBG(DEVICES, xpd, "Queuing ZT_EVENT_REMOVED on all channels to ask user to release them\n"); - for (i=0; ispan.channels; i++) - zt_qevent_lock(&xpd->chans[i],ZT_EVENT_REMOVED); - } -out: - spin_unlock_irqrestore(&xpd->lock, flags); -} - -void xpd_remove(xpd_t *xpd) -{ - xbus_t *xbus; - - BUG_ON(!xpd); - xbus = xpd->xbus; - XPD_INFO(xpd, "Remove\n"); - zaptel_unregister_xpd(xpd); - CALL_XMETHOD(card_remove, xbus, xpd); - xpd_free(xpd); -} - -void update_xpd_status(xpd_t *xpd, int alarm_flag) -{ - struct zt_span *span = &xpd->span; - - if(!SPAN_REGISTERED(xpd)) { - // XPD_NOTICE(xpd, "%s: XPD is not registered. Skipping.\n", __FUNCTION__); - return; - } - switch (alarm_flag) { - case ZT_ALARM_NONE: - xpd->last_response = jiffies; - break; - default: - // Nothing - break; - } - if(span->alarms == alarm_flag) - return; - span->alarms = alarm_flag; - zt_alarm_notify(span); - XPD_DBG(GENERAL, xpd, "Update XPD alarms: %s -> %02X\n", xpd->span.name, alarm_flag); -} - -void update_line_status(xpd_t *xpd, int pos, bool to_offhook) -{ - zt_rxsig_t rxsig; - - BUG_ON(!xpd); - if(to_offhook) { - BIT_SET(xpd->offhook, pos); - rxsig = ZT_RXSIG_OFFHOOK; - } else { - BIT_CLR(xpd->offhook, pos); - BIT_CLR(xpd->cid_on, pos); - rxsig = ZT_RXSIG_ONHOOK; - /* - * To prevent latest PCM to stay in buffers - * indefinitely, mark this channel for a - * single silence transmittion. - * - * This bit will be cleared on the next tick. - */ - BIT_SET(xpd->silence_pcm, pos); - } - /* - * We should not spinlock before calling zt_hooksig() as - * it may call back into our xpp_hooksig() and cause - * a nested spinlock scenario - */ - LINE_DBG(SIGNAL, xpd, pos, "rxsig=%s\n", (rxsig == ZT_RXSIG_ONHOOK) ? "ONHOOK" : "OFFHOOK"); - if(SPAN_REGISTERED(xpd)) - zt_hooksig(&xpd->chans[pos], rxsig); -} - -#ifdef CONFIG_PROC_FS -int proc_xpd_ztregister_read(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - unsigned long flags; - xpd_t *xpd = data; - - BUG_ON(!xpd); - spin_lock_irqsave(&xpd->lock, flags); - - len += sprintf(page + len, "%d\n", SPAN_REGISTERED(xpd) ? xpd->span.spanno : 0); - spin_unlock_irqrestore(&xpd->lock, flags); - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; -} - -static int proc_xpd_ztregister_write(struct file *file, const char __user *buffer, unsigned long count, void *data) -{ - xpd_t *xpd = data; - char buf[MAX_PROC_WRITE]; - int zt_reg; - int ret; - - BUG_ON(!xpd); - if(count >= MAX_PROC_WRITE) - return -EINVAL; - if(copy_from_user(buf, buffer, count)) - return -EFAULT; - buf[count] = '\0'; - ret = sscanf(buf, "%d", &zt_reg); - if(ret != 1) - return -EINVAL; - XPD_DBG(GENERAL, xpd, "%s\n", (zt_reg) ? "register" : "unregister"); - if(zt_reg) - ret = zaptel_register_xpd(xpd); - else - ret = zaptel_unregister_xpd(xpd); - return (ret < 0) ? ret : count; -} - -int proc_xpd_blink_read(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = 0; - unsigned long flags; - xpd_t *xpd = data; - - BUG_ON(!xpd); - spin_lock_irqsave(&xpd->lock, flags); - - len += sprintf(page + len, "%d\n", xpd->blink_mode); - spin_unlock_irqrestore(&xpd->lock, flags); - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; -} - -static int proc_xpd_blink_write(struct file *file, const char __user *buffer, unsigned long count, void *data) -{ - xpd_t *xpd = data; - char buf[MAX_PROC_WRITE]; - int blink; - int ret; - - BUG_ON(!xpd); - if(count >= MAX_PROC_WRITE) - return -EINVAL; - if(copy_from_user(buf, buffer, count)) - return -EFAULT; - buf[count] = '\0'; - ret = sscanf(buf, "%d", &blink); - if(ret != 1) - return -EINVAL; - XPD_DBG(GENERAL, xpd, "%s\n", (blink) ? "blink" : "unblink"); - xpd->blink_mode = blink; - return count; -} - -#endif - - -#define XPP_MAX_LEN 512 - -/*------------------------- Zaptel Interfaces ----------------------*/ - - -/* - * Called from zaptel with spinlock held on chan. Must not call back - * zaptel functions. - */ -int xpp_open(struct zt_chan *chan) -{ -#if 0 - xpd_t *xpd = chan->pvt; - xbus_t *xbus = xpd->xbus; - int pos = chan->chanpos - 1; - unsigned long flags; -#else - xpd_t *xpd; - xbus_t *xbus; - int pos; - unsigned long flags; - - if (!chan) { - NOTICE("open called on a null chan\n"); - return -EINVAL; - } - xpd = chan->pvt; - if (!xpd) { - NOTICE("open called on a chan with no pvt (xpd)\n"); - return -EINVAL; - } - xbus = xpd->xbus; - if (!xbus) { - NOTICE("open called on a chan with no xbus\n"); - return -EINVAL; - } - pos = chan->chanpos - 1; -#endif - - spin_lock_irqsave(&xbus->lock, flags); - atomic_inc(&xbus->xbus_ref_count); - atomic_inc(&xpd->open_counter); - if(IS_SET(xpd->digital_signalling, pos)) /* D-chan offhook */ - BIT_SET(xpd->offhook, pos); - DBG(DEVICES, "chan=%d (xbus_ref_count=%d)\n", - pos, atomic_read(&xbus->xbus_ref_count)); - spin_unlock_irqrestore(&xbus->lock, flags); - if(xpd->xops->card_open) - xpd->xops->card_open(xpd, pos); - return 0; -} - -int xpp_close(struct zt_chan *chan) -{ - xpd_t *xpd = chan->pvt; - xbus_t *xbus = xpd->xbus; - int pos = chan->chanpos - 1; - unsigned long flags; - - spin_lock_irqsave(&xbus->lock, flags); - atomic_dec(&xpd->open_counter); - if(IS_SET(xpd->digital_signalling, pos)) /* D-chan onhook */ - BIT_CLR(xpd->offhook, pos); - spin_unlock_irqrestore(&xbus->lock, flags); - if(xpd->xops->card_close) - xpd->xops->card_close(xpd, pos); - XPD_DBG(GENERAL, xpd, "pid=%d: chan=%d (xbus_ref_count=%d)\n", - current->pid, pos, atomic_read(&xbus->xbus_ref_count)); - if(atomic_dec_and_test(&xbus->xbus_ref_count)) - xbus_remove(xbus); - return 0; -} - -void report_bad_ioctl(const char *msg, xpd_t *xpd, int pos, unsigned int cmd) -{ - XPD_NOTICE(xpd, "%s: Bad ioctl\n", msg); - XPD_NOTICE(xpd, "ENOTTY: chan=%d cmd=0x%x\n", pos, cmd); - XPD_NOTICE(xpd, " IOC_TYPE=0x%02X\n", _IOC_TYPE(cmd)); - XPD_NOTICE(xpd, " IOC_DIR=0x%02X\n", _IOC_DIR(cmd)); - XPD_NOTICE(xpd, " IOC_NR=%d\n", _IOC_NR(cmd)); - XPD_NOTICE(xpd, " IOC_SIZE=0x%02X\n", _IOC_SIZE(cmd)); -} - -int xpp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long arg) -{ - xpd_t *xpd = chan->pvt; - int pos = chan->chanpos - 1; - - if(!xpd) { - ERR("%s: channel in pos %d, was already closed. Ignore.\n", - __FUNCTION__, pos); - return -ENODEV; - } - switch (cmd) { - default: - /* Some span-specific commands before we give up: */ - if (xpd->xops->card_ioctl != NULL) { - return xpd->xops->card_ioctl(xpd, pos, cmd, arg); - } - report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd); - return -ENOTTY; - } - return 0; -} - -static int xpp_hooksig(struct zt_chan *chan, zt_txsig_t txsig) -{ - xpd_t *xpd = chan->pvt; - xbus_t *xbus; - int pos = chan->chanpos - 1; - - if(!xpd) { - ERR("%s: channel in pos %d, was already closed. Ignore.\n", - __FUNCTION__, pos); - return -ENODEV; - } - xbus = xpd->xbus; - BUG_ON(!xbus); - DBG(SIGNAL, "Setting %s to %s (%d)\n", chan->name, txsig2str(txsig), txsig); - return CALL_XMETHOD(card_hooksig, xbus, xpd, pos, txsig); -} - -/* Req: Set the requested chunk size. This is the unit in which you must - report results for conferencing, etc */ -int xpp_setchunksize(struct zt_span *span, int chunksize); - -/* Enable maintenance modes */ -int xpp_maint(struct zt_span *span, int cmd) -{ - xpd_t *xpd = span->pvt; - int ret = 0; -#if 0 - char loopback_data[] = "THE-QUICK-BROWN-FOX-JUMPED-OVER-THE-LAZY-DOG"; -#endif - - DBG(GENERAL, "span->mainttimer=%d\n", span->mainttimer); - switch(cmd) { - case ZT_MAINT_NONE: - printk("XXX Turn off local and remote loops XXX\n"); - break; - case ZT_MAINT_LOCALLOOP: - printk("XXX Turn on local loopback XXX\n"); - break; - case ZT_MAINT_REMOTELOOP: - printk("XXX Turn on remote loopback XXX\n"); - break; - case ZT_MAINT_LOOPUP: - printk("XXX Send loopup code XXX\n"); - // CALL_XMETHOD(LOOPBACK_AX, xpd->xbus, xpd, loopback_data, ARRAY_SIZE(loopback_data)); - break; - case ZT_MAINT_LOOPDOWN: - printk("XXX Send loopdown code XXX\n"); - break; - case ZT_MAINT_LOOPSTOP: - printk("XXX Stop sending loop codes XXX\n"); - break; - default: - ERR("XPP: Unknown maint command: %d\n", cmd); - ret = -EINVAL; - break; - } - if (span->mainttimer || span->maintstat) - update_xpd_status(xpd, ZT_ALARM_LOOPBACK); - return ret; -} - -#ifdef CONFIG_ZAPTEL_WATCHDOG -/* - * If the watchdog detects no received data, it will call the - * watchdog routine - */ -static int xpp_watchdog(struct zt_span *span, int cause) -{ - static int rate_limit = 0; - - if((rate_limit++ % 1000) == 0) - DBG(GENERAL, "\n"); - return 0; -} -#endif - -/** - * Unregister an xpd from zaptel and release related resources - * @xpd The xpd to be unregistered - * @returns 0 on success, errno otherwise - * - * Checks that nobody holds an open channel. - * - * Called by: - * - User action through /proc - * - During xpd_remove() - */ -static int zaptel_unregister_xpd(xpd_t *xpd) -{ - unsigned long flags; - - BUG_ON(!xpd); - spin_lock_irqsave(&xpd->lock, flags); - - if(!SPAN_REGISTERED(xpd)) { - XPD_NOTICE(xpd, "Already unregistered\n"); - spin_unlock_irqrestore(&xpd->lock, flags); - return -EIDRM; - } - update_xpd_status(xpd, ZT_ALARM_NOTOPEN); - if(atomic_read(&xpd->open_counter)) { - XPD_NOTICE(xpd, "Busy (open_counter=%d). Skipping.\n", atomic_read(&xpd->open_counter)); - spin_unlock_irqrestore(&xpd->lock, flags); - return -EBUSY; - } - mdelay(2); // FIXME: This is to give chance for transmit/receiveprep to finish. - spin_unlock_irqrestore(&xpd->lock, flags); - if(xpd->card_present) - xpd->xops->card_zaptel_preregistration(xpd, 0); - atomic_dec(&xpd->zt_registered); - atomic_dec(&num_registered_spans); - zt_unregister(&xpd->span); - if(xpd->card_present) - xpd->xops->card_zaptel_postregistration(xpd, 0); - return 0; -} - -static int zaptel_register_xpd(xpd_t *xpd) -{ - struct zt_span *span; - xbus_t *xbus; - int cn; - const xops_t *xops; - - BUG_ON(!xpd); - xops = xpd->xops; - xbus = xpd->xbus; - - if (SPAN_REGISTERED(xpd)) { - XPD_ERR(xpd, "Already registered\n"); - return -EEXIST; - } - cn = xpd->channels; - XPD_DBG(DEVICES, xpd, "Initializing span: %d channels.\n", cn); - memset(xpd->chans, 0, sizeof(struct zt_chan)*cn); - memset(&xpd->span, 0, sizeof(struct zt_span)); - - span = &xpd->span; - snprintf(span->name, MAX_SPANNAME, "%s/%s", xbus->busname, xpd->xpdname); - span->deflaw = ZT_LAW_MULAW; /* default, may be overriden by card_* drivers */ - init_waitqueue_head(&span->maintq); - span->pvt = xpd; - span->channels = cn; - span->chans = xpd->chans; - - span->open = xpp_open; - span->close = xpp_close; - span->flags = ZT_FLAG_RBS; - span->hooksig = xpp_hooksig; /* Only with RBS bits */ - span->ioctl = xpp_ioctl; - span->maint = xpp_maint; -#ifdef ZAPTEL_SYNC_TICK - span->sync_tick = zaptel_sync_tick; -#endif - if (xpp_ec) - span->echocan = xpp_echocan; -#ifdef CONFIG_ZAPTEL_WATCHDOG - span->watchdog = xpp_watchdog; -#endif - - snprintf(xpd->span.desc, MAX_SPANDESC, "Xorcom XPD #%02d/%1d%1d: %s", - xbus->num, xpd->addr.unit, xpd->addr.subunit, xpd->type_name); - XPD_DBG(GENERAL, xpd, "Registering span '%s'\n", xpd->span.desc); - xpd->xops->card_zaptel_preregistration(xpd, 1); - if(zt_register(&xpd->span, prefmaster)) { - XPD_ERR(xpd, "Failed to zt_register span\n"); - return -ENODEV; - } - atomic_inc(&num_registered_spans); - atomic_inc(&xpd->zt_registered); - xpd->xops->card_zaptel_postregistration(xpd, 1); - /* - * Update zaptel about our state - */ -#if 0 - /* - * FIXME: since asterisk didn't open the channel yet, the report - * is discarded anyway. OTOH, we cannot report in xpp_open or - * xpp_chanconfig since zaptel call them with a spinlock on the channel - * and zt_hooksig tries to acquire the same spinlock, resulting in - * double spinlock deadlock (we are lucky that RH/Fedora kernel are - * compiled with spinlock debugging).... tough. - */ - for_each_line(xpd, cn) { - struct zt_chan *chans = xpd->span.chans; - - if(IS_SET(xpd->offhook, cn)) { - LINE_NOTICE(xpd, cn, "Report OFFHOOK to zaptel\n"); - zt_hooksig(&chans[cn], ZT_RXSIG_OFFHOOK); - } - } -#endif - return 0; -} - -/*------------------------- Proc debugging interface ---------------*/ - -#ifdef CONFIG_PROC_FS - -#if 0 -static int xpp_zap_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data) -{ -} -#endif - -#endif - -/*------------------------- Initialization -------------------------*/ - -static void do_cleanup(void) -{ -#ifdef CONFIG_PROC_FS - if(xpp_proc_toplevel) { - DBG(GENERAL, "Removing '%s' from proc\n", PROC_DIR); - remove_proc_entry(PROC_DIR, NULL); - xpp_proc_toplevel = NULL; - } -#endif -} - -int __init xpp_zap_init(void) -{ - int ret = 0; - - INFO("revision %s MAX_XPDS=%d (%d*%d)\n", XPP_VERSION, - MAX_XPDS, MAX_UNIT, MAX_SUBUNIT); -#ifdef CONFIG_ZAPATA_BRI_DCHANS - INFO("FEATURE: with BRISTUFF support\n"); -#else - INFO("FEATURE: without BRISTUFF support\n"); -#endif -#ifdef CONFIG_PROC_FS - xpp_proc_toplevel = proc_mkdir(PROC_DIR, NULL); - if(!xpp_proc_toplevel) { - ret = -EIO; - goto err; - } -#endif - ret = xbus_core_init(); - if(ret) { - ERR("xbus_core_init failed (%d)\n", ret); - goto err; - } - ret = xbus_pcm_init(xpp_proc_toplevel); - if(ret) { - ERR("xbus_pcm_init failed (%d)\n", ret); - xbus_core_shutdown(); - goto err; - } - return 0; -err: - do_cleanup(); - return ret; -} - -void __exit xpp_zap_cleanup(void) -{ - xbus_pcm_shutdown(); - xbus_core_shutdown(); - do_cleanup(); -} - -EXPORT_SYMBOL(print_dbg); -EXPORT_SYMBOL(card_detected); -EXPORT_SYMBOL(xpd_alloc); -EXPORT_SYMBOL(xpd_disconnect); -EXPORT_SYMBOL(update_xpd_status); -EXPORT_SYMBOL(update_line_status); -EXPORT_SYMBOL(xpp_open); -EXPORT_SYMBOL(xpp_close); -EXPORT_SYMBOL(xpp_ioctl); -EXPORT_SYMBOL(xpp_maint); -EXPORT_SYMBOL(report_bad_ioctl); - -MODULE_DESCRIPTION("XPP Zaptel Driver"); -MODULE_AUTHOR("Oron Peled "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(XPP_VERSION); - -module_init(xpp_zap_init); -module_exit(xpp_zap_cleanup); diff --git a/xpp/xpp_zap.h b/xpp/xpp_zap.h deleted file mode 100644 index fee20c5..0000000 --- a/xpp/xpp_zap.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef XPP_ZAP_H -#define XPP_ZAP_H -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "xpd.h" -#include "xproto.h" - -void xpd_disconnect(xpd_t *xpd); -void card_detected(struct card_desc_struct *card_desc); -xpd_t *xpd_alloc(size_t privsize, const xproto_table_t *proto_table, int channels); -void xpd_remove(xpd_t *xpd); -void update_xpd_status(xpd_t *xpd, int alarm_flag); -void update_line_status(xpd_t *xpd, int pos, bool good); -int xpp_open(struct zt_chan *chan); -int xpp_close(struct zt_chan *chan); -int xpp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long arg); -int xpp_maint(struct zt_span *span, int cmd); -void report_bad_ioctl(const char *msg, xpd_t *xpd, int pos, unsigned int cmd); -int total_registered_spans(void); - -#ifdef CONFIG_PROC_FS -#include - -extern struct proc_dir_entry *xpp_proc_toplevel; -#endif - -#define SPAN_REGISTERED(xpd) atomic_read(&(xpd)->zt_registered) - -#endif /* XPP_ZAP_H */ diff --git a/xpp/xproto.c b/xpp/xproto.c deleted file mode 100644 index d55949e..0000000 --- a/xpp/xproto.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "xpd.h" -#include "xproto.h" -#include "xpp_zap.h" -#include "xbus-core.h" -#include "zap_debug.h" -#include -#include - -static const char rcsid[] = "$Id$"; - -extern int print_dbg; - -static const xproto_table_t *xprotocol_tables[XPD_TYPE_NOMODULE]; - -#if MAX_UNIT*MAX_SUBUNIT > MAX_XPDS -#error MAX_XPDS is too small -#endif - -bool valid_xpd_addr(const struct xpd_addr *addr) -{ - return ((addr->subunit & ~BITMASK(SUBUNIT_BITS)) == 0) && ((addr->unit & ~BITMASK(UNIT_BITS)) == 0); -} - -/*---------------- General Protocol Management ----------------------------*/ - -const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, byte opcode) -{ - const xproto_entry_t *xe; - - //DBG(GENERAL, "\n"); - xe = &table->entries[opcode]; - return (xe->handler != NULL) ? xe : NULL; -} - -const xproto_entry_t *xproto_global_entry(byte opcode) -{ - const xproto_entry_t *xe; - - xe = xproto_card_entry(&PROTO_TABLE(GLOBAL), opcode); - //DBG(GENERAL, "opcode=0x%X xe=%p\n", opcode, xe); - return xe; -} - -xproto_handler_t xproto_global_handler(byte opcode) -{ - return xproto_card_handler(&PROTO_TABLE(GLOBAL), opcode); -} - -const xproto_table_t *xproto_table(xpd_type_t cardtype) -{ - if(cardtype >= XPD_TYPE_NOMODULE) - return NULL; - return xprotocol_tables[cardtype]; -} - -const xproto_table_t *xproto_get(xpd_type_t cardtype) -{ - const xproto_table_t *xtable; - - if(cardtype >= XPD_TYPE_NOMODULE) - return NULL; - xtable = xprotocol_tables[cardtype]; - if(!xtable) { /* Try to load the relevant module */ - int ret = request_module(XPD_TYPE_PREFIX "%d", cardtype); - if(ret != 0) { - NOTICE("%s: Failed to load module for type=%d. exit status=%d.\n", - __FUNCTION__, cardtype, ret); - /* Drop through: we may be lucky... */ - } - xtable = xprotocol_tables[cardtype]; - } - if(xtable) { - BUG_ON(!xtable->owner); - DBG(GENERAL, "%s refcount was %d\n", xtable->name, module_refcount(xtable->owner)); - if(!try_module_get(xtable->owner)) { - ERR("%s: try_module_get for %s failed.\n", __FUNCTION__, xtable->name); - return NULL; - } - } - return xtable; -} - -void xproto_put(const xproto_table_t *xtable) -{ - BUG_ON(!xtable); - DBG(GENERAL, "%s refcount was %d\n", xtable->name, module_refcount(xtable->owner)); - BUG_ON(module_refcount(xtable->owner) <= 0); - module_put(xtable->owner); -} - -xproto_handler_t xproto_card_handler(const xproto_table_t *table, byte opcode) -{ - const xproto_entry_t *xe; - - //DBG(GENERAL, "\n"); - xe = xproto_card_entry(table, opcode); - return xe->handler; -} - -void notify_bad_xpd(const char *funcname, xbus_t *xbus, const struct xpd_addr addr, const char *msg) -{ - XBUS_NOTICE(xbus, "%s: non-existing address (%1d%1d): %s\n", - funcname, addr.unit, addr.subunit, msg); -} - -int packet_process(xbus_t *xbus, xpacket_t *pack) -{ - byte op; - const xproto_entry_t *xe; - xproto_handler_t handler; - xproto_table_t *table; - xpd_t *xpd; - int ret = -EPROTO; - - BUG_ON(!pack); - if(!valid_xpd_addr(&XPACKET_ADDR(pack))) { - if(printk_ratelimit()) { - XBUS_NOTICE(xbus, "%s: from %d%d: bad address.\n", - __FUNCTION__, - XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack)); - dump_packet("packet_process -- bad address", pack, print_dbg); - } - goto out; - } - op = XPACKET_OP(pack); - xpd = xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack)); - /* XPD may be NULL (e.g: during bus polling */ - xe = xproto_global_entry(op); - /*-------- Validations -----------*/ - if(!xe) { - const xproto_table_t *xtable; - - if(!xpd) { - if(printk_ratelimit()) { - XBUS_NOTICE(xbus, "%s: from %d%d opcode=0x%02X: no such global command.\n", - __FUNCTION__, - XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack), op); - dump_packet("packet_process -- no such global command", pack, 1); - } - goto out; - } - xtable = xproto_table(xpd->type); - if(!xtable) { - if(printk_ratelimit()) - XPD_ERR(xpd, "%s: no protocol table (type=%d)\n", - __FUNCTION__, - xpd->type); - goto out; - } - xe = xproto_card_entry(xtable, op); - if(!xe) { - if(printk_ratelimit()) { - XPD_NOTICE(xpd, "%s: bad command (type=%d,opcode=0x%x)\n", - __FUNCTION__, - xpd->type, op); - dump_packet("packet_process -- bad command", pack, 1); - } - goto out; - } - } - table = xe->table; - BUG_ON(!table); - if(!table->packet_is_valid(pack)) { - if(printk_ratelimit()) { - ERR("xpp: %s: wrong size %d for opcode=0x%02X\n", - __FUNCTION__, XPACKET_LEN(pack), op); - dump_packet("packet_process -- wrong size", pack, print_dbg); - } - goto out; - } - ret = 0; /* All well */ - handler = xe->handler; - BUG_ON(!handler); - XBUS_COUNTER(xbus, RX_BYTES) += XPACKET_LEN(pack); - handler(xbus, xpd, xe, pack); -out: - return ret; -} - -static int xframe_receive_cmd(xbus_t *xbus, xframe_t *xframe) -{ - byte *xframe_end; - xpacket_t *pack; - byte *p; - int len; - int ret; - - p = xframe->packets; - xframe_end = p + XFRAME_LEN(xframe); - do { - pack = (xpacket_t *)p; - len = XPACKET_LEN(pack); - /* Sanity checks */ - if(unlikely(XPACKET_OP(pack) == XPROTO_NAME(GLOBAL,PCM_READ))) { - static int rate_limit; - - if((rate_limit++ % 1003) == 0) { - XBUS_DBG(GENERAL, xbus, "A PCM packet within a Non-PCM xframe\n"); - dump_xframe("In Non-PCM xframe", xbus, xframe); - } - ret = -EPROTO; - goto out; - } - p += len; - if(p > xframe_end || len < RPACKET_HEADERSIZE) { - static int rate_limit; - - if((rate_limit++ % 1003) == 0) { - XBUS_NOTICE(xbus, "Invalid packet length %d\n", len); - dump_xframe("BAD LENGTH", xbus, xframe); - } - ret = -EPROTO; - goto out; - } - ret = packet_process(xbus, pack); - if(unlikely(ret < 0)) - break; - } while(p < xframe_end); -out: - FREE_RECV_XFRAME(xbus, xframe); - return ret; -} - -int xframe_receive(xbus_t *xbus, xframe_t *xframe) -{ - int ret = 0; - struct timeval now; - struct timeval tv_received; - int usec; - - if(XFRAME_LEN(xframe) < RPACKET_HEADERSIZE) { - static int rate_limit; - - if((rate_limit++ % 1003) == 0) { - XBUS_NOTICE(xbus, "short xframe\n"); - dump_xframe("short xframe", xbus, xframe); - } - FREE_RECV_XFRAME(xbus, xframe); - return -EPROTO; - } - if(!XBUS_GET(xbus)) { - XBUS_DBG(GENERAL, xbus, "Dropped xframe. Is shutting down.\n"); - return -ENODEV; - } - tv_received = xframe->tv_received; - /* - * We want to check that xframes do not mix PCM and other commands - */ - if(XPACKET_IS_PCM((xpacket_t *)xframe->packets)) - xframe_receive_pcm(xbus, xframe); - else - ret = xframe_receive_cmd(xbus, xframe); - /* Calculate total processing time */ - do_gettimeofday(&now); - usec = (now.tv_sec - tv_received.tv_sec) * 1000000 + - now.tv_usec - tv_received.tv_usec; - if(usec > xbus->max_rx_process) - xbus->max_rx_process = usec; - XBUS_PUT(xbus); - return ret; -} - -#define VERBOSE_DEBUG 1 -#define ERR_REPORT_LIMIT 20 - -void dump_packet(const char *msg, const xpacket_t *packet, bool print_dbg) -{ - byte op = XPACKET_OP(packet); - byte *addr = (byte *)&XPACKET_ADDR(packet); - - if(!print_dbg) - return; - printk(KERN_DEBUG "%s: XPD=%1X-%1X%c (0x%X) OP=0x%02X LEN=%d", - msg, - XPACKET_ADDR_UNIT(packet), - XPACKET_ADDR_SUBUNIT(packet), - (XPACKET_ADDR_SYNC(packet))?'+':' ', - *addr, - op, - XPACKET_LEN(packet)); -#if VERBOSE_DEBUG - { - int i; - byte *p = (byte *)packet; - - printk(" BYTES: "); - for(i = 0; i < XPACKET_LEN(packet); i++) { - static int limiter = 0; - - if(i >= sizeof(xpacket_t)) { - if(limiter < ERR_REPORT_LIMIT) { - ERR("%s: length overflow i=%d > sizeof(xpacket_t)=%lu\n", - __FUNCTION__, i+1, (long)sizeof(xpacket_t)); - } else if(limiter == ERR_REPORT_LIMIT) { - ERR("%s: error packet #%d... squelsh reports.\n", - __FUNCTION__, limiter); - } - limiter++; - break; - } - if (print_dbg) - printk("%02X ", p[i]); - } - } -#endif - printk("\n"); -} - -void dump_reg_cmd(const char msg[], const reg_cmd_t *regcmd, bool writing) -{ - char action; - byte chipsel; - - if(regcmd->bytes != sizeof(*regcmd) - 1) { /* The size byte is not included */ - NOTICE("%s: Wrong size: regcmd->bytes = %d\n", __FUNCTION__, regcmd->bytes); - return; - } - if(writing && (REG_FIELD(regcmd, chipsel) & 0x80)) - ERR("Sending register command with reading bit ON\n"); - action = (writing) ? 'W' : 'R'; - chipsel = REG_FIELD(regcmd, chipsel) & ~0x80; - if(REG_FIELD(regcmd, do_subreg)) { - DBG(GENERAL, "%s: %d %cS %02X %02X [%02X] # data_high=%X m=%d eof=%d\n", msg, chipsel, action, - REG_FIELD(regcmd, regnum), - REG_FIELD(regcmd, subreg), - REG_FIELD(regcmd, data_low), - REG_FIELD(regcmd, data_high), - regcmd->multibyte, regcmd->eoframe); - } else if(REG_FIELD(regcmd, regnum) == 0x1E) { - DBG(GENERAL, "%s: %d %cI %02X [%02X %02X] # m=%d eof=%d\n", msg, chipsel, action, - REG_FIELD(regcmd, subreg), - REG_FIELD(regcmd, data_low), - REG_FIELD(regcmd, data_high), - regcmd->multibyte, regcmd->eoframe); - } else { - DBG(GENERAL, "%s: %d %cD %02X [%02X] # data_high=%X m=%d eof=%d\n", msg, chipsel, action, - REG_FIELD(regcmd, regnum), - REG_FIELD(regcmd, data_low), - REG_FIELD(regcmd, data_high), - regcmd->multibyte, regcmd->eoframe); - } -} - -const char *xproto_name(xpd_type_t xpd_type) -{ - const xproto_table_t *proto_table; - - BUG_ON(xpd_type >= XPD_TYPE_NOMODULE); - proto_table = xprotocol_tables[xpd_type]; - if(!proto_table) - return NULL; - return proto_table->name; -} - -#define CHECK_XOP(f) \ - if(!(xops)->f) { \ - ERR("%s: missing xmethod %s [%s (%d)]\n", __FUNCTION__, #f, name, type); \ - return -EINVAL; \ - } - -int xproto_register(const xproto_table_t *proto_table) -{ - int type; - const char *name; - const xops_t *xops; - - BUG_ON(!proto_table); - type = proto_table->type; - name = proto_table->name; - if(type >= XPD_TYPE_NOMODULE) { - NOTICE("%s: Bad xproto type %d\n", __FUNCTION__, type); - return -EINVAL; - } - DBG(GENERAL, "%s (%d)\n", name, type); - if(xprotocol_tables[type]) - NOTICE("%s: overriding registration of %s (%d)\n", __FUNCTION__, name, type); - xops = &proto_table->xops; - CHECK_XOP(card_new); - CHECK_XOP(card_init); - CHECK_XOP(card_remove); - CHECK_XOP(card_tick); - CHECK_XOP(card_pcm_fromspan); - CHECK_XOP(card_pcm_tospan); - CHECK_XOP(card_zaptel_preregistration); - CHECK_XOP(card_zaptel_postregistration); - CHECK_XOP(card_hooksig); - // CHECK_XOP(card_ioctl); // optional method -- call after testing - CHECK_XOP(card_register_reply); - CHECK_XOP(XPD_STATE); - CHECK_XOP(RING); - CHECK_XOP(RELAY_OUT); - - xprotocol_tables[type] = proto_table; - return 0; -} - -void xproto_unregister(const xproto_table_t *proto_table) -{ - int type; - const char *name; - - BUG_ON(!proto_table); - type = proto_table->type; - name = proto_table->name; - DBG(GENERAL, "%s (%d)\n", name, type); - if(type >= XPD_TYPE_NOMODULE) { - NOTICE("%s: Bad xproto type %s (%d)\n", __FUNCTION__, name, type); - return; - } - if(!xprotocol_tables[type]) - NOTICE("%s: xproto type %s (%d) is already unregistered\n", __FUNCTION__, name, type); - xprotocol_tables[type] = NULL; -} - -EXPORT_SYMBOL(dump_packet); -EXPORT_SYMBOL(dump_reg_cmd); -EXPORT_SYMBOL(xframe_receive); -EXPORT_SYMBOL(notify_bad_xpd); -EXPORT_SYMBOL(valid_xpd_addr); -EXPORT_SYMBOL(xproto_global_entry); -EXPORT_SYMBOL(xproto_card_entry); -EXPORT_SYMBOL(xproto_name); -EXPORT_SYMBOL(xproto_register); -EXPORT_SYMBOL(xproto_unregister); diff --git a/xpp/xproto.h b/xpp/xproto.h deleted file mode 100644 index f68fedf..0000000 --- a/xpp/xproto.h +++ /dev/null @@ -1,306 +0,0 @@ -#ifndef XPROTO_H -#define XPROTO_H -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "xdefs.h" - -#ifdef __KERNEL__ -#include -#include -#include - -/* - * This must match the firmware protocol version - */ -#define XPP_PROTOCOL_VERSION 29 - -struct xpd_addr { - uint8_t unit:UNIT_BITS; - uint8_t subunit:SUBUNIT_BITS; - uint8_t reserved:1; - uint8_t sync_master:1; -} PACKED; - -struct xpacket_header { - uint16_t packet_len:10; - uint16_t reserved:1; - uint16_t is_pcm:1; - uint16_t pcmslot:4; - uint8_t opcode; - struct xpd_addr addr; -} PACKED; - -#define XPACKET_OP(p) ((p)->head.opcode) -#define XPACKET_LEN(p) ((p)->head.packet_len) -#define XPACKET_IS_PCM(p) ((p)->head.is_pcm) -#define XPACKET_PCMSLOT(p) ((p)->head.pcmslot) -#define XPACKET_RESERVED(p) ((p)->head.reserved) -#define XPACKET_ADDR(p) ((p)->head.addr) -#define XPACKET_ADDR_UNIT(p) (XPACKET_ADDR(p).unit) -#define XPACKET_ADDR_SUBUNIT(p) (XPACKET_ADDR(p).subunit) -#define XPACKET_ADDR_SYNC(p) (XPACKET_ADDR(p).sync_master) -#define XPACKET_ADDR_RESERVED(p) (XPACKET_ADDR(p).reserved) - -#define PROTO_TABLE(n) n ## _protocol_table - -/* - * The LSB of the type number signifies: - * 0 - TO_PSTN - * 1 - TO_PHONE - */ -#define XPD_TYPE_FXS 3 // TO_PHONE -#define XPD_TYPE_FXO 4 // TO_PSTN -#define XPD_TYPE_BRI_TE 6 // TO_PSTN -#define XPD_TYPE_BRI_NT 7 // TO_PHONE -#define XPD_TYPE_PRI 9 // TO_PSTN/TO_PHONE (runtime) -#define XPD_TYPE_NOMODULE 15 - -typedef byte xpd_type_t; - -#define XPD_TYPE_PREFIX "xpd-type-" - -#define MODULE_ALIAS_XPD(type) \ - MODULE_ALIAS(XPD_TYPE_PREFIX __stringify(type)) - -#define PCM_CHUNKSIZE (CHANNELS_PERXPD * 8) /* samples of 8 bytes */ - -bool valid_xpd_addr(const struct xpd_addr *addr); - -#define XPROTO_NAME(card,op) card ## _ ## op -#define XPROTO_HANDLER(card,op) XPROTO_NAME(card,op ## _handler) -#define XPROTO_CALLER(card,op) XPROTO_NAME(card,op ## _send) - -#define HANDLER_DEF(card,op) \ - static int XPROTO_HANDLER(card,op) ( \ - xbus_t *xbus, \ - xpd_t *xpd, \ - const xproto_entry_t *cmd, \ - xpacket_t *pack) - -#define CALL_PROTO(card,op, ...) XPROTO_CALLER(card,op)( __VA_ARGS__ ) - -#define DECLARE_CMD(card,op, ...) \ - int CALL_PROTO(card, op, xbus_t *xbus, xpd_t *xpd, ## __VA_ARGS__ ) - -#define HOSTCMD(card, op, ...) \ - DECLARE_CMD(card, op, ## __VA_ARGS__ ) - -#define RPACKET_NAME(card,op) XPROTO_NAME(RPACKET_ ## card, op) -#define RPACKET_TYPE(card,op) struct RPACKET_NAME(card, op) - -#define DEF_RPACKET_DATA(card,op, ...) \ - RPACKET_TYPE(card,op) { \ - struct xpacket_header head; \ - __VA_ARGS__ \ - } PACKED -#define RPACKET_HEADERSIZE sizeof(struct xpacket_header) -#define RPACKET_FIELD(p,card,op,field) (((RPACKET_TYPE(card,op) *)(p))->field) -#define RPACKET_SIZE(card,op) sizeof(RPACKET_TYPE(card,op)) - -#define XENTRY(prototab,module,op) \ - [ XPROTO_NAME(module,op) ] = { \ - .handler = XPROTO_HANDLER(module,op), \ - .datalen = RPACKET_SIZE(module,op), \ - .name = #op, \ - .table = &PROTO_TABLE(prototab) \ - } - -#define XPACKET_INIT(p, card, op, to, pcm, pcmslot) \ - do { \ - XPACKET_OP(p) = XPROTO_NAME(card,op); \ - XPACKET_LEN(p) = RPACKET_SIZE(card,op); \ - XPACKET_IS_PCM(p) = (pcm); \ - XPACKET_PCMSLOT(p) = (pcmslot); \ - XPACKET_RESERVED(p) = 0; \ - XPACKET_ADDR_UNIT(p) = XBUS_UNIT(to); \ - XPACKET_ADDR_SUBUNIT(p) = XBUS_SUBUNIT(to); \ - XPACKET_ADDR_SYNC(p) = 0; \ - XPACKET_ADDR_RESERVED(p) = 0; \ - } while(0) - -#define XFRAME_NEW_CMD(frm, p, xbus, card, op, to) \ - do { \ - int len = RPACKET_SIZE(card,op); \ - \ - if(!TRANSPORT_RUNNING(xbus)) \ - return -ENODEV; \ - frm = ALLOC_SEND_XFRAME(xbus); \ - if(!frm) \ - return -ENOMEM; \ - (p) = xframe_next_packet(frm, len); \ - if(!(p)) \ - return -ENOMEM; \ - XPACKET_INIT(p, card, op, to, 0, 0); \ - } while(0) - -#endif - -/*--------------------------- register handling --------------------------------*/ -/* - * After the opcode, there are always: - * * A size (in bytes) of the rest. Only 6 bits are counted: - * - The MSB signifies a multibyte write (to BRI fifo) - * - The MSB-1 signifies end of frame to multibyte writes in BRI. - * A normal register command (not multibyte) than contains: - * * A channel selector byte: - * - ALL_CHANS (currently 31) is a broadcast request to set a - * register for all channels. - * - Smaller numbers (0-30) represent the addressed channel number. - * - The MSB signifies: - * 1 - register [R]ead request - * 0 - register [W]rite request - * * Register number - * * Subregister number -- 0 when there is no subregister - * * Data low - * * Data high -- 0 for single byte registers (direct registers) - * A multibyte register command than contains a sequence of bytes. - */ - -#define MULTIBYTE_MAX_LEN 5 /* FPGA firmware limitation */ - -typedef struct reg_cmd { - byte bytes:6; - byte eoframe:1; /* For BRI -- end of frame */ - byte multibyte:1; /* For BRI -- fifo data */ - union { - struct { - byte chipsel:CHAN_BITS; /* chip select */ - byte reserved:1; - byte do_subreg:1; - byte read_request:1; - byte regnum; - byte subreg; - byte data_low; - byte data_high; - } PACKED r; - /* For Write-Multibyte commands in BRI */ - struct { - byte xdata[MULTIBYTE_MAX_LEN]; - } PACKED d; - } PACKED alt; -} PACKED reg_cmd_t; - -/* Shortcut access macros */ -#define REG_FIELD(regptr,member) ((regptr)->alt.r.member) -#define REG_XDATA(regptr) ((regptr)->alt.d.xdata) - -#ifdef __KERNEL__ -/*--------------------------- protocol tables ----------------------------------*/ - -typedef struct xproto_entry xproto_entry_t; -typedef struct xproto_table xproto_table_t; - -typedef int (*xproto_handler_t)( - xbus_t *xbus, - xpd_t *xpd, - const xproto_entry_t *cmd, - xpacket_t *pack); - -const xproto_table_t *xproto_get(xpd_type_t cardtype); -void xproto_put(const xproto_table_t *xtable); -const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, byte opcode); -xproto_handler_t xproto_card_handler(const xproto_table_t *table, byte opcode); - -const xproto_entry_t *xproto_global_entry(byte opcode); -xproto_handler_t xproto_global_handler(byte opcode); - -#define CALL_XMETHOD(name, xbus, xpd, ...) \ - (xpd)->xops->name(xbus, xpd, ## __VA_ARGS__ ) - -struct xops { - xpd_t *(*card_new)(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table, byte subtype, byte revision); - int (*card_init)(xbus_t *xbus, xpd_t *xpd); - int (*card_remove)(xbus_t *xbus, xpd_t *xpd); - int (*card_tick)(xbus_t *xbus, xpd_t *xpd); - void (*card_pcm_fromspan)(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, xpacket_t *pack); - void (*card_pcm_tospan)(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack); - int (*card_zaptel_preregistration)(xpd_t *xpd, bool on); - int (*card_zaptel_postregistration)(xpd_t *xpd, bool on); - int (*card_hooksig)(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig); - int (*card_ioctl)(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg); - int (*card_open)(xpd_t *xpd, lineno_t pos); - int (*card_close)(xpd_t *xpd, lineno_t pos); - int (*card_register_reply)(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *reg); - - int (*XPD_STATE)(xbus_t *xbus, xpd_t *xpd, bool on); - int (*RING)(xbus_t *xbus, xpd_t *xpd, lineno_t chan, bool on); - int (*RELAY_OUT)(xbus_t *xbus, xpd_t *xpd, byte which, bool on); -}; - -struct xproto_entry { - xproto_handler_t handler; - int datalen; - const char *name; - xproto_table_t *table; -}; - -struct xproto_table { - struct module *owner; - xproto_entry_t entries[256]; /* Indexed by opcode */ - xops_t xops; - xpd_type_t type; - const char *name; - bool (*packet_is_valid)(xpacket_t *pack); - void (*packet_dump)(const char *msg, xpacket_t *pack); -}; - -#include "card_global.h" -#include "card_fxs.h" -#include "card_fxo.h" -#include "card_bri.h" -#include "card_pri.h" - - -#define MEMBER(card,op) RPACKET_TYPE(card,op) RPACKET_NAME(card,op) - -struct xpacket { - struct xpacket_header head; - union { - MEMBER(GLOBAL, NULL_REPLY); - MEMBER(GLOBAL, DESC_REQ); - MEMBER(GLOBAL, DEV_DESC); - MEMBER(GLOBAL, PCM_WRITE); - MEMBER(GLOBAL, PCM_READ); - MEMBER(GLOBAL, SYNC_REPLY); - MEMBER(GLOBAL, ERROR_CODE); - - MEMBER(FXS, SIG_CHANGED); - MEMBER(FXO, SIG_CHANGED); - - byte data[0]; - }; - /* Last byte is chksum */ -} PACKED; - -void dump_packet(const char *msg, const xpacket_t *packet, bool print_dbg); -void dump_reg_cmd(const char msg[], const reg_cmd_t *regcmd, bool writing); -int xframe_receive(xbus_t *xbus, xframe_t *xframe); -void notify_bad_xpd(const char *funcname, xbus_t *xbus, const struct xpd_addr addr, const char *msg); -int xproto_register(const xproto_table_t *proto_table); -void xproto_unregister(const xproto_table_t *proto_table); -const xproto_entry_t *xproto_global_entry(byte opcode); -const char *xproto_name(xpd_type_t xpd_type); - -#endif /* __KERNEL__ */ - -#endif /* XPROTO_H */ diff --git a/xpp/zap_debug.c b/xpp/zap_debug.c deleted file mode 100644 index bf54e62..0000000 --- a/xpp/zap_debug.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -# warning "This module is tested only with 2.6 kernels" -#endif - -#include -#include -#include -#include -#include "zap_debug.h" -#include "xdefs.h" - -static const char rcsid[] = "$Id$"; - -#define P_(x) [ x ] = { .value = x, .name = #x, } -static struct { - int value; - char *name; -} poll_names[] = { - P_(POLLIN), - P_(POLLPRI), - P_(POLLOUT), - P_(POLLERR), - P_(POLLHUP), - P_(POLLNVAL), - P_(POLLRDNORM), - P_(POLLRDBAND), - P_(POLLWRNORM), - P_(POLLWRBAND), - P_(POLLMSG), - P_(POLLREMOVE) -}; -#undef P_ - -void dump_poll(int print_dbg, const char *msg, int poll) -{ - int i; - - for(i = 0; i < ARRAY_SIZE(poll_names); i++) { - if(poll & poll_names[i].value) - DBG(GENERAL, "%s: %s\n", msg, poll_names[i].name); - } -} - -void alarm2str(int alarm, char *buf, int buflen) -{ - char *p = buf; - int left = buflen; - int i; - int n; - - if(!alarm) { - snprintf(buf, buflen, "NONE"); - return; - } - memset(buf, 0, buflen); - for(i = 0; i < 8; i++) { - if(left && (alarm & BIT(i))) { - n = snprintf(p, left, "%s,", alarmbit2str(i)); - p += n; - left -= n; - } - } - if(p > buf) /* kill last comma */ - *(p - 1) = '\0'; -} - -EXPORT_SYMBOL(dump_poll); -EXPORT_SYMBOL(alarm2str); diff --git a/xpp/zap_debug.h b/xpp/zap_debug.h deleted file mode 100644 index fb1ecc3..0000000 --- a/xpp/zap_debug.h +++ /dev/null @@ -1,190 +0,0 @@ -#ifndef ZAP_DEBUG_H -#define ZAP_DEBUG_H -/* - * Written by Oron Peled - * Copyright (C) 2004-2006, Xorcom - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include /* for zt_* defs */ - -/* Debugging Macros */ - -#define PRINTK(level, category, fmt, ...) \ - printk(KERN_ ## level "%s%s-%s: " fmt, #level, category, THIS_MODULE->name, ## __VA_ARGS__) - -#define XBUS_PRINTK(level, category, xbus, fmt, ...) \ - printk(KERN_ ## level "%s%s-%s: %s: " fmt, #level, \ - category, THIS_MODULE->name, (xbus)->busname, ## __VA_ARGS__) - -#define XPD_PRINTK(level, category, xpd, fmt, ...) \ - printk(KERN_ ## level "%s%s-%s: %s/%s: " fmt, #level, \ - category, THIS_MODULE->name, (xpd)->xbus->busname, (xpd)->xpdname, ## __VA_ARGS__) - -#define LINE_PRINTK(level, category, xpd, pos, fmt, ...) \ - printk(KERN_ ## level "%s%s-%s: %s/%s/%d: " fmt, #level, \ - category, THIS_MODULE->name, (xpd)->xbus->busname, (xpd)->xpdname, (pos), ## __VA_ARGS__) - -#define DBG(bits, fmt, ...) \ - ((void)((print_dbg & (DBG_ ## bits)) && PRINTK(DEBUG, "-" #bits, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))) -#define INFO(fmt, ...) PRINTK(INFO, "", fmt, ## __VA_ARGS__) -#define NOTICE(fmt, ...) PRINTK(NOTICE, "", fmt, ## __VA_ARGS__) -#define WARNING(fmt, ...) PRINTK(WARNING, "", fmt, ## __VA_ARGS__) -#define ERR(fmt, ...) PRINTK(ERR, "", fmt, ## __VA_ARGS__) - -#define XBUS_DBG(bits, xbus, fmt, ...) \ - ((void)((print_dbg & (DBG_ ## bits)) && XBUS_PRINTK(DEBUG, "-" #bits, xbus, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))) -#define XBUS_INFO(xbus, fmt, ...) XBUS_PRINTK(INFO, "", xbus, fmt, ## __VA_ARGS__) -#define XBUS_NOTICE(xbus, fmt, ...) XBUS_PRINTK(NOTICE, "", xbus, fmt, ## __VA_ARGS__) -#define XBUS_ERR(xbus, fmt, ...) XBUS_PRINTK(ERR, "", xbus, fmt, ## __VA_ARGS__) - -#define XPD_DBG(bits, xpd, fmt, ...) \ - ((void)((print_dbg & (DBG_ ## bits)) && XPD_PRINTK(DEBUG, "-" #bits, xpd, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))) -#define XPD_INFO(xpd, fmt, ...) XPD_PRINTK(INFO, "", xpd, fmt, ## __VA_ARGS__) -#define XPD_NOTICE(xpd, fmt, ...) XPD_PRINTK(NOTICE, "", xpd, fmt, ## __VA_ARGS__) -#define XPD_WARNING(xpd, fmt, ...) XPD_PRINTK(WARNING, "", xpd, fmt, ## __VA_ARGS__) -#define XPD_ERR(xpd, fmt, ...) XPD_PRINTK(ERR, "", xpd, fmt, ## __VA_ARGS__) - -#define LINE_DBG(bits, xpd, pos, fmt, ...) \ - ((void)((print_dbg & (DBG_ ## bits)) && LINE_PRINTK(DEBUG, "-" #bits, xpd, pos, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))) -#define LINE_NOTICE(xpd, pos, fmt, ...) LINE_PRINTK(NOTICE, "", xpd, pos, fmt, ## __VA_ARGS__) -#define LINE_ERR(xpd, pos, fmt, ...) LINE_PRINTK(ERR, "", xpd, pos, fmt, ## __VA_ARGS__) - -/* - * Bits for print_dbg - */ -#define DBG_GENERAL BIT(0) -#define DBG_PCM BIT(1) -#define DBG_LEDS BIT(2) -#define DBG_SYNC BIT(3) -#define DBG_SIGNAL BIT(4) -#define DBG_PROC BIT(5) -#define DBG_REGS BIT(6) -#define DBG_DEVICES BIT(7) /* instanciation/destruction etc. */ -#define DBG_ANY (~0) - -void dump_poll(int print_dbg, const char *msg, int poll); - -static inline char *rxsig2str(zt_rxsig_t sig) -{ - switch(sig) { - case ZT_RXSIG_ONHOOK: return "ONHOOK"; - case ZT_RXSIG_OFFHOOK: return "OFFHOOK"; - case ZT_RXSIG_START: return "START"; - case ZT_RXSIG_RING: return "RING"; - case ZT_RXSIG_INITIAL: return "INITIAL"; - } - return "Unknown rxsig"; -} - -static inline char *txsig2str(zt_txsig_t sig) -{ - switch(sig) { - case ZT_TXSIG_ONHOOK: return "TXSIG_ONHOOK"; - case ZT_TXSIG_OFFHOOK: return "TXSIG_OFFHOOK"; - case ZT_TXSIG_START: return "TXSIG_START"; - case ZT_TXSIG_KEWL: return "TXSIG_KEWL"; /* Drop battery if possible */ - } - return "Unknown txsig"; -} - -static inline char *event2str(int event) -{ - switch(event) { - case ZT_EVENT_NONE: return "NONE"; - case ZT_EVENT_ONHOOK: return "ONHOOK"; - case ZT_EVENT_RINGOFFHOOK: return "RINGOFFHOOK"; - case ZT_EVENT_WINKFLASH: return "WINKFLASH"; - case ZT_EVENT_ALARM: return "ALARM"; - case ZT_EVENT_NOALARM: return "NOALARM"; - case ZT_EVENT_ABORT: return "ABORT"; - case ZT_EVENT_OVERRUN: return "OVERRUN"; - case ZT_EVENT_BADFCS: return "BADFCS"; - case ZT_EVENT_DIALCOMPLETE: return "DIALCOMPLETE"; - case ZT_EVENT_RINGERON: return "RINGERON"; - case ZT_EVENT_RINGEROFF: return "RINGEROFF"; - case ZT_EVENT_HOOKCOMPLETE: return "HOOKCOMPLETE"; - case ZT_EVENT_BITSCHANGED: return "BITSCHANGED"; - case ZT_EVENT_PULSE_START: return "PULSE_START"; - case ZT_EVENT_TIMER_EXPIRED: return "TIMER_EXPIRED"; - case ZT_EVENT_TIMER_PING: return "TIMER_PING"; - case ZT_EVENT_POLARITY: return "POLARITY"; - } - return "Unknown event"; -} - -static inline char *hookstate2str(int hookstate) -{ - switch(hookstate) { - case ZT_ONHOOK: return "ZT_ONHOOK"; - case ZT_START: return "ZT_START"; - case ZT_OFFHOOK: return "ZT_OFFHOOK"; - case ZT_WINK: return "ZT_WINK"; - case ZT_FLASH: return "ZT_FLASH"; - case ZT_RING: return "ZT_RING"; - case ZT_RINGOFF: return "ZT_RINGOFF"; - } - return "Unknown hookstate"; -} - -/* From zaptel.c */ -static inline char *sig2str(int sig) -{ - switch (sig) { - case ZT_SIG_FXSLS: return "FXSLS"; - case ZT_SIG_FXSKS: return "FXSKS"; - case ZT_SIG_FXSGS: return "FXSGS"; - case ZT_SIG_FXOLS: return "FXOLS"; - case ZT_SIG_FXOKS: return "FXOKS"; - case ZT_SIG_FXOGS: return "FXOGS"; - case ZT_SIG_EM: return "E&M"; - case ZT_SIG_EM_E1: return "E&M-E1"; - case ZT_SIG_CLEAR: return "Clear"; - case ZT_SIG_HDLCRAW: return "HDLCRAW"; - case ZT_SIG_HDLCFCS: return "HDLCFCS"; - case ZT_SIG_HDLCNET: return "HDLCNET"; - case ZT_SIG_SLAVE: return "Slave"; - case ZT_SIG_CAS: return "CAS"; - case ZT_SIG_DACS: return "DACS"; - case ZT_SIG_DACS_RBS: return "DACS+RBS"; - case ZT_SIG_SF: return "SF (ToneOnly)"; - case ZT_SIG_NONE: - break; - } - return "Unconfigured"; -} - -static inline char *alarmbit2str(int alarmbit) -{ - /* from zaptel.h */ - switch(1 << alarmbit) { - case ZT_ALARM_NONE: return "NONE"; - case ZT_ALARM_RECOVER: return "RECOVER"; - case ZT_ALARM_LOOPBACK: return "LOOPBACK"; - case ZT_ALARM_YELLOW: return "YELLOW"; - case ZT_ALARM_RED: return "RED"; - case ZT_ALARM_BLUE: return "BLUE"; - case ZT_ALARM_NOTOPEN: return "NOTOPEN"; - } - return "UNKNOWN"; -} - -void alarm2str(int alarm, char *buf, int buflen); - -#endif /* ZAP_DEBUG_H */ diff --git a/zaptel-base.c b/zaptel-base.c deleted file mode 100644 index 45b08f2..0000000 --- a/zaptel-base.c +++ /dev/null @@ -1,7451 +0,0 @@ -/* - * Zapata Telephony Interface Driver - * - * Written by Mark Spencer - * Based on previous works, designs, and architectures conceived and - * written by Jim Dixon . - * - * Special thanks to Steve Underwood - * for substantial contributions to signal processing functions - * in zaptel and the zapata library. - * - * Yury Bokhoncovich - * Adaptation for 2.4.20+ kernels (HDLC API was changed) - * The work has been performed as a part of our move - * from Cisco 3620 to IBM x305 here in F1 Group - * - * Copyright (C) 2001 Jim Dixon / Zapata Telephony. - * Copyright (C) 2001 -2006 Digium, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#include "zconfig.h" -#include "version.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_DEVFS_FS -#include -#endif /* CONFIG_DEVFS_FS */ -#ifdef CONFIG_ZAPATA_NET -#include -#endif /* CONFIG_ZAPATA_NET */ -#include -#ifdef CONFIG_ZAPATA_PPP -#include -#include -#include -#endif -#include - -#ifndef CONFIG_OLD_HDLC_API -#define NEW_HDLC_INTERFACE -#endif - -#define __ECHO_STATE_MUTE (1 << 8) -#define ECHO_STATE_IDLE (0) -#define ECHO_STATE_PRETRAINING (1 | (__ECHO_STATE_MUTE)) -#define ECHO_STATE_STARTTRAINING (2 | (__ECHO_STATE_MUTE)) -#define ECHO_STATE_AWAITINGECHO (3 | (__ECHO_STATE_MUTE)) -#define ECHO_STATE_TRAINING (4 | (__ECHO_STATE_MUTE)) -#define ECHO_STATE_ACTIVE (5) - -/* #define BUF_MUNGE */ - -/* Grab fasthdlc with tables */ -#define FAST_HDLC_NEED_TABLES -#include "fasthdlc.h" - -#include "zaptel.h" - -#ifdef LINUX26 -#include -#endif - -/* Get helper arithmetic */ -#include "arith.h" -#if defined(CONFIG_ZAPTEL_MMX) || defined(ECHO_CAN_FP) -#include -#endif - -#define hdlc_to_ztchan(h) (((struct zt_hdlc *)(h))->chan) -#define dev_to_ztchan(h) (((struct zt_hdlc *)(dev_to_hdlc(h)->priv))->chan) -#ifdef LINUX26 -#define ztchan_to_dev(h) ((h)->hdlcnetdev->netdev) -#else -#define ztchan_to_dev(h) (&((h)->hdlcnetdev->netdev.netdev)) -#endif - -/* macro-oni for determining a unit (channel) number */ -#define UNIT(file) MINOR(file->f_dentry->d_inode->i_rdev) - -/* names of tx level settings */ -static char *zt_txlevelnames[] = { -"0 db (CSU)/0-133 feet (DSX-1)", -"133-266 feet (DSX-1)", -"266-399 feet (DSX-1)", -"399-533 feet (DSX-1)", -"533-655 feet (DSX-1)", -"-7.5db (CSU)", -"-15db (CSU)", -"-22.5db (CSU)" -} ; - -EXPORT_SYMBOL(zt_transcode_fops); -EXPORT_SYMBOL(zt_init_tone_state); -EXPORT_SYMBOL(zt_dtmf_tone); -EXPORT_SYMBOL(zt_register); -EXPORT_SYMBOL(zt_unregister); -EXPORT_SYMBOL(__zt_mulaw); -EXPORT_SYMBOL(__zt_alaw); -#ifdef CONFIG_CALC_XLAW -EXPORT_SYMBOL(__zt_lineartoulaw); -EXPORT_SYMBOL(__zt_lineartoalaw); -#else -EXPORT_SYMBOL(__zt_lin2mu); -EXPORT_SYMBOL(__zt_lin2a); -#endif -EXPORT_SYMBOL(zt_lboname); -EXPORT_SYMBOL(zt_transmit); -EXPORT_SYMBOL(zt_receive); -EXPORT_SYMBOL(zt_rbsbits); -EXPORT_SYMBOL(zt_qevent_nolock); -EXPORT_SYMBOL(zt_qevent_lock); -EXPORT_SYMBOL(zt_hooksig); -EXPORT_SYMBOL(zt_alarm_notify); -EXPORT_SYMBOL(zt_set_dynamic_ioctl); -EXPORT_SYMBOL(zt_ec_chunk); -EXPORT_SYMBOL(zt_ec_span); -EXPORT_SYMBOL(zt_hdlc_abort); -EXPORT_SYMBOL(zt_hdlc_finish); -EXPORT_SYMBOL(zt_hdlc_getbuf); -EXPORT_SYMBOL(zt_hdlc_putbuf); -EXPORT_SYMBOL(zt_alarm_channel); -EXPORT_SYMBOL(zt_register_chardev); -EXPORT_SYMBOL(zt_unregister_chardev); - -#ifdef CONFIG_PROC_FS -static struct proc_dir_entry *proc_entries[ZT_MAX_SPANS]; -#endif - -/* Here are a couple important little additions for devfs */ -#ifdef CONFIG_DEVFS_FS -#define ZT_DEVFS_MODE (S_IFCHR|S_IRUGO|S_IWUGO) -static devfs_handle_t zaptel_devfs_dir; -static devfs_handle_t channel; -static devfs_handle_t pseudo; -static devfs_handle_t ctl; -static devfs_handle_t timer; -#endif - -/* udev necessary data structures. Yeah! */ -#ifdef CONFIG_ZAP_UDEV - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) -#define CLASS_DEV_CREATE(class, devt, device, name) \ - class_device_create(class, NULL, devt, device, name) -#else -#define CLASS_DEV_CREATE(class, devt, device, name) \ - class_device_create(class, devt, device, name) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) -static struct class *zap_class = NULL; -#else -static struct class_simple *zap_class = NULL; -#define class_create class_simple_create -#define class_destroy class_simple_destroy -#define class_device_create class_simple_device_add -#define class_device_destroy(a, b) class_simple_device_remove(b) -#endif - -#endif /* CONFIG_ZAP_UDEV */ - - -/* There is a table like this in the PPP driver, too */ - -static int deftaps = 64; - -#if !defined(LINUX26) -static -__u16 fcstab[256] = -{ - 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, - 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, - 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, - 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, - 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, - 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, - 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, - 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, - 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, - 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, - 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, - 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, - 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, - 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, - 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, - 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, - 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, - 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, - 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, - 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, - 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, - 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, - 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, - 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, - 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, - 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, - 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, - 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, - 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, - 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, - 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, - 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 -}; -#endif - -static int debug; - -/* states for transmit signalling */ -typedef enum {ZT_TXSTATE_ONHOOK,ZT_TXSTATE_OFFHOOK,ZT_TXSTATE_START, - ZT_TXSTATE_PREWINK,ZT_TXSTATE_WINK,ZT_TXSTATE_PREFLASH, - ZT_TXSTATE_FLASH,ZT_TXSTATE_DEBOUNCE,ZT_TXSTATE_AFTERSTART, - ZT_TXSTATE_RINGON,ZT_TXSTATE_RINGOFF,ZT_TXSTATE_KEWL, - ZT_TXSTATE_AFTERKEWL,ZT_TXSTATE_PULSEBREAK,ZT_TXSTATE_PULSEMAKE, - ZT_TXSTATE_PULSEAFTER - } ZT_TXSTATE_t; - -typedef short sumtype[ZT_MAX_CHUNKSIZE]; - -static sumtype sums[(ZT_MAX_CONF + 1) * 3]; - -/* Translate conference aliases into actual conferences - and vice-versa */ -static short confalias[ZT_MAX_CONF + 1]; -static short confrev[ZT_MAX_CONF + 1]; - -static sumtype *conf_sums_next; -static sumtype *conf_sums; -static sumtype *conf_sums_prev; - -static struct zt_span *master; -static struct file_operations zt_fops; -struct file_operations *zt_transcode_fops = NULL; - -static struct -{ - int src; /* source conf number */ - int dst; /* dst conf number */ -} conf_links[ZT_MAX_CONF + 1]; - - -/* There are three sets of conference sum accumulators. One for the current -sample chunk (conf_sums), one for the next sample chunk (conf_sums_next), and -one for the previous sample chunk (conf_sums_prev). The following routine -(rotate_sums) "rotates" the pointers to these accululator arrays as part -of the events of sample chink processing as follows: - -The following sequence is designed to be looked at from the reference point -of the receive routine of the master span. - -1. All (real span) receive chunks are processed (with putbuf). The last one -to be processed is the master span. The data received is loaded into the -accumulators for the next chunk (conf_sums_next), to be in alignment with -current data after rotate_sums() is called (which immediately follows). -Keep in mind that putbuf is *also* a transmit routine for the pseudo parts -of channels that are in the REALANDPSEUDO conference mode. These channels -are processed from data in the current sample chunk (conf_sums), being -that this is a "transmit" function (for the pseudo part). - -2. rotate_sums() is called. - -3. All pseudo channel receive chunks are processed. This data is loaded into -the current sample chunk accumulators (conf_sums). - -4. All conference links are processed (being that all receive data for this -chunk has already been processed by now). - -5. All pseudo channel transmit chunks are processed. This data is loaded from -the current sample chunk accumulators (conf_sums). - -6. All (real span) transmit chunks are processed (with getbuf). This data is -loaded from the current sample chunk accumulators (conf_sums). Keep in mind -that getbuf is *also* a receive routine for the pseudo part of channels that -are in the REALANDPSEUDO conference mode. These samples are loaded into -the next sample chunk accumulators (conf_sums_next) to be processed as part -of the next sample chunk's data (next time around the world). - -*/ - -#define DIGIT_MODE_DTMF 0 -#define DIGIT_MODE_MFV1 1 -#define DIGIT_MODE_PULSE 2 - -#include "digits.h" - -static struct zt_dialparams global_dialparams = { - .dtmf_tonelen = DEFAULT_DTMF_LENGTH, - .mfv1_tonelen = DEFAULT_MFV1_LENGTH, -}; - -static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit); - -#if defined(CONFIG_ZAPTEL_MMX) || defined(ECHO_CAN_FP) -/* XXX kernel_fpu_begin() is NOT exported properly (in 2.4), so we have to make - a local version. Somebody fix this! XXX */ - -#ifndef LINUX26 -static inline void __save_init_fpu( struct task_struct *tsk ) -{ - if ( cpu_has_fxsr ) { - asm volatile( "fxsave %0 ; fnclex" - : "=m" (tsk->thread.i387.fxsave) ); - } else { - asm volatile( "fnsave %0 ; fwait" - : "=m" (tsk->thread.i387.fsave) ); - } - tsk->flags &= ~PF_USEDFPU; -} - -static inline void zt_kernel_fpu_begin(void) -{ - struct task_struct *tsk = current; - if (tsk->flags & PF_USEDFPU) { - __save_init_fpu(tsk); - return; - } - clts(); -} -#else -#define zt_kernel_fpu_begin kernel_fpu_begin -#endif /* LINUX26 */ -#endif - -static struct zt_timer { - int ms; /* Countdown */ - int pos; /* Position */ - int ping; /* Whether we've been ping'd */ - int tripped; /* Whether we're tripped */ - struct zt_timer *next; /* Linked list */ - wait_queue_head_t sel; -} *zaptimers = NULL; - -#ifdef DEFINE_SPINLOCK -static DEFINE_SPINLOCK(zaptimerlock); -static DEFINE_SPINLOCK(bigzaplock); -#else -static spinlock_t zaptimerlock = SPIN_LOCK_UNLOCKED; -static spinlock_t bigzaplock = SPIN_LOCK_UNLOCKED; -#endif - -struct zt_zone { - atomic_t refcount; - char name[40]; /* Informational, only */ - int ringcadence[ZT_MAX_CADENCE]; - struct zt_tone *tones[ZT_TONE_MAX]; - /* Each of these is a circular list - of zt_tones to generate what we - want. Use NULL if the tone is - unavailable */ - struct zt_tone dtmf[16]; /* DTMF tones for this zone, with desired length */ - struct zt_tone dtmf_continuous[16]; /* DTMF tones for this zone, continuous play */ - struct zt_tone mf[15]; /* MF tones for this zone, with desired length */ - struct zt_tone mf_continuous[15]; /* MF tones for this zone, continuous play */ -}; - -static struct zt_span *spans[ZT_MAX_SPANS]; -static struct zt_chan *chans[ZT_MAX_CHANNELS]; - -static int maxspans = 0; -static int maxchans = 0; -static int maxconfs = 0; -static int maxlinks = 0; - -static int default_zone = -1; - -short __zt_mulaw[256]; -short __zt_alaw[256]; - -#ifndef CONFIG_CALC_XLAW -u_char __zt_lin2mu[16384]; - -u_char __zt_lin2a[16384]; -#endif - -static u_char defgain[256]; - -#ifdef DEFINE_RWLOCK -static DEFINE_RWLOCK(zone_lock); -static DEFINE_RWLOCK(chan_lock); -#else -static rwlock_t zone_lock = RW_LOCK_UNLOCKED; -static rwlock_t chan_lock = RW_LOCK_UNLOCKED; -#endif - -static struct zt_zone *tone_zones[ZT_TONE_ZONE_MAX]; - -#define NUM_SIGS 10 - - -/* Echo cancellation */ -#if defined(ECHO_CAN_HPEC) -#include "hpec/hpec_zaptel.h" -#elif defined(ECHO_CAN_STEVE) -#include "sec.h" -#elif defined(ECHO_CAN_STEVE2) -#include "sec-2.h" -#elif defined(ECHO_CAN_KB1) -#include "kb1ec.h" -#elif defined(ECHO_CAN_MG2) -#include "mg2ec.h" -#elif defined(ECHO_CAN_JP1) -#include "jpah.h" -#endif - -static inline void rotate_sums(void) -{ - /* Rotate where we sum and so forth */ - static int pos = 0; - conf_sums_prev = sums + (ZT_MAX_CONF + 1) * pos; - conf_sums = sums + (ZT_MAX_CONF + 1) * ((pos + 1) % 3); - conf_sums_next = sums + (ZT_MAX_CONF + 1) * ((pos + 2) % 3); - pos = (pos + 1) % 3; - memset(conf_sums_next, 0, maxconfs * sizeof(sumtype)); -} - - /* return quiescent (idle) signalling states, for the various signalling types */ -static int zt_q_sig(struct zt_chan *chan) -{ -int x; - -static unsigned int in_sig[NUM_SIGS][2] = { - { ZT_SIG_NONE, 0}, - { ZT_SIG_EM, 0 | (ZT_ABIT << 8)}, - { ZT_SIG_FXSLS,ZT_BBIT | (ZT_BBIT << 8)}, - { ZT_SIG_FXSGS,ZT_ABIT | ZT_BBIT | ((ZT_ABIT | ZT_BBIT) << 8)}, - { ZT_SIG_FXSKS,ZT_BBIT | ZT_BBIT | ((ZT_ABIT | ZT_BBIT) << 8)}, - { ZT_SIG_FXOLS,0 | (ZT_ABIT << 8)}, - { ZT_SIG_FXOGS,ZT_BBIT | ((ZT_ABIT | ZT_BBIT) << 8)}, - { ZT_SIG_FXOKS,0 | (ZT_ABIT << 8)}, - { ZT_SIG_SF, 0}, - { ZT_SIG_EM_E1, ZT_DBIT | ((ZT_ABIT | ZT_DBIT) << 8) }, - } ; - - /* must have span to begin with */ - if (!chan->span) return(-1); - /* if RBS does not apply, return error */ - if (!(chan->span->flags & ZT_FLAG_RBS) || - !chan->span->rbsbits) return(-1); - if (chan->sig == ZT_SIG_CAS) - return chan->idlebits; - for (x=0;xsig) return(in_sig[x][1]); - } return(-1); /* not found -- error */ -} - -#ifdef CONFIG_PROC_FS -static char *sigstr(int sig) -{ - switch (sig) { - case ZT_SIG_FXSLS: - return "FXSLS"; - case ZT_SIG_FXSKS: - return "FXSKS"; - case ZT_SIG_FXSGS: - return "FXSGS"; - case ZT_SIG_FXOLS: - return "FXOLS"; - case ZT_SIG_FXOKS: - return "FXOKS"; - case ZT_SIG_FXOGS: - return "FXOGS"; - case ZT_SIG_EM: - return "E&M"; - case ZT_SIG_EM_E1: - return "E&M-E1"; - case ZT_SIG_CLEAR: - return "Clear"; - case ZT_SIG_HDLCRAW: - return "HDLCRAW"; - case ZT_SIG_HDLCFCS: - return "HDLCFCS"; - case ZT_SIG_HDLCNET: - return "HDLCNET"; - case ZT_SIG_HARDHDLC: - return "Hardware-assisted HDLC"; - case ZT_SIG_SLAVE: - return "Slave"; - case ZT_SIG_CAS: - return "CAS"; - case ZT_SIG_DACS: - return "DACS"; - case ZT_SIG_DACS_RBS: - return "DACS+RBS"; - case ZT_SIG_SF: - return "SF (ToneOnly)"; - case ZT_SIG_NONE: - default: - return "Unconfigured"; - } - -} - -static int zaptel_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int x, len = 0; - long span; - - /* In Linux 2.6, this MUST NOT EXECEED 1024 bytes in one read! */ - - span = (long)data; - - if (!span) - return 0; - - if (spans[span]->name) - len += sprintf(page + len, "Span %ld: %s ", span, spans[span]->name); - if (spans[span]->desc) - len += sprintf(page + len, "\"%s\"", spans[span]->desc); - else - len += sprintf(page + len, "\"\""); - - if(spans[span] == master) - len += sprintf(page + len, " (MASTER)"); - - if (spans[span]->lineconfig) { - /* framing first */ - if (spans[span]->lineconfig & ZT_CONFIG_B8ZS) - len += sprintf(page + len, " B8ZS/"); - else if (spans[span]->lineconfig & ZT_CONFIG_AMI) - len += sprintf(page + len, " AMI/"); - else if (spans[span]->lineconfig & ZT_CONFIG_HDB3) - len += sprintf(page + len, " HDB3/"); - /* then coding */ - if (spans[span]->lineconfig & ZT_CONFIG_ESF) - len += sprintf(page + len, "ESF"); - else if (spans[span]->lineconfig & ZT_CONFIG_D4) - len += sprintf(page + len, "D4"); - else if (spans[span]->lineconfig & ZT_CONFIG_CCS) - len += sprintf(page + len, "CCS"); - /* E1's can enable CRC checking */ - if (spans[span]->lineconfig & ZT_CONFIG_CRC4) - len += sprintf(page + len, "/CRC4"); - } - - len += sprintf(page + len, " "); - - /* list alarms */ - if (spans[span]->alarms && (spans[span]->alarms > 0)) { - if (spans[span]->alarms & ZT_ALARM_BLUE) - len += sprintf(page + len, "BLUE "); - if (spans[span]->alarms & ZT_ALARM_YELLOW) - len += sprintf(page + len, "YELLOW "); - if (spans[span]->alarms & ZT_ALARM_RED) - len += sprintf(page + len, "RED "); - if (spans[span]->alarms & ZT_ALARM_LOOPBACK) - len += sprintf(page + len, "LOOP "); - if (spans[span]->alarms & ZT_ALARM_RECOVER) - len += sprintf(page + len, "RECOVERING "); - if (spans[span]->alarms & ZT_ALARM_NOTOPEN) - len += sprintf(page + len, "NOTOPEN "); - - } - if (spans[span]->syncsrc && (spans[span]->syncsrc == spans[span]->spanno)) - len += sprintf(page + len, "ClockSource "); - len += sprintf(page + len, "\n"); - if (spans[span]->bpvcount) - len += sprintf(page + len, "\tBPV count: %d\n", spans[span]->bpvcount); - if (spans[span]->crc4count) - len += sprintf(page + len, "\tCRC4 error count: %d\n", spans[span]->crc4count); - if (spans[span]->ebitcount) - len += sprintf(page + len, "\tE-bit error count: %d\n", spans[span]->ebitcount); - if (spans[span]->fascount) - len += sprintf(page + len, "\tFAS error count: %d\n", spans[span]->fascount); - if (spans[span]->irqmisses) - len += sprintf(page + len, "\tIRQ misses: %d\n", spans[span]->irqmisses); - if (spans[span]->timingslips) - len += sprintf(page + len, "\tTiming slips: %d\n", spans[span]->timingslips); - len += sprintf(page + len, "\n"); - - - for (x=1;xspan && (chans[x]->span->spanno == span)) { - if (chans[x]->name) - len += sprintf(page + len, "\t%4d %s ", x, chans[x]->name); - if (chans[x]->sig) { - if (chans[x]->sig == ZT_SIG_SLAVE) - len += sprintf(page + len, "%s ", sigstr(chans[x]->master->sig)); - else { - len += sprintf(page + len, "%s ", sigstr(chans[x]->sig)); - if (chans[x]->nextslave && chans[x]->master->channo == x) - len += sprintf(page + len, "Master "); - } - } - if ((chans[x]->flags & ZT_FLAG_OPEN)) { - len += sprintf(page + len, "(In use) "); - } -#ifdef OPTIMIZE_CHANMUTE - if ((chans[x]->chanmute)) { - len += sprintf(page + len, "(no pcm) "); - } -#endif - len += sprintf(page + len, "\n"); - } - if (len <= off) { /* If everything printed so far is before beginning of request */ - off -= len; - len = 0; - } - if (len > off+count) /* stop if we've already generated enough */ - break; - } - } - if (len <= off) { /* If everything printed so far is before beginning of request */ - off -= len; - len = 0; - } - *start = page + off; - len -= off; /* un-count any remaining offset */ - if (len > count) len = count; /* don't return bytes not asked for */ - return len; -} -#endif - -static int zt_first_empty_alias(void) -{ - /* Find the first conference which has no alias pointing to it */ - int x; - for (x=1;x0;x--) { - if (confrev[x]) { - maxconfs = x+1; - return; - } - } - maxconfs = 0; -} - -static void recalc_maxlinks(void) -{ - int x; - for (x=ZT_MAX_CONF-1;x>0;x--) { - if (conf_links[x].src || conf_links[x].dst) { - maxlinks = x+1; - return; - } - } - maxlinks = 0; -} - -static int zt_first_empty_conference(void) -{ - /* Find the first conference which has no alias */ - int x; - for (x=ZT_MAX_CONF-1;x>0;x--) { - if (!confalias[x]) - return x; - } - return -1; -} - -static int zt_get_conf_alias(int x) -{ - int a; - if (confalias[x]) { - return confalias[x]; - } - - /* Allocate an alias */ - a = zt_first_empty_alias(); - confalias[x] = a; - confrev[a] = x; - - /* Highest conference may have changed */ - recalc_maxconfs(); - return a; -} - -static void zt_check_conf(int x) -{ - int y; - - /* return if no valid conf number */ - if (x <= 0) return; - /* Return if there is no alias */ - if (!confalias[x]) - return; - for (y=0;yconfna == x) && - ((chans[y]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_CONF || - (chans[y]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_CONFANN || - (chans[y]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_CONFMON || - (chans[y]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_CONFANNMON || - (chans[y]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_REALANDPSEUDO)) - return; - } - /* If we get here, nobody is in the conference anymore. Clear it out - both forward and reverse */ - confrev[confalias[x]] = 0; - confalias[x] = 0; - - /* Highest conference may have changed */ - recalc_maxconfs(); -} - -/* enqueue an event on a channel */ -static void __qevent(struct zt_chan *chan, int event) -{ - - /* if full, ignore */ - if ((chan->eventoutidx == 0) && (chan->eventinidx == (ZT_MAX_EVENTSIZE - 1))) - return; - /* if full, ignore */ - if (chan->eventinidx == (chan->eventoutidx - 1)) return; - /* save the event */ - chan->eventbuf[chan->eventinidx++] = event; - /* wrap the index, if necessary */ - if (chan->eventinidx >= ZT_MAX_EVENTSIZE) chan->eventinidx = 0; - /* wake em all up */ - if (chan->iomask & ZT_IOMUX_SIGEVENT) wake_up_interruptible(&chan->eventbufq); - wake_up_interruptible(&chan->readbufq); - wake_up_interruptible(&chan->writebufq); - wake_up_interruptible(&chan->sel); - return; -} - -void zt_qevent_nolock(struct zt_chan *chan, int event) -{ - __qevent(chan, event); -} - -void zt_qevent_lock(struct zt_chan *chan, int event) -{ - unsigned long flags; - spin_lock_irqsave(&chan->lock, flags); - __qevent(chan, event); - spin_unlock_irqrestore(&chan->lock, flags); -} - -/* sleep in user space until woken up. Equivilant of tsleep() in BSD */ -static int schluffen(wait_queue_head_t *q) -{ - DECLARE_WAITQUEUE(wait, current); - add_wait_queue(q, &wait); - current->state = TASK_INTERRUPTIBLE; - if (!signal_pending(current)) schedule(); - current->state = TASK_RUNNING; - remove_wait_queue(q, &wait); - if (signal_pending(current)) { - return -ERESTARTSYS; - } - return(0); -} - -static inline void calc_fcs(struct zt_chan *ss, int inwritebuf) -{ - int x; - unsigned int fcs=PPP_INITFCS; - unsigned char *data = ss->writebuf[inwritebuf]; - int len = ss->writen[inwritebuf]; - /* Not enough space to do FCS calculation */ - if (len < 2) - return; - for (x=0;x> 8) & 0xff; -} - -static int zt_reallocbufs(struct zt_chan *ss, int j, int numbufs) -{ - unsigned char *newbuf, *oldbuf; - unsigned long flags; - int x; - /* Check numbufs */ - if (numbufs < 2) - numbufs = 2; - if (numbufs > ZT_MAX_NUM_BUFS) - numbufs = ZT_MAX_NUM_BUFS; - /* We need to allocate our buffers now */ - if (j) { - newbuf = kmalloc(j * 2 * numbufs, GFP_KERNEL); - if (!newbuf) - return (-ENOMEM); - } else - newbuf = NULL; - /* Now that we've allocated our new buffer, we can safely - move things around... */ - spin_lock_irqsave(&ss->lock, flags); - ss->blocksize = j; /* set the blocksize */ - oldbuf = ss->readbuf[0]; /* Keep track of the old buffer */ - ss->readbuf[0] = NULL; - if (newbuf) { - for (x=0;xreadbuf[x] = newbuf + x * j; - ss->writebuf[x] = newbuf + (numbufs + x) * j; - } - } else { - for (x=0;xreadbuf[x] = NULL; - ss->writebuf[x] = NULL; - } - } - /* Mark all buffers as empty */ - for (x=0;xwriten[x] = - ss->writeidx[x]= - ss->readn[x]= - ss->readidx[x] = 0; - - /* Keep track of where our data goes (if it goes - anywhere at all) */ - if (newbuf) { - ss->inreadbuf = 0; - ss->inwritebuf = 0; - } else { - ss->inreadbuf = -1; - ss->inwritebuf = -1; - } - ss->outreadbuf = -1; - ss->outwritebuf = -1; - ss->numbufs = numbufs; - if (ss->txbufpolicy == ZT_POLICY_WHEN_FULL) - ss->txdisable = 1; - else - ss->txdisable = 0; - - if (ss->rxbufpolicy == ZT_POLICY_WHEN_FULL) - ss->rxdisable = 1; - else - ss->rxdisable = 0; - - spin_unlock_irqrestore(&ss->lock, flags); - if (oldbuf) - kfree(oldbuf); - return 0; -} - -static int zt_hangup(struct zt_chan *chan); -static void zt_set_law(struct zt_chan *chan, int law); - -/* Pull a ZT_CHUNKSIZE piece off the queue. Returns - 0 on success or -1 on failure. If failed, provides - silence */ -static int __buf_pull(struct confq *q, u_char *data, struct zt_chan *c, char *label) -{ - int oldoutbuf = q->outbuf; - /* Ain't nuffin to read */ - if (q->outbuf < 0) { - if (data) - memset(data, ZT_LIN2X(0,c), ZT_CHUNKSIZE); - return -1; - } - if (data) - memcpy(data, q->buf[q->outbuf], ZT_CHUNKSIZE); - q->outbuf = (q->outbuf + 1) % ZT_CB_SIZE; - - /* Won't be nuffin next time */ - if (q->outbuf == q->inbuf) { - q->outbuf = -1; - } - - /* If they thought there was no space then - there is now where we just read */ - if (q->inbuf < 0) - q->inbuf = oldoutbuf; - return 0; -} - -/* Returns a place to put stuff, or NULL if there is - no room */ - -static u_char *__buf_pushpeek(struct confq *q) -{ - if (q->inbuf < 0) - return NULL; - return q->buf[q->inbuf]; -} - -static u_char *__buf_peek(struct confq *q) -{ - if (q->outbuf < 0) - return NULL; - return q->buf[q->outbuf]; -} - -#ifdef BUF_MUNGE -static u_char *__buf_cpush(struct confq *q) -{ - int pos; - /* If we have no space, return where the - last space that we *did* have was */ - if (q->inbuf > -1) - return NULL; - pos = q->outbuf - 1; - if (pos < 0) - pos += ZT_CB_SIZE; - return q->buf[pos]; -} - -static void __buf_munge(struct zt_chan *chan, u_char *old, u_char *new) -{ - /* Run a weighted average of the old and new, in order to - mask a missing sample */ - int x; - int val; - for (x=0;xinbuf; - if (q->inbuf < 0) { - return -1; - } - if (data) - /* Copy in the data */ - memcpy(q->buf[q->inbuf], data, ZT_CHUNKSIZE); - - /* Advance the inbuf pointer */ - q->inbuf = (q->inbuf + 1) % ZT_CB_SIZE; - - if (q->inbuf == q->outbuf) { - /* No space anymore... */ - q->inbuf = -1; - } - /* If they don't think data is ready, let - them know it is now */ - if (q->outbuf < 0) { - q->outbuf = oldinbuf; - } - return 0; -} - -static void reset_conf(struct zt_chan *chan) -{ - int x; - /* Empty out buffers and reset to initialization */ - for (x=0;xconfin.buf[x] = chan->confin.buffer + ZT_CHUNKSIZE * x; - chan->confin.inbuf = 0; - chan->confin.outbuf = -1; - - for (x=0;xconfout.buf[x] = chan->confout.buffer + ZT_CHUNKSIZE * x; - chan->confout.inbuf = 0; - chan->confout.outbuf = -1; -} - - -static void close_channel(struct zt_chan *chan) -{ - unsigned long flags; - void *rxgain = NULL; - struct echo_can_state *ec = NULL; - int oldconf; - short *readchunkpreec; -#ifdef CONFIG_ZAPATA_PPP - struct ppp_channel *ppp; -#endif - - /* XXX Buffers should be send out before reallocation!!! XXX */ - if (!(chan->flags & ZT_FLAG_NOSTDTXRX)) - zt_reallocbufs(chan, 0, 0); - spin_lock_irqsave(&chan->lock, flags); -#ifdef CONFIG_ZAPATA_PPP - ppp = chan->ppp; - chan->ppp = NULL; -#endif - ec = chan->ec; - chan->ec = NULL; - readchunkpreec = chan->readchunkpreec; - chan->readchunkpreec = NULL; - chan->curtone = NULL; - if (chan->curzone) - atomic_dec(&chan->curzone->refcount); - chan->curzone = NULL; - chan->cadencepos = 0; - chan->pdialcount = 0; - zt_hangup(chan); - chan->itimerset = chan->itimer = 0; - chan->pulsecount = 0; - chan->pulsetimer = 0; - chan->ringdebtimer = 0; - init_waitqueue_head(&chan->sel); - init_waitqueue_head(&chan->readbufq); - init_waitqueue_head(&chan->writebufq); - init_waitqueue_head(&chan->eventbufq); - init_waitqueue_head(&chan->txstateq); - chan->txdialbuf[0] = '\0'; - chan->digitmode = DIGIT_MODE_DTMF; - chan->dialing = 0; - chan->afterdialingtimer = 0; - /* initialize IO MUX mask */ - chan->iomask = 0; - /* save old conf number, if any */ - oldconf = chan->confna; - /* initialize conference variables */ - chan->_confn = 0; - if ((chan->sig & __ZT_SIG_DACS) != __ZT_SIG_DACS) { - chan->confna = 0; - chan->confmode = 0; - } - chan->confmute = 0; - /* release conference resource, if any to release */ - if (oldconf) zt_check_conf(oldconf); - chan->gotgs = 0; - reset_conf(chan); - - if (chan->gainalloc && chan->rxgain) - rxgain = chan->rxgain; - - chan->rxgain = defgain; - chan->txgain = defgain; - chan->gainalloc = 0; - chan->eventinidx = chan->eventoutidx = 0; - chan->flags &= ~(ZT_FLAG_LOOPED | ZT_FLAG_LINEAR | ZT_FLAG_PPP | ZT_FLAG_SIGFREEZE); - - zt_set_law(chan,0); - - memset(chan->conflast, 0, sizeof(chan->conflast)); - memset(chan->conflast1, 0, sizeof(chan->conflast1)); - memset(chan->conflast2, 0, sizeof(chan->conflast2)); - - if (chan->span && chan->span->dacs && oldconf) - chan->span->dacs(chan, NULL); - - spin_unlock_irqrestore(&chan->lock, flags); - - if (chan->span && chan->span->echocan) - chan->span->echocan(chan, 0); - - if (rxgain) - kfree(rxgain); - if (ec) - echo_can_free(ec); - if (readchunkpreec) - kfree(readchunkpreec); - -#ifdef CONFIG_ZAPATA_PPP - if (ppp) { - tasklet_kill(&chan->ppp_calls); - skb_queue_purge(&chan->ppp_rq); - ppp_unregister_channel(ppp); - kfree(ppp); - } -#endif - -} - -static int free_tone_zone(int num) -{ - struct zt_zone *z; - - if ((num >= ZT_TONE_ZONE_MAX) || (num < 0)) - return -EINVAL; - - write_lock(&zone_lock); - z = tone_zones[num]; - tone_zones[num] = NULL; - write_unlock(&zone_lock); - if (!z) - return 0; - - if (atomic_read(&z->refcount)) { - /* channels are still using this zone so put it back */ - write_lock(&zone_lock); - tone_zones[num] = z; - write_unlock(&zone_lock); - - return -EBUSY; - } else { - kfree(z); - - return 0; - } -} - -static int zt_register_tone_zone(int num, struct zt_zone *zone) -{ - int res = 0; - - if ((num >= ZT_TONE_ZONE_MAX) || (num < 0)) - return -EINVAL; - - write_lock(&zone_lock); - if (tone_zones[num]) { - res = -EINVAL; - } else { - res = 0; - tone_zones[num] = zone; - } - write_unlock(&zone_lock); - - if (!res) - printk(KERN_INFO "Registered tone zone %d (%s)\n", num, zone->name); - - return res; -} - -static int start_tone(struct zt_chan *chan, int tone) -{ - int res = -EINVAL; - - /* Stop the current tone, no matter what */ - chan->tonep = 0; - chan->curtone = NULL; - chan->pdialcount = 0; - chan->txdialbuf[0] = '\0'; - chan->dialing = 0; - - if (tone == -1) { - /* Just stop the current tone */ - res = 0; - } else if ((tone >= 0 && tone <= ZT_TONE_MAX)) { - if (chan->curzone) { - /* Have a tone zone */ - if (chan->curzone->tones[tone]) { - chan->curtone = chan->curzone->tones[tone]; - res = 0; - } else /* Indicate that zone is loaded but no such tone exists */ - res = -ENOSYS; - } else /* Note that no tone zone exists at the moment */ - res = -ENODATA; - } else if (tone >= ZT_TONE_DTMF_BASE && tone <= ZT_TONE_DTMF_MAX) { - /* ZT_SENDTONE should never be used on a channel configured for pulse dialing */ - chan->dialing = 1; - res = 0; - if ((chan->digitmode == DIGIT_MODE_DTMF) && - (tone >= ZT_TONE_DTMF_BASE) && - (tone <= ZT_TONE_DTMF_MAX)) - chan->curtone = &chan->curzone->dtmf_continuous[tone - ZT_TONE_DTMF_BASE]; - else if ((chan->digitmode == DIGIT_MODE_MFV1) && - (tone >= ZT_TONE_MF_BASE) && - (tone <= ZT_TONE_MF_MAX)) - chan->curtone = &chan->curzone->mf_continuous[tone - ZT_TONE_MF_BASE]; - else { - chan->dialing = 0; - res = -EINVAL; - } - } - - if (chan->curtone) - zt_init_tone_state(&chan->ts, chan->curtone); - - return res; -} - -static int set_tone_zone(struct zt_chan *chan, int zone) -{ - int res = 0; - struct zt_zone *z; - unsigned long flags; - - /* Do not call with the channel locked. */ - - if (zone == -1) - zone = default_zone; - - if ((zone >= ZT_TONE_ZONE_MAX) || (zone < 0)) - return -EINVAL; - - read_lock(&zone_lock); - - if ((z = tone_zones[zone])) { - spin_lock_irqsave(&chan->lock, flags); - if (chan->curzone) - atomic_dec(&chan->curzone->refcount); - - atomic_inc(&z->refcount); - chan->curzone = z; - chan->tonezone = zone; - memcpy(chan->ringcadence, z->ringcadence, sizeof(chan->ringcadence)); - spin_unlock_irqrestore(&chan->lock, flags); - } else { - res = -ENODATA; - } - - read_unlock(&zone_lock); - - return res; -} - -static void zt_set_law(struct zt_chan *chan, int law) -{ - if (!law) { - if (chan->deflaw) - law = chan->deflaw; - else - if (chan->span) law = chan->span->deflaw; - else law = ZT_LAW_MULAW; - } - if (law == ZT_LAW_ALAW) { - chan->xlaw = __zt_alaw; -#ifdef CONFIG_CALC_XLAW - chan->lineartoxlaw = __zt_lineartoalaw; -#else - chan->lin2x = __zt_lin2a; -#endif - } else { - chan->xlaw = __zt_mulaw; -#ifdef CONFIG_CALC_XLAW - chan->lineartoxlaw = __zt_lineartoulaw; -#else - chan->lin2x = __zt_lin2mu; -#endif - } -} - -#ifdef CONFIG_DEVFS_FS -static devfs_handle_t register_devfs_channel(struct zt_chan *chan, devfs_handle_t dir) -{ - char path[100]; - char link[100]; - char buf[50]; - char tmp[100]; - int link_offset = 0; - int tmp_offset = 0; - int path_offset = 0; - int err = 0; - devfs_handle_t chan_dev; - umode_t mode = S_IFCHR|S_IRUGO|S_IWUGO; - unsigned int flags = DEVFS_FL_AUTO_OWNER; - - sprintf(path, "%d", chan->chanpos); - chan_dev = devfs_register(dir, path, flags, ZT_MAJOR, chan->channo, mode, &zt_fops, NULL); - if (!chan_dev) { - printk("zaptel: Something really bad happened. Unable to register devfs entry\n"); - return NULL; - } - - /* Set up the path of the destination of the link */ - link_offset = devfs_generate_path(chan_dev, link, sizeof(link) - 1); - /* Now we need to strip off the leading "zap/". If we don't, then we build a broken symlink */ - path_offset = devfs_generate_path(zaptel_devfs_dir, path, sizeof(path) - 1); /* We'll just "borrow" path for a second */ - path_offset = strlen(path+path_offset); - link_offset += path_offset; /* Taking out the "zap" */ - link_offset++; /* Add one more place for the '/'. The path generated does not contain the '/' we need to strip */ - - /* Set up the path of the file/link itself */ - tmp_offset = devfs_generate_path(zaptel_devfs_dir, tmp, sizeof(tmp) - 1); - sprintf(buf, "/%d", chan->channo); - strncpy(path, tmp+tmp_offset, sizeof(path) - 1); - strncat(path, buf, sizeof(path) - 1); - - err = devfs_mk_symlink(NULL, path, DEVFS_FL_DEFAULT, link+link_offset, &chan->fhandle_symlink, NULL); - if (err != 0) { - printk("Problem with making devfs symlink: %d\n", err); - } - - return chan_dev; -} -#endif /* CONFIG_DEVFS_FS */ - -static int zt_chan_reg(struct zt_chan *chan) -{ - int x; - int res=0; - unsigned long flags; - - write_lock_irqsave(&chan_lock, flags); - for (x=1;xlock); - chans[x] = chan; - if (maxchans < x + 1) - maxchans = x + 1; - chan->channo = x; - if (!chan->master) - chan->master = chan; - if (!chan->readchunk) - chan->readchunk = chan->sreadchunk; - if (!chan->writechunk) - chan->writechunk = chan->swritechunk; - zt_set_law(chan, 0); - close_channel(chan); - /* set this AFTER running close_channel() so that - HDLC channels wont cause hangage */ - chan->flags |= ZT_FLAG_REGISTERED; - res = 0; - break; - } - } - write_unlock_irqrestore(&chan_lock, flags); - if (x >= ZT_MAX_CHANNELS) - printk(KERN_ERR "No more channels available\n"); - return res; -} - -char *zt_lboname(int x) -{ - if ((x < 0) || ( x > 7)) - return "Unknown"; - return zt_txlevelnames[x]; -} - -#if defined(CONFIG_ZAPATA_NET) || defined(CONFIG_ZAPATA_PPP) -#endif - -#ifdef CONFIG_ZAPATA_NET -#ifdef NEW_HDLC_INTERFACE -static int zt_net_open(struct net_device *dev) -{ -#ifdef LINUX26 - int res = hdlc_open(dev); - struct zt_chan *ms = dev_to_ztchan(dev); -#else - hdlc_device *hdlc = dev_to_hdlc(dev); - struct zt_chan *ms = hdlc_to_ztchan(hdlc); - int res = hdlc_open(hdlc); -#endif - -/* if (!dev->hard_start_xmit) return res; is this really necessary? --byg */ - if (res) /* this is necessary to avoid kernel panic when UNSPEC link encap, proven --byg */ - return res; -#else -static int zt_net_open(hdlc_device *hdlc) -{ - struct zt_chan *ms = hdlc_to_ztchan(hdlc); - int res; -#endif - if (!ms) { - printk("zt_net_open: nothing??\n"); - return -EINVAL; - } - if (ms->flags & ZT_FLAG_OPEN) { - printk("%s is already open!\n", ms->name); - return -EBUSY; - } - if (!(ms->flags & ZT_FLAG_NETDEV)) { - printk("%s is not a net device!\n", ms->name); - return -EINVAL; - } - ms->txbufpolicy = ZT_POLICY_IMMEDIATE; - ms->rxbufpolicy = ZT_POLICY_IMMEDIATE; - - res = zt_reallocbufs(ms, ZT_DEFAULT_MTU_MRU, ZT_DEFAULT_NUM_BUFS); - if (res) - return res; - - fasthdlc_init(&ms->rxhdlc); - fasthdlc_init(&ms->txhdlc); - ms->infcs = PPP_INITFCS; - - netif_start_queue(ztchan_to_dev(ms)); - -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#endif -#ifdef CONFIG_ZAPATA_DEBUG - printk("ZAPNET: Opened channel %d name %s\n", ms->channo, ms->name); -#endif - return 0; -} - -#ifdef LINUX26 -static int zt_register_hdlc_device(struct net_device *dev, const char *dev_name) -{ - int result; - - if (dev_name && *dev_name) { - if ((result = dev_alloc_name(dev, dev_name)) < 0) - return result; - } - result = register_netdev(dev); - if (result != 0) - return -EIO; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,14) - if (netif_carrier_ok(dev)) - netif_carrier_off(dev); /* no carrier until DCD goes up */ -#endif - return 0; -} -#endif - -#ifdef NEW_HDLC_INTERFACE -static int zt_net_stop(struct net_device *dev) -{ -#ifdef LINUX26 - hdlc_device *h = dev_to_hdlc(dev); - struct zt_hdlc *hdlc = h->priv; -#else - hdlc_device *hdlc = dev_to_hdlc(dev); -#endif - -#else -static void zt_net_close(hdlc_device *hdlc) -{ -#endif - struct zt_chan *ms = hdlc_to_ztchan(hdlc); - if (!ms) { -#ifdef NEW_HDLC_INTERFACE - printk("zt_net_stop: nothing??\n"); - return 0; -#else - printk("zt_net_close: nothing??\n"); - return; -#endif - } - if (!(ms->flags & ZT_FLAG_NETDEV)) { -#ifdef NEW_HDLC_INTERFACE - printk("zt_net_stop: %s is not a net device!\n", ms->name); - return 0; -#else - printk("zt_net_close: %s is not a net device!\n", ms->name); - return; -#endif - } - /* Not much to do here. Just deallocate the buffers */ - netif_stop_queue(ztchan_to_dev(ms)); - zt_reallocbufs(ms, 0, 0); -#ifdef LINUX26 - hdlc_close(dev); -#else -#ifndef CONFIG_OLD_HDLC_API - hdlc_close(hdlc); -#endif -#endif -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#endif -#ifdef NEW_HDLC_INTERFACE - return 0; -#else - return; -#endif -} - -#ifdef NEW_HDLC_INTERFACE -/* kernel 2.4.20+ has introduced attach function, dunno what to do, - just copy sources from dscc4 to be sure and ready for further mastering, - NOOP right now (i.e. really a stub) --byg */ -#ifdef LINUX26 -static int zt_net_attach(struct net_device *dev, unsigned short encoding, - unsigned short parity) -#else -static int zt_net_attach(hdlc_device *hdlc, unsigned short encoding, - unsigned short parity) -#endif -{ -/* struct net_device *dev = hdlc_to_dev(hdlc); - struct dscc4_dev_priv *dpriv = dscc4_priv(dev); - - if (encoding != ENCODING_NRZ && - encoding != ENCODING_NRZI && - encoding != ENCODING_FM_MARK && - encoding != ENCODING_FM_SPACE && - encoding != ENCODING_MANCHESTER) - return -EINVAL; - - if (parity != PARITY_NONE && - parity != PARITY_CRC16_PR0_CCITT && - parity != PARITY_CRC16_PR1_CCITT && - parity != PARITY_CRC32_PR0_CCITT && - parity != PARITY_CRC32_PR1_CCITT) - return -EINVAL; - - dpriv->encoding = encoding; - dpriv->parity = parity;*/ - return 0; -} -#endif - -static struct zt_hdlc *zt_hdlc_alloc(void) -{ - struct zt_hdlc *tmp; - tmp = kmalloc(sizeof(struct zt_hdlc), GFP_KERNEL); - if (tmp) { - memset(tmp, 0, sizeof(struct zt_hdlc)); - } - return tmp; -} - -#ifdef NEW_HDLC_INTERFACE -static int zt_xmit(struct sk_buff *skb, struct net_device *dev) -{ - /* FIXME: this construction seems to be not very optimal for me but I could find nothing better at the moment (Friday, 10PM :( ) --byg */ -/* struct zt_chan *ss = hdlc_to_ztchan(list_entry(dev, struct zt_hdlc, netdev.netdev));*/ -#ifdef LINUX26 - struct zt_chan *ss = dev_to_ztchan(dev); - struct net_device_stats *stats = hdlc_stats(dev); -#else - struct zt_chan *ss = (list_entry(dev, struct zt_hdlc, netdev.netdev)->chan); - struct net_device_stats *stats = &ss->hdlcnetdev->netdev.stats; -#endif - -#else -static int zt_xmit(hdlc_device *hdlc, struct sk_buff *skb) -{ - struct zt_chan *ss = hdlc_to_ztchan(hdlc); - struct net_device *dev = &ss->hdlcnetdev->netdev.netdev; - struct net_device_stats *stats = &ss->hdlcnetdev->netdev.stats; -#endif - int retval = 1; - int x,oldbuf; - unsigned int fcs; - unsigned char *data; - unsigned long flags; - /* See if we have any buffers */ - spin_lock_irqsave(&ss->lock, flags); - if (skb->len > ss->blocksize - 2) { - printk(KERN_ERR "zt_xmit(%s): skb is too large (%d > %d)\n", dev->name, skb->len, ss->blocksize -2); - stats->tx_dropped++; - retval = 0; - } else if (ss->inwritebuf >= 0) { - /* We have a place to put this packet */ - /* XXX We should keep the SKB and avoid the memcpy XXX */ - data = ss->writebuf[ss->inwritebuf]; - memcpy(data, skb->data, skb->len); - ss->writen[ss->inwritebuf] = skb->len; - ss->writeidx[ss->inwritebuf] = 0; - /* Calculate the FCS */ - fcs = PPP_INITFCS; - for (x=0;xlen;x++) - fcs = PPP_FCS(fcs, data[x]); - /* Invert it */ - fcs ^= 0xffff; - /* Send it out LSB first */ - data[ss->writen[ss->inwritebuf]++] = (fcs & 0xff); - data[ss->writen[ss->inwritebuf]++] = (fcs >> 8) & 0xff; - /* Advance to next window */ - oldbuf = ss->inwritebuf; - ss->inwritebuf = (ss->inwritebuf + 1) % ss->numbufs; - - if (ss->inwritebuf == ss->outwritebuf) { - /* Whoops, no more space. */ - ss->inwritebuf = -1; - - netif_stop_queue(ztchan_to_dev(ss)); - } - if (ss->outwritebuf < 0) { - /* Let the interrupt handler know there's - some space for us */ - ss->outwritebuf = oldbuf; - } - dev->trans_start = jiffies; - stats->tx_packets++; - stats->tx_bytes += ss->writen[oldbuf]; -#ifdef CONFIG_ZAPATA_DEBUG - printk("Buffered %d bytes to go out in buffer %d\n", ss->writen[oldbuf], oldbuf); - for (x=0;xwriten[oldbuf];x++) - printk("%02x ", ss->writebuf[oldbuf][x]); - printk("\n"); -#endif - retval = 0; - /* Free the SKB */ - dev_kfree_skb_any(skb); - } - spin_unlock_irqrestore(&ss->lock, flags); - return retval; -} - -#ifdef NEW_HDLC_INTERFACE -static int zt_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - return hdlc_ioctl(dev, ifr, cmd); -} -#else -static int zt_net_ioctl(hdlc_device *hdlc, struct ifreq *ifr, int cmd) -{ - return -EIO; -} -#endif - -#endif - -#ifdef CONFIG_ZAPATA_PPP - -static int zt_ppp_xmit(struct ppp_channel *ppp, struct sk_buff *skb) -{ - - /* - * If we can't handle the packet right now, return 0. If we - * we handle or drop it, return 1. Always free if we return - * 1 and never if we return 0 - */ - struct zt_chan *ss = ppp->private; - int x,oldbuf; - unsigned int fcs; - unsigned char *data; - long flags; - int retval = 0; - - /* See if we have any buffers */ - spin_lock_irqsave(&ss->lock, flags); - if (!(ss->flags & ZT_FLAG_OPEN)) { - printk("Can't transmit on closed channel\n"); - retval = 1; - } else if (skb->len > ss->blocksize - 4) { - printk(KERN_ERR "zt_ppp_xmit(%s): skb is too large (%d > %d)\n", ss->name, skb->len, ss->blocksize -2); - retval = 1; - } else if (ss->inwritebuf >= 0) { - /* We have a place to put this packet */ - /* XXX We should keep the SKB and avoid the memcpy XXX */ - data = ss->writebuf[ss->inwritebuf]; - /* Start with header of two bytes */ - /* Add "ALL STATIONS" and "UNNUMBERED" */ - data[0] = 0xff; - data[1] = 0x03; - ss->writen[ss->inwritebuf] = 2; - - /* Copy real data and increment amount written */ - memcpy(data + 2, skb->data, skb->len); - - ss->writen[ss->inwritebuf] += skb->len; - - /* Re-set index back to zero */ - ss->writeidx[ss->inwritebuf] = 0; - - /* Calculate the FCS */ - fcs = PPP_INITFCS; - for (x=0;xlen + 2;x++) - fcs = PPP_FCS(fcs, data[x]); - /* Invert it */ - fcs ^= 0xffff; - - /* Point past the real data now */ - data += (skb->len + 2); - - /* Send FCS out LSB first */ - data[0] = (fcs & 0xff); - data[1] = (fcs >> 8) & 0xff; - - /* Account for FCS length */ - ss->writen[ss->inwritebuf]+=2; - - /* Advance to next window */ - oldbuf = ss->inwritebuf; - ss->inwritebuf = (ss->inwritebuf + 1) % ss->numbufs; - - if (ss->inwritebuf == ss->outwritebuf) { - /* Whoops, no more space. */ - ss->inwritebuf = -1; - } - if (ss->outwritebuf < 0) { - /* Let the interrupt handler know there's - some space for us */ - ss->outwritebuf = oldbuf; - } -#ifdef CONFIG_ZAPATA_DEBUG - printk("Buffered %d bytes (skblen = %d) to go out in buffer %d\n", ss->writen[oldbuf], skb->len, oldbuf); - for (x=0;xwriten[oldbuf];x++) - printk("%02x ", ss->writebuf[oldbuf][x]); - printk("\n"); -#endif - retval = 1; - } - spin_unlock_irqrestore(&ss->lock, flags); - if (retval) { - /* Get rid of the SKB if we're returning non-zero */ - /* N.B. this is called in process or BH context so - dev_kfree_skb is OK. */ - dev_kfree_skb(skb); - } - return retval; -} - -static int zt_ppp_ioctl(struct ppp_channel *ppp, unsigned int cmd, unsigned long flags) -{ - return -EIO; -} - -static struct ppp_channel_ops ztppp_ops = -{ - start_xmit: zt_ppp_xmit, - ioctl: zt_ppp_ioctl, -}; - -#endif - -static void zt_chan_unreg(struct zt_chan *chan) -{ - int x; - unsigned long flags; -#ifdef CONFIG_ZAPATA_NET - if (chan->flags & ZT_FLAG_NETDEV) { -#ifdef LINUX26 - unregister_hdlc_device(chan->hdlcnetdev->netdev); - free_netdev(chan->hdlcnetdev->netdev); -#else - unregister_hdlc_device(&chan->hdlcnetdev->netdev); -#endif - kfree(chan->hdlcnetdev); - chan->hdlcnetdev = NULL; - } -#endif - write_lock_irqsave(&chan_lock, flags); - if (chan->flags & ZT_FLAG_REGISTERED) { - chans[chan->channo] = NULL; - chan->flags &= ~ZT_FLAG_REGISTERED; - } -#ifdef CONFIG_ZAPATA_PPP - if (chan->ppp) { - printk("HUH??? PPP still attached??\n"); - } -#endif - maxchans = 0; - for (x=1;xmaster == chan) { - chans[x]->master = chans[x]; - } - if ((chans[x]->confna == chan->channo) && - ((chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR || - (chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORTX || - (chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORBOTH || - (chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_RX_PREECHO || - (chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_TX_PREECHO || - (chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORBOTH_PREECHO || - (chans[x]->confmode & ZT_CONF_MODE_MASK) == ZT_CONF_DIGITALMON)) { - /* Take them out of conference with us */ - /* release conference resource if any */ - if (chans[x]->confna) { - zt_check_conf(chans[x]->confna); - if (chans[x]->span && chans[x]->span->dacs) - chans[x]->span->dacs(chans[x], NULL); - } - chans[x]->confna = 0; - chans[x]->_confn = 0; - chans[x]->confmode = 0; - } - } - chan->channo = -1; - write_unlock_irqrestore(&chan_lock, flags); -} - -static ssize_t zt_chan_read(struct file *file, char *usrbuf, size_t count, int unit) -{ - struct zt_chan *chan = chans[unit]; - int amnt; - int res, rv; - int oldbuf,x; - unsigned long flags; - /* Make sure count never exceeds 65k, and make sure it's unsigned */ - count &= 0xffff; - if (!chan) - return -EINVAL; - if (count < 1) - return -EINVAL; - for(;;) { - spin_lock_irqsave(&chan->lock, flags); - if (chan->eventinidx != chan->eventoutidx) { - spin_unlock_irqrestore(&chan->lock, flags); - return -ELAST /* - chan->eventbuf[chan->eventoutidx]*/; - } - res = chan->outreadbuf; - if (chan->rxdisable) - res = -1; - spin_unlock_irqrestore(&chan->lock, flags); - if (res >= 0) break; - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - rv = schluffen(&chan->readbufq); - if (rv) return (rv); - } - amnt = count; -/* added */ -#if 0 - if ((unit == 24) || (unit == 48) || (unit == 16) || (unit == 47)) { - int myamnt = amnt; - int x; - if (amnt > chan->readn[res]) - myamnt = chan->readn[res]; - printk("zt_chan_read(unit: %d, inwritebuf: %d, outwritebuf: %d amnt: %d\n", - unit, chan->inwritebuf, chan->outwritebuf, myamnt); - printk("\t("); for (x = 0; x < myamnt; x++) printk((x ? " %02x" : "%02x"), (unsigned char)usrbuf[x]); - printk(")\n"); - } -#endif -/* end addition */ - if (chan->flags & ZT_FLAG_LINEAR) { - if (amnt > (chan->readn[res] << 1)) - amnt = chan->readn[res] << 1; - if (amnt) { - /* There seems to be a max stack size, so we have - to do this in smaller pieces */ - short lindata[128]; - int left = amnt >> 1; /* amnt is in bytes */ - int pos = 0; - int pass; - while(left) { - pass = left; - if (pass > 128) - pass = 128; - for (x=0;xreadbuf[res][x + pos], chan); - if (copy_to_user(usrbuf + (pos << 1), lindata, pass << 1)) - return -EFAULT; - left -= pass; - pos += pass; - } - } - } else { - if (amnt > chan->readn[res]) - amnt = chan->readn[res]; - if (amnt) { - if (copy_to_user(usrbuf, chan->readbuf[res], amnt)) - return -EFAULT; - } - } - spin_lock_irqsave(&chan->lock, flags); - chan->readidx[res] = 0; - chan->readn[res] = 0; - oldbuf = res; - chan->outreadbuf = (res + 1) % chan->numbufs; - if (chan->outreadbuf == chan->inreadbuf) { - /* Out of stuff */ - chan->outreadbuf = -1; - if (chan->rxbufpolicy == ZT_POLICY_WHEN_FULL) - chan->rxdisable = 1; - } - if (chan->inreadbuf < 0) { - /* Notify interrupt handler that we have some space now */ - chan->inreadbuf = oldbuf; - } - spin_unlock_irqrestore(&chan->lock, flags); - - return amnt; -} - -static ssize_t zt_chan_write(struct file *file, const char *usrbuf, size_t count, int unit) -{ - unsigned long flags; - struct zt_chan *chan = chans[unit]; - int res, amnt, oldbuf, rv,x; - /* Make sure count never exceeds 65k, and make sure it's unsigned */ - count &= 0xffff; - if (!chan) - return -EINVAL; - if (count < 1) - return -EINVAL; - for(;;) { - spin_lock_irqsave(&chan->lock, flags); - if ((chan->curtone || chan->pdialcount) && !(chan->flags & ZT_FLAG_PSEUDO)) { - chan->curtone = NULL; - chan->tonep = 0; - chan->dialing = 0; - chan->txdialbuf[0] = '\0'; - chan->pdialcount = 0; - } - if (chan->eventinidx != chan->eventoutidx) { - spin_unlock_irqrestore(&chan->lock, flags); - return -ELAST; - } - res = chan->inwritebuf; - spin_unlock_irqrestore(&chan->lock, flags); - if (res >= 0) - break; - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - /* Wait for something to be available */ - rv = schluffen(&chan->writebufq); - if (rv) - return rv; - } - - amnt = count; - if (chan->flags & ZT_FLAG_LINEAR) { - if (amnt > (chan->blocksize << 1)) - amnt = chan->blocksize << 1; - } else { - if (amnt > chan->blocksize) - amnt = chan->blocksize; - } - -#ifdef CONFIG_ZAPATA_DEBUG - printk("zt_chan_write(unit: %d, res: %d, outwritebuf: %d amnt: %d\n", - unit, chan->res, chan->outwritebuf, amnt); -#endif -#if 0 - if ((unit == 24) || (unit == 48) || (unit == 16) || (unit == 47)) { - int x; - printk("zt_chan_write/in(unit: %d, res: %d, outwritebuf: %d amnt: %d, txdisable: %d)\n", - unit, res, chan->outwritebuf, amnt, chan->txdisable); - printk("\t("); for (x = 0; x < amnt; x++) printk((x ? " %02x" : "%02x"), (unsigned char)usrbuf[x]); - printk(")\n"); - } -#endif - - if (amnt) { - if (chan->flags & ZT_FLAG_LINEAR) { - /* There seems to be a max stack size, so we have - to do this in smaller pieces */ - short lindata[128]; - int left = amnt >> 1; /* amnt is in bytes */ - int pos = 0; - int pass; - while(left) { - pass = left; - if (pass > 128) - pass = 128; - if (copy_from_user(lindata, usrbuf + (pos << 1), pass << 1)) - return -EFAULT; - left -= pass; - for (x=0;xwritebuf[res][x + pos] = ZT_LIN2X(lindata[x], chan); - pos += pass; - } - chan->writen[res] = amnt >> 1; - } else { - if (copy_from_user(chan->writebuf[res], usrbuf, amnt)) - return -EFAULT; - chan->writen[res] = amnt; - } - chan->writeidx[res] = 0; - if (chan->flags & ZT_FLAG_FCS) - calc_fcs(chan, res); - oldbuf = res; - spin_lock_irqsave(&chan->lock, flags); - chan->inwritebuf = (res + 1) % chan->numbufs; - if (chan->inwritebuf == chan->outwritebuf) { - /* Don't stomp on the transmitter, just wait for them to - wake us up */ - chan->inwritebuf = -1; - /* Make sure the transmitter is transmitting in case of POLICY_WHEN_FULL */ - chan->txdisable = 0; - } - if (chan->outwritebuf < 0) { - /* Okay, the interrupt handler has been waiting for us. Give them a buffer */ - chan->outwritebuf = oldbuf; - } - spin_unlock_irqrestore(&chan->lock, flags); - - if (chan->flags & ZT_FLAG_NOSTDTXRX && chan->span->hdlc_hard_xmit) - chan->span->hdlc_hard_xmit(chan); - } - return amnt; -} - -static int zt_ctl_open(struct inode *inode, struct file *file) -{ - /* Nothing to do, really */ -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#endif - return 0; -} - -static int zt_chan_open(struct inode *inode, struct file *file) -{ - /* Nothing to do here for now either */ -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#endif - return 0; -} - -static int zt_ctl_release(struct inode *inode, struct file *file) -{ - /* Nothing to do */ -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#endif - return 0; -} - -static int zt_chan_release(struct inode *inode, struct file *file) -{ - /* Nothing to do for now */ -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#endif - return 0; -} - -static void set_txtone(struct zt_chan *ss,int fac, int init_v2, int init_v3) -{ - if (fac == 0) - { - ss->v2_1 = 0; - ss->v3_1 = 0; - return; - } - ss->txtone = fac; - ss->v1_1 = 0; - ss->v2_1 = init_v2; - ss->v3_1 = init_v3; - return; -} - -static void zt_rbs_sethook(struct zt_chan *chan, int txsig, int txstate, int timeout) -{ -static int outs[NUM_SIGS][5] = { -/* We set the idle case of the ZT_SIG_NONE to this pattern to make idle E1 CAS -channels happy. Should not matter with T1, since on an un-configured channel, -who cares what the sig bits are as long as they are stable */ - { ZT_SIG_NONE, ZT_ABIT | ZT_CBIT | ZT_DBIT, 0, 0, 0 }, /* no signalling */ - { ZT_SIG_EM, 0, ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, - ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, 0 }, /* E and M */ - { ZT_SIG_FXSLS, ZT_BBIT | ZT_DBIT, - ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, - ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, 0 }, /* FXS Loopstart */ - { ZT_SIG_FXSGS, ZT_BBIT | ZT_DBIT, -#ifdef CONFIG_CAC_GROUNDSTART - ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, 0, 0 }, /* FXS Groundstart (CAC-style) */ -#else - ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, ZT_ABIT | ZT_CBIT, 0 }, /* FXS Groundstart (normal) */ -#endif - { ZT_SIG_FXSKS, ZT_BBIT | ZT_DBIT, - ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, - ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, 0 }, /* FXS Kewlstart */ - { ZT_SIG_FXOLS, ZT_BBIT | ZT_DBIT, ZT_BBIT | ZT_DBIT, 0, 0 }, /* FXO Loopstart */ - { ZT_SIG_FXOGS, ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, - ZT_BBIT | ZT_DBIT, 0, 0 }, /* FXO Groundstart */ - { ZT_SIG_FXOKS, ZT_BBIT | ZT_DBIT, ZT_BBIT | ZT_DBIT, 0, - ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT }, /* FXO Kewlstart */ - { ZT_SIG_SF, ZT_BBIT | ZT_CBIT | ZT_DBIT, - ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, - ZT_ABIT | ZT_BBIT | ZT_CBIT | ZT_DBIT, - ZT_BBIT | ZT_CBIT | ZT_DBIT }, /* no signalling */ - { ZT_SIG_EM_E1, ZT_DBIT, ZT_ABIT | ZT_BBIT | ZT_DBIT, - ZT_ABIT | ZT_BBIT | ZT_DBIT, ZT_DBIT }, /* E and M E1 */ - } ; - int x; - - /* if no span, return doing nothing */ - if (!chan->span) return; - if (!chan->span->flags & ZT_FLAG_RBS) { - printk("zt_rbs: Tried to set RBS hook state on non-RBS channel %s\n", chan->name); - return; - } - if ((txsig > 3) || (txsig < 0)) { - printk("zt_rbs: Tried to set RBS hook state %d (> 3) on channel %s\n", txsig, chan->name); - return; - } - if (!chan->span->rbsbits && !chan->span->hooksig) { - printk("zt_rbs: Tried to set RBS hook state %d on channel %s while span %s lacks rbsbits or hooksig function\n", - txsig, chan->name, chan->span->name); - return; - } - /* Don't do anything for RBS */ - if (chan->sig == ZT_SIG_DACS_RBS) - return; - chan->txstate = txstate; - - /* if tone signalling */ - if (chan->sig == ZT_SIG_SF) - { - chan->txhooksig = txsig; - if (chan->txtone) /* if set to make tone for tx */ - { - if ((txsig && !(chan->toneflags & ZT_REVERSE_TXTONE)) || - ((!txsig) && (chan->toneflags & ZT_REVERSE_TXTONE))) - { - set_txtone(chan,chan->txtone,chan->tx_v2,chan->tx_v3); - } - else - { - set_txtone(chan,0,0,0); - } - } - chan->otimer = timeout * ZT_CHUNKSIZE; /* Otimer is timer in samples */ - return; - } - if (chan->span->hooksig) { - if (chan->txhooksig != txsig) { - chan->txhooksig = txsig; - chan->span->hooksig(chan, txsig); - } - chan->otimer = timeout * ZT_CHUNKSIZE; /* Otimer is timer in samples */ - return; - } else { - for (x=0;xsig) { -#ifdef CONFIG_ZAPATA_DEBUG - printk("Setting bits to %d for channel %s state %d in %d signalling\n", outs[x][txsig + 1], chan->name, txsig, chan->sig); -#endif - chan->txhooksig = txsig; - chan->txsig = outs[x][txsig+1]; - chan->span->rbsbits(chan, chan->txsig); - chan->otimer = timeout * ZT_CHUNKSIZE; /* Otimer is timer in samples */ - return; - } - } - } - printk("zt_rbs: Don't know RBS signalling type %d on channel %s\n", chan->sig, chan->name); -} - -static int zt_cas_setbits(struct zt_chan *chan, int bits) -{ - /* if no span, return as error */ - if (!chan->span) return -1; - if (chan->span->rbsbits) { - chan->txsig = bits; - chan->span->rbsbits(chan, bits); - } else { - printk("Huh? CAS setbits, but no RBS bits function\n"); - } - return 0; -} - -static int zt_hangup(struct zt_chan *chan) -{ - int x,res=0; - - /* Can't hangup pseudo channels */ - if (!chan->span) - return 0; - /* Can't hang up a clear channel */ - if (chan->flags & (ZT_FLAG_CLEAR | ZT_FLAG_NOSTDTXRX)) - return -EINVAL; - - chan->kewlonhook = 0; - - - if ((chan->sig == ZT_SIG_FXSLS) || (chan->sig == ZT_SIG_FXSKS) || - (chan->sig == ZT_SIG_FXSGS)) chan->ringdebtimer = RING_DEBOUNCE_TIME; - - if (chan->span->flags & ZT_FLAG_RBS) { - if (chan->sig == ZT_SIG_CAS) { - zt_cas_setbits(chan, chan->idlebits); - } else if ((chan->sig == ZT_SIG_FXOKS) && (chan->txstate != ZT_TXSTATE_ONHOOK)) { - /* Do RBS signalling on the channel's behalf */ - zt_rbs_sethook(chan, ZT_TXSIG_KEWL, ZT_TXSTATE_KEWL, ZT_KEWLTIME); - } else - zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_ONHOOK, 0); - } else { - /* Let the driver hang up the line if it wants to */ - if (chan->span->sethook) { - if (chan->txhooksig != ZT_ONHOOK) { - chan->txhooksig = ZT_ONHOOK; - res = chan->span->sethook(chan, ZT_ONHOOK); - } else - res = 0; - } - } - /* if not registered yet, just return here */ - if (!(chan->flags & ZT_FLAG_REGISTERED)) return res; - /* Mark all buffers as empty */ - for (x = 0;x < chan->numbufs;x++) { - chan->writen[x] = - chan->writeidx[x]= - chan->readn[x]= - chan->readidx[x] = 0; - } - if (chan->readbuf[0]) { - chan->inreadbuf = 0; - chan->inwritebuf = 0; - } else { - chan->inreadbuf = -1; - chan->inwritebuf = -1; - } - chan->outreadbuf = -1; - chan->outwritebuf = -1; - chan->dialing = 0; - chan->afterdialingtimer = 0; - chan->curtone = NULL; - chan->pdialcount = 0; - chan->cadencepos = 0; - chan->txdialbuf[0] = 0; - return res; -} - -static int initialize_channel(struct zt_chan *chan) -{ - int res; - unsigned long flags; - void *rxgain=NULL; - struct echo_can_state *ec=NULL; - if ((res = zt_reallocbufs(chan, ZT_DEFAULT_BLOCKSIZE, ZT_DEFAULT_NUM_BUFS))) - return res; - - spin_lock_irqsave(&chan->lock, flags); - - chan->rxbufpolicy = ZT_POLICY_IMMEDIATE; - chan->txbufpolicy = ZT_POLICY_IMMEDIATE; - - /* Free up the echo canceller if there is one */ - ec = chan->ec; - chan->ec = NULL; - chan->echocancel = 0; - chan->echostate = ECHO_STATE_IDLE; - chan->echolastupdate = 0; - chan->echotimer = 0; - - chan->txdisable = 0; - chan->rxdisable = 0; - - chan->digitmode = DIGIT_MODE_DTMF; - chan->dialing = 0; - chan->afterdialingtimer = 0; - - chan->cadencepos = 0; - chan->firstcadencepos = 0; /* By default loop back to first cadence position */ - - /* HDLC & FCS stuff */ - fasthdlc_init(&chan->rxhdlc); - fasthdlc_init(&chan->txhdlc); - chan->infcs = PPP_INITFCS; - - /* Timings for RBS */ - chan->prewinktime = ZT_DEFAULT_PREWINKTIME; - chan->preflashtime = ZT_DEFAULT_PREFLASHTIME; - chan->winktime = ZT_DEFAULT_WINKTIME; - chan->flashtime = ZT_DEFAULT_FLASHTIME; - - if (chan->sig & __ZT_SIG_FXO) - chan->starttime = ZT_DEFAULT_RINGTIME; - else - chan->starttime = ZT_DEFAULT_STARTTIME; - chan->rxwinktime = ZT_DEFAULT_RXWINKTIME; - chan->rxflashtime = ZT_DEFAULT_RXFLASHTIME; - chan->debouncetime = ZT_DEFAULT_DEBOUNCETIME; - chan->pulsemaketime = ZT_DEFAULT_PULSEMAKETIME; - chan->pulsebreaktime = ZT_DEFAULT_PULSEBREAKTIME; - chan->pulseaftertime = ZT_DEFAULT_PULSEAFTERTIME; - - /* Initialize RBS timers */ - chan->itimerset = chan->itimer = chan->otimer = 0; - chan->ringdebtimer = 0; - - init_waitqueue_head(&chan->sel); - init_waitqueue_head(&chan->readbufq); - init_waitqueue_head(&chan->writebufq); - init_waitqueue_head(&chan->eventbufq); - init_waitqueue_head(&chan->txstateq); - - /* Reset conferences */ - reset_conf(chan); - - /* I/O Mask, etc */ - chan->iomask = 0; - /* release conference resource if any */ - if (chan->confna) zt_check_conf(chan->confna); - if ((chan->sig & __ZT_SIG_DACS) != __ZT_SIG_DACS) { - chan->confna = 0; - chan->confmode = 0; - if (chan->span && chan->span->dacs) - chan->span->dacs(chan, NULL); - } - chan->_confn = 0; - memset(chan->conflast, 0, sizeof(chan->conflast)); - memset(chan->conflast1, 0, sizeof(chan->conflast1)); - memset(chan->conflast2, 0, sizeof(chan->conflast2)); - chan->confmute = 0; - chan->gotgs = 0; - chan->curtone = NULL; - chan->tonep = 0; - chan->pdialcount = 0; - if (chan->gainalloc && chan->rxgain) - rxgain = chan->rxgain; - chan->rxgain = defgain; - chan->txgain = defgain; - chan->gainalloc = 0; - chan->eventinidx = chan->eventoutidx = 0; - zt_set_law(chan,0); - zt_hangup(chan); - - /* Make sure that the audio flag is cleared on a clear channel */ - if ((chan->sig & ZT_SIG_CLEAR) || (chan->sig & ZT_SIG_HARDHDLC)) - chan->flags &= ~ZT_FLAG_AUDIO; - - if ((chan->sig == ZT_SIG_CLEAR) || (chan->sig == ZT_SIG_HARDHDLC)) - chan->flags &= ~(ZT_FLAG_PPP | ZT_FLAG_FCS | ZT_FLAG_HDLC); - - chan->flags &= ~ZT_FLAG_LINEAR; - if (chan->curzone) { - /* Take cadence from tone zone */ - memcpy(chan->ringcadence, chan->curzone->ringcadence, sizeof(chan->ringcadence)); - } else { - /* Do a default */ - memset(chan->ringcadence, 0, sizeof(chan->ringcadence)); - chan->ringcadence[0] = chan->starttime; - chan->ringcadence[1] = ZT_RINGOFFTIME; - } - - spin_unlock_irqrestore(&chan->lock, flags); - set_tone_zone(chan, -1); - - if (chan->span && chan->span->echocan) - chan->span->echocan(chan, 0); - - if (rxgain) - kfree(rxgain); - if (ec) - echo_can_free(ec); - return 0; -} - -static int zt_timing_open(struct inode *inode, struct file *file) -{ - struct zt_timer *t; - unsigned long flags; - t = kmalloc(sizeof(struct zt_timer), GFP_KERNEL); - if (!t) - return -ENOMEM; - /* Allocate a new timer */ - memset(t, 0, sizeof(struct zt_timer)); - init_waitqueue_head(&t->sel); - file->private_data = t; -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#endif - spin_lock_irqsave(&zaptimerlock, flags); - t->next = zaptimers; - zaptimers = t; - spin_unlock_irqrestore(&zaptimerlock, flags); - return 0; -} - -static int zt_timer_release(struct inode *inode, struct file *file) -{ - struct zt_timer *t, *cur, *prev; - unsigned long flags; - t = file->private_data; - if (t) { - spin_lock_irqsave(&zaptimerlock, flags); - prev = NULL; - cur = zaptimers; - while(cur) { - if (t == cur) - break; - prev = cur; - cur = cur->next; - } - if (cur) { - if (prev) - prev->next = cur->next; - else - zaptimers = cur->next; - } - spin_unlock_irqrestore(&zaptimerlock, flags); - if (!cur) { - printk("Zap Timer: Not on list??\n"); - return 0; - } - kfree(t); -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#endif - } - return 0; -} - -static int zt_specchan_open(struct inode *inode, struct file *file, int unit, int inc) -{ - int res = 0; - - if (chans[unit] && chans[unit]->sig) { - /* Make sure we're not already open, a net device, or a slave device */ - if (chans[unit]->flags & ZT_FLAG_OPEN) - res = -EBUSY; - else if (chans[unit]->flags & ZT_FLAG_NETDEV) - res = -EBUSY; - else if (chans[unit]->master != chans[unit]) - res = -EBUSY; - else if ((chans[unit]->sig & __ZT_SIG_DACS) == __ZT_SIG_DACS) - res = -EBUSY; - else { - unsigned long flags; - /* Assume everything is going to be okay */ - res = initialize_channel(chans[unit]); - spin_lock_irqsave(&chans[unit]->lock, flags); - if (chans[unit]->flags & ZT_FLAG_PSEUDO) - chans[unit]->flags |= ZT_FLAG_AUDIO; - if (chans[unit]->span && chans[unit]->span->open) { - res = chans[unit]->span->open(chans[unit]); - } - if (!res) { - chans[unit]->file = file; -#ifndef LINUX26 - if (inc) - MOD_INC_USE_COUNT; -#endif - chans[unit]->flags |= ZT_FLAG_OPEN; - spin_unlock_irqrestore(&chans[unit]->lock, flags); - } else { - spin_unlock_irqrestore(&chans[unit]->lock, flags); - close_channel(chans[unit]); - } - } - } else - res = -ENXIO; - return res; -} - -static int zt_specchan_release(struct inode *node, struct file *file, int unit) -{ - int res=0; - if (chans[unit]) { - unsigned long flags; - spin_lock_irqsave(&chans[unit]->lock, flags); - chans[unit]->flags &= ~ZT_FLAG_OPEN; - spin_unlock_irqrestore(&chans[unit]->lock, flags); - chans[unit]->file = NULL; - close_channel(chans[unit]); - if (chans[unit]->span && chans[unit]->span->close) - res = chans[unit]->span->close(chans[unit]); - } else - res = -ENXIO; -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#endif - return res; -} - -static struct zt_chan *zt_alloc_pseudo(void) -{ - struct zt_chan *pseudo; - unsigned long flags; - /* Don't allow /dev/zap/pseudo to open if there are no spans */ - if (maxspans < 1) - return NULL; - pseudo = kmalloc(sizeof(struct zt_chan), GFP_KERNEL); - if (!pseudo) - return NULL; - memset(pseudo, 0, sizeof(struct zt_chan)); - pseudo->sig = ZT_SIG_CLEAR; - pseudo->sigcap = ZT_SIG_CLEAR; - pseudo->flags = ZT_FLAG_PSEUDO | ZT_FLAG_AUDIO; - spin_lock_irqsave(&bigzaplock, flags); - if (zt_chan_reg(pseudo)) { - kfree(pseudo); - pseudo = NULL; - } else - sprintf(pseudo->name, "Pseudo/%d", pseudo->channo); - spin_unlock_irqrestore(&bigzaplock, flags); - return pseudo; -} - -static void zt_free_pseudo(struct zt_chan *pseudo) -{ - unsigned long flags; - if (pseudo) { - spin_lock_irqsave(&bigzaplock, flags); - zt_chan_unreg(pseudo); - spin_unlock_irqrestore(&bigzaplock, flags); - kfree(pseudo); - } -} - -static int zt_open(struct inode *inode, struct file *file) -{ - int unit = UNIT(file); - int ret = -ENXIO; - struct zt_chan *chan; - /* Minor 0: Special "control" descriptor */ - if (!unit) - return zt_ctl_open(inode, file); - if (unit == 250) { - if (!zt_transcode_fops) - request_module("zttranscode"); - if (zt_transcode_fops && zt_transcode_fops->open) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - if (zt_transcode_fops->owner) { - __MOD_INC_USE_COUNT (zt_transcode_fops->owner); -#else - if (try_module_get(zt_transcode_fops->owner)) { -#endif - ret = zt_transcode_fops->open(inode, file); - if (ret) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - __MOD_DEC_USE_COUNT (zt_transcode_fops->owner); -#else - module_put(zt_transcode_fops->owner); -#endif - } - return ret; - } - return -ENXIO; - } - if (unit == 253) { - if (maxspans) { - return zt_timing_open(inode, file); - } else { - return -ENXIO; - } - } - if (unit == 254) - return zt_chan_open(inode, file); - if (unit == 255) { - if (maxspans) { - chan = zt_alloc_pseudo(); - if (chan) { - file->private_data = chan; - return zt_specchan_open(inode, file, chan->channo, 1); - } else { - return -ENXIO; - } - } else - return -ENXIO; - } - return zt_specchan_open(inode, file, unit, 1); -} - -#if 0 -static int zt_open(struct inode *inode, struct file *file) -{ - int res; - unsigned long flags; - spin_lock_irqsave(&bigzaplock, flags); - res = __zt_open(inode, file); - spin_unlock_irqrestore(&bigzaplock, flags); - return res; -} -#endif - -static ssize_t zt_read(struct file *file, char *usrbuf, size_t count, loff_t *ppos) -{ - int unit = UNIT(file); - struct zt_chan *chan; - - /* Can't read from control */ - if (!unit) { - return -EINVAL; - } - - if (unit == 253) - return -EINVAL; - - if (unit == 254) { - chan = file->private_data; - if (!chan) - return -EINVAL; - return zt_chan_read(file, usrbuf, count, chan->channo); - } - - if (unit == 255) { - chan = file->private_data; - if (!chan) { - printk("No pseudo channel structure to read?\n"); - return -EINVAL; - } - return zt_chan_read(file, usrbuf, count, chan->channo); - } - if (count < 0) - return -EINVAL; - - return zt_chan_read(file, usrbuf, count, unit); -} - -static ssize_t zt_write(struct file *file, const char *usrbuf, size_t count, loff_t *ppos) -{ - int unit = UNIT(file); - struct zt_chan *chan; - /* Can't read from control */ - if (!unit) - return -EINVAL; - if (count < 0) - return -EINVAL; - if (unit == 253) - return -EINVAL; - if (unit == 254) { - chan = file->private_data; - if (!chan) - return -EINVAL; - return zt_chan_write(file, usrbuf, count, chan->channo); - } - if (unit == 255) { - chan = file->private_data; - if (!chan) { - printk("No pseudo channel structure to read?\n"); - return -EINVAL; - } - return zt_chan_write(file, usrbuf, count, chan->channo); - } - return zt_chan_write(file, usrbuf, count, unit); - -} - -/* No bigger than 32k for everything per tone zone */ -#define MAX_SIZE 32768 -/* No more than 128 subtones */ -#define MAX_TONES 128 - -/* The tones to be loaded can (will) be a mix of regular tones, - DTMF tones and MF tones. We need to load DTMF and MF tones - a bit differently than regular tones because their storage - format is much simpler (an array structure field of the zone - structure, rather an array of pointers). -*/ -static int ioctl_load_zone(unsigned long data) -{ - struct zt_tone *samples[MAX_TONES] = { NULL, }; - short next[MAX_TONES] = { 0, }; - struct zt_tone_def_header th; - struct zt_tone_def td; - struct zt_zone *z; - struct zt_tone *t; - void *slab, *ptr; - int x; - size_t space; - size_t size; - int res; - - if (copy_from_user(&th, (struct zt_tone_def_header *) data, sizeof(th))) - return -EFAULT; - - data += sizeof(th); - - if ((th.count < 0) || (th.count > MAX_TONES)) { - printk("Too many tones included\n"); - return -EINVAL; - } - - space = size = sizeof(*z) + th.count * sizeof(*t); - - if (size > MAX_SIZE) - return -E2BIG; - - if (!(z = ptr = slab = kmalloc(size, GFP_KERNEL))) - return -ENOMEM; - - memset(slab, 0, size); - - ptr += sizeof(*z); - space -= sizeof(*z); - - strncpy(z->name, th.name, sizeof(z->name) - 1); - - for (x = 0; x < ZT_MAX_CADENCE; x++) - z->ringcadence[x] = th.ringcadence[x]; - - atomic_set(&z->refcount, 0); - - for (x = 0; x < th.count; x++) { - enum { - REGULAR_TONE, - DTMF_TONE, - MF_TONE, - } tone_type; - - if (space < sizeof(*t)) { - kfree(slab); - printk("Insufficient tone zone space\n"); - return -EINVAL; - } - - if (copy_from_user(&td, (struct zt_tone_def *) data, sizeof(td))) { - kfree(slab); - return -EFAULT; - } - - data += sizeof(td); - - if ((td.tone >= 0) && (td.tone < ZT_TONE_MAX)) { - tone_type = REGULAR_TONE; - - t = samples[x] = ptr; - - space -= sizeof(*t); - ptr += sizeof(*t); - - /* Remember which sample is next */ - next[x] = td.next; - - /* Make sure the "next" one is sane */ - if ((next[x] >= th.count) || (next[x] < 0)) { - printk("Invalid 'next' pointer: %d\n", next[x]); - kfree(slab); - return -EINVAL; - } - } else if ((td.tone >= ZT_TONE_DTMF_BASE) && - (td.tone <= ZT_TONE_DTMF_MAX)) { - tone_type = DTMF_TONE; - - td.tone -= ZT_TONE_DTMF_BASE; - t = &z->dtmf[td.tone]; - } else if ((td.tone >= ZT_TONE_MF_BASE) && - (td.tone <= ZT_TONE_MF_MAX)) { - tone_type = MF_TONE; - - td.tone -= ZT_TONE_MF_BASE; - t = &z->mf[td.tone]; - } else { - printk("Invalid tone (%d) defined\n", td.tone); - kfree(slab); - return -EINVAL; - } - - t->fac1 = td.fac1; - t->init_v2_1 = td.init_v2_1; - t->init_v3_1 = td.init_v3_1; - t->fac2 = td.fac2; - t->init_v2_2 = td.init_v2_2; - t->init_v3_2 = td.init_v3_2; - t->modulate = td.modulate; - - switch (tone_type) { - case REGULAR_TONE: - t->tonesamples = td.samples; - if (!z->tones[td.tone]) - z->tones[td.tone] = t; - break; - case DTMF_TONE: - t->tonesamples = global_dialparams.dtmf_tonelen; - t->next = &dtmf_silence; - z->dtmf_continuous[td.tone] = *t; - z->dtmf_continuous[td.tone].next = &z->dtmf_continuous[td.tone]; - break; - case MF_TONE: - t->tonesamples = global_dialparams.mfv1_tonelen; - t->next = &mfv1_silence; - /* Special case for K/P tone */ - if (td.tone == 10) - t->tonesamples *= 5 / 3; - z->mf_continuous[td.tone] = *t; - z->mf_continuous[td.tone].next = &z->mf_continuous[td.tone]; - break; - } - } - - for (x = 0; x < th.count; x++) { - if (samples[x]) - samples[x]->next = samples[next[x]]; - } - - if ((res = zt_register_tone_zone(th.zone, z))) - kfree(slab); - - return res; -} - -void zt_init_tone_state(struct zt_tone_state *ts, struct zt_tone *zt) -{ - ts->v1_1 = 0; - ts->v2_1 = zt->init_v2_1; - ts->v3_1 = zt->init_v3_1; - ts->v1_2 = 0; - ts->v2_2 = zt->init_v2_2; - ts->v3_2 = zt->init_v3_2; - ts->modulate = zt->modulate; -} - -struct zt_tone *zt_dtmf_tone(const struct zt_chan *chan, char digit) -{ - struct zt_tone *z; - - switch (chan->digitmode) { - case DIGIT_MODE_DTMF: - z = &chan->curzone->dtmf[0]; - break; - case DIGIT_MODE_MFV1: - z = &chan->curzone->mf[0]; - break; - default: - z = NULL; - } - - switch (digit) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return z + (digit - '0'); - case '*': - return z + 10; - case '#': - return z + 11; - case 'A': - case 'B': - case 'C': - return z + (digit + 12 - 'A'); - case 'D': - if (chan->digitmode == DIGIT_MODE_MFV1) - return NULL; - else - return z + (digit + 12 - 'A'); - case 'W': - return &tone_pause; - } - - return NULL; -} - -static void __do_dtmf(struct zt_chan *chan) -{ - char c; - - /* Called with chan->lock held */ - while ((c = chan->txdialbuf[0])) { - memmove(chan->txdialbuf, chan->txdialbuf + 1, sizeof(chan->txdialbuf) - 1); - switch (c) { - case 'T': - chan->digitmode = DIGIT_MODE_DTMF; - chan->tonep = 0; - break; - case 'M': - chan->digitmode = DIGIT_MODE_MFV1; - chan->tonep = 0; - break; - case 'P': - chan->digitmode = DIGIT_MODE_PULSE; - chan->tonep = 0; - break; - default: - if ((c != 'W') && (chan->digitmode == DIGIT_MODE_PULSE)) { - if ((c >= '0') && (c <= '9') && (chan->txhooksig == ZT_TXSIG_OFFHOOK)) { - chan->pdialcount = (c == '0') ? 10 : c - '0'; - zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_PULSEBREAK, - chan->pulsebreaktime); - return; - } - } else { - chan->curtone = zt_dtmf_tone(chan, c); - chan->tonep = 0; - if (chan->curtone) { - zt_init_tone_state(&chan->ts, chan->curtone); - return; - } - } - } - } - - /* Notify userspace process if there is nothing left */ - chan->dialing = 0; - __qevent(chan, ZT_EVENT_DIALCOMPLETE); -} - -static int zt_release(struct inode *inode, struct file *file) -{ - int unit = UNIT(file); - int res; - struct zt_chan *chan; - - if (!unit) - return zt_ctl_release(inode, file); - if (unit == 253) { - return zt_timer_release(inode, file); - } - if (unit == 250) { - res = zt_transcode_fops->release(inode, file); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - if (zt_transcode_fops->owner) - __MOD_DEC_USE_COUNT (zt_transcode_fops->owner); -#else - module_put(zt_transcode_fops->owner); -#endif - return res; - } - if (unit == 254) { - chan = file->private_data; - if (!chan) - return zt_chan_release(inode, file); - else - return zt_specchan_release(inode, file, chan->channo); - } - if (unit == 255) { - chan = file->private_data; - if (chan) { - res = zt_specchan_release(inode, file, chan->channo); - zt_free_pseudo(chan); - } else { - printk("Pseudo release and no private data??\n"); - res = 0; - } - return res; - } - return zt_specchan_release(inode, file, unit); -} - -#if 0 -static int zt_release(struct inode *inode, struct file *file) -{ - /* Lock the big zap lock when handling a release */ - unsigned long flags; - int res; - spin_lock_irqsave(&bigzaplock, flags); - res = __zt_release(inode, file); - spin_unlock_irqrestore(&bigzaplock, flags); - return res; -} -#endif - - -void zt_alarm_channel(struct zt_chan *chan, int alarms) -{ - unsigned long flags; - - spin_lock_irqsave(&chan->lock, flags); - if (chan->chan_alarms != alarms) { - chan->chan_alarms = alarms; - zt_qevent_nolock(chan, alarms ? ZT_EVENT_ALARM : ZT_EVENT_NOALARM); - } - spin_unlock_irqrestore(&chan->lock, flags); -} - -void zt_alarm_notify(struct zt_span *span) -{ - int x; - - span->alarms &= ~ZT_ALARM_LOOPBACK; - /* Determine maint status */ - if (span->maintstat || span->mainttimer) - span->alarms |= ZT_ALARM_LOOPBACK; - /* DON'T CHANGE THIS AGAIN. THIS WAS DONE FOR A REASON. - The expression (a != b) does *NOT* do the same thing - as ((!a) != (!b)) */ - /* if change in general state */ - if ((!span->alarms) != (!span->lastalarms)) { - span->lastalarms = span->alarms; - for (x = 0; x < span->channels; x++) - zt_alarm_channel(&span->chans[x], span->alarms); - /* Switch to other master if current master in alarm */ - for (x=1; xalarms && (spans[x]->flags & ZT_FLAG_RUNNING)) { - if(master != spans[x]) - printk("Zaptel: Master changed to %s\n", spans[x]->name); - master = spans[x]; - break; - } - } - } -} - -#define VALID_SPAN(j) do { \ - if ((j >= ZT_MAX_SPANS) || (j < 1)) \ - return -EINVAL; \ - if (!spans[j]) \ - return -ENXIO; \ -} while(0) - -#define CHECK_VALID_SPAN(j) do { \ - /* Start a given span */ \ - if (get_user(j, (int *)data)) \ - return -EFAULT; \ - VALID_SPAN(j); \ -} while(0) - -#define VALID_CHANNEL(j) do { \ - if ((j >= ZT_MAX_CHANNELS) || (j < 1)) \ - return -EINVAL; \ - if (!chans[j]) \ - return -ENXIO; \ -} while(0) - -static int zt_timer_ioctl(struct inode *node, struct file *file, unsigned int cmd, unsigned long data, struct zt_timer *timer) -{ - int j; - unsigned long flags; - switch(cmd) { - case ZT_TIMERCONFIG: - get_user(j, (int *)data); - if (j < 0) - j = 0; - spin_lock_irqsave(&zaptimerlock, flags); - timer->ms = timer->pos = j; - spin_unlock_irqrestore(&zaptimerlock, flags); - break; - case ZT_TIMERACK: - get_user(j, (int *)data); - spin_lock_irqsave(&zaptimerlock, flags); - if ((j < 1) || (j > timer->tripped)) - j = timer->tripped; - timer->tripped -= j; - spin_unlock_irqrestore(&zaptimerlock, flags); - break; - case ZT_GETEVENT: /* Get event on queue */ - j = ZT_EVENT_NONE; - spin_lock_irqsave(&zaptimerlock, flags); - /* set up for no event */ - if (timer->tripped) - j = ZT_EVENT_TIMER_EXPIRED; - if (timer->ping) - j = ZT_EVENT_TIMER_PING; - spin_unlock_irqrestore(&zaptimerlock, flags); - put_user(j,(int *)data); - break; - case ZT_TIMERPING: - spin_lock_irqsave(&zaptimerlock, flags); - timer->ping = 1; - wake_up_interruptible(&timer->sel); - spin_unlock_irqrestore(&zaptimerlock, flags); - break; - case ZT_TIMERPONG: - spin_lock_irqsave(&zaptimerlock, flags); - timer->ping = 0; - spin_unlock_irqrestore(&zaptimerlock, flags); - break; - default: - return -ENOTTY; - } - return 0; -} - -static int zt_common_ioctl(struct inode *node, struct file *file, unsigned int cmd, unsigned long data, int unit) -{ - union { - struct zt_gains gain; - struct zt_spaninfo spaninfo; - struct zt_params param; - } stack; - struct zt_chan *chan; - unsigned long flags; - unsigned char *txgain, *rxgain; - struct zt_chan *mychan; - int i,j; - int return_master = 0; - size_t size_to_copy; - - switch(cmd) { - /* get channel parameters */ - case ZT_GET_PARAMS_V1: - case ZT_GET_PARAMS: - size_to_copy = (cmd == ZT_GET_PARAMS_V1) ? sizeof(struct zt_params_v1) : - sizeof(struct zt_params); - if (copy_from_user(&stack.param, (struct zt_params *) data, size_to_copy)) - return -EFAULT; - - /* check to see if the caller wants to receive our master channel number */ - if (stack.param.channo & ZT_GET_PARAMS_RETURN_MASTER) { - return_master = 1; - stack.param.channo &= ~ZT_GET_PARAMS_RETURN_MASTER; - } - - /* Pick the right channo's */ - if (!stack.param.channo || unit) { - stack.param.channo = unit; - } - /* Check validity of channel */ - VALID_CHANNEL(stack.param.channo); - chan = chans[stack.param.channo]; - - /* point to relevant structure */ - stack.param.sigtype = chan->sig; /* get signalling type */ - /* return non-zero if rx not in idle state */ - if (chan->span) { - j = zt_q_sig(chan); - if (j >= 0) { /* if returned with success */ - stack.param.rxisoffhook = ((chan->rxsig & (j >> 8)) != (j & 0xff)); - } else { - stack.param.rxisoffhook = ((chan->rxhooksig != ZT_RXSIG_ONHOOK) && - (chan->rxhooksig != ZT_RXSIG_INITIAL)); - } - } else if ((chan->txstate == ZT_TXSTATE_KEWL) || (chan->txstate == ZT_TXSTATE_AFTERKEWL)) - stack.param.rxisoffhook = 1; - else - stack.param.rxisoffhook = 0; - if (chan->span && chan->span->rbsbits && !(chan->sig & ZT_SIG_CLEAR)) { - stack.param.rxbits = chan->rxsig; - stack.param.txbits = chan->txsig; - stack.param.idlebits = chan->idlebits; - } else { - stack.param.rxbits = -1; - stack.param.txbits = -1; - stack.param.idlebits = 0; - } - if (chan->span && (chan->span->rbsbits || chan->span->hooksig) && - !(chan->sig & ZT_SIG_CLEAR)) { - stack.param.rxhooksig = chan->rxhooksig; - stack.param.txhooksig = chan->txhooksig; - } else { - stack.param.rxhooksig = -1; - stack.param.txhooksig = -1; - } - stack.param.prewinktime = chan->prewinktime; - stack.param.preflashtime = chan->preflashtime; - stack.param.winktime = chan->winktime; - stack.param.flashtime = chan->flashtime; - stack.param.starttime = chan->starttime; - stack.param.rxwinktime = chan->rxwinktime; - stack.param.rxflashtime = chan->rxflashtime; - stack.param.debouncetime = chan->debouncetime; - stack.param.channo = chan->channo; - stack.param.chan_alarms = chan->chan_alarms; - - /* if requested, put the master channel number in the top 16 bits of the result */ - if (return_master) - stack.param.channo |= chan->master->channo << 16; - - stack.param.pulsemaketime = chan->pulsemaketime; - stack.param.pulsebreaktime = chan->pulsebreaktime; - stack.param.pulseaftertime = chan->pulseaftertime; - if (chan->span) stack.param.spanno = chan->span->spanno; - else stack.param.spanno = 0; - strncpy(stack.param.name, chan->name, sizeof(stack.param.name) - 1); - stack.param.chanpos = chan->chanpos; - stack.param.sigcap = chan->sigcap; - /* Return current law */ - if (chan->xlaw == __zt_alaw) - stack.param.curlaw = ZT_LAW_ALAW; - else - stack.param.curlaw = ZT_LAW_MULAW; - - if (copy_to_user((struct zt_params *) data, &stack.param, size_to_copy)) - return -EFAULT; - - break; - /* set channel parameters */ - case ZT_SET_PARAMS_V1: - case ZT_SET_PARAMS: - /* The difference between zt_params and zt_params_v1 is just the - * last field, which is read-only anyway. Thus we just read the - * size of the older struct. - */ - if (copy_from_user(&stack.param, (struct zt_params *) data, sizeof(struct zt_params_v1))) - return -EFAULT; - - stack.param.chan_alarms = 0; /* be explicit about the above */ - - /* Pick the right channo's */ - if (!stack.param.channo || unit) { - stack.param.channo = unit; - } - /* Check validity of channel */ - VALID_CHANNEL(stack.param.channo); - chan = chans[stack.param.channo]; - /* point to relevant structure */ - /* NOTE: sigtype is *not* included in this */ - /* get timing stack.paramters */ - chan->prewinktime = stack.param.prewinktime; - chan->preflashtime = stack.param.preflashtime; - chan->winktime = stack.param.winktime; - chan->flashtime = stack.param.flashtime; - chan->starttime = stack.param.starttime; - /* Update ringtime if not using a tone zone */ - if (!chan->curzone) - chan->ringcadence[0] = chan->starttime; - chan->rxwinktime = stack.param.rxwinktime; - chan->rxflashtime = stack.param.rxflashtime; - chan->debouncetime = stack.param.debouncetime; - chan->pulsemaketime = stack.param.pulsemaketime; - chan->pulsebreaktime = stack.param.pulsebreaktime; - chan->pulseaftertime = stack.param.pulseaftertime; - break; - case ZT_GETGAINS: /* get gain stuff */ - if (copy_from_user(&stack.gain,(struct zt_gains *) data,sizeof(stack.gain))) - return -EFAULT; - i = stack.gain.chan; /* get channel no */ - /* if zero, use current channel no */ - if (!i) i = unit; - /* make sure channel number makes sense */ - if ((i < 0) || (i > ZT_MAX_CHANNELS) || !chans[i]) return(-EINVAL); - - if (!(chans[i]->flags & ZT_FLAG_AUDIO)) return (-EINVAL); - stack.gain.chan = i; /* put the span # in here */ - for (j=0;j<256;j++) { - stack.gain.txgain[j] = chans[i]->txgain[j]; - stack.gain.rxgain[j] = chans[i]->rxgain[j]; - } - if (copy_to_user((struct zt_gains *) data,&stack.gain,sizeof(stack.gain))) - return -EFAULT; - break; - case ZT_SETGAINS: /* set gain stuff */ - if (copy_from_user(&stack.gain,(struct zt_gains *) data,sizeof(stack.gain))) - return -EFAULT; - i = stack.gain.chan; /* get channel no */ - /* if zero, use current channel no */ - if (!i) i = unit; - /* make sure channel number makes sense */ - if ((i < 0) || (i > ZT_MAX_CHANNELS) || !chans[i]) return(-EINVAL); - if (!(chans[i]->flags & ZT_FLAG_AUDIO)) return (-EINVAL); - - rxgain = kmalloc(512, GFP_KERNEL); - if (!rxgain) - return -ENOMEM; - - stack.gain.chan = i; /* put the span # in here */ - txgain = rxgain + 256; - - for (j=0;j<256;j++) { - rxgain[j] = stack.gain.rxgain[j]; - txgain[j] = stack.gain.txgain[j]; - } - - if (!memcmp(rxgain, defgain, 256) && - !memcmp(txgain, defgain, 256)) { - if (rxgain) - kfree(rxgain); - spin_lock_irqsave(&chans[i]->lock, flags); - if (chans[i]->gainalloc) - kfree(chans[i]->rxgain); - chans[i]->gainalloc = 0; - chans[i]->rxgain = defgain; - chans[i]->txgain = defgain; - spin_unlock_irqrestore(&chans[i]->lock, flags); - } else { - /* This is a custom gain setting */ - spin_lock_irqsave(&chans[i]->lock, flags); - if (chans[i]->gainalloc) - kfree(chans[i]->rxgain); - chans[i]->gainalloc = 1; - chans[i]->rxgain = rxgain; - chans[i]->txgain = txgain; - spin_unlock_irqrestore(&chans[i]->lock, flags); - } - if (copy_to_user((struct zt_gains *) data,&stack.gain,sizeof(stack.gain))) - return -EFAULT; - break; - case ZT_SPANSTAT_V1: - case ZT_SPANSTAT_V2: - case ZT_SPANSTAT: - size_to_copy = (cmd == ZT_SPANSTAT_V1) ? sizeof(struct zt_spaninfo_v1) : - (cmd == ZT_SPANSTAT_V2) ? sizeof(struct zt_spaninfo_v2) : - sizeof(struct zt_spaninfo); - if (copy_from_user(&stack.spaninfo, (struct zt_spaninfo *) data, size_to_copy)) - return -EFAULT; - i = stack.spaninfo.spanno; /* get specified span number */ - if ((i < 0) || (i >= maxspans)) return(-EINVAL); /* if bad span no */ - if (i == 0) { - /* if to figure it out for this chan */ - if (!chans[unit]) - return -EINVAL; - i = chans[unit]->span->spanno; - } - if (!spans[i]) - return -EINVAL; - stack.spaninfo.spanno = i; /* put the span # in here */ - stack.spaninfo.totalspans = 0; - if (maxspans) stack.spaninfo.totalspans = maxspans - 1; /* put total number of spans here */ - strncpy(stack.spaninfo.desc, spans[i]->desc, sizeof(stack.spaninfo.desc) - 1); - strncpy(stack.spaninfo.name, spans[i]->name, sizeof(stack.spaninfo.name) - 1); - stack.spaninfo.alarms = spans[i]->alarms; /* get alarm status */ - stack.spaninfo.bpvcount = spans[i]->bpvcount; /* get BPV count */ - stack.spaninfo.rxlevel = spans[i]->rxlevel; /* get rx level */ - stack.spaninfo.txlevel = spans[i]->txlevel; /* get tx level */ - stack.spaninfo.crc4count = spans[i]->crc4count; /* get CRC4 error count */ - stack.spaninfo.ebitcount = spans[i]->ebitcount; /* get E-bit error count */ - stack.spaninfo.fascount = spans[i]->fascount; /* get FAS error count */ - stack.spaninfo.irqmisses = spans[i]->irqmisses; /* get IRQ miss count */ - stack.spaninfo.syncsrc = spans[i]->syncsrc; /* get active sync source */ - stack.spaninfo.totalchans = spans[i]->channels; - stack.spaninfo.numchans = 0; - for (j = 0; j < spans[i]->channels; j++) { - if (spans[i]->chans[j].sig) - stack.spaninfo.numchans++; - } - /* version 2 fields */ - stack.spaninfo.lbo = spans[i]->lbo; - stack.spaninfo.lineconfig = spans[i]->lineconfig; - /* version 3 fields */ - stack.spaninfo.irq = spans[i]->irq; - stack.spaninfo.linecompat = spans[i]->linecompat; - strncpy(stack.spaninfo.lboname, zt_lboname(spans[i]->lbo), sizeof(stack.spaninfo.lboname) - 1); - if (spans[i]->manufacturer) - strncpy(stack.spaninfo.manufacturer, spans[i]->manufacturer, - sizeof(stack.spaninfo.manufacturer) - 1); - if (spans[i]->devicetype) - strncpy(stack.spaninfo.devicetype, spans[i]->devicetype, sizeof(stack.spaninfo.devicetype) - 1); - strncpy(stack.spaninfo.location, spans[i]->location, sizeof(stack.spaninfo.location) - 1); - if (spans[i]->spantype) - strncpy(stack.spaninfo.spantype, spans[i]->spantype, sizeof(stack.spaninfo.spantype) - 1); - - if (copy_to_user((struct zt_spaninfo *) data, &stack.spaninfo, size_to_copy)) - return -EFAULT; - break; - case ZT_CHANDIAG: - get_user(j, (int *)data); /* get channel number from user */ - /* make sure its a valid channel number */ - if ((j < 1) || (j >= maxchans)) - return -EINVAL; - /* if channel not mapped, not there */ - if (!chans[j]) - return -EINVAL; - - if (!(mychan = kmalloc(sizeof(*mychan), GFP_KERNEL))) - return -ENOMEM; - - /* lock channel */ - spin_lock_irqsave(&chans[j]->lock, flags); - /* make static copy of channel */ - memcpy(mychan, chans[j], sizeof(*mychan)); - /* release it. */ - spin_unlock_irqrestore(&chans[j]->lock, flags); - - printk(KERN_INFO "Dump of Zaptel Channel %d (%s,%d,%d):\n\n",j, - mychan->name,mychan->channo,mychan->chanpos); - printk(KERN_INFO "flags: %x hex, writechunk: %08lx, readchunk: %08lx\n", - mychan->flags, (long) mychan->writechunk, (long) mychan->readchunk); - printk(KERN_INFO "rxgain: %08lx, txgain: %08lx, gainalloc: %d\n", - (long) mychan->rxgain, (long)mychan->txgain, mychan->gainalloc); - printk(KERN_INFO "span: %08lx, sig: %x hex, sigcap: %x hex\n", - (long)mychan->span, mychan->sig, mychan->sigcap); - printk(KERN_INFO "inreadbuf: %d, outreadbuf: %d, inwritebuf: %d, outwritebuf: %d\n", - mychan->inreadbuf, mychan->outreadbuf, mychan->inwritebuf, mychan->outwritebuf); - printk(KERN_INFO "blocksize: %d, numbufs: %d, txbufpolicy: %d, txbufpolicy: %d\n", - mychan->blocksize, mychan->numbufs, mychan->txbufpolicy, mychan->rxbufpolicy); - printk(KERN_INFO "txdisable: %d, rxdisable: %d, iomask: %d\n", - mychan->txdisable, mychan->rxdisable, mychan->iomask); - printk(KERN_INFO "curzone: %08lx, tonezone: %d, curtone: %08lx, tonep: %d\n", - (long) mychan->curzone, mychan->tonezone, (long) mychan->curtone, mychan->tonep); - printk(KERN_INFO "digitmode: %d, txdialbuf: %s, dialing: %d, aftdialtimer: %d, cadpos. %d\n", - mychan->digitmode, mychan->txdialbuf, mychan->dialing, - mychan->afterdialingtimer, mychan->cadencepos); - printk(KERN_INFO "confna: %d, confn: %d, confmode: %d, confmute: %d\n", - mychan->confna, mychan->_confn, mychan->confmode, mychan->confmute); - printk(KERN_INFO "ec: %08lx, echocancel: %d, deflaw: %d, xlaw: %08lx\n", - (long) mychan->ec, mychan->echocancel, mychan->deflaw, (long) mychan->xlaw); - printk(KERN_INFO "echostate: %02x, echotimer: %d, echolastupdate: %d\n", - (int) mychan->echostate, mychan->echotimer, mychan->echolastupdate); - printk(KERN_INFO "itimer: %d, otimer: %d, ringdebtimer: %d\n\n", - mychan->itimer, mychan->otimer, mychan->ringdebtimer); -#if 0 - if (mychan->ec) { - int x; - /* Dump the echo canceller parameters */ - for (x=0;xec->taps;x++) { - printk(KERN_INFO "tap %d: %d\n", x, mychan->ec->fir_taps[x]); - } - } -#endif - kfree(mychan); - break; - default: - return -ENOTTY; - } - return 0; -} - -static int (*zt_dynamic_ioctl)(unsigned int cmd, unsigned long data); - -void zt_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data)) -{ - zt_dynamic_ioctl = func; -} - -static void recalc_slaves(struct zt_chan *chan) -{ - int x; - struct zt_chan *last = chan; - - /* Makes no sense if you don't have a span */ - if (!chan->span) - return; - -#ifdef CONFIG_ZAPATA_DEBUG - printk("Recalculating slaves on %s\n", chan->name); -#endif - - /* Link all slaves appropriately */ - for (x=chan->chanpos;xspan->channels;x++) - if (chan->span->chans[x].master == chan) { -#ifdef CONFIG_ZAPATA_DEBUG - printk("Channel %s, slave to %s, last is %s, its next will be %d\n", - chan->span->chans[x].name, chan->name, last->name, x); -#endif - last->nextslave = x; - last = &chan->span->chans[x]; - } - /* Terminate list */ - last->nextslave = 0; -#ifdef CONFIG_ZAPATA_DEBUG - printk("Done Recalculating slaves on %s (last is %s)\n", chan->name, last->name); -#endif -} - -static int zt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data) -{ - /* I/O CTL's for control interface */ - int i,j; - struct zt_lineconfig lc; - struct zt_chanconfig ch; - struct zt_sfconfig sf; - int sigcap; - int res = 0; - int x,y; - struct zt_chan *newmaster; - struct zt_dialparams tdp; - struct zt_maintinfo maint; - struct zt_indirect_data ind; - struct zt_versioninfo vi; - unsigned long flags; - int rv; - switch(cmd) { - case ZT_INDIRECT: - if (copy_from_user(&ind, (struct zt_indirect_data *)data, sizeof(ind))) - return -EFAULT; - VALID_CHANNEL(ind.chan); - return zt_chan_ioctl(inode, file, ind.op, (unsigned long) ind.data, ind.chan); - case ZT_SPANCONFIG: - if (copy_from_user(&lc, (struct zt_lineconfig *)data, sizeof(lc))) - return -EFAULT; - VALID_SPAN(lc.span); - if ((lc.lineconfig & 0x07f0 & spans[lc.span]->linecompat) != (lc.lineconfig & 0x07f0)) - return -EINVAL; - if (spans[lc.span]->spanconfig) { - spans[lc.span]->lineconfig = lc.lineconfig; - spans[lc.span]->lbo = lc.lbo; - spans[lc.span]->txlevel = lc.lbo; - spans[lc.span]->rxlevel = 0; - - return spans[lc.span]->spanconfig(spans[lc.span], &lc); - } - return 0; - case ZT_STARTUP: - CHECK_VALID_SPAN(j); - if (spans[j]->flags & ZT_FLAG_RUNNING) - return 0; - if (spans[j]->startup) - res = spans[j]->startup(spans[j]); - if (!res) { - /* Mark as running and hangup any channels */ - spans[j]->flags |= ZT_FLAG_RUNNING; - for (x=0;xchannels;x++) { - y = zt_q_sig(&spans[j]->chans[x]) & 0xff; - if (y >= 0) spans[j]->chans[x].rxsig = (unsigned char)y; - spin_lock_irqsave(&spans[j]->chans[x].lock, flags); - zt_hangup(&spans[j]->chans[x]); - spin_unlock_irqrestore(&spans[j]->chans[x].lock, flags); - spans[j]->chans[x].rxhooksig = ZT_RXSIG_INITIAL; - } - } - return 0; - case ZT_SHUTDOWN: - CHECK_VALID_SPAN(j); - if (spans[j]->shutdown) - res = spans[j]->shutdown(spans[j]); - spans[j]->flags &= ~ZT_FLAG_RUNNING; - return 0; - case ZT_CHANCONFIG: - if (copy_from_user(&ch, (struct zt_chanconfig *)data, sizeof(ch))) - return -EFAULT; - VALID_CHANNEL(ch.chan); - if (ch.sigtype == ZT_SIG_SLAVE) { - /* We have to use the master's sigtype */ - if ((ch.master < 1) || (ch.master >= ZT_MAX_CHANNELS)) - return -EINVAL; - if (!chans[ch.master]) - return -EINVAL; - ch.sigtype = chans[ch.master]->sig; - newmaster = chans[ch.master]; - } else if ((ch.sigtype & __ZT_SIG_DACS) == __ZT_SIG_DACS) { - newmaster = chans[ch.chan]; - if ((ch.idlebits < 1) || (ch.idlebits >= ZT_MAX_CHANNELS)) - return -EINVAL; - if (!chans[ch.idlebits]) - return -EINVAL; - } else { - newmaster = chans[ch.chan]; - } - spin_lock_irqsave(&chans[ch.chan]->lock, flags); -#ifdef CONFIG_ZAPATA_NET - if (chans[ch.chan]->flags & ZT_FLAG_NETDEV) { - if (ztchan_to_dev(chans[ch.chan])->flags & IFF_UP) { - spin_unlock_irqrestore(&chans[ch.chan]->lock, flags); - printk(KERN_WARNING "Can't switch HDLC net mode on channel %s, since current interface is up\n", chans[ch.chan]->name); - return -EBUSY; - } -#ifdef LINUX26 - spin_unlock_irqrestore(&chans[ch.chan]->lock, flags); - unregister_hdlc_device(chans[ch.chan]->hdlcnetdev->netdev); - spin_lock_irqsave(&chans[ch.chan]->lock, flags); - free_netdev(chans[ch.chan]->hdlcnetdev->netdev); -#else - unregister_hdlc_device(&chans[ch.chan]->hdlcnetdev->netdev); -#endif - kfree(chans[ch.chan]->hdlcnetdev); - chans[ch.chan]->hdlcnetdev = NULL; - chans[ch.chan]->flags &= ~ZT_FLAG_NETDEV; - } -#else - if (ch.sigtype == ZT_SIG_HDLCNET) { - spin_unlock_irqrestore(&chans[ch.chan]->lock, flags); - printk(KERN_WARNING "Zaptel networking not supported by this build.\n"); - return -ENOSYS; - } -#endif - sigcap = chans[ch.chan]->sigcap; - /* If they support clear channel, then they support the HDLC and such through - us. */ - if (sigcap & ZT_SIG_CLEAR) - sigcap |= (ZT_SIG_HDLCRAW | ZT_SIG_HDLCFCS | ZT_SIG_HDLCNET | ZT_SIG_DACS); - - if ((sigcap & ch.sigtype) != ch.sigtype) - res = -EINVAL; - - if (!res && chans[ch.chan]->span->chanconfig) - res = chans[ch.chan]->span->chanconfig(chans[ch.chan], ch.sigtype); - if (chans[ch.chan]->master) { - /* Clear the master channel */ - recalc_slaves(chans[ch.chan]->master); - chans[ch.chan]->nextslave = 0; - } - if (!res) { - chans[ch.chan]->sig = ch.sigtype; - if (chans[ch.chan]->sig == ZT_SIG_CAS) - chans[ch.chan]->idlebits = ch.idlebits; - else - chans[ch.chan]->idlebits = 0; - if ((ch.sigtype & ZT_SIG_CLEAR) == ZT_SIG_CLEAR) { - /* Set clear channel flag if appropriate */ - chans[ch.chan]->flags &= ~ZT_FLAG_AUDIO; - chans[ch.chan]->flags |= ZT_FLAG_CLEAR; - } else { - /* Set audio flag and not clear channel otherwise */ - chans[ch.chan]->flags |= ZT_FLAG_AUDIO; - chans[ch.chan]->flags &= ~ZT_FLAG_CLEAR; - } - if ((ch.sigtype & ZT_SIG_HDLCRAW) == ZT_SIG_HDLCRAW) { - /* Set the HDLC flag */ - chans[ch.chan]->flags |= ZT_FLAG_HDLC; - } else { - /* Clear the HDLC flag */ - chans[ch.chan]->flags &= ~ZT_FLAG_HDLC; - } - if ((ch.sigtype & ZT_SIG_HDLCFCS) == ZT_SIG_HDLCFCS) { - /* Set FCS to be calculated if appropriate */ - chans[ch.chan]->flags |= ZT_FLAG_FCS; - } else { - /* Clear FCS flag */ - chans[ch.chan]->flags &= ~ZT_FLAG_FCS; - } - if ((ch.sigtype & __ZT_SIG_DACS) == __ZT_SIG_DACS) { - /* Setup conference properly */ - chans[ch.chan]->confmode = ZT_CONF_DIGITALMON; - chans[ch.chan]->confna = ch.idlebits; - if (chans[ch.chan]->span && - chans[ch.chan]->span->dacs && - chans[ch.idlebits] && - chans[ch.chan]->span && - (chans[ch.chan]->span->dacs == chans[ch.idlebits]->span->dacs)) - chans[ch.chan]->span->dacs(chans[ch.chan], chans[ch.idlebits]); - } else if (chans[ch.chan]->span && chans[ch.chan]->span->dacs) - chans[ch.chan]->span->dacs(chans[ch.chan], NULL); - chans[ch.chan]->master = newmaster; - /* Note new slave if we are not our own master */ - if (newmaster != chans[ch.chan]) { - recalc_slaves(chans[ch.chan]->master); - } - if ((ch.sigtype & ZT_SIG_HARDHDLC) == ZT_SIG_HARDHDLC) { - chans[ch.chan]->flags &= ~ZT_FLAG_FCS; - chans[ch.chan]->flags &= ~ZT_FLAG_HDLC; - chans[ch.chan]->flags |= ZT_FLAG_NOSTDTXRX; - } else - chans[ch.chan]->flags &= ~ZT_FLAG_NOSTDTXRX; - } -#ifdef CONFIG_ZAPATA_NET - if (!res && - (newmaster == chans[ch.chan]) && - (chans[ch.chan]->sig == ZT_SIG_HDLCNET)) { - chans[ch.chan]->hdlcnetdev = zt_hdlc_alloc(); - if (chans[ch.chan]->hdlcnetdev) { -/* struct hdlc_device *hdlc = chans[ch.chan]->hdlcnetdev; - struct net_device *d = hdlc_to_dev(hdlc); mmm...get it right later --byg */ -#ifdef LINUX26 - chans[ch.chan]->hdlcnetdev->netdev = alloc_hdlcdev(chans[ch.chan]->hdlcnetdev); - if (chans[ch.chan]->hdlcnetdev->netdev) { - chans[ch.chan]->hdlcnetdev->chan = chans[ch.chan]; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23) - SET_MODULE_OWNER(chans[ch.chan]->hdlcnetdev->netdev); -#endif - chans[ch.chan]->hdlcnetdev->netdev->irq = chans[ch.chan]->span->irq; - chans[ch.chan]->hdlcnetdev->netdev->tx_queue_len = 50; - chans[ch.chan]->hdlcnetdev->netdev->do_ioctl = zt_net_ioctl; - chans[ch.chan]->hdlcnetdev->netdev->open = zt_net_open; - chans[ch.chan]->hdlcnetdev->netdev->stop = zt_net_stop; - dev_to_hdlc(chans[ch.chan]->hdlcnetdev->netdev)->attach = zt_net_attach; - dev_to_hdlc(chans[ch.chan]->hdlcnetdev->netdev)->xmit = zt_xmit; - spin_unlock_irqrestore(&chans[ch.chan]->lock, flags); - /* Briefly restore interrupts while we register the device */ - res = zt_register_hdlc_device(chans[ch.chan]->hdlcnetdev->netdev, ch.netdev_name); - spin_lock_irqsave(&chans[ch.chan]->lock, flags); - } else { - printk("Unable to allocate hdlc: *shrug*\n"); - res = -1; - } -#else /* LINUX26 */ - chans[ch.chan]->hdlcnetdev->chan = chans[ch.chan]; -#ifndef HDLC_MAINTAINERS_ARE_MORE_STUPID_THAN_I_THOUGHT - chans[ch.chan]->hdlcnetdev->netdev.ioctl = zt_net_ioctl; -#endif - chans[ch.chan]->hdlcnetdev->netdev.netdev.do_ioctl = zt_net_ioctl; -#ifdef NEW_HDLC_INTERFACE - chans[ch.chan]->hdlcnetdev->netdev.netdev.open = zt_net_open; - chans[ch.chan]->hdlcnetdev->netdev.netdev.stop = zt_net_stop; - chans[ch.chan]->hdlcnetdev->netdev.xmit = zt_xmit; - chans[ch.chan]->hdlcnetdev->netdev.attach = zt_net_attach; -#else - chans[ch.chan]->hdlcnetdev->netdev.open = zt_net_open; - chans[ch.chan]->hdlcnetdev->netdev.close = zt_net_close; - chans[ch.chan]->hdlcnetdev->netdev.set_mode = NULL; - chans[ch.chan]->hdlcnetdev->netdev.xmit = zt_xmit; -#endif /* NEW_HDLC_INTERFACE */ - chans[ch.chan]->hdlcnetdev->netdev.netdev.irq = chans[ch.chan]->span->irq; - chans[ch.chan]->hdlcnetdev->netdev.netdev.tx_queue_len = 50; - res = register_hdlc_device(&chans[ch.chan]->hdlcnetdev->netdev); -#endif /* LINUX26 */ - if (!res) - chans[ch.chan]->flags |= ZT_FLAG_NETDEV; - } else { - printk("Unable to allocate netdev: out of memory\n"); - res = -1; - } - } -#endif - if ((chans[ch.chan]->sig == ZT_SIG_HDLCNET) && - (chans[ch.chan] == newmaster) && - !(chans[ch.chan]->flags & ZT_FLAG_NETDEV)) - printk("Unable to register HDLC device for channel %s\n", chans[ch.chan]->name); - if (!res) { - /* Setup default law */ - chans[ch.chan]->deflaw = ch.deflaw; - /* Copy back any modified settings */ - spin_unlock_irqrestore(&chans[ch.chan]->lock, flags); - if (copy_to_user((struct zt_chanconfig *)data, &ch, sizeof(ch))) - return -EFAULT; - spin_lock_irqsave(&chans[ch.chan]->lock, flags); - /* And hangup */ - zt_hangup(chans[ch.chan]); - y = zt_q_sig(chans[ch.chan]) & 0xff; - if (y >= 0) chans[ch.chan]->rxsig = (unsigned char)y; - chans[ch.chan]->rxhooksig = ZT_RXSIG_INITIAL; - } -#ifdef CONFIG_ZAPATA_DEBUG - printk("Configured channel %s, flags %04x, sig %04x\n", chans[ch.chan]->name, chans[ch.chan]->flags, chans[ch.chan]->sig); -#endif - spin_unlock_irqrestore(&chans[ch.chan]->lock, flags); - return res; - case ZT_SFCONFIG: - if (copy_from_user(&sf, (struct zt_chanconfig *)data, sizeof(sf))) - return -EFAULT; - VALID_CHANNEL(sf.chan); - if (chans[sf.chan]->sig != ZT_SIG_SF) return -EINVAL; - spin_lock_irqsave(&chans[sf.chan]->lock, flags); - chans[sf.chan]->rxp1 = sf.rxp1; - chans[sf.chan]->rxp2 = sf.rxp2; - chans[sf.chan]->rxp3 = sf.rxp3; - chans[sf.chan]->txtone = sf.txtone; - chans[sf.chan]->tx_v2 = sf.tx_v2; - chans[sf.chan]->tx_v3 = sf.tx_v3; - chans[sf.chan]->toneflags = sf.toneflag; - if (sf.txtone) /* if set to make tone for tx */ - { - if ((chans[sf.chan]->txhooksig && !(sf.toneflag & ZT_REVERSE_TXTONE)) || - ((!chans[sf.chan]->txhooksig) && (sf.toneflag & ZT_REVERSE_TXTONE))) - { - set_txtone(chans[sf.chan],sf.txtone,sf.tx_v2,sf.tx_v3); - } - else - { - set_txtone(chans[sf.chan],0,0,0); - } - } - spin_unlock_irqrestore(&chans[sf.chan]->lock, flags); - return res; - case ZT_DEFAULTZONE: - if (get_user(j,(int *)data)) - return -EFAULT; - if ((j < 0) || (j >= ZT_TONE_ZONE_MAX)) - return -EINVAL; - write_lock(&zone_lock); - if (!tone_zones[j]) { - write_unlock(&zone_lock); - return -EINVAL; - } - if ((default_zone != -1) && tone_zones[default_zone]) - atomic_dec(&tone_zones[default_zone]->refcount); - atomic_inc(&tone_zones[j]->refcount); - default_zone = j; - write_unlock(&zone_lock); - break; - case ZT_LOADZONE: - return ioctl_load_zone(data); - case ZT_FREEZONE: - get_user(j, (int *) data); - return free_tone_zone(j); - case ZT_SET_DIALPARAMS: - if (copy_from_user(&tdp, (struct zt_dialparams *) data, sizeof(tdp))) - return -EFAULT; - if ((tdp.dtmf_tonelen > 4000) || (tdp.dtmf_tonelen < 10)) - return -EINVAL; - if ((tdp.mfv1_tonelen > 4000) || (tdp.mfv1_tonelen < 10)) - return -EINVAL; - - global_dialparams = tdp; - - /* update the lengths in all currently loaded zones */ - write_lock(&zone_lock); - for (j = 0; j < sizeof(tone_zones) / sizeof(tone_zones[0]); j++) { - struct zt_zone *z = tone_zones[j]; - - if (!z) - continue; - - for (i = 0; i < sizeof(z->dtmf) / sizeof(z->dtmf[0]); i++) - z->dtmf[i].tonesamples = tdp.dtmf_tonelen * ZT_CHUNKSIZE; - - for (i = 0; i < sizeof(z->mf) / sizeof(z->mf[0]); i++) - z->mf[i].tonesamples = tdp.mfv1_tonelen * ZT_CHUNKSIZE; - - /* Special case for K/P tone */ - z->mf[10].tonesamples *= 5 / 3; - } - write_unlock(&zone_lock); - - dtmf_silence.tonesamples = tdp.dtmf_tonelen * ZT_CHUNKSIZE; - mfv1_silence.tonesamples = tdp.mfv1_tonelen * ZT_CHUNKSIZE; - - break; - case ZT_GET_DIALPARAMS: - tdp = global_dialparams; - if (copy_to_user((struct zt_dialparams *) data, &tdp, sizeof(tdp))) - return -EFAULT; - break; - case ZT_GETVERSION: - memset(&vi, 0, sizeof(vi)); - strncpy(vi.version, ZAPTEL_VERSION, sizeof(vi.version) - 1); - echo_can_identify(vi.echo_canceller, sizeof(vi.echo_canceller) - 1); - if (copy_to_user((struct zt_versioninfo *) data, &vi, sizeof(vi))) - return -EFAULT; - break; - case ZT_MAINT: /* do maintenance stuff */ - /* get struct from user */ - if (copy_from_user(&maint,(struct zt_maintinfo *) data, sizeof(maint))) - return -EFAULT; - /* must be valid span number */ - if ((maint.spanno < 1) || (maint.spanno > ZT_MAX_SPANS) || (!spans[maint.spanno])) - return -EINVAL; - if (!spans[maint.spanno]->maint) - return -ENOSYS; - spin_lock_irqsave(&spans[maint.spanno]->lock, flags); - /* save current maint state */ - i = spans[maint.spanno]->maintstat; - /* set maint mode */ - spans[maint.spanno]->maintstat = maint.command; - switch(maint.command) { - case ZT_MAINT_NONE: - case ZT_MAINT_LOCALLOOP: - case ZT_MAINT_REMOTELOOP: - /* if same, ignore it */ - if (i == maint.command) break; - rv = spans[maint.spanno]->maint(spans[maint.spanno], maint.command); - spin_unlock_irqrestore(&spans[maint.spanno]->lock, flags); - if (rv) return rv; - spin_lock_irqsave(&spans[maint.spanno]->lock, flags); - break; - case ZT_MAINT_LOOPUP: - case ZT_MAINT_LOOPDOWN: - spans[maint.spanno]->mainttimer = ZT_LOOPCODE_TIME * ZT_CHUNKSIZE; - rv = spans[maint.spanno]->maint(spans[maint.spanno], maint.command); - spin_unlock_irqrestore(&spans[maint.spanno]->lock, flags); - if (rv) return rv; - rv = schluffen(&spans[maint.spanno]->maintq); - if (rv) return rv; - spin_lock_irqsave(&spans[maint.spanno]->lock, flags); - break; - default: - printk("zaptel: Unknown maintenance event: %d\n", maint.command); - } - zt_alarm_notify(spans[maint.spanno]); /* process alarm-related events */ - spin_unlock_irqrestore(&spans[maint.spanno]->lock, flags); - break; - case ZT_DYNAMIC_CREATE: - case ZT_DYNAMIC_DESTROY: - if (zt_dynamic_ioctl) - return zt_dynamic_ioctl(cmd, data); - else { - request_module("ztdynamic"); - if (zt_dynamic_ioctl) - return zt_dynamic_ioctl(cmd, data); - } - return -ENOSYS; -#if defined(ECHO_CAN_HPEC) - case ZT_EC_LICENSE_CHALLENGE: - case ZT_EC_LICENSE_RESPONSE: - return hpec_license_ioctl(cmd, data); -#endif /* defined(ECHO_CAN_HPEC) */ - default: - return zt_common_ioctl(inode, file, cmd, data, 0); - } - return 0; -} - -static int zt_chanandpseudo_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit) -{ - struct zt_chan *chan = chans[unit]; - union { - struct zt_dialoperation tdo; - struct zt_bufferinfo bi; - struct zt_confinfo conf; - struct zt_ring_cadence cad; - } stack; - unsigned long flags, flagso; - int i, j, k, rv; - int ret, c; - char *s; - - if (!chan) - return -EINVAL; - switch(cmd) { - case ZT_DIALING: - spin_lock_irqsave(&chan->lock, flags); - j = chan->dialing; - spin_unlock_irqrestore(&chan->lock, flags); - if (copy_to_user((int *)data,&j,sizeof(int))) - return -EFAULT; - return 0; - case ZT_DIAL: - if (copy_from_user(&stack.tdo, (struct zt_dialoperation *)data, sizeof(stack.tdo))) - return -EFAULT; - rv = 0; - /* Force proper NULL termination and uppercase entry */ - stack.tdo.dialstr[ZT_MAX_DTMF_BUF - 1] = '\0'; - for (s = stack.tdo.dialstr; *s; s++) - *s = toupper(*s); - spin_lock_irqsave(&chan->lock, flags); - switch (stack.tdo.op) { - case ZT_DIAL_OP_CANCEL: - chan->curtone = NULL; - chan->dialing = 0; - chan->txdialbuf[0] = '\0'; - chan->tonep = 0; - chan->pdialcount = 0; - break; - case ZT_DIAL_OP_REPLACE: - strcpy(chan->txdialbuf, stack.tdo.dialstr); - chan->dialing = 1; - __do_dtmf(chan); - break; - case ZT_DIAL_OP_APPEND: - if (strlen(stack.tdo.dialstr) + strlen(chan->txdialbuf) >= (ZT_MAX_DTMF_BUF - 1)) { - rv = -EBUSY; - break; - } - strncpy(chan->txdialbuf + strlen(chan->txdialbuf), stack.tdo.dialstr, ZT_MAX_DTMF_BUF - strlen(chan->txdialbuf) - 1); - if (!chan->dialing) { - chan->dialing = 1; - __do_dtmf(chan); - } - break; - default: - rv = -EINVAL; - } - spin_unlock_irqrestore(&chan->lock, flags); - return rv; - case ZT_GET_BUFINFO: - stack.bi.rxbufpolicy = chan->rxbufpolicy; - stack.bi.txbufpolicy = chan->txbufpolicy; - stack.bi.numbufs = chan->numbufs; - stack.bi.bufsize = chan->blocksize; - /* XXX FIXME! XXX */ - stack.bi.readbufs = -1; - stack.bi.writebufs = -1; - if (copy_to_user((struct zt_bufferinfo *)data, &stack.bi, sizeof(stack.bi))) - return -EFAULT; - break; - case ZT_SET_BUFINFO: - if (copy_from_user(&stack.bi, (struct zt_bufferinfo *)data, sizeof(stack.bi))) - return -EFAULT; - if (stack.bi.bufsize > ZT_MAX_BLOCKSIZE) - return -EINVAL; - if (stack.bi.bufsize < 16) - return -EINVAL; - if (stack.bi.bufsize * stack.bi.numbufs > ZT_MAX_BUF_SPACE) - return -EINVAL; - chan->rxbufpolicy = stack.bi.rxbufpolicy & 0x1; - chan->txbufpolicy = stack.bi.txbufpolicy & 0x1; - if ((rv = zt_reallocbufs(chan, stack.bi.bufsize, stack.bi.numbufs))) - return (rv); - break; - case ZT_GET_BLOCKSIZE: /* get blocksize */ - put_user(chan->blocksize,(int *)data); /* return block size */ - break; - case ZT_SET_BLOCKSIZE: /* set blocksize */ - get_user(j,(int *)data); - /* cannot be larger than max amount */ - if (j > ZT_MAX_BLOCKSIZE) return(-EINVAL); - /* cannot be less then 16 */ - if (j < 16) return(-EINVAL); - /* allocate a single kernel buffer which we then - sub divide into four pieces */ - if ((rv = zt_reallocbufs(chan, j, chan->numbufs))) - return (rv); - break; - case ZT_FLUSH: /* flush input buffer, output buffer, and/or event queue */ - get_user(i,(int *)data); /* get param */ - spin_lock_irqsave(&chan->lock, flags); - if (i & ZT_FLUSH_READ) /* if for read (input) */ - { - /* initialize read buffers and pointers */ - chan->inreadbuf = 0; - chan->outreadbuf = -1; - for (j=0;jnumbufs;j++) { - /* Do we need this? */ - chan->readn[j] = 0; - chan->readidx[j] = 0; - } - wake_up_interruptible(&chan->readbufq); /* wake_up_interruptible waiting on read */ - wake_up_interruptible(&chan->sel); /* wake_up_interruptible waiting on select */ - } - if (i & ZT_FLUSH_WRITE) /* if for write (output) */ - { - /* initialize write buffers and pointers */ - chan->outwritebuf = -1; - chan->inwritebuf = 0; - for (j=0;jnumbufs;j++) { - /* Do we need this? */ - chan->writen[j] = 0; - chan->writeidx[j] = 0; - } - wake_up_interruptible(&chan->writebufq); /* wake_up_interruptible waiting on write */ - wake_up_interruptible(&chan->sel); /* wake_up_interruptible waiting on select */ - /* if IO MUX wait on write empty, well, this - certainly *did* empty the write */ - if (chan->iomask & ZT_IOMUX_WRITEEMPTY) - wake_up_interruptible(&chan->eventbufq); /* wake_up_interruptible waiting on IOMUX */ - } - if (i & ZT_FLUSH_EVENT) /* if for events */ - { - /* initialize the event pointers */ - chan->eventinidx = chan->eventoutidx = 0; - } - spin_unlock_irqrestore(&chan->lock, flags); - break; - case ZT_SYNC: /* wait for no tx */ - for(;;) /* loop forever */ - { - spin_lock_irqsave(&chan->lock, flags); - /* Know if there is a write pending */ - i = (chan->outwritebuf > -1); - spin_unlock_irqrestore(&chan->lock, flags); - if (!i) break; /* skip if none */ - rv = schluffen(&chan->writebufq); - if (rv) return(rv); - } - break; - case ZT_IOMUX: /* wait for something to happen */ - get_user(chan->iomask,(int*)data); /* save mask */ - if (!chan->iomask) return(-EINVAL); /* cant wait for nothing */ - for(;;) /* loop forever */ - { - /* has to have SOME mask */ - ret = 0; /* start with empty return value */ - spin_lock_irqsave(&chan->lock, flags); - /* if looking for read */ - if (chan->iomask & ZT_IOMUX_READ) - { - /* if read available */ - if ((chan->outreadbuf > -1) && !chan->rxdisable) - ret |= ZT_IOMUX_READ; - } - /* if looking for write avail */ - if (chan->iomask & ZT_IOMUX_WRITE) - { - if (chan->inwritebuf > -1) - ret |= ZT_IOMUX_WRITE; - } - /* if looking for write empty */ - if (chan->iomask & ZT_IOMUX_WRITEEMPTY) - { - /* if everything empty -- be sure the transmitter is enabled */ - chan->txdisable = 0; - if (chan->outwritebuf < 0) - ret |= ZT_IOMUX_WRITEEMPTY; - } - /* if looking for signalling event */ - if (chan->iomask & ZT_IOMUX_SIGEVENT) - { - /* if event */ - if (chan->eventinidx != chan->eventoutidx) - ret |= ZT_IOMUX_SIGEVENT; - } - spin_unlock_irqrestore(&chan->lock, flags); - /* if something to return, or not to wait */ - if (ret || (chan->iomask & ZT_IOMUX_NOWAIT)) - { - /* set return value */ - put_user(ret,(int *)data); - break; /* get out of loop */ - } - rv = schluffen(&chan->eventbufq); - if (rv) return(rv); - } - /* clear IO MUX mask */ - chan->iomask = 0; - break; - case ZT_GETEVENT: /* Get event on queue */ - /* set up for no event */ - j = ZT_EVENT_NONE; - spin_lock_irqsave(&chan->lock, flags); - /* if some event in queue */ - if (chan->eventinidx != chan->eventoutidx) - { - j = chan->eventbuf[chan->eventoutidx++]; - /* get the data, bump index */ - /* if index overflow, set to beginning */ - if (chan->eventoutidx >= ZT_MAX_EVENTSIZE) - chan->eventoutidx = 0; - } - spin_unlock_irqrestore(&chan->lock, flags); - put_user(j,(int *)data); - break; - case ZT_CONFMUTE: /* set confmute flag */ - get_user(j,(int *)data); /* get conf # */ - if (!(chan->flags & ZT_FLAG_AUDIO)) return (-EINVAL); - spin_lock_irqsave(&bigzaplock, flags); - chan->confmute = j; - spin_unlock_irqrestore(&bigzaplock, flags); - break; - case ZT_GETCONFMUTE: /* get confmute flag */ - if (!(chan->flags & ZT_FLAG_AUDIO)) return (-EINVAL); - j = chan->confmute; - put_user(j,(int *)data); /* get conf # */ - rv = 0; - break; - case ZT_SETTONEZONE: - get_user(j, (int *) data); - rv = set_tone_zone(chan, j); - return rv; - case ZT_GETTONEZONE: - spin_lock_irqsave(&chan->lock, flags); - if (chan->curzone) - j = chan->tonezone; - spin_unlock_irqrestore(&chan->lock, flags); - put_user(j, (int *) data); - break; - case ZT_SENDTONE: - get_user(j,(int *)data); - spin_lock_irqsave(&chan->lock, flags); - rv = start_tone(chan, j); - spin_unlock_irqrestore(&chan->lock, flags); - return rv; - case ZT_GETCONF: /* get conf stuff */ - if (copy_from_user(&stack.conf,(struct zt_confinfo *) data,sizeof(stack.conf))) - return -EFAULT; - i = stack.conf.chan; /* get channel no */ - /* if zero, use current channel no */ - if (!i) i = chan->channo; - /* make sure channel number makes sense */ - if ((i < 0) || (i > ZT_MAX_CONF) || (!chans[i])) return(-EINVAL); - if (!(chans[i]->flags & ZT_FLAG_AUDIO)) return (-EINVAL); - stack.conf.chan = i; /* get channel number */ - stack.conf.confno = chans[i]->confna; /* get conference number */ - stack.conf.confmode = chans[i]->confmode; /* get conference mode */ - if (copy_to_user((struct zt_confinfo *) data,&stack.conf,sizeof(stack.conf))) - return -EFAULT; - break; - case ZT_SETCONF: /* set conf stuff */ - if (copy_from_user(&stack.conf,(struct zt_confinfo *) data,sizeof(stack.conf))) - return -EFAULT; - i = stack.conf.chan; /* get channel no */ - /* if zero, use current channel no */ - if (!i) i = chan->channo; - /* make sure channel number makes sense */ - if ((i < 1) || (i > ZT_MAX_CHANNELS) || (!chans[i])) return(-EINVAL); - if (!(chans[i]->flags & ZT_FLAG_AUDIO)) return (-EINVAL); - if ((stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR || - (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORTX || - (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORBOTH || - (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_RX_PREECHO || - (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_TX_PREECHO || - (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORBOTH_PREECHO) { - /* Monitor mode -- it's a channel */ - if ((stack.conf.confno < 0) || (stack.conf.confno >= ZT_MAX_CHANNELS) || !chans[stack.conf.confno]) return(-EINVAL); - } else { - /* make sure conf number makes sense, too */ - if ((stack.conf.confno < -1) || (stack.conf.confno > ZT_MAX_CONF)) return(-EINVAL); - } - - /* if taking off of any conf, must have 0 mode */ - if ((!stack.conf.confno) && stack.conf.confmode) return(-EINVAL); - /* likewise if 0 mode must have no conf */ - if ((!stack.conf.confmode) && stack.conf.confno) return (-EINVAL); - stack.conf.chan = i; /* return with real channel # */ - spin_lock_irqsave(&bigzaplock, flagso); - spin_lock_irqsave(&chan->lock, flags); - if (stack.conf.confno == -1) - stack.conf.confno = zt_first_empty_conference(); - if ((stack.conf.confno < 1) && (stack.conf.confmode)) { - /* No more empty conferences */ - spin_unlock_irqrestore(&chan->lock, flags); - spin_unlock_irqrestore(&bigzaplock, flagso); - return -EBUSY; - } - /* if changing confs, clear last added info */ - if (stack.conf.confno != chans[i]->confna) { - memset(chans[i]->conflast, 0, ZT_MAX_CHUNKSIZE); - memset(chans[i]->conflast1, 0, ZT_MAX_CHUNKSIZE); - memset(chans[i]->conflast2, 0, ZT_MAX_CHUNKSIZE); - } - j = chans[i]->confna; /* save old conference number */ - chans[i]->confna = stack.conf.confno; /* set conference number */ - chans[i]->confmode = stack.conf.confmode; /* set conference mode */ - chans[i]->_confn = 0; /* Clear confn */ - zt_check_conf(j); - zt_check_conf(stack.conf.confno); - if (chans[i]->span && chans[i]->span->dacs) { - if (((stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_DIGITALMON) && - chans[stack.conf.confno]->span && - chans[stack.conf.confno]->span->dacs == chans[i]->span->dacs && - chans[i]->txgain == defgain && - chans[i]->rxgain == defgain && - chans[stack.conf.confno]->txgain == defgain && - chans[stack.conf.confno]->rxgain == defgain) { - chans[i]->span->dacs(chans[i], chans[stack.conf.confno]); - } else { - chans[i]->span->dacs(chans[i], NULL); - } - } - /* if we are going onto a conf */ - if (stack.conf.confno && - ((stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_CONF || - (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_CONFANN || - (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_CONFMON || - (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_CONFANNMON || - (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_REALANDPSEUDO)) { - /* Get alias */ - chans[i]->_confn = zt_get_conf_alias(stack.conf.confno); - } - - if (chans[stack.conf.confno]) { - if ((stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_RX_PREECHO || - (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITOR_TX_PREECHO || - (stack.conf.confmode & ZT_CONF_MODE_MASK) == ZT_CONF_MONITORBOTH_PREECHO) - chans[stack.conf.confno]->readchunkpreec = kmalloc(sizeof(*chans[stack.conf.confno]->readchunkpreec) * ZT_CHUNKSIZE, GFP_ATOMIC); - else { - if (chans[stack.conf.confno]->readchunkpreec) { - kfree(chans[stack.conf.confno]->readchunkpreec); - chans[stack.conf.confno]->readchunkpreec = NULL; - } - } - } - - spin_unlock_irqrestore(&chan->lock, flags); - spin_unlock_irqrestore(&bigzaplock, flagso); - if (copy_to_user((struct zt_confinfo *) data,&stack.conf,sizeof(stack.conf))) - return -EFAULT; - break; - case ZT_CONFLINK: /* do conf link stuff */ - if (!(chan->flags & ZT_FLAG_AUDIO)) return (-EINVAL); - if (copy_from_user(&stack.conf,(struct zt_confinfo *) data,sizeof(stack.conf))) - return -EFAULT; - /* check sanity of arguments */ - if ((stack.conf.chan < 0) || (stack.conf.chan > ZT_MAX_CONF)) return(-EINVAL); - if ((stack.conf.confno < 0) || (stack.conf.confno > ZT_MAX_CONF)) return(-EINVAL); - /* cant listen to self!! */ - if (stack.conf.chan && (stack.conf.chan == stack.conf.confno)) return(-EINVAL); - spin_lock_irqsave(&bigzaplock, flagso); - spin_lock_irqsave(&chan->lock, flags); - /* if to clear all links */ - if ((!stack.conf.chan) && (!stack.conf.confno)) - { - /* clear all the links */ - memset(conf_links,0,sizeof(conf_links)); - recalc_maxlinks(); - spin_unlock_irqrestore(&chan->lock, flags); - spin_unlock_irqrestore(&bigzaplock, flagso); - break; - } - rv = 0; /* clear return value */ - /* look for already existant specified combination */ - for(i = 1; i <= ZT_MAX_CONF; i++) - { - /* if found, exit */ - if ((conf_links[i].src == stack.conf.chan) && - (conf_links[i].dst == stack.conf.confno)) break; - } - if (i <= ZT_MAX_CONF) /* if found */ - { - if (!stack.conf.confmode) /* if to remove link */ - { - conf_links[i].src = conf_links[i].dst = 0; - } - else /* if to add and already there, error */ - { - rv = -EEXIST; - } - } - else /* if not found */ - { - if (stack.conf.confmode) /* if to add link */ - { - /* look for empty location */ - for(i = 1; i <= ZT_MAX_CONF; i++) - { - /* if empty, exit loop */ - if ((!conf_links[i].src) && - (!conf_links[i].dst)) break; - } - /* if empty spot found */ - if (i <= ZT_MAX_CONF) - { - conf_links[i].src = stack.conf.chan; - conf_links[i].dst = stack.conf.confno; - } - else /* if no empties -- error */ - { - rv = -ENOSPC; - } - } - else /* if to remove, and not found -- error */ - { - rv = -ENOENT; - } - } - recalc_maxlinks(); - spin_unlock_irqrestore(&chan->lock, flags); - spin_unlock_irqrestore(&bigzaplock, flagso); - return(rv); - case ZT_CONFDIAG: /* output diagnostic info to console */ - if (!(chan->flags & ZT_FLAG_AUDIO)) return (-EINVAL); - get_user(j,(int *)data); /* get conf # */ - /* loop thru the interesting ones */ - for(i = ((j) ? j : 1); i <= ((j) ? j : ZT_MAX_CONF); i++) - { - c = 0; - for(k = 1; k < ZT_MAX_CHANNELS; k++) - { - /* skip if no pointer */ - if (!chans[k]) continue; - /* skip if not in this conf */ - if (chans[k]->confna != i) continue; - if (!c) printk("Conf #%d:\n",i); - c = 1; - printk("chan %d, mode %x\n", - k,chans[k]->confmode); - } - rv = 0; - for(k = 1; k <= ZT_MAX_CONF; k++) - { - if (conf_links[k].dst == i) - { - if (!c) printk("Conf #%d:\n",i); - c = 1; - if (!rv) printk("Snooping on:\n"); - rv = 1; - printk("conf %d\n",conf_links[k].src); - } - } - if (c) printk("\n"); - } - break; - case ZT_CHANNO: /* get channel number of stream */ - put_user(unit,(int *)data); /* return unit/channel number */ - break; - case ZT_SETLAW: - get_user(j, (int *)data); - if ((j < 0) || (j > ZT_LAW_ALAW)) - return -EINVAL; - zt_set_law(chan, j); - break; - case ZT_SETLINEAR: - get_user(j, (int *)data); - /* Makes no sense on non-audio channels */ - if (!(chan->flags & ZT_FLAG_AUDIO)) - return -EINVAL; - - if (j) - chan->flags |= ZT_FLAG_LINEAR; - else - chan->flags &= ~ZT_FLAG_LINEAR; - break; - case ZT_SETCADENCE: - if (data) { - /* Use specific ring cadence */ - if (copy_from_user(&stack.cad, (struct zt_ring_cadence *)data, sizeof(stack.cad))) - return -EFAULT; - memcpy(chan->ringcadence, &stack.cad, sizeof(chan->ringcadence)); - chan->firstcadencepos = 0; - /* Looking for negative ringing time indicating where to loop back into ringcadence */ - for (i=0; iringcadence[i]<0) { - chan->ringcadence[i] *= -1; - chan->firstcadencepos = i; - break; - } - } - } else { - /* Reset to default */ - chan->firstcadencepos = 0; - if (chan->curzone) { - memcpy(chan->ringcadence, chan->curzone->ringcadence, sizeof(chan->ringcadence)); - /* Looking for negative ringing time indicating where to loop back into ringcadence */ - for (i=0; iringcadence[i]<0) { - chan->ringcadence[i] *= -1; - chan->firstcadencepos = i; - break; - } - } - } else { - memset(chan->ringcadence, 0, sizeof(chan->ringcadence)); - chan->ringcadence[0] = chan->starttime; - chan->ringcadence[1] = ZT_RINGOFFTIME; - } - } - break; - default: - /* Check for common ioctl's and private ones */ - rv = zt_common_ioctl(inode, file, cmd, data, unit); - /* if no span, just return with value */ - if (!chan->span) return rv; - if ((rv == -ENOTTY) && chan->span->ioctl) - rv = chan->span->ioctl(chan, cmd, data); - return rv; - - } - return 0; -} - -#ifdef CONFIG_ZAPATA_PPP -/* - * This is called at softirq (BH) level when there are calls - * we need to make to the ppp_generic layer. We do it this - * way because the ppp_generic layer functions may not be called - * at interrupt level. - */ -static void do_ppp_calls(unsigned long data) -{ - struct zt_chan *chan = (struct zt_chan *) data; - struct sk_buff *skb; - - if (!chan->ppp) - return; - if (chan->do_ppp_wakeup) { - chan->do_ppp_wakeup = 0; - ppp_output_wakeup(chan->ppp); - } - while ((skb = skb_dequeue(&chan->ppp_rq)) != NULL) - ppp_input(chan->ppp, skb); - if (chan->do_ppp_error) { - chan->do_ppp_error = 0; - ppp_input_error(chan->ppp, 0); - } -} -#endif - -static int ioctl_echocancel(struct zt_chan *chan, struct zt_echocanparams *ecp, void *data) -{ - struct echo_can_state *ec = NULL, *tec; - struct zt_echocanparam params[ZT_MAX_ECHOCANPARAMS]; - int ret; - unsigned long flags; - - if (ecp->param_count > ZT_MAX_ECHOCANPARAMS) - return -E2BIG; - - if (ecp->tap_length == 0) { - /* disable mode, don't need to inspect params */ - spin_lock_irqsave(&chan->lock, flags); - tec = chan->ec; - chan->ec = NULL; - chan->echocancel = 0; - chan->echostate = ECHO_STATE_IDLE; - chan->echolastupdate = 0; - chan->echotimer = 0; - spin_unlock_irqrestore(&chan->lock, flags); - - /* Make sure this is zero if we're disabling echo can */ - ecp->param_count = 0; - - if (chan->span) { - if (chan->span->echocan_with_params) - chan->span->echocan_with_params(chan, ecp, NULL); - else if (chan->span->echocan) - chan->span->echocan(chan, 0); - } - - if (tec) - echo_can_free(tec); - - return 0; - } - - /* if parameters were supplied and this channel's span provides an echocan, - but not one that takes params, then we must punt here and return an error */ - if (ecp->param_count && chan->span && chan->span->echocan && - !chan->span->echocan_with_params) - return -EINVAL; - - /* enable mode, need the params */ - - if (copy_from_user(params, (struct zt_echocanparam *) data, sizeof(params[0]) * ecp->param_count)) - return -EFAULT; - - spin_lock_irqsave(&chan->lock, flags); - tec = chan->ec; - chan->ec = NULL; - spin_unlock_irqrestore(&chan->lock, flags); - - if (tec) - echo_can_free(tec); - - ret = -ENODEV; - - /* attempt to use the span's echo canceler; fall back to built-in - if it fails (but not if an error occurs) */ - if (chan->span) { - if (ecp->param_count) { - if (chan->span->echocan_with_params) - ret = chan->span->echocan_with_params(chan, ecp, params); - } else if (chan->span->echocan) { - ret = chan->span->echocan(chan, ecp->tap_length); - } else if (chan->span->echocan_with_params) { - ret = chan->span->echocan_with_params(chan, ecp, NULL); - } - } - - if (ret == -ENODEV) { - switch (ecp->tap_length) { - case 32: - case 64: - case 128: - case 256: - case 512: - case 1024: - break; - default: - ecp->tap_length = deftaps; - } - - if ((ret = echo_can_create(ecp, params, &ec))) - return ret; - - spin_lock_irqsave(&chan->lock, flags); - chan->echocancel = ecp->tap_length; - chan->ec = ec; - chan->echostate = ECHO_STATE_IDLE; - chan->echolastupdate = 0; - chan->echotimer = 0; - echo_can_disable_detector_init(&chan->txecdis); - echo_can_disable_detector_init(&chan->rxecdis); - spin_unlock_irqrestore(&chan->lock, flags); - } - - return ret; -} - -static int zt_chan_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit) -{ - struct zt_chan *chan = chans[unit]; - unsigned long flags; - int j, rv; - int ret; - int oldconf; - void *rxgain=NULL; - struct echo_can_state *ec; - struct zt_echocanparams ecp; - - if (!chan) - return -ENOSYS; - - switch(cmd) { - case ZT_SIGFREEZE: - get_user(j, (int *)data); - spin_lock_irqsave(&chan->lock, flags); - if (j) { - chan->flags |= ZT_FLAG_SIGFREEZE; - } else { - chan->flags &= ~ZT_FLAG_SIGFREEZE; - } - spin_unlock_irqrestore(&chan->lock, flags); - break; - case ZT_GETSIGFREEZE: - spin_lock_irqsave(&chan->lock, flags); - if (chan->flags & ZT_FLAG_SIGFREEZE) - j = 1; - else - j = 0; - spin_unlock_irqrestore(&chan->lock, flags); - put_user(j, (int *)data); - break; - case ZT_AUDIOMODE: - /* Only literal clear channels can be put in */ - if (chan->sig != ZT_SIG_CLEAR) return (-EINVAL); - get_user(j, (int *)data); - if (j) { - spin_lock_irqsave(&chan->lock, flags); - chan->flags |= ZT_FLAG_AUDIO; - chan->flags &= ~(ZT_FLAG_HDLC | ZT_FLAG_FCS); - spin_unlock_irqrestore(&chan->lock, flags); - } else { - /* Coming out of audio mode, also clear all - conferencing and gain related info as well - as echo canceller */ - spin_lock_irqsave(&chan->lock, flags); - chan->flags &= ~ZT_FLAG_AUDIO; - /* save old conf number, if any */ - oldconf = chan->confna; - /* initialize conference variables */ - chan->_confn = 0; - chan->confna = 0; - if (chan->span && chan->span->dacs) - chan->span->dacs(chan, NULL); - chan->confmode = 0; - chan->confmute = 0; - memset(chan->conflast, 0, sizeof(chan->conflast)); - memset(chan->conflast1, 0, sizeof(chan->conflast1)); - memset(chan->conflast2, 0, sizeof(chan->conflast2)); - ec = chan->ec; - chan->ec = NULL; - /* release conference resource, if any to release */ - reset_conf(chan); - if (chan->gainalloc && chan->rxgain) - rxgain = chan->rxgain; - else - rxgain = NULL; - - chan->rxgain = defgain; - chan->txgain = defgain; - chan->gainalloc = 0; - /* Disable any native echo cancellation as well */ - spin_unlock_irqrestore(&chan->lock, flags); - - if (chan->span && chan->span->echocan) - chan->span->echocan(chan, 0); - - if (rxgain) - kfree(rxgain); - if (ec) - echo_can_free(ec); - if (oldconf) zt_check_conf(oldconf); - } - break; - case ZT_HDLCPPP: -#ifdef CONFIG_ZAPATA_PPP - if (chan->sig != ZT_SIG_CLEAR) return (-EINVAL); - get_user(j, (int *)data); - if (j) { - if (!chan->ppp) { - chan->ppp = kmalloc(sizeof(struct ppp_channel), GFP_KERNEL); - if (chan->ppp) { - struct echo_can_state *tec; - memset(chan->ppp, 0, sizeof(struct ppp_channel)); - chan->ppp->private = chan; - chan->ppp->ops = &ztppp_ops; - chan->ppp->mtu = ZT_DEFAULT_MTU_MRU; - chan->ppp->hdrlen = 0; - skb_queue_head_init(&chan->ppp_rq); - chan->do_ppp_wakeup = 0; - tasklet_init(&chan->ppp_calls, do_ppp_calls, - (unsigned long)chan); - if ((ret = zt_reallocbufs(chan, ZT_DEFAULT_MTU_MRU, ZT_DEFAULT_NUM_BUFS))) { - kfree(chan->ppp); - chan->ppp = NULL; - return ret; - } - - if ((ret = ppp_register_channel(chan->ppp))) { - kfree(chan->ppp); - chan->ppp = NULL; - return ret; - } - tec = chan->ec; - chan->ec = NULL; - chan->echocancel = 0; - chan->echostate = ECHO_STATE_IDLE; - chan->echolastupdate = 0; - chan->echotimer = 0; - /* Make sure there's no gain */ - if (chan->gainalloc) - kfree(chan->rxgain); - chan->rxgain = defgain; - chan->txgain = defgain; - chan->gainalloc = 0; - chan->flags &= ~ZT_FLAG_AUDIO; - chan->flags |= (ZT_FLAG_PPP | ZT_FLAG_HDLC | ZT_FLAG_FCS); - if (chan->span && chan->span->echocan) - chan->span->echocan(chan, 0); - if (tec) - echo_can_free(tec); - } else - return -ENOMEM; - } - } else { - chan->flags &= ~(ZT_FLAG_PPP | ZT_FLAG_HDLC | ZT_FLAG_FCS); - if (chan->ppp) { - struct ppp_channel *ppp = chan->ppp; - chan->ppp = NULL; - tasklet_kill(&chan->ppp_calls); - skb_queue_purge(&chan->ppp_rq); - ppp_unregister_channel(ppp); - kfree(ppp); - } - } -#else - printk("Zaptel: Zaptel PPP support not compiled in\n"); - return -ENOSYS; -#endif - break; - case ZT_HDLCRAWMODE: - if (chan->sig != ZT_SIG_CLEAR) return (-EINVAL); - get_user(j, (int *)data); - chan->flags &= ~(ZT_FLAG_AUDIO | ZT_FLAG_HDLC | ZT_FLAG_FCS); - if (j) { - chan->flags |= ZT_FLAG_HDLC; - fasthdlc_init(&chan->rxhdlc); - fasthdlc_init(&chan->txhdlc); - } - break; - case ZT_HDLCFCSMODE: - if (chan->sig != ZT_SIG_CLEAR) return (-EINVAL); - get_user(j, (int *)data); - chan->flags &= ~(ZT_FLAG_AUDIO | ZT_FLAG_HDLC | ZT_FLAG_FCS); - if (j) { - chan->flags |= ZT_FLAG_HDLC | ZT_FLAG_FCS; - fasthdlc_init(&chan->rxhdlc); - fasthdlc_init(&chan->txhdlc); - } - break; - case ZT_ECHOCANCEL_PARAMS: - if (!(chan->flags & ZT_FLAG_AUDIO)) - return -EINVAL; - if (copy_from_user(&ecp, (struct zt_echocanparams *) data, sizeof(ecp))) - return -EFAULT; - data += sizeof(ecp); - if ((ret = ioctl_echocancel(chan, &ecp, (void *) data))) - return ret; - break; - case ZT_ECHOCANCEL: - if (!(chan->flags & ZT_FLAG_AUDIO)) - return -EINVAL; - get_user(j, (int *) data); - ecp.tap_length = j; - ecp.param_count = 0; - if ((ret = ioctl_echocancel(chan, &ecp, NULL))) - return ret; - break; - case ZT_ECHOTRAIN: - get_user(j, (int *)data); /* get pre-training time from user */ - if ((j < 0) || (j >= ZT_MAX_PRETRAINING)) - return -EINVAL; - j <<= 3; - if (chan->ec) { - /* Start pretraining stage */ - chan->echostate = ECHO_STATE_PRETRAINING; - chan->echotimer = j; - } else - return -EINVAL; - break; - case ZT_SETTXBITS: - if (chan->sig != ZT_SIG_CAS) - return -EINVAL; - get_user(j,(int *)data); - zt_cas_setbits(chan, j); - rv = 0; - break; - case ZT_GETRXBITS: - put_user(chan->rxsig, (int *)data); - rv = 0; - break; - case ZT_LOOPBACK: - get_user(j, (int *)data); - spin_lock_irqsave(&chan->lock, flags); - if (j) - chan->flags |= ZT_FLAG_LOOPED; - else - chan->flags &= ~ZT_FLAG_LOOPED; - spin_unlock_irqrestore(&chan->lock, flags); - rv = 0; - break; - case ZT_HOOK: - get_user(j,(int *)data); - if (chan->flags & ZT_FLAG_CLEAR) - return -EINVAL; - if (chan->sig == ZT_SIG_CAS) - return -EINVAL; - /* if no span, just do nothing */ - if (!chan->span) return(0); - spin_lock_irqsave(&chan->lock, flags); - /* if dialing, stop it */ - chan->curtone = NULL; - chan->dialing = 0; - chan->txdialbuf[0] = '\0'; - chan->tonep = 0; - chan->pdialcount = 0; - spin_unlock_irqrestore(&chan->lock, flags); - if (chan->span->flags & ZT_FLAG_RBS) { - switch (j) { - case ZT_ONHOOK: - spin_lock_irqsave(&chan->lock, flags); - zt_hangup(chan); - spin_unlock_irqrestore(&chan->lock, flags); - break; - case ZT_OFFHOOK: - spin_lock_irqsave(&chan->lock, flags); - if ((chan->txstate == ZT_TXSTATE_KEWL) || - (chan->txstate == ZT_TXSTATE_AFTERKEWL)) { - spin_unlock_irqrestore(&chan->lock, flags); - return -EBUSY; - } - zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_DEBOUNCE, chan->debouncetime); - spin_unlock_irqrestore(&chan->lock, flags); - break; - case ZT_RING: - case ZT_START: - spin_lock_irqsave(&chan->lock, flags); - if (chan->txstate != ZT_TXSTATE_ONHOOK) { - spin_unlock_irqrestore(&chan->lock, flags); - return -EBUSY; - } - if (chan->sig & __ZT_SIG_FXO) { - ret = 0; - chan->cadencepos = 0; - ret = chan->ringcadence[0]; - zt_rbs_sethook(chan, ZT_TXSIG_START, ZT_TXSTATE_RINGON, ret); - } else - zt_rbs_sethook(chan, ZT_TXSIG_START, ZT_TXSTATE_START, chan->starttime); - spin_unlock_irqrestore(&chan->lock, flags); - if (file->f_flags & O_NONBLOCK) - return -EINPROGRESS; -#if 0 - rv = schluffen(&chan->txstateq); - if (rv) return rv; -#endif - rv = 0; - break; - case ZT_WINK: - spin_lock_irqsave(&chan->lock, flags); - if (chan->txstate != ZT_TXSTATE_ONHOOK) { - spin_unlock_irqrestore(&chan->lock, flags); - return -EBUSY; - } - zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_PREWINK, chan->prewinktime); - spin_unlock_irqrestore(&chan->lock, flags); - if (file->f_flags & O_NONBLOCK) - return -EINPROGRESS; - rv = schluffen(&chan->txstateq); - if (rv) return rv; - break; - case ZT_FLASH: - spin_lock_irqsave(&chan->lock, flags); - if (chan->txstate != ZT_TXSTATE_OFFHOOK) { - spin_unlock_irqrestore(&chan->lock, flags); - return -EBUSY; - } - zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_PREFLASH, chan->preflashtime); - spin_unlock_irqrestore(&chan->lock, flags); - if (file->f_flags & O_NONBLOCK) - return -EINPROGRESS; - rv = schluffen(&chan->txstateq); - if (rv) return rv; - break; - case ZT_RINGOFF: - spin_lock_irqsave(&chan->lock, flags); - zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_ONHOOK, 0); - spin_unlock_irqrestore(&chan->lock, flags); - break; - default: - return -EINVAL; - } - } else if (chan->span->sethook) { - if (chan->txhooksig != j) { - chan->txhooksig = j; - chan->span->sethook(chan, j); - } - } else - return -ENOSYS; - break; -#ifdef CONFIG_ZAPATA_PPP - case PPPIOCGCHAN: - if (chan->flags & ZT_FLAG_PPP) - return put_user(ppp_channel_index(chan->ppp), (int *)data) ? -EFAULT : 0; - else - return -EINVAL; - break; - case PPPIOCGUNIT: - if (chan->flags & ZT_FLAG_PPP) - return put_user(ppp_unit_number(chan->ppp), (int *)data) ? -EFAULT : 0; - else - return -EINVAL; - break; -#endif - default: - return zt_chanandpseudo_ioctl(inode, file, cmd, data, unit); - } - return 0; -} - -static int zt_prechan_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data, int unit) -{ - struct zt_chan *chan = file->private_data; - int channo; - int res; - - if (chan) { - printk("Huh? Prechan already has private data??\n"); - } - switch(cmd) { - case ZT_SPECIFY: - get_user(channo,(int *)data); - if (channo < 1) - return -EINVAL; - if (channo > ZT_MAX_CHANNELS) - return -EINVAL; - res = zt_specchan_open(inode, file, channo, 0); - if (!res) { - /* Setup the pointer for future stuff */ - chan = chans[channo]; - file->private_data = chan; - /* Return success */ - return 0; - } - return res; - default: - return -ENOSYS; - } - return 0; -} - -static int zt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data) -{ - int unit = UNIT(file); - struct zt_chan *chan; - struct zt_timer *timer; - - if (!unit) - return zt_ctl_ioctl(inode, file, cmd, data); - - if (unit == 250) - return zt_transcode_fops->ioctl(inode, file, cmd, data); - - if (unit == 253) { - timer = file->private_data; - if (timer) - return zt_timer_ioctl(inode, file, cmd, data, timer); - else - return -EINVAL; - } - if (unit == 254) { - chan = file->private_data; - if (chan) - return zt_chan_ioctl(inode, file, cmd, data, chan->channo); - else - return zt_prechan_ioctl(inode, file, cmd, data, unit); - } - if (unit == 255) { - chan = file->private_data; - if (!chan) { - printk("No pseudo channel structure to read?\n"); - return -EINVAL; - } - return zt_chanandpseudo_ioctl(inode, file, cmd, data, chan->channo); - } - return zt_chan_ioctl(inode, file, cmd, data, unit); -} - -int zt_register(struct zt_span *span, int prefmaster) -{ - int x; - -#ifdef CONFIG_PROC_FS - char tempfile[17]; -#endif - if (!span) - return -EINVAL; - if (span->flags & ZT_FLAG_REGISTERED) { - printk(KERN_ERR "Span %s already appears to be registered\n", span->name); - return -EBUSY; - } - for (x=1;xname); - return -EBUSY; - } - for (x=1;xflags |= ZT_FLAG_REGISTERED; - span->spanno = x; - spin_lock_init(&span->lock); - if (!span->deflaw) { - printk("zaptel: Span %s didn't specify default law. Assuming mulaw, please fix driver!\n", span->name); - span->deflaw = ZT_LAW_MULAW; - } - - for (x=0;xchannels;x++) { - span->chans[x].span = span; - zt_chan_reg(&span->chans[x]); - } - -#ifdef CONFIG_PROC_FS - sprintf(tempfile, "zaptel/%d", span->spanno); - proc_entries[span->spanno] = create_proc_read_entry(tempfile, 0444, NULL , zaptel_proc_read, (int *)(long)span->spanno); -#endif - -#ifdef CONFIG_DEVFS_FS - { - char span_name[50]; - sprintf(span_name, "span%d", span->spanno); - span->dhandle = devfs_mk_dir(zaptel_devfs_dir, span_name, NULL); - for (x = 0; x < span->channels; x++) { - struct zt_chan *chan = &span->chans[x]; - chan->fhandle = register_devfs_channel(chan, chan->span->dhandle); /* Register our stuff with devfs */ - } - } -#endif /* CONFIG_DEVFS_FS */ - -#ifdef CONFIG_ZAP_UDEV - for (x = 0; x < span->channels; x++) { - char chan_name[50]; - if (span->chans[x].channo < 250) { - sprintf(chan_name, "zap%d", span->chans[x].channo); - CLASS_DEV_CREATE(zap_class, MKDEV(ZT_MAJOR, span->chans[x].channo), NULL, chan_name); - } - } -#endif /* CONFIG_ZAP_UDEV */ - - if (debug) - printk("Registered Span %d ('%s') with %d channels\n", span->spanno, span->name, span->channels); - if (!master || prefmaster) { - master = span; - if (debug) - printk("Span ('%s') is new master\n", span->name); - } - return 0; -} - -int zt_unregister(struct zt_span *span) -{ - int x; - int new_maxspans; - static struct zt_span *new_master; - -#ifdef CONFIG_PROC_FS - char tempfile[17]; -#endif /* CONFIG_PROC_FS */ - - if (!(span->flags & ZT_FLAG_REGISTERED)) { - printk(KERN_ERR "Span %s does not appear to be registered\n", span->name); - return -1; - } - /* Shutdown the span if it's running */ - if (span->flags & ZT_FLAG_RUNNING) - if (span->shutdown) - span->shutdown(span); - - if (spans[span->spanno] != span) { - printk(KERN_ERR "Span %s has spanno %d which is something else\n", span->name, span->spanno); - return -1; - } - if (debug) - printk("Unregistering Span '%s' with %d channels\n", span->name, span->channels); -#ifdef CONFIG_PROC_FS - sprintf(tempfile, "zaptel/%d", span->spanno); - remove_proc_entry(tempfile, NULL); -#endif /* CONFIG_PROC_FS */ -#ifdef CONFIG_DEVFS_FS - for (x = 0; x < span->channels; x++) { - devfs_unregister(span->chans[x].fhandle); - devfs_unregister(span->chans[x].fhandle_symlink); - } - devfs_unregister(span->dhandle); -#endif /* CONFIG_DEVFS_FS */ - -#ifdef CONFIG_ZAP_UDEV - for (x = 0; x < span->channels; x++) { - if (span->chans[x].channo < 250) - class_device_destroy(zap_class, MKDEV(ZT_MAJOR, span->chans[x].channo)); - } -#endif /* CONFIG_ZAP_UDEV */ - - spans[span->spanno] = NULL; - span->spanno = 0; - span->flags &= ~ZT_FLAG_REGISTERED; - for (x=0;xchannels;x++) - zt_chan_unreg(&span->chans[x]); - new_maxspans = 0; - new_master = master; /* FIXME: locking */ - if (master == span) - new_master = NULL; - for (x=1;xname: "no master"); - master = new_master; - - return 0; -} - -/* -** This routine converts from linear to ulaw -** -** Craig Reese: IDA/Supercomputing Research Center -** Joe Campbell: Department of Defense -** 29 September 1989 -** -** References: -** 1) CCITT Recommendation G.711 (very difficult to follow) -** 2) "A New Digital Technique for Implementation of Any -** Continuous PCM Companding Law," Villeret, Michel, -** et al. 1973 IEEE Int. Conf. on Communications, Vol 1, -** 1973, pg. 11.12-11.17 -** 3) MIL-STD-188-113,"Interoperability and Performance Standards -** for Analog-to_Digital Conversion Techniques," -** 17 February 1987 -** -** Input: Signed 16 bit linear sample -** Output: 8 bit ulaw sample -*/ - -#define ZEROTRAP /* turn on the trap as per the MIL-STD */ -#define BIAS 0x84 /* define the add-in bias for 16 bit samples */ -#define CLIP 32635 - -#ifdef CONFIG_CALC_XLAW -unsigned char -#else -static unsigned char __init -#endif -__zt_lineartoulaw(short sample) -{ - static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7}; - int sign, exponent, mantissa; - unsigned char ulawbyte; - - /* Get the sample into sign-magnitude. */ - sign = (sample >> 8) & 0x80; /* set aside the sign */ - if (sign != 0) sample = -sample; /* get magnitude */ - if (sample > CLIP) sample = CLIP; /* clip the magnitude */ - - /* Convert from 16 bit linear to ulaw. */ - sample = sample + BIAS; - exponent = exp_lut[(sample >> 7) & 0xFF]; - mantissa = (sample >> (exponent + 3)) & 0x0F; - ulawbyte = ~(sign | (exponent << 4) | mantissa); -#ifdef ZEROTRAP - if (ulawbyte == 0) ulawbyte = 0x02; /* optional CCITT trap */ -#endif - if (ulawbyte == 0xff) ulawbyte = 0x7f; /* never return 0xff */ - return(ulawbyte); -} - -#define AMI_MASK 0x55 - -#ifdef CONFIG_CALC_XLAW -unsigned char -#else -static inline unsigned char __init -#endif -__zt_lineartoalaw (short linear) -{ - int mask; - int seg; - int pcm_val; - static int seg_end[8] = - { - 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF - }; - - pcm_val = linear; - if (pcm_val >= 0) - { - /* Sign (7th) bit = 1 */ - mask = AMI_MASK | 0x80; - } - else - { - /* Sign bit = 0 */ - mask = AMI_MASK; - pcm_val = -pcm_val; - } - - /* Convert the scaled magnitude to segment number. */ - for (seg = 0; seg < 8; seg++) - { - if (pcm_val <= seg_end[seg]) - break; - } - /* Combine the sign, segment, and quantization bits. */ - return ((seg << 4) | ((pcm_val >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask; -} -/*- End of function --------------------------------------------------------*/ - -static inline short int __init alaw2linear (uint8_t alaw) -{ - int i; - int seg; - - alaw ^= AMI_MASK; - i = ((alaw & 0x0F) << 4); - seg = (((int) alaw & 0x70) >> 4); - if (seg) - i = (i + 0x100) << (seg - 1); - return (short int) ((alaw & 0x80) ? i : -i); -} -/*- End of function --------------------------------------------------------*/ -static void __init zt_conv_init(void) -{ - int i; - - /* - * Set up mu-law conversion table - */ - for(i = 0;i < 256;i++) - { - short mu,e,f,y; - static short etab[]={0,132,396,924,1980,4092,8316,16764}; - - mu = 255-i; - e = (mu & 0x70)/16; - f = mu & 0x0f; - y = f * (1 << (e + 3)); - y += etab[e]; - if (mu & 0x80) y = -y; - __zt_mulaw[i] = y; - __zt_alaw[i] = alaw2linear(i); - /* Default (0.0 db) gain table */ - defgain[i] = i; - } -#ifndef CONFIG_CALC_XLAW - /* set up the reverse (mu-law) conversion table */ - for(i = -32768; i < 32768; i += 4) - { - __zt_lin2mu[((unsigned short)(short)i) >> 2] = __zt_lineartoulaw(i); - __zt_lin2a[((unsigned short)(short)i) >> 2] = __zt_lineartoalaw(i); - } -#endif -} - -static inline void __zt_process_getaudio_chunk(struct zt_chan *ss, unsigned char *txb) -{ - /* We transmit data from our master channel */ - /* Called with ss->lock held */ - struct zt_chan *ms = ss->master; - /* Linear representation */ - short getlin[ZT_CHUNKSIZE], k[ZT_CHUNKSIZE]; - int x; - - /* Okay, now we've got something to transmit */ - for (x=0;xec) { - for (x=0;xtxecdis, getlin[x])) { - printk("zaptel Disabled echo canceller because of tone (tx) on channel %d\n", ss->channo); - ms->echocancel = 0; - ms->echostate = ECHO_STATE_IDLE; - ms->echolastupdate = 0; - ms->echotimer = 0; - echo_can_free(ms->ec); - ms->ec = NULL; - __qevent(ss, ZT_EVENT_EC_DISABLED); - break; - } - } - } -#endif - if ((!ms->confmute && !ms->dialing) || (ms->flags & ZT_FLAG_PSEUDO)) { - /* Handle conferencing on non-clear channel and non-HDLC channels */ - switch(ms->confmode & ZT_CONF_MODE_MASK) { - case ZT_CONF_NORMAL: - /* Do nuffin */ - break; - case ZT_CONF_MONITOR: /* Monitor a channel's rx mode */ - /* if a pseudo-channel, ignore */ - if (ms->flags & ZT_FLAG_PSEUDO) break; - /* Add monitored channel */ - if (chans[ms->confna]->flags & ZT_FLAG_PSEUDO) { - ACSS(getlin, chans[ms->confna]->getlin); - } else { - ACSS(getlin, chans[ms->confna]->putlin); - } - for (x=0;xflags & ZT_FLAG_PSEUDO) break; - /* Add monitored channel */ - if (chans[ms->confna]->flags & ZT_FLAG_PSEUDO) { - ACSS(getlin, chans[ms->confna]->putlin); - } else { - ACSS(getlin, chans[ms->confna]->getlin); - } - - for (x=0;xflags & ZT_FLAG_PSEUDO) break; - ACSS(getlin, chans[ms->confna]->putlin); - ACSS(getlin, chans[ms->confna]->getlin); - for (x=0;xflags & ZT_FLAG_PSEUDO) - break; - - if (!chans[ms->confna]->readchunkpreec) - break; - - /* Add monitored channel */ - ACSS(getlin, chans[ms->confna]->flags & ZT_FLAG_PSEUDO ? - chans[ms->confna]->readchunkpreec : chans[ms->confna]->putlin); - for (x = 0; x < ZT_CHUNKSIZE; x++) - txb[x] = ZT_LIN2X(getlin[x], ms); - - break; - case ZT_CONF_MONITOR_TX_PREECHO: /* Monitor a channel's tx mode */ - /* if a pseudo-channel, ignore */ - if (ms->flags & ZT_FLAG_PSEUDO) - break; - - if (!chans[ms->confna]->readchunkpreec) - break; - - /* Add monitored channel */ - ACSS(getlin, chans[ms->confna]->flags & ZT_FLAG_PSEUDO ? - chans[ms->confna]->putlin : chans[ms->confna]->readchunkpreec); - for (x = 0; x < ZT_CHUNKSIZE; x++) - txb[x] = ZT_LIN2X(getlin[x], ms); - - break; - case ZT_CONF_MONITORBOTH_PREECHO: /* monitor a channel's rx and tx mode */ - /* if a pseudo-channel, ignore */ - if (ms->flags & ZT_FLAG_PSEUDO) - break; - - if (!chans[ms->confna]->readchunkpreec) - break; - - ACSS(getlin, chans[ms->confna]->putlin); - ACSS(getlin, chans[ms->confna]->readchunkpreec); - - for (x = 0; x < ZT_CHUNKSIZE; x++) - txb[x] = ZT_LIN2X(getlin[x], ms); - - break; - case ZT_CONF_REALANDPSEUDO: - /* This strange mode takes the transmit buffer and - puts it on the conference, minus its last sample, - then outputs from the conference minus the - real channel's last sample. */ - /* if to talk on conf */ - if (ms->confmode & ZT_CONF_PSEUDO_TALKER) { - /* Store temp value */ - memcpy(k, getlin, ZT_CHUNKSIZE * sizeof(short)); - /* Add conf value */ - ACSS(k, conf_sums_next[ms->_confn]); - /* save last one */ - memcpy(ms->conflast2, ms->conflast1, ZT_CHUNKSIZE * sizeof(short)); - memcpy(ms->conflast1, k, ZT_CHUNKSIZE * sizeof(short)); - /* get amount actually added */ - SCSS(ms->conflast1, conf_sums_next[ms->_confn]); - /* Really add in new value */ - ACSS(conf_sums_next[ms->_confn], ms->conflast1); - } else { - memset(ms->conflast1, 0, ZT_CHUNKSIZE * sizeof(short)); - memset(ms->conflast2, 0, ZT_CHUNKSIZE * sizeof(short)); - } - memset(getlin, 0, ZT_CHUNKSIZE * sizeof(short)); - txb[0] = ZT_LIN2X(0, ms); - memset(txb + 1, txb[0], ZT_CHUNKSIZE - 1); - /* fall through to normal conf mode */ - case ZT_CONF_CONF: /* Normal conference mode */ - if (ms->flags & ZT_FLAG_PSEUDO) /* if pseudo-channel */ - { - /* if to talk on conf */ - if (ms->confmode & ZT_CONF_TALKER) { - /* Store temp value */ - memcpy(k, getlin, ZT_CHUNKSIZE * sizeof(short)); - /* Add conf value */ - ACSS(k, conf_sums[ms->_confn]); - /* get amount actually added */ - memcpy(ms->conflast, k, ZT_CHUNKSIZE * sizeof(short)); - SCSS(ms->conflast, conf_sums[ms->_confn]); - /* Really add in new value */ - ACSS(conf_sums[ms->_confn], ms->conflast); - } else memset(ms->conflast, 0, ZT_CHUNKSIZE * sizeof(short)); - memcpy(getlin, ms->getlin, ZT_CHUNKSIZE * sizeof(short)); - txb[0] = ZT_LIN2X(0, ms); - memset(txb + 1, txb[0], ZT_CHUNKSIZE - 1); - break; - } - /* fall through */ - case ZT_CONF_CONFMON: /* Conference monitor mode */ - if (ms->confmode & ZT_CONF_LISTENER) { - /* Subtract out last sample written to conf */ - SCSS(getlin, ms->conflast); - /* Add in conference */ - ACSS(getlin, conf_sums[ms->_confn]); - } - for (x=0;x_confn], getlin); - /* Start with silence */ - memset(getlin, 0, ZT_CHUNKSIZE * sizeof(short)); - /* If a listener on the conf... */ - if (ms->confmode & ZT_CONF_LISTENER) { - /* Subtract last value written */ - SCSS(getlin, ms->conflast); - /* Add in conf */ - ACSS(getlin, conf_sums[ms->_confn]); - } - for (x=0;xconfna]) - break; - if (chans[ms->confna]->flags & ZT_FLAG_PSEUDO) { - if (ms->ec) { - for (x=0;xconfna]->getlin[x], ms); - } else { - memcpy(txb, chans[ms->confna]->getraw, ZT_CHUNKSIZE); - } - } else { - if (ms->ec) { - for (x=0;xconfna]->putlin[x], ms); - } else { - memcpy(txb, chans[ms->confna]->putraw, ZT_CHUNKSIZE); - } - } - for (x=0;xconfmute || (ms->echostate & __ECHO_STATE_MUTE)) { - txb[0] = ZT_LIN2X(0, ms); - memset(txb + 1, txb[0], ZT_CHUNKSIZE - 1); - if (ms->echostate == ECHO_STATE_STARTTRAINING) { - /* Transmit impulse now */ - txb[0] = ZT_LIN2X(16384, ms); - ms->echostate = ECHO_STATE_AWAITINGECHO; - } - } - /* save value from last chunk */ - memcpy(ms->getlin_lastchunk, ms->getlin, ZT_CHUNKSIZE * sizeof(short)); - /* save value from current */ - memcpy(ms->getlin, getlin, ZT_CHUNKSIZE * sizeof(short)); - /* save value from current */ - memcpy(ms->getraw, txb, ZT_CHUNKSIZE); - /* if to make tx tone */ - if (ms->v1_1 || ms->v2_1 || ms->v3_1) - { - for (x=0;xtxgain[txb[x]]; -} - -static inline void __zt_getbuf_chunk(struct zt_chan *ss, unsigned char *txb) -{ - /* Called with ss->lock held */ - /* We transmit data from our master channel */ - struct zt_chan *ms = ss->master; - /* Buffer we're using */ - unsigned char *buf; - /* Old buffer number */ - int oldbuf; - /* Linear representation */ - int getlin; - /* How many bytes we need to process */ - int bytes = ZT_CHUNKSIZE, left; - int x; - - /* Let's pick something to transmit. First source to - try is our write-out buffer. Always check it first because - its our 'fast path' for whatever that's worth. */ - while(bytes) { - if ((ms->outwritebuf > -1) && !ms->txdisable) { - buf= ms->writebuf[ms->outwritebuf]; - left = ms->writen[ms->outwritebuf] - ms->writeidx[ms->outwritebuf]; - if (left > bytes) - left = bytes; - if (ms->flags & ZT_FLAG_HDLC) { - /* If this is an HDLC channel we only send a byte of - HDLC. */ - for(x=0;xtxhdlc.bits < 8) - /* Load a byte of data only if needed */ - fasthdlc_tx_load_nocheck(&ms->txhdlc, buf[ms->writeidx[ms->outwritebuf]++]); - *(txb++) = fasthdlc_tx_run_nocheck(&ms->txhdlc); - } - bytes -= left; - } else { - memcpy(txb, buf + ms->writeidx[ms->outwritebuf], left); - ms->writeidx[ms->outwritebuf]+=left; - txb += left; - bytes -= left; - } - /* Check buffer status */ - if (ms->writeidx[ms->outwritebuf] >= ms->writen[ms->outwritebuf]) { - /* We've reached the end of our buffer. Go to the next. */ - oldbuf = ms->outwritebuf; - /* Clear out write index and such */ - ms->writeidx[oldbuf] = 0; - ms->writen[oldbuf] = 0; - ms->outwritebuf = (ms->outwritebuf + 1) % ms->numbufs; - if (ms->outwritebuf == ms->inwritebuf) { - /* Whoopsies, we're run out of buffers. Mark ours - as -1 and wait for the filler to notify us that - there is something to write */ - ms->outwritebuf = -1; - if (ms->iomask & (ZT_IOMUX_WRITE | ZT_IOMUX_WRITEEMPTY)) - wake_up_interruptible(&ms->eventbufq); - /* If we're only supposed to start when full, disable the transmitter */ - if (ms->txbufpolicy == ZT_POLICY_WHEN_FULL) - ms->txdisable = 1; - } - if (ms->inwritebuf < 0) { - /* The filler doesn't have a place to put data. Now - that we're done with this buffer, notify them. */ - ms->inwritebuf = oldbuf; - } -/* In the very orignal driver, it was quite well known to me (Jim) that there -was a possibility that a channel sleeping on a write block needed to -be potentially woken up EVERY time a buffer was emptied, not just on the first -one, because if only done on the first one there is a slight timing potential -of missing the wakeup (between where it senses the (lack of) active condition -(with interrupts disabled) and where it does the sleep (interrupts enabled) -in the read or iomux call, etc). That is why the write and iomux calls start -with an infinite loop that gets broken out of upon an active condition, -otherwise keeps sleeping and looking. The part in this code got "optimized" -out in the later versions, and is put back now. */ - if (!(ms->flags & (ZT_FLAG_NETDEV | ZT_FLAG_PPP))) { - wake_up_interruptible(&ms->writebufq); - wake_up_interruptible(&ms->sel); - if (ms->iomask & ZT_IOMUX_WRITE) - wake_up_interruptible(&ms->eventbufq); - } - /* Transmit a flag if this is an HDLC channel */ - if (ms->flags & ZT_FLAG_HDLC) - fasthdlc_tx_frame_nocheck(&ms->txhdlc); -#ifdef CONFIG_ZAPATA_NET - if (ms->flags & ZT_FLAG_NETDEV) - netif_wake_queue(ztchan_to_dev(ms)); -#endif -#ifdef CONFIG_ZAPATA_PPP - if (ms->flags & ZT_FLAG_PPP) { - ms->do_ppp_wakeup = 1; - tasklet_schedule(&ms->ppp_calls); - } -#endif - } - } else if (ms->curtone && !(ms->flags & ZT_FLAG_PSEUDO)) { - left = ms->curtone->tonesamples - ms->tonep; - if (left > bytes) - left = bytes; - for (x=0;xts, ms->curtone); - *(txb++) = ZT_LIN2X(getlin, ms); - } - ms->tonep+=left; - bytes -= left; - if (ms->tonep >= ms->curtone->tonesamples) { - struct zt_tone *last; - /* Go to the next sample of the tone */ - ms->tonep = 0; - last = ms->curtone; - ms->curtone = ms->curtone->next; - if (!ms->curtone) { - /* No more tones... Is this dtmf or mf? If so, go to the next digit */ - if (ms->dialing) - __do_dtmf(ms); - } else { - if (last != ms->curtone) - zt_init_tone_state(&ms->ts, ms->curtone); - } - } - } else if (ms->flags & ZT_FLAG_LOOPED) { - for (x = 0; x < bytes; x++) - txb[x] = ms->readchunk[x]; - bytes = 0; - } else if (ms->flags & ZT_FLAG_HDLC) { - for (x=0;xtxhdlc.bits < 8) - fasthdlc_tx_frame_nocheck(&ms->txhdlc); - *(txb++) = fasthdlc_tx_run_nocheck(&ms->txhdlc); - } - bytes = 0; - } else if (ms->flags & ZT_FLAG_CLEAR) { - /* Clear channels that are idle in audio mode need - to send silence; in non-audio mode, always send 0xff - so stupid switches won't consider the channel active - */ - if (ms->flags & ZT_FLAG_AUDIO) { - memset(txb, ZT_LIN2X(0, ms), bytes); - } else { - memset(txb, 0xFF, bytes); - } - bytes = 0; - } else { - memset(txb, ZT_LIN2X(0, ms), bytes); /* Lastly we use silence on telephony channels */ - bytes = 0; - } - } -} - -static inline void rbs_itimer_expire(struct zt_chan *chan) -{ - /* the only way this could have gotten here, is if a channel - went onf hook longer then the wink or flash detect timeout */ - /* Called with chan->lock held */ - switch(chan->sig) - { - case ZT_SIG_FXOLS: /* if FXO, its definitely on hook */ - case ZT_SIG_FXOGS: - case ZT_SIG_FXOKS: - __qevent(chan,ZT_EVENT_ONHOOK); - chan->gotgs = 0; - break; -#if defined(EMFLASH) || defined(EMPULSE) - case ZT_SIG_EM: - case ZT_SIG_EM_E1: - if (chan->rxhooksig == ZT_RXSIG_ONHOOK) { - __qevent(chan,ZT_EVENT_ONHOOK); - break; - } - __qevent(chan,ZT_EVENT_RINGOFFHOOK); - break; -#endif -#ifdef FXSFLASH - case ZT_SIG_FXSKS: - if (chan->rxhooksig == ZT_RXSIG_ONHOOK) { - __qevent(chan, ZT_EVENT_ONHOOK); - break; - } -#endif - /* fall thru intentionally */ - default: /* otherwise, its definitely off hook */ - __qevent(chan,ZT_EVENT_RINGOFFHOOK); - break; - } -} - -static inline void __rbs_otimer_expire(struct zt_chan *chan) -{ - int len = 0; - /* Called with chan->lock held */ - - chan->otimer = 0; - /* Move to the next timer state */ - switch(chan->txstate) { - case ZT_TXSTATE_RINGOFF: - /* Turn on the ringer now that the silent time has passed */ - ++chan->cadencepos; - if (chan->cadencepos >= ZT_MAX_CADENCE) - chan->cadencepos = chan->firstcadencepos; - len = chan->ringcadence[chan->cadencepos]; - - if (!len) { - chan->cadencepos = chan->firstcadencepos; - len = chan->ringcadence[chan->cadencepos]; - } - - zt_rbs_sethook(chan, ZT_TXSIG_START, ZT_TXSTATE_RINGON, len); - __qevent(chan, ZT_EVENT_RINGERON); - break; - - case ZT_TXSTATE_RINGON: - /* Turn off the ringer now that the loud time has passed */ - ++chan->cadencepos; - if (chan->cadencepos >= ZT_MAX_CADENCE) - chan->cadencepos = 0; - len = chan->ringcadence[chan->cadencepos]; - - if (!len) { - chan->cadencepos = 0; - len = chan->curzone->ringcadence[chan->cadencepos]; - } - - zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_RINGOFF, len); - __qevent(chan, ZT_EVENT_RINGEROFF); - break; - - case ZT_TXSTATE_START: - /* If we were starting, go off hook now ready to debounce */ - zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_AFTERSTART, ZT_AFTERSTART_TIME); - wake_up_interruptible(&chan->txstateq); - break; - - case ZT_TXSTATE_PREWINK: - /* Actually wink */ - zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_WINK, chan->winktime); - break; - - case ZT_TXSTATE_WINK: - /* Wink complete, go on hook and stabalize */ - zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_ONHOOK, 0); - if (chan->file && (chan->file->f_flags & O_NONBLOCK)) - __qevent(chan, ZT_EVENT_HOOKCOMPLETE); - wake_up_interruptible(&chan->txstateq); - break; - - case ZT_TXSTATE_PREFLASH: - /* Actually flash */ - zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_FLASH, chan->flashtime); - break; - - case ZT_TXSTATE_FLASH: - zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_OFFHOOK, 0); - if (chan->file && (chan->file->f_flags & O_NONBLOCK)) - __qevent(chan, ZT_EVENT_HOOKCOMPLETE); - wake_up_interruptible(&chan->txstateq); - break; - - case ZT_TXSTATE_DEBOUNCE: - zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_OFFHOOK, 0); - /* See if we've gone back on hook */ - if ((chan->rxhooksig == ZT_RXSIG_ONHOOK) && (chan->rxflashtime > 2)) - chan->itimerset = chan->itimer = chan->rxflashtime * ZT_CHUNKSIZE; - wake_up_interruptible(&chan->txstateq); - break; - - case ZT_TXSTATE_AFTERSTART: - zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_OFFHOOK, 0); - if (chan->file && (chan->file->f_flags & O_NONBLOCK)) - __qevent(chan, ZT_EVENT_HOOKCOMPLETE); - wake_up_interruptible(&chan->txstateq); - break; - - case ZT_TXSTATE_KEWL: - zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, ZT_TXSTATE_AFTERKEWL, ZT_AFTERKEWLTIME); - if (chan->file && (chan->file->f_flags & O_NONBLOCK)) - __qevent(chan, ZT_EVENT_HOOKCOMPLETE); - wake_up_interruptible(&chan->txstateq); - break; - - case ZT_TXSTATE_AFTERKEWL: - if (chan->kewlonhook) { - __qevent(chan,ZT_EVENT_ONHOOK); - } - chan->txstate = ZT_TXSTATE_ONHOOK; - chan->gotgs = 0; - break; - - case ZT_TXSTATE_PULSEBREAK: - zt_rbs_sethook(chan, ZT_TXSIG_OFFHOOK, ZT_TXSTATE_PULSEMAKE, - chan->pulsemaketime); - wake_up_interruptible(&chan->txstateq); - break; - - case ZT_TXSTATE_PULSEMAKE: - if (chan->pdialcount) - chan->pdialcount--; - if (chan->pdialcount) - { - zt_rbs_sethook(chan, ZT_TXSIG_ONHOOK, - ZT_TXSTATE_PULSEBREAK, chan->pulsebreaktime); - break; - } - chan->txstate = ZT_TXSTATE_PULSEAFTER; - chan->otimer = chan->pulseaftertime * ZT_CHUNKSIZE; - wake_up_interruptible(&chan->txstateq); - break; - - case ZT_TXSTATE_PULSEAFTER: - chan->txstate = ZT_TXSTATE_OFFHOOK; - __do_dtmf(chan); - wake_up_interruptible(&chan->txstateq); - break; - - default: - break; - } -} - -static void __zt_hooksig_pvt(struct zt_chan *chan, zt_rxsig_t rxsig) -{ - - /* State machines for receive hookstate transitions - called with chan->lock held */ - - if ((chan->rxhooksig) == rxsig) return; - - if ((chan->flags & ZT_FLAG_SIGFREEZE)) return; - - chan->rxhooksig = rxsig; -#ifdef RINGBEGIN - if ((chan->sig & __ZT_SIG_FXS) && (rxsig == ZT_RXSIG_RING) && - (!chan->ringdebtimer)) - __qevent(chan,ZT_EVENT_RINGBEGIN); -#endif - switch(chan->sig) { - case ZT_SIG_EM: /* E and M */ - case ZT_SIG_EM_E1: - switch(rxsig) { - case ZT_RXSIG_OFFHOOK: /* went off hook */ - /* The interface is going off hook */ -#ifdef EMFLASH - if (chan->itimer) - { - __qevent(chan,ZT_EVENT_WINKFLASH); - chan->itimerset = chan->itimer = 0; - break; - } -#endif -#ifdef EMPULSE - if (chan->itimer) /* if timer still running */ - { - int plen = chan->itimerset - chan->itimer; - if (plen <= ZT_MAXPULSETIME) - { - if (plen >= ZT_MINPULSETIME) - { - chan->pulsecount++; - - chan->pulsetimer = ZT_PULSETIMEOUT; - chan->itimerset = chan->itimer = 0; - if (chan->pulsecount == 1) - __qevent(chan,ZT_EVENT_PULSE_START); - } - } - break; - } -#endif - /* set wink timer */ - chan->itimerset = chan->itimer = chan->rxwinktime * ZT_CHUNKSIZE; - break; - case ZT_RXSIG_ONHOOK: /* went on hook */ - /* This interface is now going on hook. - Check for WINK, etc */ - if (chan->itimer) - __qevent(chan,ZT_EVENT_WINKFLASH); -#if defined(EMFLASH) || defined(EMPULSE) - else { -#ifdef EMFLASH - chan->itimerset = chan->itimer = chan->rxflashtime * ZT_CHUNKSIZE; - -#else /* EMFLASH */ - chan->itimerset = chan->itimer = chan->rxwinktime * ZT_CHUNKSIZE; - -#endif /* EMFLASH */ - chan->gotgs = 0; - break; - } -#else /* EMFLASH || EMPULSE */ - else { - __qevent(chan,ZT_EVENT_ONHOOK); - chan->gotgs = 0; - } -#endif - chan->itimerset = chan->itimer = 0; - break; - default: - break; - } - break; - case ZT_SIG_FXSKS: /* FXS Kewlstart */ - /* ignore a bit poopy if loop not closed and stable */ - if (chan->txstate != ZT_TXSTATE_OFFHOOK) break; -#ifdef FXSFLASH - if (rxsig == ZT_RXSIG_ONHOOK) { - chan->itimer = ZT_FXSFLASHMAXTIME * ZT_CHUNKSIZE; - break; - } else if (rxsig == ZT_RXSIG_OFFHOOK) { - if (chan->itimer) { - /* did the offhook occur in the window? if not, ignore both events */ - if (chan->itimer <= ((ZT_FXSFLASHMAXTIME - ZT_FXSFLASHMINTIME) * ZT_CHUNKSIZE)) - __qevent(chan, ZT_EVENT_WINKFLASH); - } - chan->itimer = 0; - break; - } -#endif - /* fall through intentionally */ - case ZT_SIG_FXSGS: /* FXS Groundstart */ - if (rxsig == ZT_RXSIG_ONHOOK) { - chan->ringdebtimer = RING_DEBOUNCE_TIME; - chan->ringtrailer = 0; - if (chan->txstate != ZT_TXSTATE_DEBOUNCE) { - chan->gotgs = 0; - __qevent(chan,ZT_EVENT_ONHOOK); - } - } - break; - case ZT_SIG_FXOGS: /* FXO Groundstart */ - if (rxsig == ZT_RXSIG_START) { - /* if havent got gs, report it */ - if (!chan->gotgs) { - __qevent(chan,ZT_EVENT_RINGOFFHOOK); - chan->gotgs = 1; - } - } - /* fall through intentionally */ - case ZT_SIG_FXOLS: /* FXO Loopstart */ - case ZT_SIG_FXOKS: /* FXO Kewlstart */ - switch(rxsig) { - case ZT_RXSIG_OFFHOOK: /* went off hook */ - /* if asserti ng ring, stop it */ - if (chan->txstate == ZT_TXSTATE_START) { - zt_rbs_sethook(chan,ZT_TXSIG_OFFHOOK, ZT_TXSTATE_AFTERSTART, ZT_AFTERSTART_TIME); - } - chan->kewlonhook = 0; -#ifdef CONFIG_ZAPATA_DEBUG - printk("Off hook on channel %d, itimer = %d, gotgs = %d\n", chan->channo, chan->itimer, chan->gotgs); -#endif - if (chan->itimer) /* if timer still running */ - { - int plen = chan->itimerset - chan->itimer; - if (plen <= ZT_MAXPULSETIME) - { - if (plen >= ZT_MINPULSETIME) - { - chan->pulsecount++; - chan->pulsetimer = ZT_PULSETIMEOUT; - chan->itimer = chan->itimerset; - if (chan->pulsecount == 1) - __qevent(chan,ZT_EVENT_PULSE_START); - } - } else - __qevent(chan,ZT_EVENT_WINKFLASH); - } else { - /* if havent got GS detect */ - if (!chan->gotgs) { - __qevent(chan,ZT_EVENT_RINGOFFHOOK); - chan->gotgs = 1; - chan->itimerset = chan->itimer = 0; - } - } - chan->itimerset = chan->itimer = 0; - break; - case ZT_RXSIG_ONHOOK: /* went on hook */ - /* if not during offhook debounce time */ - if ((chan->txstate != ZT_TXSTATE_DEBOUNCE) && - (chan->txstate != ZT_TXSTATE_KEWL) && - (chan->txstate != ZT_TXSTATE_AFTERKEWL)) { - chan->itimerset = chan->itimer = chan->rxflashtime * ZT_CHUNKSIZE; - } - if (chan->txstate == ZT_TXSTATE_KEWL) - chan->kewlonhook = 1; - break; - default: - break; - } - default: - break; - } -} - -void zt_hooksig(struct zt_chan *chan, zt_rxsig_t rxsig) -{ - /* skip if no change */ - unsigned long flags; - spin_lock_irqsave(&chan->lock, flags); - __zt_hooksig_pvt(chan,rxsig); - spin_unlock_irqrestore(&chan->lock, flags); -} - -void zt_rbsbits(struct zt_chan *chan, int cursig) -{ - unsigned long flags; - if (cursig == chan->rxsig) - return; - - if ((chan->flags & ZT_FLAG_SIGFREEZE)) return; - - spin_lock_irqsave(&chan->lock, flags); - switch(chan->sig) { - case ZT_SIG_FXOGS: /* FXO Groundstart */ - /* B-bit only matters for FXO GS */ - if (!(cursig & ZT_BBIT)) { - __zt_hooksig_pvt(chan, ZT_RXSIG_START); - break; - } - /* Fall through */ - case ZT_SIG_EM: /* E and M */ - case ZT_SIG_EM_E1: - case ZT_SIG_FXOLS: /* FXO Loopstart */ - case ZT_SIG_FXOKS: /* FXO Kewlstart */ - if (cursig & ZT_ABIT) /* off hook */ - __zt_hooksig_pvt(chan,ZT_RXSIG_OFFHOOK); - else /* on hook */ - __zt_hooksig_pvt(chan,ZT_RXSIG_ONHOOK); - break; - - case ZT_SIG_FXSKS: /* FXS Kewlstart */ - case ZT_SIG_FXSGS: /* FXS Groundstart */ - /* Fall through */ - case ZT_SIG_FXSLS: - if (!(cursig & ZT_BBIT)) { - /* Check for ringing first */ - __zt_hooksig_pvt(chan, ZT_RXSIG_RING); - break; - } - if ((chan->sig != ZT_SIG_FXSLS) && (cursig & ZT_ABIT)) { - /* if went on hook */ - __zt_hooksig_pvt(chan, ZT_RXSIG_ONHOOK); - } else { - __zt_hooksig_pvt(chan, ZT_RXSIG_OFFHOOK); - } - break; - case ZT_SIG_CAS: - /* send event that something changed */ - __qevent(chan, ZT_EVENT_BITSCHANGED); - break; - - default: - break; - } - /* Keep track of signalling for next time */ - chan->rxsig = cursig; - spin_unlock_irqrestore(&chan->lock, flags); -} - -static inline void __zt_ec_chunk(struct zt_chan *ss, unsigned char *rxchunk, const unsigned char *txchunk) -{ - short rxlin, txlin; - int x; - unsigned long flags; - - spin_lock_irqsave(&ss->lock, flags); - - if (ss->readchunkpreec) { - /* Save a copy of the audio before the echo can has its way with it */ - for (x = 0; x < ZT_CHUNKSIZE; x++) - /* We only ever really need to deal with signed linear - let's just convert it now */ - ss->readchunkpreec[x] = ZT_XLAW(rxchunk[x], ss); - } - - /* Perform echo cancellation on a chunk if necessary */ - if (ss->ec) { -#if defined(CONFIG_ZAPTEL_MMX) || defined(ECHO_CAN_FP) - zt_kernel_fpu_begin(); -#endif - if (ss->echostate & __ECHO_STATE_MUTE) { - /* Special stuff for training the echo can */ - for (x=0;xechostate == ECHO_STATE_PRETRAINING) { - if (--ss->echotimer <= 0) { - ss->echotimer = 0; - ss->echostate = ECHO_STATE_STARTTRAINING; - } - } - if ((ss->echostate == ECHO_STATE_AWAITINGECHO) && (txlin > 8000)) { - ss->echolastupdate = 0; - ss->echostate = ECHO_STATE_TRAINING; - } - if (ss->echostate == ECHO_STATE_TRAINING) { - if (echo_can_traintap(ss->ec, ss->echolastupdate++, rxlin)) { -#if 0 - printk("Finished training (%d taps trained)!\n", ss->echolastupdate); -#endif - ss->echostate = ECHO_STATE_ACTIVE; - } - } - rxlin = 0; - rxchunk[x] = ZT_LIN2X((int)rxlin, ss); - } - } else { -#if !defined(ZT_EC_ARRAY_UPDATE) - for (x=0;xec, ZT_XLAW(txchunk[x], ss), rxlin); - rxchunk[x] = ZT_LIN2X((int) rxlin, ss); - } -#else /* defined(ZT_EC_ARRAY_UPDATE) */ - short rxlins[ZT_CHUNKSIZE], txlins[ZT_CHUNKSIZE]; - for (x = 0; x < ZT_CHUNKSIZE; x++) { - rxlins[x] = ZT_XLAW(rxchunk[x], ss); - txlins[x] = ZT_XLAW(txchunk[x], ss); - } - echo_can_array_update(ss->ec, rxlins, txlins); - for (x = 0; x < ZT_CHUNKSIZE; x++) - rxchunk[x] = ZT_LIN2X((int) rxlins[x], ss); -#endif /* defined(ZT_EC_ARRAY_UPDATE) */ - } -#if defined(CONFIG_ZAPTEL_MMX) || defined(ECHO_CAN_FP) - kernel_fpu_end(); -#endif - } - spin_unlock_irqrestore(&ss->lock, flags); -} - -void zt_ec_chunk(struct zt_chan *ss, unsigned char *rxchunk, const unsigned char *txchunk) -{ - __zt_ec_chunk(ss, rxchunk, txchunk); -} - -void zt_ec_span(struct zt_span *span) -{ - int x; - for (x = 0; x < span->channels; x++) { - if (span->chans[x].ec) - __zt_ec_chunk(&span->chans[x], span->chans[x].readchunk, span->chans[x].writechunk); - } -} - -/* return 0 if nothing detected, 1 if lack of tone, 2 if presence of tone */ -/* modifies buffer pointed to by 'amp' with notched-out values */ -static inline int sf_detect (sf_detect_state_t *s, - short *amp, - int samples,long p1, long p2, long p3) -{ -int i,rv = 0; -long x,y; - -#define SF_DETECT_SAMPLES (ZT_CHUNKSIZE * 5) -#define SF_DETECT_MIN_ENERGY 500 -#define NB 14 /* number of bits to shift left */ - - /* determine energy level before filtering */ - for(i = 0; i < samples; i++) - { - if (amp[i] < 0) s->e1 -= amp[i]; - else s->e1 += amp[i]; - } - /* do 2nd order IIR notch filter at given freq. and calculate - energy */ - for(i = 0; i < samples; i++) - { - x = amp[i] << NB; - y = s->x2 + (p1 * (s->x1 >> NB)) + x; - y += (p2 * (s->y2 >> NB)) + - (p3 * (s->y1 >> NB)); - s->x2 = s->x1; - s->x1 = x; - s->y2 = s->y1; - s->y1 = y; - amp[i] = y >> NB; - if (amp[i] < 0) s->e2 -= amp[i]; - else s->e2 += amp[i]; - } - s->samps += i; - /* if time to do determination */ - if ((s->samps) >= SF_DETECT_SAMPLES) - { - rv = 1; /* default to no tone */ - /* if enough energy, it is determined to be a tone */ - if (((s->e1 - s->e2) / s->samps) > SF_DETECT_MIN_ENERGY) rv = 2; - /* reset energy processing variables */ - s->samps = 0; - s->e1 = s->e2 = 0; - } - return(rv); -} - -static inline void __zt_process_putaudio_chunk(struct zt_chan *ss, unsigned char *rxb) -{ - /* We transmit data from our master channel */ - /* Called with ss->lock held */ - struct zt_chan *ms = ss->master; - /* Linear version of received data */ - short putlin[ZT_CHUNKSIZE],k[ZT_CHUNKSIZE]; - int x,r; - - if (ms->dialing) ms->afterdialingtimer = 50; - else if (ms->afterdialingtimer) ms->afterdialingtimer--; - if (ms->afterdialingtimer && (!(ms->flags & ZT_FLAG_PSEUDO))) { - /* Be careful since memset is likely a macro */ - rxb[0] = ZT_LIN2X(0, ms); - memset(&rxb[1], rxb[0], ZT_CHUNKSIZE - 1); /* receive as silence if dialing */ - } - for (x=0;xrxgain[rxb[x]]; - putlin[x] = ZT_XLAW(rxb[x], ms); - } - -#ifndef NO_ECHOCAN_DISABLE - if (ms->ec) { - for (x=0;xrxecdis, putlin[x])) { - printk("zaptel Disabled echo canceller because of tone (rx) on channel %d\n", ss->channo); - ms->echocancel = 0; - ms->echostate = ECHO_STATE_IDLE; - ms->echolastupdate = 0; - ms->echotimer = 0; - echo_can_free(ms->ec); - ms->ec = NULL; - break; - } - } - } -#endif - /* if doing rx tone decoding */ - if (ms->rxp1 && ms->rxp2 && ms->rxp3) - { - r = sf_detect(&ms->rd,putlin,ZT_CHUNKSIZE,ms->rxp1, - ms->rxp2,ms->rxp3); - /* Convert back */ - for(x=0;xrd.lastdetect) - { - if (((r == 2) && !(ms->toneflags & ZT_REVERSE_RXTONE)) || - ((r == 1) && (ms->toneflags & ZT_REVERSE_RXTONE))) - { - __qevent(ms,ZT_EVENT_RINGOFFHOOK); - } - else - { - __qevent(ms,ZT_EVENT_ONHOOK); - } - ms->rd.lastdetect = r; - } - } - } - - if (!(ms->flags & ZT_FLAG_PSEUDO)) { - memcpy(ms->putlin, putlin, ZT_CHUNKSIZE * sizeof(short)); - memcpy(ms->putraw, rxb, ZT_CHUNKSIZE); - } - - /* Take the rxc, twiddle it for conferencing if appropriate and put it - back */ - if ((!ms->confmute && !ms->afterdialingtimer) || - (ms->flags & ZT_FLAG_PSEUDO)) { - switch(ms->confmode & ZT_CONF_MODE_MASK) { - case ZT_CONF_NORMAL: /* Normal mode */ - /* Do nothing. rx goes output */ - break; - case ZT_CONF_MONITOR: /* Monitor a channel's rx mode */ - /* if not a pseudo-channel, ignore */ - if (!(ms->flags & ZT_FLAG_PSEUDO)) break; - /* Add monitored channel */ - if (chans[ms->confna]->flags & ZT_FLAG_PSEUDO) { - ACSS(putlin, chans[ms->confna]->getlin); - } else { - ACSS(putlin, chans[ms->confna]->putlin); - } - /* Convert back */ - for(x=0;xflags & ZT_FLAG_PSEUDO)) break; - /* Add monitored channel */ - if (chans[ms->confna]->flags & ZT_FLAG_PSEUDO) { - ACSS(putlin, chans[ms->confna]->putlin); - } else { - ACSS(putlin, chans[ms->confna]->getlin); - } - /* Convert back */ - for(x=0;xflags & ZT_FLAG_PSEUDO)) break; - /* Note: Technically, saturation should be done at - the end of the whole addition, but for performance - reasons, we don't do that. Besides, it only matters - when you're so loud you're clipping anyway */ - ACSS(putlin, chans[ms->confna]->getlin); - ACSS(putlin, chans[ms->confna]->putlin); - /* Convert back */ - for(x=0;xflags & ZT_FLAG_PSEUDO)) - break; - - if (!chans[ms->confna]->readchunkpreec) - break; - - /* Add monitored channel */ - ACSS(putlin, chans[ms->confna]->flags & ZT_FLAG_PSEUDO ? - chans[ms->confna]->getlin : chans[ms->confna]->readchunkpreec); - for (x = 0; x < ZT_CHUNKSIZE; x++) - rxb[x] = ZT_LIN2X(putlin[x], ms); - - break; - case ZT_CONF_MONITOR_TX_PREECHO: /* Monitor a channel's tx mode */ - /* if not a pseudo-channel, ignore */ - if (!(ms->flags & ZT_FLAG_PSEUDO)) - break; - - if (!chans[ms->confna]->readchunkpreec) - break; - - /* Add monitored channel */ - ACSS(putlin, chans[ms->confna]->flags & ZT_FLAG_PSEUDO ? - chans[ms->confna]->readchunkpreec : chans[ms->confna]->getlin); - for (x = 0; x < ZT_CHUNKSIZE; x++) - rxb[x] = ZT_LIN2X(putlin[x], ms); - - break; - case ZT_CONF_MONITORBOTH_PREECHO: /* Monitor a channel's tx and rx mode */ - /* if not a pseudo-channel, ignore */ - if (!(ms->flags & ZT_FLAG_PSEUDO)) - break; - - if (!chans[ms->confna]->readchunkpreec) - break; - - /* Note: Technically, saturation should be done at - the end of the whole addition, but for performance - reasons, we don't do that. Besides, it only matters - when you're so loud you're clipping anyway */ - ACSS(putlin, chans[ms->confna]->getlin); - ACSS(putlin, chans[ms->confna]->readchunkpreec); - for (x = 0; x < ZT_CHUNKSIZE; x++) - rxb[x] = ZT_LIN2X(putlin[x], ms); - - break; - case ZT_CONF_REALANDPSEUDO: - /* do normal conf mode processing */ - if (ms->confmode & ZT_CONF_TALKER) { - /* Store temp value */ - memcpy(k, putlin, ZT_CHUNKSIZE * sizeof(short)); - /* Add conf value */ - ACSS(k, conf_sums_next[ms->_confn]); - /* get amount actually added */ - memcpy(ms->conflast, k, ZT_CHUNKSIZE * sizeof(short)); - SCSS(ms->conflast, conf_sums_next[ms->_confn]); - /* Really add in new value */ - ACSS(conf_sums_next[ms->_confn], ms->conflast); - } else memset(ms->conflast, 0, ZT_CHUNKSIZE * sizeof(short)); - /* do the pseudo-channel part processing */ - memset(putlin, 0, ZT_CHUNKSIZE * sizeof(short)); - if (ms->confmode & ZT_CONF_PSEUDO_LISTENER) { - /* Subtract out previous last sample written to conf */ - SCSS(putlin, ms->conflast2); - /* Add in conference */ - ACSS(putlin, conf_sums[ms->_confn]); - } - /* Convert back */ - for(x=0;xflags & ZT_FLAG_PSEUDO) /* if a pseudo-channel */ - { - if (ms->confmode & ZT_CONF_LISTENER) { - /* Subtract out last sample written to conf */ - SCSS(putlin, ms->conflast); - /* Add in conference */ - ACSS(putlin, conf_sums[ms->_confn]); - } - /* Convert back */ - for(x=0;xgetlin, putlin, ZT_CHUNKSIZE * sizeof(short)); - break; - } - /* fall through */ - case ZT_CONF_CONFANN: /* Conference with announce */ - if (ms->confmode & ZT_CONF_TALKER) { - /* Store temp value */ - memcpy(k, putlin, ZT_CHUNKSIZE * sizeof(short)); - /* Add conf value */ - ACSS(k, conf_sums_next[ms->_confn]); - /* get amount actually added */ - memcpy(ms->conflast, k, ZT_CHUNKSIZE * sizeof(short)); - SCSS(ms->conflast, conf_sums_next[ms->_confn]); - /* Really add in new value */ - ACSS(conf_sums_next[ms->_confn], ms->conflast); - } else - memset(ms->conflast, 0, ZT_CHUNKSIZE * sizeof(short)); - /* rxc unmodified */ - break; - case ZT_CONF_CONFMON: - case ZT_CONF_CONFANNMON: - if (ms->confmode & ZT_CONF_TALKER) { - /* Store temp value */ - memcpy(k, putlin, ZT_CHUNKSIZE * sizeof(short)); - /* Subtract last value */ - SCSS(conf_sums[ms->_confn], ms->conflast); - /* Add conf value */ - ACSS(k, conf_sums[ms->_confn]); - /* get amount actually added */ - memcpy(ms->conflast, k, ZT_CHUNKSIZE * sizeof(short)); - SCSS(ms->conflast, conf_sums[ms->_confn]); - /* Really add in new value */ - ACSS(conf_sums[ms->_confn], ms->conflast); - } else - memset(ms->conflast, 0, ZT_CHUNKSIZE * sizeof(short)); - for (x=0;x_confn][x], ms); - break; - case ZT_CONF_DIGITALMON: - /* if not a pseudo-channel, ignore */ - if (!(ms->flags & ZT_FLAG_PSEUDO)) break; - /* Add monitored channel */ - if (chans[ms->confna]->flags & ZT_FLAG_PSEUDO) { - memcpy(rxb, chans[ms->confna]->getraw, ZT_CHUNKSIZE); - } else { - memcpy(rxb, chans[ms->confna]->putraw, ZT_CHUNKSIZE); - } - break; - } - } -} - -/* HDLC (or other) receiver buffer functions for read side */ -static inline void __putbuf_chunk(struct zt_chan *ss, unsigned char *rxb, int bytes) -{ - /* We transmit data from our master channel */ - /* Called with ss->lock held */ - struct zt_chan *ms = ss->master; - /* Our receive buffer */ - unsigned char *buf; -#if defined(CONFIG_ZAPATA_NET) || defined(CONFIG_ZAPATA_PPP) - /* SKB for receiving network stuff */ - struct sk_buff *skb=NULL; -#endif - int oldbuf; - int eof=0; - int abort=0; - int res; - int left, x; - - while(bytes) { -#if defined(CONFIG_ZAPATA_NET) || defined(CONFIG_ZAPATA_PPP) - skb = NULL; -#endif - abort = 0; - eof = 0; - /* Next, figure out if we've got a buffer to receive into */ - if (ms->inreadbuf > -1) { - /* Read into the current buffer */ - buf = ms->readbuf[ms->inreadbuf]; - left = ms->blocksize - ms->readidx[ms->inreadbuf]; - if (left > bytes) - left = bytes; - if (ms->flags & ZT_FLAG_HDLC) { - for (x=0;xrxhdlc, *(rxb++)); - bytes--; - res = fasthdlc_rx_run(&ms->rxhdlc); - /* If there is nothing there, continue */ - if (res & RETURN_EMPTY_FLAG) - continue; - else if (res & RETURN_COMPLETE_FLAG) { - /* Only count this if it's a non-empty frame */ - if (ms->readidx[ms->inreadbuf]) { - if ((ms->flags & ZT_FLAG_FCS) && (ms->infcs != PPP_GOODFCS)) { - abort = ZT_EVENT_BADFCS; - } else - eof=1; - break; - } - continue; - } else if (res & RETURN_DISCARD_FLAG) { - /* This could be someone idling with - "idle" instead of "flag" */ - if (!ms->readidx[ms->inreadbuf]) - continue; - abort = ZT_EVENT_ABORT; - break; - } else { - unsigned char rxc; - rxc = res; - ms->infcs = PPP_FCS(ms->infcs, rxc); - buf[ms->readidx[ms->inreadbuf]++] = rxc; - /* Pay attention to the possibility of an overrun */ - if (ms->readidx[ms->inreadbuf] >= ms->blocksize) { - if (!ss->span->alarms) - printk(KERN_WARNING "HDLC Receiver overrun on channel %s (master=%s)\n", ss->name, ss->master->name); - abort=ZT_EVENT_OVERRUN; - /* Force the HDLC state back to frame-search mode */ - ms->rxhdlc.state = 0; - ms->rxhdlc.bits = 0; - ms->readidx[ms->inreadbuf]=0; - break; - } - } - } - } else { - /* Not HDLC */ - memcpy(buf + ms->readidx[ms->inreadbuf], rxb, left); - rxb += left; - ms->readidx[ms->inreadbuf] += left; - bytes -= left; - /* End of frame is decided by block size of 'N' */ - eof = (ms->readidx[ms->inreadbuf] >= ms->blocksize); - if (eof && (ss->flags & ZT_FLAG_NOSTDTXRX)) { - eof = 0; - abort = ZT_EVENT_OVERRUN; - } - } - if (eof) { - /* Finished with this buffer, try another. */ - oldbuf = ms->inreadbuf; - ms->infcs = PPP_INITFCS; - ms->readn[ms->inreadbuf] = ms->readidx[ms->inreadbuf]; -#ifdef CONFIG_ZAPATA_DEBUG - printk("EOF, len is %d\n", ms->readn[ms->inreadbuf]); -#endif -#if defined(CONFIG_ZAPATA_NET) || defined(CONFIG_ZAPATA_PPP) - if (ms->flags & (ZT_FLAG_NETDEV | ZT_FLAG_PPP)) { -#ifdef CONFIG_ZAPATA_NET -#endif /* CONFIG_ZAPATA_NET */ - /* Our network receiver logic is MUCH - different. We actually only use a single - buffer */ - if (ms->readn[ms->inreadbuf] > 1) { - /* Drop the FCS */ - ms->readn[ms->inreadbuf] -= 2; - /* Allocate an SKB */ -#ifdef CONFIG_ZAPATA_PPP - if (!ms->do_ppp_error) -#endif - skb = dev_alloc_skb(ms->readn[ms->inreadbuf]); - if (skb) { - /* XXX Get rid of this memcpy XXX */ - memcpy(skb->data, ms->readbuf[ms->inreadbuf], ms->readn[ms->inreadbuf]); - skb_put(skb, ms->readn[ms->inreadbuf]); -#ifdef CONFIG_ZAPATA_NET - if (ms->flags & ZT_FLAG_NETDEV) { -#ifdef LINUX26 - struct net_device_stats *stats = hdlc_stats(ms->hdlcnetdev->netdev); -#else /* LINUX26 */ - struct net_device_stats *stats = &ms->hdlcnetdev->netdev.stats; -#endif /* LINUX26 */ - stats->rx_packets++; - stats->rx_bytes += ms->readn[ms->inreadbuf]; - } -#endif - - } else { -#ifdef CONFIG_ZAPATA_NET - if (ms->flags & ZT_FLAG_NETDEV) { -#ifdef LINUX26 - struct net_device_stats *stats = hdlc_stats(ms->hdlcnetdev->netdev); -#else /* LINUX26 */ - struct net_device_stats *stats = &ms->hdlcnetdev->netdev.stats; -#endif /* LINUX26 */ - stats->rx_dropped++; - } -#endif -#ifdef CONFIG_ZAPATA_PPP - if (ms->flags & ZT_FLAG_PPP) { - abort = ZT_EVENT_OVERRUN; - } -#endif -#if 1 -#ifdef CONFIG_ZAPATA_PPP - if (!ms->do_ppp_error) -#endif - printk("Memory squeeze, dropped one\n"); -#endif - } - } - /* We don't cycle through buffers, just - reuse the same one */ - ms->readn[ms->inreadbuf] = 0; - ms->readidx[ms->inreadbuf] = 0; - } else -#endif - { - ms->inreadbuf = (ms->inreadbuf + 1) % ms->numbufs; - if (ms->inreadbuf == ms->outreadbuf) { - /* Whoops, we're full, and have no where else - to store into at the moment. We'll drop it - until there's a buffer available */ -#ifdef CONFIG_ZAPATA_DEBUG - printk("Out of storage space\n"); -#endif - ms->inreadbuf = -1; - /* Enable the receiver in case they've got POLICY_WHEN_FULL */ - ms->rxdisable = 0; - } - if (ms->outreadbuf < 0) { /* start out buffer if not already */ - ms->outreadbuf = oldbuf; - } -/* In the very orignal driver, it was quite well known to me (Jim) that there -was a possibility that a channel sleeping on a receive block needed to -be potentially woken up EVERY time a buffer was filled, not just on the first -one, because if only done on the first one there is a slight timing potential -of missing the wakeup (between where it senses the (lack of) active condition -(with interrupts disabled) and where it does the sleep (interrupts enabled) -in the read or iomux call, etc). That is why the read and iomux calls start -with an infinite loop that gets broken out of upon an active condition, -otherwise keeps sleeping and looking. The part in this code got "optimized" -out in the later versions, and is put back now. */ - if (!ms->rxdisable) { /* if receiver enabled */ - /* Notify a blocked reader that there is data available - to be read, unless we're waiting for it to be full */ -#ifdef CONFIG_ZAPATA_DEBUG - printk("Notifying reader data in block %d\n", oldbuf); -#endif - wake_up_interruptible(&ms->readbufq); - wake_up_interruptible(&ms->sel); - if (ms->iomask & ZT_IOMUX_READ) - wake_up_interruptible(&ms->eventbufq); - } - } - } - if (abort) { - /* Start over reading frame */ - ms->readidx[ms->inreadbuf] = 0; - ms->infcs = PPP_INITFCS; - -#ifdef CONFIG_ZAPATA_NET - if (ms->flags & ZT_FLAG_NETDEV) { -#ifdef LINUX26 - struct net_device_stats *stats = hdlc_stats(ms->hdlcnetdev->netdev); -#else /* LINUX26 */ - struct net_device_stats *stats = &ms->hdlcnetdev->netdev.stats; -#endif /* LINUX26 */ - stats->rx_errors++; - if (abort == ZT_EVENT_OVERRUN) - stats->rx_over_errors++; - if (abort == ZT_EVENT_BADFCS) - stats->rx_crc_errors++; - if (abort == ZT_EVENT_ABORT) - stats->rx_frame_errors++; - } else -#endif -#ifdef CONFIG_ZAPATA_PPP - if (ms->flags & ZT_FLAG_PPP) { - ms->do_ppp_error = 1; - tasklet_schedule(&ms->ppp_calls); - } else -#endif - - if ((ms->flags & ZT_FLAG_OPEN) && !ss->span->alarms) - /* Notify the receiver... */ - __qevent(ss->master, abort); -#if 0 - printk("torintr_receive: Aborted %d bytes of frame on %d\n", amt, ss->master); -#endif - - } - } else /* No place to receive -- drop on the floor */ - break; -#ifdef CONFIG_ZAPATA_NET - if (skb && (ms->flags & ZT_FLAG_NETDEV)) -#ifdef NEW_HDLC_INTERFACE - { -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22) - skb->mac.raw = skb->data; -#else - skb_reset_mac_header(skb); -#endif - skb->dev = ztchan_to_dev(ms); -#ifdef ZAP_HDLC_TYPE_TRANS - skb->protocol = hdlc_type_trans(skb, ztchan_to_dev(ms)); -#else - skb->protocol = htons (ETH_P_HDLC); -#endif - netif_rx(skb); - } -#else - hdlc_netif_rx(&ms->hdlcnetdev->netdev, skb); -#endif -#endif -#ifdef CONFIG_ZAPATA_PPP - if (skb && (ms->flags & ZT_FLAG_PPP)) { - unsigned char *tmp; - tmp = skb->data; - skb_pull(skb, 2); - /* Make sure that it's addressed to ALL STATIONS and UNNUMBERED */ - if (!tmp || (tmp[0] != 0xff) || (tmp[1] != 0x03)) { - /* Invalid SKB -- drop */ - if (tmp) - printk("Received invalid SKB (%02x, %02x)\n", tmp[0], tmp[1]); - dev_kfree_skb_irq(skb); - } else { - skb_queue_tail(&ms->ppp_rq, skb); - tasklet_schedule(&ms->ppp_calls); - } - } -#endif - } -} - -static inline void __zt_putbuf_chunk(struct zt_chan *ss, unsigned char *rxb) -{ - __putbuf_chunk(ss, rxb, ZT_CHUNKSIZE); -} - -static void __zt_hdlc_abort(struct zt_chan *ss, int event) -{ - if (ss->inreadbuf >= 0) - ss->readidx[ss->inreadbuf] = 0; - if ((ss->flags & ZT_FLAG_OPEN) && !ss->span->alarms) - __qevent(ss->master, event); -} - -extern void zt_hdlc_abort(struct zt_chan *ss, int event) -{ - unsigned long flags; - spin_lock_irqsave(&ss->lock, flags); - __zt_hdlc_abort(ss, event); - spin_unlock_irqrestore(&ss->lock, flags); -} - -extern void zt_hdlc_putbuf(struct zt_chan *ss, unsigned char *rxb, int bytes) -{ - unsigned long flags; - int res; - int left; - - spin_lock_irqsave(&ss->lock, flags); - if (ss->inreadbuf < 0) { -#ifdef CONFIG_ZAPATA_DEBUG - printk("No place to receive HDLC frame\n"); -#endif - spin_unlock_irqrestore(&ss->lock, flags); - return; - } - /* Read into the current buffer */ - left = ss->blocksize - ss->readidx[ss->inreadbuf]; - if (left > bytes) - left = bytes; - if (left > 0) { - memcpy(ss->readbuf[ss->inreadbuf] + ss->readidx[ss->inreadbuf], rxb, left); - rxb += left; - ss->readidx[ss->inreadbuf] += left; - bytes -= left; - } - /* Something isn't fit into buffer */ - if (bytes) { -#ifdef CONFIG_ZAPATA_DEBUG - printk("HDLC frame isn't fit into buffer space\n"); -#endif - __zt_hdlc_abort(ss, ZT_EVENT_OVERRUN); - } - res = left; - spin_unlock_irqrestore(&ss->lock, flags); -} - -extern void zt_hdlc_finish(struct zt_chan *ss) -{ - int oldreadbuf; - unsigned long flags; - - spin_lock_irqsave(&ss->lock, flags); - - if ((oldreadbuf = ss->inreadbuf) < 0) { -#ifdef CONFIG_ZAPATA_DEBUG - printk("No buffers to finish\n"); -#endif - spin_unlock_irqrestore(&ss->lock, flags); - return; - } - - if (!ss->readidx[ss->inreadbuf]) { -#ifdef CONFIG_ZAPATA_DEBUG - printk("Empty HDLC frame received\n"); -#endif - spin_unlock_irqrestore(&ss->lock, flags); - return; - } - - ss->readn[ss->inreadbuf] = ss->readidx[ss->inreadbuf]; - ss->inreadbuf = (ss->inreadbuf + 1) % ss->numbufs; - if (ss->inreadbuf == ss->outreadbuf) { - ss->inreadbuf = -1; -#ifdef CONFIG_ZAPATA_DEBUG - printk("Notifying reader data in block %d\n", oldreadbuf); -#endif - ss->rxdisable = 0; - } - if (ss->outreadbuf < 0) { - ss->outreadbuf = oldreadbuf; - } - - if (!ss->rxdisable) { - wake_up_interruptible(&ss->readbufq); - wake_up_interruptible(&ss->sel); - if (ss->iomask & ZT_IOMUX_READ) - wake_up_interruptible(&ss->eventbufq); - } - spin_unlock_irqrestore(&ss->lock, flags); -} - -/* Returns 1 if EOF, 0 if data is still in frame, -1 if EOF and no buffers left */ -extern int zt_hdlc_getbuf(struct zt_chan *ss, unsigned char *bufptr, unsigned int *size) -{ - unsigned char *buf; - unsigned long flags; - int left = 0; - int res; - int oldbuf; - - spin_lock_irqsave(&ss->lock, flags); - if (ss->outwritebuf > -1) { - buf = ss->writebuf[ss->outwritebuf]; - left = ss->writen[ss->outwritebuf] - ss->writeidx[ss->outwritebuf]; - /* Strip off the empty HDLC CRC end */ - left -= 2; - if (left <= *size) { - *size = left; - res = 1; - } else - res = 0; - - memcpy(bufptr, &buf[ss->writeidx[ss->outwritebuf]], *size); - ss->writeidx[ss->outwritebuf] += *size; - - if (res) { - /* Rotate buffers */ - oldbuf = ss->outwritebuf; - ss->writeidx[oldbuf] = 0; - ss->writen[oldbuf] = 0; - ss->outwritebuf = (ss->outwritebuf + 1) % ss->numbufs; - if (ss->outwritebuf == ss->inwritebuf) { - ss->outwritebuf = -1; - if (ss->iomask & (ZT_IOMUX_WRITE | ZT_IOMUX_WRITEEMPTY)) - wake_up_interruptible(&ss->eventbufq); - /* If we're only supposed to start when full, disable the transmitter */ - if (ss->txbufpolicy == ZT_POLICY_WHEN_FULL) - ss->txdisable = 1; - res = -1; - } - - if (ss->inwritebuf < 0) - ss->inwritebuf = oldbuf; - - if (!(ss->flags & (ZT_FLAG_NETDEV | ZT_FLAG_PPP))) { - wake_up_interruptible(&ss->writebufq); - wake_up_interruptible(&ss->sel); - if ((ss->iomask & ZT_IOMUX_WRITE) && (res >= 0)) - wake_up_interruptible(&ss->eventbufq); - } - } - } else { - res = -1; - *size = 0; - } - spin_unlock_irqrestore(&ss->lock, flags); - - return res; -} - - -static void process_timers(void) -{ - unsigned long flags; - struct zt_timer *cur; - spin_lock_irqsave(&zaptimerlock, flags); - cur = zaptimers; - while(cur) { - if (cur->ms) { - cur->pos -= ZT_CHUNKSIZE; - if (cur->pos <= 0) { - cur->tripped++; - cur->pos = cur->ms; - wake_up_interruptible(&cur->sel); - } - } - cur = cur->next; - } - spin_unlock_irqrestore(&zaptimerlock, flags); -} - -static unsigned int zt_timer_poll(struct file *file, struct poll_table_struct *wait_table) -{ - struct zt_timer *timer = file->private_data; - unsigned long flags; - int ret = 0; - if (timer) { - poll_wait(file, &timer->sel, wait_table); - spin_lock_irqsave(&zaptimerlock, flags); - if (timer->tripped || timer->ping) - ret |= POLLPRI; - spin_unlock_irqrestore(&zaptimerlock, flags); - } else - ret = -EINVAL; - return ret; -} - -/* device poll routine */ -static unsigned int -zt_chan_poll(struct file *file, struct poll_table_struct *wait_table, int unit) -{ - - struct zt_chan *chan = chans[unit]; - int ret; - unsigned long flags; - - /* do the poll wait */ - if (chan) { - poll_wait(file, &chan->sel, wait_table); - ret = 0; /* start with nothing to return */ - spin_lock_irqsave(&chan->lock, flags); - /* if at least 1 write buffer avail */ - if (chan->inwritebuf > -1) { - ret |= POLLOUT | POLLWRNORM; - } - if ((chan->outreadbuf > -1) && !chan->rxdisable) { - ret |= POLLIN | POLLRDNORM; - } - if (chan->eventoutidx != chan->eventinidx) - { - /* Indicate an exception */ - ret |= POLLPRI; - } - spin_unlock_irqrestore(&chan->lock, flags); - } else - ret = -EINVAL; - return(ret); /* return what we found */ -} - -static int zt_mmap(struct file *file, struct vm_area_struct *vm) -{ - int unit = UNIT(file); - if (unit == 250) - return zt_transcode_fops->mmap(file, vm); - return -ENOSYS; -} - -static unsigned int zt_poll(struct file *file, struct poll_table_struct *wait_table) -{ - int unit = UNIT(file); - struct zt_chan *chan; - - if (!unit) - return -EINVAL; - - if (unit == 250) - return zt_transcode_fops->poll(file, wait_table); - - if (unit == 253) - return zt_timer_poll(file, wait_table); - - if (unit == 254) { - chan = file->private_data; - if (!chan) - return -EINVAL; - return zt_chan_poll(file, wait_table,chan->channo); - } - if (unit == 255) { - chan = file->private_data; - if (!chan) { - printk("No pseudo channel structure to read?\n"); - return -EINVAL; - } - return zt_chan_poll(file, wait_table, chan->channo); - } - return zt_chan_poll(file, wait_table, unit); -} - -static void __zt_transmit_chunk(struct zt_chan *chan, unsigned char *buf) -{ - unsigned char silly[ZT_CHUNKSIZE]; - /* Called with chan->lock locked */ -#ifdef OPTIMIZE_CHANMUTE - if(likely(chan->chanmute)) - return; -#endif - if (!buf) - buf = silly; - __zt_getbuf_chunk(chan, buf); - - if ((chan->flags & ZT_FLAG_AUDIO) || (chan->confmode)) { -#ifdef CONFIG_ZAPTEL_MMX - zt_kernel_fpu_begin(); -#endif - __zt_process_getaudio_chunk(chan, buf); -#ifdef CONFIG_ZAPTEL_MMX - kernel_fpu_end(); -#endif - } -} - -static inline void __zt_real_transmit(struct zt_chan *chan) -{ - /* Called with chan->lock held */ -#ifdef OPTIMIZE_CHANMUTE - if(likely(chan->chanmute)) - return; -#endif - if (chan->confmode) { - /* Pull queued data off the conference */ - __buf_pull(&chan->confout, chan->writechunk, chan, "zt_real_transmit"); - } else { - __zt_transmit_chunk(chan, chan->writechunk); - } -} - -static void __zt_getempty(struct zt_chan *ms, unsigned char *buf) -{ - int bytes = ZT_CHUNKSIZE; - int left; - unsigned char *txb = buf; - int x; - short getlin; - /* Called with ms->lock held */ - - while(bytes) { - /* Receive silence, or tone */ - if (ms->curtone) { - left = ms->curtone->tonesamples - ms->tonep; - if (left > bytes) - left = bytes; - for (x=0;xts, ms->curtone); - *(txb++) = ZT_LIN2X(getlin, ms); - } - ms->tonep+=left; - bytes -= left; - if (ms->tonep >= ms->curtone->tonesamples) { - struct zt_tone *last; - /* Go to the next sample of the tone */ - ms->tonep = 0; - last = ms->curtone; - ms->curtone = ms->curtone->next; - if (!ms->curtone) { - /* No more tones... Is this dtmf or mf? If so, go to the next digit */ - if (ms->dialing) - __do_dtmf(ms); - } else { - if (last != ms->curtone) - zt_init_tone_state(&ms->ts, ms->curtone); - } - } - } else { - /* Use silence */ - memset(txb, ZT_LIN2X(0, ms), bytes); - bytes = 0; - } - } - -} - -static void __zt_receive_chunk(struct zt_chan *chan, unsigned char *buf) -{ - /* Receive chunk of audio -- called with chan->lock held */ - unsigned char waste[ZT_CHUNKSIZE]; - -#ifdef OPTIMIZE_CHANMUTE - if(likely(chan->chanmute)) - return; -#endif - if (!buf) { - memset(waste, ZT_LIN2X(0, chan), sizeof(waste)); - buf = waste; - } - if ((chan->flags & ZT_FLAG_AUDIO) || (chan->confmode)) { -#ifdef CONFIG_ZAPTEL_MMX - zt_kernel_fpu_begin(); -#endif - __zt_process_putaudio_chunk(chan, buf); -#ifdef CONFIG_ZAPTEL_MMX - kernel_fpu_end(); -#endif - } - __zt_putbuf_chunk(chan, buf); -} - -static inline void __zt_real_receive(struct zt_chan *chan) -{ - /* Called with chan->lock held */ -#ifdef OPTIMIZE_CHANMUTE - if(likely(chan->chanmute)) - return; -#endif - if (chan->confmode) { - /* Load into queue if we have space */ - __buf_push(&chan->confin, chan->readchunk, "zt_real_receive"); - } else { - __zt_receive_chunk(chan, chan->readchunk); - } -} - -int zt_transmit(struct zt_span *span) -{ - int x,y,z; - unsigned long flags; - -#if 1 - for (x=0;xchannels;x++) { - spin_lock_irqsave(&span->chans[x].lock, flags); - if (span->chans[x].flags & ZT_FLAG_NOSTDTXRX) { - spin_unlock_irqrestore(&span->chans[x].lock, flags); - continue; - } - if (&span->chans[x] == span->chans[x].master) { - if (span->chans[x].otimer) { - span->chans[x].otimer -= ZT_CHUNKSIZE; - if (span->chans[x].otimer <= 0) { - __rbs_otimer_expire(&span->chans[x]); - } - } - if (span->chans[x].flags & ZT_FLAG_AUDIO) { - __zt_real_transmit(&span->chans[x]); - } else { - if (span->chans[x].nextslave) { - u_char data[ZT_CHUNKSIZE]; - int pos=ZT_CHUNKSIZE; - /* Process master/slaves one way */ - for (y=0;ychans[x], data); - pos = 0; - } - span->chans[z].writechunk[y] = data[pos++]; - z = span->chans[z].nextslave; - } while(z); - } - } else { - /* Process independents elsewise */ - __zt_real_transmit(&span->chans[x]); - } - } - if (span->chans[x].sig == ZT_SIG_DACS_RBS) { - if (chans[span->chans[x].confna]) { - /* Just set bits for our destination */ - if (span->chans[x].txsig != chans[span->chans[x].confna]->rxsig) { - span->chans[x].txsig = chans[span->chans[x].confna]->rxsig; - span->rbsbits(&span->chans[x], chans[span->chans[x].confna]->rxsig); - } - } - } - - } - spin_unlock_irqrestore(&span->chans[x].lock, flags); - } - if (span->mainttimer) { - span->mainttimer -= ZT_CHUNKSIZE; - if (span->mainttimer <= 0) { - span->mainttimer = 0; - if (span->maint) - span->maint(span, ZT_MAINT_LOOPSTOP); - span->maintstat = 0; - wake_up_interruptible(&span->maintq); - } - } -#endif - return 0; -} - -int zt_receive(struct zt_span *span) -{ - int x,y,z; - unsigned long flags, flagso; - -#if 1 -#ifdef CONFIG_ZAPTEL_WATCHDOG - span->watchcounter--; -#endif - for (x=0;xchannels;x++) { - if (span->chans[x].master == &span->chans[x]) { - spin_lock_irqsave(&span->chans[x].lock, flags); - if (span->chans[x].nextslave) { - /* Must process each slave at the same time */ - u_char data[ZT_CHUNKSIZE]; - int pos = 0; - for (y=0;ychans[z].readchunk[y]; - if (pos == ZT_CHUNKSIZE) { - if(!(span->chans[x].flags & ZT_FLAG_NOSTDTXRX)) - __zt_receive_chunk(&span->chans[x], data); - pos = 0; - } - z=span->chans[z].nextslave; - } while(z); - } - } else { - /* Process a normal channel */ - if (!(span->chans[x].flags & ZT_FLAG_NOSTDTXRX)) - __zt_real_receive(&span->chans[x]); - } - if (span->chans[x].itimer) { - span->chans[x].itimer -= ZT_CHUNKSIZE; - if (span->chans[x].itimer <= 0) { - rbs_itimer_expire(&span->chans[x]); - } - } - if (span->chans[x].ringdebtimer) - span->chans[x].ringdebtimer--; - if (span->chans[x].sig & __ZT_SIG_FXS) { - if (span->chans[x].rxhooksig == ZT_RXSIG_RING) - span->chans[x].ringtrailer = ZT_RINGTRAILER; - else if (span->chans[x].ringtrailer) { - span->chans[x].ringtrailer-= ZT_CHUNKSIZE; - /* See if RING trailer is expired */ - if (!span->chans[x].ringtrailer && !span->chans[x].ringdebtimer) - __qevent(&span->chans[x],ZT_EVENT_RINGOFFHOOK); - } - } - if (span->chans[x].pulsetimer) - { - span->chans[x].pulsetimer--; - if (span->chans[x].pulsetimer <= 0) - { - if (span->chans[x].pulsecount) - { - if (span->chans[x].pulsecount > 12) { - - printk("Got pulse digit %d on %s???\n", - span->chans[x].pulsecount, - span->chans[x].name); - } else if (span->chans[x].pulsecount > 11) { - __qevent(&span->chans[x], ZT_EVENT_PULSEDIGIT | '#'); - } else if (span->chans[x].pulsecount > 10) { - __qevent(&span->chans[x], ZT_EVENT_PULSEDIGIT | '*'); - } else if (span->chans[x].pulsecount > 9) { - __qevent(&span->chans[x], ZT_EVENT_PULSEDIGIT | '0'); - } else { - __qevent(&span->chans[x], ZT_EVENT_PULSEDIGIT | ('0' + - span->chans[x].pulsecount)); - } - span->chans[x].pulsecount = 0; - } - } - } - spin_unlock_irqrestore(&span->chans[x].lock, flags); - } - } - - if (span == master) { - /* Hold the big zap lock for the duration of major - activities which touch all sorts of channels */ - spin_lock_irqsave(&bigzaplock, flagso); - /* Process any timers */ - process_timers(); - /* If we have dynamic stuff, call the ioctl with 0,0 parameters to - make it run */ - if (zt_dynamic_ioctl) - zt_dynamic_ioctl(0,0); - for (x=1;xconfmode && !(chans[x]->flags & ZT_FLAG_PSEUDO)) { - u_char *data; - spin_lock_irqsave(&chans[x]->lock, flags); - data = __buf_peek(&chans[x]->confin); - __zt_receive_chunk(chans[x], data); - if (data) - __buf_pull(&chans[x]->confin, NULL,chans[x], "confreceive"); - spin_unlock_irqrestore(&chans[x]->lock, flags); - } - } - /* This is the master channel, so make things switch over */ - rotate_sums(); - /* do all the pseudo and/or conferenced channel receives (getbuf's) */ - for (x=1;xflags & ZT_FLAG_PSEUDO)) { - spin_lock_irqsave(&chans[x]->lock, flags); - __zt_transmit_chunk(chans[x], NULL); - spin_unlock_irqrestore(&chans[x]->lock, flags); - } - } - if (maxlinks) { -#ifdef CONFIG_ZAPTEL_MMX - zt_kernel_fpu_begin(); -#endif - /* process all the conf links */ - for(x = 1; x <= maxlinks; x++) { - /* if we have a destination conf */ - if (((z = confalias[conf_links[x].dst]) > 0) && - ((y = confalias[conf_links[x].src]) > 0)) { - ACSS(conf_sums[z], conf_sums[y]); - } - } -#ifdef CONFIG_ZAPTEL_MMX - kernel_fpu_end(); -#endif - } - /* do all the pseudo/conferenced channel transmits (putbuf's) */ - for (x=1;xflags & ZT_FLAG_PSEUDO)) { - unsigned char tmp[ZT_CHUNKSIZE]; - spin_lock_irqsave(&chans[x]->lock, flags); - __zt_getempty(chans[x], tmp); - __zt_receive_chunk(chans[x], tmp); - spin_unlock_irqrestore(&chans[x]->lock, flags); - } - } - for (x=1;xconfmode && !(chans[x]->flags & ZT_FLAG_PSEUDO)) { - u_char *data; - spin_lock_irqsave(&chans[x]->lock, flags); - data = __buf_pushpeek(&chans[x]->confout); - __zt_transmit_chunk(chans[x], data); - if (data) - __buf_push(&chans[x]->confout, NULL, "conftransmit"); - spin_unlock_irqrestore(&chans[x]->lock, flags); - } - } -#ifdef ZAPTEL_SYNC_TICK - for (x=0;xsync_tick) - s->sync_tick(s, s == master); - } -#endif - spin_unlock_irqrestore(&bigzaplock, flagso); - } -#endif - return 0; -} - -MODULE_AUTHOR("Mark Spencer "); -MODULE_DESCRIPTION("Zapata Telephony Interface"); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif -#ifdef MODULE_VERSION -MODULE_VERSION(ZAPTEL_VERSION); -#endif - -#ifdef LINUX26 -module_param(debug, int, 0600); -module_param(deftaps, int, 0600); -#else -MODULE_PARM(debug, "i"); -MODULE_PARM(deftaps, "i"); -#endif - -static struct file_operations zt_fops = { - owner: THIS_MODULE, - llseek: NULL, - open: zt_open, - release: zt_release, - ioctl: zt_ioctl, - read: zt_read, - write: zt_write, - poll: zt_poll, - mmap: zt_mmap, - flush: NULL, - fsync: NULL, - fasync: NULL, -}; - -#ifdef CONFIG_ZAPTEL_WATCHDOG -static struct timer_list watchdogtimer; - -static void watchdog_check(unsigned long ignored) -{ - int x; - unsigned long flags; - static int wdcheck=0; - - local_irq_save(flags); - for (x=0;xflags & ZT_FLAG_RUNNING)) { - if (spans[x]->watchcounter == ZT_WATCHDOG_INIT) { - /* Whoops, dead card */ - if ((spans[x]->watchstate == ZT_WATCHSTATE_OK) || - (spans[x]->watchstate == ZT_WATCHSTATE_UNKNOWN)) { - spans[x]->watchstate = ZT_WATCHSTATE_RECOVERING; - if (spans[x]->watchdog) { - printk("Kicking span %s\n", spans[x]->name); - spans[x]->watchdog(spans[x], ZT_WATCHDOG_NOINTS); - } else { - printk("Span %s is dead with no revival\n", spans[x]->name); - spans[x]->watchstate = ZT_WATCHSTATE_FAILED; - } - } - } else { - if ((spans[x]->watchstate != ZT_WATCHSTATE_OK) && - (spans[x]->watchstate != ZT_WATCHSTATE_UNKNOWN)) - printk("Span %s is alive!\n", spans[x]->name); - spans[x]->watchstate = ZT_WATCHSTATE_OK; - } - spans[x]->watchcounter = ZT_WATCHDOG_INIT; - } - } - local_irq_restore(flags); - if (!wdcheck) { - printk("Zaptel watchdog on duty!\n"); - wdcheck=1; - } - mod_timer(&watchdogtimer, jiffies + 2); -} - -static int __init watchdog_init(void) -{ - init_timer(&watchdogtimer); - watchdogtimer.expires = 0; - watchdogtimer.data =0; - watchdogtimer.function = watchdog_check; - /* Run every couple of jiffy or so */ - mod_timer(&watchdogtimer, jiffies + 2); - return 0; -} - -static void __exit watchdog_cleanup(void) -{ - del_timer(&watchdogtimer); -} - -#endif - -int zt_register_chardev(struct zt_chardev *dev) -{ -#ifdef CONFIG_ZAP_UDEV - char udevname[strlen(dev->name) + 3]; - - strcpy(udevname, "zap"); - strcat(udevname, dev->name); - CLASS_DEV_CREATE(zap_class, MKDEV(ZT_MAJOR, dev->minor), NULL, udevname); -#endif /* CONFIG_ZAP_UDEV */ - -#ifdef CONFIG_DEVFS_FS - dev->devfs_handle = devfs_register(zaptel_devfs_dir, dev->name, DEVFS_FL_DEFAULT, ZT_MAJOR, dev->minor, ZT_DEVFS_MODE, &zt_fops, NULL); -#endif /* CONFIG_DEVFS_FS */ - - return 0; -} - -int zt_unregister_chardev(struct zt_chardev *dev) -{ -#ifdef CONFIG_ZAP_UDEV - class_device_destroy(zap_class, MKDEV(ZT_MAJOR, dev->minor)); -#endif /* CONFIG_ZAP_UDEV */ - -#ifdef CONFIG_DEVFS_FS - devfs_unregister(dev->devfs_handle); -#endif /* CONFIG_DEVFS_FS */ - - return 0; -} - -static int __init zt_init(void) { - int res = 0; - -#ifdef CONFIG_PROC_FS - proc_entries[0] = proc_mkdir("zaptel", NULL); -#endif - -#ifdef CONFIG_ZAP_UDEV /* udev support functions */ - zap_class = class_create(THIS_MODULE, "zaptel"); - CLASS_DEV_CREATE(zap_class, MKDEV(ZT_MAJOR, 253), NULL, "zaptimer"); - CLASS_DEV_CREATE(zap_class, MKDEV(ZT_MAJOR, 254), NULL, "zapchannel"); - CLASS_DEV_CREATE(zap_class, MKDEV(ZT_MAJOR, 255), NULL, "zappseudo"); - CLASS_DEV_CREATE(zap_class, MKDEV(ZT_MAJOR, 0), NULL, "zapctl"); -#endif /* CONFIG_ZAP_UDEV */ - -#ifdef CONFIG_DEVFS_FS - { - devfs_register_chrdev(ZT_MAJOR, "zaptel", &zt_fops); - if (!(zaptel_devfs_dir = devfs_mk_dir(NULL, "zap", NULL))) - return -EBUSY; /* This would be bad */ - timer = devfs_register(zaptel_devfs_dir, "timer", DEVFS_FL_DEFAULT, ZT_MAJOR, 253, ZT_DEVFS_MODE, &zt_fops, NULL); - channel = devfs_register(zaptel_devfs_dir, "channel", DEVFS_FL_DEFAULT, ZT_MAJOR, 254, ZT_DEVFS_MODE, &zt_fops, NULL); - pseudo = devfs_register(zaptel_devfs_dir, "pseudo", DEVFS_FL_DEFAULT, ZT_MAJOR, 255, ZT_DEVFS_MODE, &zt_fops, NULL); - ctl = devfs_register(zaptel_devfs_dir, "ctl", DEVFS_FL_DEFAULT, ZT_MAJOR, 0, ZT_DEVFS_MODE, &zt_fops, NULL); - } -#else - if ((res = register_chrdev(ZT_MAJOR, "zaptel", &zt_fops))) { - printk(KERN_ERR "Unable to register Zaptel character device handler on %d\n", ZT_MAJOR); - return res; - } -#endif /* CONFIG_DEVFS_FS */ - - printk(KERN_INFO "Zapata Telephony Interface Registered on major %d\n", ZT_MAJOR); - printk(KERN_INFO "Zaptel Version: %s\n", ZAPTEL_VERSION); - echo_can_init(); - zt_conv_init(); - fasthdlc_precalc(); - rotate_sums(); - rwlock_init(&chan_lock); -#ifdef CONFIG_ZAPTEL_WATCHDOG - watchdog_init(); -#endif - return res; -} - -static void __exit zt_cleanup(void) { - int x; - -#ifdef CONFIG_PROC_FS - remove_proc_entry("zaptel", NULL); -#endif - - printk(KERN_INFO "Zapata Telephony Interface Unloaded\n"); - for (x = 0; x < ZT_TONE_ZONE_MAX; x++) { - if (tone_zones[x]) - kfree(tone_zones[x]); - } - -#ifdef CONFIG_DEVFS_FS - devfs_unregister(timer); - devfs_unregister(channel); - devfs_unregister(pseudo); - devfs_unregister(ctl); - devfs_unregister(zaptel_devfs_dir); - devfs_unregister_chrdev(ZT_MAJOR, "zaptel"); -#else -#ifdef CONFIG_ZAP_UDEV - class_device_destroy(zap_class, MKDEV(ZT_MAJOR, 253)); /* timer */ - class_device_destroy(zap_class, MKDEV(ZT_MAJOR, 254)); /* channel */ - class_device_destroy(zap_class, MKDEV(ZT_MAJOR, 255)); /* pseudo */ - class_device_destroy(zap_class, MKDEV(ZT_MAJOR, 0)); /* ctl */ - class_destroy(zap_class); -#endif /* CONFIG_ZAP_UDEV */ - unregister_chrdev(ZT_MAJOR, "zaptel"); -#endif -#ifdef CONFIG_ZAPTEL_WATCHDOG - watchdog_cleanup(); -#endif - - echo_can_shutdown(); -} - -module_init(zt_init); -module_exit(zt_cleanup); diff --git a/zaptel.h b/zaptel.h deleted file mode 100644 index f1d9b0c..0000000 --- a/zaptel.h +++ /dev/null @@ -1,2009 +0,0 @@ -/* - * Zapata Telephony Interface - * - * Written by Mark Spencer - * Based on previous works, designs, and architectures conceived and - * written by Jim Dixon . - * - * Copyright (C) 2001 Jim Dixon / Zapata Telephony. - * Copyright (C) 2001 - 2006 Digium, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _LINUX_ZAPTEL_H -#define _LINUX_ZAPTEL_H - -#ifdef __KERNEL__ -#include "zconfig.h" -#include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) -#include -#endif -#include -#include - -#ifdef CONFIG_ZAPATA_NET -#include -#endif - -#ifdef CONFIG_ZAPATA_PPP -#include -#include -#include -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -#define LINUX26 -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) -#define zap_pci_module pci_register_driver -#else -#define zap_pci_module pci_module_init -#endif - -#ifdef LINUX26 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) -#define ZAP_IRQ_HANDLER(a) static irqreturn_t a(int irq, void *dev_id) -#else -#define ZAP_IRQ_HANDLER(a) static irqreturn_t a(int irq, void *dev_id, struct pt_regs *regs) -#endif -#else -#define ZAP_IRQ_HANDLER(a) static void a(int irq, void *dev_id, struct pt_regs *regs) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) -#define ZAP_IRQ_SHARED IRQF_SHARED -#define ZAP_IRQ_DISABLED IRQF_DISABLED -#define ZAP_IRQ_SHARED_DISABLED IRQF_SHARED | IRQF_DISABLED -#else -#define ZAP_IRQ_SHARED SA_SHIRQ -#define ZAP_IRQ_DISABLED SA_INTERRUPT -#define ZAP_IRQ_SHARED_DISABLED SA_SHIRQ | SA_INTERRUPT -#endif - -#include "ecdis.h" -#include "fasthdlc.h" - -#ifdef CONFIG_DEVFS_FS -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#include -#else -#undef CONFIG_DEVFS_FS -//#warning "Zaptel doesn't support DEVFS in post 2.4 kernels. Disabling DEVFS in zaptel" -#endif -#endif /* CONFIG_DEVFS_FS */ -#endif /* __KERNEL__ */ - -#include - -#ifndef ELAST -#define ELAST 500 -#endif - -/* Per-span configuration values */ -#define ZT_CONFIG_TXLEVEL 7 /* bits 0-2 are tx level */ - -/* Line configuration */ -/* These apply to T1 */ -#define ZT_CONFIG_D4 (1 << 4) -#define ZT_CONFIG_ESF (1 << 5) -#define ZT_CONFIG_AMI (1 << 6) -#define ZT_CONFIG_B8ZS (1 << 7) -/* These apply to E1 */ -#define ZT_CONFIG_CCS (1 << 8) /* CCS (ISDN) instead of CAS (Robbed Bit) */ -#define ZT_CONFIG_HDB3 (1 << 9) /* HDB3 instead of AMI (line coding) */ -#define ZT_CONFIG_CRC4 (1 << 10) /* CRC4 framing */ -#define ZT_CONFIG_NOTOPEN (1 << 16) - -/* Signalling types */ -#define ZT_SIG_BROKEN (1 << 31) /* The port is broken and/or failed initialization */ - -#define __ZT_SIG_FXO (1 << 12) /* Never use directly */ -#define __ZT_SIG_FXS (1 << 13) /* Never use directly */ - -#define ZT_SIG_NONE (0) /* Channel not configured */ -#define ZT_SIG_FXSLS ((1 << 0) | __ZT_SIG_FXS) /* FXS, Loopstart */ -#define ZT_SIG_FXSGS ((1 << 1) | __ZT_SIG_FXS) /* FXS, Groundstart */ -#define ZT_SIG_FXSKS ((1 << 2) | __ZT_SIG_FXS) /* FXS, Kewlstart */ - -#define ZT_SIG_FXOLS ((1 << 3) | __ZT_SIG_FXO) /* FXO, Loopstart */ -#define ZT_SIG_FXOGS ((1 << 4) | __ZT_SIG_FXO) /* FXO, Groupstart */ -#define ZT_SIG_FXOKS ((1 << 5) | __ZT_SIG_FXO) /* FXO, Kewlstart */ - -#define ZT_SIG_EM (1 << 6) /* Ear & Mouth (E&M) */ - -/* The following are all variations on clear channel */ - -#define __ZT_SIG_DACS (1 << 16) - -#define ZT_SIG_CLEAR (1 << 7) /* Clear channel */ -#define ZT_SIG_HDLCRAW ((1 << 8) | ZT_SIG_CLEAR) /* Raw unchecked HDLC */ -#define ZT_SIG_HDLCFCS ((1 << 9) | ZT_SIG_HDLCRAW) /* HDLC with FCS calculation */ -#define ZT_SIG_HDLCNET ((1 << 10) | ZT_SIG_HDLCFCS) /* HDLC Network */ -#define ZT_SIG_SLAVE (1 << 11) /* Slave to another channel */ -#define ZT_SIG_SF (1 << 14) /* Single Freq. tone only, no sig bits */ -#define ZT_SIG_CAS (1 << 15) /* Just get bits */ -#define ZT_SIG_DACS (__ZT_SIG_DACS | ZT_SIG_CLEAR) /* Cross connect */ -#define ZT_SIG_EM_E1 (1 << 17) /* E1 E&M Variation */ -#define ZT_SIG_DACS_RBS ((1 << 18) | __ZT_SIG_DACS) /* Cross connect w/ RBS */ -#define ZT_SIG_HARDHDLC ((1 << 19) | ZT_SIG_CLEAR) - -/* tone flag values */ -#define ZT_REVERSE_RXTONE 1 /* reverse polarity rx tone logic */ -#define ZT_REVERSE_TXTONE 2 /* reverse polarity tx tone logic */ - -#define ZT_ABIT 8 -#define ZT_BBIT 4 -#define ZT_CBIT 2 -#define ZT_DBIT 1 - -#define ZT_MAJOR 196 - -#define ZT_CODE 'J' - -/* Default chunk size for conferences and such -- static right now, might make - variable sometime. 8 samples = 1 ms = most frequent service interval possible - for a USB device */ -#define ZT_CHUNKSIZE 8 -#define ZT_MIN_CHUNKSIZE ZT_CHUNKSIZE -#define ZT_DEFAULT_CHUNKSIZE ZT_CHUNKSIZE -#define ZT_MAX_CHUNKSIZE ZT_CHUNKSIZE -#define ZT_CB_SIZE 2 - -#define ZT_MAX_BLOCKSIZE 8192 -#define ZT_DEFAULT_NUM_BUFS 2 -#define ZT_MAX_NUM_BUFS 32 -#define ZT_MAX_BUF_SPACE 32768 - -#define ZT_DEFAULT_BLOCKSIZE 1024 -#define ZT_DEFAULT_MTR_MRU 2048 - -#define ZT_POLICY_IMMEDIATE 0 /* Start play/record immediately */ -#define ZT_POLICY_WHEN_FULL 1 /* Start play/record when buffer is full */ - -#define RING_DEBOUNCE_TIME 2000 /* 2000 ms ring debounce time */ - -#define ZT_GET_PARAMS_RETURN_MASTER 0x40000000 - -/* Extended attributes in lineconfig structure */ -#define ZT_SPANINFO_HAS_LINECONFIG -#define ZT_SPANINFO_HAS_LBONAME - -struct zt_params_v1 -{ - int channo; /* Channel number */ - int spanno; /* Span itself */ - int chanpos; /* Channel number in span */ - int sigtype; /* read-only */ - int sigcap; /* read-only */ - int rxisoffhook; /* read-only */ - int rxbits; /* read-only */ - int txbits; /* read-only */ - int txhooksig; /* read-only */ - int rxhooksig; /* read-only */ - int curlaw; /* read-only -- one of ZT_LAW_MULAW or ZT_LAW_ALAW */ - int idlebits; /* read-only -- What is considered the idle state */ - char name[40]; /* Name of channel */ - int prewinktime; - int preflashtime; - int winktime; - int flashtime; - int starttime; - int rxwinktime; - int rxflashtime; - int debouncetime; - int pulsebreaktime; - int pulsemaketime; - int pulseaftertime; -}; - -typedef struct zt_params -{ - int channo; /* Channel number */ - int spanno; /* Span itself */ - int chanpos; /* Channel number in span */ - int sigtype; /* read-only */ - int sigcap; /* read-only */ - int rxisoffhook; /* read-only */ - int rxbits; /* read-only */ - int txbits; /* read-only */ - int txhooksig; /* read-only */ - int rxhooksig; /* read-only */ - int curlaw; /* read-only -- one of ZT_LAW_MULAW or ZT_LAW_ALAW */ - int idlebits; /* read-only -- What is considered the idle state */ - char name[40]; /* Name of channel */ - int prewinktime; - int preflashtime; - int winktime; - int flashtime; - int starttime; - int rxwinktime; - int rxflashtime; - int debouncetime; - int pulsebreaktime; - int pulsemaketime; - int pulseaftertime; - __u32 chan_alarms; /* alarms on this channel */ -} ZT_PARAMS; - -struct zt_spaninfo_v1 { - int spanno; /* span number */ - char name[20]; /* Name */ - char desc[40]; /* Description */ - int alarms; /* alarms status */ - int txlevel; /* what TX level is set to */ - int rxlevel; /* current RX level */ - int bpvcount; /* current BPV count */ - int crc4count; /* current CRC4 error count */ - int ebitcount; /* current E-bit error count */ - int fascount; /* current FAS error count */ - int irqmisses; /* current IRQ misses */ - int syncsrc; /* span # of current sync source, or 0 for free run */ - int numchans; /* number of configured channels on this span */ - int totalchans; /* total number of channels on the span */ - int totaflspans; /* total number of spans in entire system */ -}; - -struct zt_spaninfo_v2 { - int spanno; /* span number */ - char name[20]; /* Name */ - char desc[40]; /* Description */ - int alarms; /* alarms status */ - int txlevel; /* what TX level is set to */ - int rxlevel; /* current RX level */ - int bpvcount; /* current BPV count */ - int crc4count; /* current CRC4 error count */ - int ebitcount; /* current E-bit error count */ - int fascount; /* current FAS error count */ - int irqmisses; /* current IRQ misses */ - int syncsrc; /* span # of current sync source, or 0 for free run */ - int numchans; /* number of configured channels on this span */ - int totalchans; /* total number of channels on the span */ - int totalspans; /* total number of spans in entire system */ - int lbo; /* line build out */ - int lineconfig; /* framing/coding */ -}; - -typedef struct zt_spaninfo { - int spanno; /* span number */ - char name[20]; /* Name */ - char desc[40]; /* Description */ - int alarms; /* alarms status */ - int txlevel; /* what TX level is set to */ - int rxlevel; /* current RX level */ - int bpvcount; /* current BPV count */ - int crc4count; /* current CRC4 error count */ - int ebitcount; /* current E-bit error count */ - int fascount; /* current FAS error count */ - int irqmisses; /* current IRQ misses */ - int syncsrc; /* span # of current sync source, or 0 for free run */ - int numchans; /* number of configured channels on this span */ - int totalchans; /* total number of channels on the span */ - int totalspans; /* total number of spans in entire system */ - int lbo; /* line build out */ - int lineconfig; /* framing/coding */ - char lboname[40]; /* line build out in text form */ - char location[40]; /* span's device location in system */ - char manufacturer[40]; /* manufacturer of span's device */ - char devicetype[40]; /* span's device type */ - int irq; /* span's device IRQ */ - int linecompat; /* signaling modes possible on this span */ - char spantype[6]; /* type of span in text form */ -} ZT_SPANINFO; - -typedef struct zt_maintinfo -{ -int spanno; /* span number 1-2 */ -int command; /* command */ -} ZT_MAINTINFO; - -typedef struct zt_confinfo -{ -int chan; /* channel number, 0 for current */ -int confno; /* conference number */ -int confmode; /* conferencing mode */ -} ZT_CONFINFO; - -typedef struct zt_gains -{ -int chan; /* channel number, 0 for current */ -unsigned char rxgain[256]; /* Receive gain table */ -unsigned char txgain[256]; /* Transmit gain table */ -} ZT_GAINS; - -typedef struct zt_lineconfig -{ -int span; /* Which span number (0 to use name) */ -char name[20]; /* Name of span to use */ -int lbo; /* line build-outs */ -int lineconfig; /* line config parameters (framing, coding) */ -int sync; /* what level of sync source we are */ -} ZT_LINECONFIG; - -typedef struct zt_chanconfig -{ -int chan; /* Channel we're applying this to (0 to use name) */ -char name[40]; /* Name of channel to use */ -int sigtype; /* Signal type */ -int deflaw; /* Default law (ZT_LAW_DEFAULT, ZT_LAW_MULAW, or ZT_LAW_ALAW */ -int master; /* Master channel if sigtype is ZT_SLAVE */ -int idlebits; /* Idle bits (if this is a CAS channel) or - channel to monitor (if this is DACS channel) */ -char netdev_name[16]; /*name for the hdlc network device*/ -} ZT_CHANCONFIG; - -typedef struct zt_sfconfig -{ -int chan; /* Channel we're applying this to (0 to use name) */ -char name[40]; /* Name of channel to use */ -long rxp1; /* receive tone det. p1 */ -long rxp2; /* receive tone det. p2 */ -long rxp3; /* receive tone det. p3 */ -int txtone; /* Tx tone factor */ -int tx_v2; /* initial v2 value */ -int tx_v3; /* initial v3 value */ -int toneflag; /* Tone flags */ -} ZT_SFCONFIG; - -typedef struct zt_bufferinfo -{ -int txbufpolicy; /* Policy for handling receive buffers */ -int rxbufpolicy; /* Policy for handling receive buffers */ -int numbufs; /* How many buffers to use */ -int bufsize; /* How big each buffer is */ -int readbufs; /* How many read buffers are full (read-only) */ -int writebufs; /* How many write buffers are full (read-only) */ -} ZT_BUFFERINFO; - -typedef struct zt_dialparams -{ -int mfv1_tonelen; /* MF tone length (KP = this * 5/3) */ -int dtmf_tonelen; /* DTMF tone length */ -int reserved[4]; /* Reserved for future expansion -- always set to 0 */ -} ZT_DIAL_PARAMS; - - -typedef struct zt_dynamic_span { - char driver[20]; /* Which low-level driver to use */ - char addr[40]; /* Destination address */ - int numchans; /* Number of channels */ - int timing; /* Timing source preference */ - int spanno; /* Span number (filled in by zaptel) */ -} ZT_DYNAMIC_SPAN; - -/* Define the max # of outgoing DTMF or MFv1 digits to queue in-kernel */ -#define ZT_MAX_DTMF_BUF 256 - -#define ZT_DIAL_OP_APPEND 1 -#define ZT_DIAL_OP_REPLACE 2 -#define ZT_DIAL_OP_CANCEL 3 - -#define ZT_LAW_DEFAULT 0 /* Default law for span */ -#define ZT_LAW_MULAW 1 /* Mu-law */ -#define ZT_LAW_ALAW 2 /* A-law */ - -typedef struct zt_dialoperation -{ -int op; -char dialstr[ZT_MAX_DTMF_BUF]; -} ZT_DIAL_OPERATION; - - -typedef struct zt_indirect_data -{ -int chan; -int op; -void *data; -} ZT_INDIRECT_DATA; - -struct zt_versioninfo { - char version[80]; - char echo_canceller[80]; -}; - -struct zt_hwgain{ - __s32 newgain; /* desired gain in dB but x10. -3.5dB would be -35 */ - __u32 tx:1; /* 0=rx; 1=tx */ -}; - - -/* ioctl definitions */ -#define ZT_CODE 'J' - -/* - * Get Transfer Block Size. - */ -#define ZT_GET_BLOCKSIZE _IOR (ZT_CODE, 1, int) - -/* - * Set Transfer Block Size. - */ -#define ZT_SET_BLOCKSIZE _IOW (ZT_CODE, 2, int) - -/* - * Flush Buffer(s) and stop I/O - */ -#define ZT_FLUSH _IOW (ZT_CODE, 3, int) - -/* - * Wait for Write to Finish - */ -#define ZT_SYNC _IOW (ZT_CODE, 4, int) - -/* - * Get channel parameters - */ -#define ZT_GET_PARAMS_V1 _IOR (ZT_CODE, 5, struct zt_params_v1) -#define ZT_GET_PARAMS _IOR (ZT_CODE, 5, struct zt_params) - -/* - * Get channel parameters - */ -#define ZT_SET_PARAMS_V1 _IOW (ZT_CODE, 6, struct zt_params_v1) -#define ZT_SET_PARAMS _IOW (ZT_CODE, 6, struct zt_params) - -/* - * Set Hookswitch Status - */ -#define ZT_HOOK _IOW (ZT_CODE, 7, int) - -/* - * Get Signalling Event - */ -#define ZT_GETEVENT _IOR (ZT_CODE, 8, int) - -/* - * Wait for something to happen (IO Mux) - */ -#define ZT_IOMUX _IOWR (ZT_CODE, 9, int) - -/* - * Get Span Status - */ -#define ZT_SPANSTAT_V1 _IOWR (ZT_CODE, 10, struct zt_spaninfo_v1) -#define ZT_SPANSTAT_V2 _IOWR (ZT_CODE, 10, struct zt_spaninfo_v2) -#define ZT_SPANSTAT _IOWR (ZT_CODE, 10, struct zt_spaninfo) - -/* - * Set Maintenance Mode - */ -#define ZT_MAINT _IOW (ZT_CODE, 11, struct zt_maintinfo) - -/* - * Get Conference Mode - */ -#define ZT_GETCONF _IOWR (ZT_CODE, 12, struct zt_confinfo) - -/* - * Set Conference Mode - */ -#define ZT_SETCONF _IOWR (ZT_CODE, 13, struct zt_confinfo) - -/* - * Setup or Remove Conference Link - */ -#define ZT_CONFLINK _IOW (ZT_CODE, 14, struct zt_confinfo) - -/* - * Display Conference Diagnostic Information on Console - */ -#define ZT_CONFDIAG _IOR (ZT_CODE, 15, int) - -/* - * Get Channel audio gains - */ -#define ZT_GETGAINS _IOWR (ZT_CODE, 16, struct zt_gains) - -/* - * Set Channel audio gains - */ -#define ZT_SETGAINS _IOWR (ZT_CODE, 17, struct zt_gains) - -/* - * Set Line (T1) Configurations and start system - */ -#define ZT_SPANCONFIG _IOW (ZT_CODE, 18, struct zt_lineconfig) - -/* - * Set Channel Configuration - */ -#define ZT_CHANCONFIG _IOW (ZT_CODE, 19, struct zt_chanconfig) - -/* - * Set Conference to mute mode - */ -#define ZT_CONFMUTE _IOW (ZT_CODE, 20, int) - -/* - * Send a particular tone (see ZT_TONE_*) - */ -#define ZT_SENDTONE _IOW (ZT_CODE, 21, int) - -/* - * Set your region for tones (see ZT_TONE_ZONE_*) - */ -#define ZT_SETTONEZONE _IOW (ZT_CODE, 22, int) - -/* - * Retrieve current region for tones (see ZT_TONE_ZONE_*) - */ -#define ZT_GETTONEZONE _IOR (ZT_CODE, 23, int) - -/* - * Master unit only -- set default zone (see ZT_TONE_ZONE_*) - */ -#define ZT_DEFAULTZONE _IOW (ZT_CODE, 24, int) - -/* - * Load a tone zone from a zt_tone_def_header, see - * below... - */ -#define ZT_LOADZONE _IOW (ZT_CODE, 25, struct zt_tone_def_header) - -/* - * Free a tone zone - */ -#define ZT_FREEZONE _IOW (ZT_CODE, 26, int) - -/* - * Set buffer policy - */ -#define ZT_SET_BUFINFO _IOW (ZT_CODE, 27, struct zt_bufferinfo) - -/* - * Get current buffer info - */ -#define ZT_GET_BUFINFO _IOR (ZT_CODE, 28, struct zt_bufferinfo) - -/* - * Get dialing parameters - */ -#define ZT_GET_DIALPARAMS _IOR (ZT_CODE, 29, struct zt_dialparams) - -/* - * Set dialing parameters - */ -#define ZT_SET_DIALPARAMS _IOW (ZT_CODE, 30, struct zt_dialparams) - -/* - * Append, replace, or cancel a dial string - */ -#define ZT_DIAL _IOW (ZT_CODE, 31, struct zt_dialoperation) - -/* - * Set a clear channel into audio mode - */ -#define ZT_AUDIOMODE _IOW (ZT_CODE, 32, int) - -/* - * Enable or disable echo cancellation on a channel - * - * For ECHOCANCEL: - * The number is zero to disable echo cancellation and non-zero - * to enable echo cancellation. If the number is between 32 - * and 1024, it will also set the number of taps in the echo canceller - * - * For ECHOCANCEL_PARAMS: - * The structure contains parameters that should be passed to the - * echo canceler instance for the selected channel. - */ -#define ZT_ECHOCANCEL _IOW (ZT_CODE, 33, int) -#define ZT_ECHOCANCEL_PARAMS _IOW (ZT_CODE, 33, struct zt_echocanparams) - -/* - * Return a channel's channel number (useful for the /dev/zap/pseudo type interfaces - */ -#define ZT_CHANNO _IOR (ZT_CODE, 34, int) - -/* - * Return a flag indicating whether channel is currently dialing - */ -#define ZT_DIALING _IOR (ZT_CODE, 35, int) - -/* Numbers 60 to 90 are reserved for private use of low level hardware - drivers */ - -/* - * Set a clear channel into HDLC w/out FCS checking/calculation mode - */ -#define ZT_HDLCRAWMODE _IOW (ZT_CODE, 36, int) - -/* - * Set a clear channel into HDLC w/ FCS mode - */ -#define ZT_HDLCFCSMODE _IOW (ZT_CODE, 37, int) - -/* - * Specify a channel on /dev/zap/chan -- must be done before any other ioctl's and is only - * valid on /dev/zap/chan - */ -#define ZT_SPECIFY _IOW (ZT_CODE, 38, int) - -/* - * Temporarily set the law on a channel to - * ZT_LAW_DEFAULT, ZT_LAW_ALAW, or ZT_LAW_MULAW. Is reset on close. - */ -#define ZT_SETLAW _IOW (ZT_CODE, 39, int) - -/* - * Temporarily set the channel to operate in linear mode when non-zero - * or default law if 0 - */ -#define ZT_SETLINEAR _IOW (ZT_CODE, 40, int) - -/* - * Set a clear channel into HDLC w/ PPP interface mode - */ -#define ZT_HDLCPPP _IOW (ZT_CODE, 41, int) - -/* - * Set the ring cadence for FXS interfaces - */ -#define ZT_SETCADENCE _IOW (ZT_CODE, 42, struct zt_ring_cadence) - -/* - * Set the bits going out for CAS interface - */ -#define ZT_SETTXBITS _IOW (ZT_CODE, 43, int) - - -/* - * Display Channel Diagnostic Information on Console - */ -#define ZT_CHANDIAG _IOR (ZT_CODE, 44, int) - -/* - * Obtain received signalling - */ -#define ZT_GETRXBITS _IOR (ZT_CODE, 45, int) - -/* - * Set Channel's SF Tone Configuration - */ -#define ZT_SFCONFIG _IOW (ZT_CODE, 46, struct zt_sfconfig) - -/* - * Set timer expiration (in samples) - */ -#define ZT_TIMERCONFIG _IOW (ZT_CODE, 47, int) - -/* - * Acknowledge timer expiration (number to acknowledge, or -1 for all) - */ -#define ZT_TIMERACK _IOW (ZT_CODE, 48, int) - -/* - * Get Conference to mute mode - */ -#define ZT_GETCONFMUTE _IOR (ZT_CODE, 49, int) - -/* - * Request echo training in some number of ms (with muting in the mean time) - */ -#define ZT_ECHOTRAIN _IOW (ZT_CODE, 50, int) - -/* - * Set on hook transfer for n number of ms -- implemnted by low level driver - */ -#define ZT_ONHOOKTRANSFER _IOW (ZT_CODE, 51, int) - -/* - * Queue Ping - */ -#define ZT_TIMERPING _IOW (ZT_CODE, 42, int) /* Should be 52, but works */ - -/* - * Acknowledge ping - */ -#define ZT_TIMERPONG _IOW (ZT_CODE, 53, int) - -/* - * Set/get signalling freeze - */ -#define ZT_SIGFREEZE _IOW (ZT_CODE, 54, int) -#define ZT_GETSIGFREEZE _IOR (ZT_CODE, 55, int) - -/* - * Do a channel IOCTL from the /dev/zap/ctl interface - */ -#define ZT_INDIRECT _IOWR (ZT_CODE, 56, struct zt_indirect_data) - - -/* - * Get the version of Zaptel that is running, and a description - * of the compiled-in echo canceller (if any) - */ -#define ZT_GETVERSION _IOR(ZT_CODE, 57, struct zt_versioninfo) - -/* - * Put the channel in loopback mode (receive from the channel is - * transmitted back on the interface) - */ -#define ZT_LOOPBACK _IOW(ZT_CODE, 58, int) - - -/* - * 60-80 are reserved for private drivers - * 80-85 are reserved for dynamic span stuff - */ - -/* - * Create a dynamic span - */ -#define ZT_DYNAMIC_CREATE _IOWR (ZT_CODE, 80, struct zt_dynamic_span) - -/* - * Destroy a dynamic span - */ -#define ZT_DYNAMIC_DESTROY _IOW (ZT_CODE, 81, struct zt_dynamic_span) - -/* - * Set the HW gain for a device - */ -#define ZT_SET_HWGAIN _IOW (ZT_CODE, 86, struct zt_hwgain) - -/* - * Enable tone detection -- implemented by low level driver - */ -#define ZT_TONEDETECT _IOW (ZT_CODE, 91, int) - -/* - * Set polarity -- implemented by individual driver. 0 = forward, 1 = reverse - */ -#define ZT_SETPOLARITY _IOW (ZT_CODE, 92, int) - -/* - * Transcoder operations - */ -#define ZT_TRANSCODE_OP _IOWR(ZT_CODE, 93, int) - -/* - * VoiceMail Waiting Indication (WMWI) -- implemented by low-level driver. - * Value: number of waiting messages (hence 0: switch messages off). - */ -#define ZT_VMWI _IOWR(ZT_CODE, 94, int) - -/* - * Startup or Shutdown a span - */ -#define ZT_STARTUP _IOW (ZT_CODE, 99, int) -#define ZT_SHUTDOWN _IOW (ZT_CODE, 100, int) - -#define ZT_TONE_ZONE_MAX 128 - -#define ZT_TONE_ZONE_DEFAULT -1 /* To restore default */ - -#define ZT_TONE_STOP -1 -#define ZT_TONE_DIALTONE 0 -#define ZT_TONE_BUSY 1 -#define ZT_TONE_RINGTONE 2 -#define ZT_TONE_CONGESTION 3 -#define ZT_TONE_CALLWAIT 4 -#define ZT_TONE_DIALRECALL 5 -#define ZT_TONE_RECORDTONE 6 -#define ZT_TONE_INFO 7 -#define ZT_TONE_CUST1 8 -#define ZT_TONE_CUST2 9 -#define ZT_TONE_STUTTER 10 -#define ZT_TONE_MAX 16 - -#define ZT_TONE_DTMF_BASE 64 -#define ZT_TONE_MF_BASE 80 - -enum { - ZT_TONE_DTMF_0 = ZT_TONE_DTMF_BASE, - ZT_TONE_DTMF_1, - ZT_TONE_DTMF_2, - ZT_TONE_DTMF_3, - ZT_TONE_DTMF_4, - ZT_TONE_DTMF_5, - ZT_TONE_DTMF_6, - ZT_TONE_DTMF_7, - ZT_TONE_DTMF_8, - ZT_TONE_DTMF_9, - ZT_TONE_DTMF_s, - ZT_TONE_DTMF_p, - ZT_TONE_DTMF_A, - ZT_TONE_DTMF_B, - ZT_TONE_DTMF_C, - ZT_TONE_DTMF_D -}; - -#define ZT_TONE_DTMF_MAX ZT_TONE_DTMF_D - -enum { - ZT_TONE_MF_0 = ZT_TONE_MF_BASE, - ZT_TONE_MF_1, - ZT_TONE_MF_2, - ZT_TONE_MF_3, - ZT_TONE_MF_4, - ZT_TONE_MF_5, - ZT_TONE_MF_6, - ZT_TONE_MF_7, - ZT_TONE_MF_8, - ZT_TONE_MF_9, - ZT_TONE_MF_s, - ZT_TONE_MF_p, - ZT_TONE_MF_A, - ZT_TONE_MF_B, - ZT_TONE_MF_C, -}; - -#define ZT_TONE_MF_MAX ZT_TONE_MF_C - -#define ZT_MAX_CADENCE 16 - -#define ZT_TONEDETECT_ON (1 << 0) /* Detect tones */ -#define ZT_TONEDETECT_MUTE (1 << 1) /* Mute audio in received channel */ - -#define ZT_TRANSCODE_MAGIC 0x74a9c0de - -/* Operations */ -#define ZT_TCOP_ALLOCATE 1 /* Allocate/reset DTE channel */ -#define ZT_TCOP_TRANSCODE 2 /* Begin transcoding a block */ -#define ZT_TCOP_GETINFO 3 /* Get information (use zt_transcode_info) */ -#define ZT_TCOP_RELEASE 4 /* Release DTE channel */ -#define ZT_TCOP_TEST 5 /* test DTE device */ -typedef struct zt_transcode_info { - unsigned int op; - unsigned int tcnum; - char name[80]; - int numchannels; - unsigned int srcfmts; - unsigned int dstfmts; -} ZT_TRANSCODE_INFO; - -#define ZT_TCCONF_USETS (1 << 0) /* Use/update timestamp field */ -#define ZT_TCCONF_USESEQ (1 << 1) /* Use/update seqno field */ - -#define ZT_TCSTAT_DSTRDY (1 << 0) /* Destination data is ready */ -#define ZT_TCSTAT_DSTBUSY (1 << 1) /* Destination data is outstanding */ - -#define __ZT_TRANSCODE_BUFSIZ 16384 -#define ZT_TRANSCODE_HDRLEN 256 -#define ZT_TRANSCODE_BUFSIZ ((__ZT_TRANSCODE_BUFSIZ) - (ZT_TRANSCODE_HDRLEN)) -#define ZT_TRANSCODE_DSTOFFSET (((ZT_TRANSCODE_BUFSIZ) / 2) + ZT_TRANSCODE_HDRLEN) -#define ZT_TRANSCODE_SRCOFFSET (((ZT_TRANSCODE_BUFSIZ) / 2) + ZT_TRANSCODE_HDRLEN) - -typedef struct zt_transcode_header { - unsigned int srcfmt; /* See formats.h -- use TCOP_RESET when you change */ - unsigned int srcoffset; /* In bytes -- written by user */ - unsigned int srclen; /* In bytes -- written by user */ - unsigned int srctimestamp; /* In samples -- written by user (only used if ZT_TCCONF_USETS is set) */ - unsigned int srcseqno; /* In units -- written by user (only used if ZT_TCCONF_USESEQ is set) */ - - unsigned int dstfmt; /* See formats.h -- use TCOP_RESET when you change */ - unsigned int dstoffset; /* In bytes -- written by user */ - unsigned int dsttimestamp; /* In samples -- read by user */ - unsigned int dstseqno; /* In units -- read by user (only used if ZT_TCCONF_USESEQ is set) */ - unsigned int dstlen; /* In bytes -- read by user */ - unsigned int dstsamples; /* In timestamp units -- read by user */ - - unsigned int magic; /* Magic value -- ZT_TRANSCODE_MAGIC, read by user */ - unsigned int config; /* Read/write by user */ - unsigned int status; /* Read/write by user */ - unsigned char userhdr[ZT_TRANSCODE_HDRLEN - (sizeof(unsigned int) * 14)]; /* Storage for user parameters */ - unsigned char srcdata[ZT_TRANSCODE_BUFSIZ / 2]; /* Storage of source data */ - unsigned char dstdata[ZT_TRANSCODE_BUFSIZ / 2]; /* Storage of destination data */ -} ZT_TRANSCODE_HEADER; - -struct zt_ring_cadence { - int ringcadence[ZT_MAX_CADENCE]; -}; - -#define ZT_MAX_ECHOCANPARAMS 8 - -struct zt_echocanparam { - char name[16]; - __s32 value; -}; - -struct zt_echocanparams { - __u32 tap_length; /* 8 taps per millisecond */ - __u32 param_count; /* number of parameters supplied */ - /* immediately follow this structure with zt_echocanparam structures */ - struct zt_echocanparam params[0]; -}; - -struct zt_tone_def_header { - int count; /* How many samples follow */ - int zone; /* Which zone we are loading */ - int ringcadence[ZT_MAX_CADENCE]; /* Ring cadence in ms (0=on, 1=off, ends with 0 value) */ - char name[40]; /* Informational name of zone */ - /* Immediately follow the zt_tone_def_header by zt_tone_def's */ -}; - -struct zt_tone_def { /* Structure for zone programming */ - int tone; /* See ZT_TONE_* */ - int next; /* What the next position in the cadence is - (They're numbered by the order the appear here) */ - int samples; /* How many samples to play for this cadence */ - /* Now come the constants we need to make tones */ - int shift; /* How much to scale down the volume (2 is nice) */ - - /* - Calculate the next 6 factors using the following equations: - l = , f1 = , f2 = - gain = pow(10.0, (l - 3.14) / 20.0) * 65536.0 / 2.0; - - // Frequency factor 1 - fac_1 = 2.0 * cos(2.0 * M_PI * (f1/8000.0)) * 32768.0; - // Last previous two samples - init_v2_1 = sin(-4.0 * M_PI * (f1/8000.0)) * gain; - init_v3_1 = sin(-2.0 * M_PI * (f1/8000.0)) * gain; - - // Frequency factor 2 - fac_2 = 2.0 * cos(2.0 * M_PI * (f2/8000.0)) * 32768.0; - // Last previous two samples - init_v2_2 = sin(-4.0 * M_PI * (f2/8000.0)) * gain; - init_v3_2 = sin(-2.0 * M_PI * (f2/8000.0)) * gain; - */ - int fac1; - int init_v2_1; - int init_v3_1; - int fac2; - int init_v2_2; - int init_v3_2; - int modulate; - -}; - -#ifdef __KERNEL__ -#endif /* KERNEL */ - -/* Define the maximum block size */ -#define ZT_MAX_BLOCKSIZE 8192 - -/* Define the default network block size */ -#define ZT_DEFAULT_MTU_MRU 2048 - -/* Flush and stop the read (input) process */ -#define ZT_FLUSH_READ 1 - -/* Flush and stop the write (output) process */ -#define ZT_FLUSH_WRITE 2 - -/* Flush and stop both (input and output) processes */ -#define ZT_FLUSH_BOTH (ZT_FLUSH_READ | ZT_FLUSH_WRITE) - -/* Flush the event queue */ -#define ZT_FLUSH_EVENT 4 - -/* Flush everything */ -#define ZT_FLUSH_ALL (ZT_FLUSH_READ | ZT_FLUSH_WRITE | ZT_FLUSH_EVENT) - - -/* Value for ZT_HOOK, set to ON hook */ -#define ZT_ONHOOK 0 - -/* Value for ZT_HOOK, set to OFF hook */ -#define ZT_OFFHOOK 1 - -/* Value for ZT_HOOK, wink (off hook momentarily) */ -#define ZT_WINK 2 - -/* Value for ZT_HOOK, flash (on hook momentarily) */ -#define ZT_FLASH 3 - -/* Value for ZT_HOOK, start line */ -#define ZT_START 4 - -/* Value for ZT_HOOK, ring line (same as start line) */ -#define ZT_RING 5 - -/* Value for ZT_HOOK, turn ringer off */ -#define ZT_RINGOFF 6 - -/* Ret. Value for GET/WAIT Event, no event */ -#define ZT_EVENT_NONE 0 - -/* Ret. Value for GET/WAIT Event, Went Onhook */ -#define ZT_EVENT_ONHOOK 1 - -/* Ret. Value for GET/WAIT Event, Went Offhook or got Ring */ -#define ZT_EVENT_RINGOFFHOOK 2 - -/* Ret. Value for GET/WAIT Event, Got Wink or Flash */ -#define ZT_EVENT_WINKFLASH 3 - -/* Ret. Value for GET/WAIT Event, Got Alarm */ -#define ZT_EVENT_ALARM 4 - -/* Ret. Value for GET/WAIT Event, Got No Alarm (after alarm) */ -#define ZT_EVENT_NOALARM 5 - -/* Ret. Value for GET/WAIT Event, HDLC Abort frame */ -#define ZT_EVENT_ABORT 6 - -/* Ret. Value for GET/WAIT Event, HDLC Frame overrun */ -#define ZT_EVENT_OVERRUN 7 - -/* Ret. Value for GET/WAIT Event, Bad FCS */ -#define ZT_EVENT_BADFCS 8 - -/* Ret. Value for dial complete */ -#define ZT_EVENT_DIALCOMPLETE 9 - -/* Ret Value for ringer going on */ -#define ZT_EVENT_RINGERON 10 - -/* Ret Value for ringer going off */ -#define ZT_EVENT_RINGEROFF 11 - -/* Ret Value for hook change complete */ -#define ZT_EVENT_HOOKCOMPLETE 12 - -/* Ret Value for bits changing on a CAS / User channel */ -#define ZT_EVENT_BITSCHANGED 13 - -/* Ret value for the beginning of a pulse coming on its way */ -#define ZT_EVENT_PULSE_START 14 - -/* Timer event -- timer expired */ -#define ZT_EVENT_TIMER_EXPIRED 15 - -/* Timer event -- ping ready */ -#define ZT_EVENT_TIMER_PING 16 - -/* Polarity reversal event */ -#define ZT_EVENT_POLARITY 17 - -/* Ring Begin event */ -#define ZT_EVENT_RINGBEGIN 18 - -/* Echo can disabled event */ -#define ZT_EVENT_EC_DISABLED 19 - -/* Channel was disconnected. Hint user to close channel */ -#define ZT_EVENT_REMOVED 20 - -#define ZT_EVENT_PULSEDIGIT (1 << 16) /* This is OR'd with the digit received */ -#define ZT_EVENT_DTMFDOWN (1 << 17) /* Ditto for DTMF key down event */ -#define ZT_EVENT_DTMFUP (1 << 18) /* Ditto for DTMF key up event */ - -/* Flag Value for IOMUX, read avail */ -#define ZT_IOMUX_READ 1 - -/* Flag Value for IOMUX, write avail */ -#define ZT_IOMUX_WRITE 2 - -/* Flag Value for IOMUX, write done */ -#define ZT_IOMUX_WRITEEMPTY 4 - -/* Flag Value for IOMUX, signalling event avail */ -#define ZT_IOMUX_SIGEVENT 8 - -/* Flag Value for IOMUX, Do Not Wait if nothing to report */ -#define ZT_IOMUX_NOWAIT 0x100 - -/* Alarm Condition bits */ -#define ZT_ALARM_NONE 0 /* No alarms */ -#define ZT_ALARM_RECOVER 1 /* Recovering from alarm */ -#define ZT_ALARM_LOOPBACK 2 /* In loopback */ -#define ZT_ALARM_YELLOW 4 /* Yellow Alarm */ -#define ZT_ALARM_RED 8 /* Red Alarm */ -#define ZT_ALARM_BLUE 16 /* Blue Alarm */ -#define ZT_ALARM_NOTOPEN 32 -/* Maintenance modes */ -#define ZT_MAINT_NONE 0 /* Normal Mode */ -#define ZT_MAINT_LOCALLOOP 1 /* Local Loopback */ -#define ZT_MAINT_REMOTELOOP 2 /* Remote Loopback */ -#define ZT_MAINT_LOOPUP 3 /* send loopup code */ -#define ZT_MAINT_LOOPDOWN 4 /* send loopdown code */ -#define ZT_MAINT_LOOPSTOP 5 /* stop sending loop codes */ - - -/* Conference modes */ -#define ZT_CONF_MODE_MASK 0xff /* mask for modes */ -#define ZT_CONF_NORMAL 0 /* normal mode */ -#define ZT_CONF_MONITOR 1 /* monitor mode (rx of other chan) */ -#define ZT_CONF_MONITORTX 2 /* monitor mode (tx of other chan) */ -#define ZT_CONF_MONITORBOTH 3 /* monitor mode (rx & tx of other chan) */ -#define ZT_CONF_CONF 4 /* conference mode */ -#define ZT_CONF_CONFANN 5 /* conference announce mode */ -#define ZT_CONF_CONFMON 6 /* conference monitor mode */ -#define ZT_CONF_CONFANNMON 7 /* conference announce/monitor mode */ -#define ZT_CONF_REALANDPSEUDO 8 /* real and pseudo port both on conf */ -#define ZT_CONF_DIGITALMON 9 /* Do not decode or interpret */ -#define ZT_CONF_MONITOR_RX_PREECHO 10 /* monitor mode (rx of other chan) - before echo can is done */ -#define ZT_CONF_MONITOR_TX_PREECHO 11 /* monitor mode (tx of other chan) - before echo can is done */ -#define ZT_CONF_MONITORBOTH_PREECHO 12 /* monitor mode (rx & tx of other chan) - before echo can is done */ -#define ZT_CONF_FLAG_MASK 0xff00 /* mask for flags */ -#define ZT_CONF_LISTENER 0x100 /* is a listener on the conference */ -#define ZT_CONF_TALKER 0x200 /* is a talker on the conference */ -#define ZT_CONF_PSEUDO_LISTENER 0x400 /* pseudo is a listener on the conference */ -#define ZT_CONF_PSEUDO_TALKER 0x800 /* pseudo is a talker on the conference */ - - -#define ZT_DEFAULT_WINKTIME 150 /* 150 ms default wink time */ -#define ZT_DEFAULT_FLASHTIME 750 /* 750 ms default flash time */ - -#define ZT_DEFAULT_PREWINKTIME 50 /* 50 ms before wink */ -#define ZT_DEFAULT_PREFLASHTIME 50 /* 50 ms before flash */ -#define ZT_DEFAULT_STARTTIME 1500 /* 1500 ms of start */ -#define ZT_DEFAULT_RINGTIME 2000 /* 2000 ms of ring on (start, FXO) */ -#if 0 -#define ZT_DEFAULT_RXWINKTIME 250 /* 250ms longest rx wink */ -#endif -#define ZT_DEFAULT_RXWINKTIME 300 /* 300ms longest rx wink (to work with the Atlas) */ -#define ZT_DEFAULT_RXFLASHTIME 1250 /* 1250ms longest rx flash */ -#define ZT_DEFAULT_DEBOUNCETIME 600 /* 600ms of FXS GS signalling debounce */ -#define ZT_DEFAULT_PULSEMAKETIME 50 /* 50 ms of line closed when dial pulsing */ -#define ZT_DEFAULT_PULSEBREAKTIME 50 /* 50 ms of line open when dial pulsing */ -#define ZT_DEFAULT_PULSEAFTERTIME 750 /* 750ms between dial pulse digits */ - -#define ZT_MINPULSETIME (15 * 8) /* 15 ms minimum */ - -#ifdef SHORT_FLASH_TIME -#define ZT_MAXPULSETIME (80 * 8) /* we need 80 ms, not 200ms, as we have a short flash */ -#else -#define ZT_MAXPULSETIME (200 * 8) /* 200 ms maximum */ -#endif - -#define ZT_PULSETIMEOUT ((ZT_MAXPULSETIME / 8) + 50) - -#define ZT_RINGTRAILER (50 * 8) /* Don't consider a ring "over" until it's been gone at least this - much time */ - -#define ZT_LOOPCODE_TIME 10000 /* send loop codes for 10 secs */ -#define ZT_ALARMSETTLE_TIME 5000 /* allow alarms to settle for 5 secs */ -#define ZT_AFTERSTART_TIME 500 /* 500ms after start */ - -#define ZT_RINGOFFTIME 4000 /* Turn off ringer for 4000 ms */ -#define ZT_KEWLTIME 500 /* 500ms for kewl pulse */ -#define ZT_AFTERKEWLTIME 300 /* 300ms after kewl pulse */ - -#define ZT_MAX_PRETRAINING 1000 /* 1000ms max pretraining time */ - -#define ZT_MAX_SPANS 128 /* Max, 128 spans */ -#define ZT_MAX_CHANNELS 1024 /* Max, 1024 channels */ -#define ZT_MAX_CONF 1024 /* Max, 1024 conferences */ - -#ifdef FXSFLASH -#define ZT_FXSFLASHMINTIME 450 /* min 450ms */ -#define ZT_FXSFLASHMAXTIME 550 /* max 550ms */ -#endif - -#ifdef __KERNEL__ - -#include - -#define ZT_MAX_EVENTSIZE 64 /* 64 events max in buffer */ - -struct zt_span; -struct zt_chan; - -struct zt_tone_state { - int v1_1; - int v2_1; - int v3_1; - int v1_2; - int v2_2; - int v3_2; - int modulate; -}; - -struct zt_chardev { - const char *name; - __u8 minor; -#ifdef CONFIG_DEVFS_FS - devfs_handle_t devfs_handle; -#endif -}; - -int zt_register_chardev(struct zt_chardev *dev); -int zt_unregister_chardev(struct zt_chardev *dev); - -#ifdef CONFIG_ZAPATA_NET -struct zt_hdlc { -#ifdef LINUX26 - struct net_device *netdev; -#else - hdlc_device netdev; -#endif - struct zt_chan *chan; -}; -#endif - -/* Echo cancellation */ -struct echo_can_state; -#if 0 -/* echo can API consists of these functions */ -void echo_can_init(void); -void echo_chan_shutdown(void); -void echo_can_identify(char *buf, size_t len); -int echo_can_create(struct zt_echocanparams *ecp, struct zt_echocanparam *p, struct echo_can_state **ec); -void echo_can_free(struct echo_can_state *ec); -short echo_can_update(struct echo_can_state *ec, short iref, short isig); -void echo_can_array_update(struct echo_can_state *ec, short *iref, short *isig); -int echo_can_traintap(struct echo_can_state *ec, int pos, short val); -#endif - -/* Conference queue stucture */ -struct confq { - u_char buffer[ZT_CHUNKSIZE * ZT_CB_SIZE]; - u_char *buf[ZT_CB_SIZE]; - int inbuf; - int outbuf; -}; - -typedef struct -{ - long x1; - long x2; - long y1; - long y2; - long e1; - long e2; - int samps; - int lastdetect; -} sf_detect_state_t; - -struct zt_chan { -#ifdef CONFIG_ZAPATA_NET - /* Must be first */ - struct zt_hdlc *hdlcnetdev; -#endif -#ifdef CONFIG_ZAPATA_PPP - struct ppp_channel *ppp; - struct tasklet_struct ppp_calls; - int do_ppp_wakeup; - int do_ppp_error; - struct sk_buff_head ppp_rq; -#endif - spinlock_t lock; - char name[40]; /* Name */ - /* Specified by zaptel */ - int channo; /* Zaptel Channel number */ - int chanpos; - int flags; - long rxp1; - long rxp2; - long rxp3; - int txtone; - int tx_v2; - int tx_v3; - int v1_1; - int v2_1; - int v3_1; - int toneflags; - sf_detect_state_t rd; - - struct zt_chan *master; /* Our Master channel (could be us) */ - /* Next slave (if appropriate) */ - int nextslave; - - u_char *writechunk; /* Actual place to write to */ - u_char swritechunk[ZT_MAX_CHUNKSIZE]; /* Buffer to be written */ - u_char *readchunk; /* Actual place to read from */ - u_char sreadchunk[ZT_MAX_CHUNKSIZE]; /* Preallocated static area */ - short *readchunkpreec; - - /* Pointer to tx and rx gain tables */ - u_char *rxgain; - u_char *txgain; - - /* Whether or not we have allocated gains or are using the default */ - int gainalloc; - - /* Specified by driver, readable by zaptel */ - void *pvt; /* Private channel data */ - struct file *file; /* File structure */ - - - struct zt_span *span; /* Span we're a member of */ - int sig; /* Signalling */ - int sigcap; /* Capability for signalling */ - __u32 chan_alarms; /* alarms status */ - - /* Used only by zaptel -- NO DRIVER SERVICEABLE PARTS BELOW */ - /* Buffer declarations */ - u_char *readbuf[ZT_MAX_NUM_BUFS]; /* read buffer */ - int inreadbuf; - int outreadbuf; - wait_queue_head_t readbufq; /* read wait queue */ - - u_char *writebuf[ZT_MAX_NUM_BUFS]; /* write buffers */ - int inwritebuf; - int outwritebuf; - wait_queue_head_t writebufq; /* write wait queue */ - - int blocksize; /* Block size */ - - int eventinidx; /* out index in event buf (circular) */ - int eventoutidx; /* in index in event buf (circular) */ - unsigned int eventbuf[ZT_MAX_EVENTSIZE]; /* event circ. buffer */ - wait_queue_head_t eventbufq; /* event wait queue */ - - wait_queue_head_t txstateq; /* waiting on the tx state to change */ - - int readn[ZT_MAX_NUM_BUFS]; /* # of bytes ready in read buf */ - int readidx[ZT_MAX_NUM_BUFS]; /* current read pointer */ - int writen[ZT_MAX_NUM_BUFS]; /* # of bytes ready in write buf */ - int writeidx[ZT_MAX_NUM_BUFS]; /* current write pointer */ - - int numbufs; /* How many buffers in channel */ - int txbufpolicy; /* Buffer policy */ - int rxbufpolicy; /* Buffer policy */ - int txdisable; /* Disable transmitter */ - int rxdisable; /* Disable receiver */ - - - /* Tone zone stuff */ - struct zt_zone *curzone; /* Zone for selecting tones */ - int tonezone; /* Tone zone for this channel */ - struct zt_tone *curtone; /* Current tone we're playing (if any) */ - int tonep; /* Current position in tone */ - struct zt_tone_state ts; /* Tone state */ - - /* Pulse dial stuff */ - int pdialcount; /* pulse dial count */ - - /* Ring cadence */ - int ringcadence[ZT_MAX_CADENCE]; - int firstcadencepos; /* Where to restart ring cadence */ - - /* Digit string dialing stuff */ - int digitmode; /* What kind of tones are we sending? */ - char txdialbuf[ZT_MAX_DTMF_BUF]; - int dialing; - int afterdialingtimer; - int cadencepos; /* Where in the cadence we are */ - - /* I/O Mask */ - int iomask; /* I/O Mux signal mask */ - wait_queue_head_t sel; /* thingy for select stuff */ - - /* HDLC state machines */ - struct fasthdlc_state txhdlc; - struct fasthdlc_state rxhdlc; - int infcs; - - /* Conferencing stuff */ - int confna; /* conference number (alias) */ - int _confn; /* Actual conference number */ - int confmode; /* conference mode */ - int confmute; /* conference mute mode */ - - /* Incoming and outgoing conference chunk queues for - communicating between zaptel master time and - other boards */ - struct confq confin; - struct confq confout; - - short getlin[ZT_MAX_CHUNKSIZE]; /* Last transmitted samples */ - unsigned char getraw[ZT_MAX_CHUNKSIZE]; /* Last received raw data */ - short getlin_lastchunk[ZT_MAX_CHUNKSIZE]; /* Last transmitted samples from last chunk */ - short putlin[ZT_MAX_CHUNKSIZE]; /* Last received samples */ - unsigned char putraw[ZT_MAX_CHUNKSIZE]; /* Last received raw data */ - short conflast[ZT_MAX_CHUNKSIZE]; /* Last conference sample -- base part of channel */ - short conflast1[ZT_MAX_CHUNKSIZE]; /* Last conference sample -- pseudo part of channel */ - short conflast2[ZT_MAX_CHUNKSIZE]; /* Previous last conference sample -- pseudo part of channel */ - - - /* Is echo cancellation enabled or disabled */ - int echocancel; - struct echo_can_state *ec; - echo_can_disable_detector_state_t txecdis; - echo_can_disable_detector_state_t rxecdis; - - int echostate; /* State of echo canceller */ - int echolastupdate; /* Last echo can update pos */ - int echotimer; /* Timer for echo update */ - - /* RBS timings */ - int prewinktime; /* pre-wink time (ms) */ - int preflashtime; /* pre-flash time (ms) */ - int winktime; /* wink time (ms) */ - int flashtime; /* flash time (ms) */ - int starttime; /* start time (ms) */ - int rxwinktime; /* rx wink time (ms) */ - int rxflashtime; /* rx flash time (ms) */ - int debouncetime; /* FXS GS sig debounce time (ms) */ - int pulsebreaktime; /* pulse line open time (ms) */ - int pulsemaketime; /* pulse line closed time (ms) */ - int pulseaftertime; /* pulse time between digits (ms) */ - - /* RING debounce timer */ - int ringdebtimer; - - /* RING trailing detector to make sure a RING is really over */ - int ringtrailer; - - /* PULSE digit receiver stuff */ - int pulsecount; - int pulsetimer; - - /* RBS timers */ - int itimerset; /* what the itimer was set to last */ - int itimer; - int otimer; - - /* RBS state */ - int gotgs; - int txstate; - int rxsig; - int txsig; - int rxsigstate; - - /* non-RBS rx state */ - int rxhooksig; - int txhooksig; - int kewlonhook; - - /* Idle signalling if CAS signalling */ - int idlebits; - - int deflaw; /* 1 = mulaw, 2=alaw, 0=undefined */ - short *xlaw; -#ifdef OPTIMIZE_CHANMUTE - int chanmute; /*!< no need for PCM data */ -#endif -#ifdef CONFIG_CALC_XLAW - unsigned char (*lineartoxlaw)(short a); -#else - unsigned char *lin2x; -#endif - -#ifdef CONFIG_DEVFS_FS - devfs_handle_t fhandle; /* File handle in devfs for the channel */ - devfs_handle_t fhandle_symlink; -#endif /* CONFIG_DEVFS_FS */ -}; - -/* defines for transmit signalling */ -typedef enum { - ZT_TXSIG_ONHOOK, /* On hook */ - ZT_TXSIG_OFFHOOK, /* Off hook */ - ZT_TXSIG_START, /* Start / Ring */ - ZT_TXSIG_KEWL /* Drop battery if possible */ -} zt_txsig_t; - -typedef enum { - ZT_RXSIG_ONHOOK, - ZT_RXSIG_OFFHOOK, - ZT_RXSIG_START, - ZT_RXSIG_RING, - ZT_RXSIG_INITIAL -} zt_rxsig_t; - - -/* Span flags */ -#define ZT_FLAG_REGISTERED (1 << 0) -#define ZT_FLAG_RUNNING (1 << 1) -#define ZT_FLAG_RBS (1 << 12) /* Span uses RBS signalling */ - -/* Channel flags */ -#define ZT_FLAG_DTMFDECODE (1 << 2) /* Channel supports native DTMF decode */ -#define ZT_FLAG_MFDECODE (1 << 3) /* Channel supports native MFr2 decode */ -#define ZT_FLAG_ECHOCANCEL (1 << 4) /* Channel supports native echo cancellation */ - -#define ZT_FLAG_HDLC (1 << 5) /* Perform HDLC */ -#define ZT_FLAG_NETDEV (1 << 6) /* Send to network */ -#define ZT_FLAG_PSEUDO (1 << 7) /* Pseudo channel */ -#define ZT_FLAG_CLEAR (1 << 8) /* Clear channel */ -#define ZT_FLAG_AUDIO (1 << 9) /* Audio mode channel */ - -#define ZT_FLAG_OPEN (1 << 10) /* Channel is open */ -#define ZT_FLAG_FCS (1 << 11) /* Calculate FCS */ -/* Reserve 12 for uniqueness with span flags */ -#define ZT_FLAG_LINEAR (1 << 13) /* Talk to user space in linear */ -#define ZT_FLAG_PPP (1 << 14) /* PPP is available */ -#define ZT_FLAG_T1PPP (1 << 15) -#define ZT_FLAG_SIGFREEZE (1 << 16) /* Freeze signalling */ -#define ZT_FLAG_NOSTDTXRX (1 << 17) /* Do NOT do standard transmit and receive on every interrupt */ -#define ZT_FLAG_LOOPED (1 << 18) /* Loopback the receive data from the channel to the transmit */ - -struct zt_span { - spinlock_t lock; - void *pvt; /* Private stuff */ - char name[40]; /* Span name */ - char desc[80]; /* Span description */ - const char *spantype; /* span type in text form */ - const char *manufacturer; /* span's device manufacturer */ - char devicetype[80]; /* span's device type */ - char location[40]; /* span device's location in system */ - int deflaw; /* Default law (ZT_MULAW or ZT_ALAW) */ - int alarms; /* Pending alarms on span */ - int flags; - int irq; /* IRQ for this span's hardware */ - int lbo; /* Span Line-Buildout */ - int lineconfig; /* Span line configuration */ - int linecompat; /* Span line compatibility */ - int channels; /* Number of channels in span */ - int txlevel; /* Tx level */ - int rxlevel; /* Rx level */ - int syncsrc; /* current sync src (gets copied here) */ - unsigned int bpvcount; /* BPV counter */ - unsigned int crc4count; /* CRC4 error counter */ - unsigned int ebitcount; /* current E-bit error count */ - unsigned int fascount; /* current FAS error count */ - - int maintstat; /* Maintenance state */ - wait_queue_head_t maintq; /* Maintenance queue */ - int mainttimer; /* Maintenance timer */ - - int irqmisses; /* Interrupt misses */ - - int timingslips; /* Clock slips */ - - struct zt_chan *chans; /* Member channel structures */ - - /* ==== Span Callback Operations ==== */ - /* Req: Set the requested chunk size. This is the unit in which you must - report results for conferencing, etc */ - int (*setchunksize)(struct zt_span *span, int chunksize); - - /* Opt: Configure the span (if appropriate) */ - int (*spanconfig)(struct zt_span *span, struct zt_lineconfig *lc); - - /* Opt: Start the span */ - int (*startup)(struct zt_span *span); - - /* Opt: Shutdown the span */ - int (*shutdown)(struct zt_span *span); - - /* Opt: Enable maintenance modes */ - int (*maint)(struct zt_span *span, int mode); - -#ifdef ZAPTEL_SYNC_TICK - /* Opt: send sync to spans */ - int (*sync_tick)(struct zt_span *span, int is_master); -#endif - - /* ==== Channel Callback Operations ==== */ - /* Opt: Set signalling type (if appropriate) */ - int (*chanconfig)(struct zt_chan *chan, int sigtype); - - /* Opt: Prepare a channel for I/O */ - int (*open)(struct zt_chan *chan); - - /* Opt: Close channel for I/O */ - int (*close)(struct zt_chan *chan); - - /* Opt: IOCTL */ - int (*ioctl)(struct zt_chan *chan, unsigned int cmd, unsigned long data); - - /* Opt: Native echo cancellation (simple) */ - int (*echocan)(struct zt_chan *chan, int ecval); - - int (*echocan_with_params)(struct zt_chan *chan, struct zt_echocanparams *ecp, struct zt_echocanparam *p); - - /* Okay, now we get to the signalling. You have several options: */ - - /* Option 1: If you're a T1 like interface, you can just provide a - rbsbits function and we'll assert robbed bits for you. Be sure to - set the ZT_FLAG_RBS in this case. */ - - /* Opt: If the span uses A/B bits, set them here */ - int (*rbsbits)(struct zt_chan *chan, int bits); - - /* Option 2: If you don't know about sig bits, but do have their - equivalents (i.e. you can disconnect battery, detect off hook, - generate ring, etc directly) then you can just specify a - sethook function, and we'll call you with appropriate hook states - to set. Still set the ZT_FLAG_RBS in this case as well */ - int (*hooksig)(struct zt_chan *chan, zt_txsig_t hookstate); - - /* Option 3: If you can't use sig bits, you can write a function - which handles the individual hook states */ - int (*sethook)(struct zt_chan *chan, int hookstate); - - /* Opt: Dacs the contents of chan2 into chan1 if possible */ - int (*dacs)(struct zt_chan *chan1, struct zt_chan *chan2); - - /* Opt: Used to tell an onboard HDLC controller that there is data ready to transmit */ - void (*hdlc_hard_xmit)(struct zt_chan *chan); - - /* Used by zaptel only -- no user servicable parts inside */ - int spanno; /* Span number for zaptel */ - int offset; /* Offset within a given card */ - int lastalarms; /* Previous alarms */ - -#ifdef CONFIG_DEVFS_FS - devfs_handle_t dhandle; /* Directory name */ -#endif - /* If the watchdog detects no received data, it will call the - watchdog routine */ - int (*watchdog)(struct zt_span *span, int cause); -#ifdef CONFIG_ZAPTEL_WATCHDOG - int watchcounter; - int watchstate; -#endif -}; - -struct zt_transcoder_channel { - void *pvt; - struct zt_transcoder *parent; - wait_queue_head_t ready; - int errorstatus; - int offset; - unsigned int chan_built; - unsigned int built_fmts; - unsigned int flags; - unsigned int srcfmt; - unsigned int dstfmt; - struct zt_transcode_header *tch; -}; - -#define ZT_TC_FLAG_BUSY (1 << 0) -#define ZT_TC_FLAG_TRANSIENT (1 << 1) - - -struct zt_transcoder { - struct zt_transcoder *next; - char name[80]; - int numchannels; - unsigned int srcfmts; - unsigned int dstfmts; - int (*operation)(struct zt_transcoder_channel *channel, int op); - /* Transcoder channels */ - struct zt_transcoder_channel channels[0]; -}; - -#define ZT_WATCHDOG_NOINTS (1 << 0) - -#define ZT_WATCHDOG_INIT 1000 - -#define ZT_WATCHSTATE_UNKNOWN 0 -#define ZT_WATCHSTATE_OK 1 -#define ZT_WATCHSTATE_RECOVERING 2 -#define ZT_WATCHSTATE_FAILED 3 - - -struct zt_dynamic_driver { - /* Driver name (e.g. Eth) */ - char name[20]; - - /* Driver description */ - char desc[80]; - - /* Create a new transmission pipe */ - void *(*create)(struct zt_span *span, char *address); - - /* Destroy a created transmission pipe */ - void (*destroy)(void *tpipe); - - /* Transmit a given message */ - int (*transmit)(void *tpipe, unsigned char *msg, int msglen); - - /* Flush any pending messages */ - int (*flush)(void); - - struct zt_dynamic_driver *next; -}; - -/* Receive a dynamic span message */ -void zt_dynamic_receive(struct zt_span *span, unsigned char *msg, int msglen); - -/* Register a dynamic driver */ -int zt_dynamic_register(struct zt_dynamic_driver *driver); - -/* Unregister a dynamic driver */ -void zt_dynamic_unregister(struct zt_dynamic_driver *driver); - -/* Receive on a span. The zaptel interface will handle all the calculations for - all member channels of the span, pulling the data from the readchunk buffer */ -int zt_receive(struct zt_span *span); - -/* Prepare writechunk buffers on all channels for this span */ -int zt_transmit(struct zt_span *span); - -/* Abort the buffer currently being receive with event "event" */ -void zt_hdlc_abort(struct zt_chan *ss, int event); - -/* Indicate to zaptel that the end of frame was received and rotate buffers */ -void zt_hdlc_finish(struct zt_chan *ss); - -/* Put a chunk of data into the current receive buffer */ -void zt_hdlc_putbuf(struct zt_chan *ss, unsigned char *rxb, int bytes); - -/* Get a chunk of data from the current transmit buffer. Returns -1 if no data - * is left to send, 0 if there is data remaining in the current message to be sent - * and 1 if the currently transmitted message is now done */ -int zt_hdlc_getbuf(struct zt_chan *ss, unsigned char *bufptr, unsigned int *size); - - -/* Register a span. Returns 0 on success, -1 on failure. Pref-master is non-zero if - we should have preference in being the master device */ -int zt_register(struct zt_span *span, int prefmaster); - -/* Allocate / free memory for a transcoder */ -struct zt_transcoder *zt_transcoder_alloc(int numchans); -void zt_transcoder_free(struct zt_transcoder *ztc); - -/* Register a transcoder */ -int zt_transcoder_register(struct zt_transcoder *tc); - -/* Unregister a transcoder */ -int zt_transcoder_unregister(struct zt_transcoder *tc); - -/* Alert a transcoder */ -int zt_transcoder_alert(struct zt_transcoder_channel *ztc); - -/* Unregister a span */ -int zt_unregister(struct zt_span *span); - -/* Gives a name to an LBO */ -char *zt_lboname(int lbo); - -/* Tell Zaptel about changes in received rbs bits */ -void zt_rbsbits(struct zt_chan *chan, int bits); - -/* Tell Zaptel abou changes in received signalling */ -void zt_hooksig(struct zt_chan *chan, zt_rxsig_t rxsig); - -/* Queue an event on a channel */ -void zt_qevent_nolock(struct zt_chan *chan, int event); - -/* Queue an event on a channel, locking it first */ -void zt_qevent_lock(struct zt_chan *chan, int event); - -/* Notify a change possible change in alarm status on a channel */ -void zt_alarm_channel(struct zt_chan *chan, int alarms); - -/* Notify a change possible change in alarm status on a span */ -void zt_alarm_notify(struct zt_span *span); - -/* Initialize a tone state */ -void zt_init_tone_state(struct zt_tone_state *ts, struct zt_tone *zt); - -/* Get a given DTMF or MF tone struct, suitable for zt_tone_nextsample. */ -struct zt_tone *zt_dtmf_tone(const struct zt_chan *chan, char digit); - -/* Echo cancel a receive and transmit chunk for a given channel. This - should be called by the low-level driver as close to the interface - as possible. ECHO CANCELLATION IS NO LONGER AUTOMATICALLY DONE - AT THE ZAPTEL LEVEL. zt_ec_chunk will not echo cancel if it should - not be doing so. rxchunk is modified in-place */ - -void zt_ec_chunk(struct zt_chan *chan, unsigned char *rxchunk, const unsigned char *txchunk); -void zt_ec_span(struct zt_span *span); - -extern struct file_operations *zt_transcode_fops; - -/* Don't use these directly -- they're not guaranteed to - be there. */ -extern short __zt_mulaw[256]; -extern short __zt_alaw[256]; -#ifdef CONFIG_CALC_XLAW -u_char __zt_lineartoulaw(short a); -u_char __zt_lineartoalaw(short a); -#else -extern u_char __zt_lin2mu[16384]; -extern u_char __zt_lin2a[16384]; -#endif - -/* Used by dynamic zaptel -- don't use directly */ -void zt_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data)); - -/* Used privately by zaptel. Avoid touching directly */ -struct zt_tone { - int fac1; - int init_v2_1; - int init_v3_1; - - int fac2; - int init_v2_2; - int init_v3_2; - - int tonesamples; /* How long to play this tone before - going to the next (in samples) */ - struct zt_tone *next; /* Next tone in this sequence */ - - int modulate; -}; - -static inline short zt_tone_nextsample(struct zt_tone_state *ts, struct zt_tone *zt) -{ - /* follow the curves, return the sum */ - - int p; - - ts->v1_1 = ts->v2_1; - ts->v2_1 = ts->v3_1; - ts->v3_1 = (zt->fac1 * ts->v2_1 >> 15) - ts->v1_1; - - ts->v1_2 = ts->v2_2; - ts->v2_2 = ts->v3_2; - ts->v3_2 = (zt->fac2 * ts->v2_2 >> 15) - ts->v1_2; - - /* Return top 16 bits */ - if (!ts->modulate) return ts->v3_1 + ts->v3_2; - /* we are modulating */ - p = ts->v3_2 - 32768; - if (p < 0) p = -p; - p = ((p * 9) / 10) + 1; - return (ts->v3_1 * p) >> 15; - -} - -static inline short zt_txtone_nextsample(struct zt_chan *ss) -{ - /* follow the curves, return the sum */ - - ss->v1_1 = ss->v2_1; - ss->v2_1 = ss->v3_1; - ss->v3_1 = (ss->txtone * ss->v2_1 >> 15) - ss->v1_1; - return ss->v3_1; -} - -/* These are the right functions to use. */ - -#define ZT_MULAW(a) (__zt_mulaw[(a)]) -#define ZT_ALAW(a) (__zt_alaw[(a)]) -#define ZT_XLAW(a,c) (c->xlaw[(a)]) - -#ifdef CONFIG_CALC_XLAW -#define ZT_LIN2MU(a) (__zt_lineartoulaw((a))) -#define ZT_LIN2A(a) (__zt_lineartoalaw((a))) - -#define ZT_LIN2X(a,c) ((c)->lineartoxlaw((a))) - -#else -/* Use tables */ -#define ZT_LIN2MU(a) (__zt_lin2mu[((unsigned short)(a)) >> 2]) -#define ZT_LIN2A(a) (__zt_lin2a[((unsigned short)(a)) >> 2]) - -/* Manipulate as appropriate for x-law */ -#define ZT_LIN2X(a,c) ((c)->lin2x[((unsigned short)(a)) >> 2]) - -#endif /* CONFIG_CALC_XLAW */ - -#endif /* __KERNEL__ */ - -/* The following is for the PCI RADIO interface only. This is specified in -this file because external processes need to interact with the device. -Some devices have private functions used for test/diagnostic only, but -this is not the case here. */ - -struct zt_radio_stat { - unsigned short ctcode_rx; /* code of currently received CTCSS - or DCS, 0 for none */ - unsigned short ctclass; /* class of currently received CTCSS or - DCS code */ - unsigned short ctcode_tx; /* code of currently encoded CTCSS or - DCS, 0 for none */ - unsigned char radstat; /* status bits of radio */ -}; - -#define RAD_SERIAL_BUFLEN 128 - -struct zt_radio_param { - unsigned short radpar; /* param identifier */ - unsigned short index; /* tone number */ - int data; /* param */ - int data2; /* param 2 */ - unsigned char buf[RAD_SERIAL_BUFLEN]; -}; - - -/* Get current status IOCTL */ -#define ZT_RADIO_GETSTAT _IOR (ZT_CODE, 57, struct zt_radio_stat) -/* Set a channel parameter IOCTL */ -#define ZT_RADIO_SETPARAM _IOW (ZT_CODE, 58, struct zt_radio_param) -/* Get a channel parameter IOCTL */ -#define ZT_RADIO_GETPARAM _IOR (ZT_CODE, 59, struct zt_radio_param) - - -/* Defines for Radio Status (zt_radio_stat.radstat) bits */ - -#define ZT_RADSTAT_RX 1 /* currently "receiving " */ -#define ZT_RADSTAT_TX 2 /* currently "transmitting" */ -#define ZT_RADSTAT_RXCT 4 /* currently receiving continuous tone with - current settings */ -#define ZT_RADSTAT_RXCOR 8 /* currently receiving COR (irrelevant of COR - ignore) */ -#define ZT_RADSTAT_IGNCOR 16 /* currently ignoring COR */ -#define ZT_RADSTAT_IGNCT 32 /* currently ignoring CTCSS/DCS decode */ -#define ZT_RADSTAT_NOENCODE 64 /* currently blocking CTCSS/DCS encode */ - -/* Defines for Radio Parameters (zt_radio_param.radpar) */ - -#define ZT_RADPAR_INVERTCOR 1 /* invert the COR signal (0/1) */ -#define ZT_RADPAR_IGNORECOR 2 /* ignore the COR signal (0/1) */ -#define ZT_RADPAR_IGNORECT 3 /* ignore the CTCSS/DCS decode (0/1) */ -#define ZT_RADPAR_NOENCODE 4 /* block the CTCSS/DCS encode (0/1) */ -#define ZT_RADPAR_CORTHRESH 5 /* COR trigger threshold (0-7) */ - -#define ZT_RADPAR_EXTRXTONE 6 /* 0 means use internal decoder, 1 means UIOA - logic true is CT decode, 2 means UIOA logic - false is CT decode */ -#define ZT_RADPAR_NUMTONES 7 /* returns maximum tone index (curently 15) */ -#define ZT_RADPAR_INITTONE 8 /* init all tone indexes to 0 (no tones) */ -#define ZT_RADPAR_RXTONE 9 /* CTCSS tone, (1-32) or DCS tone (1-777), - or 0 meaning no tone, set index also (1-15) */ -#define ZT_RADPAR_RXTONECLASS 10 /* Tone class (0-65535), set index also (1-15) */ -#define ZT_RADPAR_TXTONE 11 /* CTCSS tone (1-32) or DCS tone (1-777) or 0 - to indicate no tone, to transmit - for this tone index (0-32, 0 disables - transmit CTCSS), set index also (0-15) */ -#define ZT_RADPAR_DEBOUNCETIME 12 /* receive indication debounce time, - milliseconds (1-999) */ -#define ZT_RADPAR_BURSTTIME 13 /* end of transmit with no CT tone in - milliseconds (0-999) */ - - -#define ZT_RADPAR_UIODATA 14 /* read/write UIOA and UIOB data. Bit 0 is - UIOA, bit 1 is UIOB */ -#define ZT_RADPAR_UIOMODE 15 /* 0 means UIOA and UIOB are both outputs, 1 - means UIOA is input, UIOB is output, 2 - means UIOB is input and UIOA is output, - 3 means both UIOA and UIOB are inputs. Note - mode for UIOA is overridden when in - EXTRXTONE mode. */ - -#define ZT_RADPAR_REMMODE 16 /* Remote control data mode */ - #define ZT_RADPAR_REM_NONE 0 /* no remote control data mode */ - #define ZT_RADPAR_REM_RBI1 1 /* Doug Hall RBI-1 data mode */ - #define ZT_RADPAR_REM_SERIAL 2 /* Serial Data, 9600 BPS */ - #define ZT_RADPAR_REM_SERIAL_ASCII 3 /* Serial Ascii Data, 9600 BPS */ - -#define ZT_RADPAR_REMCOMMAND 17 /* Remote conrtol write data block & do cmd */ - -/* Data formats for capabilities and frames alike (from Asterisk) */ -/*! G.723.1 compression */ -#define ZT_FORMAT_G723_1 (1 << 0) -/*! GSM compression */ -#define ZT_FORMAT_GSM (1 << 1) -/*! Raw mu-law data (G.711) */ -#define ZT_FORMAT_ULAW (1 << 2) -/*! Raw A-law data (G.711) */ -#define ZT_FORMAT_ALAW (1 << 3) -/*! ADPCM (G.726, 32kbps) */ -#define ZT_FORMAT_G726 (1 << 4) -/*! ADPCM (IMA) */ -#define ZT_FORMAT_ADPCM (1 << 5) -/*! Raw 16-bit Signed Linear (8000 Hz) PCM */ -#define ZT_FORMAT_SLINEAR (1 << 6) -/*! LPC10, 180 samples/frame */ -#define ZT_FORMAT_LPC10 (1 << 7) -/*! G.729A audio */ -#define ZT_FORMAT_G729A (1 << 8) -/*! SpeeX Free Compression */ -#define ZT_FORMAT_SPEEX (1 << 9) -/*! iLBC Free Compression */ -#define ZT_FORMAT_ILBC (1 << 10) -/*! Maximum audio format */ -#define ZT_FORMAT_MAX_AUDIO (1 << 15) -/*! Maximum audio mask */ -#define ZT_FORMAT_AUDIO_MASK ((1 << 16) - 1) - -#define ZT_RADPAR_DEEMP 18 /* Audio De-empahsis (on or off) */ - -#define ZT_RADPAR_PREEMP 19 /* Audio Pre-empahsis (on or off) */ - -#define ZT_RADPAR_RXGAIN 20 /* Audio (In to system) Rx Gain */ - -#define ZT_RADPAR_TXGAIN 21 /* Audio (Out from system) Tx Gain */ - -struct torisa_debug { - unsigned int txerrors; - unsigned int irqcount; - unsigned int taskletsched; - unsigned int taskletrun; - unsigned int taskletexec; - int span1flags; - int span2flags; -}; - -/* Special torisa ioctl */ -#define TORISA_GETDEBUG _IOW (ZT_CODE, 60, struct torisa_debug) - -#endif /* _LINUX_ZAPTEL_H */ diff --git a/zconfig.h b/zconfig.h deleted file mode 100644 index 35056e3..0000000 --- a/zconfig.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Zaptel configuration options - * - */ -#ifndef _ZCONFIG_H -#define _ZCONFIG_H - -#ifdef __KERNEL__ -#include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) -#include -#else -#include -#endif -#endif - -/* Zaptel compile time options */ - -/* - * Uncomment if you have a European phone, or any other phone with a - * short flash time. - * This will stop the flash being mis-detected as a pulse dial "1" on - * phones with short flashes - */ -/* #define SHORT_FLASH_TIME */ - -/* - * Uncomment to disable calibration and/or DC/DC converter tests - * (not generally recommended) - */ -/* #define NO_CALIBRATION */ -/* #define NO_DCDC */ - -/* - * Boost ring voltage (Higher ring voltage, takes more power) - * Note: this only affects the wcfxsusb and wcusb drivers; all other - * drivers have a 'boostringer' module parameter. - */ -/* #define BOOST_RINGER */ - -/* - * Define CONFIG_CALC_XLAW if you have a small number of channels and/or - * a small level 2 cache, to optimize for few channels - * - */ -/* #define CONFIG_CALC_XLAW */ - -/* - * Define if you want MMX optimizations in zaptel - * - * Note: CONFIG_ZAPTEL_MMX is generally incompatible with AMD - * processors and can cause system instability! - * - */ -/* #define CONFIG_ZAPTEL_MMX */ - -/** If defined: the user must define exactly one ECHO_CAN_ var: */ -#ifndef ECHO_CAN_FROMENV - -/* - * Pick your echo canceller: MARK2, MARK3, STEVE, or STEVE2 :) - * - */ -/* #define ECHO_CAN_STEVE */ -/* #define ECHO_CAN_STEVE2 */ -/* #define ECHO_CAN_KB1 */ -/* This is the new latest and greatest */ -#define ECHO_CAN_MG2 - -/* - * This is only technically an "echo canceller"... - * It purposely drops 2 out of 3 samples and sounds horrible. - * You really only want this for testing "echo cancelled" audio. - */ -/* #define ECHO_CAN_JP1 */ - -/* - * Uncomment for aggressive residual echo suppression under - * MARK2, KB1, and MG2 echo canceler - */ -/* #define AGGRESSIVE_SUPPRESSOR */ -#endif /* ifndef ECHO_CAN_FROMENV */ -/* - * Define to turn off the echo canceler disable tone detector, - * which will cause zaptel to ignore the 2100 Hz echo cancel disable - * tone. - */ -/* #define NO_ECHOCAN_DISABLE */ - -/* udev support */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,1) -#define CONFIG_ZAP_UDEV -#endif - -/* We now use the linux kernel config to detect which options to use */ -/* You can still override them below */ -#if defined(CONFIG_HDLC) || defined(CONFIG_HDLC_MODULE) -/* #define CONFIG_ZAPATA_NET */ /* NEVER implicitly turn on ZAPATA_NET */ -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,20) -#define CONFIG_OLD_HDLC_API -#else -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,23) -/* Starting with 2.4.23 the kernel hdlc api changed again */ -/* Now we have to use hdlc_type_trans(skb, dev) instead of htons(ETH_P_HDLC) */ -#define ZAP_HDLC_TYPE_TRANS -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3) -#define HDLC_MAINTAINERS_ARE_MORE_STUPID_THAN_I_THOUGHT -#endif -#endif -#endif -#ifdef CONFIG_PPP -#define CONFIG_ZAPATA_PPP -#endif - -/* - * Uncomment CONFIG_ZAPATA_NET to enable SyncPPP, CiscoHDLC, and Frame Relay - * support. - */ -/* #define CONFIG_ZAPATA_NET */ - -/* - * Uncomment CONFIG_OLD_HDLC_API if your are compiling with ZAPATA_NET - * defined and you are using the old kernel HDLC interface (or if you get - * an error about ETH_P_HDLC while compiling). - */ -/* #define CONFIG_OLD_HDLC_API */ - -/* - * Uncomment for Generic PPP support (i.e. ZapRAS) - */ -/* #define CONFIG_ZAPATA_PPP */ -/* - * Uncomment to enable "watchdog" to monitor if interfaces - * stop taking interrupts or otherwise misbehave - */ -/* #define CONFIG_ZAPTEL_WATCHDOG */ - -/* - * Uncomment for Non-standard FXS groundstart start state (A=Low, B=Low) - * particularly for CAC channel bank groundstart FXO ports. - */ -/* #define CONFIG_CAC_GROUNDSTART */ - -/* - * Uncomment if you happen have an early TDM400P Rev H which - * sometimes forgets its PCI ID to have wcfxs match essentially all - * subvendor ID's - */ -/* #define TDM_REVH_MATCHALL */ - -/* - * Uncomment the following if you want to support E&M trunks being - * able to "flash" after going off-hook (dont ask why, just nod :-) ). - * - * NOTE: *DO NOT* Enable "EMFLASH" and "EMPULSE" at the same time!! - * - */ -/* #define EMFLASH */ - -/* - * Uncomment the following if you want to support E&M trunks being - * able to recognize Dial Pulse digits. This can validly be enabled - * so that either Dial Pulse or DTMF/MF tones will be recognized, but - * the drawback is that the ONHOOK will take an extra {rxwinktime} - * to be recognized. - * - * NOTE: *DO NOT* Enable "EMFLASH" and "EMPULSE" at the same time!! - * - */ -/* #define EMPULSE */ - -/* - * Comment out the following if you dont want events to indicate the - * beginning of an incoming ring. Most non-Asterisk applications will - * want this commented out. - */ -#define RINGBEGIN - -/* - * Uncomment the following if you need to support FXS Flash events. - * Most applications will want this commented out. - */ -/* #define FXSFLASH */ - -/* - * Enable sync_tick() calls. Allows low-level drivers to synchronize - * their internal clocks to the zaptel master clock. - */ -#define ZAPTEL_SYNC_TICK - -/* - * Skip processing PCM if low-level driver won't use it anyway - */ -/* #define OPTIMIZE_CHANMUTE */ - -#endif diff --git a/ztcfg-dude.c b/ztcfg-dude.c index f1027f4..8f655ee 100644 --- a/ztcfg-dude.c +++ b/ztcfg-dude.c @@ -39,7 +39,7 @@ #include #include #ifdef STANDALONE_ZAPATA -#include "zaptel.h" +#include "kernel/zaptel.h" #include "tonezone.h" #else #include diff --git a/ztcfg.c b/ztcfg.c index 2d94be3..99c4df3 100644 --- a/ztcfg.c +++ b/ztcfg.c @@ -38,7 +38,7 @@ #include #include #ifdef STANDALONE_ZAPATA -#include "zaptel.h" +#include "kernel/zaptel.h" #include "tonezone.h" #else #include diff --git a/ztd-eth.c b/ztd-eth.c deleted file mode 100644 index 97d3492..0000000 --- a/ztd-eth.c +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Dynamic Span Interface for Zaptel (Ethernet Interface) - * - * Written by Mark Spencer - * - * Copyright (C) 2001, Linux Support Services, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_DEVFS_FS -#include -#endif -#ifdef STANDALONE_ZAPATA -#include "zaptel.h" -#else -#include -#endif - -#define ETH_P_ZTDETH 0xd00d - -struct ztdeth_header { - unsigned short subaddr; -}; - -/* We take the raw message, put it in an ethernet frame, and add a - two byte addressing header at the top for future use */ -#ifdef DEFINE_SPINLOCK -static DEFINE_SPINLOCK(zlock); -#else -static spinlock_t zlock = SPIN_LOCK_UNLOCKED; -#endif - -static struct sk_buff_head skbs; - -static struct ztdeth { - unsigned char addr[ETH_ALEN]; - unsigned short subaddr; /* Network byte order */ - struct zt_span *span; - char ethdev[IFNAMSIZ]; - struct net_device *dev; - struct ztdeth *next; -} *zdevs = NULL; - -struct zt_span *ztdeth_getspan(unsigned char *addr, unsigned short subaddr) -{ - unsigned long flags; - struct ztdeth *z; - struct zt_span *span = NULL; - spin_lock_irqsave(&zlock, flags); - z = zdevs; - while(z) { - if (!memcmp(addr, z->addr, ETH_ALEN) && - z->subaddr == subaddr) - break; - z = z->next; - } - if (z) - span = z->span; - spin_unlock_irqrestore(&zlock, flags); - return span; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) -static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) -#else -static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) -#endif -{ - struct zt_span *span; - struct ztdeth_header *zh; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) - zh = (struct ztdeth_header *)skb_network_header(skb); -#else - zh = (struct ztdeth_header *)skb->nh.raw; -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9) - span = ztdeth_getspan(eth_hdr(skb)->h_source, zh->subaddr); -#else - span = ztdeth_getspan(skb->mac.ethernet->h_source, zh->subaddr); -#endif - if (span) { - skb_pull(skb, sizeof(struct ztdeth_header)); - zt_dynamic_receive(span, (unsigned char *)skb->data, skb->len); - } - kfree_skb(skb); - return 0; -} - -static int ztdeth_notifier(struct notifier_block *block, unsigned long event, void *ptr) -{ - struct net_device *dev = ptr; - struct ztdeth *z; - unsigned long flags; - switch(event) { - case NETDEV_GOING_DOWN: - case NETDEV_DOWN: - spin_lock_irqsave(&zlock, flags); - z = zdevs; - while(z) { - /* Note that the device no longer exists */ - if (z->dev == dev) - z->dev = NULL; - z = z->next; - } - spin_unlock_irqrestore(&zlock, flags); - break; - case NETDEV_UP: - spin_lock_irqsave(&zlock, flags); - z = zdevs; - while(z) { - /* Now that the device exists again, use it */ - if (!strcmp(z->ethdev, dev->name)) - z->dev = dev; - z = z->next; - } - spin_unlock_irqrestore(&zlock, flags); - break; - } - return 0; -} - -static int ztdeth_transmit(void *pvt, unsigned char *msg, int msglen) -{ - struct ztdeth *z; - struct sk_buff *skb; - struct ztdeth_header *zh; - unsigned long flags; - struct net_device *dev; - unsigned char addr[ETH_ALEN]; - unsigned short subaddr; /* Network byte order */ - - spin_lock_irqsave(&zlock, flags); - z = pvt; - if (z->dev) { - /* Copy fields to local variables to remove spinlock ASAP */ - dev = z->dev; - memcpy(addr, z->addr, sizeof(z->addr)); - subaddr = z->subaddr; - spin_unlock_irqrestore(&zlock, flags); - skb = dev_alloc_skb(msglen + dev->hard_header_len + sizeof(struct ztdeth_header) + 32); - if (skb) { - /* Reserve header space */ - skb_reserve(skb, dev->hard_header_len + sizeof(struct ztdeth_header)); - - /* Copy message body */ - memcpy(skb_put(skb, msglen), msg, msglen); - - /* Throw on header */ - zh = (struct ztdeth_header *)skb_push(skb, sizeof(struct ztdeth_header)); - zh->subaddr = subaddr; - - /* Setup protocol and such */ - skb->protocol = __constant_htons(ETH_P_ZTDETH); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) - skb_set_network_header(skb, 0); -#else - skb->nh.raw = skb->data; -#endif - skb->dev = dev; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) - dev_hard_header(skb, dev, ETH_P_ZTDETH, addr, dev->dev_addr, skb->len); -#else - if (dev->hard_header) - dev->hard_header(skb, dev, ETH_P_ZTDETH, addr, dev->dev_addr, skb->len); -#endif - skb_queue_tail(&skbs, skb); - } - } - else - spin_unlock_irqrestore(&zlock, flags); - return 0; -} - - -static int ztdeth_flush(void) -{ - struct sk_buff *skb; - - /* Handle all transmissions now */ - while ((skb = skb_dequeue(&skbs))) { - dev_queue_xmit(skb); - } - return 0; -} - -static struct packet_type ztdeth_ptype = { - type: __constant_htons(ETH_P_ZTDETH), /* Protocol */ - dev: NULL, /* Device (NULL = wildcard) */ - func: ztdeth_rcv, /* Receiver */ -}; - -static int digit2int(char d) -{ - switch(d) { - case 'F': - case 'E': - case 'D': - case 'C': - case 'B': - case 'A': - return d - 'A' + 10; - case 'f': - case 'e': - case 'd': - case 'c': - case 'b': - case 'a': - return d - 'a' + 10; - case '9': - case '8': - case '7': - case '6': - case '5': - case '4': - case '3': - case '2': - case '1': - case '0': - return d - '0'; - } - return -1; -} - -static int hex2int(char *s) -{ - int res; - int tmp; - /* Gotta be at least one digit */ - if (strlen(s) < 1) - return -1; - /* Can't be more than two */ - if (strlen(s) > 2) - return -1; - /* Grab the first digit */ - res = digit2int(s[0]); - if (res < 0) - return -1; - tmp = res; - /* Grab the next */ - if (strlen(s) > 1) { - res = digit2int(s[1]); - if (res < 0) - return -1; - tmp = tmp * 16 + res; - } - return tmp; -} - -static void ztdeth_destroy(void *pvt) -{ - struct ztdeth *z = pvt; - unsigned long flags; - struct ztdeth *prev=NULL, *cur; - spin_lock_irqsave(&zlock, flags); - cur = zdevs; - while(cur) { - if (cur == z) { - if (prev) - prev->next = cur->next; - else - zdevs = cur->next; - break; - } - prev = cur; - cur = cur->next; - } - spin_unlock_irqrestore(&zlock, flags); - if (cur == z) { /* Successfully removed */ - printk("TDMoE: Removed interface for %s\n", z->span->name); - kfree(z); -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#else - module_put(THIS_MODULE); -#endif - } -} - -static void *ztdeth_create(struct zt_span *span, char *addr) -{ - struct ztdeth *z; - char src[256]; - char tmp[256], *tmp2, *tmp3, *tmp4 = NULL; - int res,x; - unsigned long flags; - - z = kmalloc(sizeof(struct ztdeth), GFP_KERNEL); - if (z) { - /* Zero it out */ - memset(z, 0, sizeof(struct ztdeth)); - - /* Address should be /[/subaddr] */ - strncpy(tmp, addr, sizeof(tmp) - 1); - tmp2 = strchr(tmp, '/'); - if (tmp2) { - *tmp2 = '\0'; - tmp2++; - strncpy(z->ethdev, tmp, sizeof(z->ethdev) - 1); - } else { - printk("Invalid TDMoE address (no device) '%s'\n", addr); - kfree(z); - return NULL; - } - if (tmp2) { - tmp4 = strchr(tmp2+1, '/'); - if (tmp4) { - *tmp4 = '\0'; - tmp4++; - } - /* We don't have SSCANF :( Gotta do this the hard way */ - tmp3 = strchr(tmp2, ':'); - for (x=0;x<6;x++) { - if (tmp2) { - if (tmp3) { - *tmp3 = '\0'; - tmp3++; - } - res = hex2int(tmp2); - if (res < 0) - break; - z->addr[x] = res & 0xff; - } else - break; - if ((tmp2 = tmp3)) - tmp3 = strchr(tmp2, ':'); - } - if (x != 6) { - printk("TDMoE: Invalid MAC address in: %s\n", addr); - kfree(z); - return NULL; - } - } else { - printk("TDMoE: Missing MAC address\n"); - kfree(z); - return NULL; - } - if (tmp4) { - int sub = 0; - int mul = 1; - - /* We have a subaddr */ - tmp3 = tmp4 + strlen (tmp4) - 1; - while (tmp3 >= tmp4) { - if (*tmp3 >= '0' && *tmp3 <= '9') { - sub += (*tmp3 - '0') * mul; - } else { - printk("TDMoE: Invalid subaddress\n"); - kfree(z); - return NULL; - } - mul *= 10; - tmp3--; - } - z->subaddr = htons(sub); - } - z->dev = dev_get_by_name( -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) - &init_net, -#endif - z->ethdev); - if (!z->dev) { - printk("TDMoE: Invalid device '%s'\n", z->ethdev); - kfree(z); - return NULL; - } - z->span = span; - src[0] ='\0'; - for (x=0;x<5;x++) - sprintf(src + strlen(src), "%02x:", z->dev->dev_addr[x]); - sprintf(src + strlen(src), "%02x", z->dev->dev_addr[5]); - printk("TDMoE: Added new interface for %s at %s (addr=%s, src=%s, subaddr=%d)\n", span->name, z->dev->name, addr, src, ntohs(z->subaddr)); - - spin_lock_irqsave(&zlock, flags); - z->next = zdevs; - zdevs = z; - spin_unlock_irqrestore(&zlock, flags); -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#else - if(!try_module_get(THIS_MODULE)) - printk("TDMoE: Unable to increment module use count\n"); -#endif - } - return z; -} - -static struct zt_dynamic_driver ztd_eth = { - "eth", - "Ethernet", - ztdeth_create, - ztdeth_destroy, - ztdeth_transmit, - ztdeth_flush -}; - -static struct notifier_block ztdeth_nblock = { - notifier_call: ztdeth_notifier, -}; - -static int __init ztdeth_init(void) -{ - dev_add_pack(&ztdeth_ptype); - register_netdevice_notifier(&ztdeth_nblock); - zt_dynamic_register(&ztd_eth); - - skb_queue_head_init(&skbs); - - return 0; -} - -static void __exit ztdeth_exit(void) -{ - dev_remove_pack(&ztdeth_ptype); - unregister_netdevice_notifier(&ztdeth_nblock); - zt_dynamic_unregister(&ztd_eth); -} - -MODULE_DESCRIPTION("Zaptel Dynamic TDMoE Support"); -MODULE_AUTHOR("Mark Spencer "); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif - -module_init(ztdeth_init); -module_exit(ztdeth_exit); diff --git a/ztd-loc.c b/ztd-loc.c deleted file mode 100644 index 6486a2a..0000000 --- a/ztd-loc.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Dynamic Span Interface for Zaptel (Local Interface) - * - * Written by Nicolas Bougues - * - * Copyright (C) 2004, Axialys Interactive - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - * Note : a zaptel source must exist prior to loading this driver - * - * Address syntax : - * :[:] - * - * As of now, keys and ids are single digit only - * - * One span may have up to one "normal" peer, and one "monitor" peer - * - * Example : - * - * Say you have two spans cross connected, a thrid one monitoring RX on the - * first one, a fourth one monitoring RX on the second one - * - * 1:0 - * 1:1 - * 1:2:0 - * 1:3:1 - * - * Contrary to TDMoE, no frame loss can occur. - * - * See bug #2021 for more details - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_DEVFS_FS -#include -#endif -#ifdef STANDALONE_ZAPATA -#include "zaptel.h" -#else -#include -#endif - -#ifdef DEFINE_SPINLOCK -static DEFINE_SPINLOCK(zlock); -#else -static spinlock_t zlock = SPIN_LOCK_UNLOCKED; -#endif - -static struct ztdlocal { - unsigned short key; - unsigned short id; - struct ztdlocal *monitor_rx_peer; /* Indicates the peer span that monitors this span */ - struct ztdlocal *peer; /* Indicates the rw peer for this span */ - struct zt_span *span; - struct ztdlocal *next; -} *zdevs = NULL; - -/*static*/ int ztdlocal_transmit(void *pvt, unsigned char *msg, int msglen) -{ - struct ztdlocal *z; - unsigned long flags; - - spin_lock_irqsave(&zlock, flags); - z = pvt; - if (z->peer && z->peer->span) { - zt_dynamic_receive(z->peer->span, msg, msglen); - } - if (z->monitor_rx_peer && z->monitor_rx_peer->span) { - zt_dynamic_receive(z->monitor_rx_peer->span, msg, msglen); - } - spin_unlock_irqrestore(&zlock, flags); - return 0; -} - -static int digit2int(char d) -{ - switch(d) { - case 'F': - case 'E': - case 'D': - case 'C': - case 'B': - case 'A': - return d - 'A' + 10; - case 'f': - case 'e': - case 'd': - case 'c': - case 'b': - case 'a': - return d - 'a' + 10; - case '9': - case '8': - case '7': - case '6': - case '5': - case '4': - case '3': - case '2': - case '1': - case '0': - return d - '0'; - } - return -1; -} - -/*static*/ void ztdlocal_destroy(void *pvt) -{ - struct ztdlocal *z = pvt; - unsigned long flags; - struct ztdlocal *prev=NULL, *cur; - - spin_lock_irqsave(&zlock, flags); - cur = zdevs; - while(cur) { - if (cur->peer == z) - cur->peer = NULL; - if (cur->monitor_rx_peer == z) - cur->monitor_rx_peer = NULL; - cur = cur->next; - } - cur = zdevs; - while(cur) { - if (cur == z) { - if (prev) - prev->next = cur->next; - else - zdevs = cur->next; - break; - } - prev = cur; - cur = cur->next; - } - spin_unlock_irqrestore(&zlock, flags); - if (cur == z) { - printk("TDMoL: Removed interface for %s, key %d id %d\n", z->span->name, z->key, z->id); -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#else - module_put(THIS_MODULE); -#endif - kfree(z); - } -} - -/*static*/ void *ztdlocal_create(struct zt_span *span, char *address) -{ - struct ztdlocal *z, *l; - unsigned long flags; - int key = -1, id = -1, monitor = -1; - - if (strlen(address) >= 3) { - if (address[1] != ':') - goto INVALID_ADDRESS; - key = digit2int(address[0]); - id = digit2int(address[2]); - } - if (strlen (address) == 5) { - if (address[3] != ':') - goto INVALID_ADDRESS; - monitor = digit2int(address[4]); - } - - if (key == -1 || id == -1) - goto INVALID_ADDRESS; - - z = kmalloc(sizeof(struct ztdlocal), GFP_KERNEL); - if (z) { - /* Zero it out */ - memset(z, 0, sizeof(struct ztdlocal)); - - z->key = key; - z->id = id; - z->span = span; - - spin_lock_irqsave(&zlock, flags); - /* Add this peer to any existing spans with same key - And add them as peers to this one */ - for (l = zdevs; l; l = l->next) - if (l->key == z->key) { - if (l->id == z->id) { - printk ("TDMoL: Duplicate id (%d) for key %d\n", z->id, z->key); - goto CLEAR_AND_DEL_FROM_PEERS; - } - if (monitor == -1) { - if (l->peer) { - printk ("TDMoL: Span with key %d and id %d already has a R/W peer\n", z->key, z->id); - goto CLEAR_AND_DEL_FROM_PEERS; - } else { - l->peer = z; - z->peer = l; - } - } - if (monitor == l->id) { - if (l->monitor_rx_peer) { - printk ("TDMoL: Span with key %d and id %d already has a monitoring peer\n", z->key, z->id); - goto CLEAR_AND_DEL_FROM_PEERS; - } else { - l->monitor_rx_peer = z; - } - } - } - z->next = zdevs; - zdevs = z; - spin_unlock_irqrestore(&zlock, flags); -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#else - if(!try_module_get(THIS_MODULE)) - printk("TDMoL: Unable to increment module use count\n"); -#endif - - printk("TDMoL: Added new interface for %s, key %d id %d\n", span->name, z->key, z->id); - } - return z; - -CLEAR_AND_DEL_FROM_PEERS: - for (l = zdevs; l; l = l->next) { - if (l->peer == z) - l->peer = NULL; - if (l->monitor_rx_peer == z) - l->monitor_rx_peer = NULL; - } - kfree (z); - return NULL; - -INVALID_ADDRESS: - printk ("TDMoL: Invalid address %s\n", address); - return NULL; -} - -static struct zt_dynamic_driver ztd_local = { - "loc", - "Local", - ztdlocal_create, - ztdlocal_destroy, - ztdlocal_transmit, - NULL /* flush */ -}; - -/*static*/ int __init ztdlocal_init(void) -{ - zt_dynamic_register(&ztd_local); - return 0; -} - -/*static*/ void __exit ztdlocal_exit(void) -{ - zt_dynamic_unregister(&ztd_local); -} - -module_init(ztdlocal_init); -module_exit(ztdlocal_exit); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif diff --git a/ztdiag.c b/ztdiag.c index 1472760..50900a8 100644 --- a/ztdiag.c +++ b/ztdiag.c @@ -5,7 +5,7 @@ #include #ifdef STANDALONE_ZAPATA -#include "zaptel.h" +#include "kernel/zaptel.h" #else #include #endif diff --git a/ztdummy.c b/ztdummy.c deleted file mode 100644 index 5cedaa3..0000000 --- a/ztdummy.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Dummy Zaptel Driver for Zapata Telephony interface - * - * Required: usb-uhci module and kernel > 2.4.4 OR kernel > 2.6.0 - * - * Written by Robert Pleh - * 2.6 version by Tony Hoyle - * Unified by Mark Spencer - * Converted to use RTC on i386 by Tony Mountifield - * - * Converted to use HighResTimers on i386 by Jeffery Palmer - * - * Copyright (C) 2002, Hermes Softlab - * Copyright (C) 2004, Digium, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* - * To use the high resolution timers, in your kernel CONFIG_HIGH_RES_TIMERS - * needs to be enabled (Processor type and features -> High Resolution - * Timer Support), and optionally HPET (Processor type and features -> - * HPET Timer Support) provides a better clock source. - */ - -#include - -#ifndef VERSION_CODE -# define VERSION_CODE(vers,rel,seq) ( ((vers)<<16) | ((rel)<<8) | (seq) ) -#endif - - -#if LINUX_VERSION_CODE < VERSION_CODE(2,4,5) -# error "This kernel is too old: not supported by this file" -#endif - -/* - * NOTE: (only applies to kernel 2.6) - * If using an i386 architecture without a PC real-time clock, - * the #define USE_RTC should be commented out. - */ -#if defined(__i386__) || defined(__x86_64__) -#if LINUX_VERSION_CODE >= VERSION_CODE(2,6,13) -/* The symbol hrtimer_forward is only exported as of 2.6.22: */ -#if defined(CONFIG_HIGH_RES_TIMERS) && LINUX_VERSION_CODE >= VERSION_CODE(2,6,22) -#define USE_HIGHRESTIMER -#else -#define USE_RTC -#endif -#else -#if 0 -#define USE_RTC -#endif -#endif -#endif - -#include -#include -#include -#include -#include -#include "zaptel.h" -#ifndef LINUX26 -#include -#include -#include -#endif -#ifdef LINUX26 -#ifdef USE_HIGHRESTIMER -#include -#endif -#ifdef USE_RTC -#include -#endif -#include -#endif -#include "ztdummy.h" - - -static struct ztdummy *ztd; - -static int debug = 0; - -#ifdef LINUX26 -#ifdef USE_HIGHRESTIMER -#define CLOCK_SRC "HRtimer" -struct hrtimer zaptimer; -#elif defined(USE_RTC) -#define CLOCK_SRC "RTC" -static int rtc_rate = 0; -static int current_rate = 0; -static int taskletpending = 0; -static struct tasklet_struct ztd_tlet; -static void ztd_tasklet(unsigned long data); -#else /* Linux 2.6, but no RTC or HRTIMER used */ -#define CLOCK_SRC "Linux26" -/* 2.6 kernel timer stuff */ -static struct timer_list timer; -#endif -#else -#if LINUX_VERSION_CODE < VERSION_CODE(2,4,5) -# error "This kernel is too old: not supported by this file" -#endif -#define CLOCK_SRC "UHCI" -/* Old UCHI stuff */ -static uhci_desc_t *td; -static uhci_t *s; -static int monitor = 0; - -/* exported kernel symbols */ -extern int insert_td (uhci_t *s, uhci_desc_t *qh, uhci_desc_t* new, int flags); -extern int alloc_td (uhci_t *s, uhci_desc_t ** new, int flags); -extern int insert_td_horizontal (uhci_t *s, uhci_desc_t *td, uhci_desc_t* new); -extern int unlink_td (uhci_t *s, uhci_desc_t *element, int phys_unlink); -extern void fill_td (uhci_desc_t *td, int status, int info, __u32 buffer); -extern void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs); -extern int delete_desc (uhci_t *s, uhci_desc_t *element); -extern uhci_t **uhci_devices; - -#endif - - -#define ZAPTEL_RATE 1000 /* zaptel ticks per second */ -#define ZAPTEL_TIME (1000000 / ZAPTEL_RATE) /* zaptel tick time in us */ -#define ZAPTEL_TIME_NS (ZAPTEL_TIME * 1000) /* zaptel tick time in ns */ - -/* Different bits of the debug variable: */ -#define DEBUG_GENERAL (1 << 0) -#define DEBUG_TICKS (1 << 1) - - -#ifdef LINUX26 -#ifdef USE_RTC -static void update_rtc_rate(struct ztdummy *ztd) -{ - if (((rtc_rate & (rtc_rate - 1)) != 0) || (rtc_rate > 8192) || (rtc_rate < 2)) { - printk(KERN_NOTICE "Invalid RTC rate %d specified\n", rtc_rate); - rtc_rate = current_rate; /* Set default RTC rate */ - } - if (!rtc_rate || (rtc_rate != current_rate)) { - rtc_control(&ztd->rtc_task, RTC_IRQP_SET, current_rate = (rtc_rate ? rtc_rate : 1024)); /* 1024 Hz */ - printk(KERN_INFO "ztdummy: RTC rate is %d\n", rtc_rate); - ztd->counter = 0; - } -} - -static void ztd_tasklet(unsigned long data) -{ - if (taskletpending) - update_rtc_rate((struct ztdummy *)ztd); - taskletpending = 0; -} - -/* rtc_interrupt - called at 1024Hz from hook in RTC handler */ -static void ztdummy_rtc_interrupt(void *private_data) -{ - struct ztdummy *ztd = private_data; - unsigned long flags; - - /* Is spinlock required here??? */ - spin_lock_irqsave(&ztd->rtclock, flags); - ztd->counter += ZAPTEL_TIME; - while (ztd->counter >= current_rate) { - ztd->counter -= current_rate; - /* Update of RTC IRQ rate isn't possible from interrupt handler :( */ - if (!taskletpending && (current_rate != rtc_rate)) { - taskletpending = 1; - tasklet_hi_schedule(&ztd_tlet); - } - zt_receive(&ztd->span); - zt_transmit(&ztd->span); - } - spin_unlock_irqrestore(&ztd->rtclock, flags); -} -#elif defined(USE_HIGHRESTIMER) -static enum hrtimer_restart ztdummy_hr_int(struct hrtimer *htmr) -{ - unsigned long overrun; - - /* Trigger Zaptel */ - zt_receive(&ztd->span); - zt_transmit(&ztd->span); - - /* Overrun should always return 1, since we are in the timer that - * expired. - * We should worry if overrun is 2 or more; then we really missed - * a tick */ - overrun = hrtimer_forward(&zaptimer, htmr->expires, - ktime_set(0, ZAPTEL_TIME_NS)); - if(overrun > 1) { - if(printk_ratelimit()) - printk(KERN_NOTICE "ztdummy: HRTimer missed %lu ticks\n", - overrun - 1); - } - - if(debug && DEBUG_TICKS) { - static int count = 0; - /* Printk every 5 seconds, good test to see if timer is - * running properly */ - if (count++ % 5000 == 0) - printk(KERN_DEBUG "ztdummy: 5000 ticks from hrtimer\n"); - } - - /* Always restart the timer */ - return HRTIMER_RESTART; -} -#else -/* use kernel system tick timer if PC architecture RTC is not available */ -static void ztdummy_timer(unsigned long param) -{ - timer.expires = jiffies + 1; - add_timer(&timer); - - ztd->counter += ZAPTEL_TIME; - while (ztd->counter >= HZ) { - ztd->counter -= HZ; - zt_receive(&ztd->span); - zt_transmit(&ztd->span); - } -} -#endif -#else -static void ztdummy_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned short status; - unsigned int io_addr = s->io_addr; - - status = inw (io_addr + USBSTS); - if (status != 0) { /* interrupt from our USB port */ - static int check_int = 0; - zt_receive(&ztd->span); - zt_transmit(&ztd->span); - /* TODO: What's the relation between monitor and - * DEBUG_TICKS */ - if (monitor && check_int) { - check_int = 1; - printk(KERN_NOTICE "ztdummy: interrupt triggered \n"); - } - } - return; -} -#endif - -static int ztdummy_initialize(struct ztdummy *ztd) -{ - /* Zapata stuff */ - sprintf(ztd->span.name, "ZTDUMMY/1"); - snprintf(ztd->span.desc, sizeof(ztd->span.desc) - 1, "%s (source: " CLOCK_SRC ") %d", ztd->span.name, 1); - sprintf(ztd->chan.name, "ZTDUMMY/%d/%d", 1, 0); - strncpy(ztd->span.devicetype, "Zaptel Dummy Timing Driver", sizeof(ztd->span.devicetype) - 1); - ztd->chan.chanpos = 1; - ztd->span.chans = &ztd->chan; - ztd->span.channels = 0; /* no channels on our span */ - ztd->span.deflaw = ZT_LAW_MULAW; - init_waitqueue_head(&ztd->span.maintq); - ztd->span.pvt = ztd; - ztd->chan.pvt = ztd; - if (zt_register(&ztd->span, 0)) { - return -1; - } - return 0; -} - -int init_module(void) -{ -#ifdef LINUX26 -#ifdef USE_RTC - int err; -#endif -#else - int irq; -#ifdef DEFINE_SPINLOCK - DEFINE_SPINLOCK(mylock); -#else - spinlock_t mylock = SPIN_LOCK_UNLOCKED; -#endif - - if (uhci_devices==NULL) { - printk (KERN_ERR "ztdummy: Uhci_devices pointer error.\n"); - return -ENODEV; - } - s=*uhci_devices; /* uhci device */ - if (s==NULL) { - printk (KERN_ERR "ztdummy: No uhci_device found.\n"); - return -ENODEV; - } -#endif - - ztd = kmalloc(sizeof(struct ztdummy), GFP_KERNEL); - if (ztd == NULL) { - printk(KERN_ERR "ztdummy: Unable to allocate memory\n"); - return -ENOMEM; - } - - memset(ztd, 0x0, sizeof(struct ztdummy)); - - if (ztdummy_initialize(ztd)) { - printk(KERN_ERR "ztdummy: Unable to intialize zaptel driver\n"); - kfree(ztd); - return -ENODEV; - } - -#ifdef LINUX26 - ztd->counter = 0; -#ifdef USE_RTC - ztd->rtclock = SPIN_LOCK_UNLOCKED; - ztd->rtc_task.func = ztdummy_rtc_interrupt; - ztd->rtc_task.private_data = ztd; - err = rtc_register(&ztd->rtc_task); - if (err < 0) { - printk(KERN_ERR "ztdummy: Unable to register zaptel rtc driver\n"); - zt_unregister(&ztd->span); - kfree(ztd); - return err; - } - /* Set default RTC interrupt rate to 1024Hz */ - if (!rtc_rate) - rtc_rate = 1024; - update_rtc_rate(ztd); - rtc_control(&ztd->rtc_task, RTC_PIE_ON, 0); - tasklet_init(&ztd_tlet, ztd_tasklet, 0); -#elif defined(USE_HIGHRESTIMER) - printk(KERN_DEBUG "ztdummy: Trying to load High Resolution Timer\n"); - hrtimer_init(&zaptimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - printk(KERN_DEBUG "ztdummy: Initialized High Resolution Timer\n"); - - /* Set timer callback function */ - zaptimer.function = ztdummy_hr_int; - - printk(KERN_DEBUG "ztdummy: Starting High Resolution Timer\n"); - hrtimer_start(&zaptimer, ktime_set(0, ZAPTEL_TIME_NS), HRTIMER_MODE_REL); - printk(KERN_INFO "ztdummy: High Resolution Timer started, good to go\n"); -#else - init_timer(&timer); - timer.function = ztdummy_timer; - timer.expires = jiffies + 1; - add_timer(&timer); -#endif -#else - irq=s->irq; - spin_lock_irq(&mylock); - free_irq(s->irq, s); /* remove uhci_interrupt temporaly */ - if (request_irq (irq, ztdummy_interrupt, ZAP_IRQ_SHARED, "ztdummy", ztd)) { - spin_unlock_irq(&mylock); - err("Our request_irq %d failed!",irq); - kfree(ztd); - return -EIO; - } /* we add our handler first, to assure, that our handler gets called first */ - if (request_irq (irq, uhci_interrupt, ZAP_IRQ_SHARED, s->uhci_pci->driver->name, s)) { - spin_unlock_irq(&mylock); - err("Original request_irq %d failed!",irq); - } - spin_unlock_irq(&mylock); - - /* add td to usb host controller interrupt queue */ - alloc_td(s, &td, 0); - fill_td(td, TD_CTRL_IOC, 0, 0); - insert_td_horizontal(s, s->int_chain[0], td); /* use int_chain[0] to get 1ms interrupts */ -#endif - - if (debug) - printk(KERN_DEBUG "ztdummy: init() finished\n"); - return 0; -} - - -void cleanup_module(void) -{ -#ifdef LINUX26 -#ifdef USE_RTC - if (taskletpending) { - tasklet_disable(&ztd_tlet); - tasklet_kill(&ztd_tlet); - } - rtc_control(&ztd->rtc_task, RTC_PIE_OFF, 0); - rtc_unregister(&ztd->rtc_task); -#elif defined(USE_HIGHRESTIMER) - /* Stop high resolution timer */ - hrtimer_cancel(&zaptimer); -#else - del_timer(&timer); -#endif -#else - free_irq(s->irq, ztd); /* disable interrupts */ -#endif - zt_unregister(&ztd->span); - kfree(ztd); -#ifndef LINUX26 - unlink_td(s, td, 1); - delete_desc(s, td); -#endif - if (debug) - printk("ztdummy: cleanup() finished\n"); -} - - - -#ifdef LINUX26 -module_param(debug, int, 0600); -#ifdef USE_RTC -module_param(rtc_rate, int, 0600); -#endif -#else -MODULE_PARM(debug, "i"); -#endif - -#ifndef LINUX26 -MODULE_PARM(monitor, "i"); -#endif -MODULE_DESCRIPTION("Dummy Zaptel Driver"); -MODULE_AUTHOR("Robert Pleh "); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif diff --git a/ztdummy.h b/ztdummy.h deleted file mode 100644 index 25e37c9..0000000 --- a/ztdummy.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Dummy Zaptel Driver for Zapata Telephony interface - * - * Written by Robert Pleh - * - * Copyright (C) 2002, Hermes Softlab - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -*/ - -#include -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19) -#define USB2420 -#endif - -struct ztdummy { - struct zt_span span; - struct zt_chan chan; -#ifdef LINUX26 - unsigned int counter; -#ifdef USE_RTC - spinlock_t rtclock; - rtc_task_t rtc_task; -#endif -#endif -}; - - -#ifndef LINUX26 -/* Uhci definitions and structures - from file usb-uhci.h */ -#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ -#define USBSTS 2 - -typedef enum { - TD_TYPE, QH_TYPE -} uhci_desc_type_t; - -typedef struct { - __u32 link; - __u32 status; - __u32 info; - __u32 buffer; -} uhci_td_t, *puhci_td_t; - - -typedef struct { - __u32 head; - __u32 element; /* Queue element pointer */ -} uhci_qh_t, *puhci_qh_t; - -typedef struct { - union { - uhci_td_t td; - uhci_qh_t qh; - } hw; - uhci_desc_type_t type; - dma_addr_t dma_addr; - struct list_head horizontal; - struct list_head vertical; - struct list_head desc_list; - int last_used; -} uhci_desc_t, *puhci_desc_t; - -typedef struct { - struct list_head desc_list; // list pointer to all corresponding TDs/QHs associated with this request - dma_addr_t setup_packet_dma; - dma_addr_t transfer_buffer_dma; - unsigned long started; -#ifdef USB2420 - struct urb *next_queued_urb; // next queued urb for this EP - struct urb *prev_queued_urb; -#else - urb_t *next_queued_urb; - urb_t *prev_queued_urb; -#endif - uhci_desc_t *bottom_qh; - uhci_desc_t *next_qh; // next helper QH - char use_loop; - char flags; -} urb_priv_t, *purb_priv_t; - -struct virt_root_hub { - int devnum; /* Address of Root Hub endpoint */ - void *urb; - void *int_addr; - int send; - int interval; - int numports; - int c_p_r[8]; - struct timer_list rh_int_timer; -}; - -typedef struct uhci { - int irq; - unsigned int io_addr; - unsigned int io_size; - unsigned int maxports; - int running; - - int apm_state; - - struct uhci *next; // chain of uhci device contexts - - struct list_head urb_list; // list of all pending urbs - - spinlock_t urb_list_lock; // lock to keep consistency - - int unlink_urb_done; - atomic_t avoid_bulk; - - struct usb_bus *bus; // our bus - - __u32 *framelist; - dma_addr_t framelist_dma; - uhci_desc_t **iso_td; - uhci_desc_t *int_chain[8]; - uhci_desc_t *ls_control_chain; - uhci_desc_t *control_chain; - uhci_desc_t *bulk_chain; - uhci_desc_t *chain_end; - uhci_desc_t *td1ms; - uhci_desc_t *td32ms; - struct list_head free_desc; - spinlock_t qh_lock; - spinlock_t td_lock; - struct virt_root_hub rh; //private data of the virtual root hub - int loop_usage; // URBs using bandwidth reclamation - - struct list_head urb_unlinked; // list of all unlinked urbs - long timeout_check; - int timeout_urbs; - struct pci_dev *uhci_pci; - struct pci_pool *desc_pool; - long last_error_time; // last error output in uhci_interrupt() -} uhci_t, *puhci_t; -#endif diff --git a/ztdynamic.c b/ztdynamic.c deleted file mode 100644 index 01b22e2..0000000 --- a/ztdynamic.c +++ /dev/null @@ -1,870 +0,0 @@ -/* - * Dynamic Span Interface for Zaptel - * - * Written by Mark Spencer - * - * Copyright (C) 2001, Linux Support Services, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_DEVFS_FS -#include -#endif -#ifdef STANDALONE_ZAPATA -#include "zaptel.h" -#else -#include -#endif -#ifdef LINUX26 -#include -#endif - -/* - * Tasklets provide better system interactive response at the cost of the - * possibility of losing a frame of data at very infrequent intervals. If - * you are more concerned with the performance of your machine, enable the - * tasklets. If you are strict about absolutely no drops, then do not enable - * tasklets. - */ - -#define ENABLE_TASKLETS - -/* - * Dynamic spans implemented using TDM over X with standard message - * types. Message format is as follows: - * - * Byte #: Meaning - * 0 Number of samples per channel - * 1 Current flags on span - * Bit 0: Yellow Alarm - * Bit 1: Sig bits present - * Bits 2-7: reserved for future use - * 2-3 16-bit counter value for detecting drops, network byte order. - * 4-5 Number of channels in the message, network byte order - * 6... 16-bit words, containing sig bits for each - * four channels, least significant 4 bits being - * the least significant channel, network byte order. - * the rest data for each channel, all samples per channel - before moving to the next. - */ - -/* Arbitrary limit to the max # of channels in a span */ -#define ZT_DYNAMIC_MAX_CHANS 256 - -#define ZTD_FLAG_YELLOW_ALARM (1 << 0) -#define ZTD_FLAG_SIGBITS_PRESENT (1 << 1) -#define ZTD_FLAG_LOOPBACK (1 << 2) - -#define ERR_NSAMP (1 << 16) -#define ERR_NCHAN (1 << 17) -#define ERR_LEN (1 << 18) - -EXPORT_SYMBOL(zt_dynamic_register); -EXPORT_SYMBOL(zt_dynamic_unregister); -EXPORT_SYMBOL(zt_dynamic_receive); - -#ifdef ENABLE_TASKLETS -static int taskletrun; -static int taskletsched; -static int taskletpending; -static int taskletexec; -static int txerrors; -static struct tasklet_struct ztd_tlet; - -static void ztd_tasklet(unsigned long data); -#endif - - -static struct zt_dynamic { - char addr[40]; - char dname[20]; - int err; - int usecount; - int dead; - long rxjif; - unsigned short txcnt; - unsigned short rxcnt; - struct zt_span span; - struct zt_chan *chans; - struct zt_dynamic *next; - struct zt_dynamic_driver *driver; - void *pvt; - int timing; - int master; - unsigned char *msgbuf; -} *dspans; - -static struct zt_dynamic_driver *drivers = NULL; - -static int debug = 0; - -static int hasmaster = 0; -#ifdef DEFINE_SPINLOCK -static DEFINE_SPINLOCK(dlock); -#else -static spinlock_t dlock = SPIN_LOCK_UNLOCKED; -#endif - -#ifdef DEFINE_RWLOCK -static DEFINE_RWLOCK(drvlock); -#else -static rwlock_t drvlock = RW_LOCK_UNLOCKED; -#endif - -static void checkmaster(void) -{ - unsigned long flags; - int newhasmaster=0; - int best = 9999999; - struct zt_dynamic *z, *master=NULL; - spin_lock_irqsave(&dlock, flags); - z = dspans; - while(z) { - if (z->timing) { - z->master = 0; - if (!(z->span.alarms & ZT_ALARM_RED) && - (z->timing < best) && !z->dead) { - /* If not in alarm and they're - a better timing source, use them */ - master = z; - best = z->timing; - newhasmaster = 1; - } - } - z = z->next; - } - hasmaster = newhasmaster; - /* Mark the new master if there is one */ - if (master) - master->master = 1; - spin_unlock_irqrestore(&dlock, flags); - if (master) - printk("TDMoX: New master: %s\n", master->span.name); - else - printk("TDMoX: No master.\n"); -} - -static void ztd_sendmessage(struct zt_dynamic *z) -{ - unsigned char *buf = z->msgbuf; - unsigned short bits; - int msglen = 0; - int x; - int offset; - - /* Byte 0: Number of samples per channel */ - *buf = ZT_CHUNKSIZE; - buf++; msglen++; - - /* Byte 1: Flags */ - *buf = 0; - if (z->span.alarms & ZT_ALARM_RED) - *buf |= ZTD_FLAG_YELLOW_ALARM; - *buf |= ZTD_FLAG_SIGBITS_PRESENT; - buf++; msglen++; - - /* Bytes 2-3: Transmit counter */ - *((unsigned short *)buf) = htons((unsigned short)z->txcnt); - z->txcnt++; - buf++; msglen++; - buf++; msglen++; - - /* Bytes 4-5: Number of channels */ - *((unsigned short *)buf) = htons((unsigned short)z->span.channels); - buf++; msglen++; - buf++; msglen++; - bits = 0; - offset = 0; - for (x=0;xspan.channels;x++) { - offset = x % 4; - bits |= (z->chans[x].txsig & 0xf) << (offset << 2); - if (offset == 3) { - /* Write the bits when we have four channels */ - *((unsigned short *)buf) = htons(bits); - buf++; msglen++; - buf++; msglen++; - bits = 0; - } - } - - if (offset != 3) { - /* Finish it off if it's not done already */ - *((unsigned short *)buf) = htons(bits); - buf++; msglen++; - buf++; msglen++; - } - - for (x=0;xspan.channels;x++) { - memcpy(buf, z->chans[x].writechunk, ZT_CHUNKSIZE); - buf += ZT_CHUNKSIZE; - msglen += ZT_CHUNKSIZE; - } - - z->driver->transmit(z->pvt, z->msgbuf, msglen); - -} - -static void __ztdynamic_run(void) -{ - unsigned long flags; - struct zt_dynamic *z; - struct zt_dynamic_driver *drv; - int y; - spin_lock_irqsave(&dlock, flags); - z = dspans; - while(z) { - if (!z->dead) { - /* Ignore dead spans */ - for (y=0;yspan.channels;y++) { - /* Echo cancel double buffered data */ - zt_ec_chunk(&z->span.chans[y], z->span.chans[y].readchunk, z->span.chans[y].writechunk); - } - zt_receive(&z->span); - zt_transmit(&z->span); - /* Handle all transmissions now */ - ztd_sendmessage(z); - } - z = z->next; - } - spin_unlock_irqrestore(&dlock, flags); - - read_lock(&drvlock); - drv = drivers; - while(drv) { - /* Flush any traffic still pending in the driver */ - if (drv->flush) { - drv->flush(); - } - drv = drv->next; - } - read_unlock(&drvlock); -} - -#ifdef ENABLE_TASKLETS -static void ztdynamic_run(void) -{ - if (!taskletpending) { - taskletpending = 1; - taskletsched++; - tasklet_hi_schedule(&ztd_tlet); - } else { - txerrors++; - } -} -#else -#define ztdynamic_run __ztdynamic_run -#endif - -void zt_dynamic_receive(struct zt_span *span, unsigned char *msg, int msglen) -{ - struct zt_dynamic *ztd = span->pvt; - int newerr=0; - unsigned long flags; - int sflags; - int xlen; - int x, bits, sig; - int nchans, master; - int newalarm; - unsigned short rxpos, rxcnt; - - - spin_lock_irqsave(&dlock, flags); - if (msglen < 6) { - spin_unlock_irqrestore(&dlock, flags); - newerr = ERR_LEN; - if (newerr != ztd->err) { - printk("Span %s: Insufficient samples for header (only %d)\n", span->name, msglen); - } - ztd->err = newerr; - return; - } - - /* First, check the chunksize */ - if (*msg != ZT_CHUNKSIZE) { - spin_unlock_irqrestore(&dlock, flags); - newerr = ERR_NSAMP | msg[0]; - if (newerr != ztd->err) { - printk("Span %s: Expected %d samples, but receiving %d\n", span->name, ZT_CHUNKSIZE, msg[0]); - } - ztd->err = newerr; - return; - } - msg++; - sflags = *msg; - msg++; - - rxpos = ntohs(*((unsigned short *)msg)); - msg++; - msg++; - - nchans = ntohs(*((unsigned short *)msg)); - if (nchans != span->channels) { - spin_unlock_irqrestore(&dlock, flags); - newerr = ERR_NCHAN | nchans; - if (newerr != ztd->err) { - printk("Span %s: Expected %d channels, but receiving %d\n", span->name, span->channels, nchans); - } - ztd->err = newerr; - return; - } - msg++; - msg++; - - /* Okay now we've accepted the header, lets check our message - length... */ - - /* Start with header */ - xlen = 6; - /* Add samples of audio */ - xlen += nchans * ZT_CHUNKSIZE; - /* If RBS info is there, add that */ - if (sflags & ZTD_FLAG_SIGBITS_PRESENT) { - /* Account for sigbits -- one short per 4 channels*/ - xlen += ((nchans + 3) / 4) * 2; - } - - if (xlen != msglen) { - spin_unlock_irqrestore(&dlock, flags); - newerr = ERR_LEN | xlen; - if (newerr != ztd->err) { - printk("Span %s: Expected message size %d, but was %d instead\n", span->name, xlen, msglen); - } - ztd->err = newerr; - return; - } - - bits = 0; - - /* Record sigbits if present */ - if (sflags & ZTD_FLAG_SIGBITS_PRESENT) { - for (x=0;x> ((x % 4) << 2)) & 0xff; - - /* Update signalling if appropriate */ - if (sig != span->chans[x].rxsig) - zt_rbsbits(&span->chans[x], sig); - - } - } - - /* Record data for channels */ - for (x=0;xchans[x].readchunk, msg, ZT_CHUNKSIZE); - msg += ZT_CHUNKSIZE; - } - - master = ztd->master; - - rxcnt = ztd->rxcnt; - ztd->rxcnt = rxpos+1; - - spin_unlock_irqrestore(&dlock, flags); - - /* Check for Yellow alarm */ - newalarm = span->alarms & ~(ZT_ALARM_YELLOW | ZT_ALARM_RED); - if (sflags & ZTD_FLAG_YELLOW_ALARM) - newalarm |= ZT_ALARM_YELLOW; - - if (newalarm != span->alarms) { - span->alarms = newalarm; - zt_alarm_notify(span); - checkmaster(); - } - - /* Keep track of last received packet */ - ztd->rxjif = jiffies; - - /* note if we had a missing packet */ - if (rxpos != rxcnt) - printk("Span %s: Expected seq no %d, but received %d instead\n", span->name, rxcnt, rxpos); - - /* If this is our master span, then run everything */ - if (master) - ztdynamic_run(); - -} - -static void dynamic_destroy(struct zt_dynamic *z) -{ - /* Unregister span if appropriate */ - if (z->span.flags & ZT_FLAG_REGISTERED) - zt_unregister(&z->span); - - /* Destroy the pvt stuff if there */ - if (z->pvt) - z->driver->destroy(z->pvt); - - /* Free message buffer if appropriate */ - if (z->msgbuf) - kfree(z->msgbuf); - - /* Free channels */ - if (z->chans); - vfree(z->chans); - /* Free z */ - kfree(z); - - checkmaster(); -} - -static struct zt_dynamic *find_dynamic(ZT_DYNAMIC_SPAN *zds) -{ - struct zt_dynamic *z; - z = dspans; - while(z) { - if (!strcmp(z->dname, zds->driver) && - !strcmp(z->addr, zds->addr)) - break; - z = z->next; - } - return z; -} - -static struct zt_dynamic_driver *find_driver(char *name) -{ - struct zt_dynamic_driver *ztd; - ztd = drivers; - while(ztd) { - /* here's our driver */ - if (!strcmp(name, ztd->name)) - break; - ztd = ztd->next; - } - return ztd; -} - -static int destroy_dynamic(ZT_DYNAMIC_SPAN *zds) -{ - unsigned long flags; - struct zt_dynamic *z, *cur, *prev=NULL; - spin_lock_irqsave(&dlock, flags); - z = find_dynamic(zds); - if (!z) { - spin_unlock_irqrestore(&dlock, flags); - return -EINVAL; - } - /* Don't destroy span until it is in use */ - if (z->usecount) { - spin_unlock_irqrestore(&dlock, flags); - printk("Attempt to destroy dynamic span while it is in use\n"); - return -EBUSY; - } - /* Unlink it */ - cur = dspans; - while(cur) { - if (cur == z) { - if (prev) - prev->next = z->next; - else - dspans = z->next; - break; - } - prev = cur; - cur = cur->next; - } - spin_unlock_irqrestore(&dlock, flags); - - /* Destroy it */ - dynamic_destroy(z); - - return 0; -} - -static int ztd_rbsbits(struct zt_chan *chan, int bits) -{ - /* Don't have to do anything */ - return 0; -} - -static int ztd_open(struct zt_chan *chan) -{ - struct zt_dynamic *z; - z = chan->span->pvt; - if (z) { - if (z->dead) - return -ENODEV; - z->usecount++; - } -#ifndef LINUX26 - MOD_INC_USE_COUNT; -#else - if(!try_module_get(THIS_MODULE)) - printk("TDMoX: Unable to increment module use count\n"); -#endif - return 0; -} - -static int ztd_chanconfig(struct zt_chan *chan, int sigtype) -{ - return 0; -} - -static int ztd_close(struct zt_chan *chan) -{ - struct zt_dynamic *z; - z = chan->span->pvt; - if (z) - z->usecount--; - if (z->dead && !z->usecount) - dynamic_destroy(z); -#ifndef LINUX26 - MOD_DEC_USE_COUNT; -#else - module_put(THIS_MODULE); -#endif - return 0; -} - -static int create_dynamic(ZT_DYNAMIC_SPAN *zds) -{ - struct zt_dynamic *z; - struct zt_dynamic_driver *ztd; - unsigned long flags; - int x; - int bufsize; - - if (zds->numchans < 1) { - printk("Can't be less than 1 channel (%d)!\n", zds->numchans); - return -EINVAL; - } - if (zds->numchans >= ZT_DYNAMIC_MAX_CHANS) { - printk("Can't create dynamic span with greater than %d channels. See ztdynamic.c and increase ZT_DYNAMIC_MAX_CHANS\n", zds->numchans); - return -EINVAL; - } - - spin_lock_irqsave(&dlock, flags); - z = find_dynamic(zds); - spin_unlock_irqrestore(&dlock, flags); - if (z) - return -EEXIST; - - /* XXX There is a silly race here. We check it doesn't exist, but - someone could create it between now and then and we'd end up - with two of them. We don't want to hold the spinlock - for *too* long though, especially not if there is a possibility - of kmalloc. XXX */ - - - /* Allocate memory */ - z = (struct zt_dynamic *)kmalloc(sizeof(struct zt_dynamic), GFP_KERNEL); - if (!z) - return -ENOMEM; - - /* Zero it out */ - memset(z, 0, sizeof(struct zt_dynamic)); - - /* Allocate other memories */ - z->chans = vmalloc(sizeof(struct zt_chan) * zds->numchans); - if (!z->chans) { - dynamic_destroy(z); - return -ENOMEM; - } - - /* Zero out channel stuff */ - memset(z->chans, 0, sizeof(struct zt_chan) * zds->numchans); - - /* Allocate message buffer with sample space and header space */ - bufsize = zds->numchans * ZT_CHUNKSIZE + zds->numchans / 4 + 48; - - z->msgbuf = kmalloc(bufsize, GFP_KERNEL); - - if (!z->msgbuf) { - dynamic_destroy(z); - return -ENOMEM; - } - - /* Zero out -- probably not needed but why not */ - memset(z->msgbuf, 0, bufsize); - - /* Setup parameters properly assuming we're going to be okay. */ - strncpy(z->dname, zds->driver, sizeof(z->dname) - 1); - strncpy(z->addr, zds->addr, sizeof(z->addr) - 1); - z->timing = zds->timing; - sprintf(z->span.name, "ZTD/%s/%s", zds->driver, zds->addr); - sprintf(z->span.desc, "Dynamic '%s' span at '%s'", zds->driver, zds->addr); - z->span.channels = zds->numchans; - z->span.pvt = z; - z->span.deflaw = ZT_LAW_MULAW; - z->span.flags |= ZT_FLAG_RBS; - z->span.chans = z->chans; - z->span.rbsbits = ztd_rbsbits; - z->span.open = ztd_open; - z->span.close = ztd_close; - z->span.chanconfig = ztd_chanconfig; - for (x=0;xnumchans;x++) { - sprintf(z->chans[x].name, "ZTD/%s/%s/%d", zds->driver, zds->addr, x+1); - z->chans[x].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | - ZT_SIG_FXSKS | ZT_SIG_FXSGS | ZT_SIG_FXOLS | - ZT_SIG_FXOKS | ZT_SIG_FXOGS | ZT_SIG_SF | - ZT_SIG_DACS_RBS | ZT_SIG_CAS; - z->chans[x].chanpos = x + 1; - z->chans[x].pvt = z; - } - - spin_lock_irqsave(&dlock, flags); - ztd = find_driver(zds->driver); - if (!ztd) { - /* Try loading the right module */ - char fn[80]; - spin_unlock_irqrestore(&dlock, flags); - sprintf(fn, "ztd-%s", zds->driver); - request_module(fn); - spin_lock_irqsave(&dlock, flags); - ztd = find_driver(zds->driver); - } - spin_unlock_irqrestore(&dlock, flags); - - - /* Another race -- should let the module get unloaded while we - have it here */ - if (!ztd) { - printk("No such driver '%s' for dynamic span\n", zds->driver); - dynamic_destroy(z); - return -EINVAL; - } - - /* Create the stuff */ - z->pvt = ztd->create(&z->span, z->addr); - if (!z->pvt) { - printk("Driver '%s' (%s) rejected address '%s'\n", ztd->name, ztd->desc, z->addr); - /* Creation failed */ - return -EINVAL; - } - - /* Remember the driver */ - z->driver = ztd; - - /* Whee! We're created. Now register the span */ - if (zt_register(&z->span, 0)) { - printk("Unable to register span '%s'\n", z->span.name); - dynamic_destroy(z); - return -EINVAL; - } - - /* Okay, created and registered. add it to the list */ - spin_lock_irqsave(&dlock, flags); - z->next = dspans; - dspans = z; - spin_unlock_irqrestore(&dlock, flags); - - checkmaster(); - - /* All done */ - return z->span.spanno; - -} - -#ifdef ENABLE_TASKLETS -static void ztd_tasklet(unsigned long data) -{ - taskletrun++; - if (taskletpending) { - taskletexec++; - __ztdynamic_run(); - } - taskletpending = 0; -} -#endif - -static int ztdynamic_ioctl(unsigned int cmd, unsigned long data) -{ - ZT_DYNAMIC_SPAN zds; - int res; - switch(cmd) { - case 0: - /* This is called just before rotation. If none of our - spans are pulling timing, then now is the time to process - them */ - if (!hasmaster) - ztdynamic_run(); - return 0; - case ZT_DYNAMIC_CREATE: - if (copy_from_user(&zds, (ZT_DYNAMIC_SPAN *)data, sizeof(zds))) - return -EFAULT; - if (debug) - printk("Dynamic Create\n"); - res = create_dynamic(&zds); - if (res < 0) - return res; - zds.spanno = res; - /* Let them know the new span number */ - if (copy_to_user((ZT_DYNAMIC_SPAN *)data, &zds, sizeof(zds))) - return -EFAULT; - return 0; - case ZT_DYNAMIC_DESTROY: - if (copy_from_user(&zds, (ZT_DYNAMIC_SPAN *)data, sizeof(zds))) - return -EFAULT; - if (debug) - printk("Dynamic Destroy\n"); - return destroy_dynamic(&zds); - } - - return -ENOTTY; -} - -int zt_dynamic_register(struct zt_dynamic_driver *dri) -{ - unsigned long flags; - int res = 0; - write_lock_irqsave(&drvlock, flags); - if (find_driver(dri->name)) - res = -1; - else { - dri->next = drivers; - drivers = dri; - } - write_unlock_irqrestore(&drvlock, flags); - return res; -} - -void zt_dynamic_unregister(struct zt_dynamic_driver *dri) -{ - struct zt_dynamic_driver *cur, *prev=NULL; - struct zt_dynamic *z, *zp, *zn; - unsigned long flags; - write_lock_irqsave(&drvlock, flags); - cur = drivers; - while(cur) { - if (cur == dri) { - if (prev) - prev->next = cur->next; - else - drivers = cur->next; - break; - } - prev = cur; - cur = cur->next; - } - write_unlock_irqrestore(&drvlock, flags); - spin_lock_irqsave(&dlock, flags); - z = dspans; - zp = NULL; - while(z) { - zn = z->next; - if (z->driver == dri) { - /* Unlink */ - if (zp) - zp->next = z->next; - else - dspans = z->next; - if (!z->usecount) - dynamic_destroy(z); - else - z->dead = 1; - } else { - zp = z; - } - z = zn; - } - spin_unlock_irqrestore(&dlock, flags); -} - -struct timer_list alarmcheck; - -static void check_for_red_alarm(unsigned long ignored) -{ - unsigned long flags; - int newalarm; - int alarmchanged = 0; - struct zt_dynamic *z; - spin_lock_irqsave(&dlock, flags); - z = dspans; - while(z) { - newalarm = z->span.alarms & ~ZT_ALARM_RED; - /* If nothing received for a second, consider that RED ALARM */ - if ((jiffies - z->rxjif) > 1 * HZ) { - newalarm |= ZT_ALARM_RED; - if (z->span.alarms != newalarm) { - z->span.alarms = newalarm; - zt_alarm_notify(&z->span); - alarmchanged++; - } - } - z = z->next; - } - spin_unlock_irqrestore(&dlock, flags); - if (alarmchanged) - checkmaster(); - - /* Do the next one */ - mod_timer(&alarmcheck, jiffies + 1 * HZ); - -} - -int ztdynamic_init(void) -{ - zt_set_dynamic_ioctl(ztdynamic_ioctl); - /* Start process to check for RED ALARM */ - init_timer(&alarmcheck); - alarmcheck.expires = 0; - alarmcheck.data = 0; - alarmcheck.function = check_for_red_alarm; - /* Check once per second */ - mod_timer(&alarmcheck, jiffies + 1 * HZ); -#ifdef ENABLE_TASKLETS - tasklet_init(&ztd_tlet, ztd_tasklet, 0); -#endif - printk("Zaptel Dynamic Span support LOADED\n"); - return 0; -} - -void ztdynamic_cleanup(void) -{ -#ifdef ENABLE_TASKLETS - if (taskletpending) { - tasklet_disable(&ztd_tlet); - tasklet_kill(&ztd_tlet); - } -#endif - zt_set_dynamic_ioctl(NULL); - del_timer(&alarmcheck); - printk("Zaptel Dynamic Span support unloaded\n"); -} - -#ifdef LINUX26 -module_param(debug, int, 0600); -#else -MODULE_PARM(debug, "i"); -#endif -MODULE_DESCRIPTION("Zaptel Dynamic Span Support"); -MODULE_AUTHOR("Mark Spencer "); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif - -module_init(ztdynamic_init); -module_exit(ztdynamic_cleanup); diff --git a/ztmonitor.c b/ztmonitor.c index 707a705..13f355d 100644 --- a/ztmonitor.c +++ b/ztmonitor.c @@ -39,7 +39,7 @@ #include #include #ifdef STANDALONE_ZAPATA -#include "zaptel.h" +#include "kernel/zaptel.h" #include "tonezone.h" #else #include diff --git a/ztscan.c b/ztscan.c index 05bd012..87be973 100644 --- a/ztscan.c +++ b/ztscan.c @@ -35,7 +35,7 @@ #include #ifdef STANDALONE_ZAPATA -#include "zaptel.h" +#include "kernel/zaptel.h" #else #include #endif diff --git a/zttool.c b/zttool.c index 2428883..c1e97bc 100644 --- a/zttool.c +++ b/zttool.c @@ -43,7 +43,7 @@ #include #include #ifdef STANDALONE_ZAPATA -#include "zaptel.h" +#include "kernel/zaptel.h" #include "tonezone.h" #else #include diff --git a/zttranscode.c b/zttranscode.c deleted file mode 100644 index ca2cdd8..0000000 --- a/zttranscode.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Transcoder Interface for Zaptel - * - * Written by Mark Spencer - * - * Copyright (C) 2006-2007, Digium, Inc. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_DEVFS_FS -#include -#endif -#ifdef STANDALONE_ZAPATA -#include "zaptel.h" -#else -#include -#endif -#ifdef LINUX26 -#include -#endif - -static int debug = 0; -static struct zt_transcoder *trans; -static spinlock_t translock = SPIN_LOCK_UNLOCKED; - -EXPORT_SYMBOL(zt_transcoder_register); -EXPORT_SYMBOL(zt_transcoder_unregister); -EXPORT_SYMBOL(zt_transcoder_alert); -EXPORT_SYMBOL(zt_transcoder_alloc); -EXPORT_SYMBOL(zt_transcoder_free); - -struct zt_transcoder *zt_transcoder_alloc(int numchans) -{ - struct zt_transcoder *ztc; - unsigned int x; - size_t size = sizeof(*ztc) + (sizeof(ztc->channels[0]) * numchans); - - if (!(ztc = kmalloc(size, GFP_KERNEL))) - return NULL; - - memset(ztc, 0, size); - strcpy(ztc->name, ""); - ztc->numchannels = numchans; - for (x=0;xnumchannels;x++) { - init_waitqueue_head(&ztc->channels[x].ready); - ztc->channels[x].parent = ztc; - ztc->channels[x].offset = x; - ztc->channels[x].chan_built = 0; - ztc->channels[x].built_fmts = 0; - } - - return ztc; -} - -static int schluffen(wait_queue_head_t *q) -{ - DECLARE_WAITQUEUE(wait, current); - - add_wait_queue(q, &wait); - current->state = TASK_INTERRUPTIBLE; - - if (!signal_pending(current)) - schedule(); - - current->state = TASK_RUNNING; - remove_wait_queue(q, &wait); - - if (signal_pending(current)) - return -ERESTARTSYS; - - return 0; -} - -void zt_transcoder_free(struct zt_transcoder *ztc) -{ - kfree(ztc); -} - -/* Register a transcoder */ -int zt_transcoder_register(struct zt_transcoder *tc) -{ - struct zt_transcoder *cur; - int res = -EBUSY; - - spin_lock(&translock); - for (cur = trans; cur; cur = cur->next) { - if (cur == tc) { - spin_unlock(&translock); - return res; - } - } - - tc->next = trans; - trans = tc; - printk("Registered codec translator '%s' with %d transcoders (srcs=%08x, dsts=%08x)\n", - tc->name, tc->numchannels, tc->srcfmts, tc->dstfmts); - res = 0; - spin_unlock(&translock); - - return res; -} - -/* Unregister a transcoder */ -int zt_transcoder_unregister(struct zt_transcoder *tc) -{ - struct zt_transcoder *cur, *prev; - int res = -EINVAL; - - spin_lock(&translock); - for (cur = trans, prev = NULL; cur; prev = cur, cur = cur->next) { - if (cur == tc) - break; - } - - if (!cur) { - spin_unlock(&translock); - return res; - } - - if (prev) - prev->next = tc->next; - else - trans = tc->next; - tc->next = NULL; - printk("Unregistered codec translator '%s' with %d transcoders (srcs=%08x, dsts=%08x)\n", - tc->name, tc->numchannels, tc->srcfmts, tc->dstfmts); - res = 0; - spin_unlock(&translock); - - return res; -} - -/* Alert a transcoder */ -int zt_transcoder_alert(struct zt_transcoder_channel *ztc) -{ - if (debug) - printk("ZT Transcoder Alert!\n"); - if (ztc->tch) - ztc->tch->status &= ~ZT_TC_FLAG_BUSY; - wake_up_interruptible(&ztc->ready); - - return 0; -} - -static int zt_tc_open(struct inode *inode, struct file *file) -{ - struct zt_transcoder_channel *ztc; - struct zt_transcode_header *zth; - struct page *page; - - if (!(ztc = kmalloc(sizeof(*ztc), GFP_KERNEL))) - return -ENOMEM; - - if (!(zth = kmalloc(sizeof(*zth), GFP_KERNEL | GFP_DMA))) { - kfree(ztc); - return -ENOMEM; - } - - memset(ztc, 0, sizeof(*ztc)); - memset(zth, 0, sizeof(*zth)); - ztc->flags = ZT_TC_FLAG_TRANSIENT | ZT_TC_FLAG_BUSY; - ztc->tch = zth; - if (debug) - printk("Allocated Transcoder Channel, header is at %p!\n", zth); - zth->magic = ZT_TRANSCODE_MAGIC; - file->private_data = ztc; - for (page = virt_to_page(zth); - page < virt_to_page((unsigned long) zth + sizeof(*zth)); - page++) - SetPageReserved(page); - - return 0; -} - -static void ztc_release(struct zt_transcoder_channel *ztc) -{ - struct zt_transcode_header *zth = ztc->tch; - struct page *page; - - if (!ztc) - return; - - ztc->flags &= ~(ZT_TC_FLAG_BUSY); - - if(ztc->tch) { - for (page = virt_to_page(zth); - page < virt_to_page((unsigned long) zth + sizeof(*zth)); - page++) - ClearPageReserved(page); - kfree(ztc->tch); - } - - ztc->tch = NULL; - /* Actually reset the transcoder channel */ - if (ztc->flags & ZT_TC_FLAG_TRANSIENT) - kfree(ztc); - if (debug) - printk("Released Transcoder!\n"); -} - -static int zt_tc_release(struct inode *inode, struct file *file) -{ - ztc_release(file->private_data); - - return 0; -} - -static int do_reset(struct zt_transcoder_channel **ztc) -{ - struct zt_transcoder_channel *newztc = NULL, *origztc = NULL; - struct zt_transcode_header *zth = (*ztc)->tch; - struct zt_transcoder *tc; - unsigned int x; - unsigned int match = 0; - - if (((*ztc)->srcfmt != zth->srcfmt) || - ((*ztc)->dstfmt != zth->dstfmt)) { - /* Find new transcoder */ - spin_lock(&translock); - for (tc = trans; tc && !newztc; tc = tc->next) { - if (!(tc->srcfmts & zth->srcfmt)) - continue; - - if (!(tc->dstfmts & zth->dstfmt)) - continue; - - match = 1; - for (x = 0; x < tc->numchannels; x++) { - if (tc->channels[x].flags & ZT_TC_FLAG_BUSY) - continue; - if ((tc->channels[x].chan_built) && ((zth->srcfmt | zth->dstfmt) != tc->channels[x].built_fmts)) - continue; - - newztc = &tc->channels[x]; - newztc->flags = ZT_TC_FLAG_BUSY; - break; - } - } - spin_unlock(&translock); - - if (!newztc) - return match ? -EBUSY : -ENOSYS; - - /* Move transcoder header over */ - origztc = (*ztc); - (*ztc) = newztc; - (*ztc)->tch = origztc->tch; - origztc->tch = NULL; - (*ztc)->flags |= (origztc->flags & ~(ZT_TC_FLAG_TRANSIENT)); - ztc_release(origztc); - } - - /* Actually reset the transcoder channel */ - if ((*ztc)->parent && ((*ztc)->parent->operation)) - return (*ztc)->parent->operation((*ztc), ZT_TCOP_ALLOCATE); - - return -EINVAL; -} - -static int wait_busy(struct zt_transcoder_channel *ztc) -{ - int ret; - - for (;;) { - if (!(ztc->tch->status & ZT_TC_FLAG_BUSY)) - return 0; - if ((ret = schluffen(&ztc->ready))) - return ret; - } -} - -static int zt_tc_getinfo(unsigned long data) -{ - struct zt_transcode_info info; - unsigned int x; - struct zt_transcoder *tc; - - if (copy_from_user(&info, (struct zt_transcode_info *) data, sizeof(info))) - return -EFAULT; - - spin_lock(&translock); - for (tc = trans, x = info.tcnum; tc && x; tc = tc->next, x--); - spin_unlock(&translock); - - if (!tc) - return -ENOSYS; - - strncpy(info.name, tc->name, sizeof(info.name) - 1); - info.numchannels = tc->numchannels; - info.srcfmts = tc->srcfmts; - info.dstfmts = tc->dstfmts; - - return copy_to_user((struct zt_transcode_info *) data, &info, sizeof(info)) ? -EFAULT : 0; -} - -static int zt_tc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data) -{ - int op; - int ret; - struct zt_transcoder_channel *ztc = file->private_data; - - if (cmd != ZT_TRANSCODE_OP) - return -ENOSYS; - - if (get_user(op, (int *) data)) - return -EFAULT; - - if (debug) - printk("ZT Transcode ioctl op = %d!\n", op); - - switch(op) { - case ZT_TCOP_GETINFO: - ret = zt_tc_getinfo(data); - break; - case ZT_TCOP_ALLOCATE: - /* Reset transcoder, possibly changing who we point to */ - ret = do_reset(&ztc); - file->private_data = ztc; - break; - case ZT_TCOP_RELEASE: - ret = ztc->parent->operation(ztc, ZT_TCOP_RELEASE); - break; - case ZT_TCOP_TEST: - ret = ztc->parent->operation(ztc, ZT_TCOP_TEST); - break; - case ZT_TCOP_TRANSCODE: - if (!ztc->parent->operation) - return -EINVAL; - - ztc->tch->status |= ZT_TC_FLAG_BUSY; - if (!(ret = ztc->parent->operation(ztc, ZT_TCOP_TRANSCODE))) { - /* Wait for busy to go away if we're not non-blocking */ - if (!(file->f_flags & O_NONBLOCK)) { - if (!(ret = wait_busy(ztc))) - ret = ztc->errorstatus; - } - } else - ztc->tch->status &= ~ZT_TC_FLAG_BUSY; - break; - default: - ret = -ENOSYS; - } - - return ret; -} - -static int zt_tc_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct zt_transcoder_channel *ztc = file->private_data; - unsigned long physical; - int res; - - if (!ztc) - return -EINVAL; - - /* Do not allow an offset */ - if (vma->vm_pgoff) { - if (debug) - printk("zttranscode: Attempted to mmap with offset!\n"); - return -EINVAL; - } - - if ((vma->vm_end - vma->vm_start) != sizeof(struct zt_transcode_header)) { - if (debug) - printk("zttranscode: Attempted to mmap with size %d != %zd!\n", (int) (vma->vm_end - vma->vm_start), sizeof(struct zt_transcode_header)); - return -EINVAL; - } - - physical = (unsigned long) virt_to_phys(ztc->tch); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) - res = remap_pfn_range(vma, vma->vm_start, physical >> PAGE_SHIFT, sizeof(struct zt_transcode_header), PAGE_SHARED); -#else - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - res = remap_page_range(vma->vm_start, physical, sizeof(struct zt_transcode_header), PAGE_SHARED); - #else - res = remap_page_range(vma, vma->vm_start, physical, sizeof(struct zt_transcode_header), PAGE_SHARED); - #endif -#endif - if (res) { - if (debug) - printk("zttranscode: remap failed!\n"); - return -EAGAIN; - } - - if (debug) - printk("zttranscode: successfully mapped transcoder!\n"); - - return 0; -} - -static unsigned int zt_tc_poll(struct file *file, struct poll_table_struct *wait_table) -{ - struct zt_transcoder_channel *ztc = file->private_data; - - if (!ztc) - return -EINVAL; - - poll_wait(file, &ztc->ready, wait_table); - return ztc->tch->status & ZT_TC_FLAG_BUSY ? 0 : POLLPRI; -} - -static struct file_operations __zt_transcode_fops = { - owner: THIS_MODULE, - llseek: NULL, - open: zt_tc_open, - release: zt_tc_release, - ioctl: zt_tc_ioctl, - read: NULL, - write: NULL, - poll: zt_tc_poll, - mmap: zt_tc_mmap, - flush: NULL, - fsync: NULL, - fasync: NULL, -}; - -static struct zt_chardev transcode_chardev = { - .name = "transcode", - .minor = 250, -}; - -int zttranscode_init(void) -{ - int res; - - if (zt_transcode_fops) { - printk("Whoa, zt_transcode_fops already set?!\n"); - return -EBUSY; - } - - zt_transcode_fops = &__zt_transcode_fops; - - if ((res = zt_register_chardev(&transcode_chardev))) - return res; - - printk("Zaptel Transcoder support loaded\n"); - - return 0; -} - -void zttranscode_cleanup(void) -{ - zt_unregister_chardev(&transcode_chardev); - - zt_transcode_fops = NULL; - - printk("Zaptel Transcoder support unloaded\n"); -} - -#ifdef LINUX26 -module_param(debug, int, S_IRUGO | S_IWUSR); -#else -MODULE_PARM(debug, "i"); -#endif -MODULE_DESCRIPTION("Zaptel Transcoder Support"); -MODULE_AUTHOR("Mark Spencer "); -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif - -module_init(zttranscode_init); -module_exit(zttranscode_cleanup); -- cgit v1.2.3