redirect Config ROM reads into the kernel's ROM cache

The kernel already read each node's Configuration ROM and cached it.
So let all libraw1394 clients read from that cache instead of having
to perform all those transactions all over again.

This reduces bus traffic at application start-up and at each bus reset.
It also makes all Configuration ROM accesses fool-proof and robust.

This together with the kernel patch "firewire: core: handle ack_busy
when fetching the Config ROM" lets me use an old Panasonic camcorder
which requires us to keep pauses between response and request ---
longer than librom1394's retry pause --- with dvgrab (though still
with frequent failures of write requests to FCP_COMMAND, i.e. with lots
of "send oops" noise in the console and occasionally having to repeat
key-presses in interactive mode).

For simplicity of implementation, only the blocking raw1394_read() is
modified, not the nonblocking raw1394_start_read().

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Signed-off-by: Dan Dennedy <dan@dennedy.org>
This commit is contained in:
Stefan Richter 2011-08-13 17:08:29 +02:00
parent 52099f7148
commit db5f202d5d
1 changed files with 52 additions and 0 deletions

View File

@ -1309,12 +1309,64 @@ send_request_sync(raw1394handle_t handle, int tcode,
return (errno ? -1 : 0);
}
int
read_config_rom(fw_handle_t handle, nodeid_t node, nodeaddr_t addr,
size_t length, quadlet_t *buffer)
{
struct fw_cdev_get_info get_info;
quadlet_t rom[256];
int offset, fd, i, err;
if (node > handle->reset.root_node_id) {
handle->err = -RCODE_NO_ACK;
errno = fw_errcode_to_errno(handle->err);
return -1;
}
i = handle->nodes[node & 0x3f];
if (i == -1) {
handle->err = -RCODE_NO_ACK;
errno = fw_errcode_to_errno(handle->err);
return -1;
}
if (handle->generation != handle->devices[i].generation) {
handle->err = -RCODE_GENERATION;
errno = fw_errcode_to_errno(handle->err);
return -1;
}
fd = handle->devices[i].fd;
memset(&get_info, 0, sizeof(get_info));
memset(&rom, 0, sizeof(rom));
get_info.version = IMPLEMENTED_CDEV_ABI_VERSION;
get_info.rom = ptr_to_u64(rom);
get_info.rom_length = sizeof(rom);
get_info.bus_reset = 0;
err = ioctl(fd, FW_CDEV_IOC_GET_INFO, &get_info);
if (err)
return err;
offset = (addr - CSR_REGISTER_BASE - CSR_CONFIG_ROM) / 4;
for (i = 0; i < length / 4; i++)
buffer[i] = cpu_to_be32(rom[offset + i]);
return 0;
}
int
fw_read(raw1394handle_t handle, nodeid_t node, nodeaddr_t addr,
size_t length, quadlet_t *buffer)
{
int tcode;
if (addr >= CSR_REGISTER_BASE + CSR_CONFIG_ROM &&
addr + length <= CSR_REGISTER_BASE + CSR_CONFIG_ROM_END &&
!(addr & 3) && length > 0 && !(length & 3))
return read_config_rom(handle->mode.fw,
node, addr, length, buffer);
if (length == 4)
tcode = TCODE_READ_QUADLET_REQUEST;
else