Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=d60d7f1d5ce83d1be8d79256f711d6a645b7a2fa
Commit:     d60d7f1d5ce83d1be8d79256f711d6a645b7a2fa
Parent:     473d28c730e2de888c24b226cfe4183868eacde2
Author:     Kristian Høgsberg <[EMAIL PROTECTED]>
AuthorDate: Wed Mar 7 12:12:56 2007 -0500
Committer:  Stefan Richter <[EMAIL PROTECTED]>
CommitDate: Fri Mar 9 22:03:15 2007 +0100

    firewire: Implement CSR cycle time and bus time registers.
    
    Signed-off-by: Kristian Høgsberg <[EMAIL PROTECTED]>
    Signed-off-by: Stefan Richter <[EMAIL PROTECTED]>
---
 drivers/firewire/fw-ohci.c        |   26 ++++++++++++++-
 drivers/firewire/fw-transaction.c |   61 ++++++++++++++++++++++++++++++++++++-
 drivers/firewire/fw-transaction.h |    2 +
 3 files changed, 86 insertions(+), 3 deletions(-)

diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index a9e1346..6f9895d 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -139,6 +139,7 @@ struct fw_ohci {
        int node_id;
        int generation;
        int request_generation;
+       u32 bus_seconds;
 
        /* Spinlock for accessing fw_ohci data.  Never call out of
         * this driver with this lock held. */
@@ -959,7 +960,7 @@ static void bus_reset_tasklet(unsigned long data)
 static irqreturn_t irq_handler(int irq, void *data)
 {
        struct fw_ohci *ohci = data;
-       u32 event, iso_event;
+       u32 event, iso_event, cycle_time;
        int i;
 
        event = reg_read(ohci, OHCI1394_IntEventClear);
@@ -1002,6 +1003,12 @@ static irqreturn_t irq_handler(int irq, void *data)
                iso_event &= ~(1 << i);
        }
 
+       if (event & OHCI1394_cycle64Seconds) {
+               cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
+               if ((cycle_time & 0x80000000) == 0)
+                       ohci->bus_seconds++;
+       }
+
        return IRQ_HANDLED;
 }
 
@@ -1213,6 +1220,19 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, 
int generation)
        return retval;
 }
 
+static u64
+ohci_get_bus_time(struct fw_card *card)
+{
+       struct fw_ohci *ohci = fw_ohci(card);
+       u32 cycle_time;
+       u64 bus_time;
+
+       cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
+       bus_time = ((u64) ohci->bus_seconds << 32) | cycle_time;
+
+       return bus_time;
+}
+
 static int handle_ir_bufferfill_packet(struct context *context,
                                       struct descriptor *d,
                                       struct descriptor *last)
@@ -1686,6 +1706,7 @@ static const struct fw_card_driver ohci_driver = {
        .send_response          = ohci_send_response,
        .cancel_packet          = ohci_cancel_packet,
        .enable_phys_dma        = ohci_enable_phys_dma,
+       .get_bus_time           = ohci_get_bus_time,
 
        .allocate_iso_context   = ohci_allocate_iso_context,
        .free_iso_context       = ohci_free_iso_context,
@@ -1862,7 +1883,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id 
*ent)
                  OHCI1394_RQPkt | OHCI1394_RSPkt |
                  OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
                  OHCI1394_isochRx | OHCI1394_isochTx |
-                 OHCI1394_masterIntEnable);
+                 OHCI1394_masterIntEnable |
+                 OHCI1394_cycle64Seconds);
 
        bus_options = reg_read(ohci, OHCI1394_BusOptions);
        max_receive = (bus_options >> 12) & 0xf;
diff --git a/drivers/firewire/fw-transaction.c 
b/drivers/firewire/fw-transaction.c
index 38b286e..d36dd51 100644
--- a/drivers/firewire/fw-transaction.c
+++ b/drivers/firewire/fw-transaction.c
@@ -752,10 +752,65 @@ handle_topology_map(struct fw_card *card, struct 
fw_request *request,
 }
 
 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 <[EMAIL PROTECTED]>");
 MODULE_DESCRIPTION("Core IEEE1394 transaction logic");
 MODULE_LICENSE("GPL");
@@ -811,6 +866,10 @@ static int __init fw_core_init(void)
                                             &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);
diff --git a/drivers/firewire/fw-transaction.h 
b/drivers/firewire/fw-transaction.h
index a661afb..855beb2 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -433,6 +433,8 @@ struct fw_card_driver {
        int (*enable_phys_dma) (struct fw_card *card,
                                int node_id, int generation);
 
+       u64 (*get_bus_time) (struct fw_card *card);
+
        struct fw_iso_context *
        (*allocate_iso_context)(struct fw_card *card, int sync, int tags,
                                int type, size_t header_size);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to