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

📄 dv1394.c

📁 这个是uClinux下的ieee1394驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
					  sizeof(struct CIP_header), /* data size */					  cip_dma);						if(first_packet)				f->frame_begin_timestamp = &(block->u.out.u.empty.ol.q[3]);			else if(mid_packet)				f->mid_frame_timestamp = &(block->u.out.u.empty.ol.q[3]);			else if(last_packet) {				f->frame_end_timestamp = &(block->u.out.u.empty.ol.q[3]);				f->frame_end_branch = &(block->u.out.u.empty.ol.q[2]);			}			branch_address = &(block->u.out.u.empty.ol.q[2]);			n_descriptors = 3;			if(first_packet)				f->first_n_descriptors = n_descriptors;		} else { /* full packet */			/* second descriptor - OUTPUT_MORE for CIP header */			fill_output_more( &(block->u.out.u.full.om),					  sizeof(struct CIP_header), /* data size */					  cip_dma);						/* third (and possibly fourth) descriptor - for DV data */			/* the 480-byte payload can cross a page boundary; if so,			   we need to split it into two DMA descriptors */			/* does the 480-byte data payload cross a page boundary? */			if( (PAGE_SIZE- ((unsigned long)data_p % PAGE_SIZE) ) < 480 ) {				/* page boundary crossed */				fill_output_more( &(block->u.out.u.full.u.cross.om),						  /* data size - how much of data_p fits on the first page */						  PAGE_SIZE - (data_p % PAGE_SIZE),						  /* DMA address of data_p */						  dma_offset_to_bus(&f->video->user_dma,								    data_p - (unsigned long) f->video->user_buf));				fill_output_last( &(block->u.out.u.full.u.cross.ol),					  						  /* want completion status on all interesting packets */						  (first_packet || mid_packet || last_packet) ? 1 : 0, 						  /* want interrupt on all interesting packets */						  (first_packet || mid_packet || last_packet) ? 1 : 0,						  /* data size - remaining portion of data_p */						  480 - (PAGE_SIZE - (data_p % PAGE_SIZE)),						  /* DMA address of data_p + PAGE_SIZE - (data_p % PAGE_SIZE) */						  dma_offset_to_bus(&f->video->user_dma,								    data_p + PAGE_SIZE - (data_p % PAGE_SIZE) - (unsigned long) f->video->user_buf));				if(first_packet)					f->frame_begin_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]);				else if(mid_packet)					f->mid_frame_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]);				else if(last_packet) {					f->frame_end_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]);					f->frame_end_branch = &(block->u.out.u.full.u.cross.ol.q[2]);				}				branch_address = &(block->u.out.u.full.u.cross.ol.q[2]);				n_descriptors = 5;				if(first_packet)					f->first_n_descriptors = n_descriptors;								full_packets++;			} else {				/* fits on one page */				fill_output_last( &(block->u.out.u.full.u.nocross.ol),					  						  /* want completion status on all interesting packets */						  (first_packet || mid_packet || last_packet) ? 1 : 0,						  /* want interrupt on all interesting packets */						  (first_packet || mid_packet || last_packet) ? 1 : 0,						  480, /* data size (480 bytes of DV data) */						  						  /* DMA address of data_p */						  dma_offset_to_bus(&f->video->user_dma,								    data_p - (unsigned long) f->video->user_buf));								if(first_packet)					f->frame_begin_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]);				else if(mid_packet)					f->mid_frame_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]);				else if(last_packet) {					f->frame_end_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]);					f->frame_end_branch = &(block->u.out.u.full.u.nocross.ol.q[2]);				}				branch_address = &(block->u.out.u.full.u.nocross.ol.q[2]);				n_descriptors = 4;				if(first_packet)					f->first_n_descriptors = n_descriptors;				full_packets++;			}		}				/* link this descriptor block into the DMA program by filling in 		   the branch address of the previous block */		/* note: we are not linked into the active DMA chain yet */		if(last_branch_address) {			*(last_branch_address) = cpu_to_le32(block_dma | n_descriptors);		}		last_branch_address = branch_address;		f->n_packets++;			}	/* when we first assemble a new frame, set the final branch 	   to loop back up to the top */	*(f->frame_end_branch) = cpu_to_le32(f->descriptor_pool_dma | f->first_n_descriptors);	/* make the latest version of the frame buffer visible to the PCI card */	/* could optimize this by only syncing the pages associated with this frame */	pci_dma_sync_sg(video->ohci->dev,			&video->user_dma.sglist[0],			video->user_dma.n_dma_pages,			PCI_DMA_TODEVICE);	/* lock against DMA interrupt */	spin_lock_irqsave(&video->spinlock, irq_flags);	f->state = FRAME_READY;	video->n_clear_frames--;	last_frame = video->first_clear_frame - 1;	if(last_frame == -1)		last_frame = video->n_frames-1;	video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames;	irq_printk("   frame %d prepared, active_frame = %d, n_clear_frames = %d, first_clear_frame = %d\n last=%d\n",		   this_frame, video->active_frame, video->n_clear_frames, video->first_clear_frame, last_frame);	irq_printk("   begin_ts %08lx mid_ts %08lx end_ts %08lx end_br %08lx\n",		   (unsigned long) f->frame_begin_timestamp, 		   (unsigned long) f->mid_frame_timestamp, 		   (unsigned long) f->frame_end_timestamp, 		   (unsigned long) f->frame_end_branch);		if(video->active_frame != -1) {		/* if DMA is already active, we are almost done */		/* just link us onto the active DMA chain */		if(video->frames[last_frame]->frame_end_branch) {			u32 temp;			/* point the previous frame's tail to this frame's head */			*(video->frames[last_frame]->frame_end_branch) = cpu_to_le32(f->descriptor_pool_dma | f->first_n_descriptors);			/* this write MUST precede the next one, or we could silently drop frames */			wmb();						/* disable the want_status semaphore on the last packet */			temp = le32_to_cpu(*(video->frames[last_frame]->frame_end_branch - 2));			temp &= 0xF7CFFFFF;			*(video->frames[last_frame]->frame_end_branch - 2) = cpu_to_le32(temp);			/* flush these writes to memory ASAP */			flush_pci_write(video->ohci);			/* NOTE:			   ideally the writes should be "atomic": if			   the OHCI card reads the want_status flag in			   between them, we'll falsely report a			   dropped frame. Hopefully this window is too			   small to really matter, and the consequence			   is rather harmless. */						irq_printk("     new frame %d linked onto DMA chain\n", this_frame);		} else {			printk(KERN_ERR "dv1394: last frame not ready???\n");		}	} else {				u32 transmit_sec, transmit_cyc;		u32 ts_cyc, ts_off;		/* DMA is stopped, so this is the very first frame */		video->active_frame = this_frame;			        /* set CommandPtr to address and size of first descriptor block */		reg_write(video->ohci, video->ohci_IsoXmitCommandPtr,			  video->frames[video->active_frame]->descriptor_pool_dma |			  f->first_n_descriptors);		/* assign a timestamp based on the current cycle time...		   We'll tell the card to begin DMA 100 cycles from now,		   and assign a timestamp 103 cycles from now */		cycleTimer = reg_read(video->ohci, OHCI1394_IsochronousCycleTimer);		ct_sec = cycleTimer >> 25;		ct_cyc = (cycleTimer >> 12) & 0x1FFF;		ct_off = cycleTimer & 0xFFF;		transmit_sec = ct_sec;		transmit_cyc = ct_cyc + 100;		transmit_sec += transmit_cyc/8000;		transmit_cyc %= 8000;				ts_off = ct_off;		ts_cyc = transmit_cyc + 3;		ts_cyc %= 8000;		f->assigned_timestamp = (ts_cyc&0xF) << 12;		/* now actually write the timestamp into the appropriate CIP headers */		if(f->cip_syt1) {			f->cip_syt1->b[6] = f->assigned_timestamp >> 8;			f->cip_syt1->b[7] = f->assigned_timestamp & 0xFF;		}		if(f->cip_syt2) {			f->cip_syt2->b[6] = f->assigned_timestamp >> 8;			f->cip_syt2->b[7] = f->assigned_timestamp & 0xFF;		}				/* --- start DMA --- */		/* clear all bits in ContextControl register */		reg_write(video->ohci, video->ohci_IsoXmitContextControlClear, 0xFFFFFFFF);		wmb();		/* the OHCI card has the ability to start ISO transmission on a		   particular cycle (start-on-cycle). This way we can ensure that		   the first DV frame will have an accurate timestamp.		   		   However, start-on-cycle only appears to work if the OHCI card 		   is cycle master! Since the consequences of messing up the first		   timestamp are minimal*, just disable start-on-cycle for now.		   * my DV deck drops the first few frames before it "locks in;"		     so the first frame having an incorrect timestamp is inconsequential.		*/#if 0		reg_write(video->ohci, video->ohci_IsoXmitContextControlSet,			  (1 << 31) /* enable start-on-cycle */			  | ( (transmit_sec & 0x3) << 29)			  | (transmit_cyc << 16));		wmb();#endif				/* set the 'run' bit */		reg_write(video->ohci, video->ohci_IsoXmitContextControlSet, 0x8000);		flush_pci_write(video->ohci);				/* --- DMA should be running now --- */		debug_printk("    Cycle = %4u ContextControl = %08x CmdPtr = %08x\n",			     (reg_read(video->ohci, OHCI1394_IsochronousCycleTimer) >> 12) & 0x1FFF,			     reg_read(video->ohci, video->ohci_IsoXmitContextControlSet),			     reg_read(video->ohci, video->ohci_IsoXmitCommandPtr));		debug_printk("    DMA start - current cycle %4u, transmit cycle %4u (%2u), assigning ts cycle %2u\n",			     ct_cyc, transmit_cyc, transmit_cyc & 0xF, ts_cyc & 0xF);#if DV1394_DEBUG_LEVEL >= 2		{			/* check if DMA is really running */			int i = 0;			while(i < 20) {				mb();				mdelay(1);				if(reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) {					printk("DMA ACTIVE after %d msec\n", i);					break;				}				i++;			}			printk("set = %08x, cmdPtr = %08x\n", 			       reg_read(video->ohci, video->ohci_IsoXmitContextControlSet),			       reg_read(video->ohci, video->ohci_IsoXmitCommandPtr)			       );						if( ! (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) &  (1 << 10)) ) {				printk("DMA did NOT go active after 20ms, event = %x\n", 				       reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & 0x1F);			} else				printk("DMA is RUNNING!\n");		}#endif			}	spin_unlock_irqrestore(&video->spinlock, irq_flags);}/*** RECEIVE FUNCTIONS *****************************************************//* 	frame method put_packet	map and copy the packet data to its location in the frame 	based upon DIF section and sequence */static void inlineframe_put_packet (struct frame *f, struct packet *p){	int section_type = p->data[0] >> 5;           /* section type is in bits 5 - 7 */	int dif_sequence = p->data[1] >> 4;           /* dif sequence number is in bits 4 - 7 */	int dif_block = p->data[2];	switch (section_type) {	case 0:           /* 1 Header block */	        memcpy( (void *) f->data + dif_sequence * 150 * 80, p->data, 480);	        break;		case 1:           /* 2 Subcode blocks */	        memcpy( (void *) f->data + dif_sequence * 150 * 80 + (1 + dif_block) * 80, p->data, 480);	        break;		case 2:           /* 3 VAUX blocks */	        memcpy( (void *) f->data + dif_sequence * 150 * 80 + (3 + dif_block) * 80, p->data, 480);	        break;		case 3:           /* 9 Audio blocks interleaved with video */	        memcpy( (void *) f->data + dif_sequence * 150 * 80 + (6 + dif_block * 16) * 80, p->data, 480);	        break;		case 4:           /* 135 Video blocks interleaved with audio */	        memcpy( (void *) f->data + dif_sequence * 150 * 80 + (7 + (dif_block / 15) + dif_block) * 80, p->data, 480);	        break;		default:           /* we can not handle any other data */	        break;	}}static void start_dma_receive(struct video_card *video, struct frame *frame){	/* reset iso recv control register */	reg_write(video->ohci, video->ohci_IsoRcvContextControlClear, 0xFFFFFFFF);	wmb();		/* clear bufferFill, set isochHeader and speed (0=100) */	reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x40000000);	/* match on all tags, listen on channel */	reg_write(video->ohci, video->ohci_IsoRcvContextMatch, 0xf0000000 | video->channel);		/* address and first descriptor block + Z=1 */	reg_write(video->ohci, video->ohci_IsoRcvCommandPtr,             		  frame->descriptor_pool_dma | 1); /* Z=1 */	wmb();		/* run */	reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x8000);	flush_pci_write(video->ohci);		debug_printk("dv1394: DMA started\n");#if DV1394_DEBUG_LEVEL >= 2	{		int i;			for(i = 0; i < 1000; ++i) {			mdelay(1);			if(reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) {				printk("DMA ACTIVE after %d msec\n", i);				break;			}		}		if( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) &  (1 << 11) ) {			printk("DEAD, event = %x\n", 			       reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F);		} else			printk("RUNNING!\n");	}#endif}/*    receive_packets() - build the DMA program for receiving*/static void receive_packets(struct video_card *video, struct frame *f){	struct DMA_descriptor_block *block = NULL;	dma_addr_t block_dma = 0;	struct packet *data = NULL;	dma_addr_t data_dma = 0;	u32 *last_branch_address = NULL;	unsigned long irq_flags;	spin_lock_irqsave(&video->spinlock, irq_flags);	video->n_clear_frames = 0;	video->first_clear_frame = -1;	for (video->current_packet = 0; video->current_packet < MAX_PACKET_BUFFER; ++video->current_packet) {		/* locate a descriptor block and packet from the buffer */		block = &(f->descriptor_pool[video->current_packet]);		block_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma;				data = &(video->packet_buffer[video->current_packet]);		data_dma = ((unsigned long) data - (unsigned long) video->packet_buffer) + video->packet_buffer_dma;				/* setup DMA descriptor block */		fill_input_last( &(block->u.in.il), 512, data_dma);		/* link descriptors */		last_branch_address = f->frame_end_branch;		if (last_branch_address)			*(last_branch_address) = cpu_to_le32(block_dma | 1); /* set Z=1 */		f->frame_end_branch = &(block->u.in.il.q[2]);	}		/* loop tail to head */	if (f->frame_end_branch)		*(f->frame_end_branch) = cpu_to_le32(f->descriptor_pool_dma | 1); /* set Z=1 */	spin_unlock_irqrestore(&video->spinlock, irq_flags);	if (video->first_run) {		/* start DMA once all of the frames are READY */		video->first_run = 0;		video->current_packet = 0;		video->active_frame = f->frame_num;		start_dma_receive(video, f);	} 	else if( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) &  (1 << 11) ) {		debug_printk("DEAD, event = %x\n", 			     reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F);		/* wake */		reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12));	}

⌨️ 快捷键说明

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