aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2006-12-19 19:58:27 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-03-09 16:02:33 -0500
commit3038e353cfaf548eb94f02b172b9dbe412abd24c (patch)
tree70e50c20e117e2dacb7cd810d00fe595e60d26ce /drivers/firewire
parent08e15e81a40e3241ce93b4a43886f3abda184aa6 (diff)
firewire: Add core firewire stack.
Signed-off-by: Kristian Høgsberg <krh@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/Kconfig23
-rw-r--r--drivers/firewire/Makefile7
-rw-r--r--drivers/firewire/fw-card.c384
-rw-r--r--drivers/firewire/fw-iso.c136
-rw-r--r--drivers/firewire/fw-topology.c446
-rw-r--r--drivers/firewire/fw-topology.h84
-rw-r--r--drivers/firewire/fw-transaction.c730
-rw-r--r--drivers/firewire/fw-transaction.h422
8 files changed, 2232 insertions, 0 deletions
diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig
new file mode 100644
index 000000000000..bdd6303f1a4e
--- /dev/null
+++ b/drivers/firewire/Kconfig
@@ -0,0 +1,23 @@
1# -*- shell-script -*-
2
3menu "IEEE 1394 (FireWire) support (JUJU alternative stack)"
4
5config FW
6 tristate "IEEE 1394 (FireWire) support (JUJU alternative stack)"
7 help
8 IEEE 1394 describes a high performance serial bus, which is also
9 known as FireWire(tm) or i.Link(tm) and is used for connecting all
10 sorts of devices (most notably digital video cameras) to your
11 computer.
12
13 If you have FireWire hardware and want to use it, say Y here. This
14 is the core support only, you will also need to select a driver for
15 your IEEE 1394 adapter.
16
17 This is the "JUJU" firewire stack, an alternative
18 implementation designed for roboustness and simplicity.
19
20 To compile this driver as a module, say M here: the
21 module will be called fw-core.
22
23endmenu
diff --git a/drivers/firewire/Makefile b/drivers/firewire/Makefile
new file mode 100644
index 000000000000..db7020dd02af
--- /dev/null
+++ b/drivers/firewire/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for the Linux IEEE 1394 implementation
3#
4
5fw-core-objs := fw-card.o fw-topology.o fw-transaction.o fw-iso.o
6
7obj-$(CONFIG_FW) += fw-core.o
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
new file mode 100644
index 000000000000..d8abd70ce843
--- /dev/null
+++ b/drivers/firewire/fw-card.c
@@ -0,0 +1,384 @@
1/* -*- c-basic-offset: 8 -*-
2 *
3 * fw-card.c - card level functions
4 *
5 * Copyright (C) 2005-2006 Kristian Hoegsberg <krh@bitplanet.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include <linux/module.h>
23#include <linux/errno.h>
24#include <linux/device.h>
25#include "fw-transaction.h"
26#include "fw-topology.h"
27
28/* The lib/crc16.c implementation uses the standard (0x8005)
29 * polynomial, but we need the ITU-T (or CCITT) polynomial (0x1021).
30 * The implementation below works on an array of host-endian u32
31 * words, assuming they'll be transmited msb first. */
32static u16
33crc16_itu_t(const u32 *buffer, size_t length)
34{
35 int shift, i;
36 u32 data;
37 u16 sum, crc = 0;
38
39 for (i = 0; i < length; i++) {
40 data = *buffer++;
41 for (shift = 28; shift >= 0; shift -= 4 ) {
42 sum = ((crc >> 12) ^ (data >> shift)) & 0xf;
43 crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
44 }
45 crc &= 0xffff;
46 }
47
48 return crc;
49}
50
51static LIST_HEAD(card_list);
52
53static LIST_HEAD(descriptor_list);
54static int descriptor_count;
55
56#define bib_crc(v) ((v) << 0)
57#define bib_crc_length(v) ((v) << 16)
58#define bib_info_length(v) ((v) << 24)
59
60#define bib_link_speed(v) ((v) << 0)
61#define bib_generation(v) ((v) << 4)
62#define bib_max_rom(v) ((v) << 8)
63#define bib_max_receive(v) ((v) << 12)
64#define bib_cyc_clk_acc(v) ((v) << 16)
65#define bib_pmc ((1) << 27)
66#define bib_bmc ((1) << 28)
67#define bib_isc ((1) << 29)
68#define bib_cmc ((1) << 30)
69#define bib_imc ((1) << 31)
70
71static u32 *
72generate_config_rom (struct fw_card *card, size_t *config_rom_length)
73{
74 struct fw_descriptor *desc;
75 static u32 config_rom[256];
76 int i, j, length;
77
78 /* Initialize contents of config rom buffer. On the OHCI
79 * controller, block reads to the config rom accesses the host
80 * memory, but quadlet read access the hardware bus info block
81 * registers. That's just crack, but it means we should make
82 * sure the contents of bus info block in host memory mathces
83 * the version stored in the OHCI registers. */
84
85 memset(config_rom, 0, sizeof config_rom);
86 config_rom[0] = bib_crc_length(4) | bib_info_length(4) | bib_crc(0);
87 config_rom[1] = 0x31333934;
88
89 config_rom[2] =
90 bib_link_speed(card->link_speed) |
91 bib_generation(card->config_rom_generation++ % 14 + 2) |
92 bib_max_rom(2) |
93 bib_max_receive(card->max_receive) |
94 bib_isc | bib_cmc | bib_imc;
95 config_rom[3] = card->guid >> 32;
96 config_rom[4] = card->guid;
97
98 /* Generate root directory. */
99 i = 5;
100 config_rom[i++] = 0;
101 config_rom[i++] = 0x0c0083c0; /* node capabilities */
102 config_rom[i++] = 0x03d00d1e; /* vendor id */
103 j = i + descriptor_count;
104
105 /* Generate root directory entries for descriptors. */
106 list_for_each_entry (desc, &descriptor_list, link) {
107 config_rom[i] = desc->key | (j - i);
108 i++;
109 j += desc->length;
110 }
111
112 /* Update root directory length. */
113 config_rom[5] = (i - 5 - 1) << 16;
114
115 /* End of root directory, now copy in descriptors. */
116 list_for_each_entry (desc, &descriptor_list, link) {
117 memcpy(&config_rom[i], desc->data, desc->length * 4);
118 i += desc->length;
119 }
120
121 /* Calculate CRCs for all blocks in the config rom. This
122 * assumes that CRC length and info length are identical for
123 * the bus info block, which is always the case for this
124 * implementation. */
125 for (i = 0; i < j; i += length + 1) {
126 length = (config_rom[i] >> 16) & 0xff;
127 config_rom[i] |= crc16_itu_t(&config_rom[i + 1], length);
128 }
129
130 *config_rom_length = j;
131
132 return config_rom;
133}
134
135static void
136update_config_roms (void)
137{
138 struct fw_card *card;
139 u32 *config_rom;
140 size_t length;
141
142 list_for_each_entry (card, &card_list, link) {
143 config_rom = generate_config_rom(card, &length);
144 card->driver->set_config_rom(card, config_rom, length);
145 }
146}
147
148int
149fw_core_add_descriptor (struct fw_descriptor *desc)
150{
151 size_t i;
152
153 /* Check descriptor is valid; the length of all blocks in the
154 * descriptor has to add up to exactly the length of the
155 * block. */
156 i = 0;
157 while (i < desc->length)
158 i += (desc->data[i] >> 16) + 1;
159
160 if (i != desc->length)
161 return -1;
162
163 down_write(&fw_bus_type.subsys.rwsem);
164
165 list_add_tail (&desc->link, &descriptor_list);
166 descriptor_count++;
167 update_config_roms();
168
169 up_write(&fw_bus_type.subsys.rwsem);
170
171 return 0;
172}
173EXPORT_SYMBOL(fw_core_add_descriptor);
174
175void
176fw_core_remove_descriptor (struct fw_descriptor *desc)
177{
178 down_write(&fw_bus_type.subsys.rwsem);
179
180 list_del(&desc->link);
181 descriptor_count--;
182 update_config_roms();
183
184 up_write(&fw_bus_type.subsys.rwsem);
185}
186EXPORT_SYMBOL(fw_core_remove_descriptor);
187
188static void
189release_card(struct device *device)
190{
191 struct fw_card *card =
192 container_of(device, struct fw_card, card_device);
193
194 kfree(card);
195}
196
197static void
198flush_timer_callback(unsigned long data)
199{
200 struct fw_card *card = (struct fw_card *)data;
201
202 fw_flush_transactions(card);
203}
204
205void
206fw_card_initialize(struct fw_card *card, struct fw_card_driver *driver,
207 struct device *device)
208{
209 static int index;
210
211 card->index = index++;
212 card->driver = driver;
213 card->device = device;
214 card->current_tlabel = 0;
215 card->tlabel_mask = 0;
216 card->color = 0;
217
218 INIT_LIST_HEAD(&card->transaction_list);
219 spin_lock_init(&card->lock);
220 setup_timer(&card->flush_timer,
221 flush_timer_callback, (unsigned long)card);
222
223 card->local_node = NULL;
224
225 card->card_device.bus = &fw_bus_type;
226 card->card_device.release = release_card;
227 card->card_device.parent = card->device;
228 snprintf(card->card_device.bus_id, sizeof card->card_device.bus_id,
229 "fwcard%d", card->index);
230
231 device_initialize(&card->card_device);
232}
233EXPORT_SYMBOL(fw_card_initialize);
234
235int
236fw_card_add(struct fw_card *card,
237 u32 max_receive, u32 link_speed, u64 guid)
238{
239 int retval;
240 u32 *config_rom;
241 size_t length;
242
243 card->max_receive = max_receive;
244 card->link_speed = link_speed;
245 card->guid = guid;
246
247 /* FIXME: add #define's for phy registers. */
248 /* Activate link_on bit and contender bit in our self ID packets.*/
249 if (card->driver->update_phy_reg(card, 4, 0, 0x80 | 0x40) < 0)
250 return -EIO;
251
252 retval = device_add(&card->card_device);
253 if (retval < 0) {
254 fw_error("Failed to register card device.");
255 return retval;
256 }
257
258 /* The subsystem grabs a reference when the card is added and
259 * drops it when the driver calls fw_core_remove_card. */
260 fw_card_get(card);
261
262 down_write(&fw_bus_type.subsys.rwsem);
263 config_rom = generate_config_rom (card, &length);
264 list_add_tail(&card->link, &card_list);
265 up_write(&fw_bus_type.subsys.rwsem);
266
267 return card->driver->enable(card, config_rom, length);
268}
269EXPORT_SYMBOL(fw_card_add);
270
271
272/* The next few functions implements a dummy driver that use once a
273 * card driver shuts down an fw_card. This allows the driver to
274 * cleanly unload, as all IO to the card will be handled by the dummy
275 * driver instead of calling into the (possibly) unloaded module. The
276 * dummy driver just fails all IO. */
277
278static int
279dummy_enable(struct fw_card *card, u32 *config_rom, size_t length)
280{
281 BUG();
282 return -1;
283}
284
285static int
286dummy_update_phy_reg(struct fw_card *card, int address,
287 int clear_bits, int set_bits)
288{
289 return -ENODEV;
290}
291
292static int
293dummy_set_config_rom(struct fw_card *card,
294 u32 *config_rom, size_t length)
295{
296 /* We take the card out of card_list before setting the dummy
297 * driver, so this should never get called. */
298 BUG();
299 return -1;
300}
301
302static void
303dummy_send_request(struct fw_card *card, struct fw_packet *packet)
304{
305 packet->callback(packet, card, -ENODEV);
306}
307
308static void
309dummy_send_response(struct fw_card *card, struct fw_packet *packet)
310{
311 packet->callback(packet, card, -ENODEV);
312}
313
314static int
315dummy_enable_phys_dma(struct fw_card *card,
316 int node_id, int generation)
317{
318 return -ENODEV;
319}
320
321static struct fw_card_driver dummy_driver = {
322 .name = "dummy",
323 .enable = dummy_enable,
324 .update_phy_reg = dummy_update_phy_reg,
325 .set_config_rom = dummy_set_config_rom,
326 .send_request = dummy_send_request,
327 .send_response = dummy_send_response,
328 .enable_phys_dma = dummy_enable_phys_dma
329};
330
331void
332fw_core_remove_card(struct fw_card *card)
333{
334 card->driver->update_phy_reg(card, 4, 0x80 | 0x40, 0);
335 fw_core_initiate_bus_reset(card, 1);
336
337 down_write(&fw_bus_type.subsys.rwsem);
338 list_del(&card->link);
339 up_write(&fw_bus_type.subsys.rwsem);
340
341 /* Set up the dummy driver. */
342 card->driver = &dummy_driver;
343
344 fw_flush_transactions(card);
345
346 fw_destroy_nodes(card);
347
348 /* This also drops the subsystem reference. */
349 device_unregister(&card->card_device);
350}
351EXPORT_SYMBOL(fw_core_remove_card);
352
353struct fw_card *
354fw_card_get(struct fw_card *card)
355{
356 get_device(&card->card_device);
357
358 return card;
359}
360EXPORT_SYMBOL(fw_card_get);
361
362/* An assumption for fw_card_put() is that the card driver allocates
363 * the fw_card struct with kalloc and that it has been shut down
364 * before the last ref is dropped. */
365void
366fw_card_put(struct fw_card *card)
367{
368 put_device(&card->card_device);
369}
370EXPORT_SYMBOL(fw_card_put);
371
372int
373fw_core_initiate_bus_reset(struct fw_card *card, int short_reset)
374{
375 u32 address;
376
377 if (short_reset)
378 address = 5;
379 else
380 address = 1;
381
382 return card->driver->update_phy_reg(card, address, 0, 0x40);
383}
384EXPORT_SYMBOL(fw_core_initiate_bus_reset);
diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c
new file mode 100644
index 000000000000..61548c4d18ec
--- /dev/null
+++ b/drivers/firewire/fw-iso.c
@@ -0,0 +1,136 @@
1/* -*- c-basic-offset: 8 -*-
2 *
3 * fw-iso.c - Isochronous IO
4 * Copyright (C) 2006 Kristian Hoegsberg <krh@bitplanet.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/dma-mapping.h>
24#include <linux/vmalloc.h>
25#include <linux/mm.h>
26
27#include "fw-transaction.h"
28#include "fw-topology.h"
29
30static int
31setup_iso_buffer(struct fw_iso_context *ctx, size_t size,
32 enum dma_data_direction direction)
33{
34 struct page *page;
35 int i;
36 void *p;
37
38 ctx->buffer_size = PAGE_ALIGN(size);
39 if (size == 0)
40 return 0;
41
42 ctx->buffer = vmalloc_32_user(ctx->buffer_size);
43 if (ctx->buffer == NULL)
44 return -ENOMEM;
45
46 ctx->page_count = ctx->buffer_size >> PAGE_SHIFT;
47 ctx->pages =
48 kzalloc(ctx->page_count * sizeof(ctx->pages[0]), GFP_KERNEL);
49 if (ctx->pages == NULL) {
50 vfree(ctx->buffer);
51 return -ENOMEM;
52 }
53
54 p = ctx->buffer;
55 for (i = 0; i < ctx->page_count; i++, p += PAGE_SIZE) {
56 page = vmalloc_to_page(p);
57 ctx->pages[i] = dma_map_page(ctx->card->device,
58 page, 0, PAGE_SIZE, direction);
59 }
60
61 return 0;
62}
63
64static void destroy_iso_buffer(struct fw_iso_context *ctx)
65{
66 int i;
67
68 for (i = 0; i < ctx->page_count; i++)
69 dma_unmap_page(ctx->card->device, ctx->pages[i],
70 PAGE_SIZE, DMA_TO_DEVICE);
71
72 kfree(ctx->pages);
73 vfree(ctx->buffer);
74}
75
76struct fw_iso_context *fw_iso_context_create(struct fw_card *card, int type,
77 size_t buffer_size,
78 fw_iso_callback_t callback,
79 void *callback_data)
80{
81 struct fw_iso_context *ctx;
82 int retval;
83
84 ctx = card->driver->allocate_iso_context(card, type);
85 if (IS_ERR(ctx))
86 return ctx;
87
88 ctx->card = card;
89 ctx->type = type;
90 ctx->callback = callback;
91 ctx->callback_data = callback_data;
92
93 retval = setup_iso_buffer(ctx, buffer_size, DMA_TO_DEVICE);
94 if (retval < 0) {
95 card->driver->free_iso_context(ctx);
96 return ERR_PTR(retval);
97 }
98
99 return ctx;
100}
101
102EXPORT_SYMBOL(fw_iso_context_create);
103
104void fw_iso_context_destroy(struct fw_iso_context *ctx)
105{
106 struct fw_card *card = ctx->card;
107
108 destroy_iso_buffer(ctx);
109
110 card->driver->free_iso_context(ctx);
111}
112
113EXPORT_SYMBOL(fw_iso_context_destroy);
114
115int
116fw_iso_context_send(struct fw_iso_context *ctx,
117 int channel, int speed, int cycle)
118{
119 ctx->channel = channel;
120 ctx->speed = speed;
121
122 return ctx->card->driver->send_iso(ctx, cycle);
123}
124
125EXPORT_SYMBOL(fw_iso_context_send);
126
127int
128fw_iso_context_queue(struct fw_iso_context *ctx,
129 struct fw_iso_packet *packet, void *payload)
130{
131 struct fw_card *card = ctx->card;
132
133 return card->driver->queue_iso(ctx, packet, payload);
134}
135
136EXPORT_SYMBOL(fw_iso_context_queue);
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
new file mode 100644
index 000000000000..2778aa3da8e4
--- /dev/null
+++ b/drivers/firewire/fw-topology.c
@@ -0,0 +1,446 @@
1/* -*- c-basic-offset: 8 -*-
2 *
3 * fw-topology.c - Incremental bus scan, based on bus topology
4 *
5 * Copyright (C) 2004-2006 Kristian Hoegsberg <krh@bitplanet.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include <linux/module.h>
23#include <linux/wait.h>
24#include <linux/errno.h>
25#include "fw-transaction.h"
26#include "fw-topology.h"
27
28#define self_id_phy_id(q) (((q) >> 24) & 0x3f)
29#define self_id_extended(q) (((q) >> 23) & 0x01)
30#define self_id_link_on(q) (((q) >> 22) & 0x01)
31#define self_id_gap_count(q) (((q) >> 16) & 0x3f)
32#define self_id_phy_speed(q) (((q) >> 14) & 0x03)
33#define self_id_contender(q) (((q) >> 11) & 0x01)
34#define self_id_phy_initiator(q) (((q) >> 1) & 0x01)
35#define self_id_more_packets(q) (((q) >> 0) & 0x01)
36
37#define self_id_ext_sequence(q) (((q) >> 20) & 0x07)
38
39static u32 *count_ports(u32 *sid, int *total_port_count, int *child_port_count)
40{
41 u32 q;
42 int port_type, shift, seq;
43
44 *total_port_count = 0;
45 *child_port_count = 0;
46
47 shift = 6;
48 q = *sid;
49 seq = 0;
50
51 while (1) {
52 port_type = (q >> shift) & 0x03;
53 switch (port_type) {
54 case SELFID_PORT_CHILD:
55 (*child_port_count)++;
56 case SELFID_PORT_PARENT:
57 case SELFID_PORT_NCONN:
58 (*total_port_count)++;
59 case SELFID_PORT_NONE:
60 break;
61 }
62
63 shift -= 2;
64 if (shift == 0) {
65 if (!self_id_more_packets(q))
66 return sid + 1;
67
68 shift = 16;
69 sid++;
70 q = *sid;
71
72 /* Check that the extra packets actually are
73 * extended self ID packets and that the
74 * sequence numbers in the extended self ID
75 * packets increase as expected. */
76
77 if (!self_id_extended(q) ||
78 seq != self_id_ext_sequence(q))
79 return NULL;
80
81 seq++;
82 }
83 }
84}
85
86static int get_port_type(u32 *sid, int port_index)
87{
88 int index, shift;
89
90 index = (port_index + 5) / 8;
91 shift = 16 - ((port_index + 5) & 7) * 2;
92 return (sid[index] >> shift) & 0x03;
93}
94
95struct fw_node *fw_node_create(u32 sid, int port_count, int color)
96{
97 struct fw_node *node;
98
99 node = kzalloc(sizeof *node + port_count * sizeof node->ports[0],
100 GFP_ATOMIC);
101 if (node == NULL)
102 return NULL;
103
104 node->color = color;
105 node->node_id = self_id_phy_id(sid);
106 node->link_on = self_id_link_on(sid);
107 node->phy_speed = self_id_phy_speed(sid);
108 node->port_count = port_count;
109
110 atomic_set(&node->ref_count, 1);
111 INIT_LIST_HEAD(&node->link);
112
113 return node;
114}
115
116/**
117 * build_tree - Build the tree representation of the topology
118 * @self_ids: array of self IDs to create the tree from
119 * @self_id_count: the length of the self_ids array
120 * @local_id: the node ID of the local node
121 *
122 * This function builds the tree representation of the topology given
123 * by the self IDs from the latest bus reset. During the construction
124 * of the tree, the function checks that the self IDs are valid and
125 * internally consistent. On succcess this funtions returns the
126 * fw_node corresponding to the local card otherwise NULL.
127 */
128static struct fw_node *build_tree(struct fw_card *card)
129{
130 struct fw_node *node, *child, *local_node;
131 struct list_head stack, *h;
132 u32 *sid, *next_sid, *end, q;
133 int i, port_count, child_port_count, phy_id, parent_count, stack_depth;
134
135 local_node = NULL;
136 node = NULL;
137 INIT_LIST_HEAD(&stack);
138 stack_depth = 0;
139 sid = card->self_ids;
140 end = sid + card->self_id_count;
141 phy_id = 0;
142 card->irm_node = NULL;
143
144 while (sid < end) {
145 next_sid = count_ports(sid, &port_count, &child_port_count);
146
147 if (next_sid == NULL) {
148 fw_error("Inconsistent extended self IDs.\n");
149 return NULL;
150 }
151
152 q = *sid;
153 if (phy_id != self_id_phy_id(q)) {
154 fw_error("PHY ID mismatch in self ID: %d != %d.\n",
155 phy_id, self_id_phy_id(q));
156 return NULL;
157 }
158
159 if (child_port_count > stack_depth) {
160 fw_error("Topology stack underflow\n");
161 return NULL;
162 }
163
164 /* Seek back from the top of our stack to find the
165 * start of the child nodes for this node. */
166 for (i = 0, h = &stack; i < child_port_count; i++)
167 h = h->prev;
168 child = fw_node(h);
169
170 node = fw_node_create(q, port_count, card->color);
171 if (node == NULL) {
172 fw_error("Out of memory while building topology.");
173 return NULL;
174 }
175
176 if (phy_id == (card->node_id & 0x3f))
177 local_node = node;
178
179 if (self_id_contender(q))
180 card->irm_node = node;
181
182 parent_count = 0;
183
184 for (i = 0; i < port_count; i++) {
185 switch (get_port_type(sid, i)) {
186 case SELFID_PORT_PARENT:
187 /* Who's your daddy? We dont know the
188 * parent node at this time, so we
189 * temporarily abuse node->color for
190 * remembering the entry in the
191 * node->ports array where the parent
192 * node should be. Later, when we
193 * handle the parent node, we fix up
194 * the reference.
195 */
196 parent_count++;
197 node->color = i;
198 break;
199
200 case SELFID_PORT_CHILD:
201 node->ports[i].node = child;
202 /* Fix up parent reference for this
203 * child node. */
204 child->ports[child->color].node = node;
205 child->color = card->color;
206 child = fw_node(child->link.next);
207 break;
208 }
209 }
210
211 /* Check that the node reports exactly one parent
212 * port, except for the root, which of course should
213 * have no parents. */
214 if ((next_sid == end && parent_count != 0) ||
215 (next_sid < end && parent_count != 1)) {
216 fw_error("Parent port inconsistency for node %d: "
217 "parent_count=%d\n", phy_id, parent_count);
218 return NULL;
219 }
220
221 /* Pop the child nodes off the stack and push the new node. */
222 __list_del(h->prev, &stack);
223 list_add_tail(&node->link, &stack);
224 stack_depth += 1 - child_port_count;
225
226 sid = next_sid;
227 phy_id++;
228 }
229
230 card->root_node = node;
231
232 return local_node;
233}
234
235typedef void (*fw_node_callback_t) (struct fw_card * card,
236 struct fw_node * node,
237 struct fw_node * parent);
238
239static void
240for_each_fw_node(struct fw_card *card, struct fw_node *root,
241 fw_node_callback_t callback)
242{
243 struct list_head list;
244 struct fw_node *node, *next, *child, *parent;
245 int i;
246
247 INIT_LIST_HEAD(&list);
248
249 fw_node_get(root);
250 list_add_tail(&root->link, &list);
251 parent = NULL;
252 list_for_each_entry(node, &list, link) {
253 node->color = card->color;
254
255 for (i = 0; i < node->port_count; i++) {
256 child = node->ports[i].node;
257 if (!child)
258 continue;
259 if (child->color == card->color)
260 parent = child;
261 else {
262 fw_node_get(child);
263 list_add_tail(&child->link, &list);
264 }
265 }
266
267 callback(card, node, parent);
268 }
269
270 list_for_each_entry_safe(node, next, &list, link)
271 fw_node_put(node);
272}
273
274static void
275report_lost_node(struct fw_card *card,
276 struct fw_node *node, struct fw_node *parent)
277{
278 fw_node_event(card, node, FW_NODE_DESTROYED);
279 fw_node_put(node);
280}
281
282static void
283report_found_node(struct fw_card *card,
284 struct fw_node *node, struct fw_node *parent)
285{
286 int b_path = (node->phy_speed == SCODE_BETA);
287
288 if (parent != NULL) {
289 node->max_speed = min(parent->max_speed, node->phy_speed);
290 node->b_path = parent->b_path && b_path;
291 } else {
292 node->max_speed = node->phy_speed;
293 node->b_path = b_path;
294 }
295
296 fw_node_event(card, node, FW_NODE_CREATED);
297}
298
299void fw_destroy_nodes(struct fw_card *card)
300{
301 unsigned long flags;
302
303 spin_lock_irqsave(&card->lock, flags);
304 card->color++;
305 if (card->local_node != NULL)
306 for_each_fw_node(card, card->local_node, report_lost_node);
307 spin_unlock_irqrestore(&card->lock, flags);
308}
309
310static void move_tree(struct fw_node *node0, struct fw_node *node1, int port)
311{
312 struct fw_node *tree;
313 int i;
314
315 tree = node1->ports[port].node;
316 node0->ports[port].node = tree;
317 for (i = 0; i < tree->port_count; i++) {
318 if (tree->ports[i].node == node1) {
319 tree->ports[i].node = node0;
320 break;
321 }
322 }
323}
324
325/**
326 * update_tree - compare the old topology tree for card with the new
327 * one specified by root. Queue the nodes and mark them as either
328 * found, lost or updated. Update the nodes in the card topology tree
329 * as we go.
330 */
331static void
332update_tree(struct fw_card *card, struct fw_node *root, int *changed)
333{
334 struct list_head list0, list1;
335 struct fw_node *node0, *node1;
336 int i, event;
337
338 INIT_LIST_HEAD(&list0);
339 list_add_tail(&card->local_node->link, &list0);
340 INIT_LIST_HEAD(&list1);
341 list_add_tail(&root->link, &list1);
342
343 node0 = fw_node(list0.next);
344 node1 = fw_node(list1.next);
345 *changed = 0;
346
347 while (&node0->link != &list0) {
348
349 /* assert(node0->port_count == node1->port_count); */
350 if (node0->link_on && !node1->link_on)
351 event = FW_NODE_LINK_OFF;
352 else if (!node0->link_on && node1->link_on)
353 event = FW_NODE_LINK_ON;
354 else
355 event = FW_NODE_UPDATED;
356
357 node0->node_id = node1->node_id;
358 node0->color = card->color;
359 node0->link_on = node1->link_on;
360 node0->initiated_reset = node1->initiated_reset;
361 node1->color = card->color;
362 fw_node_event(card, node0, event);
363
364 if (card->root_node == node1)
365 card->root_node = node0;
366 if (card->irm_node == node1)
367 card->irm_node = node0;
368
369 for (i = 0; i < node0->port_count; i++) {
370 if (node0->ports[i].node && node1->ports[i].node) {
371 /* This port didn't change, queue the
372 * connected node for further
373 * investigation. */
374 if (node0->ports[i].node->color == card->color)
375 continue;
376 list_add_tail(&node0->ports[i].node->link,
377 &list0);
378 list_add_tail(&node1->ports[i].node->link,
379 &list1);
380 } else if (node0->ports[i].node) {
381 /* The nodes connected here were
382 * unplugged; unref the lost nodes and
383 * queue FW_NODE_LOST callbacks for
384 * them. */
385
386 for_each_fw_node(card, node0->ports[i].node,
387 report_lost_node);
388 node0->ports[i].node = NULL;
389 *changed = 1;
390 } else if (node1->ports[i].node) {
391 /* One or more node were connected to
392 * this port. Move the new nodes into
393 * the tree and queue FW_NODE_CREATED
394 * callbacks for them. */
395 move_tree(node0, node1, i);
396 for_each_fw_node(card, node0->ports[i].node,
397 report_found_node);
398 *changed = 1;
399 }
400 }
401
402 node0 = fw_node(node0->link.next);
403 node1 = fw_node(node1->link.next);
404 }
405}
406
407void
408fw_core_handle_bus_reset(struct fw_card *card,
409 int node_id, int generation,
410 int self_id_count, u32 * self_ids)
411{
412 struct fw_node *local_node;
413 unsigned long flags;
414 int changed;
415
416 fw_flush_transactions(card);
417
418 spin_lock_irqsave(&card->lock, flags);
419
420 card->node_id = node_id;
421 card->self_id_count = self_id_count;
422 card->generation = generation;
423 memcpy(card->self_ids, self_ids, self_id_count * 4);
424
425 local_node = build_tree(card);
426
427 card->color++;
428
429 if (local_node == NULL) {
430 fw_error("topology build failed\n");
431 /* FIXME: We need to issue a bus reset in this case. */
432 } else if (card->local_node == NULL) {
433 card->local_node = local_node;
434 for_each_fw_node(card, local_node, report_found_node);
435 } else {
436 update_tree(card, local_node, &changed);
437 }
438
439 spin_unlock_irqrestore(&card->lock, flags);
440}
441
442EXPORT_SYMBOL(fw_core_handle_bus_reset);
443
444void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
445{
446}
diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h
new file mode 100644
index 000000000000..7582d6e16cbd
--- /dev/null
+++ b/drivers/firewire/fw-topology.h
@@ -0,0 +1,84 @@
1/* -*- c-basic-offset: 8 -*-
2 *
3 * fw-topology.h -- Incremental bus scan, based on bus topology
4 *
5 * Copyright (C) 2003-2006 Kristian Hoegsberg <krh@bitplanet.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __fw_topology_h
23#define __fw_topology_h
24
25enum {
26 FW_NODE_CREATED = 0x00,
27 FW_NODE_UPDATED = 0x01,
28 FW_NODE_DESTROYED = 0x02,
29 FW_NODE_LINK_ON = 0x03,
30 FW_NODE_LINK_OFF = 0x04
31};
32
33struct fw_port {
34 struct fw_node *node;
35 unsigned speed : 3; /* S100, S200, ... S3200 */
36};
37
38struct fw_node {
39 u16 node_id;
40 u8 color;
41 u8 port_count;
42 unsigned link_on : 1;
43 unsigned initiated_reset : 1;
44 unsigned b_path : 1;
45 u8 phy_speed; /* As in the self ID packet. */
46 u8 max_speed; /* Minimum of all phy-speeds and port speeds on
47 * the path from the local node to this node. */
48
49 atomic_t ref_count;
50
51 /* For serializing node topology into a list. */
52 struct list_head link;
53
54 /* Upper layer specific data. */
55 void *data;
56
57 struct fw_port ports[0];
58};
59
60extern inline struct fw_node *
61fw_node(struct list_head *l)
62{
63 return list_entry (l, struct fw_node, link);
64}
65
66extern inline struct fw_node *
67fw_node_get(struct fw_node *node)
68{
69 atomic_inc(&node->ref_count);
70
71 return node;
72}
73
74extern inline void
75fw_node_put(struct fw_node *node)
76{
77 if (atomic_dec_and_test(&node->ref_count))
78 kfree(node);
79}
80
81void
82fw_destroy_nodes(struct fw_card *card);
83
84#endif
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
new file mode 100644
index 000000000000..c3acf7431279
--- /dev/null
+++ b/drivers/firewire/fw-transaction.c
@@ -0,0 +1,730 @@
1/* -*- c-basic-offset: 8 -*-
2 *
3 * fw-transaction.c - core IEEE1394 transaction logic
4 *
5 * Copyright (C) 2004-2006 Kristian Hoegsberg <krh@bitplanet.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/init.h>
25#include <linux/interrupt.h>
26#include <linux/pci.h>
27#include <linux/delay.h>
28#include <linux/poll.h>
29#include <linux/list.h>
30#include <linux/kthread.h>
31#include <asm/uaccess.h>
32#include <asm/semaphore.h>
33
34#include "fw-transaction.h"
35#include "fw-topology.h"
36
37#define header_pri(pri) ((pri) << 0)
38#define header_tcode(tcode) ((tcode) << 4)
39#define header_retry(retry) ((retry) << 8)
40#define header_tlabel(tlabel) ((tlabel) << 10)
41#define header_destination(destination) ((destination) << 16)
42#define header_source(source) ((source) << 16)
43#define header_rcode(rcode) ((rcode) << 12)
44#define header_offset_high(offset_high) ((offset_high) << 0)
45#define header_data_length(length) ((length) << 16)
46#define header_extended_tcode(tcode) ((tcode) << 0)
47
48#define header_get_tcode(q) (((q) >> 4) & 0x0f)
49#define header_get_tlabel(q) (((q) >> 10) & 0x3f)
50#define header_get_rcode(q) (((q) >> 4) & 0x0f)
51#define header_get_destination(q) (((q) >> 16) & 0xffff)
52#define header_get_source(q) (((q) >> 16) & 0xffff)
53#define header_get_offset_high(q) (((q) >> 0) & 0xffff)
54#define header_get_data_length(q) (((q) >> 16) & 0xffff)
55#define header_get_extended_tcode(q) (((q) >> 0) & 0xffff)
56
57#define phy_config_gap_count(gap_count) (((gap_count) << 16) | (1 << 22))
58#define phy_config_root_id(node_id) (((node_id) << 24) | (1 << 23))
59#define phy_identifier(id) ((id) << 30)
60
61static void
62close_transaction(struct fw_transaction *t, struct fw_card *card, int rcode,
63 u32 * payload, size_t length)
64{
65 unsigned long flags;
66
67 spin_lock_irqsave(&card->lock, flags);
68 card->tlabel_mask &= ~(1 << t->tlabel);
69 list_del(&t->link);
70 spin_unlock_irqrestore(&card->lock, flags);
71
72 t->callback(card, rcode, payload, length, t->callback_data);
73}
74
75static void
76transmit_complete_callback(struct fw_packet *packet,
77 struct fw_card *card, int status)
78{
79 struct fw_transaction *t =
80 container_of(packet, struct fw_transaction, packet);
81
82 switch (status) {
83 case ACK_COMPLETE:
84 close_transaction(t, card, RCODE_COMPLETE, NULL, 0);
85 break;
86 case ACK_PENDING:
87 t->timestamp = packet->timestamp;
88 break;
89 case ACK_BUSY_X:
90 case ACK_BUSY_A:
91 case ACK_BUSY_B:
92 close_transaction(t, card, RCODE_BUSY, NULL, 0);
93 break;
94 case ACK_DATA_ERROR:
95 case ACK_TYPE_ERROR:
96 close_transaction(t, card, RCODE_SEND_ERROR, NULL, 0);
97 break;
98 default:
99 /* FIXME: In this case, status is a negative errno,
100 * corresponding to an OHCI specific transmit error
101 * code. We should map that to an RCODE instead of
102 * just the generic RCODE_SEND_ERROR. */
103 close_transaction(t, card, RCODE_SEND_ERROR, NULL, 0);
104 break;
105 }
106}
107
108void
109fw_fill_packet(struct fw_packet *packet, int tcode, int tlabel,
110 int node_id, int generation, int speed,
111 unsigned long long offset, void *payload, size_t length)
112{
113 int ext_tcode;
114
115 if (tcode > 0x10) {
116 ext_tcode = tcode - 0x10;
117 tcode = TCODE_LOCK_REQUEST;
118 } else
119 ext_tcode = 0;
120
121 packet->header[0] =
122 header_retry(RETRY_X) |
123 header_tlabel(tlabel) |
124 header_tcode(tcode) |
125 header_destination(node_id | LOCAL_BUS);
126 packet->header[1] =
127 header_offset_high(offset >> 32) | header_source(0);
128 packet->header[2] =
129 offset;
130
131 switch (tcode) {
132 case TCODE_WRITE_QUADLET_REQUEST:
133 packet->header[3] = *(u32 *)payload;
134 packet->header_length = 16;
135 packet->payload_length = 0;
136 break;
137
138 case TCODE_LOCK_REQUEST:
139 case TCODE_WRITE_BLOCK_REQUEST:
140 packet->header[3] =
141 header_data_length(length) |
142 header_extended_tcode(ext_tcode);
143 packet->header_length = 16;
144 packet->payload = payload;
145 packet->payload_length = length;
146 break;
147
148 case TCODE_READ_QUADLET_REQUEST:
149 packet->header_length = 12;
150 packet->payload_length = 0;
151 break;
152
153 case TCODE_READ_BLOCK_REQUEST:
154 packet->header[3] =
155 header_data_length(length) |
156 header_extended_tcode(ext_tcode);
157 packet->header_length = 16;
158 packet->payload_length = 0;
159 break;
160 }
161
162 packet->speed = speed;
163 packet->generation = generation;
164}
165
166/**
167 * This function provides low-level access to the IEEE1394 transaction
168 * logic. Most C programs would use either fw_read(), fw_write() or
169 * fw_lock() instead - those function are convenience wrappers for
170 * this function. The fw_send_request() function is primarily
171 * provided as a flexible, one-stop entry point for languages bindings
172 * and protocol bindings.
173 *
174 * FIXME: Document this function further, in particular the possible
175 * values for rcode in the callback. In short, we map ACK_COMPLETE to
176 * RCODE_COMPLETE, internal errors set errno and set rcode to
177 * RCODE_SEND_ERROR (which is out of range for standard ieee1394
178 * rcodes). All other rcodes are forwarded unchanged. For all
179 * errors, payload is NULL, length is 0.
180 *
181 * Can not expect the callback to be called before the function
182 * returns, though this does happen in some cases (ACK_COMPLETE and
183 * errors).
184 *
185 * The payload is only used for write requests and must not be freed
186 * until the callback has been called.
187 *
188 * @param card the card from which to send the request
189 * @param tcode the tcode for this transaction. Do not use
190 * TCODE_LOCK_REQUEST directly, insted use TCODE_LOCK_MASK_SWAP
191 * etc. to specify tcode and ext_tcode.
192 * @param node_id the node_id of the destination node
193 * @param generation the generation for which node_id is valid
194 * @param speed the speed to use for sending the request
195 * @param offset the 48 bit offset on the destination node
196 * @param payload the data payload for the request subaction
197 * @param length the length in bytes of the data to read
198 * @param callback function to be called when the transaction is completed
199 * @param callback_data pointer to arbitrary data, which will be
200 * passed to the callback
201 */
202void
203fw_send_request(struct fw_card *card, struct fw_transaction *t,
204 int tcode, int node_id, int generation, int speed,
205 unsigned long long offset,
206 void *payload, size_t length,
207 fw_transaction_callback_t callback, void *callback_data)
208{
209 unsigned long flags;
210 int tlabel;
211
212 /* Bump the flush timer up 100ms first of all so we
213 * don't race with a flush timer callback. */
214
215 mod_timer(&card->flush_timer, jiffies + DIV_ROUND_UP(HZ, 10));
216
217 /* Allocate tlabel from the bitmap and put the transaction on
218 * the list while holding the card spinlock. */
219
220 spin_lock_irqsave(&card->lock, flags);
221
222 tlabel = card->current_tlabel;
223 if (card->tlabel_mask & (1 << tlabel)) {
224 spin_unlock_irqrestore(&card->lock, flags);
225 callback(card, RCODE_SEND_ERROR, NULL, 0, callback_data);
226 return;
227 }
228
229 card->current_tlabel = (card->current_tlabel + 1) & 0x1f;
230 card->tlabel_mask |= (1 << tlabel);
231
232 list_add_tail(&t->link, &card->transaction_list);
233
234 spin_unlock_irqrestore(&card->lock, flags);
235
236 /* Initialize rest of transaction, fill out packet and send it. */
237 t->node_id = node_id;
238 t->tlabel = tlabel;
239 t->callback = callback;
240 t->callback_data = callback_data;
241
242 fw_fill_packet(&t->packet, tcode, t->tlabel,
243 node_id, generation, speed, offset, payload, length);
244 t->packet.callback = transmit_complete_callback;
245
246 card->driver->send_request(card, &t->packet);
247}
248EXPORT_SYMBOL(fw_send_request);
249
250static void
251transmit_phy_packet_callback(struct fw_packet *packet,
252 struct fw_card *card, int status)
253{
254 kfree(packet);
255}
256
257static void send_phy_packet(struct fw_card *card, u32 data, int generation)
258{
259 struct fw_packet *packet;
260
261 packet = kzalloc(sizeof *packet, GFP_ATOMIC);
262 if (packet == NULL)
263 return;
264
265 packet->header[0] = data;
266 packet->header[1] = ~data;
267 packet->header_length = 8;
268 packet->payload_length = 0;
269 packet->speed = SCODE_100;
270 packet->generation = generation;
271 packet->callback = transmit_phy_packet_callback;
272
273 card->driver->send_request(card, packet);
274}
275
276void fw_send_force_root(struct fw_card *card, int node_id, int generation)
277{
278 u32 q;
279
280 q = phy_identifier(PHY_PACKET_CONFIG) | phy_config_root_id(node_id);
281 send_phy_packet(card, q, generation);
282}
283
284void fw_flush_transactions(struct fw_card *card)
285{
286 struct fw_transaction *t, *next;
287 struct list_head list;
288 unsigned long flags;
289
290 INIT_LIST_HEAD(&list);
291 spin_lock_irqsave(&card->lock, flags);
292 list_splice_init(&card->transaction_list, &list);
293 card->tlabel_mask = 0;
294 spin_unlock_irqrestore(&card->lock, flags);
295
296 list_for_each_entry_safe(t, next, &list, link)
297 t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data);
298}
299
300static struct fw_address_handler *
301lookup_overlapping_address_handler(struct list_head *list,
302 unsigned long long offset, size_t length)
303{
304 struct fw_address_handler *handler;
305
306 list_for_each_entry(handler, list, link) {
307 if (handler->offset < offset + length &&
308 offset < handler->offset + handler->length)
309 return handler;
310 }
311
312 return NULL;
313}
314
315static struct fw_address_handler *
316lookup_enclosing_address_handler(struct list_head *list,
317 unsigned long long offset, size_t length)
318{
319 struct fw_address_handler *handler;
320
321 list_for_each_entry(handler, list, link) {
322 if (handler->offset <= offset &&
323 offset + length <= handler->offset + handler->length)
324 return handler;
325 }
326
327 return NULL;
328}
329
330static DEFINE_SPINLOCK(address_handler_lock);
331static LIST_HEAD(address_handler_list);
332
333struct fw_address_region fw_low_memory_region =
334 { 0x000000000000ull, 0x000100000000ull };
335struct fw_address_region fw_high_memory_region =
336 { 0x000100000000ull, 0xffffe0000000ull };
337struct fw_address_region fw_private_region =
338 { 0xffffe0000000ull, 0xfffff0000000ull };
339struct fw_address_region fw_csr_region =
340 { 0xfffff0000000ULL, 0xfffff0000800ull };
341struct fw_address_region fw_unit_space_region =
342 { 0xfffff0000900ull, 0x1000000000000ull };
343
344EXPORT_SYMBOL(fw_low_memory_region);
345EXPORT_SYMBOL(fw_high_memory_region);
346EXPORT_SYMBOL(fw_private_region);
347EXPORT_SYMBOL(fw_csr_region);
348EXPORT_SYMBOL(fw_unit_space_region);
349
350/**
351 * Allocate a range of addresses in the node space of the OHCI
352 * controller. When a request is received that falls within the
353 * specified address range, the specified callback is invoked. The
354 * parameters passed to the callback give the details of the
355 * particular request
356 */
357
358int
359fw_core_add_address_handler(struct fw_address_handler *handler,
360 struct fw_address_region *region)
361{
362 struct fw_address_handler *other;
363 unsigned long flags;
364 int ret = -EBUSY;
365
366 spin_lock_irqsave(&address_handler_lock, flags);
367
368 handler->offset = region->start;
369 while (handler->offset + handler->length <= region->end) {
370 other =
371 lookup_overlapping_address_handler(&address_handler_list,
372 handler->offset,
373 handler->length);
374 if (other != NULL) {
375 handler->offset += other->length;
376 } else {
377 list_add_tail(&handler->link, &address_handler_list);
378 ret = 0;
379 break;
380 }
381 }
382
383 spin_unlock_irqrestore(&address_handler_lock, flags);
384
385 return ret;
386}
387
388EXPORT_SYMBOL(fw_core_add_address_handler);
389
390/**
391 * Deallocate a range of addresses allocated with fw_allocate. This
392 * will call the associated callback one last time with a the special
393 * tcode TCODE_DEALLOCATE, to let the client destroy the registered
394 * callback data. For convenience, the callback parameters offset and
395 * length are set to the start and the length respectively for the
396 * deallocated region, payload is set to NULL.
397 */
398
399void fw_core_remove_address_handler(struct fw_address_handler *handler)
400{
401 unsigned long flags;
402
403 spin_lock_irqsave(&address_handler_lock, flags);
404 list_del(&handler->link);
405 spin_unlock_irqrestore(&address_handler_lock, flags);
406}
407
408EXPORT_SYMBOL(fw_core_remove_address_handler);
409
410struct fw_request {
411 struct fw_packet response;
412 int ack;
413 u32 length;
414 u32 data[0];
415};
416
417static void
418free_response_callback(struct fw_packet *packet,
419 struct fw_card *card, int status)
420{
421 struct fw_request *request;
422
423 request = container_of(packet, struct fw_request, response);
424 kfree(request);
425}
426
427static void
428fw_fill_response(struct fw_packet *response,
429 u32 *request, u32 *data, size_t length)
430{
431 int tcode, tlabel, extended_tcode, source, destination;
432
433 tcode = header_get_tcode(request[0]);
434 tlabel = header_get_tlabel(request[0]);
435 source = header_get_destination(request[0]);
436 destination = header_get_source(request[1]);
437 extended_tcode = header_get_extended_tcode(request[3]);
438
439 response->header[0] =
440 header_retry(RETRY_1) |
441 header_tlabel(tlabel) |
442 header_destination(destination);
443 response->header[1] = header_source(source);
444 response->header[2] = 0;
445
446 switch (tcode) {
447 case TCODE_WRITE_QUADLET_REQUEST:
448 case TCODE_WRITE_BLOCK_REQUEST:
449 response->header[0] |= header_tcode(TCODE_WRITE_RESPONSE);
450 response->header_length = 12;
451 response->payload_length = 0;
452 break;
453
454 case TCODE_READ_QUADLET_REQUEST:
455 response->header[0] |=
456 header_tcode(TCODE_READ_QUADLET_RESPONSE);
457 response->header[3] = 0;
458 response->header_length = 16;
459 response->payload_length = 0;
460 break;
461
462 case TCODE_READ_BLOCK_REQUEST:
463 case TCODE_LOCK_REQUEST:
464 response->header[0] |= header_tcode(tcode + 2);
465 response->header[3] =
466 header_data_length(length) |
467 header_extended_tcode(extended_tcode);
468 response->header_length = 16;
469 response->payload = data;
470 response->payload_length = length;
471 break;
472
473 default:
474 BUG();
475 return;
476 }
477}
478
479static struct fw_request *
480allocate_request(u32 *header, int ack,
481 int speed, int timestamp, int generation)
482{
483 struct fw_request *request;
484 u32 *data, length;
485 int request_tcode;
486
487 request_tcode = header_get_tcode(header[0]);
488 switch (request_tcode) {
489 case TCODE_WRITE_QUADLET_REQUEST:
490 data = &header[3];
491 length = 4;
492 break;
493
494 case TCODE_WRITE_BLOCK_REQUEST:
495 case TCODE_LOCK_REQUEST:
496 data = &header[4];
497 length = header_get_data_length(header[3]);
498 break;
499
500 case TCODE_READ_QUADLET_REQUEST:
501 data = NULL;
502 length = 4;
503 break;
504
505 case TCODE_READ_BLOCK_REQUEST:
506 data = NULL;
507 length = header_get_data_length(header[3]);
508 break;
509
510 default:
511 BUG();
512 return NULL;
513 }
514
515 request = kmalloc(sizeof *request + length, GFP_ATOMIC);
516 if (request == NULL)
517 return NULL;
518
519 request->response.speed = speed;
520 request->response.timestamp = timestamp;
521 request->response.generation = generation;
522 request->response.callback = free_response_callback;
523 request->ack = ack;
524 request->length = length;
525 if (data)
526 memcpy(request->data, data, length);
527
528 fw_fill_response(&request->response, header, request->data, length);
529
530 return request;
531}
532
533void
534fw_send_response(struct fw_card *card, struct fw_request *request, int rcode)
535{
536 int response_tcode;
537
538 /* Broadcast packets are reported as ACK_COMPLETE, so this
539 * check is sufficient to ensure we don't send response to
540 * broadcast packets or posted writes. */
541 if (request->ack != ACK_PENDING)
542 return;
543
544 request->response.header[1] |= header_rcode(rcode);
545 response_tcode = header_get_tcode(request->response.header[0]);
546 if (rcode != RCODE_COMPLETE)
547 /* Clear the data_length field. */
548 request->response.header[3] &= 0xffff;
549 else if (response_tcode == TCODE_READ_QUADLET_RESPONSE)
550 request->response.header[3] = request->data[0];
551
552 card->driver->send_response(card, &request->response);
553}
554
555EXPORT_SYMBOL(fw_send_response);
556
557void
558fw_core_handle_request(struct fw_card *card,
559 int speed, int ack, int timestamp,
560 int generation, u32 length, u32 *header)
561{
562 struct fw_address_handler *handler;
563 struct fw_request *request;
564 unsigned long long offset;
565 unsigned long flags;
566 int tcode, destination, source, t;
567
568 if (length > 2048) {
569 /* FIXME: send error response. */
570 return;
571 }
572
573 if (ack != ACK_PENDING && ack != ACK_COMPLETE)
574 return;
575
576 t = (timestamp & 0x1fff) + 4000;
577 if (t >= 8000)
578 t = (timestamp & ~0x1fff) + 0x2000 + t - 8000;
579 else
580 t = (timestamp & ~0x1fff) + t;
581
582 request = allocate_request(header, ack, speed, t, generation);
583 if (request == NULL) {
584 /* FIXME: send statically allocated busy packet. */
585 return;
586 }
587
588 offset =
589 ((unsigned long long)
590 header_get_offset_high(header[1]) << 32) | header[2];
591 tcode = header_get_tcode(header[0]);
592 destination = header_get_destination(header[0]);
593 source = header_get_source(header[0]);
594
595 spin_lock_irqsave(&address_handler_lock, flags);
596 handler = lookup_enclosing_address_handler(&address_handler_list,
597 offset, request->length);
598 spin_unlock_irqrestore(&address_handler_lock, flags);
599
600 /* FIXME: lookup the fw_node corresponding to the sender of
601 * this request and pass that to the address handler instead
602 * of the node ID. We may also want to move the address
603 * allocations to fw_node so we only do this callback if the
604 * upper layers registered it for this node. */
605
606 if (handler == NULL)
607 fw_send_response(card, request, RCODE_ADDRESS_ERROR);
608 else
609 handler->address_callback(card, request,
610 tcode, destination, source,
611 generation, speed, offset,
612 request->data, request->length,
613 handler->callback_data);
614}
615
616EXPORT_SYMBOL(fw_core_handle_request);
617
618void
619fw_core_handle_response(struct fw_card *card,
620 int speed, int ack, int timestamp,
621 u32 length, u32 *header)
622{
623 struct fw_transaction *t;
624 unsigned long flags;
625 u32 *data;
626 size_t data_length;
627 int tcode, tlabel, destination, source, rcode;
628
629 tcode = header_get_tcode(header[0]);
630 tlabel = header_get_tlabel(header[0]);
631 destination = header_get_destination(header[0]);
632 source = header_get_source(header[1]);
633 rcode = header_get_rcode(header[1]);
634
635 spin_lock_irqsave(&card->lock, flags);
636 list_for_each_entry(t, &card->transaction_list, link) {
637 if (t->node_id == source && t->tlabel == tlabel) {
638 list_del(&t->link);
639 card->tlabel_mask &= ~(1 << t->tlabel);
640 break;
641 }
642 }
643 spin_unlock_irqrestore(&card->lock, flags);
644
645 if (&t->link == &card->transaction_list) {
646 fw_notify("Unsolicited response\n");
647 return;
648 }
649
650 /* FIXME: sanity check packet, is length correct, does tcodes
651 * and addresses match. */
652
653 switch (tcode) {
654 case TCODE_READ_QUADLET_RESPONSE:
655 data = (u32 *) &header[3];
656 data_length = 4;
657 break;
658
659 case TCODE_WRITE_RESPONSE:
660 data = NULL;
661 data_length = 0;
662 break;
663
664 case TCODE_READ_BLOCK_RESPONSE:
665 case TCODE_LOCK_RESPONSE:
666 data = &header[4];
667 data_length = header_get_data_length(header[3]);
668 break;
669
670 default:
671 /* Should never happen, this is just to shut up gcc. */
672 data = NULL;
673 data_length = 0;
674 break;
675 }
676
677 t->callback(card, rcode, data, data_length, t->callback_data);
678}
679
680EXPORT_SYMBOL(fw_core_handle_response);
681
682MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
683MODULE_DESCRIPTION("Core IEEE1394 transaction logic");
684MODULE_LICENSE("GPL");
685
686static u32 vendor_textual_descriptor_data[] = {
687 /* textual descriptor leaf () */
688 0x00080000,
689 0x00000000,
690 0x00000000,
691 0x4c696e75, /* L i n u */
692 0x78204669, /* x F i */
693 0x72657769, /* r e w i */
694 0x72652028, /* r e ( */
695 0x4a554a55, /* J U J U */
696 0x29000000, /* ) */
697};
698
699static struct fw_descriptor vendor_textual_descriptor = {
700 .length = ARRAY_SIZE(vendor_textual_descriptor_data),
701 .key = 0x81000000,
702 .data = vendor_textual_descriptor_data
703};
704
705struct bus_type fw_bus_type = {
706 .name = "fw",
707};
708
709static int __init fw_core_init(void)
710{
711 int retval;
712
713 retval = bus_register(&fw_bus_type);
714 if (retval < 0)
715 return retval;
716
717 /* Add the vendor textual descriptor. */
718 retval = fw_core_add_descriptor(&vendor_textual_descriptor);
719 BUG_ON(retval < 0);
720
721 return 0;
722}
723
724static void __exit fw_core_cleanup(void)
725{
726 bus_unregister(&fw_bus_type);
727}
728
729module_init(fw_core_init);
730module_exit(fw_core_cleanup);
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
new file mode 100644
index 000000000000..149ef1652acf
--- /dev/null
+++ b/drivers/firewire/fw-transaction.h
@@ -0,0 +1,422 @@
1/* -*- c-basic-offset: 8 -*-
2 *
3 * fw-transaction.h - Header for IEEE1394 transaction logic
4 *
5 * Copyright (C) 2003-2006 Kristian Hoegsberg <krh@bitplanet.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __fw_core_h
23#define __fw_core_h
24
25#include <linux/device.h>
26#include <linux/timer.h>
27#include <linux/interrupt.h>
28#include <linux/list.h>
29#include <linux/fs.h>
30
31#define TCODE_WRITE_QUADLET_REQUEST 0
32#define TCODE_WRITE_BLOCK_REQUEST 1
33#define TCODE_WRITE_RESPONSE 2
34#define TCODE_READ_QUADLET_REQUEST 4
35#define TCODE_READ_BLOCK_REQUEST 5
36#define TCODE_READ_QUADLET_RESPONSE 6
37#define TCODE_READ_BLOCK_RESPONSE 7
38#define TCODE_CYCLE_START 8
39#define TCODE_LOCK_REQUEST 9
40#define TCODE_STREAM_DATA 10
41#define TCODE_LOCK_RESPONSE 11
42
43#define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0)
44#define TCODE_IS_REQUEST(tcode) (((tcode) & 2) == 0)
45#define TCODE_IS_RESPONSE(tcode) (((tcode) & 2) != 0)
46#define TCODE_HAS_REQUEST_DATA(tcode) (((tcode) & 12) != 4)
47#define TCODE_HAS_RESPONSE_DATA(tcode) (((tcode) & 12) != 0)
48
49/* Juju specific tcodes */
50#define TCODE_DEALLOCATE 0x10
51#define TCODE_LOCK_MASK_SWAP 0x11
52#define TCODE_LOCK_COMPARE_SWAP 0x12
53#define TCODE_LOCK_FETCH_ADD 0x13
54#define TCODE_LOCK_LITTLE_ADD 0x14
55#define TCODE_LOCK_BOUNDED_ADD 0x15
56#define TCODE_LOCK_WRAP_ADD 0x16
57#define TCODE_LOCK_VENDOR_SPECIFIC 0x17
58
59#define SCODE_100 0x0
60#define SCODE_200 0x1
61#define SCODE_400 0x2
62#define SCODE_BETA 0x3
63
64#define EXTCODE_MASK_SWAP 0x1
65#define EXTCODE_COMPARE_SWAP 0x2
66#define EXTCODE_FETCH_ADD 0x3
67#define EXTCODE_LITTLE_ADD 0x4
68#define EXTCODE_BOUNDED_ADD 0x5
69#define EXTCODE_WRAP_ADD 0x6
70
71#define ACK_COMPLETE 0x1
72#define ACK_PENDING 0x2
73#define ACK_BUSY_X 0x4
74#define ACK_BUSY_A 0x5
75#define ACK_BUSY_B 0x6
76#define ACK_DATA_ERROR 0xd
77#define ACK_TYPE_ERROR 0xe
78
79#define RCODE_COMPLETE 0x0
80#define RCODE_CONFLICT_ERROR 0x4
81#define RCODE_DATA_ERROR 0x5
82#define RCODE_TYPE_ERROR 0x6
83#define RCODE_ADDRESS_ERROR 0x7
84
85/* Juju specific rcodes */
86#define RCODE_SEND_ERROR 0x10
87#define RCODE_CANCELLED 0x11
88#define RCODE_BUSY 0x12
89
90#define RETRY_1 0x00
91#define RETRY_X 0x01
92#define RETRY_A 0x02
93#define RETRY_B 0x03
94
95#define LOCAL_BUS 0xffc0
96
97#define SELFID_PORT_CHILD 0x3
98#define SELFID_PORT_PARENT 0x2
99#define SELFID_PORT_NCONN 0x1
100#define SELFID_PORT_NONE 0x0
101
102#define PHY_PACKET_CONFIG 0x0
103#define PHY_PACKET_LINK_ON 0x1
104#define PHY_PACKET_SELF_ID 0x2
105
106#define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args)
107#define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args)
108#define fw_debug(s, args...) printk(KERN_DEBUG KBUILD_MODNAME ": " s, ## args)
109
110static inline void
111fw_memcpy_from_be32(void *_dst, void *_src, size_t size)
112{
113 u32 *dst = _dst;
114 u32 *src = _src;
115 int i;
116
117 for (i = 0; i < size / 4; i++)
118 dst[i] = cpu_to_be32(src[i]);
119}
120
121static inline void
122fw_memcpy_to_be32(void *_dst, void *_src, size_t size)
123{
124 fw_memcpy_from_be32(_dst, _src, size);
125}
126
127struct fw_card;
128struct fw_packet;
129struct fw_node;
130struct fw_request;
131
132struct fw_descriptor {
133 struct list_head link;
134 size_t length;
135 u32 key;
136 u32 *data;
137};
138
139int fw_core_add_descriptor (struct fw_descriptor *desc);
140void fw_core_remove_descriptor (struct fw_descriptor *desc);
141
142typedef void (*fw_packet_callback_t) (struct fw_packet *packet,
143 struct fw_card *card, int status);
144
145typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode,
146 void *data,
147 size_t length,
148 void *callback_data);
149
150typedef void (*fw_address_callback_t)(struct fw_card *card,
151 struct fw_request *request,
152 int tcode, int destination, int source,
153 int generation, int speed,
154 unsigned long long offset,
155 void *data, size_t length,
156 void *callback_data);
157
158typedef void (*fw_bus_reset_callback_t)(struct fw_card *handle,
159 int node_id, int generation,
160 u32 *self_ids,
161 int self_id_count,
162 void *callback_data);
163
164struct fw_packet {
165 int speed;
166 int generation;
167 u32 header[4];
168 size_t header_length;
169 void *payload;
170 size_t payload_length;
171 u32 timestamp;
172
173 dma_addr_t payload_bus;
174
175 /* This callback is called when the packet transmission has
176 * completed; for successful transmission, the status code is
177 * the ack received from the destination, otherwise it's a
178 * negative errno: ENOMEM, ESTALE, ETIMEDOUT, ENODEV, EIO.
179 * The callback can be called from tasklet context and thus
180 * must never block.
181 */
182 fw_packet_callback_t callback;
183 int status;
184 struct list_head link;
185};
186
187struct fw_transaction {
188 int node_id; /* The generation is implied; it is always the current. */
189 int tlabel;
190 int timestamp;
191 struct list_head link;
192
193 struct fw_packet packet;
194
195 /* The data passed to the callback is valid only during the
196 * callback. */
197 fw_transaction_callback_t callback;
198 void *callback_data;
199};
200
201extern inline struct fw_packet *
202fw_packet(struct list_head *l)
203{
204 return list_entry (l, struct fw_packet, link);
205}
206
207struct fw_address_handler {
208 u64 offset;
209 size_t length;
210 fw_address_callback_t address_callback;
211 void *callback_data;
212 struct list_head link;
213};
214
215
216struct fw_address_region {
217 u64 start;
218 u64 end;
219};
220
221extern struct fw_address_region fw_low_memory_region;
222extern struct fw_address_region fw_high_memory_region;
223extern struct fw_address_region fw_private_region;
224extern struct fw_address_region fw_csr_region;
225extern struct fw_address_region fw_unit_space_region;
226
227int fw_core_add_address_handler(struct fw_address_handler *handler,
228 struct fw_address_region *region);
229void fw_core_remove_address_handler(struct fw_address_handler *handler);
230void fw_send_response(struct fw_card *card,
231 struct fw_request *request, int rcode);
232
233extern struct bus_type fw_bus_type;
234
235struct fw_card {
236 struct fw_card_driver *driver;
237 struct device *device;
238
239 int node_id;
240 int generation;
241 /* This is the generation used for timestamping incoming requests. */
242 int request_generation;
243 int current_tlabel, tlabel_mask;
244 struct list_head transaction_list;
245 struct timer_list flush_timer;
246
247 unsigned long long guid;
248 int max_receive;
249 int link_speed;
250 int config_rom_generation;
251
252 /* We need to store up to 4 self ID for a maximum of 63 devices. */
253 int self_id_count;
254 u32 self_ids[252];
255
256 spinlock_t lock; /* Take this lock when handling the lists in
257 * this struct. */
258 struct fw_node *local_node;
259 struct fw_node *root_node;
260 struct fw_node *irm_node;
261 int color;
262
263 int index;
264
265 struct device card_device;
266
267 struct list_head link;
268};
269
270struct fw_card *fw_card_get(struct fw_card *card);
271void fw_card_put(struct fw_card *card);
272
273/* The iso packet format allows for an immediate header/payload part
274 * stored in 'header' immediately after the packet info plus an
275 * indirect payload part that is pointer to by the 'payload' field.
276 * Applications can use one or the other or both to implement simple
277 * low-bandwidth streaming (e.g. audio) or more advanced
278 * scatter-gather streaming (e.g. assembling video frame automatically). */
279
280struct fw_iso_packet {
281 u16 payload_length; /* Length of indirect payload. */
282 u32 interrupt : 1; /* Generate interrupt on this packet */
283 u32 skip : 1; /* Set to not send packet at all. */
284 u32 tag : 2;
285 u32 sy : 4;
286 u32 header_length : 8; /* Length of immediate header. */
287 u32 header[0];
288};
289
290#define FW_ISO_CONTEXT_TRANSMIT 0
291#define FW_ISO_CONTEXT_RECEIVE 1
292
293struct fw_iso_context;
294
295typedef void (*fw_iso_callback_t) (struct fw_iso_context *context,
296 int status, u32 cycle, void *data);
297
298struct fw_iso_context {
299 struct fw_card *card;
300 int type;
301 int channel;
302 int speed;
303 fw_iso_callback_t callback;
304 void *callback_data;
305
306 void *buffer;
307 size_t buffer_size;
308 dma_addr_t *pages;
309 int page_count;
310};
311
312struct fw_iso_context *
313fw_iso_context_create(struct fw_card *card, int type,
314 size_t buffer_size,
315 fw_iso_callback_t callback,
316 void *callback_data);
317
318void
319fw_iso_context_destroy(struct fw_iso_context *ctx);
320
321void
322fw_iso_context_start(struct fw_iso_context *ctx,
323 int channel, int speed, int cycle);
324
325int
326fw_iso_context_queue(struct fw_iso_context *ctx,
327 struct fw_iso_packet *packet, void *payload);
328
329int
330fw_iso_context_send(struct fw_iso_context *ctx,
331 int channel, int speed, int cycle);
332
333struct fw_card_driver {
334 const char *name;
335
336 /* Enable the given card with the given initial config rom.
337 * This function is expected to activate the card, and either
338 * enable the PHY or set the link_on bit and initiate a bus
339 * reset. */
340 int (*enable) (struct fw_card *card, u32 *config_rom, size_t length);
341
342 int (*update_phy_reg) (struct fw_card *card, int address,
343 int clear_bits, int set_bits);
344
345 /* Update the config rom for an enabled card. This function
346 * should change the config rom that is presented on the bus
347 * an initiate a bus reset. */
348 int (*set_config_rom) (struct fw_card *card,
349 u32 *config_rom, size_t length);
350
351 void (*send_request) (struct fw_card *card, struct fw_packet *packet);
352 void (*send_response) (struct fw_card *card, struct fw_packet *packet);
353
354 /* Allow the specified node ID to do direct DMA out and in of
355 * host memory. The card will disable this for all node when
356 * a bus reset happens, so driver need to reenable this after
357 * bus reset. Returns 0 on success, -ENODEV if the card
358 * doesn't support this, -ESTALE if the generation doesn't
359 * match. */
360 int (*enable_phys_dma) (struct fw_card *card,
361 int node_id, int generation);
362
363 struct fw_iso_context *
364 (*allocate_iso_context)(struct fw_card *card, int type);
365 void (*free_iso_context)(struct fw_iso_context *ctx);
366
367 int (*send_iso)(struct fw_iso_context *ctx, s32 cycle);
368
369 int (*queue_iso)(struct fw_iso_context *ctx,
370 struct fw_iso_packet *packet, void *payload);
371};
372
373int
374fw_core_initiate_bus_reset(struct fw_card *card, int short_reset);
375
376void
377fw_send_request(struct fw_card *card, struct fw_transaction *t,
378 int tcode, int node_id, int generation, int speed,
379 unsigned long long offset,
380 void *data, size_t length,
381 fw_transaction_callback_t callback, void *callback_data);
382
383void fw_flush_transactions(struct fw_card *card);
384
385void
386fw_send_force_root(struct fw_card *card, int node_id, int generation);
387
388/* Called by the topology code to inform the device code of node
389 * activity; found, lost, or updated nodes */
390void
391fw_node_event(struct fw_card *card, struct fw_node *node, int event);
392
393/* API used by card level drivers */
394
395/* Do we need phy speed here also? If we add more args, maybe we
396 should go back to struct fw_card_info. */
397void
398fw_card_initialize(struct fw_card *card, struct fw_card_driver *driver,
399 struct device *device);
400int
401fw_card_add(struct fw_card *card,
402 u32 max_receive, u32 link_speed, u64 guid);
403
404void
405fw_core_remove_card(struct fw_card *card);
406
407void
408fw_core_handle_bus_reset(struct fw_card *card,
409 int node_id, int generation,
410 int self_id_count, u32 *self_ids);
411void
412fw_core_handle_request(struct fw_card *card,
413 int speed, int ack, int timestamp,
414 int generation,
415 u32 length, u32 *payload);
416void
417fw_core_handle_response(struct fw_card *card,
418 int speed, int ack, int timestamp,
419 u32 length, u32 *payload);
420
421
422#endif /* __fw_core_h */