init_card_2_30 12 KB

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