diff --git a/.cvsignore b/.cvsignore index 5de9d16..ad0dec6 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,3 +1,4 @@ libraw1394-1.2.0.tar.gz libraw1394-1.2.1.tar.gz fw-device-cdev.h +libraw1394-1.3.0.tar.gz diff --git a/libraw1394-juju.patch b/libraw1394-juju.patch index 47a5613..fe2d80b 100644 --- a/libraw1394-juju.patch +++ b/libraw1394-juju.patch @@ -1,49 +1,36 @@ -diff --git a/Makefile.am b/Makefile.am -index 04ed38a..21df527 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -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 --git a/configure.ac b/configure.ac -index fe23ca8..7e5dd66 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -24,6 +24,27 @@ AC_SUBST(lt_major) +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) ++ JUJU_DIR="$with_juju_dir" ++ LIB_SUBDIR=juju ++ AC_SUBST(JUJU_DIR) +else -+ LIB_SUBDIR=src ++ 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\""]) ++ [ --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\""]) ++ [ --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.]) ++ [Prefix of firewire device file names.]) +AC_DEFINE_UNQUOTED(FW_DEVICE_DIR, $FW_DEVICE_DIR, -+ [Directory to watch for firewire device files.]) - - #CFLAGS=${CFLAGS:-"-Wall"} - AC_OUTPUT([ -@@ -31,6 +52,7 @@ Makefile ++ [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 @@ -51,25 +38,9 @@ index fe23ca8..7e5dd66 100644 tools/Makefile doc/Makefile doc/testlibraw.1 -diff --git a/juju/Makefile.am b/juju/Makefile.am -new file mode 100644 -index 0000000..6fd6a5e ---- /dev/null -+++ b/juju/Makefile.am -@@ -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 --git a/juju/juju.h b/juju/juju.h -new file mode 100644 -index 0000000..c7a2ebd ---- /dev/null -+++ b/juju/juju.h +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 -*- + * @@ -214,15 +185,25 @@ index 0000000..c7a2ebd +}; + +#endif -diff --git a/juju/raw1394-iso.c b/juju/raw1394-iso.c -new file mode 100644 -index 0000000..5e18dab ---- /dev/null -+++ b/juju/raw1394-iso.c -@@ -0,0 +1,522 @@ +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-iso.c -- Emulation of the raw1394 rawiso API on the juju stack ++ * raw1394.c -- Emulation of the raw1394 API on the juju stack + * + * Copyright (C) 2007 Kristian Hoegsberg + * @@ -241,1968 +222,1976 @@ index 0000000..5e18dab + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + ++#include +#include -+#include -+#include -+#include -+#include +#include -+#include ++#include +#include ++#include ++#include ++#include ++#include ++#include ++#include /* for ntohl and htonl */ + +#include "juju.h" + -+static int -+queue_packet(raw1394handle_t handle, -+ unsigned int length, unsigned int header_length, -+ unsigned char tag, unsigned char sy) ++raw1394_errcode_t ++raw1394_get_errcode(raw1394handle_t handle) +{ -+ 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; ++ return handle->err; ++} + -+ if (handle->iso.head + handle->iso.max_packet_size > handle->iso.buffer_end) -+ handle->iso.head = handle->iso.buffer; ++int ++raw1394_errcode_to_errno(raw1394_errcode_t errcode) ++{ ++ switch (errcode) { + -+ /* 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; ++ case -RCODE_SEND_ERROR: ++ case -RCODE_CANCELLED: ++ case -RCODE_BUSY: ++ case -RCODE_GENERATION: ++ case -RCODE_NO_ACK: ++ return EAGAIN; + -+ err = ioctl(handle->iso.fd, FW_CDEV_IOC_QUEUE_ISO, &queue_iso); -+ if (err < 0) -+ return -1; ++ 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 -+queue_xmit_packets(raw1394handle_t handle, int limit) ++juju_to_raw1394_errcode(int rcode) +{ -+ 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; -+ } -+ } ++ /* 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. */ + -+ return 0; ++ if (rcode < 0x10) ++ return raw1394_make_errcode(ACK_COMPLETE, rcode); ++ else ++ return -rcode; +} + -+int raw1394_iso_xmit_start(raw1394handle_t handle, int start_on_cycle, -+ int prebuffer_packets) ++static int ++default_tag_handler(raw1394handle_t handle, ++ unsigned long tag, raw1394_errcode_t err) +{ -+ struct fw_cdev_start_iso start_iso; -+ int retval; ++ struct raw1394_reqhandle *rh = (struct raw1394_reqhandle *) tag; + -+ if (prebuffer_packets == -1) -+ prebuffer_packets = handle->iso.irq_interval; ++ if (rh != NULL) ++ return rh->callback(handle, rh->data, err); + -+ handle->iso.prebuffer = prebuffer_packets; -+ handle->iso.start_on_cycle = start_on_cycle; ++ return -1; ++} + -+ queue_xmit_packets(handle, prebuffer_packets); ++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 (handle->iso.prebuffer <= handle->iso.packet_count) { -+ start_iso.cycle = start_on_cycle; -+ start_iso.handle = 0; ++ if (arm_tag == 0) ++ return -1; + -+ retval = ioctl(handle->iso.fd, -+ FW_CDEV_IOC_START_ISO, &start_iso); -+ if (retval < 0) -+ return retval; -+ } ++ rh = (struct raw1394_arm_reqhandle *) arm_tag; + -+ return queue_xmit_packets(handle, handle->iso.buf_packets); ++ return rh->arm_callback(handle, data, length, rh->pcontext, type); +} + +static int -+queue_recv_packets(raw1394handle_t handle) ++default_bus_reset_handler(struct raw1394_handle *handle, unsigned int gen) +{ -+ while (handle->iso.packet_count <= handle->iso.buf_packets) -+ queue_packet(handle, handle->iso.max_packet_size, 4, 0, 0); ++ raw1394_update_generation(handle, gen); + + 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; ++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; + -+ while (p < end) { -+ header = be32_to_cpu(*p++); -+ len = header >> 16; -+ tag = (header >> 14) & 0x3; -+ channel = (header >> 8) & 0x3f; -+ sy = header & 0x0f; ++ ports = handle->ports; ++ memset(ports, 0, sizeof handle->ports); ++ dir = opendir(FW_DEVICE_DIR); ++ if (dir == NULL) ++ return -1; + -+ 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. */ ++ i = 0; ++ while (1) { ++ de = readdir(dir); ++ if (de == NULL) + break; -+ cycle++; + -+ handle->iso.tail += handle->iso.max_packet_size; -+ handle->iso.packet_count--; ++ if (strncmp(de->d_name, ++ FW_DEVICE_PREFIX, strlen(FW_DEVICE_PREFIX)) != 0) ++ continue; + -+ if (handle->iso.tail + handle->iso.max_packet_size > handle->iso.buffer_end) -+ handle->iso.tail = handle->iso.buffer; -+ } ++ snprintf(filename, sizeof filename, FW_DEVICE_DIR "/%s", de->d_name); + -+ switch (d) { -+ case RAW1394_ISO_OK: -+ case RAW1394_ISO_DEFER: -+ default: -+ break; -+ -+ case RAW1394_ISO_ERROR: -+ return -1; ++ 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); + -+ case RAW1394_ISO_STOP: -+ raw1394_iso_stop(handle); -+ return 0; ++ 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); + -+ queue_recv_packets(handle); ++ handle->port_count = i; + + return 0; +} + -+int raw1394_iso_recv_start(raw1394handle_t handle, int start_on_cycle, -+ int tag_mask, int sync) ++static int ++handle_echo_pipe(raw1394handle_t handle, ++ struct epoll_closure *ec, __uint32_t events) +{ -+ struct fw_cdev_start_iso start_iso; -+ -+ queue_recv_packets(handle); ++ quadlet_t value; + -+ 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; ++ if (read(handle->pipe_fds[0], &value, sizeof value) < 0) ++ return -1; + -+ return ioctl(handle->iso.fd, FW_CDEV_IOC_START_ISO, &start_iso); ++ return value; +} + -+static int handle_iso_event(raw1394handle_t handle, -+ struct epoll_closure *closure, __uint32_t events) ++static int ++handle_lost_device(raw1394handle_t handle, int i) +{ -+ struct fw_cdev_event_iso_interrupt *interrupt; -+ int len; ++ int phy_id; + -+ len = read(handle->iso.fd, handle->buffer, sizeof handle->buffer); -+ if (len < 0) -+ return -1; ++ /* The device got unplugged, get rid of it. The fd is ++ * automatically dropped from the epoll context when we close it. */ + -+ interrupt = (struct fw_cdev_event_iso_interrupt *) handle->buffer; -+ if (interrupt->type != FW_CDEV_EVENT_ISO_INTERRUPT) -+ return 0; ++ 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; + -+ 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; -+ } ++ return 0; +} + -+int raw1394_iso_xmit_write(raw1394handle_t handle, unsigned char *data, -+ unsigned int len, unsigned char tag, -+ unsigned char sy) ++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_queue_iso queue_iso; -+ struct fw_cdev_start_iso start_iso; -+ struct fw_cdev_iso_packet *p; ++ struct fw_cdev_send_response response; ++ int is_response; + -+ if (len > handle->iso.max_packet_size) { -+ errno = EINVAL; -+ return -1; -+ } ++ response.handle = request->handle; ++ response.rcode = RCODE_COMPLETE; ++ response.length = 0; ++ response.data = 0; + -+ /* 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) ++ 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; + -+ /* 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; ++ if (response.rcode != RCODE_COMPLETE) ++ return 0; + -+ len = ioctl(handle->iso.fd, -+ FW_CDEV_IOC_START_ISO, &start_iso); -+ if (len < 0) -+ return len; -+ } ++ is_response = request->offset >= CSR_REGISTER_BASE + CSR_FCP_RESPONSE; + -+ return 0; ++ return handle->fcp_handler(handle, ++ handle->devices[i].node_id, ++ is_response, ++ request->length, ++ (unsigned char *) request->data); +} + -+int raw1394_iso_xmit_sync(raw1394handle_t handle) ++static int ++handle_device_event(raw1394handle_t handle, ++ struct epoll_closure *ec, __uint32_t events) +{ -+ 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; ++ 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; + -+ queue_iso.packets = ptr_to_u64(&skip); -+ queue_iso.size = sizeof skip; -+ queue_iso.data = 0; -+ queue_iso.handle = 0; ++ i = device - handle->devices; ++ if (events == EPOLLHUP) ++ return handle_lost_device(handle, i); + -+ len = ioctl(handle->iso.fd, FW_CDEV_IOC_QUEUE_ISO, &queue_iso); ++ len = read(handle->devices[i].fd, ++ handle->buffer, sizeof handle->buffer); + 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); ++ 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; + -+ /* 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; ++ if (u->bus_reset.node_id != u->bus_reset.local_node_id) ++ return 0; + -+ return 0; -+} ++ memcpy(&handle->reset, &u->bus_reset, sizeof handle->reset); ++ return handle->bus_reset_handler(handle, ++ u->bus_reset.generation); + -+int raw1394_iso_recv_flush(raw1394handle_t handle) -+{ -+ /* FIXME: huh, we'll need kernel support here... */ ++ case FW_CDEV_EVENT_RESPONSE: ++ rc = u64_to_ptr(u->response.closure); + -+ return 0; -+} ++ if (rc->data != NULL) ++ memcpy(rc->data, u->response.data, rc->length); + -+static unsigned int -+round_to_power_of_two(unsigned int value) -+{ -+ unsigned int pot; ++ errcode = juju_to_raw1394_errcode(u->response.rcode); + -+ pot = 1; -+ while (pot < value) -+ pot <<= 1; ++ return handle->tag_handler(handle, rc->tag, errcode); + -+ return pot; ++ 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 -+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) ++handle_inotify(raw1394handle_t handle, struct epoll_closure *ec, ++ __uint32_t events) +{ -+ struct fw_cdev_create_iso_context create; ++ 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 retval, prot; ++ int i, len, fd, phy_id; + -+ 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; ++ 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; ++ } + } + -+ 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) ++ 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; ++ } + -+ handle->iso.fd = open(handle->local_filename, O_RDWR); -+ if (handle->iso.fd < 0) { -+ free(handle->iso.packets); ++ for (i = 0; i < MAX_DEVICES; i++) ++ if (handle->devices[i].node_id == -1) ++ break; ++ if (i == MAX_DEVICES) { ++ close(fd); + return -1; + } + -+ handle->iso.closure.func = handle_iso_event; ++ 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->iso.closure; -+ if (epoll_ctl(handle->epoll_fd, EPOLL_CTL_ADD, -+ handle->iso.fd, &ep) < 0) { -+ close(handle->iso.fd); -+ free(handle->iso.packets); ++ ep.data.ptr = &handle->devices[i].closure; ++ if (epoll_ctl(handle->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) { ++ close(fd); + 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; -+ } ++ return 0; ++} + -+ handle->iso.buffer = -+ mmap(NULL, buf_packets * max_packet_size, -+ prot, MAP_SHARED, handle->iso.fd, 0); ++int raw1394_loop_iterate(raw1394handle_t handle) ++{ ++ int i, count, retval = 0; ++ struct epoll_closure *closure; ++ struct epoll_event ep[32]; + -+ if (handle->iso.buffer == MAP_FAILED) { -+ close(handle->iso.fd); -+ free(handle->iso.packets); ++ 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); + } + -+ 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; ++ /* 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 0; ++ return retval; +} + -+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) ++raw1394handle_t raw1394_new_handle(void) +{ -+ return iso_init(handle, FW_CDEV_ISO_CONTEXT_TRANSMIT, -+ handler, NULL, buf_packets, max_packet_size, -+ channel, speed, irq_interval); ++ 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; +} + -+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) ++void raw1394_destroy_handle(raw1394handle_t handle) +{ -+ return iso_init(handle, FW_CDEV_ISO_CONTEXT_RECEIVE, -+ NULL, handler, buf_packets, max_packet_size, -+ channel, 0, irq_interval); ++ 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; +} + -+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) ++raw1394handle_t raw1394_new_handle_on_port(int port) +{ -+ /* FIXME: gah */ -+ errno = ENOSYS; -+ return -1; ++ 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_iso_recv_listen_channel(raw1394handle_t handle, -+ unsigned char channel) ++int raw1394_busreset_notify (raw1394handle_t handle, int off_on_switch) +{ -+ /* FIXME: multichannel */ -+ errno = ENOSYS; -+ return -1; ++ handle->notify_bus_reset = off_on_switch; ++ ++ return 0; +} + -+int raw1394_iso_recv_unlisten_channel(raw1394handle_t handle, -+ unsigned char channel) ++int raw1394_get_fd(raw1394handle_t handle) +{ -+ /* FIXME: multichannel */ -+ errno = ENOSYS; -+ return -1; ++ return handle->epoll_fd; +} + -+int raw1394_iso_recv_set_channel_mask(raw1394handle_t handle, u_int64_t mask) ++void raw1394_set_userdata(raw1394handle_t handle, void *data) +{ -+ /* 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); ++ handle->user_data = data; +} -diff --git a/juju/raw1394.c b/juju/raw1394.c -new file mode 100644 -index 0000000..7f73b3b ---- /dev/null -+++ b/juju/raw1394.c -@@ -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) ++void *raw1394_get_userdata(raw1394handle_t handle) +{ -+ return handle->err; ++ return handle->user_data; +} + -+int -+raw1394_errcode_to_errno(raw1394_errcode_t errcode) ++nodeid_t raw1394_get_local_id(raw1394handle_t handle) +{ -+ 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; -+ } ++ return handle->reset.local_node_id; +} + -+static int -+juju_to_raw1394_errcode(int rcode) ++nodeid_t raw1394_get_irm_id(raw1394handle_t handle) +{ -+ /* 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; ++ return handle->reset.irm_node_id; +} + -+static int -+default_tag_handler(raw1394handle_t handle, -+ unsigned long tag, raw1394_errcode_t err) ++int raw1394_get_nodecount(raw1394handle_t handle) +{ -+ struct raw1394_reqhandle *rh = (struct raw1394_reqhandle *) tag; -+ -+ if (rh != NULL) -+ return rh->callback(handle, rh->data, err); -+ -+ return -1; ++ return (handle->reset.root_node_id & 0x3f) + 1; +} + -+static int -+default_arm_tag_handler(raw1394handle_t handle, unsigned long arm_tag, -+ byte_t type, unsigned int length, void *data) ++int raw1394_get_port_info(raw1394handle_t handle, ++ struct raw1394_portinfo *pinf, ++ int maxports) +{ -+ struct raw1394_arm_reqhandle *rh; -+ -+ if (arm_tag == 0) -+ return -1; -+ -+ rh = (struct raw1394_arm_reqhandle *) arm_tag; ++ int i; + -+ return rh->arm_callback(handle, data, length, rh->pcontext, type); -+} ++ if (maxports >= handle->port_count) ++ maxports = handle->port_count; + -+static int -+default_bus_reset_handler(struct raw1394_handle *handle, unsigned int gen) -+{ -+ raw1394_update_generation(handle, gen); ++ 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 0; ++ return handle->port_count; +} + -+static int -+scan_devices(raw1394handle_t handle) ++int raw1394_set_port(raw1394handle_t handle, int port) +{ -+ 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; ++ struct epoll_event ep; ++ struct dirent *de; ++ char filename[32]; ++ DIR *dir; ++ int i, fd, phy_id; + -+ ports = handle->ports; -+ memset(ports, 0, sizeof handle->ports); -+ dir = opendir(FW_DEVICE_DIR); ++ if (port >= handle->port_count) { ++ errno = EINVAL; ++ return -1; ++ } ++ ++ dir = opendir("/dev"); + if (dir == NULL) + return -1; + -+ i = 0; -+ while (1) { ++ for (i = 0; i < MAX_DEVICES; ) { + de = readdir(dir); + if (de == NULL) + break; + -+ if (strncmp(de->d_name, -+ FW_DEVICE_PREFIX, strlen(FW_DEVICE_PREFIX)) != 0) ++ if (strncmp(de->d_name, "fw", 2) != 0) + continue; + -+ snprintf(filename, sizeof filename, FW_DEVICE_DIR "/%s", de->d_name); ++ 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); -+ err = ioctl(fd, FW_CDEV_IOC_GET_INFO, &get_info); -+ close(fd); ++ if (ioctl(fd, FW_CDEV_IOC_GET_INFO, &get_info) < 0) { ++ close(fd); ++ continue; ++ } + -+ if (err < 0) ++ if (get_info.card != handle->ports[port].card) { ++ close(fd); + 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++; ++ 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; + } -+ } -+ closedir(dir); + -+ handle->port_count = i; ++ 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; +} + -+static int -+handle_echo_pipe(raw1394handle_t handle, -+ struct epoll_closure *ec, __uint32_t events) ++int raw1394_reset_bus(raw1394handle_t handle) +{ -+ quadlet_t value; ++ return raw1394_reset_bus_new(handle, RAW1394_LONG_RESET); ++} + -+ if (read(handle->pipe_fds[0], &value, sizeof value) < 0) -+ return -1; ++int raw1394_reset_bus_new(raw1394handle_t handle, int type) ++{ ++ struct fw_cdev_initiate_bus_reset initiate; + -+ return value; ++ 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); +} + -+static int -+handle_lost_device(raw1394handle_t handle, int i) ++bus_reset_handler_t raw1394_set_bus_reset_handler(raw1394handle_t handle, ++ bus_reset_handler_t new_h) +{ -+ int phy_id; ++ bus_reset_handler_t old_h = handle->bus_reset_handler; + -+ /* 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; ++ handle->bus_reset_handler = new_h; + -+ return 0; ++ return old_h; +} + -+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) ++unsigned int raw1394_get_generation(raw1394handle_t handle) +{ -+ struct fw_cdev_send_response response; -+ int is_response; ++ return handle->generation; ++} + -+ response.handle = request->handle; -+ response.rcode = RCODE_COMPLETE; -+ response.length = 0; -+ response.data = 0; ++void raw1394_update_generation(raw1394handle_t handle, unsigned int generation) ++{ ++ handle->generation = generation; ++} + -+ if (handle->fcp_handler == NULL) -+ response.rcode = RCODE_ADDRESS_ERROR; ++tag_handler_t ++raw1394_set_tag_handler(raw1394handle_t handle, tag_handler_t new_h) ++{ ++ tag_handler_t old_h = handle->tag_handler; + -+ if (request->tcode >= TCODE_WRITE_RESPONSE) -+ response.rcode = RCODE_CONFLICT_ERROR; ++ handle->tag_handler = new_h; + -+ if (ioctl(handle->devices[i].fd, -+ FW_CDEV_IOC_SEND_RESPONSE, &response) < 0) -+ return -1; ++ return old_h; ++} + -+ if (response.rcode != RCODE_COMPLETE) -+ return 0; ++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; + -+ is_response = request->offset >= CSR_REGISTER_BASE + CSR_FCP_RESPONSE; ++ handle->arm_tag_handler = new_h; + -+ return handle->fcp_handler(handle, -+ handle->devices[i].node_id, -+ is_response, -+ request->length, -+ (unsigned char *) request->data); ++ return old_h; +} + -+static int -+handle_device_event(raw1394handle_t handle, -+ struct epoll_closure *ec, __uint32_t events) ++fcp_handler_t ++raw1394_set_fcp_handler(raw1394handle_t handle, fcp_handler_t new_h) +{ -+ 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; ++ fcp_handler_t old_h = handle->fcp_handler; + -+ i = device - handle->devices; -+ if (events == EPOLLHUP) -+ return handle_lost_device(handle, i); ++ handle->fcp_handler = new_h; + -+ len = read(handle->devices[i].fd, -+ handle->buffer, sizeof handle->buffer); -+ if (len < 0) -+ return -1; ++ return old_h; ++} + -+ 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; ++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]; ++}; + -+ if (u->bus_reset.node_id != u->bus_reset.local_node_id) -+ return 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]; ++}; + -+ memcpy(&handle->reset, &u->bus_reset, sizeof handle->reset); -+ return handle->bus_reset_handler(handle, -+ u->bus_reset.generation); ++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; + -+ case FW_CDEV_EVENT_RESPONSE: -+ rc = u64_to_ptr(u->response.closure); ++ offset = request->offset - allocation->offset; ++ response.handle = request->handle; + -+ if (rc->data != NULL) -+ memcpy(rc->data, u->response.data, rc->length); ++ 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); + -+ errcode = juju_to_raw1394_errcode(u->response.rcode); ++ type = RAW1394_ARM_WRITE; ++ in_length = request->length; ++ response.rcode = RCODE_COMPLETE; ++ response.length = 0; ++ response.data = 0; ++ break; + -+ return handle->tag_handler(handle, rc->tag, errcode); ++ case TCODE_READ_QUADLET_REQUEST: ++ case TCODE_READ_BLOCK_REQUEST: ++ printf("got read request, offset=0x%012llx, length=%d\n", ++ request->offset, request->length); + -+ case FW_CDEV_EVENT_REQUEST: -+ ac = u64_to_ptr(u->request.closure); -+ return ac->callback(handle, ac, &u->request, i); ++ 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: -+ case FW_CDEV_EVENT_ISO_INTERRUPT: -+ /* Never happens. */ -+ return -1; ++ in_length = 0; ++ type = 0; ++ break; + } -+} -+ -+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. */ ++ 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 */; + -+ 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; ++ if (ioctl(handle->devices[i].fd, ++ FW_CDEV_IOC_SEND_RESPONSE, &response) < 0) ++ 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; -+ } ++ if (!(allocation->notification_options & type)) ++ return 0; + -+ 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; -+ } ++ rrb = malloc(sizeof *rrb + in_length + response.length); + -+ return 0; -+} ++ rrb->request_response.request = &rrb->request; ++ rrb->request_response.response = &rrb->response; + -+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); ++ 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); + -+ /* 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); ++ rrb->response.response_code = response.rcode; ++ rrb->response.buffer_length = response.length; ++ memcpy(rrb->response.buffer, ++ allocation->data + offset, response.length); + -+ return retval; ++ return handle->arm_tag_handler(handle, allocation->tag, type, ++ request->length, ++ &rrb->request_response); +} + -+raw1394handle_t raw1394_new_handle(void) ++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) +{ -+ 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; ++ struct fw_cdev_allocate request; ++ struct allocation *allocation; ++ int retval; + -+ handle->iso.fd = -1; ++ allocation = malloc(sizeof *allocation + length); ++ if (allocation == NULL) ++ return -1; + -+ handle->epoll_fd = epoll_create(16); -+ if (handle->epoll_fd < 0) -+ goto out_handle; ++ 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); + -+ if (pipe(handle->pipe_fds) < 0) -+ goto out_epoll; ++ request.offset = start; ++ request.length = length; ++ request.closure = ptr_to_u64(&allocation->closure); + -+ handle->inotify_fd = inotify_init(); -+ if (handle->inotify_fd < 0) -+ goto out_pipe; ++ retval = ioctl(handle->local_fd, FW_CDEV_IOC_ALLOCATE, &request); ++ if (retval < 0) { ++ free(allocation); ++ return -1; ++ } + -+ handle->inotify_watch = -+ inotify_add_watch(handle->inotify_fd, FW_DEVICE_DIR, IN_CREATE); -+ if (handle->inotify_watch < 0) -+ goto out_inotify; ++ allocation->handle = request.handle; ++ allocation->next = handle->allocations; ++ handle->allocations = allocation; + -+ 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; ++ return 0; ++} + -+ 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; ++static struct allocation * ++lookup_allocation(raw1394handle_t handle, nodeaddr_t start, int delete) ++{ ++ struct allocation *a, **prev; + -+ for (i = 0; i < MAX_DEVICES; i++) { -+ handle->nodes[i] = -1; -+ handle->devices[i].node_id = -1; ++ 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; + } + -+ scan_devices(handle); -+ -+ return handle; ++ if (a != NULL && delete) ++ *prev = a->next; + -+ 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; ++ return a; +} + -+void raw1394_destroy_handle(raw1394handle_t handle) ++int ++raw1394_arm_unregister(raw1394handle_t handle, nodeaddr_t start) +{ -+ 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; ++ struct fw_cdev_deallocate request; ++ struct allocation *allocation; + -+ close(handle->devices[i].fd); ++ allocation = lookup_allocation(handle, start, 1); ++ if (allocation == NULL) { ++ errno = EINVAL; ++ return -1; + } + -+ close(handle->epoll_fd); -+ -+ free(handle); ++ request.handle = allocation->handle; ++ free(allocation); + -+ return; ++ return ioctl(handle->local_fd, FW_CDEV_IOC_DEALLOCATE, &request); +} + -+raw1394handle_t raw1394_new_handle_on_port(int port) ++int ++raw1394_arm_set_buf(raw1394handle_t handle, nodeaddr_t start, ++ size_t length, void *buf) +{ -+ raw1394handle_t handle; ++ struct allocation *allocation; + -+ handle = raw1394_new_handle(); -+ if (handle == NULL) -+ return NULL; ++ allocation = lookup_allocation(handle, start, 0); ++ if (allocation == NULL) { ++ errno = ENOENT; ++ return -1; ++ } + -+ if (raw1394_set_port(handle, port) < 0) -+ return NULL; ++ memcpy(allocation->data + allocation->offset - start, buf, length); + -+ return handle; ++ return 0; +} + -+int raw1394_busreset_notify (raw1394handle_t handle, int off_on_switch) ++int ++raw1394_arm_get_buf(raw1394handle_t handle, nodeaddr_t start, ++ size_t length, void *buf) +{ -+ handle->notify_bus_reset = off_on_switch; ++ struct allocation *allocation; + -+ return 0; -+} ++ allocation = lookup_allocation(handle, start, 0); ++ if (allocation == NULL) { ++ errno = ENOENT; ++ return -1; ++ } + -+int raw1394_get_fd(raw1394handle_t handle) -+{ -+ return handle->epoll_fd; -+} ++ memcpy(buf, allocation->data + allocation->offset - start, length); + -+void raw1394_set_userdata(raw1394handle_t handle, void *data) -+{ -+ handle->user_data = data; ++ return 0; +} + -+void *raw1394_get_userdata(raw1394handle_t handle) ++int ++raw1394_echo_request(raw1394handle_t handle, quadlet_t data) +{ -+ return handle->user_data; ++ return write(handle->pipe_fds[1], &data, sizeof data); +} + -+nodeid_t raw1394_get_local_id(raw1394handle_t handle) ++int raw1394_wake_up(raw1394handle_t handle) +{ -+ return handle->reset.local_node_id; ++ return raw1394_echo_request(handle, 0); +} + -+nodeid_t raw1394_get_irm_id(raw1394handle_t handle) ++int raw1394_phy_packet_write (raw1394handle_t handle, quadlet_t data) +{ -+ return handle->reset.irm_node_id; ++ errno = ENOSYS; ++ return -1; +} + -+int raw1394_get_nodecount(raw1394handle_t handle) ++int ++raw1394_start_phy_packet_write(raw1394handle_t handle, ++ quadlet_t data, unsigned long tag) +{ -+ return (handle->reset.root_node_id & 0x3f) + 1; ++ errno = ENOSYS; ++ return -1; +} + -+int raw1394_get_port_info(raw1394handle_t handle, -+ struct raw1394_portinfo *pinf, -+ int maxports) ++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 (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); ++ if (node > handle->reset.root_node_id) { ++ handle->err = -RCODE_NO_ACK; ++ errno = raw1394_errcode_to_errno(handle->err); ++ return -1; + } + -+ return handle->port_count; -+} ++ i = handle->nodes[node & 0x3f]; ++ if (i == -1) { ++ handle->err = -RCODE_NO_ACK; ++ errno = raw1394_errcode_to_errno(handle->err); ++ return -1; ++ } + -+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; ++ if (handle->generation != handle->devices[i].generation) { ++ handle->err = -RCODE_GENERATION; ++ errno = raw1394_errcode_to_errno(handle->err); + return -1; + } + -+ dir = opendir("/dev"); -+ if (dir == NULL) ++ closure = malloc(sizeof *closure); ++ if (closure == NULL) { ++ handle->err = -RCODE_SEND_ERROR; ++ errno = raw1394_errcode_to_errno(handle->err); + return -1; ++ } + -+ for (i = 0; i < MAX_DEVICES; ) { -+ de = readdir(dir); -+ if (de == NULL) -+ break; ++ closure->data = out; ++ closure->length = length; ++ closure->tag = tag; + -+ if (strncmp(de->d_name, "fw", 2) != 0) -+ continue; ++ 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); + -+ snprintf(filename, sizeof filename, "/dev/%s", de->d_name); ++ return ioctl(handle->devices[i].fd, FW_CDEV_IOC_SEND_REQUEST, request); ++} + -+ fd = open(filename, O_RDWR); -+ if (fd < 0) -+ continue; ++int ++raw1394_start_read(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr, ++ size_t length, quadlet_t *buffer, unsigned long tag) ++{ ++ int tcode; + -+ 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 (length == 4) ++ tcode = TCODE_READ_QUADLET_REQUEST; ++ else ++ tcode = TCODE_READ_BLOCK_REQUEST; + -+ if (get_info.card != handle->ports[port].card) { -+ close(fd); -+ continue; -+ } ++ return send_request(handle, tcode, ++ node, addr, length, NULL, buffer, tag); ++} + -+ 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); ++int ++raw1394_start_write(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr, ++ size_t length, quadlet_t *data, unsigned long tag) ++{ ++ int tcode; + -+ 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; -+ } ++ if (length == 4) ++ tcode = TCODE_WRITE_QUADLET_REQUEST; ++ else ++ tcode = TCODE_WRITE_BLOCK_REQUEST; + -+ 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); -+ } ++ return send_request(handle, tcode, ++ node, addr, length, data, NULL, tag); ++} + -+ i++; -+ } ++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]; + -+ return 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_reset_bus(raw1394handle_t handle) ++static int ++setup_lock64(int extcode, octlet_t data, octlet_t arg, octlet_t *buffer) +{ -+ return raw1394_reset_bus_new(handle, RAW1394_LONG_RESET); ++ 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_reset_bus_new(raw1394handle_t handle, int type) ++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) +{ -+ struct fw_cdev_initiate_bus_reset initiate; ++ quadlet_t buffer[2]; ++ int length; + -+ switch (type) { -+ case RAW1394_LONG_RESET: -+ initiate.type = FW_CDEV_LONG_RESET; -+ break; -+ case RAW1394_SHORT_RESET: -+ initiate.type = FW_CDEV_SHORT_RESET; -+ break; -+ } ++ length = setup_lock(extcode, data, arg, buffer); ++ if (length < 0) ++ return length; + -+ return ioctl(handle->local_fd, -+ FW_CDEV_IOC_INITIATE_BUS_RESET, &initiate); ++ return send_request(handle, 16 + extcode, ++ node, addr, length, buffer, result, tag); +} + -+bus_reset_handler_t raw1394_set_bus_reset_handler(raw1394handle_t handle, -+ bus_reset_handler_t new_h) ++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) +{ -+ bus_reset_handler_t old_h = handle->bus_reset_handler; ++ octlet_t buffer[2]; ++ int length; + -+ handle->bus_reset_handler = new_h; ++ length = setup_lock64(extcode, data, arg, buffer); ++ if (length < 0) ++ return length; + -+ return old_h; ++ return send_request(handle, 16 + extcode, ++ node, addr, length, buffer, result, tag); +} + -+unsigned int raw1394_get_generation(raw1394handle_t handle) ++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) +{ -+ return handle->generation; ++ /* FIXME: implement this? */ ++ return -1; +} + -+void raw1394_update_generation(raw1394handle_t handle, unsigned int generation) ++ ++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) +{ -+ handle->generation = generation; ++ /* FIXME: implement this? */ ++ return -1; +} + -+tag_handler_t -+raw1394_set_tag_handler(raw1394handle_t handle, tag_handler_t new_h) ++struct sync_data { ++ raw1394_errcode_t err; ++ int done; ++}; ++ ++static int ++sync_callback(raw1394handle_t handle, void *data, raw1394_errcode_t err) +{ -+ tag_handler_t old_h = handle->tag_handler; ++ struct sync_data *sd = data; + -+ handle->tag_handler = new_h; ++ sd->err = err; ++ sd->done = 1; + -+ return old_h; ++ return 0; +} + -+arm_tag_handler_t -+raw1394_set_arm_tag_handler(raw1394handle_t handle, arm_tag_handler_t new_h) ++static int ++send_request_sync(raw1394handle_t handle, int tcode, ++ nodeid_t node, nodeaddr_t addr, ++ size_t length, void *in, void *out) +{ -+ arm_tag_handler_t old_h = handle->arm_tag_handler; ++ struct raw1394_reqhandle reqhandle; ++ struct sync_data sd = { 0, 0 }; ++ int err; + -+ handle->arm_tag_handler = new_h; ++ reqhandle.callback = sync_callback; ++ reqhandle.data = &sd; + -+ return old_h; -+} ++ err = send_request(handle, tcode, node, addr, ++ length, in, out, (unsigned long) &reqhandle); + -+fcp_handler_t -+raw1394_set_fcp_handler(raw1394handle_t handle, fcp_handler_t new_h) -+{ -+ fcp_handler_t old_h = handle->fcp_handler; ++ while (!sd.done) { ++ if (err < 0) ++ return err; ++ err = raw1394_loop_iterate(handle); ++ } + -+ handle->fcp_handler = new_h; ++ handle->err = sd.err; ++ errno = raw1394_errcode_to_errno(sd.err); + -+ return old_h; ++ return (errno ? -1 : 0); +} + -+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) ++int ++raw1394_read(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr, ++ size_t length, quadlet_t *buffer) +{ -+ 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); ++ int tcode; + -+ type = RAW1394_ARM_WRITE; -+ in_length = request->length; -+ response.rcode = RCODE_COMPLETE; -+ response.length = 0; -+ response.data = 0; -+ break; ++ if (length == 4) ++ tcode = TCODE_READ_QUADLET_REQUEST; ++ else ++ tcode = TCODE_READ_BLOCK_REQUEST; + -+ case TCODE_READ_QUADLET_REQUEST: -+ case TCODE_READ_BLOCK_REQUEST: -+ printf("got read request, offset=0x%012llx, length=%d\n", -+ request->offset, request->length); ++ return send_request_sync(handle, tcode, ++ node, addr, length, NULL, buffer); ++} + -+ type = RAW1394_ARM_READ; -+ in_length = 0; -+ response.rcode = RCODE_COMPLETE; -+ response.length = request->length; -+ response.data = ptr_to_u64(allocation->data + offset); -+ break; ++int ++raw1394_write(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr, ++ size_t length, quadlet_t *data) ++{ ++ int tcode; + -+ case TCODE_LOCK_REQUEST: -+ type = RAW1394_ARM_LOCK; -+ in_length = request->length; -+ response.length = 4; -+ break; ++ if (length == 4) ++ tcode = TCODE_WRITE_QUADLET_REQUEST; ++ else ++ tcode = TCODE_WRITE_BLOCK_REQUEST; + -+ default: -+ in_length = 0; -+ type = 0; -+ break; -+ } ++ return send_request_sync(handle, tcode, ++ node, addr, length, data, NULL); ++} + -+ 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 */; ++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; + -+ if (ioctl(handle->devices[i].fd, -+ FW_CDEV_IOC_SEND_RESPONSE, &response) < 0) -+ return -1; -+ } ++ length = setup_lock(extcode, data, arg, buffer); ++ if (length < 0) ++ return length; + -+ if (!(allocation->notification_options & type)) -+ return 0; ++ return send_request_sync(handle, 16 + extcode, node, addr, ++ length, buffer, result); ++} + -+ rrb = malloc(sizeof *rrb + in_length + response.length); ++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; + -+ rrb->request_response.request = &rrb->request; -+ rrb->request_response.response = &rrb->response; ++ length = setup_lock64(extcode, data, arg, buffer); ++ if (length < 0) ++ return length; + -+ 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); ++ return send_request_sync(handle, 16 + extcode, node, addr, ++ length, buffer, result); ++} + -+ rrb->response.response_code = response.rcode; -+ rrb->response.buffer_length = response.length; -+ memcpy(rrb->response.buffer, -+ allocation->data + offset, response.length); ++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; ++} + -+ return handle->arm_tag_handler(handle, allocation->tag, type, -+ request->length, -+ &rrb->request_response); ++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_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) ++raw1394_start_fcp_listen(raw1394handle_t handle) +{ + struct fw_cdev_allocate request; -+ struct allocation *allocation; -+ int retval; ++ struct address_closure *closure; + -+ allocation = malloc(sizeof *allocation + length); -+ if (allocation == NULL) ++ closure = malloc(sizeof *closure); ++ if (closure == 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); ++ closure->callback = handle_fcp_request; + -+ retval = ioctl(handle->local_fd, FW_CDEV_IOC_ALLOCATE, &request); -+ if (retval < 0) { -+ free(allocation); ++ 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; -+ } + -+ allocation->handle = request.handle; -+ allocation->next = handle->allocations; -+ handle->allocations = allocation; ++ handle->fcp_allocation_handle = request.handle; + + 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) ++raw1394_stop_fcp_listen(raw1394handle_t handle) +{ + 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); ++ request.handle = handle->fcp_allocation_handle; + + 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) ++const char * ++raw1394_get_libversion(void) +{ -+ 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; ++ return VERSION " (Juju)"; +} + +int -+raw1394_arm_get_buf(raw1394handle_t handle, nodeaddr_t start, -+ size_t length, void *buf) ++raw1394_update_config_rom(raw1394handle_t handle, const quadlet_t *new_rom, ++ size_t size, unsigned char rom_version) +{ -+ 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; ++ return -1; +} + +int -+raw1394_echo_request(raw1394handle_t handle, quadlet_t data) ++raw1394_get_config_rom(raw1394handle_t handle, quadlet_t *buffer, ++ size_t buffersize, size_t *rom_size, ++ unsigned char *rom_version) +{ -+ return write(handle->pipe_fds[1], &data, sizeof data); -+} ++ struct fw_cdev_get_info get_info; ++ int err; + -+int raw1394_wake_up(raw1394handle_t handle) -+{ -+ return raw1394_echo_request(handle, 0); -+} ++ get_info.version = FW_CDEV_VERSION; ++ get_info.rom = ptr_to_u64(buffer); ++ get_info.rom_length = buffersize; ++ get_info.bus_reset = 0; + -+int raw1394_phy_packet_write (raw1394handle_t handle, quadlet_t data) -+{ -+ errno = ENOSYS; -+ return -1; ++ 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_start_phy_packet_write(raw1394handle_t handle, -+ quadlet_t data, unsigned long tag) ++raw1394_bandwidth_modify (raw1394handle_t handle, ++ unsigned int bandwidth, ++ enum raw1394_modify_mode mode) +{ -+ errno = ENOSYS; -+ return -1; -+} ++ quadlet_t buffer, compare, swap; ++ nodeaddr_t addr; ++ int result; + -+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 (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; + -+ if (node > handle->reset.root_node_id) { -+ handle->err = -RCODE_NO_ACK; -+ errno = raw1394_errcode_to_errno(handle->err); -+ return -1; -+ } ++ compare = ntohl (buffer); ++ switch (mode) { ++ case RAW1394_MODIFY_ALLOC: ++ swap = compare - bandwidth; ++ if (swap < 0) ++ return -1; ++ break; + -+ i = handle->nodes[node & 0x3f]; -+ if (i == -1) { -+ handle->err = -RCODE_NO_ACK; -+ errno = raw1394_errcode_to_errno(handle->err); ++ case RAW1394_MODIFY_FREE: ++ swap = compare + bandwidth; ++ if (swap > MAXIMUM_BANDWIDTH) ++ swap = MAXIMUM_BANDWIDTH; ++ break; ++ ++ default: + return -1; + } + -+ if (handle->generation != handle->devices[i].generation) { -+ handle->err = -RCODE_GENERATION; -+ errno = raw1394_errcode_to_errno(handle->err); ++ 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; ++} + -+ closure = malloc(sizeof *closure); -+ if (closure == NULL) { -+ handle->err = -RCODE_SEND_ERROR; -+ errno = raw1394_errcode_to_errno(handle->err); ++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; + -+ closure->data = out; -+ closure->length = length; -+ closure->tag = tag; ++ case RAW1394_MODIFY_FREE: ++ if ((buffer & bit) != 0) ++ return -1; ++ swap = buffer | bit; ++ break; + -+ 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); ++ default: ++ return -1; ++ } ++ ++ result = raw1394_lock (handle, raw1394_get_irm_id (handle), addr, ++ RAW1394_EXTCODE_COMPARE_SWAP, ++ htonl(swap), htonl(compare), &buffer); + -+ return ioctl(handle->devices[i].fd, FW_CDEV_IOC_SEND_REQUEST, request); ++ 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. ++ */ + -+int -+raw1394_start_read(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr, -+ size_t length, quadlet_t *buffer, unsigned long tag) ++#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) +{ -+ int tcode; ++ struct fw_cdev_queue_iso queue_iso; ++ struct fw_cdev_iso_packet *p; ++ int err; + -+ if (length == 4) -+ tcode = TCODE_READ_QUADLET_REQUEST; -+ else -+ tcode = TCODE_READ_BLOCK_REQUEST; ++ 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; + -+ return send_request(handle, tcode, -+ node, addr, length, NULL, buffer, tag); -+} ++ handle->iso.head += length; ++ handle->iso.packet_count++; ++ handle->iso.packet_phase++; ++ handle->iso.packet_index++; + -+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 (handle->iso.packet_phase == handle->iso.irq_interval) ++ handle->iso.packet_phase = 0; + -+ if (length == 4) -+ tcode = TCODE_WRITE_QUADLET_REQUEST; -+ else -+ tcode = TCODE_WRITE_BLOCK_REQUEST; ++ if (handle->iso.head + handle->iso.max_packet_size > handle->iso.buffer_end) ++ handle->iso.head = handle->iso.buffer; + -+ return send_request(handle, tcode, -+ node, addr, length, data, NULL, tag); ++ /* 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 -+setup_lock(int extcode, quadlet_t data, quadlet_t arg, quadlet_t *buffer) ++queue_xmit_packets(raw1394handle_t handle, int limit) +{ -+ switch (extcode) { -+ case RAW1394_EXTCODE_FETCH_ADD: -+ case RAW1394_EXTCODE_LITTLE_ADD: -+ buffer[0] = data; -+ return sizeof buffer[0]; ++ enum raw1394_iso_disposition d; ++ unsigned char tag, sy; ++ int len, cycle, dropped; + -+ 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]; ++ if (handle->iso.xmit_handler == NULL) ++ return 0; + -+ default: -+ errno = EINVAL; -+ return -1; ++ 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; +} + -+static int -+setup_lock64(int extcode, octlet_t data, octlet_t arg, octlet_t *buffer) ++int raw1394_iso_xmit_start(raw1394handle_t handle, int start_on_cycle, ++ int prebuffer_packets) +{ -+ switch (extcode) { -+ case RAW1394_EXTCODE_FETCH_ADD: -+ case RAW1394_EXTCODE_LITTLE_ADD: -+ buffer[0] = data; -+ return sizeof buffer[0]; ++ struct fw_cdev_start_iso start_iso; ++ int retval; + -+ 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]; ++ if (prebuffer_packets == -1) ++ prebuffer_packets = handle->iso.irq_interval; + -+ default: -+ errno = EINVAL; -+ return -1; ++ 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); +} + -+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) ++static int ++queue_recv_packets(raw1394handle_t handle) +{ -+ quadlet_t buffer[2]; -+ int length; -+ -+ length = setup_lock(extcode, data, arg, buffer); -+ if (length < 0) -+ return length; ++ while (handle->iso.packet_count <= handle->iso.buf_packets) ++ queue_packet(handle, handle->iso.max_packet_size, 4, 0, 0); + -+ return send_request(handle, 16 + extcode, -+ node, addr, length, buffer, result, tag); ++ return 0; +} -+ -+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) ++ ++static enum raw1394_iso_disposition ++flush_recv_packets(raw1394handle_t handle, ++ struct fw_cdev_event_iso_interrupt *interrupt) +{ -+ octlet_t buffer[2]; -+ int length; ++ 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; + -+ length = setup_lock64(extcode, data, arg, buffer); -+ if (length < 0) -+ return length; ++ case RAW1394_ISO_STOP: ++ raw1394_iso_stop(handle); ++ return 0; ++ } + -+ return send_request(handle, 16 + extcode, -+ node, addr, length, buffer, result, tag); ++ queue_recv_packets(handle); ++ ++ return 0; +} + -+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) ++int raw1394_iso_recv_start(raw1394handle_t handle, int start_on_cycle, ++ int tag_mask, int sync) +{ -+ /* FIXME: implement this? */ -+ return -1; -+} ++ struct fw_cdev_start_iso start_iso; + ++ queue_recv_packets(handle); + -+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; -+} ++ 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; + -+struct sync_data { -+ raw1394_errcode_t err; -+ int done; -+}; ++ return ioctl(handle->iso.fd, FW_CDEV_IOC_START_ISO, &start_iso); ++} + -+static int -+sync_callback(raw1394handle_t handle, void *data, raw1394_errcode_t err) ++static int handle_iso_event(raw1394handle_t handle, ++ struct epoll_closure *closure, __uint32_t events) +{ -+ struct sync_data *sd = data; ++ struct fw_cdev_event_iso_interrupt *interrupt; ++ int len; + -+ sd->err = err; -+ sd->done = 1; ++ len = read(handle->iso.fd, handle->buffer, sizeof handle->buffer); ++ if (len < 0) ++ return -1; + -+ return 0; ++ 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; ++ } +} + -+static int -+send_request_sync(raw1394handle_t handle, int tcode, -+ nodeid_t node, nodeaddr_t addr, -+ size_t length, void *in, void *out) ++int raw1394_iso_xmit_write(raw1394handle_t handle, unsigned char *data, ++ unsigned int len, unsigned char tag, ++ unsigned char sy) +{ -+ struct raw1394_reqhandle reqhandle; -+ struct sync_data sd = { 0, 0 }; -+ int err; ++ struct fw_cdev_queue_iso queue_iso; ++ struct fw_cdev_start_iso start_iso; ++ struct fw_cdev_iso_packet *p; + -+ reqhandle.callback = sync_callback; -+ reqhandle.data = &sd; ++ if (len > handle->iso.max_packet_size) { ++ errno = EINVAL; ++ return -1; ++ } + -+ err = send_request(handle, tcode, node, addr, -+ length, in, out, (unsigned long) &reqhandle); ++ /* 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; + -+ while (!sd.done) { -+ if (err < 0) -+ return err; -+ err = raw1394_loop_iterate(handle); -+ } ++ /* 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; + -+ handle->err = sd.err; -+ errno = raw1394_errcode_to_errno(sd.err); ++ len = ioctl(handle->iso.fd, ++ FW_CDEV_IOC_START_ISO, &start_iso); ++ if (len < 0) ++ return len; ++ } + -+ return (errno ? -1 : 0); ++ return 0; +} + -+int -+raw1394_read(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr, -+ size_t length, quadlet_t *buffer) ++int raw1394_iso_xmit_sync(raw1394handle_t handle) +{ -+ int tcode; ++ struct fw_cdev_iso_packet skip; ++ struct fw_cdev_queue_iso queue_iso; ++ int len; + -+ if (length == 4) -+ tcode = TCODE_READ_QUADLET_REQUEST; -+ else -+ tcode = TCODE_READ_BLOCK_REQUEST; ++ skip.payload_length = 0; ++ skip.interrupt = 1; ++ skip.skip = 1; ++ skip.tag = 0; ++ skip.sy = 0; ++ skip.header_length = 0; + -+ return send_request_sync(handle, tcode, -+ node, addr, length, NULL, buffer); ++ 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_write(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr, -+ size_t length, quadlet_t *data) ++int raw1394_iso_recv_flush(raw1394handle_t handle) +{ -+ int tcode; -+ -+ if (length == 4) -+ tcode = TCODE_WRITE_QUADLET_REQUEST; -+ else -+ tcode = TCODE_WRITE_BLOCK_REQUEST; ++ /* FIXME: huh, we'll need kernel support here... */ + -+ return send_request_sync(handle, tcode, -+ node, addr, length, data, NULL); ++ return 0; +} + -+int -+raw1394_lock(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr, -+ unsigned int extcode, quadlet_t data, quadlet_t arg, -+ quadlet_t *result) ++static unsigned int ++round_to_power_of_two(unsigned int value) +{ -+ quadlet_t buffer[2]; -+ size_t length; ++ unsigned int pot; + -+ length = setup_lock(extcode, data, arg, buffer); -+ if (length < 0) -+ return length; ++ pot = 1; ++ while (pot < value) ++ pot <<= 1; + -+ return send_request_sync(handle, 16 + extcode, node, addr, -+ length, buffer, result); ++ return pot; +} + -+int -+raw1394_lock64(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr, -+ unsigned int extcode, octlet_t data, octlet_t arg, -+ octlet_t *result) ++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) +{ -+ octlet_t buffer[2]; -+ size_t length; ++ struct fw_cdev_create_iso_context create; ++ struct epoll_event ep; ++ int retval, prot; + -+ length = setup_lock64(extcode, data, arg, buffer); -+ if (length < 0) -+ return length; ++ if (handle->iso.fd != -1) { ++ errno = EBUSY; ++ return -1; ++ } + -+ return send_request_sync(handle, 16 + extcode, node, addr, -+ length, buffer, result); -+} ++ 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; + -+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; -+} ++ handle->iso.fd = open(handle->local_filename, O_RDWR); ++ if (handle->iso.fd < 0) { ++ free(handle->iso.packets); ++ 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; -+} ++ 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; ++ } + -+int -+raw1394_start_fcp_listen(raw1394handle_t handle) -+{ -+ struct fw_cdev_allocate request; -+ struct address_closure *closure; ++ create.type = type; ++ create.channel = channel; ++ create.speed = speed; ++ create.header_size = 4; + -+ closure = malloc(sizeof *closure); -+ if (closure == NULL) -+ return -1; ++ 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; ++ } + -+ closure->callback = handle_fcp_request; ++ handle->iso.buffer = ++ mmap(NULL, buf_packets * max_packet_size, ++ prot, MAP_SHARED, handle->iso.fd, 0); + -+ 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) ++ if (handle->iso.buffer == MAP_FAILED) { ++ close(handle->iso.fd); ++ free(handle->iso.packets); + return -1; ++ } + -+ handle->fcp_allocation_handle = request.handle; ++ 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_stop_fcp_listen(raw1394handle_t handle) ++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) +{ -+ struct fw_cdev_deallocate request; -+ -+ request.handle = handle->fcp_allocation_handle; -+ -+ return ioctl(handle->local_fd, FW_CDEV_IOC_DEALLOCATE, &request); ++ return iso_init(handle, FW_CDEV_ISO_CONTEXT_TRANSMIT, ++ handler, NULL, buf_packets, max_packet_size, ++ channel, speed, irq_interval); +} + -+const char * -+raw1394_get_libversion(void) ++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 VERSION " (Juju)"; ++ return iso_init(handle, FW_CDEV_ISO_CONTEXT_RECEIVE, ++ NULL, handler, buf_packets, max_packet_size, ++ channel, 0, irq_interval); +} + -+int -+raw1394_update_config_rom(raw1394handle_t handle, const quadlet_t *new_rom, -+ size_t size, unsigned char rom_version) ++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_get_config_rom(raw1394handle_t handle, quadlet_t *buffer, -+ size_t buffersize, size_t *rom_size, -+ unsigned char *rom_version) ++int raw1394_iso_recv_listen_channel(raw1394handle_t handle, ++ unsigned char channel) +{ -+ 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; ++ /* FIXME: multichannel */ ++ errno = ENOSYS; ++ return -1; +} + -+#define MAXIMUM_BANDWIDTH 4915 -+ -+int -+raw1394_bandwidth_modify (raw1394handle_t handle, -+ unsigned int bandwidth, -+ enum raw1394_modify_mode mode) ++int raw1394_iso_recv_unlisten_channel(raw1394handle_t handle, ++ unsigned char channel) +{ -+ 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; -+ } ++ /* FIXME: multichannel */ ++ errno = ENOSYS; ++ 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_iso_recv_set_channel_mask(raw1394handle_t handle, u_int64_t mask) ++{ ++ /* FIXME: multichannel */ ++ errno = ENOSYS; ++ return -1; +} + -+int -+raw1394_channel_modify (raw1394handle_t handle, -+ unsigned int channel, -+ enum raw1394_modify_mode mode) ++void raw1394_iso_stop(raw1394handle_t handle) +{ -+ 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; ++ struct fw_cdev_stop_iso stop_iso; + -+ case RAW1394_MODIFY_FREE: -+ if ((buffer & bit) != 0) -+ return -1; -+ swap = buffer | bit; -+ break; ++ stop_iso.handle = 0; ++ ioctl(handle->iso.fd, FW_CDEV_IOC_STOP_ISO); + -+ default: -+ return -1; -+ } -+ -+ result = raw1394_lock (handle, raw1394_get_irm_id (handle), addr, -+ RAW1394_EXTCODE_COMPARE_SWAP, -+ htonl(swap), htonl(compare), &buffer); ++ 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; ++} + -+ if (result < 0 || ntohl(buffer) != compare) -+ return -1; -+ -+ return 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 --git a/tools/Makefile.am b/tools/Makefile.am -index 29b250e..5be1b6f 100644 ---- a/tools/Makefile.am -+++ b/tools/Makefile.am +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 --git a/tools/testlibraw.c b/tools/testlibraw.c -index 5f73bd9..2f02a6d 100644 ---- a/tools/testlibraw.c -+++ b/tools/testlibraw.c +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 -*- @@ -2225,7 +2214,7 @@ index 5f73bd9..2f02a6d 100644 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 handle, unsigned long tag, +@@ -45,12 +47,18 @@ int my_tag_handler(raw1394handle_t handl return 0; } @@ -2244,7 +2233,7 @@ index 5f73bd9..2f02a6d 100644 while (length) { printf(" %02x", *data); data++; -@@ -62,6 +70,47 @@ int my_fcp_handler(raw1394handle_t handle, nodeid_t nodeid, int response, +@@ -62,6 +70,47 @@ int my_fcp_handler(raw1394handle_t handl return 0; } diff --git a/libraw1394-underquoted.patch b/libraw1394-underquoted.patch deleted file mode 100644 index a1e677d..0000000 --- a/libraw1394-underquoted.patch +++ /dev/null @@ -1,47 +0,0 @@ ---- libraw1394-0.10.1/libraw1394.m4.underquoted 2004-07-15 12:59:11.467143881 +0100 -+++ libraw1394-0.10.1/libraw1394.m4 2004-07-15 12:59:57.705291918 +0100 -@@ -3,7 +3,7 @@ - dnl This just unconditionally sets the options. It should offer an option for - dnl explicitly giving the path to libraw1394 on the configure command line. - dnl --AC_DEFUN(AC_LIB_RAW1394_FLAGS, [ -+AC_DEFUN([AC_LIB_RAW1394_FLAGS], [ - LIBRAW1394_CPPFLAGS="" - LIBRAW1394_CFLAGS="" - LIBRAW1394_LIBS="-lraw1394" -@@ -16,7 +16,7 @@ - dnl - dnl AC_LIB_RAW1394_HEADERS([ACTION_IF_FOUND[,ACTION_IF_NOT_FOUND]]) - dnl --AC_DEFUN(AC_LIB_RAW1394_HEADERS, [ -+AC_DEFUN([AC_LIB_RAW1394_HEADERS], [ - AC_REQUIRE([AC_LIB_RAW1394_FLAGS]) - - ac_libraw1394_save_cppflags=$CPPFLAGS -@@ -38,7 +38,7 @@ - dnl - dnl AC_LIB_RAW1394_LIBVERSION(MINIMUMVERSION[,ACTION_IF_FOUND[,ACTION_IF_NOT_FOUND]]) - dnl --AC_DEFUN(AC_LIB_RAW1394_LIBVERSION, [ -+AC_DEFUN([AC_LIB_RAW1394_LIBVERSION], [ - AC_REQUIRE([AC_PROG_CC]) - AC_REQUIRE([AC_LIB_RAW1394_FLAGS]) - -@@ -72,7 +72,7 @@ - dnl - dnl AC_LIB_RAW1394_RUNTEST(MINIMUMVERSION[,ACTION_IF_FOUND - dnl [,ACTION_IF_NOT_FOUND[,ACTION_IF_CROSS_COMPILING]]]) --AC_DEFUN(AC_LIB_RAW1394_RUNTEST, [ -+AC_DEFUN([AC_LIB_RAW1394_RUNTEST], [ - ac_libraw1394_save_cppflags=$CPPFLAGS - ac_libraw1394_save_cflags=$CFLAGS - ac_libraw1394_save_libs=$LIBS -@@ -135,7 +135,7 @@ - dnl Versions before 0.9 can't be checked, so this will always fail if the - dnl installed libraw1394 is older than 0.9 as if the library weren't found. - dnl --AC_DEFUN(AC_LIB_RAW1394, [ -+AC_DEFUN([AC_LIB_RAW1394], [ - - AC_LIB_RAW1394_FLAGS - AC_LIB_RAW1394_HEADERS(ac_libraw1394_found=yes, ac_libraw1394_found=no) diff --git a/libraw1394.spec b/libraw1394.spec index ed7b49a..c12b991 100644 --- a/libraw1394.spec +++ b/libraw1394.spec @@ -1,7 +1,7 @@ Summary: Library providing low-level IEEE-1394 access Name: libraw1394 -Version: 1.2.1 -Release: 10%{?dist} +Version: 1.3.0 +Release: 1%{?dist} License: LGPL Group: System Environment/Libraries Source: http://www.linux1394.org/dl/libraw1394-%{version}.tar.gz @@ -77,6 +77,9 @@ rm -rf $RPM_BUILD_ROOT %changelog +* Thu Oct 18 2007 Jarod Wilson - 1.3.0-1 +- libraw1394 v1.3.0 + * Wed Aug 29 2007 Fedora Release Engineering - 1.2.1-10 - Rebuild for selinux ppc32 issue. diff --git a/sources b/sources index 09a25fe..23e349f 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -e6210ff05b7f4ec0401ad3d11f493e1a libraw1394-1.2.1.tar.gz +c5d9ab62bd25dba96af010b3471e816a libraw1394-1.3.0.tar.gz