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

📄 dv1394.c

📁 这个是uClinux下的ieee1394驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
		add_wait_queue(&video->waitq, &wait);		set_current_state(TASK_INTERRUPTIBLE);				spin_lock_irqsave(&video->spinlock, flags);		while(video->n_clear_frames < n_wait) {						spin_unlock_irqrestore(&video->spinlock, flags);								if(signal_pending(current)) {				remove_wait_queue(&video->waitq, &wait);				set_current_state(TASK_RUNNING);				ret = -EINTR;				goto out;			}			schedule();			set_current_state(TASK_INTERRUPTIBLE);						spin_lock_irqsave(&video->spinlock, flags);		}		spin_unlock_irqrestore(&video->spinlock, flags);		remove_wait_queue(&video->waitq, &wait);		set_current_state(TASK_RUNNING);		ret = 0;		break;	}	case DV1394_RECEIVE_FRAMES: {		unsigned int n_recv;		if( !video_card_initialized(video) ) {			ret = -EINVAL;			goto out;		}				n_recv = (unsigned int) arg;		/* at least one frame must be active */		if(n_recv > (video->n_frames-1) ) {			ret = -EINVAL;			goto out;		}					spin_lock_irqsave(&video->spinlock, flags);		/* release the clear frames */		video->n_clear_frames -= n_recv;		/* advance the clear frame cursor */		video->first_clear_frame = (video->first_clear_frame + n_recv) % video->n_frames;		/* reset dropped_frames */		video->dropped_frames = 0;					spin_unlock_irqrestore(&video->spinlock, flags);		ret = 0;		break;	}	case DV1394_START_RECEIVE: {		if( !video_card_initialized(video) ) {			ret = do_dv1394_init_default(video);			if(ret)				goto out;		}			receive_packets(video, video->frames[video->first_clear_frame]);		ret = 0;		break;	}	case DV1394_INIT: {		struct dv1394_init init;		if(arg == (unsigned long) NULL) {			ret = do_dv1394_init_default(video);		} else {			if(copy_from_user(&init, (void*)arg, sizeof(init))) {				ret = -EFAULT;				goto out;			}			ret = do_dv1394_init(video, &init);		}		break;	}	case DV1394_SHUTDOWN:		ret = do_dv1394_shutdown(video, 0);		break;        case DV1394_GET_STATUS: {		struct dv1394_status status;		if( !video_card_initialized(video) ) {			ret = -EINVAL;			goto out;		}		status.init.api_version = DV1394_API_VERSION;		status.init.channel = video->channel;		status.init.n_frames = video->n_frames;		status.init.format = video->pal_or_ntsc;		status.init.cip_n = video->cip_n;		status.init.cip_d = video->cip_d;		status.init.syt_offset = video->syt_offset;		status.first_clear_frame = video->first_clear_frame;		/* the rest of the fields need to be locked against the interrupt */		spin_lock_irqsave(&video->spinlock, flags);		status.active_frame = video->active_frame;		status.n_clear_frames = video->n_clear_frames;		status.dropped_frames = video->dropped_frames;		/* reset dropped_frames */		video->dropped_frames = 0;					spin_unlock_irqrestore(&video->spinlock, flags);		if(copy_to_user((void*)arg, &status, sizeof(status))) {			ret = -EFAULT;			goto out;		}		ret = 0;		break;	}	default:		break;	} out:	up(&video->sem);	return ret;}/*** DEVICE FILE INTERFACE CONTINUED ***************************************/static int dv1394_open(struct inode *inode, struct file *file){	struct video_card *video = NULL;	/* if the device was opened through devfs, then file->private_data	   has already been set to video by devfs */	if(file->private_data) {		video = (struct video_card*) file->private_data;			} else {		/* look up the card by ID */				struct list_head *lh;		unsigned long flags;				spin_lock_irqsave(&dv1394_cards_lock, flags);		if(!list_empty(&dv1394_cards)) {			struct video_card *p;			list_for_each(lh, &dv1394_cards) {				p = list_entry(lh, struct video_card, list);				if((p->id >> 2) == ieee1394_file_to_instance(file)) {					video = p;					break;				}			}		}		spin_unlock_irqrestore(&dv1394_cards_lock, flags);		if(!video) {			debug_printk("dv1394: OHCI card %d not found", ieee1394_file_to_instance(file));			return -ENODEV;		}				file->private_data = (void*) video;	}	#ifndef DV1394_ALLOW_MORE_THAN_ONE_OPEN	if( test_and_set_bit(0, &video->open) ) {		/* video is already open by someone else */		return -EBUSY; 	}#endif	return 0;}static int dv1394_release(struct inode *inode, struct file *file){	struct video_card *video = file_to_video_card(file);	/* OK to free the DMA buffer, no more mappings can exist */	do_dv1394_shutdown(video, 1);	/* clean up async I/O users */	dv1394_fasync(-1, file, 0);		/* give someone else a turn */	clear_bit(0, &video->open);	return 0;}/*** PROC_FS INTERFACE ******************************************************/#ifdef CONFIG_PROC_FSstatic LIST_HEAD(dv1394_procfs);struct dv1394_procfs_entry {	struct list_head list;    struct proc_dir_entry *procfs;	char name[32];	struct dv1394_procfs_entry *parent;};static spinlock_t dv1394_procfs_lock = SPIN_LOCK_UNLOCKED;static int dv1394_procfs_read( char *page, char **start, off_t off,			int count, int *eof, void *data){	struct video_card *video = (struct video_card*) data;	snprintf( page, count, 		"\format=%s\n\channel=%d\n\cip_n=%lu\n\cip_d=%lu\n\syt_offset=%u\n",		(video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"),		video->channel,		video->cip_n, video->cip_d, video->syt_offset );	return strlen(page);}/* lifted from the stallion.c driver */#undef  TOLOWER#define TOLOWER(x)      ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x))static unsigned long atol(char *str){	unsigned long   val;	int             base, c;	char            *sp;	val = 0;	sp = str;	if ((*sp == '0') && (*(sp+1) == 'x')) {		base = 16;		sp += 2;	} else if (*sp == '0') {		base = 8;		sp++;	} else {		base = 10;	}	for (; (*sp != 0); sp++) {		c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0');		if ((c < 0) || (c >= base)) {			printk(KERN_ERR "dv1394: atol() invalid argument %s\n", str);			val = 0;			break;		}		val = (val * base) + c;	}	return(val);}static int dv1394_procfs_write( struct file *file,			const char *buffer, unsigned long count, void *data){	int len = 0;	char new_value[65];	char *pos;	struct video_card *video = (struct video_card*) data;		if (count > 64)		len = 64;	else		len = count;					if (copy_from_user( new_value, buffer, len))		return -EFAULT;		new_value[len] = 0;	pos = strchr(new_value, '=');	if (pos != NULL) {		int val_len = len - (pos-new_value) - 1;		char buf[65];		memset(buf, 0, 65);		strncpy(buf, pos+1, val_len);		if (buf[val_len-1] == '\n') buf[val_len-1] = 0;				if (strnicmp( new_value, "format", (pos-new_value)) == 0) {			if (strnicmp( buf, "NTSC", val_len) == 0)				video->pal_or_ntsc = DV1394_NTSC;			else if (strnicmp( buf, "PAL", val_len) == 0)				video->pal_or_ntsc = DV1394_PAL;						} else if (strnicmp( new_value, "cip_n", (pos-new_value)) == 0) {			video->cip_n = atol(buf);		} else if (strnicmp( new_value, "cip_d", (pos-new_value)) == 0) {			video->cip_d = atol(buf);		} else if (strnicmp( new_value, "syt_offset", (pos-new_value)) == 0) {			video->syt_offset = atol(buf);		} else if (strnicmp( new_value, "channel", (pos-new_value)) == 0) {			video->channel = atol(buf);		}	}		return len;}struct dv1394_procfs_entry *dv1394_procfs_find( char *name){	struct list_head *lh;	struct dv1394_procfs_entry *p;			spin_lock( &dv1394_procfs_lock);	if(!list_empty(&dv1394_procfs)) {		list_for_each(lh, &dv1394_procfs) {			p = list_entry(lh, struct dv1394_procfs_entry, list);			if(!strncmp(p->name, name, sizeof(p->name))) {				spin_unlock( &dv1394_procfs_lock);				return p;			}		}	}	spin_unlock( &dv1394_procfs_lock);	return NULL;}static int dv1394_procfs_add_entry(struct video_card *video){	char buf[32];	struct dv1394_procfs_entry *p;	struct dv1394_procfs_entry *parent;	p = kmalloc(sizeof(struct dv1394_procfs_entry), GFP_KERNEL);	if(!p) {		printk(KERN_ERR "dv1394: cannot allocate dv1394_procfs_entry\n");		goto err;	}	memset(p, 0, sizeof(struct dv1394_procfs_entry));		snprintf(buf, sizeof(buf), "dv/host%d/%s", (video->id>>2),						(video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"));			parent = dv1394_procfs_find(buf);	if (parent == NULL) {		printk(KERN_ERR "dv1394: unable to locate parent procfs of %s\n", buf);		goto err_free;	}		p->procfs = create_proc_entry( 						(video->mode == MODE_RECEIVE ? "in" : "out"),						0666, parent->procfs);	if (p->procfs == NULL) {		printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/%s/%s\n",			parent->name,			(video->mode == MODE_RECEIVE ? "in" : "out"));		goto err_free;	}		p->procfs->owner = THIS_MODULE;	p->procfs->data = video;	p->procfs->read_proc = dv1394_procfs_read;	p->procfs->write_proc = dv1394_procfs_write;	spin_lock( &dv1394_procfs_lock);	INIT_LIST_HEAD(&p->list);	list_add_tail(&p->list, &dv1394_procfs);	spin_unlock( &dv1394_procfs_lock);		return 0;	 err_free:	kfree(p); err:	return -ENOMEM;}static intdv1394_procfs_add_dir( char *name,					struct dv1394_procfs_entry *parent, 					struct dv1394_procfs_entry **out){	struct dv1394_procfs_entry *p;	p = kmalloc(sizeof(struct dv1394_procfs_entry), GFP_KERNEL);	if(!p) {		printk(KERN_ERR "dv1394: cannot allocate dv1394_procfs_entry\n");		goto err;	}	memset(p, 0, sizeof(struct dv1394_procfs_entry));		if (parent == NULL) {		snprintf(p->name, sizeof(p->name), "%s", name);		p->procfs = proc_mkdir( name, ieee1394_procfs_entry);	} else {		snprintf(p->name, sizeof(p->name), "%s/%s", parent->name, name);		p->procfs = proc_mkdir( name, parent->procfs);	}	if (p->procfs == NULL) {		printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/%s\n", p->name);		goto err_free;	}	p->procfs->owner = THIS_MODULE;	p->parent = parent;	if (out != NULL) *out = p;	spin_lock( &dv1394_procfs_lock);	INIT_LIST_HEAD(&p->list);	list_add_tail(&p->list, &dv1394_procfs);	spin_unlock( &dv1394_procfs_lock);	return 0;	 err_free:	kfree(p); err:	return -ENOMEM;}void dv1394_procfs_del( char *name){	struct dv1394_procfs_entry *p = dv1394_procfs_find(name);	if (p != NULL) {		if (p->parent == NULL)			remove_proc_entry(p->name, ieee1394_procfs_entry);		else			remove_proc_entry(p->name, p->parent->procfs);				spin_lock( &dv1394_procfs_lock);		list_del(&p->list);		spin_unlock( &dv1394_procfs_lock);		kfree(p);	}}#endif /* CONFIG_PROC_FS *//*** DEVICE DRIVER HANDLERS ************************************************/static void it_tasklet_func(unsigned long data){	int wake = 0;	struct video_card *video = (struct video_card*) data;	spin_lock(&video->spinlock);		irq_printk("INTERRUPT! Video = %08lx Iso event Recv: %08x Xmit: %08x\n",		   (unsigned long) video, isoRecvIntEvent, isoXmitIntEvent);	irq_printk("ContextCont

⌨️ 快捷键说明

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