fix start_on_cycle on firewire-core

Libraw1394 uses raw1394's convention of cycle numbers always being less
than one second, i.e., in the range 0..7999.

Firewire-core uses raw cycle numbers as used by the hardware, i.e., with
several additional bits for the seconds.  This was correctly handled
when presenting timestamps returned by the kernel to the application,
but the application's start_on_cycle value was passed directly to the
kernel.

To fix this, do the same calculations that ohci1394 did internally,
i.e., interpret the start_on_cycle value as relative to the current
seconds value of the cycle timer.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
This commit is contained in:
Clemens Ladisch 2011-02-24 17:34:10 +01:00 committed by Stefan Richter
parent 728f538340
commit 793b7639cf
1 changed files with 32 additions and 3 deletions

View File

@ -21,6 +21,34 @@
#include "fw.h" #include "fw.h"
#include "raw1394_private.h" #include "raw1394_private.h"
static int calculate_start_cycle(fw_handle_t handle)
{
int cycle;
u_int32_t cycle_timer;
u_int64_t local_time;
cycle = handle->iso.start_on_cycle;
if (cycle < 0)
return cycle;
/* libraw1394's cycle is always mod 8000 */
cycle &= 0x1fff;
/* get the seconds from the current value of the cycle timer */
if (fw_read_cycle_timer(handle, &cycle_timer, &local_time) != 0)
return cycle;
cycle += (cycle_timer & 0xfe000000) >> 12;
/*
* For compatibility with raw1394, add one second
* "to give some extra time for DMA to start".
* TODO: are there still races due to cycle rollover?
*/
cycle += 1 << 13;
return cycle & 0x7fff;
}
static int static int
queue_packet(fw_handle_t handle, queue_packet(fw_handle_t handle,
unsigned int length, unsigned int header_length, unsigned int length, unsigned int header_length,
@ -140,7 +168,7 @@ int fw_iso_xmit_start(raw1394handle_t handle, int start_on_cycle,
if (fwhandle->iso.prebuffer <= fwhandle->iso.packet_count) { if (fwhandle->iso.prebuffer <= fwhandle->iso.packet_count) {
start_iso.sync = 0; /* unused */ start_iso.sync = 0; /* unused */
start_iso.tags = 0; /* unused */ start_iso.tags = 0; /* unused */
start_iso.cycle = start_on_cycle; start_iso.cycle = calculate_start_cycle(fwhandle);
start_iso.handle = fwhandle->iso.kernel_handle; start_iso.handle = fwhandle->iso.kernel_handle;
retval = ioctl(fwhandle->iso.fd, retval = ioctl(fwhandle->iso.fd,
@ -258,7 +286,8 @@ int fw_iso_recv_start(fw_handle_t handle, int start_on_cycle,
queue_recv_packets(handle); queue_recv_packets(handle);
start_iso.cycle = start_on_cycle; handle->iso.start_on_cycle = start_on_cycle;
start_iso.cycle = calculate_start_cycle(handle);
start_iso.tags = start_iso.tags =
tag_mask == -1 ? FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS : tag_mask; tag_mask == -1 ? FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS : tag_mask;
/* sync is documented as 'not used' */ /* sync is documented as 'not used' */
@ -353,7 +382,7 @@ int fw_iso_xmit_write(raw1394handle_t handle, unsigned char *data,
fwhandle->iso.packet_count >= fwhandle->iso.prebuffer) { fwhandle->iso.packet_count >= fwhandle->iso.prebuffer) {
/* Set this to 0 to indicate that we're running. */ /* Set this to 0 to indicate that we're running. */
fwhandle->iso.prebuffer = 0; fwhandle->iso.prebuffer = 0;
start_iso.cycle = fwhandle->iso.start_on_cycle; start_iso.cycle = calculate_start_cycle(fwhandle);
start_iso.handle = fwhandle->iso.kernel_handle; start_iso.handle = fwhandle->iso.kernel_handle;
retval = ioctl(fwhandle->iso.fd, retval = ioctl(fwhandle->iso.fd,