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

📄 ohci1394.c

📁 1394在linux下单独的驱动程序代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		} else {			d->prg_cpu[i]->branchAddress =				cpu_to_le32((d->prg_bus[0] & 0xfffffff0));		//Z:0,last descriptor,see pdf_doc,p96		}				d->prg_cpu[i]->address = cpu_to_le32(d->buf_bus[i]);		d->prg_cpu[i]->status = cpu_to_le32(d->buf_size);	}		d->buf_ind = 0;	d->buf_offset = 0;		if (d->type == DMA_CTX_ISO) {		/* Clear contextControl */		reg_write(ohci, d->ctrlClear, 0xffffffff);				/* Set bufferFill, isochHeader, multichannel for IR context */		reg_write(ohci, d->ctrlSet, 0xd0000000);				/* Set the context match register to match on all tags */		reg_write(ohci, d->ctxtMatch, 0xf0000000);				/* Clear the multi channel mask high and low registers */		//OHCI1394_IRMultiChanMaskHiClear:0x74,see pdf_doc,p141		reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff);		//OHCI1394_IRMultiChanMaskLoClear:0x7C,see pdf_doc,p142		reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff);				/* Set up isoRecvIntMask to generate interrupts */		//OHCI1394_IsoRecvIntMaskSet:0xA8,see pdf_doc,p68		reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << d->ctx);	}		/* Tell the controller where the first AR program is */	reg_write(ohci, d->cmdPtr, d->prg_bus[0] | 0x1);		//see 0x1CC,p97		/* Run context */	reg_write(ohci, d->ctrlSet, 0x00008000);		DBGMSG(ohci->id, "Receive DMA ctx=%d initialized", d->ctx);}/* Initialize the dma transmit context */static void initialize_dma_trm_ctx(struct dma_trm_ctx *d){	struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);		/* Stop the context */	ohci1394_stop_context(ohci, d->ctrlClear, NULL);		d->prg_ind = 0;	d->sent_ind = 0;	d->free_prgs = d->num_desc;	d->branchAddrPtr = NULL;	INIT_LIST_HEAD(&d->fifo_list);	INIT_LIST_HEAD(&d->pending_list);		if (d->type == DMA_CTX_ISO) {		/* enable interrupts */		//OHCI1394_IsoXmitIntMaskSet:0x98,see pdf_doc,p67		reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << d->ctx);	}		DBGMSG(ohci->id, "Transmit DMA ctx=%d initialized", d->ctx);}/* Count the number of available iso contexts *///called by:	ohci1394_pci_probe()//see pdf_doc,p67,p68static int get_nb_iso_ctx(struct ti_ohci *ohci, int reg){	int i,ctx=0;	u32 tmp;		reg_write(ohci, reg, 0xffffffff);	tmp = reg_read(ohci, reg);		DBGMSG(ohci->id,"Iso contexts reg: %08x implemented: %08x", reg, tmp);		/* Count the number of contexts */	for (i=0; i<32; i++) {		if (tmp & 1) ctx++;		tmp >>= 1;	}	return ctx;}static void ohci_init_config_rom(struct ti_ohci *ohci);/* Global initialization */static void ohci_initialize(struct ti_ohci *ohci){	char irq_buf[16];	quadlet_t buf;		spin_lock_init(&ohci->phy_reg_lock);	spin_lock_init(&ohci->event_lock);		/* Put some defaults to these undefined bus options */	//OHCI1394_BusOptions:0x20,see pdf_doc p41,	//IRMC,CMC and ISC,cyc_clk_acc,PMC and BMC:	???,not documented	buf = reg_read(ohci, OHCI1394_BusOptions);	buf |=  0xE0000000; /* Enable IRMC, CMC and ISC */	buf &= ~0x00ff0000; /* XXX: Set cyc_clk_acc to zero for now */	buf &= ~0x18000000; /* Disable PMC and BMC */	reg_write(ohci, OHCI1394_BusOptions, buf);		/* Set the bus number */	//OHCI1394_NodeID:0xE8,see pdf_doc,p53	//set bus number 0xffc0,nodenumber 0.	reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0);		/* Enable posted writes */	//OHCI1394_HCControlSet,0x50,see pdf_doc,p45,47	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_postedWriteEnable);		/* Clear link control register */	//OHCI1394_LinkControlClear:0xE4,see pdf_doc,p51	reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);		/* Enable cycle timer and cycle master and set the IRM	* contender bit in our self ID packets. */	//OHCI1394_LinkControlSet:0xE0,see pdf_doc,p51	reg_write(ohci, OHCI1394_LinkControlSet, 0x00300000);	//address:4,	data:0xc0	set_phy_reg_mask(ohci, 4, 0xc0);		/* Clear interrupt registers */	//OHCI1394_IntMaskClear:0x8C,see pdf_doc,p65	reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);	//OHCI1394_IntEventClear:0x84,see pdf_doc,p62	reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);		/* Set up self-id dma buffer */	//OHCI1394_SelfIDBuffer:0x64,see pdf_doc,p147	reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->selfid_buf_bus);		/* enable self-id dma */	//OHCI1394_LinkControlSet:0xE0,see pdf_doc,p51,accept self_ID packets	reg_write(ohci, OHCI1394_LinkControlSet, 0x00000200);		/* Set the Config ROM mapping register */	//OHCI1394_ConfigROMmap:0x34,see pdf_doc,p44	reg_write(ohci, OHCI1394_ConfigROMmap, ohci->csr_config_rom_bus);		/* Initialize the Config ROM */	ohci_init_config_rom(ohci);		/* Now get our max packet size */	//OHCI1394_BusOptions:0x20,see pdf_doc,p41	ohci->max_packet_size = 		1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1);		/* Don't accept phy packets into AR request context */ 	//OHCI1394_LinkControlClear:0xE4,see pdf_doc,p51	reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400);		/* Clear the interrupt mask */	//OHCI1394_IsoRecvIntMaskClear:0xAC,see pdf_doc,p68	reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);	//OHCI1394_IsoRecvIntEventClear:0xA4,see pdf_doc,p68	reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);		/* Clear the interrupt mask */	//OHCI1394_IsoXmitIntMaskClear:0x9C,see pdf_doc,p67	reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);	//OHCI1394_IsoXmitIntEventClear:0x94,see pdf_doc,p66	reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);		/* Initialize AR dma */	initialize_dma_rcv_ctx(&ohci->ar_req_context, 0);	initialize_dma_rcv_ctx(&ohci->ar_resp_context, 0);		/* Initialize AT dma */	initialize_dma_trm_ctx(&ohci->at_req_context);	initialize_dma_trm_ctx(&ohci->at_resp_context);		/* 	* Accept AT requests from all nodes. This probably 	* will have to be controlled from the subsystem	* on a per node basis.	*/	//OHCI1394_AsReqFilterHiSet:0x100,see pdf_doc,p56	reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0x80000000);		/* Specify AT retries */	//OHCI1394_ATRetries:0x08,see pdf_doc,p37	reg_write(ohci, OHCI1394_ATRetries, 		OHCI1394_MAX_AT_REQ_RETRIES |					//OHCI1394_MAX_AT_REQ_RETRIES:0x2		(OHCI1394_MAX_AT_RESP_RETRIES<<4) |		//OHCI1394_MAX_AT_RESP_RETRIES:0x02		(OHCI1394_MAX_PHYS_RESP_RETRIES<<8));	//OHCI1394_MAX_PHYS_RESP_RETRIES:0x08		/* We don't want hardware swapping */	//OHCI1394_HCControlClear:0x54,see pdf_doc,p45	reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwap);		//0x40000000		/* Enable interrupts */	//OHCI1394_IntMaskSet:0x88,see pdf_doc,p65	reg_write(ohci, OHCI1394_IntMaskSet,		OHCI1394_unrecoverableError |		//0x01000000		OHCI1394_masterIntEnable | 		//0x80000000		OHCI1394_busReset | 					//0x00020000		OHCI1394_selfIDComplete |			//0x00010000		OHCI1394_RSPkt |						//0x00000020		OHCI1394_RQPkt |						//0x00000010		OHCI1394_respTxComplete |			//0x00000002		OHCI1394_reqTxComplete |			//0x00000001		OHCI1394_isochRx |						//0x00000080		OHCI1394_isochTx |						//0x00000040		OHCI1394_cycleInconsistent);		//0x00800000		/* Enable link */	//OHCI1394_HCControlSet:0x50,see pdf_doc,p45	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);	//0x00020000		//OHCI1394_Version:0x00,see pdf_doc,p35	buf = reg_read(ohci, OHCI1394_Version);#ifndef __sparc__	sprintf (irq_buf, "%d", ohci->dev->irq);#else	sprintf (irq_buf, "%s", __irq_itoa(ohci->dev->irq));#endif	PRINT(KERN_INFO, ohci->id, "OHCI-1394 %d.%d (PCI): IRQ=[%s]  "		"MMIO=[%lx-%lx]  Max Packet=[%d]",		((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10),		((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), irq_buf,		pci_resource_start(ohci->dev, 0),		pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1,		ohci->max_packet_size);}/* * Insert a packet in the DMA fifo and generate the DMA prg* FIXME: rewrite the program in order to accept packets crossing*        page boundaries.*        check also that a single dma descriptor doesn't cross a *        page boundary.*///called by:	dma_trm_flush()//struct ti_ohci,struct dma_trm_ctx:	see ohci1394.h//struct hpsb_packet:									see ieee1394_core.hstatic void insert_packet(struct ti_ohci *ohci,						  struct dma_trm_ctx *d, struct hpsb_packet *packet){	u32 cycleTimer;	int idx = d->prg_ind;		DBGMSG(ohci->id, "Inserting packet for node " NODE_BUS_FMT	       ", tlabel=%d, tcode=0x%x, speed=%d",		   NODE_BUS_ARGS(ohci->host, packet->node_id), packet->tlabel,		   packet->tcode, packet->speed_code);		d->prg_cpu[idx]->begin.address = 0;	d->prg_cpu[idx]->begin.branchAddress = 0;		if (d->type == DMA_CTX_ASYNC_RESP) {	/* 	* For response packets, we need to put a timeout value in	* the 16 lower bits of the status... let's try 1 sec timeout 		*/ 		//OHCI1394_IsochronousCycleTimer:0xF0,see pdf_doc,p55		cycleTimer = reg_read(ohci, OHCI1394_IsochronousCycleTimer);		d->prg_cpu[idx]->begin.status = cpu_to_le32(			(((((cycleTimer>>25)&0x7)+1)&0x7)<<13) | 			((cycleTimer&0x01fff000)>>12));				DBGMSG(ohci->id, "cycleTimer: %08x timeStamp: %08x",			cycleTimer, d->prg_cpu[idx]->begin.status);	} else 		d->prg_cpu[idx]->begin.status = 0;		if ( (packet->type == hpsb_async) || (packet->type == hpsb_raw) ) {		if (packet->type == hpsb_raw) {			d->prg_cpu[idx]->data[0] = cpu_to_le32(OHCI1394_TCODE_PHY<<4);	//OHCI1394_TCODE_PHY:0xE			d->prg_cpu[idx]->data[1] = cpu_to_le32(packet->header[0]);			d->prg_cpu[idx]->data[2] = cpu_to_le32(packet->header[1]);		} else {			d->prg_cpu[idx]->data[0] = packet->speed_code<<16 |		//see pdf_doc,p84,AT Data Format				(packet->header[0] & 0xFFFF);						if (packet->tcode == TCODE_ISO_DATA) {		//TCODE_ISO_DATA:0xA,ieee1394.h				/* Sending an async stream packet */				d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000;			} else {				/* Sending a normal async request or response */				d->prg_cpu[idx]->data[1] =					(packet->header[1] & 0xFFFF) | 					(packet->header[0] & 0xFFFF0000);				d->prg_cpu[idx]->data[2] = packet->header[2];				d->prg_cpu[idx]->data[3] = packet->header[3];			}			packet_swab(d->prg_cpu[idx]->data, packet->tcode);		}				if (packet->data_size) { /* block transmit */			if (packet->tcode == TCODE_STREAM_DATA){		//0xA				d->prg_cpu[idx]->begin.control =					cpu_to_le32(DMA_CTL_OUTPUT_MORE |	//0x00000000,see pdf_doc,p70					DMA_CTL_IMMEDIATE | 0x8);					//0x02000000(key),see pdf_doc,p71=>OUTPUT_MORE_IMMEDIATE			} else {				d->prg_cpu[idx]->begin.control =					// = OUTPUT_MORE_IMMEDIATE,see pdf_doc,p71					cpu_to_le32(DMA_CTL_OUTPUT_MORE |	//0x00000000,see pdf_doc,p70					DMA_CTL_IMMEDIATE | 0x10);				//0x02000000(key),see pdf_doc,p71			}			d->prg_cpu[idx]->end.control =						// = OUTPUT_MORE_IMMEDIATE,see pdf_doc,p71				cpu_to_le32(DMA_CTL_OUTPUT_LAST |		//0x10000000,see pdf_doc,p72				DMA_CTL_IRQ | 											//0x00300000,				DMA_CTL_BRANCH |									//0x000c0000				packet->data_size);				/* 				* Check that the packet data buffer				* does not cross a page boundary.			*/			if (cross_bound((unsigned long)packet->data, 				packet->data_size)>0) {				/* FIXME: do something about it */				PRINT(KERN_ERR, ohci->id,					"%s: packet data addr: %p size %Zd bytes "					"cross page boundary", __FUNCTION__,					packet->data, packet->data_size);			}						d->prg_cpu[idx]->end.address = cpu_to_le32(				pci_map_single(ohci->dev, packet->data,				packet->data_size,				PCI_DMA_TODEVICE));			OHCI_DMA_ALLOC("single, block transmit packet");						d->prg_cpu[idx]->end.branchAddress = 0;			d->prg_cpu[idx]->end.status = 0;			if (d->branchAddrPtr) 				*(d->branchAddrPtr) = cpu_to_le32(d->prg_bus[idx] | 0x3);			d->branchAddrPtr =	&(d->prg_cpu[idx]->end.branchAddress);		} else { /* quadlet transmit */			if (packet->type == hpsb_raw)				d->prg_cpu[idx]->begin.control = 				cpu_to_le32(DMA_CTL_OUTPUT_LAST |		//0x10000000,see pdf_doc,p72				DMA_CTL_IMMEDIATE |								//0x02000000(key),see pdf_doc,p71				DMA_CTL_IRQ | 											//0x00300000,				DMA_CTL_BRANCH |									//0x000c0000				(packet->header_size + 4));			else				d->prg_cpu[idx]->begin.control =				cpu_to_le32(DMA_CTL_OUTPUT_LAST |		//0x10000000,see pdf_doc,p72				DMA_CTL_IMMEDIATE |								//0x02000000(key),see pdf_doc,p71				DMA_CTL_IRQ | 											//0x00300000,				DMA_CTL_BRANCH |									//0x000c0000				packet->header_size);						if (d->branchAddrPtr) 				*(d->branchAddrPtr) = cpu_to_le32(d->prg_bus[idx] | 0x2);			d->branchAddrPtr = &(d->prg_cpu[idx]->begin.branchAddress);		}			} else { /* iso packet */		d->prg_cpu[idx]->data[0] = packet->speed_code<<16 |		//see pdf_doc,p126,IT Data Format			(packet->header[0] & 0xFFFF);		d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000;		packet_swab(d->prg_cpu[idx]->data, packet->tcode);				d->prg_cpu[idx]->begin.control = 						//= OUTPUT_MORE_IMMEDIATE,see pdf_doc,p113			cpu_to_le32(DMA_CTL_OUTPUT_MORE | 		//0x00000000,			DMA_CTL_IMMEDIATE | 0x8);						//0x02000000,		d->prg_cpu[idx]->end.control = 			cpu_to_le32(DMA_CTL_OUTPUT_LAST |		//0x10000000,see pdf_doc,p114			DMA_CTL_UPDATE |										//0x08000000			DMA_CTL_IRQ |											//0x00300000			DMA_CTL_BRANCH |									//0x000c0000			packet->data_size);		d->prg_cpu[idx]->end.address = cpu_to_le32(			pci_map_single(ohci->dev, packet->data,			packet->data_size, PCI_DMA_TODEVICE));		OHCI_DMA_ALLOC("single, iso transmit packet");				d->prg_cpu[idx]->end.branchAddress = 0;		d->prg_cpu[idx]->end.status = 0;		DBGMSG(ohci->id, "Iso xmit context info: header[%08x %08x]\n"			"                       begin=%08x %08x %08x %08x\n"			"                             %08x %08x %08x %08x\n"			"                       end  =%08x %08x %08x %08x",			d->prg_cpu[idx]->data[0], d->prg_cpu[idx]->data[1],			d->prg_cpu[idx]->begin.control,			d->prg_cpu[idx]->begin.address,			d->prg_cpu[idx]->begin.branchAddress,			d->prg_cpu[idx]->begin.status,			d->prg_cpu[idx]->data[0],			d->prg_cpu[idx]->data[1],			d->prg_cpu[idx]->data[2],			d->prg_cpu[idx]->data[3],			d->prg_cpu[idx]->end.control,			d->prg_cpu[idx]->end.address,			d->prg_cpu[idx]->end.branchAddress,			d->prg_cpu[idx]->end.status);		if (d->branchAddrPtr)   		        *(d->branchAddrPtr) = cpu_to_le32(d->prg_bus[idx] | 0x3);		d->branchAddrPtr = &(d->prg_cpu[idx]->end.branchAddress);	}	d->free_prgs--;		/* queue the packet in the appropriate context queue */	list_add_tail(&packet->driver_list, &d->fifo_list);	d->prg_ind = (d->prg_ind+1)%d->num_desc;}/** This function fills the FIFO with the (eventual) pending packets* and runs or wakes up the DMA prg if necessary.** The function MUST be called with the d->lock held.*/ //called by:	ohci_transmit(),dma_trm_tasklet()//struct ti_ohci,struct dma_trm_ctx:	see ohci1394.h//struct hpsb_packet:									see ieee1394_core.hstatic int dma_trm_flush(struct ti_ohci *ohci, struct dma_trm_ctx *d){	struct hpsb_packet *p;	int idx,z;		if (list_empty(&d->pending_list) || d->free_prgs == 0)		return 0;		p = driver_packet(d->pending_list.next);	idx = d->prg_ind;	z = (p->data_size) ? 3 : 2;		/* insert the packets into the dma fifo */	while (d->free_prgs > 0 && !list_empty(&d->pending_list)) {		struct hpsb_packet *p = driver_packet(d->pending_list.next);		list_del(&p->driver_list);		insert_packet(ohci, d, p);	}		if (d->free_prgs == 0)		DBGMSG(ohci->id, "Transmit DMA FIFO ctx=%d is full... waiting", d->ctx);			/* Is the context running ? (should be unless it is 	   the first packet to be sent in this context) */	//OHCI1394_IsoRcvContextControlSet:0x400,see pdf_doc,138	if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) {		//may see pdf_doc,p80,p119

⌨️ 快捷键说明

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