diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-07-29 12:19:22 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-07-29 17:09:18 -0400 |
commit | 872e330e38806d835bd6c311c93ab998e2fb9058 (patch) | |
tree | 92497ce79b1157761b1aebdb63b8d74f68d42c15 /include/linux/firewire.h | |
parent | ae2a97661482c1d0f1aa41b837da95054d0e9a1b (diff) |
firewire: add isochronous multichannel reception
This adds the DMA context programming and userspace ABI for multichannel
reception, i.e. for listening on multiple channel numbers by means of a
single DMA context.
The use case is reception of more streams than there are IR DMA units
offered by the link layer. This is already implemented by the older
ohci1394 + ieee1394 + raw1394 stack. And as discussed recently on
linux1394-devel, this feature is occasionally used in practice.
The big drawbacks of this mode are that buffer layout and interrupt
generation necessarily differ from single-channel reception: Headers
and trailers are not stripped from packets, packets are not aligned with
buffer chunks, interrupts are per buffer chunk, not per packet.
These drawbacks also cause a rather hefty code footprint to support this
rarely used OHCI-1394 feature. (367 lines added, among them 94 lines of
added userspace ABI documentation.)
This implementation enforces that a multichannel reception context may
only listen to channels to which no single-channel context on the same
link layer is presently listening to. OHCI-1394 would allow to overlay
single-channel contexts by the multi-channel context, but this would be
a departure from the present first-come-first-served policy of IR
context creation.
The implementation is heavily based on an earlier one by Jay Fenlason.
Thanks Jay.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'include/linux/firewire.h')
-rw-r--r-- | include/linux/firewire.h | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/include/linux/firewire.h b/include/linux/firewire.h index d974aa4a24c9..1cd637ef62d2 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h | |||
@@ -372,17 +372,19 @@ void fw_core_remove_descriptor(struct fw_descriptor *desc); | |||
372 | * scatter-gather streaming (e.g. assembling video frame automatically). | 372 | * scatter-gather streaming (e.g. assembling video frame automatically). |
373 | */ | 373 | */ |
374 | struct fw_iso_packet { | 374 | struct fw_iso_packet { |
375 | u16 payload_length; /* Length of indirect payload. */ | 375 | u16 payload_length; /* Length of indirect payload */ |
376 | u32 interrupt:1; /* Generate interrupt on this packet */ | 376 | u32 interrupt:1; /* Generate interrupt on this packet */ |
377 | u32 skip:1; /* Set to not send packet at all. */ | 377 | u32 skip:1; /* tx: Set to not send packet at all */ |
378 | u32 tag:2; | 378 | /* rx: Sync bit, wait for matching sy */ |
379 | u32 sy:4; | 379 | u32 tag:2; /* tx: Tag in packet header */ |
380 | u32 header_length:8; /* Length of immediate header. */ | 380 | u32 sy:4; /* tx: Sy in packet header */ |
381 | u32 header[0]; | 381 | u32 header_length:8; /* Length of immediate header */ |
382 | u32 header[0]; /* tx: Top of 1394 isoch. data_block */ | ||
382 | }; | 383 | }; |
383 | 384 | ||
384 | #define FW_ISO_CONTEXT_TRANSMIT 0 | 385 | #define FW_ISO_CONTEXT_TRANSMIT 0 |
385 | #define FW_ISO_CONTEXT_RECEIVE 1 | 386 | #define FW_ISO_CONTEXT_RECEIVE 1 |
387 | #define FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL 2 | ||
386 | 388 | ||
387 | #define FW_ISO_CONTEXT_MATCH_TAG0 1 | 389 | #define FW_ISO_CONTEXT_MATCH_TAG0 1 |
388 | #define FW_ISO_CONTEXT_MATCH_TAG1 2 | 390 | #define FW_ISO_CONTEXT_MATCH_TAG1 2 |
@@ -406,24 +408,31 @@ struct fw_iso_buffer { | |||
406 | int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, | 408 | int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, |
407 | int page_count, enum dma_data_direction direction); | 409 | int page_count, enum dma_data_direction direction); |
408 | void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card); | 410 | void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card); |
411 | size_t fw_iso_buffer_lookup(struct fw_iso_buffer *buffer, dma_addr_t completed); | ||
409 | 412 | ||
410 | struct fw_iso_context; | 413 | struct fw_iso_context; |
411 | typedef void (*fw_iso_callback_t)(struct fw_iso_context *context, | 414 | typedef void (*fw_iso_callback_t)(struct fw_iso_context *context, |
412 | u32 cycle, size_t header_length, | 415 | u32 cycle, size_t header_length, |
413 | void *header, void *data); | 416 | void *header, void *data); |
417 | typedef void (*fw_iso_mc_callback_t)(struct fw_iso_context *context, | ||
418 | dma_addr_t completed, void *data); | ||
414 | struct fw_iso_context { | 419 | struct fw_iso_context { |
415 | struct fw_card *card; | 420 | struct fw_card *card; |
416 | int type; | 421 | int type; |
417 | int channel; | 422 | int channel; |
418 | int speed; | 423 | int speed; |
419 | size_t header_size; | 424 | size_t header_size; |
420 | fw_iso_callback_t callback; | 425 | union { |
426 | fw_iso_callback_t sc; | ||
427 | fw_iso_mc_callback_t mc; | ||
428 | } callback; | ||
421 | void *callback_data; | 429 | void *callback_data; |
422 | }; | 430 | }; |
423 | 431 | ||
424 | struct fw_iso_context *fw_iso_context_create(struct fw_card *card, | 432 | struct fw_iso_context *fw_iso_context_create(struct fw_card *card, |
425 | int type, int channel, int speed, size_t header_size, | 433 | int type, int channel, int speed, size_t header_size, |
426 | fw_iso_callback_t callback, void *callback_data); | 434 | fw_iso_callback_t callback, void *callback_data); |
435 | int fw_iso_context_set_channels(struct fw_iso_context *ctx, u64 *channels); | ||
427 | int fw_iso_context_queue(struct fw_iso_context *ctx, | 436 | int fw_iso_context_queue(struct fw_iso_context *ctx, |
428 | struct fw_iso_packet *packet, | 437 | struct fw_iso_packet *packet, |
429 | struct fw_iso_buffer *buffer, | 438 | struct fw_iso_buffer *buffer, |