⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 raw1394.c

📁 ieee1394驱动,不多说了!直接可以在linux2.6内核中使用
💻 C
📖 第 1 页 / 共 5 页
字号:
			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 + -