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>
This commit is contained in:
parent
473d28c730
commit
d60d7f1d5c
|
@ -139,6 +139,7 @@ struct fw_ohci {
|
||||||
int node_id;
|
int node_id;
|
||||||
int generation;
|
int generation;
|
||||||
int request_generation;
|
int request_generation;
|
||||||
|
u32 bus_seconds;
|
||||||
|
|
||||||
/* Spinlock for accessing fw_ohci data. Never call out of
|
/* Spinlock for accessing fw_ohci data. Never call out of
|
||||||
* this driver with this lock held. */
|
* 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)
|
static irqreturn_t irq_handler(int irq, void *data)
|
||||||
{
|
{
|
||||||
struct fw_ohci *ohci = data;
|
struct fw_ohci *ohci = data;
|
||||||
u32 event, iso_event;
|
u32 event, iso_event, cycle_time;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
event = reg_read(ohci, OHCI1394_IntEventClear);
|
event = reg_read(ohci, OHCI1394_IntEventClear);
|
||||||
|
@ -1002,6 +1003,12 @@ static irqreturn_t irq_handler(int irq, void *data)
|
||||||
iso_event &= ~(1 << i);
|
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;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1213,6 +1220,19 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation)
|
||||||
return retval;
|
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,
|
static int handle_ir_bufferfill_packet(struct context *context,
|
||||||
struct descriptor *d,
|
struct descriptor *d,
|
||||||
struct descriptor *last)
|
struct descriptor *last)
|
||||||
|
@ -1686,6 +1706,7 @@ static const struct fw_card_driver ohci_driver = {
|
||||||
.send_response = ohci_send_response,
|
.send_response = ohci_send_response,
|
||||||
.cancel_packet = ohci_cancel_packet,
|
.cancel_packet = ohci_cancel_packet,
|
||||||
.enable_phys_dma = ohci_enable_phys_dma,
|
.enable_phys_dma = ohci_enable_phys_dma,
|
||||||
|
.get_bus_time = ohci_get_bus_time,
|
||||||
|
|
||||||
.allocate_iso_context = ohci_allocate_iso_context,
|
.allocate_iso_context = ohci_allocate_iso_context,
|
||||||
.free_iso_context = ohci_free_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_RQPkt | OHCI1394_RSPkt |
|
||||||
OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
|
OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
|
||||||
OHCI1394_isochRx | OHCI1394_isochTx |
|
OHCI1394_isochRx | OHCI1394_isochTx |
|
||||||
OHCI1394_masterIntEnable);
|
OHCI1394_masterIntEnable |
|
||||||
|
OHCI1394_cycle64Seconds);
|
||||||
|
|
||||||
bus_options = reg_read(ohci, OHCI1394_BusOptions);
|
bus_options = reg_read(ohci, OHCI1394_BusOptions);
|
||||||
max_receive = (bus_options >> 12) & 0xf;
|
max_receive = (bus_options >> 12) & 0xf;
|
||||||
|
|
|
@ -752,10 +752,65 @@ handle_topology_map(struct fw_card *card, struct fw_request *request,
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct fw_address_handler topology_map = {
|
static struct fw_address_handler topology_map = {
|
||||||
.length = 0x400,
|
.length = 0x200,
|
||||||
.address_callback = handle_topology_map,
|
.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_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
|
||||||
MODULE_DESCRIPTION("Core IEEE1394 transaction logic");
|
MODULE_DESCRIPTION("Core IEEE1394 transaction logic");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
@ -811,6 +866,10 @@ static int __init fw_core_init(void)
|
||||||
&topology_map_region);
|
&topology_map_region);
|
||||||
BUG_ON(retval < 0);
|
BUG_ON(retval < 0);
|
||||||
|
|
||||||
|
retval = fw_core_add_address_handler(®isters,
|
||||||
|
®isters_region);
|
||||||
|
BUG_ON(retval < 0);
|
||||||
|
|
||||||
/* Add the vendor textual descriptor. */
|
/* Add the vendor textual descriptor. */
|
||||||
retval = fw_core_add_descriptor(&vendor_id_descriptor);
|
retval = fw_core_add_descriptor(&vendor_id_descriptor);
|
||||||
BUG_ON(retval < 0);
|
BUG_ON(retval < 0);
|
||||||
|
|
|
@ -433,6 +433,8 @@ struct fw_card_driver {
|
||||||
int (*enable_phys_dma) (struct fw_card *card,
|
int (*enable_phys_dma) (struct fw_card *card,
|
||||||
int node_id, int generation);
|
int node_id, int generation);
|
||||||
|
|
||||||
|
u64 (*get_bus_time) (struct fw_card *card);
|
||||||
|
|
||||||
struct fw_iso_context *
|
struct fw_iso_context *
|
||||||
(*allocate_iso_context)(struct fw_card *card, int sync, int tags,
|
(*allocate_iso_context)(struct fw_card *card, int sync, int tags,
|
||||||
int type, size_t header_size);
|
int type, size_t header_size);
|
||||||
|
|
Loading…
Reference in New Issue