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

📄 raw1394.c

📁 ieee1394驱动,不多说了!直接可以在linux2.6内核中使用
💻 C
📖 第 1 页 / 共 5 页
字号:
	    P(error) ||	    P(misc) ||	    P(generation) ||	    P(length) ||	    P(address) ||	    P(tag) ||	    P(sendb) ||	    P(recvb))		return -EFAULT;	return sizeof(struct compat_raw1394_req);}#undef P#endif/* get next completed request  (caller must hold fi->reqlists_lock) */static inline struct pending_request *__next_complete_req(struct file_info *fi){	struct list_head *lh;	struct pending_request *req = NULL;	if (!list_empty(&fi->req_complete)) {		lh = fi->req_complete.next;		list_del(lh);		req = list_entry(lh, struct pending_request, list);	}	return req;}/* atomically get next completed request */static struct pending_request *next_complete_req(struct file_info *fi){	unsigned long flags;	struct pending_request *req;	spin_lock_irqsave(&fi->reqlists_lock, flags);	req = __next_complete_req(fi);	spin_unlock_irqrestore(&fi->reqlists_lock, flags);	return req;}static ssize_t raw1394_read(struct file *file, char __user * buffer,			    size_t count, loff_t * offset_is_ignored){	struct file_info *fi = (struct file_info *)file->private_data;	struct pending_request *req;	ssize_t ret;#ifdef CONFIG_COMPAT	if (count == sizeof(struct compat_raw1394_req)) {		/* ok */	} else#endif	if (count != sizeof(struct raw1394_request)) {		return -EINVAL;	}	if (!access_ok(VERIFY_WRITE, buffer, count)) {		return -EFAULT;	}	if (file->f_flags & O_NONBLOCK) {		if (!(req = next_complete_req(fi)))			return -EAGAIN;	} else {		/*		 * NB: We call the macro wait_event_interruptible() with a		 * condition argument with side effect.  This is only possible		 * because the side effect does not occur until the condition		 * became true, and wait_event_interruptible() won't evaluate		 * the condition again after that.		 */		if (wait_event_interruptible(fi->wait_complete,					     (req = next_complete_req(fi))))			return -ERESTARTSYS;	}	if (req->req.length) {		if (copy_to_user(int2ptr(req->req.recvb), req->data,				 req->req.length)) {			req->req.error = RAW1394_ERROR_MEMFAULT;		}	}#ifdef CONFIG_COMPAT	if (count == sizeof(struct compat_raw1394_req) &&   	    sizeof(struct compat_raw1394_req) !=			sizeof(struct raw1394_request)) {		ret = raw1394_compat_read(buffer, &req->req);	} else#endif	{		if (copy_to_user(buffer, &req->req, sizeof(req->req))) {			ret = -EFAULT;			goto out;		}		ret = (ssize_t) sizeof(struct raw1394_request);	}      out:	free_pending_request(req);	return ret;}static int state_opened(struct file_info *fi, struct pending_request *req){	if (req->req.type == RAW1394_REQ_INITIALIZE) {		switch (req->req.misc) {		case RAW1394_KERNELAPI_VERSION:		case 3:			fi->state = initialized;			fi->protocol_version = req->req.misc;			req->req.error = RAW1394_ERROR_NONE;			req->req.generation = atomic_read(&internal_generation);			break;		default:			req->req.error = RAW1394_ERROR_COMPAT;			req->req.misc = RAW1394_KERNELAPI_VERSION;		}	} else {		req->req.error = RAW1394_ERROR_STATE_ORDER;	}	req->req.length = 0;	queue_complete_req(req);	return sizeof(struct raw1394_request);}static int state_initialized(struct file_info *fi, struct pending_request *req){	unsigned long flags;	struct host_info *hi;	struct raw1394_khost_list *khl;	if (req->req.generation != atomic_read(&internal_generation)) {		req->req.error = RAW1394_ERROR_GENERATION;		req->req.generation = atomic_read(&internal_generation);		req->req.length = 0;		queue_complete_req(req);		return sizeof(struct raw1394_request);	}	switch (req->req.type) {	case RAW1394_REQ_LIST_CARDS:		spin_lock_irqsave(&host_info_lock, flags);		khl = kmalloc(sizeof(*khl) * host_count, GFP_ATOMIC);		if (khl) {			req->req.misc = host_count;			req->data = (quadlet_t *) khl;			list_for_each_entry(hi, &host_info_list, list) {				khl->nodes = hi->host->node_count;				strcpy(khl->name, hi->host->driver->name);				khl++;			}		}		spin_unlock_irqrestore(&host_info_lock, flags);		if (khl) {			req->req.error = RAW1394_ERROR_NONE;			req->req.length = min(req->req.length,					      (u32) (sizeof						     (struct raw1394_khost_list)						     * req->req.misc));			req->free_data = 1;		} else {			return -ENOMEM;		}		break;	case RAW1394_REQ_SET_CARD:		spin_lock_irqsave(&host_info_lock, flags);		if (req->req.misc >= host_count) {			req->req.error = RAW1394_ERROR_INVALID_ARG;			goto out_set_card;		}		list_for_each_entry(hi, &host_info_list, list)			if (!req->req.misc--)				break;		get_device(&hi->host->device); /* FIXME handle failure case */		list_add_tail(&fi->list, &hi->file_info_list);		/* prevent unloading of the host's low-level driver */		if (!try_module_get(hi->host->driver->owner)) {			req->req.error = RAW1394_ERROR_ABORTED;			goto out_set_card;		}		WARN_ON(fi->host);		fi->host = hi->host;		fi->state = connected;		req->req.error = RAW1394_ERROR_NONE;		req->req.generation = get_hpsb_generation(fi->host);		req->req.misc = (fi->host->node_id << 16)				| fi->host->node_count;		if (fi->protocol_version > 3)			req->req.misc |= NODEID_TO_NODE(fi->host->irm_id) << 8;out_set_card:		spin_unlock_irqrestore(&host_info_lock, flags);		req->req.length = 0;		break;	default:		req->req.error = RAW1394_ERROR_STATE_ORDER;		req->req.length = 0;		break;	}	queue_complete_req(req);	return sizeof(struct raw1394_request);}static void handle_iso_listen(struct file_info *fi, struct pending_request *req){	int channel = req->req.misc;	if ((channel > 63) || (channel < -64)) {		req->req.error = RAW1394_ERROR_INVALID_ARG;	} else if (channel >= 0) {		/* allocate channel req.misc */		if (fi->listen_channels & (1ULL << channel)) {			req->req.error = RAW1394_ERROR_ALREADY;		} else {			if (hpsb_listen_channel			    (&raw1394_highlevel, fi->host, channel)) {				req->req.error = RAW1394_ERROR_ALREADY;			} else {				fi->listen_channels |= 1ULL << channel;				fi->iso_buffer = int2ptr(req->req.recvb);				fi->iso_buffer_length = req->req.length;			}		}	} else {		/* deallocate channel (one's complement neg) req.misc */		channel = ~channel;		if (fi->listen_channels & (1ULL << channel)) {			hpsb_unlisten_channel(&raw1394_highlevel, fi->host,					      channel);			fi->listen_channels &= ~(1ULL << channel);		} else {			req->req.error = RAW1394_ERROR_INVALID_ARG;		}	}	req->req.length = 0;	queue_complete_req(req);}static void handle_fcp_listen(struct file_info *fi, struct pending_request *req){	if (req->req.misc) {		if (fi->fcp_buffer) {			req->req.error = RAW1394_ERROR_ALREADY;		} else {			fi->fcp_buffer = int2ptr(req->req.recvb);		}	} else {		if (!fi->fcp_buffer) {			req->req.error = RAW1394_ERROR_ALREADY;		} else {			fi->fcp_buffer = NULL;		}	}	req->req.length = 0;	queue_complete_req(req);}static int handle_async_request(struct file_info *fi,				struct pending_request *req, int node){	unsigned long flags;	struct hpsb_packet *packet = NULL;	u64 addr = req->req.address & 0xffffffffffffULL;	switch (req->req.type) {	case RAW1394_REQ_ASYNC_READ:		DBGMSG("read_request called");		packet =		    hpsb_make_readpacket(fi->host, node, addr, req->req.length);		if (!packet)			return -ENOMEM;		if (req->req.length == 4)			req->data = &packet->header[3];		else			req->data = packet->data;		break;	case RAW1394_REQ_ASYNC_WRITE:		DBGMSG("write_request called");		packet = hpsb_make_writepacket(fi->host, node, addr, NULL,					       req->req.length);		if (!packet)			return -ENOMEM;		if (req->req.length == 4) {			if (copy_from_user			    (&packet->header[3], int2ptr(req->req.sendb),			     req->req.length))				req->req.error = RAW1394_ERROR_MEMFAULT;		} else {			if (copy_from_user			    (packet->data, int2ptr(req->req.sendb),			     req->req.length))				req->req.error = RAW1394_ERROR_MEMFAULT;		}		req->req.length = 0;		break;	case RAW1394_REQ_ASYNC_STREAM:		DBGMSG("stream_request called");		packet =		    hpsb_make_streampacket(fi->host, NULL, req->req.length,					   node & 0x3f /*channel */ ,					   (req->req.misc >> 16) & 0x3,					   req->req.misc & 0xf);		if (!packet)			return -ENOMEM;		if (copy_from_user(packet->data, int2ptr(req->req.sendb),				   req->req.length))			req->req.error = RAW1394_ERROR_MEMFAULT;		req->req.length = 0;		break;	case RAW1394_REQ_LOCK:		DBGMSG("lock_request called");		if ((req->req.misc == EXTCODE_FETCH_ADD)		    || (req->req.misc == EXTCODE_LITTLE_ADD)) {			if (req->req.length != 4) {				req->req.error = RAW1394_ERROR_INVALID_ARG;				break;			}		} else {			if (req->req.length != 8) {				req->req.error = RAW1394_ERROR_INVALID_ARG;				break;			}		}		packet = hpsb_make_lockpacket(fi->host, node, addr,					      req->req.misc, NULL, 0);		if (!packet)			return -ENOMEM;		if (copy_from_user(packet->data, int2ptr(req->req.sendb),				   req->req.length)) {			req->req.error = RAW1394_ERROR_MEMFAULT;			break;		}		req->data = packet->data;		req->req.length = 4;		break;	case RAW1394_REQ_LOCK64:		DBGMSG("lock64_request called");		if ((req->req.misc == EXTCODE_FETCH_ADD)		    || (req->req.misc == EXTCODE_LITTLE_ADD)) {			if (req->req.length != 8) {				req->req.error = RAW1394_ERROR_INVALID_ARG;				break;			}		} else {			if (req->req.length != 16) {				req->req.error = RAW1394_ERROR_INVALID_ARG;				break;			}		}		packet = hpsb_make_lock64packet(fi->host, node, addr,						req->req.misc, NULL, 0);		if (!packet)			return -ENOMEM;		if (copy_from_user(packet->data, int2ptr(req->req.sendb),				   req->req.length)) {			req->req.error = RAW1394_ERROR_MEMFAULT;			break;		}		req->data = packet->data;		req->req.length = 8;		break;	default:		req->req.error = RAW1394_ERROR_STATE_ORDER;	}	req->packet = packet;	if (req->req.error) {		req->req.length = 0;		queue_complete_req(req);		return sizeof(struct raw1394_request);	}	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;	if (hpsb_send_packet(packet) < 0) {		req->req.error = RAW1394_ERROR_SEND_ERROR;		req->req.length = 0;		hpsb_free_tlabel(packet);		queue_complete_req(req);	}	return sizeof(struct raw1394_request);}static int handle_iso_send(struct file_info *fi, struct pending_request *req,			   int channel){	unsigned long flags;	struct hpsb_packet *packet;	packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f,				     (req->req.misc >> 16) & 0x3,				     req->req.misc & 0xf);	if (!packet)		return -ENOMEM;	packet->speed_code = req->req.address & 0x3;	req->packet = packet;	if (copy_from_user(packet->data, int2ptr(req->req.sendb),			   req->req.length)) {		req->req.error = RAW1394_ERROR_MEMFAULT;		req->req.length = 0;		queue_complete_req(req);		return sizeof(struct raw1394_request);	}	req->req.length = 0;	hpsb_set_packet_complete_task(packet,				      (void (*)(void *))queue_complete_req,				      req);	spin_lock_irqsave(&fi->reqlists_lock, flags);	list_add_tail(&req->list, &fi->req_pending);	spin_unlock_irqrestore(&fi->reqlists_lock, flags);	/* Update the generation of the packet just before sending. */	packet->generation = req->req.generation;	if (hpsb_send_packet(packet) < 0) {		req->req.error = RAW1394_ERROR_SEND_ERROR;		queue_complete_req(req);	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -