diff --git a/src/dispatch.c b/src/dispatch.c index 0edfd6d..beb031a 100644 --- a/src/dispatch.c +++ b/src/dispatch.c @@ -229,7 +229,7 @@ int raw1394_loop_iterate(raw1394handle_t handle) } int raw1394_arm_register(raw1394handle_t handle, nodeaddr_t start, - size_t length, byte_t *initial_value, + size_t length, octlet_t arm_tag, arm_options_t access_rights, arm_options_t notification_options, arm_options_t client_transactions) @@ -239,12 +239,13 @@ int raw1394_arm_register(raw1394handle_t handle, nodeaddr_t start, return -1; } if (handle->is_fw) - return fw_arm_register(handle->mode.fw, start, length, initial_value, + return fw_arm_register(handle->mode.fw, start, length, arm_tag, access_rights, notification_options, client_transactions); - else - return ieee1394_arm_register(handle->mode.ieee1394, start, length, - initial_value, arm_tag, access_rights, notification_options, - client_transactions); + else { + /* FIXME: implement for raw1394 */ + errno = ENOSYS; + return -1; + } } int raw1394_arm_unregister(raw1394handle_t handle, nodeaddr_t start) @@ -259,30 +260,21 @@ int raw1394_arm_unregister(raw1394handle_t handle, nodeaddr_t start) return ieee1394_arm_unregister(handle->mode.ieee1394, start); } -int raw1394_arm_set_buf (raw1394handle_t handle, nodeaddr_t start, - size_t length, void *buf) +int +raw1394_send_rw_response(raw1394handle_t handle, int tcode, void *data, size_t len, + unsigned kernel_handle) { if (!handle) { errno = EINVAL; return -1; } if (handle->is_fw) - return fw_arm_set_buf(handle->mode.fw, start, length, buf); - else - return ieee1394_arm_set_buf(handle->mode.ieee1394, start, length, buf); -} - -int raw1394_arm_get_buf (raw1394handle_t handle, nodeaddr_t start, - size_t length, void *buf) -{ - if (!handle) { - errno = EINVAL; + return fw_send_rw_response(handle->mode.fw, tcode, data, len, kernel_handle); + else { + /* FIXME: implement for raw1394 */ + errno = ENOSYS; return -1; } - if (handle->is_fw) - return fw_arm_get_buf(handle->mode.fw, start, length, buf); - else - return ieee1394_arm_get_buf(handle->mode.ieee1394, start, length, buf); } int raw1394_echo_request(raw1394handle_t handle, quadlet_t data) diff --git a/src/eventloop.c b/src/eventloop.c index 81bb881..d6d3bd2 100644 --- a/src/eventloop.c +++ b/src/eventloop.c @@ -65,12 +65,15 @@ int ieee1394_loop_iterate(struct raw1394_handle *handle) break; case RAW1394_REQ_ARM: + /* FIXME: implement new ARM for raw1394 */ +#if 0 if (ihandle->arm_tag_handler) { retval = ihandle->arm_tag_handler(handle, req.tag, (req.misc & (0xFF)), ((req.misc >> 16) & (0xFFFF)), int2ptr(req.recvb)); - } + } +#endif break; case RAW1394_REQ_ECHO: diff --git a/src/fw.c b/src/fw.c index b9c203d..27eb8b6 100644 --- a/src/fw.c +++ b/src/fw.c @@ -31,6 +31,13 @@ */ #define IMPLEMENTED_CDEV_ABI_VERSION 4 +struct address_closure { + int (*callback)(raw1394handle_t handle, struct address_closure *ac, + int tcode, unsigned long long offset, + int source_node_id, int card, unsigned kernel_handle, + size_t length, void *data); +}; + int fw_errcode_to_errno(raw1394_errcode_t errcode) { @@ -92,18 +99,25 @@ default_tag_handler(raw1394handle_t handle, return -1; } +/* do nothing */ static int -default_arm_tag_handler(raw1394handle_t handle, unsigned long arm_tag, - byte_t type, unsigned int length, void *data) +default_arm_tag_handler( + raw1394handle_t handle, raw1394_arm_allocation_t *arm, + int tcode, unsigned long long offset, int source_node_id, + int card, unsigned kernel_handle, size_t length, void *data +) { - struct raw1394_arm_reqhandle *rh; - - if (arm_tag == 0) - return -1; - - rh = (struct raw1394_arm_reqhandle *) arm_tag; - - return rh->arm_callback(handle, data, length, rh->pcontext, type); + (void)handle; + (void)arm; + (void)tcode; + (void)offset; + (void)source_node_id; + (void)card; + (void)kernel_handle; + (void)length; + (void)data; + + return 0; } static int @@ -214,13 +228,6 @@ handle_lost_device(fw_handle_t handle, int i) return 0; } -struct address_closure { - int (*callback)(raw1394handle_t handle, struct address_closure *ac, - int tcode, unsigned long long offset, - int source_node_id, int card, unsigned kernel_handle, - size_t length, void *data); -}; - static int handle_fcp_request(raw1394handle_t handle, struct address_closure *ac, int tcode, unsigned long long offset, int source_node_id, @@ -310,9 +317,9 @@ handle_device_event(raw1394handle_t handle, return fwhandle->tag_handler(handle, tag, errcode); - case FW_CDEV_EVENT_REQUEST: - ac = u64_to_ptr(u->request.closure); - return ac->callback(handle, ac, u->request.tcode, + case FW_CDEV_EVENT_REQUEST: { + raw1394_arm_allocation_t *al = u64_to_ptr(u->response.closure); + return fwhandle->arm_tag_handler(handle, al, u->request.tcode, u->request.offset, /* wild guess, but can't do better */ fwhandle->devices[i].node_id, @@ -320,15 +327,15 @@ handle_device_event(raw1394handle_t handle, u->request.handle, u->request.length, u->request.data); - case FW_CDEV_EVENT_REQUEST2: - ac = u64_to_ptr(u->request.closure); - return ac->callback(handle, ac, u->request2.tcode, + } case FW_CDEV_EVENT_REQUEST2: { + raw1394_arm_allocation_t *al = u64_to_ptr(u->response.closure); + return fwhandle->arm_tag_handler(handle, al, u->request2.tcode, u->request2.offset, u->request2.source_node_id, u->request2.card, u->request2.handle, u->request2.length, u->request2.data); - + } case FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED: case FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED: memcpy(u64_to_ptr(u->iso_resource.closure), u, @@ -769,40 +776,26 @@ struct request_response_block { }; struct allocation { - struct address_closure closure; /* must be first member */ + raw1394_arm_allocation_t info; struct allocation *next; __u32 handle; - byte_t *buffer; - octlet_t tag; - arm_options_t access_rights; - arm_options_t notification_options; - arm_options_t client_transactions; - nodeaddr_t offset; - size_t length; - unsigned char data[0]; }; -static int -handle_arm_request(raw1394handle_t handle, struct address_closure *ac, - int tcode, unsigned long long offset, int source_node_id, - int card, unsigned kernel_handle, size_t length, void *data) +int +fw_send_rw_response(fw_handle_t fwhandle, int tcode, void *data, size_t len, + unsigned kernel_handle) { - fw_handle_t fwhandle = handle->mode.fw; - struct allocation *allocation = (struct allocation *) ac; - struct request_response_block *rrb; struct fw_cdev_send_response response; - arm_options_t type; - size_t in_length; - int pos, retval; - pos = offset - allocation->offset; + if (data == NULL) + len = 0; + response.handle = kernel_handle; - + response.data = ptr_to_u64(data); + response.length = len; switch (tcode) { case TCODE_WRITE_QUADLET_REQUEST: case TCODE_WRITE_BLOCK_REQUEST: - type = RAW1394_ARM_WRITE; - in_length = length; response.rcode = RCODE_COMPLETE; response.length = 0; response.data = 0; @@ -810,11 +803,7 @@ handle_arm_request(raw1394handle_t handle, struct address_closure *ac, case TCODE_READ_QUADLET_REQUEST: case TCODE_READ_BLOCK_REQUEST: - type = RAW1394_ARM_READ; - in_length = 0; response.rcode = RCODE_COMPLETE; - response.length = length; - response.data = ptr_to_u64(allocation->data + pos); break; case TCODE_LOCK_REQUEST: @@ -829,84 +818,18 @@ handle_arm_request(raw1394handle_t handle, struct address_closure *ac, case TCODE_LOCK_BOUNDED_ADD: case TCODE_LOCK_WRAP_ADD: case TCODE_LOCK_VENDOR_DEPENDENT: - type = RAW1394_ARM_LOCK; - in_length = length; response.length = 4; break; - - default: - in_length = 0; - type = 0; - break; } - if (!(allocation->access_rights & type)) { - response.rcode = RCODE_TYPE_ERROR; - response.length = 0; - response.data = 0; - 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 + pos, data, length); - else if (type == RAW1394_ARM_LOCK) - /* FIXME: do lock ops here */; - - if (ioctl(fwhandle->ioctl_fd, - FW_CDEV_IOC_SEND_RESPONSE, &response) < 0) - return -1; - } - - /* - * libraw1394 clients do not expect requests from nodes on - * a card other than the one set by raw1394_set_port(). - */ - if (card != fwhandle->card) - return 0; - - if (!(allocation->notification_options & type)) - return 0; - - rrb = malloc(sizeof *rrb + in_length + response.length); - if (rrb == NULL) { - errno = ENOMEM; + if (ioctl(fwhandle->ioctl_fd, FW_CDEV_IOC_SEND_RESPONSE, &response) < 0) return -1; - } - - rrb->request_response.request = &rrb->request; - rrb->request_response.response = &rrb->response; - - rrb->request.destination_nodeid = fwhandle->reset.local_node_id; - rrb->request.source_nodeid = source_node_id; - rrb->request.destination_offset = offset; - rrb->request.tlabel = 0; - 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 = tcode - 0x10; - } - rrb->request.generation = fwhandle->reset.generation; - rrb->request.buffer_length = in_length; - rrb->request.buffer = rrb->data; - 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 + pos, response.length); - - retval = fwhandle->arm_tag_handler(handle, allocation->tag, type, - length, &rrb->request_response); - free(rrb); - return retval; + return 0; } int fw_arm_register(fw_handle_t handle, nodeaddr_t start, - size_t length, byte_t *initial_value, + size_t length, octlet_t arm_tag, arm_options_t access_rights, arm_options_t notification_options, arm_options_t client_transactions) @@ -915,26 +838,22 @@ fw_arm_register(fw_handle_t handle, nodeaddr_t start, struct allocation *allocation; int retval; - allocation = malloc(sizeof *allocation + length); + allocation = malloc(sizeof *allocation); if (allocation == NULL) { errno = ENOMEM; return -1; } - allocation->closure.callback = handle_arm_request; - allocation->buffer = initial_value; - allocation->tag = arm_tag; - allocation->access_rights = access_rights; - allocation->notification_options = notification_options; - allocation->client_transactions = client_transactions; - allocation->offset = start; - allocation->length = length; - if (initial_value != NULL) - memcpy(allocation->data, initial_value, length); + allocation->info.tag = arm_tag; + allocation->info.access_rights = access_rights; + allocation->info.notification_options = notification_options; + allocation->info.client_transactions = client_transactions; + allocation->info.offset = start; + allocation->info.length = length; request.offset = start; request.length = length; - request.closure = ptr_to_u64(&allocation->closure); + request.closure = ptr_to_u64(allocation); request.region_end = start + length; retval = ioctl(handle->ioctl_fd, FW_CDEV_IOC_ALLOCATE, &request); @@ -957,7 +876,7 @@ lookup_allocation(fw_handle_t handle, nodeaddr_t start, int delete) prev = &handle->allocations; for (a = handle->allocations; a != NULL; a = a->next) { - if (a->offset <= start && start < a->offset + a->length) + if (a->info.offset <= start && start < a->info.offset + a->info.length) break; prev = &a->next; } @@ -986,40 +905,6 @@ fw_arm_unregister(fw_handle_t handle, nodeaddr_t start) return ioctl(handle->ioctl_fd, FW_CDEV_IOC_DEALLOCATE, &request); } -int -fw_arm_set_buf(fw_handle_t handle, nodeaddr_t start, - size_t length, void *buf) -{ - struct allocation *allocation; - - allocation = lookup_allocation(handle, start, 0); - if (allocation == NULL) { - errno = ENOENT; - return -1; - } - - memcpy(allocation->data + allocation->offset - start, buf, length); - - return 0; -} - -int -fw_arm_get_buf(fw_handle_t handle, nodeaddr_t start, - size_t length, void *buf) -{ - struct allocation *allocation; - - allocation = lookup_allocation(handle, start, 0); - if (allocation == NULL) { - errno = ENOENT; - return -1; - } - - memcpy(buf, allocation->data + allocation->offset - start, length); - - return 0; -} - int fw_echo_request(fw_handle_t handle, quadlet_t data) { diff --git a/src/fw.h b/src/fw.h index 7ad5b97..2d7d90c 100644 --- a/src/fw.h +++ b/src/fw.h @@ -150,16 +150,14 @@ int fw_get_port_info(fw_handle_t handle, struct raw1394_portinfo *pinf, int maxports); int fw_set_port(fw_handle_t handle, int port); int fw_reset_bus_new(fw_handle_t handle, int type); +int fw_send_rw_response(fw_handle_t handle, int tcode, void *data, size_t len, + unsigned kernel_handle); int fw_arm_register(fw_handle_t handle, nodeaddr_t start, - size_t length, byte_t *initial_value, + size_t length, octlet_t arm_tag, arm_options_t access_rights, arm_options_t notification_options, arm_options_t client_transactions); int fw_arm_unregister(fw_handle_t handle, nodeaddr_t start); -int fw_arm_set_buf(fw_handle_t handle, nodeaddr_t start, - size_t length, void *buf); -int fw_arm_get_buf(fw_handle_t handle, nodeaddr_t start, - size_t length, void *buf); int fw_echo_request(fw_handle_t handle, quadlet_t data); int fw_wake_up(fw_handle_t handle); int fw_start_read(fw_handle_t handle, nodeid_t node, nodeaddr_t addr, diff --git a/src/raw1394.h b/src/raw1394.h index 7339311..e3027fd 100644 --- a/src/raw1394.h +++ b/src/raw1394.h @@ -705,9 +705,20 @@ typedef int (*tag_handler_t)(raw1394handle_t, unsigned long tag, tag_handler_t raw1394_set_tag_handler(raw1394handle_t handle, tag_handler_t new_h); -typedef int (*arm_tag_handler_t)(raw1394handle_t handle, unsigned long arm_tag, - byte_t request_type, - unsigned int requested_length, void *data); +typedef struct raw1394_arm_allocation_t { + octlet_t tag; + arm_options_t access_rights; + arm_options_t notification_options; + arm_options_t client_transactions; + nodeaddr_t offset; + size_t length; +} raw1394_arm_allocation_t; + +typedef int (*arm_tag_handler_t)( + raw1394handle_t handle, raw1394_arm_allocation_t *arm, + int tcode, unsigned long long offset, int source_node_id, + int card, unsigned kernel_handle, size_t length, void *data +); /** * raw1394_set_arm_tag_handler - set the async request handler @@ -718,11 +729,40 @@ typedef int (*arm_tag_handler_t)(raw1394handle_t handle, unsigned long arm_tag, * arrived. The default action is to call the arm_callback in the * raw1394_arm_reqhandle pointed to by arm_tag. * + * The program will not send requests for you. The kernel_handle and tcode must be + * passed to send_rw_response() along with the data to be sent. + * + * The handler must handle the reads and writes. It must also arrange to call + * send_rw_response(). It should be safe to call send_rw_response() from inside + * the loop. + * * Returns: old handler or NULL on failure (sets errno) **/ arm_tag_handler_t raw1394_set_arm_tag_handler(raw1394handle_t handle, arm_tag_handler_t new_h); +/** + * raw1394_send_rw_response - send response to ARM + * @handle: libraw1394 handle + * @tcode: tcode from ARM tag handler + * @data: data to send + * @len: length of data + * @kernel_handle: handle from ARM tag handler + * + * Send a response to a request packet. The packet may contain data if the + * request was a read request. + * + * The request can also be an error request if the tcode is changed to + * an error code. + * + * If no data should be send, set data = NULL. + * + * Returns: 0 on success or -1 on failure. + */ +int +raw1394_send_rw_response(raw1394handle_t handle, int tcode, void *data, + size_t len, unsigned kernel_handle); + typedef int (*fcp_handler_t)(raw1394handle_t, nodeid_t nodeid, int response, size_t length, unsigned char *data); @@ -779,8 +819,6 @@ struct raw1394_arm_reqhandle { * @handle: libraw1394 handle * @start: identifies address range * @length: identifies address range - * @initial_value: pointer to buffer containing (if necessary) initial value - * NULL means undefined * @arm_tag: identifier for arm_tag_handler * (usually pointer to raw1394_arm_reqhandle) * @access_rights: access-rights for registered address range handled @@ -803,7 +841,7 @@ struct raw1394_arm_reqhandle { * Returns: 0 on success or -1 on failure (sets errno) **/ int raw1394_arm_register(raw1394handle_t handle, nodeaddr_t start, - size_t length, byte_t *initial_value, + size_t length, octlet_t arm_tag, arm_options_t access_rights, arm_options_t notification_options, arm_options_t client_transactions);