if (psizes) kfree(psizes); 
kfree(psizes); 
static int __video1394_ioctl(struct file *file,			     unsigned int cmd, unsigned long arg){	struct file_ctx *ctx = (struct file_ctx *)file->private_data;	struct ti_ohci *ohci = ctx->ohci;	unsigned long flags;	void __user *argp = (void __user *)arg;	switch(cmd)	{	case VIDEO1394_IOC_LISTEN_CHANNEL:	case VIDEO1394_IOC_TALK_CHANNEL:	{		struct video1394_mmap v;		u64 mask;		struct dma_iso_ctx *d;		int i;		if (copy_from_user(&v, argp, sizeof(v)))			return -EFAULT;		/* if channel < 0, find lowest available one */		if (v.channel < 0) {		    mask = (u64)0x1;		    for (i=0; ; i++) {			if (i == ISO_CHANNELS) {			    PRINT(KERN_ERR, ohci->host->id, 				  "No free channel found");			    return EAGAIN;			}			if (!(ohci->ISO_channel_usage & mask)) {			    v.channel = i;			    PRINT(KERN_INFO, ohci->host->id, "Found free channel %d", i);			    break;			}			mask = mask << 1;		    }		} else if (v.channel >= ISO_CHANNELS) {			PRINT(KERN_ERR, ohci->host->id,			      "Iso channel %d out of bounds", v.channel);			return -EINVAL;		} else {			mask = (u64)0x1<<v.channel;		}		PRINT(KERN_INFO, ohci->host->id, "mask: %08X%08X usage: %08X%08X\n",			(u32)(mask>>32),(u32)(mask&0xffffffff),			(u32)(ohci->ISO_channel_usage>>32),			(u32)(ohci->ISO_channel_usage&0xffffffff));		if (ohci->ISO_channel_usage & mask) {			PRINT(KERN_ERR, ohci->host->id,			      "Channel %d is already taken", v.channel);			return -EBUSY;		}		if (v.buf_size == 0 || v.buf_size > VIDEO1394_MAX_SIZE) {			PRINT(KERN_ERR, ohci->host->id,			      "Invalid %d length buffer requested",v.buf_size);			return -EINVAL;		}		if (v.nb_buffers == 0 || v.nb_buffers > VIDEO1394_MAX_SIZE) {			PRINT(KERN_ERR, ohci->host->id,			      "Invalid %d buffers requested",v.nb_buffers);			return -EINVAL;		}		if (v.nb_buffers * v.buf_size > VIDEO1394_MAX_SIZE) {			PRINT(KERN_ERR, ohci->host->id,			      "%d buffers of size %d bytes is too big",			      v.nb_buffers, v.buf_size);			return -EINVAL;		}		if (cmd == VIDEO1394_IOC_LISTEN_CHANNEL) {			d = alloc_dma_iso_ctx(ohci, OHCI_ISO_RECEIVE,					      v.nb_buffers, v.buf_size,					      v.channel, 0);			if (d == NULL) {				PRINT(KERN_ERR, ohci->host->id,				      "Couldn't allocate ir context");				return -EAGAIN;			}			initialize_dma_ir_ctx(d, v.sync_tag, v.flags);			ctx->current_ctx = d;			v.buf_size = d->buf_size;			list_add_tail(&d->link, &ctx->context_list);			PRINT(KERN_INFO, ohci->host->id,			      "iso context %d listen on channel %d",			      d->ctx, v.channel);		}		else {			d = alloc_dma_iso_ctx(ohci, OHCI_ISO_TRANSMIT,					      v.nb_buffers, v.buf_size,					      v.channel, v.packet_size);			if (d == NULL) {				PRINT(KERN_ERR, ohci->host->id,				      "Couldn't allocate it context");				return -EAGAIN;			}			initialize_dma_it_ctx(d, v.sync_tag,					      v.syt_offset, v.flags);			ctx->current_ctx = d;			v.buf_size = d->buf_size;			list_add_tail(&d->link, &ctx->context_list);			PRINT(KERN_INFO, ohci->host->id,			      "Iso context %d talk on channel %d", d->ctx,			      v.channel);		}		if (copy_to_user((void *)arg, &v, sizeof(v))) {			/* FIXME : free allocated dma resources */			return -EFAULT;		}				ohci->ISO_channel_usage |= mask;		return 0;	}	case VIDEO1394_IOC_UNLISTEN_CHANNEL:	case VIDEO1394_IOC_UNTALK_CHANNEL:	{		int channel;		u64 mask;		struct dma_iso_ctx *d;		if (copy_from_user(&channel, argp, sizeof(int)))			return -EFAULT;		if (channel < 0 || channel >= ISO_CHANNELS) {			PRINT(KERN_ERR, ohci->host->id,			      "Iso channel %d out of bound", channel);			return -EINVAL;		}		mask = (u64)0x1<<channel;		if (!(ohci->ISO_channel_usage & mask)) {			PRINT(KERN_ERR, ohci->host->id,			      "Channel %d is not being used", channel);			return -ESRCH;		}		/* Mark this channel as unused */		ohci->ISO_channel_usage &= ~mask;		if (cmd == VIDEO1394_IOC_UNLISTEN_CHANNEL)			d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, channel);		else			d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, channel);		if (d == NULL) return -ESRCH;		PRINT(KERN_INFO, ohci->host->id, "Iso context %d "		      "stop talking on channel %d", d->ctx, channel);		free_dma_iso_ctx(d);		return 0;	}	case VIDEO1394_IOC_LISTEN_QUEUE_BUFFER:	{		struct video1394_wait v;		struct dma_iso_ctx *d;		if (copy_from_user(&v, argp, sizeof(v)))			return -EFAULT;		d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);		if (d == NULL) return -EFAULT;		if ((v.buffer<0) || (v.buffer>d->num_desc)) {			PRINT(KERN_ERR, ohci->host->id,			      "Buffer %d out of range",v.buffer);			return -EINVAL;		}		spin_lock_irqsave(&d->lock,flags);		if (d->buffer_status[v.buffer]==VIDEO1394_BUFFER_QUEUED) {			PRINT(KERN_ERR, ohci->host->id,			      "Buffer %d is already used",v.buffer);			spin_unlock_irqrestore(&d->lock,flags);			return -EBUSY;		}		d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;		if (d->last_buffer>=0)			d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress =				cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0)					& 0xfffffff0) | 0x1);		d->last_buffer = v.buffer;		d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = 0;		spin_unlock_irqrestore(&d->lock,flags);		if (!(reg_read(ohci, d->ctrlSet) & 0x8000))		{			DBGMSG(ohci->host->id, "Starting iso DMA ctx=%d",d->ctx);			/* Tell the controller where the first program is */			reg_write(ohci, d->cmdPtr,				dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) | 0x1);			/* Run IR context */			reg_write(ohci, d->ctrlSet, 0x8000);		}		else {			/* Wake up dma context if necessary */			if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {				PRINT(KERN_INFO, ohci->host->id,				      "Waking up iso dma ctx=%d", d->ctx);				reg_write(ohci, d->ctrlSet, 0x1000);			}		}		return 0;	}	case VIDEO1394_IOC_LISTEN_WAIT_BUFFER:	case VIDEO1394_IOC_LISTEN_POLL_BUFFER:	{		struct video1394_wait v;		struct dma_iso_ctx *d;		int i;		if (copy_from_user(&v, argp, sizeof(v)))			return -EFAULT;		d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);		if (d == NULL) return -EFAULT;		if ((v.buffer<0) || (v.buffer>d->num_desc)) {			PRINT(KERN_ERR, ohci->host->id,			      "Buffer %d out of range",v.buffer);			return -EINVAL;		}		/*		 * I change the way it works so that it returns		 * the last received frame.		 */		spin_lock_irqsave(&d->lock, flags);		switch(d->buffer_status[v.buffer]) {		case VIDEO1394_BUFFER_READY:			d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;			break;		case VIDEO1394_BUFFER_QUEUED:			if (cmd == VIDEO1394_IOC_LISTEN_POLL_BUFFER) {			    /* for polling, return error code EINTR */			    spin_unlock_irqrestore(&d->lock, flags);			    return -EINTR;			}			spin_unlock_irqrestore(&d->lock, flags);			wait_event_interruptible(d->waitq,					video1394_buffer_state(d, v.buffer) ==					 VIDEO1394_BUFFER_READY);			if (signal_pending(current))                                return -EINTR;			spin_lock_irqsave(&d->lock, flags);			d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;			break;		default:			PRINT(KERN_ERR, ohci->host->id,			      "Buffer %d is not queued",v.buffer);			spin_unlock_irqrestore(&d->lock, flags);			return -ESRCH;		}		/* set time of buffer */		v.filltime = d->buffer_time[v.buffer];//		printk("Buffer %d time %d\n", v.buffer, (d->buffer_time[v.buffer]).tv_usec);		/*		 * Look ahead to see how many more buffers have been received		 */		i=0;		while (d->buffer_status[(v.buffer+1)%d->num_desc]==		       VIDEO1394_BUFFER_READY) {			v.buffer=(v.buffer+1)%d->num_desc;			i++;		}		spin_unlock_irqrestore(&d->lock, flags);		v.buffer=i;		if (copy_to_user(argp, &v, sizeof(v)))			return -EFAULT;		return 0;	}	case VIDEO1394_IOC_TALK_QUEUE_BUFFER:	{		struct video1394_wait v;		unsigned int *psizes = NULL;		struct dma_iso_ctx *d;		if (copy_from_user(&v, argp, sizeof(v)))			return -EFAULT;		d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);		if (d == NULL) return -EFAULT;		if ((v.buffer<0) || (v.buffer>d->num_desc)) {			PRINT(KERN_ERR, ohci->host->id,			      "Buffer %d out of range",v.buffer);			return -EINVAL;		}		if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {			int buf_size = d->nb_cmd * sizeof(unsigned int);			struct video1394_queue_variable __user *p = argp;			unsigned int __user *qv;			if (get_user(qv, &p->packet_sizes))				return -EFAULT;			psizes = kmalloc(buf_size, GFP_KERNEL);			if (!psizes)				return -ENOMEM;			if (copy_from_user(psizes, qv, buf_size)) {				kfree(psizes);				return -EFAULT;			}		}		spin_lock_irqsave(&d->lock,flags);		if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {			PRINT(KERN_ERR, ohci->host->id,			      "Buffer %d is already used",v.buffer);			spin_unlock_irqrestore(&d->lock,flags);			if (psizes)				kfree(psizes);			return -EBUSY;		}		if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {			initialize_dma_it_prg_var_packet_queue(				d, v.buffer, psizes,				ohci);		}		d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;		if (d->last_buffer >= 0) {			d->it_prg[d->last_buffer]				[ d->last_used_cmd[d->last_buffer] ].end.branchAddress =					cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer],						0) & 0xfffffff0) | 0x3);			d->it_prg[d->last_buffer]				[ d->last_used_cmd[d->last_buffer] ].begin.branchAddress =					cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer],						0) & 0xfffffff0) | 0x3);			d->next_buffer[d->last_buffer] = v.buffer;		}		d->last_buffer = v.buffer;		d->next_buffer[d->last_buffer] = -1;		d->it_prg[d->last_buffer][d->last_used_cmd[d->last_buffer]].end.branchAddress = 0;		spin_unlock_irqrestore(&d->lock,flags);		if (!(reg_read(ohci, d->ctrlSet) & 0x8000))		{			DBGMSG(ohci->host->id, "Starting iso transmit DMA ctx=%d",			       d->ctx);			put_timestamp(ohci, d, d->last_buffer);			/* Tell the controller where the first program is */			reg_write(ohci, d->cmdPtr,				dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) | 0x3);			/* Run IT context */			reg_write(ohci, d->ctrlSet, 0x8000);		}		else {			/* Wake up dma context if necessary */			if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {				PRINT(KERN_INFO, ohci->host->id,				      "Waking up iso transmit dma ctx=%d",				      d->ctx);				put_timestamp(ohci, d, d->last_buffer);				reg_write(ohci, d->ctrlSet, 0x1000);			}		}		if (psizes)			kfree(psizes);		return 0;	}	case VIDEO1394_IOC_TALK_WAIT_BUFFER:	{		struct video1394_wait v;		struct dma_iso_ctx *d;		if (copy_from_user(&v, argp, sizeof(v)))			return -EFAULT;		d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);		if (d == NULL) return -EFAULT;		if ((v.buffer<0) || (v.buffer>d->num_desc)) {			PRINT(KERN_ERR, ohci->host->id,			      "Buffer %d out of range",v.buffer);			return -EINVAL;		}		switch(d->buffer_status[v.buffer]) {		case VIDEO1394_BUFFER_READY:			d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;			return 0;		case VIDEO1394_BUFFER_QUEUED:			wait_event_interruptible(d->waitq,					(d->buffer_status[v.buffer] == VIDEO1394_BUFFER_READY));			if (signal_pending(current))				return -EINTR;			d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;			return 0;		default:			PRINT(KERN_ERR, ohci->host->id,			      "Buffer %d is not queued",v.buffer);			return -ESRCH;		}	}	default:		return -ENOTTY;	}}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/616b859fbd0e59707a24612d5b5fec791156c822/video1394.c/buggy/drivers/ieee1394/video1394.c