summaryrefslogtreecommitdiff
path: root/kernel/xpp/init_card_1_30
diff options
context:
space:
mode:
authortzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2008-05-13 21:08:09 +0000
committertzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2008-05-13 21:08:09 +0000
commitd7e54a785544ac40abc4a88383df3a913ca466e8 (patch)
treeabf630c8372e7c81407172ad31190fa8a617a8ed /kernel/xpp/init_card_1_30
parent823cf303caf13cc6e4fd2c2173804f0990b29532 (diff)
xpp r5723: Includes, among others:
* New firmware protocol version: 3.0 . * New numbers for the device types: (e.g. in card_init* scripts) - FXS: 1 (was: 3) - FXO: 2 (was: 4) - BRI: 3 (was: 6 for TE, 7 for NT) - PRI: 4 (was: 9) * Init scripts of FXS and FXO modules are now written in Perl as well (be sure to have File::Basename, e.g: perl-modules in Debian). * calibrate_slics merged into init_card_1_30 . * Module parameter print_dbg replaced with debug . Same meaning. * init_fxo_modes removed: content moved into init_card_2_30, verified at build time. * Code tested with sparse. Most warnings were fixed. * Set ZT_SIG_DACS for the bchans in the PRI and BRI modules to not get ignored by ztscan. * Handle null config_desc we get from some crazy USB controllers. * genzaptelconf: Fix reporting of empty slots in list mode. * xpp_blink can now blink a single analog port. * "slics" has been renamed "chipregs". * Fixed a small typo in fpga_load(8). * Fixed bashism in xpp_fxloader. Merged revisions 4264 via svnmerge from http://svn.digium.com/svn/zaptel/branches/1.2 git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@4266 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'kernel/xpp/init_card_1_30')
-rwxr-xr-xkernel/xpp/init_card_1_30535
1 files changed, 535 insertions, 0 deletions
diff --git a/kernel/xpp/init_card_1_30 b/kernel/xpp/init_card_1_30
new file mode 100755
index 0000000..68a6d02
--- /dev/null
+++ b/kernel/xpp/init_card_1_30
@@ -0,0 +1,535 @@
+#! /usr/bin/perl -w
+use strict;
+
+#
+# Written by Oron Peled <oron@actcom.co.il>
+# 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).
+# * 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).
+#
+#
+
+package main;
+use File::Basename;
+use Getopt::Std;
+
+my $program = basename("$0");
+my $init_dir = dirname("$0");
+BEGIN { $init_dir = dirname($0); unshift(@INC, "$init_dir", "$init_dir/zconf"); }
+use Zaptel::Config::Defaults;
+my $unit_id;
+my %opts;
+$ENV{XPP_BASE} = '/proc/xpp';
+
+getopts('o:', \%opts);
+
+my $debug;
+my $skip_calib;
+
+my $xpd_name = sprintf("XPD-%1d0", $ENV{UNIT_NUMBER});
+my $chipregs = "$ENV{XPP_BASE}/$ENV{XBUS_NAME}/$xpd_name/chipregs";
+
+sub logit {
+ print STDERR "$unit_id: @_\n";
+}
+
+sub debug {
+ logit @_ if $debug;
+}
+
+# Arrange for error logging
+if (-t STDERR) {
+ $unit_id = 'Interactive';
+ logit "Interactive startup";
+} else {
+ $unit_id = "$ENV{XBUS_NAME}/UNIT-$ENV{UNIT_NUMBER}";
+ open (STDERR, "| logger -t $program -p kern.info") || die;
+ logit "Non Interactive startup";
+}
+
+sub set_output() {
+ my $output;
+
+ if($opts{o}) {
+ $output = $opts{o};
+ } else {
+ # No subunits in FXS (everything is subunit 0)
+ $output = $chipregs;
+ }
+ open(REG, ">$output") || die "Failed to open '$output': $!\n";
+ my $oldfh = select REG;
+ print "# Setting output\n" if $opts{o};
+ return $oldfh;
+}
+
+sub mysleep($) {
+ my $timeout = shift;
+ select(undef,undef,undef,$timeout);
+}
+
+package FXS;
+
+sub gen {
+ my $fmt = shift;
+ $| = 1;
+ printf "$fmt\n", @_;
+}
+
+my @SlicNums = (0 .. 7);
+
+sub write_to_slic_file($) {
+ my $write_str = shift;
+
+ open(SLICS,">$chipregs") or
+ die("Failed writing to chipregs file $chipregs");
+ print SLICS $write_str;
+ close(SLICS) or die "Failed writing '$write_str' to '$chipregs': $!";
+ main::mysleep(0.001);
+
+}
+
+sub read_reg($$$) {
+ my $read_slic = shift;
+ my $read_reg = shift;
+ my $direct = shift;
+
+ write_to_slic_file(
+ sprintf("%s R%s %02X", $read_slic, $direct, $read_reg));
+ main::mysleep(0.005);
+ open(SLICS,$chipregs) or
+ die("Failed reading from chipregs file $chipregs");
+ #awk '/^SLIC_REPLY:/{print $5}' $SLICS | cut -dx -f2
+ my @reply = ();
+ while(<SLICS>){
+ #if (/^ /) {
+ # main::debug "answer line: $_";
+ #}
+ s/#.*//;
+ next unless /\S/;
+ if (/^ \d*\s+[RW][DI]\s+[[:xdigit:]]+\s+([[:xdigit:]]+)\s+([[:xdigit:]]*)/){
+ @reply = (hex($1), hex($2));
+ #main::debug "got [$reply]";
+ last;
+ } else {
+ main::logit("Got from '$chipregs' a non-matching line '$_'");
+ }
+ }
+ close(SLICS);
+ die("Failed reading from '$chipregs' ($read_slic,$read_reg,$direct)")
+ unless @reply;
+ 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 "%s 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');
+ }
+ main::debug($line);
+ }
+}
+
+sub init_indirect_registers() {
+ return write_to_slic_file("#
+* WI 1E 00 C2 55
+* WI 1E 01 E6 51
+* WI 1E 02 85 4B
+* WI 1E 03 37 49
+
+* WI 1E 04 33 33
+* WI 1E 05 02 02
+* WI 1E 06 02 02
+* WI 1E 07 98 01
+
+* WI 1E 08 98 01
+* WI 1E 09 11 06
+* WI 1E 0A 02 02
+* WI 1E 0B E5 00
+
+* WI 1E 0C 1C 0A
+* WI 1E 0D 30 7B
+* WI 1E 0E 63 00
+* WI 1E 0F 00 00
+
+* WI 1E 10 70 78
+* WI 1E 11 7D 00
+* WI 1E 12 00 00
+* WI 1E 13 00 00
+
+* WI 1E 14 F0 7E
+* WI 1E 15 C0 01
+* WI 1E 16 00 00
+* WI 1E 17 00 20
+
+* WI 1E 18 00 20
+* WI 1E 19 00 00
+* WI 1E 1A 00 20
+* WI 1E 1B 00 40
+
+* WI 1E 1C 00 10
+* WI 1E 1D 00 36
+* WI 1E 1E 00 10
+* WI 1E 1F 00 02
+
+* WI 1E 20 C0 07
+* WI 1E 21 00 26
+* WI 1E 22 F4 0F
+* WI 1E 23 00 80
+
+#* WI 1E 24 20 03
+#* WI 1E 25 8C 08
+#* WI 1E 26 00 01
+#* WI 1E 27 10 00
+
+* WI 1E 24 00 08
+* WI 1E 25 00 08
+* WI 1E 26 00 08
+* WI 1E 27 00 08
+
+* WI 1E 28 00 0C
+* WI 1E 29 00 0C
+* WI 1E 2B 00 01
+
+* WI 1E 63 DA 00
+* WI 1E 64 60 6B
+* WI 1E 65 74 00
+* WI 1E 66 C0 79
+
+* WI 1E 67 20 11
+* WI 1E 68 E0 3B
+#");
+}
+
+sub init_early_direct_regs() {
+ return write_to_slic_file("#
+* WD 08 00 # Audio Path Loopback Control
+* WD 4A 34 # High Battery Voltage
+* WD 4B 10 # Low Battery Voltage
+* WD 40 00 # Line Feed Control
+#")
+}
+
+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('*', $write_reg, 'D', 0x1F);
+ main::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]);
+ }
+ }
+ main::debug($debug_calib_str);
+ # TODO: unnecessary sleep in the last round:
+ main::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
+ "* WD 60 %02X\n".
+ "* WD 61 %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) {
+ main::debug("checking slic $slic");
+ while(1) {
+ if ((read_reg($slic, 60, 'D')) == 0) {
+ # move to next register
+ main::debug("slic $slic calibrated");
+ last;
+ }
+ if ( $sleep_cnt > $timeout_time/$sleep_time) {
+ main::debug("Auto Calibration: Exiting on timeout: $timeout_time.");
+ last CALIB_LOOP;
+ }
+ main::debug("auto_calibrate not done yet: slic #$slic");
+ main::mysleep(0.1);
+ $sleep_cnt++;
+ }
+ }
+ #log_calib_params();
+}
+
+sub calibrate_slics() {
+ main::logit "Calibrating '$0'";
+ auto_calibrate(0x47, 0x1E);
+ main::debug "after auto_calibrate";
+ manual_calibrate();
+ main::debug "after manul_calibrate";
+ auto_calibrate(0x40, 0x01);
+ main::debug "after auto_calibrate 2";
+ main::logit "Continue '$0'";
+}
+
+sub read_defaults() {
+ # For lab tests
+ my $labfile = "$init_dir/genzaptelconf.env";
+
+ # Source default files
+ $ENV{ZAPTEL_DEFAULTS} = "$labfile" if -r "$labfile";
+ my $var_debug = 'DEBUG_INIT_FXS';
+ my $var_skip_calib = 'INIT_FXS_SKIP_CALIB';
+ my ($default_file, %source_defaults) =
+ Zaptel::Config::Defaults::source_vars($var_debug, $var_skip_calib);
+ $debug = $source_defaults{$var_debug};
+ $skip_calib = $source_defaults{$var_skip_calib};
+ main::logit "From $default_file: $var_debug=$debug $var_skip_calib=$skip_calib";
+}
+
+package main;
+
+main::logit "Starting '$0'";
+
+FXS::read_defaults;
+main::debug "before init_indirect_registers";
+FXS::init_indirect_registers();
+main::debug "after init_indirect_registers";
+FXS::init_early_direct_regs();
+main::debug "after init_early_direct_regs";
+if($skip_calib) {
+ main::logit "==== WARNING: SKIPPED SLIC CALIBRATION =====";
+} else {
+ FXS::calibrate_slics;
+}
+set_output;
+while(<DATA>) {
+ chomp;
+ s/[#;].*$//; # remove comments
+ s/^\s+//; # trim whitespace
+ s/\s+$//; # trim whitespace
+ s/\t+/ /g; # replace tabs with spaces (for logs)
+ next unless /\S/; # Skip empty lines
+ main::debug "writing: '$_'";
+ print "$_\n";
+}
+close REG;
+
+main::logit "Ending '$0'";
+close STDERR;
+exit 0;
+
+# ----------------------------------==== 8-channel FXS unit initialization ===-----------------------------------------
+
+__DATA__
+# Change SLICs states to "Open state"s (Off,all transfers tristated to avoid data collision), Voltage sense
+* WD 40 00
+
+# Flush out energy accumulators
+* WI 1E 58 00 00
+* WI 1E 59 00 00
+* WI 1E 5A 00 00
+* WI 1E 5B 00 00
+* WI 1E 5C 00 00
+* WI 1E 5D 00 00
+* WI 1E 5E 00 00
+* WI 1E 5F 00 00
+* WI 1E 61 00 00
+* WI 1E 58 00 00
+* WI 1E C1 00 00
+* WI 1E C2 00 00
+* WI 1E C3 00 00
+* WI 1E C4 00 00
+* WI 1E C5 00 00
+* WI 1E C6 00 00
+* WI 1E C7 00 00
+* WI 1E C8 00 00
+* WI 1E C9 00 00
+* WI 1E CA 00 00
+* WI 1E CB 00 00
+* WI 1E CC 00 00
+* WI 1E CD 00 00
+* WI 1E CE 00 00
+* WI 1E CF 00 00
+* WI 1E D0 00 00
+* WI 1E D1 00 00
+* WI 1E D2 00 00
+* WI 1E 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
+* WD 03 00
+* WD 05 00
+
+# Audio path. (also initialize 0A and 0B here if necessary)
+* WD 08 00
+* WD 09 C0
+
+# Automatic/Manual Control: defaults but:
+# Cancel AOPN - Power Alarm
+# Cancel ABAT - Battery Feed Automatic Select
+* WD 43 16
+
+# Loop Closure Debounce Interval
+* WD 45 0A
+
+# Ring Detect Debounce Interval
+* WD 46 47
+
+# Battery Feed Control: Battery low (DCSW low)
+* WD 42 00
+
+# Loop Current Limit
+* WD 47 00
+
+# Ring VBath:
+* WD 4A 3F
+
+
+* WD 6C 01
+
+* WI 1E 23 00 80
+* WI 1E 24 20 03
+* WI 1E 25 8C 08
+* WI 1E 26 00 01
+* WI 1E 27 10 00
+
+#------ Metering tone
+* WI 1E 17 61 15 # Amplitue Ramp-up
+* WI 1E 18 61 15 # Max Amplitude
+* WI 1E 19 FB 30 # Frequency
+* WD 2C 00 # Timer dL
+* WD 2D 03 # Timer dH
+
+# ------------------------------------- Initialization of direct registers --------------------------------------------
+
+# Mode(8-bit,u-Law,1 PCLK ) setting, Loopbacks and Interrupts clear
+
+* WD 01 29
+#* WD 0E 00
+
+#* WD 15 00
+#* WD 16 03
+
+# Clear pending interrupts
+* WD 12 FF
+* WD 13 FF
+* WD 14 FF
+
+#* WD 4A 34
+#* WD 4B 10