From 18c6813f2c788b603dab363b9138d65d24252167 Mon Sep 17 00:00:00 2001 From: tzafrir Date: Wed, 27 May 2009 10:01:24 +0000 Subject: Big dump of newer xpp code. For finer details and separate commits, you are advised to look into the commit log of dahdi-{linux,tools}. xpp.r7150 * 116x Astribanks: - Support for the TwinStar capability and for FXO and (BRI|PRI) on same device. - New control protocol ("MPP"). - astribank_hextool - a low-level firmware loading tool instead of fpga_load . - astribank_tool - Other MPP activities . - Can still reset (but just that) through older protocol. - astribank_hexload is required for loading FPGA firmware for USB_FW.hex rev > 6885. - USB_FW rev. 7071 . - More modular FPGA firmware (1161 only). - FPGA_1161.hex rev. 7131. PIC_TYPE_* rev. 7107. - software-settings of some capabilities with astribank_allow . * XPP: - init_card_* script are less verbose. - Reduced rate of "Is a DAHDI sync master" message. - Replace member bus_id with dev_name() and set_dev_name() for building with 2.6.30. - Conditionally remove 'owner' property of procfs was dropped in 2.6.30. - astribank_hook now enabled by default. - Has an optional hook for TwinStar. * BRI: - hardhdlc support: The bri_dchan patch is no longer needed. - If bri_dchan patch applied: old code is used, and "dchan" is used. - If not: new code and "hardhdlc" is used. - zapconf will generate the right configuration, depending on the new sysfs driver attribute bri_hardhdlc, but default to "dchan" as before if not explicitly told. - Bugfix: explicitly turn off leds on startup. * FXS: - Initialization and calibration fixes. - Notify the user just one about wrong VMWI config * Dahdi-perl: - Fix detection of empty slots in wctdm. - Fix working with ethmf's extra file in /proc/zaptel - Improved detection of Rhino cards. - dahdi_genconf's generated text better explains files are generated. - /etc/xpp_order - allow specifiying an explicit order for Astribanks to register with Zaptel. - Dahdi::Xpp::Mpp - A wrapper around astribank_tool . * dahdi.init: - A separate waitfor_xpds script. May now have a wait-loop in some cases. - xpp_sync needs to only be called after dahdi_cfg . (for the PRI module). git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@4641 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- kernel/xpp/utils/zconf/Zaptel.pm | 1 + kernel/xpp/utils/zconf/Zaptel/Chans.pm | 10 +- .../xpp/utils/zconf/Zaptel/Config/Gen/Unicall.pm | 4 +- kernel/xpp/utils/zconf/Zaptel/Config/Gen/Users.pm | 2 + .../xpp/utils/zconf/Zaptel/Config/Gen/Xpporder.pm | 142 +++++++++++++ kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zapata.pm | 4 +- kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zaptel.pm | 47 ++++- kernel/xpp/utils/zconf/Zaptel/Config/Params.pm | 2 +- kernel/xpp/utils/zconf/Zaptel/Hardware.pm | 95 +++++++-- kernel/xpp/utils/zconf/Zaptel/Hardware/PCI.pm | 12 +- kernel/xpp/utils/zconf/Zaptel/Hardware/USB.pm | 88 +++++--- kernel/xpp/utils/zconf/Zaptel/Span.pm | 5 +- kernel/xpp/utils/zconf/Zaptel/Xpp.pm | 93 ++++++++- kernel/xpp/utils/zconf/Zaptel/Xpp/Mpp.pm | 221 +++++++++++++++++++++ kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm | 31 ++- kernel/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm | 24 ++- 16 files changed, 687 insertions(+), 94 deletions(-) create mode 100644 kernel/xpp/utils/zconf/Zaptel/Config/Gen/Xpporder.pm create mode 100644 kernel/xpp/utils/zconf/Zaptel/Xpp/Mpp.pm (limited to 'kernel/xpp/utils/zconf') diff --git a/kernel/xpp/utils/zconf/Zaptel.pm b/kernel/xpp/utils/zconf/Zaptel.pm index 1b73d5b..a7784f9 100644 --- a/kernel/xpp/utils/zconf/Zaptel.pm +++ b/kernel/xpp/utils/zconf/Zaptel.pm @@ -46,6 +46,7 @@ sub spans() { -d $proc_base or return (); foreach my $zfile (glob "$proc_base/*") { $zfile =~ s:$proc_base/::; + next unless ($zfile =~ /^\d+$/); my $span = Zaptel::Span->new($zfile); push(@spans, $span); } diff --git a/kernel/xpp/utils/zconf/Zaptel/Chans.pm b/kernel/xpp/utils/zconf/Zaptel/Chans.pm index aa58d1d..3090b8a 100644 --- a/kernel/xpp/utils/zconf/Zaptel/Chans.pm +++ b/kernel/xpp/utils/zconf/Zaptel/Chans.pm @@ -139,21 +139,25 @@ sub new($$$$$$) { $type = "FXS"; # likely Rhino } elsif ($fqn =~ m{\bFXO/.*}) { $type = "FXO"; # likely Rhino - } elsif ($fqn =~ m{\b---/.*}) { + } elsif ($fqn =~ m{---/.*}) { $type = "EMPTY"; # likely Rhino, empty slot. - } elsif ($fqn =~ m{\b(TE[24]|WCT1|Tor2|TorISA|WP[TE]1|cwain[12])/.*}) { + } elsif ($fqn =~ m{\b(TE[24]|WCT1|Tor2|TorISA|WP[TE]1|cwain[12]|R[124]T1)/.*}) { # 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. + # R[124]: Rhino r1t1/rxt1 cards $type = "PRI"; } elsif ($fqn =~ m{\b(B4|ZTHFC\d*|ztqoz\d*)/.*}) { # B4: The Digium wcb4xxp ZAPTEL driver # ZTHFC: HFC-s single-port card (zaphfc/vzaphfc) # ztqoz: qozap (Junghanns) multi-port HFC card $type = "BRI"; + } elsif ($fqn =~ m{\bZTD/.*}) { + # DYN : Dynamic span (TDMOE) + $type = "ZTD" } elsif ($fqn =~ m{\bztgsm/.*}) { # Junghanns GSM card $type = "GSM"; @@ -189,7 +193,7 @@ sub probe_type($) { my $num = $self->num; my $type; - if($fqn =~ m:WCTDM/| WRTDM/|OPVXA1200/:) { + if($fqn =~ m:WCTDM/|WRTDM/|OPVXA1200/:) { my %maybe; undef %maybe; diff --git a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Unicall.pm b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Unicall.pm index 3e1048d..6d9552f 100644 --- a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Unicall.pm +++ b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Unicall.pm @@ -32,7 +32,9 @@ sub generate($) { print "Generating $file\n" if $genopts->{verbose}; open(F, ">$file") || die "$0: Failed to open $file: $!\n"; my $old = select F; - printf "; Autogenerated by %s on %s -- do not hand edit\n", $0, scalar(localtime); + printf "; Autogenerated by $0 on %s\n", scalar(localtime); + print "; If you edit this file and execute $0 again,\n"; + print "; your manual changes will be LOST.\n"; print "; This file should be #included in unicall.conf\n\n"; foreach my $span (@spans) { next unless $span->is_digital(); diff --git a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Users.pm b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Users.pm index 7c9e937..dbbf9d2 100644 --- a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Users.pm +++ b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Users.pm @@ -88,6 +88,8 @@ sub generate($) { ;! Filename: @{[basename($file)]} ($file) ;! Generator: $0 ;! Creation Date: @{[scalar(localtime)]} +;! If you edit this file and execute $0 again,\n"; +;! your manual changes will be LOST.\n"; ;! [general] ; diff --git a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Xpporder.pm b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Xpporder.pm new file mode 100644 index 0000000..0d34d93 --- /dev/null +++ b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Xpporder.pm @@ -0,0 +1,142 @@ +package Zaptel::Config::Gen::Xpporder; +use strict; + +use Zaptel::Config::Gen qw(is_true); +use Zaptel::Xpp; + +sub new($$$) { + my $pack = shift || die; + my $gconfig = shift || die; + my $genopts = shift || die; + my $file = $ENV{XPPORDER_CONF} || "/etc/xpp_order"; + my $self = { + FILE => $file, + GCONFIG => $gconfig, + GENOPTS => $genopts, + }; + bless $self, $pack; + return $self; +} + +# +# Returns list of xbuses sorted by the span numbers assigned +# to their XPD's. Also checks that each XBUS span numbers are sequential. +sub get_sorted_xbuses(@) { + my @spans = @_; # Verify our spans + my @xbuses = Zaptel::Xpp::xbuses; + my %xbus_of_span; + my %xbus_beginning; + my %seen_spans; + my @sorted_xbuses; + foreach my $xbus (@xbuses) { + my $last_spanno; + foreach my $xpd ($xbus->xpds) { + my $spanno = $xpd->spanno; + if(!$spanno) { + printf STDERR "%s: Is not registered. Skipping.\n", $xpd->fqn; + next; + } + $seen_spans{$spanno}++; + if($xbus_of_span{$spanno}) { + printf STDERR "%s: Span %d already seen on %s\n", + $xpd->fqn, $spanno, $xbus_of_span{$spanno}->name; + die; + } + $xbus_of_span{$spanno} = $xbus; + # Check XPD's sequential numbering + if(defined $last_spanno) { + if($last_spanno + 1 != $spanno) { + printf STDERR "%s: Bad span numbers (%d, %d)\n", + $xpd->fqn, $last_spanno, $spanno; + die; + } + } else { + $xbus_beginning{$xbus} = $spanno; + } + $last_spanno = $spanno; + } + } + foreach my $span (@spans) { + my $spanno = $span->num; + if(!defined($seen_spans{$spanno})) { + warn "Span $spanno: Ignored: Does not belong to any XPD\n"; + } + } + @sorted_xbuses = sort { $xbus_beginning{$a} <=> $xbus_beginning{$b} } @xbuses; + return @sorted_xbuses; +} + +sub generate($$$) { + my $self = shift || die; + my $file = $self->{FILE}; + my $gconfig = $self->{GCONFIG}; + my $genopts = $self->{GENOPTS}; + my @spans = @_; # Verify it's all our spans + my @xbuses = get_sorted_xbuses(@spans); + warn "Empty configuration -- no xbuses\n" unless @xbuses; + rename "$file", "$file.bak" + or $! == 2 # ENOENT (No dependency on Errno.pm) + or die "Failed to backup old config: $!\n"; + #$gconfig->dump; + print "Generating $file\n" if $genopts->{verbose}; + open(F, ">$file") || die "$0: Failed to open $file: $!\n"; + my $old = select F; + printf "# Autogenerated by $0 on %s\n", scalar(localtime); + print "# If you edit this file and execute $0 again,\n"; + print "# your manual changes will be LOST.\n"; + print <<'HEAD'; +# +# This is an optional configuration file for ordering +# Zaptel registration. +# +# It is read from /etc/xpp_order. This location +# may be overridden via the environment variable XPPORDER_CONF +# +# Lines may contain: +# - The Astribank label (verbatim) +# - The Astribank connector string (prefixed with @) +# Ordering number of each listed Astribank is determined +# by its position in this file. +# Astribanks not listed in this file, get an ordering +# number of 99 (last). +# +# Astribanks with same ordering number are sorted by their +# connectors (to preserve legacy behavior). +# +# Examples: +#usb:1234 +#@usb-0000:06:02.2-2 +HEAD + foreach my $xbus (@xbuses) { + my $label = $xbus->label; + my $connector = $xbus->connector; + my $name = $xbus->name; + printf "%s\t# %s (%s)\n", $label, $connector, $name; + } + close F; + select $old; +} + +1; + +__END__ + +=head1 NAME + +Xpporder - Generate Astribank ordering information for zt_registration. + +=head1 SYNOPSIS + + use Zaptel::Config::Gen::Xpporder; + + my $cfg = new Zaptel::Config::Gen::Xpporder(\%global_config, \%genopts); + $cfg->generate; + +=head1 DESCRIPTION + +Generate the F. +This is the configuration for zt_registration(1). +The order is determined according to current Zaptel registration +order. + +Its location may be overriden via the environment variable F. diff --git a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zapata.pm b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zapata.pm index e8fd733..8e0ebce 100644 --- a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zapata.pm +++ b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zapata.pm @@ -140,7 +140,9 @@ sub generate($) { print "Generating $file\n" if $genopts->{verbose}; open(F, ">$file") || die "$0: Failed to open $file: $!\n"; my $old = select F; - printf "; Autogenerated by %s on %s -- do not hand edit\n", $0, scalar(localtime); + printf "; Autogenerated by $0 on %s\n", scalar(localtime); + print "; If you edit this file and execute $0 again,\n"; + print "; your manual changes will be LOST.\n"; print <<"HEAD"; ; Zaptel Channels Configurations (zapata.conf) ; diff --git a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zaptel.pm b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zaptel.pm index 2c30c33..892442f 100644 --- a/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zaptel.pm +++ b/kernel/xpp/utils/zconf/Zaptel/Config/Gen/Zaptel.pm @@ -39,11 +39,6 @@ sub gen_digital($$) { $span_crc4 = ''; $framing = 'cas'; } - my $dchan_type = 'dchan'; - if ($span->is_bri() && is_true($gconfig->{'bri_hardhdlc'})) { - $dchan_type = 'hardhdlc'; - } - $timing = ($termtype eq 'NT') ? 0 : $bri_te_last_timing++; printf "span=%d,%d,%d,%s,%s%s%s\n", $num, @@ -54,14 +49,42 @@ sub gen_digital($$) { $span_crc4, $span_yellow; printf "# termtype: %s\n", lc($termtype); - if ($gconfig->{'pri_connection_type'} eq 'PRI') { + my $dchan_type; + if ($span->is_bri()) { + my $use_bristuff = 0; + my $cfg_hardhdlc = $gconfig->{'bri_hardhdlc'}; + my $xpd = $span->xpd(); + if(!defined($cfg_hardhdlc) || $cfg_hardhdlc =~ /AUTO/i) { + # Autodetect + if(defined($xpd)) { + # Bristuff? + if(defined($xpd->dchan_hardhdlc) && !is_true($xpd->dchan_hardhdlc)) { + $use_bristuff = 1; + } + } + } elsif(!is_true($cfg_hardhdlc)) { + $use_bristuff = 1; + } + if($use_bristuff) { + $dchan_type = 'dchan'; + } else { + $dchan_type = 'hardhdlc'; + } printf "bchan=%s\n", Zaptel::Config::Gen::bchan_range($span); my $dchan = $span->dchan(); printf "$dchan_type=%d\n", $dchan->num(); - } elsif ($gconfig->{'pri_connection_type'} eq 'R2' ) { - my $idle_bits = $gconfig->{'r2_idle_bits'}; - printf "cas=%s:$idle_bits\n", Zaptel::Config::Gen::bchan_range($span); - printf "dchan=%d\n", $span->dchan()->num(); + } elsif($span->is_pri()) { + if ($gconfig->{'pri_connection_type'} eq 'PRI') { + printf "bchan=%s\n", Zaptel::Config::Gen::bchan_range($span); + my $dchan = $span->dchan(); + printf "dchan=%d\n", $dchan->num(); + } elsif ($gconfig->{'pri_connection_type'} eq 'R2' ) { + my $idle_bits = $gconfig->{'r2_idle_bits'}; + printf "cas=%s:$idle_bits\n", Zaptel::Config::Gen::bchan_range($span); + printf "dchan=%d\n", $span->dchan()->num(); + } + } else { + die "Digital span $num is not BRI, nor PRI?"; } } @@ -100,7 +123,9 @@ sub generate($$$) { print "Generating $file\n" if $genopts->{verbose}; open(F, ">$file") || die "$0: Failed to open $file: $!\n"; my $old = select F; - printf "# Autogenerated by %s on %s -- do not hand edit\n", $0, scalar(localtime); + printf "# Autogenerated by $0 on %s\n", scalar(localtime); + print "# If you edit this file and execute $0 again,\n"; + print "# your manual changes will be LOST.\n"; print <<"HEAD"; # Zaptel Configuration File # diff --git a/kernel/xpp/utils/zconf/Zaptel/Config/Params.pm b/kernel/xpp/utils/zconf/Zaptel/Config/Params.pm index 7f6ae80..35ded3b 100644 --- a/kernel/xpp/utils/zconf/Zaptel/Config/Params.pm +++ b/kernel/xpp/utils/zconf/Zaptel/Config/Params.pm @@ -106,7 +106,7 @@ sub item($$) { brint_overlap => 'no', bri_sig_style => 'bri_ptmp', echo_can => 'mg2', - bri_hardhdlc => 'no', + bri_hardhdlc => 'auto', pri_connection_type => 'PRI', r2_idle_bits => '1101', 'pri_termtype' => [ 'SPAN/* TE' ], diff --git a/kernel/xpp/utils/zconf/Zaptel/Hardware.pm b/kernel/xpp/utils/zconf/Zaptel/Hardware.pm index ff7aeea..b12368b 100644 --- a/kernel/xpp/utils/zconf/Zaptel/Hardware.pm +++ b/kernel/xpp/utils/zconf/Zaptel/Hardware.pm @@ -8,8 +8,6 @@ package Zaptel::Hardware; # $Id$ # use strict; -use Zaptel::Hardware::USB; -use Zaptel::Hardware::PCI; =head1 NAME @@ -44,6 +42,7 @@ system. It identifies devices by (USB/PCI) bus IDs. =head1 Device Attributes + As usual, object attributes can be used in either upp-case or lower-case, or lower-case functions. @@ -92,22 +91,27 @@ attributes). Astribank. =cut +# +# A global hardware handle +# -sub device_detected($$) { - my $dev = shift || die; - my $name = shift || die; - die unless defined $dev->{'BUS_TYPE'}; +my %hardware_list = ( + 'PCI' => [], + 'USB' => [], + ); + + +sub new($$) { + my $pack = shift || die "Wasn't called as a class method\n"; + my $name = shift || die "$0: Missing device name"; + my $type = shift || die "$0: Missing device type"; + my $dev = {}; + $dev->{'BUS_TYPE'} = $type; $dev->{IS_ASTRIBANK} = 0 unless defined $dev->{'IS_ASTRIBANK'}; $dev->{'HARDWARE_NAME'} = $name; + return $dev; } -sub device_removed($) { - my $dev = shift || die; - my $name = $dev->hardware_name; - die "Missing zaptel device hardware name" unless $name; -} - - =head1 device_list() Returns a list of the hardware devices on the system. @@ -117,17 +121,28 @@ You must run scan() first for this function to run meaningful output. =cut sub device_list($) { - my $self = shift || die; + my $pack = shift || die; my @types = @_; my @list; @types = qw(USB PCI) unless @types; foreach my $t (@types) { - @list = ( @list, @{$self->{$t}} ); + my $lst = $hardware_list{$t}; + @list = ( @list, @{$lst} ); } return @list; } +sub device_by_hwname($$) { + my $pack = shift || die; + my $name = shift || die; + my @list = device_list('localcall'); + + my @good = grep { $_->hardware_name eq $name } @list; + return undef unless @good; + @good > 1 && die "$pack: Multiple matches for '$name': @good"; + return $good[0]; +} =head1 drivers() @@ -139,7 +154,7 @@ loaded. sub drivers($) { my $self = shift || die; - my @devs = $self->device_list; + my @devs = device_list('localcall'); my @drvs = map { $_->{DRIVER} } @devs; # Make unique my %drivers; @@ -155,14 +170,52 @@ must be run to initialize the module. =cut +my $hardware_scanned; + 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; + return if $hardware_scanned++; + foreach my $type (qw(PCI USB)) { + eval "use Zaptel::Hardware::$type"; + die $@ if $@; + $hardware_list{$type} = [ "Zaptel::Hardware::$type"->scan_devices ]; + } +} + +sub import { + Zaptel::Hardware->scan unless grep(/\bnoscan\b/i, @_); +} + +sub showall { + my $pack = shift || die; + my @devs; + + my $printer = sub { + my $title = shift; + my @devs = @_; + + return unless @devs; + printf "%s:\n", $title; + foreach my $dev (@devs) { + printf "\t%s\n", $dev->hardware_name; + foreach my $k (sort keys %{$dev}) { + my $v = $dev->{$k}; + if($k eq 'MPPINFO') { + printf "\t\tMPPINFO:\n"; + eval "use Zaptel::Xpp::Mpp"; + die $@ if $@; + $v->showinfo("\t\t "); + } else { + printf "\t\t%-20s %s\n", $k, $v; + } + } + } + }; + foreach my $type (qw(USB PCI)) { + my $lst = $hardware_list{$type}; + &$printer("$type devices", @{$lst}); + } } 1; diff --git a/kernel/xpp/utils/zconf/Zaptel/Hardware/PCI.pm b/kernel/xpp/utils/zconf/Zaptel/Hardware/PCI.pm index e9166c7..73e3e71 100644 --- a/kernel/xpp/utils/zconf/Zaptel/Hardware/PCI.pm +++ b/kernel/xpp/utils/zconf/Zaptel/Hardware/PCI.pm @@ -134,12 +134,13 @@ 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 = { @_ }; +sub new($@) { + my $pack = shift || die "Wasn't called as a class method\n"; + my %attr = @_; + my $name = sprintf("pci:%s", $attr{PRIV_DEVICE_NAME}); + my $self = Zaptel::Hardware->new($name, 'PCI'); + %{$self} = (%{$self}, %attr); bless $self, $pack; - Zaptel::Hardware::device_detected($self, - sprintf("pci:%s", $self->{PRIV_DEVICE_NAME})); return $self; } @@ -197,7 +198,6 @@ sub scan_devices($) { 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}, diff --git a/kernel/xpp/utils/zconf/Zaptel/Hardware/USB.pm b/kernel/xpp/utils/zconf/Zaptel/Hardware/USB.pm index a2dc08f..4ac0c17 100644 --- a/kernel/xpp/utils/zconf/Zaptel/Hardware/USB.pm +++ b/kernel/xpp/utils/zconf/Zaptel/Hardware/USB.pm @@ -10,8 +10,7 @@ package Zaptel::Hardware::USB; use strict; use Zaptel::Utils; use Zaptel::Hardware; -use Zaptel::Xpp; -use Zaptel::Xpp::Xbus; +use Zaptel::Xpp::Mpp; our @ISA = qw(Zaptel::Hardware); @@ -34,46 +33,83 @@ my %usb_ids = ( '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' }, + + # Sangoma USB FXO: + '10c4:8461' => { DRIVER => 'wanpipe', DESCRIPTION => 'Sangoma WANPIPE USB-FXO Device' }, ); $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; +sub mpp_addinfo($) { + my $self = shift || die; - my ($wanted) = grep { - defined($_->usb_devname) && - $priv_device_name eq $_->usb_devname - } @xbuses; - return $wanted; + my $mppinfo = Zaptel::Xpp::Mpp->new($self); + $self->{MPPINFO} = $mppinfo if defined $mppinfo; } -sub new($$) { +sub new($@) { my $pack = shift or die "Wasn't called as a class method\n"; - my $self = { @_ }; + my %attr = @_; + my $name = sprintf("usb:%s", $attr{PRIV_DEVICE_NAME}); + my $self = Zaptel::Hardware->new($name, 'USB'); + %{$self} = (%{$self}, %attr); 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($) { +sub readval($) { + my $fname = shift || warn; + open(F, $fname) || warn "Failed opening '$fname': $!"; + my $val = ; + close F; + chomp $val; + warn "$fname is empty" unless defined $val and $val; + return $val; +} + +sub set_transport($$) { + my $pack = shift || die; + my $xbus = shift || die; + my $xbus_dir = shift; + my $transportdir = "$xbus_dir/transport"; + my $hwdev; + if(! -e "$transportdir/ep_00") { + warn "A trasnport in '$transportdir' is not USB"; + return undef; + } + my ($usbdev) = glob("$transportdir/usb_device:*"); + my $busnum; + my $devnum; + # Different kernels... + if(defined $usbdev) { # It's USB + if($usbdev =~ /.*usb_device:usbdev(\d+)\.(\d+)/) { + $busnum = $1; + $devnum = $2; + } else { + warn "Bad USB transportdir='$transportdir' usbdev='$usbdev'\n"; + } + } elsif(-d "$transportdir/usb_endpoint") { + $busnum = readval("$transportdir/busnum"); + $devnum = readval("$transportdir/devnum"); + } + my $usbname = sprintf("%03d/%03d", $busnum, $devnum); + #printf STDERR "DEBUG: %03d/%03d\n", $busnum, $devnum; + $xbus->{USB_DEVNAME} = $usbname; + $hwdev = Zaptel::Hardware->device_by_hwname("usb:$usbname"); + #print "set_transport: ", $hwdev, "\n"; + $xbus->{TRANSPORT} = $hwdev; + $hwdev->{XBUS} = $xbus; + $hwdev->{LOADED} = 'xpp_usb'; + $xbus->{IS_TWINSTAR} = $hwdev->is_twinstar; + return $hwdev; +} + +sub scan_devices($) { my $pack = shift || die; my $usb_device_list = "/proc/bus/usb/devices"; return unless (-r $usb_device_list); @@ -99,7 +135,6 @@ sub devices($) { 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, @@ -111,6 +146,7 @@ sub devices($) { } close F; @devices = sort usb_sorter @devices; + return @devices; } 1; diff --git a/kernel/xpp/utils/zconf/Zaptel/Span.pm b/kernel/xpp/utils/zconf/Zaptel/Span.pm index c771a26..23e02b6 100644 --- a/kernel/xpp/utils/zconf/Zaptel/Span.pm +++ b/kernel/xpp/utils/zconf/Zaptel/Span.pm @@ -95,7 +95,7 @@ Suggested sane framing type (e.g.: "ccs", "esf") for this type of span. =head2 yellow(), crc4() Likewise, suggestions ofr the respective fields in the span= line in -zaptel.conf for this span. +/etc/zaptel.conf for this span. =head2 signalling() @@ -147,6 +147,9 @@ my @pri_strings = ( 'Wildcard TE121', # wcte12xp 'Wildcard TE122', # wcte12xp 'T[24]XXP \(PCI\) Card ', # wct4xxp + 'R[24]T1 \(PCI\) Card', # rxt1 + 'Rhino R1T1 (E1)/PRA Card', # r1t1 + 'Rhino R1T1 (T1)/PRI Card', # r1t1 ); our $ZAPBRI_NET = 'bri_net'; diff --git a/kernel/xpp/utils/zconf/Zaptel/Xpp.pm b/kernel/xpp/utils/zconf/Zaptel/Xpp.pm index b626bfa..8473b79 100644 --- a/kernel/xpp/utils/zconf/Zaptel/Xpp.pm +++ b/kernel/xpp/utils/zconf/Zaptel/Xpp.pm @@ -8,6 +8,7 @@ package Zaptel::Xpp; # $Id$ # use strict; +use Zaptel::Hardware; use Zaptel::Xpp::Xbus; =head1 NAME @@ -28,12 +29,29 @@ Zaptel::Xpp - Perl interface to the Xorcom Astribank drivers. } =cut +# +# A global handle for all xbuses +# +my @xbuses; my $proc_base = "/proc/xpp"; our $sysfs_astribanks = "/sys/bus/astribanks/devices"; our $sysfs_xpds = "/sys/bus/xpds/devices"; our $sysfs_ab_driver = "/sys/bus/astribanks/drivers/xppdrv"; +sub scan($) { + my $pack = shift || die; + + opendir(D, $sysfs_astribanks) || return(); + while(my $entry = readdir D) { + next unless $entry =~ /xbus-(\d+)/; + my $xbus = Zaptel::Xpp::Xbus->new($1); + push(@xbuses, $xbus); + } + closedir D; + return @xbuses; +} + # Nominal sorters for xbuses sub by_name { return $a->name cmp $b->name; @@ -72,6 +90,11 @@ sub by_type { return $res; } +sub by_xpporder { + my $cmp = $a->xpporder cmp $b->xpporder; + return $cmp if $cmp != 0; + return $a->connector cmp $b->connector; +} =head1 xbuses([sort_order]) @@ -91,6 +114,19 @@ The built in sorters are: =over +=item SORT_XPPORDER + +Sort by ordering defined in F file. +Astribanks can be listed in this file by their label or by +their connector string (prefixed with <@>). + +Astribanks not listed in the F file are sorted +via ordering number 999 -- So they come after the Astribanks +that are listed. + +Astribanks with same ordering number (e.g: 999) are sorted +by their connector string (to preserve legacy behaviour). + =item SORT_CONNECTOR Sort by the connector string. For USB this defines the "path" to get to @@ -129,38 +165,73 @@ sub sorters { SORT_NAME => \&by_name, SORT_LABEL => \&by_label, SORT_TYPE => \&by_type, + SORT_XPPORDER => \&by_xpporder, # Aliases connector => \&by_connector, name => \&by_name, label => \&by_label, type => \&by_type, + xpporder => \&by_xpporder, ); my $which_sorter = shift || return sort keys %sorter_table; return $which_sorter if ref($which_sorter) eq 'CODE'; return $sorter_table{$which_sorter}; } +sub add_xpporder(@) { + my @xbuses = @_; + my $cfg = $ENV{XPPORDER_CONF} || '/etc/xpp_order'; + my %order; + + # Set defaults + foreach my $xbus (@xbuses) { + $xbus->{XPPORDER} = 99; + } + # Read from optional config file + if(!open(F, $cfg)) { + warn "$0: Failed opening '$cfg': $!" + unless $! == 2; # ENOENT + return; + } + my $count = 1; + while() { + chomp; + s/#.*//; + s/^\s*//; + s/\s*$//; + next unless /\S/; + $order{$_} = $count++; + } + close F; + # Overrides from config file + foreach my $xbus (@xbuses) { + my $label = $xbus->label; + my $connector = '@' . $xbus->connector; + my $val; + $val = $order{$label}; + $val = $order{$connector} unless defined $val; + $xbus->{XPPORDER} = $val if defined $val; + } +} + sub xbuses { - my $optsort = shift || 'SORT_CONNECTOR'; - my @xbuses; + my $optsort = shift || 'SORT_XPPORDER'; + my @sorted_xbuses; - opendir(D, $sysfs_astribanks) || return(); - while(my $entry = readdir D) { - next unless $entry =~ /xbus-(\d+)/; - my $xbus = Zaptel::Xpp::Xbus->new($1); - push(@xbuses, $xbus); + if(! @xbuses) { + @xbuses = Zaptel::Xpp->scan(); } - closedir D; + add_xpporder(@xbuses); my $sorter = sorters($optsort); die "Unknown optional sorter '$optsort'" unless defined $sorter; - @xbuses = sort $sorter @xbuses; - return @xbuses; + @sorted_xbuses = sort $sorter @xbuses; + return @sorted_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 $xbus (Zaptel::Xpp::xbuses) { foreach my $xpd ($xbus->xpds()) { return $xpd if $xpd->fqn eq $span->name; } diff --git a/kernel/xpp/utils/zconf/Zaptel/Xpp/Mpp.pm b/kernel/xpp/utils/zconf/Zaptel/Xpp/Mpp.pm new file mode 100644 index 0000000..44807bd --- /dev/null +++ b/kernel/xpp/utils/zconf/Zaptel/Xpp/Mpp.pm @@ -0,0 +1,221 @@ +package Zaptel::Xpp::Mpp; +# +# Written by Oron Peled +# Copyright (C) 2009, 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::Utils; + +=head1 NAME + +Zaptel::Xpp::Mpp - Perl interface to C + +=head1 DESCRIPTION + +This package uses C to collect information +about Astribanks via MPP (Management Processor Protocol). + +The binary default location is F. It may be +overridden via module parameter C and the +C environment variable (higher priority). + +It may also be set/unset from code via the set_astribank_tool() method. + +=head1 METHODS + +=head2 mpp_addinfo() + +Called with a list of C objects and augment their +data with C objects. + +This method is the normal external interface of this class. + +=head2 new() + +Constructor. Receive as parameter an instance of C class +and return a C object. + +Normally, used indirectly via the mpp_addinfo() method. + +=head2 set_astribank_tool() + +Override default location of astribank_tool(8). It is legal +to set it to C. + +=head2 showinfo() + +Dump an C object for debugging. + +=cut + +my $astribank_tool = '/usr/sbin/astribank_tool'; + +sub set_astribank_tool($$) { + my $pack = shift || die; + $pack eq 'Zaptel::Xpp::Mpp' or die "$0: Called from wrong package? ($pack)"; + my $arg = shift; + $astribank_tool = $arg; + #print STDERR "Setting astribank_tool='$astribank_tool'\n"; +} + +sub import { + my ($param) = grep(/^astribank_tool=/, @_); + if(defined $param) { + $param =~ s/^astribank_tool=//; + $astribank_tool = $param; + } + if(defined $ENV{ASTRIBANK_TOOL}) { + $astribank_tool = $ENV{ASTRIBANK_TOOL}; + } +} + +sub showinfo($$) { + my $self = shift || die; + my $prefix = shift || die; + + return unless defined $self; + foreach my $k (sort keys %{$self}) { + my $v = $self->{$k}; + if(ref($v) eq 'ARRAY') { + my @a = @{$v}; + my $i; + my $ki; + for($i = 0; $i < @a; $i++) { + $ki = sprintf "%s[%d]", $k, $i; + printf "$prefix%-20s %s\n", $ki, $a[$i]; + } + } else { + if($k eq 'DEV') { + printf "$prefix%-20s -> %s\n", $k, $v->hardware_name; + } else { + printf "$prefix%-20s %s\n", $k, $v; + } + } + } +} + +sub astribank_tool_cmd($) { + my $dev = shift || die; + my $usb_top; + + # Find USB bus toplevel + $usb_top = '/dev/bus/usb'; + $usb_top = '/proc/bus/usb' unless -d $usb_top; + die "No USB toplevel found\n" unless -d $usb_top; + my $name = $dev->priv_device_name(); + die "$0: Unkown private device name" unless defined $name; + my $path = "$usb_top/$name"; + return ($astribank_tool, '-D', "$path"); +} + +sub new($$$) { + my $pack = shift || die; + my $dev = shift || die; + my $product = $dev->product; + + return undef unless $dev->is_astribank; + return undef unless $dev->bus_type eq 'USB'; + return undef unless $product =~ /116./; + my $mppinfo = { + DEV => $dev, + HAS_MPP => 1, + }; + bless $mppinfo, $pack; + #print STDERR "$astribank_tool($path) -- '$product'\n"; + if(! -x $astribank_tool) { + warn "Could not run '$astribank_tool'\n"; + return $mppinfo; + } + return $mppinfo unless $product =~ /116[12]/; + $mppinfo->{'MPP_TALK'} = 1; + my @cmd = astribank_tool_cmd($dev); + my $name = $dev->priv_device_name(); + my $dbg_file = "$name"; + $dbg_file =~ s/\W/_/g; + #$dbg_file = "/tmp/twinstar-debug-$dbg_file"; + $dbg_file = "/dev/null"; + unless(open(F, "@cmd 2> '$dbg_file' |")) { + warn "Failed running '$astribank_tool': $!"; + return undef; + } + local $/ = "\n"; + local $_; + while() { + chomp; + #printf STDERR "'%s'\n", $_; + if(s/^INFO:\s*//) { + $mppinfo->{'PROTOCOL'} = $1 if /^protocol\s+version:\s*(\d+)/i; + } elsif(s/^EEPROM:\s*//) { + $mppinfo->{'EEPROM_RELEASE'} = $1 if /^release\s*:\s*([\d\.]+)/i; + $mppinfo->{'EEPROM_LABEL'} = $1 if /^label\s*:\s*([\w._'-]+)/i; + } elsif(s/^Extrainfo:\s+:\s*(.+?)$//) { + $mppinfo->{'EEPROM_EXTRAINFO'} = $1; + } elsif(s/^Capabilities:\s*TwinStar\s*:\s*(.+?)$//) { + my $cap = $1; + $mppinfo->{'TWINSTAR_CAPABLE'} = ($cap =~ /yes/i) ? 1 : 0; + } elsif(s/^TwinStar:\s*//) { + $mppinfo->{'TWINSTAR_PORT'} = $1 if /^connected\s+to\s*:\s*usb-(\d+)/i; + if(s/^USB-(\d+)\s*POWER\s*:\s*//) { + my $v = ($_ eq 'ON') ? 1 : 0; + $mppinfo->{'TWINSTAR_POWER'}->[$1] = $v; + } + if(s/^Watchdog[^:]+:\s*//) { + my $v = ($_ eq 'on-guard') ? 1 : 0; + $mppinfo->{'TWINSTAR_WATCHDOG'} = $v; + } + #printf STDERR "\t%s\n", $_; + } else { + #printf STDERR "\t%s\n", $_; + } + } + unless(close F) { + warn "Failed running '$astribank_tool': $!"; + return undef; + } + #$mppinfo->showinfo; + return $mppinfo; +} + +sub mpp_setwatchdog($$) { + my $mppinfo = shift || die; + my $on = shift; + die "$0: Bad value '$on'" unless defined($on) && $on =~ /^[0-1]$/; + my $dev = $mppinfo->dev || die; + return undef unless defined $mppinfo->mpp_talk; + my $old = $mppinfo->tws_watchdog; + my @cmd = astribank_tool_cmd($dev); + print STDERR "DEBUG($on): '@cmd'\n"; + system(@cmd, '-w', $on); + die "Running $astribank_tool failed: $?" if $?; +} + +sub mpp_jump($) { + my $mppinfo = shift || die; + my $dev = $mppinfo->dev || die; + return undef unless defined $mppinfo->mpp_talk; + my $port = $mppinfo->twinstar_port; + $port = ($port == 1) ? 0 : 1; + die "Unknown TwinStar port" unless defined $port; + my @cmd = astribank_tool_cmd($dev); + system(@cmd, '-p', $port); + die "Running $astribank_tool failed: $?" if $?; +} + +sub mpp_addinfo($@) { + my $pack = shift || die; + my @devlist = @_; + + foreach my $dev (@devlist) { + $dev->{MPPINFO} = $pack->new($dev); + } +} + +1; diff --git a/kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm b/kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm index f87e2aa..9c73404 100644 --- a/kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm +++ b/kernel/xpp/utils/zconf/Zaptel/Xpp/Xbus.pm @@ -9,6 +9,7 @@ package Zaptel::Xpp::Xbus; # use strict; use Zaptel::Utils; +use Zaptel::Hardware; use Zaptel::Xpp::Xpd; my $proc_base = "/proc/xpp"; @@ -87,6 +88,8 @@ sub read_attrs() { if($attr eq 'STATUS') { # Some values are in all caps as well $val = uc($val); + } elsif($attr eq 'CONNECTOR') { + $val =~ s/^/@/; # Add prefix } elsif($attr eq 'LABEL') { # Fix badly burned labels. $val =~ s/[[:^print:]]/_/g; @@ -95,6 +98,19 @@ sub read_attrs() { } } +sub transport_type($$) { + my $xbus = shift || die; + my $xbus_dir = shift; + my $transport = "$xbus_dir/transport"; + if(-e "$transport/ep_00") { # It's USB + $xbus->{TRANSPORT_TYPE} = 'USB'; + } else { + warn "Unkown transport in $xbus_dir\n"; + undef $xbus->{TRANSPORT_TYPE}; + } + return $xbus->{TRANSPORT_TYPE}; +} + sub read_xpdnames_old($) { my $xbus_num = shift || die; my $pat = sprintf "/proc/xpp/XBUS-%02d/XPD-[0-9][0-9]", $xbus_num; @@ -142,16 +158,11 @@ sub new($$) { $self->read_attrs; # Get transport related info my $transport = "$xbus_dir/transport"; - my ($usbdev) = glob("$transport/usb_device:*"); - if(defined $usbdev) { # It's USB - if($usbdev =~ /.*usb_device:usbdev(\d+)\.(\d+)/) { - my $busnum = $1; - my $devnum = $2; - #printf STDERR "DEBUG: %03d/%03d\n", $busnum, $devnum; - $self->{USB_DEVNAME} = sprintf("%03d/%03d", $busnum, $devnum); - } else { - warn "Bad USB transport='$transport' usbdev='$usbdev'\n"; - } + my $transport_type = $self->transport_type($xbus_dir); + if(defined $transport_type) { + my $tt = "Zaptel::Hardware::$transport_type"; + my $hw = $tt->set_transport($self, $xbus_dir); + #printf STDERR "Xbus::new transport($transport_type): %s\n", $hw->{HARDWARE_NAME}; } my @xpdnames; my @xpds; diff --git a/kernel/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm b/kernel/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm index 30a0bad..80478af 100644 --- a/kernel/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm +++ b/kernel/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm @@ -85,6 +85,25 @@ sub xpd_old_getoffhook($) { my %attr_missing_warned; # Prevent duplicate warnings +sub xpd_driver_getattr($$) { + my $xpd = shift || die; + my $attr = shift || die; + $attr = lc($attr); + my ($busnum, $unitnum, $subunitnum) = ($xpd->xbus->num, $xpd->unit, $xpd->subunit); + my $file = sprintf "$Zaptel::Xpp::sysfs_xpds/%02d:%1d:%1d/driver/$attr", + $busnum, $unitnum, $subunitnum; + if(!defined($file)) { + warn "$0: xpd_driver_getattr($attr) -- Missing attribute.\n" if + $attr_missing_warned{$attr}; + return undef; + } + open(F, $file) || return undef; + my $val = ; + close F; + chomp $val; + return $val; +} + sub xpd_getattr($$) { my $xpd = shift || die; my $attr = shift || die; @@ -162,7 +181,7 @@ sub zt_registration($$) { } sub xpds_by_spanno() { - my @xbuses = Zaptel::Xpp::xbuses("SORT_CONNECTOR"); + my @xbuses = Zaptel::Xpp::xbuses(); my @xpds = map { $_->xpds } @xbuses; @xpds = grep { $_->spanno } @xpds; @xpds = sort { $a->spanno <=> $b->spanno } @xpds; @@ -181,7 +200,7 @@ sub new($$$$$) { my $sysfsdir = shift || die; my $self = { XBUS => $xbus, - ID => "$unit$subunit", + ID => sprintf("%1d%1d", $unit, $subunit), FQN => $xbus->name . "/" . "XPD-$unit$subunit", UNIT => $unit, SUBUNIT => $subunit, @@ -198,6 +217,7 @@ sub new($$$$$) { if($type =~ /BRI_(NT|TE)/) { $self->{IS_BRI} = 1; $self->{TERMTYPE} = $1; + $self->{DCHAN_HARDHDLC} = $self->xpd_driver_getattr('dchan_hardhdlc'); } $self->{IS_PRI} = ($type =~ /[ETJ]1/); $self->{IS_DIGITAL} = ( $self->{IS_BRI} || $self->{IS_PRI} ); -- cgit v1.2.3