From 604f45167824e18ad5766e51ecf1d4d65f15118d Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 20 Jun 2010 22:52:55 +0200 Subject: firewire: cdev: freeze FW_CDEV_VERSION due to libraw1394 bug libraw1394 v2.0.0...v2.0.5 takes FW_CDEV_VERSION from an externally installed header file and uses it to declare its own implementation level in FW_CDEV_IOC_GET_INFO. This is wrong; it should set the real version for which it was actually written. If we add features to the kernel ABI that require the kernel to check a client's implementation level, we can not trust the client version if it was set from FW_CDEV_VERSION. Hence freeze FW_CDEV_VERSION at the current value (no damage has been done yet), clearly document FW_CDEV_VERSION as a dummy version and what clients are expected to do with fw_cdev_get_info.version, and use a new defined constant (which is not placed into the exported header file) as kernel implementation level. Note, in order to check in client program source code which features are present in an externally installed linux/firewire-cdev.h, use preprocessor directives like #ifdef FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE or #ifdef FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED instead of a check of FW_CDEV_VERSION. Signed-off-by: Stefan Richter --- include/linux/firewire-cdev.h | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'include/linux/firewire-cdev.h') diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 6ffb24a1f2f2..0d0cc07358af 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -219,7 +219,7 @@ union fw_cdev_event { struct fw_cdev_event_response response; struct fw_cdev_event_request request; struct fw_cdev_event_iso_interrupt iso_interrupt; - struct fw_cdev_event_iso_resource iso_resource; + struct fw_cdev_event_iso_resource iso_resource; /* added in 2.6.30 */ }; /* available since kernel version 2.6.22 */ @@ -252,22 +252,32 @@ union fw_cdev_event { #define FW_CDEV_IOC_GET_CYCLE_TIMER2 _IOWR('#', 0x14, struct fw_cdev_get_cycle_timer2) /* - * FW_CDEV_VERSION History + * ABI version history * 1 (2.6.22) - initial version + * (2.6.24) - added %FW_CDEV_IOC_GET_CYCLE_TIMER * 2 (2.6.30) - changed &fw_cdev_event_iso_interrupt.header if * &fw_cdev_create_iso_context.header_size is 8 or more + * - added %FW_CDEV_IOC_*_ISO_RESOURCE*, + * %FW_CDEV_IOC_GET_SPEED, %FW_CDEV_IOC_SEND_BROADCAST_REQUEST, + * %FW_CDEV_IOC_SEND_STREAM_PACKET * (2.6.32) - added time stamp to xmit &fw_cdev_event_iso_interrupt * (2.6.33) - IR has always packet-per-buffer semantics now, not one of * dual-buffer or packet-per-buffer depending on hardware * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable + * - added %FW_CDEV_IOC_GET_CYCLE_TIMER2 */ -#define FW_CDEV_VERSION 3 +#define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */ /** * struct fw_cdev_get_info - General purpose information ioctl - * @version: The version field is just a running serial number. - * We never break backwards compatibility, but may add more - * structs and ioctls in later revisions. + * @version: The version field is just a running serial number. Both an + * input parameter (ABI version implemented by the client) and + * output parameter (ABI version implemented by the kernel). + * A client must not fill in an %FW_CDEV_VERSION defined from an + * included kernel header file but the actual version for which + * the client was implemented. This is necessary for forward + * compatibility. We never break backwards compatibility, but + * may add more structs, events, and ioctls in later revisions. * @rom_length: If @rom is non-zero, at most rom_length bytes of configuration * ROM will be copied into that user space address. In either * case, @rom_length is updated with the actual length of the -- cgit v1.2.3 From e205597d188a9ea69ce43f740a14f07b3f5b996a Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 20 Jun 2010 22:53:55 +0200 Subject: firewire: cdev: fix ABI for FCP and address range mapping, add fw_cdev_event_request2 The problem: A target-like userspace driver, e.g. AV/C target or SBP-2/3 target, needs to be able to act as responder and requester. In the latter role, it needs to send requests to nods from which it received requests. This is currently impossible because fw_cdev_event_request lacks information about sender node ID. Reported-by: Jay Fenlason Libffado + libraw1394 + firewire-core is currently unable to drive two or more audio devices on the same bus. Reported-by: Arnold Krille This is because libffado requires destination node ID of FCP requests and sender node ID of FCP responses to match. It even prohibits libffado from working with a bus on which libraw1394 opens a /dev/fw* as default ioctl device that does not correspond with the audio device. This is because libraw1394 does not receive the sender node ID from the kernel. Moreover, fw_cdev_event_request makes it impossible to tell unicast and broadcast write requests apart. The fix: Add a replacement of struct fw_cdev_event_request request, boringly called struct fw_cdev_event_request2. The new event will be sent to a userspace client instead of the old one if the client claims compatibility with ABI version 4 or later. libraw1394 needs to be extended to make use of the new event, in order to properly support libffado and other FCP or address range mapping users who require correct sender node IDs. Further notes: While we are at it, change back the range of possible values of fw_cdev_event_request.tcode to 0x0...0xb like in ABI version <= 3. The preceding change "firewire: expose extended tcode of incoming lock requests to (userspace) drivers" expanded it to 0x0...0x17 which could catch sloppily coded clients by surprise. The extended range of codes is only used in the new fw_cdev_event_request2.tcode. Jay and I also suggested an alternative approach to fix the ABI for incoming requests: Add an FW_CDEV_IOC_GET_REQUEST_INFO ioctl which can be called after reception of an fw_cdev_event_request, before issuing of the closing FW_CDEV_IOC_SEND_RESPONSE ioctl. The new ioctl would reveal the vital information about a request that fw_cdev_event_request lacks. Jay showed an implementation of this approach. The former event approach adds 27 LOC of rather trivial code to core-cdev.c, the ioctl approach 34 LOC, some of which is nontrivial. The ioctl approach would certainly also add more LOC to userspace programs which require the expanded information on inbound requests. This approach is probably only on the lighter-weight side in case of clients that want to be compatible with kernels that lack the new capability, like libraw1394. However, the code to be added to such libraw1394-like clients in case of the event approach is a straight- forward additional switch () case in its event handler. Signed-off-by: Stefan Richter --- include/linux/firewire-cdev.h | 76 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 2 deletions(-) (limited to 'include/linux/firewire-cdev.h') diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 0d0cc07358af..52c7ffe934ad 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -32,6 +32,9 @@ #define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED 0x04 #define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED 0x05 +/* available since kernel version 2.6.36 */ +#define FW_CDEV_EVENT_REQUEST2 0x06 + /** * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types * @closure: For arbitrary use by userspace @@ -98,11 +101,46 @@ struct fw_cdev_event_response { }; /** - * struct fw_cdev_event_request - Sent on incoming request to an address region + * struct fw_cdev_event_request - Old version of &fw_cdev_event_request2 * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST + * @tcode: See &fw_cdev_event_request2 + * @offset: See &fw_cdev_event_request2 + * @handle: See &fw_cdev_event_request2 + * @length: See &fw_cdev_event_request2 + * @data: See &fw_cdev_event_request2 + * + * This event is sent instead of &fw_cdev_event_request2 if the kernel or + * the client implements ABI version <= 3. + * + * Unlike &fw_cdev_event_request2, the sender identity cannot be established, + * broadcast write requests cannot be distinguished from unicast writes, and + * @tcode of lock requests is %TCODE_LOCK_REQUEST. + * + * Requests to the FCP_REQUEST or FCP_RESPONSE register are responded to as + * with &fw_cdev_event_request2, except in kernel 2.6.32 and older which send + * the response packet of the client's %FW_CDEV_IOC_SEND_RESPONSE ioctl. + */ +struct fw_cdev_event_request { + __u64 closure; + __u32 type; + __u32 tcode; + __u64 offset; + __u32 handle; + __u32 length; + __u32 data[0]; +}; + +/** + * struct fw_cdev_event_request2 - Sent on incoming request to an address region + * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl + * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST2 * @tcode: Transaction code of the incoming request * @offset: The offset into the 48-bit per-node address space + * @source_node_id: Sender node ID + * @destination_node_id: Destination node ID + * @card: The index of the card from which the request came + * @generation: Bus generation in which the request is valid * @handle: Reference to the kernel-side pending request * @length: Data length, i.e. the request's payload size in bytes * @data: Incoming data, if any @@ -115,12 +153,42 @@ struct fw_cdev_event_response { * * The payload data for requests carrying data (write and lock requests) * follows immediately and can be accessed through the @data field. + * + * Unlike &fw_cdev_event_request, @tcode of lock requests is one of the + * firewire-core specific %TCODE_LOCK_MASK_SWAP...%TCODE_LOCK_VENDOR_DEPENDENT, + * i.e. encodes the extended transaction code. + * + * @card may differ from &fw_cdev_get_info.card because requests are received + * from all cards of the Linux host. @source_node_id, @destination_node_id, and + * @generation pertain to that card. Destination node ID and bus generation may + * therefore differ from the corresponding fields of the last + * &fw_cdev_event_bus_reset. + * + * @destination_node_id may also differ from the current node ID because of a + * non-local bus ID part or in case of a broadcast write request. Note, a + * client must call an %FW_CDEV_IOC_SEND_RESPONSE ioctl even in case of a + * broadcast write request; the kernel will then release the kernel-side pending + * request but will not actually send a response packet. + * + * In case of a write request to FCP_REQUEST or FCP_RESPONSE, the kernel already + * sent a write response immediately after the request was received; in this + * case the client must still call an %FW_CDEV_IOC_SEND_RESPONSE ioctl to + * release the kernel-side pending request, though another response won't be + * sent. + * + * If the client subsequently needs to initiate requests to the sender node of + * an &fw_cdev_event_request2, it needs to use a device file with matching + * card index, node ID, and generation for outbound requests. */ -struct fw_cdev_event_request { +struct fw_cdev_event_request2 { __u64 closure; __u32 type; __u32 tcode; __u64 offset; + __u32 source_node_id; + __u32 destination_node_id; + __u32 card; + __u32 generation; __u32 handle; __u32 length; __u32 data[0]; @@ -200,6 +268,7 @@ struct fw_cdev_event_iso_resource { * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST + * @request2: Valid if @common.type == %FW_CDEV_EVENT_REQUEST2 * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT * @iso_resource: Valid if @common.type == * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or @@ -218,6 +287,7 @@ union fw_cdev_event { struct fw_cdev_event_bus_reset bus_reset; struct fw_cdev_event_response response; struct fw_cdev_event_request request; + struct fw_cdev_event_request2 request2; /* added in 2.6.36 */ struct fw_cdev_event_iso_interrupt iso_interrupt; struct fw_cdev_event_iso_resource iso_resource; /* added in 2.6.30 */ }; @@ -263,8 +333,10 @@ union fw_cdev_event { * (2.6.32) - added time stamp to xmit &fw_cdev_event_iso_interrupt * (2.6.33) - IR has always packet-per-buffer semantics now, not one of * dual-buffer or packet-per-buffer depending on hardware + * - shared use and auto-response for FCP registers * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable * - added %FW_CDEV_IOC_GET_CYCLE_TIMER2 + * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2 */ #define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */ -- cgit v1.2.3 From 3b2b65d68fc87b02ac393a031a4ebb3de84a8218 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 20 Jun 2010 22:54:22 +0200 Subject: firewire: cdev: extend fw_cdev_event_iso_interrupt documentation Add information regarding the 2.6.32 update to the xmit variant of fw_cdev_event_iso_interrupt. Signed-off-by: Stefan Richter --- include/linux/firewire-cdev.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'include/linux/firewire-cdev.h') diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 52c7ffe934ad..8b9b27373219 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -204,10 +204,21 @@ struct fw_cdev_event_request2 { * @header: Stripped headers, if any * * This event is sent when the controller has completed an &fw_cdev_iso_packet - * with the %FW_CDEV_ISO_INTERRUPT bit set. In the receive case, the headers - * stripped of all packets up until and including the interrupt packet are - * returned in the @header field. The amount of header data per packet is as - * specified at iso context creation by &fw_cdev_create_iso_context.header_size. + * with the %FW_CDEV_ISO_INTERRUPT bit set. + * + * Isochronous transmit events: + * + * In version 1 of the ABI, &header_length is 0. In version 3 and some + * implementations of version 2 of the ABI, &header_length is a multiple of 4 + * and &header contains timestamps of all packets up until the interrupt packet. + * The format of the timestamps is as described below for isochronous reception. + * + * Isochronous receive events: + * + * The headers stripped of all packets up until and including the interrupt + * packet are returned in the @header field. The amount of header data per + * packet is as specified at iso context creation by + * &fw_cdev_create_iso_context.header_size. * * In version 1 of this ABI, header data consisted of the 1394 isochronous * packet header, followed by quadlets from the packet payload if -- cgit v1.2.3 From 250b2b6dd421c9f8844a867d2ac06e0661e0ad93 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Mon, 21 Jun 2010 23:24:35 +0200 Subject: firewire: cdev: fix fw_cdev_event_bus_reset.bm_node_id Fix an obscure ABI feature that is a bit of a hassle to implement. However, somebody put it into the ABI, so let's fill in a sensible value there. Signed-off-by: Stefan Richter --- include/linux/firewire-cdev.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/linux/firewire-cdev.h') diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 8b9b27373219..d31022b05bd9 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -66,6 +66,10 @@ struct fw_cdev_event_common { * This event is sent when the bus the device belongs to goes through a bus * reset. It provides information about the new bus configuration, such as * new node ID for this device, new root ID, and others. + * + * If @bm_node_id is 0xffff right after bus reset it can be reread by an + * %FW_CDEV_IOC_GET_INFO ioctl after bus manager selection was finished. + * Kernels with ABI version < 4 do not set @bm_node_id. */ struct fw_cdev_event_bus_reset { __u64 closure; @@ -348,6 +352,7 @@ union fw_cdev_event { * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable * - added %FW_CDEV_IOC_GET_CYCLE_TIMER2 * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2 + * - implemented &fw_cdev_event_bus_reset.bm_node_id */ #define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */ -- cgit v1.2.3 From d505e6e87127d4dbdaa5d91561eed810c180ca23 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 17 Jul 2010 21:36:02 +0200 Subject: firewire: cdev: some clarifications to the API documentation Response events: - are generated on more occasions than their documentation claimed. CSR allocation: - An already occupied CSR can be determined from errno==EBUSY. Bus resets: - Note that FW_CDEV_IOC_INITIATE_BUS_RESET is nonblocking and that the client is not required to observe a grace period since kernels 2.6.36+ will enforce it now (commit 02d37bed). - The possible values of fw_cdev_initiate_bus_reset.type are listed in the kerneldoc comment already. - Clarify that an application that uses FW_CDEV_IOC_ADD_DESCRIPTOR and FW_CDEV_IOC_REMOVE_DESCRIPTOR does not have to issue a bus reset. Isochronous I/O contexts: - At most one can be created per open file descriptor. Signed-off-by: Stefan Richter --- include/linux/firewire-cdev.h | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'include/linux/firewire-cdev.h') diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index d31022b05bd9..fde9568151d5 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -84,8 +84,9 @@ struct fw_cdev_event_bus_reset { /** * struct fw_cdev_event_response - Sent when a response packet was received - * @closure: See &fw_cdev_event_common; - * set by %FW_CDEV_IOC_SEND_REQUEST ioctl + * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_SEND_REQUEST + * or %FW_CDEV_IOC_SEND_BROADCAST_REQUEST + * or %FW_CDEV_IOC_SEND_STREAM_PACKET ioctl * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_RESPONSE * @rcode: Response code returned by the remote node * @length: Data length, i.e. the response's payload size in bytes @@ -95,6 +96,11 @@ struct fw_cdev_event_bus_reset { * sent by %FW_CDEV_IOC_SEND_REQUEST ioctl. The payload data for responses * carrying data (read and lock responses) follows immediately and can be * accessed through the @data field. + * + * The event is also generated after conclusions of transactions that do not + * involve response packets. This includes unified write transactions, + * broadcast write transactions, and transmission of asynchronous stream + * packets. @rcode indicates success or failure of such transmissions. */ struct fw_cdev_event_response { __u64 closure; @@ -447,7 +453,9 @@ struct fw_cdev_send_response { * range to be used for later deallocation of the range. * * The address range is allocated on all local nodes. The address allocation - * is exclusive except for the FCP command and response registers. + * is exclusive except for the FCP command and response registers. If an + * exclusive address region is already in use, the ioctl fails with errno set + * to %EBUSY. */ struct fw_cdev_allocate { __u64 offset; @@ -475,9 +483,14 @@ struct fw_cdev_deallocate { * Initiate a bus reset for the bus this device is on. The bus reset can be * either the original (long) bus reset or the arbitrated (short) bus reset * introduced in 1394a-2000. + * + * The ioctl returns immediately. A subsequent &fw_cdev_event_bus_reset + * indicates when the reset actually happened. Since ABI v4, this may be + * considerably later than the ioctl because the kernel ensures a grace period + * between subsequent bus resets as per IEEE 1394 bus management specification. */ struct fw_cdev_initiate_bus_reset { - __u32 type; /* FW_CDEV_SHORT_RESET or FW_CDEV_LONG_RESET */ + __u32 type; }; /** @@ -501,9 +514,10 @@ struct fw_cdev_initiate_bus_reset { * * @immediate, @key, and @data array elements are CPU-endian quadlets. * - * If successful, the kernel adds the descriptor and writes back a handle to the - * kernel-side object to be used for later removal of the descriptor block and - * immediate key. + * If successful, the kernel adds the descriptor and writes back a @handle to + * the kernel-side object to be used for later removal of the descriptor block + * and immediate key. The kernel will also generate a bus reset to signal the + * change of the configuration ROM to other nodes. * * This ioctl affects the configuration ROMs of all local nodes. * The ioctl only succeeds on device files which represent a local node. @@ -522,7 +536,8 @@ struct fw_cdev_add_descriptor { * descriptor was added * * Remove a descriptor block and accompanying immediate key from the local - * nodes' configuration ROMs. + * nodes' configuration ROMs. The kernel will also generate a bus reset to + * signal the change of the configuration ROM to other nodes. */ struct fw_cdev_remove_descriptor { __u32 handle; @@ -554,6 +569,8 @@ struct fw_cdev_remove_descriptor { * * Note that the effect of a @header_size > 4 depends on * &fw_cdev_get_info.version, as documented at &fw_cdev_event_iso_interrupt. + * + * No more than one iso context can be created per fd. */ struct fw_cdev_create_iso_context { __u32 type; -- cgit v1.2.3 From 850bb6f23b93c04ce1e4509a87fa607dc17d97c1 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Fri, 16 Jul 2010 22:25:14 +0200 Subject: firewire: cdev: add PHY packet transmission Add an FW_CDEV_IOC_SEND_PHY_PACKET ioctl() for /dev/fw* which can be used to implement bus management related functionality in userspace. This is also half of the functionality (the transmit part) that is needed to support a userspace implementation of a VersaPHY transaction layer. Safety considerations: - PHY packets are generally broadcasts and may have interesting effects on PHYs and the bus, e.g. make asynchronous arbitration impossible due to too low gap count. Hence some kind of elevated privileges should be required of a process to be able to send PHY packets. This implementation assumes that a process that is allowed to open the /dev/fw* of a local node does have this privilege. There was an inconclusive discussion about introducing POSIX capabilities as a means to check for user privileges for these kinds of operations. - The kernel does not check integrity of the supplied packet data. That would be far too much code, considering the many kinds of PHY packets. A process which got the privilege to send these packets is trusted to do it correctly. Just like with the other "send packet" ioctls, a non-blocking API is chosen; i.e. the ioctl may return even before AT DMA started. After transmission, an event for poll()/read() is enqueued. Most users are going to need a blocking API, but a blocking userspace wrapper is easy to implement, and the second of the two existing libraw1394 calls raw1394_phy_packet_write() and raw1394_start_phy_packet_write() can be better supported that way. Signed-off-by: Stefan Richter --- include/linux/firewire-cdev.h | 44 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'include/linux/firewire-cdev.h') diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index fde9568151d5..5bc051b9a013 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -34,6 +34,7 @@ /* available since kernel version 2.6.36 */ #define FW_CDEV_EVENT_REQUEST2 0x06 +#define FW_CDEV_EVENT_PHY_PACKET_SENT 0x07 /** * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types @@ -283,6 +284,19 @@ struct fw_cdev_event_iso_resource { __s32 bandwidth; }; +/** + * struct fw_cdev_event_phy_packet - A PHY packet was transmitted + * @closure: See &fw_cdev_event_common; + * set by %FW_CDEV_IOC_SEND_PHY_PACKET ioctl + * @type: %FW_CDEV_EVENT_PHY_PACKET_SENT + * @rcode: %RCODE_..., indicates success or failure of transmission + */ +struct fw_cdev_event_phy_packet { + __u64 closure; + __u32 type; + __u32 rcode; +}; + /** * union fw_cdev_event - Convenience union of fw_cdev_event_ types * @common: Valid for all types @@ -294,6 +308,7 @@ struct fw_cdev_event_iso_resource { * @iso_resource: Valid if @common.type == * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED + * @phy_packet: Valid if @common.type == %FW_CDEV_EVENT_PHY_PACKET_SENT * * Convenience union for userspace use. Events could be read(2) into an * appropriately aligned char buffer and then cast to this union for further @@ -311,6 +326,7 @@ union fw_cdev_event { struct fw_cdev_event_request2 request2; /* added in 2.6.36 */ struct fw_cdev_event_iso_interrupt iso_interrupt; struct fw_cdev_event_iso_resource iso_resource; /* added in 2.6.30 */ + struct fw_cdev_event_phy_packet phy_packet; /* added in 2.6.36 */ }; /* available since kernel version 2.6.22 */ @@ -342,6 +358,9 @@ union fw_cdev_event { /* available since kernel version 2.6.34 */ #define FW_CDEV_IOC_GET_CYCLE_TIMER2 _IOWR('#', 0x14, struct fw_cdev_get_cycle_timer2) +/* available since kernel version 2.6.36 */ +#define FW_CDEV_IOC_SEND_PHY_PACKET _IOWR('#', 0x15, struct fw_cdev_send_phy_packet) + /* * ABI version history * 1 (2.6.22) - initial version @@ -357,8 +376,9 @@ union fw_cdev_event { * - shared use and auto-response for FCP registers * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable * - added %FW_CDEV_IOC_GET_CYCLE_TIMER2 - * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2 + * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2, %FW_CDEV_EVENT_PHY_PACKET_SENT * - implemented &fw_cdev_event_bus_reset.bm_node_id + * - added %FW_CDEV_IOC_SEND_PHY_PACKET */ #define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */ @@ -808,4 +828,26 @@ struct fw_cdev_send_stream_packet { __u32 speed; }; +/** + * struct fw_cdev_send_phy_packet - send a PHY packet + * @closure: Passed back to userspace in the PHY-packet-sent event + * @data: First and second quadlet of the PHY packet + * @generation: The bus generation where packet is valid + * + * The %FW_CDEV_IOC_SEND_PHY_PACKET ioctl sends a PHY packet to all nodes + * on the same card as this device. After transmission, an + * %FW_CDEV_EVENT_PHY_PACKET_SENT event is generated. + * + * The payload @data[] shall be specified in host byte order. Usually, + * @data[1] needs to be the bitwise inverse of @data[0]. VersaPHY packets + * are an exception to this rule. + * + * The ioctl is only permitted on device files which represent a local node. + */ +struct fw_cdev_send_phy_packet { + __u64 closure; + __u32 data[2]; + __u32 generation; +}; + #endif /* _LINUX_FIREWIRE_CDEV_H */ -- cgit v1.2.3 From bf54e1462b9192fdef7ea9e2bc44fdc16a4b87bc Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Fri, 16 Jul 2010 22:25:51 +0200 Subject: firewire: cdev: add PHY packet reception Add an FW_CDEV_IOC_RECEIVE_PHY_PACKETS ioctl() and FW_CDEV_EVENT_PHY_PACKET_RECEIVED poll()/read() event for /dev/fw*. This can be used to get information from remote PHYs by remote access PHY packets. This is also the 2nd half of the functionality (the receive part) to support a userspace implementation of a VersaPHY transaction layer. Safety considerations: - PHY packets are generally broadcasts, hence some kind of elevated privileges should be required of a process to be able to listen in on PHY packets. This implementation assumes that a process that is allowed to open the /dev/fw* of a local node does have this privilege. There was an inconclusive discussion about introducing POSIX capabilities as a means to check for user privileges for these kinds of operations. Other limitations: - PHY packet reception may be switched on by ioctl() but cannot be switched off again. It would be trivial to provide an off switch, but this is not worth the code. The client should simply close() the fd then, or just ignore further events. - For sake of simplicity of API and kernel-side implementation, no filter per packet content is provided. Signed-off-by: Stefan Richter --- include/linux/firewire-cdev.h | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) (limited to 'include/linux/firewire-cdev.h') diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 5bc051b9a013..b87409160794 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -35,6 +35,7 @@ /* available since kernel version 2.6.36 */ #define FW_CDEV_EVENT_REQUEST2 0x06 #define FW_CDEV_EVENT_PHY_PACKET_SENT 0x07 +#define FW_CDEV_EVENT_PHY_PACKET_RECEIVED 0x08 /** * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types @@ -285,16 +286,24 @@ struct fw_cdev_event_iso_resource { }; /** - * struct fw_cdev_event_phy_packet - A PHY packet was transmitted - * @closure: See &fw_cdev_event_common; - * set by %FW_CDEV_IOC_SEND_PHY_PACKET ioctl - * @type: %FW_CDEV_EVENT_PHY_PACKET_SENT + * struct fw_cdev_event_phy_packet - A PHY packet was transmitted or received + * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_SEND_PHY_PACKET + * or %FW_CDEV_IOC_RECEIVE_PHY_PACKETS ioctl + * @type: %FW_CDEV_EVENT_PHY_PACKET_SENT or %..._RECEIVED * @rcode: %RCODE_..., indicates success or failure of transmission + * @length: Data length in bytes + * @data: Incoming data + * + * If @type is %FW_CDEV_EVENT_PHY_PACKET_SENT, @length is 0 and @data empty. + * If @type is %FW_CDEV_EVENT_PHY_PACKET_RECEIVED, @length is 8 and @data + * consists of the two PHY packet quadlets, in host byte order. */ struct fw_cdev_event_phy_packet { __u64 closure; __u32 type; __u32 rcode; + __u32 length; + __u32 data[0]; }; /** @@ -308,7 +317,9 @@ struct fw_cdev_event_phy_packet { * @iso_resource: Valid if @common.type == * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED - * @phy_packet: Valid if @common.type == %FW_CDEV_EVENT_PHY_PACKET_SENT + * @phy_packet: Valid if @common.type == + * %FW_CDEV_EVENT_PHY_PACKET_SENT or + * %FW_CDEV_EVENT_PHY_PACKET_RECEIVED * * Convenience union for userspace use. Events could be read(2) into an * appropriately aligned char buffer and then cast to this union for further @@ -360,6 +371,7 @@ union fw_cdev_event { /* available since kernel version 2.6.36 */ #define FW_CDEV_IOC_SEND_PHY_PACKET _IOWR('#', 0x15, struct fw_cdev_send_phy_packet) +#define FW_CDEV_IOC_RECEIVE_PHY_PACKETS _IOW('#', 0x16, struct fw_cdev_receive_phy_packets) /* * ABI version history @@ -376,9 +388,9 @@ union fw_cdev_event { * - shared use and auto-response for FCP registers * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable * - added %FW_CDEV_IOC_GET_CYCLE_TIMER2 - * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2, %FW_CDEV_EVENT_PHY_PACKET_SENT + * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2, %FW_CDEV_EVENT_PHY_PACKET_* * - implemented &fw_cdev_event_bus_reset.bm_node_id - * - added %FW_CDEV_IOC_SEND_PHY_PACKET + * - added %FW_CDEV_IOC_SEND_PHY_PACKET, _RECEIVE_PHY_PACKETS */ #define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */ @@ -850,4 +862,17 @@ struct fw_cdev_send_phy_packet { __u32 generation; }; +/** + * struct fw_cdev_receive_phy_packets - start reception of PHY packets + * @closure: Passed back to userspace in phy packet events + * + * This ioctl activates issuing of %FW_CDEV_EVENT_PHY_PACKET_RECEIVED due to + * incoming PHY packets from any node on the same bus as the device. + * + * The ioctl is only permitted on device files which represent a local node. + */ +struct fw_cdev_receive_phy_packets { + __u64 closure; +}; + #endif /* _LINUX_FIREWIRE_CDEV_H */ -- cgit v1.2.3 From cc550216ae9a2993ef3973464714dc1a39ab1f86 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 18 Jul 2010 13:00:50 +0200 Subject: firewire: cdev: add PHY pinging This extends the FW_CDEV_IOC_SEND_PHY_PACKET ioctl() for /dev/fw* to be useful for ping time measurements. One application for it would be gap count optimization in userspace that is based on ping times rather than hop count. (The latter is implemented in firewire-core itself but is not applicable to beta PHYs that act as repeater.) Signed-off-by: Stefan Richter --- include/linux/firewire-cdev.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'include/linux/firewire-cdev.h') diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index b87409160794..da0fec7e8dc0 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -294,7 +294,10 @@ struct fw_cdev_event_iso_resource { * @length: Data length in bytes * @data: Incoming data * - * If @type is %FW_CDEV_EVENT_PHY_PACKET_SENT, @length is 0 and @data empty. + * If @type is %FW_CDEV_EVENT_PHY_PACKET_SENT, @length is 0 and @data empty, + * except in case of a ping packet: Then, @length is 4, and @data[0] is the + * ping time in 49.152MHz clocks if @rcode is %RCODE_COMPLETE. + * * If @type is %FW_CDEV_EVENT_PHY_PACKET_RECEIVED, @length is 8 and @data * consists of the two PHY packet quadlets, in host byte order. */ -- cgit v1.2.3 From 8e2b2b46ea4ca5ef790dddf78b360ed736a62d7c Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Fri, 23 Jul 2010 13:05:39 +0200 Subject: firewire: cdev: improve FW_CDEV_IOC_ALLOCATE In both the ieee1394 stack and the firewire stack, the core treats kernelspace drivers better than userspace drivers when it comes to CSR address range allocation: The former may request a register to be placed automatically at a free spot anywhere inside a specified address range. The latter may only request a register at a fixed offset. Hence, userspace drivers which do not require a fixed offset potentially need to implement a retry loop with incremented offset in each retry until the kernel does not fail allocation with EBUSY. This awkward procedure is not fundamentally necessary as the core already provides a superior allocation API to kernelspace drivers. Therefore change the ioctl() ABI by addition of a region_end member in the existing struct fw_cdev_allocate. Userspace and kernelspace APIs work the same way now. There is a small cost to pay by clients though: If client source code is required to compile with older kernel headers too, then any use of the new member fw_cdev_allocate.region_end needs to be enclosed by #ifdef/#endif directives. However, any client program that seriously wants to use address range allocations will require a kernel of cdev ABI version >= 4 at runtime and a linux/firewire-cdev.h header of >= 4 anyway. This is because v4 brings FW_CDEV_EVENT_REQUEST2. The only client program in which build-time compatibility with struct fw_cdev_allocate as found in older kernel headers makes sense is libraw1394. (libraw1394 uses the older broken FW_CDEV_EVENT_REQUEST to implement a makeshift, incorrect transaction responder that does at least work somewhat in many simple scenarios, relying on guesswork by libraw1394 and by libraw1394 based applications. Plus, address range allocation and transaction responder is only one of many features that libraw1394 needs to provide, and these other features need to work with kernel and kernel-headers as old as possible. Any new linux/firewire-cdev.h based client that implements a transaction responder should never attempt to do it like libraw1394; instead it should make a header and kernel of v4 or later a hard requirement.) While we are at it, update the struct fw_cdev_allocate documentation to better reflect the recent fw_cdev_event_request2 ABI addition. Signed-off-by: Stefan Richter --- include/linux/firewire-cdev.h | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'include/linux/firewire-cdev.h') diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index da0fec7e8dc0..14831119ff71 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -394,6 +394,7 @@ union fw_cdev_event { * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2, %FW_CDEV_EVENT_PHY_PACKET_* * - implemented &fw_cdev_event_bus_reset.bm_node_id * - added %FW_CDEV_IOC_SEND_PHY_PACKET, _RECEIVE_PHY_PACKETS + * - added &fw_cdev_allocate.region_end */ #define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */ @@ -473,17 +474,21 @@ struct fw_cdev_send_response { }; /** - * struct fw_cdev_allocate - Allocate a CSR address range + * struct fw_cdev_allocate - Allocate a CSR in an address range * @offset: Start offset of the address range * @closure: To be passed back to userspace in request events - * @length: Length of the address range, in bytes + * @length: Length of the CSR, in bytes * @handle: Handle to the allocation, written by the kernel + * @region_end: First address above the address range (added in ABI v4, 2.6.36) * * Allocate an address range in the 48-bit address space on the local node * (the controller). This allows userspace to listen for requests with an - * offset within that address range. When the kernel receives a request - * within the range, an &fw_cdev_event_request event will be written back. - * The @closure field is passed back to userspace in the response event. + * offset within that address range. Every time when the kernel receives a + * request within the range, an &fw_cdev_event_request2 event will be emitted. + * (If the kernel or the client implements ABI version <= 3, an + * &fw_cdev_event_request will be generated instead.) + * + * The @closure field is passed back to userspace in these request events. * The @handle field is an out parameter, returning a handle to the allocated * range to be used for later deallocation of the range. * @@ -491,12 +496,26 @@ struct fw_cdev_send_response { * is exclusive except for the FCP command and response registers. If an * exclusive address region is already in use, the ioctl fails with errno set * to %EBUSY. + * + * If kernel and client implement ABI version >= 4, the kernel looks up a free + * spot of size @length inside [@offset..@region_end) and, if found, writes + * the start address of the new CSR back in @offset. I.e. @offset is an + * in and out parameter. If this automatic placement of a CSR in a bigger + * address range is not desired, the client simply needs to set @region_end + * = @offset + @length. + * + * If the kernel or the client implements ABI version <= 3, @region_end is + * ignored and effectively assumed to be @offset + @length. + * + * @region_end is only present in a kernel header >= 2.6.36. If necessary, + * this can for example be tested by #ifdef FW_CDEV_EVENT_REQUEST2. */ struct fw_cdev_allocate { __u64 offset; __u64 closure; __u32 length; __u32 handle; + __u64 region_end; /* available since kernel version 2.6.36 */ }; /** -- cgit v1.2.3 From 872e330e38806d835bd6c311c93ab998e2fb9058 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 29 Jul 2010 18:19:22 +0200 Subject: 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 --- include/linux/firewire-cdev.h | 281 +++++++++++++++++++++++++++++------------- 1 file changed, 195 insertions(+), 86 deletions(-) (limited to 'include/linux/firewire-cdev.h') diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 14831119ff71..bc5c26fc1c64 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -25,17 +25,18 @@ #include #include -#define FW_CDEV_EVENT_BUS_RESET 0x00 -#define FW_CDEV_EVENT_RESPONSE 0x01 -#define FW_CDEV_EVENT_REQUEST 0x02 -#define FW_CDEV_EVENT_ISO_INTERRUPT 0x03 -#define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED 0x04 -#define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED 0x05 +#define FW_CDEV_EVENT_BUS_RESET 0x00 +#define FW_CDEV_EVENT_RESPONSE 0x01 +#define FW_CDEV_EVENT_REQUEST 0x02 +#define FW_CDEV_EVENT_ISO_INTERRUPT 0x03 +#define FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED 0x04 +#define FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED 0x05 /* available since kernel version 2.6.36 */ -#define FW_CDEV_EVENT_REQUEST2 0x06 -#define FW_CDEV_EVENT_PHY_PACKET_SENT 0x07 -#define FW_CDEV_EVENT_PHY_PACKET_RECEIVED 0x08 +#define FW_CDEV_EVENT_REQUEST2 0x06 +#define FW_CDEV_EVENT_PHY_PACKET_SENT 0x07 +#define FW_CDEV_EVENT_PHY_PACKET_RECEIVED 0x08 +#define FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL 0x09 /** * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types @@ -218,35 +219,41 @@ struct fw_cdev_event_request2 { * This event is sent when the controller has completed an &fw_cdev_iso_packet * with the %FW_CDEV_ISO_INTERRUPT bit set. * - * Isochronous transmit events: + * Isochronous transmit events (context type %FW_CDEV_ISO_CONTEXT_TRANSMIT): * - * In version 1 of the ABI, &header_length is 0. In version 3 and some - * implementations of version 2 of the ABI, &header_length is a multiple of 4 - * and &header contains timestamps of all packets up until the interrupt packet. - * The format of the timestamps is as described below for isochronous reception. + * In version 3 and some implementations of version 2 of the ABI, &header_length + * is a multiple of 4 and &header contains timestamps of all packets up until + * the interrupt packet. The format of the timestamps is as described below for + * isochronous reception. In version 1 of the ABI, &header_length was 0. * - * Isochronous receive events: + * Isochronous receive events (context type %FW_CDEV_ISO_CONTEXT_RECEIVE): * * The headers stripped of all packets up until and including the interrupt * packet are returned in the @header field. The amount of header data per * packet is as specified at iso context creation by * &fw_cdev_create_iso_context.header_size. * - * In version 1 of this ABI, header data consisted of the 1394 isochronous - * packet header, followed by quadlets from the packet payload if - * &fw_cdev_create_iso_context.header_size > 4. + * Hence, _interrupt.header_length / _context.header_size is the number of + * packets received in this interrupt event. The client can now iterate + * through the mmap()'ed DMA buffer according to this number of packets and + * to the buffer sizes as the client specified in &fw_cdev_queue_iso. * - * In version 2 of this ABI, header data consist of the 1394 isochronous - * packet header, followed by a timestamp quadlet if - * &fw_cdev_create_iso_context.header_size > 4, followed by quadlets from the - * packet payload if &fw_cdev_create_iso_context.header_size > 8. + * Since version 2 of this ABI, the portion for each packet in _interrupt.header + * consists of the 1394 isochronous packet header, followed by a timestamp + * quadlet if &fw_cdev_create_iso_context.header_size > 4, followed by quadlets + * from the packet payload if &fw_cdev_create_iso_context.header_size > 8. * - * Behaviour of ver. 1 of this ABI is no longer available since ABI ver. 2. + * Format of 1394 iso packet header: 16 bits data_length, 2 bits tag, 6 bits + * channel, 4 bits tcode, 4 bits sy, in big endian byte order. + * data_length is the actual received size of the packet without the four + * 1394 iso packet header bytes. + * + * Format of timestamp: 16 bits invalid, 3 bits cycleSeconds, 13 bits + * cycleCount, in big endian byte order. * - * Format of 1394 iso packet header: 16 bits len, 2 bits tag, 6 bits channel, - * 4 bits tcode, 4 bits sy, in big endian byte order. Format of timestamp: - * 16 bits invalid, 3 bits cycleSeconds, 13 bits cycleCount, in big endian byte - * order. + * In version 1 of the ABI, no timestamp quadlet was inserted; instead, payload + * data followed directly after the 1394 is header if header_size > 4. + * Behaviour of ver. 1 of this ABI is no longer available since ABI ver. 2. */ struct fw_cdev_event_iso_interrupt { __u64 closure; @@ -256,6 +263,43 @@ struct fw_cdev_event_iso_interrupt { __u32 header[0]; }; +/** + * struct fw_cdev_event_iso_interrupt_mc - An iso buffer chunk was completed + * @closure: See &fw_cdev_event_common; + * set by %FW_CDEV_CREATE_ISO_CONTEXT ioctl + * @type: %FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL + * @completed: Offset into the receive buffer; data before this offest is valid + * + * This event is sent in multichannel contexts (context type + * %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL) for &fw_cdev_iso_packet buffer + * chunks that have the %FW_CDEV_ISO_INTERRUPT bit set. Whether this happens + * when a packet is completed and/or when a buffer chunk is completed depends + * on the hardware implementation. + * + * The buffer is continuously filled with the following data, per packet: + * - the 1394 iso packet header as described at &fw_cdev_event_iso_interrupt, + * but in little endian byte order, + * - packet payload (as many bytes as specified in the data_length field of + * the 1394 iso packet header) in big endian byte order, + * - 0...3 padding bytes as needed to align the following trailer quadlet, + * - trailer quadlet, containing the reception timestamp as described at + * &fw_cdev_event_iso_interrupt, but in little endian byte order. + * + * Hence the per-packet size is data_length (rounded up to a multiple of 4) + 8. + * When processing the data, stop before a packet that would cross the + * @completed offset. + * + * A packet near the end of a buffer chunk will typically spill over into the + * next queued buffer chunk. It is the responsibility of the client to check + * for this condition, assemble a broken-up packet from its parts, and not to + * re-queue any buffer chunks in which as yet unread packet parts reside. + */ +struct fw_cdev_event_iso_interrupt_mc { + __u64 closure; + __u32 type; + __u32 completed; +}; + /** * struct fw_cdev_event_iso_resource - Iso resources were allocated or freed * @closure: See &fw_cdev_event_common; @@ -311,16 +355,18 @@ struct fw_cdev_event_phy_packet { /** * union fw_cdev_event - Convenience union of fw_cdev_event_ types - * @common: Valid for all types - * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET - * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE - * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST - * @request2: Valid if @common.type == %FW_CDEV_EVENT_REQUEST2 - * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT - * @iso_resource: Valid if @common.type == + * @common: Valid for all types + * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET + * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE + * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST + * @request2: Valid if @common.type == %FW_CDEV_EVENT_REQUEST2 + * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT + * @iso_interrupt_mc: Valid if @common.type == + * %FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL + * @iso_resource: Valid if @common.type == * %FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED or * %FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED - * @phy_packet: Valid if @common.type == + * @phy_packet: Valid if @common.type == * %FW_CDEV_EVENT_PHY_PACKET_SENT or * %FW_CDEV_EVENT_PHY_PACKET_RECEIVED * @@ -337,10 +383,11 @@ union fw_cdev_event { struct fw_cdev_event_bus_reset bus_reset; struct fw_cdev_event_response response; struct fw_cdev_event_request request; - struct fw_cdev_event_request2 request2; /* added in 2.6.36 */ + struct fw_cdev_event_request2 request2; /* added in 2.6.36 */ struct fw_cdev_event_iso_interrupt iso_interrupt; - struct fw_cdev_event_iso_resource iso_resource; /* added in 2.6.30 */ - struct fw_cdev_event_phy_packet phy_packet; /* added in 2.6.36 */ + struct fw_cdev_event_iso_interrupt_mc iso_interrupt_mc; /* added in 2.6.36 */ + struct fw_cdev_event_iso_resource iso_resource; /* added in 2.6.30 */ + struct fw_cdev_event_phy_packet phy_packet; /* added in 2.6.36 */ }; /* available since kernel version 2.6.22 */ @@ -375,6 +422,7 @@ union fw_cdev_event { /* available since kernel version 2.6.36 */ #define FW_CDEV_IOC_SEND_PHY_PACKET _IOWR('#', 0x15, struct fw_cdev_send_phy_packet) #define FW_CDEV_IOC_RECEIVE_PHY_PACKETS _IOW('#', 0x16, struct fw_cdev_receive_phy_packets) +#define FW_CDEV_IOC_SET_ISO_CHANNELS _IOW('#', 0x17, struct fw_cdev_set_iso_channels) /* * ABI version history @@ -391,10 +439,13 @@ union fw_cdev_event { * - shared use and auto-response for FCP registers * 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable * - added %FW_CDEV_IOC_GET_CYCLE_TIMER2 - * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2, %FW_CDEV_EVENT_PHY_PACKET_* + * 4 (2.6.36) - added %FW_CDEV_EVENT_REQUEST2, %FW_CDEV_EVENT_PHY_PACKET_*, + * and &fw_cdev_allocate.region_end * - implemented &fw_cdev_event_bus_reset.bm_node_id * - added %FW_CDEV_IOC_SEND_PHY_PACKET, _RECEIVE_PHY_PACKETS - * - added &fw_cdev_allocate.region_end + * - added %FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL, + * %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL, and + * %FW_CDEV_IOC_SET_ISO_CHANNELS */ #define FW_CDEV_VERSION 3 /* Meaningless; don't use this macro. */ @@ -597,34 +648,43 @@ struct fw_cdev_remove_descriptor { __u32 handle; }; -#define FW_CDEV_ISO_CONTEXT_TRANSMIT 0 -#define FW_CDEV_ISO_CONTEXT_RECEIVE 1 +#define FW_CDEV_ISO_CONTEXT_TRANSMIT 0 +#define FW_CDEV_ISO_CONTEXT_RECEIVE 1 +#define FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL 2 /* added in 2.6.36 */ /** - * struct fw_cdev_create_iso_context - Create a context for isochronous IO - * @type: %FW_CDEV_ISO_CONTEXT_TRANSMIT or %FW_CDEV_ISO_CONTEXT_RECEIVE - * @header_size: Header size to strip for receive contexts - * @channel: Channel to bind to - * @speed: Speed for transmit contexts - * @closure: To be returned in &fw_cdev_event_iso_interrupt + * struct fw_cdev_create_iso_context - Create a context for isochronous I/O + * @type: %FW_CDEV_ISO_CONTEXT_TRANSMIT or %FW_CDEV_ISO_CONTEXT_RECEIVE or + * %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL + * @header_size: Header size to strip in single-channel reception + * @channel: Channel to bind to in single-channel reception or transmission + * @speed: Transmission speed + * @closure: To be returned in &fw_cdev_event_iso_interrupt or + * &fw_cdev_event_iso_interrupt_multichannel * @handle: Handle to context, written back by kernel * * Prior to sending or receiving isochronous I/O, a context must be created. * The context records information about the transmit or receive configuration * and typically maps to an underlying hardware resource. A context is set up * for either sending or receiving. It is bound to a specific isochronous - * channel. + * @channel. * - * If a context was successfully created, the kernel writes back a handle to the - * context, which must be passed in for subsequent operations on that context. + * In case of multichannel reception, @header_size and @channel are ignored + * and the channels are selected by %FW_CDEV_IOC_SET_ISO_CHANNELS. + * + * For %FW_CDEV_ISO_CONTEXT_RECEIVE contexts, @header_size must be at least 4 + * and must be a multiple of 4. It is ignored in other context types. * - * For receive contexts, @header_size must be at least 4 and must be a multiple - * of 4. + * @speed is ignored in receive context types. * - * Note that the effect of a @header_size > 4 depends on - * &fw_cdev_get_info.version, as documented at &fw_cdev_event_iso_interrupt. + * If a context was successfully created, the kernel writes back a handle to the + * context, which must be passed in for subsequent operations on that context. * + * Limitations: * No more than one iso context can be created per fd. + * The total number of contexts that all userspace and kernelspace drivers can + * create on a card at a time is a hardware limit, typically 4 or 8 contexts per + * direction, and of them at most one multichannel receive context. */ struct fw_cdev_create_iso_context { __u32 type; @@ -635,6 +695,22 @@ struct fw_cdev_create_iso_context { __u32 handle; }; +/** + * struct fw_cdev_set_iso_channels - Select channels in multichannel reception + * @channels: Bitmask of channels to listen to + * @handle: Handle of the mutichannel receive context + * + * @channels is the bitwise or of 1ULL << n for each channel n to listen to. + * + * The ioctl fails with errno %EBUSY if there is already another receive context + * on a channel in @channels. In that case, the bitmask of all unoccupied + * channels is returned in @channels. + */ +struct fw_cdev_set_iso_channels { + __u64 channels; + __u32 handle; +}; + #define FW_CDEV_ISO_PAYLOAD_LENGTH(v) (v) #define FW_CDEV_ISO_INTERRUPT (1 << 16) #define FW_CDEV_ISO_SKIP (1 << 17) @@ -645,42 +721,72 @@ struct fw_cdev_create_iso_context { /** * struct fw_cdev_iso_packet - Isochronous packet - * @control: Contains the header length (8 uppermost bits), the sy field - * (4 bits), the tag field (2 bits), a sync flag (1 bit), - * a skip flag (1 bit), an interrupt flag (1 bit), and the + * @control: Contains the header length (8 uppermost bits), + * the sy field (4 bits), the tag field (2 bits), a sync flag + * or a skip flag (1 bit), an interrupt flag (1 bit), and the * payload length (16 lowermost bits) - * @header: Header and payload + * @header: Header and payload in case of a transmit context. * * &struct fw_cdev_iso_packet is used to describe isochronous packet queues. - * * Use the FW_CDEV_ISO_ macros to fill in @control. + * The @header array is empty in case of receive contexts. + * + * Context type %FW_CDEV_ISO_CONTEXT_TRANSMIT: + * + * @control.HEADER_LENGTH must be a multiple of 4. It specifies the numbers of + * bytes in @header that will be prepended to the packet's payload. These bytes + * are copied into the kernel and will not be accessed after the ioctl has + * returned. + * + * The @control.SY and TAG fields are copied to the iso packet header. These + * fields are specified by IEEE 1394a and IEC 61883-1. + * + * The @control.SKIP flag specifies that no packet is to be sent in a frame. + * When using this, all other fields except @control.INTERRUPT must be zero. + * + * When a packet with the @control.INTERRUPT flag set has been completed, an + * &fw_cdev_event_iso_interrupt event will be sent. + * + * Context type %FW_CDEV_ISO_CONTEXT_RECEIVE: * - * For transmit packets, the header length must be a multiple of 4 and specifies - * the numbers of bytes in @header that will be prepended to the packet's - * payload; these bytes are copied into the kernel and will not be accessed - * after the ioctl has returned. The sy and tag fields are copied to the iso - * packet header (these fields are specified by IEEE 1394a and IEC 61883-1). - * The skip flag specifies that no packet is to be sent in a frame; when using - * this, all other fields except the interrupt flag must be zero. - * - * For receive packets, the header length must be a multiple of the context's - * header size; if the header length is larger than the context's header size, - * multiple packets are queued for this entry. The sy and tag fields are - * ignored. If the sync flag is set, the context drops all packets until - * a packet with a matching sy field is received (the sync value to wait for is - * specified in the &fw_cdev_start_iso structure). The payload length defines - * how many payload bytes can be received for one packet (in addition to payload - * quadlets that have been defined as headers and are stripped and returned in - * the &fw_cdev_event_iso_interrupt structure). If more bytes are received, the - * additional bytes are dropped. If less bytes are received, the remaining - * bytes in this part of the payload buffer will not be written to, not even by - * the next packet, i.e., packets received in consecutive frames will not - * necessarily be consecutive in memory. If an entry has queued multiple - * packets, the payload length is divided equally among them. - * - * When a packet with the interrupt flag set has been completed, the + * @control.HEADER_LENGTH must be a multiple of the context's header_size. + * If the HEADER_LENGTH is larger than the context's header_size, multiple + * packets are queued for this entry. + * + * The @control.SY and TAG fields are ignored. + * + * If the @control.SYNC flag is set, the context drops all packets until a + * packet with a sy field is received which matches &fw_cdev_start_iso.sync. + * + * @control.PAYLOAD_LENGTH defines how many payload bytes can be received for + * one packet (in addition to payload quadlets that have been defined as headers + * and are stripped and returned in the &fw_cdev_event_iso_interrupt structure). + * If more bytes are received, the additional bytes are dropped. If less bytes + * are received, the remaining bytes in this part of the payload buffer will not + * be written to, not even by the next packet. I.e., packets received in + * consecutive frames will not necessarily be consecutive in memory. If an + * entry has queued multiple packets, the PAYLOAD_LENGTH is divided equally + * among them. + * + * When a packet with the @control.INTERRUPT flag set has been completed, an * &fw_cdev_event_iso_interrupt event will be sent. An entry that has queued * multiple receive packets is completed when its last packet is completed. + * + * Context type %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL: + * + * Here, &fw_cdev_iso_packet would be more aptly named _iso_buffer_chunk since + * it specifies a chunk of the mmap()'ed buffer, while the number and alignment + * of packets to be placed into the buffer chunk is not known beforehand. + * + * @control.PAYLOAD_LENGTH is the size of the buffer chunk and specifies room + * for header, payload, padding, and trailer bytes of one or more packets. + * It must be a multiple of 4. + * + * @control.HEADER_LENGTH, TAG and SY are ignored. SYNC is treated as described + * for single-channel reception. + * + * When a buffer chunk with the @control.INTERRUPT flag set has been filled + * entirely, an &fw_cdev_event_iso_interrupt_mc event will be sent. */ struct fw_cdev_iso_packet { __u32 control; @@ -689,9 +795,9 @@ struct fw_cdev_iso_packet { /** * struct fw_cdev_queue_iso - Queue isochronous packets for I/O - * @packets: Userspace pointer to packet data + * @packets: Userspace pointer to an array of &fw_cdev_iso_packet * @data: Pointer into mmap()'ed payload buffer - * @size: Size of packet data in bytes + * @size: Size of the @packets array, in bytes * @handle: Isochronous context handle * * Queue a number of isochronous packets for reception or transmission. @@ -704,6 +810,9 @@ struct fw_cdev_iso_packet { * The kernel may or may not queue all packets, but will write back updated * values of the @packets, @data and @size fields, so the ioctl can be * resubmitted easily. + * + * In case of a multichannel receive context, @data must be quadlet-aligned + * relative to the buffer start. */ struct fw_cdev_queue_iso { __u64 packets; -- cgit v1.2.3