Compare commits

...

178 Commits

Author SHA1 Message Date
Shaun Ruffell
040ba6f43a wctc4xxp: Ensure the descriptors are zeroed out on start.
If system conditions prevent the card from loading the firmware without
touching all the descriptors in the ring, it's possible for
wctc4xxp_cleanup_descriptor_ring to attempt cleanup of a command that was never
submitted resulting in the following BUG.

  wctc4xxp 0000:02:0a.0: Failed to load firmware.
  BUG: unable to handle kernel paging request at c109556c
  IP: [<f9faa83e>] wctc4xxp_cleanup_descriptor_ring+0x8c/0x148 [wctc4xxp]

Reported-by: Xavier Carcelle <xcarcelle@avencall.com>
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-05-31 12:10:49 -05:00
Russ Meyerriecks
e2f492595c wcte13xp: New driver for digium's te13x product range
This patch adds support for Digium's new single span T1/E1 cards with built-in
octasic echo canceler.

PCI IDs:
d161:800a te133 - pci express
d161:800b te134 - pci

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-05-28 16:53:38 -05:00
Shaun Ruffell
1f20b5f8fa xpp: Don't use create_proc_read_entry()
Don't use create_proc_read_entry() as that is deprecated, but rather use
proc_create_data() and seq_file instead.

This is needed to compile against Linux 3.10.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
[tzafrir.cohen@xorcom.com: fixed passing /proc/xpp/XPD/summary xbus number]
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Cc: Russ Meyerriecks <rmeyerriecks@digium.com>
Cc: Oron Peled <oron.peled@xorcom.com>
2013-05-24 00:30:33 +03:00
Shaun Ruffell
ba2fdf2dac dahdi_dynamic_ethmf: Don't use create_proc_read_entry()
Don't use create_proc_read_entry() as that is deprecated, but rather use
proc_create_data() and seq_file instead.

This is needed to compile against Linux 3.10.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Cc: Russ Meyerriecks <rmeyerriecks@digium.com>
Cc: Oron Peled <oron.peled@xorcom.com>
2013-05-24 00:30:33 +03:00
Shaun Ruffell
84ccc652b6 dahdi: Replace create_proc_entry() with proc_create_data()
create_proc_entry() was deprecated and replace with proc_create_data() since
it's open to a race condition where the proc entry is visible before the file
operations have been set for it.

The PDE() macro also is no longer available as of Linux 3.10 and is replaced
with PDE_DATA() to get the data member from a proc entry. This is due to the
fact that 'struct proc_dir_entry' is now private to the proc_fs.

This commit changes the core of DAHDI and also introduces proc_create_data() and
PDE_DATA() for older kernels.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Cc: Russ Meyerriecks <rmeyerriecks@digium.com>
Cc: Oron Peled <oron.peled@xorcom.com>
2013-05-24 00:30:33 +03:00
Tzafrir Cohen
40da50faed xpp: FXO: fix firmware pol-rev detection
PIC_TYPE_2 rev. 11078 fixes the polarity reversal detection support added
in rev. 11039 (949aa4958f).

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-05-23 14:50:31 +03:00
Oron Peled
ef71ce476c xpp: FXO: add a "squelch_polrev" parameter
* This will prevent *ANY* polarity reversal reporting to DAHDI.
* False by default.
* Used in some rare sites with really bad line quality.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-05-23 14:50:30 +03:00
Oron Peled
e3e35d031d xpp: FXO: common function for POLREV reporting
Refactor the XPP FXO POLREV reporting into a common function.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-05-23 14:50:30 +03:00
Shaun Ruffell
2b0cca777f oct612x: Fix confusing compile error when kernel source is not present
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-05-20 17:19:55 -05:00
Shaun Ruffell
96652d88c6 wcte12xp: Reset all the framer registers when switching linemodes.
If a span was fully configured before unassigning and reassigning to a new span
type it was possible for stale values to be present in the register. When
switching from T1 to E1 via the spantype sysfs attribute this could result in a
test pattern being written.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-05-20 17:11:21 -05:00
Shaun Ruffell
c4a17f9442 wcte12xp: Allow non-interrupting cards to unload faster.
If a card stops generating interrupts for any reason, it can take awhile to
unload the driver while waiting for the commands to timeout. Now if there is a
problem, immediately set a bit that the card is failed so that no new commands
will be submitted.

Also, do not free and commands in submit since all commands are freed in get
results now. This prevents list/memory corruption when commands time out.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-05-20 17:11:21 -05:00
Shaun Ruffell
9b11847aee dahdi: Completely stop spans when unassigning.
When spans are unassigned, dahdi_span_ops.shutdown was called, but the RUNNING
flag was never cleared. Now make sure all calls to the shutdown span ops
callback are the same.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-05-20 17:11:21 -05:00
Shaun Ruffell
a3ad32c370 dahdi: Prevent potential error when only switching spantype of single span.
If you have a multiple span system configured for t1 mode, and you try to change
only the first span from t1 to e1 via sysfs, you could get an error in the
kernel log about trying to create duplicate channel.

The problem is that the check for whether there was enough room for the all the
channels of the switched span was wrong.

Reported-by: James Brown <jbrown@digium.com>
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-05-13 14:34:49 -05:00
Shaun Ruffell
9a7db0943b wcte12xp: Look for multiple loopup codes before setting looping up the framer.
This brings the wcte12xp driver in line with the wct4xxp driver. It also
eliminates the chance that the local side will errouneously go into loopup when
switched from E1 to T1 mode via the spantype sysfs attribute.

Internal-Issue-ID: DAHDI-1038
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-05-13 14:34:49 -05:00
Shaun Ruffell
db040e5cd7 wct4xxp: Allow vpm450m.c to compile against vanilla 2.6.18.
This adds definitions for bool and pr_fmt which are needed when compiling
against vanilla 2.6.18.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-05-09 12:53:21 -05:00
Shaun Ruffell
244f621eb1 wctdm24xxp: Fix FXO failure to detect battery CO disconnects.
In 2.6.2 I introduced an error in (41639330a "wctdm24xxp: Eliminate chance for
channel to be stuck in RED alarm.") which would get an FXO stuck in detecting an
ONHOOK event from the remote side.  An FXO port could go into the
BATTERY_DEBOUNCING_LOST_ALARM state and then back to the BATTERY_PRESENT state
without sending the dahdi_hooksig up to Asterisk.  Therefore, Asterisk would
never detect the state changes needed for a remote side disconnect.

This change adds two more states, BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM and
BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM so that the state machine does not
miss any needed transitions when going back to BATTERY_PRESENT or BATTERY_LOST
regardless of why the debounce was started.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-05-09 11:35:04 -05:00
Shaun Ruffell
bb5eeccef3 dahdi: Prevent memory corruption on device unload.
The channels now have embedded 'struct devices' that contain a device_private
pointer in which to store the device private data. When a device is
unregistered in the system the device privata data is freed by the device core,
even though the chan_release function doesn't free the memory
associated with the device, So when dev_set_drvdata() is called,
it's writing into freed memory.

We also need zero out the embedded struct device before registration,
since we do not have any guarantee that it points to valid memory (or, if a
channel was unregisterd with sysfs, and then reregistered without being cleared
out).  Otherwise the core could try to use the previously freed private
data again.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-05-08 11:48:28 -05:00
Shaun Ruffell
4641d5b396 wct4xxp: Companding on VPM needs to be changed when switching linemodes.
If a user switches linemode with sysfs, the VPM would never switch the
companding mode to alaw, and the result would be extreme static on all channels
of the span when the VPM is enabeld.

Now if the deflaw of the span has changed when an echocan is created, the
companding mode of the VPM channel is changed.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-05-06 15:42:33 -05:00
Shaun Ruffell
f65299e8b2 oct612x: Break the oct612x out into a separate library.
Soon there will be more than one driver in the source tree that will want to use
these files. Compiling it as a library speeds the build since it won't have to
be built for each driver that wants to link it in.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-05-06 15:42:33 -05:00
Shaun Ruffell
f4d9cbbfb1 dahdi: Save the current maintstat in the span before calling into the drivers.
Some of the card callbacks needed maintstat set when processing loopup codes
from the remote side. This change is a modification of commit: (6c02c3c
"dahdi-base: Minor maint mode error")

Without this change cetain cards would not properly process the loopup /
loopdown codes (I know I should have more specific information here but the
details escape me at the moment).

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-05-06 15:42:33 -05:00
Russ Meyerriecks
a8788692a1 dahdi: Do not define trace_printk if CONFIG_TRACING is not defined.
This was an accidental commit that slipped in as part of (a682401 "dahdi: Expose
dahdi devices in sysfs.")

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-05-06 15:42:33 -05:00
Tzafrir Cohen
be904538c7 README: xpp: xpd_fxo param use_polrev_firmware
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-04-11 10:00:48 -05:00
Tzafrir Cohen
76dda31533 README: xpp: xpd_fxo: new value of caller_id_style
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-04-11 10:00:48 -05:00
Tzafrir Cohen
8f07b4e019 Copy xpp module docs from README.Astribank
Copy xpp module documenttation from README.Astribank in dahdi-tools.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-04-11 10:00:48 -05:00
Tzafrir Cohen
9c031f66a0 README: subsections for module parameters docs
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-04-11 10:00:48 -05:00
Oron Peled
300446b1a1 xpp: FXO: new CID style -- passthrough
Adds support for setting a value of 3 to the module parameter
caller_id_style: passthrough - always pass and don't try to emulate
DTMFs.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-03-28 21:06:47 +02:00
Oron Peled
949aa4958f xpp: FXO: in-firmware polarity-reversal detection
PIC_TYPE_2 rev.11039 adds support for polarity reversal detection. Support
those messages.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-03-28 21:06:34 +02:00
Russ Meyerriecks
a34b846f61 dahdi: Fix unused variable compile warning
An unset conditional compile flag was triggering the unused variable compile
warning. Added the condition around the variable define.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-03-13 16:52:03 -05:00
Russ Meyerriecks
f09daed735 Kbuild: Fix OSLEC build error
Fixes up the kbuild to work with compiling OSLEC from the kernel source. See
HOWTO here: http://forums.digium.com/viewtopic.php?t=67164

Internal-Issue-ID: DAHLIN-317
Reported-By: Vladimir Mikhelson
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-03-13 16:51:53 -05:00
Shaun Ruffell
7714d5d94e build_tools/make_version: Only strip 'v' if followed by a digit.
Do not want to accidentally change the tag "very_cool" to "ery_cool".

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-03-08 12:09:18 -06:00
Shaun Ruffell
9b0d19c054 build_tools/make_version: Strip off the leading 'v' in the version string.
Quote: "It's a change. People hate change"

Make the version string say something like 2.6.2 instead of v2.6.2.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-03-08 11:30:44 -06:00
Shaun Ruffell
d5e5b19a02 dahdi: Tear down conference links when conferences are emptied out.
Otherwise, it's possible for a link to remain in use if a process quits without
unlinking the conferences. Now when all the channels are removed from the
conference, any links are also cleaned up.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-03-07 16:19:05 -06:00
Shaun Ruffell
a4feafc124 dahdi: Restore DAHDI_CONFLINK functionality as compile time option.
This is mostly a revert of commit r9463. If you need to use DAHDI_CONFLINK
ioctl, make sure to define CONFIG_DAHDI_CONFLINK in
include/dahdi/dahdi_config.h. Apparently there were some users of CONFLINK out
there still.

It's a compile time option now since most users won't need to run the test for
conflinks in the hot-path that is the process_masterspan function.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Tested-by: Ted Gerold <ted@twg.org>
2013-03-07 16:19:05 -06:00
Shaun Ruffell
0498450db0 dahdi: Give timers their own file_operations
Trades the memory of a file_operations structure to eliminate some tests in the
timer operations.

Internal-Issue-ID: ABE-2904
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-03-07 16:19:05 -06:00
Shaun Ruffell
b6f6232441 dahdi: Decrease dahdi_timer_lock contention.
On SMP systems there isn't a need for all dahdi timers to
synchronize on dahdi_timer_lock. Instead give each timer it's own
lock to synchronize with process_timers and use dahdi_timer_lock to
protect the global list of locks.

Also, the dahdi_timers list now only contains timers that are set to
fire. This eliminates a test for each timer in the hot path of the
process_masterspan context.

Reduces system load on many-core systems which are heavy users of
DAHDI timers.

Internal-Issue-ID: ABE-2904
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-03-07 16:19:05 -06:00
Shaun Ruffell
37a783b0fe dahdi: Remove call to lock_kernel when calling unlocked_ioctl.
The Big Kernel Lock removal is no longer experimental so we can eliminate the
call to lock_kernel when calling unlock_ioctl.

Internal-Issue-ID: ABE-2904
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-03-07 16:19:05 -06:00
Shaun Ruffell
37371f19e9 build_tools/make_version: If making from a tag show only the tag in the version.
Also, if there is no other version information use the directory name. Downloads
from gitweb will include the sha information in the build and otherwise a user
could locate the source directory via the embedded version information. I
believe this is better than an empty string.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-03-07 16:17:48 -06:00
Tzafrir Cohen
66a300f338 Redefine the removed __dev* for now
The __dev* directives and functions were removed in 3.8, as they
are no-ops. We still have use of them for older versions, thus
we should define them (as noops) if they don't exist.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-01-28 10:18:56 -06:00
Shaun Ruffell
8bf0434896 wctdm24xxp: Eliminate chance for channel to be stuck in RED alarm.
There was a code patch where it was possible to get stuck in RED ALARM on a
channel when debouncing the battery states. The state transitions would look
like this:

BATTERY_PRESENT -> BATTERY_DEBOUNCING_LOST -> BATTERY_DEBOUNCING_LOST_ALARM --
(send alarm up to asterisk) --> BATTERY_LOST -> BATTERY_DEBOUNCING_PRESENT ->
BATTERY_DEBOUNCING_PRESENT_ALARM -> BATTERY_DEBOUNCING_LOST -> BATTERY_PRESENT

In the above sequence there was never any transition from
BATTERY_DEBOUNCING_PRESENT_ALARM to BATTERY_PRESENT so the alarm to Asterisk was
never cleared and the channel stayed stuck.

Now when you loose battery when in the BATTERY_DEBOUNCING_PRESENT_ALARM go all
the way back to the BATTERY_LOST state instead of the BATTERY_DEBOUNCING_LOST
state so that all the events are properly sent up.

This fixes a regression introduced in 2.6.0 with commit (r10169 "wctdm24xxp: Use
interval for debouncing FXO battery." 874b76bd22).

Internal-Issue-ID: DAHDI-1019
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-01-25 11:43:54 -06:00
Shaun Ruffell
a6be603590 wctdm24xxp: Use framecount and not jiffies when looking for battery present.
The logic to check for battery lost and battery present were using different
time bases. One was using jiffies and the other was using framecount. Since
framecount is always in milliseconds, let's use that to stay consistent.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-01-25 11:43:52 -06:00
Shaun Ruffell
85e6cdde83 wcb4xxp: Allocate memory in hfc_decode_st_state() with GFP_ATOMIC.
hfc_decode_st_state() will be called from interrupt context when the debug flag
is set to 32. Therefore, must use GFP_ATOMIC when allocating memory.

Only affects the wcb4xxp driver when called with particular debug flags set.

Internal-Issue-ID: DAHLIN-314
Reported-by: Gerald Schnabel
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-01-23 16:14:07 -06:00
Shaun Ruffell
69fb09d011 dahdi: Initialize the channels cdev structure.
This is necessary to prevent a crash when opening files by the new
device files, which do not have a valid file_operations structure.
This fixes a problem does not exist in any releases of DAHDI.

Since none of the existing tools or applications open files from the
new location of /dev/dahdi/channels/<span>/<offset>, this wasn't
seen until just recently.

Reported-by: Ted Gerold <ted@twg.org>
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-01-22 10:08:02 -06:00
Shaun Ruffell
da0aa6f231 xpp: Do not typedef bool on RHEL 5.2 or later.
Without digging into the specifics, it looks like Red Hat Linux 5.9
removed the hex_asc definition that was previously used to determine
if the bool definition was backported.

We can simply use the RHEL_RELEASE_CODE now since we do not support any
releases before the 5 series now.

Reported-By: Vladimir Mikhelson
Internal-Issue-ID: DAHLIN-312
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-01-22 10:05:23 -06:00
Tzafrir Cohen
a46f906a0d Only use bus and no class for channel devices
It's wrong (and explicit oops with kernel >= 2.6.19) to set both
bus and class for the same device. But setting the class is not needed
in order to create a device. So just remove our dynamic devices from the
dahdi_class. It will only contain the fixed-named devices.

This fixes regression from cb4e4d0068.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2012-12-21 13:36:51 -06:00
Shaun Ruffell
9de213b104 wct4xxp: t4_serial_setup() was called more often than necessary.
The driver iterates through all the spans on a given device during assignment,
checking for unassigned spans, but it was erroneously testing the span on which
assigned was called.

This just removes some unexpected behavior and provides a slight performance
increase on load and does not impact the functionality of the driver as far as
I'm aware.

Reported-by: Doug Bailey <dbailey@digium.com>
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2012-12-21 13:22:37 -06:00
Shaun Ruffell
19cef998bd sysfs: Remove signed one-bit fields.
Eliminates the following warning from sparse:
  drivers/dahdi/dahdi-sysfs-chan.c:50:29: error: dubious one-bit signed bitfield

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2012-12-21 13:22:37 -06:00
Shaun Ruffell
82cf3c7b13 dahdi: Trivial change of '__u32' -> 'u32' in struct dahdi_count.
struct dahdi_count is not directly exposed to user space, so we can use the
native u32 type instead of __u32 to clarify that.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2012-12-21 13:22:37 -06:00
Shaun Ruffell
f916f1e91f dahdi: Move 'timingslips' in with the other maintenance counters.
This allows timingslips to be reset along with the other counters and clarifies
the intended use.

This came up when Doug Bailey asked why he couldn't use dahdi_maint to clear
timing slips in addition to the other counters.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2012-12-21 13:22:37 -06:00
Tzafrir Cohen
a8dfd61e53 gitignore: Add README.html to git ignore list
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2012-12-12 14:18:48 -06:00
Russ Meyerriecks
6846663d1e Merge tag 'review-sysfs-chan' of http://git.tzafrir.org.il/git/dahdi-linux into for-trunk
SysFS Channel representation changes

* Kernel (and SysFS) objects for channels.
* A bus of their own.
* Dynamically allocate a minor (no conflict with /dev/dahdi/timer et. al.).
* Device files located under /dev/dahdi/channels instead of
  /dev/dahdi/spans [e.g: /dev/dahdi/channels/2/4)
  - A link back should is doable with a simple udev rule.
* Bus name is dahdi_channels instead of dahdi_chans
  [e.g: /sys/bus/dahdi_channels]
* Driver name is dahdi instead of dahdi_chans
  [e.g: /sys/bus/dahdi_channels/drivers/dahdi]
* Attributes are all strings (or lists of strings), including 'sig' and
  'sigcap'.
2012-12-12 14:06:11 -06:00
Tzafrir Cohen
e1245b9dd6 Document new channel sysfs interface
Document the new sysfs interface and the changes to /dev .

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2012-12-12 19:23:38 +02:00
Oron Peled
00221e8bfd sysfs: new channel attr (ec_factory, ec_state)
Signed-off-by: Oron Peled <oron.peled@xorcom.com>
2012-12-12 00:18:49 +02:00
Oron Peled
4da324d4df sysfs: stringify channels 'sigcap' attribute
Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2012-12-12 00:18:49 +02:00
Oron Peled
d863af110f dahdi: sysfs: add channel attributes
Signed-off-by: Oron Peled <oron.peled@xorcom.com>
2012-12-12 00:18:49 +02:00
Oron Peled
cb4e4d0068 dahdi: sysfs: use dynamically allocated chrdev's
* Channels have their own dynamically allocated major number
* No arbitrary limit of minor < 250 (no collision with /dev/timer, etc)
* We still have arbitrary limit of channo < DAHDI_MAX_CHANNELS
  (should be raised?)
* FIXME: need to check to FIXME's

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
2012-12-12 00:18:49 +02:00
Oron Peled
3a94ac322d dahdi: sysfs: chrdev region (not usefull yet)
Signed-off-by: Oron Peled <oron.peled@xorcom.com>
2012-12-12 00:18:49 +02:00
Oron Peled
53219879c8 dahdi: sysfs: a channel bus (not usefull yet)
* Added minimal infrastructure:
  - A 'chan_device' member to struct dahdi_chan
  - An empty 'device_attribute' array
  - A 'bus_type' with its methods
  - A 'device_driver' with its methods
  - Initialization/Cleanup code

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
2012-12-12 00:18:49 +02:00
Shaun Ruffell
5f7ebe98da dahdi: Only watch transitions of ABIT when using E&M signalling.
This resolves an issue with a Glenayre GL3000 Paging Terminal with v8.000
software. The Glenayre would change both A and B bits to signal on/off hook
states, but there were a couple of milliseconds between when those bits changed.
This resulted in DAHDI generating an on-hook event to Asterisk before generating
the off-hook event and therefore Asterisk terminated the call prematurely.

Looking the A and B bits before this patch:

Asterisk (AB)   Glenayre (AB)
00              00                 Both sides on-hook
11              00                 Asterisk goes off hook to sieze line.
11              01                 Glenayre starts going-offhook. On-hook event
                                     sent to Asterisk from drivers since bits
                                     changed but ABIT was still 0.
11              11                 Glenayre finishes going off-hook. Off-hook
                                     event sent to Asterisk since ABIT changed
                                     from 0 to 1.
00              11                 Asterisk, processes on-hook event and goes
                                     on-hook itself to release line.
00              00                 Glenayre releases line. Call fails.

After this patch:

Asterisk (AB)   Glenayre (AB)
00              00                 Both sides on-hook
11              00                 Asterisk initiates call
11              01                 Glenayre starts handling call. No event is
                                     sent to Asterisk since only ABIT is checked.
11              11                 Glanayre finishes going off-hook. Call
                                     proceeds normally.

Internal-Issue-ID: DAHDI-1009
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2012-12-11 10:27:57 -06:00
Shaun Ruffell
ef065a5e2a Revert "dahdi_dynamic_eth: Move tx packet flushing to process context."
dahdi_dynamic now always calls the flush function in softirq context so packet
flushing no longer needs to be pushed off to process context since interrupts
are enabled.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2012-12-11 10:27:56 -06:00
Shaun Ruffell
f44b252472 dahdi_dynamic: Use a tasklet for flushing dynamic drivers.
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2012-12-11 10:27:56 -06:00
Tzafrir Cohen
d889fb39d3 Add .gitignore file
Allows 'git status' command to better show untracked files which one may be
interested in.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
Acked-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2012-12-10 16:21:19 -06:00
Tzafrir Cohen
6a3163e05c xpp: pre/post_unregister: not for the EC
Don't run the pre- and post-unregister hooks on a non-phone XPD
(practically: the echo canceller). This fixes a panic with manual
'dahdi_registertion off' as it is now called for the whole device
(regression of 2.6.x).

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10735 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-11-15 13:40:56 +00:00
Tzafrir Cohen
38bf049c45 How to get OSLEC from dahdi-linux-extra
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10734 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-10-11 13:25:28 +00:00
Shaun Ruffell
abad4b4479 wct4xxp: EC channel calculation in TONEDETECT assumes TE820.
Since r10290 "wct4xxp: Add support for TE820 and VPMOCT256." [1],
the TONEDETECT ioctl was not calculating the VPM channel correctly
on non TE820 cards. This fixes a regression first introduced in
2.6.0.

[1] http://svnview.digium.com/svn/dahdi?view=revision&revision=10290

Internal-Issue-ID: DAHLIN-302
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10733 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-10-04 20:24:55 +00:00
Shaun Ruffell
dea3d51b24 dahdi: Running without the Big Kernel Lock (BKL) is no longer experimental.
The warning was originally added in r9721 "dahdi: Experimentally
remove dependency on the Big Kernel Lock." [1].

[1] http://svnview.digium.com/svn/dahdi?view=revision&revision=9721

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10732 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-10-04 20:24:46 +00:00
Russ Meyerriecks
b73e870a3a dahdi: Remove 'getlin_lastchunk' from struct dahdi_chan.
'getlin_lastchunk' has not been used since r65 "Version 0.1.6 from FTP" [1]

One less thing to think about...

[1] http://svnview.digium.com/svn/dahdi?view=revision&revision=65

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10731 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-10-04 20:24:42 +00:00
Shaun Ruffell
da8b96d725 dahdi: Remove unused 'rxbufpolicy' and 'rxdisable' from dahdi_chan.
Since r5021 [1], first released in DAHDI-Linux 2.2.0, it's been impossible for
user space to change the rxbufpolicy. This hasn't caused any problems and it's
safe to remove a few more of the vestiges of the rxbufpolicy from the driver.

This streamlines the code path in a few places and saves 8 bytes from the size
of struct dahdi_chan.

The user visible parts are maintained and will indicate
DAHDI_POLICY_IMMEDIATE, like it has since 2.2.0.

[1] http://svnview.digium.com/svn/dahdi?view=revision&revision=5021

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10730 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-10-04 20:24:37 +00:00
Shaun Ruffell
d349fe62fe wctdm24xxp: Set dahdi_span.spantype to SPANTYPE_ANALOG_MIXED.
Since r10683 "convert span->spantype to enumerated type" [1] the spantype was
changed from a string provided by the board drivers to an enumerated type that
is handled by the core of DAHDI. This was done to simplify the task of
dahdi_genconf since there is only one place to look for the valid strings that
can be exported in sysfs.

This eliminates the following warning on driver load:
  Warning: Span %s didn't specify a spantype. Please fix driver!

[1] http://svnview.digium.com/svn/dahdi?view=revision&revision=10683

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10729 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-10-04 20:24:33 +00:00
Shaun Ruffell
ba595821ce wct4xxp: Ensure all spans are configured by default.
Not configuring all the spans on an octal card can result in some of the
spans not working in clear channel modes.

Now ensure that all spans receive a default configuration regardless how
they are configured from user space.

Internal-Issue-ID: DAHLIN-289
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10728 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-10-04 20:24:29 +00:00
Shaun Ruffell
25ce85e770 dahdi: Filter 'HWEC' from DAHDI_GETVERSION results if hwec is really not present.
Internally in DAHDI there is always a hardware echocan factory registered and
available. Having this factory always registered allows for DAHDI to work in a
backward compatible fashion. Namely, by default DAHDI will always use a hardware
echocan if one is available unless 'hwec_overrides_swec' dahdi module parameter
is set to 0 on load. However, if there were no real hardware echocans available
in the system dahdi would still report "Echo Canceller(s): HWEC" in the
dahdi_cfg -v output since the hwec factory is always there.

After this change dahdi_cfg will no longer report HWEC as one of the available
echocans if there isn't a physical span present that actually has a hardware
echocan.

Internal-Issue-ID: DAHLIN-300
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10727 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-10-04 20:24:24 +00:00
Shaun Ruffell
ca710bae94 dahdi: Increase the number of conference buffers to eight.
When DAHDI is bridging channels between two different cards, or a user is trying
to record from a channel on a card that is not using the same timing source as
the master span, it is possible to miss audio.

For example, given the following scenario:

<T1 Span> <---> <ISDN CARD> <---> <ANALOG CARD> <---> <local handset>

If DAHDI was set to natively bridge the call from the T1 span to the local
handset it is possible that system conditions could result in one of the cards
servicing their interrupt three times before the other card has a chance to.
Since there are currently only two conference buffers to pass audio between the
cards, one chunk (1ms) of audio will be dropped since the card servicing it's
interrupt more frequently will run out of space to copy audio for the other card
and will have emptied the audio buffer from the other card.

Increasing the number of conference buffers to eight greatly reduces the
probability of audio from being dropped under these conditions at cost of an
additional 72 (32-bit) or 96 (64-bit) bytes per DAHDI channel.

Internal-Issue-ID: DAHLIN-159, DAHDI-976
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10726 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-10-04 20:24:17 +00:00
Shaun Ruffell
84e70cdac5 wctdm24xxp: Only two polarity reversals are needed to validate RING on FXO ports.
This fixes a regression introduced in commit r10186 "wctdm24xxp: Use time
interval for debouncing FXO ring detect." [1] which was first released in
DAHDI-Linux 2.6.0. This only affects users with analog trunks whose providers do
not present 4 polarity reversals on the ring signals. The reporter of this issue
is based in South Africa.

[1] http://svnview.digium.com/svn/dahdi?view=revision&revision=10168

In prior versions, the ring detector did not check for polarity reversals, only
the presence of ringing voltage unless fwringdetect or neonmwi_monitor mode was
set, and even when one of those modes were set, the driver only needed two
reversals to validate a ring. This commit allows the driver to always stay in
fwringdetect mode but restores the requirement for only two reversals.

Also included in this commit is a change to ensure that ringing is not reported
when debouncing lost battery which can happen when voltage is swinging through
0.

Reported-and-Tested-by: Jaco Kroon <jaco@uls.co.za>
Internal-Issue-ID: DAHLIN-298
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10719 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-09-21 18:16:35 +00:00
Russ Meyerriecks
6c02c3c156 dahdi-base: Minor maint mode error
The previous maint state was saved regardless if the base driver returned an
error or not. This caused strange behavior in dahdi tools. Moved the maint
state save to after the switch case to reflect this.

https://issues.asterisk.org/jira/browse/DAHDI-984

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10718 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-09-21 18:16:30 +00:00
Shaun Ruffell
fe791b5b02 dahdi: pci-aspm.h was included in 2.6.26 not 2.6.25.
When compiling against kernels 2.6.25, you could get the following error.

  error: linux/pci-aspm.h: No such file or directory

This fixes a build regression introduced in r10556 "dahdi: Add
dahdi_pci_disable_link_state for kernel < 2.6.25." [1]

[1] http://svnview.digium.com/svn/dahdi?view=revision&revision=10556

Reported-by: Jean-Philippe Lord
Internal-Issue-ID: DAHLIN-299
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10705 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-08-16 21:32:40 +00:00
Shaun Ruffell
7e614f4d29 wcte12xp: Fix stack corruption when checking T1 RBS states.
This fixes an (embarrassing) error in t1_check_sigbits in the previous commit
where I was writing pass the end of an array on the stack.

Now instead of using an array on the stack, of which all elements were not used,
the pending commands are now stored on a list. I also removed the automatic free
of commands from __t1_getresults and now the function that allocated the command
now frees them.

I believe this will be less error-prone going forward.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10700 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-07-11 16:13:22 +00:00
Shaun Ruffell
24ed250673 wcte12xp: Fix pulse digit detection when set for FXO signalling modes.
The frequency that the RBS registers were polled was too slow to catch the pulse
dialing digits. The result was that often times dahdi would generate WINK events
instead of PULSEDIGIT events.

This speeds up the rate at which the registers are checked from 100ms to 33ms
and also makes the process of checking the registers quicker by queing up all
the reads at once.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10699 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-06-26 17:10:54 +00:00
Shaun Ruffell
3d89ef975c wcte12xp: Allow default_linemode to be set to j1.
To enable J1 mode previously one would configure the card in T1 mode and then
set the j1mode module parameter. Now "modprobe wcte12xp default_linemode=j1"
will work like the other linemodes globally for all cards manged by this driver.
J1 can also be set on a card-by-card basis in sysfs.

Also move pr_fmt to top of file so pr_xxx macros print the module name as
intended.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10696 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-06-22 17:59:37 +00:00
Shaun Ruffell
eecf45cf5f wcte12xp: Destroy the cache if the linemode is not recognized.
Fixes the following errors when running:
  # modprobe wcte12xp default_linemode=blah; modprobe wcte12xp default_linemode=blah

'blah' is an unknown span type.kmem_cache_create: duplicate cache wcte12xp

Call Trace:
 [<ffffffff800394cf>] kmem_cache_create+0x572/0x5ac
 [<ffffffff800a926e>] __link_module+0x0/0x18
 [<ffffffff80064624>] __down_read+0x12/0x92
 [<ffffffff8002224d>] __up_read+0x19/0x7f
 [<ffffffff8818b01f>] :wcte12xp:te12xp_init+0x1f/0xde
 [<ffffffff800a9e37>] sys_init_module+0xbd/0x206
 [<ffffffff8005d28d>] tracesys+0xd5/0xe0

Reported-by: James Brown <jbrown@digium.com>
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10695 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-06-22 17:59:34 +00:00
Oron Peled
76ce8d5951 xpp: usermode_helper() bugfix for kernels >= 3.3.0
* UMH_WAIT_PROC semantics (and value) was changed from enum to
  a bitmask (via #define)
* This constant was missing from kernels older than 2.6.23

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10692 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-06-21 17:34:09 +00:00
Tzafrir Cohen
c73656edc5 README fixes: DKMS indentation and such
git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10691 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-06-11 11:58:14 +00:00
Shaun Ruffell
e903273e3c dahdi_ioctl_spanstat() backward compat hack
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10686 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-05-23 12:39:07 +00:00
Shaun Ruffell
1058502286 sysfs: refactor lineconfig string representation
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10685 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-05-23 12:36:42 +00:00
Shaun Ruffell
bb2c15c103 sysfs: add a linecompat span attribute
This way, dahdi_genconf may gather needed information without issuing
ioctl()'s

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10684 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-05-23 12:35:56 +00:00
Shaun Ruffell
579132bb89 convert span->spantype to enumerated type
* This is a minimal convertion -- everything compiles and looks OK.
* We print a warning for spans registering without a spantype.
* Low-level drivers may later want (but not required)
  to fold their internal representations to this canonical
  representation -- it will save code and make it more readable.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10683 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-05-23 12:20:23 +00:00
Doug Bailey
b7081c2b45 Assign NULL values to pointers to insure that future kfree calls do not cause errors.
git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10678 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-27 19:36:55 +00:00
Shaun Ruffell
e8e460af8a wcb4xxp: Fix typo in last commit that broke compilation.
I failed to compile test r10661 and introduced a typo when fixing a
checkpatch.pl warning.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10662 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-18 00:17:15 +00:00
Matthew Fredrickson
d6c9c4c9da wcb4xxp: Support for when network side deactivates layer1.
This is a port of the functionality in the wctdm24xxp driver to support power
savings modes. Specifically, if the the network side of a BRI spans deactivates
the span to save power, the B410P  previously automatically activated it again.
Now, if persistentlayer1=0 module parameter is set, the span will be allowed to
stay deactivated until layer two has a message to send on the dchannel.

This patch does not change any of the default behavior of the B410P driver and
the defaults for the persistentlayer1 option is inconsistent with that of the
B400M modules in the wctdm24xxp driver.

Internal-Issue-ID: ABE-2845
From: Matthew Fredrickson <creslin@digium.com>

[ Minor formatting, exposed the persistentlayer1 as module parameter, changed
defaults for teignorered, alarmdebounce, and persistentlayer1 to match current
defaults in wcb4xxp driver ]

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10661 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-18 00:12:06 +00:00
Shaun Ruffell
5cbf189ec4 xpp: Fix compilation when CONFIG_DAHDI_WATCHDOG is defined.
Looks like a hold over from when dahdi_span_ops was first implemented in r8985
"dahdi: Move the callbacks in dahdi_span into its own structure" [1].

[1] http://svnview.digium.com/svn/dahdi?view=revision&revision=8985
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10658 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-11 20:09:44 +00:00
Mike Sinkovsky
d70f59d6e0 dahdi: Fix compilation when CONFIG_DAHDI_WATCHDOG is defined.
From: Mike Sinkovsky <msink@trikom.ru>

Internal-Issue-ID: DAHLIN-288
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10655 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-11 17:39:31 +00:00
Tzafrir Cohen
199cd70d2c FPGA_1161.201.hex rev 10545: fix reset of XR1000
Previous commit (r10649) included an incorrect version. Including full message
from that commit for the description.

rev. 10502 of the FPGA firmware for the new E-Main rev. 4 fixes a potential
issue when used on Xorcom XR1000 systems: an issue with the power supply may
cause the unit to reset.

Note that there is no issue with previous models, with a normal setup of an
Astribank, or other XRx000 systems.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10652 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-11 09:06:29 +00:00
Tzafrir Cohen
432e83165c FPGA_1161.201.hex rev 10532: fix reset of XR1000
rev. 10502 of the FPGA firmware for the new E-Main rev. 4 fixes a potential
issue when used on Xorcom XR1000 systems: an issue with the power supply may
cause the unit to reset.

Note that there is no issue with previous models, with a normal setup of an
Astribank, or other XRx000 systems.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10649 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-10 21:36:43 +00:00
Shaun Ruffell
a1c4dfb99c wcte12xp, wctdm24xxp, wct4xxp: Print warning about potential GPL violation w/HOTPLUG_FIRMWARE=no.
Print a warning message that it may be a GPL violation to redistribute these
binaries if the firmware for the VPMOCT032/64/128/256 is compiled in.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10646 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-05 20:32:37 +00:00
Shaun Ruffell
b0801b23e8 wcb4xxp: Remove asm/system.h include.
Not needed anymore and will break compilation on Kernel versions >= 3.4 since
commit 0195c00244dc2e [1]

[1] http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commit;h=0195c00244dc2e

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10641 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-05 16:15:27 +00:00
Shaun Ruffell
3d52bdd52f dahdi_dummy: Include timer.h instead of time.h
It appears that some kernel configurations do not include timer.h in any of
the include files that are included by dahdi_dummy. The timer_structs are
defined in timer.h and not time.h, so this change is correct even though I
never could find a configuation myself that actually failed to compile.

This has negligible impact since dahdi_dummy is not compiled by default.

Internal-Issue-ID: DAHLIN-185
Reported-by: Steve Murphy
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10640 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-05 16:15:22 +00:00
Shaun Ruffell
f800ac611f dahdi: Fix compilation when CONFIG_DAHDI_NET is defined.
'irq' field was removed from dahdi_span in r10276 "dahdi: Remove
dahdi_span.irq and move dahdi_span.irqmisses into dahdi_device." [1]
which was first released in dahdi-linux 2.6.0.

[1] http://svnview.digium.com/svn/dahdi?view=revision&revision=10276

Reported-by: Pavel Selivanov
Internal-Issue-ID: DAHLIN-278
Patches: hdlc.patch by Pavel Selivanov (license #5420)
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10634 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-03 21:54:34 +00:00
Shaun Ruffell
8b3870e6a7 dahdi: Fix compilation when CONFIG_DAHDI_ECHOCAN_PROCESS_TX is defined.
'ec_state' was renamed to 'dahdi_echocan_state' in r6529 [1] but support for
CONFIG_DAHDI_ECHOCAN_PROCESS_TX was first committed in r9442 [2]. So it
appears that I never compiled tested this exact commit when it went in for the
2.5.0 release.

[1] http://svnview.digium.com/svn/dahdi?view=revision&revision=6529
[2] http://svnview.digium.com/svn/dahdi?view=revision&revision=9442

Reported-by: Pavel Selivanov
Internal-Issue-ID: DAHLIN-279
Patches: ec.patch uploaded by Pavel Selivanov (License #5420)
[ edited the patch slightly for minor formatting ]
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10633 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-03 21:54:29 +00:00
Shaun Ruffell
347fe2b225 dahdi_dynamic_loc: Change and check the dyn->pvt pointer under lock.
Fixes a crash on unload if the sync_tick callback was running at the same time
the dynamic local span was destroyed. It was possible for
dahdi_dynamic_local_transmit to dereference a pointer that may have already
been freed.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10627 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-03 19:44:45 +00:00
Shaun Ruffell
034818dd81 dahdi_dynamic_eth: Make ztdeth_exit() symetrical with ztdeth_init() and fix race on unload.
Minor change to follow generally recommended practice. Prevents new packets
from being queued up for devices when they are about to be cleaned up. Also
clean up any skbs that may still be on the queue after unloading.

Also closes anoter potential kernel oops on module unload. It was possible to
delete the private structure while the master span process was running. The
result was an attempt to page memory from interrupt context.

Make sure that the pvt function is set and cleared under the zlock. Also do
not assume that the pvt pointer is valid in ztdeth_transmit.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10626 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-03 19:44:41 +00:00
Shaun Ruffell
9c0bb57efb dahdi_dynamic: Close race on unload if red alarm timer was running when unloaded.
I saw a kernel oops that was the result of the timer running after the
dahdi_dynamic module was unloaded. Now we wait for the timer to complete, and
then delete it again in case it reactivated itself.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10625 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-03 19:44:37 +00:00
Shaun Ruffell
d46ad9bca1 dahdi_dynamic: Remove calls to __module_get().
The board drivers are the ones calling the unregister function, and
therefore we do not need to worry about them unloading while calling the
destroy callback.

When destroying spans with the ioctl, replace __module_get() with
try_module_get. This avoids hitting a BUG in module_get on kernel versions <
2.6.29.

ALSO move the call to try_module_get out of the dahdi_dynamic_release function
and into destroy. This way if the destroy callback isn't called because the
dynamic driver is unloading the dynamic device can be left on the list to be
cleaned up by the dahdi_dynamic_unregister_driver function().

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10624 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-03 19:44:33 +00:00
Shaun Ruffell
4ee22f19d1 dahdi_dynamic: Do not call into dahdi_dynamic without holding reference.
Instead of registering a function pointer, register a dahdi_dynamic_ops
structure that contains the owner as well as the ioctl callback. This way
dahdi.ko can bump up the reference count on dahdi_dynamic.ko before calling
the ioctl callback.

Also, use the registration mutex to guard against the module being unloaded
between the time the structure pointer was checked, and the module reference
is taken.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10623 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-03 19:44:27 +00:00
Shaun Ruffell
7e9491bce1 wctdm24xxp, wcte12xp: Allow VPMOCT032 firmware to be compiled into driver.
Enables the driver to update firmware on systems that do not have the firmware
loader configured / enabled (Linux config option CONFIG_FW_LOADER). Compiling
the firmware into the driver increase the memory footprint by around ~440K.

Internal-Issue-ID: DAHDI-963
Reported-and-Tested-by: Guenther Kelleter
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10618 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-02 13:58:11 +00:00
Shaun Ruffell
eab20e05cb Remove Makefiles that are only needed on kernels < 2.6.9
Newer versions of kernel build system do not require these Makefiles and
support for kernels older than 2.6.9 are no longer supported by DAHDI.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10617 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-02 13:58:03 +00:00
Shaun Ruffell
0cd7f34201 wctdm24xxp: Remove forward declaration of inline for GCC 3.4.4
GCC 3.4.4 does not allow forward declaration of inline functions.

Internal-Issue-ID: DAHLIN-286
Reported-by: Guenther Kelleter
Patches: wctdm24xxp-inline.patch uploaded by Guenther Kelleter (License #6372)
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10613 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-29 15:25:23 +00:00
Shaun Ruffell
ed60a36854 wct4xxp: Trivial formatting changes around request_irq.
Quiet some checkpatch warnings introduced by the last patch. I kept this
separate since it may have obscured the real change made in the previous
commit if combined.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10590 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-22 18:31:22 +00:00
Shaun Ruffell
2b60d3b8e0 wct4xxp: Disable all interrupts explicitly in interrupt handler.
The driver makes the assumption that interrupts are disabled but this cannot
be guaranteed. We'll explicity disable interrupts on the local processor while
the interrupt handler is running.

This eliminates the "IRQF_DISABLED is not guaranteed on shared IRQs" warning
when loading the driver.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10589 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-22 18:31:17 +00:00
Shaun Ruffell
b69830b3d3 dahdi_dynamic_eth: Fix compilation on kernels < 2.6.22.
Resolves the follwing build error:
  drivers/dahdi/dahdi_dynamic_eth.c: In function ‘ztdeth_exit’:
  drivers/dahdi/dahdi_dynamic_eth.c:448: error: implicit declaration of function ‘cancel_work_sync’

RHEL kernel versions 2.6.18-238 (5.6) and greater had cancel_work_sync()
backported which is what I did my original smoke test on.

Reported-by: Oron Peled <oron.peled@xorcom.com>
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10588 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-22 18:31:13 +00:00
Shaun Ruffell
e54f0189a7 dahdi_dynamic_eth: Prevent crash is packet arrives before span is fully configured.
It was possible after a dynamic ethernet span was created for a packet to come
in before the dahdi_span was fully initialized. The result would be a NULL
pointer dereference. Now just discard any packets that might come in during
this time window.

Internal-Issue-ID: DAHLIN-280
Reported-by: Pavel Selivanov
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10587 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-22 18:31:08 +00:00
Oron Peled
59caf11dbe xpp: FXS: added a 'lower_ringing_noise' parameter
* Adds a new parameter, 'lower_ringing_noise', to module xpd_fxs.

* Makes the "power-down" behaviour that was added
  in upstream svn r10478, switchable in runtime.

* By default (false), makes the vbat_h behave like it did
  before the power-down change.
  - I.e: vbat_h is held throughout the ringing period (during
    both ring-up/ring-down)
  - So this patch revert part of r10478

* When switched to true, activate the "power-down" behaviour.
  - I.e: vbat_h follows the ring-up/ring-down.
  - This behaviour lowers the noise caused by group ringing of
    FXS channels in the same unit, but causes problems with CallerID.

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10574 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-21 20:18:26 +00:00
Oron Peled
8aad29e4de xpp: FXS: atomic vbat_h power handling
* In do_chan_power() make vbat_h changes atomic.
* As a result we can ignore duplicate requests.
  This will allow cleaner logic in the next commit.
* Added proper debug messages.

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10573 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-21 20:17:14 +00:00
Shaun Ruffell
3e1c317323 dahdi_dynamic: Since dynamic devices are 'parentless' we must name them.
This in conjunction with r10449 "A parent-less device should not crash dahdi",
this allows dahdi_dynamic spans to work post the dahdi_devices changes in
2.6.0.

The full address of the device is not used since kernels prior to 2.6.31 limit
the length of a devicename to 20 characters.  The full address of the device
can be pulled out of the "hardware_id" and "type" fields of the span.

This patch is just to get things working again. dahdi_dynamic devices *may*
still have issues if the auto_assign_spans module parameter is 0.

Internal-Issue-ID: DAHLIN-280
Reported-by: Pavel Selivanov
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10563 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-21 18:56:21 +00:00
Shaun Ruffell
4769ee67cd dahdi_dynamic_eth: Move tx packet flushing to process context.
The masterspan can be, and often is, called with interrupts disabled but
dev_queue_xmit() needs to be called with interrupts enabled. This potentially
fixes a deadlock.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10562 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-21 18:56:16 +00:00
Shaun Ruffell
5dd3050d5a dahdi: Update dev_set_name / dev_name for RHEL 5.6+.
This is needed because dev_name() is mapped to kobject_name() in a backport,
but the kobject name isn't set until after device_add().  The result would be
parentless devices would fail since dahdi would not think a name was set for
these devices.

For these systems, we'll set both the bus_id string and the underlying
kobject_name.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10561 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-21 18:56:12 +00:00
Shaun Ruffell
bf4919e46b Update Digium copyright on files changed since beginning of the year.
In addition to updating the year, this also adds some boilerplate to
dahdi-sysfs.c and dahdi-sysfs-chan.c that wasn't there previously.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10560 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-21 18:56:05 +00:00
Shaun Ruffell
aa8bd2f546 wct4xxp: __t4_frame_in and __t4_framer_out slowdowns.
This is a partial revert of r10234 "wct4xxp: __t4_framer_in and
__t4_framer_out speedups."

There were some platform + firmware version combinations that would fail to
properly configure the framer with the aforementioned speedups. The originally
reported sympton was that interrupts would fail to start and while
troubleshooting I also saw cases where one of the spans would stay in alarm
after starting. By adding in additional reads to the version register, the
overall process of writing / reading from the framer control registers is
slowed down which increases reliability.

This change does *not* affect the main path of TDM data which is DMAed
directly into buffers in host memory and are not read / written to / from
framer registers directly.

Reported-and-Tested-by: Vahan Yerkanian <vahan@arminco.com>
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10559 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-21 16:34:06 +00:00
Shaun Ruffell
0f61ab172d wct4xxp: Add compile-time option to disable ASPM for PCIe devices.
Certain BIOSes appear to enable ASPM even though it is not fully supported by
the platform. Also, since the PCIe links for TDM cards are always in use it
does not make sense to allow them to transition to the disabled state.

Just turn off power management on the PCIe links completely. For more
information see http://lwn.net/Articles/449448/.

Internal-Issue-ID: DAHLIN-283
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10558 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-21 16:34:02 +00:00
Shaun Ruffell
2c97dd21bd wcte12xp, wctdm24xxp: Add compile-time option to disable ASPM for PCIe devices.
Certain BIOSes appear to enable ASPM even though it is not fully supported by
the platform. Also, since the PCIe links for TDM cards are always in use it
does not make sense to allow them to transition to the disabled state.

Just turn off power management on the PCIe links completely. For more
information see http://lwn.net/Articles/449448/.

Internal-Issue-ID: DAHLIN-283
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10557 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-21 16:33:57 +00:00
Shaun Ruffell
da11ba2f0f dahdi: Add dahdi_pci_disable_link_state for kernel < 2.6.25.
Will allow the ASPM (Active State Power Management) state to be disabled on
PCIe devices before kernel version 2.6.25.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10556 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-21 16:33:51 +00:00
Tzafrir Cohen
b278ce23b5 xpp: firmwares: useless 0x1A at EOF
Remove a mostly harmless 0x1A (^Z) at the end of the file. If you
add a NL after it, it breaks the firmware loading.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10550 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-20 10:53:39 +00:00
Tzafrir Cohen
857801bd37 xpp: also install the new .201 fixrmware files
The Makefile changes needed to install the two new files.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10536 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-18 15:35:11 +00:00
Tzafrir Cohen
f26bd63c6c xpp: firmwares to support E-Main 4
USB firmware (USB_FW.201.hex 10402) and FPGA firmware
(FPGA_1161.201.hex 10480) with support of the new E-Main 4 Astribank
mainboard.

(This was accidentally labeled as 'E-Main 3' in some previous commit
messages)

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10535 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-18 14:49:58 +00:00
Tzafrir Cohen
e2bf7013ef xpp: USB_FW rev 10401: minor 6FXS/2FXO caps issue
Fixes an issues with the 6FXS/2FXO module: if an extra FXS or FXO module
is added to a system with such a module, an excessive number of port
licenses was accidentally required (as if the 6FXS/2FXO module required
8FXS/8FXO licenses).

Internal-Issue-ID: #1371
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10534 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-18 14:46:57 +00:00
Shaun Ruffell
92e2020fd2 dahdi_dummy: Fix compilation since dahdi-linux 2.6.0.
Even though dahdi_dummy is no longer built by default, the adoption of
dahdi_devices in 2.6 broke the ability to compile. This was not intended as
there are some packagers who still patch the Kbuild file to enable
dahdi_dummy.

Internal-Issue-ID: DAHLIN-274
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10486 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-15 16:01:22 +00:00
Shaun Ruffell
d1be14acf2 xpp: '%d' -> '%lu' when displaying module_refcount on kernel versions >= 3.3
Upstream commit bd77c047 "module: struct module_ref should contains long
fields" changed the return of module_refcount from int to unsigned long. This
change eliminates a warning from the string format specifier.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10485 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-15 15:41:40 +00:00
Shaun Ruffell
59197c5112 xpp: Use 'bool' type for boolean module parameters on kernel versions >= 2.6.31.
Eliminates warnings that are a result of upstream commit 72db395ffa
"module_param: check that bool parameters really are bool."

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10484 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-15 15:41:36 +00:00
Shaun Ruffell
07c9bcecf2 dahdi: Remove __exit annotation from dahdi_sysfs_exit().
This removes the following warning:

Section mismatch in reference from the function init_module() to the function .exit.text:dahdi_sysfs_exit()
The function __init init_module() references a function __exit
dahdi_sysfs_exit(). This is often seen when error handling in the init
function uses functionality in the exit path.  The fix is often to remove the
__exit annotation of dahdi_sysfs_exit() so it may be used outside an exit
section.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10483 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-15 15:41:32 +00:00
Shaun Ruffell
2da38234d6 dahdi: Use monotonic clock for coretimer.
DAHDI internal timing currently uses the "wall clock" to determine how much
time is passing for mixing and timers. When the wall time changes, like when
the system time is set via ntp or date, DAHDI currently will display a
"Detected time shift" message since it believes there is too much audio to
mix. There may also be audio problems if the wall time is shifting
occasionally due to slewing of the clock.

Now use a monotonic clock to determine how much real-time has passed for
timing purposes. This makes DAHDI insensitive to any changes in the wall time
on the system.

This only applies when using DAHDI's internal timer like when there are not
any telphony cards installed. There are still potential audio problems if the
platform is unable to accurately determine the passage of time.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10482 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-15 15:41:27 +00:00
Tzafrir Cohen
7ee8ba80cc README: note on DKMS
git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10480 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-15 14:39:15 +00:00
Oron Peled
791a701524 xpp: FXS: improve fxs_info output layout
* Rotate the channels table in /proc/xpp/XBUS-*/XPD-*/fxs_info
  - This way we don't overflow 80 columns
  - Can also add more info items per-channel
* Linearize LED output for easier grep'ping

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10479 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-15 12:53:07 +00:00
Oron Peled
12e2626351 xpp: FXS: better power-down to lower noise
* Now every linefeed control command which is not RING'ing
  powers-down the SLIC. This reduce audible noise when
  several channels are ringing.

* Simplify code by removing redundant calls to do_chan_power()
  before linefeed_control()

* Manage vbat_h state so we skip do_chan_power() calls when
  there isn't a state change

* Export vbat_h state to /proc/.../fxs_info

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10478 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-15 12:52:32 +00:00
Oron Peled
1fbf6d8562 xpp: BRI: make it always SYNC_MODE_AB (like PRI)
Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10477 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-15 12:52:07 +00:00
Oron Peled
bb63d03bba xpp: PRI/BRI: fix channels opening/closing:
* If a DAHDI_AUDIO_NOTIFY is issued, offhook the channel
   (added to BRI).

 * If D-channel is closed, onhook all channels (added to PRI)

 * If a clear channel is closed and the D-Channel is not
   open (e.g: with patgen/pattest), onhook this channel
   (added to both BRI and PRI)

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10476 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-15 12:51:22 +00:00
Oron Peled
40d3c42686 xpp: init_card: better variable naming
Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10475 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-15 12:50:49 +00:00
Oron Peled
ee8bc184da xpp: reset Astribank SPI busses
* A driver reload should reset Astribank hardware
* This patch send an SPI reset after we get AB_DESCRIPTION reply from Astribank

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10474 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-15 12:49:55 +00:00
Shaun Ruffell
e07a70f403 wctdm24xxp: Shorten RINGOFF debounce interval from 512ms to 128ms.
In commit r10168 "wctdm24xxp: Use time interval for debouncing FXO ring
detect" [1], I inadvertently changed the debounce interval of the RINGOFF
event from 128ms to 512ms. The result was a potential failure to detect CID,
depending on line conditions, since Asterisk would bump the rx gains on the
channel in the middle of the CID spill as opposed to before the CID spill.

This fixes a regression first introduced in DAHDI-Linux 2.6.0.

[1] http://svnview.digium.com/svn/dahdi?view=revision&revision=10168

Internal-Issue-ID: DAHDI-951
Reported-and-Tested-by: Jack Wilson <ljwilson@digitalav.com>
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10473 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-13 22:12:37 +00:00
Oron Peled
fc1824fd3c Remove support for kernels < 2.6.18
This patch removes support for kernel versions < 2.6.18, as those are
not actively supported in any major Linux distribution (except RHEL4,
which is in the "extended" support level of the product life cycle).

This removes much of the more #ifdef-rich parts of the code.

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Acked-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10472 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-13 20:09:12 +00:00
Oron Peled
308a773fb2 sysfs channels: cleanup device files handling
* Shortcut CLASS_DEV_CREATE/CLASS_DEV_DESTROY. No need to pass repetitive
  data (and NULL) on every call.

* Create/remove fixed device files (ctl, timer, channel, pseudo) via
  generic code (fixed_devfiles_create()/fixed_devfiles_remove()) instead
  of repetitive code and flags.

* Try to make all removal/cleanup functions idempotent, so we can
  safely call them on any failure without the need for multiple goto
  destinations.

* Rename 'device_state_flags' to 'should_cleanup' and its member
  flags to a better/consistent naming.

* Rename dahdi_sysfs_exit() to dahdi_sysfs_cleanup() and call it from
  a new proper dahdi_sysfs_exit()

* In dahdi_sysfs_init(), handle dahdi_sysfs_chan_init() failures

* Add dahdi_dbg() message before creating/removing all DEVICES
  objects.

* Also move two KERN_INFO messages to a more correct locations:
  - The version reporting should be first (in dahdi-base.c)
  - The "Telephony... on major" reporting should be at the end
    of dahdi_sysfs_init()

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10464 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-02-22 12:12:10 +00:00
Oron Peled
56a3c35273 sysfs channels: dahdi-sysfs-chan.c
* Move sysfs class and device files management into dahdi-sysfs-chan.c
* This does not change functionality, just a preparation for later
  code cleanups and improvements.

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10463 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-02-22 12:11:48 +00:00
Oron Peled
6b59211b3d sysfs channels: refactor compat macros
* Refactor all kernel version compatibility macros that relate
  to sysfs and device files to new header: dahdi-sysfs.h
* No functional change.
* Preparing for a refactor channel device file handling into a new
  source file.

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10462 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-02-22 12:11:23 +00:00
Oron Peled
3df0b7aedc sysfs: add 'lineconfig' attribute to span
This patch exposes the span 'lineconfig' via sysfs: textual representation
of the framing and coding of the span.

This is needed in order for the Dahdi perl classes (in tools) to get
the inforamtion for e.g. dahdi_genconf to work without the guesswork of
parsing /proc/dahdi .

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10461 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-02-22 12:10:59 +00:00
Oron Peled
84b9b4c84a dahdi: build fix for Kernels < 2.6.16
* Fixes building for kernels < 2.6.16 (and some older Centos 4 ones).
* Broken by http://svn.asterisk.org/svn/dahdi/linux/trunk@9721
  (Jan-2011)

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10460 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-02-09 15:25:33 +00:00
Oron Peled
1c6d3ad23c code cleanup: remove unused debug_printk()
The dahdi_echocan_* modules had an unused debug_printk() macro. Remove
them because:

* They were unused
* There were multiple definitions
* They were unsafe. Someone doing an
    if(foo)
      debug_printk(...);
    else
      do_something();
  may be surprised ;-)
* They used 'debug' as a debug level, while the rest of DAHDI debug
  macros treat it as a bit-field.

Leave only a single definition in wcte12xp/base.c which is safe.

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10459 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-02-09 15:25:03 +00:00
Oron Peled
9f37999c19 code cleanup - refactor module_printk()
* Remove multiple definitions
* Move canonical one to include/dahdi/kernel.h

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10458 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-02-09 15:24:40 +00:00
Tzafrir Cohen
4762177be0 USB_RECOV.hex: recovering from xpp hardware issues
USB_RECOV.hex, rev. 9760. It may be used to recover from certain
issues of the USB controller of the Astribank (when an Astribank
is not detected as such) by Support staff.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10455 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-02-07 21:50:04 +00:00
Oron Peled
8e22110bfd fix class_create() return value test
In case of error class_create check IS_ERR()/PTR_ERR() and not for NULL.

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10453 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-25 22:02:37 +00:00
Oron Peled
3cf9003a26 xpp: FXO: improve ring debounce notice
* Less jargon.
* Fixes calculation: shows time passed rather than remaining time.
* Closes xorcom #1398.

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10452 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-25 22:02:08 +00:00
Oron Peled
7c8586d4f1 show Master change to/from core timer
show Master change to/from core timer if DEBUG_MAIN (GENERAL) flag is on.

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10451 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-25 21:19:45 +00:00
Oron Peled
ed6def895b A channel-less span should not crash dahdi
* Always check span->channels before accessing span->chans[0]
* Clean one dev_notice() text that accessed span->chans[0]
* Check channels in basechan_show() sysfs attribute

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10450 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-25 21:18:25 +00:00
Oron Peled
b8b7b86332 A parent-less device should not crash dahdi
* A parent-less device should not crash dahdi:
  - Access span->parent->dev instead of span->parent-dev.parent
    in soem cases.
  - Access span->parent->dev via new inline span_device()
  - Use span_device() in all dahdi_dev_{dbg,info}()

* Allow low-level drivers to set their device name.
  - Drivers that don't use this feature get the default name
    based on the parent device name
  - Parent-less devices which don't set their name, fails
    to register with -EINVAL

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10449 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-25 21:18:00 +00:00
Tzafrir Cohen
20c316ee21 dev_set_name(): remove unneeded ';'
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10448 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-25 21:17:34 +00:00
Oron Peled
57e827b2f4 remove a duplicate dev_set_name()
Remove duplicate definition from dahdi-sysfs.c

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10447 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-25 21:17:10 +00:00
Oron Peled
ac95ade8ae better chan_printk() output
Add the word "chan-" before channel numbers

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10446 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-25 21:16:40 +00:00
Tzafrir Cohen
b79e172d23 Astribank I firmwares rev. 7107
A slightly newer firmware (Xorcom rev. 7107) for older (non Astribank
II) Astribank modules. Was accidentally left uncommited. Includes minor
bug fixes.

No change for any relatively recent (Astribank II) Astribank.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10443 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-25 18:34:43 +00:00
Tzafrir Cohen
f76ebe2d75 Build OSLEC EC if in the tree
Build the OSLEC echo canceller (drivers/staging/echo and
dahdi_echocan_oslec) if the code of oslec is present in the tree.

Also closing another issue regarding documentation of building OSLEC,
as it is now even clearer than before.

Patch has been used in the Debian package for quite some time.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

(closes issue DAHLIN-110)
Reported by: biohumanoid (Pavel Selivanov)
Patches:
     oslec_auto.diff uploaded by tzafrir (license 5035)

(closes issue DAHLIN-261)

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10440 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-17 14:26:25 +00:00
Oron Peled
ad60b833e8 dahdi: style - checkpatch clean dahdi-sysfs.c
Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10439 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-12 18:40:15 +00:00
Oron Peled
8228de4d11 xpp: style - remove extra braces
Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10438 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-12 17:14:15 +00:00
Oron Peled
2f03aa8bcb xpp: style - kfree() is NULL safe
Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10437 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-12 17:13:41 +00:00
Oron Peled
9e541045d9 xpp: style - add const to file_operations
Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10436 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-12 17:13:15 +00:00
Oron Peled
a28ffb3af5 xpp: style - manual whitespace/line-breaks cleanup
Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10435 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-12 17:12:48 +00:00
Oron Peled
0244106553 xpp: style - one macro cleanup
* Wrap in do {} while(0)
* Move closer to its use (it's #undef'ed anyway after this section)
* Also re-organize line-breaking in the same code section

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10434 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-12 17:12:15 +00:00
Oron Peled
f9fb9622ec xpp: style - no more typedef byte
Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10433 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-12 17:11:46 +00:00
Tzafrir Cohen
bb5b3a6de4 xpp: style: fix an improper line break.
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10432 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-11 20:33:03 +00:00
Oron Peled
cc083d440f xpp: style - place EXPORT_SYMBOL() (manually)
Manually place EXPORT_SYMBOL() after symbols (or at end of functions).

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10431 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-11 20:01:32 +00:00
Oron Peled
dbf3f017d9 xpp: style - clean many long lines (manually)
Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10430 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-11 19:56:35 +00:00
Tzafrir Cohen
4ff781c2ba xpp: fix "non-const" index, right header, indent
Synchronize some changes from out internal tree:
* Fix a few of the places where indent did a lousy job.
* sparse did not like using the const MAX_ARGS as an index. Make it a define.
* Incorrect header included in card_fxs.c (doh!).
* One more funciton to statify.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10429 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-11 17:04:36 +00:00
Oron Peled
a2a695c742 xpp: style - Run Lindent
* Here it is:
  KERNEL_STYLE="-npro -kr -i8 -ts8 -sob -l80 -ss -ncs -cp1"
  TYPEDEFS='
	-T gfp_t
	-T __user
	-T u_char
	-T __u8
	-T byte
	-T bool
	-T charp
	-T xusb_t
	-T xbus_t
	-T xpd_t
	-T xproto_table_t
	-T xproto_entry_t
	-T xframe_t
	-T xpacket_t
	-T reg_cmd_t
	'

  indent $TYPEDEFS $KERNEL_STYLE \
	--ignore-newlines	\
	--indent-label0	\
	--no-space-after-function-call-names	\
	"$@"

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10428 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-11 15:22:46 +00:00
Oron Peled
97ad9f8d03 xpp: style - convert typedef of byte to __u8
* Applied via:
  perl -pi \
	-e '/"/ and next;' \
	-e '/^\s*\*/ and next;' \
	-e '/\/\*.*byte/ and next;' \
	-e '/typedef.*byte/ and next;' \
	-e 's/\bbyte\b/__u8/g' "$@"

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10427 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-11 15:21:54 +00:00
Oron Peled
f84d579847 xpp: style - add space after comma
* Applied via:
  sed -i -e '/"/!s/,\([^ \t]\)/, \1/g' "$@"

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10426 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-11 15:21:13 +00:00
Oron Peled
6caa62da4a xpp: style - insert space afer if/while/for/switch
* Applied via:
  perl -pi -e 's/\b(if|while|for|switch)\b\(/$1 (/g' "$@"

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10425 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-11 15:20:05 +00:00
Oron Peled
8ed4c4a1ee xpp: style - Remove space before tabs
* Applied via:
  perl -pi -e 's/ +\t/\t/g;' "$@"

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10424 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-11 15:19:01 +00:00
Oron Peled
c7946df16e xpp: style - Remove 0/NULL static initializers
* Applied via:
  perl -pi -e 's/(\bstatic\b[^=]*?)\s*=\s*(0|NULL)\s*;/$1;/' "$@"

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10423 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-11 15:17:42 +00:00
Oron Peled
535ef8086c xpp: style: convert __FUNCTION__ to __func__
* Applied via:
  perl -pi -e 's/\b__FUNCTION__\b/__func__/g' "$@"

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10422 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-11 15:17:09 +00:00
Oron Peled
647212c45f xpp: style - remove eolspace
* Applied via:
  perl -pi -e 's/[ \t]+$//' "$@"

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10421 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-11 15:16:34 +00:00
Shaun Ruffell
5475f33f3d wct4xxp: VPM module creates noise on alternate channels on E1 spans.
The VPMOCT128 module was using the VPMOCT256 timeslots assigments which would
mean that channels that should be marked alaw were being set in ulaw. This
only affected E1 spans since by default all spans are configured for ulaw by
default.

This fixes a regression introduced in r10290 [1] "wct4xxp: Add support for
TE820 and VPMOCT256", first released in 2.6.0, that only affects E1 spans on a
quad and dual-span card when used with the hardware echocanceler.

[1] http://svnview.digium.com/svn/dahdi?view=revision&revision=10290

Internal-Issue-ID: DAHDI-945, DAHLIN-275
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10414 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-10 20:45:35 +00:00
Shaun Ruffell
6485e9b0ba wctdm24xxp: FXS on-hook transmission timer incorrect.
The DAHDI_ONHOOKTRANSFER ioctl was incorrectly setting the ohttimer to 0. The
result was that an FXS port was leaving the on-hook transfer state before
finishing the transmission.

This was discovered while looking at why ./fxstest dtmfcid  was not able to
pass the DTMF callerid digits to an attached FXO port properly.

Fixes a regression introduced in r10167 "wctdm24xxp: Use interval for checking
FXS on hook transfer timer." [1], first released in 2.6.0.

[1] http://svnview.digium.com/svn/dahdi?view=revision&revision=10167

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10413 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-10 20:45:30 +00:00
Oron Peled
a01b9aaf14 xpp: handle failures during dahdi_register_device()
* If dahdi_register_device() failed, not all resources were freed.
  When dahdi_unregister_device() was called later (during driver
  removal) a panic was caused.

* Add proper error handling for possible failures in
  xbus_register_dahdi_device():
  - new xbus_free_ddev() safely free an xbus->ddev
  - This is called from all failures points.
  - It is also called from xbus_unregister_dahdi_device()

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10410 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-05 17:35:17 +00:00
Oron Peled
9c642364a7 xpp: Don't deactivate XPDs on unregistration
* A bug was introduced during migration to dahdi_device code:
    http://svnview.digium.com/svn/dahdi?view=rev&rev=10273
* Marking XPDs as non-functional (card_present=0, XPD_STATE_NOHW)
  was moved from xbus_request_removal() into xpd_dahdi_preunregister()
* As a result, unregistering an Astribank, made it non-functional
  so trying to re-register it later caused errors (e.g: "Cannot open"
  error message from xpp_open())
* This fix move XPD deactivation into the proper location (during
  xbus_deactivate()

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10409 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-05 17:34:16 +00:00
Oron Peled
0f619852d8 xpp: bugfix: fix bad refcount
Code path called in error condition contained an superflous put_xpd() call

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10408 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-05 17:33:47 +00:00
98 changed files with 37647 additions and 10288 deletions

41
.gitignore vendored Normal file
View File

@@ -0,0 +1,41 @@
# Files that are generated as part of the build process which we do not want git
# to track.
*.[oa]
*.mod
*.mod.[oc]
*.ko
*.cmd
*.order
*.tar.gz
tags
cscope.*
*.symvers
*.markers
.*.o.d
README.html
modules.order
Module.markers
build_tools/checkpatch.pl
drivers/dahdi/xpp/*.verified
drivers/dahdi/.tmp_versions/
drivers/dahdi/Module.symvers
drivers/dahdi/makefw
drivers/dahdi/radfw.h
drivers/dahdi/tor2fw.h
drivers/dahdi/xpp/init_fxo_modes
drivers/dahdi/xpp/print_fxo_modes
drivers/dahdi/xpp/xpp_version.h
include/dahdi/version.h
drivers/dahdi/vpmadt032_loader/vpmadt032_loader.h
drivers/dahdi/vpmadt032_loader/vpmadt032_x86_32.o_shipped
drivers/dahdi/vpmadt032_loader/vpmadt032_x86_64.o_shipped
drivers/dahdi/firmware/dahdi-fw-hx8.bin
drivers/dahdi/firmware/dahdi-fw-oct6114-064.bin
drivers/dahdi/firmware/dahdi-fw-oct6114-128.bin
drivers/dahdi/firmware/dahdi-fw-oct6114-256.bin
drivers/dahdi/firmware/dahdi-fw-tc400m.bin
drivers/dahdi/firmware/dahdi-fw-te820.bin
drivers/dahdi/firmware/dahdi-fw-vpmoct032.bin
drivers/dahdi/firmware/make_firmware_object

View File

@@ -67,13 +67,7 @@ GENERATED_DOCS:=README.html
ifneq ($(wildcard .version),)
DAHDIVERSION:=$(shell cat .version)
else
ifneq ($(wildcard .svn),)
DAHDIVERSION:=$(shell build_tools/make_version . dahdi/linux)
else
ifneq ($(wildcard .git),)
DAHDIVERSION:=$(shell build_tools/make_version . dahdi/linux)
endif
endif
endif
all: modules
@@ -92,7 +86,7 @@ include/dahdi/version.h: FORCE
fi
@rm -f $@.tmp
prereq: include/dahdi/version.h firmware-loaders
prereq: include/dahdi/version.h firmware-loaders oct612x-lib
stackcheck: $(CHECKSTACK) modules
objdump -d drivers/dahdi/*.ko drivers/dahdi/*/*.ko | $(CHECKSTACK)
@@ -128,6 +122,13 @@ uninstall-firmware:
firmware-loaders:
$(MAKE) -C drivers/dahdi/firmware firmware-loaders
oct612x-lib:
ifeq (no,$(HAS_KSRC))
@echo "You do not appear to have the sources for the $(KVERS) kernel installed."
@exit 1
endif
$(MAKE) -C $(KSRC) M='$(PWD)/drivers/dahdi/oct612x'
install-include:
for hdr in $(INST_HEADERS); do \
install -D -m 644 include/dahdi/$$hdr $(DESTDIR)/usr/include/dahdi/$$hdr; \
@@ -195,6 +196,7 @@ ifneq (no,$(HAS_KSRC))
endif
@rm -f $(GENERATED_DOCS)
$(MAKE) -C drivers/dahdi/firmware clean
$(MAKE) -C $(KSRC) M='$(PWD)/drivers/dahdi/oct612x' clean
distclean: dist-clean

325
README
View File

@@ -163,6 +163,24 @@ to the script:
./build_tools/make_static_devs -d tmp/newroot/dev/dahdi
DKMS
~~~~
DKMS, Dynamic Kernel Module Support, is a framework for building Linux
kernel modules. It is used, among others, by several distributions that
package the DAHDI kernel modules.
DKMS is designed to provide updates over drivers installed from original
kernel modules tree. Thus it installed modules into /lib/modules/updates
or /lib/modules/VERSION/updates . This is generally not an issue on
normal operation. However if you try to install DAHDI from source on
a system with DAHDI installed from DKMS this way (potentially of an
older version), be sure to remove the DKMS-installed modules from the
updates directory. If you're not sure, the following command will give
you a clue of the versions installed:
find /lib/modules -name dahdi.ko
Installing the B410P drivers with mISDN
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DAHDI includes the wcb4xxp driver for the B410P, however, support for the
@@ -212,13 +230,10 @@ under driver/staging/echo . In fact, dahdi_echocan_oslec assumes that
this is where the oslec code lies. If it is elsewhere you'll need to fix
the #include line.
Thus for the moment, the simplest way to build OSLEC with dahdi is:
1. Copy the directory `drivers/staging/echo` from a recent kernel tree
(at least 2.6.28-rc1) to the a subdirectory with the same name in the
dahdi-linux tree.
2. Edit drivers/dahdi/Kbuild and uncomment the two lines related to OSLEC.
Thus for the moment, the simplest way to build OSLEC with dahdi is to
copy the directory `drivers/staging/echo` from a recent kernel tree (at
least 2.6.28-rc1) to the a subdirectory with the same name in the
dahdi-linux tree.
After doing that, you'll see the following when building (running
'make')
@@ -233,6 +248,15 @@ be reported on the
https://lists.sourceforge.net/lists/listinfo/freetel-oslec[OSLEC mailing
list].
Alternatively you can also get the OSLEC code from the dahdi-linux-extra
GIT repository:
git clone git://gitorious.org/dahdi-extra/dahdi-linux-extra.git
cd dahdi-linux-extra
git archive extra-2.6 drivers/staging | (cd ..; tar xf -)
cd ..; rm -rf dahdi-linux-extra
Live Install
~~~~~~~~~~~~
In many cases you already have DAHDI installed on your system but would
@@ -421,54 +445,17 @@ reside directly under /sys/module/'module_name' .
Useful module parameters:
debug (most modules)::
Sets debug mode / debug level. With most modules 'debug' can be either
disabled (0, the default value) or enabled (any other value).
+
+
wctdm and wcte1xp print several extra debugging messages if the value
of debug is more than 1.
+
+
Some modules have "debugging flags" bits - the value of debug is a
bitmask and several messages are printed if some bits are set:
- wctdm24xxp:
* 1: DEBUG_CARD
* 2: DEBUG_ECHOCAN
- wct4xxp:
* 1: DEBUG_MAIN
* 2: DEBUG_DTMF
* 4: DEBUG_REGS
* 8: DEBUG_TSI
* 16: DEBUG_ECHOCAN
* 32: DEBUG_RBS
* 64: DEBUG_FRAMER
- xpp: See also README.Astribank:
* 1: GENERAL - General debug comments.
* 2: PCM - PCM-related messages. Tend to flood logs.
* 4: LEDS - Anything related to the LEDs status control. The driver
produces a lot of messages when the option is enabled.
* 8: SYNC - Synchronization related messages.
* 16: SIGNAL - DAHDI signalling related messages.
* 32: PROC - Messages related to the procfs interface.
* 64: REGS - Reading and writing to chip registers. Tends to flood
logs.
* 128: DEVICES - Device instantiation, destruction and such.
* 256 - COMMANDS - Protocol commands. Tends to flood logs.
=== debug
(most modules)
deftaps (dahdi)::
The default size for the echo canceller. The number is in "taps", that
is "samples", 1/8 ms. The default is 64 - for a tail size of 8 ms.
+
+
Asterisk's chan_dahdi tends to pass its own value anyway, with a
different default size. So normally setting this doesn't change
anything.
Sets debug mode / debug level. With most modules 'debug' can be either
disabled (0, the default value) or enabled (any other value).
max_pseudo_channels (dahdi)::
The maximum number of pseudo channels that dahdi will allow userspace to
create. Pseudo channels are used when conferencing channels together.
The default is 512.
wctdm and wcte1xp print several extra debugging messages if the value
of debug is more than 1.
Some modules have "debugging flags" bits - the value of debug is a
bitmask and several messages are printed if some bits are set:
To get a list of parameters supported by a module, use
@@ -476,13 +463,178 @@ To get a list of parameters supported by a module, use
Or, for a module you have just built:
modinfo ./module_name.ko
modinfo ./drivers/dahdi/module_name.ko
For the xpp modules this will also include the description and default
value of the module. You can find a list of useful xpp module parameters
in README.Astribank .
- wctdm24xxp:
* 1: DEBUG_CARD
* 2: DEBUG_ECHOCAN
- wct4xxp:
* 1: DEBUG_MAIN
* 2: DEBUG_DTMF
* 4: DEBUG_REGS
* 8: DEBUG_TSI
* 16: DEBUG_ECHOCAN
* 32: DEBUG_RBS
* 64: DEBUG_FRAMER
- xpp: See also README.Astribank:
* 1: GENERAL - General debug comments.
* 2: PCM - PCM-related messages. Tend to flood logs.
* 4: LEDS - Anything related to the LEDs status control. The driver
produces a lot of messages when the option is enabled.
* 8: SYNC - Synchronization related messages.
* 16: SIGNAL - DAHDI signalling related messages.
* 32: PROC - Messages related to the procfs interface.
* 64: REGS - Reading and writing to chip registers. Tends to flood
logs.
* 128: DEVICES - Device instantiation, destruction and such.
* 256 - COMMANDS - Protocol commands. Tends to flood logs.
+
+
The script xpp_debug in the source tree can help settting them at run
time.
=== deftaps
(dahdi)
The default size for the echo canceller. The number is in "taps", that
is "samples", 1/8 ms. The default is 64 - for a tail size of 8 ms.
Asterisk's chan_dahdi tends to pass its own value anyway, with a
different default size. So normally setting this doesn't change
anything.
=== max_pseudo_channels
(dahdi)
The maximum number of pseudo channels that dahdi will allow userspace to
create. Pseudo channels are used when conferencing channels together.
The default is 512.
=== auto_assign_spans
(dahdi)
See <<_span_assignments,Span Assignments>> below.
XPP (Astribank) module parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
==== debug
(all modules) - see above.
==== dahdi_autoreg
(xpp)
Register spans automatically (1) or not (0). Default: 0.
Setting it simplifies operations with a single Astribank and no other
DAHDI hardware. However if you have such systems, automatic
registration can cause the order of spans to be unpredictable.
The standard startup scripts use 'dahdi_registration on' instead of this.
==== initdir
(xpp)
This is the directory containing the initialization scripts.
The default is /usr/share/dahdi .
Setting this value could be useful if that location is inconvenient for you.
==== rx_tasklet
(xpp)
Enable (1) or disable (0) doing most of the packets processing in
separate tasklets. This should probably help on higher-end systems with
multiple Astribanks.
==== vmwi_ioctl
(xpd_fxs)
Does userspace support VMWI notification via ioctl? Default: 1 (yes).
Disable this (0) to have the driver attempt to detect the voicemail
message waiting indication status for this port from FSK messages
userspace (Asterisk) sends. Set the ports to use AC neon-lamp style
message waiting indication. The detection from the FSK messages takes
extra CPU cycles but is required with e.g. Asterisk < 1.6.0 .
Also note that in order for this parameter to take effect, it must be
set before the span is registered. This practically means that it
should be set through modprobe.d files.
See also Voicemail Indication in README.Astribank.
==== usb1
(xpp_usb)
Enable (1) or disable (0) support of USB1 devices. Disabled by default.
USB1 devices are not well-tested. It seems that they don't work at all
for Astribank BRI. Generally they should work with the current code, but
we expect the voice quality issues. Hence we would like to make it
very clear that you if you have a USB1 port (rather than a USB2 one, as
recommended) you will have to take an action to enable the device.
==== poll intervals
(various)
There are various values which the driver occasionally polls the
device for. For instance, the parameter poll_battery_interval for
xpd_fxo to poll the battery, in order to know if the telco line is
actually connected.
The value of those parameters is typically a number in milliseconds.
0 is used to disable polling. Under normal operation there should be
no reason to play with those parameters.
==== dtmf_detection
(xpd_fxs)
Enable (1) or disable (0) support of hardware DTMF detection by the
Astribank.
==== caller_id_style
(xpd_fxo)
Various types of caller ID signalling styles require knowing the PCM
even when the line is on-hook (which is usually a waste of CPU and
bandwidth). This parameter allows fine-tuning the behaviour here:
* 0 (default) - Don't pass extra PCM when on-hook.
* 1 ETSI-FSK: Wait for polarity reversal to come before a ring and
then start passing PCM until the caller ID has been passed.
* 2 ETSI-DTMF: Always pass PCM and generate a DTMF if polarity reversal is
detected before ring.
* 3 Passthrough: Always pass PCM as-is.
This parameter is read-only. It cannot be changed at run-time.
==== battery_threshold
(xpd_fxo)
Minimum voltage that shows there is battery. Defaults to 3. Normally you
should not need to change this, unless dealing with a funky PSTN
provider.
==== battery_debounce
(xpd_fxo)
Minimum interval (msec) for detection of battery off (as opposed to e.g.
a temporary power denial to signal a hangup). Defaults to 1000. As with
battery_threshold above, there's normally no need to tweak it.
==== use_polrev_firmware
(xpd_fxo)
Enable (1, default) or disable (0) support for polarity reversal
detection in the hardware. Only has effect with PIC_TYPE_2.hex rev. >=
11039 and with the initialization changes (init_card_2_30) in rev.
949aa49.
This parameter is read-only. It cannot be changed at run-time.
Internals
---------
DAHDI Device Files
@@ -494,9 +646,12 @@ or dynamically through the udev system.
* /dev/dahdi/ctl (196:0) - a general device file for various information and
control operations on the DAHDI channels.
* /dev/dahdi/channels/N/M - A device file for channel M in span N
(M is chanpos - numbering relative to the current span).
* /dev/dahdi/NNN (196:NNN) - for NNN in the range 1-249. A device file for
DAHDI channel NNN. It can be used to read data from the channel
and write data to the channel.
and write data to the channel. It is not generated by default but may
be generated as a symlink using udev rules.
* /dev/dahdi/transcode (196:250) - Used to connect to a DAHDI transcoding
device.
* /dev/dahdi/timer (196:253) - Allows setting timers. Used anywhere?
@@ -805,6 +960,12 @@ A free-form description of the span.
===== /sys/bus/dahdi_spans/devices/span-N/lbo
LBO setting for the channel.
===== /sys/bus/dahdi_spans/devices/span-N/lineconfig
The framing and coding of the span, for a digital span. Textual
represenation:
<B8ZS|AMI|HDB3>/<D4|ESF|CCS>[/CRC4]
===== /sys/bus/dahdi_spans/devices/span-N/local_spanno
The number of the span within the DAHDI device.
@@ -818,6 +979,60 @@ A very short type string.
Current sync source.
Channels Bus
^^^^^^^^^^^^
Each DAHDI channel is represented by a node under
/sys/bus/dahdi_channels/devices with the name 'dahdi!channels!N!M'
(where N is the number of the span and M is the number of the channel
in the span - chanpos). Channels of each span also reside under the node
of the span.
Useful attributes in the channel node (All attributed listed below are
read-only):
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/alarms
List of names of the current active alarms (space separated). Normally
(no alarms) empty. Example:
RED YELLOW
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/blocksize
The block size set by userspace.
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/channo
The (global) channel number.
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/chanpos
The channel number within the span.
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/dev
Major and minor device numbers.
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/ec_factory
The name of the echo canceller to be used in the channel, if one is
configured. Example:
MG2
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/ec_state
State of the echo canceller. ACTIVE: configured and inuse. INACTIVE
otherwise.
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/in_use
1 if the channel is in use (was opepend by userspace), 0 otherwise.
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/name
A name string for the channel
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/sig
The signalling types set for the channel. A space-separated list of
signalling types.
===== /sys/bus/dahdi_spans/devices/span-N/dahdi!channels!N!M/sigcap
The signalling types this channel may be configured to handle. A space-
separated list of signalling types.
User-space Interface
~~~~~~~~~~~~~~~~~~~~
User-space programs can only work with DAHDI channels. The basic

View File

@@ -59,7 +59,7 @@ elif [ -d ${1}/.git ]; then
MODIFIED=""
SVN_REV=`git log --pretty=full -1 | grep -F "git-svn-id:" | sed -e "s/.*\@\([^\s]*\)\s.*/\1/g"`
if [ -z "$SVN_REV" ]; then
VERSION=`git describe --long --always --tags --dirty=M 2> /dev/null`
VERSION=`git describe --tags --dirty=M 2> /dev/null | sed -e "s/^v\([0-9]\)/\1/"`
if [ $? -ne 0 ]; then
if [ "`git ls-files -m | wc -l`" != "0" ]; then
MODIFIED="M"
@@ -115,4 +115,8 @@ elif [ -d ${1}/.git ]; then
echo SVN-${RESULT##-}-r${SVN_REV}${MODIFIED}
fi
else
# Use the directory information in the absence of any other version
# information
pwd -P
fi

View File

@@ -11,6 +11,14 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT4XXP) += wct4xxp/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTC4XXP) += wctc4xxp/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM24XXP) += wctdm24xxp/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE13XP) += wcte13xp.o
wcte13xp-objs := wcte13xp-base.o oct612x/lib.a
CFLAGS_wcte13xp-base.o += -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api
ifeq ($(HOTPLUG_FIRMWARE),yes)
CFLAGS_wcte13xp-base.o += -DHOTPLUG_FIRMWARE
endif
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM) += wctdm.o
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VOICEBUS) += voicebus/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCB4XXP) += wcb4xxp/
@@ -33,14 +41,13 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_MG2) += dahdi_echocan_mg2.o
obj-m += $(DAHDI_MODULES_EXTRA)
# Only enable this if you think you know what you're doing. This is not
# supported yet:
#obj-m += dahdi_echocan_oslec.o
#
# A quick and dirty way to build OSLEC, if you happened to place it
# yourself in the dahdi source tree. This is experimental. See README
# regarding OSLEC.
#obj-m += ../staging/echo/
# If you want to build OSLEC, include the code in the standard location:
# drivers/staging/echo . The DAHDI OSLEC echo canceller will be built as
# well:
ifneq (,$(wildcard $(src)/../staging/echo/echo.c))
obj-m += dahdi_echocan_oslec.o
obj-m += ../staging/echo/echo.o
endif
CFLAGS_MODULE += -I$(DAHDI_INCLUDE) -I$(src)
@@ -78,7 +85,7 @@ CFLAGS_dahdi_dynamic_ethmf.o := -DNEW_SKB_LINEARIZE
endif
endif
dahdi-objs := dahdi-base.o dahdi-sysfs.o dahdi-version.o
dahdi-objs := dahdi-base.o dahdi-sysfs.o dahdi-sysfs-chan.o dahdi-version.o
###############################################################################
# Find appropriate ARCH value for VPMADT032 and HPEC binary modules

View File

@@ -1,6 +0,0 @@
ifdef KBUILD_EXTMOD
# We only get here on kernels 2.6.0-2.6.9 .
# For newer kernels, Kbuild will be included directly by the kernel
# build system.
include $(src)/Kbuild
endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,483 @@
/* dahdi-sysfs-chan.c
*
* Copyright (C) 2011-2012, Xorcom
* Copyright (C) 2011-2012, Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#include <linux/version.h>
#define DAHDI_PRINK_MACROS_USE_debug
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/ctype.h>
#include <dahdi/kernel.h>
#include "dahdi.h"
#include "dahdi-sysfs.h"
/* shortcuts, for code readability */
#define MAKE_DAHDI_DEV(num, name) \
CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, num), NULL, name)
#define DEL_DAHDI_DEV(num) \
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, num))
static struct class *dahdi_class;
static dev_t dahdi_channels_devt; /*!< Device number of first channel */
static struct cdev dahdi_channels_cdev; /*!< Channels chardev's */
/*
* Flags to remember what initializations already
* succeeded.
*/
static struct {
u32 channel_driver:1;
u32 channels_bus:1;
u32 cdev:1;
} should_cleanup;
#define chan_attr(field, format_string) \
static BUS_ATTR_READER(field##_show, dev, buf) \
{ \
struct dahdi_chan *chan; \
\
chan = dev_to_chan(dev); \
return sprintf(buf, format_string, chan->field); \
}
chan_attr(name, "%s\n");
chan_attr(channo, "%d\n");
chan_attr(chanpos, "%d\n");
chan_attr(blocksize, "%d\n");
#ifdef OPTIMIZE_CHANMUTE
chan_attr(chanmute, "%d\n");
#endif
static BUS_ATTR_READER(sigcap_show, dev, buf)
{
struct dahdi_chan *chan;
int len = 0;
int i;
uint sigtypes[] = {
DAHDI_SIG_FXSLS,
DAHDI_SIG_FXSGS,
DAHDI_SIG_FXSKS,
DAHDI_SIG_FXOLS,
DAHDI_SIG_FXOGS,
DAHDI_SIG_FXOKS,
DAHDI_SIG_EM,
DAHDI_SIG_CLEAR,
DAHDI_SIG_HDLCRAW,
DAHDI_SIG_HDLCFCS,
DAHDI_SIG_HDLCNET,
DAHDI_SIG_SLAVE,
DAHDI_SIG_SF,
DAHDI_SIG_CAS,
DAHDI_SIG_EM_E1,
DAHDI_SIG_DACS_RBS,
DAHDI_SIG_HARDHDLC,
DAHDI_SIG_MTP2,
};
chan = dev_to_chan(dev);
for (i = 0; i < ARRAY_SIZE(sigtypes); i++) {
uint x = chan->sigcap & sigtypes[i];
if (x == sigtypes[i])
len += sprintf(buf + len, "%s ", sigstr(x));
}
while (len > 0 && isspace(buf[len - 1])) /* trim */
len--;
len += sprintf(buf + len, "\n");
return len;
}
static BUS_ATTR_READER(sig_show, dev, buf)
{
struct dahdi_chan *chan;
chan = dev_to_chan(dev);
return sprintf(buf, "%s\n", sigstr(chan->sig));
}
static BUS_ATTR_READER(in_use_show, dev, buf)
{
struct dahdi_chan *chan;
chan = dev_to_chan(dev);
return sprintf(buf, "%d\n", test_bit(DAHDI_FLAGBIT_OPEN, &chan->flags));
}
static BUS_ATTR_READER(alarms_show, dev, buf)
{
struct dahdi_chan *chan;
int len;
chan = dev_to_chan(dev);
len = fill_alarm_string(buf, PAGE_SIZE, chan->chan_alarms);
buf[len++] = '\n';
return len;
}
static BUS_ATTR_READER(ec_factory_show, dev, buf)
{
struct dahdi_chan *chan;
int len = 0;
chan = dev_to_chan(dev);
if (chan->ec_factory)
len += sprintf(buf, "%s", chan->ec_factory->get_name(chan));
buf[len++] = '\n';
return len;
}
static BUS_ATTR_READER(ec_state_show, dev, buf)
{
struct dahdi_chan *chan;
int len = 0;
chan = dev_to_chan(dev);
if (chan->ec_factory)
len += sprintf(buf, "%sACTIVE", (chan->ec_state) ? "" : "IN");
buf[len++] = '\n';
return len;
}
static struct device_attribute chan_dev_attrs[] = {
__ATTR_RO(name),
__ATTR_RO(channo),
__ATTR_RO(chanpos),
__ATTR_RO(sig),
__ATTR_RO(sigcap),
__ATTR_RO(alarms),
__ATTR_RO(ec_factory),
__ATTR_RO(ec_state),
__ATTR_RO(blocksize),
#ifdef OPTIMIZE_CHANMUTE
__ATTR_RO(chanmute),
#endif
__ATTR_RO(in_use),
__ATTR_NULL,
};
static void chan_release(struct device *dev)
{
struct dahdi_chan *chan;
BUG_ON(!dev);
chan = dev_to_chan(dev);
chan_dbg(DEVICES, chan, "SYSFS\n");
}
static int chan_match(struct device *dev, struct device_driver *driver)
{
struct dahdi_chan *chan;
chan = dev_to_chan(dev);
chan_dbg(DEVICES, chan, "SYSFS\n");
return 1;
}
static struct bus_type chan_bus_type = {
.name = "dahdi_channels",
.match = chan_match,
.dev_attrs = chan_dev_attrs,
};
static int chan_probe(struct device *dev)
{
struct dahdi_chan *chan;
chan = dev_to_chan(dev);
chan_dbg(DEVICES, chan, "SYSFS\n");
return 0;
}
static int chan_remove(struct device *dev)
{
struct dahdi_chan *chan;
chan = dev_to_chan(dev);
chan_dbg(DEVICES, chan, "SYSFS\n");
return 0;
}
static struct device_driver chan_driver = {
.name = "dahdi",
.bus = &chan_bus_type,
#ifndef OLD_HOTPLUG_SUPPORT
.owner = THIS_MODULE,
#endif
.probe = chan_probe,
.remove = chan_remove
};
int chan_sysfs_create(struct dahdi_chan *chan)
{
struct device *dev;
struct dahdi_span *span;
int res;
dev_t devt;
chan_dbg(DEVICES, chan, "Creating channel %d\n", chan->channo);
if (test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags))
return 0;
span = chan->span;
devt = MKDEV(MAJOR(dahdi_channels_devt), chan->channo);
dev = &chan->chan_device;
memset(dev, 0, sizeof(*dev));
dev->devt = devt;
dev->bus = &chan_bus_type;
dev->parent = span->span_device;
/*
* FIXME: the name cannot be longer than KOBJ_NAME_LEN
*/
dev_set_name(dev, "dahdi!channels!%d!%d", span->spanno, chan->chanpos);
dev_set_drvdata(dev, chan);
dev->release = chan_release;
res = device_register(dev);
if (res) {
chan_err(chan, "%s: device_register failed: %d\n",
__func__, res);
put_device(dev);
return res;
}
set_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags);
return 0;
}
void chan_sysfs_remove(struct dahdi_chan *chan)
{
struct device *dev = &chan->chan_device;
chan_dbg(DEVICES, chan, "Destroying channel %d\n", chan->channo);
if (!dev_get_drvdata(dev))
return;
if (!test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags))
return;
dev = &chan->chan_device;
BUG_ON(dev_get_drvdata(dev) != chan);
device_unregister(dev);
/* FIXME: should have been done earlier in dahdi_chan_unreg */
chan->channo = -1;
clear_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags);
}
/*
* Used by dahdi_transcode.c
*/
int dahdi_register_chardev(struct dahdi_chardev *dev)
{
static const char *DAHDI_STRING = "dahdi!";
char *udevname;
udevname = kzalloc(strlen(dev->name) + sizeof(DAHDI_STRING) + 1,
GFP_KERNEL);
if (!udevname)
return -ENOMEM;
strcpy(udevname, DAHDI_STRING);
strcat(udevname, dev->name);
MAKE_DAHDI_DEV(dev->minor, udevname);
kfree(udevname);
return 0;
}
EXPORT_SYMBOL(dahdi_register_chardev);
/*
* Used by dahdi_transcode.c
*/
int dahdi_unregister_chardev(struct dahdi_chardev *dev)
{
DEL_DAHDI_DEV(dev->minor);
return 0;
}
EXPORT_SYMBOL(dahdi_unregister_chardev);
/*--------- Sysfs Device handling ----*/
/*
* Describe fixed device files and maintain their
* pointer so fixed_devfiles_remove() can always be called
* and work cleanly
*/
static struct {
int minor;
char *name;
void *dev; /* FIXME: wrong type because of old kernels */
} fixed_minors[] = {
{ DAHDI_CTL, "dahdi!ctl", },
{ DAHDI_TIMER, "dahdi!timer", },
{ DAHDI_CHANNEL, "dahdi!channel",},
{ DAHDI_PSEUDO, "dahdi!pseudo", },
};
/*
* Removes /dev/dahdi/{ctl,timer,channel,pseudo}
*
* It is safe to call it during initialization error handling,
* as it skips non existing objects.
*/
static void fixed_devfiles_remove(void)
{
int i;
if (!dahdi_class)
return;
for (i = 0; i < ARRAY_SIZE(fixed_minors); i++) {
void *d = fixed_minors[i].dev;
if (d && !IS_ERR(d))
dahdi_dbg(DEVICES, "Removing fixed device file %s\n",
fixed_minors[i].name);
DEL_DAHDI_DEV(fixed_minors[i].minor);
}
}
/*
* Creates /dev/dahdi/{ctl,timer,channel,pseudo}
*/
static int fixed_devfiles_create(void)
{
int i;
int res = 0;
if (!dahdi_class) {
dahdi_err("%s: dahdi_class is not initialized yet!\n",
__func__);
res = -ENODEV;
goto cleanup;
}
for (i = 0; i < ARRAY_SIZE(fixed_minors); i++) {
char *name = fixed_minors[i].name;
int minor = fixed_minors[i].minor;
void *dummy;
dahdi_dbg(DEVICES, "Making fixed device file %s\n", name);
dummy = (void *)MAKE_DAHDI_DEV(minor, name);
if (IS_ERR(dummy)) {
int res = PTR_ERR(dummy);
dahdi_err("%s: failed (%d: %s). Error: %d\n",
__func__, minor, name, res);
goto cleanup;
}
fixed_minors[i].dev = dummy;
}
return 0;
cleanup:
fixed_devfiles_remove();
return res;
}
/*
* Called during driver unload and while handling any error during
* driver load.
* Always clean any (and only) objects that were initialized (invariant)
*/
static void sysfs_channels_cleanup(void)
{
if (should_cleanup.cdev) {
dahdi_dbg(DEVICES, "removing channels cdev\n");
cdev_del(&dahdi_channels_cdev);
should_cleanup.cdev = 0;
}
if (dahdi_channels_devt) {
dahdi_dbg(DEVICES, "unregistering chrdev_region\n");
unregister_chrdev_region(dahdi_channels_devt,
DAHDI_MAX_CHANNELS);
}
fixed_devfiles_remove();
if (dahdi_class) {
dahdi_dbg(DEVICES, "Destroying DAHDI class:\n");
class_destroy(dahdi_class);
dahdi_class = NULL;
}
if (should_cleanup.channel_driver) {
dahdi_dbg(DEVICES, "Removing channel driver\n");
driver_unregister(&chan_driver);
should_cleanup.channel_driver = 0;
}
if (should_cleanup.channels_bus) {
dahdi_dbg(DEVICES, "Removing channels bus\n");
bus_unregister(&chan_bus_type);
should_cleanup.channels_bus = 0;
}
}
int __init dahdi_sysfs_chan_init(const struct file_operations *fops)
{
int res = 0;
dahdi_dbg(DEVICES, "Registering channels bus\n");
res = bus_register(&chan_bus_type);
if (res) {
dahdi_err("%s: bus_register(%s) failed. Error number %d\n",
__func__, chan_bus_type.name, res);
goto cleanup;
}
should_cleanup.channels_bus = 1;
dahdi_dbg(DEVICES, "Registering channel driver\n");
res = driver_register(&chan_driver);
if (res) {
dahdi_err("%s: driver_register(%s) failed. Error number %d",
__func__, chan_driver.name, res);
goto cleanup;
}
should_cleanup.channel_driver = 1;
dahdi_class = class_create(THIS_MODULE, "dahdi");
if (IS_ERR(dahdi_class)) {
res = PTR_ERR(dahdi_class);
dahdi_err("%s: class_create(dahi_chan) failed. Error: %d\n",
__func__, res);
goto cleanup;
}
res = fixed_devfiles_create();
if (res)
goto cleanup;
dahdi_dbg(DEVICES, "allocating chrdev_region\n");
res = alloc_chrdev_region(&dahdi_channels_devt,
0,
DAHDI_MAX_CHANNELS,
"dahdi_channels");
if (res) {
dahdi_err("%s: Failed allocating chrdev for %d channels (%d)",
__func__, DAHDI_MAX_CHANNELS, res);
goto cleanup;
}
dahdi_dbg(DEVICES, "adding channels cdev\n");
cdev_init(&dahdi_channels_cdev, fops);
res = cdev_add(&dahdi_channels_cdev, dahdi_channels_devt,
DAHDI_MAX_CHANNELS);
if (res) {
dahdi_err("%s: cdev_add() failed (%d)", __func__, res);
goto cleanup;
}
should_cleanup.cdev = 1;
return 0;
cleanup:
sysfs_channels_cleanup();
return res;
}
void dahdi_sysfs_chan_exit(void)
{
sysfs_channels_cleanup();
}

View File

@@ -1,108 +1,35 @@
/* dahdi-sysfs.c
*
* Copyright (C) 2011-2012, Xorcom
* Copyright (C) 2011-2012, Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#include <linux/kernel.h>
#include <linux/version.h>
#define DAHDI_PRINK_MACROS_USE_debug
#include <dahdi/kernel.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/ctype.h>
#include "dahdi.h"
/* FIXME: Move to kernel.h */
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
#define CLASS_DEV_CREATE(class, devt, device, name) \
device_create(class, device, devt, NULL, "%s", name)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
#define CLASS_DEV_CREATE(class, devt, device, name) \
device_create(class, device, devt, name)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
#define CLASS_DEV_CREATE(class, devt, device, name) \
class_device_create(class, NULL, devt, device, name)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
#define CLASS_DEV_CREATE(class, devt, device, name) \
class_device_create(class, devt, device, name)
#else
#define CLASS_DEV_CREATE(class, devt, device, name) \
class_simple_device_add(class, devt, device, name)
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
#define CLASS_DEV_DESTROY(class, devt) \
device_destroy(class, devt)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
#define CLASS_DEV_DESTROY(class, devt) \
class_device_destroy(class, devt)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
#define CLASS_DEV_DESTROY(class, devt) \
class_simple_device_remove(devt)
#else
#define CLASS_DEV_DESTROY(class, devt) \
class_simple_device_remove(class, devt)
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
static struct class *dahdi_class = NULL;
#else
static struct class_simple *dahdi_class = NULL;
#define class_create class_simple_create
#define class_destroy class_simple_destroy
#endif
/*
* Very old hotplug support
*/
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 9)
#define OLD_HOTPLUG_SUPPORT /* for older kernels */
#define OLD_HOTPLUG_SUPPORT_269
#endif
#ifdef OLD_HOTPLUG_SUPPORT_269
/* Copy from new kernels lib/kobject_uevent.c */
enum kobject_action {
KOBJ_ADD,
KOBJ_REMOVE,
KOBJ_CHANGE,
KOBJ_MOUNT,
KOBJ_UMOUNT,
KOBJ_OFFLINE,
KOBJ_ONLINE,
};
#endif
/*
* Hotplug replaced with uevent in 2.6.16
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
#define OLD_HOTPLUG_SUPPORT /* for older kernels */
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
#define DEVICE_ATTR_READER(name, dev, buf) \
ssize_t name(struct device *dev, struct device_attribute *attr,\
char *buf)
#define DEVICE_ATTR_WRITER(name, dev, buf, count) \
ssize_t name(struct device *dev, struct device_attribute *attr,\
const char *buf, size_t count)
#define BUS_ATTR_READER(name, dev, buf) \
ssize_t name(struct device *dev, struct device_attribute *attr, \
char *buf)
#define BUS_ATTR_WRITER(name, dev, buf, count) \
ssize_t name(struct device *dev, struct device_attribute *attr,\
const char *buf, size_t count)
#else
#define DEVICE_ATTR_READER(name, dev, buf) \
ssize_t name(struct device *dev, char *buf)
#define DEVICE_ATTR_WRITER(name, dev, buf, count) \
ssize_t name(struct device *dev, const char *buf, size_t count)
#define BUS_ATTR_READER(name, dev, buf) \
ssize_t name(struct device *dev, char *buf)
#define BUS_ATTR_WRITER(name, dev, buf, count) \
ssize_t name(struct device *dev, const char *buf, size_t count)
#endif
#define DRIVER_ATTR_READER(name, drv, buf) \
ssize_t name(struct device_driver *drv, char * buf)
#include "dahdi-sysfs.h"
static char *initdir = "/usr/share/dahdi";
@@ -118,23 +45,6 @@ static inline struct dahdi_span *dev_to_span(struct device *dev)
return dev_get_drvdata(dev);
}
#ifdef OLD_HOTPLUG_SUPPORT
static int span_hotplug(struct device *dev, char **envp, int envnum,
char *buff, int bufsize)
{
struct dahdi_span *span;
if (!dev)
return -ENODEV;
span = dev_to_span(dev);
envp[0] = buff;
if (snprintf(buff, bufsize, "SPAN_NAME=%s", span->name) >= bufsize)
return -ENOMEM;
envp[1] = NULL;
return 0;
}
#else
#define SPAN_VAR_BLOCK \
do { \
DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s", initdir); \
@@ -152,12 +62,6 @@ static int span_hotplug(struct device *dev, char **envp, int envnum,
return err; \
} while (0)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
#define dev_name(dev) ((dev)->bus_id)
#define dev_set_name(dev, format, ...) \
snprintf((dev)->bus_id, BUS_ID_SIZE, format, ## __VA_ARGS__);
#endif
static int span_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
@@ -204,8 +108,6 @@ static int span_uevent(struct device *dev, struct kobj_uevent_env *kenv)
#endif
#endif /* OLD_HOTPLUG_SUPPORT */
#define span_attr(field, format_string) \
static BUS_ATTR_READER(field##_show, dev, buf) \
{ \
@@ -217,11 +119,18 @@ static BUS_ATTR_READER(field##_show, dev, buf) \
span_attr(name, "%s\n");
span_attr(desc, "%s\n");
span_attr(spantype, "%s\n");
span_attr(alarms, "0x%x\n");
span_attr(lbo, "%d\n");
span_attr(syncsrc, "%d\n");
static BUS_ATTR_READER(spantype_show, dev, buf)
{
struct dahdi_span *span;
span = dev_to_span(dev);
return sprintf(buf, "%s\n", dahdi_spantype2str(span->spantype));
}
static BUS_ATTR_READER(local_spanno_show, dev, buf)
{
struct dahdi_span *span;
@@ -251,6 +160,8 @@ static BUS_ATTR_READER(basechan_show, dev, buf)
struct dahdi_span *span;
span = dev_to_span(dev);
if (!span->channels)
return -ENODEV;
return sprintf(buf, "%d\n", span->chans[0]->channo);
}
@@ -262,6 +173,38 @@ static BUS_ATTR_READER(channels_show, dev, buf)
return sprintf(buf, "%d\n", span->channels);
}
static BUS_ATTR_READER(lineconfig_show, dev, buf)
{
struct dahdi_span *span;
int len = 0;
span = dev_to_span(dev);
len += lineconfig_str(span->lineconfig, buf, 20);
len += sprintf(buf + len, "\n");
return len;
}
static BUS_ATTR_READER(linecompat_show, dev, buf)
{
struct dahdi_span *span;
int bit;
int len = 0;
span = dev_to_span(dev);
for (bit = 4; bit <= 12; bit++) {
if (span->linecompat & (1 << bit)) {
const char *name = dahdi_lineconfig_bit_name(bit);
if (name)
len += sprintf(buf + len, "%s ", name);
}
}
/* chomp */
while (len > 0 && isspace(buf[len - 1]))
buf[--len] = '\0';
len += sprintf(buf + len, "\n");
return len;
}
static struct device_attribute span_dev_attrs[] = {
__ATTR_RO(name),
__ATTR_RO(desc),
@@ -274,6 +217,8 @@ static struct device_attribute span_dev_attrs[] = {
__ATTR_RO(is_sync_master),
__ATTR_RO(basechan),
__ATTR_RO(channels),
__ATTR_RO(lineconfig),
__ATTR_RO(linecompat),
__ATTR_NULL,
};
@@ -284,11 +229,7 @@ static struct driver_attribute dahdi_attrs[] = {
static struct bus_type spans_bus_type = {
.name = "dahdi_spans",
.match = span_match,
#ifdef OLD_HOTPLUG_SUPPORT
.hotplug = span_hotplug,
#else
.uevent = span_uevent,
#endif
.dev_attrs = span_dev_attrs,
.drv_attrs = dahdi_attrs,
};
@@ -316,9 +257,7 @@ static struct device_driver dahdi_driver = {
.bus = &spans_bus_type,
.probe = span_probe,
.remove = span_remove,
#ifndef OLD_HOTPLUG_SUPPORT
.owner = THIS_MODULE
#endif
};
static void span_uevent_send(struct dahdi_span *span, enum kobject_action act)
@@ -328,26 +267,7 @@ static void span_uevent_send(struct dahdi_span *span, enum kobject_action act)
kobj = &span->span_device->kobj;
span_dbg(DEVICES, span, "SYFS dev_name=%s action=%d\n",
dev_name(span->span_device), act);
#if defined(OLD_HOTPLUG_SUPPORT_269)
{
/* Copy from new kernels lib/kobject_uevent.c */
static const char *const str[] = {
[KOBJ_ADD] "add",
[KOBJ_REMOVE] "remove",
[KOBJ_CHANGE] "change",
[KOBJ_MOUNT] "mount",
[KOBJ_UMOUNT] "umount",
[KOBJ_OFFLINE] "offline",
[KOBJ_ONLINE] "online"
};
kobject_hotplug(str[act], kobj);
}
#elif defined(OLD_HOTPLUG_SUPPORT)
kobject_hotplug(kobj, act);
#else
kobject_uevent(kobj, act);
#endif
}
static void span_release(struct device *dev)
@@ -355,32 +275,6 @@ static void span_release(struct device *dev)
dahdi_dbg(DEVICES, "%s: %s\n", __func__, dev_name(dev));
}
int dahdi_register_chardev(struct dahdi_chardev *dev)
{
static const char *DAHDI_STRING = "dahdi!";
char *udevname;
udevname = kzalloc(strlen(dev->name) + sizeof(DAHDI_STRING) + 1,
GFP_KERNEL);
if (!udevname)
return -ENOMEM;
strcpy(udevname, DAHDI_STRING);
strcat(udevname, dev->name);
CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, dev->minor), NULL, udevname);
kfree(udevname);
return 0;
}
EXPORT_SYMBOL(dahdi_register_chardev);
int dahdi_unregister_chardev(struct dahdi_chardev *dev)
{
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, dev->minor));
return 0;
}
EXPORT_SYMBOL(dahdi_unregister_chardev);
void span_sysfs_remove(struct dahdi_span *span)
{
struct device *span_device;
@@ -392,15 +286,8 @@ void span_sysfs_remove(struct dahdi_span *span)
if (!span_device)
return;
for (x = 0; x < span->channels; x++) {
struct dahdi_chan *chan = span->chans[x];
if (!test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags))
continue;
CLASS_DEV_DESTROY(dahdi_class,
MKDEV(DAHDI_MAJOR, chan->channo));
clear_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags);
}
for (x = 0; x < span->channels; x++)
chan_sysfs_remove(span->chans[x]);
if (!dev_get_drvdata(span_device))
return;
@@ -451,28 +338,9 @@ int span_sysfs_create(struct dahdi_span *span)
}
for (x = 0; x < span->channels; x++) {
struct dahdi_chan *chan = span->chans[x];
char chan_name[32];
void *dummy;
if (chan->channo >= 250)
continue;
if (test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags))
continue;
snprintf(chan_name, sizeof(chan_name), "dahdi!%d",
chan->channo);
dummy = (void *)CLASS_DEV_CREATE(dahdi_class,
MKDEV(DAHDI_MAJOR, chan->channo),
NULL, chan_name);
if (IS_ERR(dummy)) {
res = PTR_ERR(dummy);
chan_err(chan, "Failed creating sysfs device: %d\n",
res);
res = chan_sysfs_create(span->chans[x]);
if (res)
goto cleanup;
}
set_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags);
}
return 0;
@@ -481,58 +349,38 @@ cleanup:
return res;
}
#define MAKE_DAHDI_DEV(num, name) \
CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, num), NULL, name)
#define DEL_DAHDI_DEV(num) \
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, num))
/* Only used to flag that the device exists: */
static struct {
unsigned int ctl:1;
unsigned int timer:1;
unsigned int channel:1;
unsigned int pseudo:1;
unsigned int sysfs_driver_registered:1;
unsigned int sysfs_spans_bus_type:1;
unsigned int dahdi_device_bus_registered:1;
} dummy_dev;
unsigned int clean_dahdi_driver:1;
unsigned int clean_span_bus_type:1;
unsigned int clean_device_bus:1;
unsigned int clean_chardev:1;
} should_cleanup;
static inline struct dahdi_device *to_ddev(struct device *dev)
{
return container_of(dev, struct dahdi_device, dev);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
static ssize_t dahdi_device_manufacturer_show(struct device *dev, char *buf)
#else
static ssize_t
dahdi_device_manufacturer_show(struct device *dev,
struct device_attribute *attr, char *buf)
#endif
{
struct dahdi_device *ddev = to_ddev(dev);
return sprintf(buf, "%s\n", ddev->manufacturer);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
static ssize_t dahdi_device_type_show(struct device *dev, char *buf)
#else
static ssize_t
dahdi_device_type_show(struct device *dev,
struct device_attribute *attr, char *buf)
#endif
{
struct dahdi_device *ddev = to_ddev(dev);
return sprintf(buf, "%s\n", ddev->devicetype);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
static ssize_t dahdi_device_span_count_show(struct device *dev, char *buf)
#else
static ssize_t
dahdi_device_span_count_show(struct device *dev,
struct device_attribute *attr, char *buf)
#endif
{
struct dahdi_device *ddev = to_ddev(dev);
unsigned int count = 0;
@@ -544,13 +392,9 @@ dahdi_device_span_count_show(struct device *dev,
return sprintf(buf, "%d\n", count);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
static ssize_t dahdi_device_hardware_id_show(struct device *dev, char *buf)
#else
static ssize_t
dahdi_device_hardware_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
#endif
{
struct dahdi_device *ddev = to_ddev(dev);
@@ -558,28 +402,18 @@ dahdi_device_hardware_id_show(struct device *dev,
(ddev->hardware_id) ? ddev->hardware_id : "");
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
static ssize_t
dahdi_device_auto_assign(struct device *dev, const char *buf, size_t count)
#else
static ssize_t
dahdi_device_auto_assign(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
#endif
{
struct dahdi_device *ddev = to_ddev(dev);
dahdi_assign_device_spans(ddev);
return count;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
static ssize_t
dahdi_device_assign_span(struct device *dev, const char *buf, size_t count)
#else
static ssize_t
dahdi_device_assign_span(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
#endif
{
int ret;
struct dahdi_span *span;
@@ -591,7 +425,7 @@ dahdi_device_assign_span(struct device *dev, struct device_attribute *attr,
ret = sscanf(buf, "%u:%u:%u", &local_span_number, &desired_spanno,
&desired_basechanno);
if (ret != 3) {
dev_notice(dev, "badly formatted input (should be <num>:<num>:<num>)\n");
dev_notice(dev, "bad input (should be <num>:<num>:<num>)\n");
return -EINVAL;
}
@@ -607,18 +441,14 @@ dahdi_device_assign_span(struct device *dev, struct device_attribute *attr,
return (ret) ? ret : count;
}
}
dev_notice(dev, "no match for local span number %d\n", local_span_number);
dev_notice(dev, "no match for local span number %d\n",
local_span_number);
return -EINVAL;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
static ssize_t
dahdi_device_unassign_span(struct device *dev, const char *buf, size_t count)
#else
static ssize_t
dahdi_device_unassign_span(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
#endif
{
int ret;
unsigned int local_span_number;
@@ -644,13 +474,9 @@ dahdi_device_unassign_span(struct device *dev, struct device_attribute *attr,
return (ret < 0) ? ret : count;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
static ssize_t dahdi_spantype_show(struct device *dev, char *buf)
#else
static ssize_t
dahdi_spantype_show(struct device *dev,
struct device_attribute *attr, char *buf)
#endif
{
struct dahdi_device *ddev = to_ddev(dev);
int count = 0;
@@ -659,7 +485,8 @@ dahdi_spantype_show(struct device *dev,
/* TODO: Make sure this doesn't overflow the page. */
list_for_each_entry(span, &ddev->spans, device_node) {
count = sprintf(buf, "%d:%s\n", local_spanno(span), span->spantype);
count = sprintf(buf, "%d:%s\n",
local_spanno(span), dahdi_spantype2str(span->spantype));
buf += count;
total += count;
}
@@ -667,24 +494,27 @@ dahdi_spantype_show(struct device *dev,
return total;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13)
static ssize_t
dahdi_spantype_store(struct device *dev, const char *buf, size_t count)
#else
static ssize_t
dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
#endif
{
struct dahdi_device *const ddev = to_ddev(dev);
int ret;
struct dahdi_span *span;
unsigned int local_span_number;
char desired_spantype[80];
char spantype_name[80];
enum spantypes spantype;
ret = sscanf(buf, "%u:%70s", &local_span_number, desired_spantype);
if (ret != 2)
ret = sscanf(buf, "%u:%70s", &local_span_number, spantype_name);
if (ret != 2) {
dev_err(&ddev->dev, "Wrong input format: '%s'\n", buf);
return -EINVAL;
}
spantype = dahdi_str2spantype(spantype_name);
if (spantype == SPANTYPE_INVALID) {
dev_err(&ddev->dev, "Invalid spantype: '%s'\n", buf);
return -EINVAL;
}
list_for_each_entry(span, &ddev->spans, device_node) {
if (local_spanno(span) == local_span_number)
@@ -698,8 +528,9 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
}
if (local_spanno(span) != local_span_number) {
module_printk(KERN_WARNING, "%d is not a valid local span number "
"for this device.\n", local_span_number);
module_printk(KERN_WARNING,
"%d is not a valid local span number "
"for this device.\n", local_span_number);
return -EINVAL;
}
@@ -709,7 +540,7 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
return -EINVAL;
}
ret = span->ops->set_spantype(span, &desired_spantype[0]);
ret = span->ops->set_spantype(span, spantype);
return (ret < 0) ? ret : count;
}
@@ -731,49 +562,30 @@ static struct bus_type dahdi_device_bus = {
.dev_attrs = dahdi_device_attrs,
};
void dahdi_sysfs_exit(void)
static void dahdi_sysfs_cleanup(void)
{
dahdi_dbg(DEVICES, "SYSFS\n");
if (dummy_dev.pseudo) {
dahdi_dbg(DEVICES, "Removing /dev/dahdi/pseudo:\n");
DEL_DAHDI_DEV(DAHDI_PSEUDO);
dummy_dev.pseudo = 0;
}
if (dummy_dev.channel) {
dahdi_dbg(DEVICES, "Removing /dev/dahdi/channel:\n");
DEL_DAHDI_DEV(DAHDI_CHANNEL);
dummy_dev.channel = 0;
}
if (dummy_dev.timer) {
dahdi_dbg(DEVICES, "Removing /dev/dahdi/timer:\n");
DEL_DAHDI_DEV(DAHDI_TIMER);
dummy_dev.timer = 0;
}
if (dummy_dev.ctl) {
dahdi_dbg(DEVICES, "Removing /dev/dahdi/ctl:\n");
DEL_DAHDI_DEV(DAHDI_CTL);
dummy_dev.ctl = 0;
}
if (dahdi_class) {
dahdi_dbg(DEVICES, "Destroying DAHDI class:\n");
class_destroy(dahdi_class);
dahdi_class = NULL;
}
if (dummy_dev.sysfs_driver_registered) {
if (should_cleanup.clean_dahdi_driver) {
dahdi_dbg(DEVICES, "Unregister driver\n");
driver_unregister(&dahdi_driver);
dummy_dev.sysfs_driver_registered = 0;
should_cleanup.clean_dahdi_driver = 0;
}
if (dummy_dev.sysfs_spans_bus_type) {
if (should_cleanup.clean_span_bus_type) {
dahdi_dbg(DEVICES, "Unregister span bus type\n");
bus_unregister(&spans_bus_type);
dummy_dev.sysfs_spans_bus_type = 0;
should_cleanup.clean_span_bus_type = 0;
}
dahdi_sysfs_chan_exit();
if (should_cleanup.clean_chardev) {
dahdi_dbg(DEVICES, "Unregister character device\n");
unregister_chrdev(DAHDI_MAJOR, "dahdi");
should_cleanup.clean_chardev = 0;
}
unregister_chrdev(DAHDI_MAJOR, "dahdi");
if (dummy_dev.dahdi_device_bus_registered) {
if (should_cleanup.clean_device_bus) {
dahdi_dbg(DEVICES, "Unregister DAHDI device bus\n");
bus_unregister(&dahdi_device_bus);
dummy_dev.dahdi_device_bus_registered = 0;
should_cleanup.clean_device_bus = 0;
}
}
@@ -796,10 +608,17 @@ int dahdi_sysfs_add_device(struct dahdi_device *ddev, struct device *parent)
{
int ret;
struct device *const dev = &ddev->dev;
const char *dn;
dev->parent = parent;
dev->bus = &dahdi_device_bus;
dev_set_name(dev, "%s:%s", parent->bus->name, dev_name(parent));
dn = dev_name(dev);
if (!dn || !*dn) {
/* Invent default name based on parent */
if (!parent)
return -EINVAL;
dev_set_name(dev, "%s:%s", parent->bus->name, dev_name(parent));
}
ret = device_add(dev);
return ret;
}
@@ -818,79 +637,54 @@ void dahdi_sysfs_unregister_device(struct dahdi_device *ddev)
int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops)
{
int res = 0;
void *dev;
dahdi_dbg(DEVICES, "Registering DAHDI device bus\n");
res = bus_register(&dahdi_device_bus);
if (res)
return res;
should_cleanup.clean_device_bus = 1;
dummy_dev.dahdi_device_bus_registered = 1;
dahdi_dbg(DEVICES,
"Registering character device (major=%d)\n", DAHDI_MAJOR);
res = register_chrdev(DAHDI_MAJOR, "dahdi", dahdi_fops);
if (res) {
module_printk(KERN_ERR, "Unable to register DAHDI character device handler on %d\n", DAHDI_MAJOR);
module_printk(KERN_ERR,
"Unable to register DAHDI character device "
"handler on %d\n", DAHDI_MAJOR);
return res;
}
module_printk(KERN_INFO, "Telephony Interface Registered on major %d\n",
DAHDI_MAJOR);
module_printk(KERN_INFO, "Version: %s\n", dahdi_version);
should_cleanup.clean_chardev = 1;
dahdi_class = class_create(THIS_MODULE, "dahdi");
if (!dahdi_class) {
res = -EEXIST;
res = dahdi_sysfs_chan_init(dahdi_fops);
if (res)
goto cleanup;
}
dahdi_dbg(DEVICES, "Creating /dev/dahdi/timer:\n");
dev = MAKE_DAHDI_DEV(DAHDI_TIMER, "dahdi!timer");
if (IS_ERR(dev)) {
res = PTR_ERR(dev);
goto cleanup;
}
dummy_dev.timer = 1;
dahdi_dbg(DEVICES, "Creating /dev/dahdi/channel:\n");
dev = MAKE_DAHDI_DEV(DAHDI_CHANNEL, "dahdi!channel");
if (IS_ERR(dev)) {
res = PTR_ERR(dev);
goto cleanup;
}
dummy_dev.channel = 1;
dahdi_dbg(DEVICES, "Creating /dev/dahdi/pseudo:\n");
dev = MAKE_DAHDI_DEV(DAHDI_PSEUDO, "dahdi!pseudo");
if (IS_ERR(dev)) {
res = PTR_ERR(dev);
goto cleanup;
}
dummy_dev.pseudo = 1;
dahdi_dbg(DEVICES, "Creating /dev/dahdi/ctl:\n");
dev = MAKE_DAHDI_DEV(DAHDI_CTL, "dahdi!ctl");
if (IS_ERR(dev)) {
res = PTR_ERR(dev);
goto cleanup;
}
dummy_dev.ctl = 1;
res = bus_register(&spans_bus_type);
if (res != 0) {
if (res) {
dahdi_err("%s: bus_register(%s) failed. Error number %d",
__func__, spans_bus_type.name, res);
goto cleanup;
}
dummy_dev.sysfs_spans_bus_type = 1;
should_cleanup.clean_span_bus_type = 1;
res = driver_register(&dahdi_driver);
if (res < 0) {
if (res) {
dahdi_err("%s: driver_register(%s) failed. Error number %d",
__func__, dahdi_driver.name, res);
goto cleanup;
}
dummy_dev.sysfs_driver_registered = 1;
should_cleanup.clean_dahdi_driver = 1;
module_printk(KERN_INFO, "Telephony Interface Registered on major %d\n",
DAHDI_MAJOR);
return 0;
cleanup:
dahdi_sysfs_exit();
dahdi_sysfs_cleanup();
return res;
}
void dahdi_sysfs_exit(void)
{
dahdi_sysfs_cleanup();
}

View File

@@ -0,0 +1,55 @@
#ifndef DAHDI_SYSFS_H
#define DAHDI_SYSFS_H
#define DEVICE_ATTR_READER(name, dev, buf) \
ssize_t name(struct device *dev, \
struct device_attribute *attr, \
char *buf)
#define DEVICE_ATTR_WRITER(name, dev, buf, count) \
ssize_t name(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count)
#define BUS_ATTR_READER(name, dev, buf) \
ssize_t name(struct device *dev, \
struct device_attribute *attr, \
char *buf)
#define BUS_ATTR_WRITER(name, dev, buf, count) \
ssize_t name(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count)
#define DRIVER_ATTR_READER(name, drv, buf) \
ssize_t name(struct device_driver *drv, char * buf)
/* Device file creation macros */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
#define CLASS_DEV_CREATE(class, devt, device, name) \
device_create(class, device, devt, NULL, "%s", name)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
#define CLASS_DEV_CREATE(class, devt, device, name) \
device_create(class, device, devt, name)
#else
#define CLASS_DEV_CREATE(class, devt, device, name) \
class_device_create(class, NULL, devt, device, name)
#endif
/* Device file destruction macros */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
#define CLASS_DEV_DESTROY(class, devt) \
device_destroy(class, devt)
#else
#define CLASS_DEV_DESTROY(class, devt) \
class_device_destroy(class, devt)
#endif
/* Global */
int __init dahdi_sysfs_chan_init(const struct file_operations *fops);
void dahdi_sysfs_chan_exit(void);
/* Channel Handling */
int chan_sysfs_create(struct dahdi_chan *chan);
void chan_sysfs_remove(struct dahdi_chan *chan);
#endif /* DAHDI_SYSFS_H */

View File

@@ -6,6 +6,7 @@
*
* Written by Tzafrir Cohen <tzafrir.cohen@xorcom.com>
* Copyright (C) 2011, Xorcom
* Copyright (C) 2011, Digium, Inc
*
* All rights reserved.
*

View File

@@ -10,7 +10,7 @@
* Converted to use HighResTimers on i386 by Jeffery Palmer <jeff@triggerinc.com>
*
* Copyright (C) 2002, Hermes Softlab
* Copyright (C) 2004-2009, Digium, Inc.
* Copyright (C) 2004-2012, Digium, Inc.
*
* All rights reserved.
*
@@ -53,7 +53,7 @@
#if defined(USE_HIGHRESTIMER)
#include <linux/hrtimer.h>
#else
#include <linux/time.h>
#include <linux/timer.h>
#endif
#include <dahdi/kernel.h>
@@ -75,6 +75,7 @@ static inline void hrtimer_set_expires(struct hrtimer *timer, ktime_t time)
#endif
struct dahdi_dummy {
struct dahdi_device *ddev;
struct dahdi_span span;
struct dahdi_chan _chan;
struct dahdi_chan *chan;
@@ -205,37 +206,44 @@ static const struct dahdi_span_ops dummy_ops = {
static int dahdi_dummy_initialize(struct dahdi_dummy *ztd)
{
int res = 0;
/* DAHDI stuff */
ztd->ddev = dahdi_create_device();
if (!ztd->ddev)
return -ENOMEM;
dev_set_name(&ztd->ddev->dev, "dahdi_dummy");
ztd->chan = &ztd->_chan;
sprintf(ztd->span.name, "DAHDI_DUMMY/1");
snprintf(ztd->span.desc, sizeof(ztd->span.desc) - 1, "%s (source: " CLOCK_SRC ") %d", ztd->span.name, 1);
sprintf(ztd->chan->name, "DAHDI_DUMMY/%d/%d", 1, 0);
strlcpy(ztd->span.devicetype, "DAHDI Dummy Timing",
sizeof(ztd->span.devicetype));
ztd->ddev->devicetype = "DAHDI Dummy Timing";
ztd->chan->chanpos = 1;
ztd->span.chans = &ztd->chan;
ztd->span.channels = 0; /* no channels on our span */
ztd->span.deflaw = DAHDI_LAW_MULAW;
ztd->chan->pvt = ztd;
ztd->span.ops = &dummy_ops;
if (dahdi_register(&ztd->span, 0)) {
return -1;
}
return 0;
list_add_tail(&ztd->span.device_node, &ztd->ddev->spans);
res = dahdi_register_device(ztd->ddev, NULL);
return res;
}
int init_module(void)
{
int res;
ztd = kzalloc(sizeof(*ztd), GFP_KERNEL);
if (ztd == NULL) {
printk(KERN_ERR "dahdi_dummy: Unable to allocate memory\n");
return -ENOMEM;
}
if (dahdi_dummy_initialize(ztd)) {
printk(KERN_ERR "dahdi_dummy: Unable to intialize DAHDI driver\n");
res = dahdi_dummy_initialize(ztd);
if (res) {
printk(KERN_ERR
"dahdi_dummy: Unable to intialize DAHDI driver (%d)\n",
res);
kfree(ztd);
return -ENODEV;
return res;
}
#if defined(USE_HIGHRESTIMER)
@@ -273,7 +281,8 @@ void cleanup_module(void)
atomic_set(&shutdown, 1);
del_timer_sync(&timer);
#endif
dahdi_unregister(&ztd->span);
dahdi_unregister_device(ztd->ddev);
dahdi_free_device(ztd->ddev);
kfree(ztd);
if (debug)
printk(KERN_DEBUG "dahdi_dummy: cleanup() finished\n");

View File

@@ -3,7 +3,7 @@
*
* Written by Mark Spencer <markster@digium.com>
*
* Copyright (C) 2001-2010, Digium, Inc.
* Copyright (C) 2001-2012, Digium, Inc.
*
* All rights reserved.
*
@@ -88,6 +88,8 @@ static int txerrors;
static struct tasklet_struct dahdi_dynamic_tlet;
static void dahdi_dynamic_tasklet(unsigned long data);
#else
static struct tasklet_struct dahdi_dynamic_flush_tlet;
#endif
static DEFINE_MUTEX(dspan_mutex);
@@ -208,12 +210,25 @@ static void __dahdi_dynamic_run(void)
dahdi_dynamic_sendmessage(d);
}
#ifdef ENABLE_TASKLETS
/* If tasklets are not enabled, the above section will be called in
* interrupt context and the flushing of each driver will be called in a
* separate tasklet that only handles that. This is necessary since some
* of the dynamic spans need to call functions that require interrupts
* to be enabled but dahdi_transmit / ...sendmessage needs to be called
* each time the masterspan is processed which happens with interrupts
* disabled.
*
*/
tasklet_hi_schedule(&dahdi_dynamic_flush_tlet);
#else
list_for_each_entry_rcu(drv, &driver_list, list) {
/* Flush any traffic still pending in the driver */
if (drv->flush) {
drv->flush();
}
}
#endif
rcu_read_unlock();
}
@@ -385,16 +400,6 @@ static void dahdi_dynamic_release(struct kref *kref)
WARN_ON(test_bit(DAHDI_FLAGBIT_REGISTERED, &d->span.flags));
if (d->pvt) {
if (d->driver && d->driver->destroy) {
__module_get(d->driver->owner);
d->driver->destroy(d);
module_put(d->driver->owner);
} else {
WARN_ON(1);
}
}
kfree(d->msgbuf);
for (x = 0; x < d->span.channels; x++)
@@ -406,12 +411,7 @@ static void dahdi_dynamic_release(struct kref *kref)
static inline int dynamic_put(struct dahdi_dynamic *d)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12)
kref_put(&d->kref, dahdi_dynamic_release);
return 1;
#else
return kref_put(&d->kref, dahdi_dynamic_release);
#endif
}
static inline void dynamic_get(struct dahdi_dynamic *d)
@@ -470,6 +470,24 @@ static int _destroy_dynamic(struct dahdi_dynamic_span *dds)
return -EBUSY;
}
if (d->pvt) {
if (d->driver && d->driver->destroy) {
if (!try_module_get(d->driver->owner)) {
/* The driver for this device is in the
* process of unloading. Leave this dynamic on
* the list so it's cleaned up when the driver
* unregisters. */
dynamic_put(d);
return -ENXIO;
}
d->driver->destroy(d);
module_put(d->driver->owner);
} else {
WARN_ON(1);
}
d->pvt = NULL;
}
dahdi_unregister_device(d->ddev);
spin_lock_irqsave(&dspan_lock, flags);
@@ -605,9 +623,10 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
strlcpy(d->dname, dds->driver, sizeof(d->dname));
strlcpy(d->addr, dds->addr, sizeof(d->addr));
d->timing = dds->timing;
sprintf(d->span.name, "DYN/%s/%s", dds->driver, dds->addr);
sprintf(d->span.desc, "Dynamic '%s' span at '%s'",
dds->driver, dds->addr);
snprintf(d->span.name, sizeof(d->span.name), "DYN/%s/%s",
dds->driver, dds->addr);
snprintf(d->span.desc, sizeof(d->span.desc),
"Dynamic '%s' span at '%s'", dds->driver, dds->addr);
d->span.deflaw = DAHDI_LAW_MULAW;
d->span.flags |= DAHDI_FLAG_RBS;
d->span.chans = d->chans;
@@ -658,6 +677,9 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
return res;
}
d->ddev->devicetype = d->span.name;
d->ddev->hardware_id = d->span.name;
dev_set_name(&d->ddev->dev, "dynamic:%s:%d", dds->driver, dtd->id++);
list_add_tail(&d->span.device_node, &d->ddev->spans);
/* Whee! We're created. Now register the span */
if (dahdi_register_device(d->ddev, d->dev)) {
@@ -701,6 +723,20 @@ static void dahdi_dynamic_tasklet(unsigned long data)
}
taskletpending = 0;
}
#else
static void dahdi_dynamic_flush_tasklet(unsigned long data)
{
struct dahdi_dynamic_driver *drv;
rcu_read_lock();
list_for_each_entry_rcu(drv, &driver_list, list) {
/* Flush any traffic still pending in the driver */
if (drv->flush) {
drv->flush();
}
}
rcu_read_unlock();
}
#endif
static int dahdi_dynamic_ioctl(unsigned int cmd, unsigned long data)
@@ -763,19 +799,17 @@ void dahdi_dynamic_unregister_driver(struct dahdi_dynamic_driver *dri)
list_for_each_entry_safe(d, n, &dspan_list, list) {
if (d->driver == dri) {
if (d->pvt) {
if (d->driver && d->driver->destroy) {
__module_get(d->driver->owner);
if (d->driver && d->driver->destroy)
d->driver->destroy(d);
module_put(d->driver->owner);
} else {
else
WARN_ON(1);
}
}
dahdi_unregister_device(d->ddev);
spin_lock_irqsave(&dspan_lock, flags);
list_del_rcu(&d->list);
spin_unlock_irqrestore(&dspan_lock, flags);
synchronize_rcu();
d->driver = NULL;
dynamic_put(d);
}
}
@@ -819,10 +853,13 @@ static void check_for_red_alarm(unsigned long ignored)
mod_timer(&alarmcheck, jiffies + 1 * HZ);
}
static const struct dahdi_dynamic_ops dahdi_dynamic_ops = {
.owner = THIS_MODULE,
.ioctl = dahdi_dynamic_ioctl,
};
static int dahdi_dynamic_init(void)
{
dahdi_set_dynamic_ioctl(dahdi_dynamic_ioctl);
/* Start process to check for RED ALARM */
init_timer(&alarmcheck);
alarmcheck.expires = 0;
@@ -832,20 +869,31 @@ static int dahdi_dynamic_init(void)
mod_timer(&alarmcheck, jiffies + 1 * HZ);
#ifdef ENABLE_TASKLETS
tasklet_init(&dahdi_dynamic_tlet, dahdi_dynamic_tasklet, 0);
#else
tasklet_init(&dahdi_dynamic_flush_tlet, dahdi_dynamic_flush_tasklet, 0);
#endif
dahdi_set_dynamic_ops(&dahdi_dynamic_ops);
printk(KERN_INFO "DAHDI Dynamic Span support LOADED\n");
return 0;
}
static void dahdi_dynamic_cleanup(void)
{
dahdi_set_dynamic_ops(NULL);
#ifdef ENABLE_TASKLETS
if (taskletpending) {
tasklet_disable(&dahdi_dynamic_tlet);
tasklet_kill(&dahdi_dynamic_tlet);
}
#else
tasklet_disable(&dahdi_dynamic_flush_tlet);
tasklet_kill(&dahdi_dynamic_flush_tlet);
#endif
dahdi_set_dynamic_ioctl(NULL);
del_timer_sync(&alarmcheck);
/* Must call again in case it was running before and rescheduled
* itself. */
del_timer(&alarmcheck);
printk(KERN_INFO "DAHDI Dynamic Span support unloaded\n");
}

View File

@@ -3,7 +3,7 @@
*
* Written by Mark Spencer <markster@digium.com>
*
* Copyright (C) 2001-2008, Digium, Inc.
* Copyright (C) 2001-2012, Digium, Inc.
*
* All rights reserved.
*
@@ -71,14 +71,12 @@ static struct dahdi_span *ztdeth_getspan(unsigned char *addr, unsigned short sub
if (z)
span = z->span;
spin_unlock_irqrestore(&zlock, flags);
if (!span || !test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags))
return NULL;
return span;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
#else
static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
#endif
{
struct dahdi_span *span;
struct ztdeth_header *zh;
@@ -87,11 +85,7 @@ static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
#else
zh = (struct ztdeth_header *)skb->nh.raw;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
span = ztdeth_getspan(eth_hdr(skb)->h_source, zh->subaddr);
#else
span = ztdeth_getspan(skb->mac.ethernet->h_source, zh->subaddr);
#endif
if (span) {
skb_pull(skb, sizeof(struct ztdeth_header));
#ifdef NEW_SKB_LINEARIZE
@@ -152,7 +146,7 @@ static void ztdeth_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
spin_lock_irqsave(&zlock, flags);
z = dyn->pvt;
if (z->dev) {
if (z && z->dev) {
/* Copy fields to local variables to remove spinlock ASAP */
dev = z->dev;
memcpy(addr, z->addr, sizeof(z->addr));
@@ -191,15 +185,16 @@ static void ztdeth_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
spin_unlock_irqrestore(&zlock, flags);
}
/**
* ztdeth_flush - Flush all pending transactions.
*
* This function is always called in softirq context.
*/
static int ztdeth_flush(void)
{
struct sk_buff *skb;
/* Handle all transmissions now */
while ((skb = skb_dequeue(&skbs))) {
while ((skb = skb_dequeue(&skbs)))
dev_queue_xmit(skb);
}
return 0;
}
@@ -284,11 +279,12 @@ static void ztdeth_destroy(struct dahdi_dynamic *dyn)
prev = cur;
cur = cur->next;
}
spin_unlock_irqrestore(&zlock, flags);
if (cur == z) { /* Successfully removed */
dyn->pvt = NULL;
printk(KERN_INFO "TDMoE: Removed interface for %s\n", z->span->name);
kfree(z);
}
spin_unlock_irqrestore(&zlock, flags);
}
static int ztdeth_create(struct dahdi_dynamic *dyn, const char *addr)
@@ -411,20 +407,22 @@ static struct notifier_block ztdeth_nblock = {
static int __init ztdeth_init(void)
{
skb_queue_head_init(&skbs);
dev_add_pack(&ztdeth_ptype);
register_netdevice_notifier(&ztdeth_nblock);
dahdi_dynamic_register_driver(&ztd_eth);
skb_queue_head_init(&skbs);
return 0;
}
static void __exit ztdeth_exit(void)
{
dev_remove_pack(&ztdeth_ptype);
unregister_netdevice_notifier(&ztdeth_nblock);
dahdi_dynamic_unregister_driver(&ztd_eth);
unregister_netdevice_notifier(&ztdeth_nblock);
dev_remove_pack(&ztdeth_ptype);
skb_queue_purge(&skbs);
}
MODULE_DESCRIPTION("DAHDI Dynamic TDMoE Support");

View File

@@ -36,6 +36,7 @@
#include <linux/netdevice.h>
#include <linux/notifier.h>
#include <linux/crc32.h>
#include <linux/seq_file.h>
/**
* Undefine USE_PROC_FS, if you do not want the /proc/dahdi/dynamic-ethmf
@@ -224,13 +225,8 @@ static inline int ethmf_trx_spans_ready(unsigned int addr_hash, struct ztdeth *(
/**
* Ethernet receiving side processing function.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev)
#else
static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
#endif
{
int num_spans = 0, span_index = 0;
unsigned char *data;
@@ -267,13 +263,8 @@ static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev,
rcu_read_lock();
do {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9)
find_ethmf(eth_hdr(skb)->h_source,
htons(span_index), &z, &span);
#else
find_ethmf(skb->mac.ethernet->h_source,
htons(span_index), &z, &span);
#endif
if (unlikely(!z || !span)) {
/* The recv'd span does not belong to us */
/* ethmf_errors_inc(); */
@@ -396,10 +387,6 @@ static void ztdethmf_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
struct net_device *dev;
unsigned char addr[ETH_ALEN];
int spans_ready = 0, index = 0;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
static DEFINE_SPINLOCK(lock);
unsigned long flags;
#endif
if (atomic_read(&shutdown))
return;
@@ -411,24 +398,12 @@ static void ztdethmf_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
return;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
if (!atomic_read(&z->ready)) {
spin_lock_irqsave(&lock, flags);
atomic_inc(&z->ready);
if (1 == atomic_read(&z->ready)) {
memcpy(z->msgbuf, msg, msglen);
z->msgbuf_len = msglen;
}
spin_unlock_irqrestore(&lock, flags);
}
#else
if (!atomic_read(&z->ready)) {
if (atomic_inc_return(&z->ready) == 1) {
memcpy(z->msgbuf, msg, msglen);
z->msgbuf_len = msglen;
}
}
#endif
spans_ready = ethmf_trx_spans_ready(z->addr_hash, &ready_spans);
if (spans_ready) {
@@ -722,71 +697,69 @@ static void timer_callback(unsigned long param)
#ifdef USE_PROC_FS
static struct proc_dir_entry *proc_entry;
static const char *ztdethmf_procname = "dahdi/dynamic-ethmf";
static int ztdethmf_proc_read(char *page, char **start, off_t off, int count,
int *eof, void *data)
static int ztdethmf_proc_show(struct seq_file *sfile, void *not_used)
{
struct ztdeth *z = NULL;
int len = 0, i = 0;
int i = 0;
unsigned int group = 0, c = 0;
rcu_read_lock();
len += sprintf(page + len, "Errors: %d\n\n", atomic_read(&errcount));
seq_printf(sfile, "Errors: %d\n\n", atomic_read(&errcount));
for (group = 0; group < ETHMF_MAX_GROUPS; ++group) {
if (atomic_read(&(ethmf_groups[group].spans))) {
len += sprintf(page + len, "Group #%d (0x%x)\n", i++, ethmf_groups[group].hash_addr);
len += sprintf(page + len, " Spans: %d\n",
atomic_read(&(ethmf_groups[group].spans)));
seq_printf(sfile, "Group #%d (0x%x)\n", i++,
ethmf_groups[group].hash_addr);
seq_printf(sfile, "Spans: %d\n",
atomic_read(&(ethmf_groups[group].spans)));
c = 1;
list_for_each_entry_rcu(z, &ethmf_list, list) {
if (z->addr_hash == ethmf_groups[group].hash_addr) {
if (c == 1) {
len += sprintf(page + len,
seq_printf(sfile,
" Device: %s (MAC: %02x:%02x:%02x:%02x:%02x:%02x)\n",
z->ethdev,
z->addr[0], z->addr[1], z->addr[2],
z->addr[3], z->addr[4], z->addr[5]);
}
len += sprintf(page + len, " Span %d: subaddr=%u ready=%d delay=%d real_channels=%d no_front_padding=%d\n",
seq_printf(sfile, " Span %d: subaddr=%u ready=%d delay=%d real_channels=%d no_front_padding=%d\n",
c++, ntohs(z->subaddr),
atomic_read(&z->ready), atomic_read(&z->delay),
z->real_channels, atomic_read(&z->no_front_padding));
}
}
len += sprintf(page + len, " Device UPs: %u\n",
seq_printf(sfile, " Device UPs: %u\n",
atomic_read(&(ethmf_groups[group].devupcount)));
len += sprintf(page + len, " Device DOWNs: %u\n",
seq_printf(sfile, " Device DOWNs: %u\n",
atomic_read(&(ethmf_groups[group].devdowncount)));
len += sprintf(page + len, " Rx Frames: %u\n",
seq_printf(sfile, " Rx Frames: %u\n",
atomic_read(&(ethmf_groups[group].rxframecount)));
len += sprintf(page + len, " Tx Frames: %u\n",
seq_printf(sfile, " Tx Frames: %u\n",
atomic_read(&(ethmf_groups[group].txframecount)));
len += sprintf(page + len, " Rx Bytes: %u\n",
seq_printf(sfile, " Rx Bytes: %u\n",
atomic_read(&(ethmf_groups[group].rxbytecount)));
len += sprintf(page + len, " Tx Bytes: %u\n",
seq_printf(sfile, " Tx Bytes: %u\n",
atomic_read(&(ethmf_groups[group].txbytecount)));
if (len <= off) {
off -= len;
len = 0;
}
if (len > off+count)
break;
}
}
rcu_read_unlock();
if (len <= off) {
off -= len;
len = 0;
}
*start = page + off;
len -= off;
if (len > count)
len = count;
return len;
return 0;
}
static int ztdethmf_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, ztdethmf_proc_show, NULL);
}
static const struct file_operations ztdethmf_proc_fops = {
.open = ztdethmf_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
#endif
static int __init ztdethmf_init(void)
@@ -804,8 +777,8 @@ static int __init ztdethmf_init(void)
skb_queue_head_init(&skbs);
#ifdef USE_PROC_FS
proc_entry = create_proc_read_entry(ztdethmf_procname, 0444, NULL,
ztdethmf_proc_read, NULL);
proc_entry = proc_create_data(ztdethmf_procname, 0444, NULL,
&ztdethmf_proc_fops, NULL);
if (!proc_entry) {
printk(KERN_ALERT "create_proc_read_entry failed.\n");
}

View File

@@ -78,10 +78,11 @@ static LIST_HEAD(dynamic_local_list);
static void
dahdi_dynamic_local_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
{
struct dahdi_dynamic_local *const d = dyn->pvt;
struct dahdi_dynamic_local *d;
unsigned long flags;
spin_lock_irqsave(&local_lock, flags);
d = dyn->pvt;
if (d && d->peer && d->peer->span) {
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &d->peer->span->flags))
dahdi_dynamic_receive(d->peer->span, msg, msglen);
@@ -130,11 +131,12 @@ static int digit2int(char d)
static void dahdi_dynamic_local_destroy(struct dahdi_dynamic *dyn)
{
struct dahdi_dynamic_local *d = dyn->pvt;
struct dahdi_dynamic_local *d;
unsigned long flags;
struct dahdi_dynamic_local *cur;
spin_lock_irqsave(&local_lock, flags);
d = dyn->pvt;
list_for_each_entry(cur, &dynamic_local_list, node) {
if (cur->peer == d)
cur->peer = NULL;

View File

@@ -7,7 +7,7 @@
* This "echo can" will completely hose your audio.
* Don't use it unless you're absolutely sure you know what you're doing.
*
* Copyright (C) 2007-2008, Digium, Inc.
* Copyright (C) 2007-2012, Digium, Inc.
*
* All rights reserved.
*
@@ -38,9 +38,6 @@
static int debug;
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec);
static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);

View File

@@ -5,7 +5,7 @@
*
* Based upon mec2.h
*
* Copyright (C) 2002, Digium, Inc.
* Copyright (C) 2002-2012, Digium, Inc.
*
* Additional background on the techniques used in this code can be found in:
*
@@ -44,9 +44,6 @@
static int debug;
static int aggressive;
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
/* Uncomment to provide summary statistics for overall echo can performance every 4000 samples */
/* #define MEC2_STATS 4000 */

View File

@@ -5,7 +5,7 @@
*
* Based upon kb1ec.h and mec2.h
*
* Copyright (C) 2002, Digium, Inc.
* Copyright (C) 2002-2012, Digium, Inc.
*
* Additional background on the techniques used in this code can be found in:
*
@@ -44,9 +44,6 @@
static int debug;
static int aggressive;
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
#define ABS(a) abs(a!=-32768?a:-32767)
#define RESTORE_COEFFS {\

View File

@@ -36,8 +36,6 @@
#include <dahdi/kernel.h>
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec);
static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);

View File

@@ -48,9 +48,6 @@
static int debug;
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
#include "arith.h"
#ifndef NULL

View File

@@ -47,9 +47,6 @@
static int debug;
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
#include "fir.h"
#ifndef NULL

View File

@@ -22,6 +22,7 @@
.PHONY: dist-clean clean all uninstall have_download install object-build hotplug-install hotplug-dirs hotplug-uninstall make_firmware_object firmware-loaders
OCT6114_032_VERSION:=1.05.01
OCT6114_064_VERSION:=1.05.01
OCT6114_128_VERSION:=1.05.01
OCT6114_256_VERSION:=1.05.01
@@ -30,10 +31,12 @@ VPMADT032_VERSION:=1.25.0
HX8_VERSION:=2.06
VPMOCT032_VERSION:=1.12.0
WCT820_VERSION:=1.76
TE133_VERSION:=6f0017
TE134_VERSION:=6f0017
FIRMWARE_URL:=http://downloads.digium.com/pub/telephony/firmware/releases
ALL_FIRMWARE=FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256 FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032 FIRMWARE-TE820
ALL_FIRMWARE=FIRMWARE-OCT6114-032 FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256 FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032 FIRMWARE-TE820 FIRMWARE-TE133 FIRMWARE-TE134
# Firmware files should use the naming convention: dahdi-fw-<base name>-<sub name>-<version> or dahdi-fw-<base name>-<version>
# First example: dahdi-fw-oct6114-064-1.05.01
@@ -42,22 +45,27 @@ ALL_FIRMWARE=FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256 FIRM
# This means this is version MR5.6 of the tc400m firmware
# Build a list of firmware package filenames we need
FIRMWARE:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-064=dahdi-fw-oct6114-064-$(OCT6114_064_VERSION).tar.gz)
FIRMWARE:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-032=dahdi-fw-oct6114-032-$(OCT6114_032_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-OCT6114-064=dahdi-fw-oct6114-064-$(OCT6114_064_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-OCT6114-128=dahdi-fw-oct6114-128-$(OCT6114_128_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-OCT6114-256=dahdi-fw-oct6114-256-$(OCT6114_256_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-TC400M=dahdi-fw-tc400m-$(TC400M_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-HX8=dahdi-fw-hx8-$(HX8_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032-$(VPMOCT032_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE820=dahdi-fw-te820-$(WCT820_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE133=dahdi-fw-te133-$(TE133_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE134=dahdi-fw-te134-$(TE134_VERSION).tar.gz)
FWLOADERS:=dahdi-fwload-vpmadt032-$(VPMADT032_VERSION).tar.gz
# Build a list of object files if hotplug will not be used
OBJECT_FILES:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-032=dahdi-fw-oct6114-032.o)
OBJECT_FILES:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-064=dahdi-fw-oct6114-064.o)
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-OCT6114-128=dahdi-fw-oct6114-128.o)
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-OCT6114-256=dahdi-fw-oct6114-256.o)
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-TC400M=dahdi-fw-tc400m.o)
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-HX8=dahdi-fw-hx8.o)
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032.o)
# Force usage of wget, for now
DOWNLOAD=wget
@@ -106,6 +114,17 @@ $(DESTDIR)/usr/lib/hotplug/firmware $(DESTDIR)/lib/firmware:
# Install all downloaded firmware images for hotplug usage
hotplug-install: $(DESTDIR)/usr/lib/hotplug/firmware $(DESTDIR)/lib/firmware $(FIRMWARE)
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-032-$(OCT6114_032_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-032-$(OCT6114_032_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-oct6114-032.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-oct6114-032.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-032-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-032-$(OCT6114_032_VERSION)
@install -m 644 dahdi-fw-oct6114-032.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-032-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-032-$(OCT6114_032_VERSION)
else
@echo "Firmware dahdi-fw-oct6114-032.bin is already installed with required version $(OCT6114_032_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-oct6114-064.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-oct6114-064.bin $(DESTDIR)/usr/lib/hotplug/firmware
@@ -184,6 +203,29 @@ else
@echo "Firmware dahdi-fw-te820.bin is already installed with required version $(WCT820_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te133-$(TE133_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-te133-$(TE133_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-te133.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-te133.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te133-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te133-$(TE133_VERSION)
@install -m 644 dahdi-fw-te133.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-te133-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-te133-$(TE133_VERSION)
else
@echo "Firmware dahdi-fw-te133.bin is already installed with required version $(TE133_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te134-$(TE134_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-te134-$(TE134_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-te134.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-te134.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te134-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te134-$(TE134_VERSION)
@install -m 644 dahdi-fw-te134.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-te134-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-te134-$(TE134_VERSION)
else
@echo "Firmware dahdi-fw-te134.bin is already installed with required version $(TE134_VERSION)"
endif
# Uninstall any installed dahdi firmware images from hotplug firmware directories
hotplug-uninstall:
if [ -d $(DESTDIR)/usr/lib/hotplug/firmware ]; then \
@@ -201,6 +243,11 @@ make_firmware_object: make_firmware_object.in ../dahdi-base.o
sed -e s/BFDNAME/$${BFDNAME}/ -e s/BFDARCH/$${BFDARCH}/ $< > $@
@chmod +x $@
# Build object file of an oct6114 032 firmware image for linking
dahdi-fw-oct6114-032.o: dahdi-fw-oct6114-032-$(OCT6114_032_VERSION).tar.gz dahdi-fw-oct6114-032.bin make_firmware_object
@echo Making firmware object file for dahdi-fw-oct6114-032.bin
./make_firmware_object dahdi-fw-oct6114-032.bin $@
# Build object file of an oct6114 064 firmware image for linking
dahdi-fw-oct6114-064.o: dahdi-fw-oct6114-064-$(OCT6114_064_VERSION).tar.gz dahdi-fw-oct6114-064.bin make_firmware_object
@echo Making firmware object file for dahdi-fw-oct6114-064.bin
@@ -220,3 +267,8 @@ dahdi-fw-oct6114-256.o: dahdi-fw-oct6114-256-$(OCT6114_256_VERSION).tar.gz dahdi
dahdi-fw-tc400m.o: dahdi-fw-tc400m-$(TC400M_VERSION).tar.gz dahdi-fw-tc400m.bin make_firmware_object
@echo Making firmware object file for dahdi-fw-tc400m.bin
./make_firmware_object dahdi-fw-tc400m.bin $@
# Build object file of a VPMOCT032 firmware image for linking
dahdi-fw-vpmoct032.o: dahdi-fw-vpmoct032-$(VPMOCT032_VERSION).tar.gz dahdi-fw-vpmoct032.bin make_firmware_object
@echo Making firmware object file for dahdi-fw-vpmoct032.bin
./make_firmware_object dahdi-fw-vpmoct032.bin $@

View File

@@ -1,7 +1,7 @@
/*
* DAHDI Telephony Interface to Digium High-Performance Echo Canceller
*
* Copyright (C) 2006-2008 Digium, Inc.
* Copyright (C) 2006-2012 Digium, Inc.
*
* All rights reserved.
*
@@ -31,9 +31,6 @@
static int debug;
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
#include "hpec_user.h"
#include "hpec.h"
@@ -75,18 +72,9 @@ static int __attribute__((regparm(0), format(printf, 1, 2))) logger(const char *
int res;
va_list args;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
va_start(args, format);
res = vprintk(format, args);
va_end(args);
#else
char buf[256];
va_start(args, format);
res = vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
printk(KERN_INFO "%s" buf);
#endif
return res;
}

View File

@@ -1,38 +1,30 @@
CFLAGS=-V3.4 -ffunction-sections -I/lib/modules/$(shell uname -r)/build/include -Iinclude -Ioctdeviceapi -Ioctdeviceapi/oct6100api -DGFP_ATOMIC=0 -Dkmalloc=calloc -Dkfree=free
LDFLAGS=-V3.4 -Wl,-Map -Wl,test.map -Wl,--gc-sections
#
# Produces the oct612x library
#
octapi_files = octdeviceapi/oct6100api/oct6100_api/oct6100_adpcm_chan.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_channel.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_chip_open.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_chip_stats.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_debug.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_events.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_interrupts.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_memory.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_miscellaneous.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_mixer.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_phasing_tsst.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_remote_debug.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_tlv.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_tone_detection.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_tsi_cnct.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_tsst.o \
apilib/bt/octapi_bt0.o \
apilib/largmath/octapi_largmath.o \
apilib/llman/octapi_llman.o
APIDIR=octdeviceapi/oct6100api/oct6100_api
OCTASIC_OBJS=$(APIDIR)/oct6100_adpcm_chan.o \
$(APIDIR)/oct6100_channel.o \
$(APIDIR)/oct6100_chip_open.o \
$(APIDIR)/oct6100_chip_stats.o \
$(APIDIR)/oct6100_conf_bridge.o \
$(APIDIR)/oct6100_debug.o \
$(APIDIR)/oct6100_events.o \
$(APIDIR)/oct6100_interrupts.o \
$(APIDIR)/oct6100_memory.o \
$(APIDIR)/oct6100_miscellaneous.o \
$(APIDIR)/oct6100_mixer.o \
$(APIDIR)/oct6100_phasing_tsst.o \
$(APIDIR)/oct6100_playout_buf.o \
$(APIDIR)/oct6100_remote_debug.o \
$(APIDIR)/oct6100_tlv.o \
$(APIDIR)/oct6100_tone_detection.o \
$(APIDIR)/oct6100_tsi_cnct.o \
$(APIDIR)/oct6100_tsst.o \
$(APIDIR)/oct6100_user.o \
apilib/bt/octapi_bt0.o \
apilib/largmath/octapi_largmath.o \
apilib/llman/octapi_llman.o
all: test
test.o: test.c
test: test.o $(OCTASIC_OBJS)
clean:
rm -rf test test.o
rm -rf $(OCTASIC_OBJS)
# TODO: ccflags was added in 2.6.24 in commit f77bf01425b11947eeb3b5b54. This
# should be changed to a conditional compilation based on the Kernel Version.
# ccflags-y := -I$(src)/.. -Wno-undef -I$(src)/include -I$(src)/octdeviceapi -I$(src)/octdeviceapi/oct6100api
EXTRA_CFLAGS = -I$(src)/.. -Wno-undef -I$(src)/include -I$(src)/octdeviceapi -I$(src)/octdeviceapi/oct6100api
lib-y := $(octapi_files)

View File

@@ -290,12 +290,12 @@ static void init_spans(struct tor2 *tor)
s->channels = 24;
s->deflaw = DAHDI_LAW_MULAW;
s->linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
s->spantype = "T1";
s->spantype = SPANTYPE_DIGITAL_T1;
} else {
s->channels = 31;
s->deflaw = DAHDI_LAW_ALAW;
s->linecompat = DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4;
s->spantype = "E1";
s->spantype = SPANTYPE_DIGITAL_E1;
}
s->chans = tor->chans[x];
s->flags = DAHDI_FLAG_RBS;

View File

@@ -2,4 +2,17 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VOICEBUS) += dahdi_voicebus.o
dahdi_voicebus-objs := voicebus.o GpakCust.o GpakApi.o voicebus_net.o vpmoct.o
EXTRA_CFLAGS := -I$(src)/.. -Wno-undef
FIRM_DIR := ../firmware
ifneq ($(HOTPLUG_FIRMWARE),yes)
dahdi_voicebus-objs += $(FIRM_DIR)/dahdi-fw-vpmoct032.o
$(warning WARNING: You are compiling firmware into voicebus.ko which is not available under the terms of the GPL. It may be a violation of the GPL to distribute the resulting image since it combines both GPL and non-GPL work. You should consult a lawyer of your own before distributing such an image.)
else
EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE
endif
EXTRA_CFLAGS += -I$(src)/.. -Wno-undef
$(obj)/$(FIRM_DIR)/dahdi-fw-vpmoct032.o: $(obj)/voicebus.o
$(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-vpmoct032.o

View File

@@ -1,6 +0,0 @@
ifdef KBUILD_EXTMOD
# We only get here on kernels 2.6.0-2.6.9 .
# For newer kernels, Kbuild will be included directly by the kernel
# build system.
include $(src)/Kbuild
endif

View File

@@ -57,6 +57,15 @@
* (and not tasklet). */
#define CONFIG_VOICEBUS_INTERRUPT
/*
* Enable the following definition in order to disable Active-State Power
* Management on the PCIe bridge for PCIe cards. This has been known to work
* around issues where the BIOS enables it on the cards even though the
* platform does not support it.
*
*/
#undef CONFIG_VOICEBUS_DISABLE_ASPM
/* Define this to use a FIFO for the software echocan reference.
* (experimental) */
#undef CONFIG_VOICEBUS_ECREFERENCE

View File

@@ -443,6 +443,47 @@ static void vpmoct_set_defaults(struct vpmoct *vpm)
vpmoct_write_dword(vpm, 0x30, 0);
}
static const char *const FIRMWARE_NAME = "dahdi-fw-vpmoct032.bin";
#if defined(HOTPLUG_FIRMWARE)
static int
vpmoct_request_firmware(const struct firmware **fw, struct device *dev)
{
return request_firmware(fw, FIRMWARE_NAME, dev);
}
static void vpmoct_release_firmware(const struct firmware *fw)
{
release_firmware(fw);
}
#else
static int
vpmoct_request_firmware(const struct firmware **fw_p, struct device *dev)
{
struct firmware *fw;
extern void _binary_dahdi_fw_vpmoct032_bin_size;
extern u8 _binary_dahdi_fw_vpmoct032_bin_start[];
*fw_p = fw = kzalloc(sizeof(*fw), GFP_KERNEL);
if (!fw)
return -ENOMEM;
fw->data = _binary_dahdi_fw_vpmoct032_bin_start;
/* Yes... this is weird. objcopy gives us a symbol containing
the size of the firmware, not a pointer a variable containing the
size. The only way we can get the value of the symbol is to take
its address, so we define it as a pointer and then cast that value
to the proper type. */
fw->size = (size_t) &_binary_dahdi_fw_vpmoct032_bin_size;
return 0;
}
static void vpmoct_release_firmware(const struct firmware *fw)
{
kfree(fw);
}
#endif
/**
* vpmoct_load_flash - Check the current flash version and possibly load.
* @vpm: The VPMOCT032 module to check / load.
@@ -463,10 +504,9 @@ static void vpmoct_load_flash(struct work_struct *data)
const struct firmware *fw;
const struct vpmoct_header *header;
char serial[VPMOCT_SERIAL_SIZE+1];
const char *const FIRMWARE_NAME = "dahdi-fw-vpmoct032.bin";
int i;
res = request_firmware(&fw, FIRMWARE_NAME, vpm->dev);
res = vpmoct_request_firmware(&fw, vpm->dev);
if (res) {
dev_warn(vpm->dev,
"vpmoct: Failed to load firmware from userspace! %d\n",
@@ -505,7 +545,7 @@ static void vpmoct_load_flash(struct work_struct *data)
FIRMWARE_NAME);
/* Just use the old version of the fimware. */
release_firmware(fw);
vpmoct_release_firmware(fw);
vpmoct_set_defaults(vpm);
vpmoct_load_complete(work, true);
return;
@@ -514,7 +554,7 @@ static void vpmoct_load_flash(struct work_struct *data)
if (vpm->minor == header->minor &&
vpm->major == header->major) {
/* Proper version is running */
release_firmware(fw);
vpmoct_release_firmware(fw);
vpmoct_set_defaults(vpm);
vpmoct_load_complete(work, true);
return;
@@ -548,14 +588,14 @@ static void vpmoct_load_flash(struct work_struct *data)
if (vpmoct_check_firmware_crc(vpm, fw->size-VPMOCT_FIRM_HEADER_LEN*2,
header->major, header->minor))
goto error;
release_firmware(fw);
vpmoct_release_firmware(fw);
vpmoct_set_defaults(vpm);
vpmoct_load_complete(work, true);
return;
error:
dev_info(vpm->dev, "Unable to load firmware\n");
release_firmware(fw);
vpmoct_release_firmware(fw);
/* TODO: Should we disable module if the firmware doesn't load? */
vpmoct_load_complete(work, false);
return;

View File

@@ -1,7 +1,7 @@
/*
* DAHDI Telephony Interface to VPMADT032 Firmware Loader
*
* Copyright (C) 2008-2011 Digium, Inc. All rights reserved.
* Copyright (C) 2008-2012 Digium, Inc. 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 version 2 as
@@ -38,18 +38,9 @@ logger(const char *format, ...)
int res;
va_list args;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9)
va_start(args, format);
res = vprintk(format, args);
va_end(args);
#else
char buf[256];
va_start(args, format);
res = vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
printk(KERN_INFO "%s" buf);
#endif
return res;
}

View File

@@ -1,7 +0,0 @@
ifdef KBUILD_EXTMOD
# We only get here on kernels 2.6.0-2.6.9 .
# For newer kernels, Kbuild will be included directly by the kernel
# build system.
include $(src)/Kbuild
else
endif

View File

@@ -2,7 +2,7 @@
* WCB410P Quad-BRI PCI Driver
* Written by Andrew Kohlsmith <akohlsmith@mixdown.ca>
*
* Copyright (C) 2009-2011 Digium, Inc.
* Copyright (C) 2009-2012 Digium, Inc.
* All rights reserved.
*
*/
@@ -35,7 +35,6 @@
#include <linux/spinlock.h>
#include <linux/device.h> /* dev_err() */
#include <linux/interrupt.h>
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* copy_*_user */
#include <linux/workqueue.h> /* work_struct */
#include <linux/timer.h> /* timer_struct */
@@ -91,6 +90,7 @@ static int milliwatt = 0;
static int pedanticpci = 0;
static int teignorered = 0;
static int alarmdebounce = 500;
static int persistentlayer1 = 1;
static int vpmsupport = 1;
static int timer_1_ms = 2000;
static int timer_3_ms = 30000;
@@ -140,7 +140,7 @@ static struct devtype hfc8s_BN = {"BeroNet BN8S0", .ports = 8, .card_type = BN8S
static struct devtype hfc4s_SW = {"Swyx 4xS0 SX2 QuadBri", .ports = 4, .card_type = BSWYX_SX2 };
static struct devtype hfc4s_EV = {"CCD HFC-4S Eval. Board", .ports = 4,
.card_type = QUADBRI_EVAL };
#define CARD_HAS_EC(card) ((card)->card_type == B410P)
static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);
@@ -1198,7 +1198,6 @@ static int b4xxp_find_sync(struct b4xxp *b4)
return src;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18))
static ssize_t b4_timing_master_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -1226,13 +1225,6 @@ static void remove_sysfs_files(struct b4xxp *b4)
&dev_attr_timing_master);
}
#else
static inline void create_sysfs_files(struct b4xxp *b4) { return; }
static inline void remove_sysfs_files(struct b4xxp *b4) { return; }
#endif /* LINUX_KERNEL > 2.6.18 */
/*
* allocates memory and pretty-prints a given S/T state engine state to it.
* calling routine is responsible for freeing the pointer returned!
@@ -1250,7 +1242,8 @@ static char *hfc_decode_st_state(struct b4xxp *b4, int port, unsigned char state
"?", "?", "?", "?", "?", "?", "?", "?" }
};
if (!(str = kmalloc(256, GFP_KERNEL))) {
str = kmalloc(256, GFP_ATOMIC);
if (!str) {
dev_warn(&b4->pdev->dev, "could not allocate mem for ST state decode string!\n");
return NULL;
}
@@ -1303,6 +1296,9 @@ static void hfc_force_st_state(struct b4xxp *b4, int port, int state, int resume
hfc_handle_state(&b4->spans[port]);
}
static void hfc_stop_st(struct b4xxp_span *s);
static void hfc_start_st(struct b4xxp_span *s);
/* figures out what to do when an S/T port's timer expires. */
static void hfc_timer_expire(struct b4xxp_span *s, int t_no)
{
@@ -1316,10 +1312,15 @@ static void hfc_timer_expire(struct b4xxp_span *s, int t_no)
s->hfc_timer_on[t_no]);
}
/*
* there are three timers associated with every HFC S/T port.
* T1 is used by the NT state machine, and is the maximum time the NT side should wait for G3 (active) state.
* T2 is not actually used in the driver, it is handled by the HFC-4S internally.
* T3 is used by the TE state machine; it is the maximum time the TE side should wait for the INFO4 (activated) signal.
* There are four timers associated with every HFC S/T port:
* T1 is used by the NT state machine, and is the maximum time the NT side
* should wait for G3 (active) state.
* T2 is not actually used in the driver, it is handled by the HFC-4S
* internally.
* T3 is used by the TE state machine; it is the maximum time the TE side should
* wait for the INFO4 (activated) signal.
* T4 is a special timer used for debug purposes for monitoring of L1 state
* during activation attempt.
*/
/* First, disable the expired timer; hfc_force_st_state() may activate it again. */
@@ -1333,7 +1334,14 @@ static void hfc_timer_expire(struct b4xxp_span *s, int t_no)
hfc_force_st_state(b4, s->port, 1, 1);
break;
case HFC_T3: /* switch to F3 (deactivated), resume auto mode */
hfc_force_st_state(b4, s->port, 3, 1);
hfc_stop_st(s);
if (persistentlayer1)
hfc_start_st(s);
break;
case HFC_T4:
hfc_handle_state(s);
s->hfc_timers[HFC_T4] = b4->ticks + 1000;
s->hfc_timer_on[HFC_T4] = 1;
break;
default:
if (printk_ratelimit()) {
@@ -1356,9 +1364,9 @@ static void hfc_update_st_timers(struct b4xxp *b4)
for (i=0; i < b4->numspans; i++) {
s = &b4->spans[i];
for (j=HFC_T1; j <= HFC_T3; j++) {
/* we don't really do timer2, it is expired by the state change handler */
for (j = HFC_T1; j < ARRAY_SIZE(s->hfc_timers); j++) {
/* we don't really do timer2, it is expired by the
* state change handler */
if (j == HFC_T2)
continue;
@@ -1442,6 +1450,7 @@ static void hfc_handle_state(struct b4xxp_span *s)
break;
case 0x7: /* TE state F7: Activated */
s->hfc_timer_on[HFC_T3] = 0;
s->hfc_timer_on[HFC_T4] = 0;
s->newalarm = 0;
break;
}
@@ -1463,14 +1472,17 @@ static void hfc_handle_state(struct b4xxp_span *s)
/* If we're in F3 and receiving INFO0, start T3 and jump to F4 */
if (!nt && (sta == 3) && (state & V_INFO0)) {
s->hfc_timers[HFC_T3] = b4->ticks + timer_3_ms;
s->hfc_timer_on[HFC_T3] = 1;
if (DBG_ST) {
dev_info(&b4->pdev->dev,
"port %d: receiving INFO0 in state 3, "
"setting T3 and jumping to F4\n", s->port + 1);
if (persistentlayer1) {
s->hfc_timers[HFC_T3] = b4->ticks + timer_3_ms;
s->hfc_timer_on[HFC_T3] = 1;
if (DBG_ST) {
dev_info(&b4->pdev->dev,
"port %d: receiving INFO0 in state 3, "
"setting T3 and jumping to F4\n",
s->port + 1);
}
hfc_start_st(s);
}
hfc_force_st_state(b4, s->port, 4, 1);
}
/* read in R_BERT_STA to determine where our current sync source is */
@@ -1485,6 +1497,24 @@ static void hfc_handle_state(struct b4xxp_span *s)
}
}
static void hfc_stop_all_timers(struct b4xxp_span *s)
{
s->hfc_timer_on[HFC_T4] = 0;
s->hfc_timer_on[HFC_T3] = 0;
s->hfc_timer_on[HFC_T2] = 0;
s->hfc_timer_on[HFC_T1] = 0;
}
static void hfc_stop_st(struct b4xxp_span *s)
{
struct b4xxp *b4 = s->parent;
hfc_stop_all_timers(s);
b4xxp_setreg_ra(b4, R_ST_SEL, s->port, A_ST_WR_STA,
V_ST_ACT_DEACTIVATE);
}
/*
* resets an S/T interface to a given NT/TE mode
*/
@@ -1495,10 +1525,16 @@ static void hfc_reset_st(struct b4xxp_span *s)
b4 = s->parent;
hfc_stop_st(s);
/* force state G0/F0 (reset), then force state 1/2 (deactivated/sensing) */
b4xxp_setreg_ra(b4, R_ST_SEL, s->port, A_ST_WR_STA, V_ST_LD_STA);
flush_pci(); /* make sure write hit hardware */
s->span.alarms = DAHDI_ALARM_RED;
s->newalarm = DAHDI_ALARM_RED;
dahdi_alarm_notify(&s->span);
udelay(10);
/* set up the clock control register. Must be done before we activate the interface. */
@@ -1529,9 +1565,13 @@ static void hfc_start_st(struct b4xxp_span *s)
/* start T1 if in NT mode, T3 if in TE mode */
if (s->te_mode) {
s->hfc_timers[HFC_T3] = b4->ticks + 500; /* 500ms wait first time, timer_t3_ms afterward. */
s->hfc_timers[HFC_T3] = b4->ticks + timer_3_ms;
s->hfc_timer_on[HFC_T3] = 1;
s->hfc_timer_on[HFC_T1] = 0;
s->hfc_timers[HFC_T4] = b4->ticks + 1000;
s->hfc_timer_on[HFC_T4] = 1;
if (DBG_ST) {
dev_info(&b4->pdev->dev,
"setting port %d t3 timer to %lu\n",
@@ -1549,17 +1589,6 @@ static void hfc_start_st(struct b4xxp_span *s)
}
}
#if 0 /* TODO: This function is not called anywhere */
static void hfc_stop_st(struct b4xxp_span *s)
{
b4xxp_setreg_ra(s->parent, R_ST_SEL, s->port, A_ST_WR_STA, V_ST_ACT_DEACTIVATE);
s->hfc_timer_on[HFC_T1] = 0;
s->hfc_timer_on[HFC_T2] = 0;
s->hfc_timer_on[HFC_T3] = 0;
}
#endif
/*
* read in the HFC GPIO to determine each port's mode (TE or NT).
* Then, reset and start the port.
@@ -1592,8 +1621,6 @@ static void hfc_init_all_st(struct b4xxp *b4)
dev_info(&b4->pdev->dev,
"Port %d: %s mode\n", i + 1, (nt ? "NT" : "TE"));
hfc_reset_st(s);
hfc_start_st(s);
}
}
@@ -1850,10 +1877,10 @@ static int hdlc_tx_frame(struct b4xxp_span *bspan)
char debugbuf[256];
unsigned long irq_flags;
/* if we're ignoring TE red alarms and we are in alarm, restart the S/T state machine */
if (bspan->te_mode && teignorered && bspan->newalarm == DAHDI_ALARM_RED) {
hfc_force_st_state(b4, bspan->port, 3, 1);
}
/* if we're ignoring TE red alarms and we are in alarm, restart the
* S/T state machine */
if (bspan->te_mode && bspan->newalarm != 0)
hfc_start_st(bspan);
fifo = bspan->fifos[2];
res = dahdi_hdlc_getbuf(bspan->sigchan, buf, &size);
@@ -2341,6 +2368,10 @@ static int b4xxp_spanconfig(struct file *file, struct dahdi_span *span,
if (lc->sync)
b4->spans[lc->sync - 1].sync = (span->offset + 1);
hfc_reset_st(bspan);
if (persistentlayer1)
hfc_start_st(bspan);
b4xxp_reset_span(bspan);
/* call startup() manually here, because DAHDI won't call the startup function unless it receives an IOCTL to do so, and dahdi_cfg doesn't. */
@@ -2475,7 +2506,9 @@ static void init_spans(struct b4xxp *b4)
bspan = &b4->spans[i];
bspan->parent = b4;
bspan->span.spantype = (bspan->te_mode) ? "TE" : "NT";
bspan->span.spantype = (bspan->te_mode)
? SPANTYPE_DIGITAL_BRI_TE
: SPANTYPE_DIGITAL_BRI_NT;
bspan->span.offset = i;
bspan->span.channels = WCB4XXP_CHANNELS_PER_SPAN;
bspan->span.flags = 0;
@@ -3119,6 +3152,7 @@ module_param(vpmsupport, int, S_IRUGO);
module_param(timer_1_ms, int, S_IRUGO | S_IWUSR);
module_param(timer_3_ms, int, S_IRUGO | S_IWUSR);
module_param(companding, charp, S_IRUGO);
module_param(persistentlayer1, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "bitmap: 1=general 2=dtmf 4=regops 8=fops 16=ec 32=st state 64=hdlc 128=alarm");
MODULE_PARM_DESC(spanfilter, "debug filter for spans. bitmap: 1=port 1, 2=port 2, 4=port 3, 8=port 4");

View File

@@ -376,6 +376,7 @@
#define HFC_T1 0
#define HFC_T2 1
#define HFC_T3 2
#define HFC_T4 3
#define MAX_SPANS_PER_CARD 8
@@ -396,8 +397,8 @@ struct b4xxp_span {
unsigned long alarmtimer;
int te_mode; /* 1=TE, 0=NT */
unsigned long hfc_timers[WCB4XXP_CHANNELS_PER_SPAN]; /* T1, T2, T3 */
int hfc_timer_on[WCB4XXP_CHANNELS_PER_SPAN]; /* 1=timer active */
unsigned long hfc_timers[4]; /* T1, T2, T3, Fake T4 */
int hfc_timer_on[4]; /* 1=timer active */
int fifos[WCB4XXP_CHANNELS_PER_SPAN]; /* B1, B2, D <--> host fifo numbers */
/* HDLC controller fields */

View File

@@ -792,12 +792,12 @@ static int t1xxp_software_init(struct t1xxp *wc)
wc->span.channels = 31;
wc->span.deflaw = DAHDI_LAW_ALAW;
wc->span.linecompat = DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4;
wc->span.spantype = "E1";
wc->span.spantype = SPANTYPE_DIGITAL_E1;
} else {
wc->span.channels = 24;
wc->span.deflaw = DAHDI_LAW_MULAW;
wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
wc->span.spantype = "T1";
wc->span.spantype = SPANTYPE_DIGITAL_T1;
}
for (x=0;x<wc->span.channels;x++) {
sprintf(wc->chans[x]->name, "WCT1/%d/%d", wc->num, x + 1);

View File

@@ -14,10 +14,11 @@ ifeq ($(HOTPLUG_FIRMWARE),yes)
EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE
endif
wct4xxp-objs := base.o vpm450m.o $(shell $(src)/../oct612x/octasic-helper objects ../oct612x)
wct4xxp-objs := base.o vpm450m.o ../oct612x/lib.a
ifneq ($(HOTPLUG_FIRMWARE),yes)
wct4xxp-objs += $(FIRM_DIR)/dahdi-fw-oct6114-064.o $(FIRM_DIR)/dahdi-fw-oct6114-128.o $(FIRM_DIR)/dahdi-fw-oct6114-256.o
$(warning WARNING: You are compiling firmware into wct4xxp.ko which is not available under the terms of the GPL. It may be a violation of the GPL to distribute the resulting image since it combines both GPL and non-GPL work. You should consult a lawyer of your own before distributing such an image.)
endif
$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-064.o: $(obj)/base.o

View File

@@ -1,8 +0,0 @@
ifdef KBUILD_EXTMOD
# We only get here on kernels 2.6.0-2.6.9 .
# For newer kernels, Kbuild will be included directly by the kernel
# build system.
include $(src)/Kbuild
else
endif

View File

@@ -9,7 +9,7 @@
* Russ Meyerriecks <rmeyerriecks@digium.com>
*
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
* Copyright (C) 2001-2011, Digium, Inc.
* Copyright (C) 2001-2012, Digium, Inc.
*
* All rights reserved.
*
@@ -119,11 +119,7 @@ struct cpu_workqueue_struct {
*/
struct workqueue_struct {
/* TODO: Find out exactly where the API changed */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
struct cpu_workqueue_struct *cpu_wq;
#else
struct cpu_workqueue_struct cpu_wq[NR_CPUS];
#endif
const char *name;
struct list_head list; /* Empty if single thread */
};
@@ -173,6 +169,15 @@ static inline int t4_queue_work(struct workqueue_struct *wq, struct work_struct
/* #define CONFIG_FORCE_EXTENDED_RESET */
/* #define CONFIG_NOEXTENDED_RESET */
/*
* Uncomment the following definition in order to disable Active-State Power
* Management on the PCIe bridge for PCIe cards. This has been known to work
* around issues where the BIOS enables it on the cards even though the
* platform does not support it.
*
*/
/* #define CONFIG_WCT4XXP_DISABLE_ASPM */
#if defined(CONFIG_FORCE_EXTENDED_RESET) && defined(CONFIG_NOEXTENDED_RESET)
#error "You cannot define both CONFIG_FORCE_EXTENDED_RESET and " \
"CONFIG_NOEXTENDED_RESET."
@@ -378,9 +383,14 @@ struct t4 {
struct spi_state st;
};
static inline bool is_pcie(const struct t4 *wc)
{
return (wc->devtype->flags & FLAG_EXPRESS) > 0;
}
static inline bool has_e1_span(const struct t4 *wc)
{
return (wc->t1e1) != 0;
return (wc->t1e1 > 0);
}
static inline bool is_octal(const struct t4 *wc)
@@ -426,6 +436,7 @@ static const struct dahdi_echocan_ops vpm_ec_ops = {
#endif
static void __set_clear(struct t4 *wc, int span);
static int _t4_startup(struct file *file, struct dahdi_span *span);
static int t4_startup(struct file *file, struct dahdi_span *span);
static int t4_shutdown(struct dahdi_span *span);
static int t4_rbsbits(struct dahdi_chan *chan, int bits);
@@ -670,11 +681,12 @@ static unsigned int __t4_framer_in(const struct t4 *wc, int unit,
val = ((unit & 0x3) << 8) | (addr & 0xff) | haddr;
writel(val, wc_laddr);
/* readl(wc_version); */
readl(wc_version);
writel(val | WC_LFRMR_CS | WC_LREAD, wc_laddr);
readl(wc_version);
ret = readb(wc_ldata);
writel(val, wc_laddr);
readl(wc_version);
return ret;
}
@@ -700,11 +712,13 @@ static void __t4_framer_out(const struct t4 *wc, int unit, const u8 addr,
val = ((unit & 0x3) << 8) | (addr & 0xff) | haddr;
writel(val, wc_laddr);
readl(wc_version);
writel(value, wc_ldata);
readl(wc_version);
writel(val | WC_LFRMR_CS | WC_LWRITE, wc_laddr);
/* readl(wc_version); */
readl(wc_version);
writel(val, wc_laddr);
readl(wc_version);
}
static void t4_framer_out(struct t4 *wc, int unit,
@@ -1107,6 +1121,7 @@ static int t4_echocan_create(struct dahdi_chan *chan,
int channel;
const struct dahdi_echocan_ops *ops;
const struct dahdi_echocan_features *features;
const bool alaw = (chan->span->deflaw == 2);
if (!vpmsupport || !wc->vpm)
return -ENODEV;
@@ -1127,19 +1142,19 @@ static int t4_echocan_create(struct dahdi_chan *chan,
channel = has_e1_span(wc) ? chan->chanpos : chan->chanpos + 4;
if (wc->vpm) {
if (is_octal(wc))
channel = channel << 3;
else
channel = channel << 2;
channel |= chan->span->offset;
if (debug & DEBUG_ECHOCAN)
dev_notice(&wc->dev->dev, "echocan: Card is %d, "
"Channel is %d, Span is %d, offset is %d "
"length %d\n", wc->num, chan->chanpos,
chan->span->offset, channel, ecp->tap_length);
vpm450m_setec(wc->vpm, channel, ecp->tap_length);
if (is_octal(wc))
channel = channel << 3;
else
channel = channel << 2;
channel |= chan->span->offset;
if (debug & DEBUG_ECHOCAN) {
dev_notice(&wc->dev->dev,
"echocan: Card is %d, Channel is %d, Span is %d, offset is %d length %d\n",
wc->num, chan->chanpos, chan->span->offset,
channel, ecp->tap_length);
}
vpm450m_set_alaw_companding(wc->vpm, channel, alaw);
vpm450m_setec(wc->vpm, channel, ecp->tap_length);
return 0;
}
@@ -1148,23 +1163,23 @@ static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec
struct t4 *wc = chan->pvt;
int channel;
memset(ec, 0, sizeof(*ec));
if (!wc->vpm)
return;
memset(ec, 0, sizeof(*ec));
channel = has_e1_span(wc) ? chan->chanpos : chan->chanpos + 4;
if (wc->vpm) {
if (is_octal(wc))
channel = channel << 3;
else
channel = channel << 2;
channel |= chan->span->offset;
if (debug & DEBUG_ECHOCAN)
dev_notice(&wc->dev->dev, "echocan: Card is %d, "
"Channel is %d, Span is %d, offset is %d "
"length 0\n", wc->num, chan->chanpos,
chan->span->offset, channel);
vpm450m_setec(wc->vpm, channel, 0);
if (is_octal(wc))
channel = channel << 3;
else
channel = channel << 2;
channel |= chan->span->offset;
if (debug & DEBUG_ECHOCAN) {
dev_notice(&wc->dev->dev,
"echocan: Card is %d, Channel is %d, Span is %d, offset is %d length 0\n",
wc->num, chan->chanpos, chan->span->offset, channel);
}
vpm450m_setec(wc->vpm, channel, 0);
}
#endif
@@ -1222,9 +1237,11 @@ static int t4_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long dat
else
clear_bit(chan->chanpos - 1, &ts->dtmfmutemask);
channel = (chan->chanpos) << 3;
if (!has_e1_span(wc))
channel += (4 << 3);
channel = has_e1_span(wc) ? chan->chanpos : chan->chanpos + 4;
if (is_octal(wc))
channel = channel << 3;
else
channel = channel << 2;
channel |= chan->span->offset;
vpm450m_setdtmf(wc->vpm, channel, j & DAHDI_TONEDETECT_ON,
j & DAHDI_TONEDETECT_MUTE);
@@ -1680,7 +1697,7 @@ static void t4_chan_set_sigcap(struct dahdi_span *span, int x)
}
static int
t4_spanconfig(struct file *file, struct dahdi_span *span,
_t4_spanconfig(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc)
{
int i;
@@ -1720,13 +1737,36 @@ t4_spanconfig(struct file *file, struct dahdi_span *span,
/* If we're already running, then go ahead and apply the changes */
if (span->flags & DAHDI_FLAG_RUNNING)
return t4_startup(file, span);
return _t4_startup(file, span);
if (debug)
dev_info(&wc->dev->dev, "Done with spanconfig!\n");
return 0;
}
static int
t4_spanconfig(struct file *file, struct dahdi_span *span,
struct dahdi_lineconfig *lc)
{
int ret;
struct dahdi_device *const ddev = span->parent;
struct dahdi_span *s;
ret = _t4_spanconfig(file, span, lc);
/* Make sure all the spans have a basic configuration in case they are
* not all specified in the configuration files. */
lc->sync = 0;
list_for_each_entry(s, &ddev->spans, device_node) {
WARN_ON(!s->channels);
if (!s->channels)
continue;
if (!s->chans[0]->sigcap)
_t4_spanconfig(file, s, lc);
}
return ret;
}
static int
t4_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
{
@@ -2020,7 +2060,7 @@ static void t4_span_assigned(struct dahdi_span *span)
/* We use this to make sure all the spans are assigned before
* running the serial setup. */
list_for_each_entry(pos, &wc->ddev->spans, device_node) {
if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags))
if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &pos->flags))
++unassigned_spans;
}
@@ -2076,6 +2116,8 @@ static int t4_alloc_channels(struct t4 *wc, struct t4_span *ts,
for (i = 0; i < ARRAY_SIZE(ts->chans); ++i) {
kfree(ts->chans[i]);
kfree(ts->ec[i]);
ts->chans[i] = NULL;
ts->ec[i] = NULL;
}
ts->linemode = linemode;
@@ -2115,13 +2157,13 @@ static void t4_init_one_span(struct t4 *wc, struct t4_span *ts)
switch (ts->linemode) {
case T1:
ts->span.spantype = "T1";
ts->span.spantype = SPANTYPE_DIGITAL_T1;
break;
case E1:
ts->span.spantype = "E1";
ts->span.spantype = SPANTYPE_DIGITAL_E1;
break;
case J1:
ts->span.spantype = "J1";
ts->span.spantype = SPANTYPE_DIGITAL_J1;
break;
}
@@ -2170,40 +2212,53 @@ static void t4_init_one_span(struct t4 *wc, struct t4_span *ts)
/**
* t4_set_linemode - Allows user space to change the linemode before spans are assigned.
* @span: span on which to change the linemode.
* @linemode: Textual description of the new linemode.
* @linemode: A value from enumerated spantypes
*
* This callback is used to override the E1/T1 mode jumper settings and set
* the linemode on for each span. Called when the "spantype" attribute
* is written in sysfs under the dahdi_device.
*
*/
static int t4_set_linemode(struct dahdi_span *span, const char *linemode)
static int t4_set_linemode(struct dahdi_span *span, enum spantypes linemode)
{
struct t4_span *ts = container_of(span, struct t4_span, span);
struct t4 *wc = ts->owner;
int res = 0;
enum linemode mode;
const char *old_name;
static DEFINE_MUTEX(linemode_lock);
dev_dbg(&wc->dev->dev, "Setting '%s' to '%s'\n", span->name, linemode);
dev_dbg(&wc->dev->dev, "Setting '%s' to '%s'\n", span->name,
dahdi_spantype2str(linemode));
if (!strcasecmp(span->spantype, linemode))
if (span->spantype == linemode)
return 0;
if (!strcasecmp(linemode, "t1")) {
/* Do not allow the t1e1 member to be changed by multiple threads. */
mutex_lock(&linemode_lock);
old_name = dahdi_spantype2str(span->spantype);
switch (linemode) {
case SPANTYPE_DIGITAL_T1:
dev_info(&wc->dev->dev,
"Changing from %s to T1 line mode.\n", span->spantype);
"Changing from %s to T1 line mode.\n", old_name);
mode = T1;
} else if (!strcasecmp(linemode, "e1")) {
wc->t1e1 &= ~(1 << span->offset);
break;
case SPANTYPE_DIGITAL_E1:
dev_info(&wc->dev->dev,
"Changing from %s to E1 line mode.\n", span->spantype);
"Changing from %s to E1 line mode.\n", old_name);
mode = E1;
} else if (!strcasecmp(linemode, "j1")) {
wc->t1e1 |= (1 << span->offset);
break;
case SPANTYPE_DIGITAL_J1:
dev_info(&wc->dev->dev,
"Changing from %s to J1 line mode.\n", span->spantype);
"Changing from %s to J1 line mode.\n", old_name);
mode = J1;
} else {
wc->t1e1 &= ~(1 << span->offset);
break;
default:
dev_err(&wc->dev->dev,
"'%s' is an unknown linemode.\n", linemode);
"Got invalid linemode %d from dahdi\n", linemode);
res = -EINVAL;
}
@@ -2213,6 +2268,7 @@ static int t4_set_linemode(struct dahdi_span *span, const char *linemode)
dahdi_init_span(span);
}
mutex_unlock(&linemode_lock);
return res;
}
@@ -2280,13 +2336,13 @@ static void init_spans(struct t4 *wc)
"T%dXXP (PCI) Card %d Span %d", wc->numspans, wc->num, x+1);
switch (ts->linemode) {
case T1:
ts->span.spantype = "T1";
ts->span.spantype = SPANTYPE_DIGITAL_T1;
break;
case E1:
ts->span.spantype = "E1";
ts->span.spantype = SPANTYPE_DIGITAL_E1;
break;
case J1:
ts->span.spantype = "J1";
ts->span.spantype = SPANTYPE_DIGITAL_J1;
break;
}
@@ -2400,7 +2456,6 @@ static void __t4_set_sclk_src(struct t4 *wc, int mode, int master, int slave)
__t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18))
static ssize_t t4_timing_master_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -2431,13 +2486,6 @@ static void remove_sysfs_files(struct t4 *wc)
&dev_attr_timing_master);
}
#else
static inline void create_sysfs_files(struct t4 *wc) { return; }
static inline void remove_sysfs_files(struct t4 *wc) { return; }
#endif /* LINUX_KERNEL > 2.6.18 */
static inline void __t4_update_timing(struct t4 *wc)
{
int i;
@@ -2819,7 +2867,7 @@ static int t4_check_for_interrupts(struct t4 *wc)
return 0;
}
static int t4_startup(struct file *file, struct dahdi_span *span)
static int _t4_startup(struct file *file, struct dahdi_span *span)
{
#ifdef SUPPORT_GEN1
int i;
@@ -2952,6 +3000,21 @@ static int t4_startup(struct file *file, struct dahdi_span *span)
return 0;
}
static int t4_startup(struct file *file, struct dahdi_span *span)
{
int ret;
struct dahdi_device *const ddev = span->parent;
struct dahdi_span *s;
ret = _t4_startup(file, span);
list_for_each_entry(s, &ddev->spans, device_node) {
if (!test_bit(DAHDI_FLAGBIT_RUNNING, &s->flags)) {
_t4_startup(file, s);
}
}
return ret;
}
#ifdef SUPPORT_GEN1
static inline void e1_check(struct t4 *wc, int span, int val)
{
@@ -3627,7 +3690,7 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
}
if (!ts->span.alarms) {
if ((isr3 & 0x3) || (isr4 & 0xc0))
ts->span.timingslips++;
ts->span.count.timingslips++;
if (debug & DEBUG_MAIN) {
if (isr3 & 0x02)
@@ -3648,7 +3711,7 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
wc->numspans, span + 1);
}
} else
ts->span.timingslips = 0;
ts->span.count.timingslips = 0;
spin_lock_irqsave(&wc->reglock, flags);
/* HDLC controller checks - receive side */
@@ -3767,7 +3830,7 @@ static inline void t4_framer_interrupt(struct t4 *wc, int span)
}
#ifdef SUPPORT_GEN1
DAHDI_IRQ_HANDLER(t4_interrupt)
static irqreturn_t _t4_interrupt(int irq, void *dev_id)
{
struct t4 *wc = dev_id;
unsigned long flags;
@@ -3835,6 +3898,16 @@ DAHDI_IRQ_HANDLER(t4_interrupt)
return IRQ_RETVAL(1);
}
DAHDI_IRQ_HANDLER(t4_interrupt)
{
irqreturn_t ret;
unsigned long flags;
local_irq_save(flags);
ret = _t4_interrupt(irq, dev_id);
local_irq_restore(flags);
return ret;
}
#endif
static int t4_allocate_buffers(struct t4 *wc, int numbufs,
@@ -3952,7 +4025,7 @@ static void t4_isr_bh(unsigned long data)
#endif
}
DAHDI_IRQ_HANDLER(t4_interrupt_gen2)
static irqreturn_t _t4_interrupt_gen2(int irq, void *dev_id)
{
struct t4 *wc = dev_id;
unsigned int status;
@@ -4148,6 +4221,16 @@ out:
return IRQ_RETVAL(1);
}
DAHDI_IRQ_HANDLER(t4_interrupt_gen2)
{
irqreturn_t ret;
unsigned long flags;
local_irq_save(flags);
ret = _t4_interrupt_gen2(irq, dev_id);
local_irq_restore(flags);
return ret;
}
#ifdef SUPPORT_GEN1
static int t4_reset_dma(struct t4 *wc)
{
@@ -4617,12 +4700,6 @@ static int t8_update_firmware(struct t4 *wc, const struct firmware *fw,
const u32 BASE_ADDRESS = 0x00080000;
const u8 *data, *end;
size_t size = 0;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
u32 *pci_state;
pci_state = kzalloc(64 * sizeof(u32), GFP_KERNEL);
if (!pci_state)
return -ENOMEM;
#endif
/* Erase flash */
erase_half(wc);
@@ -4647,11 +4724,7 @@ static int t8_update_firmware(struct t4 *wc, const struct firmware *fw,
/* Reset te820 fpga after loading firmware */
dev_info(&wc->dev->dev, "Firmware load complete. Reseting device.\n");
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
res = pci_save_state(wc->dev, pci_state);
#else
res = pci_save_state(wc->dev);
#endif
if (res)
goto error_exit;
/* Set the fpga reset bits and clobber the remainder of the
@@ -4659,11 +4732,7 @@ static int t8_update_firmware(struct t4 *wc, const struct firmware *fw,
t4_pci_out(wc, WC_LEDS, 0xe0000000);
msleep(1000);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
pci_restore_state(wc->dev, pci_state);
#else
pci_restore_state(wc->dev);
#endif
/* Signal the driver to restart initialization.
* This will back out all initialization so far and
@@ -4671,9 +4740,6 @@ static int t8_update_firmware(struct t4 *wc, const struct firmware *fw,
return -EAGAIN;
error_exit:
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
kfree(pci_state);
#endif
return res;
}
@@ -5072,6 +5138,13 @@ t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
spin_lock_init(&wc->reglock);
wc->devtype = (const struct devtype *)(ent->driver_data);
#ifdef CONFIG_WCT4XXP_DISABLE_ASPM
if (is_pcie(wc)) {
pci_disable_link_state(pdev->bus->self, PCIE_LINK_STATE_L0S |
PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
};
#endif
if (is_octal(wc))
wc->numspans = 8;
else if (wc->devtype->flags & FLAG_2PORT)
@@ -5188,22 +5261,23 @@ t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
#ifdef SUPPORT_GEN1
if (request_irq(pdev->irq, (wc->devtype->flags & FLAG_2NDGEN) ?
t4_interrupt_gen2 : t4_interrupt,
DAHDI_IRQ_SHARED_DISABLED,
DAHDI_IRQ_SHARED,
(wc->numspans == 8) ? "wct8xxp" :
(wc->numspans == 2) ? "wct2xxp" :
"wct4xxp",
wc))
wc)) {
#else
if (!(wc->tspans[0]->spanflags & FLAG_2NDGEN)) {
dev_notice(&wc->dev->dev, "This driver does not "
"support 1st gen modules\n");
free_wc(wc);
return -ENODEV;
}
if (request_irq(pdev->irq, t4_interrupt_gen2, DAHDI_IRQ_SHARED_DISABLED, "t4xxp", wc))
if (!(wc->tspans[0]->spanflags & FLAG_2NDGEN)) {
dev_notice(&wc->dev->dev, "This driver does not "
"support 1st gen modules\n");
free_wc(wc);
return -ENODEV;
}
if (request_irq(pdev->irq, t4_interrupt_gen2,
DAHDI_IRQ_SHARED, "t4xxp", wc)) {
#endif
{
dev_notice(&wc->dev->dev, "t4xxp: Unable to request IRQ %d\n",
dev_notice(&wc->dev->dev, "Unable to request IRQ %d\n",
pdev->irq);
free_wc(wc);
return -EIO;
@@ -5383,13 +5457,11 @@ static DEFINE_PCI_DEVICE_TABLE(t4_pci_tbl) =
{ 0, }
};
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12)
static void _t4_shutdown(struct pci_dev *pdev)
{
struct t4 *wc = pci_get_drvdata(pdev);
t4_hardware_stop(wc);
}
#endif
static int t4_suspend(struct pci_dev *pdev, pm_message_t state)
{
@@ -5400,9 +5472,7 @@ static struct pci_driver t4_driver = {
.name = "wct4xxp",
.probe = t4_init_one_retry,
.remove = __devexit_p(t4_remove_one),
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12)
.shutdown = _t4_shutdown,
#endif
.suspend = t4_suspend,
.id_table = t4_pci_tbl,
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2006 Digium, Inc.
* Copyright (C) 2005-2012 Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
@@ -19,19 +19,20 @@
* this program for more details.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/string.h>
#include <linux/time.h>
#include <linux/version.h>
#include <dahdi/kernel.h>
#include <stdbool.h>
#include "vpm450m.h"
#include "oct6100api/oct6100_api.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
#include <linux/config.h>
#endif
/* API for Octasic access */
UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime)
{
@@ -181,6 +182,7 @@ struct vpm450m {
#define FLAG_DTMF (1 << 0)
#define FLAG_MUTE (1 << 1)
#define FLAG_ECHO (1 << 2)
#define FLAG_ALAW (1 << 3)
static unsigned int tones[] = {
SOUT_DTMF_1,
@@ -220,6 +222,50 @@ static unsigned int tones[] = {
ROUT_G168_1100GB_ON,
};
void vpm450m_set_alaw_companding(struct vpm450m *vpm450m, int channel,
bool alaw)
{
tOCT6100_CHANNEL_MODIFY *modify;
UINT32 ulResult;
UINT32 law_to_use = (alaw) ? cOCT6100_PCM_A_LAW :
cOCT6100_PCM_U_LAW;
if (channel >= ARRAY_SIZE(vpm450m->chanflags)) {
pr_err("Channel out of bounds in %s\n", __func__);
return;
}
/* If we're already in this companding mode, no need to do anything. */
if (alaw == ((vpm450m->chanflags[channel] & FLAG_ALAW) > 0))
return;
modify = kzalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC);
if (!modify) {
pr_notice("Unable to allocate memory for setec!\n");
return;
}
Oct6100ChannelModifyDef(modify);
modify->ulChannelHndl = vpm450m->aulEchoChanHndl[channel];
modify->fTdmConfigModified = TRUE;
modify->TdmConfig.ulSinPcmLaw = law_to_use;
modify->TdmConfig.ulRinPcmLaw = law_to_use;
modify->TdmConfig.ulSoutPcmLaw = law_to_use;
modify->TdmConfig.ulRoutPcmLaw = law_to_use;
ulResult = Oct6100ChannelModify(vpm450m->pApiInstance, modify);
if (ulResult != GENERIC_OK) {
pr_notice("Failed to apply echo can changes on channel %d %d %08x!\n",
vpm450m->aulEchoChanHndl[channel], channel, ulResult);
} else {
pr_info("Changed companding on channel %d to %s.\n", channel,
(alaw) ? "alaw" : "ulaw");
if (alaw)
vpm450m->chanflags[channel] |= FLAG_ALAW;
else
vpm450m->chanflags[channel] &= ~(FLAG_ALAW);
}
kfree(modify);
}
static void vpm450m_setecmode(struct vpm450m *vpm450m, int channel, int mode)
{
tOCT6100_CHANNEL_MODIFY *modify;
@@ -252,6 +298,11 @@ void vpm450m_setdtmf(struct vpm450m *vpm450m, int channel, int detect, int mute)
tOCT6100_CHANNEL_MODIFY *modify;
UINT32 ulResult;
if (channel >= ARRAY_SIZE(vpm450m->chanflags)) {
pr_err("Channel out of bounds in %s\n", __func__);
return;
}
modify = kmalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_KERNEL);
if (!modify) {
printk(KERN_NOTICE "wct4xxp: Unable to allocate memory for setdtmf!\n");
@@ -290,6 +341,11 @@ void vpm450m_setdtmf(struct vpm450m *vpm450m, int channel, int detect, int mute)
void vpm450m_setec(struct vpm450m *vpm450m, int channel, int eclen)
{
if (channel >= ARRAY_SIZE(vpm450m->chanflags)) {
pr_err("Channel out of bounds in %s\n", __func__);
return;
}
if (eclen) {
vpm450m->chanflags[channel] |= FLAG_ECHO;
vpm450m_setecmode(vpm450m, channel, cOCT6100_ECHO_OP_MODE_HT_RESET);
@@ -422,6 +478,7 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
tOCT6100_GET_INSTANCE_SIZE InstanceSize;
tOCT6100_CHANNEL_OPEN *ChannelOpen;
UINT32 ulResult;
const unsigned int mask = (8 == numspans) ? 0x7 : 0x3;
unsigned int sout_stream, rout_stream;
struct vpm450m *vpm450m;
int x,y,law;
@@ -527,10 +584,13 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
* therefore, the lower 2 bits tell us which span this
* timeslot/channel
*/
if (isalaw[x & 0x07])
if (isalaw[x & mask]) {
law = cOCT6100_PCM_A_LAW;
else
vpm450m->chanflags[x] |= FLAG_ALAW;
} else {
law = cOCT6100_PCM_U_LAW;
vpm450m->chanflags[x] &= ~(FLAG_ALAW);
}
Oct6100ChannelOpenDef(ChannelOpen);
ChannelOpen->pulChannelHndl = &vpm450m->aulEchoChanHndl[x];
ChannelOpen->ulUserChanId = x;

View File

@@ -39,5 +39,7 @@ void vpm450m_setdtmf(struct vpm450m *instance, int channel, int dtmfdetect, int
int vpm450m_checkirq(struct vpm450m *vpm450m);
int vpm450m_getdtmf(struct vpm450m *vpm450m, int *channel, int *tone, int *start);
void release_vpm450m(struct vpm450m *instance);
void vpm450m_set_alaw_companding(struct vpm450m *vpm450m,
int channel, bool alaw);
#endif

View File

@@ -1,7 +0,0 @@
ifdef KBUILD_EXTMOD
# We only get here on kernels 2.6.0-2.6.9 .
# For newer kernels, Kbuild will be included directly by the kernel
# build system.
include $(src)/Kbuild
else
endif

View File

@@ -1,6 +1,6 @@
/* Wildcard TC400B Driver
*
* Copyright (C) 2006-2010, Digium, Inc.
* Copyright (C) 2006-2012, Digium, Inc.
*
* All rights reserved.
*
@@ -42,11 +42,7 @@
#include "dahdi/kernel.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
#include <asm/io.h>
#else
#include <linux/io.h>
#endif
/* COMPILE TIME OPTIONS =================================================== */
@@ -73,13 +69,6 @@
dev_info(&(wc)->pdev->dev, _fmt, ## _args); \
} \
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
/* also added in RHEL kernels with the OpenInfiniband backport: */
#if LINUX_VERSION_CODE != KERNEL_VERSION(2, 6, 9) || !defined(DEFINE_SPINLOCK)
typedef unsigned gfp_t; /* Added in 2.6.14 */
#endif
#endif
/* define CONFIG_WCTC4XXP_POLLING to operate in a pure polling mode. This is
* was placed in as a debugging tool for a particluar system that wasn't
@@ -877,6 +866,7 @@ wctc4xxp_initialize_descriptor_ring(struct pci_dev *pdev,
memset(dr->desc, 0, (sizeof(*d) + dr->padding) * DRING_SIZE);
for (i = 0; i < DRING_SIZE; ++i) {
d = wctc4xxp_descriptor(dr, i);
memset(d, 0, sizeof(*d));
d->des1 = cpu_to_le32(des1);
}

View File

@@ -1,6 +0,0 @@
ifdef KBUILD_EXTMOD
# We only get here on kernels 2.6.0-2.6.9 .
# For newer kernels, Kbuild will be included directly by the kernel
# build system.
include $(src)/Kbuild
endif

View File

@@ -7,7 +7,7 @@
* Support for Hx8 by Andrew Kohlsmith <akohlsmith@mixdown.ca> and Matthew
* Fredrickson <creslin@digium.com>
*
* Copyright (C) 2005 - 2011 Digium, Inc.
* Copyright (C) 2005 - 2012 Digium, Inc.
* All rights reserved.
*
* Sections for QRV cards written by Jim Dixon <jim@lambdatel.com>
@@ -191,6 +191,11 @@ static const struct wctdm_desc wcaex410 = { "Wildcard AEX410", FLAG_EXPRESS, 4 }
static const struct wctdm_desc wcha80000 = { "HA8-0000", 0, 8 };
static const struct wctdm_desc wchb80000 = { "HB8-0000", FLAG_EXPRESS, 8 };
static inline bool is_pcie(const struct wctdm *wc)
{
return (wc->desc->flags & FLAG_EXPRESS) > 0;
}
/**
* Returns true if the card is one of the Hybrid Digital Analog Cards.
*/
@@ -1068,9 +1073,22 @@ wctdm_isr_getreg(struct wctdm *wc, struct wctdm_module *const mod, u8 address)
list_add(&cmd->node, &mod->pending_cmds);
}
/* Must be called with wc.reglock held and local interrupts disabled */
static inline void
wctdm_setreg_intr(struct wctdm *wc, struct wctdm_module *mod,
int addr, int val);
wctdm_setreg_intr(struct wctdm *wc, struct wctdm_module *mod, int addr, int val)
{
struct wctdm_cmd *cmd;
cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
if (unlikely(!cmd))
return;
cmd->complete = NULL;
cmd->cmd = CMD_WR(addr, val);
list_add_tail(&cmd->node, &mod->pending_cmds);
}
static void cmd_checkisr(struct wctdm *wc, struct wctdm_module *const mod)
{
@@ -1215,22 +1233,6 @@ static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char *sframe)
spin_unlock(&wc->reglock);
}
/* Must be called with wc.reglock held and local interrupts disabled */
static inline void
wctdm_setreg_intr(struct wctdm *wc, struct wctdm_module *mod, int addr, int val)
{
struct wctdm_cmd *cmd;
cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
if (unlikely(!cmd))
return;
cmd->complete = NULL;
cmd->cmd = CMD_WR(addr, val);
list_add_tail(&cmd->node, &mod->pending_cmds);
}
int wctdm_setreg(struct wctdm *wc, struct wctdm_module *mod, int addr, int val)
{
struct wctdm_cmd *cmd;
@@ -1831,19 +1833,22 @@ static void wctdm_qrvdri_check_hook(struct wctdm *wc, int card)
static inline bool is_fxo_ringing(const struct fxo *const fxo)
{
return ((fxo->hook_ring_shadow & 0x60) &&
(fxo->battery_state == BATTERY_PRESENT));
((fxo->battery_state == BATTERY_PRESENT) ||
(fxo->battery_state == BATTERY_DEBOUNCING_LOST)));
}
static inline bool is_fxo_ringing_positive(const struct fxo *const fxo)
{
return (((fxo->hook_ring_shadow & 0x60) == 0x20) &&
(fxo->battery_state == BATTERY_PRESENT));
((fxo->battery_state == BATTERY_PRESENT) ||
(fxo->battery_state == BATTERY_DEBOUNCING_LOST)));
}
static inline bool is_fxo_ringing_negative(const struct fxo *const fxo)
{
return (((fxo->hook_ring_shadow & 0x60) == 0x40) &&
(fxo->battery_state == BATTERY_PRESENT));
((fxo->battery_state == BATTERY_PRESENT) ||
(fxo->battery_state == BATTERY_DEBOUNCING_LOST)));
}
static inline void set_ring(struct fxo *fxo, enum ring_detector_state new)
@@ -1854,19 +1859,21 @@ static inline void set_ring(struct fxo *fxo, enum ring_detector_state new)
static void wctdm_fxo_ring_detect(struct wctdm *wc, struct wctdm_module *mod)
{
struct fxo *const fxo = &mod->mod.fxo;
static const unsigned int POLARITY_CHANGES_NEEDED = 2;
/* Look for ring status bits (Ring Detect Signal Negative and Ring
* Detect Signal Positive) to transition back and forth some number of
* times to indicate that a ring is occurring. Provide some number of
* samples to allow for the transitions to occur before giving up.
* NOTE: neon mwi voltages will trigger one of these bits to go active
* but not to have transitions between the two bits (i.e. no negative
* to positive or positive to negative traversals) */
* Detect Signal Positive) to transition back and forth
* POLARITY_CHANGES_NEEDED times to indicate that a ring is occurring.
* Provide some number of samples to allow for the transitions to occur
* before giving up. NOTE: neon mwi voltages will trigger one of these
* bits to go active but not to have transitions between the two bits
* (i.e. no negative to positive or positive to negative traversals) */
switch (fxo->ring_state) {
case DEBOUNCING_RINGING_POSITIVE:
if (is_fxo_ringing_negative(fxo)) {
if (++fxo->ring_polarity_change_count > 4) {
if (++fxo->ring_polarity_change_count >
POLARITY_CHANGES_NEEDED) {
mod_hooksig(wc, mod, DAHDI_RXSIG_RING);
set_ring(fxo, RINGING);
if (debug) {
@@ -1884,7 +1891,8 @@ static void wctdm_fxo_ring_detect(struct wctdm *wc, struct wctdm_module *mod)
break;
case DEBOUNCING_RINGING_NEGATIVE:
if (is_fxo_ringing_positive(fxo)) {
if (++fxo->ring_polarity_change_count > 4) {
if (++fxo->ring_polarity_change_count >
POLARITY_CHANGES_NEEDED) {
mod_hooksig(wc, mod, DAHDI_RXSIG_RING);
set_ring(fxo, RINGING);
if (debug) {
@@ -1904,7 +1912,7 @@ static void wctdm_fxo_ring_detect(struct wctdm *wc, struct wctdm_module *mod)
if (!is_fxo_ringing(fxo)) {
set_ring(fxo, DEBOUNCING_RINGOFF);
fxo->ringdebounce_timer =
wc->framecount + ringdebounce / 2;
wc->framecount + ringdebounce / 8;
}
break;
case DEBOUNCING_RINGOFF:
@@ -1953,19 +1961,26 @@ wctdm_check_battery_lost(struct wctdm *wc, struct wctdm_module *const mod)
battery present or unknown, debounce timer (going to battery lost)
*/
switch (fxo->battery_state) {
case BATTERY_DEBOUNCING_PRESENT_ALARM:
fxo->battery_state = BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM;
fxo->battdebounce_timer = wc->framecount + battdebounce;
break;
case BATTERY_DEBOUNCING_PRESENT:
/* we were going to BATTERY_PRESENT, but
* battery was lost again. */
fxo->battery_state = BATTERY_LOST;
break;
case BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM:
fxo->battery_state = BATTERY_DEBOUNCING_LOST_ALARM;
fxo->battdebounce_timer = wc->framecount +
battalarm - battdebounce;
break;
case BATTERY_UNKNOWN:
mod_hooksig(wc, mod, DAHDI_RXSIG_ONHOOK);
case BATTERY_DEBOUNCING_PRESENT_ALARM: /* intentional drop through */
case BATTERY_PRESENT:
fxo->battery_state = BATTERY_DEBOUNCING_LOST;
fxo->battdebounce_timer = wc->framecount + battdebounce;
break;
case BATTERY_DEBOUNCING_LOST:
case BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM:
case BATTERY_DEBOUNCING_LOST: /* Intentional drop through */
if (time_after(wc->framecount, fxo->battdebounce_timer)) {
if (debug) {
dev_info(&wc->vb.pdev->dev,
@@ -2014,8 +2029,9 @@ wctdm_check_battery_present(struct wctdm *wc, struct wctdm_module *const mod)
struct fxo *const fxo = &mod->mod.fxo;
switch (fxo->battery_state) {
case BATTERY_DEBOUNCING_PRESENT:
if (time_after(jiffies, fxo->battdebounce_timer)) {
case BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM:
case BATTERY_DEBOUNCING_PRESENT: /* intentional drop through */
if (time_after(wc->framecount, fxo->battdebounce_timer)) {
if (debug) {
dev_info(&wc->vb.pdev->dev,
"BATTERY on %d/%d (%s)!\n",
@@ -2040,12 +2056,12 @@ wctdm_check_battery_present(struct wctdm *wc, struct wctdm_module *const mod)
* of its time period has already passed while
* debouncing occurred */
fxo->battery_state = BATTERY_DEBOUNCING_PRESENT_ALARM;
fxo->battdebounce_timer = jiffies +
msecs_to_jiffies(battalarm - battdebounce);
fxo->battdebounce_timer = wc->framecount +
battalarm - battdebounce;
}
break;
case BATTERY_DEBOUNCING_PRESENT_ALARM:
if (time_after(jiffies, fxo->battdebounce_timer)) {
if (time_after(wc->framecount, fxo->battdebounce_timer)) {
fxo->battery_state = BATTERY_PRESENT;
dahdi_alarm_channel(get_dahdi_chan(wc, mod),
DAHDI_ALARM_NONE);
@@ -2053,18 +2069,23 @@ wctdm_check_battery_present(struct wctdm *wc, struct wctdm_module *const mod)
break;
case BATTERY_PRESENT:
break;
case BATTERY_DEBOUNCING_LOST_ALARM:
fxo->battery_state = BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM;
fxo->battdebounce_timer = wc->framecount + battdebounce;
break;
case BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM:
fxo->battery_state = BATTERY_DEBOUNCING_PRESENT_ALARM;
fxo->battdebounce_timer = wc->framecount +
battalarm - battdebounce;
break;
case BATTERY_DEBOUNCING_LOST:
/* we were going to BATTERY_LOST, but battery appeared again,
* so clear the debounce timer */
fxo->battery_state = BATTERY_PRESENT;
break;
case BATTERY_UNKNOWN:
mod_hooksig(wc, mod, DAHDI_RXSIG_OFFHOOK);
case BATTERY_LOST: /* intentional drop through */
case BATTERY_DEBOUNCING_LOST_ALARM:
fxo->battery_state = BATTERY_DEBOUNCING_PRESENT;
fxo->battdebounce_timer = jiffies +
msecs_to_jiffies(battdebounce);
fxo->battdebounce_timer = wc->framecount + battdebounce;
break;
}
}
@@ -3727,14 +3748,15 @@ static int wctdm_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long
if (((fxs->lasttxhook & SLIC_LF_SETMASK) == SLIC_LF_ACTIVE_FWD) ||
((fxs->lasttxhook & SLIC_LF_SETMASK) == SLIC_LF_ACTIVE_REV)) {
int res;
x = set_lasttxhook_interruptible(wc, fxs,
res = set_lasttxhook_interruptible(wc, fxs,
(POLARITY_XOR(fxs) ?
SLIC_LF_OHTRAN_REV : SLIC_LF_OHTRAN_FWD),
&mod->sethook);
if (debug & DEBUG_CARD) {
if (x) {
if (res) {
dev_info(&wc->vb.pdev->dev,
"Channel %d TIMEOUT: "
"OnHookTransfer start\n",
@@ -4517,10 +4539,11 @@ wctdm_init_span(struct wctdm *wc, int spanno, int chanoffset, int chancount,
s->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4;
s->span.linecompat |= DAHDI_CONFIG_ESF | DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4;
s->span.linecompat |= DAHDI_CONFIG_NTTE | DAHDI_CONFIG_TERM;
s->span.spantype = "TE";
s->span.spantype = SPANTYPE_DIGITAL_BRI_TE;
} else {
s->span.ops = &wctdm24xxp_analog_span_ops;
s->span.flags = DAHDI_FLAG_RBS;
s->span.spantype = SPANTYPE_ANALOG_MIXED;
/* analog sigcap handled in fixup_analog_span() */
}
@@ -5678,6 +5701,13 @@ __wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
wc->vb.pdev = pdev;
wc->vb.debug = &debug;
#ifdef CONFIG_VOICEBUS_DISABLE_ASPM
if (is_pcie(wc)) {
pci_disable_link_state(pdev->bus->self, PCIE_LINK_STATE_L0S |
PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
};
#endif
if (is_hx8(wc)) {
wc->vb.ops = &hx8_voicebus_operations;
ret = voicebus_boot_init(&wc->vb, wc->board_name);
@@ -6050,13 +6080,11 @@ static DEFINE_PCI_DEVICE_TABLE(wctdm_pci_tbl) = {
{ 0 }
};
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12)
static void wctdm_shutdown(struct pci_dev *pdev)
{
struct wctdm *wc = pci_get_drvdata(pdev);
voicebus_quiesce(&wc->vb);
}
#endif
MODULE_DEVICE_TABLE(pci, wctdm_pci_tbl);
@@ -6069,9 +6097,7 @@ static struct pci_driver wctdm_driver = {
.name = "wctdm24xxp",
.probe = wctdm_init_one,
.remove = __devexit_p(wctdm_remove_one),
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12)
.shutdown = wctdm_shutdown,
#endif
.suspend = wctdm_suspend,
.id_table = wctdm_pci_tbl,
};

View File

@@ -106,9 +106,11 @@ struct calregs {
enum battery_state {
BATTERY_UNKNOWN = 0,
BATTERY_DEBOUNCING_PRESENT,
BATTERY_DEBOUNCING_PRESENT_FROM_LOST_ALARM,
BATTERY_DEBOUNCING_PRESENT_ALARM,
BATTERY_PRESENT,
BATTERY_DEBOUNCING_LOST,
BATTERY_DEBOUNCING_LOST_FROM_PRESENT_ALARM,
BATTERY_DEBOUNCING_LOST_ALARM,
BATTERY_LOST,
};

View File

@@ -2150,7 +2150,9 @@ static int b400m_set_ntte(struct b400m_span *bspan, int te_mode, int term_on)
int all_modes = 0, all_terms = 0;
int i;
bspan->wspan->span.spantype = (te_mode > 0) ? "TE" : "NT";
bspan->wspan->span.spantype = (te_mode > 0)
? SPANTYPE_DIGITAL_BRI_TE
: SPANTYPE_DIGITAL_BRI_NT;
bspan->te_mode = te_mode;
bspan->term_on = term_on;

View File

@@ -1000,12 +1000,12 @@ static int t1xxp_software_init(struct t1 *wc)
else
wc->span.channels = 31;
wc->span.deflaw = DAHDI_LAW_ALAW;
wc->span.spantype = "E1";
wc->span.spantype = SPANTYPE_DIGITAL_E1;
wc->span.linecompat = DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4;
} else {
wc->span.channels = 24;
wc->span.deflaw = DAHDI_LAW_MULAW;
wc->span.spantype = "T1";
wc->span.spantype = SPANTYPE_DIGITAL_T1;
wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
}
wc->span.chans = wc->chans;

View File

@@ -1,6 +0,0 @@
ifdef KBUILD_EXTMOD
# We only get here on kernels 2.6.0-2.6.9 .
# For newer kernels, Kbuild will be included directly by the kernel
# build system.
include $(src)/Kbuild
endif

View File

@@ -8,7 +8,7 @@
* Matthew Fredrickson <creslin@digium.com>
* William Meadows <wmeadows@digium.com>
*
* Copyright (C) 2007-2011, Digium, Inc.
* Copyright (C) 2007-2012, Digium, Inc.
*
* All rights reserved.
*
@@ -27,6 +27,8 @@
* this program for more details.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/module.h>
@@ -55,18 +57,14 @@
#error VOICEBUS_SFRAME_SIZE != SFRAME_SIZE
#endif
#ifndef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#endif
static int debug;
static int j1mode = 0;
static int j1mode = -1;
static int alarmdebounce = 2500; /* LOF/LFA def to 2.5s AT&T TR54016*/
static int losalarmdebounce = 2500; /* LOS def to 2.5s AT&T TR54016*/
static int aisalarmdebounce = 2500; /* AIS(blue) def to 2.5s AT&T TR54016*/
static int yelalarmdebounce = 500; /* RAI(yellow) def to 0.5s AT&T devguide */
static int t1e1override = -1; /* deprecated */
static char *default_linemode = "auto"; /* 'auto', 'e1', or 't1' */
static char *default_linemode = "auto"; /* 'auto', 'e1', 't1', or 'j1' */
static int latency = VOICEBUS_DEFAULT_LATENCY;
static unsigned int max_latency = VOICEBUS_DEFAULT_MAXLATENCY;
static int vpmsupport = 1;
@@ -99,6 +97,11 @@ static const struct t1_desc te120p = {"Wildcard TE120P"};
static const struct t1_desc te122 = {"Wildcard TE122"};
static const struct t1_desc te121 = {"Wildcard TE121"};
static inline bool is_pcie(const struct t1 *t1)
{
return (0 == strcmp(t1->variety, te121.name));
}
/* names of HWEC modules */
static const char *vpmadt032_name = "VPMADT032";
static const char *vpmoct_name = "VPMOCT032";
@@ -640,21 +643,32 @@ static inline int t1_setreg(struct t1 *wc, int addr, int val)
return 0;
}
static int t1_getreg(struct t1 *wc, int addr)
static void __t1_getreg(struct t1 *wc, int addr, struct command *cmd)
{
struct command *cmd = NULL;
unsigned long ret;
unsigned long flags;
might_sleep();
cmd = get_free_cmd(wc);
if (!cmd)
return -ENOMEM;
cmd->address = addr;
cmd->data = 0x00;
cmd->flags = __CMD_RD;
submit_cmd(wc, cmd);
}
static int __t1_getresult(struct t1 *wc, struct command *cmd)
{
int ret;
unsigned long flags;
might_sleep();
if (test_bit(IOERROR, &wc->bit_flags)) {
spin_lock_irqsave(&wc->reglock, flags);
list_del_init(&cmd->node);
spin_unlock_irqrestore(&wc->reglock, flags);
if (printk_ratelimit()) {
dev_warn(&wc->vb.pdev->dev,
"Timeout in %s\n", __func__);
}
return -EIO;
}
ret = wait_for_completion_interruptible_timeout(&cmd->complete, HZ*10);
if (unlikely(!ret)) {
spin_lock_irqsave(&wc->reglock, flags);
@@ -663,13 +677,13 @@ static int t1_getreg(struct t1 *wc, int addr)
* can go ahead and free it right away. */
list_del_init(&cmd->node);
spin_unlock_irqrestore(&wc->reglock, flags);
free_cmd(wc, cmd);
if (-ERESTARTSYS != ret) {
if (printk_ratelimit()) {
dev_warn(&wc->vb.pdev->dev,
"Timeout in %s\n", __func__);
}
ret = -EIO;
set_bit(IOERROR, &wc->bit_flags);
}
return ret;
} else {
@@ -680,15 +694,26 @@ static int t1_getreg(struct t1 *wc, int addr)
ret = wait_for_completion_timeout(&cmd->complete, HZ*2);
WARN_ON(!ret);
ret = cmd->data;
free_cmd(wc, cmd);
return ret;
}
}
ret = cmd->data;
free_cmd(wc, cmd);
return ret;
}
static int t1_getreg(struct t1 *wc, int addr)
{
int res;
struct command *cmd = NULL;
cmd = get_free_cmd(wc);
if (!cmd)
return -ENOMEM;
__t1_getreg(wc, addr, cmd);
res = __t1_getresult(wc, cmd);
free_cmd(wc, cmd);
return res;
}
static void t1_setleds(struct t1 *wc, int leds)
{
struct command *cmd;
@@ -826,6 +851,75 @@ static void free_wc(struct t1 *wc)
kfree(wc);
}
/**
* t1_reset_registers - Put register back to their default values
*
* Since the card does not have an ability to reset just the framer
* specifically, we need to write all the default values to the framer.
*
*/
static void t1_reset_registers(struct t1 *wc)
{
int i;
struct t1_reg {
u8 address;
u8 value;
} __attribute__((packed));
struct t1_reg *reg;
static struct t1_reg DEFAULT_REGS[] = {
{0x00, 0x7d}, {0x01, 0x7d}, {0x02, 0x00}, {0x03, 0x00},
{0x04, 0xfd}, {0x05, 0xff}, {0x06, 0xff}, {0x07, 0xff},
{0x08, 0x05}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
{0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
{0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
{0x14, 0xff}, {0x15, 0xff}, {0x16, 0xff}, {0x17, 0xff},
{0x18, 0xff}, {0x19, 0xff}, {0x1a, 0x00}, {0x1b, 0x00},
{0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
{0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x04},
{0x24, 0x00}, {0x25, 0x05}, {0x26, 0x7b}, {0x27, 0x03},
{0x28, 0x40}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
{0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
{0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
{0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x80},
{0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x20}, {0x3b, 0x00},
{0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x0a}, {0x3f, 0x00},
{0x40, 0x04}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
{0x44, 0x30}, {0x45, 0x00}, {0x46, 0xc0}, {0x47, 0xff},
{0x48, 0x00}, {0x49, 0x1c}, {0x4a, 0x05}, {0x4b, 0x03},
{0x4c, 0xa3}, {0x4d, 0x28}, {0x4e, 0x00}, {0x4f, 0xc0},
{0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
{0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
{0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
{0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
{0x60, 0x00}, {0x61, 0x20}, {0x62, 0x00}, {0x63, 0x00},
{0x64, 0x5a}, {0x65, 0x02}, {0x66, 0x00}, {0x67, 0x00},
{0x68, 0x10}, {0x69, 0x09}, {0x6a, 0x00}, {0x6b, 0x03},
{0x6c, 0x00}, {0x6d, 0xc0}, {0x6e, 0x40}, {0x6f, 0x00},
{0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
{0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
{0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
{0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
{0x80, 0x00}, {0x81, 0x22}, {0x82, 0x65}, {0x83, 0x35},
{0x84, 0x31}, {0x85, 0x60}, {0x86, 0x03}, {0x87, 0x00},
{0x88, 0x00}, {0x89, 0x00}, {0x8a, 0x00}, {0x8b, 0x00},
{0x8c, 0x00}, {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0x00},
{0x90, 0x00}, {0x91, 0x00}, {0x92, 0x00}, {0x93, 0x18},
{0x94, 0xfb}, {0x95, 0x0b}, {0x96, 0x00}, {0x97, 0x0b},
{0x98, 0xdb}, {0x99, 0xdf}, {0x9a, 0x48}, {0x9b, 0x00},
{0x9c, 0x3f}, {0x9d, 0x3f}, {0x9e, 0x77}, {0x9f, 0x77},
{0xa0, 0x00}, {0xa1, 0xff}, {0xa2, 0xff}, {0xa3, 0xff},
{0xa4, 0x00}, {0xa5, 0x00}, {0xa6, 0x00}, {0xa7, 0x00},
{0xa8, 0x00}
};
for (i = 0; i < ARRAY_SIZE(DEFAULT_REGS); ++i) {
reg = &DEFAULT_REGS[i];
t1_setreg(wc, reg->address, reg->value);
}
/* Flush previous writes. */
t1_getreg(wc, 0x1d);
}
static void t4_serial_setup(struct t1 *wc)
{
t1_setreg(wc, 0x85, 0xe0); /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0 */
@@ -878,7 +972,8 @@ static void t1_configure_t1(struct t1 *wc, int lineconfig, int txlevel)
fmr1 = 0x9e; /* FMR1: Mode 0, T1 mode, CRC on for ESF, 2.048 Mhz system data rate, no XAIS */
fmr2 = 0x20; /* FMR2: no payload loopback, don't auto yellow alarm */
if (j1mode)
if (SPANTYPE_DIGITAL_J1 == wc->span.spantype)
fmr4 = 0x1c;
else
fmr4 = 0x0c; /* FMR4: Lose sync on 2 out of 5 framing bits, auto resync */
@@ -918,7 +1013,7 @@ static void t1_configure_t1(struct t1 *wc, int lineconfig, int txlevel)
t1_setreg(wc, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */
t1_setreg(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */
if (j1mode)
if (SPANTYPE_DIGITAL_J1 == wc->span.spantype)
t1_setreg(wc, 0x24, 0x80); /* J1 overide */
/* Generate pulse mask for T1 */
@@ -1179,15 +1274,47 @@ static int t1xxp_rbsbits(struct dahdi_chan *chan, int bits)
return 0;
}
static inline void t1_check_sigbits(struct t1 *wc)
static void t1_check_sigbits(struct t1 *wc)
{
struct command_container {
struct command *cmd;
struct list_head node;
unsigned int index;
};
struct command_container *cont;
LIST_HEAD(commands);
int a,i,rxs;
if (!(test_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags)))
return;
if (dahdi_is_e1_span(&wc->span)) {
/* Send out all the commands first. */
for (i = 0; i < 15; i++) {
a = t1_getreg(wc, 0x71 + i);
if (!(wc->span.chans[i+16]->sig & DAHDI_SIG_CLEAR) ||
!(wc->span.chans[i]->sig & DAHDI_SIG_CLEAR)) {
cont = kzalloc(sizeof(*cont), GFP_KERNEL);
if (!cont) {
WARN_ON_ONCE(1);
goto done;
}
cont->cmd = get_free_cmd(wc);
if (!cont->cmd) {
WARN_ON_ONCE(1);
goto done;
}
cont->index = i;
list_add_tail(&cont->node, &commands);
__t1_getreg(wc, 0x71 + i, cont->cmd);
}
}
/* Now check the results */
list_for_each_entry_reverse(cont, &commands, node) {
i = cont->index;
a = __t1_getresult(wc, cont->cmd);
free_cmd(wc, cont->cmd);
cont->cmd = NULL;
if (a > -1) {
/* Get high channel in low bits */
rxs = (a & 0xf);
@@ -1205,8 +1332,29 @@ static inline void t1_check_sigbits(struct t1 *wc)
}
}
} else if (wc->span.lineconfig & DAHDI_CONFIG_D4) {
for (i = 0; i < 24; i+=4) {
a = t1_getreg(wc, 0x70 + (i>>2));
/* First we'll send out the commands */
for (i = 0; i < 24; i += 4) {
cont = kzalloc(sizeof(*cont), GFP_KERNEL);
if (!cont) {
WARN_ON_ONCE(1);
goto done;
}
cont->cmd = get_free_cmd(wc);
if (!cont->cmd) {
WARN_ON_ONCE(1);
goto done;
}
cont->index = i;
list_add_tail(&cont->node, &commands);
__t1_getreg(wc, 0x70 + (i>>2), cont->cmd);
}
/* Now we'll check the results */
list_for_each_entry_reverse(cont, &commands, node) {
i = cont->index;
a = __t1_getresult(wc, cont->cmd);
free_cmd(wc, cont->cmd);
cont->cmd = NULL;
if (a > -1) {
/* Get high channel in low bits */
rxs = (a & 0x3) << 2;
@@ -1236,8 +1384,28 @@ static inline void t1_check_sigbits(struct t1 *wc)
}
}
} else {
for (i = 0; i < 24; i+=2) {
a = t1_getreg(wc, 0x70 + (i>>1));
/* First send out the commands. */
for (i = 0; i < 24; i += 2) {
cont = kzalloc(sizeof(*cont), GFP_KERNEL);
if (!cont) {
WARN_ON_ONCE(1);
goto done;
}
cont->cmd = get_free_cmd(wc);
if (!cont->cmd) {
WARN_ON_ONCE(1);
goto done;
}
cont->index = i;
list_add_tail(&cont->node, &commands);
__t1_getreg(wc, 0x70 + (i>>1), cont->cmd);
}
list_for_each_entry_reverse(cont, &commands, node) {
i = cont->index;
a = __t1_getresult(wc, cont->cmd);
free_cmd(wc, cont->cmd);
cont->cmd = NULL;
if (a > -1) {
/* Get high channel in low bits */
rxs = (a & 0xf);
@@ -1255,6 +1423,21 @@ static inline void t1_check_sigbits(struct t1 *wc)
}
}
}
done:
while (!list_empty(&commands)) {
cont = container_of(commands.next,
struct command_container, node);
if (unlikely(cont->cmd)) {
/* We do not care about the result, let's just wait for
* the rest of the system to finish with it. */
__t1_getresult(wc, cont->cmd);
free_cmd(wc, cont->cmd);
cont->cmd = NULL;
}
list_del(&cont->node);
kfree(cont);
}
return;
}
struct maint_work_struct {
@@ -1841,18 +2024,32 @@ static int t1_software_init(struct t1 *wc, enum linemode type)
memset(chans, 0, sizeof(chans));
memset(ec, 0, sizeof(ec));
if (type == E1) {
switch (type) {
case E1:
wc->span.channels = 31;
wc->span.spantype = "E1";
wc->span.spantype = SPANTYPE_DIGITAL_E1;
wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_HDB3 |
DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4;
wc->span.deflaw = DAHDI_LAW_ALAW;
} else {
break;
case T1:
wc->span.channels = 24;
wc->span.spantype = "T1";
wc->span.spantype = SPANTYPE_DIGITAL_T1;
wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS |
DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
wc->span.deflaw = DAHDI_LAW_MULAW;
break;
case J1:
wc->span.channels = 24;
wc->span.spantype = SPANTYPE_DIGITAL_J1;
wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS |
DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
wc->span.deflaw = DAHDI_LAW_MULAW;
break;
default:
spin_unlock_irqrestore(&wc->reglock, flags);
res = -EINVAL;
goto error_exit;
}
spin_unlock_irqrestore(&wc->reglock, flags);
@@ -1861,7 +2058,7 @@ static int t1_software_init(struct t1 *wc, enum linemode type)
return -ENOMEM;
t1_info(wc, "Setting up global serial parameters for %s\n",
(dahdi_is_e1_span(&wc->span) ? "E1" : "T1"));
dahdi_spantype2str(wc->span.spantype));
t4_serial_setup(wc);
set_bit(DAHDI_FLAGBIT_RBS, &wc->span.flags);
@@ -1895,13 +2092,13 @@ error_exit:
* DAHDI).
*
*/
static int t1xxp_set_linemode(struct dahdi_span *span, const char *linemode)
static int t1xxp_set_linemode(struct dahdi_span *span, enum spantypes linemode)
{
int res;
struct t1 *wc = container_of(span, struct t1, span);
/* We may already be set to the requested type. */
if (!strcasecmp(span->spantype, linemode))
if (span->spantype == linemode)
return 0;
res = t1_wait_for_ready(wc);
@@ -1911,21 +2108,35 @@ static int t1xxp_set_linemode(struct dahdi_span *span, const char *linemode)
/* Stop the processing of the channels since we're going to change
* them. */
clear_bit(INITIALIZED, &wc->bit_flags);
synchronize_irq(wc->vb.pdev->irq);
smp_mb__after_clear_bit();
del_timer_sync(&wc->timer);
flush_workqueue(wc->wq);
if (!strcasecmp(linemode, "t1")) {
t1_reset_registers(wc);
switch (linemode) {
case SPANTYPE_DIGITAL_T1:
dev_info(&wc->vb.pdev->dev,
"Changing from E1 to T1 line mode.\n");
"Changing from %s to T1 line mode.\n",
dahdi_spantype2str(wc->span.spantype));
res = t1_software_init(wc, T1);
} else if (!strcasecmp(linemode, "e1")) {
break;
case SPANTYPE_DIGITAL_E1:
dev_info(&wc->vb.pdev->dev,
"Changing from T1 to E1 line mode.\n");
"Changing from %s to E1 line mode.\n",
dahdi_spantype2str(wc->span.spantype));
res = t1_software_init(wc, E1);
} else {
break;
case SPANTYPE_DIGITAL_J1:
dev_info(&wc->vb.pdev->dev,
"Changing from %s to E1 line mode.\n",
dahdi_spantype2str(wc->span.spantype));
res = t1_software_init(wc, J1);
default:
dev_err(&wc->vb.pdev->dev,
"'%s' is an unknown linemode.\n", linemode);
"Got invalid linemode '%s' from dahdi\n",
dahdi_spantype2str(linemode));
res = -EINVAL;
}
@@ -1962,14 +2173,15 @@ static int t1_hardware_post_init(struct t1 *wc, enum linemode *type)
int x;
/* T1 or E1 */
if (-1 != t1e1override) {
pr_info("t1e1override is deprecated. Please use 'default_linemode'.\n");
*type = (t1e1override) ? E1 : T1;
if ((-1 != t1e1override) || (-1 != j1mode)) {
*type = (t1e1override) ? E1 : (j1mode) ? J1 : T1;
} else {
if (!strcasecmp(default_linemode, "e1")) {
*type = E1;
} else if (!strcasecmp(default_linemode, "t1")) {
*type = T1;
} else if (!strcasecmp(default_linemode, "j1")) {
*type = J1;
} else {
u8 pins;
res = t1_getpins(wc, &pins);
@@ -1978,7 +2190,8 @@ static int t1_hardware_post_init(struct t1 *wc, enum linemode *type)
*type = (pins & 0x01) ? T1 : E1;
}
}
debug_printk(wc, 1, "linemode: %s\n", (*type == T1) ? "T1" : "E1");
debug_printk(wc, 1, "linemode: %s\n", (*type == T1) ? "T1" :
(J1 == *type) ? "J1" : "E1");
/* what version of the FALC are we using? */
reg = t1_setreg(wc, 0x4a, 0xaa);
@@ -2009,19 +2222,41 @@ static int t1_hardware_post_init(struct t1 *wc, enum linemode *type)
return 0;
}
static inline void t1_check_alarms(struct t1 *wc)
static void t1_check_alarms(struct t1 *wc)
{
unsigned char c,d;
int alarms;
int x,j;
unsigned char fmr4; /* must read this always */
struct command *cmds[3];
if (!(test_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags)))
return;
c = t1_getreg(wc, 0x4c);
fmr4 = t1_getreg(wc, 0x20); /* must read this even if we don't use it */
d = t1_getreg(wc, 0x4d);
for (x = 0; x < ARRAY_SIZE(cmds); ++x) {
cmds[x] = get_free_cmd(wc);
if (!cmds[x]) {
WARN_ON(1);
for (x = 0; x < ARRAY_SIZE(cmds); ++x)
free_cmd(wc, cmds[x]);
return;
}
}
/* Since this is voicebus, if we issue all the reads initially and then
* check the results we can save ourselves some time. Otherwise, each
* read will take a minimum of 3ms to go through the complete pipeline.
*/
__t1_getreg(wc, 0x4c, cmds[0]);
__t1_getreg(wc, 0x20, cmds[1]); /* must read this even if not used */
__t1_getreg(wc, 0x4d, cmds[2]);
d = __t1_getresult(wc, cmds[2]);
fmr4 = __t1_getresult(wc, cmds[1]);
c = __t1_getresult(wc, cmds[0]);
for (x=0; x < ARRAY_SIZE(cmds); ++x)
free_cmd(wc, cmds[x]);
/* Assume no alarms */
alarms = 0;
@@ -2053,27 +2288,32 @@ static inline void t1_check_alarms(struct t1 *wc)
/* Detect loopup code if we're not sending one */
if ((!wc->span.mainttimer) && (d & 0x08)) {
/* Loop-up code detected */
if ((wc->span.maintstat != DAHDI_MAINT_REMOTELOOP)) {
if ((++wc->loopupcnt > 80) &&
(wc->span.maintstat != DAHDI_MAINT_REMOTELOOP)) {
t1_notice(wc, "Loopup detected,"\
" enabling remote loop\n");
t1_setreg(wc, 0x36, 0x08); /* LIM0: Disable any local loop */
t1_setreg(wc, 0x37, 0xf6); /* LIM1: Enable remote loop */
wc->span.maintstat = DAHDI_MAINT_REMOTELOOP;
}
} else
} else {
wc->loopupcnt = 0;
}
/* Same for loopdown code */
if ((!wc->span.mainttimer) && (d & 0x10)) {
/* Loop-down code detected */
if ((wc->span.maintstat == DAHDI_MAINT_REMOTELOOP)) {
if ((++wc->loopdowncnt > 80) &&
(wc->span.maintstat == DAHDI_MAINT_REMOTELOOP)) {
t1_notice(wc, "Loopdown detected,"\
" disabling remote loop\n");
t1_setreg(wc, 0x36, 0x08); /* LIM0: Disable any local loop */
t1_setreg(wc, 0x37, 0xf0); /* LIM1: Disable remote loop */
wc->span.maintstat = DAHDI_MAINT_NONE;
}
} else
} else {
wc->loopdowncnt = 0;
}
}
if (wc->span.lineconfig & DAHDI_CONFIG_NOTOPEN) {
@@ -2437,11 +2677,11 @@ static void timer_work_func(struct work_struct *work)
{
struct t1 *wc = container_of(work, struct t1, timer_work);
#endif
if (test_bit(INITIALIZED, &wc->bit_flags))
mod_timer(&wc->timer, jiffies + HZ/30);
t1_do_counters(wc);
t1_check_alarms(wc);
t1_check_sigbits(wc);
if (test_bit(INITIALIZED, &wc->bit_flags))
mod_timer(&wc->timer, jiffies + HZ/10);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
@@ -2697,13 +2937,7 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
spin_lock_init(&wc->reglock);
INIT_LIST_HEAD(&wc->active_cmds);
INIT_LIST_HEAD(&wc->pending_cmds);
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
wc->timer.function = te12xp_timer;
wc->timer.data = (unsigned long)wc;
init_timer(&wc->timer);
# else
setup_timer(&wc->timer, te12xp_timer, (unsigned long)wc);
# endif
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
INIT_WORK(&wc->timer_work, timer_work_func, wc);
@@ -2749,6 +2983,13 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
}
#endif /* CONFIG_VOICEBUS_ECREFERENCE */
#ifdef CONFIG_VOICEBUS_DISABLE_ASPM
if (is_pcie(wc)) {
pci_disable_link_state(pdev->bus->self, PCIE_LINK_STATE_L0S |
PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
};
#endif
snprintf(wc->name, sizeof(wc->name)-1, "wcte12xp%d", index);
pci_set_drvdata(pdev, wc);
wc->vb.ops = &voicebus_operations;
@@ -2876,13 +3117,11 @@ static DEFINE_PCI_DEVICE_TABLE(te12xp_pci_tbl) = {
{ 0 }
};
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12)
static void te12xp_shutdown(struct pci_dev *pdev)
{
struct t1 *wc = pci_get_drvdata(pdev);
voicebus_quiesce(&wc->vb);
}
#endif
static int te12xp_suspend(struct pci_dev *pdev, pm_message_t state)
{
@@ -2895,9 +3134,7 @@ static struct pci_driver te12xp_driver = {
.name = "wcte12xp",
.probe = te12xp_init_one,
.remove = __devexit_p(te12xp_remove_one),
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12)
.shutdown = te12xp_shutdown,
#endif
.suspend = te12xp_suspend,
.id_table = te12xp_pci_tbl,
};
@@ -2920,14 +3157,20 @@ static int __init te12xp_init(void)
if (!cmd_cache)
return -ENOMEM;
if (-1 != t1e1override) {
pr_info("'t1e1override' is deprecated. "
"Please use 'default_linemode' instead\n");
if ((-1 != t1e1override) || (-1 != j1mode)) {
pr_info("'t1e1override' and 'j1mode' are deprecated. "
"Please use 'default_linemode' instead.\n");
/* If someone is setting j1mode, then, t1e1override most likely
* needs to be forced to t1 mode */
if (j1mode > 0)
t1e1override = 0;
} else if (strcasecmp(default_linemode, "auto") &&
strcasecmp(default_linemode, "t1") &&
strcasecmp(default_linemode, "j1") &&
strcasecmp(default_linemode, "e1")) {
pr_err("'%s' is an unknown span type.", default_linemode);
pr_err("'%s' is an unknown span type.\n", default_linemode);
default_linemode = "auto";
kmem_cache_destroy(cmd_cache);
return -EINVAL;
}
res = dahdi_pci_module(&te12xp_driver);

View File

@@ -77,6 +77,7 @@
enum linemode {
T1 = 1,
E1,
J1,
};
struct command {
@@ -113,6 +114,7 @@ struct t1 {
#define INITIALIZED 1
#define SHUTDOWN 2
#define READY 3
#define IOERROR 4
unsigned long bit_flags;
unsigned long alarmtimer;
unsigned char ledstate;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -25,7 +25,7 @@
#include "xpd.h"
enum bri_opcodes {
XPROTO_NAME(BRI, SET_LED) = 0x33,
XPROTO_NAME(BRI, SET_LED) = 0x33,
};
#endif /* CARD_BRI_H */
#endif /* CARD_BRI_H */

View File

@@ -42,25 +42,20 @@ static DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
static bool echo_packet_is_valid(xpacket_t *pack);
static void echo_packet_dump(const char *msg, xpacket_t *pack);
DEF_RPACKET_DATA(ECHO, SET,
byte timeslots[ECHO_TIMESLOTS];
);
DEF_RPACKET_DATA(ECHO, SET, __u8 timeslots[ECHO_TIMESLOTS];);
DEF_RPACKET_DATA(ECHO, SET_REPLY,
byte status;
byte reserved;
);
DEF_RPACKET_DATA(ECHO, SET_REPLY, __u8 status; __u8 reserved;);
struct ECHO_priv_data {
};
static xproto_table_t PROTO_TABLE(ECHO);
static xproto_table_t PROTO_TABLE(ECHO);
/*---------------- ECHO: Methods -------------------------------------------*/
static xpd_t *ECHO_card_new(xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, byte subtype,
int subunits, int subunit_ports, bool to_phone)
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone)
{
xpd_t *xpd = NULL;
int channels = 0;
@@ -70,8 +65,9 @@ static xpd_t *ECHO_card_new(xbus_t *xbus, int unit, int subunit,
return NULL;
}
XBUS_DBG(GENERAL, xbus, "\n");
xpd = xpd_alloc(xbus, unit, subunit, subtype, subunits,
sizeof(struct ECHO_priv_data), proto_table, channels);
xpd =
xpd_alloc(xbus, unit, subunit, subtype, subunits,
sizeof(struct ECHO_priv_data), proto_table, channels);
if (!xpd)
return NULL;
xpd->type_name = "ECHO";
@@ -122,19 +118,17 @@ static int ECHO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
static int rate_limit;
if ((rate_limit++ % 1003) < 5)
notify_bad_xpd(__func__, xbus, addr,
orig_xpd->xpdname);
notify_bad_xpd(__func__, xbus, addr, orig_xpd->xpdname);
return -EPROTO;
}
spin_lock_irqsave(&xpd->lock, flags);
/* Update /proc info only if reply related to last reg read request */
if (
REG_FIELD(&xpd->requested_reply, regnum) ==
REG_FIELD(info, regnum) &&
REG_FIELD(&xpd->requested_reply, do_subreg) ==
REG_FIELD(info, do_subreg) &&
REG_FIELD(&xpd->requested_reply, subreg) ==
REG_FIELD(info, subreg)) {
if (REG_FIELD(&xpd->requested_reply, regnum) ==
REG_FIELD(info, regnum)
&& REG_FIELD(&xpd->requested_reply, do_subreg) ==
REG_FIELD(info, do_subreg)
&& REG_FIELD(&xpd->requested_reply, subreg) ==
REG_FIELD(info, subreg)) {
xpd->last_reply = *info;
}
spin_unlock_irqrestore(&xpd->lock, flags);
@@ -146,7 +140,7 @@ static int ECHO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
static /* 0x39 */ HOSTCMD(ECHO, SET)
{
struct xbus_echo_state *es;
byte *ts;
__u8 *ts;
xframe_t *xframe;
xpacket_t *pack;
int ret;
@@ -172,7 +166,7 @@ static int ECHO_ec_set(xpd_t *xpd, int pos, bool on)
{
int ts_number;
int ts_mask;
byte *ts;
__u8 *ts;
ts = xpd->xbus->echo_state.timeslots;
/*
@@ -198,7 +192,7 @@ static int ECHO_ec_set(xpd_t *xpd, int pos, bool on)
ts[ts_number] &= ~ts_mask;
}
LINE_DBG(GENERAL, xpd, pos, "%s = %d -- ts_number=%d ts_mask=0x%X\n",
__func__, on, ts_number, ts_mask);
__func__, on, ts_number, ts_mask);
return 0;
}
@@ -207,7 +201,7 @@ static int ECHO_ec_get(xpd_t *xpd, int pos)
int ts_number;
int ts_mask;
int is_on;
byte *ts;
__u8 *ts;
ts = xpd->xbus->echo_state.timeslots;
ts_mask = (xpd->addr.unit == 0) ? 0x1 : 0x2; /* Which bit? */
@@ -220,14 +214,14 @@ static int ECHO_ec_get(xpd_t *xpd, int pos)
}
#if 0
LINE_DBG(GENERAL, xpd, pos, "ec_get=%d -- ts_number=%d ts_mask=0x%X\n",
is_on, ts_number, ts_mask);
is_on, ts_number, ts_mask);
#endif
return is_on;
}
static void ECHO_ec_dump(xbus_t *xbus)
{
byte *ts;
__u8 *ts;
int i;
ts = xbus->echo_state.timeslots;
@@ -236,12 +230,11 @@ static void ECHO_ec_dump(xbus_t *xbus)
"EC-DUMP[%03d]: "
"0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X "
"0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
i,
ts[i+0], ts[i+1], ts[i+2], ts[i+3], ts[i+4], ts[i+5],
ts[i+6], ts[i+7],
ts[i+8], ts[i+9], ts[i+10], ts[i+11], ts[i+12],
ts[i+13], ts[i+14], ts[i+15]
);
i, ts[i + 0], ts[i + 1], ts[i + 2], ts[i + 3],
ts[i + 4], ts[i + 5], ts[i + 6], ts[i + 7], ts[i + 8],
ts[i + 9], ts[i + 10], ts[i + 11], ts[i + 12],
ts[i + 13], ts[i + 14], ts[i + 15]
);
}
}
@@ -255,7 +248,7 @@ static int ECHO_ec_update(xbus_t *xbus)
/*---------------- ECHO: Astribank Reply Handlers --------------------------*/
HANDLER_DEF(ECHO, SET_REPLY)
{
byte status;
__u8 status;
BUG_ON(!xpd);
status = RPACKET_FIELD(pack, ECHO, SET_REPLY, status);
@@ -263,26 +256,26 @@ HANDLER_DEF(ECHO, SET_REPLY)
return 0;
}
static const struct xops echo_xops = {
.card_new = ECHO_card_new,
.card_init = ECHO_card_init,
.card_remove = ECHO_card_remove,
.card_tick = ECHO_card_tick,
.card_register_reply = ECHO_card_register_reply,
static const struct xops echo_xops = {
.card_new = ECHO_card_new,
.card_init = ECHO_card_init,
.card_remove = ECHO_card_remove,
.card_tick = ECHO_card_tick,
.card_register_reply = ECHO_card_register_reply,
};
static const struct echoops echoops = {
.ec_set = ECHO_ec_set,
.ec_get = ECHO_ec_get,
.ec_update = ECHO_ec_update,
.ec_dump = ECHO_ec_dump,
static const struct echoops echoops = {
.ec_set = ECHO_ec_set,
.ec_get = ECHO_ec_get,
.ec_update = ECHO_ec_update,
.ec_dump = ECHO_ec_dump,
};
static xproto_table_t PROTO_TABLE(ECHO) = {
.owner = THIS_MODULE,
.entries = {
/* Table Card Opcode */
XENTRY(ECHO, ECHO, SET_REPLY),
/* Table Card Opcode */
XENTRY( ECHO, ECHO, SET_REPLY ),
},
.name = "ECHO",
.ports_per_subunit = 1,
@@ -295,7 +288,7 @@ static xproto_table_t PROTO_TABLE(ECHO) = {
static bool echo_packet_is_valid(xpacket_t *pack)
{
const xproto_entry_t *xe = NULL;
const xproto_entry_t *xe = NULL;
// DBG(GENERAL, "\n");
xe = xproto_card_entry(&PROTO_TABLE(ECHO), XPACKET_OP(pack));
return xe != NULL;
@@ -309,14 +302,14 @@ static void echo_packet_dump(const char *msg, xpacket_t *pack)
/*------------------------- sysfs stuff --------------------------------*/
static int echo_xpd_probe(struct device *dev)
{
xpd_t *ec_xpd;
int ret = 0;
xpd_t *ec_xpd;
int ret = 0;
ec_xpd = dev_to_xpd(dev);
/* Is it our device? */
if (ec_xpd->type != XPD_TYPE_ECHO) {
XPD_ERR(ec_xpd, "drop suggestion for %s (%d)\n",
dev_name(dev), ec_xpd->type);
XPD_ERR(ec_xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
ec_xpd->type);
return -EINVAL;
}
XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
@@ -325,23 +318,20 @@ static int echo_xpd_probe(struct device *dev)
static int echo_xpd_remove(struct device *dev)
{
xpd_t *ec_xpd;
xpd_t *ec_xpd;
ec_xpd = dev_to_xpd(dev);
XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
return 0;
}
static struct xpd_driver echo_driver = {
.type = XPD_TYPE_ECHO,
.driver = {
.name = "echo",
#ifndef OLD_HOTPLUG_SUPPORT
.owner = THIS_MODULE,
#endif
.probe = echo_xpd_probe,
.remove = echo_xpd_remove
}
static struct xpd_driver echo_driver = {
.type = XPD_TYPE_ECHO,
.driver = {
.name = "echo",
.owner = THIS_MODULE,
.probe = echo_xpd_probe,
.remove = echo_xpd_remove}
};
static int __init card_echo_startup(void)

View File

@@ -24,8 +24,8 @@
#include "xpd.h"
enum echo_opcodes {
XPROTO_NAME(ECHO, SET) = 0x39,
XPROTO_NAME(ECHO, SET_REPLY) = 0x3A,
XPROTO_NAME(ECHO, SET) = 0x39,
XPROTO_NAME(ECHO, SET_REPLY) = 0x3A,
};
#endif /* CARD_ECHO_H */
#endif /* CARD_ECHO_H */

File diff suppressed because it is too large Load Diff

View File

@@ -25,17 +25,16 @@
#include "xpd.h"
enum fxo_opcodes {
XPROTO_NAME(FXO, SIG_CHANGED) = 0x06,
/**/
XPROTO_NAME(FXO, DAA_WRITE) = 0x0F, /* Write to DAA */
XPROTO_NAME(FXO, CHAN_CID) = 0x0F, /* Write to DAA */
XPROTO_NAME(FXO, LED) = 0x0F, /* Write to DAA */
XPROTO_NAME(FXO, SIG_CHANGED) = 0x06, /**/
XPROTO_NAME(FXO, DAA_WRITE) = 0x0F, /* Write to DAA */
XPROTO_NAME(FXO, CHAN_CID) = 0x0F, /* Write to DAA */
XPROTO_NAME(FXO, LED) = 0x0F, /* Write to DAA */
};
DEF_RPACKET_DATA(FXO, SIG_CHANGED,
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
);
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
);
#endif /* CARD_FXO_H */
#endif /* CARD_FXO_H */

File diff suppressed because it is too large Load Diff

View File

@@ -25,17 +25,15 @@
#include "xpd.h"
enum fxs_opcodes {
XPROTO_NAME(FXS, SIG_CHANGED) = 0x06,
/**/
XPROTO_NAME(FXS, CHAN_POWER) = 0x0F, /* Write to SLIC */
XPROTO_NAME(FXS, CHAN_CID) = 0x0F, /* Write to SLIC */
XPROTO_NAME(FXS, LED) = 0x0F, /* Write to SLIC */
XPROTO_NAME(FXS, SIG_CHANGED) = 0x06,
/**/ XPROTO_NAME(FXS, CHAN_POWER) = 0x0F, /* Write to SLIC */
XPROTO_NAME(FXS, CHAN_CID) = 0x0F, /* Write to SLIC */
XPROTO_NAME(FXS, LED) = 0x0F, /* Write to SLIC */
};
DEF_RPACKET_DATA(FXS, SIG_CHANGED,
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
);
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
);
#endif /* CARD_FXS_H */
#endif /* CARD_FXS_H */

View File

@@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/kmod.h>
#include "xdefs.h"
#include "xpd.h"
#include "xpp_dahdi.h"
@@ -32,21 +33,22 @@
static const char rcsid[] = "$Id$";
DEF_PARM(charp,initdir, "/usr/share/dahdi", 0644, "The directory of card initialization scripts");
DEF_PARM(charp, initdir, "/usr/share/dahdi", 0644,
"The directory of card initialization scripts");
#define CHIP_REGISTERS "chipregs"
extern int debug;
extern int debug;
/*---------------- GLOBAL PROC handling -----------------------------------*/
static int send_magic_request(xbus_t *xbus,
unsigned unit, xportno_t portno, bool eoftx)
static int send_magic_request(xbus_t *xbus, unsigned unit, xportno_t portno,
bool eoftx)
{
xframe_t *xframe;
xpacket_t *pack;
reg_cmd_t *reg_cmd;
int ret;
xframe_t *xframe;
xpacket_t *pack;
reg_cmd_t *reg_cmd;
int ret;
/*
* Zero length multibyte is legal and has special meaning for the
@@ -65,203 +67,210 @@ static int send_magic_request(xbus_t *xbus,
dump_xframe(__func__, xbus, xframe, debug);
ret = send_cmd_frame(xbus, xframe);
if (ret < 0)
PORT_ERR(xbus, unit, portno,
"%s: failed sending xframe\n", __func__);
PORT_ERR(xbus, unit, portno, "%s: failed sending xframe\n",
__func__);
return ret;
}
static int parse_hexbyte(const char *buf)
{
char *endp;
unsigned val;
char *endp;
unsigned val;
val = simple_strtoul(buf, &endp, 16);
if(*endp != '\0' || val > 0xFF)
if (*endp != '\0' || val > 0xFF)
return -EBADR;
return (byte)val;
return (__u8)val;
}
static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
{
int argno;
char num_args;
int portno;
bool writing;
int op; /* [W]rite, [R]ead */
int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti */
bool do_subreg = 0;
int regnum;
int subreg;
int data_low;
bool do_datah;
int data_high;
int ret = -EBADR;
int argno;
char num_args;
int portno;
bool writing;
int op; /* [W]rite, [R]ead */
int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti */
bool do_subreg = 0;
int regnum;
int subreg;
int data_low;
bool do_datah;
int data_high;
int ret = -EBADR;
num_args = 2; /* port + operation */
if(argc < num_args) {
num_args = 2; /* port + operation */
if (argc < num_args) {
XPD_ERR(xpd, "Not enough arguments (%d)\n", argc);
XPD_ERR(xpd,
"Any Command is composed of at least %d words (got only %d)\n",
num_args, argc);
"Any Command is composed of at least %d words "
"(got only %d)\n",
num_args, argc);
goto out;
}
/* Process the arguments */
argno = 0;
if(strcmp(argv[argno], "*") == 0) {
if (strcmp(argv[argno], "*") == 0) {
portno = PORT_BROADCAST;
//XPD_DBG(REGS, xpd, "Port broadcast\n");
} else {
portno = parse_hexbyte(argv[argno]);
if(portno < 0 || portno >= 8) {
if (portno < 0 || portno >= 8) {
XPD_ERR(xpd, "Illegal port number '%s'\n", argv[argno]);
goto out;
}
//XPD_DBG(REGS, xpd, "Port is %d\n", portno);
}
argno++;
if(strlen(argv[argno]) != 2) {
if (strlen(argv[argno]) != 2) {
XPD_ERR(xpd, "Wrong operation codes '%s'\n", argv[argno]);
goto out;
}
op = argv[argno][0];
switch(op) {
case 'W':
writing = 1;
num_args++; /* data low */
//XPD_DBG(REGS, xpd, "WRITING\n");
break;
case 'R':
writing = 0;
//XPD_DBG(REGS, xpd, "READING\n");
break;
default:
XPD_ERR(xpd, "Unknown operation type '%c'\n", op);
goto out;
switch (op) {
case 'W':
writing = 1;
num_args++; /* data low */
//XPD_DBG(REGS, xpd, "WRITING\n");
break;
case 'R':
writing = 0;
//XPD_DBG(REGS, xpd, "READING\n");
break;
default:
XPD_ERR(xpd, "Unknown operation type '%c'\n", op);
goto out;
}
addr_mode = argv[argno][1];
switch(addr_mode) {
case 'I':
XPD_NOTICE(xpd, "'I' is deprecated in register commands. Use 'S' instead.\n");
/* fall through */
case 'S':
do_subreg = 1;
num_args += 2; /* register + subreg */
//XPD_DBG(REGS, xpd, "SUBREG\n");
break;
case 'D':
do_subreg = 0;
num_args++; /* register */
//XPD_DBG(REGS, xpd, "DIRECT\n");
break;
case 'M':
case 'm':
if(op != 'W') {
XPD_ERR(xpd,
"Can use Multibyte (%c) only with op 'W'\n", addr_mode);
goto out;
}
num_args--; /* No data low */
//XPD_DBG(REGS, xpd, "Multibyte (%c)\n", addr_mode);
break;
default:
XPD_ERR(xpd, "Unknown addressing type '%c'\n", addr_mode);
switch (addr_mode) {
case 'I':
XPD_NOTICE(xpd,
"'I' is deprecated in register commands. "
"Use 'S' instead.\n");
/* fall through */
case 'S':
do_subreg = 1;
num_args += 2; /* register + subreg */
//XPD_DBG(REGS, xpd, "SUBREG\n");
break;
case 'D':
do_subreg = 0;
num_args++; /* register */
//XPD_DBG(REGS, xpd, "DIRECT\n");
break;
case 'M':
case 'm':
if (op != 'W') {
XPD_ERR(xpd,
"Can use Multibyte (%c) only with op 'W'\n",
addr_mode);
goto out;
}
num_args--; /* No data low */
//XPD_DBG(REGS, xpd, "Multibyte (%c)\n", addr_mode);
break;
default:
XPD_ERR(xpd, "Unknown addressing type '%c'\n", addr_mode);
goto out;
}
if(argv[argno][2] != '\0') {
if (argv[argno][2] != '\0') {
XPD_ERR(xpd, "Bad operation field '%s'\n", argv[argno]);
goto out;
}
if(argc < num_args) {
if (argc < num_args) {
XPD_ERR(xpd,
"Command \"%s\" is composed of at least %d words (got only %d)\n",
argv[argno], num_args, argc);
"Command \"%s\" is composed of at least %d words "
"(got only %d)\n",
argv[argno], num_args, argc);
goto out;
}
argno++;
if(addr_mode == 'M' || addr_mode == 'm') {
if(argno < argc) {
if (addr_mode == 'M' || addr_mode == 'm') {
if (argno < argc) {
XPD_ERR(xpd,
"Magic-Multibyte(%c) with %d extra arguments\n",
addr_mode, argc - argno);
"Magic-Multibyte(%c) with %d extra arguments\n",
addr_mode, argc - argno);
goto out;
}
ret = send_magic_request(xpd->xbus, xpd->addr.unit, portno,
addr_mode == 'm');
ret =
send_magic_request(xpd->xbus, xpd->addr.unit, portno,
addr_mode == 'm');
goto out;
}
/* Normal (non-Magic) register commands */
do_datah = 0;
if(argno >= argc) {
if (argno >= argc) {
XPD_ERR(xpd, "Missing register number\n");
goto out;
}
regnum = parse_hexbyte(argv[argno]);
if(regnum < 0) {
if (regnum < 0) {
XPD_ERR(xpd, "Illegal register number '%s'\n", argv[argno]);
goto out;
}
//XPD_DBG(REGS, xpd, "Register is %X\n", regnum);
argno++;
if(do_subreg) {
if(argno >= argc) {
if (do_subreg) {
if (argno >= argc) {
XPD_ERR(xpd, "Missing subregister number\n");
goto out;
}
subreg = parse_hexbyte(argv[argno]);
if(subreg < 0) {
XPD_ERR(xpd, "Illegal subregister number '%s'\n", argv[argno]);
if (subreg < 0) {
XPD_ERR(xpd, "Illegal subregister number '%s'\n",
argv[argno]);
goto out;
}
//XPD_DBG(REGS, xpd, "Subreg is %X\n", subreg);
argno++;
} else
subreg = 0;
if(writing) {
if(argno >= argc) {
if (writing) {
if (argno >= argc) {
XPD_ERR(xpd, "Missing data low number\n");
goto out;
}
data_low = parse_hexbyte(argv[argno]);
if(data_low < 0) {
XPD_ERR(xpd, "Illegal data_low number '%s'\n", argv[argno]);
if (data_low < 0) {
XPD_ERR(xpd, "Illegal data_low number '%s'\n",
argv[argno]);
goto out;
}
//XPD_DBG(REGS, xpd, "Data Low is %X\n", data_low);
argno++;
} else
data_low = 0;
if(argno < argc) {
if (argno < argc) {
do_datah = 1;
if(!argv[argno]) {
if (!argv[argno]) {
XPD_ERR(xpd, "Missing data high number\n");
goto out;
}
data_high = parse_hexbyte(argv[argno]);
if(data_high < 0) {
XPD_ERR(xpd, "Illegal data_high number '%s'\n", argv[argno]);
if (data_high < 0) {
XPD_ERR(xpd, "Illegal data_high number '%s'\n",
argv[argno]);
goto out;
}
//XPD_DBG(REGS, xpd, "Data High is %X\n", data_high);
argno++;
} else
data_high = 0;
if(argno < argc) {
XPD_ERR(xpd,
"Command contains an extra %d argument\n",
argc - argno);
if (argno < argc) {
XPD_ERR(xpd, "Command contains an extra %d argument\n",
argc - argno);
goto out;
}
#if 0
XPD_DBG(REGS, xpd,
"portno=%d writing=%d regnum=%d do_subreg=%d subreg=%d dataL=%d do_datah=%d dataH=%d\n",
portno, /* portno */
writing, /* writing */
regnum,
do_subreg, /* use subreg */
subreg, /* subreg */
data_low,
do_datah, /* use data_high*/
data_high);
"portno=%d writing=%d regnum=%d do_subreg=%d subreg=%d "
"dataL=%d do_datah=%d dataH=%d\n",
portno, /* portno */
writing, /* writing */
regnum, do_subreg, /* use subreg */
subreg, /* subreg */
data_low, do_datah, /* use data_high */
data_high);
#endif
ret = xpp_register_request(xpd->xbus, xpd, portno,
writing, regnum, do_subreg, subreg,
@@ -270,36 +279,38 @@ out:
return ret;
}
#define MAX_ARGS 10
int parse_chip_command(xpd_t *xpd, char *cmdline)
{
xbus_t *xbus;
int ret = -EBADR;
byte buf[MAX_PROC_WRITE];
char *str;
char *p;
static const int MAX_ARGS = 10;
char *argv[MAX_ARGS + 1];
int argc;
int i;
xbus_t *xbus;
int ret = -EBADR;
__u8 buf[MAX_PROC_WRITE];
char *str;
char *p;
char *argv[MAX_ARGS + 1];
int argc;
int i;
BUG_ON(!xpd);
xbus = xpd->xbus;
if(!XBUS_FLAGS(xbus, CONNECTED)) {
if (!XBUS_FLAGS(xbus, CONNECTED)) {
XBUS_DBG(GENERAL, xbus, "Dropped packet. Disconnected.\n");
return -EBUSY;
}
strlcpy(buf, cmdline, MAX_PROC_WRITE); /* Save a copy */
if(buf[0] == '#' || buf[0] == ';')
if (buf[0] == '#' || buf[0] == ';')
XPD_DBG(REGS, xpd, "Note: '%s'\n", buf);
if((p = strchr(buf, '#')) != NULL) /* Truncate comments */
if ((p = strchr(buf, '#')) != NULL) /* Truncate comments */
*p = '\0';
if((p = strchr(buf, ';')) != NULL) /* Truncate comments */
if ((p = strchr(buf, ';')) != NULL) /* Truncate comments */
*p = '\0';
for(p = buf; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */
/* Trim leading whitespace */
for (p = buf; *p && (*p == ' ' || *p == '\t'); p++)
;
str = p;
for(i = 0; (p = strsep(&str, " \t")) != NULL && i < MAX_ARGS; ) {
if(*p != '\0') {
for (i = 0; (p = strsep(&str, " \t")) != NULL && i < MAX_ARGS;) {
if (*p != '\0') {
argv[i] = p;
// XPD_DBG(REGS, xpd, "ARG %d = '%s'\n", i, p);
i++;
@@ -307,11 +318,12 @@ int parse_chip_command(xpd_t *xpd, char *cmdline)
}
argv[i] = NULL;
argc = i;
if(p) {
XPD_ERR(xpd, "Too many words (%d) to process. Last was '%s'\n", i, p);
if (p) {
XPD_ERR(xpd, "Too many words (%d) to process. Last was '%s'\n",
i, p);
goto out;
}
if(argc)
if (argc)
ret = execute_chip_command(xpd, argc, argv);
else
ret = 0; /* empty command - no op */
@@ -328,11 +340,11 @@ static void global_packet_dump(const char *msg, xpacket_t *pack);
/* 0x07 */ HOSTCMD(GLOBAL, AB_REQUEST)
{
int ret = -ENODEV;
xframe_t *xframe;
xpacket_t *pack;
int ret = -ENODEV;
xframe_t *xframe;
xpacket_t *pack;
if(!xbus) {
if (!xbus) {
DBG(DEVICES, "NO XBUS\n");
return -EINVAL;
}
@@ -342,33 +354,35 @@ static void global_packet_dump(const char *msg, xpacket_t *pack);
RPACKET_FIELD(pack, GLOBAL, AB_REQUEST, rev) = XPP_PROTOCOL_VERSION;
RPACKET_FIELD(pack, GLOBAL, AB_REQUEST, reserved) = 0;
XBUS_DBG(DEVICES, xbus, "Protocol Version %d\n", XPP_PROTOCOL_VERSION);
if(xbus_setstate(xbus, XBUS_STATE_SENT_REQUEST))
if (xbus_setstate(xbus, XBUS_STATE_SENT_REQUEST))
ret = send_cmd_frame(xbus, xframe);
return ret;
}
int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
bool writing, byte regnum, bool do_subreg, byte subreg,
byte data_low, bool do_datah, byte data_high, bool should_reply)
bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
__u8 data_low, bool do_datah, __u8 data_high,
bool should_reply)
{
int ret = 0;
xframe_t *xframe;
xpacket_t *pack;
reg_cmd_t *reg_cmd;
int ret = 0;
xframe_t *xframe;
xpacket_t *pack;
reg_cmd_t *reg_cmd;
if(!xbus) {
if (!xbus) {
DBG(REGS, "NO XBUS\n");
return -EINVAL;
}
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx);
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST,
xpd->xbus_idx);
LINE_DBG(REGS, xpd, portno, "%c%c %02X %02X %02X %02X\n",
(writing)?'W':'R',
(do_subreg)?'S':'D',
regnum, subreg, data_low, data_high);
(writing) ? 'W' : 'R', (do_subreg) ? 'S' : 'D', regnum, subreg,
data_low, data_high);
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
reg_cmd->bytes = sizeof(*reg_cmd) - 1; // do not count the 'bytes' field
/* do not count the 'bytes' field */
reg_cmd->bytes = sizeof(*reg_cmd) - 1;
reg_cmd->is_multibyte = 0;
if(portno == PORT_BROADCAST) {
if (portno == PORT_BROADCAST) {
reg_cmd->portnum = 0;
REG_FIELD(reg_cmd, all_ports_broadcast) = 1;
} else {
@@ -384,14 +398,15 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
REG_FIELD(reg_cmd, do_datah) = do_datah;
REG_FIELD(reg_cmd, data_low) = data_low;
REG_FIELD(reg_cmd, data_high) = data_high;
if(should_reply)
if (should_reply)
xpd->requested_reply = *reg_cmd;
if(debug & DBG_REGS) {
dump_reg_cmd("REG_REQ", 1, xbus, xpd->addr.unit, reg_cmd->portnum, reg_cmd);
if (debug & DBG_REGS) {
dump_reg_cmd("REG_REQ", 1, xbus, xpd->addr.unit,
reg_cmd->portnum, reg_cmd);
dump_packet("REG_REQ", pack, 1);
}
if(!xframe->usec_towait) { /* default processing time of SPI */
if(subreg)
if (!xframe->usec_towait) { /* default processing time of SPI */
if (subreg)
xframe->usec_towait = 2000;
else
xframe->usec_towait = 1000;
@@ -399,18 +414,19 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
ret = send_cmd_frame(xbus, xframe);
return ret;
}
EXPORT_SYMBOL(xpp_register_request);
/*
* The XPD parameter is totaly ignored by the driver and firmware as well.
*/
/* 0x19 */ HOSTCMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift)
{
xframe_t *xframe;
xpacket_t *pack;
const char *mode_name;
xframe_t *xframe;
xpacket_t *pack;
const char *mode_name;
BUG_ON(!xbus);
if((mode_name = sync_mode_name(mode)) == NULL) {
if ((mode_name = sync_mode_name(mode)) == NULL) {
XBUS_ERR(xbus, "SYNC_SOURCE: bad sync_mode=0x%X\n", mode);
return -EINVAL;
}
@@ -422,19 +438,37 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
return 0;
}
/* 0x23 */ HOSTCMD(GLOBAL, RESET_SYNC_COUNTERS)
/*
* Wrapper for different types of xbus reset
*/
static int send_xbus_reset(xbus_t *xbus, uint8_t reset_mask)
{
xframe_t *xframe;
xpacket_t *pack;
xframe_t *xframe;
xpacket_t *pack;
BUG_ON(!xbus);
//XBUS_DBG(SYNC, xbus, "\n");
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, RESET_SYNC_COUNTERS, 0);
RPACKET_FIELD(pack, GLOBAL, RESET_SYNC_COUNTERS, mask) = 0x10;
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, XBUS_RESET, 0);
RPACKET_FIELD(pack, GLOBAL, XBUS_RESET, mask) = reset_mask;
send_cmd_frame(xbus, xframe);
return 0;
}
/* 0x23 */ HOSTCMD(GLOBAL, RESET_SPI)
{
XBUS_DBG(DEVICES, xbus, "Sending SPI reset\n");
/* toggle reset line */
send_xbus_reset(xbus, 0x04);
send_xbus_reset(xbus, 0x00);
return 0;
}
/* 0x23 */ HOSTCMD(GLOBAL, RESET_SYNC_COUNTERS)
{
//XBUS_DBG(SYNC, xbus, "\n");
return send_xbus_reset(xbus, 0x10);
}
/*---------------- GLOBAL: Astribank Reply Handlers -----------------------*/
HANDLER_DEF(GLOBAL, NULL_REPLY)
@@ -443,14 +477,14 @@ HANDLER_DEF(GLOBAL, NULL_REPLY)
return 0;
}
HANDLER_DEF(GLOBAL, AB_DESCRIPTION) /* 0x08 */
{
struct xbus_workqueue *worker;
byte rev;
struct unit_descriptor *units;
int count_units;
int i;
int ret = 0;
HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
{ /* 0x08 */
struct xbus_workqueue *worker;
__u8 rev;
struct unit_descriptor *units;
int count_units;
int i;
int ret = 0;
if (!xbus) {
NOTICE("%s: xbus is gone!!!\n", __func__);
@@ -458,31 +492,31 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION) /* 0x08 */
}
rev = RPACKET_FIELD(pack, GLOBAL, AB_DESCRIPTION, rev);
units = RPACKET_FIELD(pack, GLOBAL, AB_DESCRIPTION, unit_descriptor);
count_units = XPACKET_LEN(pack) - ((byte *)units - (byte *)pack);
count_units = XPACKET_LEN(pack) - ((__u8 *)units - (__u8 *)pack);
count_units /= sizeof(*units);
if(rev != XPP_PROTOCOL_VERSION) {
if (rev != XPP_PROTOCOL_VERSION) {
XBUS_NOTICE(xbus, "Bad protocol version %d (should be %d)\n",
rev, XPP_PROTOCOL_VERSION);
rev, XPP_PROTOCOL_VERSION);
ret = -EPROTO;
goto proto_err;
}
if(count_units > NUM_UNITS) {
if (count_units > NUM_UNITS) {
XBUS_NOTICE(xbus, "Too many units %d (should be %d)\n",
count_units, NUM_UNITS);
count_units, NUM_UNITS);
ret = -EPROTO;
goto proto_err;
}
if(count_units <= 0) {
XBUS_NOTICE(xbus, "Empty astribank? (%d units)\n",
count_units);
if (count_units <= 0) {
XBUS_NOTICE(xbus, "Empty astribank? (%d units)\n", count_units);
ret = -EPROTO;
goto proto_err;
}
if(!xbus_setstate(xbus, XBUS_STATE_RECVD_DESC)) {
if (!xbus_setstate(xbus, XBUS_STATE_RECVD_DESC)) {
ret = -EPROTO;
goto proto_err;
}
XBUS_INFO(xbus, "DESCRIPTOR: %d cards, protocol revision %d\n", count_units, rev);
XBUS_INFO(xbus, "DESCRIPTOR: %d cards, protocol revision %d\n",
count_units, rev);
if (xbus_check_unique(xbus))
return -EBUSY;
xbus->revision = rev;
@@ -492,12 +526,14 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION) /* 0x08 */
ret = -ENODEV;
goto out;
}
for(i = 0; i < count_units; i++) {
struct unit_descriptor *this_unit = &units[i];
struct card_desc_struct *card_desc;
unsigned long flags;
for (i = 0; i < count_units; i++) {
struct unit_descriptor *this_unit = &units[i];
struct card_desc_struct *card_desc;
unsigned long flags;
if((card_desc = KZALLOC(sizeof(struct card_desc_struct), GFP_ATOMIC)) == NULL) {
if ((card_desc =
KZALLOC(sizeof(struct card_desc_struct),
GFP_ATOMIC)) == NULL) {
XBUS_ERR(xbus, "Card description allocation failed.\n");
ret = -ENOMEM;
goto out;
@@ -510,22 +546,22 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION) /* 0x08 */
card_desc->numchips = this_unit->numchips;
card_desc->ports_per_chip = this_unit->ports_per_chip;
card_desc->port_dir = this_unit->port_dir;
card_desc->ports = card_desc->numchips * card_desc->ports_per_chip;
XBUS_INFO(xbus, " CARD %d type=%d.%d ports=%d (%dx%d), port-dir=0x%02X\n",
card_desc->xpd_addr.unit,
card_desc->type,
card_desc->subtype,
card_desc->ports,
card_desc->numchips,
card_desc->ports_per_chip,
card_desc->port_dir
);
card_desc->ports =
card_desc->numchips * card_desc->ports_per_chip;
XBUS_INFO(xbus,
" CARD %d type=%d.%d ports=%d (%dx%d), "
"port-dir=0x%02X\n",
card_desc->xpd_addr.unit, card_desc->type,
card_desc->subtype, card_desc->ports,
card_desc->numchips, card_desc->ports_per_chip,
card_desc->port_dir);
spin_lock_irqsave(&worker->worker_lock, flags);
worker->num_units++;
XBUS_COUNTER(xbus, UNITS)++;
list_add_tail(&card_desc->card_list, &worker->card_list);
spin_unlock_irqrestore(&worker->worker_lock, flags);
}
CALL_PROTO(GLOBAL, RESET_SPI, xbus, NULL);
if (!xbus_process_worker(xbus)) {
ret = -ENODEV;
goto out;
@@ -539,21 +575,23 @@ out:
HANDLER_DEF(GLOBAL, REGISTER_REPLY)
{
reg_cmd_t *reg = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REPLY, regcmd);
reg_cmd_t *reg = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REPLY, regcmd);
if(!xpd) {
static int rate_limit;
if (!xpd) {
static int rate_limit;
if((rate_limit++ % 1003) < 5)
notify_bad_xpd(__FUNCTION__, xbus, XPACKET_ADDR(pack), "");
if ((rate_limit++ % 1003) < 5)
notify_bad_xpd(__func__, xbus, XPACKET_ADDR(pack), "");
return -EPROTO;
}
if(debug & DBG_REGS) {
dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->portnum, reg);
if (debug & DBG_REGS) {
dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->portnum,
reg);
dump_packet("REG_REPLY", pack, 1);
}
if (! XMETHOD(card_register_reply, xpd)) {
XPD_ERR(xpd, "REGISTER_REPLY: without card_register_reply() method\n");
if (!XMETHOD(card_register_reply, xpd)) {
XPD_ERR(xpd,
"REGISTER_REPLY: missing card_register_reply()\n");
return -EINVAL;
}
return CALL_XMETHOD(card_register_reply, xpd, reg);
@@ -561,12 +599,12 @@ HANDLER_DEF(GLOBAL, REGISTER_REPLY)
HANDLER_DEF(GLOBAL, SYNC_REPLY)
{
byte mode = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, sync_mode);
byte drift = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, drift);
const char *mode_name;
__u8 mode = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, sync_mode);
__u8 drift = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, drift);
const char *mode_name;
BUG_ON(!xbus);
if((mode_name = sync_mode_name(mode)) == NULL) {
if ((mode_name = sync_mode_name(mode)) == NULL) {
XBUS_ERR(xbus, "SYNC_REPLY: bad sync_mode=0x%X\n", mode);
return -EINVAL;
}
@@ -580,24 +618,26 @@ HANDLER_DEF(GLOBAL, SYNC_REPLY)
HANDLER_DEF(GLOBAL, ERROR_CODE)
{
char tmp_name[TMP_NAME_LEN];
static long rate_limit;
byte category_code;
byte errorbits;
char tmp_name[TMP_NAME_LEN];
static long rate_limit;
__u8 category_code;
__u8 errorbits;
BUG_ON(!xbus);
if((rate_limit++ % 5003) > 200)
if ((rate_limit++ % 5003) > 200)
return 0;
category_code = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, category_code);
errorbits = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, errorbits);
if(!xpd) {
if (!xpd) {
snprintf(tmp_name, TMP_NAME_LEN, "%s(%1d%1d)", xbus->busname,
XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
} else {
snprintf(tmp_name, TMP_NAME_LEN, "%s/%s", xbus->busname, xpd->xpdname);
snprintf(tmp_name, TMP_NAME_LEN, "%s/%s", xbus->busname,
xpd->xpdname);
}
NOTICE("%s: FIRMWARE %s: category=%d errorbits=0x%02X (rate_limit=%ld)\n",
tmp_name, cmd->name, category_code, errorbits, rate_limit);
NOTICE
("%s: FIRMWARE %s: category=%d errorbits=0x%02X (rate_limit=%ld)\n",
tmp_name, cmd->name, category_code, errorbits, rate_limit);
dump_packet("FIRMWARE: ", pack, 1);
/*
* FIXME: Should implement an error recovery plan
@@ -605,15 +645,14 @@ HANDLER_DEF(GLOBAL, ERROR_CODE)
return 0;
}
xproto_table_t PROTO_TABLE(GLOBAL) = {
.entries = {
/* Prototable Card Opcode */
XENTRY( GLOBAL, GLOBAL, NULL_REPLY ),
XENTRY( GLOBAL, GLOBAL, AB_DESCRIPTION ),
XENTRY( GLOBAL, GLOBAL, NULL_REPLY ),
XENTRY( GLOBAL, GLOBAL, AB_DESCRIPTION ),
XENTRY( GLOBAL, GLOBAL, SYNC_REPLY ),
XENTRY( GLOBAL, GLOBAL, ERROR_CODE ),
XENTRY( GLOBAL, GLOBAL, REGISTER_REPLY ),
XENTRY( GLOBAL, GLOBAL, ERROR_CODE ),
XENTRY( GLOBAL, GLOBAL, REGISTER_REPLY ),
},
.name = "GLOBAL",
.packet_is_valid = global_packet_is_valid,
@@ -622,7 +661,7 @@ xproto_table_t PROTO_TABLE(GLOBAL) = {
static bool global_packet_is_valid(xpacket_t *pack)
{
const xproto_entry_t *xe;
const xproto_entry_t *xe;
//DBG(GENERAL, "\n");
xe = xproto_global_entry(XPACKET_OP(pack));
@@ -636,28 +675,37 @@ static void global_packet_dump(const char *msg, xpacket_t *pack)
#define MAX_PATH_STR 128
#ifndef UMH_WAIT_PROC
/*
* - UMH_WAIT_PROC was introduced as enum in 2.6.23
* with a value of 1
* - It was changed to a macro (and it's value was modified) in 3.3.0
*/
#define UMH_WAIT_PROC 1
#endif
int run_initialize_registers(xpd_t *xpd)
{
int ret;
xbus_t *xbus;
char busstr[MAX_ENV_STR];
char busnumstr[MAX_ENV_STR];
char modelstr[MAX_ENV_STR];
char unitstr[MAX_ENV_STR];
char subunitsstr[MAX_ENV_STR];
char typestr[MAX_ENV_STR];
char directionstr[MAX_ENV_STR];
char revstr[MAX_ENV_STR];
char connectorstr[MAX_ENV_STR];
char xbuslabel[MAX_ENV_STR];
char init_card[MAX_PATH_STR];
byte direction_mask;
int i;
char *argv[] = {
int ret;
xbus_t *xbus;
char busstr[MAX_ENV_STR];
char busnumstr[MAX_ENV_STR];
char modelstr[MAX_ENV_STR];
char unitstr[MAX_ENV_STR];
char subunitsstr[MAX_ENV_STR];
char typestr[MAX_ENV_STR];
char directionstr[MAX_ENV_STR];
char revstr[MAX_ENV_STR];
char connectorstr[MAX_ENV_STR];
char xbuslabel[MAX_ENV_STR];
char init_card[MAX_PATH_STR];
__u8 direction_mask;
int i;
char *argv[] = {
init_card,
NULL
};
char *envp[] = {
char *envp[] = {
busstr,
busnumstr,
modelstr,
@@ -673,74 +721,82 @@ int run_initialize_registers(xpd_t *xpd)
BUG_ON(!xpd);
xbus = xpd->xbus;
if(!initdir || !initdir[0]) {
if (!initdir || !initdir[0]) {
XPD_NOTICE(xpd, "Missing initdir parameter\n");
ret = -EINVAL;
goto err;
}
if(!xpd_setstate(xpd, XPD_STATE_INIT_REGS)) {
if (!xpd_setstate(xpd, XPD_STATE_INIT_REGS)) {
ret = -EINVAL;
goto err;
}
direction_mask = 0;
for(i = 0; i < xpd->subunits; i++) {
xpd_t *su = xpd_byaddr(xbus, xpd->addr.unit, i);
for (i = 0; i < xpd->subunits; i++) {
xpd_t *su = xpd_byaddr(xbus, xpd->addr.unit, i);
if(!su) {
XPD_ERR(xpd,
"Have %d subunits, but not subunit #%d\n",
if (!su) {
XPD_ERR(xpd, "Have %d subunits, but not subunit #%d\n",
xpd->subunits, i);
continue;
}
direction_mask |= (PHONEDEV(su).direction == TO_PHONE) ? BIT(i) : 0;
direction_mask |=
(PHONEDEV(su).direction == TO_PHONE) ? BIT(i) : 0;
}
snprintf(busstr, MAX_ENV_STR, "XBUS_NAME=%s", xbus->busname);
snprintf(busnumstr, MAX_ENV_STR, "XBUS_NUMBER=%d", xbus->num);
snprintf(modelstr, MAX_ENV_STR, "XBUS_MODEL_STRING=%s", xbus->transport.model_string);
snprintf(modelstr, MAX_ENV_STR, "XBUS_MODEL_STRING=%s",
xbus->transport.model_string);
snprintf(unitstr, MAX_ENV_STR, "UNIT_NUMBER=%d", xpd->addr.unit);
snprintf(typestr, MAX_ENV_STR, "UNIT_TYPE=%d", xpd->type);
snprintf(subunitsstr, MAX_ENV_STR, "UNIT_SUBUNITS=%d", xpd->subunits);
snprintf(directionstr, MAX_ENV_STR, "UNIT_SUBUNITS_DIR=%d", direction_mask);
snprintf(directionstr, MAX_ENV_STR, "UNIT_SUBUNITS_DIR=%d",
direction_mask);
snprintf(revstr, MAX_ENV_STR, "XBUS_REVISION=%d", xbus->revision);
snprintf(connectorstr, MAX_ENV_STR, "XBUS_CONNECTOR=%s", xbus->connector);
snprintf(connectorstr, MAX_ENV_STR, "XBUS_CONNECTOR=%s",
xbus->connector);
snprintf(xbuslabel, MAX_ENV_STR, "XBUS_LABEL=%s", xbus->label);
if(snprintf(init_card, MAX_PATH_STR, "%s/init_card_%d_%d",
initdir, xpd->type, xbus->revision) > MAX_PATH_STR) {
XPD_NOTICE(xpd, "Cannot initialize. pathname is longer than %d characters.\n", MAX_PATH_STR);
if (snprintf
(init_card, MAX_PATH_STR, "%s/init_card_%d_%d", initdir, xpd->type,
xbus->revision) > MAX_PATH_STR) {
XPD_NOTICE(xpd,
"Cannot initialize. pathname is longer "
"than %d characters.\n",
MAX_PATH_STR);
ret = -E2BIG;
goto err;
}
if(!XBUS_IS(xbus, RECVD_DESC)) {
XBUS_ERR(xbus, "Skipped register initialization. In state %s.\n",
xbus_statename(XBUS_STATE(xbus)));
if (!XBUS_IS(xbus, RECVD_DESC)) {
XBUS_ERR(xbus,
"Skipped register initialization. In state %s.\n",
xbus_statename(XBUS_STATE(xbus)));
ret = -ENODEV;
goto err;
}
XPD_DBG(DEVICES, xpd, "running '%s' for type=%d revision=%d\n",
init_card, xpd->type, xbus->revision);
ret = call_usermodehelper(init_card, argv, envp, 1);
init_card, xpd->type, xbus->revision);
ret = call_usermodehelper(init_card, argv, envp, UMH_WAIT_PROC);
/*
* Carefully report results
*/
if(ret == 0)
if (ret == 0)
XPD_DBG(DEVICES, xpd, "'%s' finished OK\n", init_card);
else if(ret < 0) {
XPD_ERR(xpd, "Failed running '%s' (errno %d)\n", init_card, ret);
else if (ret < 0) {
XPD_ERR(xpd, "Failed running '%s' (errno %d)\n", init_card,
ret);
} else {
byte exitval = ((unsigned)ret >> 8) & 0xFF;
byte sigval = ret & 0xFF;
__u8 exitval = ((unsigned)ret >> 8) & 0xFF;
__u8 sigval = ret & 0xFF;
if(!exitval) {
XPD_ERR(xpd, "'%s' killed by signal %d\n", init_card, sigval);
if (!exitval) {
XPD_ERR(xpd, "'%s' killed by signal %d\n", init_card,
sigval);
} else {
XPD_ERR(xpd, "'%s' aborted with exitval %d\n", init_card, exitval);
XPD_ERR(xpd, "'%s' aborted with exitval %d\n",
init_card, exitval);
}
ret = -EINVAL;
}
err:
return ret;
}
EXPORT_SYMBOL(sync_mode_name);
EXPORT_SYMBOL(run_initialize_registers);
EXPORT_SYMBOL(xpp_register_request);

View File

@@ -26,88 +26,60 @@
#include "xbus-pcm.h"
enum global_opcodes {
XPROTO_NAME(GLOBAL, AB_REQUEST) = 0x07,
XPROTO_NAME(GLOBAL, AB_DESCRIPTION) = 0x08,
XPROTO_NAME(GLOBAL, REGISTER_REQUEST) = 0x0F,
XPROTO_NAME(GLOBAL, REGISTER_REPLY) = 0x10,
/**/
XPROTO_NAME(GLOBAL, PCM_WRITE) = 0x11,
XPROTO_NAME(GLOBAL, PCM_READ) = 0x12,
/**/
XPROTO_NAME(GLOBAL, SYNC_SOURCE) = 0x19,
XPROTO_NAME(GLOBAL, SYNC_REPLY) = 0x1A,
/**/
XPROTO_NAME(GLOBAL, ERROR_CODE) = 0x22,
XPROTO_NAME(GLOBAL, RESET_SYNC_COUNTERS) = 0x23,
XPROTO_NAME(GLOBAL, NULL_REPLY) = 0xFE,
XPROTO_NAME(GLOBAL, AB_REQUEST) = 0x07,
XPROTO_NAME(GLOBAL, AB_DESCRIPTION) = 0x08,
XPROTO_NAME(GLOBAL, REGISTER_REQUEST) = 0x0F,
XPROTO_NAME(GLOBAL, REGISTER_REPLY) = 0x10,
/**/ XPROTO_NAME(GLOBAL, PCM_WRITE) = 0x11,
XPROTO_NAME(GLOBAL, PCM_READ) = 0x12,
/**/ XPROTO_NAME(GLOBAL, SYNC_SOURCE) = 0x19,
XPROTO_NAME(GLOBAL, SYNC_REPLY) = 0x1A,
/**/ XPROTO_NAME(GLOBAL, ERROR_CODE) = 0x22,
XPROTO_NAME(GLOBAL, XBUS_RESET) = 0x23,
XPROTO_NAME(GLOBAL, NULL_REPLY) = 0xFE,
};
struct unit_descriptor {
struct xpd_addr addr;
byte subtype:4;
byte type:4;
byte numchips;
byte ports_per_chip;
byte port_dir; /* bitmask: 0 - PSTN, 1 - PHONE */
byte reserved[2];
struct xpd_addr ec_addr;
struct xpd_addr addr;
__u8 subtype:4;
__u8 type:4;
__u8 numchips;
__u8 ports_per_chip;
__u8 port_dir; /* bitmask: 0 - PSTN, 1 - PHONE */
__u8 reserved[2];
struct xpd_addr ec_addr;
};
#define NUM_UNITS 6
DEF_RPACKET_DATA(GLOBAL, NULL_REPLY);
DEF_RPACKET_DATA(GLOBAL, AB_REQUEST,
byte rev;
byte reserved;
);
DEF_RPACKET_DATA(GLOBAL, AB_DESCRIPTION,
byte rev;
byte reserved[3];
struct unit_descriptor unit_descriptor[NUM_UNITS];
);
DEF_RPACKET_DATA(GLOBAL, REGISTER_REQUEST,
reg_cmd_t reg_cmd;
);
DEF_RPACKET_DATA(GLOBAL, PCM_WRITE,
xpp_line_t lines;
byte pcm[PCM_CHUNKSIZE];
);
DEF_RPACKET_DATA(GLOBAL, PCM_READ,
xpp_line_t lines;
byte pcm[PCM_CHUNKSIZE];
);
DEF_RPACKET_DATA(GLOBAL, SYNC_SOURCE,
byte sync_mode;
byte drift;
);
DEF_RPACKET_DATA(GLOBAL, SYNC_REPLY,
byte sync_mode;
byte drift;
);
DEF_RPACKET_DATA(GLOBAL, REGISTER_REPLY,
reg_cmd_t regcmd;
);
DEF_RPACKET_DATA(GLOBAL, RESET_SYNC_COUNTERS,
byte mask;
);
DEF_RPACKET_DATA(GLOBAL, ERROR_CODE,
byte category_code;
byte errorbits;
byte bad_packet[0];
);
DEF_RPACKET_DATA(GLOBAL, AB_REQUEST, __u8 rev; __u8 reserved;);
DEF_RPACKET_DATA(GLOBAL, AB_DESCRIPTION, __u8 rev; __u8 reserved[3];
struct unit_descriptor unit_descriptor[NUM_UNITS];);
DEF_RPACKET_DATA(GLOBAL, REGISTER_REQUEST, reg_cmd_t reg_cmd;);
DEF_RPACKET_DATA(GLOBAL, PCM_WRITE, xpp_line_t lines; __u8 pcm[PCM_CHUNKSIZE];);
DEF_RPACKET_DATA(GLOBAL, PCM_READ, xpp_line_t lines; __u8 pcm[PCM_CHUNKSIZE];);
DEF_RPACKET_DATA(GLOBAL, SYNC_SOURCE, __u8 sync_mode; __u8 drift;);
DEF_RPACKET_DATA(GLOBAL, SYNC_REPLY, __u8 sync_mode; __u8 drift;);
DEF_RPACKET_DATA(GLOBAL, REGISTER_REPLY, reg_cmd_t regcmd;);
DEF_RPACKET_DATA(GLOBAL, XBUS_RESET, __u8 mask;);
DEF_RPACKET_DATA(GLOBAL, ERROR_CODE, __u8 category_code; __u8 errorbits;
__u8 bad_packet[0];);
/* 0x07 */ DECLARE_CMD(GLOBAL, AB_REQUEST);
/* 0x19 */ DECLARE_CMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift);
/* 0x23 */ DECLARE_CMD(GLOBAL, RESET_SPI);
/* 0x23 */ DECLARE_CMD(GLOBAL, RESET_SYNC_COUNTERS);
int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
bool writing, byte regnum, bool do_subreg, byte subreg,
byte data_low, bool do_datah, byte data_high, bool should_reply);
bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
__u8 data_low, bool do_datah, __u8 data_high,
bool should_reply);
int send_multibyte_request(xbus_t *xbus, unsigned unit, xportno_t portno,
bool eoftx, byte *buf, unsigned len);
bool eoftx, __u8 *buf, unsigned len);
extern xproto_table_t PROTO_TABLE(GLOBAL);
int run_initialize_registers(xpd_t *xpd);
int parse_chip_command(xpd_t *xpd, char *cmdline);
extern charp initdir;
#endif /* CARD_GLOBAL_H */
#endif /* CARD_GLOBAL_H */

File diff suppressed because it is too large Load Diff

View File

@@ -25,8 +25,7 @@
#include "xpd.h"
enum pri_opcodes {
XPROTO_NAME(PRI, SET_LED) = 0x33,
XPROTO_NAME(PRI, SET_LED) = 0x33,
};
#endif /* CARD_PRI_H */
#endif /* CARD_PRI_H */

View File

@@ -20,11 +20,6 @@
*
*/
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
# warning "This module is tested only with 2.6 kernels"
#endif
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/module.h>
@@ -35,57 +30,48 @@
static const char rcsid[] = "$Id$";
#define P_(x) [ x ] = { .value = x, .name = #x, }
static struct {
static struct {
int value;
char *name;
} poll_names[] = {
P_(POLLIN),
P_(POLLPRI),
P_(POLLOUT),
P_(POLLERR),
P_(POLLHUP),
P_(POLLNVAL),
P_(POLLRDNORM),
P_(POLLRDBAND),
P_(POLLWRNORM),
P_(POLLWRBAND),
P_(POLLMSG),
P_(POLLREMOVE)
P_(POLLIN), P_(POLLPRI), P_(POLLOUT), P_(POLLERR), P_(POLLHUP),
P_(POLLNVAL), P_(POLLRDNORM), P_(POLLRDBAND), P_(POLLWRNORM),
P_(POLLWRBAND), P_(POLLMSG), P_(POLLREMOVE)
};
#undef P_
void dump_poll(int debug, const char *msg, int poll)
{
int i;
int i;
for(i = 0; i < ARRAY_SIZE(poll_names); i++) {
if(poll & poll_names[i].value)
for (i = 0; i < ARRAY_SIZE(poll_names); i++) {
if (poll & poll_names[i].value)
DBG(GENERAL, "%s: %s\n", msg, poll_names[i].name);
}
}
EXPORT_SYMBOL(dump_poll);
void alarm2str(int alarm, char *buf, int buflen)
{
char *p = buf;
int left = buflen;
int i;
int n;
char *p = buf;
int left = buflen;
int i;
int n;
if(!alarm) {
if (!alarm) {
snprintf(buf, buflen, "NONE");
return;
}
memset(buf, 0, buflen);
for(i = 0; i < 8; i++) {
if(left && (alarm & BIT(i))) {
for (i = 0; i < 8; i++) {
if (left && (alarm & BIT(i))) {
n = snprintf(p, left, "%s,", alarmbit2str(i));
p += n;
left -= n;
}
}
if(p > buf) /* kill last comma */
if (p > buf) /* kill last comma */
*(p - 1) = '\0';
}
EXPORT_SYMBOL(dump_poll);
EXPORT_SYMBOL(alarm2str);

View File

@@ -26,55 +26,76 @@
/* Debugging Macros */
#define PRINTK(level, category, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: " fmt, #level, category, THIS_MODULE->name, ## __VA_ARGS__)
#define PRINTK(level, category, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: " fmt, \
#level, category, THIS_MODULE->name, ## __VA_ARGS__)
#define XBUS_PRINTK(level, category, xbus, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: %s: " fmt, #level, \
#define XBUS_PRINTK(level, category, xbus, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: %s: " fmt, #level, \
category, THIS_MODULE->name, (xbus)->busname, ## __VA_ARGS__)
#define XPD_PRINTK(level, category, xpd, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: %s/%s: " fmt, #level, \
category, THIS_MODULE->name, (xpd)->xbus->busname, (xpd)->xpdname, ## __VA_ARGS__)
#define XPD_PRINTK(level, category, xpd, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: %s/%s: " fmt, #level, \
category, THIS_MODULE->name, \
(xpd)->xbus->busname, (xpd)->xpdname, ## __VA_ARGS__)
#define LINE_PRINTK(level, category, xpd, pos, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: %s/%s/%d: " fmt, #level, \
category, THIS_MODULE->name, (xpd)->xbus->busname, (xpd)->xpdname, (pos), ## __VA_ARGS__)
#define LINE_PRINTK(level, category, xpd, pos, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: %s/%s/%d: " fmt, #level, \
category, THIS_MODULE->name, \
(xpd)->xbus->busname, (xpd)->xpdname, (pos), ## __VA_ARGS__)
#define PORT_PRINTK(level, category, xbus, unit, port, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: %s UNIT=%d PORT=%d: " fmt, #level, \
category, THIS_MODULE->name, (xbus)->busname, (unit), (port), ## __VA_ARGS__)
#define PORT_PRINTK(level, category, xbus, unit, port, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: %s UNIT=%d PORT=%d: " fmt, #level, \
category, THIS_MODULE->name, \
(xbus)->busname, (unit), (port), ## __VA_ARGS__)
#define DBG(bits, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && PRINTK(DEBUG, "-" #bits, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)))
#define DBG(bits, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && \
PRINTK(DEBUG, "-" #bits, "%s: " fmt, \
__func__, ## __VA_ARGS__)))
#define INFO(fmt, ...) PRINTK(INFO, "", fmt, ## __VA_ARGS__)
#define NOTICE(fmt, ...) PRINTK(NOTICE, "", fmt, ## __VA_ARGS__)
#define WARNING(fmt, ...) PRINTK(WARNING, "", fmt, ## __VA_ARGS__)
#define ERR(fmt, ...) PRINTK(ERR, "", fmt, ## __VA_ARGS__)
#define XBUS_DBG(bits, xbus, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && XBUS_PRINTK(DEBUG, "-" #bits, xbus, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)))
#define XBUS_INFO(xbus, fmt, ...) XBUS_PRINTK(INFO, "", xbus, fmt, ## __VA_ARGS__)
#define XBUS_NOTICE(xbus, fmt, ...) XBUS_PRINTK(NOTICE, "", xbus, fmt, ## __VA_ARGS__)
#define XBUS_ERR(xbus, fmt, ...) XBUS_PRINTK(ERR, "", xbus, fmt, ## __VA_ARGS__)
#define XBUS_DBG(bits, xbus, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && XBUS_PRINTK(DEBUG, "-" #bits, \
xbus, "%s: " fmt, __func__, ## __VA_ARGS__)))
#define XBUS_INFO(xbus, fmt, ...) \
XBUS_PRINTK(INFO, "", xbus, fmt, ## __VA_ARGS__)
#define XBUS_NOTICE(xbus, fmt, ...) \
XBUS_PRINTK(NOTICE, "", xbus, fmt, ## __VA_ARGS__)
#define XBUS_ERR(xbus, fmt, ...) \
XBUS_PRINTK(ERR, "", xbus, fmt, ## __VA_ARGS__)
#define XPD_DBG(bits, xpd, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && XPD_PRINTK(DEBUG, "-" #bits, xpd, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)))
#define XPD_INFO(xpd, fmt, ...) XPD_PRINTK(INFO, "", xpd, fmt, ## __VA_ARGS__)
#define XPD_NOTICE(xpd, fmt, ...) XPD_PRINTK(NOTICE, "", xpd, fmt, ## __VA_ARGS__)
#define XPD_WARNING(xpd, fmt, ...) XPD_PRINTK(WARNING, "", xpd, fmt, ## __VA_ARGS__)
#define XPD_ERR(xpd, fmt, ...) XPD_PRINTK(ERR, "", xpd, fmt, ## __VA_ARGS__)
#define XPD_DBG(bits, xpd, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && XPD_PRINTK(DEBUG, "-" #bits, \
xpd, "%s: " fmt, __func__, ## __VA_ARGS__)))
#define XPD_INFO(xpd, fmt, ...) \
XPD_PRINTK(INFO, "", xpd, fmt, ## __VA_ARGS__)
#define XPD_NOTICE(xpd, fmt, ...) \
XPD_PRINTK(NOTICE, "", xpd, fmt, ## __VA_ARGS__)
#define XPD_WARNING(xpd, fmt, ...) \
XPD_PRINTK(WARNING, "", xpd, fmt, ## __VA_ARGS__)
#define XPD_ERR(xpd, fmt, ...) \
XPD_PRINTK(ERR, "", xpd, fmt, ## __VA_ARGS__)
#define LINE_DBG(bits, xpd, pos, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && LINE_PRINTK(DEBUG, "-" #bits, xpd, pos, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)))
#define LINE_NOTICE(xpd, pos, fmt, ...) LINE_PRINTK(NOTICE, "", xpd, pos, fmt, ## __VA_ARGS__)
#define LINE_ERR(xpd, pos, fmt, ...) LINE_PRINTK(ERR, "", xpd, pos, fmt, ## __VA_ARGS__)
#define LINE_DBG(bits, xpd, pos, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && LINE_PRINTK(DEBUG, "-" #bits, \
xpd, pos, "%s: " fmt, __func__, ## __VA_ARGS__)))
#define LINE_NOTICE(xpd, pos, fmt, ...) \
LINE_PRINTK(NOTICE, "", xpd, pos, fmt, ## __VA_ARGS__)
#define LINE_ERR(xpd, pos, fmt, ...) \
LINE_PRINTK(ERR, "", xpd, pos, fmt, ## __VA_ARGS__)
#define PORT_DBG(bits, xbus, unit, port, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && PORT_PRINTK(DEBUG, "-" #bits, \
xbus, unit, port, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)))
#define PORT_NOTICE(xbus, unit, port, fmt, ...) PORT_PRINTK(NOTICE, "", xbus, unit, port, fmt, ## __VA_ARGS__)
#define PORT_ERR(xbus, unit, port, fmt, ...) PORT_PRINTK(ERR, "", xbus, unit, port, fmt, ## __VA_ARGS__)
#define PORT_DBG(bits, xbus, unit, port, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && \
PORT_PRINTK(DEBUG, "-" #bits, \
xbus, unit, port, "%s: " fmt, __func__, ## __VA_ARGS__)))
#define PORT_NOTICE(xbus, unit, port, fmt, ...) \
PORT_PRINTK(NOTICE, "", xbus, unit, port, fmt, ## __VA_ARGS__)
#define PORT_ERR(xbus, unit, port, fmt, ...) \
PORT_PRINTK(ERR, "", xbus, unit, port, fmt, ## __VA_ARGS__)
/*
* Bits for debug
@@ -94,63 +115,98 @@ void dump_poll(int debug, const char *msg, int poll);
static inline char *rxsig2str(enum dahdi_rxsig sig)
{
switch(sig) {
case DAHDI_RXSIG_ONHOOK: return "ONHOOK";
case DAHDI_RXSIG_OFFHOOK: return "OFFHOOK";
case DAHDI_RXSIG_START: return "START";
case DAHDI_RXSIG_RING: return "RING";
case DAHDI_RXSIG_INITIAL: return "INITIAL";
switch (sig) {
case DAHDI_RXSIG_ONHOOK:
return "ONHOOK";
case DAHDI_RXSIG_OFFHOOK:
return "OFFHOOK";
case DAHDI_RXSIG_START:
return "START";
case DAHDI_RXSIG_RING:
return "RING";
case DAHDI_RXSIG_INITIAL:
return "INITIAL";
}
return "Unknown rxsig";
}
static inline char *txsig2str(enum dahdi_txsig sig)
{
switch(sig) {
case DAHDI_TXSIG_ONHOOK: return "TXSIG_ONHOOK";
case DAHDI_TXSIG_OFFHOOK: return "TXSIG_OFFHOOK";
case DAHDI_TXSIG_START: return "TXSIG_START";
case DAHDI_TXSIG_KEWL: return "TXSIG_KEWL"; /* Drop battery if possible */
case DAHDI_TXSIG_TOTAL: break;
switch (sig) {
case DAHDI_TXSIG_ONHOOK:
return "TXSIG_ONHOOK";
case DAHDI_TXSIG_OFFHOOK:
return "TXSIG_OFFHOOK";
case DAHDI_TXSIG_START:
return "TXSIG_START";
case DAHDI_TXSIG_KEWL:
return "TXSIG_KEWL"; /* Drop battery if possible */
case DAHDI_TXSIG_TOTAL:
break;
}
return "Unknown txsig";
}
static inline char *event2str(int event)
{
switch(event) {
case DAHDI_EVENT_NONE: return "NONE";
case DAHDI_EVENT_ONHOOK: return "ONHOOK";
case DAHDI_EVENT_RINGOFFHOOK: return "RINGOFFHOOK";
case DAHDI_EVENT_WINKFLASH: return "WINKFLASH";
case DAHDI_EVENT_ALARM: return "ALARM";
case DAHDI_EVENT_NOALARM: return "NOALARM";
case DAHDI_EVENT_ABORT: return "ABORT";
case DAHDI_EVENT_OVERRUN: return "OVERRUN";
case DAHDI_EVENT_BADFCS: return "BADFCS";
case DAHDI_EVENT_DIALCOMPLETE: return "DIALCOMPLETE";
case DAHDI_EVENT_RINGERON: return "RINGERON";
case DAHDI_EVENT_RINGEROFF: return "RINGEROFF";
case DAHDI_EVENT_HOOKCOMPLETE: return "HOOKCOMPLETE";
case DAHDI_EVENT_BITSCHANGED: return "BITSCHANGED";
case DAHDI_EVENT_PULSE_START: return "PULSE_START";
case DAHDI_EVENT_TIMER_EXPIRED: return "TIMER_EXPIRED";
case DAHDI_EVENT_TIMER_PING: return "TIMER_PING";
case DAHDI_EVENT_POLARITY: return "POLARITY";
switch (event) {
case DAHDI_EVENT_NONE:
return "NONE";
case DAHDI_EVENT_ONHOOK:
return "ONHOOK";
case DAHDI_EVENT_RINGOFFHOOK:
return "RINGOFFHOOK";
case DAHDI_EVENT_WINKFLASH:
return "WINKFLASH";
case DAHDI_EVENT_ALARM:
return "ALARM";
case DAHDI_EVENT_NOALARM:
return "NOALARM";
case DAHDI_EVENT_ABORT:
return "ABORT";
case DAHDI_EVENT_OVERRUN:
return "OVERRUN";
case DAHDI_EVENT_BADFCS:
return "BADFCS";
case DAHDI_EVENT_DIALCOMPLETE:
return "DIALCOMPLETE";
case DAHDI_EVENT_RINGERON:
return "RINGERON";
case DAHDI_EVENT_RINGEROFF:
return "RINGEROFF";
case DAHDI_EVENT_HOOKCOMPLETE:
return "HOOKCOMPLETE";
case DAHDI_EVENT_BITSCHANGED:
return "BITSCHANGED";
case DAHDI_EVENT_PULSE_START:
return "PULSE_START";
case DAHDI_EVENT_TIMER_EXPIRED:
return "TIMER_EXPIRED";
case DAHDI_EVENT_TIMER_PING:
return "TIMER_PING";
case DAHDI_EVENT_POLARITY:
return "POLARITY";
}
return "Unknown event";
}
static inline char *hookstate2str(int hookstate)
{
switch(hookstate) {
case DAHDI_ONHOOK: return "DAHDI_ONHOOK";
case DAHDI_START: return "DAHDI_START";
case DAHDI_OFFHOOK: return "DAHDI_OFFHOOK";
case DAHDI_WINK: return "DAHDI_WINK";
case DAHDI_FLASH: return "DAHDI_FLASH";
case DAHDI_RING: return "DAHDI_RING";
case DAHDI_RINGOFF: return "DAHDI_RINGOFF";
switch (hookstate) {
case DAHDI_ONHOOK:
return "DAHDI_ONHOOK";
case DAHDI_START:
return "DAHDI_START";
case DAHDI_OFFHOOK:
return "DAHDI_OFFHOOK";
case DAHDI_WINK:
return "DAHDI_WINK";
case DAHDI_FLASH:
return "DAHDI_FLASH";
case DAHDI_RING:
return "DAHDI_RING";
case DAHDI_RINGOFF:
return "DAHDI_RINGOFF";
}
return "Unknown hookstate";
}
@@ -159,25 +215,42 @@ static inline char *hookstate2str(int hookstate)
static inline char *sig2str(int sig)
{
switch (sig) {
case DAHDI_SIG_FXSLS: return "FXSLS";
case DAHDI_SIG_FXSKS: return "FXSKS";
case DAHDI_SIG_FXSGS: return "FXSGS";
case DAHDI_SIG_FXOLS: return "FXOLS";
case DAHDI_SIG_FXOKS: return "FXOKS";
case DAHDI_SIG_FXOGS: return "FXOGS";
case DAHDI_SIG_EM: return "E&M";
case DAHDI_SIG_EM_E1: return "E&M-E1";
case DAHDI_SIG_CLEAR: return "Clear";
case DAHDI_SIG_HDLCRAW: return "HDLCRAW";
case DAHDI_SIG_HDLCFCS: return "HDLCFCS";
case DAHDI_SIG_HDLCNET: return "HDLCNET";
case DAHDI_SIG_SLAVE: return "Slave";
case DAHDI_SIG_CAS: return "CAS";
case DAHDI_SIG_DACS: return "DACS";
case DAHDI_SIG_DACS_RBS: return "DACS+RBS";
case DAHDI_SIG_SF: return "SF (ToneOnly)";
case DAHDI_SIG_NONE:
break;
case DAHDI_SIG_FXSLS:
return "FXSLS";
case DAHDI_SIG_FXSKS:
return "FXSKS";
case DAHDI_SIG_FXSGS:
return "FXSGS";
case DAHDI_SIG_FXOLS:
return "FXOLS";
case DAHDI_SIG_FXOKS:
return "FXOKS";
case DAHDI_SIG_FXOGS:
return "FXOGS";
case DAHDI_SIG_EM:
return "E&M";
case DAHDI_SIG_EM_E1:
return "E&M-E1";
case DAHDI_SIG_CLEAR:
return "Clear";
case DAHDI_SIG_HDLCRAW:
return "HDLCRAW";
case DAHDI_SIG_HDLCFCS:
return "HDLCFCS";
case DAHDI_SIG_HDLCNET:
return "HDLCNET";
case DAHDI_SIG_SLAVE:
return "Slave";
case DAHDI_SIG_CAS:
return "CAS";
case DAHDI_SIG_DACS:
return "DACS";
case DAHDI_SIG_DACS_RBS:
return "DACS+RBS";
case DAHDI_SIG_SF:
return "SF (ToneOnly)";
case DAHDI_SIG_NONE:
break;
}
return "Unconfigured";
}
@@ -185,18 +258,25 @@ static inline char *sig2str(int sig)
static inline char *alarmbit2str(int alarmbit)
{
/* from dahdi/kernel.h */
switch(1 << alarmbit) {
case DAHDI_ALARM_NONE: return "NONE";
case DAHDI_ALARM_RECOVER: return "RECOVER";
case DAHDI_ALARM_LOOPBACK: return "LOOPBACK";
case DAHDI_ALARM_YELLOW: return "YELLOW";
case DAHDI_ALARM_RED: return "RED";
case DAHDI_ALARM_BLUE: return "BLUE";
case DAHDI_ALARM_NOTOPEN: return "NOTOPEN";
switch (1 << alarmbit) {
case DAHDI_ALARM_NONE:
return "NONE";
case DAHDI_ALARM_RECOVER:
return "RECOVER";
case DAHDI_ALARM_LOOPBACK:
return "LOOPBACK";
case DAHDI_ALARM_YELLOW:
return "YELLOW";
case DAHDI_ALARM_RED:
return "RED";
case DAHDI_ALARM_BLUE:
return "BLUE";
case DAHDI_ALARM_NOTOPEN:
return "NOTOPEN";
}
return "UNKNOWN";
}
void alarm2str(int alarm, char *buf, int buflen);
#endif /* DAHDI_DEBUG_H */
#endif /* DAHDI_DEBUG_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,12 @@
# Install firmwares and initialization scripts for the Astribank
# drivers
FPGA_FW = FPGA_FXS.hex FPGA_1141.hex FPGA_1151.hex FPGA_1161.hex
USB_FW = USB_FW.hex USB_FW.201.hex USB_RECOV.hex
FPGA_FW = FPGA_FXS.hex FPGA_1141.hex FPGA_1151.hex FPGA_1161.hex \
FPGA_1161.201.hex
PIC_FW = PIC_TYPE_1.hex PIC_TYPE_2.hex PIC_TYPE_3.hex PIC_TYPE_4.hex
OCT_FW = $(wildcard OCT6104E-256D.ima)
FIRMWARES = USB_FW.hex $(FPGA_FW) $(PIC_FW) $(OCT_FW)
FIRMWARES = $(USB_FW) $(FPGA_FW) $(PIC_FW) $(OCT_FW)
PROTO_VER = 30
SCRIPTS_BASE = $(patsubst %,init_card_%_$(PROTO_VER),1 2 3 4 5)
SCRIPTS = $(SCRIPTS_BASE:%=../%)

View File

@@ -1,7 +1,7 @@
#
# $Id: PIC_TYPE_2.hex 9732 2011-08-24 19:13:55Z dima $
# $Id: PIC_TYPE_2.hex 11078 2013-04-11 16:52:37Z dima $
#
:03000000A57A4896
:03000000A5DA4836
:03000100C41C41DB
:030002000390392F
:0300030067967984
@@ -42,319 +42,375 @@
:03002600CFC9013E
:030027001652026C
:0300280064403001
:03002900A3290107
:03002900A38901A7
:03002A00704C40D7
:03002B00A41FFF10
:03002C00C011659B
:03002D001E1C0294
:03002E00C03FFFD1
:03002F0016115057
:030030002016B9DE
:03003100125D025B
:0300320020A022E9
:03003300643C0228
:03003400A3AD0178
:03003500365162DF
:030036003652053A
:030037002C8030EA
:03003800D00901EB
:03003900A33204EB
:03003A0020503023
:03003B0072490106
:03003C00A3E2023A
:03003D00A40030EC
:03003E0002D901E3
:03003F00A4180002
:0300400002E214C5
:03004100800E70BE
:030042000223088E
:030043002063082F
:030044006433081A
:03004500A4A30869
:0300460032203F26
:030047002C880002
:03004800D00C00D9
:03004900A4403997
:03004A00CFE038CC
:03004B00162C0769
:03004C00C01D4094
:03004D00604034DC
:03004E00122C0869
:03004F00206038F6
:03005000643219FE
:03005100A56E0792
:0300520036202035
:030053002C83609B
:03005400D0036076
:03005500A50360A0
:03005600800360C4
:03005700C07C105A
:03005800166038F7
:03005900743219E5
:03005A00A5FE07F9
:03005B00C01120B1
:03005C001CCC2099
:03005D00E07180CF
:03005E0002CE705F
:03005F00206743D4
:0300600090AA70F3
:03006100205C021E
:03006200D2018048
:03006300D40E07B1
:0300640003D6437D
:03006500C1CA739A
:03002B00A47FFFB0
:03002C00C40165A7
:03002D00150C02AD
:03002E00743FFF1D
:03002F00A32150BA
:03003000C026B92E
:03003100A33D02EA
:03003200C01022D9
:03003300121C029A
:03003400C03D01CB
:030035001611623F
:0300360020120590
:0300370012503034
:0300380020A901FB
:030039006432042A
:03003A00A40030EF
:03003B0036590132
:03003C0036520237
:03003D002C8030E4
:03003E00D00901E5
:03003F00A3980083
:0300400020521437
:03004100724E708C
:03004200A44308CC
:03004300A46308AB
:0300440002D308DC
:03004500A4730899
:0300460002E03F96
:030047008008002E
:03004800022C0087
:03004900206039FB
:03004A00643038E7
:03004B00A50C07FA
:03004C00322D4012
:03004D002C8034D0
:03004E00D00C08CB
:03004F00A4A03832
:03005000CFE219E3
:03005100162E0761
:03005200C01020BB
:03005300604360A7
:0300540012236014
:03005500206360C5
:03005600643360B0
:03005700A5CC1025
:0300580036203817
:030059002C8219DD
:03005A00D00E07BE
:03005B00A561207C
:03005C00800C20F5
:03005D00C07180EF
:03005E00166E70AB
:03005F00743743B0
:03006000A65A702D
:03006100C01C02BE
:030062001CC1803E
:03006300E07E0735
:0300640002C6438E
:03006500200A73FB
:03006600022C0366
:03006700C0018055
:03006800024E073E
:0300690021D6435A
:03006A00030A7313
:03006B00901C04E2
:03006C00202180D0
:03006D00030E0778
:03006E00901643A6
:03006F00204A73B1
:03007000030C017D
:03007100901038B4
:03007200210A72EE
:03007300024C1824
:03007400C0303861
:0300750008421925
:03007600603E0FDA
:03007700A7A0221D
:03007800209C00C9
:03007900A7C038E5
:0300670020618095
:03006800643E07EC
:03006900A6E643C5
:03006A00322A73C4
:03006B002C8C04D6
:03006C00D0018040
:03006D00A68E0755
:03006E00C0164376
:03006F00142A73DD
:03007000743C01DC
:03007100ACB038F8
:03007200206A728F
:0300730090AC1836
:03007400205038E1
:03007500D202199B
:03007600D40E0F96
:0300770003D02291
:03007800C04C0079
:030079000220382A
:03007A00C00200C1
:03007B00A7CE0706
:03007C00187F02E8
:03007D0014974392
:03007E00643A835E
:03007F00AABC0018
:030080001A7031C2
:03008100C50C1299
:03008200039A904E
:030083007992006F
:03008400A83E078C
:0300850020BF0396
:03008600D007435D
:03008700038A8C5D
:03008800219C00B8
:03008900E07031F3
:03008A00348C189B
:03008B00348A9024
:03008C00348C00B1
:03008D003480318B
:03008E00030C164A
:03008F00206A9054
:0300900034803B7E
:03009100348E0F9B
:0300920034808235
:03009300348703AC
:03009400D05A9AA5
:03009500031C0F3A
:03009600C00FFF99
:0300970003215BE7
:030098000331022F
:03009900C70A9BF8
:03009A0003921BB3
:03009B00C500306D
:03009C00039E0FB1
:03009D00C1C03BA4
:03009E00030C024E
:03009F00C0003965
:0300A000031C003E
:0300A100204039C3
:0300A200032C80AC
:03007B00024E072B
:03007C0021DF027F
:03007D0003074333
:03007E00901A8352
:03007F00202C0032
:0300800003003149
:03008100901C12BE
:03008200204A9081
:0300830003020075
:03008400901E07C4
:03008500210F0345
:03008600E017433D
:03008700643A8C4C
:03008800ACBC000D
:0300890021003122
:03008A00024C180D
:03008B00E80A90F0
:03008C00743C00C1
:03008D00AB803114
:03008E00C50C1688
:03008F00039A9041
:0300900079903B29
:03009100A90E0FA6
:0300920020B08219
:03009300D0070390
:03009400038A9A42
:03009500219C0F9C
:03009600E07FFF09
:0300970034815B56
:03009800348102AE
:03009900348A9B0B
:03009A0034821B92
:03009B000300302F
:03009C00206E0FC4
:03009D0034803B71
:03009E00348C029D
:03009F0034803971
:0300A000348C009D
:0300A100D0503903
:0300A200031C80BC
:0300A300C00D0885
:0300A400033039ED
:0300A500C70C0085
:0300A6000390398B
:0300A700C50C4045
:0300A80003903989
:0300A900C407D9B0
:0300AA00039AA90D
:0300AB0020CC0066
:0300AC0074302687
:0300AD00B1702708
:0300AE00C0002B64
:0300AF00024020EC
:0300B000C05C032E
:0300B10002202CFE
:0300B200205C20AF
:0300B300D20D80EB
:0300B400D4002550
:0300B50003DC2049
:0300B60021D02432
:0300B700030C0037
:0300B80090102283
:0300B900202205FD
:0300BA0003003010
:0300BB0090190198
:0300BC00204204DB
:0300BD000300300D
:0300BE0090190195
:0300BF00C012026A
:0300A400032039FD
:0300A500033C0019
:0300A600C7003957
:0300A700039C4077
:0300A800C5003957
:0300A9000397D9E1
:0300AA00C04AA9A0
:0300AB00030C0043
:0300AC00C000266B
:0300AD0003102716
:0300AE0020402BC4
:0300AF000320200B
:0300B000C00C037E
:0300B10003302CED
:0300B200C70C2058
:0300B300039D802A
:0300B400C500255F
:0300B500039C2089
:0300B600C400245F
:0300B700039C00A7
:0300B800C400225F
:0300B900FFF2054E
:0300BA00165030AD
:0300BB00D2090166
:0300BC0003D20468
:0300BD00C0403010
:0300BE0002290113
:0300BF00C002027A
:0300C000150030F8
:0300C100024901F0
:0300C20021AC402E
:0300C3009420394D
:0300C400202C01EC
:0300C50003A0375E
:0300C600206C604B
:0300C7007432C8C8
:0300C800AD5AC767
:0300C900C9FC006F
:0300CA0016B03736
:0300CB00C006D993
:0300CC006B0AD0EC
:0300CD00D206F95F
:0300CE006D0B4D6A
:0300C20021DC40FE
:0300C300030039FE
:0300C400901C018C
:0300C500202037C1
:0300C600030C60C8
:0300C7009012C8CC
:0300C800204AC704
:0300C900030C0025
:0300CA009010375C
:0300CB002066D9D3
:0300CC0090AAD027
:0300CD002056F9C1
:0300CE00D20B4D05
:0300CF00D40ACB85
:0300D00012B94022
:0300D100C80C2038
:0300D2001AB195CB
:0300D30020B64311
:0300D400038ADFBD
:0300D500206C019B
:0300D60002A1DFA5
:0300D700C0409B8B
:0300D800086703B3
:0300D900703ADF9B
:0300DA00ADE7D3BC
:0300DB00C00B480F
:0300DC00024CFFD4
:0300DD00AE202230
:0300DE00C04B2AEA
:0300DF000AA21F53
:0300E000C0290A2A
:0300E100024C20AE
:0300E200917125F4
:0300E300C016D371
:0300E40003EAEA42
:0300E500206C206C
:0300E600643095EE
:0300E700AEB6436F
:0300E80037EAF202
:0300E9002C8AEF6F
:0300EA00AE8C4099
:0300EB00C6012526
:0300EC00150C00F0
:0300ED0074302448
:0300EE00AFFB1A4B
:0300EF0021E217F4
:0300F0001AF024DF
:0300F10014FB1AE3
:0300F200743C401B
:0300F300B17105E3
:0300F400C0403DCC
:0300F500124C00AA
:0300F600917024E2
:0300F700C0021D27
:0300F80002403093
:0300F900200901DA
:0300FA0094221538
:0300FB0020203092
:0300FC00020901F5
:0300FD00035204A7
:0300FE00B17030AE
:0300FF00CFF90135
:0301000019E210F1
:0301010016F024D1
:03010200C037F70C
:03010300081B0BCB
:03010400743C0246
:03010500B0EFFF59
:03010600C01164C1
:03010700024C02A5
:030108002001577C
:030109009421241A
:03010A00202B1790
:03010B000207D711
:03010C00035B177B
:03010D00B17C01C1
:03010E00C00FFF20
:03010F0018116460
:03011000643C014B
:030111006B015728
:03011200B14124D4
:03011300B17B17A6
:03011400C01217FF
:0301150012402471
:03011600917B17C3
:03011700369C0211
:03011800C01D0106
:030119001E616400
:03011A0021BC8085
:03011B000866F380
:03011C0074312516
:03011D00A57205C3
:03011E000260304C
:03011F00C02901F3
:03012000FFF215D6
:0301210016B030E5
:03012200C02901F0
:0301230023A20410
:0301240074303004
:0301250012B9010B
:0301260020B7D32C
:03012700038B48FF
:03012800C44210BE
:030129000390221E
:03012A00C40C50B2
:03012B0003903905
:03012C00C0079970
:03012D00023B2C66
:03012E00AC2212EE
:03012F00B2F030FB
:03013000000214B6
:030131000000319A
:03013200000213B5
:0301330000003297
:03013400000C00BC
:0301350000003394
:03013600000C704A
:030137000000398C
:03013800000C5068
:030139000000398A
:03013A00000215AB
:03013B0000003091
:03013C00000C00B4
:03013D000000318E
:03013E00000202BA
:03013F000000328B
:03014000000C00B0
:0301410000003388
:03014200000C703E
:0301430000003980
:03014400000C505C
:030145000000397E
:03014600000C406A
:030147000000397C
:03014800000C00A8
:030149000000397A
:03014A00000C00A6
:03014B00000C00A5
:03014C00000AC2E4
:03014D00000C00A3
:03014E0000002589
:03014F00000C1091
:0301500000003D6F
:030151000009178B
:03015200000C049A
:0301530000002584
:03015400000C009C
:0301550000003D6A
:0301560000091786
:03015700000C0297
:030158000000257F
:03015900000C088F
:03015A0000003D65
:03015B0000091781
:03015C00000C0094
:03015D0000002679
:03015E00000C0191
:03015F0000002974
:03016000000C2070
:0301610000002378
:03016200000A0090
:03016300000B632B
:0300D00003D94011
:0300D100C1CC207F
:0300D20002219573
:0300D300C0064321
:0300D400024ADFFE
:0300D50021DC012A
:0300D6000301DF44
:0300D70090109BEB
:0300D800202703DB
:0300D900030ADF38
:0300DA009017D3A9
:0300DB00204B486F
:0300DC00030CFF13
:0300DD009010225E
:0300DE00210B2AC9
:0300DF0002421FBB
:0300E000C0390A1A
:0300E100084C20A8
:0300E20060312565
:0300E300AE66D333
:0300E400209AEA75
:0300E500AE8C20BE
:0300E600C00095C2
:0300E700AE86439F
:0300E800187AF291
:0300E900149AEF77
:0300EA00643C4033
:0300EB00B17125CB
:0300EC001A7C007B
:0300ED00C5002427
:0300EE00039B1A57
:0300EF00799217EC
:0300F000AEF0244B
:0300F10020BB1A17
:0300F200D00C40EF
:0300F30003810581
:0300F40021903D1B
:0300F500E07C00AC
:0300F6003480242F
:0300F70034821D33
:0300F80034803021
:0300F90034890146
:0300FA00030215E9
:0300FB0020603052
:0300FC0034890143
:0300FD0034820446
:0300FE003480301B
:0300FF0034890140
:03010000D05210CA
:03010100031024C4
:03010200C007F73C
:03010300032B0BC0
:03010400033C02B7
:03010500C70FFF22
:03010600039164FE
:03010700C50C0222
:0301080003915709
:03010900C1C1244D
:03010A00030B17CD
:03010B00C007D753
:03010C00031B17BB
:03010D00204C0182
:03010E00032FFFBD
:03010F00C00164C8
:03011000033C01AC
:03011100C70157CC
:0301120003912432
:03011300C50B1702
:030114000392173C
:03011500C40024FF
:03011600039B1731
:0301170020CC02F7
:03011800743D0132
:03011900B8316496
:03011A00C00C8096
:03011B000246F3A6
:03011C00C05125AA
:03011D00022205B6
:03011E002050303E
:03011F00D2090101
:03012000D40215F1
:0301210003D030D8
:0301220021D901DF
:03012300030204D0
:0301240090103008
:030125002029018D
:030126000307D3F9
:03012700901B48E2
:0301280020421062
:03012900030022AE
:03012A00901C50D6
:03012B00C01039C8
:03012C001507991B
:03012D00024B2C56
:03012E0021A212F9
:03012F0094803089
:0301300020221476
:0301310003A031F7
:0301320020621335
:03013300743032F3
:03013400B41C00F8
:03013500C9F033DB
:0301360016BC7084
:03013700C00039CC
:030138006B0C50FD
:03013900D20039B8
:03013A006D02153E
:03013B00D40030BD
:03013C0012BC00F2
:03013D00C80031C6
:03013E001AB202F0
:03013F0020B032BB
:03014000038C002D
:0301410020603308
:0301420002AC709C
:03014300C0403980
:03014400086C50F4
:03014500703039DE
:03014600B4AC4016
:03014700C00039BC
:03014800024C0066
:03014900B4E039E6
:03014A00C04C00A6
:03014B000AAC00FB
:03014C00C02AC204
:03014D00024C0061
:03014E0091702588
:03014F00C01C10C1
:0301500003E03D8C
:030151002069170B
:03015200643C0406
:03015300B570255F
:0301540037EC0085
:030155002C803DBE
:03015600B5491791
:03015700C60C02D1
:030158001500256A
:03015900743C08EB
:03015A00B6B03DFF
:03015B0021E91780
:03015C001AFC008A
:03015D0014F02675
:03015E00743C01ED
:03015F00B830298C
:03016000C04C2070
:0301610012402326
:03016200917A008F
:03016300C00B636B
:0301640002400056
:0301650020000077
:0301660094800082
:0301670020200055
:0301680002000092
:0301690003500040
:03016A00B83000AA
:03016B00CFF000D2
:03016C0019E00097
:03016D0016F00089
:03016E00C030009E
:03016F0008100075
:03017000743000E8
:03017100B7A00034
:03017200C01000BA
:0301730002400047
:0301740020000068
:0301750094800073
:0301760020200046
:0301770002000083
:0301780003500031
:03017900B830009B
:03017A00C00000C2
:03017B0018100059
:03017C00643000EC
:03017D006B000014
:03017E00B80000C6
:03017F00B8300095
:03018000C01000AC
:0301810012400029
:0301820091700079
:03018300369000B3
:03018400C01000A8
:030185001E6000F9
:0301860021B000A5
:030187000860000D
:03018800743000D0
:03018900A5D000FE
:03018A0002600010
:03018B00C0200091
:03018C00FFF00081
:03018D0016B000A9
:03018E00C020008E
:03018F0023A000AA
:03019000743000C8
:0301910012B000A9
:0301920020B0009A
:03019300038000E6
:03019400C4400064
:03019500039000D4
:03019600C40000A2
:03019700039000D2
:03019800C00000A4
:0301990002300031
:03019A00AC200096
:03019B00B9B000F8
:00000001FF

View File

@@ -0,0 +1,578 @@
#
# $Id: USB_FW.201.hex 10402 2012-02-15 15:34:50Z dima $
#
:03004300021F0099
:03005300021F0089
:101F0000021E3100021E8E00021E7800021E4900D1
:081F1000021C2000021BA900C5
:101000001201000200000040AAAAAAAAAAAA01028C
:1010100003010A0600020000004001000902370037
:10102000020100C0000904000002FFFFFF040705E1
:101030000202000200070586020002000904010006
:1010400002FFFFFF050705040200020007058802F2
:10105000000200001201000200000040E4E451110F
:101060000000010203010A06000200000040010026
:1010700009023700020100C0320904000002FFFF2C
:10108000FF04070502024000000705860240000039
:101090000904010002FFFFFF0507050402400000EC
:1010A0000705880240000006040016001400120024
:1010B0000A00260004030904160358006F0072009A
:1010C00063006F006D0020004C00540044001403C6
:1010D00041007300740072006900620061006E00DC
:1010E0006B001203530065007200690061006C0020
:1010F0004E006F000A0346005000470041002603DF
:101100004D0061006E00610067006D0065006E00BB
:101110007400500072006F0063006500730073007C
:061120006F0072000000E8
:050FF6000300000000F3
:100F3C0041E0370041E0B60042E0B1000041E0384A
:100F4C0000021BE0850218E07943E0B30000004D7D
:0F0F5C00E03931303339354D202020202020005E
:101D71008B538A548955E5581558AE57700215573B
:101D81004E6014AB530555E555AA54700205541421
:081D9100F9ED12077780DF2253
:101BE6008B538A548955E55A155AAE5970021559C0
:101BF6004E6026AB560558E558AA5770020557148D
:101C0600F9120731FFAB530555E555AA5470020585
:0A1C16005414F9EF12077780CD2275
:101DC100D2B7E490E670F0F5B575B5E653B5E743E3
:101DD100B28853B2FCC2B3D2B1C2B2C2B67F32FE34
:061DE100121E07D2B6221B
:101E6100538EF75389FB5389F74389015389FDE465
:071E7100F58AF58CD2A922CD
:1018B2008C448D45AA06A9077556018A5789587521
:1018C2005900755A1C7B017AE0794C121BE690E0B4
:1018D20064E0FCA3E0FDA3E0FEA3E064D1FFEE64BC
:1018E2008DFEED644CFDEC6449FC90E064120853FB
:1018F2007EE07F4C7D1C7C001213707EE07F4C7B6F
:101902001C7A00AD45AC441214247D1C7C00AF450A
:10191200AE441211F57D1C7C00AF45AE44021C564C
:08183F008E448F458C468D4755
:10184700C20712001290E15BEFF0BF5004D207808D
:1018570057E490E15CF0A3F090E15CE0FEA3E0FFC9
:10186700C39410EE648094805030E5472FF582E5ED
:10187700463EF583E0FF90E15CE0FCA3E02545F5FB
:1018870082E5443CF583E0B5071090E15DE004F0A4
:1018970070C690E15CE004F080BE90E15CE070040B
:0A18A700A3E064107002D207A2074C
:0118B1002214
:020E12008F410E
:100E14001200128F42E4F546F547AD47AC46121472
:100E2400DA74692547F582E434E0F583E543F00597
:100E340047E54770020546C39408E54664809480FC
:100E440040D8E541600490E069F090E069E0B4C006
:100E540008754400754508800675441D754536754A
:100E64004600754708C3E5479410E54664809480BE
:100E740050231214D674692547F582E434E0F583CF
:100E8400E543F00547E547700205460545E545702D
:100E9400D4054480D07543FF75441D7545197546C6
:100EA40000754710C3E547942CE546648094805050
:100EB40033E542B4510E7B007A007943AD45AC442E
:100EC400FF1214E274692547F582E434E0F583E502
:100ED40043F00547E547700205460545E54570C4FE
:100EE400054480C075441D75453EE4F543F546F55B
:100EF40047C3E5479406E54664809480502FE54255
:100F0400B4510A90E069E0B4C2031214D6744625C1
:100F140047F582E434E0F583E543F00547E547709F
:100F24000205460545E54570C8054480C490E0695E
:070F3400E0B4C20374C0F039
:010F3B002293
:0A1988008E448F458B468A4789483C
:101992007E00E5452DF54DEE3544F54C1200128FD3
:1019A20049E5496451600BC3E5459410E544940050
:1019B200503585444A85454BC3E54B954DE54A95DF
:1019C2004C5024AB46AA47A948AD4BAC4AAF49128A
:1019D2001740054BE54B7002054A74012548F5484E
:0719E200E43547F54780D111
:0119E90022DB
:0617C7008B418A428943B8
:1017CD00D2067556017557E0755869755900755AE9
:1017DD00107B017AE07995121BE6E5432410F9E4BC
:1017ED003542854156F5578958755900755A0C7B08
:1017FD00017AE079A5121BE67EE07F957CE07D1AEB
:10180D001218B27EE07F1AE543241CF9E43542FC40
:10181D00AD0112183F5016AB41E5432410F9E435E4
:10182D0042FA7D1C7F197E1D1219888002C206A204
:01183D0006A4
:01183E002287
:101126007F03121D46EF2402FFE43EA90775410125
:10113600F542894390E06AE0FFE50C2408F582E475
:10114600350BF583EFF090E06BE0FFE50C2409F535
:1011560082E4350BF583EFF090E06CE0FFE50C24BC
:101166000AF582E4350BF583EFF090E06DE0FFE5DC
:101176000C240BF582E4350BF583EFF090E06EE07E
:10118600FFE50C240CF582E4350BF583EFF090E0D7
:101196006FE0FFE50C240DF582E4350BF583EFF0E7
:1011A6007F087E00E4FDEDC39408502874692FF58E
:1011B60082E434E0F583E0FCAB41AA42A94375F032
:1011C60002EDA4F58285F083EC1207890D0FBF00AE
:1011D600010E80D2E5192404F582E43518F583E082
:0E11E60030E0047F0180027F0090E037EFF0E0
:0111F40022D8
:101B250090E06CE02FFFE50C240AF582E4350BF517
:101B350083EFF0E50C240BF582E4350BF583E0FE2D
:101B4500E50C240AF582E4350BF583E0FDEDFF9005
:101B5500E0B1EEF0A3EFF0D206121CBD90E680E0F6
:041B650054F7F0221F
:1016200090E600E054E74410F090E60174C0F090BA
:10163000E6107420F000000090E611F00000009029
:10164000E6047480F0000000740FF0000000E4F085
:1016500000000090E6187410F0000000E490E61915
:10166000F000000090E61A7408F0000000E490E634
:101670001BF000000090E6497482F0000000F000CA
:10168000000090E6247402F0000000E490E625F0EB
:1016900000000090E6957480F0000000F00000006B
:1016A00043AF017B017AE07914755700755806E461
:0416B000FD021D71A9
:061E0100D2837F0A7E007F
:101E07007C007D181207ABEF1FAC0670011E4C70EB
:021E1700F622B1
:0A1A43008E418F428B438A4489458F
:101A4D00E4F546F547C3E5479542E54695415036E1
:101A5D00AB43AA44A94585478285468312074AFFB1
:101A6D00E4FBFAC2B2EF1392B1EFC313FFD2B20B84
:101A7D00BB00010AEB64084A70E9C2B20547E547AD
:071A8D0070C3054680BFD3C2
:011A9400222F
:101E190090E60174C0F0C2B67FC27E01121E07D2DD
:081E2900B67F327E00021E07A5
:101EA400D287121E01C287121E03C2837F0A7E00DC
:031EB400021E0704
:021B6900AB07C8
:101B6B00E4F9FAEBC413131354011392877F027E2B
:101B7B0000121E07D2837F057E00121E07E925E0A7
:101B8B00FFA2B3E4334FF97F057E00121E07EB254E
:0D1B9B00E0FBC283121E030ABA08C8AF01A6
:011BA800221A
:061A95008B558A568957AB
:101A9B00A2AFE433F55D121EA4E4F55CE55CC395DF
:101AAB005B5027AB55AA56A957855C8275830012EC
:101ABB00074AFF121B69AB58AA59A95A855C827554
:101ACB008300EF120789055C80D2120036E55D2496
:031ADB00FF92AFC8
:011ADE0022E5
:0B003600C287121E03121E01D2872297
:101DE70075418F8F42755800755900755A4B755B51
:0A1DF700027B007A007941021A9580
:101C8C0078417C007D007BFF7A0F79F67E007F0522
:101C9C0012070B30B415755800755900755A4175FB
:101CAC005B057B007A007941121A95E5435401FFDC
:011CBC002205
:100B4E007541007542007543007545017546E075A7
:100B5E0047007548017549E0754A08E4F551FFF5FF
:100B6E00527B017AE07900F557755808FD121D7118
:100B7E00AB45AA46A9477401120777E4F550E55034
:100B8E00C454F0AB45AA46A94790000112078985C7
:100B9E004858854959854A5A755B08121A95AB48CB
:100BAE00AA49A94A90000212074AFE5403FFEE54C6
:100BBE0070F55124E0602924F0604B24F0605D2430
:100BCE00F0606F24406003020C5675410185184297
:100BDE00851943EF24FE600624FE703B801C801FA7
:100BEE00E5192401FDE43518A905754101F5428981
:100BFE0043EF24FC60092402700A7552028052757C
:100C0E005206804D8011E5192402FDE43518A90520
:100C1E00754101F54289437552088035E519240363
:100C2E00FDE43518A905754101F542894375520455
:100C3E00801FE5192405FDE43518A905754101F558
:100C4E00428943755298800975410075420075437B
:100C5E0000E542454345416022AB41AA42A94312F9
:100C6E000731FED395524006AD52AE0580008E443C
:100C7E00120731C39544120777800CE55170047E3C
:100C8E000180027E008E44744B2550F8A644055018
:100C9E00E550C394055003020B8CAB45AA46A947F9
:100CAE007488120777AB45E5472401F9E43546FA17
:100CBE0075560075570075584B755900755A0512C3
:100CCE001BE6854858854959854A5A755B08AB45D8
:070CDE00AA46A947021A957E
:1019EA008F4190E0B1E0FEA3E054F064607003EE32
:1019FA00641160037F012290E037E070037F0F22B9
:101A0A00E5417003308108E541B401062080037F77
:101A1A00102290E0B6E0B541037F0122E4F511D22D
:101A2A0006121CBDAF4190E0B6EFF024FF92B590CC
:091A3A00E680E054F7F07F002281
:04000E0090FC04F06E
:1000120090E678E0541824F06008240870087F50B5
:0800220080067F518002E4FF1B
:01002A0022B3
:0C14D600AD45AC447B007A007943AF4286
:0C14E2008F488C498D4A8B4B8A4C894DF9
:1014EE00E4F54EF54F755003FDF551F552A2AF33AD
:1014FE00F553E54824AF600D047012754E00754F1C
:10150E00017D018008754E00754F02E4FDE54860CF
:10151E0051E54F454E604BE54990E0B3F0E54AA3E7
:10152E00F074B32DF582E434E0AD82FCAB4FAF48DE
:10153E001219227551008F527F0A7E00121ADFE5B2
:10154E0052455160107CE07D687B01AF4812157BDF
:10155E007551008F5290E068E0AB4BAA4CA94D122A
:0C156E000777E55324FF92AFAE51AF5257
:01157A00224E
:0C1740008F4E8C4F8D508B518A52895374
:10174C00E4F554F555755603FDF557F558A2AF332E
:10175C00F559E54E24AF600D0470127554007555A3
:10176C00027D018008755400755503E4FDE54E605B
:10177C003FE55545546039E54F90E0B3F0E550A393
:10178C00F0AB51AA52A95312073190E0B5F0C2B791
:10179C0074B32DF582E434E0AD82FCAB55AF4E1240
:1017AC0019227557008F587F0A7E00121ADFD2B7A4
:0A17BC00E55924FF92AFAE57AF5875
:0117C6002200
:10005600E4F531F532F535F53CF53DF53EF53FE590
:10006600AA5484600302063A90E694E0FE90E69570
:10007600E0FBEEF53CEBF53DC39405E53C94004012
:100086000790F404E0FD80027DFFED12085F00CECC
:100096000102C30503080703580903D80B011E0E06
:1000A60000E40F019411025E130541250401310499
:1000B6005732046A3404B23504C93604E63703E518
:1000C6004503F647000005BA75310075320790FC06
:1000D600047481F0A37414F0E4A3F00205DD7F0F2D
:1000E600121DE775310075320690FC047480F0E449
:1000F600A3F0753505F511FE74002535F9EE34F4D7
:10010600FA7B011217C7400690FC05740EF0E4FF57
:10011600120E127F8F0202BD7F0E121DE77531008F
:10012600753205748E12000E8F3F7B007A0079407F
:10013600E4FDFC1214E2E53F64516019E53F6450AA
:10014600601375310075320690FC047480F0A37458
:100156000BF00205DD90E0B7E0FF120E12740025E9
:1001660032F974FC3531FA7B01C0038B567557E0C2
:10017600755869755900755A2CD003121BE6742CF4
:100186002532F532E43531F5317F8E0202BD753107
:100196000075320790FC047491F090E678E090FCCC
:1001A60005F030B3047F0280027F0030B4047E0184
:1001B60080027E00EE4F90FC06F074002532F97442
:1001C600FC3531FA7B01755700755812E4FD121D96
:1001D6007174002532F974FC3531FA7B01C0038B4A
:1001E600567557E0755839755900755A06D0031279
:1001F6001BE674062532F532E43531F531FE74001E
:100206002532F974FC3EFA7B01C0038B567557E024
:10021600755814755900755A06D003121BE67406F4
:100226002532F532E43531F531FE74002532F974A4
:10023600FC3EFA7B01C0038B567557E07558467530
:100246005900755A06D003121BE674062532F5329C
:10025600E43531F5310205DD7F13121DE7753100F6
:1002660075321D749312000E8F3F75381D75390057
:10027600753600753705D3E5399418E538941D5061
:1002860034E53FB4510E7B007A007940AD39AC3885
:10029600FF1214E274002537F58274FC3536F583B7
:1002A600E540F00539E539700205380537E5377060
:1002B600C5053680C17F93121DE70205DD75310045
:1002C60075320690FC047480F0E4A3F090F405E027
:1002D60090E038F0E0147071121E1930B31B755699
:1002E600017557F4755806755900755A067B017ADB
:1002F600E07914121BE60205DD90FC057401F0029C
:1003060003D075310075320690FC047480F0E4A3C6
:10031600F0753507AF35FEC3E53D9FF534E53C9EE8
:10032600F53390E038E014702074002FF974F43E31
:10033600FA7B01AF34AE33121A435004E40204C20E
:1003460090FC05740CF00205DD90FC057403F002C8
:1003560005DD75310075320690FC047480F0E4A367
:10036600F090E038E014705CE4FFFE20B411C2B2F5
:10037600D2B1D2B20FBF00010EEF640A4E70EC305C
:10038600B43A90E6017403F07F647E00121E079073
:10039600E0B7E0FF120E127EE07F697CE07DB812C6
:1003A60018B27EE07FB8AD1CAC1B12183F50051288
:1003B6000B4E801690FC05740EF0800E90FC0574B2
:1003C6000DF0800690FC057403F0E490E038F0022E
:1003D60005DDE4F531F5327F02121B250205DDE469
:1003E600FF120E12121126E4FF1219EAE4FF800230
:1003F6007F01121B25121E190205DD7531007532AB
:100406000690FC047480F0E4A3F090F405E0F53E59
:10041600E4F511E53E64016004E53E703290E0B11A
:10042600E0FEA3E054F064607003EE6411600280A5
:100436007290E037E070028058E5116401600AE5C9
:1004460011700C121C8CEF6006853E110205DD80D2
:100456005275310075320690FC0474B2F0A3E511B2
:10046600F00205DD75310075320690FC047480F0EB
:10047600E4A3F090F405E0F53EFF1219EAEF24F14B
:10048600600F1460152410701AE4F531F532020578
:10049600DD90FC05740FF00205DD90FC057410F08C
:1004A6000205DD90FC057401F00205DD753100756D
:1004B600320690FC0474B5F090E0B6E090FC05F0CE
:1004C6000205DD75310075320690FC0474B6F0A2A3
:1004D60080E43325E0FFA281E4334FA3F00205DD7B
:1004E600853C31853D3290FC0474B7F0753505C303
:1004F600E53D9535F534E53C9400F5337400253536
:10050600F582E434F4F583E0648870030205DDAF18
:10051600357E0074002FF9EE34F4FA7B01C003C077
:100526000174002FF9EE34FC8B58F559895A85343D
:100536005BD001D003121A950205DD7531007532C4
:100546000590FC0474A5F01200128F3F7B007A0020
:100556007940E4FDFC1214E290E036E0FF0532E556
:1005660032AC3170020531142400F58274FC3CF57E
:1005760083EFF090E0B7E0FF0532E532AC31700270
:100586000531142400F58274FC3CF583EFF0053246
:10059600E532AE3170020531142400F58274FC3E5A
:1005A600F583E540F090E6017403F07F647E001267
:1005B6001E07802375310075320690FC047480F0A6
:1005C600C3E53D9405E53C94005006A37407F0800E
:1005D6000690FC057406F090F404E0B48004A3E0F1
:1005E600701290F404E06405600FE06407600AE0AE
:1005F60064096005E490E038F0E5324531602CE5A9
:1006060032FD90FC00F0E531FFA3F090F402E0909B
:10061600FC02F090F403E090FC03F090E69CEFF00F
:1006260000000090E69DEDF000000090E6957480D5
:04063600F0000000D0
:01063A00229D
:02004100D322C8
:0800030090E6BAE0F51DD322DE
:101ECA0090E740E51DF0E490E68AF090E68B04F096
:021EDA00D32211
:08002B0090E6BAE0F51AD322B9
:101EDC0090E740E51AF0E490E68AF090E68B04F087
:021EEC00D322FF
:101D990090E6B9E0242F600D04701990E604E0FF85
:101DA900430780800890E604E0FF53077F000000A6
:071DB900EFF08002D322C30A
:011DC0002200
:101E3100C0E0C083C082D2015391EF90E65D74018E
:081E4100F0D082D083D0E03222
:101E7800C0E0C083C0825391EF90E65D7404F0D057
:061E880082D083D0E0329D
:101E8E00C0E0C083C0825391EF90E65D7402F0D043
:061E9E0082D083D0E03287
:101C2000C0E0C083C08285120D85130E850E8285AB
:101C30000D83A37402F085090F850A108510828533
:101C40000F83A37407F05391EF90E65D7410F0D00A
:061C500082D083D0E032D7
:101E4900C0E0C083C082D2035391EF90E65D74086D
:081E5900F0D082D083D0E0320A
:101BA900C0E0C083C08290E680E030E72085090D5F
:101BB900850A0E850E82850D83A37402F085120FA6
:101BC900851310851082850F83A37407F05391EF55
:0D1BD90090E65D7420F0D082D083D0E03221
:101EB700000102020303040405050300000000C03B
:031EC700C2000056
:060F6B0001110001080065
:03000B000212BC22
:1012BC00C0E0C0F0C083C082C0D075D000C000C0F8
:0D12CC0001C002C003C004C005C006C00779
:1012D90078217C007D007BFF7A1E79C17E007F0525
:1012E90012070B90E0B6E0F526C204752700E50861
:1012F900600415088056750805E5117004C204805C
:1013090043A280308101B3500B3081047F008030CB
:101319007F01802C30B415755800755900755A2114
:10132900755B057B007A007921121A95E523540132
:10133900F527701090E0B6E060047F0080027F011D
:0C1349008F26D204300405AF261219EAEA
:10135500D007D006D005D004D003D002D001D000EC
:0B136500D0D0D082D083D0F0D0E03296
:100CE50078567CE17D017BFF7A1E79C67E007F0404
:100CF50012070BC203C200D202C201121DC1121E8D
:100D050061121620750B10750C00751410751512EF
:100D1500750910750A1C75121075137085120F85EB
:100D250013107516107517B412001290E154EFF0F8
:100D35007B017AE17955E4FDFC1214E290E155E07E
:100D4500FF90E036F0E490E0B7F0EF64C26059EF51
:100D550064C06054E490E15AF090E15AE0FFC39416
:100D650004504A74562FF582E434E1F583E0FF60C0
:100D75003C120E127EE07F697CE07DB81218B27ECF
:100D8500E07FB8AD1CAC1B12183F501490E15AE03F
:100D95002456F582E434E1F583E090E0B7F0800D68
:100DA50090E15AE004F080B1E4FF120E1212112610
:100DB500D2E843D82090E668E04409F090E65CE08C
:100DC500443DF012001290E154EFF07B017AE17995
:100DD50055E4FDFC1214E290E155E064C26007E4BD
:100DE50090E0B6F0C2B57F01121B25D2AFD28C536D
:100DF5008EF8C203C2AF120056D2AF3001051209F8
:0D0E050026C2013003EEC203121D1A80E761
:0B00460090E50DE030E402C322D3225D
:1009260090E6B9E070030209EB147003020A602432
:10093600FE7003020ADB24FB70030209E514700350
:100946000209DF1470030209D31470030209D924C3
:10095600056003020B3A1200414003020B4690E683
:10096600BBE024FE602714603E24FD60111460275E
:1009760024067056E50B90E6B3F0E50C80421200B3
:10098600465044E51490E6B3F0E5158033E50D9046
:10099600E6B3F0E50E802985120F851310E50F905A
:1009A600E6B3F0E510801990E6BAE0FF121D46AAFC
:1009B60006A9077B01EA494B600DEE90E6B3F0EF1E
:1009C60090E6B4F0020B46020B35020B35121EDC24
:1009D600020B4612002B020B46120003020B4612B4
:1009E6001ECA020B4690E6B8E0247F601514601913
:1009F60024027063A200E43325E0FFA202E4334F31
:100A06008041E490E740F0803F90E6BCE0547EFFF2
:100A16007E00E0D394807C0040047D0180027D004E
:100A2600EC4EFEED4F24B7F582741E3EF583E4933B
:100A3600FF3395E0FEEF24A1FFEE34E68F82F583C7
:100A4600E0540190E740F0E4A3F090E68AF090E6E7
:100A56008B7402F0020B46020B3590E6B8E024FEDA
:100A6600601624026003020B4690E6BAE0B4010564
:100A7600C200020B46020B3590E6BAE0705590E6CE
:100A8600BCE0547EFF7E00E0D394807C0040047D71
:100A96000180027D00EC4EFEED4F24B7F582741EF8
:100AA6003EF583E493FF3395E0FEEF24A1FFEE3499
:100AB600E68F82F583E054FEF090E6BCE0548013A6
:100AC6001313541FFFE0540F2F90E683F0E04420E9
:100AD600F0806D805A90E6B8E024FE60192402701A
:100AE6004E90E6BAE0B40104D200805490E6BAE033
:100AF6006402604C803990E6BCE0547EFF7E00E0E4
:100B0600D394807C0040047D0180027D00EC4EFE83
:100B1600ED4F24B7F582741E3EF583E493FF3395BB
:100B2600E0FEEF24A1FFEE34E68F82F583800D9080
:100B3600E6A08008121D99500790E6A0E04401F057
:070B460090E6A0E04480F0FE
:010B4D002285
:03003300020FFBBE
:040FFB0053D8EF32A6
:100F71006080E0D4292E43C9A2D87C013D3654A11A
:100F8100ECF0061362A705F3C0C7738C98932BD9B5
:100F9100BC4C82CA1E9B573CFDD4E01667426F18B9
:100FA1008A17E512BE4EC4D6DA9EDE49A0FBF58E45
:100FB100BB2FEE7AA968799115B2073F94C21089C7
:100FC1000B225F21807F5D9A5A903227353ECCE714
:100FD100BFF79703FF1930B348A5B5D1D75E922A61
:100FE100AC56AAC64FB838D296A47DB676FC6BE251
:040FF1009C7404F1F7
:081370008C468D47AB07AA066D
:10137800E4F548F549C3E5499547E5466480F8E54D
:1013880048648098400302141FE54925E0FFE548BA
:1013980033FE74D42FF58274E03EF583E0FF7E00BF
:1013A800AC46AD471207BD8C4A8D4BE54925E0FF99
:1013B800E54833FE74D52FF58274E03EF583E0FFEF
:1013C8007E00AC46AD471207BD8C4C8D4DE54B6594
:1013D8004D7004E54A654C6030EB254BF582EA35E3
:1013E8004AF583E0F9EB254DF582EA354CF583E0C3
:1013F800FFEB254BF582EA354AF583EFF0EB254DF7
:10140800F582EA354CF583E9F00549E549600302C0
:0B141800137D054802137D7E007F015C
:0114230022A6
:0C1424008E468F478C488D498A4A8B4BBE
:10143000E54745466006E54945487004E4FEFF225D
:10144000E4F54CF54DC3E54D954BE54A6480F8E570
:101450004C648098507BE4F54EF54FE549254DF5F9
:1014600082E548354CF583E4F0C3E54F954BE54AFA
:101470006480F8E54E6480985049E54F254D24D4AA
:10148000F582E434E0F583E0FFE547254FF582E59A
:1014900046354EF583E0FEEF8EF0A4FFE549254D7D
:1014A000F582E548354CF583E02FFFE549254DF5FC
:1014B00082E548354CF583EFF0054FE54F70AA05FE
:1014C0004E80A6054DE54D6003021445054C0214FF
:0514D000457E007F01D4
:0114D50022F4
:101CEC00120731FF90000312074A12077790000386
:101CFC00EF12078990000212074AFF9000011207A9
:0E1D0C004A900002120789900001EF02078939
:0811F5008E468F478C488D499E
:1011FD00E4F54AF54BE549AE487802CEA2E713CEA9
:10120D0013D8F8FFC3E54B9FEE6480F8E54A648080
:10121D009840030212B7E54BAE4A7802C333CE3382
:10122D00CED8F92547FFEE3546FAA9077B018B4C41
:10123D00F54D894E74D5254BF582E434E0F583E008
:10124D00541FFFE48F52F551F550F54F121CECABC6
:10125D004CAA4DA94E120819C374209552F9F812D3
:10126D000806C004C005C006C007A94E120819A97A
:10127D0052A8011207F3D003D002D001D000EF4BDA
:10128D00FFEE4AFEED49FDEC48FCAB4CAA4DA94ED4
:10129D00120839AB4CAA4DA94E121CEC054BE54B6F
:0E12AD006003021202054A0212027E007F0157
:0112BB002210
:101C5600D3ED9410EC64809480402AED1D70011C35
:101C6600142FF582EE3CF583E0FB547F24D4F582F5
:101C7600E434E0F583E0F9540F2FF582E43EF58372
:051C8600E06BF080CBD3
:011C8B002236
:101D1A0090E682E030E004E020E60B90E682E030D4
:101D2A00E119E030E71590E680E04401F07F147E87
:0C1D3A0000121ADF90E680E054FEF02258
:101CBD0030060990E680E0440AF0800790E680E067
:101CCD004408F07FDC7E05121ADF90E65D74FFF0AC
:0F1CDD0090E65FF05391EF90E680E054F7F0222D
:101ADF008E5A8F5B90E600E054187012E55B24017C
:101AEF00FFE4355AC313F55AEF13F55B801590E6F3
:101AFF0000E05418FFBF100BE55B25E0F55BE55ADE
:101B0F0033F55AE55B155BAE5A7002155A4E6005F8
:061B1F00121EEE80EE2212
:06157B008C548D55AE07F3
:10158100EB70037F012290E678E020E6F990E6789F
:101591007480F0EE25E0440190E679F090E678E081
:1015A10030E0F990E678E020E26BE030E167BB01E2
:1015B1000790E678E04420F090E679E0F5561BEBE1
:1015C100603090E678E030E0F990E678E020E2459E
:1015D100BB010790E678E04420F090E679E0FF0552
:1015E10055E555AC547002055414F5828C83EFF027
:1015F10080CC90E678E030E0F990E678E020E215E2
:1016010090E678E04440F090E679E0855582855493
:0E16110083F07F012290E678E04440F07F00F5
:01161F0022A8
:1019220090E678E020E6F990E6787480F0EF25E022
:1019320090E679F090E678E030E0F990E678E02001
:10194200E23AE030E136EBD3940040260DEDAE04EE
:1019520070010C14F5828E83E090E679F01B90E61C
:1019620078E030E0F990E678E020E210E020E1D67D
:10197200800A90E678E04440F07F012290E678E029
:051982004440F07F006D
:01198700223D
:021D4600A907EB
:101D4800AE16AF178F828E83A3E064037017AD01C0
:101D580019ED7001228F828E83E07C002FFDEC3E0E
:081D6800FEAF0580DFE4FEFF81
:011D70002250
:101EEE007400F58690FDA57C05A3E582458370F907
:011EFE0022C1
:030000000216B431
:0C16B400787FE4F6D8FD75815D0216FB1E
:10063B00E709F608DFFA8046E709F208DFFA803EA1
:10064B0088828C83E709F0A3DFFA8032E309F6088E
:10065B00DFFA8078E309F208DFFA807088828C83F6
:10066B00E309F0A3DFFA806489828A83E0A3F608AA
:10067B00DFFA805889828A83E0A3F208DFFA804C84
:10068B0080D280FA80C680D4806980F2803380105B
:10069B0080A680EA809A80A880DA80E280CA8033C4
:1006AB0089828A83ECFAE493A3C8C582C8CCC5833C
:1006BB00CCF0A3C8C582C8CCC583CCDFE9DEE7800C
:1006CB000D89828A83E493A3F608DFF9ECFAA9F08B
:1006DB00EDFB2289828A83ECFAE0A3C8C582C8CCE1
:1006EB00C583CCF0A3C8C582C8CCC583CCDFEADEFA
:1006FB00E880DB89828A83E493A3F208DFF980CC5C
:10070B0088F0EF60010E4E60C388F0ED2402B40454
:10071B000050B9F582EB2402B4040050AF232345FB
:06072B00822390068B738F
:10073100BB010689828A83E0225002E722BBFE02C6
:09074100E32289828A83E49322F9
:10074A00BB010CE58229F582E5833AF583E0225064
:10075A0006E92582F8E622BBFE06E92582F8E222AE
:0D076A00E58229F582E5833AF583E49322C8
:10077700BB010689828A83F0225002F722BBFE0161
:02078700F3225B
:10078900F8BB010DE58229F582E5833AF583E8F0A6
:10079900225006E92582C8F622BBFE05E92582C852
:0207A900F2223A
:1007AB00EF8DF0A4A8F0CF8CF0A428CE8DF0A42E62
:0207BB00FE221C
:1007BD00C2D5EC30E709B2D5E4C39DFDE49CFCEE57
:1007CD0030E715B2D5E4C39FFFE49EFE120885C342
:1007DD00E49DFDE49CFC800312088530D507C3E43D
:0607ED009FFFE49EFE22C6
:1007F300E8600FECC313FCED13FDEE13FEEF13FFE4
:03080300D8F12207
:10080600E8600FEFC333FFEE33FEED33FDEC33FC50
:03081600D8F122F4
:10081900BB010789828A830208E65005E9F80208C4
:10082900DABBFE05E9F80208F289828A830208FE2A
:10083900BB010789828A830208535005E9F8020936
:0A0849000EBBFE05E9F802091A22B1
:0C085300ECF0A3EDF0A3EEF0A3EFF02218
:10085F00D083D082F8E4937012740193700DA3A328
:10086F0093F8740193F5828883E47374029368603C
:06087F00EFA3A3A380DF3C
:1016C000020CE5E493A3F8E493A34003F68001F24F
:1016D00008DFF48029E493A3F85407240CC8C3332B
:1016E000C4540F4420C8834004F456800146F6DFFA
:1016F000E4800B0102040810204080900F3CE47E3F
:10170000019360BCA3FF543F30E509541FFEE493EE
:10171000A360010ECF54C025E060A840B8E493A3B5
:10172000FAE493A3F8E493A3C8C582C8CAC583CAE0
:10173000F0A3C8C582C8CAC583CADFE9DEE780BE98
:010FF50000FB
:10088500BC000BBE0029EF8DF084FFADF022E4CC57
:10089500F875F008EF2FFFEE33FEEC33FCEE9DEC20
:1008A500984005FCEE9DFE0FD5F0E9E4CEFD22ED66
:1008B500F8F5F0EE8420D21CFEADF075F008EF2FB0
:1008C500FFED33FD4007985006D5F0F222C398FDA1
:0508D5000FD5F0EA223E
:0C08DA00E6FC08E6FD08E6FE08E6FF224A
:0C08E600E0FCA3E0FDA3E0FEA3E0FF2285
:0C08F200E2FC08E2FD08E2FE08E2FF2242
:1008FE00E493FC740193FD740293FE740393FF2240
:0C090E00ECF608EDF608EEF608EFF62215
:0C091A00ECF208EDF208EEF208EFF22219
:00000001FF

View File

@@ -1,10 +1,10 @@
#
# $Id: USB_FW.hex 10085 2011-11-13 14:33:46Z dima $
# $Id: USB_FW.hex 10401 2012-02-15 15:30:24Z dima $
#
:03004300021E009A
:03005300021E008A
:101E0000021E3000021E8D00021E7700021E4800D6
:081E1000021C1B00021BA400D0
:03004300021F0099
:03005300021F0089
:101F0000021E3400021E9100021E7B00021E4C00C5
:081F1000021C1F00021BA800C7
:101000001201000200000040AAAAAAAAAAAA01028C
:1010100003010A0600020000004001000902370037
:10102000020100C0000904000002FFFFFF040705E1
@@ -24,197 +24,199 @@
:101100004D0061006E00610067006D0065006E00BB
:101110007400500072006F0063006500730073007C
:061120006F0072000000E8
:050FF7000300000000F2
:1011ED0041E0370041E0BB0042E0B6000041E0388D
:1011FD0000021BE08A0218E07E43E0B800000052B6
:10120D00E039393733343A393936344D50202020CE
:04121D00202020006D
:101D96008B508A518952E5551555AE54700215542B
:101DA6004E6014AB500552E552AA5170020551140B
:081DB600F9ED12077180DF2234
:101BE1008B508A518952E5571557AE5670021556DA
:101BF1004E6026AB530555E555AA547002055414A1
:101C0100F912072BFFAB500552E552AA517002059C
:0A1C11005114F9EF12077180CD2283
:101D6C00C2B5C2B7E490E670F075B5E653B5EE4374
:101D7C00B28053B2F4A2B53390E0BBF0C2B3C2B69A
:0A1D8C007F327E00121DECD2B62259
:101E6000538EF75389FB5389F74389015389FDE466
:071E7000F58AF58CD2A922CE
:1017B3008C428D43AA06A9077553018A548955752E
:1017C300560075571C7B017AE07951121BE190E0BA
:1017D30051E0B4C20374C0F090E069E0FCA3E0FD03
:1017E300A3E0FEA3E064D1FFEE648DFEED644CFD47
:1017F300EC6449FC90E06912084D7EE07F517D1C4A
:101803007C001213607EE07F517B1C7A00AD43ACF9
:10181300421214147D1C7C00AF43AE421211267D8C
:0A1823001C7C00AF43AE42021C51D2
:0818A5008E428F438C448D45F7
:1018AD00C20712001290E160EFF0BF5004D2078022
:1018BD0057E490E161F0A3F090E161E0FEA3E0FF59
:1018CD00C39410EE648094805030E5452FF582E589
:1018DD00443EF583E0FF90E161E0FCA3E02543F594
:1018ED0082E5423CF583E0B5071090E162E004F03B
:1018FD0070C690E161E004F080BE90E161E070049B
:0A190D00A3E064107002D207A207E5
:0119170022AD
:020DE4008F3F3F
:100DE6001200128F40E4F544F545AD45AC441214AB
:100DF600CA746E2545F582E434E0F583E541F005D5
:100E060045E54570020544C39408E5446480948032
:100E160040D8E53F600490E06EF090E06EE0B4C02C
:100E260008754200754308800675421D7543367580
:100E36004400754508C3E5459410E54464809480F4
:100E460050231214C6746E2545F582E434E0F5830A
:100E5600E541F00545E545700205440543E5437067
:100E6600D4054280D07541FF75421D7543197544FE
:100E760000754510C3E545942CE544648094805084
:100E860033E540B4510E7B007A007941AD43AC4264
:100E9600FF1214D2746E2545F582E434E0F583E53D
:100EA60041F00545E545700205440543E54370C438
:100EB600054280C075421D75433EE4F541F544F593
:100EC60045C3E5459406E54464809480502FE5408B
:100ED600B4510A90E06EE0B4C2031214C6744B25F6
:100EE60045F582E434E0F583E541F00545E54570D6
:100EF6000205440543E54370C8054280C490E06E90
:070F0600E0B4C20374C0F067
:010F0D0022C1
:0A197E008E428F438B448A45894650
:101988007E00E5432DF54BEE3542F54A1200128FE5
:1019980047E5476451600BC3E5439410E542940062
:1019A8005035854248854349C3E549954BE54895F7
:1019B8004A5024AB44AA45A946AD49AC48AF4712A2
:1019C80017300549E5497002054874012546F54672
:0719D800E43545F54580D11F
:0119DF0022E5
:06182D008B3F8A40894157
:10183300D2067553017554E075556E75560075578C
:10184300107B017AE0799A121BE1E5412410F9E457
:101853003540853F53F554895575560075570C7BB4
:10186300017AE079AA121BE17EE07F9A7CE07D1A7F
:101873001217B37EE07F1AE541241CF9E43540FCDE
:10188300AD011218A55016AB3FE5412410F9E4351C
:1018930040FA7D1C7F197E1D12197E8002C206A2AA
:0118A300063E
:0118A4002221
:100F0E007F03121D41EF2402FFE43EA907753F0146
:100F1E00F540894190E06FE0FFE50C2408F582E48E
:100F2E00350BF583EFF090E070E0FFE50C2409F54A
:100F3E0082E4350BF583EFF090E071E0FFE50C24D1
:100F4E000AF582E4350BF583EFF090E072E0FFE5F1
:100F5E000C240BF582E4350BF583EFF090E073E093
:100F6E00FFE50C240CF582E4350BF583EFF090E0F1
:100F7E0074E0FFE50C240DF582E4350BF583EFF0FC
:100F8E007F087E00E4FDEDC394085028746E2FF5A3
:100F9E0082E434E0F583E0FCAB3FAA40A94175F052
:100FAE0002EDA4F58285F083EC1207830D0FBF00CE
:100FBE00010E80D2E5192404F582E43518F583E09C
:0E0FCE0030E0047F0180027F0090E037EFF0FA
:010FDC0022F2
:101B200090E071E02FFFE50C240AF582E4350BF517
:101B300083EFF0E50C240BF582E4350BF583E0FE32
:101B4000E50C240AF582E4350BF583E0FDEDFF900A
:101B5000E0B6EEF0A3EFF0D206121CB890E680E0FB
:041B600054F7F02224
:1016100090E600E054E74410F090E60174C0F090CA
:10162000E6107420F000000090E611F00000009039
:10163000E6047480F0000000740FF0000000E4F095
:1016400000000090E6187410F0000000E490E61925
:10165000F000000090E61A7408F0000000E490E644
:101660001BF000000090E6497482F0000000F000DA
:10167000000090E6247402F0000000E490E625F0FB
:1016800000000090E6957480F0000000F00000007B
:1016900043AF017B017AE07914755400755506E477
:0416A000FD021D9694
:061DE600D2877F0A7E0097
:101DEC007C007D181207A5EF1FAC0670011E4C700D
:021DFC00F622CD
:0A1A39008E3F8F408B418A428943A3
:101A4300E4F544F545C3E5459540E544953F503BF2
:101A5300AB41AA42A943854582854483120744FFCB
:101A6300E4FBFAC2B2EF1392B7EFC313FFD2B20B88
:101A7300BB00010AEB64084A70E9C2B220B002C39A
:0C1A8300220545E54570BE054480BAD33D
:011A8F002234
:101E180090E60174C0F0C2B67F967E00121DECD227
:081E2800B67F327E00021DECC2
:101EA300D2B1121DE6C2B1121DE8C2877F0A7E00BD
:031EB300021DEC21
:021B6400AB07CD
:101B6600E4F9FAEBC413131354011392B17F027E06
:101B760000121DECD2877F057E00121DECE925E0E0
:101B8600FFA283E4334FF97F057E00121DECEB259F
:0D1B9600E0FBC287121DE80ABA08C8AF01C3
:011BA300221F
:061A90008B538A548955B6
:101A9600A2AFE433F55B121EA3E4F55AE55AC395EB
:101AA600595027AB53AA54A955855A8275830012FB
:101AB6000744FF121B64AB56AA57A958855A82756C
:101AC6008300EF120783055A80D2120036E55B24A5
:031AD600FF92AFCD
:011AD90022EA
:0B003600C2B1121DE8121DE6D2B1227B
:100FDD00753F8F8F40755600755700755849755977
:0A0FED00027B007A00793F021A909F
:101C8700783F7C007D007BFF7A0F79F77E007F0528
:101C970012070530B41575560075570075583F750E
:101CA70059057B007A00793F121A90E5415401FFEC
:011CB700220A
:051EF1000300000000E9
:1011F50041E0370041E0B70042E0B2000041E0388D
:1012050000021BE0860218E07A43E0B40000004EBD
:10121500E03931303339354D502020202020200051
:101D9A008B518A528953E5561556AE557002155520
:101DAA004E6014AB510553E553AA52700205521402
:081DBA00F9ED12077180DF2230
:101BE5008B518A528953E5581558AE5770021557CF
:101BF5004E6026AB540556E556AA55700205551498
:101C0500F912072BFFAB510553E553AA5270020594
:0A1C15005214F9EF12077180CD227E
:101D7000C2B5C2B7E490E670F075B5E653B5EE4370
:101D8000B28053B2F4A2B53390E0B7F0C2B3C2B69A
:0A1D90007F327E00121E0AD2B62236
:101E6400538EF75389FB5389F74389015389FDE462
:071E7400F58AF58CD2A922CA
:1017B7008C428D43AA06A9077554018A5589567527
:1017C700570075581C7B017AE0794D121BE590E0B4
:1017D7004DE0B4C20374C0F090E065E0FCA3E0FD07
:1017E700A3E0FEA3E064D1FFEE648DFEED644CFD43
:1017F700EC6449FC90E06512084D7EE07F4D7D1C4E
:101807007C001213647EE07F4D7B1C7A00AD43ACF5
:10181700421214187D1C7C00AF43AE42120F367D76
:0A1827001C7C00AF43AE42021C55CA
:0818A9008E428F438C448D45F3
:1018B100C20712001290E15CEFF0BF5004D2078022
:1018C10057E490E15DF0A3F090E15DE0FEA3E0FF5D
:1018D100C39410EE648094805030E5452FF582E585
:1018E100443EF583E0FF90E15DE0FCA3E02543F594
:1018F10082E5423CF583E0B5071090E15EE004F03B
:1019010070C690E15DE004F080BE90E15DE070049E
:0A191100A3E064107002D207A207E1
:01191B0022A9
:020E0C008F3F16
:100E0E001200128F40E4F544F545AD45AC44121482
:100E1E00CE746A2545F582E434E0F583E541F005AC
:100E2E0045E54570020544C39408E544648094800A
:100E3E0040D8E53F600490E06AF090E06AE0B4C00C
:100E4E0008754200754308800675421D7543367558
:100E5E004400754508C3E5459410E54464809480CC
:100E6E0050231214CA746A2545F582E434E0F583E2
:100E7E00E541F00545E545700205440543E543703F
:100E8E00D4054280D07541FF75421D7543197544D6
:100E9E0000754510C3E545942CE54464809480505C
:100EAE0033E540B4510E7B007A007941AD43AC423C
:100EBE00FF1214D6746A2545F582E434E0F583E515
:100ECE0041F00545E545700205440543E54370C410
:100EDE00054280C075421D75433EE4F541F544F56B
:100EEE0045C3E5459406E54464809480502FE54063
:100EFE00B4510A90E06AE0B4C2031214CA744725D2
:100F0E0045F582E434E0F583E541F00545E54570AD
:100F1E000205440543E54370C8054280C490E06A6B
:070F2E00E0B4C20374C0F03F
:010F35002299
:0A1982008E428F438B448A4589464C
:10198C007E00E5432DF54BEE3542F54A1200128FE1
:10199C0047E5476451600BC3E5439410E54294005E
:1019AC005035854248854349C3E549954BE54895F3
:1019BC004A5024AB44AA45A946AD49AC48AF47129E
:1019CC0017340549E5497002054874012546F5466A
:0719DC00E43545F54580D11B
:0119E30022E1
:061831008B3F8A40894153
:10183700D2067554017555E075566A755700755887
:10184700107B017AE07996121BE5E5412410F9E453
:101857003540853F54F555895675570075580C7BAB
:10186700017AE079A6121BE57EE07F967CE07D1A7F
:101877001217B77EE07F1AE541241CF9E43540FCD6
:10188700AD011218A95016AB3FE5412410F9E43514
:1018970040FA7D1C7F197E1D1219828002C206A2A2
:0118A700063A
:0118A800221D
:101126007F03121D45EF2402FFE43EA907753F0128
:10113600F540894190E06BE0FFE50C2408F582E478
:10114600350BF583EFF090E06CE0FFE50C2409F534
:1011560082E4350BF583EFF090E06DE0FFE50C24BB
:101166000AF582E4350BF583EFF090E06EE0FFE5DB
:101176000C240BF582E4350BF583EFF090E06FE07D
:10118600FFE50C240CF582E4350BF583EFF090E0D7
:1011960070E0FFE50C240DF582E4350BF583EFF0E6
:1011A6007F087E00E4FDEDC394085028746A2FF58D
:1011B60082E434E0F583E0FCAB3FAA40A94175F038
:1011C60002EDA4F58285F083EC1207830D0FBF00B4
:1011D600010E80D2E5192404F582E43518F583E082
:0E11E60030E0047F0180027F0090E037EFF0E0
:0111F40022D8
:101B240090E06DE02FFFE50C240AF582E4350BF517
:101B340083EFF0E50C240BF582E4350BF583E0FE2E
:101B4400E50C240AF582E4350BF583E0FDEDFF9006
:101B5400E0B2EEF0A3EFF0D206121CBC90E680E0F7
:041B640054F7F02220
:1016140090E600E054E74410F090E60174C0F090C6
:10162400E6107420F000000090E611F00000009035
:10163400E6047480F0000000740FF0000000E4F091
:1016440000000090E6187410F0000000E490E61921
:10165400F000000090E61A7408F0000000E490E640
:101664001BF000000090E6497482F0000000F000D6
:10167400000090E6247402F0000000E490E625F0F7
:1016840000000090E6957480F0000000F000000077
:1016940043AF017B017AE07914755500755606E471
:0416A400FD021D9A8C
:061E0400D2877F0A7E0078
:101E0A007C007D181207A5EF1FAC0670011E4C70EE
:021E1A00F622AE
:0A1A3D008E3F8F408B418A4289439F
:101A4700E4F544F545C3E5459540E544953F503BEE
:101A5700AB41AA42A943854582854483120744FFC7
:101A6700E4FBFAC2B2EF1392B7EFC313FFD2B20B84
:101A7700BB00010AEB64084A70E9C2B220B002C396
:0C1A8700220545E54570BE054480BAD339
:011A93002230
:101E1C0090E60174C0F0C2B67F967E00121E0AD204
:081E2C00B67F327E00021E0A9F
:101EA700D2B1121E04C2B1121E06C2877F0A7E007B
:031EB700021E0AFE
:021B6800AB07C9
:101B6A00E4F9FAEBC413131354011392B17F027E02
:101B7A0000121E0AD2877F057E00121E0AE925E09E
:101B8A00FFA283E4334FF97F057E00121E0AEB257C
:0D1B9A00E0FBC287121E060ABA08C8AF01A0
:011BA700221B
:061A94008B538A548955B2
:101A9A00A2AFE433F55B121EA7E4F55AE55AC395E3
:101AAA00595027AB53AA54A955855A8275830012F7
:101ABA000744FF121B68AB56AA57A958855A827564
:101ACA008300EF120783055A80D2120036E55B24A1
:031ADA00FF92AFC9
:011ADD0022E6
:0B003600C2B1121E06121E04D2B1223D
:101DEA00753F8F8F4075560075570075584975595C
:0A1DFA00027B007A00793F021A9480
:101C8B00783F7C007D007BFF7A1E79F17E007F051B
:101C9B0012070530B41575560075570075583F750A
:101CAB0059057B007A00793F121A94E5415401FFE4
:011CBB002206
:100B4800753F007540007541007543017544E075B7
:100B580045007546017547E0754808E4FFF54F7B89
:100B6800017AE07900F554755508FD121D96AB43DE
:100B7800AA44A9457401120771E4F54EE54EC45420
:100B8800F0AB43AA44A94590000112078385465655
:100B9800854757854858755908121A90AB46AA4791
:100BA800A948900002120744FF530770EF24E06041
:100BB8001B24F0602A24F0603C24F0604E2440702E
:100BC80060753F018518408519418024E519240185
:100BD800FDE43518A905753F01F54089418011E507
:100BE800192402FDE43518A905753F01F54089412E
:100BF800754F088035E5192403FDE43518A90575F6
:100C08003F01F5408941754F04801FE5192405FD12
:100C1800E43518A905753F01F5408941754F98805D
:100C280009753F00754000754100E5404541453F65
:100C38006022AB3FAA40A94112072BFED3954F4033
:100C480006AD4FAE0580008E4212072BC3954212A7
:100C58000771800BEF70047E0180027E008E427463
:100C680049254EF8A642054EE54EC39405500302A9
:100C78000B84AB43AA44A9457488120771AB43E5BA
:100C8800452401F9E43544FA755300755400755547
:100C980049755600755705121BE185465685475715
:0F0CA800854858755908AB43AA44A945021A90CC
:1019E0008F3F90E0B6E0FEA3E054F064607003EE39
:1019F000641160037F012290E037E070037F0F22C3
:101A0000E53F7003308108E53FB401062080037F85
:101A1000102290E0BBE0B53F037F0122E4F511D234
:101A200006121CB8AF3F90E0BBEFF024FF92B590D8
:091A3000E680E054F7F07F00228B
:100B580045007546017547E0754808E4F54FFFF50F
:100B6800507B017AE07900F555755608FD121D9AFB
:100B7800AB43AA44A9457401120771E4F54EE54E4A
:100B8800C454F0AB43AA44A94590000112078385D9
:100B98004656854757854858755908121A94AB46E2
:100BA800AA47A948900002120744FE5403FFEE54D6
:100BB80070F54F24E0602924F0604B24F0605D2438
:100BC800F0606F24406003020C50753F01851840A7
:100BD800851941EF24FE600624FE703B801C801FAF
:100BE800E5192401FDE43518A905753F01F540898B
:100BF80041EF24FC60092402700A75500280527586
:100C08005006804D8011E5192402FDE43518A90528
:100C1800753F01F54089417550088035E519240371
:100C2800FDE43518A905753F01F540894175500463
:100C3800801FE5192405FDE43518A905753F01F560
:100C48004089417550988009753F0075400075418D
:100C580000E5404541453F6022AB3FAA40A941120B
:100C6800072BFED395504006AD50AE0580008E424E
:100C780012072BC39542120771800CE54F70047E52
:100C88000180027E008E427449254EF8A642054E28
:100C9800E54EC394055003020B86AB43AA44A9450D
:100CA8007488120771AB43E5452401F9E43544FA29
:100CB80075540075550075564975570075580512D5
:100CC8001BE5854656854757854858755908AB43EF
:070CD800AA44A945021A9489
:1019E4008F3F90E0B2E0FEA3E054F064607003EE39
:1019F400641160037F012290E037E070037F0F22BF
:101A0400E53F7003308108E53FB401062080037F81
:101A1400102290E0B7E0B53F037F0122E4F511D234
:101A240006121CBCAF3F90E0B7EFF024FF92B590D4
:091A3400E680E054F7F07F002287
:04000E0090FC04F06E
:1000120090E678E0541824F06008240870087F50B5
:0800220080067F518002E4FF1B
:01002A0022B3
:0C14C600AD43AC427B007A007941AF409E
:0C14D2008F468C478D488B498A4A894B15
:1014DE00E4F54CF54D754E03FDF54FF550A2AF33C7
:1014EE00F551E54624AF600D047012754C00754D34
:1014FE00017D018008754C00754D02E4FDE54660E6
:10150E0051E54D454C604BE54790E0B8F0E548A3FA
:10151E00F074B82DF582E434E0AD82FCAB4DAF46ED
:10152E00121918754F008F507F0A7E00121ADAE5D5
:10153E0050454F60107CE07D6D7B01AF4612156B00
:10154E00754F008F5090E06DE0AB49AA4AA94B123F
:0C155E000771E55124FF92AFAE4FAF5073
:01156A00225E
:0C1730008F4C8C4D8D4E8B4F8A50895190
:10173C00E4F552F553755403FDF555F556A2AF3348
:10174C00F557E54C24AF600D0470127552007553BB
:10175C00027D018008755200755303E4FDE54C6071
:10176C003BE55345526035E54D90E0B8F0E54EA3AE
:10177C00F0AB4FAA50A95112072B90E0BAF074B8F5
:10178C002DF582E434E0AD82FCAB53AF4C1219184A
:10179C007555008F567F0A7E00121ADAE55724FF22
:0617AC0092AFAE55AF56EE
:0117B2002214
:0C14CA00AD43AC427B007A007941AF409A
:0C14D6008F468C478D488B498A4A894B11
:1014E200E4F54CF54D754E03FDF54FF550A2AF33C3
:1014F200F551E54624AF600D047012754C00754D30
:10150200017D018008754C00754D02E4FDE54660E1
:1015120051E54D454C604BE54790E0B4F0E548A3FA
:10152200F074B42DF582E434E0AD82FCAB4DAF46ED
:1015320012191C754F008F507F0A7E00121ADEE5C9
:1015420050454F60107CE07D697B01AF4612156FFC
:10155200754F008F5090E069E0AB49AA4AA94B123F
:0C1562000771E55124FF92AFAE4FAF506F
:01156E00225A
:0C1734008F4C8C4D8D4E8B4F8A5089518C
:10174000E4F552F553755403FDF555F556A2AF3344
:10175000F557E54C24AF600D0470127552007553B7
:10176000027D018008755200755303E4FDE54C606D
:101770003BE55345526035E54D90E0B4F0E54EA3AE
:10178000F0AB4FAA50A95112072B90E0B6F074B4F9
:101790002DF582E434E0AD82FCAB53AF4C12191C42
:1017A0007555008F567F0A7E00121ADEE55724FF1A
:0617B00092AFAE55AF56EA
:0117B6002210
:10005600E4F531F532F535F53AF53BF53CF53DE598
:10006600AA5484600302063490E694E0FE90E69576
:10007600E0FBEEF53AEBF53BC39405E53A94004018
@@ -224,67 +226,67 @@
:1000B6004732045A3404A23504B93604D63703D578
:1000C6004503E647000005B475310075320790FC1C
:1000D600047481F0A37414F0E4A3F00205D77F0F33
:1000E600120FDD75310075320690FC047480F0E461
:1000E600121DEA75310075320690FC047480F0E446
:1000F600A3F0753505F511FE74002535F9EE34F4D7
:10010600FA7B0112182D400690FC05740EF0E4FFF0
:10011600120DE47F8F0202B37F0E120FDD753100E0
:10010600FA7B01121831400690FC05740EF0E4FFEC
:10011600120E0C7F8F0202B37F0E121DEA7531009C
:10012600753205748E12000E8F3D7B007A00793E83
:10013600E4FDFC1214D2E53D64516019E53D6450BE
:10013600E4FDFC1214D6E53D64516019E53D6450BA
:10014600601375310075320690FC047480F0A37458
:100156000BF00205D790E0BCE0FF120DE474002519
:1001660032F974FC3531FA7B01C0038B537554E0C8
:1001760075556E75560075572CD003121BE1742CFD
:100156000BF00205D790E0B8E0FF120E0C740025F4
:1001660032F974FC3531FA7B01C0038B547555E0C6
:1001760075566A75570075582CD003121BE5742CFA
:100186002532F532E43531F5317F8E0202B3753111
:100196000075320790FC047491F090E678E090FCCC
:1001A60005F030B4047F0180027F0090FC06EFF07A
:1001B60074002532F974FC3531FA7B0175540075EB
:1001C6005512E4FD121D9674002532F974FC353182
:1001D600FA7B01C0038B537554E07555397556008B
:1001E600755706D003121BE174062532F532E43545
:1001B60074002532F974FC3531FA7B0175550075EA
:1001C6005612E4FD121D9A74002532F974FC35317D
:1001D600FA7B01C0038B547555E075563975570087
:1001E600755806D003121BE574062532F532E43540
:1001F60031F531FE74002532F974FC3EFA7B01C0FC
:10020600038B537554E0755514755600755706D013
:1002160003121BE174062532F532E43531F531FE61
:1002260074002532F974FC3EFA7B01C0038B5375CA
:1002360054E075554B755600755706D003121BE1F1
:10020600038B547555E0755614755700755806D00E
:1002160003121BE574062532F532E43531F531FE5D
:1002260074002532F974FC3EFA7B01C0038B5475C9
:1002360055E0755647755700755806D003121BE5ED
:1002460074062532F532E43531F5310205D77F13D0
:10025600120FDD75310075321D749312000E8F3D3D
:10025600121DEA75310075321D749312000E8F3D22
:1002660075381D753900753600753705D3E539942F
:1002760018E538941D5034E53DB4510E7B007A00E4
:10028600793EAD39AC38FF1214D274002537F582A9
:10028600793EAD39AC38FF1214D674002537F582A5
:1002960074FC3536F583E53EF00539E5397002051F
:1002A600380537E53770C5053680C17F93120FDDF7
:1002A600380537E53770C5053680C17F93121DEADC
:1002B6000205D775310075320690FC047480F0E4AF
:1002C600A3F090F405E090E038F0E014702A30B026
:1002D6001E121E187553017554F475550675560091
:1002E6007557067B017AE07914121BE10205D79057
:1002D6001E121E1C7554017555F475560675570089
:1002E6007558067B017AE07914121BE50205D79052
:1002F600FC057401F00203C08056753100753206A4
:1003060090FC047480F0E4A3F0753507AF35FEC3A6
:10031600E53B9FF534E53A9EF53390E038E01470FE
:100326002F20B00330B42074002FF974F43EFA7B0A
:1003360001AF34AE33121A395004E40204B290FC11
:1003360001AF34AE33121A3D5004E40204B290FC0D
:1003460005740CF00205D790FC057402F00205D77F
:1003560090FC057403F00205D775310075320690DE
:10036600FC047480F0E4A3F090E038E014704530AB
:10037600B43A90E6017403F07F647E00121DEC909F
:10038600E0BCE0FF120DE47EE07F6E7CE07DBD12F6
:1003960017B37EE07FBDAD1CAC1B1218A55005122D
:10037600B43A90E6017403F07F647E00121E0A9080
:10038600E0B8E0FF120E0C7EE07F6A7CE07DB912D9
:1003960017B77EE07FB9AD1CAC1B1218A950051229
:1003A6000B48801690FC05740EF0800E90FC0574C8
:1003B6000DF0800690FC057403F0E490E038F0023E
:1003C60005D7E4F531F5327F02121B200205D7E48A
:1003D600FF120DE4120F0EE4FF1219E0E4FF800293
:1003E6007F01121B20121E180205D77531007532C7
:1003C60005D7E4F531F5327F02121B240205D7E486
:1003D600FF120E0C121126E4FF1219E4E4FF80024C
:1003E6007F01121B24121E1C0205D77531007532BF
:1003F6000690FC047480F0E4A3F090F405E0F53C6C
:10040600E4F511E53C64016004E53C703290E0B629
:10040600E4F511E53C64016004E53C703290E0B22D
:10041600E0FEA3E054F064607003EE6411600280B5
:100426007290E037E070028058E5116401600AE5D9
:1004360011700C121C87EF6006853C110205D780EF
:1004360011700C121C8BEF6006853C110205D780EB
:100446005275310075320690FC0474B2F0A3E511C2
:10045600F00205D775310075320690FC047480F001
:10046600E4A3F090F405E0F53CFF1219E0EF24F167
:10046600E4A3F090F405E0F53CFF1219E4EF24F163
:10047600600F1460152410701AE4F531F532020588
:10048600D790FC05740FF00205D790FC057410F0A8
:100496000205D790FC057401F00205D77531007589
:1004A600320690FC0474B5F090E0BBE090FC05F0D9
:1004A600320690FC0474B5F090E0B7E090FC05F0DD
:1004B6000205D775310075320690FC0474B6F0A2B9
:1004C60080E43325E0FFA281E4334FA3F00205D791
:1004D600853A31853B3290FC0474B7F0753505C317
@@ -292,11 +294,11 @@
:1004F600F582E434F4F583E0648870030205D7AF2F
:10050600357E0074002FF9EE34F4FA7B01C003C087
:100516000174002FF9EE34FC8B56F5578958853453
:1005260059D001D003121A900205D77531007532E1
:1005260059D001D003121A940205D77531007532DD
:100536000590FC0474A5F01200128F3D7B007A0032
:10054600793EE4FDFC1214D290E036E0FF0532E578
:10054600793EE4FDFC1214D690E036E0FF0532E574
:1005560032AC3170020531142400F58274FC3CF58E
:1005660083EFF090E0BCE0FF0532E532AC3170027B
:1005660083EFF090E0B8E0FF0532E532AC3170027F
:100576000531142400F58274FC3CF583EFF0053256
:10058600E532AE3170020531142400F58274FC3E6A
:10059600F583E53EF00532E532AE317002053114E1
@@ -312,66 +314,66 @@
:0106340022A3
:02004100D322C8
:0800030090E6BAE0F51DD322DE
:101EC90090E740E51DF0E490E68AF090E68B04F097
:021ED900D32212
:101ECD0090E740E51DF0E490E68AF090E68B04F093
:021EDD00D3220E
:08002B0090E6BAE0F51AD322B9
:101EDB0090E740E51AF0E490E68AF090E68B04F088
:021EEB00D32200
:101DBE0090E6B9E0242F600D04701990E604E0FF60
:101DCE00430780800890E604E0FF53077F00000081
:071DDE00EFF08002D322C3E5
:011DE50022DB
:101E3000C0E0C083C082D2015391EF90E65D74018F
:081E4000F0D082D083D0E03223
:101E7700C0E0C083C0825391EF90E65D7404F0D058
:061E870082D083D0E0329E
:101E8D00C0E0C083C0825391EF90E65D7402F0D044
:061E9D0082D083D0E03288
:101C1B00C0E0C083C08285120D85130E850E8285B0
:101C2B000D83A37402F085090F850A108510828538
:101C3B000F83A37407F05391EF90E65D7410F0D00F
:061C4B0082D083D0E032DC
:101E4800C0E0C083C082D2035391EF90E65D74086E
:081E5800F0D082D083D0E0320B
:101BA400C0E0C083C08290E680E030E72085090D64
:101BB400850A0E850E82850D83A37402F085120FAB
:101BC400851310851082850F83A37407F05391EF5A
:0D1BD40090E65D7420F0D082D083D0E03226
:101EB600000102020303040405050300000000C03C
:031EC600C2000057
:06122100011100010800AC
:03000B000212AC32
:1012AC00C0E0C0F0C083C082C0D075D000C000C008
:0D12BC0001C002C003C004C005C006C00789
:1012C90078217C007D007BFF7A1E79C07E007F0536
:1012D90012070590E0BBE0F526C204752700E50872
:1012E900600415088056750805E5117004C204806C
:1012F90043A280308101B3500B3081047F008030DC
:101309007F01802C30B4157556007557007558212A
:101319007559057B007A007921121A90E523540149
:10132900F527701090E0BBE060047F0080027F0128
:0C1339008F26D204300405AF261219E004
:10134500D007D006D005D004D003D002D001D000FC
:0B135500D0D0D082D083D0F0D0E032A6
:100CB700785B7CE17D017BFF7A1E79C57E007F042E
:100CC700120705C203C200D202C201121D6C121E16
:100CD70060121610750B10750C007514107515122F
:100CE700750910750A1C75121075137085120F851A
:100CF70013107516107517B412001290E159EFF022
:100D07007B017AE1795AE4FDFC1214D290E15AE0B2
:100D1700FF90E036F0E490E0BCF0EF64C26059EF7A
:100D270064C06054E490E15FF090E15FE0FFC3943A
:100D370004504A745B2FF582E434E1F583E0FF60E9
:100D47003C120DE47EE07F6E7CE07DBD1217B37E22
:100D5700E07FBDAD1CAC1B1218A5501490E15FE0FD
:100D6700245BF582E434E1F583E090E0BCF0800D8C
:100D770090E15FE004F080B1E4FF120DE4120F0E82
:100D8700D2E843D82090E668E04409F090E65CE0BA
:100D9700443DF012001290E159EFF07B017AE179BE
:100DA7005AE4FDFC1214D290E15AE064C26007E4F1
:100DB70090E0BBF0C2B57F01121B20D2AFD28C539B
:100DC7008EF8C203C2AF120056D2AF300105120926
:0D0DD70020C2013003EEC203121D1580E79B
:101EDF0090E740E51AF0E490E68AF090E68B04F084
:021EEF00D322FC
:101DC20090E6B9E0242F600D04701990E604E0FF5C
:101DD200430780800890E604E0FF53077F0000007D
:071DE200EFF08002D322C3E1
:011DE90022D7
:101E3400C0E0C083C082D2015391EF90E65D74018B
:081E4400F0D082D083D0E0321F
:101E7B00C0E0C083C0825391EF90E65D7404F0D054
:061E8B0082D083D0E0329A
:101E9100C0E0C083C0825391EF90E65D7402F0D040
:061EA10082D083D0E03284
:101C1F00C0E0C083C08285120D85130E850E8285AC
:101C2F000D83A37402F085090F850A108510828534
:101C3F000F83A37407F05391EF90E65D7410F0D00B
:061C4F0082D083D0E032D8
:101E4C00C0E0C083C082D2035391EF90E65D74086A
:081E5C00F0D082D083D0E03207
:101BA800C0E0C083C08290E680E030E72085090D60
:101BB800850A0E850E82850D83A37402F085120FA7
:101BC800851310851082850F83A37407F05391EF56
:0D1BD80090E65D7420F0D082D083D0E03222
:101EBA00000102020303040405050300000000C038
:031ECA00C2000053
:06122500011100010800A8
:03000B000212B02E
:1012B000C0E0C0F0C083C082C0D075D000C000C004
:0D12C00001C002C003C004C005C006C00785
:1012CD0078217C007D007BFF7A1E79C47E007F052E
:1012DD0012070590E0B7E0F526C204752700E50872
:1012ED00600415088056750805E5117004C2048068
:1012FD0043A280308101B3500B3081047F008030D8
:10130D007F01802C30B41575560075570075582126
:10131D007559057B007A007921121A94E523540141
:10132D00F527701090E0B7E060047F0080027F0128
:0C133D008F26D204300405AF261219E4FC
:10134900D007D006D005D004D003D002D001D000F8
:0B135900D0D0D082D083D0F0D0E032A2
:100CDF0078577CE17D017BFF7A1E79C97E007F0406
:100CEF00120705C203C200D202C201121D70121EEA
:100CFF0064121614750B10750C00751410751512FF
:100D0F00750910750A1C75121075137085120F85F1
:100D1F0013107516107517B412001290E155EFF0FD
:100D2F007B017AE17956E4FDFC1214D690E156E08E
:100D3F00FF90E036F0E490E0B8F0EF64C26059EF56
:100D4F0064C06054E490E15BF090E15BE0FFC3941A
:100D5F0004504A74572FF582E434E1F583E0FF60C5
:100D6F003C120E0C7EE07F6A7CE07DB91217B77ED5
:100D7F00E07FB9AD1CAC1B1218A9501490E15BE0D9
:100D8F002457F582E434E1F583E090E0B8F0800D6C
:100D9F0090E15BE004F080B1E4FF120E0C1211261B
:100DAF00D2E843D82090E668E04409F090E65CE092
:100DBF00443DF012001290E155EFF07B017AE1799A
:100DCF0056E4FDFC1214D690E156E064C26007E4CD
:100DDF0090E0B7F0C2B57F01121B24D2AFD28C5373
:100DEF008EF8C203C2AF120056D2AF3001051209FE
:0D0DFF0020C2013003EEC203121D1980E76F
:0B00460090E50DE030E402C322D3225D
:1009200090E6B9E070030209E5147003020A5A2444
:10093000FE7003020AD524FB70030209DF14700362
@@ -381,22 +383,22 @@
:1009700024067056E50B90E6B3F0E50C80421200B9
:10098000465044E51490E6B3F0E5158033E50D904C
:10099000E6B3F0E50E802985120F851310E50F9060
:1009A000E6B3F0E510801990E6BAE0FF121D41AA07
:1009A000E6B3F0E510801990E6BAE0FF121D45AA03
:1009B00006A9077B01EA494B600DEE90E6B3F0EF24
:1009C00090E6B4F0020B40020B2F020B2F121EDB3D
:1009C00090E6B4F0020B40020B2F020B2F121EDF39
:1009D000020B4012002B020B40120003020B4012CC
:1009E0001EC9020B4090E6B8E0247F601514601920
:1009E0001ECD020B4090E6B8E0247F60151460191C
:1009F00024027063A200E43325E0FFA202E4334F37
:100A00008041E490E740F0803F90E6BCE0547EFFF8
:100A10007E00E0D394807C0040047D0180027D0054
:100A2000EC4EFEED4F24B6F582741E3EF583E49342
:100A2000EC4EFEED4F24BAF582741E3EF583E4933E
:100A3000FF3395E0FEEF24A1FFEE34E68F82F583CD
:100A4000E0540190E740F0E4A3F090E68AF090E6ED
:100A50008B7402F0020B40020B2F90E6B8E024FEEC
:100A6000601624026003020B4090E6BAE0B4010570
:100A7000C200020B40020B2F90E6BAE0705590E6E0
:100A8000BCE0547EFF7E00E0D394807C0040047D77
:100A90000180027D00EC4EFEED4F24B6F582741EFF
:100A90000180027D00EC4EFEED4F24BAF582741EFB
:100AA0003EF583E493FF3395E0FEEF24A1FFEE349F
:100AB000E68F82F583E054FEF090E6BCE0548013AC
:100AC0001313541FFFE0540F2F90E683F0E04420EF
@@ -404,110 +406,110 @@
:100AE0004E90E6BAE0B40104D200805490E6BAE039
:100AF0006402604C803990E6BCE0547EFF7E00E0EA
:100B0000D394807C0040047D0180027D00EC4EFE89
:100B1000ED4F24B6F582741E3EF583E493FF3395C2
:100B1000ED4F24BAF582741E3EF583E493FF3395BE
:100B2000E0FEEF24A1FFEE34E68F82F583800D9086
:100B3000E6A08008121DBE500790E6A0E04401F038
:100B3000E6A08008121DC2500790E6A0E04401F034
:070B400090E6A0E04480F004
:010B4700228B
:03003300020FFCBD
:040FFC0053D8EF32A5
:101227006080E0D9292E43C9A2D87C013D3654A15C
:10123700ECF0061362A705F3C0C7738C98932BD9FC
:10124700BC4C82CA1E9B573CFDD4E01667426F1800
:101257008A17E512BE4EC4D6DA9EDE49A0FBF58E8C
:10126700BB2FEE7AA968799115B2073F94C210890E
:101277000B225F21807F5D9A5A903227353ECCE75B
:10128700BFF79703FF1930B348A5B5D1D75E922AA8
:10129700AC56AAC64FB838D296A47DB676FC6BE298
:0412A7009C7404F13E
:081360008C448D45AB07AA0681
:10136800E4F546F547C3E5479545E5446480F8E567
:1013780046648098400302140FE54725E0FFE546E0
:1013880033FE74D92FF58274E03EF583E0FF7E00CA
:10139800AC44AD451207B78C488D49E54725E0FFB9
:1013A800E54633FE74DA2FF58274E03EF583E0FFFC
:1013B8007E00AC44AD451207B78C4A8D4BE54965B4
:1013C8004B7004E548654A6030EB2549F582EA35FB
:1013D80048F583E0F9EB254BF582EA354AF583E0D9
:1013E800FFEB2549F582EA3548F583EFF0EB254B0D
:1013F800F582EA354AF583E9F00547E547600302D7
:0B140800136D054602136D7E007F018E
:0114130022B6
:0C1414008E448F458C468D478A488B49DA
:10142000E54545446006E54745467004E4FEFF2275
:10143000E4F54AF54BC3E54B9549E5486480F8E58A
:101440004A648098507BE4F54CF54DE547254BF513
:1014500082E546354AF583E4F0C3E54D9549E54814
:101460006480F8E54C6480985049E54D254B24D9BB
:10147000F582E434E0F583E0FFE545254DF582E5AE
:1014800044354CF583E0FEEF8EF0A4FFE547254B95
:10149000F582E546354AF583E02FFFE547254BF514
:1014A00082E546354AF583EFF0054DE54D70AA0516
:1014B0004C80A6054BE54B6003021435054A021427
:0514C000357E007F01F4
:0114C5002204
:101CE70012072BFF9000031207441207719000039D
:101CF700EF120783900002120744FF9000011207BA
:0E1D070044900002120783900001EF02078350
:081126008E448F458C468D4775
:10112E00E4F548F549E547AE467802CEA2E713CE80
:10113E0013D8F8FFC3E5499FEE6480F8E548648054
:10114E009840030211E8E549AE487802C333CE3326
:10115E00CED8F92545FFEE3544FAA9077B018B4A17
:10116E00F54B894C74DA2549F582E434E0F583E0D9
:10117E00541FFFE48F50F54FF54EF54D121CE7ABA3
:10118E004AAA4BA94C120813C374209550F9F812B1
:10119E000800C004C005C006C007A94C120813A958
:1011AE0050A8011207EDD003D002D001D000EF4BB2
:1011BE00FFEE4AFEED49FDEC48FCAB4AAA4BA94CAA
:1011CE00120833AB4AAA4BA94C121CE70549E54954
:0E11DE00600302113305480211337E007F01C9
:0111EC0022E0
:101C5100D3ED9410EC64809480402AED1D70011C3A
:101C6100142FF582EE3CF583E0FB547F24D9F582F5
:101C7100E434E0F583E0F9540F2FF582E43EF58377
:051C8100E06BF080CBD8
:011C8600223B
:101D150090E682E030E004E020E60B90E682E030D9
:101D2500E119E030E71590E680E04401F07F147E8C
:0C1D350000121ADA90E680E054FEF02262
:101CB80030060990E680E0440AF0800790E680E06C
:101CC8004408F07FDC7E05121ADA90E65D74FFF0B6
:0F1CD80090E65FF05391EF90E680E054F7F02232
:101ADA008E588F5990E600E054187012E559240187
:101AEA00FFE43558C313F558EF13F559801590E6FE
:101AFA0000E05418FFBF100BE55925E0F559E558E9
:101B0A0033F558E5591559AE58700215584E600507
:061B1A00121EED80EE2218
:06156B008C528D53AE0707
:10157100EB70037F012290E678E020E6F990E678AF
:101581007480F0EE25E0440190E679F090E678E091
:1015910030E0F990E678E020E26BE030E167BB01F2
:1015A1000790E678E04420F090E679E0F5541BEBF3
:1015B100603090E678E030E0F990E678E020E245AE
:1015C100BB010790E678E04420F090E679E0FF0562
:1015D10053E553AC527002055214F5828C83EFF03F
:1015E10080CC90E678E030E0F990E678E020E215F2
:1015F10090E678E04440F090E679E08553828552A8
:0E16010083F07F012290E678E04440F07F0005
:01160F0022B8
:1019180090E678E020E6F990E6787480F0EF25E02C
:1019280090E679F090E678E030E0F990E678E0200B
:10193800E23AE030E136EBD3940040260DEDAE04F8
:1019480070010C14F5828E83E090E679F01B90E626
:1019580078E030E0F990E678E020E210E020E1D687
:10196800800A90E678E04440F07F012290E678E033
:051978004440F07F0077
:01197D002247
:021D4100A907F0
:101D4300AE16AF178F828E83A3E064037017AD01C5
:101D530019ED7001228F828E83E07C002FFDEC3E13
:081D6300FEAF0580DFE4FEFF86
:011D6B002255
:101EED007400F58690FDA57C05A3E582458370F908
:011EFD0022C2
:030000000216A441
:0C16A400787FE4F6D8FD75815B0216EB40
:03003300021EF6B4
:041EF60053D8EF329C
:10122B006080E0D5292E43C9A2D87C013D3654A15C
:10123B00ECF0061362A705F3C0C7738C98932BD9F8
:10124B00BC4C82CA1E9B573CFDD4E01667426F18FC
:10125B008A17E512BE4EC4D6DA9EDE49A0FBF58E88
:10126B00BB2FEE7AA968799115B2073F94C210890A
:10127B000B225F21807F5D9A5A903227353ECCE757
:10128B00BFF79703FF1930B348A5B5D1D75E922AA4
:10129B00AC56AAC64FB838D296A47DB676FC6BE294
:0412AB009C7404F13A
:081364008C448D45AB07AA067D
:10136C00E4F546F547C3E5479545E5446480F8E563
:10137C00466480984003021413E54725E0FFE546D8
:10138C0033FE74D52FF58274E03EF583E0FF7E00CA
:10139C00AC44AD451207B78C488D49E54725E0FFB5
:1013AC00E54633FE74D62FF58274E03EF583E0FFFC
:1013BC007E00AC44AD451207B78C4A8D4BE54965B0
:1013CC004B7004E548654A6030EB2549F582EA35F7
:1013DC0048F583E0F9EB254BF582EA354AF583E0D5
:1013EC00FFEB2549F582EA3548F583EFF0EB254B09
:1013FC00F582EA354AF583E9F00547E547600302D3
:0B140C00137105460213717E007F0182
:0114170022B2
:0C1418008E448F458C468D478A488B49D6
:10142400E54545446006E54745467004E4FEFF2271
:10143400E4F54AF54BC3E54B9549E5486480F8E586
:101444004A648098507BE4F54CF54DE547254BF50F
:1014540082E546354AF583E4F0C3E54D9549E54810
:101464006480F8E54C6480985049E54D254B24D5BB
:10147400F582E434E0F583E0FFE545254DF582E5AA
:1014840044354CF583E0FEEF8EF0A4FFE547254B91
:10149400F582E546354AF583E02FFFE547254BF510
:1014A40082E546354AF583EFF0054DE54D70AA0512
:1014B4004C80A6054BE54B6003021439054A02141F
:0514C400397E007F01EC
:0114C9002200
:101CEB0012072BFF90000312074412077190000399
:101CFB00EF120783900002120744FF9000011207B6
:0E1D0B0044900002120783900001EF0207834C
:080F36008E448F458C468D4767
:100F3E00E4F548F549E547AE467802CEA2E713CE72
:100F4E0013D8F8FFC3E5499FEE6480F8E548648046
:100F5E00984003020FF8E549AE487802C333CE330A
:100F6E00CED8F92545FFEE3544FAA9077B018B4A09
:100F7E00F54B894C74D62549F582E434E0F583E0CF
:100F8E00541FFFE48F50F54FF54EF54D121CEBAB91
:100F9E004AAA4BA94C120813C374209550F9F812A3
:100FAE000800C004C005C006C007A94C120813A94A
:100FBE0050A8011207EDD003D002D001D000EF4BA4
:100FCE00FFEE4AFEED49FDEC48FCAB4AAA4BA94C9C
:100FDE00120833AB4AAA4BA94C121CEB0549E54942
:0E0FEE006003020F430548020F437E007F019F
:010FFC0022D2
:101C5500D3ED9410EC64809480402AED1D70011C36
:101C6500142FF582EE3CF583E0FB547F24D5F582F5
:101C7500E434E0F583E0F9540F2FF582E43EF58373
:051C8500E06BF080CBD4
:011C8A002237
:101D190090E682E030E004E020E60B90E682E030D5
:101D2900E119E030E71590E680E04401F07F147E88
:0C1D390000121ADE90E680E054FEF0225A
:101CBC0030060990E680E0440AF0800790E680E068
:101CCC004408F07FDC7E05121ADE90E65D74FFF0AE
:0F1CDC0090E65FF05391EF90E680E054F7F0222E
:101ADE008E588F5990E600E054187012E559240183
:101AEE00FFE43558C313F558EF13F559801590E6FA
:101AFE0000E05418FFBF100BE55925E0F559E558E5
:101B0E0033F558E5591559AE58700215584E600503
:061B1E00121F1880EE22E8
:06156F008C528D53AE0703
:10157500EB70037F012290E678E020E6F990E678AB
:101585007480F0EE25E0440190E679F090E678E08D
:1015950030E0F990E678E020E26BE030E167BB01EE
:1015A5000790E678E04420F090E679E0F5541BEBEF
:1015B500603090E678E030E0F990E678E020E245AA
:1015C500BB010790E678E04420F090E679E0FF055E
:1015D50053E553AC527002055214F5828C83EFF03B
:1015E50080CC90E678E030E0F990E678E020E215EE
:1015F50090E678E04440F090E679E08553828552A4
:0E16050083F07F012290E678E04440F07F0001
:0116130022B4
:10191C0090E678E020E6F990E6787480F0EF25E028
:10192C0090E679F090E678E030E0F990E678E02007
:10193C00E23AE030E136EBD3940040260DEDAE04F4
:10194C0070010C14F5828E83E090E679F01B90E622
:10195C0078E030E0F990E678E020E210E020E1D683
:10196C00800A90E678E04440F07F012290E678E02F
:05197C004440F07F0073
:011981002243
:021D4500A907EC
:101D4700AE16AF178F828E83A3E064037017AD01C1
:101D570019ED7001228F828E83E07C002FFDEC3E0F
:081D6700FEAF0580DFE4FEFF82
:011D6F002251
:101F18007400F58690FDA57C05A3E582458370F9DC
:011F28002296
:030000000216A83D
:0C16A800787FE4F6D8FD75815B0216EF38
:10063500E709F608DFFA8046E709F208DFFA803EA7
:1006450088828C83E709F0A3DFFA8032E309F60894
:10065500DFFA8078E309F208DFFA807088828C83FC
@@ -552,15 +554,15 @@
:10085900D083D082F8E4937012740193700DA3A32E
:1008690093F8740193F5828883E473740293686042
:06087900EFA3A3A380DF42
:1016B000020CB7E493A3F8E493A34003F68001F28D
:1016C00008DFF48029E493A3F85407240CC8C3333B
:1016D000C4540F4420C8834004F456800146F6DF0A
:1016E000E4800B01020408102040809011EDE47E9C
:1016F000019360BCA3FF543F30E509541FFEE493FF
:10170000A360010ECF54C025E060A840B8E493A3C5
:10171000FAE493A3F8E493A3C8C582C8CAC583CAF0
:10172000F0A3C8C582C8CAC583CADFE9DEE780BEA8
:0112AB000042
:1016B400020CDFE493A3F8E493A34003F68001F261
:1016C40008DFF48029E493A3F85407240CC8C33337
:1016D400C4540F4420C8834004F456800146F6DF06
:1016E400E4800B01020408102040809011F5E47E90
:1016F400019360BCA3FF543F30E509541FFEE493FB
:10170400A360010ECF54C025E060A840B8E493A3C1
:10171400FAE493A3F8E493A3C8C582C8CAC583CAEC
:10172400F0A3C8C582C8CAC583CADFE9DEE780BEA4
:0112AF00003E
:10087F00BC000BBE0029EF8DF084FFADF022E4CC5D
:10088F00F875F008EF2FFFEE33FEEC33FCEE9DEC26
:10089F00984005FCEE9DFE0FD5F0E9E4CEFD22ED6C
@@ -574,4 +576,3 @@
:0C090800ECF608EDF608EEF608EFF6221B
:0C091400ECF208EDF208EEF208EFF2221F
:00000001FF


View File

@@ -0,0 +1,421 @@
#
# $Id: USB_RECOV.hex 9760 2011-09-05 12:33:27Z dima $
#
:03004300021600A2
:0300530002160092
:10160000021580000215C6000215B00002159800F0
:081610000213F20002137B003B
:100A00001201000200000040AAAAAAAAAAAA010292
:100A100003010A060002000000400100090237003D
:100A2000020100C0000904000002FFFFFF040705E7
:100A3000020200020007058602000200090401000C
:100A400002FFFFFF050705040200020007058802F8
:100A5000000200001201000200000040E4E4511115
:100A60000000010203010A0600020000004001002C
:100A700009023700020100C0320904000002FFFF32
:100A8000FF0407050202400000070586024000003F
:100A90000904010002FFFFFF0507050402400000F2
:100AA000070588024000000604001600140012002A
:100AB0000A00260004030904160358006F007200A0
:100AC00063006F006D0020004C00540044001403CC
:100AD00041007300740072006900620061006E00E2
:100AE0006B001203530065007200690061006C0026
:100AF0004E006F000A0346005000470041002603E5
:100B00004D0061006E00610067006D0065006E00C1
:100B10007400500072006F00630065007300730082
:060B20006F0072000000EE
:08164300584F52434F4D2000A7
:100E650041E0B20042E0AD0000021BE0810218E063
:100E75007543E0AF0000004CE036393734364D207D
:060E8500202020202000C7
:101517008B2A8A2B892CE52F152FAE2E7002152EBC
:101527004E6014AB2A052CE52CAA2B7002052B1450
:08153700F9ED12019280DF22A0
:1013B8008B328A338934E5391539AE3870021538DD
:1013C8004E6026AB350537E537AA36700205361468
:1013D800F912014CFFAB320534E534AA337002052B
:0A13E8003314F9EF12019280CD22B8
:1011FD008C2A8D2BAA06A9077535018A3689377574
:10120D00380075391C7B017AE079481213B890E0EB
:10121D0060E0FCA3E0FDA3E0FEA3E064D1FFEE647B
:10122D008DFEED644CFDEC6449FC90E06012026EA5
:10123D007EE07F487D1C7C00120CFF7EE07F487BAA
:10124D001C7A00AD2BAC2A120DB37D1C7C00AF2B8C
:10125D00AE2A120C387D1C7C00AF2BAE2A0214284E
:08099F008E2A8F2B8C2C8D2D6C
:1009A700C204121567BF5004D204803BE4F52EF54C
:1009B7002FE52D252FF582E52C352EF583E0FFE574
:1009C7002B252FF582E52A352EF583E0B5070E0591
:1009D7002FE52F7002052E6410452E70D4E52F6485
:0909E70010452E7002D204A20496
:0109F00022E4
:020875008F32C0
:100877001215678F33E4F537F538AD38AC37120FFB
:100887001474652538F582E434E0F583E534F00522
:1008970038E53870020537C39408E53764809480DB
:1008A70040D8E532600490E065F090E065E0B4C0C0
:1008B70008753500753608800675351D7536367529
:1008C7003700753808C3E5389410E537648094809D
:1008D7005023120F1074652538F582E434E0F58350
:1008E700E534F00538E538700205370536E536702A
:1008F700D4053580D07534FF75351D7536197537B4
:1009070000753810C3E538942CE53764809480501F
:1009170033E533B4510E7B007A007934AD36AC350C
:10092700FF120F1C74652538F582E434E0F583E582
:1009370034F00538E538700205370536E53670C4FA
:10094700053580C075351D75363EE4F534F537F548
:1009570038C3E5389406E53764809480502FE53333
:10096700B4510A90E065E0B4C203120F1074422537
:1009770038F582E434E0F583E534F00538E538707E
:100987000205370536E53670C8053580C490E06541
:07099700E0B4C20374C0F0DC
:01099E002236
:0A12D3008E2A8F2B8B2C8A2D892E7A
:1012DD007E00E52B2DF533EE352AF5321215678F8D
:1012ED002FE52F6451600BC3E52B9410E52A940074
:1012FD005035852A30852B31C3E5319533E5309551
:10130D00325024AB2CAA2DA92EAD31AC30AF2F12FB
:10131D00117A0531E531700205307401252EF52E57
:07132D00E4352DF52D80D100
:011334002296
:020B26008F320C
:100B28007F031214ECEF2402FFE43EA9077533019A
:100B3800F534893578367C007D007BFF7A16794359
:100B48007E007F08120126E532600464017054E5D6
:100B58000C2408F582E4350BF58374B4F0E50C2415
:100B680009F582E4350BF5837404F0E50C240AF5E5
:100B780082E4350BF5837413F0E50C240BF582E45D
:100B8800350BF5837486F0E50C240CF582E4350BFF
:100B9800F583E4F0E50C240DF582E4350BF583E4E8
:100BA800F0806C90E066E0FFE50C2408F582E435FF
:100BB8000BF583EFF090E067E0FFE50C2409F58280
:100BC800E4350BF583EFF090E068E0FFE50C240ACC
:100BD800F582E4350BF583EFF090E069E0FFE50C72
:100BE800240BF582E4350BF583EFF090E06AE0FF23
:100BF800E50C240CF582E4350BF583EFF090E06BFF
:100C0800E0FFE50C240DF582E4350BF583EFF0E405
:100C1800FF74362FF8E6FEAB33AA34A93575F00217
:0F0C2800EFA4F58285F083EE1201A40FBF08E25E
:010C3700229A
:10145E00E4F532E50C240BF582E4350BF583E0FE62
:10146E00E50C240AF582E4350BF583E0FDEDFF90E3
:10147E00E0ADEEF0A3EFF0D20412000390E680E0B0
:03148E0054F7F020
:011491002238
:10105A0090E600E054E74410F090E60174C0F09086
:10106A00E6107420F000000090E611F000000090F5
:10107A00E6047480F0000000740FF0000000E4F051
:10108A0000000090E6187410F0000000E490E619E1
:10109A00F000000090E61A7408F0000000E490E600
:1010AA001BF000000090E6497482F0000000F00096
:1010BA00000090E6247402F0000000E490E625F0B7
:1010CA0000000090E6957480F0000000F000000037
:1010DA0043AF017B017AE07914752E00752F06E47F
:0410EA00FD021517D7
:1015DC007C007D181201C6EF1FAC0670011E4C700A
:0215EC00F622E5
:1015670090E678E0541824F06008240870087F504B
:0815770080067F518002E4FFB1
:01157F002249
:0C0F1000AD36AC357B007A007934AF338D
:0C0F1C008F398C3A8D3B8B3C8A3D893E1E
:100F2800E4F53FF540754103FDF542F543A2AF33C3
:100F3800F544E53924AF600D047012753F00754023
:100F4800017D018008753F00754002E4FDE53960C8
:100F580051E540453F604BE53A90E0AFF0E53BA3F3
:100F6800F074AF2DF582E434E0AD82FCAB40AF39CC
:100F780012126D7542008F437F0A7E00121335E509
:100F880043454260107CE07D647B01AF39120FB5A8
:100F98007542008F4390E064E0AB3CAA3DA93E1245
:0C0FA8000192E54424FF92AFAE42AF433B
:010FB400221A
:0C117A008F348C358D368B378A388939DC
:10118600E4F53AF53B753C03FDF53DF53EA2AF337C
:10119600F53FE53424AF600D047012753A00753BD7
:1011A600027D018008753A00753B03E4FDE5346075
:1011B6003BE53B453A6035E53590E0AFF0E536A3D3
:1011C600F0AB37AA38A93912014C90E0B1F074AFF0
:1011D6002DF582E434E0AD82FCAB3BAF3412126DE8
:1011E600753D008F3E7F0A7E00121335E53F24FFD2
:0611F60092AFAE3DAF3EDA
:0111FC0022D0
:10054300E4F52AF52BF52CF52DF52EF52FF530E5F1
:10055300AA5484600302071190E694E0FE90E695A6
:10056300E0FBEEF52DEBF52EC39405E52D9400404D
:100573000790F404E0FD80027DFFED24F570030293
:10058300062524E6700302064F24E0700302062CBE
:1005930024FE7003020649243960030206B3752A58
:1005A30000752B0590FC04748EF01215678F30E5EF
:1005B3003064516019E53064506013752A00752B5F
:1005C3000690FC047480F0A3740BF00206D6121597
:1005D300678F307B007A007931E4FDFC120F1CAF8A
:1005E300311208757400252BF974FC352AFA7B0146
:1005F300C0038B357536E075376575380075392C52
:10060300D0031213B87400252BF58274FC352AF538
:1006130083E531F0742C252BF52BE4352AF52A02DA
:1006230006D6E4F52AF52B801D1215678F307B0063
:100633007A007931E4FDFC120F1CAF311208757F8B
:10064300C0120B26800012145E0206D6752A0075AE
:100653002B0590FC0474A5F01215678F307B007A8C
:10066300007931E4FDFC120F1C052BE52BAE2A703B
:1006730002052A142400F58274FC3EF583E508F094
:10068300052BE52BAE2A7002052A142400F582748B
:10069300FC3EF583E515F0052BE52BAE2A7002052C
:1006A3002A142400F58274FC3EF583E531F080239F
:1006B300752A00752B0690FC047480F0C3E52E9414
:1006C30005E52D94005006A37407F0800690FC0501
:1006D3007406F0E52B452A602CE52BFD90FC00F019
:1006E300E52AFFA3F090F402E090FC02F090F403FB
:1006F300E090FC03F090E69CEFF000000090E69D94
:0E070300EDF000000090E6957480F00000001C
:0107110022C5
:02004100D322C8
:0800460090E6BAE0F51DD3229B
:1015EE0090E740E51DF0E490E68AF090E68B04F07B
:0215FE00D322F6
:08163B0090E6BAE0F51AD32293
:1016180090E740E51AF0E490E68AF090E68B04F053
:02162800D322CB
:10153F0090E6B9E0242F600D04701990E604E0FFE7
:10154F00430780800890E604E0FF53077F00000008
:07155F00EFF08002D322C36C
:011566002262
:10158000C0E0C083C082D2015391EF90E65D740148
:08159000F0D082D083D0E032DC
:1015B000C0E0C083C0825391EF90E65D7404F0D028
:0615C00082D083D0E0326E
:1015C600C0E0C083C0825391EF90E65D7402F0D014
:0615D60082D083D0E03258
:1013F200C0E0C083C08285110D85120E850E8285E4
:101402000D83A37402F085090F850A108510828569
:101412000F83A37407F05391EF90E65D7410F0D040
:0614220082D083D0E0320D
:10159800C0E0C083C082D2035391EF90E65D740827
:0815A800F0D082D083D0E032C4
:10137B00C0E0C083C08290E680E030E72085090D95
:10138B00850A0E850E82850D83A37402F085110FDD
:10139B00851210851082850F83A37407F05391EF8C
:0D13AB0090E65D7420F0D082D083D0E03257
:0E09F10000010202030304040505C0C2000059
:1007120078237C007D007BFF7A0979FB7E007F04D1
:10072200120126C203C200D202C20112105A750B74
:100732000A750C0075130A75141275090A750A1CDC
:1007420075110A75127085110F85121075160A75CA
:1007520017B41215678F217B007A007922E4FDFC21
:10076200120F1C852208E4F515F52774232527F8B6
:10077200E6FF605C1208757EE07F657CE07DB31267
:1007820011FD7EE07FB3AD1CAC1B12099F50387483
:10079200232527F8E6F515652260277B007A007984
:1007A200157D01E4FFFE1212D37B007A007922E468
:1007B200FDFCAF21120F1CE52265156013751501B2
:1007C200800E7515FF80090527E527C39404409B19
:1007D200E5157059FB7A0079227D01FCAF21120FD9
:1007E2001CE522752900F5287B007A0079227D021A
:1007F2007C00AF21120F1CE5224229E52964E47036
:1008020004E52864E470267515C0FB7A0079157D2D
:1008120001FFFE1212D37B007A007922E4FDFCAFC5
:1008220021120F1CE52265156003751501AF151223
:100832000B26D2E843D82090E668E04409F090E61F
:100842005CE0443DF0E51564C06005E515B4C20303
:1008520012145ED2AF538EF8C203C2AF120543D256
:10086200AF30010512031BC2013003EEC2031214A2
:03087200C080E75C
:0B00360090E50DE030E402C322D3226D
:10031B0090E6B9E070030203E01470030204552465
:10032B00FE70030204D024FB70030203DA14700383
:10033B000203D41470030203C81470030203CE2407
:10034B0005600302052F120041400302053B90E6B6
:10035B00BBE024FE602714603E24FD60111460276F
:10036B0024067056E50B90E6B3F0E50C80421200C4
:10037B00365044E51390E6B3F0E5148033E50D9069
:10038B00E6B3F0E50E802985110F851210E50F906D
:10039B00E6B3F0E510801990E6BAE0FF1214ECAA70
:1003AB0006A9077B01EA494B600DEE90E6B3F0EF2F
:1003BB0090E6B4F002053B02052A02052A12161834
:1003CB0002053B12163B02053B12004602053B128F
:1003DB0015EE02053B90E6B8E0247F60151460191A
:1003EB0024027063A200E43325E0FFA202E4334F42
:1003FB008041E490E740F0803F90E6BCE0547EFF04
:10040B007E00E0D394807C0040047D0180027D005F
:10041B00EC4EFEED4F24F1F58274093EF583E49327
:10042B00FF3395E0FEEF24A1FFEE34E68F82F583D8
:10043B00E0540190E740F0E4A3F090E68AF090E6F8
:10044B008B7402F002053B02052A90E6B8E024FE0D
:10045B0060162402600302053B90E6BAE0B4010586
:10046B00C20002053B02052A90E6BAE0705590E601
:10047B00BCE0547EFF7E00E0D394807C0040047D82
:10048B000180027D00EC4EFEED4F24F1F5827409E4
:10049B003EF583E493FF3395E0FEEF24A1FFEE34AA
:1004AB00E68F82F583E054FEF090E6BCE0548013B7
:1004BB001313541FFFE0540F2F90E683F0E04420FA
:1004CB00F0806D805A90E6B8E024FE60192402702B
:1004DB004E90E6BAE0B40104D200805490E6BAE044
:1004EB006402604C803990E6BCE0547EFF7E00E0F5
:1004FB00D394807C0040047D0180027D00EC4EFE95
:10050B00ED4F24F1F58274093EF583E493FF3395A7
:10051B00E0FEEF24A1FFEE34E68F82F583800D9091
:10052B00E6A0800812153F500790E6A0E04401F0CA
:07053B0090E6A0E04480F00F
:010542002296
:0300330002004E7A
:04004E0053D8EF3262
:100E8B006080E0CF292E43C9A2D87C013D3654A106
:100E9B00ECF0061362A705F3C0C7738C98932BD99C
:100EAB00BC4C82CA1E9B573CFDD4E01667426F18A0
:100EBB008A17E512BE4EC4D6DA9EDE49A0FBF58E2C
:100ECB00BB2FEE7AA968799115B2073F94C21089AE
:100EDB000B225F21807F5D9A5A903227353ECCE7FB
:100EEB00BFF79703FF1930B348A5B5D1D75E922A48
:100EFB00AC56AAC64FB838D296A47DB676FC6BE238
:040F0B009C7404F1DD
:080CFF008C2C8D2DAB07AA0619
:100D0700E4F52EF52FC3E52F952DE52C6480F8E546
:100D17002E6480984003020DAEE52F25E0FFE52EF7
:100D270033FE74CF2FF58274E03EF583E0FF7E003B
:100D3700AC2CAD2D1201D88C308D31E52F25E0FF7D
:100D4700E52E33FE74D02FF58274E03EF583E0FF85
:100D57007E00AC2CAD2D1201D88C328D33E5316578
:100D6700337004E53065326030EB2531F582EA35C2
:100D770030F583E0F9EB2533F582EA3532F583E088
:100D8700FFEB2531F582EA3530F583EFF0EB2533BC
:100D9700F582EA3532F583E9F0052FE52F60030286
:0B0DA7000D0C052E020D0C7E007F01DC
:010DB200221E
:0C0DB3008E2C8F2D8C2E8D2F8A308B31D2
:100DBF00E52D452C6006E52F452E7004E4FEFF223D
:100DCF00E4F532F533C3E5339531E5306480F8E56A
:100DDF0032648098507BE4F534F535E52F2533F5F3
:100DEF0082E52E3532F583E4F0C3E5359531E530F4
:100DFF006480F8E5346480985049E535253324CF75
:100E0F00F582E434E0F583E0FFE52D2535F582E545
:100E1F002C3534F583E0FEEF8EF0A4FFE52F25335C
:100E2F00F582E52E3532F583E02FFFE52F2533F5DB
:100E3F0082E52E3532F583EFF00535E53570AA05DD
:100E4F003480A60533E5336003020DD40532020D5D
:050E5F00D47E007F01BC
:010E6400226B
:1014920012014CFF900003120165120192900003A9
:1014A200EF1201A4900002120165FF9000011201E7
:0E14B200659000021201A4900001EF0201A457
:080C38008E2C8F2D8C2E8D2FC8
:100C4000E4F530F531E52FAE2E7802CEA2E713CED3
:100C500013D8F8FFC3E5319FEE6480F8E530648077
:100C6000984003020CFAE531AE307802C333CE333C
:100C7000CED8F9252DFFEE352CFAA9077B018B3252
:100C8000F533893474D02531F582E434E0F583E01E
:100C9000541FFFE48F38F537F536F535121492AB53
:100CA00032AA33A934120234C374209538F9F812E9
:100CB0000221C004C005C006C007A934120234A92D
:100CC00038A80112020ED003D002D001D000EF4BA1
:100CD000FFEE4AFEED49FDEC48FCAB32AA33A934E5
:100CE000120254AB32AA33A9341214920531E53101
:0E0CF0006003020C450530020C457E007F01BA
:010CFE0022D3
:10142800D3ED9410EC64809480402AED1D70011C6B
:10143800142FF582EE3CF583E0FB547F24CFF58230
:10144800E434E0F583E0F9540F2FF582E43EF583A8
:05145800E06BF080CB09
:01145D00226C
:1014C00090E682E030E004E020E60B90E682E03037
:1014D000E119E030E71590E680E04401F07F147EEA
:0C14E0000012133590E680E054FEF0226C
:1000030030040990E680E0440AF0800790E680E03F
:100013004408F07FDC7E0512133590E65D74FFF033
:0F00230090E65FF05391EF90E680E054F7F02203
:101335008E458F4690E600E054187012E54624016C
:10134500FFE43545C313F545EF13F546801590E6E3
:1013550000E05418FFBF100BE54625E0F546E545CE
:1013650033F545E5461546AE45700215454E600513
:0613750012162A80EE2290
:060FB5008C458D46AE07DD
:100FBB00EB70037F012290E678E020E6F990E6786B
:100FCB007480F0EE25E0440190E679F090E678E04D
:100FDB0030E0F990E678E020E26BE030E167BB01AE
:100FEB000790E678E04420F090E679E0F5471BEBBC
:100FFB00603090E678E030E0F990E678E020E2456A
:10100B00BB010790E678E04420F090E679E0FF051D
:10101B0046E546AC457002054514F5828C83EFF02E
:10102B0080CC90E678E030E0F990E678E020E215AD
:10103B0090E678E04440F090E679E085468285457D
:0E104B0083F07F012290E678E04440F07F00C1
:011059002274
:10126D0090E678E020E6F990E6787480F0EF25E0DE
:10127D0090E679F090E678E030E0F990E678E020BD
:10128D00E23AE030E136EBD3940040260DEDAE04AA
:10129D0070010C14F5828E83E090E679F01B90E6D8
:1012AD0078E030E0F990E678E020E210E020E1D639
:1012BD00800A90E678E04440F07F012290E678E0E5
:0512CD004440F07F0029
:0112D20022F9
:0214EC00A9074E
:1014EE00AE16AF178F828E83A3E064037017AD0123
:1014FE0019ED7001228F828E83E07C002FFDEC3E71
:08150E00FEAF0580DFE4FEFFE3
:0115160022B2
:10162A007400F58690FDA57C05A3E582458370F9D3
:01163A00228D
:030000000210EEFD
:0C10EE00787FE4F6D8FD758147021135CB
:10005600E709F608DFFA8046E709F208DFFA803E8C
:1000660088828C83E709F0A3DFFA8032E309F60879
:10007600DFFA8078E309F208DFFA807088828C83E1
:10008600E309F0A3DFFA806489828A83E0A3F60895
:10009600DFFA805889828A83E0A3F208DFFA804C6F
:1000A60080D280FA80C680D4806980F28033801046
:1000B60080A680EA809A80A880DA80E280CA8033AF
:1000C60089828A83ECFAE493A3C8C582C8CCC58327
:1000D600CCF0A3C8C582C8CCC583CCDFE9DEE780F7
:1000E6000D89828A83E493A3F608DFF9ECFAA9F076
:1000F600EDFB2289828A83ECFAE0A3C8C582C8CCCC
:10010600C583CCF0A3C8C582C8CCC583CCDFEADEE4
:10011600E880DB89828A83E493A3F208DFF980CC46
:1001260088F0EF60010E4E60C388F0ED2402B4043F
:100136000050B9F582EB2402B4040050AF232345E6
:0601460082239000A67365
:10014C00BB010689828A83E0225002E722BBFE02B1
:09015C00E32289828A83E49322E4
:10016500BB010CE58229F582E5833AF583E022504F
:1001750006E92582F8E622BBFE06E92582F8E22299
:0D018500E58229F582E5833AF583E49322B3
:10019200BB010689828A83F0225002F722BBFE014C
:0201A200F32246
:1001A400F8BB010DE58229F582E5833AF583E8F091
:1001B400225006E92582C8F622BBFE05E92582C83D
:0201C400F22225
:1001C600EF8DF0A4A8F0CF8CF0A428CE8DF0A42E4D
:0201D600FE2207
:1001D800C2D5EC30E709B2D5E4C39DFDE49CFCEE42
:1001E80030E715B2D5E4C39FFFE49EFE12027AC33E
:1001F800E49DFDE49CFC800312027A30D507C3E439
:060208009FFFE49EFE22B0
:10020E00E8600FECC313FCED13FDEE13FEEF13FFCE
:03021E00D8F122F2
:10022100E8600FEFC333FFEE33FEED33FDEC33FC3B
:03023100D8F122DF
:10023400BB010789828A830202DB5005E9F80202C6
:10024400CFBBFE05E9F80202E789828A830202F342
:10025400BB010789828A8302026E5005E9F8020312
:0A02640003BBFE05E9F802030F22B8
:0C026E00ECF0A3EDF0A3EEF0A3EFF02203
:1010FA00020712E493A3F8E493A34003F68001F2F3
:10110A0008DFF48029E493A3F85407240CC8C333F6
:10111A00C4540F4420C8834004F456800146F6DFC5
:10112A00E4800B0102040810204080900E65E47EE2
:10113A00019360BCA3FF543F30E509541FFEE493BA
:10114A00A360010ECF54C025E060A840B8E493A381
:10115A00FAE493A3F8E493A3C8C582C8CAC583CAAC
:10116A00F0A3C8C582C8CAC583CADFE9DEE780BE64
:010F0F0000E1
:10027A00BC000BBE0029EF8DF084FFADF022E4CC68
:10028A00F875F008EF2FFFEE33FEEC33FCEE9DEC31
:10029A00984005FCEE9DFE0FD5F0E9E4CEFD22ED77
:1002AA00F8F5F0EE8420D21CFEADF075F008EF2FC1
:1002BA00FFED33FD4007985006D5F0F222C398FDB2
:0502CA000FD5F0EA224F
:0C02CF00E6FC08E6FD08E6FE08E6FF225B
:0C02DB00E0FCA3E0FDA3E0FEA3E0FF2296
:0C02E700E2FC08E2FD08E2FE08E2FF2253
:1002F300E493FC740193FD740293FE740393FF2251
:0C030300ECF608EDF608EEF608EFF62226
:0C030F00ECF208EDF208EEF208EFF2222A
:00000001FF

View File

@@ -51,7 +51,7 @@ BEGIN { $init_dir = dirname($0); unshift(@INC, "$init_dir"); }
use XppConfig $init_dir;
my $unit_id;
my %opts;
my $vbat_48 = 0;
my $eeprom_release_201 = 0;
getopts('o:', \%opts);
@@ -94,7 +94,7 @@ if (-t STDERR) {
}
logit "XBUS_MODEL_STRING='$ENV{XBUS_MODEL_STRING}'";
if ($ENV{XBUS_MODEL_STRING} =~ m{.*/.*/201}) {
$vbat_48 = 1;
$eeprom_release_201 = 1;
}
$chipregs = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/chipregs",
$ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER};
@@ -292,8 +292,8 @@ sub init_indirect_registers() {
}
sub init_early_direct_regs() {
my $lbv = ($vbat_48) ? "20" : "10";
my $vcm = ($vbat_48) ? "02" : "03";
my $lbv = ($eeprom_release_201) ? "20" : "10";
my $vcm = ($eeprom_release_201) ? "02" : "03";
return write_to_slic_file("#
* WD 08 00 # Audio Path Loopback Control

View File

@@ -415,6 +415,9 @@ close STDERR;
exit 0;
__DATA__
* WD 12 02 # Full wave rectified ring detection
* WD 03 01 # Polarity reversal detect mask
* WD 04 00 # Clear interrupt status
* WD 21 08 # Disable PCM transfers
* WD 18 99
* WD 06 00

View File

@@ -7,7 +7,9 @@ static int mmap_match(struct device *dev, struct device_driver *driver)
{
return !strncmp(dev_name(dev), driver->name, strlen(driver->name));
}
static int mmap_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
static int mmap_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
envp[0] = buffer;
envp[1] = NULL;
@@ -33,8 +35,6 @@ static struct device mmap_bus = {
.release = mmap_bus_release,
};
int register_mmap_device(struct mmap_device *dev)
{
dev->dev.bus = &mmap_bus_type;
@@ -43,12 +43,12 @@ int register_mmap_device(struct mmap_device *dev)
strncpy(dev->dev.bus_id, dev->name, BUS_ID_SIZE);
return device_register(&dev->dev);
}
EXPORT_SYMBOL(register_mmap_device);
void unregister_mmap_device(struct mmap_device *dev)
{
device_unregister(&dev->dev);
}
EXPORT_SYMBOL(register_mmap_device);
EXPORT_SYMBOL(unregister_mmap_device);
int register_mmap_driver(struct mmap_driver *driver)
@@ -56,12 +56,12 @@ int register_mmap_driver(struct mmap_driver *driver)
driver->driver.bus = &mmap_bus_type;
return driver_register(&driver->driver);
}
EXPORT_SYMBOL(register_mmap_driver);
void unregister_mmap_driver(struct mmap_driver *driver)
{
driver_unregister(&driver->driver);
}
EXPORT_SYMBOL(register_mmap_driver);
EXPORT_SYMBOL(unregister_mmap_driver);
int register_mmap_bus(void)
@@ -78,13 +78,13 @@ bus_reg:
bus_type_reg:
return ret;
}
EXPORT_SYMBOL(register_mmap_bus);
void unregister_mmap_bus(void)
{
device_unregister(&mmap_bus);
bus_unregister(&mmap_bus_type);
}
EXPORT_SYMBOL(register_mmap_bus);
EXPORT_SYMBOL(unregister_mmap_bus);
MODULE_AUTHOR("Alexander Landau <landau.alex@gmail.com>");

View File

@@ -19,11 +19,13 @@
#include "xframe_queue.h"
/* Check at compile time that sizeof(xframe_t) is a multiple of 4 */
typedef char sizeof_xframe_t_should_be_divisible_by_4[((sizeof(xframe_t) % 4) == 0) * 2 - 1];
typedef char
sizeof_xframe_t_should_be_divisible_by_4[((sizeof(xframe_t) % 4) ==
0) * 2 - 1];
#define ssync() __builtin_bfin_ssync()
//#define AB_IN_BUF PF5
//#define AB_IN_BUF PF5
/* firmware pins */
#define DATA PG8
#define NCONFIG PG9
@@ -33,13 +35,13 @@ typedef char sizeof_xframe_t_should_be_divisible_by_4[((sizeof(xframe_t) % 4) ==
#ifdef DEBUG_VIA_GPIO
/*
* For debugging we can use the following two pins.
* For debugging we can use the following two pins.
* These two pins are not used *after initialization*
*/
#define DEBUG_GPIO1 CONF_DONE
#define DEBUG_GPIO2 NSTATUS
static int rx_intr_counter;
static int rx_intr_counter;
#endif
#define FPGA_RX_IRQ IRQ_PF7
@@ -49,9 +51,15 @@ static int rx_intr_counter;
#define END_OF_FRAME 0x0001
#define GET_LEN 0x0002
#define START_RD_BURST 0x0008
#define AS_BF_MODE 0x0010 //stand alone Astribank without USB (Asterisk BlackFin Mode)
#define EC_BF_MODE 0x0020 //all data between Astribank and USB routed thru BF(EchoCanceler BlackFin Mode)
#define NO_BF_MODE 0x0040 //Astribank worke with USB only (no BlackFin Mode)
/* stand alone Astribank without USB (Asterisk BlackFin Mode) */
#define AS_BF_MODE 0x0010
/*
* all data between Astribank and USB routed
* thru BF(EchoCanceler BlackFin Mode)
*/
#define EC_BF_MODE 0x0020
/* Astribank worke with USB only (no BlackFin Mode) */
#define NO_BF_MODE 0x0040
#define SET_XA_DIR 0x0080
#define GET_XPD_STS 0x0100
#define GET_CHECKSUM 0x0200
@@ -80,9 +88,8 @@ static void print_buffer(const char *msg, const char *buf, int len)
{
int i;
printk(KERN_ERR "%s", msg);
for (i = 0; i < len; i++) {
for (i = 0; i < len; i++)
printk("%02X ", (unsigned char)buf[i]);
}
printk("\n");
}
@@ -96,7 +103,8 @@ static void update_counter(struct counter *c, struct timeval *tv1)
c->intr_min = diff;
if (c->intr_max < diff)
c->intr_max = diff;
c->intr_avg = (c->intr_avg*c->intr_count + diff) / (c->intr_count+1);
c->intr_avg =
(c->intr_avg * c->intr_count + diff) / (c->intr_count + 1);
c->intr_count++;
}
@@ -105,7 +113,7 @@ static irqreturn_t xpp_mmap_rx_irq(int irq, void *dev_id)
unsigned short rxcnt;
xbus_t *xbus;
xframe_t *xframe;
byte *buf;
__u8 *buf;
bool in_use = 0;
struct timeval tv1;
@@ -115,7 +123,7 @@ static irqreturn_t xpp_mmap_rx_irq(int irq, void *dev_id)
xbus = xbus_num(global_xbus->num);
BUG_ON(!xbus);
if(!XBUS_GET(xbus)) {
if (!XBUS_GET(xbus)) {
if (printk_ratelimit())
XBUS_ERR(xbus, "Dropping packet. Is shutting down.\n");
goto out;
@@ -129,7 +137,7 @@ static irqreturn_t xpp_mmap_rx_irq(int irq, void *dev_id)
NOTICE("Got %d bytes\n", rxcnt);
goto out;
}
if(rxcnt >= XFRAME_DATASIZE) {
if (rxcnt >= XFRAME_DATASIZE) {
if (printk_ratelimit())
ERR("Bad rxcnt=%d\n", rxcnt);
goto out;
@@ -153,18 +161,22 @@ static irqreturn_t xpp_mmap_rx_irq(int irq, void *dev_id)
outw(START_RD_BURST, FPGA_BASE_ADDR + 4);
insw((unsigned long)FPGA_BASE_ADDR, buf, rxcnt / 2);
#if 0
for (count = 0; count < rxcnt; count+=2) {
for (count = 0; count < rxcnt; count += 2) {
unsigned short v = inw(FPGA_BASE_ADDR);
buf[count] = v & 0xFF;
buf[count+1] = v >> 8;
buf[count + 1] = v >> 8;
}
#endif
if (rxcnt & 1)
buf[rxcnt-1] = inw(FPGA_BASE_ADDR);
/* Sanity check: length of first packet in frame should be no more than the frame length */
if (((buf[0] | (buf[1]<<8)) & 0x3FF) > rxcnt) {
if (rxcnt & 1)
buf[rxcnt - 1] = inw(FPGA_BASE_ADDR);
/*
* Sanity check: length of first packet in frame
* should be no more than the frame length
*/
if (((buf[0] | (buf[1] << 8)) & 0x3FF) > rxcnt) {
if (printk_ratelimit()) {
ERR("Packet len=%d, frame len=%d\n", (buf[0] | (buf[1]<<8)) & 0x3FF, rxcnt);
ERR("Packet len=%d, frame len=%d\n",
(buf[0] | (buf[1] << 8)) & 0x3FF, rxcnt);
print_buffer("16 bytes of packet: ", buf, 16);
}
goto free;
@@ -199,7 +211,7 @@ static void send_buffer(unsigned char *buf, unsigned long len)
print_buffer("Sent: ", buf, len);
outsw((unsigned long)FPGA_BASE_ADDR, buf, len / 2);
if (len & 1)
outw((unsigned short)buf[len-1], FPGA_BASE_ADDR);
outw((unsigned short)buf[len - 1], FPGA_BASE_ADDR);
outw(END_OF_FRAME, FPGA_BASE_ADDR + 4);
}
@@ -258,7 +270,10 @@ static int xframe_send_common(xbus_t *xbus, xframe_t *xframe, bool pcm)
if (pcm && pcm_in_pool_count >= 1) {
static int rate_limit;
if ((rate_limit++ % 1000) == 0)
XBUS_ERR(xbus, "Dropped PCM xframe (pcm_in_pool_count=%d).\n", pcm_in_pool_count);
XBUS_ERR(xbus,
"Dropped PCM xframe "
"(pcm_in_pool_count=%d).\n",
pcm_in_pool_count);
FREE_SEND_XFRAME(xbus, xframe);
pcm_dropped++;
} else {
@@ -266,7 +281,9 @@ static int xframe_send_common(xbus_t *xbus, xframe_t *xframe, bool pcm)
static int rate_limit;
spin_unlock_irqrestore(&tx_ready_lock, flags);
if ((rate_limit++ % 1000) == 0)
XBUS_ERR(xbus, "Dropped xframe. Cannot enqueue.\n");
XBUS_ERR(xbus,
"Dropped xframe. "
"Cannot enqueue.\n");
FREE_SEND_XFRAME(xbus, xframe);
return -E2BIG;
}
@@ -284,10 +301,12 @@ static xframe_t *alloc_xframe(xbus_t *xbus, gfp_t gfp_flags)
if (!xframe) {
static int rate_limit;
if ((rate_limit++ % 1000) < 5)
XBUS_ERR(xbus, "frame allocation failed (%d)\n", rate_limit);
XBUS_ERR(xbus, "frame allocation failed (%d)\n",
rate_limit);
return NULL;
}
xframe_init(xbus, xframe, ((byte*)xframe) + sizeof(xframe_t), XFRAME_DATASIZE, xbus);
xframe_init(xbus, xframe, ((__u8 *)xframe) + sizeof(xframe_t),
XFRAME_DATASIZE, xbus);
return xframe;
}
@@ -316,28 +335,26 @@ static struct xbus_ops xmmap_ops = {
static int fill_proc_queue(char *p, struct xframe_queue *q)
{
int len;
int len;
len = sprintf(p,
"%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02ld.%ld ms\n",
q->name,
q->steady_state_count,
q->count,
q->max_count,
q->worst_count,
q->overflows,
q->worst_lag_usec / 1000,
q->worst_lag_usec % 1000);
"%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d "
"worst_lag %02ld.%ld ms\n",
q->name, q->steady_state_count, q->count, q->max_count,
q->worst_count, q->overflows, q->worst_lag_usec / 1000,
q->worst_lag_usec % 1000);
xframe_queue_clearstats(q);
return len;
}
static int fill_proc_counter(char *p, struct counter *c)
{
return sprintf(p, "min=%ld\nmax=%ld\navg=%ld\ncount=%ld\n", c->intr_min, c->intr_max, c->intr_avg, c->intr_count);
return sprintf(p, "min=%ld\nmax=%ld\navg=%ld\ncount=%ld\n", c->intr_min,
c->intr_max, c->intr_avg, c->intr_count);
}
static int xpp_mmap_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
static int xpp_mmap_proc_read(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
int len = 0;
len += fill_proc_queue(page + len, &txpool);
@@ -347,7 +364,7 @@ static int xpp_mmap_proc_read(char *page, char **start, off_t off, int count, in
len += fill_proc_counter(page + len, &rx_counter);
len += sprintf(page + len, "\ntx_counter:\n");
len += fill_proc_counter(page + len, &tx_counter);
if (len <= off+count) {
if (len <= off + count) {
*eof = 1;
tx_counter.intr_min = rx_counter.intr_min = INT_MAX;
tx_counter.intr_max = rx_counter.intr_max = 0;
@@ -363,14 +380,15 @@ static int xpp_mmap_proc_read(char *page, char **start, off_t off, int count, in
return len;
}
static int xpp_mmap_proc_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
static int xpp_mmap_proc_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
int i = 0;
char *txchunk, *p, *endp;
if (count >= XFRAME_DATASIZE*3+10)
if (count >= XFRAME_DATASIZE * 3 + 10)
return -EINVAL;
p = txchunk = kmalloc(count+1, GFP_KERNEL);
p = txchunk = kmalloc(count + 1, GFP_KERNEL);
if (copy_from_user(txchunk, buffer, count)) {
count = -EFAULT;
goto out;
@@ -379,13 +397,15 @@ static int xpp_mmap_proc_write(struct file *file, const char __user *buffer, uns
while (*p) {
unsigned long value;
while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++;
if (*p == '\0') break;
while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')
p++;
if (*p == '\0')
break;
value = simple_strtoul(p, &endp, 16);
if (endp == p || value > 0xFF) {
INFO("%s: Bad input\n", __FUNCTION__);
count = -EINVAL;
goto out;
INFO("%s: Bad input\n", __func__);
count = -EINVAL;
goto out;
}
p = endp;
txchunk[i++] = (char)value;
@@ -399,8 +419,8 @@ out:
static struct mmap_driver astribank_driver = {
.module = THIS_MODULE,
.driver = {
.name = "xpp_mmap",
},
.name = "xpp_mmap",
},
};
static struct mmap_device astribank_dev = {
@@ -408,42 +428,52 @@ static struct mmap_device astribank_dev = {
.driver = &astribank_driver,
};
static int __init xpp_mmap_load_fpga(u8 *data, size_t size)
static int __init xpp_mmap_load_fpga(u8 * data, size_t size)
{
size_t i;
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() | DATA | NCONFIG | DCLK); //set data, nconfig and dclk to port out
/* set data, nconfig and dclk to port out */
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() | DATA | NCONFIG | DCLK);
bfin_write_PORTG_FER(bfin_read_PORTG_FER() & ~(DATA | NCONFIG | DCLK));
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() & ~(CONF_DONE | NSTATUS));//set conf_done and nstatus to port in
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() & ~(DATA | NCONFIG | DCLK));
/* set conf_done and nstatus to port in */
bfin_write_PORTGIO_DIR(
bfin_read_PORTGIO_DIR() & ~(CONF_DONE | NSTATUS));
bfin_write_PORTGIO_INEN(
bfin_read_PORTGIO_INEN() & ~(DATA | NCONFIG | DCLK));
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() | CONF_DONE | NSTATUS);
bfin_write_PORTGIO_CLEAR(NCONFIG); //reset fpga during configuration holds nCONFIG low
udelay(40); //Tcfg ~40us delay
bfin_write_PORTGIO_SET(NCONFIG); //transition nCONFIG to high - reset end.
udelay(40); //Tcf2ck ~40us delay
/* reset fpga during configuration holds nCONFIG low */
bfin_write_PORTGIO_CLEAR(NCONFIG);
udelay(40); /* Tcfg ~40us delay */
/* transition nCONFIG to high - reset end. */
bfin_write_PORTGIO_SET(NCONFIG);
udelay(40); /* Tcf2ck ~40us delay */
if (!(bfin_read_PORTGIO() & NSTATUS))
return -EIO; //report reset faill - Tcf2st1 pass
return -EIO; /* report reset faill - Tcf2st1 pass */
#if 0
if (!(bfin_read_PORTGIO() & CONF_DONE))
return -EIO;
#endif
bfin_write_PORTGIO_CLEAR(DCLK);
for (i=0; i<size; i++) { // loop EP2OUT buffer data to FPGA
for (i = 0; i < size; i++) { /* loop EP2OUT buffer data to FPGA */
int j;
u8 byte = data[i];
for (j=0; j<8; j++) //send the configuration data through the DATA0 pin one bit at a time.
u8 __u8 = data[i];
/*
* Send the configuration data through the DATA0 pin
* one bit at a time.
*/
for (j = 0; j < 8; j++)
{
if (byte & 1)
if (__u8 & 1)
bfin_write_PORTGIO_SET(DATA);
else
bfin_write_PORTGIO_CLEAR(DATA);
byte >>= 1;
__u8 >>= 1;
bfin_write_PORTGIO_SET(DCLK);
bfin_write_PORTGIO_CLEAR(DCLK);
}
if (!(bfin_read_PORTGIO() & NSTATUS))
return -EIO; //check the nSTATUS
return -EIO; /* check the nSTATUS */
}
bfin_write_PORTGIO_CLEAR(DATA);
udelay(1);
@@ -455,20 +485,29 @@ static int __init xpp_mmap_load_fpga(u8 *data, size_t size)
* some pins that were used only during initialization
* to be used for debugging from now on.
*/
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() | DEBUG_GPIO1 | DEBUG_GPIO2); //set to port out
bfin_write_PORTG_FER(bfin_read_PORTG_FER() & ~(DEBUG_GPIO1 | DEBUG_GPIO2));
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() & ~(DEBUG_GPIO1 | DEBUG_GPIO2));
/* set to port out */
bfin_write_PORTGIO_DIR(
bfin_read_PORTGIO_DIR() | DEBUG_GPIO1 | DEBUG_GPIO2);
bfin_write_PORTG_FER(bfin_read_PORTG_FER() &
~(DEBUG_GPIO1 | DEBUG_GPIO2));
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() &
~(DEBUG_GPIO1 | DEBUG_GPIO2));
#endif
udelay(40); //tCD2UM - CONF_DONE high to user mode
udelay(40); /* tCD2UM - CONF_DONE high to user mode */
return 0;
}
static void __exit xpp_mmap_unload_fpga(void)
{
bfin_write_PORTGIO_CLEAR(NCONFIG); //reset fpga during configuration holds nCONFIG low
udelay(40); //Tcfg ~40us delay
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() & ~( DATA | NCONFIG | DCLK)); //disable output pin
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() & ~( CONF_DONE | NSTATUS));//disable input buffer
/* reset fpga during configuration holds nCONFIG low */
bfin_write_PORTGIO_CLEAR(NCONFIG);
udelay(40); /* Tcfg ~40us delay */
/* disable output pin */
bfin_write_PORTGIO_DIR(
bfin_read_PORTGIO_DIR() & ~(DATA | NCONFIG | DCLK));
/* disable input buffer */
bfin_write_PORTGIO_INEN(
bfin_read_PORTGIO_INEN() & ~(CONF_DONE | NSTATUS));
INFO("FPGA Firmware unloaded\n");
}
@@ -476,7 +515,8 @@ static int __init xpp_mmap_load_firmware(void)
{
const struct firmware *fw;
int ret;
if ((ret = request_firmware(&fw, "astribank.bin", &astribank_dev.dev)) < 0)
if ((ret =
request_firmware(&fw, "astribank.bin", &astribank_dev.dev)) < 0)
return ret;
xpp_mmap_load_fpga(fw->data, fw->size);
release_firmware(fw);
@@ -498,29 +538,33 @@ static int __init xpp_mmap_init(void)
ERR("xpp_mmap_load_firmware() failed, errno=%d\n", ret);
goto fail_fw;
}
if ((ret = request_irq(FPGA_RX_IRQ, xpp_mmap_rx_irq, IRQF_TRIGGER_RISING, "xpp_mmap_rx", NULL)) < 0) {
if ((ret =
request_irq(FPGA_RX_IRQ, xpp_mmap_rx_irq, IRQF_TRIGGER_RISING,
"xpp_mmap_rx", NULL)) < 0) {
ERR("Unable to attach to RX interrupt %d\n", FPGA_RX_IRQ);
goto fail_irq_rx;
}
if ((ret = request_irq(FPGA_TX_IRQ, xpp_mmap_tx_irq, IRQF_TRIGGER_RISING, "xpp_mmap_tx", NULL)) < 0) {
if ((ret =
request_irq(FPGA_TX_IRQ, xpp_mmap_tx_irq, IRQF_TRIGGER_RISING,
"xpp_mmap_tx", NULL)) < 0) {
ERR("Unable to attach to TX interrupt %d\n", FPGA_TX_IRQ);
goto fail_irq_tx;
}
if (!request_region((resource_size_t)FPGA_BASE_ADDR, 8, "xpp_mmap")) {
if (!request_region((resource_size_t) FPGA_BASE_ADDR, 8, "xpp_mmap")) {
ERR("Unable to request memory region at %p\n", FPGA_BASE_ADDR);
goto fail_region;
}
outw(AS_BF_MODE, FPGA_BASE_ADDR + 4);
outw(AS_BF_MODE, FPGA_BASE_ADDR + 4);
xframe_cache = kmem_cache_create("xframe_cache",
sizeof(xframe_t) + XFRAME_DATASIZE,
0, 0,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
NULL,
xframe_cache =
kmem_cache_create("xframe_cache",
sizeof(xframe_t) + XFRAME_DATASIZE, 0, 0,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
NULL,
#endif
NULL);
if(!xframe_cache) {
NULL);
if (!xframe_cache) {
ret = -ENOMEM;
goto fail_cache;
}
@@ -532,9 +576,11 @@ static int __init xpp_mmap_init(void)
}
strncpy(global_xbus->connector, "mmap", XBUS_DESCLEN);
strncpy(global_xbus->label, "mmap:0", LABEL_SIZE);
xframe_queue_init(&txpool, 10, 200, "mmap_txpool", global_xbus);
if (!(proc_entry = create_proc_entry("xpp_mmap", 0, global_xbus->proc_xbus_dir))) {
if (!
(proc_entry =
create_proc_entry("xpp_mmap", 0, global_xbus->proc_xbus_dir))) {
ERR("create_proc_entry() failed\n");
ret = -EINVAL;
goto fail_proc;
@@ -552,7 +598,7 @@ fail_proc:
fail_xbus:
kmem_cache_destroy(xframe_cache);
fail_cache:
release_region((resource_size_t)FPGA_BASE_ADDR, 8);
release_region((resource_size_t) FPGA_BASE_ADDR, 8);
fail_region:
free_irq(FPGA_TX_IRQ, NULL);
fail_irq_tx:
@@ -579,7 +625,7 @@ static void __exit xpp_mmap_exit(void)
xbus_disconnect(xbus);
kmem_cache_destroy(xframe_cache);
release_region((resource_size_t)FPGA_BASE_ADDR, 8);
release_region((resource_size_t) FPGA_BASE_ADDR, 8);
free_irq(FPGA_RX_IRQ, NULL);
free_irq(FPGA_TX_IRQ, NULL);

View File

@@ -20,31 +20,26 @@
*
*/
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
# warning "This module is tested only with 2.6 kernels"
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/parport.h>
#include "parport_debug.h"
static struct parport *debug_sync_parport = NULL;
static int parport_toggles[8]; /* 8 bit flip-flop */
static struct parport *debug_sync_parport;
static int parport_toggles[8]; /* 8 bit flip-flop */
void flip_parport_bit(unsigned char bitnum)
{
static unsigned char last_value;
static unsigned char last_value;
DEFINE_SPINLOCK(lock);
unsigned long flags;
unsigned char mask;
unsigned char value;
unsigned long flags;
unsigned char mask;
unsigned char value;
if(!debug_sync_parport) {
if(printk_ratelimit()) {
if (!debug_sync_parport) {
if (printk_ratelimit()) {
printk(KERN_NOTICE "%s: no debug parallel port\n",
THIS_MODULE->name);
THIS_MODULE->name);
}
return;
}
@@ -52,7 +47,7 @@ void flip_parport_bit(unsigned char bitnum)
mask = 1 << bitnum;
spin_lock_irqsave(&lock, flags);
value = last_value & ~mask;
if(parport_toggles[bitnum] % 2) /* square wave */
if (parport_toggles[bitnum] % 2) /* square wave */
value |= mask;
last_value = value;
parport_toggles[bitnum]++;
@@ -63,10 +58,11 @@ EXPORT_SYMBOL(flip_parport_bit);
static void parport_attach(struct parport *port)
{
printk(KERN_INFO "%s: Using %s for debugging\n", THIS_MODULE->name, port->name);
if(debug_sync_parport) {
printk(KERN_INFO "%s: Using %s for debugging\n", THIS_MODULE->name,
port->name);
if (debug_sync_parport) {
printk(KERN_ERR "%s: Using %s, ignore new attachment %s\n",
THIS_MODULE->name, debug_sync_parport->name, port->name);
THIS_MODULE->name, debug_sync_parport->name, port->name);
return;
}
parport_get_port(port);
@@ -76,16 +72,16 @@ static void parport_attach(struct parport *port)
static void parport_detach(struct parport *port)
{
printk(KERN_INFO "%s: Releasing %s\n", THIS_MODULE->name, port->name);
if(debug_sync_parport != port) {
if (debug_sync_parport != port) {
printk(KERN_ERR "%s: Using %s, ignore new detachment %s\n",
THIS_MODULE->name, debug_sync_parport->name, port->name);
THIS_MODULE->name, debug_sync_parport->name, port->name);
return;
}
parport_put_port(debug_sync_parport);
debug_sync_parport = NULL;
}
static struct parport_driver debug_parport_driver = {
static struct parport_driver debug_parport_driver = {
.name = "parport_debug",
.attach = parport_attach,
.detach = parport_detach,
@@ -93,7 +89,7 @@ static struct parport_driver debug_parport_driver = {
int __init parallel_dbg_init(void)
{
int ret;
int ret;
ret = parport_register_driver(&debug_parport_driver);
return ret;

View File

@@ -28,4 +28,4 @@ void flip_parport_bit(unsigned char bitnum);
#define flip_parport_bit(bitnum)
#endif
#endif /* PARPORT_DEBUG_H */
#endif /* PARPORT_DEBUG_H */

View File

@@ -3,30 +3,35 @@
int main(int argc, char *argv[])
{
size_t i;
for (i=0; i<(sizeof(fxo_modes)/sizeof(struct fxo_mode)); i++) {
if (fxo_modes[i].name == NULL) break;
int reg16=0, reg26=0, reg30=0, reg31=0x20;
char ring_osc[BUFSIZ]="", ring_x[BUFSIZ] = "";
for (i = 0; i < (sizeof(fxo_modes) / sizeof(struct fxo_mode)); i++) {
if (fxo_modes[i].name == NULL)
break;
int reg16 = 0, reg26 = 0, reg30 = 0, reg31 = 0x20;
char ring_osc[BUFSIZ] = "", ring_x[BUFSIZ] = "";
reg16 |= (fxo_modes[i].ohs << 6);
reg16 |= (fxo_modes[i].rz << 1);
reg16 |= (fxo_modes[i].rt);
reg26 |= (fxo_modes[i].dcv << 6);
reg26 |= (fxo_modes[i].mini << 4);
reg26 |= (fxo_modes[i].ilim << 1);
reg30 = (fxo_modes[i].acim);
reg31 |= (fxo_modes[i].ohs2 << 3);
if (fxo_modes[i].ring_osc)
snprintf(ring_osc, BUFSIZ, "ring_osc=%04X", fxo_modes[i].ring_osc);
snprintf(ring_osc, BUFSIZ, "ring_osc=%04X",
fxo_modes[i].ring_osc);
if (fxo_modes[i].ring_x)
snprintf(ring_x, BUFSIZ, "ring_x=%04X", fxo_modes[i].ring_x);
printf("%-15s\treg16=%02X\treg26=%02X\treg30=%02X\treg31=%02X\t%s\t%s\n",
fxo_modes[i].name, reg16, reg26, reg30, reg31, ring_osc, ring_x);
snprintf(ring_x, BUFSIZ, "ring_x=%04X",
fxo_modes[i].ring_x);
printf("%-15s\treg16=%02X\treg26=%02X\treg30=%02X\t"
"reg31=%02X\t%s\t%s\n",
fxo_modes[i].name, reg16, reg26, reg30, reg31,
ring_osc, ring_x);
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -39,10 +39,10 @@ struct xbus_workqueue;
#ifdef __KERNEL__
struct xbus_ops {
int (*xframe_send_pcm)(xbus_t *xbus, xframe_t *xframe);
int (*xframe_send_cmd)(xbus_t *xbus, xframe_t *xframe);
xframe_t *(*alloc_xframe)(xbus_t *xbus, gfp_t gfp_flags);
void (*free_xframe)(xbus_t *xbus, xframe_t *xframe);
int (*xframe_send_pcm) (xbus_t *xbus, xframe_t *xframe);
int (*xframe_send_cmd) (xbus_t *xbus, xframe_t *xframe);
xframe_t *(*alloc_xframe) (xbus_t *xbus, gfp_t gfp_flags);
void (*free_xframe) (xbus_t *xbus, xframe_t *xframe);
};
/*
@@ -67,19 +67,11 @@ enum {
/* yucky, make an instance so we can size it... */
static struct xbus_counters {
char *name;
char *name;
} xbus_counters[] = {
C_(UNITS),
C_(TX_XFRAME_PCM),
C_(RX_XFRAME_PCM),
C_(TX_PACK_PCM),
C_(RX_PACK_PCM),
C_(TX_BYTES),
C_(RX_BYTES),
C_(TX_PCM_FRAG),
C_(RX_CMD),
C_(TX_CMD),
};
C_(UNITS), C_(TX_XFRAME_PCM), C_(RX_XFRAME_PCM), C_(TX_PACK_PCM),
C_(RX_PACK_PCM), C_(TX_BYTES), C_(RX_BYTES),
C_(TX_PCM_FRAG), C_(RX_CMD), C_(TX_CMD),};
#undef C_
@@ -99,17 +91,17 @@ enum xbus_state {
const char *xbus_statename(enum xbus_state st);
struct xbus_transport {
struct xbus_ops *ops;
void *priv;
struct device *transport_device;
ushort max_send_size;
enum xbus_state xbus_state;
unsigned long transport_flags;
spinlock_t state_lock;
atomic_t transport_refcount;
wait_queue_head_t transport_unused;
spinlock_t lock;
char model_string[MAX_ENV_STR];
struct xbus_ops *ops;
void *priv;
struct device *transport_device;
ushort max_send_size;
enum xbus_state xbus_state;
unsigned long transport_flags;
spinlock_t state_lock;
atomic_t transport_refcount;
wait_queue_head_t transport_unused;
spinlock_t lock;
char model_string[MAX_ENV_STR];
};
#define MAX_SEND_SIZE(xbus) ((xbus)->transport.max_send_size)
@@ -118,7 +110,8 @@ struct xbus_transport {
#define TRANSPORT_EXIST(xbus) ((xbus)->transport.ops != NULL)
#define XBUS_FLAG_CONNECTED 0
#define XBUS_FLAGS(xbus, flg) test_bit(XBUS_FLAG_ ## flg, &((xbus)->transport.transport_flags))
#define XBUS_FLAGS(xbus, flg) \
test_bit(XBUS_FLAG_ ## flg, &((xbus)->transport.transport_flags))
struct xbus_ops *transportops_get(xbus_t *xbus);
void transportops_put(xbus_t *xbus);
@@ -127,35 +120,39 @@ void transportops_put(xbus_t *xbus);
* Encapsulate all poll related data of a single xbus.
*/
struct xbus_workqueue {
struct workqueue_struct *wq;
struct work_struct xpds_init_work;
bool xpds_init_done;
struct list_head card_list;
int num_units;
int num_units_initialized;
wait_queue_head_t wait_for_xpd_initialization;
spinlock_t worker_lock;
struct semaphore running_initialization;
struct workqueue_struct *wq;
struct work_struct xpds_init_work;
bool xpds_init_done;
struct list_head card_list;
int num_units;
int num_units_initialized;
wait_queue_head_t wait_for_xpd_initialization;
spinlock_t worker_lock;
struct semaphore running_initialization;
};
/*
* Allocate/Free an xframe from pools of empty xframes.
* Calls to {get,put}_xframe are wrapped in
* Calls to {get, put}_xframe are wrapped in
* the macros bellow, so we take/return it
* to the correct pool.
*/
xframe_t *get_xframe(struct xframe_queue *q);
void put_xframe(struct xframe_queue *q, xframe_t *xframe);
#define ALLOC_SEND_XFRAME(xbus) get_xframe(&(xbus)->send_pool)
#define ALLOC_RECV_XFRAME(xbus) get_xframe(&(xbus)->receive_pool)
#define FREE_SEND_XFRAME(xbus, xframe) put_xframe(&(xbus)->send_pool, (xframe))
#define FREE_RECV_XFRAME(xbus, xframe) put_xframe(&(xbus)->receive_pool, (xframe))
#define ALLOC_SEND_XFRAME(xbus) \
get_xframe(&(xbus)->send_pool)
#define ALLOC_RECV_XFRAME(xbus) \
get_xframe(&(xbus)->receive_pool)
#define FREE_SEND_XFRAME(xbus, xframe) \
put_xframe(&(xbus)->send_pool, (xframe))
#define FREE_RECV_XFRAME(xbus, xframe) \
put_xframe(&(xbus)->receive_pool, (xframe))
xbus_t *xbus_num(uint num);
xbus_t *get_xbus(const char *msg, uint num);
void put_xbus(const char *msg, xbus_t *xbus);
int refcount_xbus(xbus_t *xbus);
xbus_t *xbus_num(uint num);
xbus_t *get_xbus(const char *msg, uint num);
void put_xbus(const char *msg, xbus_t *xbus);
int refcount_xbus(xbus_t *xbus);
/*
* Echo canceller related data
@@ -163,17 +160,17 @@ int refcount_xbus(xbus_t *xbus);
#define ECHO_TIMESLOTS 128
struct echoops {
int (*ec_set)(xpd_t *xpd, int pos, bool on);
int (*ec_get)(xpd_t *xpd, int pos);
int (*ec_update)(xbus_t *xbus);
void (*ec_dump)(xbus_t *xbus);
int (*ec_set) (xpd_t *xpd, int pos, bool on);
int (*ec_get) (xpd_t *xpd, int pos);
int (*ec_update) (xbus_t *xbus);
void (*ec_dump) (xbus_t *xbus);
};
struct xbus_echo_state {
const struct echoops *echoops;
byte timeslots[ECHO_TIMESLOTS];
int xpd_idx;
struct device_attribute *da[MAX_XPDS];
const struct echoops *echoops;
__u8 timeslots[ECHO_TIMESLOTS];
int xpd_idx;
struct device_attribute *da[MAX_XPDS];
};
#define ECHOOPS(xbus) ((xbus)->echo_state.echoops)
#define EC_METHOD(name, xbus) (ECHOOPS(xbus)->name)
@@ -183,126 +180,128 @@ struct xbus_echo_state {
* An xbus is a transport layer for Xorcom Protocol commands
*/
struct xbus {
char busname[XBUS_NAMELEN]; /* set by xbus_new() */
char busname[XBUS_NAMELEN]; /* set by xbus_new() */
/* low-level bus drivers set these 2 fields */
char connector[XBUS_DESCLEN];
char label[LABEL_SIZE];
byte revision; /* Protocol revision */
struct xbus_transport transport;
struct dahdi_device *ddev;
char connector[XBUS_DESCLEN];
char label[LABEL_SIZE];
__u8 revision; /* Protocol revision */
struct xbus_transport transport;
struct dahdi_device *ddev;
int num;
struct xpd *xpds[MAX_XPDS];
struct xbus_echo_state echo_state;
int num;
struct xpd *xpds[MAX_XPDS];
struct xbus_echo_state echo_state;
int command_tick_counter;
int usec_nosend; /* Firmware flow control */
struct xframe_queue command_queue;
wait_queue_head_t command_queue_empty;
int command_tick_counter;
int usec_nosend; /* Firmware flow control */
struct xframe_queue command_queue;
wait_queue_head_t command_queue_empty;
struct xframe_queue send_pool; /* empty xframes for send */
struct xframe_queue receive_pool; /* empty xframes for receive */
struct xframe_queue send_pool; /* empty xframes for send */
struct xframe_queue receive_pool; /* empty xframes for receive */
/* tasklet processing */
struct xframe_queue receive_queue;
struct tasklet_struct receive_tasklet;
int cpu_rcv_intr[NR_CPUS];
int cpu_rcv_tasklet[NR_CPUS];
struct xframe_queue receive_queue;
struct tasklet_struct receive_tasklet;
int cpu_rcv_intr[NR_CPUS];
int cpu_rcv_tasklet[NR_CPUS];
struct quirks {
unsigned int has_fxo:1;
unsigned int has_digital_span:1;
} quirks;
bool self_ticking;
enum sync_mode sync_mode;
} quirks;
bool self_ticking;
enum sync_mode sync_mode;
/* Managed by low-level drivers: */
enum sync_mode sync_mode_default;
struct timer_list command_timer;
unsigned int xbus_frag_count;
struct xframe_queue pcm_tospan;
enum sync_mode sync_mode_default;
struct timer_list command_timer;
unsigned int xbus_frag_count;
struct xframe_queue pcm_tospan;
struct xpp_ticker ticker; /* for tick rate */
struct xpp_drift drift; /* for tick offset */
struct xpp_ticker ticker; /* for tick rate */
struct xpp_drift drift; /* for tick offset */
atomic_t pcm_rx_counter;
unsigned int global_counter;
atomic_t pcm_rx_counter;
unsigned int global_counter;
/* Device-Model */
struct device astribank;
struct device astribank;
#define dev_to_xbus(dev) container_of(dev, struct xbus, astribank)
struct kref kref;
struct kref kref;
#define kref_to_xbus(k) container_of(k, struct xbus, kref)
spinlock_t lock;
spinlock_t lock;
/* PCM metrics */
struct timeval last_tx_sync;
struct timeval last_rx_sync;
unsigned long max_tx_sync;
unsigned long min_tx_sync;
unsigned long max_rx_sync;
unsigned long min_rx_sync;
unsigned long max_rx_process; /* packet processing time (usec) */
struct timeval last_tx_sync;
struct timeval last_rx_sync;
unsigned long max_tx_sync;
unsigned long min_tx_sync;
unsigned long max_rx_sync;
unsigned long min_rx_sync;
unsigned long max_rx_process; /* packet processing time (usec) */
#ifdef SAMPLE_TICKS
#define SAMPLE_SIZE 1000
int sample_ticks[SAMPLE_SIZE];
bool sample_running;
int sample_pos;
int sample_ticks[SAMPLE_SIZE];
bool sample_running;
int sample_pos;
#endif
struct xbus_workqueue worker;
struct xbus_workqueue worker;
/*
* Sync adjustment
*/
int sync_adjustment;
int sync_adjustment_offset;
long pll_updated_at;
int sync_adjustment;
int sync_adjustment_offset;
long pll_updated_at;
atomic_t num_xpds;
atomic_t num_xpds;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_xbus_dir;
struct proc_dir_entry *proc_xbus_summary;
struct proc_dir_entry *proc_xbus_dir;
struct proc_dir_entry *proc_xbus_summary;
#ifdef PROTOCOL_DEBUG
struct proc_dir_entry *proc_xbus_command;
struct proc_dir_entry *proc_xbus_command;
#endif
#endif
/* statistics */
int counters[XBUS_COUNTER_MAX];
int counters[XBUS_COUNTER_MAX];
};
#endif
#define XFRAME_MAGIC 123456L
struct xframe {
unsigned long xframe_magic;
struct list_head frame_list;
atomic_t frame_len;
xbus_t *xbus;
struct timeval tv_created;
struct timeval tv_queued;
struct timeval tv_submitted;
struct timeval tv_received;
unsigned long xframe_magic;
struct list_head frame_list;
atomic_t frame_len;
xbus_t *xbus;
struct timeval tv_created;
struct timeval tv_queued;
struct timeval tv_submitted;
struct timeval tv_received;
/* filled by transport layer */
size_t frame_maxlen;
byte *packets; /* max XFRAME_DATASIZE */
byte *first_free;
int usec_towait; /* prevent overflowing AB */
void *priv;
size_t frame_maxlen;
__u8 *packets; /* max XFRAME_DATASIZE */
__u8 *first_free;
int usec_towait; /* prevent overflowing AB */
void *priv;
};
void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize, void *priv);
void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize,
void *priv);
#define XFRAME_LEN(frame) atomic_read(&(frame)->frame_len)
int xbus_core_init(void); /* Initializer */
void xbus_core_shutdown(void); /* Terminator */
int xbus_core_init(void); /* Initializer */
void xbus_core_shutdown(void); /* Terminator */
/* Frame handling */
void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, int debug);
void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe,
int debug);
int send_cmd_frame(xbus_t *xbus, xframe_t *xframe);
/*
@@ -316,58 +315,45 @@ xpacket_t *xframe_next_packet(xframe_t *xframe, int len);
/*
* Map: unit+subunit <--> index in xbus->xpds[]
*/
#define XPD_IDX(unit,subunit) ((unit) * MAX_SUBUNIT + (subunit))
#define XPD_IDX(unit, subunit) ((unit) * MAX_SUBUNIT + (subunit))
#define XBUS_UNIT(idx) ((idx) / MAX_SUBUNIT)
#define XBUS_SUBUNIT(idx) ((idx) % MAX_SUBUNIT)
xpd_t *xpd_of(const xbus_t *xbus, int xpd_num);
xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit);
int xbus_check_unique(xbus_t *xbus);
bool xbus_setstate(xbus_t *xbus, enum xbus_state newstate);
bool xbus_setflags(xbus_t *xbus, int flagbit, bool on);
xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, struct device *transport_device, void *priv);
void xbus_free(xbus_t *xbus);
int xbus_connect(xbus_t *xbus);
int xbus_activate(xbus_t *xbus);
void xbus_deactivate(xbus_t *xbus);
void xbus_disconnect(xbus_t *xbus);
void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe);
int xbus_process_worker(xbus_t *xbus);
int waitfor_xpds(xbus_t *xbus, char *buf);
xpd_t *xpd_of(const xbus_t *xbus, int xpd_num);
xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit);
int xbus_check_unique(xbus_t *xbus);
bool xbus_setstate(xbus_t *xbus, enum xbus_state newstate);
bool xbus_setflags(xbus_t *xbus, int flagbit, bool on);
xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size,
struct device *transport_device, void *priv);
void xbus_free(xbus_t *xbus);
int xbus_connect(xbus_t *xbus);
int xbus_activate(xbus_t *xbus);
void xbus_deactivate(xbus_t *xbus);
void xbus_disconnect(xbus_t *xbus);
void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe);
int xbus_process_worker(xbus_t *xbus);
int waitfor_xpds(xbus_t *xbus, char *buf);
int xbus_xpd_bind(xbus_t *xbus, xpd_t *xpd, int unit, int subunit);
int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd);
int xbus_xpd_bind(xbus_t *xbus, xpd_t *xpd, int unit, int subunit);
int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd);
/* sysfs */
int xpd_device_register(xbus_t *xbus, xpd_t *xpd);
void xpd_device_unregister(xpd_t *xpd);
int echocancel_xpd(xpd_t *xpd, int on);
int xpd_device_register(xbus_t *xbus, xpd_t *xpd);
void xpd_device_unregister(xpd_t *xpd);
int echocancel_xpd(xpd_t *xpd, int on);
int xbus_is_registered(xbus_t *xbus);
int xbus_register_dahdi_device(xbus_t *xbus);
void xbus_unregister_dahdi_device(xbus_t *xbus);
int xbus_is_registered(xbus_t *xbus);
int xbus_register_dahdi_device(xbus_t *xbus);
void xbus_unregister_dahdi_device(xbus_t *xbus);
int xpp_driver_init(void);
void xpp_driver_exit(void);
int xbus_sysfs_transport_create(xbus_t *xbus);
void xbus_sysfs_transport_remove(xbus_t *xbus);
int xbus_sysfs_create(xbus_t *xbus);
void xbus_sysfs_remove(xbus_t *xbus);
int xpp_driver_init(void);
void xpp_driver_exit(void);
int xbus_sysfs_transport_create(xbus_t *xbus);
void xbus_sysfs_transport_remove(xbus_t *xbus);
int xbus_sysfs_create(xbus_t *xbus);
void xbus_sysfs_remove(xbus_t *xbus);
#ifdef OLD_HOTPLUG_SUPPORT_269
/* Copy from new kernels lib/kobject_uevent.c */
enum kobject_action {
KOBJ_ADD,
KOBJ_REMOVE,
KOBJ_CHANGE,
KOBJ_MOUNT,
KOBJ_UMOUNT,
KOBJ_OFFLINE,
KOBJ_ONLINE,
};
#endif
void astribank_uevent_send(xbus_t *xbus, enum kobject_action act);
#endif /* XBUS_CORE_H */
void astribank_uevent_send(xbus_t *xbus, enum kobject_action act);
#endif /* XBUS_CORE_H */

File diff suppressed because it is too large Load Diff

View File

@@ -33,10 +33,10 @@
#ifdef __KERNEL__
enum sync_mode {
SYNC_MODE_NONE = 0x00,
SYNC_MODE_AB = 0x01, /* Astribank sync */
SYNC_MODE_PLL = 0x03, /* Adjust XPD's PLL according to HOST */
SYNC_MODE_QUERY = 0x80,
SYNC_MODE_NONE = 0x00,
SYNC_MODE_AB = 0x01, /* Astribank sync */
SYNC_MODE_PLL = 0x03, /* Adjust XPD's PLL according to HOST */
SYNC_MODE_QUERY = 0x80,
};
/*
@@ -46,7 +46,7 @@ enum sync_mode {
* time representations.
*/
struct xpp_timestamp {
struct timeval tv;
struct timeval tv;
};
/*
@@ -58,12 +58,12 @@ struct xpp_timestamp {
* from other dahdi devices).
*/
struct xpp_ticker { /* for rate calculation */
int count;
int cycle;
struct xpp_timestamp first_sample;
struct xpp_timestamp last_sample;
int tick_period; /* usec/tick */
spinlock_t lock;
int count;
int cycle;
struct xpp_timestamp first_sample;
struct xpp_timestamp last_sample;
int tick_period; /* usec/tick */
spinlock_t lock;
};
/*
@@ -71,66 +71,65 @@ struct xpp_ticker { /* for rate calculation */
* xbus ticker to a reference ticker.
*/
struct xpp_drift {
int delta_tick; /* from ref_ticker */
int lost_ticks; /* occurances */
int lost_tick_count;
int sync_inaccuracy;
struct xpp_timestamp last_lost_tick;
long delta_sum;
int offset_prev;
int offset_range;
int offset_min;
int offset_max;
int min_speed;
int max_speed;
spinlock_t lock;
int delta_tick; /* from ref_ticker */
int lost_ticks; /* occurances */
int lost_tick_count;
int sync_inaccuracy;
struct xpp_timestamp last_lost_tick;
long delta_sum;
int offset_prev;
int offset_range;
int offset_min;
int offset_max;
int min_speed;
int max_speed;
spinlock_t lock;
};
void xpp_drift_init(xbus_t *xbus);
static inline long usec_diff(const struct timeval *tv1, const struct timeval *tv2)
static inline long usec_diff(const struct timeval *tv1,
const struct timeval *tv2)
{
long diff_sec;
long diff_usec;
long diff_sec;
long diff_usec;
diff_sec = tv1->tv_sec - tv2->tv_sec;
diff_usec = tv1->tv_usec - tv2->tv_usec;
return diff_sec * 1000000 + diff_usec;
}
int xbus_pcm_init(void *top);
void xbus_pcm_shutdown(void);
int send_pcm_frame(xbus_t *xbus, xframe_t *xframe);
void pcm_recompute(xpd_t *xpd, xpp_line_t tmp_pcm_mask);
void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe);
void update_wanted_pcm_mask(xpd_t *xpd, xpp_line_t new_mask, uint new_pcm_len);
void generic_card_pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask);
void generic_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack);
void generic_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack);
int generic_timing_priority(xpd_t *xpd);
int generic_echocancel_timeslot(xpd_t *xpd, int pos);
int generic_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask);
void fill_beep(u_char *buf, int num, int duration);
const char *sync_mode_name(enum sync_mode mode);
void xbus_set_command_timer(xbus_t *xbus, bool on);
void xbus_request_sync(xbus_t *xbus, enum sync_mode mode);
void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift);
int xbus_command_queue_tick(xbus_t *xbus);
void xbus_reset_counters(xbus_t *xbus);
void elect_syncer(const char *msg);
int exec_sync_command(const char *buf, size_t count);
int fill_sync_string(char *buf, size_t count);
int xbus_pcm_init(void *top);
void xbus_pcm_shutdown(void);
int send_pcm_frame(xbus_t *xbus, xframe_t *xframe);
void pcm_recompute(xpd_t *xpd, xpp_line_t tmp_pcm_mask);
void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe);
void update_wanted_pcm_mask(xpd_t *xpd, xpp_line_t new_mask, uint new_pcm_len);
void generic_card_pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask);
void generic_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack);
void generic_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack);
int generic_timing_priority(xpd_t *xpd);
int generic_echocancel_timeslot(xpd_t *xpd, int pos);
int generic_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask);
void fill_beep(u_char *buf, int num, int duration);
const char *sync_mode_name(enum sync_mode mode);
void xbus_set_command_timer(xbus_t *xbus, bool on);
void xbus_request_sync(xbus_t *xbus, enum sync_mode mode);
void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift);
int xbus_command_queue_tick(xbus_t *xbus);
void xbus_reset_counters(xbus_t *xbus);
void elect_syncer(const char *msg);
int exec_sync_command(const char *buf, size_t count);
int fill_sync_string(char *buf, size_t count);
#ifdef DAHDI_SYNC_TICK
void dahdi_sync_tick(struct dahdi_span *span, int is_master);
void dahdi_sync_tick(struct dahdi_span *span, int is_master);
#endif
#ifdef DEBUG_PCMTX
extern int pcmtx;
extern int pcmtx_chan;
extern int pcmtx;
extern int pcmtx_chan;
#endif
#endif /* __KERNEL__ */
#endif /* XBUS_PCM_H */
#endif /* __KERNEL__ */
#endif /* XBUS_PCM_H */

File diff suppressed because it is too large Load Diff

View File

@@ -34,18 +34,21 @@
/* This is to enable user-space programs to include this. */
#include <stdint.h>
typedef uint8_t __u8;
typedef uint8_t __u8;
typedef uint32_t __u32;
#include <stdio.h>
#define DBG(fmt, ...) printf("DBG: %s: " fmt, __FUNCTION__, ## __VA_ARGS__)
#define DBG(fmt, ...) printf("DBG: %s: " fmt, __func__, ## __VA_ARGS__)
#define INFO(fmt, ...) printf("INFO: " fmt, ## __VA_ARGS__)
#define NOTICE(fmt, ...) printf("NOTICE: " fmt, ## __VA_ARGS__)
#define ERR(fmt, ...) printf("ERR: " fmt, ## __VA_ARGS__)
#define __user
struct list_head { struct list_head *next; struct list_head *prev; };
struct list_head {
struct list_head *next;
struct list_head *prev;
};
#endif
@@ -53,15 +56,15 @@ struct list_head { struct list_head *next; struct list_head *prev; };
#define ALL_LINES ((lineno_t)-1)
#ifndef BIT /* added in 2.6.24 */
#ifndef BIT /* added in 2.6.24 */
#define BIT(i) (1UL << (i))
#endif
#define BIT_SET(x,i) ((x) |= BIT(i))
#define BIT_CLR(x,i) ((x) &= ~BIT(i))
#define IS_SET(x,i) (((x) & BIT(i)) != 0)
#define BIT_SET(x, i) ((x) |= BIT(i))
#define BIT_CLR(x, i) ((x) &= ~BIT(i))
#define IS_SET(x, i) (((x) & BIT(i)) != 0)
#define BITMASK(i) (((u64)1 << (i)) - 1)
#define MAX_PROC_WRITE 100 /* Largest buffer we allow writing our /proc files */
#define MAX_PROC_WRITE 100 /* Longest write allowed to our /proc files */
#define CHANNELS_PERXPD 32 /* Depends on xpp_line_t and protocol fields */
#define MAX_SPANNAME 20 /* From dahdi/kernel.h */
@@ -77,7 +80,8 @@ struct list_head { struct list_head *next; struct list_head *prev; };
#define UNIT_BITS 3 /* Bit for Astribank unit number */
#define SUBUNIT_BITS 3 /* Bit for Astribank subunit number */
#define MAX_UNIT (1 << UNIT_BITS) /* 1 FXS + 3 FXS/FXO | 1 BRI + 3 FXS/FXO */
/* 1 FXS + 3 FXS/FXO | 1 BRI + 3 FXS/FXO */
#define MAX_UNIT (1 << UNIT_BITS)
#define MAX_SUBUNIT (1 << SUBUNIT_BITS) /* 8 port BRI */
/*
@@ -95,74 +99,72 @@ struct list_head { struct list_head *next; struct list_head *prev; };
#define VALID_XPD_NUM(x) ((x) < MAX_XPDS && (x) >= 0)
#define CHAN_BITS 5 /* 0-31 for E1 */
#define CHAN_BITS 5 /* 0-31 for E1 */
typedef char *charp;
typedef unsigned char byte;
typedef char *charp;
#ifdef __KERNEL__
/* Kernel versions... */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
#define KMEM_CACHE_T kmem_cache_t
#else
#else
#define KMEM_CACHE_T struct kmem_cache
#endif
#endif
#define KZALLOC(size, gfp) my_kzalloc(size, gfp)
#define KZFREE(p) do { \
memset((p), 0, sizeof(*(p))); \
kfree(p); \
} while(0);
#define KZFREE(p) \
do { \
memset((p), 0, sizeof(*(p))); \
kfree(p); \
} while (0);
/*
* Hotplug replaced with uevent in 2.6.16
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
#define OLD_HOTPLUG_SUPPORT // for older kernels
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
#define OLD_HOTPLUG_SUPPORT_269// for way older kernels
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
#define DEVICE_ATTR_READER(name,dev,buf) \
ssize_t name(struct device *dev, struct device_attribute *attr, char *buf)
#define DEVICE_ATTR_WRITER(name,dev,buf, count) \
ssize_t name(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
#define DEVICE_ATTR_READER(name, dev, buf) \
ssize_t name(struct device *dev, \
struct device_attribute *attr, char *buf)
#define DEVICE_ATTR_WRITER(name, dev, buf, count) \
ssize_t name(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count)
#else
#define DEVICE_ATTR_READER(name,dev,buf) \
#define DEVICE_ATTR_READER(name, dev, buf) \
ssize_t name(struct device *dev, char *buf)
#define DEVICE_ATTR_WRITER(name,dev,buf, count) \
#define DEVICE_ATTR_WRITER(name, dev, buf, count) \
ssize_t name(struct device *dev, const char *buf, size_t count)
#endif
#define DRIVER_ATTR_READER(name,drv,buf) \
#define DRIVER_ATTR_READER(name, drv, buf) \
ssize_t name(struct device_driver *drv, char * buf)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
#define SET_PROC_DIRENTRY_OWNER(p) do { (p)->owner = THIS_MODULE; } while(0);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
#define SET_PROC_DIRENTRY_OWNER(p) \
do { \
(p)->owner = THIS_MODULE; \
} while (0);
#else
#define SET_PROC_DIRENTRY_OWNER(p) do { } while(0);
#define SET_PROC_DIRENTRY_OWNER(p) do { } while (0);
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
/* Also don't define this for later RHEL >= 5.2 . hex_asc is from the
* same linux-2.6-net-infrastructure-updates-to-mac80211-iwl4965.patch
* as is the bool typedef. */
#if LINUX_VERSION_CODE != KERNEL_VERSION(2,6,18) || ! defined(hex_asc)
typedef int bool;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
/* Also don't define this for later RHEL >= 5.2. */
#if defined(RHEL_RELEASE_CODE) && defined(RHEL_RELEASE_VERSION)
#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5, 3)
typedef int bool;
#endif
#else
typedef int bool;
#endif
#endif
#else
typedef int bool;
typedef int bool;
#endif
typedef struct xbus xbus_t;
typedef struct xpd xpd_t;
typedef struct xframe xframe_t;
typedef struct xpacket xpacket_t;
typedef __u32 xpp_line_t; /* at most 31 lines for E1 */
typedef byte lineno_t;
typedef byte xportno_t;
typedef struct xbus xbus_t;
typedef struct xpd xpd_t;
typedef struct xframe xframe_t;
typedef struct xpacket xpacket_t;
typedef __u32 xpp_line_t; /* at most 31 lines for E1 */
typedef __u8 lineno_t;
typedef __u8 xportno_t;
#define PORT_BROADCAST 255
#endif /* XDEFS_H */
#endif /* XDEFS_H */

View File

@@ -7,7 +7,9 @@ extern int debug;
static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags);
static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe);
void xframe_queue_init(struct xframe_queue *q, unsigned int steady_state_count, unsigned int max_count, const char *name, void *priv)
void xframe_queue_init(struct xframe_queue *q,
unsigned int steady_state_count, unsigned int max_count,
const char *name, void *priv)
{
memset(q, 0, sizeof(*q));
spin_lock_init(&q->lock);
@@ -17,61 +19,60 @@ void xframe_queue_init(struct xframe_queue *q, unsigned int steady_state_count,
q->name = name;
q->priv = priv;
}
EXPORT_SYMBOL(xframe_queue_init);
void xframe_queue_clearstats(struct xframe_queue *q)
{
q->worst_count = 0;
//q->overflows = 0; /* Never clear overflows */
//q->overflows = 0; /* Never clear overflows */
q->worst_lag_usec = 0L;
}
EXPORT_SYMBOL(xframe_queue_clearstats);
static void __xframe_dump_queue(struct xframe_queue *q)
{
xframe_t *xframe;
int i = 0;
char prefix[30];
struct timeval now;
xframe_t *xframe;
int i = 0;
char prefix[30];
struct timeval now;
do_gettimeofday(&now);
printk(KERN_DEBUG "%s: dump queue '%s' (first packet in each frame)\n",
THIS_MODULE->name,
q->name);
THIS_MODULE->name, q->name);
list_for_each_entry_reverse(xframe, &q->head, frame_list) {
xpacket_t *pack = (xpacket_t *)&xframe->packets[0];
long usec = usec_diff(&now, &xframe->tv_queued);
xpacket_t *pack = (xpacket_t *)&xframe->packets[0];
long usec = usec_diff(&now, &xframe->tv_queued);
snprintf(prefix, ARRAY_SIZE(prefix), " %3d> %5ld.%03ld msec",
i++, usec / 1000, usec % 1000);
i++, usec / 1000, usec % 1000);
dump_packet(prefix, pack, 1);
}
}
static bool __xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
{
int ret = 1;
static int overflow_cnt = 0;
int ret = 1;
static int overflow_cnt;
if(unlikely(q->disabled)) {
if (unlikely(q->disabled)) {
ret = 0;
goto out;
}
if(q->count >= q->max_count) {
if (q->count >= q->max_count) {
q->overflows++;
if ((overflow_cnt++ % 1000) < 5) {
NOTICE("Overflow of %-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02ld.%ld ms\n",
q->name,
q->steady_state_count,
q->count,
q->max_count,
q->worst_count,
q->overflows,
q->worst_lag_usec / 1000,
q->worst_lag_usec % 1000);
NOTICE("Overflow of %-15s: counts %3d, %3d, %3d "
"worst %3d, overflows %3d "
"worst_lag %02ld.%ld ms\n",
q->name, q->steady_state_count, q->count,
q->max_count, q->worst_count, q->overflows,
q->worst_lag_usec / 1000,
q->worst_lag_usec % 1000);
__xframe_dump_queue(q);
}
ret = 0;
goto out;
}
if(++q->count > q->worst_count)
if (++q->count > q->worst_count)
q->worst_count = q->count;
list_add_tail(&xframe->frame_list, &q->head);
do_gettimeofday(&xframe->tv_queued);
@@ -81,33 +82,36 @@ out:
bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
{
unsigned long flags;
int ret;
unsigned long flags;
int ret;
spin_lock_irqsave(&q->lock, flags);
ret = __xframe_enqueue(q, xframe);
spin_unlock_irqrestore(&q->lock, flags);
return ret;
}
EXPORT_SYMBOL(xframe_enqueue);
static xframe_t *__xframe_dequeue(struct xframe_queue *q)
{
xframe_t *frm = NULL;
struct list_head *h;
struct timeval now;
unsigned long usec_lag;
xframe_t *frm = NULL;
struct list_head *h;
struct timeval now;
unsigned long usec_lag;
if(list_empty(&q->head))
if (list_empty(&q->head))
goto out;
h = q->head.next;
list_del_init(h);
--q->count;
frm = list_entry(h, xframe_t, frame_list);
do_gettimeofday(&now);
usec_lag =
(now.tv_sec - frm->tv_queued.tv_sec)*1000*1000 +
(now.tv_usec - frm->tv_queued.tv_usec);
if(q->worst_lag_usec < usec_lag)
usec_lag =
(now.tv_sec - frm->tv_queued.tv_sec) * 1000 * 1000 + (now.tv_usec -
frm->
tv_queued.
tv_usec);
if (q->worst_lag_usec < usec_lag)
q->worst_lag_usec = usec_lag;
out:
return frm;
@@ -115,59 +119,68 @@ out:
xframe_t *xframe_dequeue(struct xframe_queue *q)
{
unsigned long flags;
xframe_t *frm;
unsigned long flags;
xframe_t *frm;
spin_lock_irqsave(&q->lock, flags);
frm = __xframe_dequeue(q);
spin_unlock_irqrestore(&q->lock, flags);
return frm;
}
EXPORT_SYMBOL(xframe_dequeue);
void xframe_queue_disable(struct xframe_queue *q, bool disabled)
{
q->disabled = disabled;
}
EXPORT_SYMBOL(xframe_queue_disable);
void xframe_queue_clear(struct xframe_queue *q)
{
xframe_t *xframe;
xbus_t *xbus = q->priv;
int i = 0;
xframe_t *xframe;
xbus_t *xbus = q->priv;
int i = 0;
xframe_queue_disable(q, 1);
while((xframe = xframe_dequeue(q)) != NULL) {
while ((xframe = xframe_dequeue(q)) != NULL) {
transport_free_xframe(xbus, xframe);
i++;
}
XBUS_DBG(DEVICES, xbus, "%s: finished queue clear (%d items)\n", q->name, i);
XBUS_DBG(DEVICES, xbus, "%s: finished queue clear (%d items)\n",
q->name, i);
}
EXPORT_SYMBOL(xframe_queue_clear);
uint xframe_queue_count(struct xframe_queue *q)
{
return q->count;
}
EXPORT_SYMBOL(xframe_queue_count);
/*------------------------- Frame Alloc/Dealloc --------------------*/
static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags)
{
struct xbus_ops *ops;
xframe_t *xframe;
unsigned long flags;
struct xbus_ops *ops;
xframe_t *xframe;
unsigned long flags;
BUG_ON(!xbus);
ops = transportops_get(xbus);
if(unlikely(!ops)) {
if (unlikely(!ops)) {
XBUS_ERR(xbus, "Missing transport\n");
return NULL;
}
spin_lock_irqsave(&xbus->transport.lock, flags);
//XBUS_INFO(xbus, "%s (transport_refcount=%d)\n", __FUNCTION__, atomic_read(&xbus->transport.transport_refcount));
#if 0
XBUS_INFO(xbus, "%s (transport_refcount=%d)\n",
__func__, atomic_read(&xbus->transport.transport_refcount));
#endif
xframe = ops->alloc_xframe(xbus, gfp_flags);
if(!xframe) {
if (!xframe) {
static int rate_limit;
if((rate_limit++ % 3001) == 0)
if ((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus,
"Failed xframe allocation from transport (%d)\n",
rate_limit);
@@ -180,14 +193,17 @@ static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags)
static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe)
{
struct xbus_ops *ops;
unsigned long flags;
struct xbus_ops *ops;
unsigned long flags;
BUG_ON(!xbus);
ops = xbus->transport.ops;
BUG_ON(!ops);
spin_lock_irqsave(&xbus->transport.lock, flags);
//XBUS_INFO(xbus, "%s (transport_refcount=%d)\n", __FUNCTION__, atomic_read(&xbus->transport.transport_refcount));
#if 0
XBUS_INFO(xbus, "%s (transport_refcount=%d)\n",
__func__, atomic_read(&xbus->transport.transport_refcount));
#endif
ops->free_xframe(xbus, xframe);
transportops_put(xbus);
spin_unlock_irqrestore(&xbus->transport.lock, flags);
@@ -195,45 +211,48 @@ static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe)
static bool xframe_queue_adjust(struct xframe_queue *q)
{
xbus_t *xbus;
xframe_t *xframe;
int delta;
unsigned long flags;
int ret = 0;
xbus_t *xbus;
xframe_t *xframe;
int delta;
unsigned long flags;
int ret = 0;
BUG_ON(!q);
xbus = q->priv;
BUG_ON(!xbus);
spin_lock_irqsave(&q->lock, flags);
delta = q->count - q->steady_state_count;
if(delta < -XFRAME_QUEUE_MARGIN) {
if (delta < -XFRAME_QUEUE_MARGIN) {
/* Increase pool by one frame */
//XBUS_INFO(xbus, "%s(%d): Allocate one\n", q->name, delta);
xframe = transport_alloc_xframe(xbus, GFP_ATOMIC);
if(!xframe) {
if (!xframe) {
static int rate_limit;
if((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus, "%s: failed frame allocation\n", q->name);
if ((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus, "%s: failed frame allocation\n",
q->name);
goto out;
}
if(!__xframe_enqueue(q, xframe)) {
if (!__xframe_enqueue(q, xframe)) {
static int rate_limit;
if((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus, "%s: failed enqueueing frame\n", q->name);
if ((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus, "%s: failed enqueueing frame\n",
q->name);
transport_free_xframe(xbus, xframe);
goto out;
}
} else if(delta > XFRAME_QUEUE_MARGIN) {
} else if (delta > XFRAME_QUEUE_MARGIN) {
/* Decrease pool by one frame */
//XBUS_INFO(xbus, "%s(%d): Free one\n", q->name, delta);
xframe = __xframe_dequeue(q);
if(!xframe) {
if (!xframe) {
static int rate_limit;
if((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus, "%s: failed dequeueing frame\n", q->name);
if ((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus, "%s: failed dequeueing frame\n",
q->name);
goto out;
}
transport_free_xframe(xbus, xframe);
@@ -246,19 +265,20 @@ out:
xframe_t *get_xframe(struct xframe_queue *q)
{
xframe_t *xframe;
xbus_t *xbus;
xframe_t *xframe;
xbus_t *xbus;
BUG_ON(!q);
xbus = (xbus_t *)q->priv;
BUG_ON(!xbus);
xframe_queue_adjust(q);
xframe = xframe_dequeue(q);
if(!xframe) {
if (!xframe) {
static int rate_limit;
if((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus, "%s STILL EMPTY (%d)\n", q->name, rate_limit);
if ((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus, "%s STILL EMPTY (%d)\n", q->name,
rate_limit);
return NULL;
}
BUG_ON(xframe->xframe_magic != XFRAME_MAGIC);
@@ -273,34 +293,25 @@ xframe_t *get_xframe(struct xframe_queue *q)
*
* memset(xframe->packets, 0, xframe->frame_maxlen);
*/
//XBUS_INFO(xbus, "%s\n", __FUNCTION__);
//XBUS_INFO(xbus, "%s\n", __func__);
return xframe;
}
EXPORT_SYMBOL(get_xframe);
void put_xframe(struct xframe_queue *q, xframe_t *xframe)
{
xbus_t *xbus;
xbus_t *xbus;
BUG_ON(!q);
xbus = (xbus_t *)q->priv;
BUG_ON(!xbus);
//XBUS_INFO(xbus, "%s\n", __FUNCTION__);
//XBUS_INFO(xbus, "%s\n", __func__);
BUG_ON(!TRANSPORT_EXIST(xbus));
if(unlikely(!xframe_enqueue(q, xframe))) {
if (unlikely(!xframe_enqueue(q, xframe))) {
XBUS_ERR(xbus, "Failed returning xframe to %s\n", q->name);
transport_free_xframe(xbus, xframe);
return;
}
xframe_queue_adjust(q);
}
EXPORT_SYMBOL(xframe_queue_init);
EXPORT_SYMBOL(xframe_queue_clearstats);
EXPORT_SYMBOL(xframe_enqueue);
EXPORT_SYMBOL(xframe_dequeue);
EXPORT_SYMBOL(xframe_queue_disable);
EXPORT_SYMBOL(xframe_queue_clear);
EXPORT_SYMBOL(xframe_queue_count);
EXPORT_SYMBOL(get_xframe);
EXPORT_SYMBOL(put_xframe);

View File

@@ -8,23 +8,22 @@
#define XFRAME_QUEUE_MARGIN 10
struct xframe_queue {
struct list_head head;
bool disabled;
unsigned int count;
unsigned int max_count;
unsigned int steady_state_count;
spinlock_t lock;
const char *name;
void *priv;
struct list_head head;
bool disabled;
unsigned int count;
unsigned int max_count;
unsigned int steady_state_count;
spinlock_t lock;
const char *name;
void *priv;
/* statistics */
unsigned int worst_count;
unsigned int overflows;
unsigned long worst_lag_usec; /* since xframe creation */
unsigned int worst_count;
unsigned int overflows;
unsigned long worst_lag_usec; /* since xframe creation */
};
void xframe_queue_init(struct xframe_queue *q,
unsigned int steady_state_count, unsigned int max_count,
const char *name, void *priv);
void xframe_queue_init(struct xframe_queue *q, unsigned int steady_state_count,
unsigned int max_count, const char *name, void *priv);
__must_check bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe);
__must_check xframe_t *xframe_dequeue(struct xframe_queue *q);
void xframe_queue_clearstats(struct xframe_queue *q);
@@ -32,4 +31,4 @@ void xframe_queue_disable(struct xframe_queue *q, bool disabled);
void xframe_queue_clear(struct xframe_queue *q);
uint xframe_queue_count(struct xframe_queue *q);
#endif /* XFRAME_QUEUE_ */
#endif /* XFRAME_QUEUE_ */

View File

@@ -31,71 +31,60 @@
#include <linux/device.h>
#include <linux/version.h>
#include <asm/atomic.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
#include <linux/semaphore.h>
#else
#include <asm/semaphore.h>
#endif
#include <linux/moduleparam.h>
#endif /* __KERNEL__ */
#endif /* __KERNEL__ */
#include <dahdi/kernel.h>
#ifdef __KERNEL__
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
/* also added in RHEL kernels with the OpenInfiniband backport: */
#if LINUX_VERSION_CODE != KERNEL_VERSION(2,6,9) || !defined(DEFINE_SPINLOCK)
typedef unsigned gfp_t; /* Added in 2.6.14 */
#endif
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
/*
* FIXME: Kludge for 2.6.19
* bool is now defined as a proper boolean type (gcc _Bool)
* but the command line parsing framework handles it as int.
*/
#define DEF_PARM_BOOL(name,init,perm,desc) \
int name = init; \
module_param(name, bool, perm); \
#define DEF_PARM_BOOL(name, init, perm, desc) \
int name = init; \
module_param(name, bool, perm); \
MODULE_PARM_DESC(name, desc " [default " #init "]")
#define DEF_PARM(type,name,init,perm,desc) \
type name = init; \
module_param(name, type, perm); \
MODULE_PARM_DESC(name, desc " [default " #init "]")
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
/*
* Old 2.6 kernels had module_param_array() macro that receive the counter
* by value.
*/
#define DEF_ARRAY(type,name,count,init,desc) \
unsigned int name ## _num_values; \
type name[count] = { [0 ... ((count)-1)] = (init) }; \
module_param_array(name, type, name ## _num_values, 0644); \
MODULE_PARM_DESC(name, desc " ( 1-" __MODULE_STRING(count) ")")
#else
#define DEF_ARRAY(type,name,count,init,desc) \
unsigned int name ## _num_values; \
type name[count] = {[0 ... ((count)-1)] = init}; \
module_param_array(name, type, &name ## _num_values, 0644); \
MODULE_PARM_DESC(name, desc " ( 1-" __MODULE_STRING(count) ")")
#define DEF_PARM_BOOL(name, init, perm, desc) \
bool name = init; \
module_param(name, bool, perm); \
MODULE_PARM_DESC(name, desc " [default " #init "]")
#endif
#endif // __KERNEL__
#define DEF_PARM(type, name, init, perm, desc) \
type name = init; \
module_param(name, type, perm); \
MODULE_PARM_DESC(name, desc " [default " #init "]")
#define DEF_ARRAY(type, name, count, init, desc) \
unsigned int name ## _num_values; \
type name[count] = {[0 ... ((count)-1)] = init}; \
module_param_array(name, type, &name ## _num_values, 0644); \
MODULE_PARM_DESC(name, desc " ( 1-" __MODULE_STRING(count) ")")
#endif // __KERNEL__
#define CARD_DESC_MAGIC 0xca9dde5c
struct card_desc_struct {
struct list_head card_list;
u32 magic;
byte type; /* LSB: 1 - to_phone, 0 - to_line */
byte subtype;
struct xpd_addr xpd_addr;
byte numchips;
byte ports_per_chip;
byte ports;
byte port_dir;
struct xpd_addr ec_addr; /* echo canceler address */
struct card_desc_struct {
struct list_head card_list;
u32 magic;
__u8 type; /* LSB: 1 - to_phone, 0 - to_line */
__u8 subtype;
struct xpd_addr xpd_addr;
__u8 numchips;
__u8 ports_per_chip;
__u8 ports;
__u8 port_dir;
struct xpd_addr ec_addr; /* echo canceler address */
};
typedef enum xpd_direction {
@@ -120,12 +109,9 @@ enum {
/* yucky, make an instance so we can size it... */
static struct xpd_counters {
char *name;
char *name;
} xpd_counters[] = {
C_(PCM_READ),
C_(PCM_WRITE),
C_(RECV_ERRORS),
};
C_(PCM_READ), C_(PCM_WRITE), C_(RECV_ERRORS),};
#undef C_
@@ -138,43 +124,43 @@ enum xpd_state {
XPD_STATE_NOHW,
};
bool xpd_setstate(xpd_t *xpd, enum xpd_state newstate);
const char *xpd_statename(enum xpd_state st);
bool xpd_setstate(xpd_t *xpd, enum xpd_state newstate);
const char *xpd_statename(enum xpd_state st);
#define PHONEDEV(xpd) ((xpd)->phonedev)
#define IS_PHONEDEV(xpd) (PHONEDEV(xpd).phoneops)
struct phonedev {
const struct phoneops *phoneops; /* Card level operations */
struct dahdi_span span;
struct dahdi_chan *chans[32];
#define XPD_CHAN(xpd,chan) (PHONEDEV(xpd).chans[(chan)])
const struct phoneops *phoneops; /* Card level operations */
struct dahdi_span span;
struct dahdi_chan *chans[32];
#define XPD_CHAN(xpd, chan) (PHONEDEV(xpd).chans[(chan)])
struct dahdi_echocan_state *ec[32];
int channels;
xpd_direction_t direction; /* TO_PHONE, TO_PSTN */
xpp_line_t no_pcm; /* Temporary: disable PCM (for USB-1) */
xpp_line_t offhook_state; /* Actual chip state: 0 - ONHOOK, 1 - OFHOOK */
xpp_line_t oht_pcm_pass; /* Transfer on-hook PCM */
int channels;
xpd_direction_t direction; /* TO_PHONE, TO_PSTN */
xpp_line_t no_pcm; /* Temporary: disable PCM (for USB-1) */
xpp_line_t offhook_state; /* chip state: 0 - ONHOOK, 1 - OFHOOK */
xpp_line_t oht_pcm_pass; /* Transfer on-hook PCM */
/* Voice Mail Waiting Indication: */
unsigned int msg_waiting[CHANNELS_PERXPD];
xpp_line_t digital_outputs; /* 0 - no, 1 - yes */
xpp_line_t digital_inputs; /* 0 - no, 1 - yes */
xpp_line_t digital_signalling; /* BRI signalling channels */
uint timing_priority; /* from 'span' directives in chan_dahdi.conf */
unsigned int msg_waiting[CHANNELS_PERXPD];
xpp_line_t digital_outputs; /* 0 - no, 1 - yes */
xpp_line_t digital_inputs; /* 0 - no, 1 - yes */
xpp_line_t digital_signalling; /* BRI signalling channels */
uint timing_priority; /* from 'span' directives in chan_dahdi.conf */
/* Assure atomicity of changes to pcm_len and wanted_pcm_mask */
spinlock_t lock_recompute_pcm;
spinlock_t lock_recompute_pcm;
/* maintained by card drivers */
uint pcm_len; /* allocation length of PCM packet (dynamic) */
xpp_line_t wanted_pcm_mask;
xpp_line_t silence_pcm; /* inject silence during next tick */
xpp_line_t mute_dtmf;
uint pcm_len; /* allocation length of PCM packet (dynamic) */
xpp_line_t wanted_pcm_mask;
xpp_line_t silence_pcm; /* inject silence during next tick */
xpp_line_t mute_dtmf;
bool ringing[CHANNELS_PERXPD];
bool ringing[CHANNELS_PERXPD];
atomic_t dahdi_registered; /* Am I fully registered with dahdi */
atomic_t open_counter; /* Number of open channels */
atomic_t dahdi_registered; /* Am I fully registered with dahdi */
atomic_t open_counter; /* Number of open channels */
/* Echo cancelation */
u_char ec_chunk1[CHANNELS_PERXPD][DAHDI_CHUNKSIZE];
@@ -186,51 +172,52 @@ struct phonedev {
*/
struct xpd {
char xpdname[XPD_NAMELEN];
struct phonedev phonedev;
struct phonedev phonedev;
const struct xops *xops;
xpd_type_t type;
const char *type_name;
byte subtype;
int subunits; /* all siblings */
enum xpd_state xpd_state;
struct device xpd_dev;
const struct xops *xops;
xpd_type_t type;
const char *type_name;
__u8 subtype;
int subunits; /* all siblings */
enum xpd_state xpd_state;
struct device xpd_dev;
#define dev_to_xpd(dev) container_of(dev, struct xpd, xpd_dev)
struct kref kref;
struct kref kref;
#define kref_to_xpd(k) container_of(k, struct xpd, kref)
xbus_t *xbus; /* The XBUS we are connected to */
struct device *echocancel;
xbus_t *xbus; /* The XBUS we are connected to */
struct device *echocancel;
spinlock_t lock;
spinlock_t lock;
int flags;
unsigned long blink_mode; /* bitmask of blinking ports */
int flags;
unsigned long blink_mode; /* bitmask of blinking ports */
#define DEFAULT_LED_PERIOD (1000/8) /* in tick */
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_xpd_dir;
struct proc_dir_entry *proc_xpd_summary;
struct proc_dir_entry *proc_xpd_dir;
struct proc_dir_entry *proc_xpd_summary;
#endif
int counters[XPD_COUNTER_MAX];
int counters[XPD_COUNTER_MAX];
const xproto_table_t *xproto; /* Card level protocol table */
void *priv; /* Card level private data */
bool card_present;
reg_cmd_t requested_reply;
reg_cmd_t last_reply;
const xproto_table_t *xproto; /* Card level protocol table */
void *priv; /* Card level private data */
bool card_present;
reg_cmd_t requested_reply;
reg_cmd_t last_reply;
unsigned long last_response; /* in jiffies */
unsigned xbus_idx; /* index in xbus->xpds[] */
struct xpd_addr addr;
unsigned long last_response; /* in jiffies */
unsigned xbus_idx; /* index in xbus->xpds[] */
struct xpd_addr addr;
struct list_head xpd_list;
unsigned int timer_count;
unsigned int timer_count;
};
#define for_each_line(xpd,i) for((i) = 0; (i) < PHONEDEV(xpd).channels; (i)++)
#define for_each_line(xpd, i) \
for ((i) = 0; (i) < PHONEDEV(xpd).channels; (i)++)
#define IS_BRI(xpd) ((xpd)->type == XPD_TYPE_BRI)
#define TICK_TOLERANCE 500 /* usec */
#define TICK_TOLERANCE 500 /* usec */
#ifdef DEBUG_SYNC_PARPORT
void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1);
@@ -240,27 +227,28 @@ void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1);
static inline void *my_kzalloc(size_t size, gfp_t flags)
{
void *p;
void *p;
p = kmalloc(size, flags);
if(p)
if (p)
memset(p, 0, size);
return p;
}
struct xpd_driver {
xpd_type_t type;
xpd_type_t type;
struct device_driver driver;
#define driver_to_xpd_driver(driver) container_of(driver, struct xpd_driver, driver)
struct device_driver driver;
#define driver_to_xpd_driver(driver) \
container_of(driver, struct xpd_driver, driver)
};
int xpd_driver_register(struct device_driver *driver);
void xpd_driver_unregister(struct device_driver *driver);
xpd_t *get_xpd(const char *msg, xpd_t *xpd);
void put_xpd(const char *msg, xpd_t *xpd);
int refcount_xpd(xpd_t *xpd);
int xpd_driver_register(struct device_driver *driver);
void xpd_driver_unregister(struct device_driver *driver);
xpd_t *get_xpd(const char *msg, xpd_t *xpd);
void put_xpd(const char *msg, xpd_t *xpd);
int refcount_xpd(xpd_t *xpd);
#endif
#endif /* XPD_H */
#endif /* XPD_H */

File diff suppressed because it is too large Load Diff

View File

@@ -30,37 +30,40 @@ int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset);
int xpd_dahdi_postregister(xpd_t *xpd);
void xpd_dahdi_preunregister(xpd_t *xpd);
void xpd_dahdi_postunregister(xpd_t *xpd);
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
int unit, int subunit, byte type, byte subtype, int subunits, int subunit_ports, byte port_dir);
xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit, int subtype, int subunits, size_t privsize, const xproto_table_t *proto_table, int channels);
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table, int unit,
int subunit, __u8 type, __u8 subtype, int subunits,
int subunit_ports, __u8 port_dir);
xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit, int subtype, int subunits,
size_t privsize, const xproto_table_t *proto_table,
int channels);
void xpd_free(xpd_t *xpd);
void xpd_remove(xpd_t *xpd);
void update_xpd_status(xpd_t *xpd, int alarm_flag);
const char *xpp_echocan_name(const struct dahdi_chan *chan);
int xpp_echocan_create(struct dahdi_chan *chan,
struct dahdi_echocanparams *ecp,
struct dahdi_echocanparam *p,
struct dahdi_echocan_state **ec);
int xpp_echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
struct dahdi_echocanparam *p,
struct dahdi_echocan_state **ec);
void hookstate_changed(xpd_t *xpd, int pos, bool good);
int xpp_open(struct dahdi_chan *chan);
int xpp_close(struct dahdi_chan *chan);
int xpp_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long arg);
int xpp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig);
int xpp_maint(struct dahdi_span *span, int cmd);
int xpp_watchdog(struct dahdi_span *span, int cause);
void xpp_span_assigned(struct dahdi_span *span);
void report_bad_ioctl(const char *msg, xpd_t *xpd, int pos, unsigned int cmd);
int total_registered_spans(void);
void oht_pcm(xpd_t *xpd, int pos, bool pass);
void mark_offhook(xpd_t *xpd, int pos, bool to_offhook);
#define IS_OFFHOOK(xpd,pos) IS_SET((xpd)->phonedev.offhook_state, (pos))
#define IS_OFFHOOK(xpd, pos) IS_SET((xpd)->phonedev.offhook_state, (pos))
void notify_rxsig(xpd_t *xpd, int pos, enum dahdi_rxsig rxsig);
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
extern struct proc_dir_entry *xpp_proc_toplevel;
extern struct proc_dir_entry *xpp_proc_toplevel;
#endif
#define SPAN_REGISTERED(xpd) atomic_read(&PHONEDEV(xpd).dahdi_registered)
#endif /* XPP_DAHDI_H */
#endif /* XPP_DAHDI_H */

File diff suppressed because it is too large Load Diff

View File

@@ -30,7 +30,7 @@
static const char rcsid[] = "$Id$";
extern int debug;
extern int debug;
static const xproto_table_t *xprotocol_tables[XPD_TYPE_NOMODULE];
@@ -40,12 +40,15 @@ static const xproto_table_t *xprotocol_tables[XPD_TYPE_NOMODULE];
bool valid_xpd_addr(const struct xpd_addr *addr)
{
return ((addr->subunit & ~BITMASK(SUBUNIT_BITS)) == 0) && ((addr->unit & ~BITMASK(UNIT_BITS)) == 0);
return ((addr->subunit & ~BITMASK(SUBUNIT_BITS)) == 0)
&& ((addr->unit & ~BITMASK(UNIT_BITS)) == 0);
}
EXPORT_SYMBOL(valid_xpd_addr);
/*---------------- General Protocol Management ----------------------------*/
/*------ General Protocol Management ----------------------------*/
const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, byte opcode)
const xproto_entry_t *xproto_card_entry(const xproto_table_t *table,
__u8 opcode)
{
const xproto_entry_t *xe;
@@ -53,8 +56,9 @@ const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, byte opcode
xe = &table->entries[opcode];
return (xe->handler != NULL) ? xe : NULL;
}
EXPORT_SYMBOL(xproto_card_entry);
const xproto_entry_t *xproto_global_entry(byte opcode)
const xproto_entry_t *xproto_global_entry(__u8 opcode)
{
const xproto_entry_t *xe;
@@ -62,42 +66,52 @@ const xproto_entry_t *xproto_global_entry(byte opcode)
//DBG(GENERAL, "opcode=0x%X xe=%p\n", opcode, xe);
return xe;
}
EXPORT_SYMBOL(xproto_global_entry);
xproto_handler_t xproto_global_handler(byte opcode)
xproto_handler_t xproto_global_handler(__u8 opcode)
{
return xproto_card_handler(&PROTO_TABLE(GLOBAL), opcode);
}
static const xproto_table_t *xproto_table(xpd_type_t cardtype)
{
if(cardtype >= XPD_TYPE_NOMODULE)
if (cardtype >= XPD_TYPE_NOMODULE)
return NULL;
return xprotocol_tables[cardtype];
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
#define MODULE_REFCOUNT_FORMAT "%s refcount was %d\n"
#else
#define MODULE_REFCOUNT_FORMAT "%s refcount was %lu\n"
#endif
const xproto_table_t *xproto_get(xpd_type_t cardtype)
{
const xproto_table_t *xtable;
if(cardtype >= XPD_TYPE_NOMODULE)
if (cardtype >= XPD_TYPE_NOMODULE)
return NULL;
xtable = xprotocol_tables[cardtype];
if(!xtable) { /* Try to load the relevant module */
if (!xtable) { /* Try to load the relevant module */
int ret = request_module(XPD_TYPE_PREFIX "%d", cardtype);
if(ret != 0) {
NOTICE("%s: Failed to load module for type=%d. exit status=%d.\n",
__FUNCTION__, cardtype, ret);
if (ret != 0) {
NOTICE("%s: Failed to load module for type=%d. "
"exit status=%d.\n",
__func__, cardtype, ret);
/* Drop through: we may be lucky... */
}
xtable = xprotocol_tables[cardtype];
}
if(xtable) {
if (xtable) {
BUG_ON(!xtable->owner);
#ifdef CONFIG_MODULE_UNLOAD
DBG(GENERAL, "%s refcount was %d\n", xtable->name, module_refcount(xtable->owner));
DBG(GENERAL, MODULE_REFCOUNT_FORMAT, xtable->name,
module_refcount(xtable->owner));
#endif
if(!try_module_get(xtable->owner)) {
ERR("%s: try_module_get for %s failed.\n", __FUNCTION__, xtable->name);
if (!try_module_get(xtable->owner)) {
ERR("%s: try_module_get for %s failed.\n", __func__,
xtable->name);
return NULL;
}
}
@@ -108,13 +122,15 @@ void xproto_put(const xproto_table_t *xtable)
{
BUG_ON(!xtable);
#ifdef CONFIG_MODULE_UNLOAD
DBG(GENERAL, "%s refcount was %d\n", xtable->name, module_refcount(xtable->owner));
DBG(GENERAL, MODULE_REFCOUNT_FORMAT, xtable->name,
module_refcount(xtable->owner));
BUG_ON(module_refcount(xtable->owner) <= 0);
#endif
module_put(xtable->owner);
}
xproto_handler_t xproto_card_handler(const xproto_table_t *table, byte opcode)
xproto_handler_t xproto_card_handler(const xproto_table_t *table,
__u8 opcode)
{
const xproto_entry_t *xe;
@@ -123,78 +139,89 @@ xproto_handler_t xproto_card_handler(const xproto_table_t *table, byte opcode)
return xe->handler;
}
void notify_bad_xpd(const char *funcname, xbus_t *xbus, const struct xpd_addr addr, const char *msg)
void notify_bad_xpd(const char *funcname, xbus_t *xbus,
const struct xpd_addr addr, const char *msg)
{
XBUS_NOTICE(xbus, "%s: non-existing address (%1d%1d): %s\n",
funcname, addr.unit, addr.subunit, msg);
XBUS_NOTICE(xbus, "%s: non-existing address (%1d%1d): %s\n", funcname,
addr.unit, addr.subunit, msg);
}
EXPORT_SYMBOL(notify_bad_xpd);
static int packet_process(xbus_t *xbus, xpacket_t *pack)
{
byte op;
const xproto_entry_t *xe;
xproto_handler_t handler;
xproto_table_t *table;
xpd_t *xpd;
int ret = -EPROTO;
__u8 op;
const xproto_entry_t *xe;
xproto_handler_t handler;
xproto_table_t *table;
xpd_t *xpd;
int ret = -EPROTO;
BUG_ON(!pack);
if(!valid_xpd_addr(&XPACKET_ADDR(pack))) {
if(printk_ratelimit()) {
if (!valid_xpd_addr(&XPACKET_ADDR(pack))) {
if (printk_ratelimit()) {
XBUS_NOTICE(xbus, "%s: from %d%d: bad address.\n",
__FUNCTION__,
XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
dump_packet("packet_process -- bad address", pack, debug);
__func__, XPACKET_ADDR_UNIT(pack),
XPACKET_ADDR_SUBUNIT(pack));
dump_packet("packet_process -- bad address", pack,
debug);
}
goto out;
}
op = XPACKET_OP(pack);
xpd = xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
xpd =
xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack),
XPACKET_ADDR_SUBUNIT(pack));
/* XPD may be NULL (e.g: during bus polling */
xe = xproto_global_entry(op);
/*-------- Validations -----------*/
if(!xe) {
if (!xe) {
const xproto_table_t *xtable;
if(!xpd) {
if(printk_ratelimit()) {
XBUS_NOTICE(xbus, "%s: from %d%d opcode=0x%02X: no such global command.\n",
__FUNCTION__,
XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack), op);
dump_packet("packet_process -- no such global command", pack, 1);
if (!xpd) {
if (printk_ratelimit()) {
XBUS_NOTICE(xbus,
"%s: from %d%d opcode=0x%02X: "
"no such global command.\n",
__func__, XPACKET_ADDR_UNIT(pack),
XPACKET_ADDR_SUBUNIT(pack), op);
dump_packet
("packet_process -- no such global command",
pack, 1);
}
goto out;
}
xtable = xproto_table(xpd->type);
if(!xtable) {
if(printk_ratelimit())
XPD_ERR(xpd, "%s: no protocol table (type=%d)\n",
__FUNCTION__,
xpd->type);
if (!xtable) {
if (printk_ratelimit())
XPD_ERR(xpd,
"%s: no protocol table (type=%d)\n",
__func__, xpd->type);
goto out;
}
xe = xproto_card_entry(xtable, op);
if(!xe) {
if(printk_ratelimit()) {
XPD_NOTICE(xpd, "%s: bad command (type=%d,opcode=0x%x)\n",
__FUNCTION__,
xpd->type, op);
dump_packet("packet_process -- bad command", pack, 1);
if (!xe) {
if (printk_ratelimit()) {
XPD_NOTICE(xpd,
"%s: bad command (type=%d,opcode=0x%x)\n",
__func__, xpd->type, op);
dump_packet("packet_process -- bad command",
pack, 1);
}
goto out;
}
}
table = xe->table;
BUG_ON(!table);
if(!table->packet_is_valid(pack)) {
if(printk_ratelimit()) {
if (!table->packet_is_valid(pack)) {
if (printk_ratelimit()) {
ERR("xpp: %s: wrong size %d for opcode=0x%02X\n",
__FUNCTION__, XPACKET_LEN(pack), op);
dump_packet("packet_process -- wrong size", pack, debug);
__func__, XPACKET_LEN(pack), op);
dump_packet("packet_process -- wrong size", pack,
debug);
}
goto out;
}
ret = 0; /* All well */
ret = 0; /* All well */
handler = xe->handler;
BUG_ON(!handler);
XBUS_COUNTER(xbus, RX_BYTES) += XPACKET_LEN(pack);
@@ -205,13 +232,13 @@ out:
static int xframe_receive_cmd(xbus_t *xbus, xframe_t *xframe)
{
byte *xframe_end;
xpacket_t *pack;
byte *p;
int len;
int ret;
__u8 *xframe_end;
xpacket_t *pack;
__u8 *p;
int len;
int ret;
if(debug & DBG_COMMANDS)
if (debug & DBG_COMMANDS)
dump_xframe("RX-CMD", xbus, xframe, DBG_ANY);
p = xframe->packets;
xframe_end = p + XFRAME_LEN(xframe);
@@ -219,31 +246,34 @@ static int xframe_receive_cmd(xbus_t *xbus, xframe_t *xframe)
pack = (xpacket_t *)p;
len = XPACKET_LEN(pack);
/* Sanity checks */
if(unlikely(XPACKET_OP(pack) == XPROTO_NAME(GLOBAL,PCM_READ))) {
static int rate_limit;
if (unlikely(XPACKET_OP(pack) == XPROTO_NAME(GLOBAL, PCM_READ))) {
static int rate_limit;
if((rate_limit++ % 1003) == 0) {
XBUS_DBG(GENERAL, xbus, "A PCM packet within a Non-PCM xframe\n");
dump_xframe("In Non-PCM xframe", xbus, xframe, debug);
if ((rate_limit++ % 1003) == 0) {
XBUS_DBG(GENERAL, xbus,
"A PCM packet within a Non-PCM xframe\n");
dump_xframe("In Non-PCM xframe",
xbus, xframe, debug);
}
ret = -EPROTO;
goto out;
}
p += len;
if(p > xframe_end || len < RPACKET_HEADERSIZE) {
static int rate_limit;
if (p > xframe_end || len < RPACKET_HEADERSIZE) {
static int rate_limit;
if((rate_limit++ % 1003) == 0) {
XBUS_NOTICE(xbus, "Invalid packet length %d\n", len);
if ((rate_limit++ % 1003) == 0) {
XBUS_NOTICE(xbus, "Invalid packet length %d\n",
len);
dump_xframe("BAD LENGTH", xbus, xframe, debug);
}
ret = -EPROTO;
goto out;
}
ret = packet_process(xbus, pack);
if(unlikely(ret < 0))
if (unlikely(ret < 0))
break;
} while(p < xframe_end);
} while (p < xframe_end);
out:
FREE_RECV_XFRAME(xbus, xframe);
return ret;
@@ -251,22 +281,22 @@ out:
int xframe_receive(xbus_t *xbus, xframe_t *xframe)
{
int ret = 0;
struct timeval now;
struct timeval tv_received;
int usec;
int ret = 0;
struct timeval now;
struct timeval tv_received;
int usec;
if(XFRAME_LEN(xframe) < RPACKET_HEADERSIZE) {
static int rate_limit;
if (XFRAME_LEN(xframe) < RPACKET_HEADERSIZE) {
static int rate_limit;
if((rate_limit++ % 1003) == 0) {
if ((rate_limit++ % 1003) == 0) {
XBUS_NOTICE(xbus, "short xframe\n");
dump_xframe("short xframe", xbus, xframe, debug);
}
FREE_RECV_XFRAME(xbus, xframe);
return -EPROTO;
}
if(!XBUS_FLAGS(xbus, CONNECTED)) {
if (!XBUS_FLAGS(xbus, CONNECTED)) {
XBUS_DBG(GENERAL, xbus, "Dropped xframe. Is shutting down.\n");
return -ENODEV;
}
@@ -274,8 +304,8 @@ int xframe_receive(xbus_t *xbus, xframe_t *xframe)
/*
* We want to check that xframes do not mix PCM and other commands
*/
if(XPACKET_IS_PCM((xpacket_t *)xframe->packets)) {
if(!XBUS_IS(xbus, READY))
if (XPACKET_IS_PCM((xpacket_t *)xframe->packets)) {
if (!XBUS_IS(xbus, READY))
FREE_RECV_XFRAME(xbus, xframe);
else
xframe_receive_pcm(xbus, xframe);
@@ -285,47 +315,48 @@ int xframe_receive(xbus_t *xbus, xframe_t *xframe)
}
/* Calculate total processing time */
do_gettimeofday(&now);
usec = (now.tv_sec - tv_received.tv_sec) * 1000000 +
now.tv_usec - tv_received.tv_usec;
if(usec > xbus->max_rx_process)
usec =
(now.tv_sec - tv_received.tv_sec) * 1000000 + now.tv_usec -
tv_received.tv_usec;
if (usec > xbus->max_rx_process)
xbus->max_rx_process = usec;
return ret;
}
EXPORT_SYMBOL(xframe_receive);
#define VERBOSE_DEBUG 1
#define ERR_REPORT_LIMIT 20
void dump_packet(const char *msg, const xpacket_t *packet, bool debug)
{
byte op = XPACKET_OP(packet);
byte *addr = (byte *)&XPACKET_ADDR(packet);
__u8 op = XPACKET_OP(packet);
__u8 *addr = (__u8 *)&XPACKET_ADDR(packet);
if(!debug)
if (!debug)
return;
printk(KERN_DEBUG "%s: XPD=%1X-%1X%c (0x%X) OP=0x%02X LEN=%d",
msg,
XPACKET_ADDR_UNIT(packet),
XPACKET_ADDR_SUBUNIT(packet),
(XPACKET_ADDR_SYNC(packet))?'+':' ',
*addr,
op,
XPACKET_LEN(packet));
printk(KERN_DEBUG "%s: XPD=%1X-%1X%c (0x%X) OP=0x%02X LEN=%d", msg,
XPACKET_ADDR_UNIT(packet), XPACKET_ADDR_SUBUNIT(packet),
(XPACKET_ADDR_SYNC(packet)) ? '+' : ' ', *addr, op,
XPACKET_LEN(packet));
#if VERBOSE_DEBUG
{
int i;
byte *p = (byte *)packet;
__u8 *p = (__u8 *)packet;
printk(" BYTES: ");
for(i = 0; i < XPACKET_LEN(packet); i++) {
static int limiter = 0;
for (i = 0; i < XPACKET_LEN(packet); i++) {
static int limiter;
if(i >= sizeof(xpacket_t)) {
if(limiter < ERR_REPORT_LIMIT) {
ERR("%s: length overflow i=%d > sizeof(xpacket_t)=%lu\n",
__FUNCTION__, i+1, (long)sizeof(xpacket_t));
} else if(limiter == ERR_REPORT_LIMIT) {
ERR("%s: error packet #%d... squelsh reports.\n",
__FUNCTION__, limiter);
if (i >= sizeof(xpacket_t)) {
if (limiter < ERR_REPORT_LIMIT) {
ERR("%s: length overflow "
"i=%d > sizeof(xpacket_t)=%lu\n",
__func__, i + 1,
(long)sizeof(xpacket_t));
} else if (limiter == ERR_REPORT_LIMIT) {
ERR("%s: error packet #%d... "
"squelsh reports.\n",
__func__, limiter);
}
limiter++;
break;
@@ -337,112 +368,121 @@ void dump_packet(const char *msg, const xpacket_t *packet, bool debug)
#endif
printk("\n");
}
EXPORT_SYMBOL(dump_packet);
void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
byte unit, xportno_t port, const reg_cmd_t *regcmd)
__u8 unit, xportno_t port, const reg_cmd_t *regcmd)
{
char action;
char modifier;
char port_buf[MAX_PROC_WRITE];
char reg_buf[MAX_PROC_WRITE];
char data_buf[MAX_PROC_WRITE];
char action;
char modifier;
char port_buf[MAX_PROC_WRITE];
char reg_buf[MAX_PROC_WRITE];
char data_buf[MAX_PROC_WRITE];
if(regcmd->bytes > sizeof(*regcmd) - 1) { /* The size byte is not included */
PORT_NOTICE(xbus, unit, port, "%s: %s: Too long: regcmd->bytes = %d\n",
__FUNCTION__, msg, regcmd->bytes);
/* The size byte is not included */
if (regcmd->bytes > sizeof(*regcmd) - 1) {
PORT_NOTICE(xbus, unit, port,
"%s: %s: Too long: regcmd->bytes = %d\n", __func__,
msg, regcmd->bytes);
return;
}
if(regcmd->is_multibyte) {
char buf[MAX_PROC_WRITE + 1];
int i;
int n = 0;
size_t len = regcmd->bytes;
const byte *p = REG_XDATA(regcmd);
if (regcmd->is_multibyte) {
char buf[MAX_PROC_WRITE + 1];
int i;
int n = 0;
size_t len = regcmd->bytes;
const __u8 *p = REG_XDATA(regcmd);
buf[0] = '\0';
for(i = 0; i < len && n < MAX_PROC_WRITE; i++)
n += snprintf(&buf[n], MAX_PROC_WRITE - n, "%02X ", p[i]);
for (i = 0; i < len && n < MAX_PROC_WRITE; i++)
n += snprintf(&buf[n], MAX_PROC_WRITE - n, "%02X ",
p[i]);
PORT_DBG(REGS, xbus, unit, port,
"UNIT-%d PORT-%d: Multibyte(eoframe=%d) %s[0..%zd]: %s%s\n",
unit, port, regcmd->eoframe,
msg, len-1, buf, (n >= MAX_PROC_WRITE)?"...":"");
"UNIT-%d PORT-%d: Multibyte(eoframe=%d) "
"%s[0..%zd]: %s%s\n",
unit, port, regcmd->eoframe, msg, len - 1, buf,
(n >= MAX_PROC_WRITE) ? "..." : "");
return;
}
if(regcmd->bytes != sizeof(*regcmd) - 1) { /* The size byte is not included */
PORT_NOTICE(xbus, unit, port, "%s: %s: Wrong size: regcmd->bytes = %d\n",
__FUNCTION__, msg, regcmd->bytes);
/* The size byte is not included */
if (regcmd->bytes != sizeof(*regcmd) - 1) {
PORT_NOTICE(xbus, unit, port,
"%s: %s: Wrong size: regcmd->bytes = %d\n",
__func__, msg, regcmd->bytes);
return;
}
snprintf(port_buf, MAX_PROC_WRITE, "%d%s",
regcmd->portnum,
(REG_FIELD(regcmd, all_ports_broadcast)) ? "*" : "");
snprintf(port_buf, MAX_PROC_WRITE, "%d%s", regcmd->portnum,
(REG_FIELD(regcmd, all_ports_broadcast)) ? "*" : "");
action = (REG_FIELD(regcmd, read_request)) ? 'R' : 'W';
modifier = 'D';
if(REG_FIELD(regcmd, do_subreg)) {
snprintf(reg_buf, MAX_PROC_WRITE, "%02X %02X",
REG_FIELD(regcmd, regnum),
REG_FIELD(regcmd, subreg));
if (REG_FIELD(regcmd, do_subreg)) {
snprintf(reg_buf, MAX_PROC_WRITE, "%02X %02X",
REG_FIELD(regcmd, regnum), REG_FIELD(regcmd, subreg));
modifier = 'S';
} else {
snprintf(reg_buf, MAX_PROC_WRITE, "%02X",
REG_FIELD(regcmd, regnum));
snprintf(reg_buf, MAX_PROC_WRITE, "%02X",
REG_FIELD(regcmd, regnum));
}
if(REG_FIELD(regcmd, read_request)) {
if (REG_FIELD(regcmd, read_request)) {
data_buf[0] = '\0';
} else if(REG_FIELD(regcmd, do_datah)) {
snprintf(data_buf, MAX_PROC_WRITE, "%02X %02X",
REG_FIELD(regcmd, data_low),
REG_FIELD(regcmd, data_high));
} else if (REG_FIELD(regcmd, do_datah)) {
snprintf(data_buf, MAX_PROC_WRITE, "%02X %02X",
REG_FIELD(regcmd, data_low), REG_FIELD(regcmd,
data_high));
modifier = 'I';
} else {
snprintf(data_buf, MAX_PROC_WRITE, "%02X",
REG_FIELD(regcmd, data_low));
snprintf(data_buf, MAX_PROC_WRITE, "%02X",
REG_FIELD(regcmd, data_low));
}
PORT_DBG(REGS, xbus, unit, port, "%s: %s %c%c %s %s\n",
msg, port_buf, action, modifier,
reg_buf, data_buf);
PORT_DBG(REGS, xbus, unit, port, "%s: %s %c%c %s %s\n", msg, port_buf,
action, modifier, reg_buf, data_buf);
}
EXPORT_SYMBOL(dump_reg_cmd);
const char *xproto_name(xpd_type_t xpd_type)
{
const xproto_table_t *proto_table;
const xproto_table_t *proto_table;
BUG_ON(xpd_type >= XPD_TYPE_NOMODULE);
proto_table = xprotocol_tables[xpd_type];
if(!proto_table)
if (!proto_table)
return NULL;
return proto_table->name;
}
EXPORT_SYMBOL(xproto_name);
#define CHECK_XOP(xops, f) \
if(!(xops)->f) { \
ERR("%s: missing xmethod %s [%s (%d)]\n", __FUNCTION__, #f, name, type); \
if (!(xops)->f) { \
ERR("%s: missing xmethod %s [%s (%d)]\n", \
__func__, #f, name, type); \
return -EINVAL; \
}
#define CHECK_PHONEOP(phoneops, f) \
if(!(phoneops)->f) { \
ERR("%s: missing phone method %s [%s (%d)]\n", __FUNCTION__, #f, name, type); \
if (!(phoneops)->f) { \
ERR("%s: missing phone method %s [%s (%d)]\n", \
__func__, #f, name, type); \
return -EINVAL; \
}
int xproto_register(const xproto_table_t *proto_table)
{
int type;
const char *name;
const struct xops *xops;
const struct phoneops *phoneops;
int type;
const char *name;
const struct xops *xops;
const struct phoneops *phoneops;
BUG_ON(!proto_table);
type = proto_table->type;
name = proto_table->name;
if(type >= XPD_TYPE_NOMODULE) {
NOTICE("%s: Bad xproto type %d\n", __FUNCTION__, type);
if (type >= XPD_TYPE_NOMODULE) {
NOTICE("%s: Bad xproto type %d\n", __func__, type);
return -EINVAL;
}
DBG(GENERAL, "%s (%d)\n", name, type);
if(xprotocol_tables[type])
NOTICE("%s: overriding registration of %s (%d)\n", __FUNCTION__, name, type);
if (xprotocol_tables[type])
NOTICE("%s: overriding registration of %s (%d)\n", __func__,
name, type);
xops = proto_table->xops;
CHECK_XOP(xops, card_new);
CHECK_XOP(xops, card_init);
@@ -460,38 +500,30 @@ int xproto_register(const xproto_table_t *proto_table)
CHECK_PHONEOP(phoneops, card_dahdi_preregistration);
CHECK_PHONEOP(phoneops, card_dahdi_postregistration);
/* optional method -- call after testing: */
/*CHECK_PHONEOP(phoneops, card_ioctl);*/
/*CHECK_PHONEOP(phoneops, card_ioctl); */
}
xprotocol_tables[type] = proto_table;
return 0;
}
EXPORT_SYMBOL(xproto_register);
void xproto_unregister(const xproto_table_t *proto_table)
{
int type;
const char *name;
int type;
const char *name;
BUG_ON(!proto_table);
type = proto_table->type;
name = proto_table->name;
DBG(GENERAL, "%s (%d)\n", name, type);
if(type >= XPD_TYPE_NOMODULE) {
NOTICE("%s: Bad xproto type %s (%d)\n", __FUNCTION__, name, type);
if (type >= XPD_TYPE_NOMODULE) {
NOTICE("%s: Bad xproto type %s (%d)\n", __func__, name, type);
return;
}
if(!xprotocol_tables[type])
NOTICE("%s: xproto type %s (%d) is already unregistered\n", __FUNCTION__, name, type);
if (!xprotocol_tables[type])
NOTICE("%s: xproto type %s (%d) is already unregistered\n",
__func__, name, type);
xprotocol_tables[type] = NULL;
}
EXPORT_SYMBOL(dump_packet);
EXPORT_SYMBOL(dump_reg_cmd);
EXPORT_SYMBOL(xframe_receive);
EXPORT_SYMBOL(notify_bad_xpd);
EXPORT_SYMBOL(valid_xpd_addr);
EXPORT_SYMBOL(xproto_global_entry);
EXPORT_SYMBOL(xproto_card_entry);
EXPORT_SYMBOL(xproto_name);
EXPORT_SYMBOL(xproto_register);
EXPORT_SYMBOL(xproto_unregister);

View File

@@ -35,25 +35,25 @@
#define XPP_PROTOCOL_VERSION 30
struct xpd_addr {
uint8_t subunit:SUBUNIT_BITS;
uint8_t reserved:1;
uint8_t unit:UNIT_BITS;
uint8_t sync_master:1;
uint8_t subunit:SUBUNIT_BITS;
uint8_t reserved:1;
uint8_t unit:UNIT_BITS;
uint8_t sync_master:1;
} PACKED;
#define MKADDR(p, u, s) do { \
(p)->unit = (u); \
(p)->subunit = (s); \
(p)->sync_master = 0; \
} while(0)
} while (0)
struct xpacket_header {
uint16_t packet_len:10;
uint16_t reserved:1;
uint16_t is_pcm:1;
uint16_t pcmslot:4;
uint8_t opcode;
struct xpd_addr addr;
uint16_t packet_len:10;
uint16_t reserved:1;
uint16_t is_pcm:1;
uint16_t pcmslot:4;
uint8_t opcode;
struct xpd_addr addr;
} PACKED;
#define XPACKET_OP(p) ((p)->head.opcode)
@@ -71,8 +71,8 @@ struct xpacket_header {
/*
* The LSB of the type number signifies:
* 0 - TO_PSTN
* 1 - TO_PHONE
* 0 - TO_PSTN
* 1 - TO_PHONE
*/
#define XPD_TYPE_FXS 1 // TO_PHONE
#define XPD_TYPE_FXO 2 // TO_PSTN
@@ -81,60 +81,61 @@ struct xpacket_header {
#define XPD_TYPE_ECHO 5 // Octasic echo canceller
#define XPD_TYPE_NOMODULE 7
typedef byte xpd_type_t;
typedef __u8 xpd_type_t;
#define XPD_TYPE_PREFIX "xpd-type-"
#define MODULE_ALIAS_XPD(type) \
#define MODULE_ALIAS_XPD(type) \
MODULE_ALIAS(XPD_TYPE_PREFIX __stringify(type))
#define PCM_CHUNKSIZE (CHANNELS_PERXPD * 8) /* samples of 8 bytes */
bool valid_xpd_addr(const struct xpd_addr *addr);
#define XPROTO_NAME(card,op) card ## _ ## op
#define XPROTO_HANDLER(card,op) XPROTO_NAME(card,op ## _handler)
#define XPROTO_CALLER(card,op) XPROTO_NAME(card,op ## _send)
#define XPROTO_NAME(card, op) card ## _ ## op
#define XPROTO_HANDLER(card, op) XPROTO_NAME(card, op ## _handler)
#define XPROTO_CALLER(card, op) XPROTO_NAME(card, op ## _send)
#define HANDLER_DEF(card,op) \
static int XPROTO_HANDLER(card,op) ( \
#define HANDLER_DEF(card, op) \
static int XPROTO_HANDLER(card, op) ( \
xbus_t *xbus, \
xpd_t *xpd, \
const xproto_entry_t *cmd, \
xpacket_t *pack)
#define CALL_PROTO(card,op, ...) XPROTO_CALLER(card,op)( __VA_ARGS__ )
#define CALL_PROTO(card, op, ...) XPROTO_CALLER(card, op)(__VA_ARGS__)
#define DECLARE_CMD(card,op, ...) \
int CALL_PROTO(card, op, xbus_t *xbus, xpd_t *xpd, ## __VA_ARGS__ )
#define DECLARE_CMD(card, op, ...) \
int CALL_PROTO(card, op, xbus_t *xbus, xpd_t *xpd, ## __VA_ARGS__)
#define HOSTCMD(card, op, ...) \
DECLARE_CMD(card, op, ## __VA_ARGS__ )
#define HOSTCMD(card, op, ...) \
DECLARE_CMD(card, op, ## __VA_ARGS__)
#define RPACKET_NAME(card,op) XPROTO_NAME(RPACKET_ ## card, op)
#define RPACKET_TYPE(card,op) struct RPACKET_NAME(card, op)
#define RPACKET_NAME(card, op) XPROTO_NAME(RPACKET_ ## card, op)
#define RPACKET_TYPE(card, op) struct RPACKET_NAME(card, op)
#define DEF_RPACKET_DATA(card,op, ...) \
RPACKET_TYPE(card,op) { \
#define DEF_RPACKET_DATA(card, op, ...) \
RPACKET_TYPE(card, op) { \
struct xpacket_header head; \
__VA_ARGS__ \
} PACKED
#define RPACKET_HEADERSIZE sizeof(struct xpacket_header)
#define RPACKET_FIELD(p,card,op,field) (((RPACKET_TYPE(card,op) *)(p))->field)
#define RPACKET_SIZE(card,op) sizeof(RPACKET_TYPE(card,op))
#define RPACKET_FIELD(p, card, op, field) \
(((RPACKET_TYPE(card, op) *)(p))->field)
#define RPACKET_SIZE(card, op) sizeof(RPACKET_TYPE(card, op))
#define XENTRY(prototab,module,op) \
[ XPROTO_NAME(module,op) ] = { \
.handler = XPROTO_HANDLER(module,op), \
.datalen = RPACKET_SIZE(module,op), \
#define XENTRY(prototab, module, op) \
[ XPROTO_NAME(module, op) ] = { \
.handler = XPROTO_HANDLER(module, op), \
.datalen = RPACKET_SIZE(module, op), \
.name = #op, \
.table = &PROTO_TABLE(prototab) \
}
#define XPACKET_INIT(p, card, op, to, pcm, pcmslot) \
#define XPACKET_INIT(p, card, op, to, pcm, pcmslot) \
do { \
XPACKET_OP(p) = XPROTO_NAME(card,op); \
XPACKET_LEN(p) = RPACKET_SIZE(card,op); \
XPACKET_OP(p) = XPROTO_NAME(card, op); \
XPACKET_LEN(p) = RPACKET_SIZE(card, op); \
XPACKET_IS_PCM(p) = (pcm); \
XPACKET_PCMSLOT(p) = (pcmslot); \
XPACKET_RESERVED(p) = 0; \
@@ -142,138 +143,138 @@ bool valid_xpd_addr(const struct xpd_addr *addr);
XPACKET_ADDR_SUBUNIT(p) = XBUS_SUBUNIT(to); \
XPACKET_ADDR_SYNC(p) = 0; \
XPACKET_ADDR_RESERVED(p) = 0; \
} while(0)
} while (0)
#define XFRAME_NEW_CMD(frm, p, xbus, card, op, to) \
#define XFRAME_NEW_CMD(frm, p, xbus, card, op, to) \
do { \
int pack_len = RPACKET_SIZE(card,op); \
int pack_len = RPACKET_SIZE(card, op); \
\
if(!XBUS_FLAGS(xbus, CONNECTED)) \
if (!XBUS_FLAGS(xbus, CONNECTED)) \
return -ENODEV; \
(frm) = ALLOC_SEND_XFRAME(xbus); \
if(!(frm)) \
if (!(frm)) \
return -ENOMEM; \
(p) = xframe_next_packet(frm, pack_len); \
if(!(p)) \
if (!(p)) \
return -ENOMEM; \
XPACKET_INIT(p, card, op, to, 0, 0); \
(frm)->usec_towait = 0; \
} while(0)
} while (0)
#endif
/*--------------------------- register handling --------------------------------*/
/*----------------- register handling --------------------------------*/
#define MULTIBYTE_MAX_LEN 5 /* FPGA firmware limitation */
typedef struct reg_cmd {
byte bytes:3; /* Length (for Multibyte) */
byte eoframe:1; /* For BRI -- end of frame */
byte portnum:3; /* For port specific registers */
byte is_multibyte:1;
__u8 bytes:3; /* Length (for Multibyte) */
__u8 eoframe:1; /* For BRI -- end of frame */
__u8 portnum:3; /* For port specific registers */
__u8 is_multibyte:1;
union {
struct {
byte reserved:4;
byte do_datah:1;
byte do_subreg:1;
byte read_request:1;
byte all_ports_broadcast:1;
byte regnum;
byte subreg;
byte data_low;
byte data_high;
__u8 reserved:4;
__u8 do_datah:1;
__u8 do_subreg:1;
__u8 read_request:1;
__u8 all_ports_broadcast:1;
__u8 regnum;
__u8 subreg;
__u8 data_low;
__u8 data_high;
} PACKED r;
/* For Write-Multibyte commands in BRI */
struct {
byte xdata[MULTIBYTE_MAX_LEN];
__u8 xdata[MULTIBYTE_MAX_LEN];
} PACKED d;
} PACKED alt;
} PACKED reg_cmd_t;
/* Shortcut access macros */
#define REG_FIELD(regptr,member) ((regptr)->alt.r.member)
#define REG_FIELD(regptr, member) ((regptr)->alt.r.member)
#define REG_XDATA(regptr) ((regptr)->alt.d.xdata)
#ifdef __KERNEL__
/*--------------------------- protocol tables ----------------------------------*/
/*----------------- protocol tables ----------------------------------*/
typedef struct xproto_entry xproto_entry_t;
typedef struct xproto_table xproto_table_t;
typedef struct xproto_entry xproto_entry_t;
typedef struct xproto_table xproto_table_t;
typedef int (*xproto_handler_t)(
xbus_t *xbus,
xpd_t *xpd,
const xproto_entry_t *cmd,
xpacket_t *pack);
typedef int (*xproto_handler_t) (xbus_t *xbus, xpd_t *xpd,
const xproto_entry_t *cmd, xpacket_t *pack);
const xproto_table_t *xproto_get(xpd_type_t cardtype);
void xproto_put(const xproto_table_t *xtable);
const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, byte opcode);
xproto_handler_t xproto_card_handler(const xproto_table_t *table, byte opcode);
const xproto_entry_t *xproto_card_entry(const xproto_table_t *table,
__u8 opcode);
xproto_handler_t xproto_card_handler(const xproto_table_t *table,
__u8 opcode);
const xproto_entry_t *xproto_global_entry(byte opcode);
xproto_handler_t xproto_global_handler(byte opcode);
const xproto_entry_t *xproto_global_entry(__u8 opcode);
xproto_handler_t xproto_global_handler(__u8 opcode);
/*
* XMETHOD() resolve to method pointer (NULL for optional methods)
* CALL_XMETHOD() calls the method, passing mandatory arguments
*/
#define XMETHOD(name, xpd) ((xpd)->xops->name)
#define CALL_XMETHOD(name, xpd, ...) \
(XMETHOD(name, (xpd))((xpd)->xbus, (xpd), ## __VA_ARGS__ ))
#define CALL_XMETHOD(name, xpd, ...) \
(XMETHOD(name, (xpd))((xpd)->xbus, (xpd), ## __VA_ARGS__))
/*
* PHONE_METHOD() resolve to method pointer (NULL for optional methods)
* CALL_PHONE_METHOD() calls the method, passing mandatory arguments
*/
#define PHONE_METHOD(name, xpd) (PHONEDEV(xpd).phoneops->name)
#define CALL_PHONE_METHOD(name, xpd, ...) \
(PHONE_METHOD(name, (xpd))((xpd), ## __VA_ARGS__ ))
#define CALL_PHONE_METHOD(name, xpd, ...) \
(PHONE_METHOD(name, (xpd))((xpd), ## __VA_ARGS__))
struct phoneops {
void (*card_pcm_recompute)(xpd_t *xpd, xpp_line_t pcm_mask);
void (*card_pcm_fromspan)(xpd_t *xpd, xpacket_t *pack);
void (*card_pcm_tospan)(xpd_t *xpd, xpacket_t *pack);
int (*echocancel_timeslot)(xpd_t *xpd, int pos);
int (*echocancel_setmask)(xpd_t *xpd, xpp_line_t ec_mask);
int (*card_timing_priority)(xpd_t *xpd);
int (*card_dahdi_preregistration)(xpd_t *xpd, bool on);
int (*card_dahdi_postregistration)(xpd_t *xpd, bool on);
int (*card_hooksig)(xpd_t *xpd, int pos, enum dahdi_txsig txsig);
int (*card_ioctl)(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg);
int (*card_open)(xpd_t *xpd, lineno_t pos);
int (*card_close)(xpd_t *xpd, lineno_t pos);
int (*card_state)(xpd_t *xpd, bool on);
void (*card_pcm_recompute) (xpd_t *xpd, xpp_line_t pcm_mask);
void (*card_pcm_fromspan) (xpd_t *xpd, xpacket_t *pack);
void (*card_pcm_tospan) (xpd_t *xpd, xpacket_t *pack);
int (*echocancel_timeslot) (xpd_t *xpd, int pos);
int (*echocancel_setmask) (xpd_t *xpd, xpp_line_t ec_mask);
int (*card_timing_priority) (xpd_t *xpd);
int (*card_dahdi_preregistration) (xpd_t *xpd, bool on);
int (*card_dahdi_postregistration) (xpd_t *xpd, bool on);
int (*card_hooksig) (xpd_t *xpd, int pos, enum dahdi_txsig txsig);
int (*card_ioctl) (xpd_t *xpd, int pos, unsigned int cmd,
unsigned long arg);
int (*card_open) (xpd_t *xpd, lineno_t pos);
int (*card_close) (xpd_t *xpd, lineno_t pos);
int (*card_state) (xpd_t *xpd, bool on);
};
struct xops {
xpd_t *(*card_new)(xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, byte subtype,
int subunits, int subunit_ports, bool to_phone);
int (*card_init)(xbus_t *xbus, xpd_t *xpd);
int (*card_remove)(xbus_t *xbus, xpd_t *xpd);
int (*card_tick)(xbus_t *xbus, xpd_t *xpd);
int (*card_register_reply)(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *reg);
xpd_t *(*card_new) (xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone);
int (*card_init) (xbus_t *xbus, xpd_t *xpd);
int (*card_remove) (xbus_t *xbus, xpd_t *xpd);
int (*card_tick) (xbus_t *xbus, xpd_t *xpd);
int (*card_register_reply) (xbus_t *xbus, xpd_t *xpd, reg_cmd_t *reg);
};
struct xproto_entry {
xproto_handler_t handler;
int datalen;
const char *name;
xproto_table_t *table;
xproto_handler_t handler;
int datalen;
const char *name;
xproto_table_t *table;
};
struct xproto_table {
struct module *owner;
xproto_entry_t entries[256]; /* Indexed by opcode */
const struct xops *xops; /* Card level operations */
const struct phoneops *phoneops; /* DAHDI operations */
const struct echoops *echoops; /* Echo Canceller operations */
xpd_type_t type;
byte ports_per_subunit;
const char *name;
bool (*packet_is_valid)(xpacket_t *pack);
void (*packet_dump)(const char *msg, xpacket_t *pack);
struct module *owner;
xproto_entry_t entries[256]; /* Indexed by opcode */
const struct xops *xops; /* Card level operations */
const struct phoneops *phoneops; /* DAHDI operations */
const struct echoops *echoops; /* Echo Canceller operations */
xpd_type_t type;
__u8 ports_per_subunit;
const char *name;
bool (*packet_is_valid) (xpacket_t *pack);
void (*packet_dump) (const char *msg, xpacket_t *pack);
};
#include "card_global.h"
@@ -282,11 +283,10 @@ struct xproto_table {
#include "card_bri.h"
#include "card_pri.h"
#define MEMBER(card,op) RPACKET_TYPE(card,op) RPACKET_NAME(card,op)
#define MEMBER(card, op) RPACKET_TYPE(card, op) RPACKET_NAME(card, op)
struct xpacket {
struct xpacket_header head;
struct xpacket_header head;
union {
MEMBER(GLOBAL, NULL_REPLY);
MEMBER(GLOBAL, PCM_WRITE);
@@ -297,20 +297,22 @@ struct xpacket {
MEMBER(FXS, SIG_CHANGED);
MEMBER(FXO, SIG_CHANGED);
byte data[0];
__u8 data[0];
};
/* Last byte is chksum */
} PACKED;
void dump_packet(const char *msg, const xpacket_t *packet, bool debug);
void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus, byte unit, xportno_t port, const reg_cmd_t *regcmd);
void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
__u8 unit, xportno_t port, const reg_cmd_t *regcmd);
int xframe_receive(xbus_t *xbus, xframe_t *xframe);
void notify_bad_xpd(const char *funcname, xbus_t *xbus, const struct xpd_addr addr, const char *msg);
void notify_bad_xpd(const char *funcname, xbus_t *xbus,
const struct xpd_addr addr, const char *msg);
int xproto_register(const xproto_table_t *proto_table);
void xproto_unregister(const xproto_table_t *proto_table);
const xproto_entry_t *xproto_global_entry(byte opcode);
const xproto_entry_t *xproto_global_entry(__u8 opcode);
const char *xproto_name(xpd_type_t xpd_type);
#endif /* __KERNEL__ */
#endif /* __KERNEL__ */
#endif /* XPROTO_H */
#endif /* XPROTO_H */

View File

@@ -21,9 +21,6 @@
#ifdef __KERNEL__
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
#include <linux/config.h>
#endif
#endif
/* DAHDI compile time options */
@@ -76,10 +73,8 @@
/* You can still override them below */
#if defined(CONFIG_HDLC) || defined(CONFIG_HDLC_MODULE)
#define DAHDI_HDLC_TYPE_TRANS
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3)
#define HDLC_MAINTAINERS_ARE_MORE_STUPID_THAN_I_THOUGHT
#endif
#endif
/*
* Uncomment CONFIG_DAHDI_NET to enable SyncPPP, CiscoHDLC, and Frame Relay
@@ -195,4 +190,10 @@
*/
/* #define CONFIG_DAHDI_MIRROR */
/*
* Adds support for conference links. There are some non-Asterisk users of this
* functionality.
*/
/* #define CONFIG_DAHDI_CONFLINK */
#endif

View File

@@ -6,7 +6,7 @@
* written by Jim Dixon <jim@lambdatel.com>.
*
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
* Copyright (C) 2001 - 2010 Digium, Inc.
* Copyright (C) 2001 - 2012 Digium, Inc.
*
* All rights reserved.
*
@@ -38,11 +38,9 @@
#include <dahdi/dahdi_config.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
#include <linux/config.h>
#endif
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/ioctl.h>
@@ -60,11 +58,7 @@
#include <linux/poll.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
#define dahdi_pci_module pci_register_driver
#else
#define dahdi_pci_module pci_module_init
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
#define DAHDI_IRQ_HANDLER(a) static irqreturn_t a(int irq, void *dev_id)
@@ -72,37 +66,47 @@
#define DAHDI_IRQ_HANDLER(a) static irqreturn_t a(int irq, void *dev_id, struct pt_regs *regs)
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
#ifdef CONFIG_PCI
#include <linux/pci-aspm.h>
#endif
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
#define HAVE_NET_DEVICE_OPS
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
#define DAHDI_IRQ_SHARED IRQF_SHARED
#define DAHDI_IRQ_DISABLED IRQF_DISABLED
#define DAHDI_IRQ_SHARED_DISABLED IRQF_SHARED | IRQF_DISABLED
#else
#define DAHDI_IRQ_SHARED SA_SHIRQ
#define DAHDI_IRQ_DISABLED SA_INTERRUPT
#define DAHDI_IRQ_SHARED_DISABLED SA_SHIRQ | SA_INTERRUPT
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)
#ifndef dev_notice
#define dev_notice(dev, format, arg...) \
dev_printk(KERN_NOTICE , dev , format , ## arg)
#endif
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
# ifdef RHEL_RELEASE_VERSION
# if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5, 6)
#define dev_name(dev) ((dev)->bus_id)
#define dev_set_name(dev, format, ...) \
snprintf((dev)->bus_id, BUS_ID_SIZE, format, ## __VA_ARGS__)
# else
#define dev_set_name(dev, format, ...) \
do { \
kobject_set_name(&(dev)->kobj, format, ## __VA_ARGS__); \
snprintf((dev)->bus_id, BUS_ID_SIZE, \
kobject_name(&(dev)->kobj)); \
} while (0)
# endif
# else
#define dev_name(dev) ((dev)->bus_id)
# endif
#define dev_set_name(dev, format, ...) \
snprintf((dev)->bus_id, BUS_ID_SIZE, format, ## __VA_ARGS__);
snprintf((dev)->bus_id, BUS_ID_SIZE, format, ## __VA_ARGS__)
# endif
#endif
/* __dev* were removed in 3.8. They still have effect in 2.6.18. */
#ifndef __devinit
# define __devinit
# define __devinitdata
# define __devexit
# define __devexit_p(x) x
#endif
/*! Default chunk size for conferences and such -- static right now, might make
@@ -112,7 +116,7 @@
#define DAHDI_MIN_CHUNKSIZE DAHDI_CHUNKSIZE
#define DAHDI_DEFAULT_CHUNKSIZE DAHDI_CHUNKSIZE
#define DAHDI_MAX_CHUNKSIZE DAHDI_CHUNKSIZE
#define DAHDI_CB_SIZE 2
#define DAHDI_CB_SIZE (1 << 3)
/* DAHDI operates at 8Khz by default */
#define DAHDI_MS_TO_SAMPLES(ms) ((ms) * 8)
@@ -496,10 +500,7 @@ struct dahdi_chan {
int numbufs; /*!< How many buffers in channel */
int txbufpolicy; /*!< Buffer policy */
int rxbufpolicy; /*!< Buffer policy */
int txdisable; /*!< Disable transmitter */
int rxdisable; /*!< Disable receiver */
/* Tone zone stuff */
struct dahdi_zone *curzone; /*!< Zone for selecting tones */
@@ -544,7 +545,6 @@ struct dahdi_chan {
short getlin[DAHDI_MAX_CHUNKSIZE]; /*!< Last transmitted samples */
unsigned char getraw[DAHDI_MAX_CHUNKSIZE]; /*!< Last received raw data */
short getlin_lastchunk[DAHDI_MAX_CHUNKSIZE]; /*!< Last transmitted samples from last chunk */
short putlin[DAHDI_MAX_CHUNKSIZE]; /*!< Last received samples */
unsigned char putraw[DAHDI_MAX_CHUNKSIZE]; /*!< Last received raw data */
short conflast[DAHDI_MAX_CHUNKSIZE]; /*!< Last conference sample -- base part of channel */
@@ -614,6 +614,8 @@ struct dahdi_chan {
#else
unsigned char *lin2x;
#endif
struct device chan_device; /*!< Kernel object for this chan */
#define dev_to_chan(dev) container_of(dev, struct dahdi_chan, chan_device)
};
#ifdef CONFIG_DAHDI_NET
@@ -747,15 +749,16 @@ static inline int dahdi_have_netdev(const struct dahdi_chan *chan) { return 0; }
#endif
struct dahdi_count {
__u32 fe; /*!< Framing error counter */
__u32 cv; /*!< Coding violations counter */
__u32 bpv; /*!< Bipolar Violation counter */
__u32 crc4; /*!< CRC4 error counter */
__u32 ebit; /*!< current E-bit error count */
__u32 fas; /*!< current FAS error count */
__u32 be; /*!< current bit error count */
__u32 prbs; /*!< current PRBS detected pattern */
__u32 errsec; /*!< errored seconds */
u32 fe; /*!< Framing error counter */
u32 cv; /*!< Coding violations counter */
u32 bpv; /*!< Bipolar Violation counter */
u32 crc4; /*!< CRC4 error counter */
u32 ebit; /*!< current E-bit error count */
u32 fas; /*!< current FAS error count */
u32 be; /*!< current bit error count */
u32 prbs; /*!< current PRBS detected pattern */
u32 errsec; /*!< errored seconds */
u32 timingslips; /*!< Clock slips */
};
/* map flagbits to flag masks */
@@ -797,6 +800,23 @@ struct dahdi_count {
#define DAHDI_FLAG_TXUNDERRUN DAHDI_FLAG(TXUNDERRUN)
#define DAHDI_FLAG_RXOVERRUN DAHDI_FLAG(RXOVERRUN)
enum spantypes {
SPANTYPE_INVALID = 0,
SPANTYPE_ANALOG_FXS,
SPANTYPE_ANALOG_FXO,
SPANTYPE_ANALOG_MIXED,
SPANTYPE_DIGITAL_E1,
SPANTYPE_DIGITAL_T1,
SPANTYPE_DIGITAL_J1,
SPANTYPE_DIGITAL_BRI_NT,
SPANTYPE_DIGITAL_BRI_TE,
SPANTYPE_DIGITAL_BRI_SOFT,
};
const char *dahdi_spantype2str(enum spantypes st);
enum spantypes dahdi_str2spantype(const char *name);
const char *dahdi_lineconfig_bit_name(int lineconfig_bit);
ssize_t lineconfig_str(int lineconfig, char buf[], size_t size);
struct file;
struct dahdi_span_ops {
@@ -895,7 +915,7 @@ struct dahdi_span_ops {
/*! Called when the spantype / linemode is changed before the span is
* assigned a number. */
int (*set_spantype)(struct dahdi_span *span, const char *spantype);
int (*set_spantype)(struct dahdi_span *span, enum spantypes st);
};
/**
@@ -926,7 +946,7 @@ struct dahdi_span {
spinlock_t lock;
char name[40]; /*!< Span name */
char desc[80]; /*!< Span description */
const char *spantype; /*!< span type in text form */
enum spantypes spantype; /*!< span type */
int deflaw; /*!< Default law (DAHDI_MULAW or DAHDI_ALAW) */
int alarms; /*!< Pending alarms on span */
unsigned long flags;
@@ -944,8 +964,6 @@ struct dahdi_span {
int maintstat; /*!< Maintenance state */
int mainttimer; /*!< Maintenance timer */
int timingslips; /*!< Clock slips */
struct dahdi_chan **chans; /*!< Member channel structures */
const struct dahdi_span_ops *ops; /*!< span callbacks. */
@@ -1101,6 +1119,9 @@ struct dahdi_dynamic_driver {
struct list_head list;
struct module *owner;
/*! Numberic id of next device created by this driver. */
unsigned int id;
};
/*! \brief Receive a dynamic span message */
@@ -1216,6 +1237,12 @@ void dahdi_init_tone_state(struct dahdi_tone_state *ts, struct dahdi_tone *zt);
/*! \brief Get a given MF tone struct, suitable for dahdi_tone_nextsample. */
struct dahdi_tone *dahdi_mf_tone(const struct dahdi_chan *chan, char digit, int digitmode);
/*! \brief Convert signalling bits to human readable string */
const char *sigstr(int sig);
/*! \brief Convert alarm bits to human readable string */
int fill_alarm_string(char *buf, int count, int alarms);
/* Echo cancel a receive and transmit chunk for a given channel. This
should be called by the low-level driver as close to the interface
as possible. ECHO CANCELLATION IS NO LONGER AUTOMATICALLY DONE
@@ -1262,8 +1289,13 @@ extern u_char __dahdi_lin2mu[16384];
extern u_char __dahdi_lin2a[16384];
#endif
struct dahdi_dynamic_ops {
struct module *owner;
int (*ioctl)(unsigned int cmd, unsigned long data);
};
/*! \brief Used by dynamic DAHDI -- don't use directly */
void dahdi_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data));
void dahdi_set_dynamic_ops(const struct dahdi_dynamic_ops *ops);
/*! \brief Used by DAHDI HPEC module -- don't use directly */
void dahdi_set_hpec_ioctl(int (*func)(unsigned int cmd, unsigned long data));
@@ -1369,9 +1401,33 @@ static inline short dahdi_txtone_nextsample(struct dahdi_chan *ss)
/*! Maximum audio mask */
#define DAHDI_FORMAT_AUDIO_MASK ((1 << 16) - 1)
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
static inline void *PDE_DATA(const struct inode *inode)
{
return PDE(inode)->data;
}
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
#define KERN_CONT ""
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
static inline struct proc_dir_entry *proc_create_data(const char *name,
mode_t mode,
struct proc_dir_entry *parent,
const struct file_operations *proc_fops,
void *data)
{
struct proc_dir_entry *pde = create_proc_entry(name, mode, parent);
if (!pde)
return NULL;
pde->proc_fops = proc_fops;
pde->data = data;
return pde;
}
#endif /* CONFIG_PROC_FS */
#ifndef clamp
#define clamp(x, low, high) min(max(low, x), high)
#endif
@@ -1382,6 +1438,16 @@ static inline short dahdi_txtone_nextsample(struct dahdi_chan *ss)
#define fatal_signal_pending(p) \
(signal_pending((p)) && sigismember(&(p)->pending.signal, SIGKILL))
#ifdef CONFIG_PCI
#ifndef PCIE_LINK_STATE_L0S
#define PCIE_LINK_STATE_L0S 1
#define PCIE_LINK_STATE_L1 2
#define PCIE_LINK_STATE_CLKPM 4
#endif
#define pci_disable_link_state dahdi_pci_disable_link_state
void dahdi_pci_disable_link_state(struct pci_dev *pdev, int state);
#endif /* CONFIG_PCI */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
#ifndef __packed
@@ -1409,68 +1475,12 @@ static inline int strcasecmp(const char *s1, const char *s2)
return c1 - c2;
}
#endif /* clamp_val */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
static inline void list_replace(struct list_head *old, struct list_head *new)
{
new->next = old->next;
new->next->prev = new;
new->prev = old->prev;
new->prev->next = new;
}
#ifndef WARN_ON_ONCE
#define WARN_ON_ONCE(__condition) do { \
static int __once = 1; \
if (unlikely(__condition)) { \
if (__once) { \
__once = 0; \
WARN_ON(0); \
} \
} \
} while (0)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17)
#ifndef POLLRDHUP
#define POLLRDHUP 0
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
#define kzalloc(a, b) kcalloc(1, a, b)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12)
#define synchronize_rcu() synchronize_kernel()
#define kasprintf dahdi_kasprintf
char *dahdi_kasprintf(gfp_t gfp, const char *fmt, ...);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)
#if !defined(HAVE_WAIT_FOR_COMPLETION_TIMEOUT)
static inline unsigned long
wait_for_completion_interruptible_timeout(struct completion *x,
unsigned long timeout)
{
/* There is a race condition here. If x->done is reset to 0
* before the call to wait_for_completion after this thread wakes.
*/
timeout = wait_event_interruptible_timeout(x->wait, x->done, timeout);
if (timeout)
wait_for_completion(x);
return timeout;
}
#endif
typedef u32 __bitwise pm_message_t;
#endif /* 2.6.11 */
#endif /* 2.6.12 */
#endif /* 2.6.14 */
#endif /* 2.6.17 */
#endif /* 2.6.18 */
#endif /* 2.6.22 */
#endif /* 2.6.25 */
#endif /* 2.6.26 */
#endif /* 2.6.31 */
#ifndef CONFIG_TRACING
#define trace_printk printk
#endif
#endif /* 3.10.0 */
#ifndef DEFINE_SPINLOCK
#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
@@ -1516,6 +1526,10 @@ struct mutex {
#define DAHDI_PSEUDO 255
/* prink-wrapper macros */
#define module_printk(level, fmt, args...) \
printk(level "%s: " fmt, THIS_MODULE->name, ## args)
#define DAHDI_PRINTK(level, category, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: " fmt, #level, category, \
THIS_MODULE->name, ## __VA_ARGS__)
@@ -1523,7 +1537,7 @@ struct mutex {
printk(KERN_ ## level "%s%s-%s: span-%d: " fmt, #level, \
category, THIS_MODULE->name, (span)->spanno, ## __VA_ARGS__)
#define chan_printk(level, category, chan, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: %d: " fmt, #level, \
printk(KERN_ ## level "%s%s-%s: chan-%d: " fmt, #level, \
category, THIS_MODULE->name, (chan)->channo, ## __VA_ARGS__)
#define dahdi_err(fmt, ...) DAHDI_PRINTK(ERR, "", fmt, ## __VA_ARGS__)
#define span_info(span, fmt, ...) span_printk(INFO, "", span, fmt, \

View File

@@ -636,6 +636,11 @@ struct dahdi_confinfo {
#define DAHDI_SETCONF_V1 _IOW(DAHDI_CODE, 12, struct dahdi_confinfo)
#define DAHDI_SETCONF _IOWR(DAHDI_CODE, 13, struct dahdi_confinfo)
/*
* Setup or Remove Conference Link
*/
#define DAHDI_CONFLINK _IOW(DAHDI_CODE, 14, struct dahdi_confinfo)
/*
* Display Conference Diagnostic Information on Console
*/