summaryrefslogtreecommitdiff
path: root/drivers/firewire
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2010-06-10 08:24:03 +0200
committerClemens Ladisch <clemens@ladisch.de>2010-06-10 08:24:03 +0200
commit3e07ec0eee1662f89e57f84aff625065beb2b209 (patch)
treeef164bc604c9b22d21983ae90dbe24636264db9d /drivers/firewire
parentbda3b8a1faf209a98063ccd77d6833a2bb0fc77e (diff)
firewire: core: add CSR STATE_CLEAR/STATE_SET support
The state registers are zero and read-only in this implementation, so they are not of much use. However, the specification requires that they are present for transaction capable nodes, and the Base 1394 Test Suite tests for them, so we better implement them. Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/core-transaction.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c
index f33a629c8379..6971400b6354 100644
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -969,6 +969,30 @@ static const struct fw_address_region registers_region =
{ .start = CSR_REGISTER_BASE,
.end = CSR_REGISTER_BASE | CSR_CONFIG_ROM, };
+static u32 read_state_register(struct fw_card *card)
+{
+ /*
+ * Fixed bits (IEEE 1394-2008 8.3.2.2.1):
+ * Bits 0-1 (state) always read 00=running.
+ * Bits 2,3 (off, atn) are not implemented as per the spec.
+ * Bit 4 (elog) is not implemented because there is no error log.
+ * Bit 6 (dreq) cannot be set. It is intended to "disable requests
+ * from unreliable nodes"; however, IEEE 1212 states that devices
+ * may "clear their own dreq bit when it has been improperly set".
+ * Our implementation might be seen as an improperly extensive
+ * interpretation of "improperly", but the 1212-2001 revision
+ * dropped this bit altogether, so we're in the clear. :o)
+ * Bit 7 (lost) always reads 0 because a power reset has never occurred
+ * during normal operation.
+ * Bit 9 (linkoff) is not implemented because the PC is not powered
+ * from the FireWire cable.
+ * Bit 15 (gone) always reads 0. It must be set at a power/command/bus
+ * reset, but then cleared when the units are ready again, which
+ * happens immediately for us.
+ */
+ return 0;
+}
+
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,
@@ -979,6 +1003,26 @@ static void handle_registers(struct fw_card *card, struct fw_request *request,
int rcode = RCODE_COMPLETE;
switch (reg) {
+ case CSR_STATE_CLEAR:
+ if (tcode == TCODE_READ_QUADLET_REQUEST) {
+ *data = cpu_to_be32(read_state_register(card));
+ } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) {
+ } else {
+ rcode = RCODE_TYPE_ERROR;
+ }
+ break;
+
+ case CSR_STATE_SET:
+ if (tcode == TCODE_READ_QUADLET_REQUEST) {
+ *data = cpu_to_be32(read_state_register(card));
+ } else if (tcode == TCODE_WRITE_QUADLET_REQUEST) {
+ /* FIXME: implement cmstr */
+ /* FIXME: implement abdicate */
+ } else {
+ rcode = RCODE_TYPE_ERROR;
+ }
+ break;
+
case CSR_CYCLE_TIME:
if (TCODE_IS_READ_REQUEST(tcode) && length == 4)
*data = cpu_to_be32(card->driver->get_cycle_time(card));