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

📄 vmeuniverse.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
			l->address = x;			return 1;		}	}	return 0;}static intmapOverAll(int ismaster, int (*func)(int,int,volatile LERegister *,void*), void *arg){#define base	vmeUniverse0BaseAddrvolatile LERegister	*rptr;unsigned long	port;int	rval;	/* get the universe base address */	if (!base && vmeUniverseInit()) {		uprintf(stderr,"unable to find the universe in pci config space\n");		return -1;	}	rptr = (base + 		(ismaster ? UNIV_REGOFF_PCITGT0_CTRL : UNIV_REGOFF_VMESLV0_CTRL)/sizeof(LERegister));#undef TSILL#ifdef TSILL	uprintf(stderr,"mapoverall: base is 0x%08x, rptr 0x%08x\n",base,rptr);#endif#undef TSILL	for (port=0; port<4; port++) {		if ((rval=func(ismaster,port,rptr,arg))) return rval;		rptr+=5; /* register block spacing */	}	/* only rev. 2 has 8 ports */	if (UNIV_REV(base)<2) return -1;	rptr = (base + 		(ismaster ? UNIV_REGOFF_PCITGT4_CTRL : UNIV_REGOFF_VMESLV4_CTRL)/sizeof(LERegister));	for (port=4; port<UNIV_NUM_MPORTS; port++) {		if ((rval=func(ismaster,port,rptr,arg))) return rval;		rptr+=5; /* register block spacing */	}	return 0;#undef base}static voidshowUniversePorts(int ismaster, FILE *f){	if (!f) f=stdout;	uprintf(f,"Universe %s Ports:\n",ismaster ? "Master" : "Slave");	uprintf(f,"Port  VME-Addr   Size       PCI-Adrs   Mode:\n");	mapOverAll(ismaster,showUniversePort,f);}intvmeUniverseXlateAddr(	int master, 		/* look in the master windows */	int reverse,		/* reverse mapping; for masters: map local to VME */	unsigned long as,	/* address space */	unsigned long aIn,	/* address to look up */	unsigned long *paOut/* where to put result */	){int	rval;XlatRec l;	l.aspace  = as;	l.address = aIn;	l.reverse = reverse;	/* map result -1/0/1 to -2/-1/0 with 0 on success */	rval = mapOverAll(master,xlatePort,(void*)&l) - 1;	*paOut = l.address;	return rval;}voidvmeUniverseReset(void){	/* disable/reset special cycles (ADOH, RMW) */	vmeUniverseWriteReg(0, UNIV_REGOFF_SCYC_CTL);	vmeUniverseWriteReg(0, UNIV_REGOFF_SCYC_ADDR);	vmeUniverseWriteReg(0, UNIV_REGOFF_SCYC_EN);	/* set coupled window timeout to 0 (release VME after each transaction)	 * CRT (coupled request timeout) is unused by Universe II	 */	vmeUniverseWriteReg(UNIV_LMISC_CRT_128_US, UNIV_REGOFF_LMISC);	/* disable/reset DMA engine */	vmeUniverseWriteReg(0, UNIV_REGOFF_DCTL);	vmeUniverseWriteReg(0, UNIV_REGOFF_DTBC);	vmeUniverseWriteReg(0, UNIV_REGOFF_DLA);	vmeUniverseWriteReg(0, UNIV_REGOFF_DVA);	vmeUniverseWriteReg(0, UNIV_REGOFF_DCPP);	/* disable location monitor */	vmeUniverseWriteReg(0, UNIV_REGOFF_LM_CTL);	/* disable universe register access from VME bus */	vmeUniverseWriteReg(0, UNIV_REGOFF_VRAI_CTL);	/* disable VME bus image of VME CSR */	vmeUniverseWriteReg(0, UNIV_REGOFF_VCSR_CTL);	/* I had problems with a Joerger vtr10012_8 card who would	 * only be accessible after tweaking the U2SPEC register	 * (the t27 parameter helped).	 * I use the same settings here that are used by the	 * Synergy VGM-powerpc BSP for vxWorks.	 */	if (2==UNIV_REV(vmeUniverse0BaseAddr))		vmeUniverseWriteReg(UNIV_U2SPEC_DTKFLTR |						UNIV_U2SPEC_MASt11   |						UNIV_U2SPEC_READt27_NODELAY |						UNIV_U2SPEC_POSt28_FAST |						UNIV_U2SPEC_PREt28_FAST,						UNIV_REGOFF_U2SPEC);	/* disable interrupts, reset routing */	vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_EN);	vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_MAP0);	vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_MAP1);	vmeUniverseWriteReg(0, UNIV_REGOFF_VINT_EN);	vmeUniverseWriteReg(0, UNIV_REGOFF_VINT_MAP0);	vmeUniverseWriteReg(0, UNIV_REGOFF_VINT_MAP1);	vmeUniverseDisableAllSlaves();	vmeUniverseDisableAllMasters();		vmeUniverseWriteReg(UNIV_VCSR_CLR_SYSFAIL, UNIV_REGOFF_VCSR_CLR);	/* clear interrupt status bits */	vmeUniverseWriteReg(UNIV_LINT_STAT_CLR, UNIV_REGOFF_LINT_STAT);	vmeUniverseWriteReg(UNIV_VINT_STAT_CLR, UNIV_REGOFF_VINT_STAT);	vmeUniverseWriteReg(UNIV_V_AMERR_V_STAT, UNIV_REGOFF_V_AMERR);	vmeUniverseWriteReg(		vmeUniverseReadReg(UNIV_REGOFF_PCI_CSR) |		UNIV_PCI_CSR_D_PE | UNIV_PCI_CSR_S_SERR | UNIV_PCI_CSR_R_MA |		UNIV_PCI_CSR_R_TA | UNIV_PCI_CSR_S_TA,		UNIV_REGOFF_PCI_CSR);	vmeUniverseWriteReg(UNIV_L_CMDERR_L_STAT, UNIV_REGOFF_L_CMDERR);	vmeUniverseWriteReg(		UNIV_DGCS_STOP | UNIV_DGCS_HALT | UNIV_DGCS_DONE |		UNIV_DGCS_LERR | UNIV_DGCS_VERR | UNIV_DGCS_P_ERR,		UNIV_REGOFF_DGCS);}intvmeUniverseInit(void){int rval;	if ((rval=vmeUniverseFindPciBase(0,&vmeUniverse0BaseAddr))) {		uprintf(stderr,"unable to find the universe in pci config space\n");	} else {		uprintf(stderr,"Universe II PCI-VME bridge detected at 0x%08x, IRQ %d\n",				(unsigned int)vmeUniverse0BaseAddr, vmeUniverse0PciIrqLine);	}	return rval;}voidvmeUniverseMasterPortsShow(FILE *f){	showUniversePorts(1,f);}voidvmeUniverseSlavePortsShow(FILE *f){	showUniversePorts(0,f);}intvmeUniverseMasterPortCfg(	unsigned long	port,	unsigned long	address_space,	unsigned long	vme_address,	unsigned long	local_address,	unsigned long	length){	return cfgUniversePort(1,port,address_space,vme_address,local_address,length);}intvmeUniverseSlavePortCfg(	unsigned long	port,	unsigned long	address_space,	unsigned long	vme_address,	unsigned long	local_address,	unsigned long	length){	return cfgUniversePort(0,port,address_space,vme_address,local_address,length);}voidvmeUniverseDisableAllSlaves(void){	mapOverAll(0,disableUniversePort,0);}voidvmeUniverseDisableAllMasters(void){	mapOverAll(1,disableUniversePort,0);}intvmeUniverseStartDMA(	unsigned long local_addr,	unsigned long vme_addr,	unsigned long count){	if (!vmeUniverse0BaseAddr && vmeUniverseInit()) return -1;	if ((local_addr & 7) != (vme_addr & 7)) {		uprintf(stderr,"vmeUniverseStartDMA: misaligned addresses\n");		return -1;	}	{	/* help the compiler allocate registers */	register volatile LERegister *b=vmeUniverse0BaseAddr;	register unsigned long dgcsoff=UNIV_REGOFF_DGCS,dgcs;	dgcs=READ_LE(b, dgcsoff);	/* clear status and make sure CHAIN is clear */	dgcs &= ~UNIV_DGCS_CHAIN;	WRITE_LE(dgcs,		      b, dgcsoff);	WRITE_LE(local_addr,		      b, UNIV_REGOFF_DLA);	WRITE_LE(vme_addr,		      b, UNIV_REGOFF_DVA);	WRITE_LE(count,		      b, UNIV_REGOFF_DTBC);	dgcs |= UNIV_DGCS_GO;	EIEIO_REG; /* make sure GO is written after everything else */	WRITE_LE(dgcs,		      b, dgcsoff);	}	SYNC; /* enforce command completion */	return 0;}unsigned longvmeUniverseReadReg(unsigned long offset){unsigned long rval;	rval = READ_LE(vmeUniverse0BaseAddr,offset);	return rval;}voidvmeUniverseWriteReg(unsigned long value, unsigned long offset){	WRITE_LE(value, vmeUniverse0BaseAddr, offset);}voidvmeUniverseCvtToLE(unsigned long *ptr, unsigned long num){#if !defined(__LITTLE_ENDIAN__) || (__LITTLE_ENDIAN__ != 1)register unsigned long *p=ptr+num;	while (p > ptr) {#if (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)		__asm__ __volatile__(			"lwzu 0, -4(%0)\n"			"stwbrx 0, 0, %0\n"			: "=r"(p) : "r"(p) : "r0"			);#elif defined(__rtems__)		p--; st_le32(p, *p);#else#error	"vmeUniverse: endian conversion not implemented for this architecture"#endif	}#endif}/* RTEMS interrupt subsystem */#ifdef __rtems__#include <bsp/irq.h>typedef structUniverseIRQEntryRec_ {		VmeUniverseISR	isr;		void			*usrData;} UniverseIRQEntryRec, *UniverseIRQEntry;static UniverseIRQEntry universeHdlTbl[UNIV_NUM_INT_VECS]={0};int        vmeUniverseIrqMgrInstalled=0;static int vmeIrqUnivOut=-1;static int specialIrqUnivOut=-1;VmeUniverseISRvmeUniverseISRGet(unsigned long vector, void **parg){	if (vector>=UNIV_NUM_INT_VECS ||		! universeHdlTbl[vector])		return 0;	if (parg)		*parg=universeHdlTbl[vector]->usrData;	return universeHdlTbl[vector]->isr;}static voiduniverseSpecialISR(void){register UniverseIRQEntry	ip;register unsigned			vec;register unsigned long		status;	status=vmeUniverseReadReg(UNIV_REGOFF_LINT_STAT);	/* scan all LINT bits except for the 'normal' VME interrupts */	/* do VOWN first */	vec=UNIV_VOWN_INT_VEC;	if ( (status & UNIV_LINT_STAT_VOWN) && (ip=universeHdlTbl[vec]))		ip->isr(ip->usrData,vec);	/* now continue with DMA and scan through all bits;	 * we assume the vectors are in the right order!	 *	 * The initial right shift brings the DMA bit into position 0;	 * the loop is left early if there are no more bits set.	 */	for (status>>=8; status; status>>=1) {		vec++;		if ((status&1) && (ip=universeHdlTbl[vec]))			ip->isr(ip->usrData,vec);	}	/* clear all special interrupts */	vmeUniverseWriteReg(					~((UNIV_LINT_STAT_VIRQ7<<1)-UNIV_LINT_STAT_VIRQ1),					UNIV_REGOFF_LINT_STAT					);/* *	clear our line in the VINT_STAT register *  seems to be not neccessary...	vmeUniverseWriteReg(					UNIV_VINT_STAT_LINT(specialIrqUnivOut),					UNIV_REGOFF_VINT_STAT); */}/* * interrupts from VME to PCI seem to be processed more or less * like this: * * *   VME IRQ ------  *                  & ----- LINT_STAT ----  *                  |                       &  ---------- PCI LINE *                  |                       | *                  |                       |  *       LINT_EN ---------------------------  * *  I.e.  *   - if LINT_EN is disabled, a VME IRQ will not set LINT_STAT. *   - while LINT_STAT is set, it will pull the PCI line unless *     masked by LINT_EN. *   - VINT_STAT(lint_bit) seems to have no effect beyond giving *     status info. * *  Hence, it is possible to *    - arm (set LINT_EN, routing etc.) *    - receive an irq (sets. LINT_STAT) *    - the ISR then: *      	  * clears LINT_EN, results in masking LINT_STAT (which *      	    is still set to prevent another VME irq at the same *      	    level to be ACKEd by the universe. *      	  * do PCI_EOI to allow nesting of higher VME irqs. *      	    (previous step also cleared LINT_EN of lower levels) *      	  * when the handler returns, clear LINT_STAT *      	  * re-enable setting LINT_EN. */static voiduniverseVMEISR(void){UniverseIRQEntry ip;unsigned long lvl,msk,lintstat,linten,status;		/* determine the highest priority IRQ source */		lintstat=vmeUniverseReadReg(UNIV_REGOFF_LINT_STAT);		for (msk=UNIV_LINT_STAT_VIRQ7, lvl=7;			 lvl>0;			 lvl--, msk>>=1) {			if (lintstat & msk) break;		}		if (!lvl) {				/* try the special handler */				universeSpecialISR();				/* 				 * let the pic end this cycle				 */				BSP_PIC_DO_EOI;				return;		}		linten = vmeUniverseReadReg(UNIV_REGOFF_LINT_EN);		/* mask this and all lower levels */		vmeUniverseWriteReg(						linten & ~((msk<<1)-UNIV_LINT_STAT_VIRQ1),						UNIV_REGOFF_LINT_EN						);		/* end this interrupt		 * cycle on the PCI bus, so higher level interrupts can be		 * caught from now on...		 */		BSP_PIC_DO_EOI;		/* get vector and dispatch handler */		status = vmeUniverseReadReg(UNIV_REGOFF_VIRQ1_STATID - 4 + (lvl<<2));		/* determine the highest priority IRQ source */		if (status & UNIV_VIRQ_ERR) {				/* TODO: log error message - RTEMS has no logger :-( */		} else if (!(ip=universeHdlTbl[status & UNIV_VIRQ_STATID_MASK])) {				/* TODO: log error message - RTEMS has no logger :-( */		} else {				/* dispatch handler, it must clear the IRQ at the device */				ip->isr(ip->usrData, status&UNIV_VIRQ_STATID_MASK);		}		/* clear this interrupt level */		vmeUniverseWriteReg(msk, UNIV_REGOFF_LINT_STAT);/* *  this seems not to be necessary; we just leave the *  bit set to save a couple of instructions...		vmeUniverseWriteReg(					UNIV_VINT_STAT_LINT(vmeIrqUnivOut),					UNIV_REGOFF_VINT_STAT);*/		/* re-enable the previous level */		vmeUniverseWriteReg(linten, UNIV_REGOFF_LINT_EN);}/* STUPID API */static voidmy_no_op(const rtems_irq_connect_data * arg){}static intmy_isOn(const rtems_irq_connect_data *arg){		return (int)vmeUniverseReadReg(UNIV_REGOFF_LINT_EN);}intvmeUniverseInstallIrqMgr(int vmeOut,						 int vmeIrqPicLine,						 int specialOut,						 int specialIrqPicLine){rtems_irq_connect_data aarrggh;	/* check parameters */	if ((vmeIrqUnivOut=vmeOut) < 0 || vmeIrqUnivOut > 7) return -1;	if ((specialIrqUnivOut=specialOut) > 7) return -2;	if (specialOut >=0 && specialIrqPicLine < 0) return -3;	/* give them a chance to override buggy PCI info */	if (vmeIrqPicLine >= 0) {		uprintf(stderr,"Overriding main IRQ line PCI info with %d\n",				vmeIrqPicLine);		vmeUniverse0PciIrqLine=vmeIrqPicLine;	}	if (vmeUniverseIrqMgrInstalled) return -4;	aarrggh.on=my_no_op; /* at _least_ they could check for a 0 pointer */	aarrggh.off=my_no_op;	aarrggh.isOn=my_isOn;	aarrggh.hdl=universeVMEISR;	aarrggh.name=vmeUniverse0PciIrqLine + BSP_PCI_IRQ0;	if (!BSP_install_rtems_irq_handler(&aarrggh))			BSP_panic("unable to install vmeUniverse irq handler");	if (specialIrqUnivOut > 0) {			/* install the special handler to a separate irq */			aarrggh.hdl=universeSpecialISR;			aarrggh.name=specialIrqPicLine + BSP_PCI_IRQ0;			if (!BSP_install_rtems_irq_handler(&aarrggh))				BSP_panic("unable to install vmeUniverse secondary irq handler");	} else {		specialIrqUnivOut = vmeIrqUnivOut;	}	/* setup routing */	vmeUniverseWriteReg(		(UNIV_LINT_MAP0_VIRQ7(vmeIrqUnivOut) |		 UNIV_LINT_MAP0_VIRQ6(vmeIrqUnivOut) |		 UNIV_LINT_MAP0_VIRQ5(vmeIrqUnivOut) |		 UNIV_LINT_MAP0_VIRQ4(vmeIrqUnivOut) |		 UNIV_LINT_MAP0_VIRQ3(vmeIrqUnivOut) |		 UNIV_LINT_MAP0_VIRQ2(vmeIrqUnivOut) |		 UNIV_LINT_MAP0_VIRQ1(vmeIrqUnivOut) |		 UNIV_LINT_MAP0_VOWN(specialIrqUnivOut)		),		UNIV_REGOFF_LINT_MAP0);	vmeUniverseWriteReg(		(UNIV_LINT_MAP1_ACFAIL(specialIrqUnivOut) |		 UNIV_LINT_MAP1_SYSFAIL(specialIrqUnivOut) |		 UNIV_LINT_MAP1_SW_INT(specialIrqUnivOut) |		 UNIV_LINT_MAP1_SW_IACK(specialIrqUnivOut) |		 UNIV_LINT_MAP1_VERR(specialIrqUnivOut) |		 UNIV_LINT_MAP1_LERR(specialIrqUnivOut) |		 UNIV_LINT_MAP1_DMA(specialIrqUnivOut)		),		UNIV_REGOFF_LINT_MAP1);	vmeUniverseIrqMgrInstalled=1;	return 0;}intvmeUniverseInstallISR(unsigned long vector, VmeUniverseISR hdl, void *arg){UniverseIRQEntry ip;		if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !vmeUniverseIrqMgrInstalled)				return -1;		ip=universeHdlTbl[vector];		if (ip || !(ip=(UniverseIRQEntry)malloc(sizeof(UniverseIRQEntryRec))))				return -1;		ip->isr=hdl;		ip->usrData=arg;		universeHdlTbl[vector]=ip;		return 0;}intvmeUniverseRemoveISR(unsigned long vector, VmeUniverseISR hdl, void *arg){UniverseIRQEntry ip;		if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !vmeUniverseIrqMgrInstalled)				return -1;		ip=universeHdlTbl[vector];		if (!ip || ip->isr!=hdl || ip->usrData!=arg)				return -1;		universeHdlTbl[vector]=0;		free(ip);		return 0;}intvmeUniverseIntEnable(unsigned int level){		if (!vmeUniverseIrqMgrInstalled || level<1 || level>7)				return -1;		vmeUniverseWriteReg(				(vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) | 				 (UNIV_LINT_EN_VIRQ1 << (level-1))				),				UNIV_REGOFF_LINT_EN);		return 0;}intvmeUniverseIntDisable(unsigned int level){		if (!vmeUniverseIrqMgrInstalled || level<1 || level>7)				return -1;		vmeUniverseWriteReg(				(vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) & 				 ~ (UNIV_LINT_EN_VIRQ1 << (level-1))				),				UNIV_REGOFF_LINT_EN);		return 0;}#endif

⌨️ 快捷键说明

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