~gandelman-a/ubuntu/precise/dahdi-linux/merge879743

1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
1
#! /usr/bin/perl -w
2
use strict;
3
4
# Make warnings fatal
5
local $SIG{__WARN__} = sub { die @_ };
6
7
#
1.2.6 by Tzafrir Cohen
Import upstream version 2.5.0.1+dfsg
8
# $Id: init_card_4_30 9709 2011-01-30 18:10:33Z tzafrir $
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
9
#
10
11
#
12
# Written by Oron Peled <oron@actcom.co.il>
13
# Copyright (C) 2007, Xorcom
14
#
15
# All rights reserved.
16
#
17
# This program is free software;	you can redistribute it and/or modify
18
# it under the terms of the GNU General Public License as published by
19
# the Free Software Foundation;	either version 2 of the License, or
20
# (at your option) any later version.
21
#
22
# See the file LICENSE in the top level of this tarball.
23
#
24
25
# This script is run from the xpp kernel module upon detection
26
# of a new XPD.
27
#
28
# Expects the following environment variables to be set:
29
#	XBUS_NAME	- bus name
30
#	UNIT_NUMBER	- xpd unit number
31
#	UNIT_SUBUNITS	- number of subunits in this xpd
32
#	UNIT_TYPE	- xpd type number (from protocol reply):
33
#			1 - FXS
34
#			2 - FXO
35
#			3 - BRI
36
#			4 - PRI
37
#	XBUS_REVISION	- xbus revision number
38
#	XBUS_CONNECTOR	- xbus connector string
39
#	XBUS_LABEL	- xbus label string
40
#
41
# Output data format:
42
#	- An optional comment start with ';' or '#' until the end of line
43
#	- Optional Blank lines are ignored
44
#	- Fields are whitespace separated (spaces or tabs)
45
#
46
# The fields are (in command line order):
47
#	1. CHIP select in decimal (ignored, taken from 3 LSB's of subunit number)
48
#	2. Command word:
49
#		- RD	Read Direct register.
50
#		- WD	Write Direct register.
51
#	3. Register number in hexadecimal.
52
#	5. Data byte in hexadecimal. (for WD command only).
53
#
54
55
package main;
56
use File::Basename;
57
use Getopt::Std;
58
59
my $program = basename("$0");
60
my $init_dir = dirname("$0");
1.1.1 by Mark Purcell
Import upstream version 2.2.0~dfsg~rc4
61
BEGIN { $init_dir = dirname($0); unshift(@INC, "$init_dir"); }
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
62
use XppConfig $init_dir;
63
my $unit_id;
64
my %opts;
65
66
getopts('o:', \%opts);
67
68
my %settings;
69
70
sub logit {
71
	print STDERR "$unit_id: @_\n";
72
}
73
1.1.1 by Mark Purcell
Import upstream version 2.2.0~dfsg~rc4
74
sub debug {
75
	logit @_ if $settings{debug};
76
}
77
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
78
# Arrange for error logging
79
if (-t STDERR) {
80
	$unit_id = 'Interactive';
1.1.1 by Mark Purcell
Import upstream version 2.2.0~dfsg~rc4
81
	debug "Interactive startup";
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
82
} else {
83
	$unit_id = "$ENV{XBUS_NAME}/UNIT-$ENV{UNIT_NUMBER}";
84
	open (STDERR, "| logger -t $program -p kern.info") || die;
1.1.1 by Mark Purcell
Import upstream version 2.2.0~dfsg~rc4
85
	debug "Non Interactive startup";
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
86
	foreach my $k (qw(
87
			XBUS_NAME
88
			XBUS_NUMBER
89
			UNIT_NUMBER
90
			UNIT_TYPE
91
			UNIT_SUBUNITS
92
			UNIT_SUBUNITS_DIR
93
			XBUS_REVISION
94
			XBUS_CONNECTOR
95
			XBUS_LABEL)) {
96
		unless(defined $ENV{$k}) {
97
			logit "Missing ENV{$k}\n";
98
			die;
99
		}
100
	}
101
}
102
103
sub select_subunit($) {
104
	my $subunit = shift;
105
	die unless defined $subunit;
106
	my $output;
107
108
	if($opts{o}) {
109
		$output = $opts{o};
110
	} else {
111
		$output = sprintf "/sys/bus/xpds/devices/%02d:%1d:%1d/chipregs",
112
				$ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER}, $subunit;
113
		if(! -f $output) {
114
			my $xpd_name = sprintf("XPD-%1d%1d", $ENV{UNIT_NUMBER}, $subunit);
115
			$output = "/proc/xpp/$ENV{XBUS_NAME}/$xpd_name/chipregs";
116
			logit "OLD DRIVER: does not use /sys chipregs. Falling back to /proc"
117
				if -f $output;
118
		}
119
	}
