📄 libvme.cpp
字号:
//------------------------------------------------------------------------------ //title: VMEBus Library for Universe Driver//version: Linux 1.1//date: April 1999//designer: Michael Wyrick //programmer: Michael Wyrick //company: Umbra System Inc.//platform: Linux 2.2.x, 2.4.x //language: GCC 2.95, 3.0//module: //------------------------------------------------------------------------------ // Purpose: // Docs: //------------------------------------------------------------------------------ #include <stdio.h>#include <ctype.h>#include <fcntl.h>#include <unistd.h>#include <sys/ioctl.h>#include "universe.h"#include "libvme.h"// Internal constants only to libvme#define VME_CYCLE 0x10#define VME_SIZE 0x60#define MODE_PROGRAMMED 0x01#define MODE_DMA 0x02#define VME_SUP_USR 0x08#define VME_PRG_DATA 0x04#define MODE_PROGRAMMED 0x01#define MODE_DMA 0x02#define DEBUG#undef DEBUG//-----------------------------------------------------------------------------// Function : SwapEndian// Inputs : any MultiByte type// Outputs : a MultiByte type with the Bytes swapped// Description: Flip the Endianess of any Multibyte Type// Remarks :// History ://-----------------------------------------------------------------------------template<class T>T SwapEndian(T in){ T out; int s = sizeof(T); char *pin = reinterpret_cast<char *>(&in); char *pout = reinterpret_cast<char *>(&out); for (int x=0;x<s;x++) pout[x] = pin[(s-1)-x]; return out;}//-----------------------------------------------------------------------------// Function : VMEBus construstor// Inputs :// addr = VME Base Address to map// count = Size of mapping window// space = which VME address space the memory is in (i.e. user/data etc.)// which_img = which of the four universe images to use// Outputs :// Description:// Add a space description here// if which_img is -1 then scan for and pick the next free image,// only image 3 can be used for SUPERVISOR mappings// Remarks :// History ://-----------------------------------------------------------------------------VMEBus::VMEBus(unsigned int addr, int count, char space, int which_img){ int to = 0; int am = 0; int size = 0; iSwapEndian = 1; ctl = 0x00800000; if (space & VME_SUPERVISOR) // Only image can use supervisor space which_img = 3; if (which_img == -1) { // Auto Image if ((vme_handle = open("//dev//vme_m0",O_RDWR,0)) > 0) { pci_base_addr = 0xC0000000; } else { if ((vme_handle = open("//dev//vme_m1",O_RDWR,0)) > 0) { pci_base_addr = 0xC4000000; } else { if ((vme_handle = open("//dev//vme_m2",O_RDWR,0)) > 0) { pci_base_addr = 0xC8000000; } else { if ((vme_handle = open("//dev//vme_m3",O_RDWR,0)) > 0) { pci_base_addr = 0xCD000000; } } } } } else { switch (which_img) { // Force Selected image case 0 : vme_handle = open("//dev//vme_m0",O_RDWR,0); pci_base_addr = 0xC0000000; break; case 1 : vme_handle = open("//dev//vme_m1",O_RDWR,0); pci_base_addr = 0xC4000000; break; case 2 : vme_handle = open("//dev//vme_m2",O_RDWR,0); pci_base_addr = 0xC8000000; break; case 3 : vme_handle = open("//dev//vme_m3",O_RDWR,0); pci_base_addr = 0xCC000000; break; } } uni_handle = open("//dev//vme_ctl",O_RDWR,0); if (vme_handle < 0) { throw VME_DriverBusy(); } if (uni_handle < 0) { throw VME_DriverBusy(); } size = space & VME_SIZE; switch (size) { case VME_SIZE_DO8: ctl &= ~CTL_VDW; ctl |= CTL_VDW_8; break; case VME_SIZE_D16: ctl &= ~CTL_VDW; ctl |= CTL_VDW_16; break; case VME_SIZE_D32: ctl &= ~CTL_VDW; ctl |= CTL_VDW_32; break; case VME_SIZE_D64: ctl &= ~CTL_VDW; ctl |= CTL_VDW_64; break; } am = space & 0x03; if (space & VME_PRG_DATA) { ctl |= CTL_PGM; } else { ctl &= ~CTL_PGM; } if (space & VME_SUP_USR) { ctl |= CTL_SUPER; } else { ctl &= ~CTL_SUPER; } if (space & VME_CYCLE) { ctl |= CTL_VCT; } else { ctl &= ~CTL_VCT; } if (am == VME_A16) { vme_space = am; ctl &= ~CTL_VAS; ctl |= CTL_VAS_A16; } else if (am == VME_A24) { vme_space = am; ctl &= ~CTL_VAS; ctl |= CTL_VAS_A24; } else if (am == VME_A32) { vme_space = am; ctl &= ~CTL_VAS; ctl |= CTL_VAS_A32; } else if (am == VME_CR_CSR) { vme_space = am; ctl &= ~CTL_VAS; ctl |= CTL_VAS_CR_CSR; } else { throw VME_InvalidMapping(); } pci_bound_addr = pci_base_addr + (((count-1) / 0x10000)+1)*0x10000; vme_base_addr = addr; to = -pci_base_addr + vme_base_addr; ctl &= ~CTL_EN; // Disable Slave ioctl(vme_handle,IOCTL_SET_CTL,ctl); ioctl(vme_handle,IOCTL_SET_TO,to); ioctl(vme_handle,IOCTL_SET_BD,pci_bound_addr); ioctl(vme_handle,IOCTL_SET_BS,pci_base_addr); // Must set this after BD ctl |= CTL_EN; // Enable Slave ioctl(vme_handle,IOCTL_SET_CTL,ctl); if (space & VME_DMA_MODE) ioctl(vme_handle,IOCTL_SET_MODE,MODE_DMA); else ioctl(vme_handle,IOCTL_SET_MODE,MODE_PROGRAMMED);}//-----------------------------------------------------------------------------// Function : ~VMEBus// Inputs : // Outputs :// Description: Close handles to Universe Driver// Remarks :// History ://-----------------------------------------------------------------------------VMEBus::~VMEBus(){ close(vme_handle); close(uni_handle);}//-----------------------------------------------------------------------------// Function : ReadUniReg// Inputs : // int reg - Universe Register address to read// Outputs : value of universe register// Description:// Remarks : See Universe ca91c042 documentation for registers// History ://-----------------------------------------------------------------------------unsigned int VMEBus::ReadUniReg(int reg){ unsigned int v; lseek(uni_handle,reg,SEEK_SET); read(uni_handle,&v,4); return v;}//-----------------------------------------------------------------------------// Function : WriteUniReg// Inputs : // int reg - Universe Register address to read// uint v - value to write to the register// Outputs :// Description: Write a value to the universe register// Remarks : See Universe ca91c042 documentation for registers// History ://-----------------------------------------------------------------------------void VMEBus::WriteUniReg(int reg, unsigned int v){ lseek(uni_handle,reg,SEEK_SET); write(uni_handle,&v,4);}//-----------------------------------------------------------------------------// Function : ReadByte// Inputs : // int addr - VME byte Address to Read the byte from// Outputs : the byte that was read// Description: Read a byte from the VME Bus// Remarks : Will throw a BusError execption if there is an error// History ://-----------------------------------------------------------------------------unsigned char VMEBus::ReadByte(int addr){ int c; unsigned char v[4]; lseek(vme_handle,addr,SEEK_SET); c = read(vme_handle,v,1);#ifdef DEBUG printf("<libvme:ReadByte> addr=%08X v=%02X s=%01X\n", addr, *v, c);#endif if (c != 1) { lasterror = -1; throw VME_BusError(addr + c, c, VME_TYPE_READ); } else lasterror = 0; return v[0];}//-----------------------------------------------------------------------------// Function : ReadWord// Inputs : // int addr - VME byte Address to Read the word from// Outputs : the value of the word// Description: Read a word from the VME Bus// Remarks : Will throw a BusError execption if there is an error// History ://-----------------------------------------------------------------------------unsigned short VMEBus::ReadWord(int addr){ int c; unsigned short v[2]; lseek(vme_handle,addr,SEEK_SET); c = read(vme_handle,&v,2);#ifdef DEBUG printf("<libvme:ReadWord> addr=%08X v=%02X s=%01X\n", addr, *v, c);#endif if (c != 2) { lasterror = -1; throw VME_BusError(addr + c, c, VME_TYPE_READ); } else lasterror = 0; if (iSwapEndian) return SwapEndian(v[0]); else return v[0]; }//-----------------------------------------------------------------------------// Function : ReadLong
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -