📄 raw1394.c
字号:
vfree(addr->addr_space_buffer); kfree(addr); return (-EFAULT); } free_pending_request(req); /* immediate success or fail */ /* INSERT ENTRY */ spin_lock_irqsave(&host_info_lock, flags); list_add_tail(&addr->addr_list, &fi->addr_list); spin_unlock_irqrestore(&host_info_lock, flags); return sizeof(struct raw1394_request); } retval = hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops, req->req.address, req->req.address + req->req.length); if (retval) { /* INSERT ENTRY */ spin_lock_irqsave(&host_info_lock, flags); list_add_tail(&addr->addr_list, &fi->addr_list); spin_unlock_irqrestore(&host_info_lock, flags); } else { DBGMSG("arm_register failed errno: %d \n", retval); vfree(addr->addr_space_buffer); kfree(addr); return (-EALREADY); } free_pending_request(req); /* immediate success or fail */ return sizeof(struct raw1394_request);}static int arm_unregister(struct file_info *fi, struct pending_request *req){ int found = 0; int retval = 0; struct list_head *entry; struct arm_addr *addr = NULL; struct host_info *hi; struct file_info *fi_hlp = NULL; struct arm_addr *arm_addr = NULL; int another_host; unsigned long flags; DBGMSG("arm_Unregister called addr(Offset): " "%8.8x %8.8x", (u32) ((req->req.address >> 32) & 0xFFFF), (u32) (req->req.address & 0xFFFFFFFF)); spin_lock_irqsave(&host_info_lock, flags); /* get addr */ entry = fi->addr_list.next; while (entry != &(fi->addr_list)) { addr = list_entry(entry, struct arm_addr, addr_list); if (addr->start == req->req.address) { found = 1; break; } entry = entry->next; } if (!found) { DBGMSG("arm_Unregister addr not found"); spin_unlock_irqrestore(&host_info_lock, flags); return (-EINVAL); } DBGMSG("arm_Unregister addr found"); another_host = 0; /* another host with valid address-entry containing same addressrange */ list_for_each_entry(hi, &host_info_list, list) { if (hi->host != fi->host) { list_for_each_entry(fi_hlp, &hi->file_info_list, list) { entry = fi_hlp->addr_list.next; while (entry != &(fi_hlp->addr_list)) { arm_addr = list_entry(entry, struct arm_addr, addr_list); if (arm_addr->start == addr->start) { DBGMSG("another host ownes " "same addressrange"); another_host = 1; break; } entry = entry->next; } if (another_host) { break; } } } } if (another_host) { DBGMSG("delete entry from list -> success"); list_del(&addr->addr_list); spin_unlock_irqrestore(&host_info_lock, flags); vfree(addr->addr_space_buffer); kfree(addr); free_pending_request(req); /* immediate success or fail */ return sizeof(struct raw1394_request); } retval = hpsb_unregister_addrspace(&raw1394_highlevel, fi->host, addr->start); if (!retval) { printk(KERN_ERR "raw1394: arm_Unregister failed -> EINVAL\n"); spin_unlock_irqrestore(&host_info_lock, flags); return (-EINVAL); } DBGMSG("delete entry from list -> success"); list_del(&addr->addr_list); spin_unlock_irqrestore(&host_info_lock, flags); vfree(addr->addr_space_buffer); kfree(addr); free_pending_request(req); /* immediate success or fail */ return sizeof(struct raw1394_request);}/* Copy data from ARM buffer(s) to user buffer. */static int arm_get_buf(struct file_info *fi, struct pending_request *req){ struct arm_addr *arm_addr = NULL; unsigned long flags; unsigned long offset; struct list_head *entry; DBGMSG("arm_get_buf " "addr(Offset): %04X %08X length: %u", (u32) ((req->req.address >> 32) & 0xFFFF), (u32) (req->req.address & 0xFFFFFFFF), (u32) req->req.length); spin_lock_irqsave(&host_info_lock, flags); entry = fi->addr_list.next; while (entry != &(fi->addr_list)) { arm_addr = list_entry(entry, struct arm_addr, addr_list); if ((arm_addr->start <= req->req.address) && (arm_addr->end > req->req.address)) { if (req->req.address + req->req.length <= arm_addr->end) { offset = req->req.address - arm_addr->start; spin_unlock_irqrestore(&host_info_lock, flags); DBGMSG ("arm_get_buf copy_to_user( %08X, %p, %u )", (u32) req->req.recvb, arm_addr->addr_space_buffer + offset, (u32) req->req.length); if (copy_to_user (int2ptr(req->req.recvb), arm_addr->addr_space_buffer + offset, req->req.length)) return (-EFAULT); /* We have to free the request, because we * queue no response, and therefore nobody * will free it. */ free_pending_request(req); return sizeof(struct raw1394_request); } else { DBGMSG("arm_get_buf request exceeded mapping"); spin_unlock_irqrestore(&host_info_lock, flags); return (-EINVAL); } } entry = entry->next; } spin_unlock_irqrestore(&host_info_lock, flags); return (-EINVAL);}/* Copy data from user buffer to ARM buffer(s). */static int arm_set_buf(struct file_info *fi, struct pending_request *req){ struct arm_addr *arm_addr = NULL; unsigned long flags; unsigned long offset; struct list_head *entry; DBGMSG("arm_set_buf " "addr(Offset): %04X %08X length: %u", (u32) ((req->req.address >> 32) & 0xFFFF), (u32) (req->req.address & 0xFFFFFFFF), (u32) req->req.length); spin_lock_irqsave(&host_info_lock, flags); entry = fi->addr_list.next; while (entry != &(fi->addr_list)) { arm_addr = list_entry(entry, struct arm_addr, addr_list); if ((arm_addr->start <= req->req.address) && (arm_addr->end > req->req.address)) { if (req->req.address + req->req.length <= arm_addr->end) { offset = req->req.address - arm_addr->start; spin_unlock_irqrestore(&host_info_lock, flags); DBGMSG ("arm_set_buf copy_from_user( %p, %08X, %u )", arm_addr->addr_space_buffer + offset, (u32) req->req.sendb, (u32) req->req.length); if (copy_from_user (arm_addr->addr_space_buffer + offset, int2ptr(req->req.sendb), req->req.length)) return (-EFAULT); /* We have to free the request, because we * queue no response, and therefore nobody * will free it. */ free_pending_request(req); return sizeof(struct raw1394_request); } else { DBGMSG("arm_set_buf request exceeded mapping"); spin_unlock_irqrestore(&host_info_lock, flags); return (-EINVAL); } } entry = entry->next; } spin_unlock_irqrestore(&host_info_lock, flags); return (-EINVAL);}static int reset_notification(struct file_info *fi, struct pending_request *req){ DBGMSG("reset_notification called - switch %s ", (req->req.misc == RAW1394_NOTIFY_OFF) ? "OFF" : "ON"); if ((req->req.misc == RAW1394_NOTIFY_OFF) || (req->req.misc == RAW1394_NOTIFY_ON)) { fi->notification = (u8) req->req.misc; free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ return sizeof(struct raw1394_request); } /* error EINVAL (22) invalid argument */ return (-EINVAL);}static int write_phypacket(struct file_info *fi, struct pending_request *req){ struct hpsb_packet *packet = NULL; int retval = 0; quadlet_t data; unsigned long flags; data = be32_to_cpu((u32) req->req.sendb); DBGMSG("write_phypacket called - quadlet 0x%8.8x ", data); packet = hpsb_make_phypacket(fi->host, data); if (!packet) return -ENOMEM; req->req.length = 0; req->packet = packet; hpsb_set_packet_complete_task(packet, (void (*)(void *))queue_complete_cb, req); spin_lock_irqsave(&fi->reqlists_lock, flags); list_add_tail(&req->list, &fi->req_pending); spin_unlock_irqrestore(&fi->reqlists_lock, flags); packet->generation = req->req.generation; retval = hpsb_send_packet(packet); DBGMSG("write_phypacket send_packet called => retval: %d ", retval); if (retval < 0) { req->req.error = RAW1394_ERROR_SEND_ERROR; req->req.length = 0; queue_complete_req(req); } return sizeof(struct raw1394_request);}static int get_config_rom(struct file_info *fi, struct pending_request *req){ int ret = sizeof(struct raw1394_request); quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL); int status; if (!data) return -ENOMEM; status = csr1212_read(fi->host->csr.rom, CSR1212_CONFIG_ROM_SPACE_OFFSET, data, req->req.length); if (copy_to_user(int2ptr(req->req.recvb), data, req->req.length)) ret = -EFAULT; if (copy_to_user (int2ptr(req->req.tag), &fi->host->csr.rom->cache_head->len, sizeof(fi->host->csr.rom->cache_head->len))) ret = -EFAULT; if (copy_to_user(int2ptr(req->req.address), &fi->host->csr.generation, sizeof(fi->host->csr.generation))) ret = -EFAULT; if (copy_to_user(int2ptr(req->req.sendb), &status, sizeof(status))) ret = -EFAULT; kfree(data); if (ret >= 0) { free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ } return ret;}static int update_config_rom(struct file_info *fi, struct pending_request *req){ int ret = sizeof(struct raw1394_request); quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL); if (!data) return -ENOMEM; if (copy_from_user(data, int2ptr(req->req.sendb), req->req.length)) { ret = -EFAULT; } else { int status = hpsb_update_config_rom(fi->host, data, req->req.length, (unsigned char)req->req. misc); if (copy_to_user (int2ptr(req->req.recvb), &status, sizeof(status))) ret = -ENOMEM; } kfree(data); if (ret >= 0) { free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ fi->cfgrom_upd = 1; } return ret;}static int modify_config_rom(struct file_info *fi, struct pending_request *req){ struct csr1212_keyval *kv; struct csr1212_csr_rom_cache *cache; struct csr1212_dentry *dentry; u32 dr; int ret = 0; if (req->req.misc == ~0) { if (req->req.length == 0) return -EINVAL; /* Find an unused slot */ for (dr = 0; dr < RAW1394_MAX_USER_CSR_DIRS && fi->csr1212_dirs[dr]; dr++) ; if (dr == RAW1394_MAX_USER_CSR_DIRS) return -ENOMEM; fi->csr1212_dirs[dr] = csr1212_new_directory(CSR1212_KV_ID_VENDOR); if (!fi->csr1212_dirs[dr]) return -ENOMEM; } else { dr = req->req.misc; if (!fi->csr1212_dirs[dr]) return -EINVAL; /* Delete old stuff */ for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head; dentry; dentry = dentry->next) { csr1212_detach_keyval_from_directory(fi->host->csr.rom-> root_kv, dentry->kv); } if (req->req.length == 0) { csr1212_release_keyval(fi->csr1212_dirs[dr]); fi->csr1212_dirs[dr] = NULL; hpsb_update_config_rom_image(fi->host); free_pending_request(req); return sizeof(struct raw1394_request); } } cache = csr1212_rom_cache_malloc(0, req->req.length); if (!cache) { csr1212_release_keyval(fi->csr1212_dirs[dr]); fi->csr1212_dirs[dr] = NULL; return -ENOMEM; } cache->filled_head = kmalloc(sizeof(*cache->filled_head), GFP_KERNEL); if (!cache->filled_head) { csr1212_release_keyval(fi->csr1212_dirs[dr]); fi->csr1212_dirs[dr] = NULL; CSR1212_FREE(cache); return -ENOMEM; } cache->filled_tail = cache->filled_head; if (copy_from_user(cache->data, int2ptr(req->req.sendb), req->req.length)) { csr1212_release_keyval(fi->csr1212_dirs[dr]); fi->csr1212_dirs[dr] = NULL; ret = -EFAULT; } else { cache->len = req->req.length; cache->filled_head->offset_start = 0; cache->filled_head->offset_end = cache->size - 1; cache->layout_head = cache->layout_tail = fi->csr1212_dirs[dr]; ret = CSR1212_SUCCESS; /* parse all the items */ for (kv = cache->layout_head; ret == CSR1212_SUCCESS && kv; kv = kv->next) { ret = csr1212_parse_keyval(kv, cache); } /* attach top level items to the root directory */ for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head; ret == CSR1212_SUCCESS && dentry; dentry = dentry->next) { ret = csr1212_attach_keyval_to_directory(fi->host->csr. rom->root_kv, dentry->kv); } if (ret == CSR1212_SUCCESS) { ret = hpsb_update_config_rom_image(fi->host); if (ret >= 0 && copy_to_user(int2ptr(req->req.recvb), &dr, sizeof(dr))) { ret = -ENOMEM; } } } kfree(cache->filled_head); CSR1212_FREE(cache); if (ret >= 0) { /* we have to free the request, because we queue no response, * and therefore nobody will free it */ free_pending_request(req); return sizeof(struct raw1394_request); } else { for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head; dentry; dentry = dentry->next) { csr1212_detach_keyval_from_directory(fi->host->csr.rom-> root_kv, dentry->kv); } csr1212_release_keyval(fi->csr1212_dirs[dr]); fi->csr1212_dirs[dr] = NULL; return ret; }}static int state_connected(struct file_info *fi, struct pending_request *req){ int node = req->req.address >> 48; req->req.error = RAW1394_ERROR_NONE; switch (req->req.type) { case RAW1394_REQ_ECHO: queue_complete_req(req); return sizeof(struct raw1394_request); case RAW1394_REQ_ISO_SEND: print_old_iso_deprecation(); return handle_iso_send(fi, req, node); case RAW1394_REQ_ARM_REGISTER: return arm_register(fi, req); case RAW1394_REQ_AR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -