- struct pending_request *req;
- struct host_info *hi;
- struct file_info *fi = NULL;
- struct list_head *entry;
- struct arm_addr *arm_addr = NULL;
- struct arm_request *arm_req = NULL;
- struct arm_response *arm_resp = NULL;
- int found=0, size=0, rcode=-1;
- struct arm_request_response *arm_req_resp = NULL;
-
- DBGMSG("arm_read called by node: %X"
- "addr: %4.4x %8.8x length: %Zu", nodeid,
- (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
- length);
- spin_lock(&host_info_lock);
- hi = find_host_info(host); /* search address-entry */
- if (hi != NULL) {
- list_for_each_entry(fi, &hi->file_info_list, list) {
- entry = fi->addr_list.next;
- while (entry != &(fi->addr_list)) {
- arm_addr = list_entry(entry, struct arm_addr, addr_list);
- if (((arm_addr->start) <= (addr)) &&
- ((arm_addr->end) >= (addr+length))) {
- found = 1;
- break;
- }
- entry = entry->next;
- }
- if (found) {
- break;
- }
- }
- }
- rcode = -1;
- if (!found) {
- printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found"
- " -> rcode_address_error\n");
- spin_unlock(&host_info_lock);
- return (RCODE_ADDRESS_ERROR);
- } else {
- DBGMSG("arm_read addr_entry FOUND");
- }
- if (arm_addr->rec_length < length) {
- DBGMSG("arm_read blocklength too big -> rcode_data_error");
- rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */
- }
- if (rcode == -1) {
- if (arm_addr->access_rights & ARM_READ) {
- if (!(arm_addr->client_transactions & ARM_READ)) {
- memcpy(buffer,(arm_addr->addr_space_buffer)+(addr-(arm_addr->start)),
- length);
- DBGMSG("arm_read -> (rcode_complete)");
- rcode = RCODE_COMPLETE;
- }
- } else {
- rcode = RCODE_TYPE_ERROR; /* function not allowed */
- DBGMSG("arm_read -> rcode_type_error (access denied)");
- }
- }
- if (arm_addr->notification_options & ARM_READ) {
- DBGMSG("arm_read -> entering notification-section");
- req = __alloc_pending_request(SLAB_ATOMIC);
- if (!req) {
- DBGMSG("arm_read -> rcode_conflict_error");
- spin_unlock(&host_info_lock);
- return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
- The request may be retried */
- }
- if (rcode == RCODE_COMPLETE) {
- size = sizeof(struct arm_request)+sizeof(struct arm_response) +
- length * sizeof(byte_t) +
- sizeof (struct arm_request_response);
- } else {
- size = sizeof(struct arm_request)+sizeof(struct arm_response) +
- sizeof (struct arm_request_response);
- }
- req->data = kmalloc(size, SLAB_ATOMIC);
- if (!(req->data)) {
- free_pending_request(req);
- DBGMSG("arm_read -> rcode_conflict_error");
- spin_unlock(&host_info_lock);
- return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
- The request may be retried */
- }
- req->free_data=1;
- req->file_info = fi;
- req->req.type = RAW1394_REQ_ARM;
- req->req.generation = get_hpsb_generation(host);
- req->req.misc = ( ((length << 16) & (0xFFFF0000)) | (ARM_READ & 0xFF));
- req->req.tag = arm_addr->arm_tag;
- req->req.recvb = arm_addr->recvb;
- req->req.length = size;
- arm_req_resp = (struct arm_request_response *) (req->data);
- arm_req = (struct arm_request *) ((byte_t *)(req->data) +
- (sizeof (struct arm_request_response)));
- arm_resp = (struct arm_response *) ((byte_t *)(arm_req) +
- (sizeof(struct arm_request)));
- arm_req->buffer = NULL;
- arm_resp->buffer = NULL;
- if (rcode == RCODE_COMPLETE) {
- byte_t *buf = (byte_t *)arm_resp + sizeof(struct arm_response);
- memcpy (buf,
- (arm_addr->addr_space_buffer)+(addr-(arm_addr->start)),
- length);
- arm_resp->buffer = int2ptr((arm_addr->recvb) +
- sizeof (struct arm_request_response) +
- sizeof (struct arm_request) +
- sizeof (struct arm_response));
- }
- arm_resp->buffer_length = (rcode == RCODE_COMPLETE) ? length : 0;
- arm_resp->response_code = rcode;
- arm_req->buffer_length = 0;
- arm_req->generation = req->req.generation;
- arm_req->extended_transaction_code = 0;
- arm_req->destination_offset = addr;
- arm_req->source_nodeid = nodeid;
- arm_req->destination_nodeid = host->node_id;
- arm_req->tlabel = (flags >> 10) & 0x3f;
- arm_req->tcode = (flags >> 4) & 0x0f;
- arm_req_resp->request = int2ptr((arm_addr->recvb) +
- sizeof (struct arm_request_response));
- arm_req_resp->response = int2ptr((arm_addr->recvb) +
- sizeof (struct arm_request_response) +
- sizeof (struct arm_request));
- queue_complete_req(req);
- }
- spin_unlock(&host_info_lock);
- return(rcode);
+ unsigned long irqflags;
+ struct pending_request *req;
+ struct host_info *hi;
+ struct file_info *fi = NULL;
+ struct list_head *entry;
+ struct arm_addr *arm_addr = NULL;
+ struct arm_request *arm_req = NULL;
+ struct arm_response *arm_resp = NULL;
+ int found = 0, size = 0, rcode = -1;
+ struct arm_request_response *arm_req_resp = NULL;
+
+ DBGMSG("arm_read called by node: %X"
+ "addr: %4.4x %8.8x length: %Zu", nodeid,
+ (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
+ length);
+ spin_lock_irqsave(&host_info_lock, irqflags);
+ hi = find_host_info(host); /* search address-entry */
+ if (hi != NULL) {
+ list_for_each_entry(fi, &hi->file_info_list, list) {
+ entry = fi->addr_list.next;
+ while (entry != &(fi->addr_list)) {
+ arm_addr =
+ list_entry(entry, struct arm_addr,
+ addr_list);
+ if (((arm_addr->start) <= (addr))
+ && ((arm_addr->end) >= (addr + length))) {
+ found = 1;
+ break;
+ }
+ entry = entry->next;
+ }
+ if (found) {
+ break;
+ }
+ }
+ }
+ rcode = -1;
+ if (!found) {
+ printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found"
+ " -> rcode_address_error\n");
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
+ return (RCODE_ADDRESS_ERROR);
+ } else {
+ DBGMSG("arm_read addr_entry FOUND");
+ }
+ if (arm_addr->rec_length < length) {
+ DBGMSG("arm_read blocklength too big -> rcode_data_error");
+ rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */
+ }
+ if (rcode == -1) {
+ if (arm_addr->access_rights & ARM_READ) {
+ if (!(arm_addr->client_transactions & ARM_READ)) {
+ memcpy(buffer,
+ (arm_addr->addr_space_buffer) + (addr -
+ (arm_addr->
+ start)),
+ length);
+ DBGMSG("arm_read -> (rcode_complete)");
+ rcode = RCODE_COMPLETE;
+ }
+ } else {
+ rcode = RCODE_TYPE_ERROR; /* function not allowed */
+ DBGMSG("arm_read -> rcode_type_error (access denied)");
+ }
+ }
+ if (arm_addr->notification_options & ARM_READ) {
+ DBGMSG("arm_read -> entering notification-section");
+ req = __alloc_pending_request(SLAB_ATOMIC);
+ if (!req) {
+ DBGMSG("arm_read -> rcode_conflict_error");
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
+ return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
+ The request may be retried */
+ }
+ if (rcode == RCODE_COMPLETE) {
+ size =
+ sizeof(struct arm_request) +
+ sizeof(struct arm_response) +
+ length * sizeof(byte_t) +
+ sizeof(struct arm_request_response);
+ } else {
+ size =
+ sizeof(struct arm_request) +
+ sizeof(struct arm_response) +
+ sizeof(struct arm_request_response);
+ }
+ req->data = kmalloc(size, SLAB_ATOMIC);
+ if (!(req->data)) {
+ free_pending_request(req);
+ DBGMSG("arm_read -> rcode_conflict_error");
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
+ return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
+ The request may be retried */
+ }
+ req->free_data = 1;
+ req->file_info = fi;
+ req->req.type = RAW1394_REQ_ARM;
+ req->req.generation = get_hpsb_generation(host);
+ req->req.misc =
+ (((length << 16) & (0xFFFF0000)) | (ARM_READ & 0xFF));
+ req->req.tag = arm_addr->arm_tag;
+ req->req.recvb = arm_addr->recvb;
+ req->req.length = size;
+ arm_req_resp = (struct arm_request_response *)(req->data);
+ arm_req = (struct arm_request *)((byte_t *) (req->data) +
+ (sizeof
+ (struct
+ arm_request_response)));
+ arm_resp =
+ (struct arm_response *)((byte_t *) (arm_req) +
+ (sizeof(struct arm_request)));
+ arm_req->buffer = NULL;
+ arm_resp->buffer = NULL;
+ if (rcode == RCODE_COMPLETE) {
+ byte_t *buf =
+ (byte_t *) arm_resp + sizeof(struct arm_response);
+ memcpy(buf,
+ (arm_addr->addr_space_buffer) + (addr -
+ (arm_addr->
+ start)),
+ length);
+ arm_resp->buffer =
+ int2ptr((arm_addr->recvb) +
+ sizeof(struct arm_request_response) +
+ sizeof(struct arm_request) +
+ sizeof(struct arm_response));
+ }
+ arm_resp->buffer_length =
+ (rcode == RCODE_COMPLETE) ? length : 0;
+ arm_resp->response_code = rcode;
+ arm_req->buffer_length = 0;
+ arm_req->generation = req->req.generation;
+ arm_req->extended_transaction_code = 0;
+ arm_req->destination_offset = addr;
+ arm_req->source_nodeid = nodeid;
+ arm_req->destination_nodeid = host->node_id;
+ arm_req->tlabel = (flags >> 10) & 0x3f;
+ arm_req->tcode = (flags >> 4) & 0x0f;
+ arm_req_resp->request = int2ptr((arm_addr->recvb) +
+ sizeof(struct
+ arm_request_response));
+ arm_req_resp->response =
+ int2ptr((arm_addr->recvb) +
+ sizeof(struct arm_request_response) +
+ sizeof(struct arm_request));
+ queue_complete_req(req);
+ }
+ spin_unlock_irqrestore(&host_info_lock, irqflags);
+ return (rcode);