120
	open(REG, ">$output") || die "Failed to open '$output': $!\n";
121
	my $oldfh = select REG;
122
	print "# Selecting subunit $subunit\n" if $opts{o};
123
	return $oldfh;
124
}
125
126
package PRI;
127
128
sub gen {
129
	my $fmt = shift;
130
	$| = 1;
131
	printf "$fmt\n", @_;
132
}
133
134
sub init_quad() {
135
	main::select_subunit(0);
136
137
	PRI::gen "0 WD D6 20"; 		# GPC6.COMP_DIS=1
138
					# (Compatibility Mode Disable)
139
140
	# Tuning of clocking unit to the 16.384 MHz reference frequence
141
	# by setting Global Clock Mode registers (GCM[1:8]), same for E1 and T1/J1
142
	PRI::gen "0 WD 92 00"; 		# GCM1
143
	PRI::gen "0 WD 93 18";		# GCM2
144
	PRI::gen "0 WD 94 FB";		# GCM3
145
	PRI::gen "0 WD 95 0B";		# GCM4
146
	PRI::gen "0 WD 96 01";		# GCM5
147
	PRI::gen "0 WD 97 0B";		# GCM6
148
	PRI::gen "0 WD 98 DB";		# GCM7
149
	PRI::gen "0 WD 99 DF";		# GCM8
150
}
151
152
sub finish_quad() {
1.1.4 by Jean-Michel Dault
Import upstream version 2.2.1+dfsg
153
	PRI::gen "0 WD BB 2C"; 		# REGFP
154
	PRI::gen "0 WD BC FF"; 		# REGFD
155
	PRI::gen "0 WD BB AC"; 		# REGFP
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
156
	PRI::gen "0 WD BB 2B"; 		# REGFP
157
	PRI::gen "0 WD BC 00"; 		# REGFD
158
	PRI::gen "0 WD BB AB"; 		# REGFP
1.1.4 by Jean-Michel Dault
Import upstream version 2.2.1+dfsg
159
	PRI::gen "0 WD BB 2A"; 		# REGFP
160
	PRI::gen "0 WD BC FF"; 		# REGFD
161
	PRI::gen "0 WD BB AA"; 		# REGFP
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
162
	PRI::gen "0 WD BB 29"; 		# REGFP
163
	PRI::gen "0 WD BC FF"; 		# REGFD
164
	PRI::gen "0 WD BB A9"; 		# REGFP
1.1.4 by Jean-Michel Dault
Import upstream version 2.2.1+dfsg
165
	PRI::gen "0 WD BB 28"; 		# REGFP
166
	PRI::gen "0 WD BC 00"; 		# REGFD
167
	PRI::gen "0 WD BB A8"; 		# REGFP
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
168
	PRI::gen "0 WD BB 27"; 		# REGFP
169
	PRI::gen "0 WD BC FF"; 		# REGFD
170
	PRI::gen "0 WD BB A7"; 		# REGFP
1.1.4 by Jean-Michel Dault
Import upstream version 2.2.1+dfsg
171
	PRI::gen "0 WD BB 00"; 		# REGFP
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
172
173
#	PRI::gen "0 WD 80 00"; 	# PC1 (Port configuration 1): RPB_1.SYPR           , XPB_1.SYPX
174
}
175
176
sub read_defaults() {
177
	if(XppConfig::read_config(\%settings)) {
178
		main::logit "Defaults from $settings{xppconf}";
179
	} else {
180
		main::logit "No defaults file, use hard-coded defaults.";
181
	}
182
}
183
184
package PRI::Port;
185
186
sub new {
187
	my $pack = shift;
188
	my $port = { @_ };
189
	bless $port, $pack;
190
	return $port;
191
}
192
193
sub get_pri_protocol {
194
	my $port = shift;
195
	my $subunit = $port->{PORT_NUM};
196
	my $xpd_name = "XPD-$ENV{UNIT_NUMBER}$subunit";
197
	my $pri_protocol;
198
	my @keys = (
199
			"pri_protocol/connector:$ENV{XBUS_CONNECTOR}/$xpd_name",
200
			"pri_protocol/label:$ENV{XBUS_LABEL}/$xpd_name",
201
			"pri_protocol/$ENV{XBUS_NAME}/$xpd_name",
202
			"pri_protocol"
203
		);
204
	foreach my $k (@keys) {
205
		$k = lc($k);		# Lowercase
206
		$pri_protocol = $settings{$k};
207
		if(defined $pri_protocol) {
208
			$port->{pri_protocol} = $pri_protocol;
209
			return $pri_protocol;
210
		}
211
	}
212
	return undef;
213
}
214
215
sub write_pri_info {
216
	my $port = shift;
217
	my $subunit = $port->{PORT_NUM};
218
	my $pri_protocol = $port->get_pri_protocol;
219
	my $xpd_name = sprintf("XPD-%1d%1d", $ENV{UNIT_NUMBER}, $subunit);
220
221
	if(defined $pri_protocol) {
222
		main::logit "$xpd_name: pri_protocol $pri_protocol";
223
		my $file = sprintf "/sys/bus/xpds/devices/%02d:%1d:%1d/pri_protocol",
224
				$ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER}, $subunit;
225
		if(! -f $file) {
226
			$file = "/proc/xpp/$ENV{XBUS_NAME}/$xpd_name/pri_info";
227
			main::logit "OLD DRIVER: does not use /sys chipregs. Falling back to /proc"
228
				if -f $file;
229
		}
230
		open(INFO, ">$file") || die "Failed to open '$file': $!\n";
231
		print INFO "$pri_protocol\n" || die "Failed writing '$pri_protocol' to '$file': $!\n";
232
		close INFO || die "Failed during close of '$file': $!\n";
233
	} else {
1.1.1 by Mark Purcell
Import upstream version 2.2.0~dfsg~rc4
234
		main::logit "$xpd_name: pri_protocol not given. Driver will use defaults.";
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
235
	}
