aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2007-02-16 17:34:51 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-03-09 16:03:04 -0500
commit98b6cbe83b6e8db54638746c9040c7962d96b322 (patch)
treead9d7587a5dde5510b402da8681e8c3d150d7ca5 /drivers
parent21efb3cfc6ed49991638000f58bb23b838c76e25 (diff)
firewire: Implement sync and tag matching for isochronous receive.
Signed-off-by: Kristian Høgsberg <krh@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/firewire/fw-device-cdev.c10
-rw-r--r--drivers/firewire/fw-device-cdev.h8
-rw-r--r--drivers/firewire/fw-iso.c8
-rw-r--r--drivers/firewire/fw-ohci.c32
-rw-r--r--drivers/firewire/fw-transaction.h13
5 files changed, 64 insertions, 7 deletions
diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c
index 5c876188677f..33fe5768a078 100644
--- a/drivers/firewire/fw-device-cdev.c
+++ b/drivers/firewire/fw-device-cdev.c
@@ -416,6 +416,12 @@ static int ioctl_create_iso_context(struct client *client, void __user *arg)
416 if (request.channel > 63) 416 if (request.channel > 63)
417 return -EINVAL; 417 return -EINVAL;
418 418
419 if (request.sync > 15)
420 return -EINVAL;
421
422 if (request.tags == 0 || request.tags > 15)
423 return -EINVAL;
424
419 if (request.speed > SCODE_3200) 425 if (request.speed > SCODE_3200)
420 return -EINVAL; 426 return -EINVAL;
421 427
@@ -424,6 +430,8 @@ static int ioctl_create_iso_context(struct client *client, void __user *arg)
424 request.channel, 430 request.channel,
425 request.speed, 431 request.speed,
426 request.header_size, 432 request.header_size,
433 request.sync,
434 request.tags,
427 iso_callback, client); 435 iso_callback, client);
428 if (IS_ERR(client->iso_context)) 436 if (IS_ERR(client->iso_context))
429 return PTR_ERR(client->iso_context); 437 return PTR_ERR(client->iso_context);
@@ -495,7 +503,7 @@ static int ioctl_queue_iso(struct client *client, void __user *arg)
495 if (__copy_from_user 503 if (__copy_from_user
496 (u.packet.header, p->header, header_length)) 504 (u.packet.header, p->header, header_length))
497 return -EFAULT; 505 return -EFAULT;
498 if (u.packet.skip && 506 if (u.packet.skip && ctx->type == FW_ISO_CONTEXT_TRANSMIT &&
499 u.packet.header_length + u.packet.payload_length > 0) 507 u.packet.header_length + u.packet.payload_length > 0)
500 return -EINVAL; 508 return -EINVAL;
501 if (payload + u.packet.payload_length > payload_end) 509 if (payload + u.packet.payload_length > payload_end)
diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h
index 99e6aa629f4a..739f54fe08cf 100644
--- a/drivers/firewire/fw-device-cdev.h
+++ b/drivers/firewire/fw-device-cdev.h
@@ -131,11 +131,19 @@ struct fw_cdev_allocate {
131#define FW_CDEV_ISO_CONTEXT_TRANSMIT 0 131#define FW_CDEV_ISO_CONTEXT_TRANSMIT 0
132#define FW_CDEV_ISO_CONTEXT_RECEIVE 1 132#define FW_CDEV_ISO_CONTEXT_RECEIVE 1
133 133
134#define FW_CDEV_ISO_CONTEXT_MATCH_TAG0 1
135#define FW_CDEV_ISO_CONTEXT_MATCH_TAG1 2
136#define FW_CDEV_ISO_CONTEXT_MATCH_TAG2 4
137#define FW_CDEV_ISO_CONTEXT_MATCH_TAG3 8
138#define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS 15
139
134struct fw_cdev_create_iso_context { 140struct fw_cdev_create_iso_context {
135 __u32 type; 141 __u32 type;
136 __u32 header_size; 142 __u32 header_size;
137 __u32 channel; 143 __u32 channel;
138 __u32 speed; 144 __u32 speed;
145 __u32 sync;
146 __u32 tags;
139}; 147};
140 148
141struct fw_cdev_iso_packet { 149struct fw_cdev_iso_packet {
diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c
index dc5a7e3558ec..728cbb3ee91d 100644
--- a/drivers/firewire/fw-iso.c
+++ b/drivers/firewire/fw-iso.c
@@ -107,12 +107,14 @@ void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer,
107 107
108struct fw_iso_context * 108struct fw_iso_context *
109fw_iso_context_create(struct fw_card *card, int type, 109fw_iso_context_create(struct fw_card *card, int type,
110 int channel, int speed, size_t header_size, 110 int channel, int speed,
111 int sync, int tags, size_t header_size,
111 fw_iso_callback_t callback, void *callback_data) 112 fw_iso_callback_t callback, void *callback_data)
112{ 113{
113 struct fw_iso_context *ctx; 114 struct fw_iso_context *ctx;
114 115
115 ctx = card->driver->allocate_iso_context(card, type, header_size); 116 ctx = card->driver->allocate_iso_context(card, type,
117 sync, tags, header_size);
116 if (IS_ERR(ctx)) 118 if (IS_ERR(ctx))
117 return ctx; 119 return ctx;
118 120
@@ -120,6 +122,8 @@ fw_iso_context_create(struct fw_card *card, int type,
120 ctx->type = type; 122 ctx->type = type;
121 ctx->channel = channel; 123 ctx->channel = channel;
122 ctx->speed = speed; 124 ctx->speed = speed;
125 ctx->sync = sync;
126 ctx->tags = tags;
123 ctx->header_size = header_size; 127 ctx->header_size = header_size;
124 ctx->callback = callback; 128 ctx->callback = callback;
125 ctx->callback_data = callback_data; 129 ctx->callback_data = callback_data;
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 0088acd7718e..ea43a5ed18cf 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -1337,7 +1337,8 @@ static int handle_it_packet(struct context *context,
1337} 1337}
1338 1338
1339static struct fw_iso_context * 1339static struct fw_iso_context *
1340ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) 1340ohci_allocate_iso_context(struct fw_card *card, int type,
1341 int sync, int tags, size_t header_size)
1341{ 1342{
1342 struct fw_ohci *ohci = fw_ohci(card); 1343 struct fw_ohci *ohci = fw_ohci(card);
1343 struct iso_context *ctx, *list; 1344 struct iso_context *ctx, *list;
@@ -1427,7 +1428,8 @@ static int ohci_start_iso(struct fw_iso_context *base, s32 cycle)
1427 reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index); 1428 reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index);
1428 reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index); 1429 reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index);
1429 reg_write(ohci, context_match(ctx->context.regs), 1430 reg_write(ohci, context_match(ctx->context.regs),
1430 0xf0000000 | ctx->base.channel); 1431 (ctx->base.tags << 28) |
1432 (ctx->base.sync << 8) | ctx->base.channel);
1431 context_run(&ctx->context, mode); 1433 context_run(&ctx->context, mode);
1432 } 1434 }
1433 1435
@@ -1573,6 +1575,26 @@ ohci_queue_iso_transmit(struct fw_iso_context *base,
1573 1575
1574 return 0; 1576 return 0;
1575} 1577}
1578
1579static int
1580setup_wait_descriptor(struct context *ctx)
1581{
1582 struct descriptor *d;
1583 dma_addr_t d_bus;
1584
1585 d = context_get_descriptors(ctx, 1, &d_bus);
1586 if (d == NULL)
1587 return -ENOMEM;
1588
1589 d->control = cpu_to_le16(descriptor_input_more |
1590 descriptor_status |
1591 descriptor_branch_always |
1592 descriptor_wait);
1593
1594 context_append(ctx, d, 1, 0);
1595
1596 return 0;
1597}
1576 1598
1577static int 1599static int
1578ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, 1600ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
@@ -1591,6 +1613,9 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
1591 /* FIXME: Cycle lost behavior should be configurable: lose 1613 /* FIXME: Cycle lost behavior should be configurable: lose
1592 * packet, retransmit or terminate.. */ 1614 * packet, retransmit or terminate.. */
1593 1615
1616 if (packet->skip && setup_wait_descriptor(&ctx->context) < 0)
1617 return -ENOMEM;
1618
1594 p = packet; 1619 p = packet;
1595 z = 2; 1620 z = 2;
1596 1621
@@ -1655,6 +1680,9 @@ ohci_queue_iso_receive_bufferfill(struct fw_iso_context *base,
1655 offset = payload & ~PAGE_MASK; 1680 offset = payload & ~PAGE_MASK;
1656 rest = packet->payload_length; 1681 rest = packet->payload_length;
1657 1682
1683 if (packet->skip && setup_wait_descriptor(&ctx->context) < 0)
1684 return -ENOMEM;
1685
1658 while (rest > 0) { 1686 while (rest > 0) {
1659 d = context_get_descriptors(&ctx->context, 1, &d_bus); 1687 d = context_get_descriptors(&ctx->context, 1, &d_bus);
1660 if (d == NULL) 1688 if (d == NULL)
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index 22e45ccd7b1d..cbea845dc40a 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -332,6 +332,12 @@ struct fw_iso_packet {
332#define FW_ISO_CONTEXT_TRANSMIT 0 332#define FW_ISO_CONTEXT_TRANSMIT 0
333#define FW_ISO_CONTEXT_RECEIVE 1 333#define FW_ISO_CONTEXT_RECEIVE 1
334 334
335#define FW_ISO_CONTEXT_MATCH_TAG0 1
336#define FW_ISO_CONTEXT_MATCH_TAG1 2
337#define FW_ISO_CONTEXT_MATCH_TAG2 4
338#define FW_ISO_CONTEXT_MATCH_TAG3 8
339#define FW_ISO_CONTEXT_MATCH_ALL_TAGS 15
340
335struct fw_iso_context; 341struct fw_iso_context;
336 342
337typedef void (*fw_iso_callback_t) (struct fw_iso_context *context, 343typedef void (*fw_iso_callback_t) (struct fw_iso_context *context,
@@ -357,6 +363,8 @@ struct fw_iso_context {
357 int type; 363 int type;
358 int channel; 364 int channel;
359 int speed; 365 int speed;
366 int sync;
367 int tags;
360 size_t header_size; 368 size_t header_size;
361 fw_iso_callback_t callback; 369 fw_iso_callback_t callback;
362 void *callback_data; 370 void *callback_data;
@@ -374,7 +382,8 @@ fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card);
374 382
375struct fw_iso_context * 383struct fw_iso_context *
376fw_iso_context_create(struct fw_card *card, int type, 384fw_iso_context_create(struct fw_card *card, int type,
377 int channel, int speed, size_t header_size, 385 int channel, int speed,
386 int sync, int tags, size_t header_size,
378 fw_iso_callback_t callback, void *callback_data); 387 fw_iso_callback_t callback, void *callback_data);
379 388
380void 389void
@@ -425,7 +434,7 @@ struct fw_card_driver {
425 int node_id, int generation); 434 int node_id, int generation);
426 435
427 struct fw_iso_context * 436 struct fw_iso_context *
428 (*allocate_iso_context)(struct fw_card *card, 437 (*allocate_iso_context)(struct fw_card *card, int sync, int tags,
429 int type, size_t header_size); 438 int type, size_t header_size);
430 void (*free_iso_context)(struct fw_iso_context *ctx); 439 void (*free_iso_context)(struct fw_iso_context *ctx);
431 440