From bf9a5589d11c512d42947c54e3638c4ce121cd7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Thu, 12 Apr 2007 21:24:30 +0000 Subject: [PATCH] - Make rawiso support actually work. - Update fw-device-cdev.h to sync with latest kernel patch. --- libraw1394-juju.patch | 285 +++++++++++++++++++----------------------- libraw1394.spec | 8 +- 2 files changed, 132 insertions(+), 161 deletions(-) diff --git a/libraw1394-juju.patch b/libraw1394-juju.patch index e18e779..cb221fe 100644 --- a/libraw1394-juju.patch +++ b/libraw1394-juju.patch @@ -67,7 +67,7 @@ index 0000000..6fd6a5e +pkginclude_HEADERS = ../src/raw1394.h ../src/csr.h ../src/ieee1394.h diff --git a/juju/juju.h b/juju/juju.h new file mode 100644 -index 0000000..8c18630 +index 0000000..d78d362 --- /dev/null +++ b/juju/juju.h @@ -0,0 +1,143 @@ @@ -196,9 +196,9 @@ index 0000000..8c18630 + int irq_interval; + int packet_phase; + int packet_count; ++ int packet_index; + int buf_packets; + int max_packet_size; -+ int packet_header_index; + int prebuffer; + int start_on_cycle; + enum raw1394_iso_dma_recv_mode recv_mode; @@ -216,10 +216,10 @@ index 0000000..8c18630 +#endif diff --git a/juju/raw1394-iso.c b/juju/raw1394-iso.c new file mode 100644 -index 0000000..bbf49f0 +index 0000000..a320440 --- /dev/null +++ b/juju/raw1394-iso.c -@@ -0,0 +1,547 @@ +@@ -0,0 +1,513 @@ +/* -*- c-basic-offset: 8 -*- + * + * raw1394-iso.c -- Emulation of the raw1394 rawiso API on the juju stack @@ -252,76 +252,73 @@ index 0000000..bbf49f0 + +#include "juju.h" + -+static enum raw1394_iso_disposition -+queue_xmit_packets(raw1394handle_t handle) ++static int ++queue_packet(raw1394handle_t handle, ++ unsigned int length, unsigned int header_length, ++ unsigned char tag, unsigned char sy) +{ -+ struct fw_cdev_iso_packet *p = handle->iso.packets; + struct fw_cdev_queue_iso queue_iso; -+ enum raw1394_iso_disposition d; -+ unsigned int len, dropped; -+ unsigned char tag, sy, *first_payload; -+ int cycle, i; -+ -+ first_payload = handle->iso.head; -+ for (i = 0; i < handle->iso.irq_interval; i++) { -+ cycle = -1; -+ dropped = 0; -+ -+ if (handle->iso.head + handle->iso.max_packet_size > -+ handle->iso.buffer_end) { -+ handle->iso.head = handle->iso.buffer; -+ break; -+ } -+ -+ d = handle->iso.xmit_handler(handle, handle->iso.head, -+ &len, &tag, &sy, cycle, dropped); -+ if (d != RAW1394_ISO_OK) -+ break; ++ struct fw_cdev_iso_packet *p; ++ int err; + -+ 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; ++ p = &handle->iso.packets[handle->iso.packet_index]; ++ p->payload_length = length; ++ p->interrupt = ++ handle->iso.packet_phase == handle->iso.irq_interval - 1; ++ p->skip = 0; ++ p->tag = tag; ++ p->sy = sy; ++ p->header_length = header_length; + -+ handle->iso.head += len; -+ handle->iso.packet_count++; -+ handle->iso.packet_phase++; ++ handle->iso.head += length; ++ handle->iso.packet_count++; ++ handle->iso.packet_phase++; ++ handle->iso.packet_index++; + -+ if (handle->iso.packet_phase == handle->iso.irq_interval) -+ handle->iso.packet_phase = 0; -+ } ++ 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.size = i * sizeof handle->iso.packets[0]; -+ queue_iso.data = ptr_to_u64(first_payload); ++ if (handle->iso.head + handle->iso.max_packet_size > handle->iso.buffer_end) ++ handle->iso.head = handle->iso.buffer; + -+ len = ioctl(handle->iso.fd, FW_CDEV_IOC_QUEUE_ISO, &queue_iso); -+ if (len < 0) -+ return RAW1394_ISO_ERROR; ++ /* Queue the packets in the kernel if we filled up the packets ++ * array or wrapped the payload buffer. */ ++ if (handle->iso.packet_index == handle->iso.irq_interval || ++ handle->iso.head == handle->iso.buffer) { ++ queue_iso.packets = ptr_to_u64(handle->iso.packets); ++ queue_iso.size = handle->iso.packet_index * sizeof handle->iso.packets[0]; ++ queue_iso.data = ptr_to_u64(handle->iso.first_payload); ++ handle->iso.packet_index = 0; ++ handle->iso.first_payload = handle->iso.head; + -+ return d; ++ err = ioctl(handle->iso.fd, FW_CDEV_IOC_QUEUE_ISO, &queue_iso); ++ if (err < 0) ++ return -1; ++ } +} + +static int -+flush_xmit_packets(raw1394handle_t handle, int limit) ++queue_xmit_packets(raw1394handle_t handle, int limit) +{ + enum raw1394_iso_disposition d; -+ int len; ++ unsigned char tag, sy; ++ int len, cycle, dropped; + + if (handle->iso.xmit_handler == NULL) + return 0; + -+ if (limit < handle->iso.irq_interval) -+ limit = handle->iso.irq_interval; ++ while (handle->iso.packet_count < limit) { ++ ++ d = handle->iso.xmit_handler(handle, handle->iso.head, ++ &len, &tag, &sy, cycle, dropped); + -+ while (handle->iso.packet_count + handle->iso.irq_interval <= limit) { -+ d = queue_xmit_packets(handle); + switch (d) { ++ case RAW1394_ISO_OK: ++ queue_packet(handle, len, 0, tag, sy); ++ break; + case RAW1394_ISO_DEFER: + case RAW1394_ISO_AGAIN: ++ default: + return 0; + case RAW1394_ISO_ERROR: + return -1; @@ -346,7 +343,7 @@ index 0000000..bbf49f0 + handle->iso.prebuffer = prebuffer_packets; + handle->iso.start_on_cycle = start_on_cycle; + -+ flush_xmit_packets(handle, prebuffer_packets); ++ queue_xmit_packets(handle, prebuffer_packets); + + if (handle->iso.prebuffer <= handle->iso.packet_count) { + start_iso.cycle = start_on_cycle; @@ -357,48 +354,14 @@ index 0000000..bbf49f0 + return retval; + } + -+ return flush_xmit_packets(handle, handle->iso.buf_packets); ++ return queue_xmit_packets(handle, handle->iso.buf_packets); +} + +static int +queue_recv_packets(raw1394handle_t handle) +{ -+ struct fw_cdev_queue_iso queue_iso; -+ struct fw_cdev_iso_packet *p = handle->iso.packets; -+ unsigned int len; -+ unsigned char *first_payload; -+ int i; -+ -+ first_payload = handle->iso.head; -+ for (i = 0; i < handle->iso.irq_interval; i++, p++) { -+ if (handle->iso.head + handle->iso.max_packet_size > -+ handle->iso.buffer_end) { -+ handle->iso.head = handle->iso.buffer; -+ break; -+ } -+ -+ p->payload_length = handle->iso.max_packet_size; -+ p->interrupt = handle->iso.packet_phase == handle->iso.irq_interval - 1; -+ p->skip = 0; -+ p->tag = 0; -+ p->sy = 0; -+ p->header_length = 4; -+ -+ handle->iso.head += handle->iso.max_packet_size; -+ handle->iso.packet_count++; -+ handle->iso.packet_phase++; -+ -+ 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.size = i * sizeof handle->iso.packets[0]; -+ queue_iso.data = ptr_to_u64(first_payload); -+ -+ len = ioctl(handle->iso.fd, FW_CDEV_IOC_QUEUE_ISO, &queue_iso); -+ if (len < 0) -+ return -1; ++ while (handle->iso.packet_count <= handle->iso.buf_packets) ++ queue_packet(handle, handle->iso.max_packet_size, 4, 0, 0); + + return 0; +} @@ -411,12 +374,12 @@ index 0000000..bbf49f0 + quadlet_t header, *p, *end; + unsigned int len, cycle, dropped; + unsigned char channel, tag, sy; -+ unsigned char *data; + + p = interrupt->header; + end = (void *) interrupt->header + interrupt->header_length; + cycle = interrupt->cycle; + dropped = 0; ++ d = RAW1394_ISO_OK; + + while (p < end) { + header = be32_to_cpu(*p++); @@ -435,13 +398,15 @@ index 0000000..bbf49f0 + + handle->iso.tail += handle->iso.max_packet_size; + handle->iso.packet_count--; -+ if (handle->iso.tail == handle->iso.buffer_end) ++ ++ if (handle->iso.tail + handle->iso.max_packet_size > handle->iso.buffer_end) + handle->iso.tail = handle->iso.buffer; + } + + switch (d) { + case RAW1394_ISO_OK: + case RAW1394_ISO_DEFER: ++ default: + break; + + case RAW1394_ISO_ERROR: @@ -452,9 +417,7 @@ index 0000000..bbf49f0 + return 0; + } + -+ while (handle->iso.packet_count + handle->iso.irq_interval <= -+ handle->iso.buf_packets) -+ queue_recv_packets(handle); ++ queue_recv_packets(handle); + + return 0; +} @@ -464,9 +427,7 @@ index 0000000..bbf49f0 +{ + struct fw_cdev_start_iso start_iso; + -+ while (handle->iso.packet_count + handle->iso.irq_interval <= -+ handle->iso.buf_packets) -+ queue_recv_packets(handle); ++ queue_recv_packets(handle); + + start_iso.cycle = start_on_cycle; + start_iso.tags = @@ -494,7 +455,7 @@ index 0000000..bbf49f0 + switch (handle->iso.type) { + case FW_CDEV_ISO_CONTEXT_TRANSMIT: + handle->iso.packet_count -= handle->iso.irq_interval; -+ return flush_xmit_packets(handle, handle->iso.buf_packets); ++ return queue_xmit_packets(handle, handle->iso.buf_packets); + case FW_CDEV_ISO_CONTEXT_RECEIVE: + return flush_recv_packets(handle, interrupt); + default: @@ -511,15 +472,6 @@ index 0000000..bbf49f0 + struct fw_cdev_start_iso start_iso; + struct fw_cdev_iso_packet *p; + -+ { -+ int i; -+ __u32 *p = (__u32 *) data; -+ -+ for (i = 0; i < 10; i++) -+ fprintf(stderr, "0x%08x ", p[i]); -+ fprintf(stderr, "\n"); -+ } -+ + if (len > handle->iso.max_packet_size) { + errno = EINVAL; + return -1; @@ -529,43 +481,10 @@ index 0000000..bbf49f0 + 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; + + memcpy(handle->iso.head, data, len); -+ -+ handle->iso.head += len; -+ handle->iso.packet_count++; -+ handle->iso.packet_phase++; -+ handle->iso.packet_header_index++; -+ -+ if (handle->iso.packet_phase == handle->iso.irq_interval) -+ handle->iso.packet_phase = 0; -+ -+ if (handle->iso.head + handle->iso.max_packet_size > handle->iso.buffer_end) -+ handle->iso.head = handle->iso.buffer; -+ -+ /* 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.head == handle->iso.buffer) { -+ queue_iso.packets = ptr_to_u64(handle->iso.packets); -+ queue_iso.size = handle->iso.packet_header_index * sizeof handle->iso.packets[0]; -+ queue_iso.data = ptr_to_u64(handle->iso.first_payload); -+ handle->iso.packet_header_index = 0; -+ handle->iso.first_payload = handle->iso.head; -+ -+ len = ioctl(handle->iso.fd, FW_CDEV_IOC_QUEUE_ISO, &queue_iso); -+ if (len < 0) -+ return -1; -+ } ++ if (queue_packet(handle, len, 0, tag, sy) < 0) ++ return -1; + + /* Start the streaming if it's not already running and if + * we've buffered up enough packets. */ @@ -586,7 +505,39 @@ index 0000000..bbf49f0 + +int raw1394_iso_xmit_sync(raw1394handle_t handle) +{ -+ /* FIXME: queue a skip packet and wait for that interrupt. */ ++ struct fw_cdev_iso_packet skip; ++ struct fw_cdev_queue_iso queue_iso; ++ int len; ++ ++ skip.payload_length = 0; ++ skip.interrupt = 1; ++ skip.skip = 1; ++ skip.tag = 0; ++ skip.sy = 0; ++ skip.header_length = 0; ++ ++ queue_iso.packets = ptr_to_u64(&skip); ++ queue_iso.size = sizeof skip; ++ queue_iso.data = 0; ++ ++ len = ioctl(handle->iso.fd, FW_CDEV_IOC_QUEUE_ISO, &queue_iso); ++ if (len < 0) ++ return -1; ++ ++ /* Now that we've queued the skip packet, we'll get an ++ * interrupt when the transmit buffer is flushed, so all we do ++ * here is wait. */ ++ while (handle->iso.packet_count > 0) ++ raw1394_loop_iterate(handle); ++ ++ /* The iso mainloop thinks that interrutps indicate another ++ * irq_interval number of packets was sent, so the skip ++ * interrupt makes it go out of whack. We just reset it. */ ++ handle->iso.head = handle->iso.buffer; ++ handle->iso.tail = handle->iso.buffer; ++ handle->iso.first_payload = handle->iso.buffer; ++ handle->iso.packet_phase = 0; ++ handle->iso.packet_count = 0; + + return 0; +} @@ -598,6 +549,18 @@ index 0000000..bbf49f0 + return 0; +} + ++static unsigned int ++round_to_power_of_two(unsigned int value) ++{ ++ unsigned int pot; ++ ++ pot = 1; ++ while (pot < value) ++ pot <<= 1; ++ ++ return pot; ++} ++ +static int +iso_init(raw1394handle_t handle, int type, + raw1394_iso_xmit_handler_t xmit_handler, @@ -617,6 +580,18 @@ index 0000000..bbf49f0 + return -1; + } + ++ switch (type) { ++ case FW_CDEV_ISO_CONTEXT_TRANSMIT: ++ prot = PROT_READ | PROT_WRITE; ++ break; ++ case FW_CDEV_ISO_CONTEXT_RECEIVE: ++ prot = PROT_READ; ++ break; ++ default: ++ errno = EINVAL; ++ return -1; ++ } ++ + handle->iso.type = type; + if (irq_interval < 0) + handle->iso.irq_interval = 256; @@ -625,7 +600,7 @@ index 0000000..bbf49f0 + handle->iso.xmit_handler = xmit_handler; + handle->iso.recv_handler = recv_handler; + handle->iso.buf_packets = buf_packets; -+ handle->iso.max_packet_size = max_packet_size; ++ handle->iso.max_packet_size = round_to_power_of_two(max_packet_size); + handle->iso.packet_phase = 0; + handle->iso.packet_count = 0; + handle->iso.packets = @@ -662,15 +637,6 @@ index 0000000..bbf49f0 + return retval; + } + -+ switch (type) { -+ case FW_CDEV_ISO_CONTEXT_TRANSMIT: -+ prot = PROT_READ | PROT_WRITE; -+ break; -+ case FW_CDEV_ISO_CONTEXT_RECEIVE: -+ prot = PROT_READ; -+ break; -+ } -+ + handle->iso.buffer = + mmap(NULL, buf_packets * max_packet_size, + prot, MAP_SHARED, handle->iso.fd, 0); @@ -769,10 +735,10 @@ index 0000000..bbf49f0 +} diff --git a/juju/raw1394.c b/juju/raw1394.c new file mode 100644 -index 0000000..fd5756d +index 0000000..7f73b3b --- /dev/null +++ b/juju/raw1394.c -@@ -0,0 +1,1440 @@ +@@ -0,0 +1,1441 @@ +/* -*- c-basic-offset: 8 -*- + * + * raw1394.c -- Emulation of the raw1394 API on the juju stack @@ -804,6 +770,7 @@ index 0000000..fd5756d +#include +#include +#include ++#include /* for ntohl and htonl */ + +#include "juju.h" + @@ -1840,7 +1807,7 @@ index 0000000..fd5756d + case RAW1394_EXTCODE_WRAP_ADD: + buffer[0] = arg; + buffer[1] = data; -+ return sizeof buffer; ++ return 2 * sizeof buffer[0]; + + default: + errno = EINVAL; @@ -1863,7 +1830,7 @@ index 0000000..fd5756d + case RAW1394_EXTCODE_WRAP_ADD: + buffer[0] = arg; + buffer[1] = data; -+ return sizeof buffer; ++ return 2 * sizeof buffer[0]; + + default: + errno = EINVAL; diff --git a/libraw1394.spec b/libraw1394.spec index 3c5a578..51151e0 100644 --- a/libraw1394.spec +++ b/libraw1394.spec @@ -1,7 +1,7 @@ Summary: Library providing low-level IEEE-1394 access Name: libraw1394 Version: 1.2.1 -Release: 4%{?dist} +Release: 5%{?dist} License: LGPL Group: System Environment/Libraries Source: http://www.linux1394.org/dl/libraw1394-%{version}.tar.gz @@ -28,7 +28,7 @@ Development libraries needed to build applications against libraw1394. %prep %setup -q -%patch0 -p0 -b .juju +%patch0 -p1 -b .juju %build @@ -75,6 +75,10 @@ rm -rf $RPM_BUILD_ROOT %changelog +* Thu Apr 12 2007 Kristian Høgsberg - 1.2.1-5 +- Make rawiso support actually work. +- Update fw-device-cdev.h to sync with latest kernel patch. + * Tue Apr 3 2007 Kristian Høgsberg - 1.2.1-4 - Update juju patch with rawiso support.