236
}
237
238
sub port_setup($) {
239
	my $port = shift;
240
	my $portno = $port->{PORT_NUM};
1.2.5 by Tzafrir Cohen
Import upstream version 2.4.1+dfsg
241
	my $pri_protocol = $port->get_pri_protocol;
242
243
	PRI::gen "$portno WD 28 40"; 	# XPM2.XLT Tristate
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
244
245
	my $cmr5 = sprintf("%x", ($portno << 5));
246
247
	PRI::gen "$portno WD 42 $cmr5"; # CMR5.DRSS=portno
248
249
	PRI::gen "$portno WD 26 F6"; 	# XPM0: Pulse Shape Programming for R1=18Ohms 
250
	PRI::gen "$portno WD 27 02"; 	# XPM1: ...3V Pulse Level at the line (Vp-p=6v)
251
252
					# if (unchannelized)
253
	#PRI::gen "$portno WD 1F 22";	# LOOP (Channel Looback): 
254
					#      ECLB (Enable Channel Loop-Back) 
255
					#      CLA  (Channel Address)
256
	PRI::gen "$portno WD 2B EF";	# IDL (Idle): 
257
					#      If channel loopback is enabled than transmit this code on the outgoing
258
	PRI::gen "$portno WD 1F 00";	# LOOP (Channel Looback): 
259
	#if($portno eq 0){ 
260
	#	PRI::gen "0 WD 1F 00";	# LOOP (Channel Looback): 
261
	#				#      channels (XL1/XL2)
262
	#}else { 
263
	#	PRI::gen "0 WD 1F 20";	# LOOP (Channel Looback): 
264
	#}
265
266
	# only one of the following loopbacks can be activated in the same time 
267
	my $LIM1_RL  = 0 << 1; 	# RL  (Remote  Loopback)
268
	my $lim1 = 0xB0 | $LIM1_RL;
269
	PRI::gen "$portno WD 37 %02X", $lim1;
270
					# LIM1: ~RL (Remote Loop bit 0x02),
271
					#       ~DRS (Dual Rail Select, latch receive data while trasmit),
272
					#       RIL1, RIL0 (Receive Input Treshold 0.62 V),
273
					#       CLOS (Clear data in case of LOS)
274
	PRI::gen "$portno WD 3A 20";	# LIM2: SLT1, SLT0 = 01 
275
					#            (Receiver Slicer Threshold, the receive slicer 
276
					#             generates a mark (digital one) if the voltage at
277
					#             RL1/2 exceeds 50% of the peak amplitude,
278
					#             default, recommended in E1 mode).
279
	  
280
	PRI::gen "$portno WD 38 0A"; 	# PCD: (Pulse Count Detection, LOS Detection after 176 consecutive 0s)
281
	PRI::gen "$portno WD 39 15"; 	# PCR: (Pulse Count Recovery, LOS Recovery after 22 ones in PCD interval)
282
283
	# Configure system interface
284
	PRI::gen "$portno WD 3E C2";	# SIC1: SSC1 (System clock    ) is 8.192 Mhz, 
285
					#       SSD1 (System Data rate) is 8.192 Mbit/s,
286
					#	~BIM (Byte interleaved mode),
287
					#	XBS  (Transmit Buffer Size) is 2 frames
288
	PRI::gen "$portno WD 40 04";	# SIC3: Edges for capture, Synchronous Pulse Receive @Rising Edge
289
	PRI::gen "$portno WD 41 04";	# CMR4: RCLK is 8.192 MHz
290
	PRI::gen "$portno WD 43 04";	# CMR5: TCLK is 8.192 MHz
291
	PRI::gen "$portno WD 44 34";	# CMR6: Receive reference clock generated by channel 1,
292
					#       RCLK is at 8.192 Mhz dejittered, Clock recovered from the line
293
					#       TCLK is at 8.192 MHz is de-jittered by DCO-R to drive a6.176 MHz 
294
					#       clock on RCLK.*/
295
296
	PRI::gen "$portno WD 22 00"; 	# XC0: (Transmit Counter Offset = 497/T=2)
1.1.4 by Jean-Michel Dault
Import upstream version 2.2.1+dfsg
297
	PRI::gen "$portno WD 23 04"; 	# XC1: X=4  => T=4-X=0 offset
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
298
299
	PRI::gen "$portno WD 24 00"; 	# RC0: (Receive  Counter Offset = 497/T=2)
1.1.4 by Jean-Michel Dault
Import upstream version 2.2.1+dfsg
300
	PRI::gen "$portno WD 25 05"; 	# RC1: Remaining part of RC0
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
301
302
	my $sic2 = sprintf("%x", 0x00 | ($portno << 1));
303
304
	PRI::gen "$portno WD 3F $sic2";	# SIC2: No FFS, no center receive elastic buffer, data active at phase ($sic >> 1)
305
		
306
	# enable the following interrupt sources
1.2.5 by Tzafrir Cohen
Import upstream version 2.4.1+dfsg
307
	PRI::gen "$portno WD 14 F7"; 	# IMR0 (Interrupt Mask Register2): Enable CASC_E1/RSC_T1
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
308
	PRI::gen "$portno WD 16 00"; 	# IMR2 (Interrupt Mask Register2): Enable ALL
309
		
310
	PRI::gen "$portno WD 17 3F"; 	# IMR3 ~ES, ~SEC (Enable ES and SEC interrupts)
311
	PRI::gen "$portno WD 18 00"; 	# IMR4: Enable ALL
1.2.5 by Tzafrir Cohen
Import upstream version 2.4.1+dfsg
312
	PRI::gen "$portno WD 46 80"; 	# GCR: (Global Configuration Register)
313
					#      VIS (Masked Interrupts Visible)
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
314
315
	PRI::gen "$portno WD 08 04";	# IPC: SYNC is 8 Khz
316
317
	PRI::gen "$portno WD 02 51"; 	# CMDR (Command Register): RRES, XRES, SRES (Receiver/Transmitter reset)
318
	PRI::gen "$portno WD 02 00"; 	# CMDR
319
320
321
	PRI::gen "$portno WD 45 00";	# CMR2: External sources for SYPR, SCLKR, SYPX, SCLKX for TX and RX.
322
323
	#  Configure ports
324
	PRI::gen "$portno WD 85 80";		# GPC1 (Global Port Configuration 1):
325
	#PRI::gen "$portno WD 85 00";		# GPC1 (Global Port Configuration 1):
326
								#      SMM (System Interface Multiplex Mode)
327
	PRI::gen "$portno WD 80 00";	# PC1: SYPR/SYPX provided to RPA/XPA inputs
328
329
	PRI::gen "$portno WD 84 31";	# PC5: XMFS active low, SCLKR is input, RCLK is output (unused)
330
	PRI::gen "$portno WD 3B 00";	# Clear LCR1 - Loop Code Register 1
331
332
	#  printk("TE110P: Successfully initialized serial bus for card\n");
333
334
	# Initialize PCM and SIG regs
335
	PRI::gen "$portno WD A0 00";	# TSEO (Time Slot Even/Odd Select) 
336
	PRI::gen "$portno WD A1 FF";	# TSBS (Time Slot Bit Select)- only selected bits are used for HDLC channel 1
337
					#      in selected time slots
338
	PRI::gen "$portno WD 03 89";	# Mode Register:
339
					#      MDS  (Mode Select) = 100 (No address comparison)
340
					#      HRAC (Receiver Active - HDLC channel 1) 
341
					#      RFT2 (HDLC Receive FIFO is 64 byte deep)
1.2.5 by Tzafrir Cohen
Import upstream version 2.4.1+dfsg
342
	my $ccr1 = 0x18;		# CCR1 (Common Configuration Register1)
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
343
					#      EITS (Enable Internal Time Slot 0 to 31 Signalling)
344
					#      ITF  (Interframe Time Fill)
1.2.5 by Tzafrir Cohen
Import upstream version 2.4.1+dfsg
345
	my $sysfs_pri_protocol;
346
	if (defined $pri_protocol) {
347
		$sysfs_pri_protocol = $pri_protocol;
348
	} else {
349
		my $file = sprintf "/sys/bus/xpds/devices/%02d:%1d:%1d/pri_protocol",
350
				$ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER}, $portno;
1.2.6 by Tzafrir Cohen
Import upstream version 2.5.0.1+dfsg
351
		# The 'open' will fail if the port does not exist.
352
		# (or rather: the XPD for it does not exist). While
353
		# we only read this file to get the default E1/T1 value,
354
		# if it does not exist, it also implies the commands sent would
355
		# get nowhere. So we might as well quit now.
1.2.5 by Tzafrir Cohen
Import upstream version 2.4.1+dfsg
356
		open(F, $file) || return;
357
		$sysfs_pri_protocol = <F>;
358
		close F;
359
		chomp $sysfs_pri_protocol;
360
	}
