Commit 1d9176d6 authored by dan.eichel's avatar dan.eichel
Browse files

Tsi148 PCI-VME bridge support for MVME6100 boards added

parent ca633051
......@@ -11,15 +11,19 @@ LIB_SRCS_DEFAULT = VMEtas_nop.c
LIB_SRCS_vxWorks = VMEtas_vxWorks.c
ifeq ($(T_A),RTEMS-mvme2100)
LIB_SRCS_RTEMS = VMEtas_RTEMS-UniverseII.c
LIB_SRCS_RTEMS = VMEtas_RTEMS-UniverseII.c
LIB_SRCS_RTEMS += VMEtas_RTEMS-shared.c
endif
ifeq ($(T_A),RTEMS-mvme5500)
LIB_SRCS_RTEMS = VMEtas_RTEMS-UniverseII.c
LIB_SRCS_RTEMS = VMEtas_RTEMS-UniverseII.c
LIB_SRCS_RTEMS += VMEtas_RTEMS-shared.c
endif
ifeq ($(T_A),RTEMS-beatnik)
LIB_SRCS_RTEMS = VMEtas_RTEMS-UniverseII.c
LIB_SRCS_RTEMS = VMEtas_RTEMS-UniverseII.c
LIB_SRCS_RTEMS += VMEtas_RTEMS-Tsi148.c
LIB_SRCS_RTEMS += VMEtas_RTEMS-beatnik.c
endif
include $(TOP)/configure/RULES
......
......@@ -15,6 +15,7 @@
#ifndef INCVMEtash
#define INCVMEtash
extern void VMEtas_init(void);
extern int VMEtas(unsigned char *addr);
#endif /* ifndef INCVMEtash */
/*+*********************************************************************
*
* File: VMEtas_RTEMS-Tsi148.c
*
* Descr.: test and set a VME byte addr
*
* Author(s): Dan Eichel
*
* Copyright (c) 2018 by Berliner Elektronenspeicherring-Gesellschaft
* fuer Synchrotronstrahlung m.b.H.,
* Berlin, Germany
*
*********************************************************************-*/
#include <rtems.h> /* rtems_interrupt_disable */
#include <bsp.h> /* in_8, in_be32, out_be32 */
#include <bsp/vmeTsi148.h> /* vmeTsi148RegBase */
extern volatile uint32_t *vmeTsi148RegBase;
/* register offsets are measured in bytes, not words;
this macro encapsulated the necessary shifting and the type casts */
#define out_tsi_reg(reg, val)\
out_be32((volatile unsigned *)((unsigned) vmeTsi148RegBase + (reg>>2)), val)
#define in_tsi_reg(reg)\
in_be32((volatile unsigned *)((unsigned) vmeTsi148RegBase + (reg>>2)))
/* next word aligned address below or equal to addr */
#define align(addr)\
((unsigned)(addr) & ~0x3)
/* offset of addr relative to the address of the aligned word that contains it */
#define unaligned_by(addr)\
((unsigned)(addr) - align(addr))
/* VMEbus RMW Address Upper Register */
#define RMWAU 0x220
/* VMEbus RMW Address Lower Register */
#define RMWAL 0x224
/* VMEbus RMW Enable Register */
#define RMWEN 0x228
/* VMEbus RMW Compare Register */
#define RMWC 0x22C
/* VMEbus RMW Swap Register */
#define RMWS 0x230
/* VME Master Control Register */
#define VMECTRL 0x230
/*
* This routine performs a test-and-set (TAS) on the specified address, which
* must be on a (different) VME board. This emulates the TAS instruction known
* from the mc68000 processors. For compatibility with the old motorola CPUs
* only the highest bit in the adressed byte will be affected.
*
* The implementation uses the ability of the Tsi148 chip to perform an
* atomic Read-Modify-Write cycle on the VME bus. This special mode of the
* Tsi148 must be programmed only using word (4 byte) aligned addresses,
* which means we must shift the enable mask and the desired value to be
* swapped back so that they are relative to the next lower (or equal) word
* aligned address (cf. Tsi148 User Manual, Page 203 Read-Modify-Write,
* Chapter 10.4.28 - 10.4.32 for detailed description).
*
* RETURNS: TRUE if the value had not been set but is now
* FALSE if the value was already set.
*/
int Tsi148_VMEtas(unsigned char *addr)
{
int state;
/* value to write back if not set */
unsigned char value = (1<<7);
rtems_interrupt_level level;
unsigned addr_offset = unaligned_by(addr);
unsigned swap = (unsigned)value << 8 * addr_offset;
unsigned mask = swap;
rtems_interrupt_disable(level);
/* set up the Tsi148 chip so that the next read from addr
triggers an atomic RMW cycle */
/* enable special cycle for the bits in mask */
out_tsi_reg(RMWEN, mask);
/* when doing the special cycle, compare with zero */
out_tsi_reg(RMWC, 0);
/* set the value to be swapped back if comparison succeeds */
out_tsi_reg(RMWS, swap);
/* set the 64bit address that triggers the RMW cycle */
out_tsi_reg(RMWAU, 0 );
out_tsi_reg(RMWAL, align(LOCAL2PCI_ADDR( addr ) ));
/* program the Tsi148 chip to do a RMW cycle */
mask = in_tsi_reg(VMECTRL);
mask |= (1 << 20);
out_tsi_reg(VMECTRL, mask);
/* trigger the RMW by reading from addr */
state = in_8(addr);
/* disable RMW cycle */
mask &= ~(1 << 20);
out_tsi_reg(VMECTRL, mask);
rtems_interrupt_enable(level);
return !(state & value);
}
......@@ -17,8 +17,6 @@
#include <bsp/vmeUniverse.h> /* register offsets and constants */
#include <bsp.h> /* PCI_DRAM_OFFSET */
#include "VMEtas.h"
/* register offsets in bsp/vmeUniverse.h are measured in bytes, not words;
this macro encapsulated the necessary shifting and the type casts */
#define out_univ_reg(reg, val)\
......@@ -49,7 +47,7 @@
* RETURNS: TRUE if the value had not been set but is now
* FALSE if the value was already set.
*/
int VMEtas(unsigned char *addr)
int UnivII_VMEtas(unsigned char *addr)
{
int state;
/* value to write back if not set */
......
/*+*********************************************************************
*
* File: VMEtas_RTEMS-beatnik.c
*
* Descr.: wrapper for beatnik targets
*
* Author(s): Dan Eichel
*
* Copyright (c) 2018 by Berliner Elektronenspeicherring-Gesellschaft
* fuer Synchrotronstrahlung m.b.H.,
* Berlin, Germany
*
*********************************************************************-*/
#include <stdio.h> /* printf */
#include <bsp.h> /* BSP_getBoardType */
#include "VMEtas.h"
int Dummy_VMEtas(unsigned char *addr)
{
printf("WARNING: VMEtas() not initialized! Call VMEtas_init() firstly\n");
return 0;
}
static int (*funcptr)(unsigned char*) = &Dummy_VMEtas;
extern int UnivII_VMEtas(unsigned char *addr);
extern int Tsi148_VMEtas(unsigned char *addr);
void VMEtas_init(void)
{
switch (BSP_getBoardType()) {
case MVME6100: funcptr = &Tsi148_VMEtas; break;
case MVME5500: funcptr = &UnivII_VMEtas; break;
default: printf("ERROR: unknown Board type! VMEtas will not run properly\n");
}
}
int VMEtas(unsigned char *addr)
{
return funcptr(addr);
}
/*+*********************************************************************
*
* File: VMEtas_RTEMS-Shared.c
*
* Descr.: test and set a VME byte addr
*
* Author(s): Dan Eichel
*
* Copyright (c) 2018 by Berliner Elektronenspeicherring-Gesellschaft
* fuer Synchrotronstrahlung m.b.H.,
* Berlin, Germany
*
*********************************************************************-*/
#include "VMEtas.h"
extern int UnivII_VMEtas(unsigned char *addr);
void VMEtas_init(void)
{
}
int VMEtas(unsigned char *addr)
{
return UnivII_VMEtas(addr);
}
......@@ -15,6 +15,10 @@
#include <stdio.h>
#include "VMEtas.h"
void VMEtas_init(void)
{
}
int VMEtas(unsigned char *addr)
{
printf("WARNING: VMEtas() not implemented for this arch!\n");
......
......@@ -16,6 +16,10 @@
#include "VMEtas.h"
void VMEtas_init(void)
{
}
int VMEtas(unsigned char *addr)
{
return (0 == sysBusTas((char *)addr));
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment