diff --git a/.cvsignore b/.cvsignore
index ad0dec6..750d5f4 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -2,3 +2,4 @@ libraw1394-1.2.0.tar.gz
libraw1394-1.2.1.tar.gz
fw-device-cdev.h
libraw1394-1.3.0.tar.gz
+libraw1394-2.0.0-20080430_git.tar.bz2
diff --git a/libraw1394-juju-bitfield-update.patch b/libraw1394-juju-bitfield-update.patch
deleted file mode 100644
index 9df17f6..0000000
--- a/libraw1394-juju-bitfield-update.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-diff -Naurp libraw1394-1.3.0/juju/juju.h libraw1394-1.3.0.bitfield/juju/juju.h
---- libraw1394-1.3.0/juju/juju.h 2007-10-24 16:47:26.000000000 -0400
-+++ libraw1394-1.3.0.bitfield/juju/juju.h 2007-10-24 16:50:47.000000000 -0400
-@@ -29,8 +29,6 @@
- #include "../src/csr.h"
- #include "config.h"
-
--#define ACK_COMPLETE 1
--
- #define ptr_to_u64(p) ((__u64)(unsigned long)(p))
- #define u64_to_ptr(p) ((void *)(unsigned long)(p))
-
-diff -Naurp libraw1394-1.3.0/juju/raw1394-iso.c libraw1394-1.3.0.bitfield/juju/raw1394-iso.c
---- libraw1394-1.3.0/juju/raw1394-iso.c 2007-10-24 16:47:26.000000000 -0400
-+++ libraw1394-1.3.0.bitfield/juju/raw1394-iso.c 2007-10-24 16:53:06.000000000 -0400
-@@ -40,13 +40,14 @@ queue_packet(raw1394handle_t handle,
- int err;
-
- 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;
-+ p->control =
-+ FW_CDEV_ISO_PAYLOAD_LENGTH(length) |
-+ FW_CDEV_ISO_TAG(tag) |
-+ FW_CDEV_ISO_SY(sy) |
-+ FW_CDEV_ISO_HEADER_LENGTH(header_length);
-+
-+ if (handle->iso.packet_phase == handle->iso.irq_interval - 1)
-+ p->control |= FW_CDEV_ISO_INTERRUPT;
-
- handle->iso.head += length;
- handle->iso.packet_count++;
-@@ -291,12 +292,7 @@ int raw1394_iso_xmit_sync(raw1394handle_
- 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;
-+ skip.control = FW_CDEV_ISO_INTERRUPT | FW_CDEV_ISO_SKIP;
-
- queue_iso.packets = ptr_to_u64(&skip);
- queue_iso.size = sizeof skip;
diff --git a/libraw1394-juju-munmap-correct-max_packet_size.patch b/libraw1394-juju-munmap-correct-max_packet_size.patch
deleted file mode 100644
index 8903436..0000000
--- a/libraw1394-juju-munmap-correct-max_packet_size.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-diff -Naurp libraw1394-1.3.0/juju/raw1394-iso.c libraw1394-1.3.0.fix/juju/raw1394-iso.c
---- libraw1394-1.3.0/juju/raw1394-iso.c 2008-04-28 13:57:30.000000000 -0400
-+++ libraw1394-1.3.0.fix/juju/raw1394-iso.c 2008-04-28 14:06:21.000000000 -0400
-@@ -421,7 +421,7 @@ iso_init(raw1394handle_t handle, int typ
- }
-
- handle->iso.buffer =
-- mmap(NULL, buf_packets * max_packet_size,
-+ mmap(NULL, buf_packets * handle->iso.max_packet_size,
- prot, MAP_SHARED, handle->iso.fd, 0);
-
- if (handle->iso.buffer == MAP_FAILED) {
-@@ -432,7 +432,7 @@ iso_init(raw1394handle_t handle, int typ
- }
-
- handle->iso.buffer_end = handle->iso.buffer +
-- buf_packets * max_packet_size;
-+ buf_packets * handle->iso.max_packet_size;
- handle->iso.head = handle->iso.buffer;
- handle->iso.tail = handle->iso.buffer;
- handle->iso.first_payload = handle->iso.buffer;
diff --git a/libraw1394-juju-no-double-free-on-shutdown.patch b/libraw1394-juju-no-double-free-on-shutdown.patch
deleted file mode 100644
index f05fd63..0000000
--- a/libraw1394-juju-no-double-free-on-shutdown.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-diff -Naurp libraw1394-1.3.0/juju/raw1394-iso.c libraw1394-1.3.0.fix/juju/raw1394-iso.c
---- libraw1394-1.3.0/juju/raw1394-iso.c 2007-10-22 13:55:58.000000000 -0400
-+++ libraw1394-1.3.0.fix/juju/raw1394-iso.c 2007-10-22 15:27:54.000000000 -0400
-@@ -394,6 +394,7 @@ iso_init(raw1394handle_t handle, int typ
- handle->iso.fd = open(handle->local_filename, O_RDWR);
- if (handle->iso.fd < 0) {
- free(handle->iso.packets);
-+ handle->iso.packets = NULL;
- return -1;
- }
-
-@@ -404,6 +405,7 @@ iso_init(raw1394handle_t handle, int typ
- handle->iso.fd, &ep) < 0) {
- close(handle->iso.fd);
- free(handle->iso.packets);
-+ handle->iso.packets = NULL;
- return -1;
- }
-
-@@ -417,6 +419,8 @@ iso_init(raw1394handle_t handle, int typ
- if (retval < 0) {
- close(handle->iso.fd);
- free(handle->iso.packets);
-+ handle->iso.packets = NULL;
-+ printf("ioctl call failed, retval = %d\n", retval);
- return retval;
- }
-
-@@ -427,6 +431,7 @@ iso_init(raw1394handle_t handle, int typ
- if (handle->iso.buffer == MAP_FAILED) {
- close(handle->iso.fd);
- free(handle->iso.packets);
-+ handle->iso.packets = NULL;
- return -1;
- }
-
-@@ -515,8 +520,12 @@ void raw1394_iso_stop(raw1394handle_t ha
-
- void raw1394_iso_shutdown(raw1394handle_t handle)
- {
-- munmap(handle->iso.buffer,
-- handle->iso.buf_packets * handle->iso.max_packet_size);
-+ if (handle->iso.buffer) {
-+ munmap(handle->iso.buffer,
-+ handle->iso.buf_packets * handle->iso.max_packet_size);
-+ handle->iso.buffer = NULL;
-+ }
- close(handle->iso.fd);
- free(handle->iso.packets);
-+ handle->iso.packets = NULL;
- }
diff --git a/libraw1394-juju.patch b/libraw1394-juju.patch
deleted file mode 100644
index fe2d80b..0000000
--- a/libraw1394-juju.patch
+++ /dev/null
@@ -1,2334 +0,0 @@
-diff -Naurp libraw1394-1.3.0.orig/configure.ac libraw1394-1.3.0/configure.ac
---- libraw1394-1.3.0.orig/configure.ac 2007-05-30 01:32:37.000000000 -0400
-+++ libraw1394-1.3.0/configure.ac 2007-10-18 22:21:34.000000000 -0400
-@@ -24,6 +24,28 @@ AC_SUBST(lt_major)
- AC_SUBST(lt_revision)
- AC_SUBST(lt_age)
-
-+AC_ARG_WITH(juju-dir,[ --with-juju-dir=
Path to juju include files])
-+if ! test -z "$with_juju_dir" ; then
-+ JUJU_DIR="$with_juju_dir"
-+ LIB_SUBDIR=juju
-+ AC_SUBST(JUJU_DIR)
-+else
-+ LIB_SUBDIR=src
-+fi
-+AC_SUBST(LIB_SUBDIR)
-+
-+AC_ARG_WITH(fw-device-prefix,
-+ [ --with-fw-device-prefix= Prefix of firewire device file names (default "fw").],
-+ [FW_DEVICE_PREFIX="\"$withval\""], [FW_DEVICE_PREFIX="\"fw\""])
-+AC_ARG_WITH(fw-device-dir,
-+ [ --with-fw-device-dir= Directory to watch for firewire device files (default "/dev").],
-+ [FW_DEVICE_DIR="\"$withval\""], [FW_DEVICE_DIR="\"/dev\""])
-+
-+AC_DEFINE_UNQUOTED(FW_DEVICE_PREFIX, $FW_DEVICE_PREFIX,
-+ [Prefix of firewire device file names.])
-+AC_DEFINE_UNQUOTED(FW_DEVICE_DIR, $FW_DEVICE_DIR,
-+ [Directory to watch for firewire device files.])
-+
- dnl Check to see if valgrind is available
- AC_ARG_WITH(valgrind, AC_HELP_STRING([--with-valgrind],[compile with valgrind support]))
- if test x$with_valgrind = xyes ; then
-@@ -36,6 +58,7 @@ Makefile
- libraw1394.pc
- libraw1394.spec
- src/Makefile
-+juju/Makefile
- tools/Makefile
- doc/Makefile
- doc/testlibraw.1
-diff -Naurp libraw1394-1.3.0.orig/juju/juju.h libraw1394-1.3.0/juju/juju.h
---- libraw1394-1.3.0.orig/juju/juju.h 1969-12-31 19:00:00.000000000 -0500
-+++ libraw1394-1.3.0/juju/juju.h 2007-10-18 22:18:46.000000000 -0400
-@@ -0,0 +1,143 @@
-+/* -*- c-basic-offset: 8 -*-
-+ *
-+ * juju.h -- Internal header file for raw1394 emulation
-+ *
-+ * Copyright (C) 2007 Kristian Hoegsberg
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software Foundation,
-+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ */
-+
-+#ifndef __juju_h
-+#define __juju_h
-+
-+#include
-+#include
-+#include
-+#include "../src/raw1394.h"
-+#include "../src/csr.h"
-+#include "config.h"
-+
-+#define ACK_COMPLETE 1
-+
-+#define ptr_to_u64(p) ((__u64)(unsigned long)(p))
-+#define u64_to_ptr(p) ((void *)(unsigned long)(p))
-+
-+static inline __u32
-+be32_to_cpu(__u32 q)
-+{
-+ union { char c[4]; __u32 q; } u = { { 1, 0, 0, 0 } };
-+
-+ return u.q == 1 ? bswap_32(q) : q;
-+}
-+
-+static inline __u32
-+cpu_to_be32(__u32 q)
-+{
-+ return be32_to_cpu(q);
-+}
-+
-+#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
-+
-+#define BUFFER_SIZE (16 * 1024)
-+
-+#define MAX_PORTS 16
-+
-+struct epoll_closure {
-+ int (*func)(raw1394handle_t handle,
-+ struct epoll_closure *closure, __uint32_t events);
-+};
-+
-+struct port {
-+ char device_file[32];
-+ char *name;
-+ int node_count;
-+ int card;
-+};
-+
-+#define MAX_DEVICES 63
-+#define FILENAME_SIZE 16
-+
-+struct device {
-+ struct epoll_closure closure;
-+ int fd;
-+ int node_id;
-+ int generation;
-+ char filename[FILENAME_SIZE];
-+};
-+
-+struct request_closure {
-+ void *data;
-+ size_t length;
-+ unsigned long tag;
-+ struct raw1394_reqhandle reqhandle;
-+};
-+
-+struct allocation;
-+
-+struct raw1394_handle {
-+ struct port ports[MAX_PORTS];
-+ int port_count;
-+ int err;
-+ int generation;
-+ void *user_data;
-+ int notify_bus_reset;
-+
-+ bus_reset_handler_t bus_reset_handler;
-+ tag_handler_t tag_handler;
-+ arm_tag_handler_t arm_tag_handler;
-+ fcp_handler_t fcp_handler;
-+ __u32 fcp_allocation_handle;
-+ struct allocation *allocations;
-+
-+ int epoll_fd;
-+ int inotify_fd;
-+ int inotify_watch;
-+ int pipe_fds[2];
-+
-+ struct epoll_closure pipe_closure;
-+ struct epoll_closure inotify_closure;
-+
-+ struct device devices[MAX_DEVICES];
-+ int nodes[MAX_DEVICES];
-+ int local_fd;
-+ char local_filename[FILENAME_SIZE];
-+
-+ struct fw_cdev_event_bus_reset reset;
-+
-+ struct {
-+ struct epoll_closure closure;
-+ int fd;
-+ int type;
-+ int irq_interval;
-+ int packet_phase;
-+ int packet_count;
-+ int packet_index;
-+ int buf_packets;
-+ int max_packet_size;
-+ int prebuffer;
-+ int start_on_cycle;
-+ enum raw1394_iso_dma_recv_mode recv_mode;
-+ raw1394_iso_xmit_handler_t xmit_handler;
-+ raw1394_iso_recv_handler_t recv_handler;
-+ unsigned char *buffer, *buffer_end, *head;
-+ unsigned char *tail, *first_payload;
-+
-+ struct fw_cdev_iso_packet *packets;
-+ } iso;
-+
-+ char buffer[BUFFER_SIZE];
-+};
-+
-+#endif
-diff -Naurp libraw1394-1.3.0.orig/juju/Makefile.am libraw1394-1.3.0/juju/Makefile.am
---- libraw1394-1.3.0.orig/juju/Makefile.am 1969-12-31 19:00:00.000000000 -0500
-+++ libraw1394-1.3.0/juju/Makefile.am 2007-10-18 22:18:46.000000000 -0400
-@@ -0,0 +1,8 @@
-+lib_LTLIBRARIES = libraw1394.la
-+
-+INCLUDES = -I$(JUJU_DIR)
-+libraw1394_la_LDFLAGS = -version-info @lt_major@:@lt_revision@:@lt_age@
-+
-+libraw1394_la_SOURCES = raw1394.c raw1394-iso.c juju.h
-+
-+pkginclude_HEADERS = ../src/raw1394.h ../src/csr.h ../src/ieee1394.h
-diff -Naurp libraw1394-1.3.0.orig/juju/raw1394.c libraw1394-1.3.0/juju/raw1394.c
---- libraw1394-1.3.0.orig/juju/raw1394.c 1969-12-31 19:00:00.000000000 -0500
-+++ libraw1394-1.3.0/juju/raw1394.c 2007-10-18 22:18:46.000000000 -0400
-@@ -0,0 +1,1441 @@
-+/* -*- c-basic-offset: 8 -*-
-+ *
-+ * raw1394.c -- Emulation of the raw1394 API on the juju stack
-+ *
-+ * Copyright (C) 2007 Kristian Hoegsberg
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software Foundation,
-+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include /* for ntohl and htonl */
-+
-+#include "juju.h"
-+
-+raw1394_errcode_t
-+raw1394_get_errcode(raw1394handle_t handle)
-+{
-+ return handle->err;
-+}
-+
-+int
-+raw1394_errcode_to_errno(raw1394_errcode_t errcode)
-+{
-+ switch (errcode) {
-+
-+ case -RCODE_SEND_ERROR:
-+ case -RCODE_CANCELLED:
-+ case -RCODE_BUSY:
-+ case -RCODE_GENERATION:
-+ case -RCODE_NO_ACK:
-+ return EAGAIN;
-+
-+ case raw1394_make_errcode(ACK_COMPLETE, RCODE_COMPLETE):
-+ return 0;
-+ case raw1394_make_errcode(ACK_COMPLETE, RCODE_CONFLICT_ERROR):
-+ return EAGAIN;
-+ case raw1394_make_errcode(ACK_COMPLETE, RCODE_DATA_ERROR):
-+ return EREMOTEIO;
-+ case raw1394_make_errcode(ACK_COMPLETE, RCODE_TYPE_ERROR):
-+ return EPERM;
-+ case raw1394_make_errcode(ACK_COMPLETE, RCODE_ADDRESS_ERROR):
-+ return EINVAL;
-+ default:
-+ return EINVAL;
-+ }
-+}
-+
-+static int
-+juju_to_raw1394_errcode(int rcode)
-+{
-+ /* Best effort matching juju extended rcodes to raw1394 err
-+ * code. Since the raw1394 errcode decoding are macros we try
-+ * to convert the juju rcodes to something that looks enough
-+ * like the raw1394 errcodes that we retain ABI compatibility.
-+ *
-+ * Juju rcodes less than 0x10 are standard ieee1394 rcodes,
-+ * which we map to a raw1394 errcode by or'ing in an
-+ * ACK_COMPLETE ack code in the upper 16 bits. Errors
-+ * internal to raw1394 are negative values, but juju encodes
-+ * these errors as rcodes greater than or equal to 0x10. In
-+ * this case, we just the negated value, which will look like
-+ * an raw1394 internal error code. */
-+
-+ if (rcode < 0x10)
-+ return raw1394_make_errcode(ACK_COMPLETE, rcode);
-+ else
-+ return -rcode;
-+}
-+
-+static int
-+default_tag_handler(raw1394handle_t handle,
-+ unsigned long tag, raw1394_errcode_t err)
-+{
-+ struct raw1394_reqhandle *rh = (struct raw1394_reqhandle *) tag;
-+
-+ if (rh != NULL)
-+ return rh->callback(handle, rh->data, err);
-+
-+ return -1;
-+}
-+
-+static int
-+default_arm_tag_handler(raw1394handle_t handle, unsigned long arm_tag,
-+ byte_t type, unsigned int length, void *data)
-+{
-+ struct raw1394_arm_reqhandle *rh;
-+
-+ if (arm_tag == 0)
-+ return -1;
-+
-+ rh = (struct raw1394_arm_reqhandle *) arm_tag;
-+
-+ return rh->arm_callback(handle, data, length, rh->pcontext, type);
-+}
-+
-+static int
-+default_bus_reset_handler(struct raw1394_handle *handle, unsigned int gen)
-+{
-+ raw1394_update_generation(handle, gen);
-+
-+ return 0;
-+}
-+
-+static int
-+scan_devices(raw1394handle_t handle)
-+{
-+ DIR *dir;
-+ struct dirent *de;
-+ char filename[32];
-+ struct fw_cdev_get_info get_info;
-+ struct fw_cdev_event_bus_reset reset;
-+ int fd, err, i;
-+ struct port *ports;
-+
-+ ports = handle->ports;
-+ memset(ports, 0, sizeof handle->ports);
-+ dir = opendir(FW_DEVICE_DIR);
-+ if (dir == NULL)
-+ return -1;
-+
-+ i = 0;
-+ while (1) {
-+ de = readdir(dir);
-+ if (de == NULL)
-+ break;
-+
-+ if (strncmp(de->d_name,
-+ FW_DEVICE_PREFIX, strlen(FW_DEVICE_PREFIX)) != 0)
-+ continue;
-+
-+ snprintf(filename, sizeof filename, FW_DEVICE_DIR "/%s", de->d_name);
-+
-+ fd = open(filename, O_RDWR);
-+ if (fd < 0)
-+ continue;
-+ get_info.version = FW_CDEV_VERSION;
-+ get_info.rom = 0;
-+ get_info.rom_length = 0;
-+ get_info.bus_reset = ptr_to_u64(&reset);
-+ err = ioctl(fd, FW_CDEV_IOC_GET_INFO, &get_info);
-+ close(fd);
-+
-+ if (err < 0)
-+ continue;
-+
-+ if (i < MAX_PORTS && reset.node_id == reset.local_node_id) {
-+ strncpy(ports[i].device_file, filename,
-+ sizeof ports[i].device_file);
-+ ports[i].node_count = (reset.root_node_id & 0x3f) + 1;
-+ ports[i].card = get_info.card;
-+ i++;
-+ }
-+ }
-+ closedir(dir);
-+
-+ handle->port_count = i;
-+
-+ return 0;
-+}
-+
-+static int
-+handle_echo_pipe(raw1394handle_t handle,
-+ struct epoll_closure *ec, __uint32_t events)
-+{
-+ quadlet_t value;
-+
-+ if (read(handle->pipe_fds[0], &value, sizeof value) < 0)
-+ return -1;
-+
-+ return value;
-+}
-+
-+static int
-+handle_lost_device(raw1394handle_t handle, int i)
-+{
-+ int phy_id;
-+
-+ /* The device got unplugged, get rid of it. The fd is
-+ * automatically dropped from the epoll context when we close it. */
-+
-+ close(handle->devices[i].fd);
-+ phy_id = handle->devices[i].node_id & 0x3f;
-+ if (handle->nodes[phy_id] == i)
-+ handle->nodes[phy_id] = -1;
-+ handle->devices[i].node_id = -1;
-+
-+ return 0;
-+}
-+
-+struct address_closure {
-+ int (*callback)(raw1394handle_t handle, struct address_closure *ac,
-+ struct fw_cdev_event_request *request, int i);
-+};
-+
-+static int
-+handle_fcp_request(raw1394handle_t handle, struct address_closure *ac,
-+ struct fw_cdev_event_request *request, int i)
-+{
-+ struct fw_cdev_send_response response;
-+ int is_response;
-+
-+ response.handle = request->handle;
-+ response.rcode = RCODE_COMPLETE;
-+ response.length = 0;
-+ response.data = 0;
-+
-+ if (handle->fcp_handler == NULL)
-+ response.rcode = RCODE_ADDRESS_ERROR;
-+
-+ if (request->tcode >= TCODE_WRITE_RESPONSE)
-+ response.rcode = RCODE_CONFLICT_ERROR;
-+
-+ if (ioctl(handle->devices[i].fd,
-+ FW_CDEV_IOC_SEND_RESPONSE, &response) < 0)
-+ return -1;
-+
-+ if (response.rcode != RCODE_COMPLETE)
-+ return 0;
-+
-+ is_response = request->offset >= CSR_REGISTER_BASE + CSR_FCP_RESPONSE;
-+
-+ return handle->fcp_handler(handle,
-+ handle->devices[i].node_id,
-+ is_response,
-+ request->length,
-+ (unsigned char *) request->data);
-+}
-+
-+static int
-+handle_device_event(raw1394handle_t handle,
-+ struct epoll_closure *ec, __uint32_t events)
-+{
-+ union fw_cdev_event *u;
-+ struct device *device = (struct device *) ec;
-+ struct address_closure *ac;
-+ struct request_closure *rc;
-+ raw1394_errcode_t errcode;
-+ int len, phy_id;
-+ int i;
-+
-+ i = device - handle->devices;
-+ if (events == EPOLLHUP)
-+ return handle_lost_device(handle, i);
-+
-+ len = read(handle->devices[i].fd,
-+ handle->buffer, sizeof handle->buffer);
-+ if (len < 0)
-+ return -1;
-+
-+ u = (void *) handle->buffer;
-+ switch (u->common.type) {
-+ case FW_CDEV_EVENT_BUS_RESET:
-+ /* Clear old entry, unless it's been overwritten. */
-+ phy_id = handle->devices[i].node_id & 0x3f;
-+ if (handle->nodes[phy_id] == i)
-+ handle->nodes[phy_id] = -1;
-+ handle->nodes[u->bus_reset.node_id & 0x3f] = i;
-+ handle->devices[i].node_id = u->bus_reset.node_id;
-+ handle->devices[i].generation = u->bus_reset.generation;
-+
-+ if (u->bus_reset.node_id != u->bus_reset.local_node_id)
-+ return 0;
-+
-+ memcpy(&handle->reset, &u->bus_reset, sizeof handle->reset);
-+ return handle->bus_reset_handler(handle,
-+ u->bus_reset.generation);
-+
-+ case FW_CDEV_EVENT_RESPONSE:
-+ rc = u64_to_ptr(u->response.closure);
-+
-+ if (rc->data != NULL)
-+ memcpy(rc->data, u->response.data, rc->length);
-+
-+ errcode = juju_to_raw1394_errcode(u->response.rcode);
-+
-+ return handle->tag_handler(handle, rc->tag, errcode);
-+
-+ case FW_CDEV_EVENT_REQUEST:
-+ ac = u64_to_ptr(u->request.closure);
-+ return ac->callback(handle, ac, &u->request, i);
-+
-+ default:
-+ case FW_CDEV_EVENT_ISO_INTERRUPT:
-+ /* Never happens. */
-+ return -1;
-+ }
-+}
-+
-+static int
-+handle_inotify(raw1394handle_t handle, struct epoll_closure *ec,
-+ __uint32_t events)
-+{
-+ struct inotify_event *event;
-+ char filename[32];
-+ struct fw_cdev_get_info info;
-+ struct fw_cdev_event_bus_reset reset;
-+ struct epoll_event ep;
-+ int i, len, fd, phy_id;
-+
-+ event = (struct inotify_event *) handle->buffer;
-+ len = read(handle->inotify_fd, event, BUFFER_SIZE);
-+ if (!(event->mask & IN_CREATE))
-+ return -1;
-+ if (strncmp(event->name,
-+ FW_DEVICE_PREFIX, strlen(FW_DEVICE_PREFIX)) != 0)
-+ return 0;
-+ snprintf(filename, sizeof filename, FW_DEVICE_DIR "/%s", event->name);
-+ fd = open(filename, O_RDWR);
-+ if (fd < 0) {
-+ switch (errno) {
-+ case ENOENT:
-+ /* Huh, it disappeared before we could
-+ * open it. */
-+ return 0;
-+ case EACCES:
-+ /* We don't have permission to talk to
-+ * this device, maybe it's a storage
-+ * device. */
-+ return 0;
-+ default:
-+ /* Anything else is bad news. */
-+ return -1;
-+ }
-+ }
-+
-+ info.version = FW_CDEV_VERSION;
-+ info.rom = 0;
-+ info.rom_length = 0;
-+ info.bus_reset = ptr_to_u64(&reset);
-+ if (ioctl(fd, FW_CDEV_IOC_GET_INFO, &info) < 0) {
-+ close(fd);
-+ return -1;
-+ }
-+
-+ for (i = 0; i < MAX_DEVICES; i++)
-+ if (handle->devices[i].node_id == -1)
-+ break;
-+ if (i == MAX_DEVICES) {
-+ close(fd);
-+ return -1;
-+ }
-+
-+ phy_id = reset.node_id & 0x3f;
-+ handle->nodes[phy_id] = i;
-+ handle->devices[i].node_id = reset.node_id;
-+ handle->devices[i].generation = reset.generation;
-+ handle->devices[i].fd = fd;
-+ strncpy(handle->devices[i].filename, filename,
-+ sizeof handle->devices[i].filename);
-+ handle->devices[i].closure.func = handle_device_event;
-+ ep.events = EPOLLIN;
-+ ep.data.ptr = &handle->devices[i].closure;
-+ if (epoll_ctl(handle->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) {
-+ close(fd);
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+int raw1394_loop_iterate(raw1394handle_t handle)
-+{
-+ int i, count, retval = 0;
-+ struct epoll_closure *closure;
-+ struct epoll_event ep[32];
-+
-+ count = epoll_wait(handle->epoll_fd, ep, ARRAY_LENGTH(ep), -1);
-+ if (count < 0)
-+ return -1;
-+
-+ for (i = 0; i < count; i++) {
-+ closure = ep[i].data.ptr;
-+ retval = closure->func(handle, closure, ep[i].events);
-+ }
-+
-+ /* It looks like we have to add this work-around to get epoll
-+ * to recompute the POLLIN status of the epoll_fd. */
-+ epoll_wait(handle->epoll_fd, ep, ARRAY_LENGTH(ep), 0);
-+
-+ return retval;
-+}
-+
-+raw1394handle_t raw1394_new_handle(void)
-+{
-+ raw1394handle_t handle;
-+ struct epoll_event ep;
-+ int i;
-+
-+ handle = malloc(sizeof *handle);
-+
-+ handle->tag_handler = default_tag_handler;
-+ handle->arm_tag_handler = default_arm_tag_handler;
-+ handle->allocations = NULL;
-+
-+ handle->notify_bus_reset = RAW1394_NOTIFY_ON;
-+ handle->bus_reset_handler = default_bus_reset_handler;
-+
-+ handle->iso.fd = -1;
-+
-+ handle->epoll_fd = epoll_create(16);
-+ if (handle->epoll_fd < 0)
-+ goto out_handle;
-+
-+ if (pipe(handle->pipe_fds) < 0)
-+ goto out_epoll;
-+
-+ handle->inotify_fd = inotify_init();
-+ if (handle->inotify_fd < 0)
-+ goto out_pipe;
-+
-+ handle->inotify_watch =
-+ inotify_add_watch(handle->inotify_fd, FW_DEVICE_DIR, IN_CREATE);
-+ if (handle->inotify_watch < 0)
-+ goto out_inotify;
-+
-+ handle->pipe_closure.func = handle_echo_pipe;
-+ ep.events = EPOLLIN;
-+ ep.data.ptr = &handle->pipe_closure;
-+ if (epoll_ctl(handle->epoll_fd, EPOLL_CTL_ADD,
-+ handle->pipe_fds[0], &ep) < 0)
-+ goto out_inotify;
-+
-+ handle->inotify_closure.func = handle_inotify;
-+ ep.events = EPOLLIN;
-+ ep.data.ptr = &handle->inotify_closure;
-+ if (epoll_ctl(handle->epoll_fd, EPOLL_CTL_ADD,
-+ handle->inotify_fd, &ep) < 0)
-+ goto out_inotify;
-+
-+ for (i = 0; i < MAX_DEVICES; i++) {
-+ handle->nodes[i] = -1;
-+ handle->devices[i].node_id = -1;
-+ }
-+
-+ scan_devices(handle);
-+
-+ return handle;
-+
-+ out_inotify:
-+ close(handle->inotify_fd);
-+ out_pipe:
-+ close(handle->pipe_fds[0]);
-+ close(handle->pipe_fds[1]);
-+ out_epoll:
-+ close(handle->epoll_fd);
-+ out_handle:
-+ free(handle);
-+ return NULL;
-+}
-+
-+void raw1394_destroy_handle(raw1394handle_t handle)
-+{
-+ int i;
-+
-+ close(handle->inotify_fd);
-+ close(handle->pipe_fds[0]);
-+ close(handle->pipe_fds[1]);
-+
-+ for (i = 0; i < MAX_DEVICES; i++) {
-+ if (handle->devices[i].node_id == -1)
-+ continue;
-+
-+ close(handle->devices[i].fd);
-+ }
-+
-+ close(handle->epoll_fd);
-+
-+ free(handle);
-+
-+ return;
-+}
-+
-+raw1394handle_t raw1394_new_handle_on_port(int port)
-+{
-+ raw1394handle_t handle;
-+
-+ handle = raw1394_new_handle();
-+ if (handle == NULL)
-+ return NULL;
-+
-+ if (raw1394_set_port(handle, port) < 0)
-+ return NULL;
-+
-+ return handle;
-+}
-+
-+int raw1394_busreset_notify (raw1394handle_t handle, int off_on_switch)
-+{
-+ handle->notify_bus_reset = off_on_switch;
-+
-+ return 0;
-+}
-+
-+int raw1394_get_fd(raw1394handle_t handle)
-+{
-+ return handle->epoll_fd;
-+}
-+
-+void raw1394_set_userdata(raw1394handle_t handle, void *data)
-+{
-+ handle->user_data = data;
-+}
-+
-+void *raw1394_get_userdata(raw1394handle_t handle)
-+{
-+ return handle->user_data;
-+}
-+
-+nodeid_t raw1394_get_local_id(raw1394handle_t handle)
-+{
-+ return handle->reset.local_node_id;
-+}
-+
-+nodeid_t raw1394_get_irm_id(raw1394handle_t handle)
-+{
-+ return handle->reset.irm_node_id;
-+}
-+
-+int raw1394_get_nodecount(raw1394handle_t handle)
-+{
-+ return (handle->reset.root_node_id & 0x3f) + 1;
-+}
-+
-+int raw1394_get_port_info(raw1394handle_t handle,
-+ struct raw1394_portinfo *pinf,
-+ int maxports)
-+{
-+ int i;
-+
-+ if (maxports >= handle->port_count)
-+ maxports = handle->port_count;
-+
-+ for (i = 0; i < maxports; i++) {
-+ pinf[i].nodes = handle->ports[i].node_count;
-+ strncpy(pinf[i].name, handle->ports[i].device_file,
-+ sizeof pinf[i].name);
-+ }
-+
-+ return handle->port_count;
-+}
-+
-+int raw1394_set_port(raw1394handle_t handle, int port)
-+{
-+ struct fw_cdev_get_info get_info;
-+ struct fw_cdev_event_bus_reset reset;
-+ struct epoll_event ep;
-+ struct dirent *de;
-+ char filename[32];
-+ DIR *dir;
-+ int i, fd, phy_id;
-+
-+ if (port >= handle->port_count) {
-+ errno = EINVAL;
-+ return -1;
-+ }
-+
-+ dir = opendir("/dev");
-+ if (dir == NULL)
-+ return -1;
-+
-+ for (i = 0; i < MAX_DEVICES; ) {
-+ de = readdir(dir);
-+ if (de == NULL)
-+ break;
-+
-+ if (strncmp(de->d_name, "fw", 2) != 0)
-+ continue;
-+
-+ snprintf(filename, sizeof filename, "/dev/%s", de->d_name);
-+
-+ fd = open(filename, O_RDWR);
-+ if (fd < 0)
-+ continue;
-+
-+ get_info.version = FW_CDEV_VERSION;
-+ get_info.rom = 0;
-+ get_info.rom_length = 0;
-+ get_info.bus_reset = ptr_to_u64(&reset);
-+ if (ioctl(fd, FW_CDEV_IOC_GET_INFO, &get_info) < 0) {
-+ close(fd);
-+ continue;
-+ }
-+
-+ if (get_info.card != handle->ports[port].card) {
-+ close(fd);
-+ continue;
-+ }
-+
-+ phy_id = reset.node_id & 0x3f;
-+ handle->nodes[phy_id] = i;
-+ handle->devices[i].node_id = reset.node_id;
-+ handle->devices[i].generation = reset.generation;
-+ handle->devices[i].fd = fd;
-+ strncpy(handle->devices[i].filename, filename,
-+ sizeof handle->devices[i].filename);
-+
-+ handle->devices[i].closure.func = handle_device_event;
-+ ep.events = EPOLLIN;
-+ ep.data.ptr = &handle->devices[i].closure;
-+ if (epoll_ctl(handle->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) {
-+ close(fd);
-+ return -1;
-+ }
-+
-+ handle->generation = reset.generation;
-+ if (reset.node_id == reset.local_node_id) {
-+ memcpy(&handle->reset, &reset, sizeof handle->reset);
-+ handle->local_fd = fd;
-+ strncpy(handle->local_filename, filename,
-+ sizeof handle->local_filename);
-+ }
-+
-+ i++;
-+ }
-+
-+ return 0;
-+}
-+
-+int raw1394_reset_bus(raw1394handle_t handle)
-+{
-+ return raw1394_reset_bus_new(handle, RAW1394_LONG_RESET);
-+}
-+
-+int raw1394_reset_bus_new(raw1394handle_t handle, int type)
-+{
-+ struct fw_cdev_initiate_bus_reset initiate;
-+
-+ switch (type) {
-+ case RAW1394_LONG_RESET:
-+ initiate.type = FW_CDEV_LONG_RESET;
-+ break;
-+ case RAW1394_SHORT_RESET:
-+ initiate.type = FW_CDEV_SHORT_RESET;
-+ break;
-+ }
-+
-+ return ioctl(handle->local_fd,
-+ FW_CDEV_IOC_INITIATE_BUS_RESET, &initiate);
-+}
-+
-+bus_reset_handler_t raw1394_set_bus_reset_handler(raw1394handle_t handle,
-+ bus_reset_handler_t new_h)
-+{
-+ bus_reset_handler_t old_h = handle->bus_reset_handler;
-+
-+ handle->bus_reset_handler = new_h;
-+
-+ return old_h;
-+}
-+
-+unsigned int raw1394_get_generation(raw1394handle_t handle)
-+{
-+ return handle->generation;
-+}
-+
-+void raw1394_update_generation(raw1394handle_t handle, unsigned int generation)
-+{
-+ handle->generation = generation;
-+}
-+
-+tag_handler_t
-+raw1394_set_tag_handler(raw1394handle_t handle, tag_handler_t new_h)
-+{
-+ tag_handler_t old_h = handle->tag_handler;
-+
-+ handle->tag_handler = new_h;
-+
-+ return old_h;
-+}
-+
-+arm_tag_handler_t
-+raw1394_set_arm_tag_handler(raw1394handle_t handle, arm_tag_handler_t new_h)
-+{
-+ arm_tag_handler_t old_h = handle->arm_tag_handler;
-+
-+ handle->arm_tag_handler = new_h;
-+
-+ return old_h;
-+}
-+
-+fcp_handler_t
-+raw1394_set_fcp_handler(raw1394handle_t handle, fcp_handler_t new_h)
-+{
-+ fcp_handler_t old_h = handle->fcp_handler;
-+
-+ handle->fcp_handler = new_h;
-+
-+ return old_h;
-+}
-+
-+struct request_response_block {
-+ struct raw1394_arm_request_response request_response;
-+ struct raw1394_arm_request request;
-+ struct raw1394_arm_response response;
-+ unsigned char data[0];
-+};
-+
-+struct allocation {
-+ struct address_closure closure;
-+ struct allocation *next;
-+ __u32 handle;
-+ byte_t *buffer;
-+ octlet_t tag;
-+ arm_options_t access_rights;
-+ arm_options_t notification_options;
-+ arm_options_t client_transactions;
-+ nodeaddr_t offset;
-+ size_t length;
-+ unsigned char data[0];
-+};
-+
-+static int
-+handle_arm_request(raw1394handle_t handle, struct address_closure *ac,
-+ struct fw_cdev_event_request *request, int i)
-+{
-+ struct allocation *allocation = (struct allocation *) ac;
-+ struct request_response_block *rrb;
-+ struct fw_cdev_send_response response;
-+ arm_options_t type;
-+ size_t in_length;
-+ int offset;
-+
-+ offset = request->offset - allocation->offset;
-+ response.handle = request->handle;
-+
-+ switch (request->tcode) {
-+ case TCODE_WRITE_QUADLET_REQUEST:
-+ case TCODE_WRITE_BLOCK_REQUEST:
-+ printf("got write request, offset=0x%012llx, length=%d\n",
-+ request->offset, request->length);
-+
-+ type = RAW1394_ARM_WRITE;
-+ in_length = request->length;
-+ response.rcode = RCODE_COMPLETE;
-+ response.length = 0;
-+ response.data = 0;
-+ break;
-+
-+ case TCODE_READ_QUADLET_REQUEST:
-+ case TCODE_READ_BLOCK_REQUEST:
-+ printf("got read request, offset=0x%012llx, length=%d\n",
-+ request->offset, request->length);
-+
-+ type = RAW1394_ARM_READ;
-+ in_length = 0;
-+ response.rcode = RCODE_COMPLETE;
-+ response.length = request->length;
-+ response.data = ptr_to_u64(allocation->data + offset);
-+ break;
-+
-+ case TCODE_LOCK_REQUEST:
-+ type = RAW1394_ARM_LOCK;
-+ in_length = request->length;
-+ response.length = 4;
-+ break;
-+
-+ default:
-+ in_length = 0;
-+ type = 0;
-+ break;
-+ }
-+
-+ if (!(allocation->access_rights & type)) {
-+ response.rcode = RCODE_TYPE_ERROR;
-+ response.length = 0;
-+ response.data = 0;
-+ if (ioctl(handle->devices[i].fd,
-+ FW_CDEV_IOC_SEND_RESPONSE, &response) < 0)
-+ return -1;
-+ } else if (!(allocation->client_transactions & type)) {
-+ if (type == RAW1394_ARM_WRITE)
-+ memcpy(allocation->data + offset,
-+ request->data, request->length);
-+ else if (type == RAW1394_ARM_LOCK)
-+ /* FIXME: do lock ops here */;
-+
-+ if (ioctl(handle->devices[i].fd,
-+ FW_CDEV_IOC_SEND_RESPONSE, &response) < 0)
-+ return -1;
-+ }
-+
-+ if (!(allocation->notification_options & type))
-+ return 0;
-+
-+ rrb = malloc(sizeof *rrb + in_length + response.length);
-+
-+ rrb->request_response.request = &rrb->request;
-+ rrb->request_response.response = &rrb->response;
-+
-+ rrb->request.destination_nodeid = handle->reset.local_node_id;
-+ rrb->request.source_nodeid = handle->devices[i].node_id;
-+ rrb->request.destination_offset = request->offset;
-+ rrb->request.tlabel = 0;
-+ if (request->tcode < 0x10) {
-+ rrb->request.tcode = request->tcode;
-+ rrb->request.extended_transaction_code = 0;
-+ } else {
-+ rrb->request.tcode = TCODE_LOCK_REQUEST;
-+ rrb->request.extended_transaction_code = request->tcode - 0x10;
-+ }
-+ rrb->request.generation = handle->reset.generation;
-+ rrb->request.buffer_length = in_length;
-+ memcpy(rrb->request.buffer, request->data, in_length);
-+
-+ rrb->response.response_code = response.rcode;
-+ rrb->response.buffer_length = response.length;
-+ memcpy(rrb->response.buffer,
-+ allocation->data + offset, response.length);
-+
-+ return handle->arm_tag_handler(handle, allocation->tag, type,
-+ request->length,
-+ &rrb->request_response);
-+}
-+
-+int
-+raw1394_arm_register(raw1394handle_t handle, nodeaddr_t start,
-+ size_t length, byte_t *initial_value,
-+ octlet_t arm_tag, arm_options_t access_rights,
-+ arm_options_t notification_options,
-+ arm_options_t client_transactions)
-+{
-+ struct fw_cdev_allocate request;
-+ struct allocation *allocation;
-+ int retval;
-+
-+ allocation = malloc(sizeof *allocation + length);
-+ if (allocation == NULL)
-+ return -1;
-+
-+ allocation->closure.callback = handle_arm_request;
-+ allocation->buffer = initial_value;
-+ allocation->tag = arm_tag;
-+ allocation->access_rights = access_rights;
-+ allocation->notification_options = notification_options;
-+ allocation->client_transactions = client_transactions;
-+ allocation->offset = start;
-+ allocation->length = length;
-+ if (initial_value != NULL)
-+ memcpy(allocation->data, initial_value, length);
-+
-+ request.offset = start;
-+ request.length = length;
-+ request.closure = ptr_to_u64(&allocation->closure);
-+
-+ retval = ioctl(handle->local_fd, FW_CDEV_IOC_ALLOCATE, &request);
-+ if (retval < 0) {
-+ free(allocation);
-+ return -1;
-+ }
-+
-+ allocation->handle = request.handle;
-+ allocation->next = handle->allocations;
-+ handle->allocations = allocation;
-+
-+ return 0;
-+}
-+
-+static struct allocation *
-+lookup_allocation(raw1394handle_t handle, nodeaddr_t start, int delete)
-+{
-+ struct allocation *a, **prev;
-+
-+ prev = &handle->allocations;
-+ for (a = handle->allocations; a != NULL; a = a->next) {
-+ if (a->offset <= start && start < a->offset + a->length)
-+ break;
-+ prev = &a->next;
-+ }
-+
-+ if (a != NULL && delete)
-+ *prev = a->next;
-+
-+ return a;
-+}
-+
-+int
-+raw1394_arm_unregister(raw1394handle_t handle, nodeaddr_t start)
-+{
-+ struct fw_cdev_deallocate request;
-+ struct allocation *allocation;
-+
-+ allocation = lookup_allocation(handle, start, 1);
-+ if (allocation == NULL) {
-+ errno = EINVAL;
-+ return -1;
-+ }
-+
-+ request.handle = allocation->handle;
-+ free(allocation);
-+
-+ return ioctl(handle->local_fd, FW_CDEV_IOC_DEALLOCATE, &request);
-+}
-+
-+int
-+raw1394_arm_set_buf(raw1394handle_t handle, nodeaddr_t start,
-+ size_t length, void *buf)
-+{
-+ struct allocation *allocation;
-+
-+ allocation = lookup_allocation(handle, start, 0);
-+ if (allocation == NULL) {
-+ errno = ENOENT;
-+ return -1;
-+ }
-+
-+ memcpy(allocation->data + allocation->offset - start, buf, length);
-+
-+ return 0;
-+}
-+
-+int
-+raw1394_arm_get_buf(raw1394handle_t handle, nodeaddr_t start,
-+ size_t length, void *buf)
-+{
-+ struct allocation *allocation;
-+
-+ allocation = lookup_allocation(handle, start, 0);
-+ if (allocation == NULL) {
-+ errno = ENOENT;
-+ return -1;
-+ }
-+
-+ memcpy(buf, allocation->data + allocation->offset - start, length);
-+
-+ return 0;
-+}
-+
-+int
-+raw1394_echo_request(raw1394handle_t handle, quadlet_t data)
-+{
-+ return write(handle->pipe_fds[1], &data, sizeof data);
-+}
-+
-+int raw1394_wake_up(raw1394handle_t handle)
-+{
-+ return raw1394_echo_request(handle, 0);
-+}
-+
-+int raw1394_phy_packet_write (raw1394handle_t handle, quadlet_t data)
-+{
-+ errno = ENOSYS;
-+ return -1;
-+}
-+
-+int
-+raw1394_start_phy_packet_write(raw1394handle_t handle,
-+ quadlet_t data, unsigned long tag)
-+{
-+ errno = ENOSYS;
-+ return -1;
-+}
-+
-+static int
-+send_request(raw1394handle_t handle, int tcode,
-+ nodeid_t node, nodeaddr_t addr,
-+ size_t length, void *in, void *out, unsigned long tag)
-+{
-+ struct fw_cdev_send_request *request;
-+ struct request_closure *closure;
-+ int i;
-+
-+ if (node > handle->reset.root_node_id) {
-+ handle->err = -RCODE_NO_ACK;
-+ errno = raw1394_errcode_to_errno(handle->err);
-+ return -1;
-+ }
-+
-+ i = handle->nodes[node & 0x3f];
-+ if (i == -1) {
-+ handle->err = -RCODE_NO_ACK;
-+ errno = raw1394_errcode_to_errno(handle->err);
-+ return -1;
-+ }
-+
-+ if (handle->generation != handle->devices[i].generation) {
-+ handle->err = -RCODE_GENERATION;
-+ errno = raw1394_errcode_to_errno(handle->err);
-+ return -1;
-+ }
-+
-+ closure = malloc(sizeof *closure);
-+ if (closure == NULL) {
-+ handle->err = -RCODE_SEND_ERROR;
-+ errno = raw1394_errcode_to_errno(handle->err);
-+ return -1;
-+ }
-+
-+ closure->data = out;
-+ closure->length = length;
-+ closure->tag = tag;
-+
-+ request = (struct fw_cdev_send_request *) handle->buffer;
-+ request->tcode = tcode;
-+ request->generation = handle->generation;
-+ request->offset = addr;
-+ request->length = length;
-+ request->closure = ptr_to_u64(closure);
-+ request->data = ptr_to_u64(in);
-+
-+ return ioctl(handle->devices[i].fd, FW_CDEV_IOC_SEND_REQUEST, request);
-+}
-+
-+int
-+raw1394_start_read(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr,
-+ size_t length, quadlet_t *buffer, unsigned long tag)
-+{
-+ int tcode;
-+
-+ if (length == 4)
-+ tcode = TCODE_READ_QUADLET_REQUEST;
-+ else
-+ tcode = TCODE_READ_BLOCK_REQUEST;
-+
-+ return send_request(handle, tcode,
-+ node, addr, length, NULL, buffer, tag);
-+}
-+
-+int
-+raw1394_start_write(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr,
-+ size_t length, quadlet_t *data, unsigned long tag)
-+{
-+ int tcode;
-+
-+ if (length == 4)
-+ tcode = TCODE_WRITE_QUADLET_REQUEST;
-+ else
-+ tcode = TCODE_WRITE_BLOCK_REQUEST;
-+
-+ return send_request(handle, tcode,
-+ node, addr, length, data, NULL, tag);
-+}
-+
-+static int
-+setup_lock(int extcode, quadlet_t data, quadlet_t arg, quadlet_t *buffer)
-+{
-+ switch (extcode) {
-+ case RAW1394_EXTCODE_FETCH_ADD:
-+ case RAW1394_EXTCODE_LITTLE_ADD:
-+ buffer[0] = data;
-+ return sizeof buffer[0];
-+
-+ case RAW1394_EXTCODE_MASK_SWAP:
-+ case RAW1394_EXTCODE_COMPARE_SWAP:
-+ case RAW1394_EXTCODE_BOUNDED_ADD:
-+ case RAW1394_EXTCODE_WRAP_ADD:
-+ buffer[0] = arg;
-+ buffer[1] = data;
-+ return 2 * sizeof buffer[0];
-+
-+ default:
-+ errno = EINVAL;
-+ return -1;
-+ }
-+}
-+
-+static int
-+setup_lock64(int extcode, octlet_t data, octlet_t arg, octlet_t *buffer)
-+{
-+ switch (extcode) {
-+ case RAW1394_EXTCODE_FETCH_ADD:
-+ case RAW1394_EXTCODE_LITTLE_ADD:
-+ buffer[0] = data;
-+ return sizeof buffer[0];
-+
-+ case RAW1394_EXTCODE_MASK_SWAP:
-+ case RAW1394_EXTCODE_COMPARE_SWAP:
-+ case RAW1394_EXTCODE_BOUNDED_ADD:
-+ case RAW1394_EXTCODE_WRAP_ADD:
-+ buffer[0] = arg;
-+ buffer[1] = data;
-+ return 2 * sizeof buffer[0];
-+
-+ default:
-+ errno = EINVAL;
-+ return -1;
-+ }
-+}
-+
-+int
-+raw1394_start_lock(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr,
-+ unsigned int extcode, quadlet_t data, quadlet_t arg,
-+ quadlet_t *result, unsigned long tag)
-+{
-+ quadlet_t buffer[2];
-+ int length;
-+
-+ length = setup_lock(extcode, data, arg, buffer);
-+ if (length < 0)
-+ return length;
-+
-+ return send_request(handle, 16 + extcode,
-+ node, addr, length, buffer, result, tag);
-+}
-+
-+int
-+raw1394_start_lock64(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr,
-+ unsigned int extcode, octlet_t data, octlet_t arg,
-+ octlet_t *result, unsigned long tag)
-+{
-+ octlet_t buffer[2];
-+ int length;
-+
-+ length = setup_lock64(extcode, data, arg, buffer);
-+ if (length < 0)
-+ return length;
-+
-+ return send_request(handle, 16 + extcode,
-+ node, addr, length, buffer, result, tag);
-+}
-+
-+int
-+raw1394_start_async_stream(raw1394handle_t handle, unsigned int channel,
-+ unsigned int tag, unsigned int sy,
-+ unsigned int speed, size_t length, quadlet_t *data,
-+ unsigned long rawtag)
-+{
-+ /* FIXME: implement this? */
-+ return -1;
-+}
-+
-+
-+int
-+raw1394_start_async_send(raw1394handle_t handle,
-+ size_t length, size_t header_length,
-+ unsigned int expect_response,
-+ quadlet_t *data, unsigned long rawtag)
-+{
-+ /* FIXME: implement this? */
-+ return -1;
-+}
-+
-+struct sync_data {
-+ raw1394_errcode_t err;
-+ int done;
-+};
-+
-+static int
-+sync_callback(raw1394handle_t handle, void *data, raw1394_errcode_t err)
-+{
-+ struct sync_data *sd = data;
-+
-+ sd->err = err;
-+ sd->done = 1;
-+
-+ return 0;
-+}
-+
-+static int
-+send_request_sync(raw1394handle_t handle, int tcode,
-+ nodeid_t node, nodeaddr_t addr,
-+ size_t length, void *in, void *out)
-+{
-+ struct raw1394_reqhandle reqhandle;
-+ struct sync_data sd = { 0, 0 };
-+ int err;
-+
-+ reqhandle.callback = sync_callback;
-+ reqhandle.data = &sd;
-+
-+ err = send_request(handle, tcode, node, addr,
-+ length, in, out, (unsigned long) &reqhandle);
-+
-+ while (!sd.done) {
-+ if (err < 0)
-+ return err;
-+ err = raw1394_loop_iterate(handle);
-+ }
-+
-+ handle->err = sd.err;
-+ errno = raw1394_errcode_to_errno(sd.err);
-+
-+ return (errno ? -1 : 0);
-+}
-+
-+int
-+raw1394_read(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr,
-+ size_t length, quadlet_t *buffer)
-+{
-+ int tcode;
-+
-+ if (length == 4)
-+ tcode = TCODE_READ_QUADLET_REQUEST;
-+ else
-+ tcode = TCODE_READ_BLOCK_REQUEST;
-+
-+ return send_request_sync(handle, tcode,
-+ node, addr, length, NULL, buffer);
-+}
-+
-+int
-+raw1394_write(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr,
-+ size_t length, quadlet_t *data)
-+{
-+ int tcode;
-+
-+ if (length == 4)
-+ tcode = TCODE_WRITE_QUADLET_REQUEST;
-+ else
-+ tcode = TCODE_WRITE_BLOCK_REQUEST;
-+
-+ return send_request_sync(handle, tcode,
-+ node, addr, length, data, NULL);
-+}
-+
-+int
-+raw1394_lock(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr,
-+ unsigned int extcode, quadlet_t data, quadlet_t arg,
-+ quadlet_t *result)
-+{
-+ quadlet_t buffer[2];
-+ size_t length;
-+
-+ length = setup_lock(extcode, data, arg, buffer);
-+ if (length < 0)
-+ return length;
-+
-+ return send_request_sync(handle, 16 + extcode, node, addr,
-+ length, buffer, result);
-+}
-+
-+int
-+raw1394_lock64(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr,
-+ unsigned int extcode, octlet_t data, octlet_t arg,
-+ octlet_t *result)
-+{
-+ octlet_t buffer[2];
-+ size_t length;
-+
-+ length = setup_lock64(extcode, data, arg, buffer);
-+ if (length < 0)
-+ return length;
-+
-+ return send_request_sync(handle, 16 + extcode, node, addr,
-+ length, buffer, result);
-+}
-+
-+int
-+raw1394_async_stream(raw1394handle_t handle, unsigned int channel,
-+ unsigned int tag, unsigned int sy, unsigned int speed,
-+ size_t length, quadlet_t *data)
-+{
-+ /* FIXME: implement this? */
-+ return -1;
-+}
-+
-+int
-+raw1394_async_send(raw1394handle_t handle,
-+ size_t length, size_t header_length,
-+ unsigned int expect_response,
-+ quadlet_t *data)
-+{
-+ /* FIXME: implement this? */
-+ return -1;
-+}
-+
-+int
-+raw1394_start_fcp_listen(raw1394handle_t handle)
-+{
-+ struct fw_cdev_allocate request;
-+ struct address_closure *closure;
-+
-+ closure = malloc(sizeof *closure);
-+ if (closure == NULL)
-+ return -1;
-+
-+ closure->callback = handle_fcp_request;
-+
-+ request.offset = CSR_REGISTER_BASE + CSR_FCP_COMMAND;
-+ request.length = CSR_FCP_END - CSR_FCP_COMMAND;
-+ request.closure = ptr_to_u64(closure);
-+ if (ioctl(handle->local_fd, FW_CDEV_IOC_ALLOCATE, &request) < 0)
-+ return -1;
-+
-+ handle->fcp_allocation_handle = request.handle;
-+
-+ return 0;
-+}
-+
-+int
-+raw1394_stop_fcp_listen(raw1394handle_t handle)
-+{
-+ struct fw_cdev_deallocate request;
-+
-+ request.handle = handle->fcp_allocation_handle;
-+
-+ return ioctl(handle->local_fd, FW_CDEV_IOC_DEALLOCATE, &request);
-+}
-+
-+const char *
-+raw1394_get_libversion(void)
-+{
-+ return VERSION " (Juju)";
-+}
-+
-+int
-+raw1394_update_config_rom(raw1394handle_t handle, const quadlet_t *new_rom,
-+ size_t size, unsigned char rom_version)
-+{
-+ return -1;
-+}
-+
-+int
-+raw1394_get_config_rom(raw1394handle_t handle, quadlet_t *buffer,
-+ size_t buffersize, size_t *rom_size,
-+ unsigned char *rom_version)
-+{
-+ struct fw_cdev_get_info get_info;
-+ int err;
-+
-+ get_info.version = FW_CDEV_VERSION;
-+ get_info.rom = ptr_to_u64(buffer);
-+ get_info.rom_length = buffersize;
-+ get_info.bus_reset = 0;
-+
-+ err = ioctl(handle->local_fd, FW_CDEV_IOC_GET_INFO, &get_info);
-+ if (err)
-+ return err;
-+
-+ *rom_size = get_info.rom_length;
-+ *rom_version = 0;
-+
-+ return 0;
-+}
-+
-+#define MAXIMUM_BANDWIDTH 4915
-+
-+int
-+raw1394_bandwidth_modify (raw1394handle_t handle,
-+ unsigned int bandwidth,
-+ enum raw1394_modify_mode mode)
-+{
-+ quadlet_t buffer, compare, swap;
-+ nodeaddr_t addr;
-+ int result;
-+
-+ if (bandwidth == 0)
-+ return 0;
-+
-+ addr = CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE;
-+ /* Read current bandwidth usage from IRM. */
-+ result = raw1394_read (handle, raw1394_get_irm_id (handle), addr,
-+ sizeof buffer, &buffer);
-+ if (result < 0)
-+ return -1;
-+
-+ compare = ntohl (buffer);
-+ switch (mode) {
-+ case RAW1394_MODIFY_ALLOC:
-+ swap = compare - bandwidth;
-+ if (swap < 0)
-+ return -1;
-+ break;
-+
-+ case RAW1394_MODIFY_FREE:
-+ swap = compare + bandwidth;
-+ if (swap > MAXIMUM_BANDWIDTH)
-+ swap = MAXIMUM_BANDWIDTH;
-+ break;
-+
-+ default:
-+ return -1;
-+ }
-+
-+ result = raw1394_lock(handle, raw1394_get_irm_id (handle), addr,
-+ RAW1394_EXTCODE_COMPARE_SWAP,
-+ htonl(swap), htonl(compare), &buffer);
-+ if (result < 0 || ntohl(buffer) != compare)
-+ return -1;
-+
-+ return 0;
-+}
-+
-+int
-+raw1394_channel_modify (raw1394handle_t handle,
-+ unsigned int channel,
-+ enum raw1394_modify_mode mode)
-+{
-+ quadlet_t buffer, compare, swap, bit;
-+ nodeaddr_t addr;
-+ int result;
-+
-+ if (channel >= 64)
-+ return -1;
-+ addr = CSR_REGISTER_BASE +
-+ CSR_CHANNELS_AVAILABLE_HI + 4 * (channel / 32);
-+ /* Read currently available channels from IRM. */
-+ result = raw1394_read(handle, raw1394_get_irm_id (handle), addr,
-+ sizeof buffer, &buffer);
-+ if (result < 0)
-+ return -1;
-+
-+ /* IEEE numbers bits from MSB (0) to LSB (31). */
-+ bit = 1 << (31 - (channel & 31));
-+ compare = ntohl(buffer);
-+ switch (mode) {
-+ case RAW1394_MODIFY_ALLOC:
-+ if ((compare & bit) == 0)
-+ return -1;
-+ swap = buffer & ~bit;
-+ break;
-+
-+ case RAW1394_MODIFY_FREE:
-+ if ((buffer & bit) != 0)
-+ return -1;
-+ swap = buffer | bit;
-+ break;
-+
-+ default:
-+ return -1;
-+ }
-+
-+ result = raw1394_lock (handle, raw1394_get_irm_id (handle), addr,
-+ RAW1394_EXTCODE_COMPARE_SWAP,
-+ htonl(swap), htonl(compare), &buffer);
-+
-+ if (result < 0 || ntohl(buffer) != compare)
-+ return -1;
-+
-+ return 0;
-+}
-diff -Naurp libraw1394-1.3.0.orig/juju/raw1394-iso.c libraw1394-1.3.0/juju/raw1394-iso.c
---- libraw1394-1.3.0.orig/juju/raw1394-iso.c 1969-12-31 19:00:00.000000000 -0500
-+++ libraw1394-1.3.0/juju/raw1394-iso.c 2007-10-18 22:18:46.000000000 -0400
-@@ -0,0 +1,522 @@
-+/* -*- c-basic-offset: 8 -*-
-+ *
-+ * raw1394-iso.c -- Emulation of the raw1394 rawiso API on the juju stack
-+ *
-+ * Copyright (C) 2007 Kristian Hoegsberg
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software Foundation,
-+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#include "juju.h"
-+
-+static int
-+queue_packet(raw1394handle_t handle,
-+ unsigned int length, unsigned int header_length,
-+ unsigned char tag, unsigned char sy)
-+{
-+ struct fw_cdev_queue_iso queue_iso;
-+ struct fw_cdev_iso_packet *p;
-+ int err;
-+
-+ 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 += 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.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_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);
-+ queue_iso.handle = 0;
-+ handle->iso.packet_index = 0;
-+ handle->iso.first_payload = handle->iso.head;
-+
-+ err = ioctl(handle->iso.fd, FW_CDEV_IOC_QUEUE_ISO, &queue_iso);
-+ if (err < 0)
-+ return -1;
-+ }
-+}
-+
-+static int
-+queue_xmit_packets(raw1394handle_t handle, int limit)
-+{
-+ enum raw1394_iso_disposition d;
-+ unsigned char tag, sy;
-+ int len, cycle, dropped;
-+
-+ if (handle->iso.xmit_handler == NULL)
-+ return 0;
-+
-+ while (handle->iso.packet_count < limit) {
-+
-+ d = handle->iso.xmit_handler(handle, handle->iso.head,
-+ &len, &tag, &sy, cycle, dropped);
-+
-+ 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;
-+ case RAW1394_ISO_STOP:
-+ raw1394_iso_stop(handle);
-+ return 0;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+int raw1394_iso_xmit_start(raw1394handle_t handle, int start_on_cycle,
-+ int prebuffer_packets)
-+{
-+ struct fw_cdev_start_iso start_iso;
-+ int retval;
-+
-+ if (prebuffer_packets == -1)
-+ prebuffer_packets = handle->iso.irq_interval;
-+
-+ handle->iso.prebuffer = prebuffer_packets;
-+ handle->iso.start_on_cycle = start_on_cycle;
-+
-+ queue_xmit_packets(handle, prebuffer_packets);
-+
-+ if (handle->iso.prebuffer <= handle->iso.packet_count) {
-+ start_iso.cycle = start_on_cycle;
-+ start_iso.handle = 0;
-+
-+ retval = ioctl(handle->iso.fd,
-+ FW_CDEV_IOC_START_ISO, &start_iso);
-+ if (retval < 0)
-+ return retval;
-+ }
-+
-+ return queue_xmit_packets(handle, handle->iso.buf_packets);
-+}
-+
-+static int
-+queue_recv_packets(raw1394handle_t handle)
-+{
-+ while (handle->iso.packet_count <= handle->iso.buf_packets)
-+ queue_packet(handle, handle->iso.max_packet_size, 4, 0, 0);
-+
-+ return 0;
-+}
-+
-+static enum raw1394_iso_disposition
-+flush_recv_packets(raw1394handle_t handle,
-+ struct fw_cdev_event_iso_interrupt *interrupt)
-+{
-+ enum raw1394_iso_disposition d;
-+ quadlet_t header, *p, *end;
-+ unsigned int len, cycle, dropped;
-+ unsigned char channel, tag, sy;
-+
-+ 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++);
-+ len = header >> 16;
-+ tag = (header >> 14) & 0x3;
-+ channel = (header >> 8) & 0x3f;
-+ sy = header & 0x0f;
-+
-+ d = handle->iso.recv_handler(handle, handle->iso.tail, len,
-+ channel, tag, sy, cycle, dropped);
-+ if (d != RAW1394_ISO_OK)
-+ /* FIXME: we need to save the headers so we
-+ * can restart this loop. */
-+ break;
-+ cycle++;
-+
-+ handle->iso.tail += handle->iso.max_packet_size;
-+ handle->iso.packet_count--;
-+
-+ 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:
-+ return -1;
-+
-+ case RAW1394_ISO_STOP:
-+ raw1394_iso_stop(handle);
-+ return 0;
-+ }
-+
-+ queue_recv_packets(handle);
-+
-+ return 0;
-+}
-+
-+int raw1394_iso_recv_start(raw1394handle_t handle, int start_on_cycle,
-+ int tag_mask, int sync)
-+{
-+ struct fw_cdev_start_iso start_iso;
-+
-+ queue_recv_packets(handle);
-+
-+ start_iso.cycle = start_on_cycle;
-+ start_iso.tags =
-+ tag_mask == -1 ? FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS : tag_mask;
-+ /* sync is documented as 'not used' */
-+ start_iso.sync = 0;
-+ start_iso.handle = 0;
-+
-+ return ioctl(handle->iso.fd, FW_CDEV_IOC_START_ISO, &start_iso);
-+}
-+
-+static int handle_iso_event(raw1394handle_t handle,
-+ struct epoll_closure *closure, __uint32_t events)
-+{
-+ struct fw_cdev_event_iso_interrupt *interrupt;
-+ int len;
-+
-+ len = read(handle->iso.fd, handle->buffer, sizeof handle->buffer);
-+ if (len < 0)
-+ return -1;
-+
-+ interrupt = (struct fw_cdev_event_iso_interrupt *) handle->buffer;
-+ if (interrupt->type != FW_CDEV_EVENT_ISO_INTERRUPT)
-+ return 0;
-+
-+ switch (handle->iso.type) {
-+ case FW_CDEV_ISO_CONTEXT_TRANSMIT:
-+ handle->iso.packet_count -= handle->iso.irq_interval;
-+ return queue_xmit_packets(handle, handle->iso.buf_packets);
-+ case FW_CDEV_ISO_CONTEXT_RECEIVE:
-+ return flush_recv_packets(handle, interrupt);
-+ default:
-+ /* Doesn't happen. */
-+ return -1;
-+ }
-+}
-+
-+int raw1394_iso_xmit_write(raw1394handle_t handle, unsigned char *data,
-+ unsigned int len, unsigned char tag,
-+ unsigned char sy)
-+{
-+ struct fw_cdev_queue_iso queue_iso;
-+ struct fw_cdev_start_iso start_iso;
-+ struct fw_cdev_iso_packet *p;
-+
-+ if (len > handle->iso.max_packet_size) {
-+ errno = EINVAL;
-+ return -1;
-+ }
-+
-+ /* Block until we have space for another packet. */
-+ while (handle->iso.packet_count + handle->iso.irq_interval >
-+ handle->iso.buf_packets)
-+ raw1394_loop_iterate(handle);
-+
-+ memcpy(handle->iso.head, data, len);
-+ 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. */
-+ 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;
-+ start_iso.handle = 0;
-+
-+ 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)
-+{
-+ 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;
-+ queue_iso.handle = 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;
-+}
-+
-+int raw1394_iso_recv_flush(raw1394handle_t handle)
-+{
-+ /* FIXME: huh, we'll need kernel support here... */
-+
-+ 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,
-+ raw1394_iso_recv_handler_t recv_handler,
-+ unsigned int buf_packets,
-+ unsigned int max_packet_size,
-+ unsigned char channel,
-+ enum raw1394_iso_speed speed,
-+ int irq_interval)
-+{
-+ struct fw_cdev_create_iso_context create;
-+ struct epoll_event ep;
-+ int retval, prot;
-+
-+ if (handle->iso.fd != -1) {
-+ errno = EBUSY;
-+ 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;
-+ else
-+ handle->iso.irq_interval = irq_interval;
-+ handle->iso.xmit_handler = xmit_handler;
-+ handle->iso.recv_handler = recv_handler;
-+ handle->iso.buf_packets = buf_packets;
-+ 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 =
-+ malloc(handle->iso.irq_interval * sizeof handle->iso.packets[0]);
-+ if (handle->iso.packets == NULL)
-+ return -1;
-+
-+ handle->iso.fd = open(handle->local_filename, O_RDWR);
-+ if (handle->iso.fd < 0) {
-+ free(handle->iso.packets);
-+ return -1;
-+ }
-+
-+ handle->iso.closure.func = handle_iso_event;
-+ ep.events = EPOLLIN;
-+ ep.data.ptr = &handle->iso.closure;
-+ if (epoll_ctl(handle->epoll_fd, EPOLL_CTL_ADD,
-+ handle->iso.fd, &ep) < 0) {
-+ close(handle->iso.fd);
-+ free(handle->iso.packets);
-+ return -1;
-+ }
-+
-+ create.type = type;
-+ create.channel = channel;
-+ create.speed = speed;
-+ create.header_size = 4;
-+
-+ retval = ioctl(handle->iso.fd,
-+ FW_CDEV_IOC_CREATE_ISO_CONTEXT, &create);
-+ if (retval < 0) {
-+ close(handle->iso.fd);
-+ free(handle->iso.packets);
-+ return retval;
-+ }
-+
-+ handle->iso.buffer =
-+ mmap(NULL, buf_packets * max_packet_size,
-+ prot, MAP_SHARED, handle->iso.fd, 0);
-+
-+ if (handle->iso.buffer == MAP_FAILED) {
-+ close(handle->iso.fd);
-+ free(handle->iso.packets);
-+ return -1;
-+ }
-+
-+ handle->iso.buffer_end = handle->iso.buffer +
-+ buf_packets * max_packet_size;
-+ handle->iso.head = handle->iso.buffer;
-+ handle->iso.tail = handle->iso.buffer;
-+ handle->iso.first_payload = handle->iso.buffer;
-+
-+ return 0;
-+}
-+
-+int raw1394_iso_xmit_init(raw1394handle_t handle,
-+ raw1394_iso_xmit_handler_t handler,
-+ unsigned int buf_packets,
-+ unsigned int max_packet_size,
-+ unsigned char channel,
-+ enum raw1394_iso_speed speed,
-+ int irq_interval)
-+{
-+ return iso_init(handle, FW_CDEV_ISO_CONTEXT_TRANSMIT,
-+ handler, NULL, buf_packets, max_packet_size,
-+ channel, speed, irq_interval);
-+}
-+
-+int raw1394_iso_recv_init(raw1394handle_t handle,
-+ raw1394_iso_recv_handler_t handler,
-+ unsigned int buf_packets,
-+ unsigned int max_packet_size,
-+ unsigned char channel,
-+ enum raw1394_iso_dma_recv_mode mode,
-+ int irq_interval)
-+{
-+ return iso_init(handle, FW_CDEV_ISO_CONTEXT_RECEIVE,
-+ NULL, handler, buf_packets, max_packet_size,
-+ channel, 0, irq_interval);
-+}
-+
-+int raw1394_iso_multichannel_recv_init(raw1394handle_t handle,
-+ raw1394_iso_recv_handler_t handler,
-+ unsigned int buf_packets,
-+ unsigned int max_packet_size,
-+ int irq_interval)
-+{
-+ /* FIXME: gah */
-+ errno = ENOSYS;
-+ return -1;
-+}
-+
-+int raw1394_iso_recv_listen_channel(raw1394handle_t handle,
-+ unsigned char channel)
-+{
-+ /* FIXME: multichannel */
-+ errno = ENOSYS;
-+ return -1;
-+}
-+
-+int raw1394_iso_recv_unlisten_channel(raw1394handle_t handle,
-+ unsigned char channel)
-+{
-+ /* FIXME: multichannel */
-+ errno = ENOSYS;
-+ return -1;
-+}
-+
-+int raw1394_iso_recv_set_channel_mask(raw1394handle_t handle, u_int64_t mask)
-+{
-+ /* FIXME: multichannel */
-+ errno = ENOSYS;
-+ return -1;
-+}
-+
-+void raw1394_iso_stop(raw1394handle_t handle)
-+{
-+ struct fw_cdev_stop_iso stop_iso;
-+
-+ stop_iso.handle = 0;
-+ ioctl(handle->iso.fd, FW_CDEV_IOC_STOP_ISO);
-+
-+ 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;
-+}
-+
-+void raw1394_iso_shutdown(raw1394handle_t handle)
-+{
-+ munmap(handle->iso.buffer,
-+ handle->iso.buf_packets * handle->iso.max_packet_size);
-+ close(handle->iso.fd);
-+ free(handle->iso.packets);
-+}
-diff -Naurp libraw1394-1.3.0.orig/Makefile.am libraw1394-1.3.0/Makefile.am
---- libraw1394-1.3.0.orig/Makefile.am 2004-11-05 19:26:44.000000000 -0500
-+++ libraw1394-1.3.0/Makefile.am 2007-10-18 22:18:46.000000000 -0400
-@@ -1,6 +1,7 @@
- # process this file with automake to create a Makefile.in
-
--SUBDIRS = src tools doc debian
-+SUBDIRS = $(LIB_SUBDIR) tools doc debian
-+DIST_SUBDIRS = src juju
-
- pkgconfigdir = @libdir@/pkgconfig
- pkgconfig_DATA = libraw1394.pc
-diff -Naurp libraw1394-1.3.0.orig/tools/Makefile.am libraw1394-1.3.0/tools/Makefile.am
---- libraw1394-1.3.0.orig/tools/Makefile.am 2004-11-05 19:26:44.000000000 -0500
-+++ libraw1394-1.3.0/tools/Makefile.am 2007-10-18 22:18:46.000000000 -0400
-@@ -2,4 +2,4 @@ MAINTAINERCLEANFILES = Makefile.in
-
- # testlibraw
- bin_PROGRAMS = testlibraw sendiso dumpiso
--LDADD = ../src/libraw1394.la
-+LDADD = ../$(LIB_SUBDIR)/libraw1394.la
-diff -Naurp libraw1394-1.3.0.orig/tools/testlibraw.c libraw1394-1.3.0/tools/testlibraw.c
---- libraw1394-1.3.0.orig/tools/testlibraw.c 2004-01-31 15:26:03.000000000 -0500
-+++ libraw1394-1.3.0/tools/testlibraw.c 2007-10-18 22:18:46.000000000 -0400
-@@ -1,4 +1,5 @@
--/*
-+/* -*- c-basic-offset: 8 -*-
-+ *
- * libraw1394 - library for raw access to the 1394 bus with the Linux subsystem.
- *
- * Copyright (C) 1999,2000 Andreas Bombe
-@@ -13,12 +14,13 @@
- #include
- #include
- #include
-+#include
-
- #include "../src/raw1394.h"
- #include "../src/csr.h"
-
-
--#define TESTADDR (CSR_REGISTER_BASE + CSR_CYCLE_TIME)
-+#define TESTADDR (CSR_REGISTER_BASE + CSR_CONFIG_ROM)
-
- const char not_compatible[] = "\
- This libraw1394 does not work with your version of Linux. You need a different\n\
-@@ -45,12 +47,18 @@ int my_tag_handler(raw1394handle_t handl
- return 0;
- }
-
-+static const unsigned char fcp_data[] =
-+ { 0x1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
-+
- int my_fcp_handler(raw1394handle_t handle, nodeid_t nodeid, int response,
- size_t length, unsigned char *data)
- {
- printf("got fcp %s from node %d of %d bytes:",
- (response ? "response" : "command"), nodeid & 0x3f, length);
-
-+ if (memcmp(fcp_data, data, sizeof fcp_data) != 0)
-+ printf("ERROR: fcp payload not correct\n");
-+
- while (length) {
- printf(" %02x", *data);
- data++;
-@@ -62,6 +70,47 @@ int my_fcp_handler(raw1394handle_t handl
- return 0;
- }
-
-+static void
-+test_fcp(raw1394handle_t handle)
-+{
-+ printf("\ntesting FCP monitoring on local node\n");
-+ raw1394_set_fcp_handler(handle, my_fcp_handler);
-+ raw1394_start_fcp_listen(handle);
-+ raw1394_write(handle, raw1394_get_local_id(handle),
-+ CSR_REGISTER_BASE + CSR_FCP_COMMAND, sizeof(fcp_data),
-+ (quadlet_t *)fcp_data);
-+ raw1394_write(handle, raw1394_get_local_id(handle),
-+ CSR_REGISTER_BASE + CSR_FCP_RESPONSE, sizeof(fcp_data),
-+ (quadlet_t *)fcp_data);
-+}
-+
-+static void
-+read_topology_map(raw1394handle_t handle)
-+{
-+ quadlet_t map[70];
-+ nodeid_t local_id;
-+ int node_count, self_id_count, i, retval;
-+
-+ local_id = raw1394_get_local_id(handle) | 0xffc0;
-+
-+ retval = raw1394_read(handle, local_id,
-+ CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP, 12, &map[0]);
-+ if (retval < 0)
-+ perror("topology map: raw1394_read failed with error");
-+
-+ self_id_count = ntohl(map[2]) & 0xffff;
-+ node_count = ntohl(map[2]) >> 16;
-+ retval = raw1394_read(handle, local_id,
-+ CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP + 12,
-+ self_id_count * sizeof map[0], &map[3]);
-+ if (retval < 0)
-+ perror("topology map: raw1394_read failed with error");
-+
-+ printf("topology map: %d nodes, %d self ids, generation %d\n",
-+ node_count, self_id_count, ntohl(map[1]));
-+ for (i = 0; i < self_id_count; i++)
-+ printf(" 0x%08x\n", ntohl(map[3 + i]));
-+}
-
- int main(int argc, char **argv)
- {
-@@ -73,7 +122,6 @@ int main(int argc, char **argv)
- int retval;
-
- struct pollfd pfd;
-- unsigned char fcp_test[] = { 0x1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
- quadlet_t rom[0x100];
- size_t rom_size;
- unsigned char rom_version;
-@@ -150,17 +198,8 @@ int main(int argc, char **argv)
- }
- }
-
-- printf("\ntesting FCP monitoring on local node\n");
-- raw1394_set_fcp_handler(handle, my_fcp_handler);
-- raw1394_start_fcp_listen(handle);
-- raw1394_write(handle, raw1394_get_local_id(handle),
-- CSR_REGISTER_BASE + CSR_FCP_COMMAND, sizeof(fcp_test),
-- (quadlet_t *)fcp_test);
-- raw1394_write(handle, raw1394_get_local_id(handle),
-- CSR_REGISTER_BASE + CSR_FCP_RESPONSE, sizeof(fcp_test),
-- (quadlet_t *)fcp_test);
--
--
-+ test_fcp(handle);
-+ read_topology_map(handle);
-
- printf("testing config rom stuff\n");
- retval=raw1394_get_config_rom(handle, rom, 0x100, &rom_size, &rom_version);
-@@ -176,16 +215,19 @@ int main(int argc, char **argv)
- retval=raw1394_update_config_rom(handle, rom, rom_size, rom_version);
- printf("update_config_rom returned %d\n",retval);
-
-+ printf("\nposting 0xdeadbeef as an echo request\n");
-+ raw1394_echo_request(handle, 0xdeadbeef);
-
--
-- printf("\npolling for leftover messages\n");
-+ printf("polling for leftover messages\n");
- pfd.fd = raw1394_get_fd(handle);
- pfd.events = POLLIN;
- pfd.revents = 0;
- while (1) {
- retval = poll(&pfd, 1, 10);
- if (retval < 1) break;
-- raw1394_loop_iterate(handle);
-+ retval = raw1394_loop_iterate(handle);
-+ if (retval != 0)
-+ printf("raw1394_loop_iterate() returned 0x%08x\n", retval);
- }
-
- if (retval < 0) perror("poll failed");
diff --git a/libraw1394-memset-and-patch-up-leaks-git.patch b/libraw1394-memset-and-patch-up-leaks-git.patch
new file mode 100644
index 0000000..7d432e9
--- /dev/null
+++ b/libraw1394-memset-and-patch-up-leaks-git.patch
@@ -0,0 +1,140 @@
+Originally submitted via Red Hat bugzilla by Philippe Troin:
+https://bugzilla.redhat.com/show_bug.cgi?id=451727
+
+Description:
+
+While trying to track down some crashes in kino, I found the following problems
+with libraw1394:
+
+ * There is a DIR* leak in raw1394_set_port().
+ * Lots of data structures are not fully initialized when calling IEEE1394
+ ioctl()s. These cause valgrind errors (benign, as valgrind does not know
+ how to interpret all ioctls. However these also cause kino to crash in
+ libraw1394. I've added a bunch of memset()s to prevent this problem from
+ happening.
+
+Author: Philippe Troin
+
+Forward-ported to libraw1394 git tree by Jarod Wilson.
+
+Signed-off-by: Jarod Wilson
+
+--
+
+ src/fw-iso.c | 2 ++
+ src/fw.c | 15 ++++++++++++++-
+ tools/testlibraw.c | 1 +
+ 3 files changed, 17 insertions(+), 1 deletions(-)
+
+diff --git a/src/fw-iso.c b/src/fw-iso.c
+index 471d981..a1794c3 100644
+--- a/src/fw-iso.c
++++ b/src/fw-iso.c
+@@ -401,6 +401,7 @@ iso_init(fw_handle_t handle, int type,
+ }
+
+ handle->iso.closure.func = handle_iso_event;
++ memset(&ep, 0, sizeof(ep));
+ ep.events = EPOLLIN;
+ ep.data.ptr = &handle->iso.closure;
+ if (epoll_ctl(handle->epoll_fd, EPOLL_CTL_ADD,
+@@ -411,6 +412,7 @@ iso_init(fw_handle_t handle, int type,
+ return -1;
+ }
+
++ memset(&create, 0, sizeof(create));
+ create.type = type;
+ create.channel = channel;
+ create.speed = speed;
+diff --git a/src/fw.c b/src/fw.c
+index 1322fe2..3c61385 100644
+--- a/src/fw.c
++++ b/src/fw.c
+@@ -149,6 +149,8 @@ scan_devices(fw_handle_t handle)
+ fd = open(filename, O_RDWR);
+ if (fd < 0)
+ continue;
++ memset(&get_info, 0, sizeof(get_info));
++ memset(&reset, 0, sizeof(reset));
+ get_info.version = FW_CDEV_VERSION;
+ get_info.rom = 0;
+ get_info.rom_length = 0;
+@@ -404,7 +406,10 @@ fw_handle_t fw_new_handle(void)
+ struct epoll_event ep;
+ int i;
+
++ memset(&ep, 0, sizeof(ep));
++
+ handle = malloc(sizeof *handle);
++ memset(handle, 0, sizeof(*handle));
+
+ handle->tag_handler = default_tag_handler;
+ handle->arm_tag_handler = default_arm_tag_handler;
+@@ -580,6 +585,8 @@ int fw_set_port(fw_handle_t handle, int port)
+ if (fd < 0)
+ continue;
+
++ memset(&get_info, 0, sizeof(get_info));
++ memset(&reset, 0, sizeof(reset));
+ get_info.version = FW_CDEV_VERSION;
+ get_info.rom = 0;
+ get_info.rom_length = 0;
+@@ -603,10 +610,12 @@ int fw_set_port(fw_handle_t handle, int port)
+ sizeof handle->devices[i].filename);
+
+ handle->devices[i].closure.func = handle_device_event;
++ memset(&ep, 0, sizeof(ep));
+ ep.events = EPOLLIN;
+ ep.data.ptr = &handle->devices[i].closure;
+ if (epoll_ctl(handle->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) {
+ close(fd);
++ closedir(dir);
+ return -1;
+ }
+
+@@ -621,6 +630,8 @@ int fw_set_port(fw_handle_t handle, int port)
+ i++;
+ }
+
++ closedir(dir);
++
+ return 0;
+ }
+
+@@ -1220,6 +1231,7 @@ fw_start_fcp_listen(fw_handle_t handle)
+
+ closure->callback = handle_fcp_request;
+
++ memset(&request, 0, sizeof(request));
+ request.offset = CSR_REGISTER_BASE + CSR_FCP_COMMAND;
+ request.length = CSR_FCP_END - CSR_FCP_COMMAND;
+ request.closure = ptr_to_u64(closure);
+@@ -1256,6 +1268,7 @@ fw_get_config_rom(fw_handle_t handle, quadlet_t *buffer,
+ struct fw_cdev_get_info get_info;
+ int err;
+
++ memset(&get_info, 0, sizeof(get_info));
+ get_info.version = FW_CDEV_VERSION;
+ get_info.rom = ptr_to_u64(buffer);
+ get_info.rom_length = buffersize;
+@@ -1284,7 +1297,7 @@ fw_bandwidth_modify (raw1394handle_t handle,
+
+ if (bandwidth == 0)
+ return 0;
+-
++
+ addr = CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE;
+ /* Read current bandwidth usage from IRM. */
+ result = raw1394_read (handle, raw1394_get_irm_id (handle), addr,
+diff --git a/tools/testlibraw.c b/tools/testlibraw.c
+index 2f02a6d..efd87ad 100644
+--- a/tools/testlibraw.c
++++ b/tools/testlibraw.c
+@@ -202,6 +202,7 @@ int main(int argc, char **argv)
+ read_topology_map(handle);
+
+ printf("testing config rom stuff\n");
++ memset(rom, 0, sizeof(rom));
+ retval=raw1394_get_config_rom(handle, rom, 0x100, &rom_size, &rom_version);
+ printf("get_config_rom returned %d, romsize %d, rom_version %d\n",retval,rom_size,rom_version);
+ printf("here are the first 10 quadlets:\n");
diff --git a/libraw1394.spec b/libraw1394.spec
index 48d6fe0..c7dc27c 100644
--- a/libraw1394.spec
+++ b/libraw1394.spec
@@ -1,23 +1,27 @@
+%define gitrev 20080430_git
+
Summary: Library providing low-level IEEE-1394 access
Name: libraw1394
-Version: 1.3.0
-Release: 6%{?dist}
+Version: 2.0.0
+Release: 0.1.%{gitrev}%{?dist}
License: LGPLv2+
Group: System Environment/Libraries
-Source: http://www.linux1394.org/dl/libraw1394-%{version}.tar.gz
+#Source: http://www.linux1394.org/dl/libraw1394-%{version}.tar.gz
+# Pre-2.0.0 snapshot generated from git://dennedy.org/libraw1394.git
+Source: %{name}-%{version}-%{gitrev}.tar.bz2
URL: http://www.linux1394.org/
ExcludeArch: s390 s390x
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: autoconf automake libtool kernel-headers
-Patch0: libraw1394-juju.patch
-Patch1: libraw1394-juju-no-double-free-on-shutdown.patch
-Patch2: libraw1394-juju-bitfield-update.patch
-Patch3: libraw1394-juju-munmap-correct-max_packet_size.patch
+Patch0: libraw1394-memset-and-patch-up-leaks-git.patch
%description
The libraw1394 library provides direct access to the IEEE-1394 bus through
-the Linux 1394 subsystem's raw1394 user space interface.
+the Linux 1394 subsystem's raw1394 user space interface. Support for both
+the classic ieee1394 and new firewire linux driver stacks is included, with
+run-time detection of the active stack. Fedora comes with the firewire stack
+by default.
%package devel
Summary: Development libs for libraw1394
@@ -31,16 +35,10 @@ Development libraries needed to build applications against libraw1394.
%setup -q
%patch0 -p1
-%patch1 -p1 -b .free
-%patch2 -p1 -b .bitf
-%patch3 -p1 -b .munmap
%build
-aclocal
-autoheader
-autoconf
-automake
-%configure --disable-static --with-juju-dir=$PWD/..
+./autogen.sh
+%configure --disable-static
make %{?_smp_mflags}
%install
@@ -76,6 +74,14 @@ rm -rf $RPM_BUILD_ROOT
%changelog
+* Tue Jun 17 2008 Jarod Wilson - 2.0.0-0.1.20080430_git
+- Update to pre-2.0.0 git tree, which features merged "juju" firewire
+ stack support, enabled simultaneously with classic ieee1394 support
+
+* Tue Jun 17 2008 Jarod Wilson - 1.3.0-7
+- Fully initialize data structures and plug dir leak. Resolves
+ crashes when used with kino (Philippe Troin, #451727)
+
* Mon Apr 28 2008 Jarod Wilson - 1.3.0-6
- Unmap the correct memory range on iso receive teardown, fixes
segfault on exit from dvgrab (Mladen Kuntner, #444354)
diff --git a/sources b/sources
index 23e349f..eabe1d8 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-c5d9ab62bd25dba96af010b3471e816a libraw1394-1.3.0.tar.gz
+6ef4d6b593d919c36d65856f19be34b5 libraw1394-2.0.0-20080430_git.tar.bz2