361
	if($sysfs_pri_protocol eq 'T1') {
362
		$ccr1 |= 0x80;		#      RSCC (Serial CAS Format Selection)
363
	}
364
365
	PRI::gen "$portno WD 09 %02X", $ccr1;
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
366
	PRI::gen "$portno WD 0A 04";	# CCR2 (Common Configuration Register2)
367
					#      RCRC (enable CRC - HDLC channel 1enable CRC - HDLC channel 1)
368
	PRI::gen "$portno WD 0C 00";	# RTR1 (Receive  Time Slot register 1)
369
	PRI::gen "$portno WD 0D 00";	# RTR2 (Receive  Time Slot register 2)
370
	PRI::gen "$portno WD 0E 00";	# RTR3 (Receive  Time Slot register 3), TS16 (Enable time slot 16) 
371
	PRI::gen "$portno WD 0F 00";	# RTR4 (Receive  Time Slot register 4)
372
373
	PRI::gen "$portno WD 10 00";	# TTR1 (Transmit Time Slot register 1)
374
	PRI::gen "$portno WD 11 00";	# TTR2 (Transmit Time Slot register 2)
375
	PRI::gen "$portno WD 12 00";	# TTR3 (Transmit Time Slot register 3), TS16 (Enable time slot 16) 
376
	PRI::gen "$portno WD 13 00";	# TTR4 (Transmit Time Slot register 4)
