Version 12.1 released. Made it apply cleanly on bristuff-0.3.0-PRE-1y-l, merging new Makefile and kernel deprecation fixes from upstream. Also fixing bug in the debug output on 64 bit architectures, thanks for the patch to Jan Engelhardt.
Version 13 released. Just made it apply cleanly on bristuff-0.4.0-test1, no functional changes whatsoever.
Version 9.2 released. Made it apply cleanly on bristuff-0.2.0-RC8r. The module options being accessible via sysfs has been merged from upstream in this branch, too, now, otherwise there are no functional changes.
Version 12 released. Made it apply cleanly on bristuff-0.3.0-PRE-1o. The module options being accessible via sysfs has been merged from upstream, otherwise there are no functional changes.
Versions 9.1 and 11 released. Just made it apply cleanly on bristuff-0.2.0-RC8q and bristuff-0.3.0-PRE-1f, respectively—no functional changes whatsoever.
Version 10 released. Just made it apply cleanly on bristuff-0.3.0-PRE-1, no functional changes whatsoever.
Version 9 released. Just made it apply cleanly on bristuff-0.2.0-RC8o, no functional changes whatsoever. Please note that a new version with some major changes is being worked on that also will contain fixes for some issues some of you have reported for the last version—those reports have not been ignored!
Version 8 released. Just made it apply cleanly on bristuff-0.2.0-RC8j, no functional changes whatsoever.
Version 7 released. Mostly made it apply cleanly on bristuff-0.2.0-RC8h. Additionally, there is a new and undocumented parameter "jitterbuffer" which probably soon will be changed again and which when left unspecified doesn't change the driver's behaviour with regard to earlier versions, so I'd suggest you simply ignore it until further notice.
Version 6 released. Just made it apply cleanly on bristuff-0.2.0-RC8a, no functional changes whatsoever.
Version 5 released. Just made it apply cleanly on bristuff-0.2.0-RC8, no functional changes whatsoever.
Version 4 released. No big changes, just added code to drop d channel frames with bad CRC and optimized b channel handling a little bit.
Version 3 released. This version is based on bristuff-0.2.0-RC7j. The d channel handling has been completely replaced, too, now—I hope that this will make some remaining d channel problems vanish. At least a theoretical problem of the original driver that could cause frames to accumulate in the d channel FIFO is fixed by the patch. Also, a problem introduced by former versions of this patch that could cause the driver to crash upon unloading when the timer_card was not the last card detected by the driver should be fixed now. Thanks for the bug report and for testing the patch to Lars von Wedel. Also many thanks for testing the patch to Deti Fliegl, Kilian Krause, and Wolfgang Liegel.
Note that the patch removes all the RTAI code that was added to the original driver in bristuff version 0.2.0-RC7h! The only benefit of the RTAI stuff when compared to the patch as-is is lower CPU usage (I don't know how much, but the driver with this patch version causes less than 1 % CPU load on a Pentium 3 with 500 MHz, so it probably doesn't matter anyway) while it at the same time introduces possible buffer under- and overruns (because it's clocked by the RTC rather than the card's clock) and makes using the driver more complicated as you have to install RTAI first. So, you don't need RTAI in order to use the patched driver—any 2.4 or 2.6 series kernel should do!
Version 2 released. This version applies cleanly on bristuff-0.2.0-RC5. Additionally, it includes a patch for cleanly disabling interrupts upon unloading. The way it is done in the original driver is somewhat of a dirty hack that might go wrong on SMP systems. Thanks to Deti Fliegl for pointing out the original problem (which is now partially fixed in bristuff-0.2.0-RC5) and testing the patch.
Here you find a patch for kapejod's zaphfc driver from the bristuff package. The patch improves the driver in three ways (actually, meanwhile, it contains a few more improvements—but those explained below are still the most important ones):
It adds support for the slave mode of the HFC chip, thus allowing the frame clock of one card to sync to that of an other.
It changes the driver to (mostly) use only one interrupt, no matter how many cards there are in the system, thereby greatly reducing the cpu load caused by the driver when handling more than one card (I call this feature "interrupt bundling" in the following).
It makes the b channel handling (and thus the whole driver) much more tolerant to lost interrupts.
Please be aware that the latter two basically are addressed by bristuff versions 0.2.0-RC7h and later, too—in a way that introduces new problems, though. See below for what these problems are like. In the following, I will describe each of the three improvements in some more detail. The sections on "interrupt bundling" and "interrupt loss tolerant b channel handling" are somewhat outdated with regard to bristuff 0.2.0-RC7h and later—the behaviour of the patched driver is unchanged, though. Again, see below for the description of the changes introduced by bristuff 0.2.0-RC7h.
Before I describe in detail how it works and how to make use of it, I will try to explain what the "slave mode" is good for, so you can decide whether you need to understand the rest of it.
Every HFC-S PCI A card has a 12.288 MHz crystal on it from which, amongst other things, the 8 kHz frame clock is derived. This is the clock which clocks the sending out of frames on the ISDN interface as well as the generation of the interrupt which is used by the zaphfc driver for zaptel timing. Now when you have two cards in an asterisk box, each clocked by an independent crystal, the slight difference in the two crystals' frequency over time will cause the data buffers in between them (that is, the cards' FIFOs, the driver's buffers, and, probably the biggest chunk, asterisk's jitter buffer) to shrink or to grow and thus to finally run empty or to overrun, respectively, depending on whether transmission goes from the slower to the faster card or the other way around. Either way, the transmission is disturbed, be it by dropped data or by insertion of invented data. On voice connections you will hear a little crackling when that happens, which usually won't hurt. Fax machines and modems, though, generally don't like jumps in the time domain (which kindof is what is happening), so if you want to use multiple HFC-S PCI A cards for switching modem or fax connections through them reliably, this might be a problem. A problem which can be solved, though, using this patch and a soldering iron. If you think this doesn't apply to you, you might want to skip the following section. Also, you don't have to worry if all your lines are PSTN connections: Only HFC-S PCI A cards in NT mode can be used in slave mode. Cards in TE mode always synchronize to the clock of the connected ISDN line—and any number of PSTN ISDN lines should be in sync anyway, causing any cards in TE mode connected to them to be in sync, too.
When you look at the datasheet of cologne chip's HFC-S PCI A, you will find that it has a so-called "PCM bus interface" (or "GCI/IOM2 bus interface" as it is called in the datasheet). This is basically a serial synchronous bus that can be used for directly transferring b channel data between components connected to the bus without any cpu involved. One of the side effects of its functioning as a synchronous bus is that the frame clock of all connected devices runs completely synchronously—which is exactly what we need. This is achieved by having one master on the bus that drives the clock lines (there are two clock lines, called C4 and F0, see below in the pinout diagram) with its own local clock and a number of slaves that synchronize their local clock to these clock lines by the means of a PLL. The patch just makes use of this capability of the chip to synchronize its own frame clock to an external source (usually another chip of the same kind)—no data is transferred over the PCM bus, though; it's only the clock lines that are used for syncing!
Now, if you want to make use of this capability, apart from applying the
patch, you have to do some soldering. Below you see the pinout diagram
of the chip as it can be found on page eight of
the chip's
datasheet. You have to connect the pins #55, #54 and #52 of all
slaves and the master in parallel. Usually, you will use one of the
cards running in TE mode and connected to the PSTN as the master and connect all
the cards running in NT mode to it as slaves, so that the PSTN clock is
propagated to the NT side of your asterisk box. I successfully used
0.1 mm diameter magnet wire for connecting the chip's pins
to a connector glued to the card that allows the cards to be connected
easily using a short piece of ribbon cable with matching connectors.
Anyway, never forget that whatever you do, you do it at your own
risk! If you don't have any soldering experience,
you might easily damage the card and maybe even more!
The original driver activates the 8 kHz timing interrupt of every card that is found in the system, causing quite some cpu load if there is more than one card. The patched version only uses the timing interrupt of one card, no matter how many cards there are in the system, thus greatly reducing the idle cpu load if there are several cards in the system. The interrupt loss tolerant b channel handling described below should make this work reliably even when cards are not running synchronously. I haven't tried this myself, but theoretically, there should be no problem.
The original zaphfc driver has serious problems with interrupt sharing and with any concurrent load on the system in general. When using the original driver, each card in the system generates 8000 interrupts per second at least. Whenever one interrupt is not serviced by the driver before the next one occurs, one interrupt will be lost—and that happens easily, especially when you have more than one card, a not-so-new computer, some more things for the computer to do, or some combination of it. Except that the patch makes only one card generate the 8000 interrupts per second and thereby already greatly reduces the problems with several cards in one computer (see above), interrupts, of course, still can get lost. What really makes the difference here is how this is handled by the driver. With the original driver, lost interrupts "accumulate": If only a single interrupt is lost every five minutes, after one hour the send FIFO is shrunk by 12 frames and the receive FIFO is grown by 12 frames, sooner or later causing over- and underruns. The patched driver uses the card's hardware counters to re-synchronize in such a case, so that a problem only can occur if more than eight interrupts are lost in series, which normally should not happen.
The only price you have to pay for this increased immunity against high system load, except for having to apply an additional patch, is a little higher latency: The patch increases the maximum latency of the outbound channels by 1 ms to a total of 2 ms and the maximum latency of the inbound channels by 2 ms to a total of 3 ms. I strongly doubt, though, that this will cause any problems in any case whatsoever.
Bristuff 0.2.0-RC7h introduced the use of RTAI for b channel timing purposes. This also greatly reduces the CPU IRQ load since an RTAI timer of only 1 kHz is used, instead of the card's 8 kHz clock, plus only a single such timer is used for all cards, much like this patch uses only the clock of a single card for servicing all cards in the system.
However, the way the RTAI code in the original bristuff zaphfc driver is constructed causes some problems: It potentially leads to buffer over- and underruns. RTAI is clocked by some computer-internal clock source that runs completely unsynchronized to the card's clock and that thus probably will deviate from it, depending on the clock source's manufacturing tolerance as well as its temperature and other environmental factors. Now, when this unsynchronized clock causes the card's FIFOs to be filled and emptied by the driver at the computer's side at a rate that is different from the rate at which the card's logic is filling and emptying them at the line interface side, that will cause the FIFOs to run empty and full, respectively, at times.
This problem in principle could be worked around—however, I don't see any major advantages inherent in the use of RTAI over the way the patch currently works, as CPU utilisation is pretty low with recent versions anyway. Considering that the use of RTAI also makes the installation more complicated (needs an RTAI enabled kernel as opposed to the driver patched with this patch which should work with any vanilla 2.4 or 2.6 series kernel), that's why I'll stay away from RTAI for now—this patch removes all RTAI code from the zaphfc driver!
Now, after I have explained in detail how things should work in theory, let me tell you how well things prove in reality ;-)
I'm currently using the patched driver on a Pentium 3 with 500 MHz and four HFC-S PCI A cards, one of them sharing its interrupt with the on-board 3Com NIC. Two of the cards are connected in TE mode to the PSTN, two are connected in NT mode to a legacy Auerswald PBX. One of the PSTN-side cards provides the frame clock that the cards interfacing the PBX synchronize to. The machine is running Linux kernel version 2.4.27.
Flood pinging the machine through the 100 Mb/s NIC such that ssh responsiveness is rather bad while at the same time running
for a few minutes did not cause any noticable problems. Neither were there any buffer over- or underruns reported in the system log nor was there any distortion audible on the telephone connection going on at the same time. With the original driver the connection was crackling all the time when doing this and you had quite a bit to read in the system log afterwards.
Also, idle cpu usage went down from 25 % with the original driver to 7 % with the patched version (update: version 3 is below 1 % now, though that's probably not a matter of the zaphfc driver or this patch). So, all in all, theory seems to work acceptably in practice.
As far as stability is concerned: So far, I had no crashes caused by this driver in about one week of continuous operation nor any other problems that are likely to be caused by the patch (only asterisk segfaulting in libpri and such, which happened with the original driver, too). However, this is only one test environment, so I don't know how it will behave on other computers, other kernels, with a different number of cards, …—your feedback therefore is very welcome.
Installation is simple: Install as usual, just apply the patch before compiling the zaphfc driver. Something along this line should do the trick when you are in the source directory:
$ zcat /path/to/zaphfc_0.3.0-PRE-1f_florz-11.diff.gz | patch -p1
When it comes to loading the driver, you now have a few more choices. Namely the module options sync_slave and timer_card.
sync_slave works the same way modes does: It's a bitmask in which a 1 bit means the card should be configured for slave mode while 0 means that it should be in master mode. The default is for all cards to be in master mode, which is backward compatible with the original driver. If you don't understand what this is for, just leave it unspecified.
The timer_card option specifies which of the cards in the system is to generate the 8 kHz interrupt that is used for timing. The cards are numbered starting at zero—you have to specify the number of the card, this is not a bitmask like the other options! By default, the first card is used. It's probably best to use a card which does not share interrupts with any other devices. In order to find out which card uses which interrupt, just load the driver once and have a look at the kernel log messages, then unload it and load it again with the timer_card setting of your choice.
For reliability reasons, I'd also choose a card in master mode since it does not depend on any external connections in order to be able to generate the interrupt, so in the event that a wire breaks or something, the smallest number of cards possible stops working.
In my setup described above, the driver is loaded like this:
# insmod zaphfc.o modes=12 sync_slave=12 timer_card=2
That means that the first and the second card are running in TE and master mode while the third and the fourth card are running in NT and slave mode. The third card generates the 8 kHz interrupt.
The original driver can be found in kapejod's bristuff package at http://www.junghanns.net/downloads/. In the following table, each version of the patch is listed together with the bristuff versions it has been tested with.
Except for historical interest you probably want to use the most recent version of the patch ;-)
Please note that the zaphfc driver is not changed in every release of the bristuff package, which means that the patch doesn't need to be changed either—and I won't usually release a new version when the only change would be in the version number ;-) Thus, a version of the patch that was originally created for some older version of bristuff might still be applicable to newer bristuff versions. If the patch program doesn't complain, that's usually a good sign; if you want to be sure, just do a diff between the version of zaphfc the patch was originally created for and the version you intend to patch and see whether there are any differences. If not, just go ahead. Should any differences show up, though, and there is no newer patch available yet, you should consider dropping me a line.
If you have any questions, suggestions, bug reports or whatever else you think I could be interested in, let me know: Florian Zumbiehl <florz@gmx.de>, PGP key AF260AB1. Usually, you find me as florz on IRCNet and Freenode, too.