Make raw1394_iso_xmit_write work.
This commit is contained in:
parent
d9b43daf48
commit
aa70f855b3
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
if (handle->iso.prebuffer <= handle->iso.packet_count) {
|
||||||
start_iso.cycle = start_on_cycle;
|
start_iso.cycle = start_on_cycle;
|
||||||
|
|
||||||
retval = ioctl(handle->iso.fd, FW_CDEV_IOC_START_ISO, &start_iso);
|
retval = ioctl(handle->iso.fd,
|
||||||
|
FW_CDEV_IOC_START_ISO, &start_iso);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
return retval;
|
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,27 +267,78 @@ 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;
|
||||||
|
|
||||||
|
len = ioctl(handle->iso.fd, FW_CDEV_IOC_QUEUE_ISO, &queue_iso);
|
||||||
|
if (len < 0)
|
||||||
return -1;
|
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)
|
||||||
{
|
{
|
||||||
/* FIXME: queue a skip packet and wait for that interrupt. */
|
/* FIXME: queue a skip packet and wait for that interrupt. */
|
||||||
|
|
Reference in New Issue