377
378
	# configure the best performance of the Bipolar Violation detection for all four channels
379
	PRI::gen "$portno WD BD 00";	# BFR (Bugfix Register): ~BVP (Bipolar Violations),
380
					#                         use Improved Bipolar Violation Detection instead
381
}
382
383
package main;
384
1.1.1 by Mark Purcell
Import upstream version 2.2.0~dfsg~rc4
385
main::debug "Starting '$0'";
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
386
387
PRI::read_defaults;
388
389
sub main() {
390
	my @ports;
391
	my $subunit;
392
1.1.1 by Mark Purcell
Import upstream version 2.2.0~dfsg~rc4
393
	main::debug "main(): Initializing chip ($ENV{UNIT_SUBUNITS} ports)";
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
394
	PRI::init_quad;
395
	# Must initialize all 4 ports, regardless how much there are
396
	for($subunit = 0; $subunit < 4; $subunit++) {
1.1.1 by Mark Purcell
Import upstream version 2.2.0~dfsg~rc4
397
		#main::debug "main(): Initializing subunit $subunit";
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
398
		my $p = PRI::Port->new(
399
				'PORT_NUM'		=> $subunit,
400
				'EXIST'			=> ($subunit < $ENV{UNIT_SUBUNITS})
401
				);
402
		$p->port_setup;
403
		push(@ports, $p);
404
	}
405
	PRI::finish_quad;
406
	foreach my $p (@ports) {
407
		if($p->{EXIST}) {
408
			$p->write_pri_info;
409
		}
410
	}
411
}
412
413
main;
414
1.1.1 by Mark Purcell
Import upstream version 2.2.0~dfsg~rc4
415
main::debug "Ending '$0'";
1 by Mark Purcell
Import upstream version 2.1.0.4~dfsg
416
417
close REG;
418
close STDERR;
419
exit 0;