123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- #! /usr/bin/perl -w
- use strict;
- # Make warnings fatal
- local $SIG{__WARN__} = sub { die @_ };
- #
- # 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.
- # - RS Read Sub-register.
- # - WD Write Direct register.
- # - WS Write Sub-register.
- # 3. Register number in hexadecimal.
- # 4. Low data byte in hexadecimal. (for WD and WS commands).
- # 5. High data byte in hexadecimal. (for WS 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"); }
- use XppConfig $init_dir;
- my $unit_id;
- my %opts;
- $Getopt::Std::STANDARD_HELP_VERSION = 1;
- our $VERSION = '$Id$';
- sub usage() {
- print <<"EOF";
- $0 [-L] [-v verify_file] [-o output_file]
- -L: List all available opermodes and exit
- -v: verify opermodes and exit
- -o: simulate: output to file instead of astribank
- EOF
- exit 1;
- }
- sub HELP_MESSAGE() {
- eval {usage};
- return 0;
- }
- getopts('Lo:v:', \%opts) || usage;
- my %settings;
- $settings{debug} = 0;
- my $chipregs;
- sub logit {
- print STDERR "$unit_id: @_\n";
- }
- sub debug {
- logit @_ if $settings{debug};
- }
- # Arrange for error logging
- if (-t STDERR || $opts{v}) {
- $unit_id = 'Interactive';
- debug "Interactive startup";
- } else {
- $unit_id = "$ENV{XBUS_NAME}/UNIT-$ENV{UNIT_NUMBER}";
- open (STDERR, "| logger -t $program -p kern.info") || die;
- debug "Non Interactive startup";
- foreach my $k (qw(
- XBUS_NAME
- XBUS_NUMBER
- UNIT_NUMBER
- UNIT_TYPE
- UNIT_SUBUNITS
- UNIT_SUBUNITS_DIR
- XBUS_REVISION
- XBUS_CONNECTOR
- XBUS_LABEL)) {
- unless(defined $ENV{$k}) {
- logit "Missing ENV{$k}\n";
- die;
- }
- }
- $chipregs = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/chipregs",
- $ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER};
- if(! -f $chipregs) {
- my $xpd_name = sprintf("XPD-%1d0", $ENV{UNIT_NUMBER});
- $chipregs = "/proc/xpp/$ENV{XBUS_NAME}/$xpd_name/chipregs";
- logit "OLD DRIVER: does not use /sys chipregs. Falling back to /proc"
- if -f $chipregs;
- }
- }
- 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;
- main::logit "# Setting output" if $opts{o};
- return $oldfh;
- }
- package FXO;
- sub gen {
- my $fmt = shift;
- $| = 1;
- printf "$fmt\n", @_;
- }
- my $OPERMODE = 'FCC';
- sub turn_off_leds() {
- # Turning off red LEDs
- # Warning: do not send WD 31 20 A0 !
- foreach my $i (0..7) {
- FXO::gen "$i WD 20 A0";
- }
- }
- # This data is manually taken from utils/init_fxo_modes which is generated
- # during build.
- # Running this script with a single 'verify' argument, during build,
- # compare this data to a (possibly updated) utils/init_fxo_modes file.
- my $OPERMODE_DATA = "
- FCC reg16=01 reg26=C0 reg30=00 reg31=20
- TBR21 reg16=00 reg26=C2 reg30=02 reg31=20 ring_osc=7E6C ring_x=023A
- ARGENTINA reg16=00 reg26=C0 reg30=00 reg31=20
- AUSTRALIA reg16=40 reg26=30 reg30=03 reg31=20
- AUSTRIA reg16=00 reg26=C2 reg30=03 reg31=28
- BAHRAIN reg16=00 reg26=C2 reg30=02 reg31=20
- BELGIUM reg16=00 reg26=C2 reg30=02 reg31=28
- BRAZIL reg16=00 reg26=30 reg30=00 reg31=20
- BULGARIA reg16=00 reg26=C2 reg30=03 reg31=20
- CANADA reg16=00 reg26=C0 reg30=00 reg31=20
- CHILE reg16=00 reg26=C0 reg30=00 reg31=20
- CHINA reg16=00 reg26=30 reg30=0F reg31=20
- COLOMBIA reg16=00 reg26=C0 reg30=00 reg31=20
- CROATIA reg16=00 reg26=C2 reg30=02 reg31=20
- CYPRUS reg16=00 reg26=C2 reg30=02 reg31=20
- CZECH reg16=00 reg26=C2 reg30=02 reg31=20
- DENMARK reg16=00 reg26=C2 reg30=02 reg31=28
- ECUADOR reg16=00 reg26=C0 reg30=00 reg31=20
- EGYPT reg16=00 reg26=30 reg30=00 reg31=20
- ELSALVADOR reg16=00 reg26=C0 reg30=00 reg31=20
- FINLAND reg16=00 reg26=C2 reg30=02 reg31=28
- FRANCE reg16=00 reg26=C2 reg30=02 reg31=28
- GERMANY reg16=00 reg26=C2 reg30=03 reg31=28
- GREECE reg16=00 reg26=C2 reg30=02 reg31=28
- GUAM reg16=00 reg26=C0 reg30=00 reg31=20
- HONGKONG reg16=00 reg26=C0 reg30=00 reg31=20
- HUNGARY reg16=00 reg26=C0 reg30=00 reg31=20
- ICELAND reg16=00 reg26=C2 reg30=02 reg31=28
- INDIA reg16=00 reg26=C0 reg30=04 reg31=20
- INDONESIA reg16=00 reg26=C0 reg30=00 reg31=20
- IRELAND reg16=00 reg26=C2 reg30=02 reg31=28
- ISRAEL reg16=00 reg26=C2 reg30=02 reg31=20
- ITALY reg16=00 reg26=C2 reg30=02 reg31=28
- JAPAN reg16=00 reg26=30 reg30=00 reg31=20
- JORDAN reg16=00 reg26=30 reg30=00 reg31=20
- KAZAKHSTAN reg16=00 reg26=C0 reg30=00 reg31=20
- KUWAIT reg16=00 reg26=C0 reg30=00 reg31=20
- LATVIA reg16=00 reg26=C2 reg30=02 reg31=20
- LEBANON reg16=00 reg26=C2 reg30=02 reg31=20
- LUXEMBOURG reg16=00 reg26=C2 reg30=02 reg31=28
- MACAO reg16=00 reg26=C0 reg30=00 reg31=20
- MALAYSIA reg16=00 reg26=30 reg30=00 reg31=20
- MALTA reg16=00 reg26=C2 reg30=02 reg31=20
- MEXICO reg16=00 reg26=C0 reg30=00 reg31=20
- MOROCCO reg16=00 reg26=C2 reg30=02 reg31=20
- NETHERLANDS reg16=00 reg26=C2 reg30=02 reg31=28
- NEWZEALAND reg16=00 reg26=C0 reg30=04 reg31=20
- NIGERIA reg16=00 reg26=C2 reg30=02 reg31=20
- NORWAY reg16=00 reg26=C2 reg30=02 reg31=28
- OMAN reg16=00 reg26=30 reg30=00 reg31=20
- PAKISTAN reg16=00 reg26=30 reg30=00 reg31=20
- PERU reg16=00 reg26=C0 reg30=00 reg31=20
- PHILIPPINES reg16=00 reg26=30 reg30=00 reg31=20
- POLAND reg16=03 reg26=C0 reg30=00 reg31=20
- PORTUGAL reg16=00 reg26=C2 reg30=02 reg31=28
- ROMANIA reg16=00 reg26=C0 reg30=00 reg31=20
- RUSSIA reg16=00 reg26=30 reg30=00 reg31=20
- SAUDIARABIA reg16=00 reg26=C0 reg30=00 reg31=20
- SINGAPORE reg16=00 reg26=C0 reg30=00 reg31=20
- SLOVAKIA reg16=00 reg26=C0 reg30=03 reg31=20
- SLOVENIA reg16=00 reg26=C0 reg30=02 reg31=20
- SOUTHAFRICA reg16=42 reg26=C0 reg30=03 reg31=20
- SOUTHKOREA reg16=00 reg26=C0 reg30=00 reg31=20
- SPAIN reg16=00 reg26=C2 reg30=02 reg31=28
- SWEDEN reg16=00 reg26=C2 reg30=02 reg31=28
- SWITZERLAND reg16=00 reg26=C2 reg30=02 reg31=28
- SYRIA reg16=00 reg26=30 reg30=00 reg31=20
- TAIWAN reg16=00 reg26=30 reg30=00 reg31=20
- THAILAND reg16=00 reg26=30 reg30=00 reg31=20
- UAE reg16=00 reg26=C0 reg30=00 reg31=20
- UK reg16=00 reg26=C2 reg30=05 reg31=28
- USA reg16=00 reg26=C0 reg30=00 reg31=20
- YEMEN reg16=00 reg26=C0 reg30=00 reg31=20
- ";
- my %opermode_table;
- sub opermode_setup() {
- main::logit "Setting OPERMODE=$OPERMODE";
- # Several countries (South Africa, UAE, anybody else)
- # require a shorter delay:
- if($OPERMODE eq 'SOUTHAFRICA' or $OPERMODE eq 'UAE') {
- FXO::gen "* WD 17 2B";
- }
- # defaults, based on fxo_modes from wctdm.c .
- # Decimal register numbers!
- my %regs = (
- 16 => 0,
- 26 => 0,
- 30 => 0,
- 31 => 0x20,
- );
- my $mode = $opermode_table{$OPERMODE};
- if(defined $mode) {
- foreach my $k (keys %regs) {
- my $fullkey = "reg$k";
- $regs{$k} = $mode->{$fullkey};
- }
- }
- foreach my $k (keys %regs) {
- # Our values are HEXADECIMAL without a 0x prefix!!!
- my $cmd = sprintf "* WD %02X %02X", $k, hex($regs{$k});
- main::debug " regs: '$cmd'";
- FXO::gen "$cmd";
- }
- main::debug "Finished Opermode";
- }
- sub parse_opermode_line($) {
- my $line = shift or return();
- chomp $line;
- $line =~ s/#.*//;
- my @params = split(/\s+/, $line);
- my $location = shift @params;
- my $entry = {};
- foreach my $p (@params) {
- my ($key, $val) = split(/=/, $p, 2);
- $entry->{$key} = $val;
- }
- return ($location, $entry);
- }
- sub opermode_preprocess() {
- undef %opermode_table;
- foreach my $line (split(/\n/, $OPERMODE_DATA)) {
- my ($location, $entry) = parse_opermode_line($line);
- next unless defined $location;
- #print "$location\t", ref($entry), "\n";
- die "An entry for '$location' already exists\n"
- if exists $opermode_table{$location};
- $opermode_table{$location} = $entry;
- }
- }
- sub opermode_to_string($) {
- my $mode = shift or die;
- my @params;
- foreach my $k (sort keys %{$mode}) {
- push(@params, "$k=$mode->{$k}");
- }
- return join(" ", @params);
- }
- sub opermode_list() {
- my $l = join("\n", sort keys %opermode_table);
- print "$l\n";
- }
- sub opermode_verify($) {
- my $input = shift or die;
- my %verification_table;
- my %location_lines;
- my $mismatches = 0;
- open(F, $input) or die "$0: Failed opening '$input': $!\n";
- while(<F>) {
- chomp;
- #print "$_\n";
- s/#.*//;
- my @params = split;
- my $location = shift @params;
- foreach my $p (@params) {
- my ($key, $val) = split(/=/, $p, 2);
- $verification_table{$location}{$key} = $val;
- }
- $location_lines{$location} = $.;
- }
- close F;
- # First test: check for missing data in our program
- foreach my $location (sort keys %verification_table) {
- my $mode = $opermode_table{$location};
- if(! defined $mode) {
- printf STDERR "Missing from $0: '$location' at $input:$location_lines{$location}\n";
- $mismatches++;
- next;
- }
- my $verify_mode = $verification_table{$location};
- my $str1 = opermode_to_string($mode);
- my $str2 = opermode_to_string($verify_mode);
- if($str1 ne $str2) {
- print STDERR "DIFF: '$location' at $input:$location_lines{$location}\n";
- printf STDERR "\t%-20s: %s\n", "program", $str1;
- printf STDERR "\t%-20s: %s\n", "verify", $str2;
- $mismatches++;
- }
- }
- # Second test: check for extra data in our program
- foreach my $location (sort keys %opermode_table) {
- my $mode = $verification_table{$location};
- if(! defined $mode) {
- printf STDERR "Extra in $0 '$location'\n";
- $mismatches++;
- next;
- }
- }
- print STDERR "Total $mismatches mismatches\n" if $mismatches;
- return $mismatches;
- }
- sub read_defaults() {
- if(XppConfig::read_config(\%settings)) {
- main::logit "Defaults from $settings{xppconf}";
- my $o = $settings{opermode};
- if(defined($o)) {
- # Verify
- $o = uc($o); # Uppercase
- my $mode = $opermode_table{$o};
- if(! defined $mode) {
- main::logit "Unknown opermode='$o'";
- die;
- }
- $OPERMODE = $o;
- main::logit "Set OPERMODE = $o";
- }
- } else {
- main::logit "No defaults file, use hard-coded defaults.";
- }
- }
- package main;
- FXO::opermode_preprocess; # Must be first
- if($opts{v}) {
- my $verify_file = $opts{v};
- usage unless $verify_file;
- main::debug "$0: opermode verification (input='$verify_file')";
- my $mismatches = FXO::opermode_verify($verify_file);
- die "$0: Verification against $verify_file failed\n" if $mismatches != 0;
- exit 0;
- } elsif($opts{L}) {
- FXO::opermode_list();
- exit 0;
- }
- main::debug "Starting";
- FXO::read_defaults;
- die "OPERMODE is undefined" unless $OPERMODE;
- set_output;
- FXO::turn_off_leds;
- 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: '$_'";
- FXO::gen "$_";
- }
- FXO::opermode_setup;
- close REG;
- main::debug "Ending '$0'";
- close STDERR;
- exit 0;
- __DATA__
- * WD 21 08 # Disable PCM transfers
- * WD 18 99
- * WD 06 00
- # ----------- DAA PCM start offset ----------
- * WD 23 00
- * WD 25 00
- 0 WD 22 00
- 0 WD 24 00
- 0 WD 21 28 # Enable PCM transfers, when offsets are set
- 1 WD 22 08
- 1 WD 24 08
- 1 WD 21 28
- 2 WD 22 10
- 2 WD 24 10
- 2 WD 21 28
- 3 WD 22 18
- 3 WD 24 18
- 3 WD 21 28
- 4 WD 22 20
- 4 WD 24 20
- 4 WD 21 28
- 5 WD 22 28
- 5 WD 24 28
- 5 WD 21 28
- 6 WD 22 30
- 6 WD 24 30
- 6 WD 21 28
- 7 WD 22 38
- 7 WD 24 38
- 7 WD 21 28
- # ----------- DAA ONHOOK --------------------
- * WD 05 00
- # Set tip to ring voltage to 3.5 volts while off-hook
- # instead of default of 3.1
- * WD 1A C0
|