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:
parent
52099f7148
commit
db5f202d5d
52
src/fw.c
52
src/fw.c
|
@ -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
|
||||
|
|
Reference in New Issue