diff options
author | Kristian Høgsberg <krh@redhat.com> | 2007-03-07 12:12:56 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2007-03-09 16:03:15 -0500 |
commit | d60d7f1d5ce83d1be8d79256f711d6a645b7a2fa (patch) | |
tree | dd3f02960657d4270efb0990b5cdfe0eeef62ad5 | |
parent | 473d28c730e2de888c24b226cfe4183868eacde2 (diff) |
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>
-rw-r--r-- | drivers/firewire/fw-ohci.c | 26 | ||||
-rw-r--r-- | drivers/firewire/fw-transaction.c | 61 | ||||
-rw-r--r-- | 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 a9e13468f60c..6f9895d201b8 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c | |||
@@ -139,6 +139,7 @@ struct fw_ohci { | |||
139 | int node_id; | 139 | int node_id; |
140 | int generation; | 140 | int generation; |
141 | int request_generation; | 141 | int request_generation; |
142 | u32 bus_seconds; | ||
142 | 143 | ||
143 | /* Spinlock for accessing fw_ohci data. Never call out of | 144 | /* Spinlock for accessing fw_ohci data. Never call out of |
144 | * this driver with this lock held. */ | 145 | * this driver with this lock held. */ |
@@ -959,7 +960,7 @@ static void bus_reset_tasklet(unsigned long data) | |||
959 | static irqreturn_t irq_handler(int irq, void *data) | 960 | static irqreturn_t irq_handler(int irq, void *data) |
960 | { | 961 | { |
961 | struct fw_ohci *ohci = data; | 962 | struct fw_ohci *ohci = data; |
962 | u32 event, iso_event; | 963 | u32 event, iso_event, cycle_time; |
963 | int i; | 964 | int i; |
964 | 965 | ||
965 | event = reg_read(ohci, OHCI1394_IntEventClear); | 966 | event = reg_read(ohci, OHCI1394_IntEventClear); |
@@ -1002,6 +1003,12 @@ static irqreturn_t irq_handler(int irq, void *data) | |||
1002 | iso_event &= ~(1 << i); | 1003 | iso_event &= ~(1 << i); |
1003 | } | 1004 | } |
1004 | 1005 | ||
1006 | if (event & OHCI1394_cycle64Seconds) { | ||
1007 | cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer); | ||
1008 | if ((cycle_time & 0x80000000) == 0) | ||
1009 | ohci->bus_seconds++; | ||
1010 | } | ||
1011 | |||
1005 | return IRQ_HANDLED; | 1012 | return IRQ_HANDLED; |
1006 | } | 1013 | } |
1007 | 1014 | ||
@@ -1213,6 +1220,19 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) | |||
1213 | return retval; | 1220 | return retval; |
1214 | } | 1221 | } |
1215 | 1222 | ||
1223 | static u64 | ||
1224 | ohci_get_bus_time(struct fw_card *card) | ||
1225 | { | ||
1226 | struct fw_ohci *ohci = fw_ohci(card); | ||
1227 | u32 cycle_time; | ||
1228 | u64 bus_time; | ||
1229 | |||
1230 | cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer); | ||
1231 | bus_time = ((u64) ohci->bus_seconds << 32) | cycle_time; | ||
1232 | |||
1233 | return bus_time; | ||
1234 | } | ||
1235 | |||
1216 | static int handle_ir_bufferfill_packet(struct context *context, | 1236 | static int handle_ir_bufferfill_packet(struct context *context, |
1217 | struct descriptor *d, | 1237 | struct descriptor *d, |
1218 | struct descriptor *last) | 1238 | struct descriptor *last) |
@@ -1686,6 +1706,7 @@ static const struct fw_card_driver ohci_driver = { | |||
1686 | .send_response = ohci_send_response, | 1706 | .send_response = ohci_send_response, |
1687 | .cancel_packet = ohci_cancel_packet, | 1707 | .cancel_packet = ohci_cancel_packet, |
1688 | .enable_phys_dma = ohci_enable_phys_dma, | 1708 | .enable_phys_dma = ohci_enable_phys_dma, |
1709 | .get_bus_time = ohci_get_bus_time, | ||
1689 | 1710 | ||
1690 | .allocate_iso_context = ohci_allocate_iso_context, | 1711 | .allocate_iso_context = ohci_allocate_iso_context, |
1691 | .free_iso_context = ohci_free_iso_context, | 1712 | .free_iso_context = ohci_free_iso_context, |
@@ -1862,7 +1883,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) | |||
1862 | OHCI1394_RQPkt | OHCI1394_RSPkt | | 1883 | OHCI1394_RQPkt | OHCI1394_RSPkt | |
1863 | OHCI1394_reqTxComplete | OHCI1394_respTxComplete | | 1884 | OHCI1394_reqTxComplete | OHCI1394_respTxComplete | |
1864 | OHCI1394_isochRx | OHCI1394_isochTx | | 1885 | OHCI1394_isochRx | OHCI1394_isochTx | |
1865 | OHCI1394_masterIntEnable); | 1886 | OHCI1394_masterIntEnable | |
1887 | OHCI1394_cycle64Seconds); | ||
1866 | 1888 | ||
1867 | bus_options = reg_read(ohci, OHCI1394_BusOptions); | 1889 | bus_options = reg_read(ohci, OHCI1394_BusOptions); |
1868 | max_receive = (bus_options >> 12) & 0xf; | 1890 | max_receive = (bus_options >> 12) & 0xf; |
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 38b286ed744f..d36dd512a59d 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, | |||
752 | } | 752 | } |
753 | 753 | ||
754 | static struct fw_address_handler topology_map = { | 754 | static struct fw_address_handler topology_map = { |
755 | .length = 0x400, | 755 | .length = 0x200, |
756 | .address_callback = handle_topology_map, | 756 | .address_callback = handle_topology_map, |
757 | }; | 757 | }; |
758 | 758 | ||
759 | const struct fw_address_region registers_region = | ||
760 | { .start = 0xfffff0000000ull, .end = 0xfffff0000400ull, }; | ||
761 | |||
762 | static void | ||
763 | handle_registers(struct fw_card *card, struct fw_request *request, | ||
764 | int tcode, int destination, int source, | ||
765 | int generation, int speed, | ||
766 | unsigned long long offset, | ||
767 | void *payload, size_t length, void *callback_data) | ||
768 | { | ||
769 | int reg = offset - CSR_REGISTER_BASE; | ||
770 | unsigned long long bus_time; | ||
771 | __be32 *data = payload; | ||
772 | |||
773 | switch (reg) { | ||
774 | case CSR_CYCLE_TIME: | ||
775 | case CSR_BUS_TIME: | ||
776 | if (!TCODE_IS_READ_REQUEST(tcode) || length != 4) { | ||
777 | fw_send_response(card, request, RCODE_TYPE_ERROR); | ||
778 | break; | ||
779 | } | ||
780 | |||
781 | bus_time = card->driver->get_bus_time(card); | ||
782 | if (reg == CSR_CYCLE_TIME) | ||
783 | *data = cpu_to_be32(bus_time); | ||
784 | else | ||
785 | *data = cpu_to_be32(bus_time >> 25); | ||
786 | fw_send_response(card, request, RCODE_COMPLETE); | ||
787 | break; | ||
788 | |||
789 | case CSR_BUS_MANAGER_ID: | ||
790 | case CSR_BANDWIDTH_AVAILABLE: | ||
791 | case CSR_CHANNELS_AVAILABLE_HI: | ||
792 | case CSR_CHANNELS_AVAILABLE_LO: | ||
793 | /* FIXME: these are handled by the OHCI hardware and | ||
794 | * the stack never sees these request. If we add | ||
795 | * support for a new type of controller that doesn't | ||
796 | * handle this in hardware we need to deal with these | ||
797 | * transactions. */ | ||
798 | BUG(); | ||
799 | break; | ||
800 | |||
801 | case CSR_BUSY_TIMEOUT: | ||
802 | /* FIXME: Implement this. */ | ||
803 | default: | ||
804 | fw_send_response(card, request, RCODE_ADDRESS_ERROR); | ||
805 | break; | ||
806 | } | ||
807 | } | ||
808 | |||
809 | static struct fw_address_handler registers = { | ||
810 | .length = 0x400, | ||
811 | .address_callback = handle_registers, | ||
812 | }; | ||
813 | |||
759 | MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>"); | 814 | MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>"); |
760 | MODULE_DESCRIPTION("Core IEEE1394 transaction logic"); | 815 | MODULE_DESCRIPTION("Core IEEE1394 transaction logic"); |
761 | MODULE_LICENSE("GPL"); | 816 | MODULE_LICENSE("GPL"); |
@@ -811,6 +866,10 @@ static int __init fw_core_init(void) | |||
811 | &topology_map_region); | 866 | &topology_map_region); |
812 | BUG_ON(retval < 0); | 867 | BUG_ON(retval < 0); |
813 | 868 | ||
869 | retval = fw_core_add_address_handler(®isters, | ||
870 | ®isters_region); | ||
871 | BUG_ON(retval < 0); | ||
872 | |||
814 | /* Add the vendor textual descriptor. */ | 873 | /* Add the vendor textual descriptor. */ |
815 | retval = fw_core_add_descriptor(&vendor_id_descriptor); | 874 | retval = fw_core_add_descriptor(&vendor_id_descriptor); |
816 | BUG_ON(retval < 0); | 875 | BUG_ON(retval < 0); |
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index a661afb9d68f..855beb27216d 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h | |||
@@ -433,6 +433,8 @@ struct fw_card_driver { | |||
433 | int (*enable_phys_dma) (struct fw_card *card, | 433 | int (*enable_phys_dma) (struct fw_card *card, |
434 | int node_id, int generation); | 434 | int node_id, int generation); |
435 | 435 | ||
436 | u64 (*get_bus_time) (struct fw_card *card); | ||
437 | |||
436 | struct fw_iso_context * | 438 | struct fw_iso_context * |
437 | (*allocate_iso_context)(struct fw_card *card, int sync, int tags, | 439 | (*allocate_iso_context)(struct fw_card *card, int sync, int tags, |
438 | int type, size_t header_size); | 440 | int type, size_t header_size); |