diff --git a/src/Makefile.am b/src/Makefile.am index c40ac89..cfaae51 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,6 +10,7 @@ libraw1394_la_SOURCES = \ eventloop.c \ readwrite.c \ iso.c \ + fcp.c \ kernel-raw1394.h \ raw1394_private.h diff --git a/src/eventloop.c b/src/eventloop.c index 62f5202..e898ba7 100644 --- a/src/eventloop.c +++ b/src/eventloop.c @@ -36,6 +36,15 @@ int raw1394_loop_iterate(struct raw1394_handle *handle) } break; + case RAW1394_REQ_FCP_REQUEST: + if (handle->fcp_handler) { + retval = handle->fcp_handler(handle, req->misc & 0xffff, + req->misc >> 16, + req->length, + (char *)handle->buffer); + } + break; + default: if (handle->tag_handler) { retval = handle->tag_handler(handle, req->tag, @@ -90,3 +99,14 @@ iso_handler_t raw1394_set_iso_handler(struct raw1394_handle *handle, handle->iso_handler[channel] = new; return NULL; } + +fcp_handler_t raw1394_set_fcp_handler(struct raw1394_handle *handle, + fcp_handler_t new) +{ + fcp_handler_t old; + + old = handle->fcp_handler; + handle->fcp_handler = new; + + return old; +} diff --git a/src/fcp.c b/src/fcp.c new file mode 100644 index 0000000..e3c0800 --- /dev/null +++ b/src/fcp.c @@ -0,0 +1,53 @@ + +#include +#include + +#include "raw1394.h" +#include "kernel-raw1394.h" +#include "raw1394_private.h" + +static int do_fcp_listen(struct raw1394_handle *handle) +{ + struct sync_cb_data sd = { 0, 0 }; + struct raw1394_reqhandle rh = { (req_callback_t)_raw1394_sync_cb, &sd }; + int err; + struct raw1394_request *req = &handle->req; + + CLEAR_REQ(req); + req->type = RAW1394_REQ_FCP_LISTEN; + req->generation = handle->generation; + req->misc = 0; + req->tag = (unsigned long)&rh; + req->recvb = handle->buffer; + req->length = 512; + + err = write(handle->fd, req, sizeof(*req)); + while (!sd.done) { + if (err < 0) return err; + err = raw1394_loop_iterate(handle); + } + + switch (sd.errcode) { + case RAW1394_ERROR_ALREADY: + errno = EALREADY; + return -1; + + case RAW1394_ERROR_INVALID_ARG: + errno = EINVAL; + return -1; + + default: + errno = 0; + return sd.errcode; + } +} + +int raw1394_start_fcp_listen(struct raw1394_handle *handle) +{ + return do_fcp_listen(handle); +} + +int raw1394_stop_fcp_listen(struct raw1394_handle *handle) +{ + return do_fcp_listen(handle); +} diff --git a/src/kernel-raw1394.h b/src/kernel-raw1394.h index b1b0e4b..f23bfc0 100644 --- a/src/kernel-raw1394.h +++ b/src/kernel-raw1394.h @@ -5,7 +5,7 @@ #define RAW1394_DEVICE_MAJOR 171 #define RAW1394_DEVICE_NAME "raw1394" -#define RAW1394_KERNELAPI_VERSION 1 +#define RAW1394_KERNELAPI_VERSION 2 /* state: opened */ #define RAW1394_REQ_INITIALIZE 1 @@ -21,10 +21,12 @@ #define RAW1394_REQ_LOCK64 103 #define RAW1394_REQ_ISO_LISTEN 200 +#define RAW1394_REQ_FCP_LISTEN 201 /* kernel to user */ #define RAW1394_REQ_BUS_RESET 10000 #define RAW1394_REQ_ISO_RECEIVE 10001 +#define RAW1394_REQ_FCP_REQUEST 10002 /* error codes */ #define RAW1394_ERROR_NONE 0 @@ -67,6 +69,7 @@ struct raw1394_khost_list { struct iso_block_store { atomic_t refcount; + size_t data_size; quadlet_t data[0]; }; @@ -83,6 +86,8 @@ struct file_info { spinlock_t reqlists_lock; wait_queue_head_t poll_wait_complete; + u8 *fcp_buffer; + u64 listen_channels; quadlet_t *iso_buffer; size_t iso_buffer_length; diff --git a/src/raw1394.h b/src/raw1394.h index 81abb0a..899cd5a 100644 --- a/src/raw1394.h +++ b/src/raw1394.h @@ -104,6 +104,16 @@ iso_handler_t raw1394_set_iso_handler(raw1394handle_t handle, unsigned int channel, iso_handler_t new_h); +/* + * Set the handler that will be called when the local FCP_COMMAND or + * FCP_RESPONSE register gets written to. Returns old handler. + * + * The handler arg nodeid contains the node ID of the writer. If response is 0 + * FCP_COMMAND was written, FCP_RESPONSE otherwise. + */ +typedef int (*fcp_handler_t)(raw1394handle_t, nodeid_t nodeid, int response, + size_t length, unsigned char *data); +fcp_handler_t raw1394_set_fcp_handlet(raw1394handle_t, fcp_handler_t); /* * This is the general request handle. It is used by the default tag handler @@ -147,6 +157,13 @@ int raw1394_lock(struct raw1394_handle *handle, nodeid_t node, nodeaddr_t addr, int raw1394_start_iso_rcv(raw1394handle_t handle, unsigned int channel); int raw1394_stop_iso_rcv(raw1394handle_t handle, unsigned int channel); +/* + * Start and stop receiving requests sent to the local FCP_COMMAND and + * FCP_RESPONSE registers. + */ +int raw1394_start_fcp_listen(struct raw1394_handle *handle); +int raw1394_stop_fcp_listen(struct raw1394_handle *handle); + #ifdef __cplusplus } #endif diff --git a/src/raw1394_private.h b/src/raw1394_private.h index 570bc00..e8440b8 100644 --- a/src/raw1394_private.h +++ b/src/raw1394_private.h @@ -11,6 +11,7 @@ struct raw1394_handle { bus_reset_handler_t bus_reset_handler; tag_handler_t tag_handler; + fcp_handler_t fcp_handler; iso_handler_t iso_handler[64]; struct raw1394_request req;