forked from Imagelibrary/rtems
2003-02-20 Till Straumann <strauman@slac.stanford.edu>
PR 349/bsps * README.universe, vmeUniverse/README.porting vmeUniverse/README.universe, vmeUniverse/vmeUniverse.c, vmeUniverse/vmeUniverse.h: Update of the VME universe driver. * vmeUniverse/README.porting: New file.
This commit is contained in:
@@ -1,3 +1,11 @@
|
|||||||
|
2003-02-20 Till Straumann <strauman@slac.stanford.edu>
|
||||||
|
|
||||||
|
PR 349/bsps
|
||||||
|
* README.universe, vmeUniverse/README.porting
|
||||||
|
vmeUniverse/README.universe, vmeUniverse/vmeUniverse.c,
|
||||||
|
vmeUniverse/vmeUniverse.h: Update of the VME universe driver.
|
||||||
|
* vmeUniverse/README.porting: New file.
|
||||||
|
|
||||||
2002-10-28 Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
2002-10-28 Eugeny S. Mints <Eugeny.Mints@oktet.ru>
|
||||||
|
|
||||||
* ide_ctrl.c: New file.
|
* ide_ctrl.c: New file.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# $Id$
|
# $Id$
|
||||||
#
|
#
|
||||||
|
|
||||||
The vmeUniverse driver needs some support from the BSP for
|
The vmeUniverse driver needs some support from the BSP for
|
||||||
|
|||||||
@@ -6,7 +6,51 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
/*
|
||||||
* $Log$
|
* $Log$
|
||||||
|
* Revision 1.34 2003/02/10 23:20:05 till
|
||||||
|
* - added some macro magic to make porting easier (ppcn_60x BSP in mind)
|
||||||
|
* - made mgrInstalled public (vmeUniverseIrqMgrInstalled) so BSPs can
|
||||||
|
* supply their own versions of the mgrInstall() routine.
|
||||||
|
* - added READMEs to CVS
|
||||||
|
*
|
||||||
|
* Revision 1.33.2.1 2003/02/10 23:01:40 till
|
||||||
|
* - added some macro magic to make porting easier (ppcn_60x BSP in mind)
|
||||||
|
* - made mgrInstalled public (vmeUniverseIrqMgrInstalled) so BSPs can
|
||||||
|
* supply their own versions of the mgrInstall() routine.
|
||||||
|
*
|
||||||
|
* Revision 1.32 2002/09/05 02:50:41 till
|
||||||
|
* - use k_vsprintf(), not vsprintf() during early boot (RTEMS)
|
||||||
|
*
|
||||||
|
* Revision 1.31 2002/08/16 23:35:15 strauman
|
||||||
|
* - fixed typos
|
||||||
|
*
|
||||||
|
* Revision 1.30 2002/08/16 22:53:37 till
|
||||||
|
* - made address translation more generic; allow to look for reverse mappings
|
||||||
|
* also.
|
||||||
|
* - removed vmeUniverseLocalToBus() and vmeUniverseBusToLocal() and made
|
||||||
|
* vmeUniverseXlateAddr() public instead.
|
||||||
|
*
|
||||||
|
* Revision 1.29 2002/08/16 22:16:25 till
|
||||||
|
* - tweak U2SPEC (fix Joerger vtr10012_8 problem) the same
|
||||||
|
* way the synergy BSP does (rev 2 chips only)
|
||||||
|
*
|
||||||
|
* Revision 1.28 2002/08/15 23:16:01 till
|
||||||
|
* - bugfix: vmeUniverseISRGet() dereferenced a possibly NULL pointer
|
||||||
|
*
|
||||||
|
* Revision 1.25 2002/07/19 05:18:40 till
|
||||||
|
* - CVS log: again a problem. Cannot embed /_* *_/ comments in the log
|
||||||
|
* because the log has to be commented as a whole. I had tried
|
||||||
|
* #if 0 #endif - doesn't work because cpp expands char constants???
|
||||||
|
* WHAT A NUISANCE
|
||||||
|
*
|
||||||
|
* Revision 1.24 2002/07/19 02:44:14 till
|
||||||
|
* - added a new parameter to the IRQ manager install routine:
|
||||||
|
* the main interrupt's line can now also be specified (reading
|
||||||
|
* from PCI config does not always work - some boards don't
|
||||||
|
* have correct information there - PMC's will have a similar
|
||||||
|
* problem, though!)
|
||||||
|
*
|
||||||
* Revision 1.21 2002/04/11 06:54:48 till
|
* Revision 1.21 2002/04/11 06:54:48 till
|
||||||
* - silenced message about 'successfully configured a port'
|
* - silenced message about 'successfully configured a port'
|
||||||
*
|
*
|
||||||
@@ -32,14 +76,13 @@
|
|||||||
*
|
*
|
||||||
* Revision 1.15 2002/01/23 06:15:30 till
|
* Revision 1.15 2002/01/23 06:15:30 till
|
||||||
* - changed master port data width to 64 bit.
|
* - changed master port data width to 64 bit.
|
||||||
* /* NOTE: reading the CY961 (Echotek ECDR814) with VDW32
|
* NOTE: reading the CY961 (Echotek ECDR814) with VDW32
|
||||||
* * generated bus errors when reading 32-bit words
|
* generated bus errors when reading 32-bit words
|
||||||
* * - very weird, because the registers are 16-bit
|
* - very weird, because the registers are 16-bit
|
||||||
* * AFAIK.
|
* AFAIK.
|
||||||
* * - 32-bit accesses worked fine on vxWorks which
|
* - 32-bit accesses worked fine on vxWorks which
|
||||||
* * has the port set to 64-bit.
|
* has the port set to 64-bit.
|
||||||
* * ????????
|
* ????????
|
||||||
* */
|
|
||||||
*
|
*
|
||||||
* Revision 1.14 2002/01/11 19:30:54 till
|
* Revision 1.14 2002/01/11 19:30:54 till
|
||||||
* - added more register defines to header
|
* - added more register defines to header
|
||||||
@@ -55,7 +98,7 @@
|
|||||||
*
|
*
|
||||||
* Revision 1.11 2002/01/08 03:59:52 till
|
* Revision 1.11 2002/01/08 03:59:52 till
|
||||||
* - vxworks always defines _LITTLE_ENDIAN, fixed the conditionals
|
* - vxworks always defines _LITTLE_ENDIAN, fixed the conditionals
|
||||||
* so it should work on __vxworks and on __rtems now.
|
* so it should work on __vxworks and on __rtems__ now.
|
||||||
* - rtems uprintf wrapper reverts to printk if stdio is not yet
|
* - rtems uprintf wrapper reverts to printk if stdio is not yet
|
||||||
* initialized (uses _impure_ptr->__sdidinit)
|
* initialized (uses _impure_ptr->__sdidinit)
|
||||||
* - tested bus address translation utility routines
|
* - tested bus address translation utility routines
|
||||||
@@ -89,7 +132,7 @@
|
|||||||
*
|
*
|
||||||
* Revision 1.1.1.1 2001/07/12 23:15:19 till
|
* Revision 1.1.1.1 2001/07/12 23:15:19 till
|
||||||
* - cvs import
|
* - cvs import
|
||||||
*
|
*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -137,16 +180,23 @@
|
|||||||
/* we rely on a vxWorks definition here */
|
/* we rely on a vxWorks definition here */
|
||||||
#define VX_AM_SUP 4
|
#define VX_AM_SUP 4
|
||||||
|
|
||||||
#ifdef __rtems
|
#ifdef __rtems__
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <rtems/bspIo.h> /* printk */
|
#include <rtems/bspIo.h> /* printk */
|
||||||
#include <bsp/pci.h>
|
#include <bsp/pci.h>
|
||||||
#include <bsp.h>
|
#include <bsp.h>
|
||||||
|
|
||||||
#define pciFindDevice BSP_pciFindDevice
|
/* allow the BSP to override the default routines */
|
||||||
#define pciConfigInLong pci_read_config_dword
|
#ifndef BSP_PCI_FIND_DEVICE
|
||||||
#define pciConfigInByte pci_read_config_byte
|
#define BSP_PCI_FIND_DEVICE BSP_pciFindDevice
|
||||||
|
#endif
|
||||||
|
#ifndef BSP_PCI_CONFIG_IN_LONG
|
||||||
|
#define BSP_PCI_CONFIG_IN_LONG pci_read_config_dword
|
||||||
|
#endif
|
||||||
|
#ifndef BSP_PCI_CONFIG_IN_BYTE
|
||||||
|
#define BSP_PCI_CONFIG_IN_BYTE pci_read_config_byte
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef unsigned int pci_ulong;
|
typedef unsigned int pci_ulong;
|
||||||
#define PCI_TO_LOCAL_ADDR(memaddr) ((pci_ulong)(memaddr) + PCI_MEM_BASE)
|
#define PCI_TO_LOCAL_ADDR(memaddr) ((pci_ulong)(memaddr) + PCI_MEM_BASE)
|
||||||
@@ -155,11 +205,16 @@ typedef unsigned int pci_ulong;
|
|||||||
#elif defined(__vxworks)
|
#elif defined(__vxworks)
|
||||||
typedef unsigned long pci_ulong;
|
typedef unsigned long pci_ulong;
|
||||||
#define PCI_TO_LOCAL_ADDR(memaddr) (memaddr)
|
#define PCI_TO_LOCAL_ADDR(memaddr) (memaddr)
|
||||||
#define PCI_INTERRUPT_LINE 0x3c
|
#define BSP_PCI_FIND_DEVICE pciFindDevice
|
||||||
|
#define BSP_PCI_CONFIG_IN_LONG pciConfigInLong
|
||||||
|
#define BSP_PCI_CONFIG_IN_BYTE pciConfigInByte
|
||||||
#else
|
#else
|
||||||
#error "vmeUniverse not ported to this architecture yet"
|
#error "vmeUniverse not ported to this architecture yet"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef PCI_INTERRUPT_LINE
|
||||||
|
#define PCI_INTERRUPT_LINE 0x3c
|
||||||
|
#endif
|
||||||
|
|
||||||
volatile LERegister *vmeUniverse0BaseAddr=0;
|
volatile LERegister *vmeUniverse0BaseAddr=0;
|
||||||
int vmeUniverse0PciIrqLine=-1;
|
int vmeUniverse0PciIrqLine=-1;
|
||||||
@@ -192,7 +247,7 @@ WRITE_LE(
|
|||||||
#elif (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
|
#elif (defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC)) && (__BIG_ENDIAN__ == 1)
|
||||||
/* offset is in bytes and MUST not end up in r0 */
|
/* offset is in bytes and MUST not end up in r0 */
|
||||||
__asm__ __volatile__("stwbrx %1, %0, %2" :: "b"(off),"r"(val),"r"(adrs));
|
__asm__ __volatile__("stwbrx %1, %0, %2" :: "b"(off),"r"(val),"r"(adrs));
|
||||||
#elif defined(__rtems)
|
#elif defined(__rtems__)
|
||||||
st_le32((volatile unsigned long*)(((unsigned long)adrs)+off), val);
|
st_le32((volatile unsigned long*)(((unsigned long)adrs)+off), val);
|
||||||
#else
|
#else
|
||||||
#error "little endian register writing not implemented"
|
#error "little endian register writing not implemented"
|
||||||
@@ -221,7 +276,7 @@ READ_LE0(volatile LERegister *adrs)
|
|||||||
register unsigned long rval;
|
register unsigned long rval;
|
||||||
__asm__ __volatile__("lwbrx %0, 0, %1":"=r"(rval):"r"(adrs));
|
__asm__ __volatile__("lwbrx %0, 0, %1":"=r"(rval):"r"(adrs));
|
||||||
return rval;
|
return rval;
|
||||||
#elif defined(__rtems)
|
#elif defined(__rtems__)
|
||||||
return ld_le32((volatile unsigned long*)adrs);
|
return ld_le32((volatile unsigned long*)adrs);
|
||||||
#else
|
#else
|
||||||
#error "little endian register reading not implemented"
|
#error "little endian register reading not implemented"
|
||||||
@@ -254,17 +309,18 @@ return READ_LE0((volatile LERegister *)(((unsigned long)adrs)+off));
|
|||||||
|
|
||||||
#define UNIV_REV(base) (READ_LE(base,2*sizeof(LERegister)) & 0xff)
|
#define UNIV_REV(base) (READ_LE(base,2*sizeof(LERegister)) & 0xff)
|
||||||
|
|
||||||
#ifdef __rtems
|
#ifdef __rtems__
|
||||||
static int
|
static int
|
||||||
uprintk(char *fmt, va_list ap)
|
uprintk(char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
int rval;
|
int rval;
|
||||||
|
extern int k_vsprintf(char *, char *, va_list);
|
||||||
/* during bsp init, there is no malloc and no stdio,
|
/* during bsp init, there is no malloc and no stdio,
|
||||||
* hence we assemble the message on the stack and revert
|
* hence we assemble the message on the stack and revert
|
||||||
* to printk
|
* to printk
|
||||||
*/
|
*/
|
||||||
char buf[200];
|
char buf[200];
|
||||||
rval = vsprintf(buf,fmt,ap);
|
rval = k_vsprintf(buf,fmt,ap);
|
||||||
if (rval > sizeof(buf))
|
if (rval > sizeof(buf))
|
||||||
BSP_panic("vmeUniverse/uprintk: buffer overrun");
|
BSP_panic("vmeUniverse/uprintk: buffer overrun");
|
||||||
printk(buf);
|
printk(buf);
|
||||||
@@ -280,7 +336,7 @@ uprintf(FILE *f, char *fmt, ...)
|
|||||||
va_list ap;
|
va_list ap;
|
||||||
int rval;
|
int rval;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
#ifdef __rtems
|
#ifdef __rtems__
|
||||||
if (!f || !_impure_ptr->__sdidinit) {
|
if (!f || !_impure_ptr->__sdidinit) {
|
||||||
/* Might be called at an early stage when
|
/* Might be called at an early stage when
|
||||||
* stdio is not yet initialized.
|
* stdio is not yet initialized.
|
||||||
@@ -307,7 +363,7 @@ int bus,dev,fun;
|
|||||||
pci_ulong busaddr;
|
pci_ulong busaddr;
|
||||||
unsigned char irqline;
|
unsigned char irqline;
|
||||||
|
|
||||||
if (pciFindDevice(
|
if (BSP_PCI_FIND_DEVICE(
|
||||||
PCI_VENDOR_TUNDRA,
|
PCI_VENDOR_TUNDRA,
|
||||||
PCI_DEVICE_UNIVERSEII,
|
PCI_DEVICE_UNIVERSEII,
|
||||||
instance,
|
instance,
|
||||||
@@ -315,17 +371,17 @@ unsigned char irqline;
|
|||||||
&dev,
|
&dev,
|
||||||
&fun))
|
&fun))
|
||||||
return -1;
|
return -1;
|
||||||
if (pciConfigInLong(bus,dev,fun,PCI_UNIVERSE_BASE0,&busaddr))
|
if (BSP_PCI_CONFIG_IN_LONG(bus,dev,fun,PCI_UNIVERSE_BASE0,&busaddr))
|
||||||
return -1;
|
return -1;
|
||||||
if ((unsigned long)(busaddr) & 1) {
|
if ((unsigned long)(busaddr) & 1) {
|
||||||
/* it's IO space, try BASE1 */
|
/* it's IO space, try BASE1 */
|
||||||
if (pciConfigInLong(bus,dev,fun,PCI_UNIVERSE_BASE1,&busaddr)
|
if (BSP_PCI_CONFIG_IN_LONG(bus,dev,fun,PCI_UNIVERSE_BASE1,&busaddr)
|
||||||
|| ((unsigned long)(busaddr) & 1))
|
|| ((unsigned long)(busaddr) & 1))
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*pbase=(volatile LERegister*)PCI_TO_LOCAL_ADDR(busaddr);
|
*pbase=(volatile LERegister*)PCI_TO_LOCAL_ADDR(busaddr);
|
||||||
|
|
||||||
if (pciConfigInByte(bus,dev,fun,PCI_INTERRUPT_LINE,&irqline))
|
if (BSP_PCI_CONFIG_IN_BYTE(bus,dev,fun,PCI_INTERRUPT_LINE,&irqline))
|
||||||
return -1;
|
return -1;
|
||||||
else
|
else
|
||||||
vmeUniverse0PciIrqLine = irqline;
|
vmeUniverse0PciIrqLine = irqline;
|
||||||
@@ -608,6 +664,7 @@ showUniversePort(
|
|||||||
typedef struct XlatRec_ {
|
typedef struct XlatRec_ {
|
||||||
unsigned long address;
|
unsigned long address;
|
||||||
unsigned long aspace;
|
unsigned long aspace;
|
||||||
|
unsigned reverse; /* find reverse mapping of this port */
|
||||||
} XlatRec, *Xlat;
|
} XlatRec, *Xlat;
|
||||||
|
|
||||||
/* try to translate an address through the bridge
|
/* try to translate an address through the bridge
|
||||||
@@ -653,12 +710,22 @@ unsigned long cntrl, start, bound, offst, mask, x;
|
|||||||
offst = READ_LE0(preg++) & mask;
|
offst = READ_LE0(preg++) & mask;
|
||||||
|
|
||||||
/* translate address to the other bus */
|
/* translate address to the other bus */
|
||||||
x = l->address - offst;
|
if (l->reverse) {
|
||||||
|
/* reverse mapping, i.e. for master ports we map from
|
||||||
|
* VME to PCI, for slave ports we map from VME to PCI
|
||||||
|
*/
|
||||||
|
if (l->address >= start && l->address < bound) {
|
||||||
|
l->address+=offst;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
x = l->address - offst;
|
||||||
|
|
||||||
if (x >= start && x < bound) {
|
if (x >= start && x < bound) {
|
||||||
/* valid address found */
|
/* valid address found */
|
||||||
l->address = x;
|
l->address = x;
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -711,31 +778,26 @@ showUniversePorts(int ismaster, FILE *f)
|
|||||||
mapOverAll(ismaster,showUniversePort,f);
|
mapOverAll(ismaster,showUniversePort,f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xlate(int ismaster, unsigned long as, unsigned long aIn, unsigned long *paOut)
|
int
|
||||||
|
vmeUniverseXlateAddr(
|
||||||
|
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;
|
int rval;
|
||||||
XlatRec l;
|
XlatRec l;
|
||||||
l.aspace = as;
|
l.aspace = as;
|
||||||
l.address = aIn;
|
l.address = aIn;
|
||||||
|
l.reverse = reverse;
|
||||||
/* map result -1/0/1 to -2/-1/0 with 0 on success */
|
/* map result -1/0/1 to -2/-1/0 with 0 on success */
|
||||||
rval = mapOverAll(ismaster,xlatePort,(void*)&l) - 1;
|
rval = mapOverAll(master,xlatePort,(void*)&l) - 1;
|
||||||
*paOut = l.address;
|
*paOut = l.address;
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* public functions */
|
|
||||||
int
|
|
||||||
vmeUniverseLocalToBusAdrs(unsigned long as, unsigned long localAdrs, unsigned long *pbusAdrs)
|
|
||||||
{
|
|
||||||
return xlate(0,as,localAdrs,pbusAdrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
vmeUniverseBusToLocalAdrs(unsigned long as, unsigned long busAdrs, unsigned long *plocalAdrs)
|
|
||||||
{
|
|
||||||
return xlate(1,as,busAdrs,plocalAdrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
vmeUniverseReset(void)
|
vmeUniverseReset(void)
|
||||||
{
|
{
|
||||||
@@ -765,6 +827,21 @@ vmeUniverseReset(void)
|
|||||||
/* disable VME bus image of VME CSR */
|
/* disable VME bus image of VME CSR */
|
||||||
vmeUniverseWriteReg(0, UNIV_REGOFF_VCSR_CTL);
|
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 */
|
/* disable interrupts, reset routing */
|
||||||
vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_EN);
|
vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_EN);
|
||||||
vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_MAP0);
|
vmeUniverseWriteReg(0, UNIV_REGOFF_LINT_MAP0);
|
||||||
@@ -924,7 +1001,7 @@ register unsigned long *p=ptr+num;
|
|||||||
"stwbrx 0, 0, %0\n"
|
"stwbrx 0, 0, %0\n"
|
||||||
: "=r"(p) : "r"(p) : "r0"
|
: "=r"(p) : "r"(p) : "r0"
|
||||||
);
|
);
|
||||||
#elif defined(__rtems)
|
#elif defined(__rtems__)
|
||||||
p--; st_le32(p, *p);
|
p--; st_le32(p, *p);
|
||||||
#else
|
#else
|
||||||
#error "vmeUniverse: endian conversion not implemented for this architecture"
|
#error "vmeUniverse: endian conversion not implemented for this architecture"
|
||||||
@@ -935,7 +1012,7 @@ register unsigned long *p=ptr+num;
|
|||||||
|
|
||||||
/* RTEMS interrupt subsystem */
|
/* RTEMS interrupt subsystem */
|
||||||
|
|
||||||
#ifdef __rtems
|
#ifdef __rtems__
|
||||||
#include <bsp/irq.h>
|
#include <bsp/irq.h>
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@@ -944,16 +1021,18 @@ UniverseIRQEntryRec_ {
|
|||||||
void *usrData;
|
void *usrData;
|
||||||
} UniverseIRQEntryRec, *UniverseIRQEntry;
|
} UniverseIRQEntryRec, *UniverseIRQEntry;
|
||||||
|
|
||||||
static UniverseIRQEntry universeHdlTbl[257]={0};
|
static UniverseIRQEntry universeHdlTbl[UNIV_NUM_INT_VECS]={0};
|
||||||
|
|
||||||
static int mgrInstalled=0;
|
int vmeUniverseIrqMgrInstalled=0;
|
||||||
static int vmeIrqUnivOut=-1;
|
static int vmeIrqUnivOut=-1;
|
||||||
static int specialIrqUnivOut=-1;
|
static int specialIrqUnivOut=-1;
|
||||||
|
|
||||||
VmeUniverseISR
|
VmeUniverseISR
|
||||||
vmeUniverseISRGet(unsigned long vector, void **parg)
|
vmeUniverseISRGet(unsigned long vector, void **parg)
|
||||||
{
|
{
|
||||||
if (vector>255) return 0;
|
if (vector>=UNIV_NUM_INT_VECS ||
|
||||||
|
! universeHdlTbl[vector])
|
||||||
|
return 0;
|
||||||
if (parg)
|
if (parg)
|
||||||
*parg=universeHdlTbl[vector]->usrData;
|
*parg=universeHdlTbl[vector]->usrData;
|
||||||
return universeHdlTbl[vector]->isr;
|
return universeHdlTbl[vector]->isr;
|
||||||
@@ -962,10 +1041,29 @@ vmeUniverseISRGet(unsigned long vector, void **parg)
|
|||||||
static void
|
static void
|
||||||
universeSpecialISR(void)
|
universeSpecialISR(void)
|
||||||
{
|
{
|
||||||
UniverseIRQEntry ip;
|
register UniverseIRQEntry ip;
|
||||||
/* try the special handler */
|
register unsigned vec;
|
||||||
if ((ip=universeHdlTbl[UNIV_SPECIAL_IRQ_VECTOR])) {
|
register unsigned long status;
|
||||||
ip->isr(ip->usrData, UNIV_SPECIAL_IRQ_VECTOR);
|
|
||||||
|
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 */
|
/* clear all special interrupts */
|
||||||
vmeUniverseWriteReg(
|
vmeUniverseWriteReg(
|
||||||
@@ -1092,16 +1190,25 @@ my_isOn(const rtems_irq_connect_data *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
vmeUniverseInstallIrqMgr(int vmeOut, int specialOut, int specialIrqPicLine)
|
vmeUniverseInstallIrqMgr(int vmeOut,
|
||||||
|
int vmeIrqPicLine,
|
||||||
|
int specialOut,
|
||||||
|
int specialIrqPicLine)
|
||||||
{
|
{
|
||||||
rtems_irq_connect_data aarrggh;
|
rtems_irq_connect_data aarrggh;
|
||||||
|
|
||||||
/* check parameters */
|
/* check parameters */
|
||||||
if ((vmeIrqUnivOut=vmeOut) < 0 || vmeIrqUnivOut > 7) return -1;
|
if ((vmeIrqUnivOut=vmeOut) < 0 || vmeIrqUnivOut > 7) return -1;
|
||||||
if ((specialIrqUnivOut=specialOut) > 7) return -2;
|
if ((specialIrqUnivOut=specialOut) > 7) return -2;
|
||||||
if (specialIrqPicLine < 0) return -3;
|
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 %i\n",
|
||||||
|
vmeIrqPicLine);
|
||||||
|
vmeUniverse0PciIrqLine=vmeIrqPicLine;
|
||||||
|
}
|
||||||
|
|
||||||
if (mgrInstalled) return -4;
|
if (vmeUniverseIrqMgrInstalled) return -4;
|
||||||
|
|
||||||
aarrggh.on=my_no_op; /* at _least_ they could check for a 0 pointer */
|
aarrggh.on=my_no_op; /* at _least_ they could check for a 0 pointer */
|
||||||
aarrggh.off=my_no_op;
|
aarrggh.off=my_no_op;
|
||||||
@@ -1142,7 +1249,7 @@ rtems_irq_connect_data aarrggh;
|
|||||||
UNIV_LINT_MAP1_DMA(specialIrqUnivOut)
|
UNIV_LINT_MAP1_DMA(specialIrqUnivOut)
|
||||||
),
|
),
|
||||||
UNIV_REGOFF_LINT_MAP1);
|
UNIV_REGOFF_LINT_MAP1);
|
||||||
mgrInstalled=1;
|
vmeUniverseIrqMgrInstalled=1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1152,7 +1259,7 @@ vmeUniverseInstallISR(unsigned long vector, VmeUniverseISR hdl, void *arg)
|
|||||||
{
|
{
|
||||||
UniverseIRQEntry ip;
|
UniverseIRQEntry ip;
|
||||||
|
|
||||||
if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !mgrInstalled)
|
if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !vmeUniverseIrqMgrInstalled)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ip=universeHdlTbl[vector];
|
ip=universeHdlTbl[vector];
|
||||||
@@ -1170,7 +1277,7 @@ vmeUniverseRemoveISR(unsigned long vector, VmeUniverseISR hdl, void *arg)
|
|||||||
{
|
{
|
||||||
UniverseIRQEntry ip;
|
UniverseIRQEntry ip;
|
||||||
|
|
||||||
if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !mgrInstalled)
|
if (vector>sizeof(universeHdlTbl)/sizeof(universeHdlTbl[0]) || !vmeUniverseIrqMgrInstalled)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ip=universeHdlTbl[vector];
|
ip=universeHdlTbl[vector];
|
||||||
@@ -1185,7 +1292,7 @@ UniverseIRQEntry ip;
|
|||||||
int
|
int
|
||||||
vmeUniverseIntEnable(unsigned int level)
|
vmeUniverseIntEnable(unsigned int level)
|
||||||
{
|
{
|
||||||
if (!mgrInstalled || level<1 || level>7)
|
if (!vmeUniverseIrqMgrInstalled || level<1 || level>7)
|
||||||
return -1;
|
return -1;
|
||||||
vmeUniverseWriteReg(
|
vmeUniverseWriteReg(
|
||||||
(vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) |
|
(vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) |
|
||||||
@@ -1198,7 +1305,7 @@ vmeUniverseIntEnable(unsigned int level)
|
|||||||
int
|
int
|
||||||
vmeUniverseIntDisable(unsigned int level)
|
vmeUniverseIntDisable(unsigned int level)
|
||||||
{
|
{
|
||||||
if (!mgrInstalled || level<1 || level>7)
|
if (!vmeUniverseIrqMgrInstalled || level<1 || level>7)
|
||||||
return -1;
|
return -1;
|
||||||
vmeUniverseWriteReg(
|
vmeUniverseWriteReg(
|
||||||
(vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) &
|
(vmeUniverseReadReg(UNIV_REGOFF_LINT_EN) &
|
||||||
|
|||||||
@@ -14,16 +14,25 @@
|
|||||||
#include <vme.h>
|
#include <vme.h>
|
||||||
#else
|
#else
|
||||||
/* vxworks compatible addressing modes */
|
/* vxworks compatible addressing modes */
|
||||||
|
#define VME_AM_STD_SUP_ASCENDING 0x3f
|
||||||
#define VME_AM_STD_SUP_PGM 0x3e
|
#define VME_AM_STD_SUP_PGM 0x3e
|
||||||
|
#define VME_AM_STD_USR_ASCENDING 0x3b
|
||||||
#define VME_AM_STD_USR_PGM 0x3a
|
#define VME_AM_STD_USR_PGM 0x3a
|
||||||
#define VME_AM_STD_SUP_DATA 0x3d
|
#define VME_AM_STD_SUP_DATA 0x3d
|
||||||
#define VME_AM_STD_USR_DATA 0x39
|
#define VME_AM_STD_USR_DATA 0x39
|
||||||
|
#define VME_AM_EXT_SUP_ASCENDING 0x0f
|
||||||
#define VME_AM_EXT_SUP_PGM 0x0e
|
#define VME_AM_EXT_SUP_PGM 0x0e
|
||||||
|
#define VME_AM_EXT_USR_ASCENDING 0x0b
|
||||||
#define VME_AM_EXT_USR_PGM 0x0a
|
#define VME_AM_EXT_USR_PGM 0x0a
|
||||||
#define VME_AM_EXT_SUP_DATA 0x0d
|
#define VME_AM_EXT_SUP_DATA 0x0d
|
||||||
#define VME_AM_EXT_USR_DATA 0x09
|
#define VME_AM_EXT_USR_DATA 0x09
|
||||||
#define VME_AM_SUP_SHORT_IO 0x2d
|
#define VME_AM_SUP_SHORT_IO 0x2d
|
||||||
#define VME_AM_USR_SHORT_IO 0x29
|
#define VME_AM_USR_SHORT_IO 0x29
|
||||||
|
|
||||||
|
#define VME_AM_IS_SHORT(a) (((a) & 0xf0) == 0x20)
|
||||||
|
#define VME_AM_IS_STD(a) (((a) & 0xf0) == 0x30)
|
||||||
|
#define VME_AM_IS_EXT(a) (((a) & 0xf0) == 0x00)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef unsigned long LERegister; /* emphasize contents are little endian */
|
typedef unsigned long LERegister; /* emphasize contents are little endian */
|
||||||
@@ -338,6 +347,18 @@ typedef struct VmeUniverseDMAPacketRec_ {
|
|||||||
# define UNIV_MISC_CTL_SYSCON (1<<17) /* (R/W) 1:universe is system controller */
|
# define UNIV_MISC_CTL_SYSCON (1<<17) /* (R/W) 1:universe is system controller */
|
||||||
# define UNIV_MISC_CTL_V64AUTO (1<<16) /* (R/W) 1:initiate VME64 auto id slave participation */
|
# define UNIV_MISC_CTL_V64AUTO (1<<16) /* (R/W) 1:initiate VME64 auto id slave participation */
|
||||||
|
|
||||||
|
/* U2SPEC described in VGM manual */
|
||||||
|
/* NOTE: the Joerger vtr10012_8 needs the timing to be tweaked!!!! READt27 must be _no_delay_
|
||||||
|
*/
|
||||||
|
#define UNIV_REGOFF_U2SPEC 0x4fc
|
||||||
|
# define UNIV_U2SPEC_DTKFLTR (1<<12) /* DTAck filter: 0: slow, better filter; 1: fast, poorer filter */
|
||||||
|
# define UNIV_U2SPEC_MASt11 (1<<10) /* Master parameter t11 (DS hi time during BLT and MBLTs) */
|
||||||
|
# define UNIV_U2SPEC_READt27_DEFAULT (0<<8) /* VME master parameter t27: (latch data after DTAck + 25ns) */
|
||||||
|
# define UNIV_U2SPEC_READt27_FAST (1<<8) /* VME master parameter t27: (latch data faster than 25ns) */
|
||||||
|
# define UNIV_U2SPEC_READt27_NODELAY (2<<8) /* VME master parameter t27: (latch data without any delay) */
|
||||||
|
# define UNIV_U2SPEC_POSt28_FAST (1<<2) /* VME slave parameter t28: (faster time of DS to DTAck for posted write) */
|
||||||
|
# define UNIV_U2SPEC_PREt28_FAST (1<<0) /* VME slave parameter t28: (faster time of DS to DTAck for prefetch read) */
|
||||||
|
|
||||||
/* Location Monitor control register */
|
/* Location Monitor control register */
|
||||||
#define UNIV_REGOFF_LM_CTL 0xf64
|
#define UNIV_REGOFF_LM_CTL 0xf64
|
||||||
# define UNIV_LM_CTL_EN (1<<31) /* image enable */
|
# define UNIV_LM_CTL_EN (1<<31) /* image enable */
|
||||||
@@ -489,15 +510,21 @@ vmeUniverseMasterPortCfg(
|
|||||||
|
|
||||||
/* translate an address through the bridge
|
/* translate an address through the bridge
|
||||||
*
|
*
|
||||||
* vmeUniverseLocalToBusAdrs() yields a VME a address that reflects
|
* vmeUniverseXlateAddr(0,0,addr,as,&result)
|
||||||
|
* yields a VME a address that reflects
|
||||||
* a local memory location as seen from the VME bus through the universe
|
* a local memory location as seen from the VME bus through the universe
|
||||||
* VME slave.
|
* VME slave.
|
||||||
*
|
*
|
||||||
* likewise does vmeUniverseBusToLocalAdrs() translate a VME bus addr
|
* likewise does vmeUniverseXlateAddr(1,0,addr,as,&result)
|
||||||
* (through the VME master) to the PCI side of the bridge.
|
* translate a VME bus addr (through the VME master) to the
|
||||||
|
* PCI side of the bridge.
|
||||||
*
|
*
|
||||||
* a valid address space modifier must be specified.
|
* a valid address space modifier must be specified.
|
||||||
*
|
*
|
||||||
|
* The 'reverse' parameter may be used to find a reverse
|
||||||
|
* mapping, i.e. the pci address in a master window can be
|
||||||
|
* found if the respective vme address is known etc.
|
||||||
|
*
|
||||||
* RETURNS: translated address in *pbusAdrs / *plocalAdrs
|
* RETURNS: translated address in *pbusAdrs / *plocalAdrs
|
||||||
*
|
*
|
||||||
* 0: success
|
* 0: success
|
||||||
@@ -505,11 +532,13 @@ vmeUniverseMasterPortCfg(
|
|||||||
* -2: invalid modifier
|
* -2: invalid modifier
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
vmeUniverseLocalToBusAdrs(unsigned long am, unsigned long localAdrs, unsigned long *pbusAdrs);
|
vmeUniverseXlateAddr(
|
||||||
|
int master, /* look in the master windows */
|
||||||
int
|
int reverse, /* reverse mapping; for masters: map local to VME */
|
||||||
vmeUniverseBusToLocalAdrs(unsigned long am, unsigned long busAdrs, unsigned long *plocalAdrs);
|
unsigned long as, /* address space */
|
||||||
|
unsigned long addr, /* address to look up */
|
||||||
|
unsigned long *paOut/* where to put result */
|
||||||
|
);
|
||||||
|
|
||||||
/* configure a VME slave (PCI master) port */
|
/* configure a VME slave (PCI master) port */
|
||||||
int
|
int
|
||||||
@@ -556,7 +585,7 @@ vmeUniverseResetBus(void)
|
|||||||
UNIV_REGOFF_MISC_CTL);
|
UNIV_REGOFF_MISC_CTL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __rtems
|
#ifdef __rtems__
|
||||||
/* VME Interrupt Handler functionality */
|
/* VME Interrupt Handler functionality */
|
||||||
|
|
||||||
/* we dont use the current RTEMS/BSP interrupt API for the
|
/* we dont use the current RTEMS/BSP interrupt API for the
|
||||||
@@ -608,15 +637,38 @@ int
|
|||||||
vmeUniverseIntDisable(unsigned int level);
|
vmeUniverseIntDisable(unsigned int level);
|
||||||
|
|
||||||
|
|
||||||
/* use this special vector to connect a handler to the
|
/* use these special vectors to connect a handler to the
|
||||||
* universe specific interrupts (such as "DMA done",
|
* universe specific interrupts (such as "DMA done",
|
||||||
* VOWN, error irqs etc.)
|
* VOWN, error irqs etc.)
|
||||||
* NOTE: The wrapper clears all status LINT bits (except
|
* NOTE: The wrapper clears all status LINT bits (except
|
||||||
* for regular VME irqs). Also note that it is the user's
|
* for regular VME irqs). Also note that it is the user's
|
||||||
* responsibility to enable the necessary interrupts in
|
* responsibility to enable the necessary interrupts in
|
||||||
* LINT_EN
|
* LINT_EN
|
||||||
|
*
|
||||||
|
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
* DO NOT CHANGE THE ORDER OF THESE VECTORS - THE DRIVER
|
||||||
|
* DEPENDS ON IT
|
||||||
|
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
#define UNIV_SPECIAL_IRQ_VECTOR 256
|
#define UNIV_VOWN_INT_VEC 256
|
||||||
|
#define UNIV_DMA_INT_VEC 257
|
||||||
|
#define UNIV_LERR_INT_VEC 258
|
||||||
|
#define UNIV_VERR_INT_VEC 259
|
||||||
|
#define UNIV_VME_SW_IACK_INT_VEC 260
|
||||||
|
#define UNIV_PCI_SW_INT_VEC 261
|
||||||
|
#define UNIV_SYSFAIL_INT_VEC 262
|
||||||
|
#define UNIV_ACFAIL_INT_VEC 263
|
||||||
|
#define UNIV_MBOX0_INT_VEC 264
|
||||||
|
#define UNIV_MBOX1_INT_VEC 265
|
||||||
|
#define UNIV_MBOX2_INT_VEC 266
|
||||||
|
#define UNIV_MBOX3_INT_VEC 267
|
||||||
|
#define UNIV_LM0_INT_VEC 268
|
||||||
|
#define UNIV_LM1_INT_VEC 269
|
||||||
|
#define UNIV_LM2_INT_VEC 270
|
||||||
|
#define UNIV_LM3_INT_VEC 271
|
||||||
|
|
||||||
|
#define UNIV_NUM_INT_VECS 272
|
||||||
|
|
||||||
/* the universe interrupt handler is capable of routing all sorts of
|
/* the universe interrupt handler is capable of routing all sorts of
|
||||||
* (VME) interrupts to 8 different lines (some of) which may be hooked up
|
* (VME) interrupts to 8 different lines (some of) which may be hooked up
|
||||||
@@ -634,13 +686,18 @@ vmeUniverseIntDisable(unsigned int level);
|
|||||||
*
|
*
|
||||||
* Hence the manager sets up routing VME interrupts to 1 or 2 universe
|
* Hence the manager sets up routing VME interrupts to 1 or 2 universe
|
||||||
* OUTPUTS. However, it must also be told to which PIC INPUTS they
|
* OUTPUTS. However, it must also be told to which PIC INPUTS they
|
||||||
* are wired. The first PIC input line is read from PCI config space
|
* are wired.
|
||||||
* but the second must be passed to this routine.
|
* Optionally, the first PIC input line can be read from PCI config space
|
||||||
|
* but the second must be passed to this routine. Note that the info read
|
||||||
|
* from PCI config space is wrong for many boards!
|
||||||
*
|
*
|
||||||
* PARAMETERS:
|
* PARAMETERS:
|
||||||
* vmeIRQunivOut: to which output pin (of the universe) should the 7
|
* vmeIrqUnivOut: to which output pin (of the universe) should the 7
|
||||||
* VME irq levels be routed.
|
* VME irq levels be routed.
|
||||||
* specialIRQunivOut: to which output pin (of the universe) should the
|
* vmeIrqPicLine: specifies to which PIC input the 'main' output is
|
||||||
|
* wired. If passed a value < 0, the driver reads this
|
||||||
|
* information from PCI config space ("IRQ line").
|
||||||
|
* specialIrqUnivOut: to which output pin (of the universe) should the
|
||||||
* internally irqs be routed. Use 'vmeIRQunivOut'
|
* internally irqs be routed. Use 'vmeIRQunivOut'
|
||||||
* if < 0.
|
* if < 0.
|
||||||
* specialIrqPicLine: specifies to which PIC input the 'special' output
|
* specialIrqPicLine: specifies to which PIC input the 'special' output
|
||||||
@@ -651,7 +708,10 @@ vmeUniverseIntDisable(unsigned int level);
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
vmeUniverseInstallIrqMgr(int vmeIrqUnivOut, int specialIrqUnivOut, int specialIrqPicLine);
|
vmeUniverseInstallIrqMgr(int vmeIrqUnivOut,
|
||||||
|
int vmeIrqPicLine,
|
||||||
|
int specialIrqUnivOut,
|
||||||
|
int specialIrqPicLine);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user