summaryrefslogtreecommitdiff
path: root/drivers/dahdi/xpp/init_card_4_30
diff options
context:
space:
mode:
authorKevin P. Fleming <kpfleming@digium.com>2008-05-21 15:11:48 +0000
committerKevin P. Fleming <kpfleming@digium.com>2008-05-21 15:11:48 +0000
commit802b567e6c7ba7803a950324cbed13f7d57944cb (patch)
tree6b90ca3119aaa2e4073d3b651ac965dea5d3430e /drivers/dahdi/xpp/init_card_4_30
parentec5ce88e015b41c2f46f6c9b783339b945f9502a (diff)
start copying kernel bits
git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@4315 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/xpp/init_card_4_30')
-rwxr-xr-xdrivers/dahdi/xpp/init_card_4_30387
1 files changed, 387 insertions, 0 deletions
diff --git a/drivers/dahdi/xpp/init_card_4_30 b/drivers/dahdi/xpp/init_card_4_30
new file mode 100755
index 0000000..25e6ec7
--- /dev/null
+++ b/drivers/dahdi/xpp/init_card_4_30
@@ -0,0 +1,387 @@
+#! /usr/bin/perl -w
+use strict;
+
+#
+# $Id$
+#
+
+#
+# Written by Oron Peled <oron@actcom.co.il>
+# 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:
+# XBUS_NAME - bus name
+# UNIT_NUMBER - xpd unit number
+# UNIT_SUBUNITS - number of subunits in this xpd
+# UNIT_TYPE - xpd type number (from protocol reply):
+# 1 - FXS
+# 2 - FXO
+# 3 - BRI
+# 4 - PRI
+# XBUS_REVISION - xbus revision number
+# XBUS_CONNECTOR - xbus connector string
+#
+# 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.
+# 5. Data byte in hexadecimal. (for WD command only).
+#
+
+package main;
+use File::Basename;
+use Getopt::Std;
+
+my $program = basename("$0");
+my $init_dir = dirname("$0");
+my $unit_id;
+my %opts;
+$ENV{XPP_BASE} = '/proc/xpp';
+my @pri_specs;
+
+getopts('o:', \%opts);
+
+sub logit {
+ print STDERR "$unit_id: @_\n";
+}
+
+# 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 select_subunit($) {
+ my $subunit = shift;
+ die unless defined $subunit;
+ my $output;
+
+ if($opts{o}) {
+ $output = $opts{o};
+ } else {
+ my $xpd_name = sprintf("XPD-%1d%1d", $ENV{UNIT_NUMBER}, $subunit);
+ $output = "$ENV{XPP_BASE}/$ENV{XBUS_NAME}/$xpd_name/chipregs";
+ }
+ open(REG, ">$output") || die "Failed to open '$output': $!\n";
+ my $oldfh = select REG;
+ print "# Selecting subunit $subunit\n" if $opts{o};
+ return $oldfh;
+}
+
+package PRI;
+
+sub gen {
+ my $fmt = shift;
+ $| = 1;
+ printf "$fmt\n", @_;
+}
+
+sub init_quad() {
+ main::select_subunit(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
+}
+
+sub finish_quad() {
+ 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 WD 80 00"; # PC1 (Port configuration 1): RPB_1.SYPR , XPB_1.SYPX
+ PRI::gen "0 WD 81 0B"; # PC2 (Port configuration 2): RPB_1.GPOH (ResetID ), XPB_1.GPOL (MUX_SEL0)
+ PRI::gen "0 WD 82 9B"; # PC3 (Port configuration 3): RPC_1.GPI (nConfig0), XPC_1.GPOL (MUX_SEL1)
+ PRI::gen "0 WD 83 9B"; # PC4 (Port configuration 4): RPD_1.GPI (nConfig1), XPD_1.GPOL (MUX_SEL2)
+}
+
+sub read_pri_specs() {
+ # 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
+ #main::logit "From $default_file: $setup_var=\n$setup_string";
+ @pri_specs = split(/\s+/, $setup_string);
+ push(@pri_specs, 'NUM/*=TE,E1'); # Fall back default (last)
+ main::logit "pri_specs: @pri_specs";
+}
+
+package PRI::Port;
+
+sub new {
+ my $pack = shift;
+ my $port = { @_ };
+ bless $port, $pack;
+ $port->process_pri_spec;
+ return $port;
+}
+
+sub write_pri_info {
+ my $port = shift;
+ my $subunit = $port->{PORT_NUM};
+ my @pri_setup = @{$port->{PRI_SETUP}};
+ my $pri_type = $pri_setup[0] || die "Missing pri_type parameter";
+ my $pri_proto = $pri_setup[1] || die "Missing pri_proto parameter";
+ my $xpd_name = "XPD-$ENV{UNIT_NUMBER}$subunit";
+ my $info = "$ENV{XPP_BASE}/$ENV{XBUS_NAME}/$xpd_name/pri_info";
+
+ main::logit "$xpd_name: PRI_SETUP $pri_type $pri_proto";
+ 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";
+}
+
+sub process_pri_spec($) {
+ my $port = shift;
+ my $subunit = $port->{PORT_NUM};
+ my $xpd_name = "XPD-$ENV{UNIT_NUMBER}$subunit";
+ my $match;
+ my $setup;
+ my @pri_setup;
+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}/$xpd_name",
+ "NUM/$ENV{XBUS_NAME}/$xpd_name"
+ );
+ foreach my $pattern (@patlist) {
+ #logit "testmatch: $pattern =~ $match";
+ if($pattern =~ $match) {
+ main::logit "$xpd_name: MATCH '$pattern' ~ '$match' setup=$setup";
+ last SPEC;
+ }
+ }
+ }
+ die "No setup matching $ENV{XBUS_NAME}/$xpd_name\n" unless defined $setup;
+ @pri_setup = split(/,/, $setup);
+ die "Bad setup string '$setup'\n" unless @pri_setup;
+ $port->{'PRI_SETUP'} = \@pri_setup;
+}
+
+sub port_setup($) {
+ my $port = shift;
+ my $portno = $port->{PORT_NUM};
+
+ # 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;
+
+ PRI::gen "$portno WD 26 F6"; # XPM0: Pulse Shape Programming for R1=18Ohms
+ PRI::gen "$portno WD 27 02"; # XPM1: ...3V Pulse Level at the line (Vp-p=6v)
+ PRI::gen "$portno WD 28 00"; # XPM2: ~XLT (transmit line is not in the high impedance state)
+
+ # if (unchannelized)
+ #PRI::gen "$portno WD 1F 22"; # LOOP (Channel Looback):
+ # ECLB (Enable Channel Loop-Back)
+ # CLA (Channel Address)
+ PRI::gen "$portno WD 2B EF"; # IDL (Idle):
+ # If channel loopback is enabled than transmit this code on the outgoing
+ PRI::gen "$portno WD 1F 00"; # LOOP (Channel Looback):
+ #if($portno eq 0){
+ # PRI::gen "0 WD 1F 00"; # LOOP (Channel Looback):
+ # # channels (XL1/XL2)
+ #}else {
+ # PRI::gen "0 WD 1F 20"; # LOOP (Channel Looback):
+ #}
+
+ PRI::gen "$portno WD 37 %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 "$portno WD 3A 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 "$portno WD 38 0A"; # PCD: (Pulse Count Detection, LOS Detection after 176 consecutive 0s)
+ PRI::gen "$portno WD 39 15"; # PCR: (Pulse Count Recovery, LOS Recovery after 22 ones in PCD interval)
+
+ # Configure system interface
+ PRI::gen "$portno WD 3E 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 "$portno WD 40 04"; # SIC3: Edges for capture, Synchronous Pulse Receive @Rising Edge
+ PRI::gen "$portno WD 41 04"; # CMR4: RCLK is 8.192 MHz
+ PRI::gen "$portno WD 43 04"; # CMR5: TCLK is 8.192 MHz
+ PRI::gen "$portno WD 44 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 "$portno WD 22 00"; # XC0: (Transmit Counter Offset = 497/T=2)
+ PRI::gen "$portno WD 23 04"; # XC1:
+
+ PRI::gen "$portno WD 24 00"; # RC0: (Receive Counter Offset = 497/T=2)
+ PRI::gen "$portno WD 25 05"; # RC1:
+
+ my $sic2 = sprintf("%x", 0x00 | ($portno << 1));
+
+ PRI::gen "$portno WD 3F $sic2"; # SIC2: No FFS, no center receive elastic buffer, data active at phase ($sic >> 1)
+
+ # enable the following interrupt sources
+ PRI::gen "$portno WD 16 00"; # IMR2 (Interrupt Mask Register2): Enable ALL
+
+ PRI::gen "$portno WD 17 3F"; # IMR3 ~ES, ~SEC (Enable ES and SEC interrupts)
+ PRI::gen "$portno WD 18 00"; # IMR4: Enable ALL
+
+ PRI::gen "$portno WD 08 04"; # IPC: SYNC is 8 Khz
+
+ PRI::gen "$portno WD 02 51"; # CMDR (Command Register): RRES, XRES, SRES (Receiver/Transmitter reset)
+ PRI::gen "$portno WD 02 00"; # CMDR
+
+
+ # Configure interrupts
+ PRI::gen "$portno WD 46 40"; # GCR: Interrupt on Activation/Deactivation of AIX, LOS
+
+ PRI::gen "$portno WD 45 00"; # CMR2: External sources for SYPR, SCLKR, SYPX, SCLKX for TX and RX.
+ #PRI::gen "$portno WD 22 00"; # XC0: Normal operation of Sa-bits
+ #PRI::gen "$portno WD 23 04"; # XC1: X=4 => T=4-X=0 offset
+ #PRI::gen "$portno WD 24 00"; # RC0: 0 offset
+ #PRI::gen "$portno WD 25 00"; # RC1: Remaining part of RC0
+
+ # Configure ports
+ PRI::gen "$portno WD 85 80"; # GPC1 (Global Port Configuration 1):
+ #PRI::gen "$portno WD 85 00"; # GPC1 (Global Port Configuration 1):
+ # SMM (System Interface Multiplex Mode)
+ PRI::gen "$portno WD 80 00"; # PC1: SYPR/SYPX provided to RPA/XPA inputs
+
+ PRI::gen "$portno WD 84 31"; # PC5: XMFS active low, SCLKR is input, RCLK is output (unused)
+ PRI::gen "$portno WD 86 03"; # PC6: CLK1 is Tx Clock output, CLK2 is 8.192 Mhz from DCO-R
+ PRI::gen "$portno WD 3B 00"; # Clear LCR1 - Loop Code Register 1
+
+ # printk("TE110P: Successfully initialized serial bus for card\n");
+
+ # Initialize PCM and SIG regs
+ PRI::gen "$portno WD A0 00"; # TSEO (Time Slot Even/Odd Select)
+ PRI::gen "$portno WD A1 FF"; # TSBS (Time Slot Bit Select)- only selected bits are used for HDLC channel 1
+ # in selected time slots
+ PRI::gen "$portno WD 03 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 "$portno WD 09 18"; # CCR1 (Common Configuration Register1)
+ # EITS (Enable Internal Time Slot 0 to 31 Signalling)
+ # ITF (Interframe Time Fill)
+ PRI::gen "$portno WD 0A 04"; # CCR2 (Common Configuration Register2)
+ # RCRC (enable CRC - HDLC channel 1enable CRC - HDLC channel 1)
+ PRI::gen "$portno WD 0C 00"; # RTR1 (Receive Time Slot register 1)
+ PRI::gen "$portno WD 0D 00"; # RTR2 (Receive Time Slot register 2)
+ PRI::gen "$portno WD 0E 00"; # RTR3 (Receive Time Slot register 3), TS16 (Enable time slot 16)
+ PRI::gen "$portno WD 0F 00"; # RTR4 (Receive Time Slot register 4)
+
+ PRI::gen "$portno WD 10 00"; # TTR1 (Transmit Time Slot register 1)
+ PRI::gen "$portno WD 11 00"; # TTR2 (Transmit Time Slot register 2)
+ PRI::gen "$portno WD 12 00"; # TTR3 (Transmit Time Slot register 3), TS16 (Enable time slot 16)
+ PRI::gen "$portno WD 13 00"; # TTR4 (Transmit Time Slot register 4)
+
+ # configure the best performance of the Bipolar Violation detection for all four channels
+ PRI::gen "$portno WD BD 00"; # BFR (Bugfix Register): ~BVP (Bipolar Violations),
+ # use Improved Bipolar Violation Detection instead
+}
+
+package main;
+BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/zconf"); }
+use Zaptel::Config::Defaults;
+
+logit "Starting '$0'";
+
+PRI::read_pri_specs;
+
+sub main() {
+ my @ports;
+ my $subunit;
+
+ logit "main(): Initializing chip ($ENV{UNIT_SUBUNITS} ports)";
+ PRI::init_quad;
+ # Must initialize all 4 ports, regardless how much there are
+ for($subunit = 0; $subunit < 4; $subunit++) {
+ my $is_nt = 0;
+
+ #logit "main(): Initializing subunit $subunit is_nt=$is_nt";
+ my $p = PRI::Port->new(
+ 'PORT_NUM' => $subunit,
+ 'PRI_NT' => $is_nt,
+ 'EXIST' => ($subunit < $ENV{UNIT_SUBUNITS})
+ );
+ $p->port_setup;
+ push(@ports, $p);
+ }
+ PRI::finish_quad;
+ foreach my $p (@ports) {
+ if($p->{EXIST}) {
+ $p->write_pri_info;
+ }
+ }
+}
+
+main;
+
+logit "Ending '$0'";
+
+close REG;
+close STDERR;
+exit 0;