Make raw1394_iso_xmit_write work.

This commit is contained in:
Kristian Høgsberg 2007-04-03 13:31:36 -04:00
parent d9b43daf48
commit aa70f855b3
2 changed files with 98 additions and 38 deletions

View File

@ -127,10 +127,13 @@ struct raw1394_handle {
int packet_count; int packet_count;
int buf_packets; int buf_packets;
int max_packet_size; int max_packet_size;
int packet_header_index;
int prebuffer;
int start_on_cycle;
enum raw1394_iso_dma_recv_mode recv_mode; enum raw1394_iso_dma_recv_mode recv_mode;
raw1394_iso_xmit_handler_t xmit_handler; raw1394_iso_xmit_handler_t xmit_handler;
raw1394_iso_recv_handler_t recv_handler; raw1394_iso_recv_handler_t recv_handler;
unsigned char *buffer, *head, *tail; unsigned char *buffer;
struct fw_cdev_queue_iso queue_iso; struct fw_cdev_queue_iso queue_iso;
struct fw_cdev_iso_packet *packets; struct fw_cdev_iso_packet *packets;

View File

@ -31,14 +31,14 @@
#include "juju.h" #include "juju.h"
static int static int
refill_xmit_buffer(raw1394handle_t handle, struct fw_cdev_queue_iso *queue_iso) queue_xmit_packets(raw1394handle_t handle)
{ {
int i;
struct fw_cdev_iso_packet *p = handle->iso.packets; struct fw_cdev_iso_packet *p = handle->iso.packets;
struct fw_cdev_queue_iso queue_iso;
enum raw1394_iso_disposition d; enum raw1394_iso_disposition d;
unsigned int len, dropped; unsigned int len, dropped;
unsigned char tag, sy, *data, *buffer; unsigned char tag, sy, *data, *buffer;
int cycle; int cycle, i;
buffer = handle->iso.buffer + buffer = handle->iso.buffer +
handle->iso.packet_index * handle->iso.max_packet_size; handle->iso.packet_index * handle->iso.max_packet_size;
@ -52,7 +52,8 @@ refill_xmit_buffer(raw1394handle_t handle, struct fw_cdev_queue_iso *queue_iso)
/* FIXME: handle the different dispositions. */ /* FIXME: handle the different dispositions. */
p->payload_length = len; p->payload_length = len;
p->interrupt = handle->iso.packet_phase == 0; p->interrupt =
handle->iso.packet_phase == handle->iso.irq_interval - 1;
p->skip = 0; p->skip = 0;
p->tag = tag; p->tag = tag;
p->sy = sy; p->sy = sy;
@ -63,19 +64,21 @@ refill_xmit_buffer(raw1394handle_t handle, struct fw_cdev_queue_iso *queue_iso)
handle->iso.packet_count++; handle->iso.packet_count++;
handle->iso.packet_phase++; handle->iso.packet_phase++;
if (handle->iso.packet_phase == handle->iso.irq_interval)
handle->iso.packet_phase = 0;
if (handle->iso.packet_index == handle->iso.buf_packets) { if (handle->iso.packet_index == handle->iso.buf_packets) {
handle->iso.packet_index = 0; handle->iso.packet_index = 0;
break; break;
} }
if (handle->iso.packet_phase == handle->iso.irq_interval)
handle->iso.packet_phase = 0;
} }
queue_iso->packets = ptr_to_u64(handle->iso.packets); queue_iso.packets = ptr_to_u64(handle->iso.packets);
queue_iso->size = queue_iso.size = i * sizeof handle->iso.packets[0];
handle->iso.irq_interval * sizeof handle->iso.packets[0]; queue_iso.data = ptr_to_u64(buffer);
queue_iso->data = ptr_to_u64(buffer);
len = ioctl(handle->iso.fd, FW_CDEV_IOC_QUEUE_ISO, &queue_iso);
if (len < 0)
return -1;
return 0; return 0;
} }
@ -83,20 +86,16 @@ refill_xmit_buffer(raw1394handle_t handle, struct fw_cdev_queue_iso *queue_iso)
static int static int
flush_xmit_packets(raw1394handle_t handle, int limit) flush_xmit_packets(raw1394handle_t handle, int limit)
{ {
struct fw_cdev_queue_iso queue_iso;
int len; int len;
handle->iso.packet_index -= handle->iso.irq_interval; if (handle->iso.xmit_handler == NULL)
return 0;
while (handle->iso.packet_index + handle->iso.irq_interval <= limit) { if (limit < handle->iso.irq_interval)
if (handle->iso.queue_iso.size == 0) limit = handle->iso.irq_interval;
refill_xmit_buffer(handle, &queue_iso);
len = ioctl(handle->iso.fd, FW_CDEV_IOC_QUEUE_ISO, &queue_iso); while (handle->iso.packet_count + handle->iso.irq_interval <= limit)
if (len < 0) queue_xmit_packets(handle);
return -1;
if (handle->iso.queue_iso.size > 0)
break;
}
return 0; return 0;
} }
@ -110,13 +109,19 @@ int raw1394_iso_xmit_start(raw1394handle_t handle, int start_on_cycle,
if (prebuffer_packets == -1) if (prebuffer_packets == -1)
prebuffer_packets = handle->iso.irq_interval; prebuffer_packets = handle->iso.irq_interval;
handle->iso.prebuffer = prebuffer_packets;
handle->iso.start_on_cycle = start_on_cycle;
flush_xmit_packets(handle, prebuffer_packets); flush_xmit_packets(handle, prebuffer_packets);
start_iso.cycle = start_on_cycle; if (handle->iso.prebuffer <= handle->iso.packet_count) {
start_iso.cycle = start_on_cycle;
retval = ioctl(handle->iso.fd, FW_CDEV_IOC_START_ISO, &start_iso); retval = ioctl(handle->iso.fd,
if (retval < 0) FW_CDEV_IOC_START_ISO, &start_iso);
return retval; if (retval < 0)
return retval;
}
return flush_xmit_packets(handle, handle->iso.buf_packets); return flush_xmit_packets(handle, handle->iso.buf_packets);
} }
@ -248,6 +253,7 @@ static int handle_iso_event(raw1394handle_t handle,
switch (handle->iso.type) { switch (handle->iso.type) {
case FW_CDEV_ISO_CONTEXT_TRANSMIT: case FW_CDEV_ISO_CONTEXT_TRANSMIT:
handle->iso.packet_count -= handle->iso.irq_interval;
return flush_xmit_packets(handle, handle->iso.buf_packets); return flush_xmit_packets(handle, handle->iso.buf_packets);
case FW_CDEV_ISO_CONTEXT_RECEIVE: case FW_CDEV_ISO_CONTEXT_RECEIVE:
return flush_recv_packets(handle, interrupt); return flush_recv_packets(handle, interrupt);
@ -261,25 +267,76 @@ int raw1394_iso_xmit_write(raw1394handle_t handle, unsigned char *data,
unsigned int len, unsigned char tag, unsigned int len, unsigned char tag,
unsigned char sy) unsigned char sy)
{ {
struct fw_cdev_iso_packet packet; struct fw_cdev_queue_iso queue_iso;
struct fw_cdev_start_iso start_iso;
struct fw_cdev_iso_packet *p;
void *buffer;
int first;
packet.payload_length = len; if (len > handle->iso.max_packet_size) {
packet.interrupt = handle->iso.packet_phase == 0; errno = EINVAL;
packet.skip = 0; return -1;
packet.tag = tag; }
packet.sy = sy;
packet.header_length = 0;
while (handle->iso.packet_count + handle->iso.irq_interval > handle->iso.buf_packets)
raw1394_loop_iterate(handle);
p = &handle->iso.packets[handle->iso.packet_header_index];
p->payload_length = len;
p->interrupt =
handle->iso.packet_phase == handle->iso.irq_interval - 1;
p->skip = 0;
p->tag = tag;
p->sy = sy;
p->header_length = 0;
buffer = handle->iso.buffer +
handle->iso.packet_index * handle->iso.max_packet_size;
memcpy(buffer, data, len);
handle->iso.packet_index++;
handle->iso.packet_count++;
handle->iso.packet_phase++; handle->iso.packet_phase++;
handle->iso.packet_header_index++;
first = handle->iso.packet_index - handle->iso.packet_header_index;
if (handle->iso.packet_index == handle->iso.buf_packets)
handle->iso.packet_index = 0;
if (handle->iso.packet_phase == handle->iso.irq_interval) if (handle->iso.packet_phase == handle->iso.irq_interval)
handle->iso.packet_phase = 0; handle->iso.packet_phase = 0;
/* FIXME: circular buffer goo. */ /* Queue the packets in the kernel if we filled up the packets
* array or wrapped the payload buffer. */
if (handle->iso.packet_header_index == handle->iso.irq_interval ||
handle->iso.packet_index == 0) {
buffer = handle->iso.buffer + first * handle->iso.max_packet_size;
memcpy(handle->iso.head, data, len); queue_iso.packets = ptr_to_u64(handle->iso.packets);
handle->iso.head += len; queue_iso.size = handle->iso.packet_header_index * sizeof handle->iso.packets[0];
queue_iso.data = ptr_to_u64(buffer);
handle->iso.packet_header_index = 0;
return -1; len = ioctl(handle->iso.fd, FW_CDEV_IOC_QUEUE_ISO, &queue_iso);
if (len < 0)
return -1;
}
/* Start the streaming if it's not already running and if
* we've buffered up enough packets. */
if (handle->iso.prebuffer > 0 &&
handle->iso.packet_count >= handle->iso.prebuffer) {
/* Set this to 0 to indicate that we're running. */
handle->iso.prebuffer = 0;
start_iso.cycle = handle->iso.start_on_cycle;
len = ioctl(handle->iso.fd,
FW_CDEV_IOC_START_ISO, &start_iso);
if (len < 0)
return len;
}
return 0;
} }
int raw1394_iso_xmit_sync(raw1394handle_t handle) int raw1394_iso_xmit_sync(raw1394handle_t handle)