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

📄 dv1394.c

📁 ieee1394驱动,不多说了!直接可以在linux2.6内核中使用
💻 C
📖 第 1 页 / 共 5 页
字号:
						  PAGE_SIZE - (data_p % PAGE_SIZE),						  /* DMA address of data_p */						  dma_region_offset_to_bus(&video->dv_buf,									   data_p - (unsigned long) video->dv_buf.kvirt));				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_region_offset_to_bus(&video->dv_buf,									   data_p + PAGE_SIZE - (data_p % PAGE_SIZE) - (unsigned long) video->dv_buf.kvirt));				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_region_offset_to_bus(&video->dv_buf,									   data_p - (unsigned long) video->dv_buf.kvirt));				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 this frame visible to the PCI card */	dma_region_sync_for_device(&video->dv_buf, f->data - (unsigned long) video->dv_buf.kvirt, video->frame_size);	/* 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		video->dma_running = 1;		/* 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];	/* sanity check */	if (dif_sequence > 11 || dif_block > 149) return;	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){	if (video->first_run == 1) {		video->first_run = 0;		/* start DMA once all of the frames are READY */		video->n_clear_frames = 0;		video->first_clear_frame = -1;		video->current_packet = 0;		video->active_frame = 0;		/* 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,			  video->frames[0]->descriptor_pool_dma | 1); /* Z=1 */		wmb();		video->dma_running = 1;		/* 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	} 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));	}}/*   receive_packets() - build the DMA program for receiving*/static void receive_packets(struct video_card *video){	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;	int want_interrupt = 0;	struct frame *f = NULL;	int i, j;	spin_lock_irqsave(&video->spinlock, irq_flags);	for (j = 0; j < video->n_frames; j++) {		/* connect frames */		if (j > 0 && f != NULL && f->frame_end_branch != NULL)			*(f->frame_end_branch) = cpu_to_le32(video->frames[j]->descriptor_pool_dma | 1); /* set Z=1 */		f = video->frames[j];		for (i = 0; i < MAX_PACKETS; i++) {			/* locate a descriptor block and packet from the buffer */			block = &(f->descriptor_pool[i]);			block_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma;			data = ((struct packet*)video->packet_buf.kvirt) + f->frame_num * MAX_PACKETS + i;			data_dma = dma_region_offset_to_bus( &video->packet_buf,							     ((unsigned long) data - (unsigned long) video->packet_buf.kvirt) );			/* setup DMA descriptor block */			want_interrupt = ((i % (MAX_PACKETS/2)) == 0 || i == (MAX_PACKETS-1));			fill_input_last( &(block->u.in.il), want_interrupt, 512, data_dma);			/* link descriptors */			last_branch_address = f->frame_end_branch;			if (last_branch_address != NULL)				*(last_branch_address) = cpu_to_le32(block_dma | 1); /* set Z=1 */			f->frame_end_branch = &(block->u.in.il.q[2]);		}	} /* next j */	spin_unlock_irqrestore(&video->spinlock, irq_flags);}/*** MANAGEMENT FUNCTIONS **************************************************/static int do_dv1394_init(struct video_card *video, struct dv1394_init *init){	unsigned long flags, new_buf_size;	int i;	u64 chan_mask;	int retval = -EINVAL;	debug_printk("dv1394: initialising %d\n", video->id);	if (init->api_version != DV1394_API_VERSION)

⌨️ 快捷键说明

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