Revert "Remove support for xpp drivers."
[dahdi/linux.git] / drivers / dahdi / xpp / init_card_2_30
1 #! /usr/bin/perl -w
2 use strict;
3
4 # Make warnings fatal
5 local $SIG{__WARN__} = sub { die @_ };
6
7 #
8 # Written by Oron Peled <oron@actcom.co.il>
9 # Copyright (C) 2006, Xorcom
10 #
11 # All rights reserved.
12 #
13 # This program is free software; you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation; either version 2 of the License, or
16 # (at your option) any later version.
17 #
18 # See the file LICENSE in the top level of this tarball.
19 #
20
21 #
22 # $Id$
23 #
24 # Data format:
25 #       - A comment start with ';' or '#' until the end of line
26 #       - Blank lines are ignored
27 #       - Fields are whitespace separated (spaces or tabs)
28 #
29 # The fields are (in command line order):
30 #       1. SLIC select in decimal (range 0-7).
31 #          * is a special value which means ALL SLICS (only some registers
32 #          accept settings for ALL SLICS).
33 #       2. Command word:
34 #               - RD    Read Direct register.
35 #               - RS    Read Sub-register.
36 #               - WD    Write Direct register.
37 #               - WS    Write Sub-register.
38 #       3. Register number in hexadecimal.
39 #       4. Low data byte in hexadecimal. (for WD and WS commands).
40 #       5. High data byte in hexadecimal. (for WS command only).
41 #
42 #
43
44 package main;
45 use File::Basename;
46 use Getopt::Std;
47
48 my $program = basename("$0");
49 my $init_dir = dirname("$0");
50 BEGIN { $init_dir = dirname($0); unshift(@INC, "$init_dir"); }
51 use XppConfig $init_dir;
52 my $unit_id;
53 my %opts;
54 $Getopt::Std::STANDARD_HELP_VERSION = 1;
55 our $VERSION = '$Id$';
56
57 sub usage() {
58         print <<"EOF";
59 $0 [-L] [-v verify_file] [-o output_file]
60         -L: List all available opermodes and exit
61         -v: verify opermodes and exit
62         -o: simulate: output to file instead of astribank
63 EOF
64         exit 1;
65 }
66
67 sub HELP_MESSAGE() {
68         eval {usage};
69         return 0;
70 }
71
72 getopts('Lo:v:', \%opts) || usage;
73
74 my %settings;
75 $settings{debug} = 0;
76 my $chipregs;
77
78 sub logit {
79         print STDERR "$unit_id: @_\n";
80 }
81
82 sub debug {
83         logit @_ if $settings{debug};
84 }
85
86 # Arrange for error logging
87 if (-t STDERR || $opts{v}) {
88         $unit_id = 'Interactive';
89         debug "Interactive startup";
90 } else {
91         $unit_id = "$ENV{XBUS_NAME}/UNIT-$ENV{UNIT_NUMBER}";
92         open (STDERR, "| logger -t $program -p kern.info") || die;
93         debug "Non Interactive startup";
94         foreach my $k (qw(
95                         XBUS_NAME
96                         XBUS_NUMBER
97                         UNIT_NUMBER
98                         UNIT_TYPE
99                         UNIT_SUBUNITS
100                         UNIT_SUBUNITS_DIR
101                         XBUS_REVISION
102                         XBUS_CONNECTOR
103                         XBUS_LABEL)) {
104                 unless(defined $ENV{$k}) {
105                         logit "Missing ENV{$k}\n";
106                         die;
107                 }
108         }
109         $chipregs = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/chipregs",
110                 $ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER};
111         if(! -f $chipregs) {
112                 my $xpd_name = sprintf("XPD-%1d0", $ENV{UNIT_NUMBER});
113                 $chipregs = "/proc/xpp/$ENV{XBUS_NAME}/$xpd_name/chipregs";
114                 logit "OLD DRIVER: does not use /sys chipregs. Falling back to /proc"
115                         if -f $chipregs;
116         }
117 }
118
119 sub set_output() {
120         my $output;
121
122         if($opts{o}) {
123                 $output = $opts{o};
124         } else {
125                 # No subunits in FXS (everything is subunit 0)
126                 $output = $chipregs;
127         }
128         open(REG, ">$output") || die "Failed to open '$output': $!\n";
129         my $oldfh = select REG;
130         main::logit "# Setting output" if $opts{o};
131         return $oldfh;
132 }
133
134 package FXO;
135
136 sub gen {
137         my $fmt = shift;
138         $| = 1;
139         printf "$fmt\n", @_;
140 }
141
142 my $OPERMODE = 'FCC';
143
144 sub turn_off_leds() {
145         # Turning off red LEDs
146         # Warning: do not send WD 31 20 A0 !
147         foreach my $i (0..7) {
148                 FXO::gen "$i WD 20 A0";
149         }
150 }
151
152 # This data is manually taken from utils/init_fxo_modes which is generated
153 # during build.
154 # Running this script with a single 'verify' argument, during build,
155 # compare this data to a (possibly updated) utils/init_fxo_modes file.
156 my $OPERMODE_DATA = "
157 FCC             reg16=01        reg26=C0        reg30=00        reg31=20                
158 TBR21           reg16=00        reg26=C2        reg30=02        reg31=20        ring_osc=7E6C   ring_x=023A
159 ARGENTINA       reg16=00        reg26=C0        reg30=00        reg31=20                
160 AUSTRALIA       reg16=40        reg26=30        reg30=03        reg31=20                
161 AUSTRIA         reg16=00        reg26=C2        reg30=03        reg31=28                
162 BAHRAIN         reg16=00        reg26=C2        reg30=02        reg31=20                
163 BELGIUM         reg16=00        reg26=C2        reg30=02        reg31=28                
164 BRAZIL          reg16=00        reg26=30        reg30=00        reg31=20                
165 BULGARIA        reg16=00        reg26=C2        reg30=03        reg31=20                
166 CANADA          reg16=00        reg26=C0        reg30=00        reg31=20                
167 CHILE           reg16=00        reg26=C0        reg30=00        reg31=20                
168 CHINA           reg16=00        reg26=30        reg30=0F        reg31=20                
169 COLOMBIA        reg16=00        reg26=C0        reg30=00        reg31=20                
170 CROATIA         reg16=00        reg26=C2        reg30=02        reg31=20                
171 CYPRUS          reg16=00        reg26=C2        reg30=02        reg31=20                
172 CZECH           reg16=00        reg26=C2        reg30=02        reg31=20                
173 DENMARK         reg16=00        reg26=C2        reg30=02        reg31=28                
174 ECUADOR         reg16=00        reg26=C0        reg30=00        reg31=20                
175 EGYPT           reg16=00        reg26=30        reg30=00        reg31=20                
176 ELSALVADOR      reg16=00        reg26=C0        reg30=00        reg31=20                
177 FINLAND         reg16=00        reg26=C2        reg30=02        reg31=28                
178 FRANCE          reg16=00        reg26=C2        reg30=02        reg31=28                
179 GERMANY         reg16=00        reg26=C2        reg30=03        reg31=28                
180 GREECE          reg16=00        reg26=C2        reg30=02        reg31=28                
181 GUAM            reg16=00        reg26=C0        reg30=00        reg31=20                
182 HONGKONG        reg16=00        reg26=C0        reg30=00        reg31=20                
183 HUNGARY         reg16=00        reg26=C0        reg30=00        reg31=20                
184 ICELAND         reg16=00        reg26=C2        reg30=02        reg31=28                
185 INDIA           reg16=00        reg26=C0        reg30=04        reg31=20                
186 INDONESIA       reg16=00        reg26=C0        reg30=00        reg31=20                
187 IRELAND         reg16=00        reg26=C2        reg30=02        reg31=28                
188 ISRAEL          reg16=00        reg26=C2        reg30=02        reg31=20                
189 ITALY           reg16=00        reg26=C2        reg30=02        reg31=28                
190 JAPAN           reg16=00        reg26=30        reg30=00        reg31=20                
191 JORDAN          reg16=00        reg26=30        reg30=00        reg31=20                
192 KAZAKHSTAN      reg16=00        reg26=C0        reg30=00        reg31=20                
193 KUWAIT          reg16=00        reg26=C0        reg30=00        reg31=20                
194 LATVIA          reg16=00        reg26=C2        reg30=02        reg31=20                
195 LEBANON         reg16=00        reg26=C2        reg30=02        reg31=20                
196 LUXEMBOURG      reg16=00        reg26=C2        reg30=02        reg31=28                
197 MACAO           reg16=00        reg26=C0        reg30=00        reg31=20                
198 MALAYSIA        reg16=00        reg26=30        reg30=00        reg31=20                
199 MALTA           reg16=00        reg26=C2        reg30=02        reg31=20                
200 MEXICO          reg16=00        reg26=C0        reg30=00        reg31=20                
201 MOROCCO         reg16=00        reg26=C2        reg30=02        reg31=20                
202 NETHERLANDS     reg16=00        reg26=C2        reg30=02        reg31=28                
203 NEWZEALAND      reg16=00        reg26=C0        reg30=04        reg31=20                
204 NIGERIA         reg16=00        reg26=C2        reg30=02        reg31=20                
205 NORWAY          reg16=00        reg26=C2        reg30=02        reg31=28                
206 OMAN            reg16=00        reg26=30        reg30=00        reg31=20                
207 PAKISTAN        reg16=00        reg26=30        reg30=00        reg31=20                
208 PERU            reg16=00        reg26=C0        reg30=00        reg31=20                
209 PHILIPPINES     reg16=00        reg26=30        reg30=00        reg31=20                
210 POLAND          reg16=03        reg26=C0        reg30=00        reg31=20                
211 PORTUGAL        reg16=00        reg26=C2        reg30=02        reg31=28                
212 ROMANIA         reg16=00        reg26=C0        reg30=00        reg31=20                
213 RUSSIA          reg16=00        reg26=30        reg30=00        reg31=20                
214 SAUDIARABIA     reg16=00        reg26=C0        reg30=00        reg31=20                
215 SINGAPORE       reg16=00        reg26=C0        reg30=00        reg31=20                
216 SLOVAKIA        reg16=00        reg26=C0        reg30=03        reg31=20                
217 SLOVENIA        reg16=00        reg26=C0        reg30=02        reg31=20                
218 SOUTHAFRICA     reg16=42        reg26=C0        reg30=03        reg31=20                
219 SOUTHKOREA      reg16=00        reg26=C0        reg30=00        reg31=20                
220 SPAIN           reg16=00        reg26=C2        reg30=02        reg31=28                
221 SWEDEN          reg16=00        reg26=C2        reg30=02        reg31=28                
222 SWITZERLAND     reg16=00        reg26=C2        reg30=02        reg31=28                
223 SYRIA           reg16=00        reg26=30        reg30=00        reg31=20                
224 TAIWAN          reg16=00        reg26=30        reg30=00        reg31=20                
225 THAILAND        reg16=00        reg26=30        reg30=00        reg31=20                
226 UAE             reg16=00        reg26=C0        reg30=00        reg31=20                
227 UK              reg16=00        reg26=C2        reg30=05        reg31=28                
228 USA             reg16=00        reg26=C0        reg30=00        reg31=20                
229 YEMEN           reg16=00        reg26=C0        reg30=00        reg31=20                
230         ";
231
232 my %opermode_table;
233
234 sub opermode_setup() {
235         main::logit "Setting OPERMODE=$OPERMODE";
236         # Several countries (South Africa, UAE, anybody else)
237         # require a shorter delay:
238         if($OPERMODE eq 'SOUTHAFRICA' or $OPERMODE eq 'UAE') {
239                 FXO::gen "* WD 17 2B";
240         }
241         # defaults, based on fxo_modes from wctdm.c . 
242         # Decimal register numbers!
243         my %regs = (
244                         16      => 0,
245                         26      => 0,
246                         30      => 0,
247                         31      => 0x20,
248                 );
249         my $mode = $opermode_table{$OPERMODE};
250         if(defined $mode) {
251                 foreach my $k (keys %regs) {
252                         my $fullkey = "reg$k";
253                         $regs{$k} = $mode->{$fullkey};
254                 }
255         }
256         foreach my $k (keys %regs) {
257                 # Our values are HEXADECIMAL without a 0x prefix!!!
258                 my $cmd = sprintf "* WD %02X %02X", $k, hex($regs{$k});
259                 main::debug "    regs: '$cmd'";
260                 FXO::gen "$cmd";
261         }
262         main::debug "Finished Opermode";
263 }
264
265 sub parse_opermode_line($) {
266         my $line = shift or return();
267
268         chomp $line;
269         $line =~ s/#.*//;
270         my @params = split(/\s+/, $line);
271         my $location = shift @params;
272         my $entry = {};
273         foreach my $p (@params) {
274                 my ($key, $val) = split(/=/, $p, 2);
275                 $entry->{$key} = $val;
276         }
277         return ($location, $entry);
278 }
279
280 sub opermode_preprocess() {
281         undef %opermode_table;
282         foreach my $line (split(/\n/, $OPERMODE_DATA)) {
283                 my ($location, $entry) = parse_opermode_line($line);
284                 next unless defined $location;
285                 #print "$location\t", ref($entry), "\n";
286                 die "An entry for '$location' already exists\n"
287                         if exists $opermode_table{$location};
288                 $opermode_table{$location} = $entry;
289         }
290 }
291
292 sub opermode_to_string($) {
293         my $mode = shift or die;
294         my @params;
295
296         foreach my $k (sort keys %{$mode}) {
297                 push(@params, "$k=$mode->{$k}");
298         }
299         return join(" ", @params);
300 }
301
302 sub opermode_list() {
303         my $l = join("\n", sort keys %opermode_table);
304         print "$l\n";
305 }
306
307 sub opermode_verify($) {
308         my $input = shift or die;
309         my %verification_table;
310         my %location_lines;
311         my $mismatches = 0;
312
313         open(F, $input) or die "$0: Failed opening '$input': $!\n";
314         while(<F>) {
315                 chomp;
316                 #print "$_\n";
317                 s/#.*//;
318                 my @params = split;
319                 my $location = shift @params;
320                 foreach my $p (@params) {
321                         my ($key, $val) = split(/=/, $p, 2);
322                         $verification_table{$location}{$key} = $val;
323                 }
324                 $location_lines{$location} = $.;
325         }
326         close F;
327         # First test: check for missing data in our program
328         foreach my $location (sort keys %verification_table) {
329                 my $mode = $opermode_table{$location};
330                 if(! defined $mode) {
331                         printf STDERR  "Missing from $0: '$location' at $input:$location_lines{$location}\n";
332                         $mismatches++;
333                         next;
334                 }
335                 my $verify_mode = $verification_table{$location};
336                 my $str1 = opermode_to_string($mode);
337                 my $str2 = opermode_to_string($verify_mode);
338                 if($str1 ne $str2) {
339                         print STDERR  "DIFF: '$location' at $input:$location_lines{$location}\n";
340                         printf STDERR  "\t%-20s: %s\n", "program", $str1;
341                         printf STDERR  "\t%-20s: %s\n", "verify", $str2;
342                         $mismatches++;
343                 }
344         }
345         # Second test: check for extra data in our program
346         foreach my $location (sort keys %opermode_table) {
347                 my $mode = $verification_table{$location};
348                 if(! defined $mode) {
349                         printf STDERR  "Extra in $0 '$location'\n";
350                         $mismatches++;
351                         next;
352                 }
353         }
354         print STDERR "Total $mismatches mismatches\n" if $mismatches;
355         return $mismatches;
356 }
357
358 sub read_defaults() {
359         if(XppConfig::read_config(\%settings)) {
360                 main::logit "Defaults from $settings{xppconf}";
361                 my $o = $settings{opermode};
362                 if(defined($o)) {
363                         # Verify
364                         $o = uc($o);    # Uppercase
365                         my $mode = $opermode_table{$o};
366                         if(! defined $mode) {
367                                 main::logit "Unknown opermode='$o'";
368                                 die;
369                         }
370                         $OPERMODE = $o;
371                         main::logit "Set OPERMODE = $o";
372                 }
373         } else {
374                 main::logit "No defaults file, use hard-coded defaults.";
375         }
376 }
377
378 package main;
379
380 FXO::opermode_preprocess;       # Must be first
381
382 if($opts{v}) {
383         my $verify_file = $opts{v};
384         usage unless $verify_file;
385         main::debug "$0: opermode verification (input='$verify_file')";
386         my $mismatches = FXO::opermode_verify($verify_file);
387         die "$0: Verification against $verify_file failed\n" if $mismatches != 0;
388         exit 0;
389 } elsif($opts{L}) {
390         FXO::opermode_list();
391         exit 0;
392 }
393
394 main::debug "Starting";
395
396 FXO::read_defaults;
397 die "OPERMODE is undefined" unless $OPERMODE;
398 set_output;
399 FXO::turn_off_leds;
400 while(<DATA>) {
401         chomp;
402         s/[#;].*$//;            # remove comments
403         s/^\s+//;               # trim whitespace
404         s/\s+$//;               # trim whitespace
405         s/\t+/ /g;              # replace tabs with spaces (for logs)
406         next unless /\S/;       # Skip empty lines
407         main::debug "writing: '$_'";
408         FXO::gen "$_";
409 }
410 FXO::opermode_setup;
411 close REG;
412
413 main::debug "Ending '$0'";
414 close STDERR;
415 exit 0;
416
417 __DATA__
418 *       WD      12      02      # Full wave rectified ring detection
419 *       WD      03      01      # Polarity reversal detect mask
420 *       WD      04      00      # Clear interrupt status
421 *       WD      21      08      # Disable PCM transfers
422 *       WD      18      99
423 *       WD      06      00
424
425 # ----------- DAA PCM start offset ----------
426
427 *       WD      23      00
428 *       WD      25      00
429
430 0       WD      22      00
431 0       WD      24      00
432 0       WD      21      28      # Enable PCM transfers, when offsets are set
433
434 1       WD      22      08
435 1       WD      24      08
436 1       WD      21      28
437
438 2       WD      22      10
439 2       WD      24      10
440 2       WD      21      28
441
442 3       WD      22      18
443 3       WD      24      18
444 3       WD      21      28
445
446 4       WD      22      20
447 4       WD      24      20
448 4       WD      21      28
449
450 5       WD      22      28
451 5       WD      24      28
452 5       WD      21      28
453
454 6       WD      22      30
455 6       WD      24      30
456 6       WD      21      28
457
458 7       WD      22      38
459 7       WD      24      38
460 7       WD      21      28
461
462 # ----------- DAA ONHOOK --------------------
463 *       WD      05      00
464
465 # Set tip to ring voltage to 3.5 volts while off-hook
466 # instead of default of 3.1
467 *       WD      1A      C0