📄 vic068vme.c
字号:
/* vic068.c - VTC VMEbus Interface Controller (VIC068) *//* Copyright 1984-1996 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01h,20dec96,dat fixed SPR 3430, bug in sysIntDisable.01g,11jul96,wlf doc: more cleanup.01f,11jul96,wlf doc: cleanup.01e,13jun96,wlf doc: cleanup and spelling chgs to a printf and logMsg.01d,09Aug95,kkk fix warnings for i960 (spr# 4177)01c,25apr94,wmd Changed line to correctly test range of interrupt level.01b,02mar93,ccc removed reference to HKV960, fixed warnings.01a,02oct92,ccc written.*//*DESCRIPTIONThis library provides VMEbus Interface Controller (VIC) routines.*//* LINTLIBRARY */#include "drv/vme/vic068.h"/* locals */struct mailbox { FUNCPTR sysMailboxRoutine; /* routine called upon interrupt */ int sysMailboxArg; /* argument passed to routine */ BOOL sysMailboxConnected; /* mail connected state */ } mailTab[] = { {((FUNCPTR) logMsg), ((int) "mailbox0 interrupt\n"), FALSE}, {((FUNCPTR) logMsg), ((int) "mailbox1 interrupt\n"), FALSE}, {((FUNCPTR) logMsg), ((int) "mailbox2 interrupt\n"), FALSE}, {((FUNCPTR) logMsg), ((int) "mailbox3 interrupt\n"), FALSE}, {((FUNCPTR) logMsg), ((int) "mailbox4 interrupt\n"), FALSE}, {((FUNCPTR) logMsg), ((int) "mailbox5 interrupt\n"), FALSE}, {((FUNCPTR) logMsg), ((int) "mailbox6 interrupt\n"), FALSE}, {((FUNCPTR) logMsg), ((int) "mailbox7 interrupt\n"), FALSE} };/* temp routines for sysMailboxConnect */LOCAL FUNCPTR tmpMailboxRoutine = (FUNCPTR) logMsg;LOCAL int tmpMailboxArg = (int) "mailbox interrupt\n";LOCAL BOOL tmpMailboxConnected = FALSE;LOCAL char * sysMailboxBase = 0;/* forward declarations */UINT8 sysVMEIntAck ();/******************************************************************************** sysBusIntGen - generate a bus interrupt** This routine generates a bus interrupt of a specified level with a* specified vector.** RETURNS: OK, or ERROR if <sysIntLvl> is out of range or the board cannot* generate a bus interrupt.** SEE ALSO: sysBusIntAck()*/STATUS sysBusIntGen ( INT32 sysIntLvl, /* bus interrupt level to generate (1-7) */ INT32 vector /* interrupt vector to generate (0-255) */ ) { int sysIplNo = DEFAULT_IPL; /* check to see if sysIntLvl and IPL are in range */ if ((sysIntLvl < 1) || (sysIntLvl > 7)) return (ERROR); /* check for unacknowledged interrupt */ if (*VIC_VIRSR & (1 << sysIntLvl)) { logMsg ("Unacknowledged interrupt present on VMEbus.\n"); return (ERROR); } /* write vector to appropriate location */ *(VIC_VIVR1 + (sysIntLvl - 1) * 4) = (UINT8) vector; *VIC_VIRSR = (1 | (1 << sysIntLvl)); /* generate the VME interrupt */ *(VIC_VIICR) = 0x80 | sysIplNo; return (OK); }/********************************************************************************* sysMailboxInt - handle a mailbox interrupt** This routine handles mailbox interrupts. The icg and icm switches will * generate an interrupt on a clear to set transition. The mailboxes are * numbered here from 0-7 (icgs 1-4: mailbox 0-3, icms 1-4: mailbox 4-7.** The icgs mailboxes are cleared by writing to the clear address of the * associated mailbox. This isn't necessary with the icms mailboxes but it* would function the same if the icms clear was written to.*/LOCAL void sysMailboxInt (void) { UINT8 iack = 0; /* interrupt vector */ int box; /* mailbox pointer into the mailTab array */ UINT8 ipl; /* ipl number of interrupting mailbox */ UINT8 switchReg; /* interrupting mailbox */ UINT32 ix; /* * Acknowledge the interrupt based on the ipl number. The ipl number is * determined by which mailbox set (icgs or icms) caused the interrupt and * the appropriate interrupt control register is read */ switchReg = *VIC_ICSR; /* retrieve the ipl number from the requested mailbox's Int control reg */ ipl = (switchReg & 0xf) ? (*VIC_ICMICR & ICMICR_IRQ_LVL_MASK) : (*VIC_ICGICR & ICGICR_IRQ_LVL_MASK); switch (ipl) { case TARGET_IPL0: iack = *VIC_IACK_IPL0; break; case TARGET_IPL1: iack = *VIC_IACK_IPL1; break; case TARGET_IPL2: iack = *VIC_IACK_IPL2; break; default: logMsg ("VIC mailbox interrupt error. Wrong ipl number.\n"); } /* determine the mailbox number based on the status register */ switch (switchReg) { case 0x1 : case 0x2 : case 0x4 : case 0x8 : box = (iack & 0x3) + 4; /* the mailbox is passed in with the */ /* vector number (lower 2 bits) */ break; case 0x10: box = 3; break; case 0x20: box = 2; break; case 0x40: box = 1; break; case 0x80: box = 0; break; default: logMsg ("VIC mailbox interrupt error. Wrong switch number.\n"); box = 7; } /* clear the the interrupt by writing to the clear address associated with * the mailbox that got hit */ if (box < 4) /* clear the icgs box */ *VIC_ICSR &= 0x0f & ~(switchReg); else /* clear the icms side of interrupt status register */ *VIC_ICSR &= 0xf0 & (~switchReg); /* call mailbox service routine */ if (mailTab[box].sysMailboxRoutine != NULL) (*mailTab[box].sysMailboxRoutine) (mailTab[box].sysMailboxArg);#ifdef DEBUG if (*VIC_ICSR) logMsg ("missed interrupt\n"); /**/#endif /* DEBUG */ vxIPNDClear (ipl); /* clear pending bit in IPND reg */ for (ix = 0; ix < 16; ix++) ; /* required to provide settling time */ }/******************************************************************************** sysMailboxEnable - enable the mailbox interrupt** This routine enables the mailbox interrupt. It should be called* after sysMailboxConnect(). ** The mailbox table is filled in based on what was done in* sysMailboxConnect(). There are eight mailboxes to choose from. The* mailbox used is determined from the address of the mailbox to be enabled.* Zero is reserved for the backplane driver.** RETURNS: OK, always.** SEE ALSO: sysMailboxConnect()*/STATUS sysMailboxEnable ( char *mailboxAdrs /* mailbox address */ ) { UINT8 mask; UINT8 boxNum; /* mailbox number to enable */ UINT8 boxSet; /* interprocessor or global mailbox */ /* determine the mailbox number based on the A1-A3 address lines */ boxNum = (((UINT8) (int) mailboxAdrs & 0x0e) >> 1); /* determine which mailbox set based on A4/A5 address lines */ boxSet = (UINT8) (int) mailboxAdrs & (VME_ICGS | VME_ICMS); boxNum += (boxSet == VME_ICMS) ? 4 : 0; if (mailTab[boxNum].sysMailboxConnected) return (ERROR); /* already used try another */ mailTab[boxNum].sysMailboxRoutine = tmpMailboxRoutine; mailTab[boxNum].sysMailboxArg = tmpMailboxArg; mailTab[boxNum].sysMailboxConnected = tmpMailboxConnected; /* reinitialize the temporary mailbox variables */ tmpMailboxRoutine = (FUNCPTR) logMsg; tmpMailboxArg = (int) "mailbox interrupt\n"; tmpMailboxConnected = FALSE; if (intConnect ((VOIDFUNCPTR *) INT_VEC_MBOX, (VOIDFUNCPTR) sysMailboxInt, 0) == ERROR) { printf ("had an error connecting to interrupt\n"); return (ERROR); } /* set mailbox base address and save for future reference */ sysMailboxBase = (char *) ((UINT32)mailboxAdrs & 0xffffff00); if (boxSet == (UINT8) VME_ICMS) /* read current mailbox configuration */ mask = *VIC_ICMICR; else mask = *VIC_ICGICR;#ifdef DEBUG if (bpDebug & 0x4) printf ("BoxEnable -- mailboxAdrs: %#x mbox >> 8: %#x mask: %#x boxSet: %#x\n", mailboxAdrs, (UINT32) mailboxAdrs >> 8, mask, boxSet);#endif /* DEBUG */ /* set the box enable bit */ mask &= (boxSet == VME_ICMS) ? ~(1 << boxNum) : ~(1 << (boxNum + 4));#ifdef DEBUG if (bpDebug & 0x4) printf ("BoxEnable-- ~(1 << equ) : %#x\n", (boxSet == VME_ICMS) ? ~(1 << boxNum) : ~(1 << (boxNum + 4)));#endif /* DEBUG */ mask = (mask & 0xF8) + VIC_MAILBOX_IPL0; /* set the IPL number */#ifdef DEBUG if (bpDebug & 0x4) printf ("sysMailboxBase: %#x boxNum: %#x mask: %#x\n", sysMailboxBase, boxNum, mask);#endif /* DEBUG */ *VIC_ICSR = 0x0; /* clear mailbox flags */ if (boxSet == VME_ICMS) /* enable the selected mailbox */ *VIC_ICMICR = mask; else *VIC_ICGICR = mask; *VIC_ICGIVBR = INT_VEC_MBOX; *VIC_ICMIVBR = INT_VEC_MBOX; /* enable the 960 interrupt mask register based on the ipl number in the * interrupt control register. */ vxIMRSet (mask & 0x3); return (OK); }/******************************************************************************** sysMailboxConnect - connect a routine to the mailbox interrupt** This routine specifies the interrupt service routine to be called at each* mailbox interrupt. It should be called before* sysMailboxEnable(). ** This routine sets up temporary variables until the box number is* determined. The mailbox number is determined from the address passed into* sysMailboxEnable().** RETURNS: OK, or ERROR if the routine cannot be connected to the interrupt.** SEE ALSO: intConnect(), sysMailboxEnable()*/STATUS sysMailboxConnect ( FUNCPTR routine, /* routine called at each mailbox interrupt */ int arg /* argument with which to call routine */ ) {#ifdef DEBUG if (bpDebug & 0x4) printf ("sysMailBoxConnect-- routine: %#x, arg: %#x\n", routine, arg);#endif /* DEBUG */ if (tmpMailboxConnected) return (ERROR); /* tried to connect another routine before enabling */ /* last routine connected. See sysMailboxEnable *//* put the passed parameters in temporary storage until mailbox is enabled */ tmpMailboxRoutine = routine; tmpMailboxArg = arg; tmpMailboxConnected = TRUE; return (OK); }/******************************************************************************** sysBusTas - test and set a location across the bus** This routine performs a 80960 test-and-set instruction across the backplane.** RETURNS: TRUE if the value had not been set but is now, or FALSE if the value* was set already.** SEE ALSO: vxTas()*/BOOL sysBusTas ( char *addr /* address to be tested and set */ ) { volatile UINT dummy; UINT oldRelCntrl; BOOL retVal; /* get current state of release control register */ oldRelCntrl = *VIC_RCR; /* tell the vic to release the bus only when done */ *VIC_RCR = RCR_RWD; dummy = *addr; /* attempt to grab the bus for good measure */ retVal = vxTas (addr); /* put release control register back to previous state */ *VIC_RCR = oldRelCntrl;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -