if (request.channel > 63)
return -EINVAL;
+ if (request.sync > 15)
+ return -EINVAL;
+
+ if (request.tags == 0 || request.tags > 15)
+ return -EINVAL;
+
if (request.speed > SCODE_3200)
return -EINVAL;
request.channel,
request.speed,
request.header_size,
+ request.sync,
+ request.tags,
iso_callback, client);
if (IS_ERR(client->iso_context))
return PTR_ERR(client->iso_context);
if (__copy_from_user
(u.packet.header, p->header, header_length))
return -EFAULT;
- if (u.packet.skip &&
+ if (u.packet.skip && ctx->type == FW_ISO_CONTEXT_TRANSMIT &&
u.packet.header_length + u.packet.payload_length > 0)
return -EINVAL;
if (payload + u.packet.payload_length > payload_end)
#define FW_CDEV_ISO_CONTEXT_TRANSMIT 0
#define FW_CDEV_ISO_CONTEXT_RECEIVE 1
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG0 1
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG1 2
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG2 4
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG3 8
+#define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS 15
+
struct fw_cdev_create_iso_context {
__u32 type;
__u32 header_size;
__u32 channel;
__u32 speed;
+ __u32 sync;
+ __u32 tags;
};
struct fw_cdev_iso_packet {
struct fw_iso_context *
fw_iso_context_create(struct fw_card *card, int type,
- int channel, int speed, size_t header_size,
+ int channel, int speed,
+ int sync, int tags, size_t header_size,
fw_iso_callback_t callback, void *callback_data)
{
struct fw_iso_context *ctx;
- ctx = card->driver->allocate_iso_context(card, type, header_size);
+ ctx = card->driver->allocate_iso_context(card, type,
+ sync, tags, header_size);
if (IS_ERR(ctx))
return ctx;
ctx->type = type;
ctx->channel = channel;
ctx->speed = speed;
+ ctx->sync = sync;
+ ctx->tags = tags;
ctx->header_size = header_size;
ctx->callback = callback;
ctx->callback_data = callback_data;
}
static struct fw_iso_context *
-ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size)
+ohci_allocate_iso_context(struct fw_card *card, int type,
+ int sync, int tags, size_t header_size)
{
struct fw_ohci *ohci = fw_ohci(card);
struct iso_context *ctx, *list;
reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index);
reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index);
reg_write(ohci, context_match(ctx->context.regs),
- 0xf0000000 | ctx->base.channel);
+ (ctx->base.tags << 28) |
+ (ctx->base.sync << 8) | ctx->base.channel);
context_run(&ctx->context, mode);
}
return 0;
}
+
+static int
+setup_wait_descriptor(struct context *ctx)
+{
+ struct descriptor *d;
+ dma_addr_t d_bus;
+
+ d = context_get_descriptors(ctx, 1, &d_bus);
+ if (d == NULL)
+ return -ENOMEM;
+
+ d->control = cpu_to_le16(descriptor_input_more |
+ descriptor_status |
+ descriptor_branch_always |
+ descriptor_wait);
+
+ context_append(ctx, d, 1, 0);
+
+ return 0;
+}
static int
ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
/* FIXME: Cycle lost behavior should be configurable: lose
* packet, retransmit or terminate.. */
+ if (packet->skip && setup_wait_descriptor(&ctx->context) < 0)
+ return -ENOMEM;
+
p = packet;
z = 2;
offset = payload & ~PAGE_MASK;
rest = packet->payload_length;
+ if (packet->skip && setup_wait_descriptor(&ctx->context) < 0)
+ return -ENOMEM;
+
while (rest > 0) {
d = context_get_descriptors(&ctx->context, 1, &d_bus);
if (d == NULL)
#define FW_ISO_CONTEXT_TRANSMIT 0
#define FW_ISO_CONTEXT_RECEIVE 1
+#define FW_ISO_CONTEXT_MATCH_TAG0 1
+#define FW_ISO_CONTEXT_MATCH_TAG1 2
+#define FW_ISO_CONTEXT_MATCH_TAG2 4
+#define FW_ISO_CONTEXT_MATCH_TAG3 8
+#define FW_ISO_CONTEXT_MATCH_ALL_TAGS 15
+
struct fw_iso_context;
typedef void (*fw_iso_callback_t) (struct fw_iso_context *context,
int type;
int channel;
int speed;
+ int sync;
+ int tags;
size_t header_size;
fw_iso_callback_t callback;
void *callback_data;
struct fw_iso_context *
fw_iso_context_create(struct fw_card *card, int type,
- int channel, int speed, size_t header_size,
+ int channel, int speed,
+ int sync, int tags, size_t header_size,
fw_iso_callback_t callback, void *callback_data);
void
int node_id, int generation);
struct fw_iso_context *
- (*allocate_iso_context)(struct fw_card *card,
+ (*allocate_iso_context)(struct fw_card *card, int sync, int tags,
int type, size_t header_size);
void (*free_iso_context)(struct fw_iso_context *ctx);