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