2007-05-07 20:33:32 -04:00
/*
2006-12-19 19:58:27 -05:00
* Copyright ( C ) 2003 - 2006 Kristian Hoegsberg < krh @ bitplanet . net >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
2006-12-28 16:20:00 +01:00
# ifndef __fw_transaction_h
# define __fw_transaction_h
2006-12-19 19:58:27 -05:00
# include <linux/device.h>
# include <linux/timer.h>
# include <linux/interrupt.h>
# include <linux/list.h>
# include <linux/fs.h>
2007-02-16 17:34:38 -05:00
# include <linux/dma-mapping.h>
2007-05-07 20:33:37 -04:00
# include <linux/firewire-constants.h>
2006-12-19 19:58:27 -05:00
2007-01-26 00:38:26 -05:00
# define TCODE_IS_READ_REQUEST(tcode) (((tcode) & ~1) == 4)
2006-12-19 19:58:27 -05:00
# define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0)
# define TCODE_IS_REQUEST(tcode) (((tcode) & 2) == 0)
# define TCODE_IS_RESPONSE(tcode) (((tcode) & 2) != 0)
# define TCODE_HAS_REQUEST_DATA(tcode) (((tcode) & 12) != 4)
# define TCODE_HAS_RESPONSE_DATA(tcode) (((tcode) & 12) != 0)
# define LOCAL_BUS 0xffc0
2007-01-21 20:44:09 +01:00
# define SELFID_PORT_CHILD 0x3
# define SELFID_PORT_PARENT 0x2
# define SELFID_PORT_NCONN 0x1
# define SELFID_PORT_NONE 0x0
2006-12-19 19:58:27 -05:00
# define PHY_PACKET_CONFIG 0x0
# define PHY_PACKET_LINK_ON 0x1
# define PHY_PACKET_SELF_ID 0x2
2007-03-23 10:24:02 -06:00
/* Bit fields _within_ the PHY registers. */
# define PHY_LINK_ACTIVE 0x80
# define PHY_CONTENDER 0x40
# define PHY_BUS_RESET 0x40
# define PHY_BUS_SHORT_RESET 0x40
2007-01-26 00:38:26 -05:00
# define CSR_REGISTER_BASE 0xfffff0000000ULL
/* register offsets relative to CSR_REGISTER_BASE */
# define CSR_STATE_CLEAR 0x0
# define CSR_STATE_SET 0x4
# define CSR_NODE_IDS 0x8
# define CSR_RESET_START 0xc
# define CSR_SPLIT_TIMEOUT_HI 0x18
# define CSR_SPLIT_TIMEOUT_LO 0x1c
# define CSR_CYCLE_TIME 0x200
# define CSR_BUS_TIME 0x204
# define CSR_BUSY_TIMEOUT 0x210
# define CSR_BUS_MANAGER_ID 0x21c
# define CSR_BANDWIDTH_AVAILABLE 0x220
# define CSR_CHANNELS_AVAILABLE 0x224
# define CSR_CHANNELS_AVAILABLE_HI 0x224
# define CSR_CHANNELS_AVAILABLE_LO 0x228
# define CSR_BROADCAST_CHANNEL 0x234
# define CSR_CONFIG_ROM 0x400
# define CSR_CONFIG_ROM_END 0x800
# define CSR_FCP_COMMAND 0xB00
# define CSR_FCP_RESPONSE 0xD00
# define CSR_FCP_END 0xF00
# define CSR_TOPOLOGY_MAP 0x1000
# define CSR_TOPOLOGY_MAP_END 0x1400
# define CSR_SPEED_MAP 0x2000
# define CSR_SPEED_MAP_END 0x3000
2006-12-19 19:58:27 -05:00
# define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args)
# define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args)
static inline void
fw_memcpy_from_be32 ( void * _dst , void * _src , size_t size )
{
u32 * dst = _dst ;
u32 * src = _src ;
int i ;
for ( i = 0 ; i < size / 4 ; i + + )
dst [ i ] = cpu_to_be32 ( src [ i ] ) ;
}
static inline void
fw_memcpy_to_be32 ( void * _dst , void * _src , size_t size )
{
fw_memcpy_from_be32 ( _dst , _src , size ) ;
}
struct fw_card ;
struct fw_packet ;
struct fw_node ;
struct fw_request ;
struct fw_descriptor {
struct list_head link ;
size_t length ;
2007-03-07 12:12:36 -05:00
u32 immediate ;
2006-12-19 19:58:27 -05:00
u32 key ;
2007-01-14 15:29:07 +01:00
const u32 * data ;
2006-12-19 19:58:27 -05:00
} ;
2007-05-07 20:33:34 -04:00
int fw_core_add_descriptor ( struct fw_descriptor * desc ) ;
void fw_core_remove_descriptor ( struct fw_descriptor * desc ) ;
2006-12-19 19:58:27 -05:00
2007-05-07 20:33:34 -04:00
typedef void ( * fw_packet_callback_t ) ( struct fw_packet * packet ,
struct fw_card * card , int status ) ;
2006-12-19 19:58:27 -05:00
typedef void ( * fw_transaction_callback_t ) ( struct fw_card * card , int rcode ,
void * data ,
size_t length ,
void * callback_data ) ;
2007-07-17 02:15:36 +02:00
/*
* Important note : The callback must guarantee that either fw_send_response ( )
* or kfree ( ) is called on the @ request .
*/
2006-12-19 19:58:27 -05:00
typedef void ( * fw_address_callback_t ) ( struct fw_card * card ,
struct fw_request * request ,
int tcode , int destination , int source ,
int generation , int speed ,
unsigned long long offset ,
void * data , size_t length ,
void * callback_data ) ;
typedef void ( * fw_bus_reset_callback_t ) ( struct fw_card * handle ,
int node_id , int generation ,
u32 * self_ids ,
int self_id_count ,
void * callback_data ) ;
struct fw_packet {
2007-01-21 20:44:09 +01:00
int speed ;
int generation ;
u32 header [ 4 ] ;
size_t header_length ;
void * payload ;
size_t payload_length ;
u32 timestamp ;
2007-05-07 20:33:32 -04:00
/*
* This callback is called when the packet transmission has
2007-01-21 20:44:09 +01:00
* completed ; for successful transmission , the status code is
* the ack received from the destination , otherwise it ' s a
* negative errno : ENOMEM , ESTALE , ETIMEDOUT , ENODEV , EIO .
* The callback can be called from tasklet context and thus
* must never block .
*/
fw_packet_callback_t callback ;
2007-01-26 00:37:57 -05:00
int ack ;
2007-01-21 20:44:09 +01:00
struct list_head link ;
2007-03-07 12:12:49 -05:00
void * driver_data ;
2006-12-19 19:58:27 -05:00
} ;
struct fw_transaction {
2007-01-21 20:44:09 +01:00
int node_id ; /* The generation is implied; it is always the current. */
int tlabel ;
int timestamp ;
struct list_head link ;
2006-12-19 19:58:27 -05:00
2007-01-21 20:44:09 +01:00
struct fw_packet packet ;
2006-12-19 19:58:27 -05:00
2007-05-07 20:33:32 -04:00
/*
* The data passed to the callback is valid only during the
* callback .
*/
2007-01-21 20:44:09 +01:00
fw_transaction_callback_t callback ;
void * callback_data ;
2006-12-19 19:58:27 -05:00
} ;
2007-01-22 19:17:37 +01:00
static inline struct fw_packet *
2006-12-19 19:58:27 -05:00
fw_packet ( struct list_head * l )
{
2007-05-07 20:33:34 -04:00
return list_entry ( l , struct fw_packet , link ) ;
2006-12-19 19:58:27 -05:00
}
struct fw_address_handler {
2007-01-21 20:44:09 +01:00
u64 offset ;
size_t length ;
fw_address_callback_t address_callback ;
void * callback_data ;
struct list_head link ;
2006-12-19 19:58:27 -05:00
} ;
struct fw_address_region {
u64 start ;
u64 end ;
} ;
2007-01-14 15:29:07 +01:00
extern const struct fw_address_region fw_low_memory_region ;
extern const struct fw_address_region fw_high_memory_region ;
extern const struct fw_address_region fw_private_region ;
extern const struct fw_address_region fw_csr_region ;
extern const struct fw_address_region fw_unit_space_region ;
2006-12-19 19:58:27 -05:00
int fw_core_add_address_handler ( struct fw_address_handler * handler ,
2007-01-14 15:29:07 +01:00
const struct fw_address_region * region ) ;
2006-12-19 19:58:27 -05:00
void fw_core_remove_address_handler ( struct fw_address_handler * handler ) ;
2007-01-26 00:38:26 -05:00
void fw_fill_response ( struct fw_packet * response , u32 * request_header ,
int rcode , void * payload , size_t length ) ;
2006-12-19 19:58:27 -05:00
void fw_send_response ( struct fw_card * card ,
struct fw_request * request , int rcode ) ;
extern struct bus_type fw_bus_type ;
struct fw_card {
2007-01-14 15:29:07 +01:00
const struct fw_card_driver * driver ;
2006-12-19 19:58:27 -05:00
struct device * device ;
2007-03-07 12:12:37 -05:00
struct kref kref ;
2006-12-19 19:58:27 -05:00
2007-01-21 20:44:09 +01:00
int node_id ;
int generation ;
/* This is the generation used for timestamping incoming requests. */
int request_generation ;
int current_tlabel , tlabel_mask ;
struct list_head transaction_list ;
2006-12-19 19:58:27 -05:00
struct timer_list flush_timer ;
2007-01-26 00:38:45 -05:00
unsigned long reset_jiffies ;
2006-12-19 19:58:27 -05:00
2007-01-21 20:44:09 +01:00
unsigned long long guid ;
2007-07-21 22:43:05 +02:00
unsigned max_receive ;
2006-12-19 19:58:27 -05:00
int link_speed ;
int config_rom_generation ;
2007-05-07 20:33:32 -04:00
/*
* We need to store up to 4 self ID for a maximum of 63
* devices plus 3 words for the topology map header .
*/
2007-01-21 20:44:09 +01:00
int self_id_count ;
2007-03-07 12:12:55 -05:00
u32 topology_map [ 252 + 3 ] ;
2006-12-19 19:58:27 -05:00
spinlock_t lock ; /* Take this lock when handling the lists in
* this struct . */
struct fw_node * local_node ;
struct fw_node * root_node ;
struct fw_node * irm_node ;
int color ;
2007-01-26 00:37:50 -05:00
int gap_count ;
2007-06-18 19:44:12 +02:00
bool beta_repeaters_present ;
2006-12-19 19:58:27 -05:00
int index ;
struct list_head link ;
2006-12-19 19:58:31 -05:00
2007-01-26 00:38:45 -05:00
/* Work struct for BM duties. */
2006-12-19 19:58:31 -05:00
struct delayed_work work ;
2007-01-26 00:38:45 -05:00
int bm_retries ;
int bm_generation ;
2006-12-19 19:58:27 -05:00
} ;
struct fw_card * fw_card_get ( struct fw_card * card ) ;
void fw_card_put ( struct fw_card * card ) ;
2007-05-07 20:33:32 -04:00
/*
* The iso packet format allows for an immediate header / payload part
2006-12-19 19:58:27 -05:00
* stored in ' header ' immediately after the packet info plus an
* indirect payload part that is pointer to by the ' payload ' field .
* Applications can use one or the other or both to implement simple
* low - bandwidth streaming ( e . g . audio ) or more advanced
2007-05-07 20:33:32 -04:00
* scatter - gather streaming ( e . g . assembling video frame automatically ) .
*/
2006-12-19 19:58:27 -05:00
struct fw_iso_packet {
2007-01-21 20:44:09 +01:00
u16 payload_length ; /* Length of indirect payload. */
2006-12-19 19:58:27 -05:00
u32 interrupt : 1 ; /* Generate interrupt on this packet */
u32 skip : 1 ; /* Set to not send packet at all. */
u32 tag : 2 ;
u32 sy : 4 ;
u32 header_length : 8 ; /* Length of immediate header. */
2007-01-21 20:44:09 +01:00
u32 header [ 0 ] ;
2006-12-19 19:58:27 -05:00
} ;
# define FW_ISO_CONTEXT_TRANSMIT 0
# define FW_ISO_CONTEXT_RECEIVE 1
2007-02-16 17:34:51 -05:00
# 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
2006-12-19 19:58:27 -05:00
struct fw_iso_context ;
2007-05-07 20:33:34 -04:00
typedef void ( * fw_iso_callback_t ) ( struct fw_iso_context * context ,
u32 cycle ,
size_t header_length ,
void * header ,
void * data ) ;
2006-12-19 19:58:27 -05:00
2007-05-07 20:33:32 -04:00
/*
* An iso buffer is just a set of pages mapped for DMA in the
2007-02-16 17:34:38 -05:00
* specified direction . Since the pages are to be used for DMA , they
* are not mapped into the kernel virtual address space . We store the
* DMA address in the page private . The helper function
2007-05-07 20:33:32 -04:00
* fw_iso_buffer_map ( ) will map the pages into a given vma .
*/
2007-02-16 17:34:38 -05:00
struct fw_iso_buffer {
enum dma_data_direction direction ;
struct page * * pages ;
int page_count ;
} ;
2006-12-19 19:58:27 -05:00
struct fw_iso_context {
struct fw_card * card ;
int type ;
int channel ;
int speed ;
2007-02-16 17:34:40 -05:00
size_t header_size ;
2006-12-19 19:58:27 -05:00
fw_iso_callback_t callback ;
void * callback_data ;
} ;
2007-02-16 17:34:38 -05:00
int
fw_iso_buffer_init ( struct fw_iso_buffer * buffer ,
struct fw_card * card ,
int page_count ,
enum dma_data_direction direction ) ;
int
fw_iso_buffer_map ( struct fw_iso_buffer * buffer , struct vm_area_struct * vma ) ;
void
fw_iso_buffer_destroy ( struct fw_iso_buffer * buffer , struct fw_card * card ) ;
2006-12-19 19:58:27 -05:00
struct fw_iso_context *
2007-02-16 17:34:50 -05:00
fw_iso_context_create ( struct fw_card * card , int type ,
2007-03-14 17:34:54 -04:00
int channel , int speed , size_t header_size ,
2007-02-16 17:34:40 -05:00
fw_iso_callback_t callback , void * callback_data ) ;
2007-02-16 17:34:38 -05:00
2006-12-19 19:58:27 -05:00
void
fw_iso_context_destroy ( struct fw_iso_context * ctx ) ;
int
fw_iso_context_queue ( struct fw_iso_context * ctx ,
2007-02-16 17:34:38 -05:00
struct fw_iso_packet * packet ,
struct fw_iso_buffer * buffer ,
unsigned long payload ) ;
2006-12-19 19:58:27 -05:00
int
2007-03-14 17:34:54 -04:00
fw_iso_context_start ( struct fw_iso_context * ctx ,
int cycle , int sync , int tags ) ;
2006-12-19 19:58:27 -05:00
2007-02-16 17:34:42 -05:00
int
fw_iso_context_stop ( struct fw_iso_context * ctx ) ;
2006-12-19 19:58:27 -05:00
struct fw_card_driver {
2007-01-21 20:44:09 +01:00
const char * name ;
2006-12-19 19:58:27 -05:00
2007-05-07 20:33:32 -04:00
/*
* Enable the given card with the given initial config rom .
2007-01-21 20:44:09 +01:00
* This function is expected to activate the card , and either
* enable the PHY or set the link_on bit and initiate a bus
2007-05-07 20:33:32 -04:00
* reset .
*/
2007-05-07 20:33:34 -04:00
int ( * enable ) ( struct fw_card * card , u32 * config_rom , size_t length ) ;
2006-12-19 19:58:27 -05:00
2007-05-07 20:33:34 -04:00
int ( * update_phy_reg ) ( struct fw_card * card , int address ,
int clear_bits , int set_bits ) ;
2006-12-19 19:58:27 -05:00
2007-05-07 20:33:32 -04:00
/*
* Update the config rom for an enabled card . This function
2007-01-21 20:44:09 +01:00
* should change the config rom that is presented on the bus
2007-05-07 20:33:32 -04:00
* an initiate a bus reset .
*/
2007-05-07 20:33:34 -04:00
int ( * set_config_rom ) ( struct fw_card * card ,
u32 * config_rom , size_t length ) ;
2006-12-19 19:58:27 -05:00
2007-05-07 20:33:34 -04:00
void ( * send_request ) ( struct fw_card * card , struct fw_packet * packet ) ;
void ( * send_response ) ( struct fw_card * card , struct fw_packet * packet ) ;
2007-02-06 14:49:32 -05:00
/* Calling cancel is valid once a packet has been submitted. */
2007-05-07 20:33:34 -04:00
int ( * cancel_packet ) ( struct fw_card * card , struct fw_packet * packet ) ;
2006-12-19 19:58:27 -05:00
2007-05-07 20:33:32 -04:00
/*
* Allow the specified node ID to do direct DMA out and in of
2006-12-19 19:58:27 -05:00
* host memory . The card will disable this for all node when
* a bus reset happens , so driver need to reenable this after
* bus reset . Returns 0 on success , - ENODEV if the card
* doesn ' t support this , - ESTALE if the generation doesn ' t
2007-05-07 20:33:32 -04:00
* match .
*/
2007-05-07 20:33:34 -04:00
int ( * enable_phys_dma ) ( struct fw_card * card ,
int node_id , int generation ) ;
2006-12-19 19:58:27 -05:00
2007-05-07 20:33:34 -04:00
u64 ( * get_bus_time ) ( struct fw_card * card ) ;
2007-03-07 12:12:56 -05:00
2006-12-19 19:58:27 -05:00
struct fw_iso_context *
2007-03-14 17:34:54 -04:00
( * allocate_iso_context ) ( struct fw_card * card ,
2007-02-16 17:34:46 -05:00
int type , size_t header_size ) ;
2006-12-19 19:58:27 -05:00
void ( * free_iso_context ) ( struct fw_iso_context * ctx ) ;
2007-03-14 17:34:54 -04:00
int ( * start_iso ) ( struct fw_iso_context * ctx ,
s32 cycle , u32 sync , u32 tags ) ;
2006-12-19 19:58:27 -05:00
int ( * queue_iso ) ( struct fw_iso_context * ctx ,
2007-02-16 17:34:38 -05:00
struct fw_iso_packet * packet ,
struct fw_iso_buffer * buffer ,
unsigned long payload ) ;
2007-02-16 17:34:42 -05:00
int ( * stop_iso ) ( struct fw_iso_context * ctx ) ;
2006-12-19 19:58:27 -05:00
} ;
int
fw_core_initiate_bus_reset ( struct fw_card * card , int short_reset ) ;
void
fw_send_request ( struct fw_card * card , struct fw_transaction * t ,
int tcode , int node_id , int generation , int speed ,
unsigned long long offset ,
void * data , size_t length ,
fw_transaction_callback_t callback , void * callback_data ) ;
2007-02-06 14:49:32 -05:00
int fw_cancel_transaction ( struct fw_card * card ,
struct fw_transaction * transaction ) ;
2006-12-19 19:58:27 -05:00
void fw_flush_transactions ( struct fw_card * card ) ;
2007-01-26 00:37:50 -05:00
void fw_send_phy_config ( struct fw_card * card ,
int node_id , int generation , int gap_count ) ;
2006-12-19 19:58:27 -05:00
2007-05-07 20:33:32 -04:00
/*
* Called by the topology code to inform the device code of node
* activity ; found , lost , or updated nodes .
*/
2006-12-19 19:58:27 -05:00
void
fw_node_event ( struct fw_card * card , struct fw_node * node , int event ) ;
/* API used by card level drivers */
void
2007-01-14 15:29:07 +01:00
fw_card_initialize ( struct fw_card * card , const struct fw_card_driver * driver ,
2006-12-19 19:58:27 -05:00
struct device * device ) ;
int
fw_card_add ( struct fw_card * card ,
u32 max_receive , u32 link_speed , u64 guid ) ;
void
fw_core_remove_card ( struct fw_card * card ) ;
void
fw_core_handle_bus_reset ( struct fw_card * card ,
int node_id , int generation ,
int self_id_count , u32 * self_ids ) ;
void
2007-01-26 00:37:57 -05:00
fw_core_handle_request ( struct fw_card * card , struct fw_packet * request ) ;
2006-12-19 19:58:27 -05:00
2007-01-26 00:37:57 -05:00
void
fw_core_handle_response ( struct fw_card * card , struct fw_packet * packet ) ;
2006-12-19 19:58:27 -05:00
2006-12-28 16:20:00 +01:00
# endif /* __fw_transaction_h */