| 1 |
|
| 2 | #ifndef _FIREWIRE_CORE_H
|
| 3 | #define _FIREWIRE_CORE_H
|
| 4 |
|
| 5 | #include <linux/compiler.h>
|
| 6 | #include <linux/device.h>
|
| 7 | #include <linux/dma-mapping.h>
|
| 8 | #include <linux/fs.h>
|
| 9 | #include <linux/list.h>
|
| 10 | #include <linux/xarray.h>
|
| 11 | #include <linux/mm_types.h>
|
| 12 | #include <linux/rwsem.h>
|
| 13 | #include <linux/slab.h>
|
| 14 | #include <linux/types.h>
|
| 15 |
|
| 16 | #include <linux/refcount.h>
|
| 17 |
|
| 18 | struct device;
|
| 19 | struct fw_card;
|
| 20 | struct fw_device;
|
| 21 | struct fw_iso_buffer;
|
| 22 | struct fw_iso_context;
|
| 23 | struct fw_iso_packet;
|
| 24 | struct fw_node;
|
| 25 | struct fw_packet;
|
| 26 |
|
| 27 |
|
| 28 |
|
| 29 |
|
| 30 | |
| 31 | #define GAP_COUNT_MISMATCHED 0
|
| 32 |
|
| 33 | #define isoc_cycles_to_jiffies(cycles) usecs_to_jiffies((u32)div_u64((u64)cycles * USEC_PER_SEC, 8000))
|
| 34 |
|
| 35 | extern __printf(2, 3)
|
| 36 | void fw_err(const struct fw_card *card, const char *fmt, ...);
|
| 37 | extern __printf(2, 3)
|
| 38 | void fw_notice(const struct fw_card *card, const char *fmt, ...);
|
| 39 |
|
| 40 |
|
| 41 | #define PHY_LINK_ACTIVE 0x80
|
| 42 | #define PHY_CONTENDER 0x40
|
| 43 | #define PHY_BUS_RESET 0x40
|
| 44 | #define PHY_EXTENDED_REGISTERS 0xe0
|
| 45 | #define PHY_BUS_SHORT_RESET 0x40
|
| 46 | #define PHY_INT_STATUS_BITS 0x3c
|
| 47 | #define PHY_ENABLE_ACCEL 0x02
|
| 48 | #define PHY_ENABLE_MULTI 0x01
|
| 49 | #define PHY_PAGE_SELECT 0xe0
|
| 50 |
|
| 51 | #define BANDWIDTH_AVAILABLE_INITIAL 4915
|
| 52 | #define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31)
|
| 53 | #define BROADCAST_CHANNEL_VALID (1 << 30)
|
| 54 |
|
| 55 | #define CSR_STATE_BIT_CMSTR (1 << 8)
|
| 56 | #define CSR_STATE_BIT_ABDICATE (1 << 10)
|
| 57 |
|
| 58 | struct fw_card_driver {
|
| 59 | |
| 60 | * Enable the given card with the given initial config rom.
|
| 61 | * This function is expected to activate the card, and either
|
| 62 | * enable the PHY or set the link_on bit and initiate a bus
|
| 63 | * reset.
|
| 64 |
|
| 65 | int (*enable)(struct fw_card *card,
|
| 66 | const __be32 *config_rom, size_t length);
|
| 67 |
|
| 68 | |
| 69 | void (*disable)(struct fw_card *card);
|
| 70 |
|
| 71 | int (*read_phy_reg)(struct fw_card *card, int address);
|
| 72 | int (*update_phy_reg)(struct fw_card *card, int address,
|
| 73 | int clear_bits, int set_bits);
|
| 74 |
|
| 75 | |
| 76 | * Update the config rom for an enabled card. This function
|
| 77 | * should change the config rom that is presented on the bus
|
| 78 | * and initiate a bus reset.
|
| 79 |
|
| 80 | int (*set_config_rom)(struct fw_card *card,
|
| 81 | const __be32 *config_rom, size_t length);
|
| 82 |
|
| 83 | void (*send_request)(struct fw_card *card, struct fw_packet *packet);
|
| 84 | void (*send_response)(struct fw_card *card, struct fw_packet *packet);
|
| 85 |
|
| 86 | int (*cancel_packet)(struct fw_card *card, struct fw_packet *packet);
|
| 87 |
|
| 88 | |
| 89 | * Allow the specified node ID to do direct DMA out and in of
|
| 90 | * host memory. The card will disable this for all node when
|
| 91 | * a bus reset happens, so driver need to re-enable this after
|
| 92 | * bus reset. Returns 0 on success, -ENODEV if the card
|
| 93 | * doesn't support this, -ESTALE if the generation doesn't
|
| 94 | * match.
|
| 95 |
|
| 96 | int (*enable_phys_dma)(struct fw_card *card,
|
| 97 | int node_id, int generation);
|
| 98 |
|
| 99 | u32 (*read_csr)(struct fw_card *card, int csr_offset);
|
| 100 | void (*write_csr)(struct fw_card *card, int csr_offset, u32 value);
|
| 101 |
|
| 102 | struct fw_iso_context *
|
| 103 | (*allocate_iso_context)(struct fw_card *card, int type, int channel, size_t header_size,
|
| 104 | size_t header_storage_size);
|
| 105 | void (*free_iso_context)(struct fw_iso_context *ctx);
|
| 106 |
|
| 107 | int (*start_iso)(struct fw_iso_context *ctx,
|
| 108 | s32 cycle, u32 sync, u32 tags);
|
| 109 |
|
| 110 | int (*set_iso_channels)(struct fw_iso_context *ctx, u64 *channels);
|
| 111 |
|
| 112 | int (*queue_iso)(struct fw_iso_context *ctx,
|
| 113 | struct fw_iso_packet *packet,
|
| 114 | struct fw_iso_buffer *buffer,
|
| 115 | unsigned long payload);
|
| 116 |
|
| 117 | void (*flush_queue_iso)(struct fw_iso_context *ctx);
|
| 118 |
|
| 119 | int (*flush_iso_completions)(struct fw_iso_context *ctx);
|
| 120 |
|
| 121 | int (*stop_iso)(struct fw_iso_context *ctx);
|
| 122 | };
|
| 123 |
|
| 124 | void fw_card_initialize(struct fw_card *card,
|
| 125 | const struct fw_card_driver *driver, struct device *device);
|
| 126 | int fw_card_add(struct fw_card *card, u32 max_receive, u32 link_speed, u64 guid,
|
| 127 | unsigned int supported_isoc_contexts);
|
| 128 | void fw_core_remove_card(struct fw_card *card);
|
| 129 | int fw_compute_block_crc(__be32 *block);
|
| 130 | void fw_schedule_bm_work(struct fw_card *card, unsigned long delay);
|
| 131 |
|
| 132 |
|
| 133 |
|
| 134 | extern const struct file_operations fw_device_ops;
|
| 135 |
|
| 136 | void fw_device_cdev_update(struct fw_device *device);
|
| 137 | void fw_device_cdev_remove(struct fw_device *device);
|
| 138 | void fw_cdev_handle_phy_packet(struct fw_card *card, struct fw_packet *p);
|
| 139 |
|
| 140 |
|
| 141 |
|
| 142 |
|
| 143 | extern struct rw_semaphore fw_device_rwsem;
|
| 144 | extern struct xarray fw_device_xa;
|
| 145 | extern int fw_cdev_major;
|
| 146 |
|
| 147 | static inline struct fw_device *fw_device_get(struct fw_device *device)
|
| 148 | {
|
| 149 | get_device(&device->device);
|
| 150 |
|
| 151 | return device;
|
| 152 | }
|
| 153 |
|
| 154 | static inline void fw_device_put(struct fw_device *device)
|
| 155 | {
|
| 156 | put_device(&device->device);
|
| 157 | }
|
| 158 |
|
| 159 | struct fw_device *fw_device_get_by_devt(dev_t devt);
|
| 160 | int fw_device_set_broadcast_channel(struct device *dev, void *gen);
|
| 161 | void fw_node_event(struct fw_card *card, struct fw_node *node, int event);
|
| 162 |
|
| 163 |
|
| 164 |
|
| 165 |
|
| 166 | int fw_iso_buffer_alloc(struct fw_iso_buffer *buffer, int page_count);
|
| 167 | int fw_iso_buffer_map_dma(struct fw_iso_buffer *buffer, struct fw_card *card,
|
| 168 | enum dma_data_direction direction);
|
| 169 | size_t fw_iso_buffer_lookup(struct fw_iso_buffer *buffer, dma_addr_t completed);
|
| 170 |
|
| 171 | static inline void fw_iso_context_init_work(struct fw_iso_context *ctx, work_func_t func)
|
| 172 | {
|
| 173 | INIT_WORK(&ctx->work, func);
|
| 174 | }
|
| 175 |
|
| 176 | static inline struct fw_iso_context *fw_iso_mc_context_create(struct fw_card *card,
|
| 177 | fw_iso_mc_callback_t callback, void *callback_data)
|
| 178 | {
|
| 179 | union fw_iso_callback cb = { .mc = callback };
|
| 180 |
|
| 181 | return __fw_iso_context_create(card, FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL, 0, 0, 0, 0, cb,
|
| 182 | callback_data);
|
| 183 | }
|
| 184 |
|
| 185 |
|
| 186 |
|
| 187 |
|
| 188 | |
| 189 | #define BUS_MANAGER_ID_NOT_REGISTERED 0x3f
|
| 190 |
|
| 191 | enum {
|
| 192 | FW_NODE_CREATED,
|
| 193 | FW_NODE_UPDATED,
|
| 194 | FW_NODE_DESTROYED,
|
| 195 | FW_NODE_LINK_ON,
|
| 196 | FW_NODE_LINK_OFF,
|
| 197 | FW_NODE_INITIATED_RESET,
|
| 198 | };
|
| 199 |
|
| 200 | struct fw_node {
|
| 201 | u16 node_id;
|
| 202 | u8 color;
|
| 203 | u8 port_count;
|
| 204 | u8 link_on:1;
|
| 205 | u8 initiated_reset:1;
|
| 206 | u8 b_path:1;
|
| 207 | u8 phy_speed:2;
|
| 208 | u8 max_speed:2; |
| 209 | * local node to this node.
|
| 210 | u8 max_depth:4;
|
| 211 | u8 max_hops:4;
|
| 212 |
|
| 213 | struct kref kref;
|
| 214 |
|
| 215 |
|
| 216 | struct list_head link;
|
| 217 |
|
| 218 | |
| 219 | struct fw_device *device;
|
| 220 |
|
| 221 | struct fw_node *ports[] __counted_by(port_count);
|
| 222 | };
|
| 223 |
|
| 224 | static inline struct fw_node *fw_node_get(struct fw_node *node)
|
| 225 | {
|
| 226 | kref_get(&node->kref);
|
| 227 |
|
| 228 | return node;
|
| 229 | }
|
| 230 |
|
| 231 | static void release_node(struct kref *kref)
|
| 232 | {
|
| 233 | struct fw_node *node = container_of(kref, struct fw_node, kref);
|
| 234 |
|
| 235 | kfree(node);
|
| 236 | }
|
| 237 |
|
| 238 | static inline void fw_node_put(struct fw_node *node)
|
| 239 | {
|
| 240 | kref_put(&node->kref, release_node);
|
| 241 | }
|
| 242 |
|
| 243 | static inline struct fw_device *fw_node_get_device(struct fw_node *node)
|
| 244 | {
|
| 245 | return node->device;
|
| 246 | }
|
| 247 |
|
| 248 | static inline void fw_node_set_device(struct fw_node *node, struct fw_device *device)
|
| 249 | {
|
| 250 | node->device = device;
|
| 251 | }
|
| 252 |
|
| 253 | void fw_core_handle_bus_reset(struct fw_card *card, int node_id,
|
| 254 | int generation, int self_id_count, u32 *self_ids, bool bm_abdicate);
|
| 255 | void fw_destroy_nodes(struct fw_card *card);
|
| 256 |
|
| 257 | |
| 258 | * Check whether new_generation is the immediate successor of old_generation.
|
| 259 | * Take counter roll-over at 255 (as per OHCI) into account.
|
| 260 |
|
| 261 | static inline bool is_next_generation(int new_generation, int old_generation)
|
| 262 | {
|
| 263 | return (new_generation & 0xff) == ((old_generation + 1) & 0xff);
|
| 264 | }
|
| 265 |
|
| 266 |
|
| 267 |
|
| 268 |
|
| 269 | #define TCODE_LINK_INTERNAL 0xe
|
| 270 |
|
| 271 | static inline bool tcode_is_read_request(unsigned int tcode)
|
| 272 | {
|
| 273 | return (tcode & ~1u) == 4u;
|
| 274 | }
|
| 275 |
|
| 276 | static inline bool tcode_is_block_packet(unsigned int tcode)
|
| 277 | {
|
| 278 | return (tcode & 1u) != 0u;
|
| 279 | }
|
| 280 |
|
| 281 | static inline bool tcode_is_link_internal(unsigned int tcode)
|
| 282 | {
|
| 283 | return (tcode == TCODE_LINK_INTERNAL);
|
| 284 | }
|
| 285 |
|
| 286 | #define LOCAL_BUS 0xffc0
|
| 287 |
|
| 288 |
|
| 289 | #define FW_MAX_PHYSICAL_RANGE (1ULL << 32)
|
| 290 |
|
| 291 | void fw_core_handle_request(struct fw_card *card, struct fw_packet *request);
|
| 292 | void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);
|
| 293 | int fw_get_response_length(struct fw_request *request);
|
| 294 | void fw_fill_response(struct fw_packet *response, u32 *request_header,
|
| 295 | int rcode, void *payload, size_t length);
|
| 296 |
|
| 297 | void fw_request_get(struct fw_request *request);
|
| 298 | void fw_request_put(struct fw_request *request);
|
| 299 |
|
| 300 | void fw_cancel_pending_transactions(struct fw_card *card);
|
| 301 |
|
| 302 | |
| 303 | |
| 304 | static inline u32 cycle_time_to_ohci_tstamp(u32 tstamp)
|
| 305 | {
|
| 306 | return (tstamp & 0x0ffff000) >> 12;
|
| 307 | }
|
| 308 |
|
| 309 | #define FW_PHY_CONFIG_NO_NODE_ID -1
|
| 310 | #define FW_PHY_CONFIG_CURRENT_GAP_COUNT -1
|
| 311 | void fw_send_phy_config(struct fw_card *card,
|
| 312 | int node_id, int generation, int gap_count);
|
| 313 |
|
| 314 | static inline bool is_ping_packet(u32 *data)
|
| 315 | {
|
| 316 | return (data[0] & 0xc0ffffff) == 0 && ~data[0] == data[1];
|
| 317 | }
|
| 318 |
|
| 319 | static inline bool is_in_fcp_region(u64 offset, size_t length)
|
| 320 | {
|
| 321 | return offset >= (CSR_REGISTER_BASE | CSR_FCP_COMMAND) &&
|
| 322 | offset + length <= (CSR_REGISTER_BASE | CSR_FCP_END);
|
| 323 | }
|
| 324 |
|
| 325 | #endif
|