* internally consistent. On succcess this funtions returns the
* fw_node corresponding to the local card otherwise NULL.
*/
-static struct fw_node *build_tree(struct fw_card *card)
+static struct fw_node *build_tree(struct fw_card *card,
+ u32 *sid, int self_id_count)
{
struct fw_node *node, *child, *local_node;
struct list_head stack, *h;
- u32 *sid, *next_sid, *end, q;
+ u32 *next_sid, *end, q;
int i, port_count, child_port_count, phy_id, parent_count, stack_depth;
int gap_count, topology_type;
node = NULL;
INIT_LIST_HEAD(&stack);
stack_depth = 0;
- sid = card->self_ids;
- end = sid + card->self_id_count;
+ end = sid + self_id_count;
phy_id = 0;
card->irm_node = NULL;
gap_count = self_id_gap_count(*sid);
}
}
+static void
+update_topology_map(struct fw_card *card, u32 *self_ids, int self_id_count)
+{
+ int node_count;
+ u32 crc;
+
+ card->topology_map[1]++;
+ node_count = (card->root_node->node_id & 0x3f) + 1;
+ card->topology_map[2] = (node_count << 16) | self_id_count;
+ crc = crc16_itu_t(card->topology_map + 1, self_id_count + 2);
+ card->topology_map[0] = ((self_id_count + 2) << 16) | crc;
+ memcpy(&card->topology_map[3], self_ids, self_id_count * 4);
+}
+
void
fw_core_handle_bus_reset(struct fw_card *card,
int node_id, int generation,
card->bm_retries = 0;
card->node_id = node_id;
- card->self_id_count = self_id_count;
card->generation = generation;
- memcpy(card->self_ids, self_ids, self_id_count * 4);
card->reset_jiffies = jiffies;
schedule_delayed_work(&card->work, 0);
- local_node = build_tree(card);
+ local_node = build_tree(card, self_ids, self_id_count);
+
+ update_topology_map(card, self_ids, self_id_count);
card->color++;
static void
fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
- int node_id, int generation, int speed,
+ int node_id, int source_id, int generation, int speed,
unsigned long long offset, void *payload, size_t length)
{
int ext_tcode;
header_tcode(tcode) |
header_destination(node_id);
packet->header[1] =
- header_offset_high(offset >> 32) | header_source(0);
+ header_offset_high(offset >> 32) | header_source(source_id);
packet->header[2] =
offset;
fw_transaction_callback_t callback, void *callback_data)
{
unsigned long flags;
- int tlabel;
+ int tlabel, source;
/* Bump the flush timer up 100ms first of all so we
* don't race with a flush timer callback. */
spin_lock_irqsave(&card->lock, flags);
+ source = card->node_id;
tlabel = card->current_tlabel;
if (card->tlabel_mask & (1 << tlabel)) {
spin_unlock_irqrestore(&card->lock, flags);
t->callback_data = callback_data;
fw_fill_request(&t->packet, tcode, t->tlabel,
- node_id, generation, speed, offset, payload, length);
+ node_id, source, generation,
+ speed, offset, payload, length);
t->packet.callback = transmit_complete_callback;
card->driver->send_request(card, &t->packet);
}
EXPORT_SYMBOL(fw_core_handle_response);
+const struct fw_address_region topology_map_region =
+ { .start = 0xfffff0001000ull, .end = 0xfffff0001400ull, };
+
+static void
+handle_topology_map(struct fw_card *card, struct fw_request *request,
+ int tcode, int destination, int source,
+ int generation, int speed,
+ unsigned long long offset,
+ void *payload, size_t length, void *callback_data)
+{
+ int i, start, end;
+ u32 *map;
+
+ if (!TCODE_IS_READ_REQUEST(tcode)) {
+ fw_send_response(card, request, RCODE_TYPE_ERROR);
+ return;
+ }
+
+ if ((offset & 3) > 0 || (length & 3) > 0) {
+ fw_send_response(card, request, RCODE_ADDRESS_ERROR);
+ return;
+ }
+
+ start = (offset - topology_map_region.start) / 4;
+ end = start + length / 4;
+ map = payload;
+
+ for (i = 0; i < length / 4; i++)
+ map[i] = cpu_to_be32(card->topology_map[start + i]);
+
+ fw_send_response(card, request, RCODE_COMPLETE);
+}
+
+static struct fw_address_handler topology_map = {
+ .length = 0x400,
+ .address_callback = handle_topology_map,
+};
+
MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
MODULE_DESCRIPTION("Core IEEE1394 transaction logic");
MODULE_LICENSE("GPL");
return fw_cdev_major;
}
+ retval = fw_core_add_address_handler(&topology_map,
+ &topology_map_region);
+ BUG_ON(retval < 0);
+
/* Add the vendor textual descriptor. */
retval = fw_core_add_descriptor(&vendor_id_descriptor);
BUG_ON(retval < 0);