diff --git a/src/fw.c b/src/fw.c index 5f5bc69..e5c23d1 100644 --- a/src/fw.c +++ b/src/fw.c @@ -28,7 +28,11 @@ /* * ABI version history is documented in linux/firewire-cdev.h. */ +#ifdef FW_CDEV_EVENT_REQUEST2 +#define IMPLEMENTED_CDEV_ABI_VERSION 4 +#else #define IMPLEMENTED_CDEV_ABI_VERSION 2 +#endif int fw_errcode_to_errno(raw1394_errcode_t errcode) @@ -215,41 +219,41 @@ handle_lost_device(fw_handle_t handle, int i) struct address_closure { int (*callback)(raw1394handle_t handle, struct address_closure *ac, - struct fw_cdev_event_request *request, int i); + int tcode, unsigned long long offset, + int source_node_id, unsigned kernel_handle, + size_t length, void *data); }; static int handle_fcp_request(raw1394handle_t handle, struct address_closure *ac, - struct fw_cdev_event_request *request, int i) + int tcode, unsigned long long offset, int source_node_id, + unsigned kernel_handle, size_t length, void *data) { struct fw_cdev_send_response response; int is_response; - response.handle = request->handle; - response.rcode = RCODE_COMPLETE; - response.length = 0; - response.data = 0; + response.handle = kernel_handle; + response.rcode = RCODE_COMPLETE; + response.length = 0; + response.data = 0; if (handle->mode.fw->fcp_handler == NULL) response.rcode = RCODE_ADDRESS_ERROR; - if (request->tcode >= TCODE_WRITE_RESPONSE) + if (tcode >= TCODE_WRITE_RESPONSE) response.rcode = RCODE_CONFLICT_ERROR; - if (ioctl(handle->mode.fw->devices[i].fd, + if (ioctl(handle->mode.fw->ioctl_fd, FW_CDEV_IOC_SEND_RESPONSE, &response) < 0) return -1; if (response.rcode != RCODE_COMPLETE) return 0; - is_response = request->offset >= CSR_REGISTER_BASE + CSR_FCP_RESPONSE; + is_response = offset >= CSR_REGISTER_BASE + CSR_FCP_RESPONSE; - return handle->mode.fw->fcp_handler(handle, - handle->mode.fw->devices[i].node_id, - is_response, - request->length, - (unsigned char *) request->data); + return handle->mode.fw->fcp_handler(handle, source_node_id, + is_response, length, data); } static int @@ -307,7 +311,22 @@ handle_device_event(raw1394handle_t handle, case FW_CDEV_EVENT_REQUEST: ac = u64_to_ptr(u->request.closure); - return ac->callback(handle, ac, &u->request, i); + return ac->callback(handle, ac, u->request.tcode, + u->request.offset, + /* wild guess, but can't do better */ + fwhandle->devices[i].node_id, + u->request.handle, + u->request.length, u->request.data); + +#ifdef FW_CDEV_EVENT_REQUEST2 /* added in kernel 2.6.36 */ + case FW_CDEV_EVENT_REQUEST2: + ac = u64_to_ptr(u->request.closure); + return ac->callback(handle, ac, u->request2.tcode, + u->request2.offset, + u->request2.source_node_id, + u->request2.handle, + u->request2.length, u->request2.data); +#endif #ifdef FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED /* added in kernel 2.6.30 */ case FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED: @@ -695,7 +714,7 @@ struct request_response_block { }; struct allocation { - struct address_closure closure; + struct address_closure closure; /* must be first member */ struct allocation *next; __u32 handle; byte_t *buffer; @@ -710,7 +729,8 @@ struct allocation { static int handle_arm_request(raw1394handle_t handle, struct address_closure *ac, - struct fw_cdev_event_request *request, int i) + int tcode, unsigned long long offset, int source_node_id, + unsigned kernel_handle, size_t length, void *data) { fw_handle_t fwhandle = handle->mode.fw; struct allocation *allocation = (struct allocation *) ac; @@ -718,19 +738,19 @@ handle_arm_request(raw1394handle_t handle, struct address_closure *ac, struct fw_cdev_send_response response; arm_options_t type; size_t in_length; - int offset; + int pos; - offset = request->offset - allocation->offset; - response.handle = request->handle; + pos = offset - allocation->offset; + response.handle = kernel_handle; - switch (request->tcode) { + switch (tcode) { case TCODE_WRITE_QUADLET_REQUEST: case TCODE_WRITE_BLOCK_REQUEST: printf("got write request, offset=0x%012llx, length=%d\n", - request->offset, request->length); + offset, (int)length); type = RAW1394_ARM_WRITE; - in_length = request->length; + in_length = length; response.rcode = RCODE_COMPLETE; response.length = 0; response.data = 0; @@ -739,18 +759,29 @@ handle_arm_request(raw1394handle_t handle, struct address_closure *ac, case TCODE_READ_QUADLET_REQUEST: case TCODE_READ_BLOCK_REQUEST: printf("got read request, offset=0x%012llx, length=%d\n", - request->offset, request->length); + offset, (int)length); type = RAW1394_ARM_READ; in_length = 0; response.rcode = RCODE_COMPLETE; - response.length = request->length; - response.data = ptr_to_u64(allocation->data + offset); + response.length = length; + response.data = ptr_to_u64(allocation->data + pos); break; case TCODE_LOCK_REQUEST: + /* + * TCODE_LOCK_REQUEST is generated by ABI v3 and older, cannot + * be handled. Fall through for now. FIXME. + */ + case TCODE_LOCK_MASK_SWAP: + case TCODE_LOCK_COMPARE_SWAP: + case TCODE_LOCK_FETCH_ADD: + case TCODE_LOCK_LITTLE_ADD: + case TCODE_LOCK_BOUNDED_ADD: + case TCODE_LOCK_WRAP_ADD: + case TCODE_LOCK_VENDOR_DEPENDENT: type = RAW1394_ARM_LOCK; - in_length = request->length; + in_length = length; response.length = 4; break; @@ -764,17 +795,16 @@ handle_arm_request(raw1394handle_t handle, struct address_closure *ac, response.rcode = RCODE_TYPE_ERROR; response.length = 0; response.data = 0; - if (ioctl(fwhandle->devices[i].fd, + if (ioctl(fwhandle->ioctl_fd, FW_CDEV_IOC_SEND_RESPONSE, &response) < 0) return -1; } else if (!(allocation->client_transactions & type)) { if (type == RAW1394_ARM_WRITE) - memcpy(allocation->data + offset, - request->data, request->length); + memcpy(allocation->data + pos, data, length); else if (type == RAW1394_ARM_LOCK) /* FIXME: do lock ops here */; - if (ioctl(fwhandle->devices[i].fd, + if (ioctl(fwhandle->ioctl_fd, FW_CDEV_IOC_SEND_RESPONSE, &response) < 0) return -1; } @@ -792,30 +822,28 @@ handle_arm_request(raw1394handle_t handle, struct address_closure *ac, rrb->request_response.response = &rrb->response; rrb->request.destination_nodeid = fwhandle->reset.local_node_id; - rrb->request.source_nodeid = fwhandle->devices[i].node_id; - rrb->request.destination_offset = request->offset; + rrb->request.source_nodeid = source_node_id; + rrb->request.destination_offset = offset; rrb->request.tlabel = 0; - if (request->tcode < 0x10) { - rrb->request.tcode = request->tcode; + if (tcode < 0x10) { + rrb->request.tcode = tcode; rrb->request.extended_transaction_code = 0; } else { rrb->request.tcode = TCODE_LOCK_REQUEST; - rrb->request.extended_transaction_code = request->tcode - 0x10; + rrb->request.extended_transaction_code = tcode - 0x10; } rrb->request.generation = fwhandle->reset.generation; rrb->request.buffer_length = in_length; rrb->request.buffer = rrb->data; - memcpy(rrb->request.buffer, request->data, in_length); + memcpy(rrb->request.buffer, data, in_length); rrb->response.response_code = response.rcode; rrb->response.buffer_length = response.length; rrb->response.buffer = rrb->data + in_length; - memcpy(rrb->response.buffer, - allocation->data + offset, response.length); + memcpy(rrb->response.buffer, allocation->data + pos, response.length); return fwhandle->arm_tag_handler(handle, allocation->tag, type, - request->length, - &rrb->request_response); + length, &rrb->request_response); } int @@ -849,7 +877,9 @@ fw_arm_register(fw_handle_t handle, nodeaddr_t start, request.offset = start; request.length = length; request.closure = ptr_to_u64(&allocation->closure); - +#if IMPLEMENTED_CDEV_ABI_VERSION >= 4 + request.region_end = start + length; +#endif retval = ioctl(handle->ioctl_fd, FW_CDEV_IOC_ALLOCATE, &request); if (retval < 0) { free(allocation); @@ -1343,6 +1373,9 @@ fw_start_fcp_listen(fw_handle_t handle) request.offset = CSR_REGISTER_BASE + CSR_FCP_COMMAND; request.length = CSR_FCP_END - CSR_FCP_COMMAND; request.closure = ptr_to_u64(closure); +#if IMPLEMENTED_CDEV_ABI_VERSION >= 4 + request.region_end = CSR_REGISTER_BASE + CSR_FCP_END; +#endif if (ioctl(handle->ioctl_fd, FW_CDEV_IOC_ALLOCATE, &request) < 0) return -1;