diff options
author | Jay Fenlason, Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-01-04 15:23:29 (GMT) |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-03-24 19:56:44 (GMT) |
commit | acfe8333572cad5dc70fce18ac966be0446548d7 (patch) | |
tree | 7402f2c6759465c351d735855990620e24a644e2 | |
parent | 33580a3ef5ba3bc0ee1b520df82a24bb37ce28f0 (diff) | |
download | linux-acfe8333572cad5dc70fce18ac966be0446548d7.tar.xz |
firewire: cdev: add ioctl for broadcast write requests
Write transactions to the broadcast node ID are a convenient way to
trigger functions of multiple nodes at once. IIDC is a protocol which
can make use of this if multiple cameras with same command_regs_base are
connected at the same bus.
Based on
Date: Wed, 10 Sep 2008 11:32:16 -0400
From: Jay Fenlason <fenlason@redhat.com>
Subject: [patch] SEND_BROADCAST_REQUEST
Changes: ioctl_send_request() and ioctl_send_broadcast_request() now
share code. Broadcast speed corrected to S100. Check for proper tcode.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
-rw-r--r-- | drivers/firewire/fw-cdev.c | 74 | ||||
-rw-r--r-- | include/linux/firewire-cdev.h | 1 |
2 files changed, 48 insertions, 27 deletions
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 05ad2a8..a1637a8 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c @@ -518,10 +518,10 @@ static void complete_transaction(struct fw_card *card, int rcode, client_put(client); } -static int ioctl_send_request(struct client *client, void *buffer) +static int init_request(struct client *client, + struct fw_cdev_send_request *request, + int destination_id, int speed) { - struct fw_device *device = client->device; - struct fw_cdev_send_request *request = buffer; struct outbound_transaction_event *e; int ret; @@ -544,24 +544,6 @@ static int ioctl_send_request(struct client *client, void *buffer) goto failed; } - switch (request->tcode) { - case TCODE_WRITE_QUADLET_REQUEST: - case TCODE_WRITE_BLOCK_REQUEST: - case TCODE_READ_QUADLET_REQUEST: - case TCODE_READ_BLOCK_REQUEST: - case TCODE_LOCK_MASK_SWAP: - case TCODE_LOCK_COMPARE_SWAP: - case TCODE_LOCK_FETCH_ADD: - case TCODE_LOCK_LITTLE_ADD: - case TCODE_LOCK_BOUNDED_ADD: - case TCODE_LOCK_WRAP_ADD: - case TCODE_LOCK_VENDOR_DEPENDENT: - break; - default: - ret = -EINVAL; - goto failed; - } - e->r.resource.release = release_transaction; ret = add_client_resource(client, &e->r.resource, GFP_KERNEL); if (ret < 0) @@ -570,12 +552,9 @@ static int ioctl_send_request(struct client *client, void *buffer) /* Get a reference for the transaction callback */ client_get(client); - fw_send_request(device->card, &e->r.transaction, - request->tcode & 0x1f, - device->node->node_id, - request->generation, - device->max_speed, - request->offset, + fw_send_request(client->device->card, &e->r.transaction, + request->tcode & 0x1f, destination_id, + request->generation, speed, request->offset, e->response.data, request->length, complete_transaction, e); @@ -589,6 +568,31 @@ static int ioctl_send_request(struct client *client, void *buffer) return ret; } +static int ioctl_send_request(struct client *client, void *buffer) +{ + struct fw_cdev_send_request *request = buffer; + + switch (request->tcode) { + case TCODE_WRITE_QUADLET_REQUEST: + case TCODE_WRITE_BLOCK_REQUEST: + case TCODE_READ_QUADLET_REQUEST: + case TCODE_READ_BLOCK_REQUEST: + case TCODE_LOCK_MASK_SWAP: + case TCODE_LOCK_COMPARE_SWAP: + case TCODE_LOCK_FETCH_ADD: + case TCODE_LOCK_LITTLE_ADD: + case TCODE_LOCK_BOUNDED_ADD: + case TCODE_LOCK_WRAP_ADD: + case TCODE_LOCK_VENDOR_DEPENDENT: + break; + default: + return -EINVAL; + } + + return init_request(client, request, client->device->node->node_id, + client->device->max_speed); +} + static void release_request(struct client *client, struct client_resource *resource) { @@ -1229,6 +1233,21 @@ static int ioctl_get_speed(struct client *client, void *buffer) return 0; } +static int ioctl_send_broadcast_request(struct client *client, void *buffer) +{ + struct fw_cdev_send_request *request = buffer; + + switch (request->tcode) { + case TCODE_WRITE_QUADLET_REQUEST: + case TCODE_WRITE_BLOCK_REQUEST: + break; + default: + return -EINVAL; + } + + return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100); +} + static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { ioctl_get_info, ioctl_send_request, @@ -1248,6 +1267,7 @@ static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { ioctl_allocate_iso_resource_once, ioctl_deallocate_iso_resource_once, ioctl_get_speed, + ioctl_send_broadcast_request, }; static int dispatch_ioctl(struct client *client, diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index f819c10..340a785 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -230,6 +230,7 @@ union fw_cdev_event { #define FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE _IOW('#', 0x0f, struct fw_cdev_allocate_iso_resource) #define FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE_ONCE _IOW('#', 0x10, struct fw_cdev_allocate_iso_resource) #define FW_CDEV_IOC_GET_SPEED _IOR('#', 0x11, struct fw_cdev_get_speed) +#define FW_CDEV_IOC_SEND_BROADCAST_REQUEST _IOW('#', 0x12, struct fw_cdev_send_request) /* FW_CDEV_VERSION History * |