From db5f202d5d050cb78bb6696f7ec56954da3a8a6c Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 13 Aug 2011 17:08:29 +0200 Subject: [PATCH] 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 Signed-off-by: Dan Dennedy --- src/fw.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/fw.c b/src/fw.c index baa3e93..fc51e2f 100644 --- a/src/fw.c +++ b/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