Use new iso resource allocation ioctls

This allows raw1394_bandwidth_modify() and raw1394_channel_modify()
to work on juju without write access to the IRM's character device file.

If either the build-time requirement of firewire-cdev header ABI >= v.2
or the runtime requirement of firewire-core ABI >= v.2 is not satisfied,
the code falls back to transactions to the IRM as before.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
This commit is contained in:
Stefan Richter 2009-01-11 22:45:02 +01:00
parent da5156af5a
commit c58e16442b
3 changed files with 110 additions and 2 deletions

View File

@ -541,7 +541,10 @@ int raw1394_bandwidth_modify (raw1394handle_t handle, unsigned int bandwidth,
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
return ieee1394_bandwidth_modify(handle, bandwidth, mode); if (handle->is_fw)
return fw_bandwidth_modify(handle, bandwidth, mode);
else
return ieee1394_bandwidth_modify(handle, bandwidth, mode);
} }
int raw1394_channel_modify (raw1394handle_t handle, unsigned int channel, int raw1394_channel_modify (raw1394handle_t handle, unsigned int channel,
@ -551,7 +554,10 @@ int raw1394_channel_modify (raw1394handle_t handle, unsigned int channel,
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
return ieee1394_channel_modify(handle, channel, mode); if (handle->is_fw)
return fw_channel_modify(handle, channel, mode);
else
return ieee1394_channel_modify(handle, channel, mode);
} }
int raw1394_iso_xmit_init(raw1394handle_t handle, int raw1394_iso_xmit_init(raw1394handle_t handle,

View File

@ -294,6 +294,13 @@ handle_device_event(raw1394handle_t handle,
ac = u64_to_ptr(u->request.closure); ac = u64_to_ptr(u->request.closure);
return ac->callback(handle, ac, &u->request, i); return ac->callback(handle, ac, &u->request, i);
#ifdef FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED /* added in kernel 2.6.30 */
case FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED:
case FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED:
memcpy(u64_to_ptr(u->iso_resource.closure), u,
sizeof u->iso_resource);
return 0;
#endif
default: default:
case FW_CDEV_EVENT_ISO_INTERRUPT: case FW_CDEV_EVENT_ISO_INTERRUPT:
/* Never happens. */ /* Never happens. */
@ -631,6 +638,7 @@ int fw_set_port(fw_handle_t handle, int port)
handle->local_device = &handle->devices[i]; handle->local_device = &handle->devices[i];
handle->generation = reset.generation; handle->generation = reset.generation;
handle->abi_version = get_info.version;
i++; i++;
} }
@ -1324,3 +1332,90 @@ fw_get_config_rom(fw_handle_t handle, quadlet_t *buffer,
return 0; return 0;
} }
#ifdef FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE /* added in kernel 2.6.30 */
static int
iso_resource_modify(raw1394handle_t handle, unsigned int bandwidth,
int channel, enum raw1394_modify_mode mode)
{
fw_handle_t fwhandle = handle->mode.fw;
struct fw_cdev_allocate_iso_resource resource;
struct fw_cdev_event_iso_resource event;
int ioctl_nr;
int err;
if (channel > 63) {
errno = EINVAL;
return -1;
}
event.closure = 0;
event.channel = -1;
event.bandwidth = 0;
resource.closure = ptr_to_u64(&event);
resource.channels = channel >= 0 ? 1ULL << channel : 0;
resource.bandwidth = bandwidth;
ioctl_nr = mode == RAW1394_MODIFY_ALLOC ?
FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE :
FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE_ONCE;
err = ioctl(fwhandle->ioctl_fd, ioctl_nr, &resource);
while (err >= 0 && event.closure != resource.closure)
err = fw_loop_iterate(handle);
if (err < 0)
return err;
if ((channel >= 0 && event.channel < 0) ||
(bandwidth > 0 && event.bandwidth == 0)) {
errno = EIO;
return -1;
}
return 0;
}
static inline int abi_v2_available(raw1394handle_t handle)
{
return handle->mode.fw->abi_version >= 2;
}
#else
static inline int
iso_resource_modify(raw1394handle_t handle, unsigned int bandwidth,
int channel, enum raw1394_modify_mode mode)
{
return -1;
}
static inline int abi_v2_available(raw1394handle_t handle)
{
return 0;
}
#endif /* defined(FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE) */
int
fw_bandwidth_modify(raw1394handle_t handle, unsigned int bandwidth,
enum raw1394_modify_mode mode)
{
if (abi_v2_available(handle))
return iso_resource_modify(handle, bandwidth, -1, mode);
else
return ieee1394_bandwidth_modify(handle, bandwidth, mode);
}
int
fw_channel_modify(raw1394handle_t handle, unsigned int channel,
enum raw1394_modify_mode mode)
{
if (abi_v2_available(handle))
return iso_resource_modify(handle, 0, channel, mode);
else
return ieee1394_channel_modify(handle, channel, mode);
}

View File

@ -81,6 +81,7 @@ struct fw_handle {
int port_count; int port_count;
int err; int err;
int generation; int generation;
int abi_version;
void *userdata; void *userdata;
int notify_bus_reset; int notify_bus_reset;
@ -202,6 +203,12 @@ int fw_update_config_rom(fw_handle_t handle, const quadlet_t *new_rom,
int fw_get_config_rom(fw_handle_t handle, quadlet_t *buffer, int fw_get_config_rom(fw_handle_t handle, quadlet_t *buffer,
size_t buffersize, size_t *rom_size, size_t buffersize, size_t *rom_size,
unsigned char *rom_version); unsigned char *rom_version);
int fw_bandwidth_modify(raw1394handle_t handle,
unsigned int bandwidth,
enum raw1394_modify_mode mode);
int fw_channel_modify(raw1394handle_t handle,
unsigned int channel,
enum raw1394_modify_mode mode);
int fw_iso_xmit_start(raw1394handle_t handle, int start_on_cycle, int fw_iso_xmit_start(raw1394handle_t handle, int start_on_cycle,
int prebuffer_packets); int prebuffer_packets);