firewire: Implement CSR cycle time and bus time registers.

Signed-off-by: Kristian Høgsberg <krh@redhat.com>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
index 38b286ed..d36dd51 100644
--- a/drivers/firewire/fw-transaction.c
+++ b/drivers/firewire/fw-transaction.c
@@ -752,10 +752,65 @@
 }
 
 static struct fw_address_handler topology_map = {
-	.length			= 0x400,
+	.length			= 0x200,
 	.address_callback	= handle_topology_map,
 };
 
+const struct fw_address_region registers_region =
+	{ .start = 0xfffff0000000ull, .end = 0xfffff0000400ull, };
+
+static void
+handle_registers(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 reg = offset - CSR_REGISTER_BASE;
+	unsigned long long bus_time;
+	__be32 *data = payload;
+
+	switch (reg) {
+	case CSR_CYCLE_TIME:
+	case CSR_BUS_TIME:
+		if (!TCODE_IS_READ_REQUEST(tcode) || length != 4) {
+			fw_send_response(card, request, RCODE_TYPE_ERROR);
+			break;
+		}
+
+		bus_time = card->driver->get_bus_time(card);
+		if (reg == CSR_CYCLE_TIME)
+			*data = cpu_to_be32(bus_time);
+		else
+			*data = cpu_to_be32(bus_time >> 25);
+		fw_send_response(card, request, RCODE_COMPLETE);
+		break;
+
+	case CSR_BUS_MANAGER_ID:
+	case CSR_BANDWIDTH_AVAILABLE:
+	case CSR_CHANNELS_AVAILABLE_HI:
+	case CSR_CHANNELS_AVAILABLE_LO:
+		/* FIXME: these are handled by the OHCI hardware and
+		 * the stack never sees these request. If we add
+		 * support for a new type of controller that doesn't
+		 * handle this in hardware we need to deal with these
+		 * transactions. */
+		BUG();
+		break;
+
+	case CSR_BUSY_TIMEOUT:
+		/* FIXME: Implement this. */
+	default:
+		fw_send_response(card, request, RCODE_ADDRESS_ERROR);
+		break;
+	}
+}
+
+static struct fw_address_handler registers = {
+	.length			= 0x400,
+	.address_callback	= handle_registers,
+};
+
 MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
 MODULE_DESCRIPTION("Core IEEE1394 transaction logic");
 MODULE_LICENSE("GPL");
@@ -811,6 +866,10 @@
 					     &topology_map_region);
 	BUG_ON(retval < 0);
 
+	retval = fw_core_add_address_handler(&registers,
+					     &registers_region);
+	BUG_ON(retval < 0);
+
 	/* Add the vendor textual descriptor. */
 	retval = fw_core_add_descriptor(&vendor_id_descriptor);
 	BUG_ON(retval < 0);