465 lines
12 KiB
Plaintext
465 lines
12 KiB
Plaintext
|
#! /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
|