summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar ddennedy 2002-11-18 07:40:21 +0000
committerGravatar ddennedy 2002-11-18 07:40:21 +0000
commitb9de121a85abef26f07da8d55530964eb9797f17 (patch)
tree7321424534f5afcc1cf3671a9afff9dc567aa443
parentadded missing arm.c from weihs branch (diff)
merged rawiso branch
git-svn-id: svn://svn.linux1394.org/libraw1394/trunk@93 53a565d1-3bb7-0310-b661-cf11e63c67ab
Diffstat (limited to '')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/eventloop.c6
-rw-r--r--src/iso.c329
-rw-r--r--src/kernel-raw1394.h70
-rw-r--r--src/main.c12
-rw-r--r--src/raw1394.h60
-rw-r--r--src/raw1394_private.h15
7 files changed, 488 insertions, 6 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index b6a0140..ea1acd1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,4 +18,4 @@ libraw1394_la_SOURCES = \
raw1394_private.h
# headers to be installed
-pkginclude_HEADERS = raw1394.h csr.h ieee1394.h kernel-raw1394.h
+pkginclude_HEADERS = raw1394.h csr.h ieee1394.h
diff --git a/src/eventloop.c b/src/eventloop.c
index 4eb83b6..c360a63 100644
--- a/src/eventloop.c
+++ b/src/eventloop.c
@@ -94,9 +94,15 @@ int raw1394_loop_iterate(struct raw1394_handle *handle)
int2ptr(req->recvb));
}
break;
+
case RAW1394_REQ_ECHO:
retval=req->misc;
break;
+
+ case RAW1394_REQ_RAWISO_ACTIVITY:
+ retval = _raw1394_iso_iterate(handle);
+ break;
+
default:
if (handle->tag_handler) {
retval = handle->tag_handler(handle, req->tag,
diff --git a/src/iso.c b/src/iso.c
index 3d7131e..007d72c 100644
--- a/src/iso.c
+++ b/src/iso.c
@@ -2,6 +2,7 @@
* libraw1394 - library for raw access to the 1394 bus with the Linux subsystem.
*
* Copyright (C) 1999,2000,2001,2002 Andreas Bombe
+ * new ISO API by Dan Maas
*
* This library is licensed under the GNU Lesser General Public License (LGPL),
* version 2.1 or later. See the file COPYING.LIB in the distribution for
@@ -11,11 +12,15 @@
#include <config.h>
#include <errno.h>
#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
#include "raw1394.h"
#include "kernel-raw1394.h"
#include "raw1394_private.h"
+/* old ISO API - kept for backwards compatibility */
static int do_iso_listen(struct raw1394_handle *handle, int channel)
{
@@ -86,3 +91,327 @@ int raw1394_stop_iso_rcv(struct raw1394_handle *handle, unsigned int channel)
return do_iso_listen(handle, ~channel);
}
+
+
+
+/* new ISO API */
+
+
+/* reset the dropped counter each time it is seen */
+static unsigned int _raw1394_iso_dropped(raw1394handle_t handle)
+{
+ unsigned int retval = handle->iso_packets_dropped;
+ handle->iso_packets_dropped = 0;
+ return retval;
+}
+
+
+/* common code for iso_xmit_init and iso_recv_init */
+static int do_iso_init(raw1394handle_t handle,
+ unsigned int buf_packets,
+ unsigned int max_packet_size,
+ int channel,
+ enum raw1394_iso_speed speed,
+ int irq_interval,
+ int xmit)
+{
+ size_t pgsize;
+
+ /* already initialized? */
+ if(handle->iso_buffer)
+ return -1;
+
+ handle->iso_status.config.buf_packets = buf_packets;
+ handle->iso_status.config.max_packet_size = max_packet_size;
+ handle->iso_status.config.channel = channel;
+ handle->iso_status.config.speed = speed;
+ handle->iso_status.config.irq_interval = irq_interval;
+
+ if(ioctl(handle->fd, xmit ? RAW1394_ISO_XMIT_INIT : RAW1394_ISO_RECV_INIT, &handle->iso_status))
+ return -1;
+
+ handle->iso_buffer_bytes = handle->iso_status.config.buf_packets * handle->iso_status.buf_stride;
+
+ /* make sure buffer is a multiple of the page size (for mmap) */
+ pgsize = getpagesize();
+ if(handle->iso_buffer_bytes % pgsize)
+ handle->iso_buffer_bytes += pgsize - (handle->iso_buffer_bytes % pgsize);
+
+ /* mmap the DMA buffer */
+ handle->iso_buffer = mmap(NULL, handle->iso_buffer_bytes, PROT_READ | PROT_WRITE,
+ MAP_SHARED, handle->fd, 0);
+
+ if(handle->iso_buffer == (unsigned char*) MAP_FAILED) {
+ handle->iso_buffer = NULL;
+ ioctl(handle->fd, RAW1394_ISO_SHUTDOWN, 0);
+ return -1;
+ }
+
+ handle->iso_status.overflows = 0;
+ handle->iso_packets_dropped = 0;
+
+ handle->iso_xmit_handler = NULL;
+ handle->iso_recv_handler = NULL;
+
+ return 0;
+}
+
+/**
+ * raw1394_iso_xmit_init - initialize isochronous transmission
+ * @handler: handler function for queueing packets
+ * @buf_packets: number of isochronous packets to buffer
+ * @max_packet_size: largest packet you need to handle, in bytes (not including the 8-byte isochronous header)
+ * @channel: isochronous channel on which to transmit
+ * @speed: speed at which to transmit
+ * @irq_interval: maximum latency of wake-ups, in packets (-1 if you don't care)
+ *
+ * Allocates all user and kernel resources necessary for isochronous transmission.
+ **/
+int raw1394_iso_xmit_init(raw1394handle_t handle,
+ raw1394_iso_xmit_handler_t handler,
+ unsigned int buf_packets,
+ unsigned int max_packet_size,
+ int channel,
+ enum raw1394_iso_speed speed,
+ int irq_interval)
+{
+ if(do_iso_init(handle, buf_packets, max_packet_size, channel, speed, irq_interval, 1))
+ return -1;
+
+ handle->iso_xmit_handler = handler;
+ return 0;
+}
+
+/**
+ * raw1394_iso_recv_init - initialize isochronous reception
+ * @handler: handler function for receiving packets
+ * @buf_packets: number of isochronous packets to buffer
+ * @max_packet_size: largest packet you need to handle, in bytes (not including the 8-byte isochronous header)
+ * @channel: isochronous channel to receive
+ * @speed: speed at which to receive
+ * @irq_interval: maximum latency of wake-ups, in packets (-1 if you don't care)
+ *
+ * Allocates all user and kernel resources necessary for isochronous reception.
+ **/
+int raw1394_iso_recv_init(raw1394handle_t handle,
+ raw1394_iso_recv_handler_t handler,
+ unsigned int buf_packets,
+ unsigned int max_packet_size,
+ int channel,
+ int irq_interval)
+{
+ /* any speed will work */
+ if(do_iso_init(handle, buf_packets, max_packet_size, channel, RAW1394_ISO_SPEED_100, irq_interval, 0))
+ return -1;
+
+ handle->iso_recv_handler = handler;
+ return 0;
+}
+
+/**
+ * raw1394_iso_recv_start - begin isochronous reception
+ * @start_on_cycle: isochronous cycle number on which to start (-1 if you don't care)
+ **/
+int raw1394_iso_recv_start(raw1394handle_t handle, int start_on_cycle)
+{
+ if(!handle->iso_buffer)
+ return -1;
+ if(!handle->iso_recv_handler)
+ return -1;
+
+ if(ioctl(handle->fd, RAW1394_ISO_RECV_START, start_on_cycle))
+ return -1;
+
+ return 0;
+}
+
+
+static int _raw1394_iso_xmit_queue_packets(raw1394handle_t handle)
+{
+ struct raw1394_iso_status *stat = &handle->iso_status;
+ int retval = 0, packets_done = 0;
+
+ if(!handle->iso_buffer)
+ return -1;
+
+ if(!handle->iso_xmit_handler)
+ return -1;
+
+ while(stat->n_packets > 0) {
+ enum raw1394_iso_disposition disp;
+ unsigned char *packet_data;
+ struct raw1394_iso_packet_info *info;
+ unsigned int len;
+ unsigned char tag, sy;
+
+ packet_data = handle->iso_buffer + stat->first_packet * stat->buf_stride
+ + stat->packet_data_offset;
+
+ info = (struct raw1394_iso_packet_info*) (handle->iso_buffer
+ + stat->first_packet * stat->buf_stride
+ + stat->packet_info_offset);
+
+ /* call handler */
+ disp = handle->iso_xmit_handler(handle,
+ packet_data,
+ &len, &tag, &sy,
+ info->cycle,
+ _raw1394_iso_dropped(handle));
+
+ /* check if packet is too long */
+ if(len > stat->config.max_packet_size) {
+ retval = -1;
+ break;
+ }
+
+ /* set packet metadata */
+ info->len = len;
+ info->tag = tag;
+ info->sy = sy;
+
+ /* advance packet cursors and cycle counter */
+ stat->n_packets--;
+ stat->first_packet = (stat->first_packet + 1) % stat->config.buf_packets;
+ packets_done++;
+
+ if(disp == RAW1394_ISO_DEFER) {
+ break;
+ } else if(disp == RAW1394_ISO_ERROR) {
+ retval = -1;
+ break;
+ }
+ }
+
+ if(packets_done > 0) {
+ if(ioctl(handle->fd, RAW1394_ISO_PRODUCE_CONSUME, packets_done))
+ return -1;
+ }
+
+ return retval;
+}
+
+
+/**
+ * raw1394_iso_xmit_start - begin isochronous transmission
+ * @start_on_cycle: isochronous cycle number on which to start (-1 if you don't care)
+ * @prebuffer_packets: number of packets to queue up before starting transmission (-1 if you don't care)
+ **/
+int raw1394_iso_xmit_start(raw1394handle_t handle, int start_on_cycle, int prebuffer_packets)
+{
+ int args[2];
+
+ if(!handle->iso_buffer)
+ return -1;
+ if(!handle->iso_xmit_handler)
+ return -1;
+
+ args[0] = start_on_cycle;
+ args[1] = prebuffer_packets;
+
+ if(ioctl(handle->fd, RAW1394_ISO_XMIT_START, &args[0]))
+ return -1;
+
+ return 0;
+}
+
+/**
+ * raw1394_iso_stop - halt isochronous transmission or reception
+ **/
+void raw1394_iso_stop(raw1394handle_t handle)
+{
+ if(!handle->iso_buffer)
+ return;
+
+ ioctl(handle->fd, RAW1394_ISO_STOP, 0);
+}
+
+/**
+ * raw1394_iso_shutdown - clean up and deallocate all resources for isochronous transmission or reception
+ **/
+void raw1394_iso_shutdown(raw1394handle_t handle)
+{
+ if(handle->iso_buffer) {
+ raw1394_iso_stop(handle);
+ munmap(handle->iso_buffer, handle->iso_buffer_bytes);
+ ioctl(handle->fd, RAW1394_ISO_SHUTDOWN, 0);
+ handle->iso_buffer = NULL;
+ }
+}
+
+static int _raw1394_iso_recv_packets(raw1394handle_t handle)
+{
+ struct raw1394_iso_status *stat = &handle->iso_status;
+ struct raw1394_iso_packet_info *info;
+
+ int retval = 0, packets_done = 0;
+
+ if(!handle->iso_buffer)
+ return -1;
+
+ if(!handle->iso_recv_handler)
+ return -1;
+
+ while(stat->n_packets > 0) {
+ unsigned char *packet_data;
+ struct raw1394_iso_packet_info *info;
+ enum raw1394_iso_disposition disp;
+
+ packet_data = handle->iso_buffer + stat->first_packet * stat->buf_stride
+ + stat->packet_data_offset;
+
+ info = (struct raw1394_iso_packet_info*) (handle->iso_buffer
+ + stat->first_packet * stat->buf_stride
+ + stat->packet_info_offset);
+
+ /* call handler */
+ disp = handle->iso_recv_handler(handle,
+ packet_data,
+ info->len, info->channel,
+ info->tag, info->sy,
+ info->cycle,
+ _raw1394_iso_dropped(handle));
+
+ /* advance packet cursors */
+ stat->n_packets--;
+ stat->first_packet = (stat->first_packet + 1) % stat->config.buf_packets;
+ packets_done++;
+
+ if(disp == RAW1394_ISO_DEFER) {
+ break;
+ } else if(disp == RAW1394_ISO_ERROR) {
+ retval = -1;
+ break;
+ }
+ }
+
+ if(packets_done > 0) {
+ if(ioctl(handle->fd, RAW1394_ISO_PRODUCE_CONSUME, packets_done))
+ return -1;
+ }
+
+ return retval;
+}
+
+/* run the ISO state machine; called from raw1394_loop_iterate() */
+int _raw1394_iso_iterate(raw1394handle_t handle)
+{
+ int err;
+
+ if(!handle->iso_buffer)
+ return 0;
+
+ err = ioctl(handle->fd, RAW1394_ISO_GET_STATUS, &handle->iso_status);
+ if(err != 0)
+ return err;
+
+ handle->iso_packets_dropped += handle->iso_status.overflows;
+
+ if(handle->iso_xmit_handler) {
+ return _raw1394_iso_xmit_queue_packets(handle);
+ } else if(handle->iso_recv_handler) {
+ return _raw1394_iso_recv_packets(handle);
+ }
+
+ return 0;
+}
+
diff --git a/src/kernel-raw1394.h b/src/kernel-raw1394.h
index 1fe55d0..c6e5c59 100644
--- a/src/kernel-raw1394.h
+++ b/src/kernel-raw1394.h
@@ -40,6 +40,7 @@
#define RAW1394_REQ_ISO_RECEIVE 10001
#define RAW1394_REQ_FCP_REQUEST 10002
#define RAW1394_REQ_ARM 10003
+#define RAW1394_REQ_RAWISO_ACTIVITY 10004
/* error codes */
#define RAW1394_ERROR_NONE 0
@@ -118,6 +119,64 @@ typedef struct arm_request_response {
*/
+/* rawiso API */
+
+/* ioctls */
+#define RAW1394_ISO_XMIT_INIT 1 /* arg: raw1394_iso_status* */
+#define RAW1394_ISO_RECV_INIT 2 /* arg: raw1394_iso_status* */
+#define RAW1394_ISO_RECV_START 3 /* arg: int, starting cycle */
+#define RAW1394_ISO_XMIT_START 8 /* arg: int[2], { starting cycle, prebuffer } */
+#define RAW1394_ISO_STOP 4
+#define RAW1394_ISO_GET_STATUS 5 /* arg: raw1394_iso_status* */
+#define RAW1394_ISO_PRODUCE_CONSUME 6 /* arg: int, # of packets */
+#define RAW1394_ISO_SHUTDOWN 7
+
+/* per-packet metadata embedded in the ringbuffer */
+/* must be identical to hpsb_iso_packet_info in iso.h! */
+struct raw1394_iso_packet_info {
+ unsigned short len;
+ unsigned short cycle;
+ unsigned char channel; /* recv only */
+ unsigned char tag;
+ unsigned char sy;
+};
+
+struct raw1394_iso_config {
+ unsigned int buf_packets;
+ unsigned int max_packet_size;
+ int channel;
+ int speed; /* xmit only */
+ int irq_interval;
+};
+
+/* argument to RAW1394_ISO_XMIT/RECV_INIT and RAW1394_ISO_GET_STATUS */
+struct raw1394_iso_status {
+ /* current settings */
+ struct raw1394_iso_config config;
+
+ /* byte offset between successive packets in the buffer */
+ int buf_stride;
+
+ /* byte offset of data payload within each packet */
+ int packet_data_offset;
+
+ /* byte offset of struct iso_packet_info within each packet */
+ int packet_info_offset;
+
+ /* index of next packet to fill with data (ISO transmission)
+ or next packet containing data recieved (ISO reception) */
+ unsigned int first_packet;
+
+ /* number of packets waiting to be filled with data (ISO transmission)
+ or containing data received (ISO reception) */
+ unsigned int n_packets;
+
+ /* approximate number of packets dropped due to overflow or
+ underflow of the packet buffer (a value of zero guarantees
+ that no packets have been dropped) */
+ unsigned int overflows;
+};
+
#ifdef __KERNEL__
struct iso_block_store {
@@ -126,6 +185,10 @@ struct iso_block_store {
quadlet_t data[0];
};
+enum raw1394_iso_state { RAW1394_ISO_INACTIVE = 0,
+ RAW1394_ISO_RECV = 1,
+ RAW1394_ISO_XMIT = 2 };
+
struct file_info {
struct list_head list;
@@ -144,11 +207,16 @@ struct file_info {
u8 *fcp_buffer;
+ /* old ISO API */
u64 listen_channels;
quadlet_t *iso_buffer;
size_t iso_buffer_length;
u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */
+
+ /* new rawiso API */
+ enum raw1394_iso_state iso_state;
+ struct hpsb_iso *iso_handle;
};
struct arm_addr {
@@ -166,7 +234,7 @@ struct pending_request {
struct list_head list;
struct file_info *file_info;
struct hpsb_packet *packet;
- struct tq_struct tq;
+/* struct tq_struct tq; */
struct iso_block_store *ibs;
quadlet_t *data;
int free_data;
diff --git a/src/main.c b/src/main.c
index 7bb847a..b1c69f8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -149,6 +149,7 @@ struct raw1394_handle *raw1394_new_handle(void)
handle->tag_handler = tag_handler_default;
handle->arm_tag_handler = arm_tag_handler_default;
memset(handle->iso_handler, 0, sizeof(handle->iso_handler));
+ handle->iso_buffer = NULL;
return handle;
}
@@ -162,10 +163,13 @@ struct raw1394_handle *raw1394_new_handle(void)
**/
void raw1394_destroy_handle(struct raw1394_handle *handle)
{
- if (handle) {
- close(handle->fd);
- free(handle);
- }
+ if (handle) {
+ if(handle->iso_buffer) {
+ raw1394_iso_shutdown(handle);
+ }
+ close(handle->fd);
+ free(handle);
+ }
}
/**
diff --git a/src/raw1394.h b/src/raw1394.h
index c1f7b16..4c317bc 100644
--- a/src/raw1394.h
+++ b/src/raw1394.h
@@ -47,6 +47,66 @@ typedef struct arm_request_response {
struct arm_response *response;
} *arm_request_response_t;
+/* new ISO API */
+
+enum raw1394_iso_speed {
+ RAW1394_ISO_SPEED_100 = 0,
+ RAW1394_ISO_SPEED_200 = 1,
+ RAW1394_ISO_SPEED_400 = 2,
+};
+
+/* return values from xmit/recv handlers */
+
+enum raw1394_iso_disposition {
+ /* continue on to the next packet */
+ RAW1394_ISO_OK = 0,
+
+ /* no error, but return from raw1394_loop_iterate() immediately */
+ RAW1394_ISO_DEFER = 1,
+
+ /* return from raw1394_loop_iterate() immediately, which will return an error */
+ RAW1394_ISO_ERROR = 2,
+};
+
+typedef int (*raw1394_iso_xmit_handler_t)(raw1394handle_t,
+ unsigned char *data,
+ unsigned int *len,
+ unsigned char *tag,
+ unsigned char *sy,
+ unsigned int cycle,
+ unsigned int dropped);
+
+typedef int (*raw1394_iso_recv_handler_t)(raw1394handle_t,
+ unsigned char *data,
+ unsigned int len,
+ unsigned char channel,
+ unsigned char tag,
+ unsigned char sy,
+ unsigned int cycle,
+ unsigned int dropped);
+
+int raw1394_iso_xmit_init(raw1394handle_t handle,
+ raw1394_iso_xmit_handler_t handler,
+ unsigned int buf_packets,
+ unsigned int max_packet_size,
+ int channel,
+ enum raw1394_iso_speed speed,
+ int irq_interval);
+
+int raw1394_iso_recv_init(raw1394handle_t handle,
+ raw1394_iso_recv_handler_t handler,
+ unsigned int buf_packets,
+ unsigned int max_packet_size,
+ int channel,
+ int irq_interval);
+
+
+int raw1394_iso_xmit_start(raw1394handle_t handle, int start_on_cycle, int prebuffer_packets);
+int raw1394_iso_recv_start(raw1394handle_t handle, int start_on_cycle);
+
+void raw1394_iso_stop(raw1394handle_t handle);
+void raw1394_iso_shutdown(raw1394handle_t handle);
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/src/raw1394_private.h b/src/raw1394_private.h
index 733feae..9c0b345 100644
--- a/src/raw1394_private.h
+++ b/src/raw1394_private.h
@@ -23,6 +23,20 @@ struct raw1394_handle {
fcp_handler_t fcp_handler;
iso_handler_t iso_handler[64];
+ /* new ISO API */
+
+ /* memory mapping of the DMA buffer */
+ unsigned char *iso_buffer;
+ unsigned long iso_buffer_bytes;
+
+ /* status buffer, updated from _raw1394_iso_iterate() */
+ struct raw1394_iso_status iso_status;
+ unsigned int iso_packets_dropped;
+
+ /* user-supplied handlers */
+ raw1394_iso_xmit_handler_t iso_xmit_handler;
+ raw1394_iso_recv_handler_t iso_recv_handler;
+
struct raw1394_request req;
quadlet_t buffer[HBUF_SIZE/4]; /* 2048 */
};
@@ -33,6 +47,7 @@ struct sync_cb_data {
};
int _raw1394_sync_cb(struct raw1394_handle*, struct sync_cb_data*, int);
+int _raw1394_iso_iterate(raw1394handle_t handle);
#define CLEAR_REQ(reqp) memset((reqp), 0, sizeof(struct raw1394_request))