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

📄 raw1394.c

📁 1394在linux下单独的驱动程序代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		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){	size_t return_size;	unsigned char rom_version;	int ret=sizeof(struct raw1394_request);	quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL);	int status;	if (!data) return -ENOMEM;	status = hpsb_get_config_rom(fi->host, data, 		req->req.length, &return_size, &rom_version);	if (copy_to_user(int2ptr(req->req.recvb), data, 		req->req.length))		ret = -EFAULT;	if (copy_to_user(int2ptr(req->req.tag), &return_size, 		sizeof(return_size)))		ret = -EFAULT;	if (copy_to_user(int2ptr(req->req.address), &rom_version, 		sizeof(rom_version)))		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, SLAB_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 */	}	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:		return handle_iso_send(fi, req, node);			case RAW1394_REQ_ARM_REGISTER:		return arm_register(fi, req);			case RAW1394_REQ_ARM_UNREGISTER:		return arm_unregister(fi, req);			case RAW1394_REQ_RESET_NOTIFY:		return reset_notification(fi, req);			case RAW1394_REQ_ISO_LISTEN:		handle_iso_listen(fi, req);		return sizeof(struct raw1394_request);			case RAW1394_REQ_FCP_LISTEN:		handle_fcp_listen(fi, req);		return sizeof(struct raw1394_request);			case RAW1394_REQ_RESET_BUS:		if (req->req.misc == RAW1394_LONG_RESET) {			DBGMSG("busreset called (type: LONG)");			hpsb_reset_bus(fi->host, LONG_RESET);			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);		}		if (req->req.misc == RAW1394_SHORT_RESET) {			DBGMSG("busreset called (type: SHORT)");			hpsb_reset_bus(fi->host, SHORT_RESET);			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);	case RAW1394_REQ_GET_ROM:		return get_config_rom(fi, req);			case RAW1394_REQ_UPDATE_ROM:		return update_config_rom(fi, req);	}		if (req->req.generation != get_hpsb_generation(fi->host)) {		req->req.error = RAW1394_ERROR_GENERATION;		req->req.generation = get_hpsb_generation(fi->host);		req->req.length = 0;		queue_complete_req(req);		return sizeof(struct raw1394_request);	}		switch (req->req.type) {	case RAW1394_REQ_PHYPACKET:		return write_phypacket(fi, req);	case RAW1394_REQ_ASYNC_SEND:		return handle_async_send(fi, req);	}		if (req->req.length == 0) {		req->req.error = RAW1394_ERROR_INVALID_ARG;		queue_complete_req(req);		return sizeof(struct raw1394_request);	}		return handle_async_request(fi, req, node);}static ssize_t raw1394_write(struct file *file, const char *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 retval = 0;		if (count != sizeof(struct raw1394_request)) {		return -EINVAL;	}		req = alloc_pending_request();	if (req == NULL) {		return -ENOMEM;	}	req->file_info = fi;		if (copy_from_user(&req->req, buffer, sizeof(struct raw1394_request))) {		free_pending_request(req);		return -EFAULT;	}		switch (fi->state) {	case opened:		retval = state_opened(fi, req);		break;			case initialized:		retval = state_initialized(fi, req);		break;			case connected:		retval = state_connected(fi, req);		break;	}		if (retval < 0) {		free_pending_request(req);	}		return retval;}/* rawiso operations *//* check if any RAW1394_REQ_RAWISO_ACTIVITY event is already in the* completion queue (reqlists_lock must be taken) */static inline int __rawiso_event_in_queue(struct file_info *fi){	struct list_head *lh;	struct pending_request *req;		list_for_each(lh, &fi->req_complete) {		req = list_entry(lh, struct pending_request, list);		if (req->req.type == RAW1394_REQ_RAWISO_ACTIVITY) {			return 1;		}	}		return 0;}/* put a RAWISO_ACTIVITY event in the queue, if one isn't there already */static void queue_rawiso_event(struct file_info *fi){	unsigned long flags;		spin_lock_irqsave(&fi->reqlists_lock, flags);		/* only one ISO activity event may be in the queue */	if (!__rawiso_event_in_queue(fi)) {		struct pending_request *req = __alloc_pending_request(SLAB_ATOMIC);				if (req) {			req->file_info = fi;			req->req.type = RAW1394_REQ_RAWISO_ACTIVITY;			req->req.generation = get_hpsb_generation(fi->host);			__queue_complete_req(req);		} else {			/* on allocation failure, signal an overflow */			if (fi->iso_handle) {				atomic_inc(&fi->iso_handle->overflows);			}		}	}	spin_unlock_irqrestore(&fi->reqlists_lock, flags);}static void rawiso_activity_cb(struct hpsb_iso *iso){	unsigned long flags;	struct list_head *lh;	struct host_info *hi;		spin_lock_irqsave(&host_info_lock, flags);	hi = find_host_info(iso->host);		if (hi != NULL) {		list_for_each(lh, &hi->file_info_list) {			struct file_info *fi = list_entry(lh, struct file_info, list);			if (fi->iso_handle == iso)				queue_rawiso_event(fi);		}	}		spin_unlock_irqrestore(&host_info_lock, flags);}/* helper function - gather all the kernel iso status bits for returning to user-space */static void raw1394_iso_fill_status(struct hpsb_iso *iso, struct raw1394_iso_status *stat){	stat->config.data_buf_size = iso->buf_size;	stat->config.buf_packets = iso->buf_packets;	stat->config.channel = iso->channel;	stat->config.speed = iso->speed;	stat->config.irq_interval = iso->irq_interval;	stat->n_packets = hpsb_iso_n_ready(iso);	stat->overflows = atomic_read(&iso->overflows);	stat->xmit_cycle = iso->xmit_cycle;}static int raw1394_iso_xmit_init(struct file_info *fi, void *uaddr){	struct raw1394_iso_status stat;		if (!fi->host)		return -EINVAL;		if (copy_from_user(&stat, uaddr, sizeof(stat)))		return -EFAULT;		fi->iso_handle = hpsb_iso_xmit_init(fi->host,		stat.config.data_buf_size,		stat.config.buf_packets,		stat.config.channel,		stat.config.speed,		stat.config.irq_interval,		rawiso_activity_cb);	if (!fi->iso_handle)		return -ENOMEM;		fi->iso_state = RAW1394_ISO_XMIT;		raw1394_iso_fill_status(fi->iso_handle, &stat);	if (copy_to_user(uaddr, &stat, sizeof(stat)))		return -EFAULT;		/* queue an event to get things started */	rawiso_activity_cb(fi->iso_handle);		return 0;}static int raw1394_iso_recv_init(struct file_info *fi, void *uaddr){	struct raw1394_iso_status stat;		if (!fi->host)		return -EINVAL;		if (copy_from_user(&stat, uaddr, sizeof(stat)))		return -EFAULT;		fi->iso_handle = hpsb_iso_recv_init(fi->host,		stat.config.data_buf_size,		stat.config.buf_packets,		stat.config.channel,		stat.config.irq_interval,		rawiso_activity_cb);	if (!fi->iso_handle)		return -ENOMEM;		fi->iso_state = RAW1394_ISO_RECV;		raw1394_iso_fill_status(fi->iso_handle, &stat);	if (copy_to_user(uaddr, &stat, sizeof(stat)))		return -EFAULT;	return 0;}static int raw1394_iso_get_status(struct file_info *fi, void *uaddr){	struct raw1394_iso_status stat;	struct hpsb_iso *iso = fi->iso_handle;		raw1394_iso_fill_status(fi->iso_handle, &stat);	if (copy_to_user(uaddr, &stat, sizeof(stat)))		return -EFAULT;		/* reset overflow counter */	atomic_set(&iso->overflows, 0);		return 0;}/* copy N packet_infos out of the ringbuffer into user-supplied array */static int raw1394_iso_recv_packets(struct file_info *fi, void *uaddr){	struct raw1394_iso_packets upackets;	unsigned int packet = fi->iso_handle->first_packet;	int i;		if (copy_from_user(&upackets, uaddr, sizeof(upackets)))		return -EFAULT;		if (upackets.n_packets > hpsb_iso_n_ready(fi->iso_handle))		return -EINVAL;		/* ensure user-supplied buffer is accessible and big enough */	if (verify_area(VERIFY_WRITE, upackets.infos,		upackets.n_packets * sizeof(struct raw1394_iso_packet_info)))		return -EFAULT;		/* copy the packet_infos out */	for (i = 0; i < upackets.n_packets; i++) {		if (__copy_to_user(&upackets.infos[i],			&fi->iso_handle->infos[packet],			sizeof(struct raw1394_iso_packet_info)))			return -EFAULT;				packet = (packet + 1) % fi->iso_handle->buf_packets;	}		return 0;}/* copy N packet_infos from user to ringbuffer, and queue them for transmission */static int raw1394_iso_send_packets(struct file_info *fi, void *uaddr){	struct raw1394_iso_packets upackets;	int i, rv;		if (copy_from_user(&upackets, uaddr, sizeof(upackets)))		return -EFAULT;		if (upackets.n_packets > hpsb_iso_n_ready(fi->iso_handle))		return -EINVAL;		/* ensure user-supplied buffer is accessible and big enough */	if (verify_area(VERIFY_READ, upackets.infos,		upackets.n_packets * sizeof(struct raw1394_iso_packet_info)))		return -EFAULT;		/* copy the infos structs in and queue the packets */	for (i = 0; i < upackets.n_packets; i++) {		struct raw1394_iso_packet_info info;				if (__copy_from_user(&info, &upackets.infos[i],			sizeof(struct raw1394_iso_packet_info)))			return -EFAULT;				rv = hpsb_iso_xmit_queue_packet(fi->iso_handle, info.offset,			info.len, info.tag, info.sy);		if (rv)			return rv;	}		return 0;}static void raw1394_iso_shutdown(struct file_info *fi){	if (fi->iso_handle)		hpsb_iso_shutdown(fi->iso_handle);		fi->iso_handle = NULL;	fi->iso_state = RAW1394_ISO_INACTIVE;}/* mmap the rawiso xmit/recv buffer */static int raw1394_mmap(struct file *file, struct vm_area_struct *vma){	struct file_info *fi = file->private_data;		if (fi->iso_state == RAW1394_ISO_INACTIVE)		return -EINVAL;		return dma_region_mmap(&fi->iso_handle->data_buf, file, vma);}/* ioctl is only used for rawiso operations */static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	struct file_info *fi = file->private_data;		switch(fi->iso_state) {	case RAW1394_ISO_INACTIVE:		switch(cmd) {		case RAW1394_IOC_ISO_XMIT_INIT:			return raw1394_iso_xmit_init(fi, (void*) arg);		case RAW1394_IOC_ISO_RECV_INIT:			return raw1394_iso_recv_init(fi, (void*) arg);		default:			break;		}		break;		case RAW1394_ISO_RECV:			switch(cmd) {			case RAW1394_IOC_ISO_RECV_START: {				/* copy args from user-space */				int args[3];				if (copy_from_user(&args[0], (void*) arg, sizeof(args)))					return -EFAULT;				return hpsb_iso_recv_start(fi->iso_handle, args[0], args[1], args[2]);											 }			case RAW1394_IOC_ISO_XMIT_RECV_STOP:				hpsb_iso_stop(fi->iso_handle);				return 0;			case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:				return hpsb_iso_recv_listen_channel(fi->iso_handle, arg);			case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:				return hpsb_iso_recv_unlisten_channel(fi->iso_handle, arg);			case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK: {				/* copy the u64 from user-space */				u64 mask;				if (copy_from_user(&mask, (void*) arg, sizeof(mask)))					return -EFAULT;				return hpsb_iso_recv_set_channel_mask(fi->iso_handle, mask);														}			case RAW1394_IOC_ISO_GET_STATUS:				return raw1394_iso_get_st

⌨️ 快捷键说明

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