From ad302ea835907656ecfe1cc73de3df3bb29e7095 Mon Sep 17 00:00:00 2001 From: Rolf Bork <rolf.bork@ligo.org> Date: Thu, 21 Dec 2017 16:38:31 +0000 Subject: [PATCH] These modules were developed for early long rnage PCIe network switch but no longer used. git-svn-id: https://redoubt.ligo-wa.caltech.edu/svn/advLigoRTS/trunk@4604 6dcd42c9-f523-4c6d-aada-af552506706e --- src/fe/controllerSwitch.c | 576 ------------------------------ src/fe/moduleLoadSwitch.c | 733 -------------------------------------- 2 files changed, 1309 deletions(-) delete mode 100644 src/fe/controllerSwitch.c delete mode 100644 src/fe/moduleLoadSwitch.c diff --git a/src/fe/controllerSwitch.c b/src/fe/controllerSwitch.c deleted file mode 100644 index 2bd05c215..000000000 --- a/src/fe/controllerSwitch.c +++ /dev/null @@ -1,576 +0,0 @@ -/*----------------------------------------------------------------------*/ -/* */ -/* ------------------- */ -/* */ -/* LIGO */ -/* */ -/* THE LASER INTERFEROMETER GRAVITATIONAL WAVE OBSERVATORY. */ -/* */ -/* (C) The LIGO Project, 2012. */ -/* */ -/* */ -/*----------------------------------------------------------------------*/ - -/// @file controllerSwitch.c -/// @brief Main scheduler program for compiled real-time kernal object. \n -/// @detail More information can be found in the following DCC document: -///< <a href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=7688">T0900607 CDS RT Sequencer Software</a> -/// @author R.Bork, A.Ivanov -/// @copyright Copyright (C) 2014 LIGO Project \n -///< California Institute of Technology \n -///< Massachusetts Institute of Technology \n\n -/// @license This program is free software: you can redistribute it and/or modify -///< it under the terms of the GNU General Public License as published by -///< the Free Software Foundation, version 3 of the License. \n -///< This program is distributed in the hope that it will be useful, -///< but WITHOUT ANY WARRANTY; without even the implied warranty of -///< MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -///< GNU General Public License for more details. - - -#include <linux/version.h> -#include <linux/init.h> -#undef printf -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/proc_fs.h> -#include <linux/kthread.h> -#include <asm/delay.h> -#include <asm/cacheflush.h> - -#include <linux/slab.h> -/// Can't use printf in kernel module so redefine to use Linux printk function -#define printf printk -#include <drv/cdsHardware.h> -#include "inlineMath.h" - -#include </usr/src/linux/arch/x86/include/asm/processor.h> -#include </usr/src/linux/arch/x86/include/asm/cacheflush.h> - -// Code can be run without shutting down CPU by changing this compile flag -#undef NO_CPU_SHUTDOWN -#ifndef NO_CPU_SHUTDOWN -extern int vprintkl(const char*, va_list); -extern int printkl(const char*, ...); -char fmt1[512]; -int printk(const char *fmt, ...) { - va_list args; - int r; - - strcat(strcpy(fmt1, SYSTEM_NAME_STRING_LOWER), ": "); - strcat(fmt1, fmt); - va_start(args, fmt); - r = vprintkl(fmt1, args); - va_end(args); - return r; -} -#endif - - -#include "fm10Gen.h" // CDS filter module defs and C code -#include "feComms.h" // Lvea control RFM network defs. -#include "daqmap.h" // DAQ network layout -#include "controller.h" - -#include "drv/map.h" // PCI hardware defs -#include "drv/epicsXfer.c" // User defined EPICS to/from FE data transfer function -#include "timing.c" // timing module / IRIG-B functions - -#include "drv/inputFilterModule.h" -#include "drv/inputFilterModule1.h" - -#ifdef DOLPHIN_TEST -#include "dolphinNet1.c" -#endif - -/// Maintains present cycle count within a one second period. -int cycleNum = 0; -/// Value of readback from DAC FIFO size registers; used in diags for FIFO overflow/underflow. -unsigned int cycle_gps_time = 0; // Time at which ADCs triggered -unsigned int cycle_gps_event_time = 0; // Time at which ADCs triggered -unsigned int cycle_gps_ns = 0; -unsigned int cycle_gps_event_ns = 0; -unsigned int gps_receiver_locked = 0; // Lock/unlock flag for GPS time card -/// GPS time in GPS seconds -unsigned int timeSec = 0; -unsigned int timeSecDiag = 0; -/* 1 - error occured on shmem; 2 - RFM; 3 - Dolphin */ -unsigned int ipcErrBits = 0; -int adcTime; ///< Used in code cycle timing -int adcHoldTime; ///< Stores time between code cycles -int adcHoldTimeMax; ///< Stores time between code cycles -int adcHoldTimeEverMax; ///< Maximum cycle time recorded -int adcHoldTimeEverMaxWhen; -int cpuTimeEverMax; ///< Maximum code cycle time recorded -int cpuTimeEverMaxWhen; -int startGpsTime; -int adcHoldTimeMin; -int adcHoldTimeAvg; -int adcHoldTimeAvgPerSec; -int usrTime; ///< Time spent in user app code -int usrHoldTime; ///< Max time spent in user app code -int cardCountErr = 0; -int cycleTime; ///< Current cycle time -int timeHold = 0; ///< Max code cycle time within 1 sec period -int timeHoldHold = 0; ///< Max code cycle time within 1 sec period; hold for another sec -int timeHoldWhen= 0; ///< Cycle number within last second when maximum reached; running -int timeHoldWhenHold = 0; ///< Cycle number within last second when maximum reached - -// The following are for timing histograms written to /proc files -#if defined(SERVO64K) || defined(SERVO32K) -unsigned int cycleHist[32]; -unsigned int cycleHistMax[32]; -unsigned int cycleHistWhen[32]; -unsigned int cycleHistWhenHold[32]; -#elif defined(SERVO16K) -unsigned int cycleHist[64]; -unsigned int cycleHistMax[64]; -unsigned int cycleHistWhen[64]; -unsigned int cycleHistWhenHold[64]; -#endif - - -int getGpsTime(unsigned int *tsyncSec, unsigned int *tsyncUsec); - -// Include C code modules -#include "moduleLoadSwitch.c" -#include "map.c" - - -char daqArea[2*DAQ_DCU_SIZE]; // Space allocation for daqLib buffers -int cpuId = 1; - -// All systems not running at 64K require up/down sampling to communicate I/O data -// with IOP, which is running at 64K. -// Following defines the filter coeffs for these up/down filters. -#ifdef OVERSAMPLE - - -/* Recalculated filters in biquad form */ - -/* Oversamping base rate is 64K */ -/* Coeffs for the 2x downsampling (32K system) filter */ -static double __attribute__ ((unused)) feCoeff2x[9] = - {0.053628649721183, - 0.2568759660371100, -0.3225906481359000, 1.2568801238621801, 1.6774135096891700, - -0.2061764045745400, -1.0941543149527400, 2.0846376586498803, 2.1966597482716801}; - -/* Coeffs for the 4x downsampling (16K system) filter */ -static double __attribute__ ((unused)) feCoeff4x[9] = - {0.014805052402446, - 0.7166258547451800, -0.0683289874517300, 0.3031629575762000, 0.5171469569032900, - 0.6838596423885499, -0.2534855521841101, 1.6838609161411500, 1.7447155374502499}; - -// -// New Brian Lantz 4k decimation filter -static double __attribute__ ((unused)) feCoeff16x[9] = - {0.010203728365, - 0.8052941009065100, -0.0241751519071000, 0.3920490703701900, 0.5612099784288400, - 0.8339678987936501, -0.0376022631287799, -0.0131581721533700, 0.1145865116421301}; - - -/* Coeffs for the 32x downsampling filter (2K system) per Brian Lantz May 5, 2009 */ -static double __attribute__ ((unused)) feCoeff32x[9] = - {0.010581064947739, - 0.90444302586137004, -0.0063413204375699639, -0.056459743474659874, 0.032075154877300172, - 0.92390910024681006, -0.0097523655540199261, 0.077383808424050127, 0.14238741130302013}; - - -// History buffers for oversampling filters -double dHistory[(MAX_ADC_MODULES * 32)][MAX_HISTRY]; -double dDacHistory[(MAX_DAC_MODULES * 16)][MAX_HISTRY]; -#else - -#define OVERSAMPLE_TIMES 1 -#endif - -#ifdef DUAL_DAQ_DC - #define MX_OK 15 -#else - #define MX_OK 3 -#endif - -// Whether run on internal timer (when no ADC cards found) -int run_on_timer = 1; - -// Initial diag reset flag -int initialDiagReset = 1; - -// Cache flushing mumbo jumbo suggested by Thomas Gleixner, it is probably useless -// Did not see any effect - char fp [64*1024]; - - -//*********************************************************************** -// TASK: fe_start() -// This routine is the skeleton for all front end code -//*********************************************************************** -/// This function is the main real-time sequencer or scheduler for all code built -/// using the RCG. \n -/// There are two primary modes of operation, based on two compile options: \n -/// - ADC_MASTER: Software is compiled as an I/O Processor (IOP). -/// - ADC_SLAVE: Normal user control process. -/// This code runs in a continuous loop at the rate specified in the RCG model. The -/// loop is synchronized and triggered by the arrival of ADC data, the ADC module in turn -/// is triggered to sample by the 64KHz clock provided by the Timing Distribution System. -/// - -void *fe_start(void *arg) -{ - int longestWrite2 = 0; - int tempClock[4]; - int ii,jj,kk,ll,mm; // Dummy loop counter variables - static int cpuClock[CPU_TIMER_CNT]; /// @param cpuClock[] Code timing diag variables - - int adcWait = 0; - - static int dacWriteEnable = 0; /// @param dacWriteEnable No DAC outputs until >4 times through code - ///< Code runs longer for first few cycles on startup as it settles in, - int dacEnable = 0; - int pBits[9] = {1,2,4,8,16,32,64,128,256}; /// @param pBits[] Lookup table for quick power of 2 calcs - RFM_FE_COMMS *pEpicsComms; /// @param *pEpicsComms Pointer to EPICS shared memory space - int timeHoldMax = 0; /// @param timeHoldMax Max code cycle time since last diag reset - int status; /// @param status Typical function return value - int dcuId; /// @param dcuId DAQ ID number for this process - static int missedCycle = 0; /// @param missedCycle Incremented error counter when too many values in ADC FIFO - int diagWord = 0; /// @param diagWord Code diagnostic bit pattern returned to EPICS - int system = 0; - int syncSource = SYNC_SRC_NONE; /// @param syncSource Code startup synchronization source - - int feStatus = 0; - - static unsigned int clk, clk1; // Used only when run on timer enabled (test mode) - - int cnt = 0; - unsigned long cpc; - -/// **********************************************************************************************\n -/// Start Initialization Process \n -/// **********************************************************************************************\n - memset (tempClock, 0, sizeof(tempClock)); - - /// \> Flush L1 cache - memset (fp, 0, 64*1024); - memset (fp, 1, 64*1024); - clflush_cache_range ((void *)fp, 64*1024); - - fz_daz(); /// \> Kill the denorms! - -// Set memory for cycle time history diagnostics -#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K) - memset(cycleHist, 0, sizeof(cycleHist)); - memset(cycleHistMax, 0, sizeof(cycleHistMax)); - memset(cycleHistWhen, 0, sizeof(cycleHistWhen)); - memset(cycleHistWhenHold, 0, sizeof(cycleHistWhenHold)); -#endif - - /// \> Init comms with EPICS processor */ - pEpicsComms = (RFM_FE_COMMS *)_epics_shm; - pLocalEpics = (CDS_EPICS *)&pEpicsComms->epicsSpace; - pEpicsDaq = (char *)&(pLocalEpics->epicsOutput); -// printf("Epics at 0x%x and DAQ at 0x%x size = %d \n",pLocalEpics,pEpicsDaq,sizeof(CDS_EPICS_IN)); - -#ifdef OVERSAMPLE - /// \> Zero out filter histories - memset(dHistory, 0, sizeof(dHistory)); - memset(dDacHistory, 0, sizeof(dDacHistory)); -#endif - - /// \> Set pointers to filter module data buffers. \n - /// - ---- Prior to V2.8, separate local/shared memories for FILT_MOD data.\n - /// - ---- V2.8 and later, code uses EPICS shared memory only. This was done to: \n - /// - -------- Allow daqLib.c to retrieve filter module data directly from shared memory. \n - /// - -------- Avoid copy of filter module data between to memory locations, which was slow. \n - pDsp[system] = (FILT_MOD *)(&pEpicsComms->dspSpace); - pCoeff[system] = (VME_COEF *)(&pEpicsComms->coeffSpace); - dspPtr[system] = (FILT_MOD *)(&pEpicsComms->dspSpace); - - /// \> Clear the FE reset which comes from Epics - pLocalEpics->epicsInput.vmeReset = 0; - - // Clear input masks - pLocalEpics->epicsInput.burtRestore_mask = 0; - pLocalEpics->epicsInput.dacDuoSet_mask = 0; - memset(proc_futures, 0, sizeof(proc_futures)); - -/// \> Init code synchronization source. - syncSource = SYNC_SRC_1PPS; - -printf("Sync source = %d\n",syncSource); - - -/// \> Wait for BURT restore.\n -/// - ---- Code will exit if BURT flag not set by EPICS sequencer. - // Do not proceed until EPICS has had a BURT restore ******************************* - printf("Waiting for EPICS BURT Restore = %d\n", pLocalEpics->epicsInput.burtRestore); - cnt = 0; - do{ - udelay(MAX_UDELAY); - udelay(MAX_UDELAY); - udelay(MAX_UDELAY); - printf("Waiting for EPICS BURT %d\n", cnt++); - cpu_relax(); - }while(!pLocalEpics->epicsInput.burtRestore); - - printf("BURT Restore Complete\n"); - -// BURT has completed ******************************************************************* - -/// < Read in all Filter Module EPICS coeff settings - for(ii=0;ii<MAX_MODULES;ii++) - { - checkFiltReset(ii, dspPtr[0], pDsp[0], &dspCoeff[0], MAX_MODULES, pCoeff[0]); - } - - // Need this FE dcuId to make connection to FB - dcuId = pLocalEpics->epicsInput.dcuId; - pLocalEpics->epicsOutput.dcuId = dcuId; - - // Reset timing diagnostics - pLocalEpics->epicsOutput.diagWord = 0; - pLocalEpics->epicsOutput.timeDiag = 0; - pLocalEpics->epicsOutput.timeErr = syncSource; - for(ii=0;ii<32;ii++) { - pLocalEpics->epicsOutput.gdsMon[ii] = 0; - } - -/// \> Init IIR filter banks -// Initialize filter banks ********************************************* - for (system = 0; system < NUM_SYSTEMS; system++) { - for(ii=0;ii<MAX_MODULES;ii++){ - for(jj=0;jj<FILTERS;jj++){ - for(kk=0;kk<MAX_COEFFS;kk++){ - dspCoeff[system].coeffs[ii].filtCoeff[jj][kk] = 0.0; - } - dspCoeff[system].coeffs[ii].filtSections[jj] = 0; - } - } - } - - /// \> Initialize all filter module excitation signals to zero - for (system = 0; system < NUM_SYSTEMS; system++) - for(ii=0;ii<MAX_MODULES;ii++) - // dsp[system].data[ii].exciteInput = 0.0; - pDsp[0]->data[ii].exciteInput = 0.0; - - - /// \> Initialize IIR filter bank values - if (initVars(pDsp[0], pDsp[0], dspCoeff, MAX_MODULES, pCoeff[0])) { - printf("Filter module init failed, exiting\n"); - return 0; - } - - printf("Initialized servo control parameters.\n"); - -udelay(1000); - - pLocalEpics->epicsOutput.ipcStat = 0; - pLocalEpics->epicsOutput.fbNetStat = 0; - pLocalEpics->epicsOutput.tpCnt = 0; - - // Clear the code exit flag - vmeDone = 0; - - /// \> Call user application software initialization routine. - printf("Calling feCode() to initialize\n"); - iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0], (struct CDS_EPICS *)pLocalEpics,1); - - // Clear timing diags. - adcHoldTime = 0; - adcHoldTimeMax = 0; - adcHoldTimeEverMax = 0; - adcHoldTimeEverMaxWhen = 0; - cpuTimeEverMax = 0; - cpuTimeEverMaxWhen = 0; - startGpsTime = 0; - adcHoldTimeMin = 0xffff; - adcHoldTimeAvg = 0; - usrHoldTime = 0; - missedCycle = 0; - - printf("\n*******************************\n"); - printf("* Running on timer! *\n"); - printf("*******************************\n"); - - timeSec = current_time() -1; - - rdtscl(adcTime); - - /// ******************************************************************************\n - /// Enter the infinite FE control loop ******************************************\n - - /// ******************************************************************************\n - // Calculate how many CPU cycles per code cycle - cpc = cpu_khz * 1000; - cpc /= CYCLE_PER_SECOND; - printf("CPC is %d \n",cpc); - - rdtscll(clk); - rdtscl(cpuClock[CPU_TIME_CYCLE_START]); - unsigned long long clkchk = 0; - - while(!vmeDone){ // Run forever until user hits reset - rdtscll(clk); - // Pause until next cycle begins - if (cycleNum == 0) { - // pLocalEpics->epicsOutput.awgStat = (pEpicsComms->padSpace.awgtpman_gps != timeSec); - // if(pLocalEpics->epicsOutput.awgStat) feStatus |= FE_ERROR_AWG; - /// - ---- Check if DAC outputs are enabled, report error. - if(!iopDacEnable) feStatus |= FE_ERROR_DAC_ENABLE; - // Increment GPS second on cycle 0 - timeSec = current_time(); - if (cycle_gps_time == 0) startGpsTime = timeSec; - cycle_gps_time = timeSec; - pLocalEpics->epicsOutput.timeDiag = timeSec; - // printf("Time is %d - clk = %ld\n",timeSec,clk); - } - rdtscl(cpuClock[CPU_TIME_CYCLE_START]); - - -/// \> Call the front end specific application ******************\n -/// - -- This is where the user application produced by RCG gets called and executed. \n\n - rdtscl(cpuClock[CPU_TIME_USR_START]); - iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0],(struct CDS_EPICS *)pLocalEpics,0); - rdtscl(cpuClock[CPU_TIME_USR_END]); - -/// \> Send IPC info the gdsMon ******************\n -#ifdef ADC_MASTER - if(cycleNum == 5) { - ioMemData->ipcDetect[0][0] = pLocalEpics->epicsOutput.gdsMon[0]; - ioMemData->ipcDetect[0][1] = pLocalEpics->epicsOutput.gdsMon[1]; - ioMemData->ipcDetect[0][2] = pLocalEpics->epicsOutput.gdsMon[2]; - ioMemData->ipcDetect[0][3] = pLocalEpics->epicsOutput.gdsMon[3]; - ioMemData->ipcDetect[1][0] = pLocalEpics->epicsOutput.gdsMon[4]; - ioMemData->ipcDetect[1][1] = pLocalEpics->epicsOutput.gdsMon[5]; - ioMemData->ipcDetect[1][2] = pLocalEpics->epicsOutput.gdsMon[6]; - ioMemData->ipcDetect[1][3] = pLocalEpics->epicsOutput.gdsMon[7]; - } -#else - if(cycleNum == 15) { - pLocalEpics->epicsOutput.gdsMon[10] = ioMemData->ipcDetect[0][0]; - pLocalEpics->epicsOutput.gdsMon[11] = ioMemData->ipcDetect[0][1]; - pLocalEpics->epicsOutput.gdsMon[12] = ioMemData->ipcDetect[0][2]; - pLocalEpics->epicsOutput.gdsMon[13] = ioMemData->ipcDetect[0][3]; - pLocalEpics->epicsOutput.gdsMon[14] = ioMemData->ipcDetect[1][0]; - pLocalEpics->epicsOutput.gdsMon[15] = ioMemData->ipcDetect[1][1]; - pLocalEpics->epicsOutput.gdsMon[16] = ioMemData->ipcDetect[1][2]; - pLocalEpics->epicsOutput.gdsMon[17] = ioMemData->ipcDetect[1][3]; - } -#endif - - -/// BEGIN HOUSEKEEPING ************************************************ \n - - pLocalEpics->epicsOutput.cycle = cycleNum; - - -/// \> Cycle 18, Send timing info to EPICS at 1Hz - if(cycleNum ==HKP_TIMING_UPDATES) - { - pLocalEpics->epicsOutput.cpuMeter = timeHold; - pLocalEpics->epicsOutput.cpuMeterMax = timeHoldMax; - // pLocalEpics->epicsOutput.dacEnable = dacEnable; - timeHoldHold = timeHold; - timeHold = 0; - timeHoldWhenHold = timeHoldWhen; - - if(timeHoldMax > CYCLE_TIME_ALRM) - { - diagWord |= FE_PROC_TIME_ERR; - feStatus |= FE_ERROR_TIMING; - } - // pLocalEpics->epicsOutput.stateWord = feStatus; - feStatus = 0; - if(pLocalEpics->epicsInput.diagReset || initialDiagReset) - { - initialDiagReset = 0; - pLocalEpics->epicsInput.diagReset = 0; - pLocalEpics->epicsInput.ipcDiagReset = 1; - // pLocalEpics->epicsOutput.diags[1] = 0; - timeHoldMax = 0; - diagWord = 0; - ipcErrBits = 0; - - // feStatus = 0; - } - // Flip the onePPS various once/sec as a watchdog monitor. - pLocalEpics->epicsOutput.diagWord = diagWord; - } - - - /// \> Check if code exit is requested - if(cycleNum == MAX_MODULES) - vmeDone = stop_working_threads | checkEpicsReset(cycleNum, (struct CDS_EPICS *)pLocalEpics); - - -/// \> Cycle 19, write updated diag info to EPICS - if(cycleNum == HKP_DIAG_UPDATES) - { - pLocalEpics->epicsOutput.userTime = usrHoldTime; - } - - // Capture end of cycle time. - rdtscl(cpuClock[CPU_TIME_CYCLE_END]); - - /// \> Compute code cycle time diag information. - cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE; - if (longestWrite2 < ((tempClock[3]-tempClock[2])/CPURATE)) longestWrite2 = (tempClock[3]-tempClock[2])/CPURATE; - if (cycleTime > (1000000/CYCLE_PER_SECOND)) { - // printf("cycle %d time %d; adcWait %d; write1 %d; write2 %d; longest write2 %d\n", cycleNum, cycleTime, adcWait, (tempClock[1]-tempClock[0])/CPURATE, (tempClock[3]-tempClock[2])/CPURATE, longestWrite2); - } - // Hold the max cycle time over the last 1 second - if(cycleTime > timeHold) { - timeHold = cycleTime; - timeHoldWhen = cycleNum; - } - // Hold the max cycle time since last diag reset - if(cycleTime > timeHoldMax) timeHoldMax = cycleTime; - adcHoldTime = (cpuClock[CPU_TIME_CYCLE_START] - adcTime)/CPURATE; - // Avoid calculating the max hold time for the first few seconds - if (cycleNum != 0 && (startGpsTime+3) < cycle_gps_time) { - if(adcHoldTime > adcHoldTimeMax) adcHoldTimeMax = adcHoldTime; - if(adcHoldTime < adcHoldTimeMin) adcHoldTimeMin = adcHoldTime; - adcHoldTimeAvg += adcHoldTime; - if (adcHoldTimeMax > adcHoldTimeEverMax) { - adcHoldTimeEverMax = adcHoldTimeMax; - adcHoldTimeEverMaxWhen = cycle_gps_time; - //printf("Maximum adc hold time %d on cycle %d gps %d\n", adcHoldTimeMax, cycleNum, cycle_gps_time); - } - if (timeHoldMax > cpuTimeEverMax) { - cpuTimeEverMax = timeHoldMax; - cpuTimeEverMaxWhen = cycle_gps_time; - } - } - adcTime = cpuClock[CPU_TIME_CYCLE_START]; - // Calc the max time of one cycle of the user code - // For IOP, more interested in time to get thru ADC read code and send to slave apps - usrTime = (cpuClock[CPU_TIME_USR_START] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE; - if(usrTime > usrHoldTime) usrHoldTime = usrTime; - - /// \> Update internal cycle counters - cycleNum += 1; - cycleNum %= CYCLE_PER_SECOND; - if(subcycle == DAQ_CYCLE_CHANGE) - { - daqCycle = (daqCycle + 1) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; - if(!(daqCycle % 2)) pLocalEpics->epicsOutput.epicsSync = daqCycle; - } - if(subcycle == END_OF_DAQ_BLOCK) /*we have reached the 16Hz second barrier*/ - { - /* Reset the data cycle counter */ - subcycle = 0; - - } - else{ - /* Increment the internal cycle counter */ - subcycle ++; - } - -/// \> If not exit request, then continue INFINITE LOOP ******* - } - - printf("exiting from fe_code()\n"); - pLocalEpics->epicsOutput.cpuMeter = 0; - - /* System reset command received */ - return (void *)-1; -} diff --git a/src/fe/moduleLoadSwitch.c b/src/fe/moduleLoadSwitch.c deleted file mode 100644 index fca93efdf..000000000 --- a/src/fe/moduleLoadSwitch.c +++ /dev/null @@ -1,733 +0,0 @@ -/// @file moduleLoad.c -/// @brief File contains startup routines for real-time code. - -#include <asm/uaccess.h> -#include <linux/ctype.h> -#include <linux/spinlock_types.h> -#include <proc.h> - - -// These externs and "16" need to go to a header file (mbuf.h) -extern void *kmalloc_area[16]; -extern int mbuf_allocate_area(char *name, int size, struct file *file); -extern void *fe_start(void *arg); -extern int run_on_timer; -extern char daqArea[2*DAQ_DCU_SIZE]; // Space allocation for daqLib buffers - -#include FE_PROC_FILE - -/// /proc filesystem directory entry -struct proc_dir_entry *proc_dir_entry; -/// /proc/{sysname}/status entry -struct proc_dir_entry *proc_entry; -/// /proc/{sysname}/gps entry -struct proc_dir_entry *proc_gps_entry; -/// /proc/{sysname}/epics directory entry -struct proc_dir_entry *proc_epics_dir_entry; -/// /proc/{sysname}/futures entry -struct proc_dir_entry *proc_futures_entry; - -void remove_epics_proc_files(void); -int create_epics_proc_files(void); - -/// Routine to read the /proc/{model}/status file. \n \n -/// We give all of our information in one go, so if the -/// user asks us if we have more information the \n -/// answer should always be no. -/// -/// This is important because the standard read -/// function from the library would continue to issue \n -/// the read system call until the kernel replies -/// that it has no more information, or until its \n -/// buffer is filled. -int -procfile_status_read(char *buffer, - char **buffer_location, - off_t offset, int buffer_length, int *eof, void *data) -{ - int ret, i; - i = 0; - *buffer = 0; - - /* - * We give all of our information in one go, so if the - * user asks us if we have more information the - * answer should always be no. - * - * This is important because the standard read - * function from the library would continue to issue - * the read system call until the kernel replies - * that it has no more information, or until its - * buffer is filled. - */ - if (offset > 0) { - /* we have finished to read, return 0 */ - ret = 0; - } else { -#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K) || defined(SERVO256K) || defined(SERVO128K) || defined(COMMDATA_INLINE) - char b[128]; -#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO256K) || defined(SERVO128K) - static const int nb = 32; -#elif defined(SERVO16K) - static const int nb = 64; -#endif -#endif - /* fill the buffer, return the buffer size */ - ret = sprintf(buffer, - - "startGpsTime=%d\n" - "uptime=%d\n" - "cpuTimeEverMax=%d\n" - "cpuTimeEverMaxWhen=%d\n" - "adcHoldTime=%d\n" - "adcHoldTimeEverMax=%d\n" - "adcHoldTimeEverMaxWhen=%d\n" - "adcHoldTimeMax=%d\n" - "adcHoldTimeMin=%d\n" - "adcHoldTimeAvg=%d\n" - "usrTime=%d\n" - "usrHoldTime=%d\n" - "cycle=%d\n" - "gps=%d\n" - "buildDate=%s\n" - "cpuTimeMax(cur,past sec)=%d,%d\n" - "cpuTimeMaxCycle(cur,past sec)=%d,%d\n", - - startGpsTime, - cycle_gps_time - startGpsTime, - cpuTimeEverMax, - cpuTimeEverMaxWhen, - adcHoldTime, - adcHoldTimeEverMax, - adcHoldTimeEverMaxWhen, - adcHoldTimeMax, - adcHoldTimeMin, - adcHoldTimeAvgPerSec, - usrTime, - usrHoldTime, - cycleNum, - cycle_gps_time, - build_date, - cycleTime, timeHoldHold, - timeHoldWhen, timeHoldWhenHold); -#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K) - strcat(buffer, "cycleHist: "); - for (i = 0; i < nb; i++) { - if (!cycleHistMax[i]) continue; - sprintf(b, "%d=%d@%d ", i, cycleHistMax[i], cycleHistWhenHold[i]); - strcat(buffer, b); - } - strcat(buffer, "\n"); -#endif - -#ifdef COMMDATA_INLINE - // See if we have any IPC with errors and print the numbers out - // - sprintf(b, "ipcErrBits=0x%x\n", ipcErrBits); - strcat(buffer, b); - - // The following loop has a chance to overflow the buffer, - // which is set to PROC_BLOCK_SIZE. (PAGE_SIZE-1024 = 3072 bytes). - // We will simply stop printing at that point. -#define PROC_BLOCK_SIZE (3*1024) - unsigned int byte_cnt = strlen(buffer) + 1; - for (i = 0; i < myIpcCount; i++) { - if (ipcInfo[i].errTotal) { - unsigned int cnt = - sprintf(b, "IPC net=%d num=%d name=%s sender=%s errcnt=%d\n", - ipcInfo[i].netType, ipcInfo[i].ipcNum, - ipcInfo[i].name, ipcInfo[i].senderModelName, - ipcInfo[i].errTotal); - if (byte_cnt + cnt > PROC_BLOCK_SIZE) break; - byte_cnt += cnt; - strcat(buffer, b); - } - } -#endif - ret = strlen(buffer); - } - - return ret; -} - -/// Routine to read the /proc/{model}/gps file. \n \n -/// -int -procfile_gps_read(char *buffer, - char **buffer_location, - off_t offset, int buffer_length, int *eof, void *data) -{ - *buffer = 0; - - if (offset > 0) { - /* we have finished to read, return 0 */ - return 0; - } else { - /* fill the buffer, return the buffer size */ - /* print current GPS time and zero padded fraction */ - return sprintf(buffer, "%d.%02d\n", cycle_gps_time, (cycleNum*100/CYCLE_PER_SECOND)%100); - } - // Never reached -} - -/// Routine to read the /proc/{model}/epics/{chname} files. \n \n -/// -int -procfile_epics_read(char *buffer, - char **buffer_location, - off_t offset, int buffer_length, int *eof, void *data) -{ - *buffer = 0; - - if (offset > 0) { - /* we have finished to read, return 0 */ - return 0; - } else { - /* fill the buffer, return the buffer size */ - struct proc_epics *pe = (struct proc_epics *)data; - unsigned int ncel = pe->nrow * pe->ncol; // Matrix size - switch (pe -> type) { - case 0: /* int */ - return sprintf(buffer, "%s%d\n", - (*((char *)(((void *)pLocalEpics) + pe->mask_idx)))? "\t": "", - *((int *)(((void *)pLocalEpics) + pe->idx))); - // printf("Accessing data at %x\n", (((void *)pLocalEpics) + pe->idx)); - break; - case 1: /* double */ { - char lb[64]; - if (ncel) { /* Print Matrix */ - unsigned int i, j; - unsigned int nrow = pe->nrow; - unsigned int ncol = pe->ncol; - unsigned int s = 0; - unsigned int masked = *((char *)(((void *)pLocalEpics) + pe->mask_idx)); - for (i = 0; i < nrow; i++) { - if (masked) s += sprintf(buffer + s, "\t"); - for (j = 0; j < ncol; j++) { - s += sprintf(buffer + s, "%s ", dtoa_r(lb, ((double *)(((void *)pLocalEpics) + pe->idx))[ncol*i + j])); - } - s += sprintf(buffer + s, "\n"); - } - return s; - } else { /* Print single value */ - return sprintf(buffer, "%s%s\n", - (*((char *)(((void *)pLocalEpics) + pe->mask_idx)))? "\t": "", - dtoa_r(lb, *((double *)(((void *)pLocalEpics) + pe->idx)))); - } - break; - } - } - } - // Never reached -} - -#define PROC_BLOCK_SIZE (3*1024) - -// Scan a double -double -simple_strtod(char *start, char **end) { - int integer; - if (*start != '.') { - integer = simple_strtol(start, end, 10); - if (*end == start) return 0.0; - start = *end; - } else integer = 0; - if (*start != '.') return integer; - else { - start++; - double frac = simple_strtol(start, end, 10); - if (*end == start) return integer; - int i; - for (i = 0; i < (*end - start); i++) frac /= 10.0; - return ((double)integer) + frac; - } - // Never reached -} - - -int -procfile_epics_write(struct file *file, const char __user *buf, - unsigned long count, void *data) -{ - ssize_t ret = -ENOMEM; - char *page; - char *start; - unsigned int future = 0; - - if (count > PROC_BLOCK_SIZE) - return -EOVERFLOW; - - start = page = (char *)__get_free_page(GFP_KERNEL); - if (page) { - ret = -EFAULT; - if (copy_from_user(page, buf, count)) - goto out; - page[count] = 0; - ret = count; - struct proc_epics *pe = (struct proc_epics *)data; - char *end; - for(;isspace(*start);start++); - // See if this a single-character command - switch (*start) { - case 'm': - *((char *)(((void *)pLocalEpics) + pe->mask_idx)) = 1; - start++; - break; - case 'u': - *((char *)(((void *)pLocalEpics) + pe->mask_idx)) = 0; - start++; - break; - case 'f': - future=1; - start++; - break; - } - for(;isspace(*start);start++); - double new_double = 0.0; - int new_int = 0; - switch (pe -> type) { - case 0: /* int */ - new_int = simple_strtol(start, &end, 10); - if (new_int > INT_MAX || new_int < INT_MIN) { - ret = -EFAULT; - goto out; - } - break; - case 1: /* double */ - new_double = simple_strtod(start, &end); - //printf("User wrote %s\n", dtoa1(new_double)); - break; - } - if (end == start) goto out; - // See if this is a matrix - int idx = 0; - int ncel = pe->nrow * pe->ncol; - if (ncel) { - // Expect the cell index number next - start = end; - for(;isspace(*start);start++); - idx = simple_strtol(start, &end, 10); - if (idx >= ncel || idx < 0) { - ret = -EFAULT; - goto out; - } - - } - if (!future) { - switch (pe -> type) { - case 0: /* int */ - *((int *)(((void *)pLocalEpics) + pe->idx)) = new_int; - break; - case 1: /* double */ - ((double *)(((void *)pLocalEpics) + pe->idx))[idx] = new_double; - break; - } - } else if ((*((char *)(((void *)pLocalEpics) + pe->mask_idx)))) { // Allow to setup a future only if masked - unsigned long cycle; - start = end; - for(;isspace(*start);start++); - // check for gps seconds - double gps = simple_strtod(start, &end); - if (end == start) { - gps = cycle_gps_time + 5; - cycle = cycleNum; - } else { - // Convert gps time - unsigned long gps_int = gps; - gps -= gps_int; - cycle = gps * CYCLE_PER_SECOND; - gps = gps_int; - } - // Add new future setpoint - // Find first available slot - int i; - static DEFINE_SPINLOCK(fut_lock); - spin_lock(&fut_lock); - for (i = 0; (i < MAX_PROC_FUTURES) && proc_futures[i].proc_epics; i++); - if (i == MAX_PROC_FUTURES) { - spin_unlock(&fut_lock); - ret = -ENOMEM; - } else { - // Found a slot - proc_futures[i].cycle = cycle; - proc_futures[i].gps = gps; - proc_futures[i].val = pe->type? new_double: new_int; - proc_futures[i].idx = idx; - - // This pointer has to be set last; Indicates a vailid entry for the - // real-time code in controller.c - proc_futures[i].proc_epics = pe; // FE code reads/writes this variable - spin_unlock(&fut_lock); - } - } else ret = -EFAULT; - } -out: - free_page((unsigned long)page); - return ret; -} - -/// Routine to read the /proc/{model}/epics/futures files. \n \n -/// -// :TODO: the function does not check for buffer overflow, Linux kernel catches it though, -// when proc_futures contains too many entries. -int -procfile_futures_read(char *buffer, - char **buffer_location, - off_t offset, int buffer_length, int *eof, void *data) -{ - *buffer = 0; - - if (offset > 0) { - /* we have finished to read, return 0 */ - return 0; - } else { - /* fill the buffer, return the buffer size */ - char b[128]; - int i; - for (i = 0; i < MAX_PROC_FUTURES; i++) { - // Copy the entry to avoid race with the FE code - struct proc_futures pf = proc_futures[i]; - if (pf.proc_epics) { - char s[64]; - char s1[64]; - if (pf.idx) { /* matrix */ - sprintf(b, "%s %s@%s %d %d\n", pf.proc_epics->name, dtoa_r(s, pf.val), dtoa_r(s1, pf.idx), pf.gps, pf.cycle); - } else { - sprintf(b, "%s %s %d %d\n", pf.proc_epics->name, dtoa_r(s, pf.val), pf.gps, pf.cycle); - } - strcat(buffer, b); - } - } - return strlen(buffer); - } - // Never reached -} - - -static const ner = sizeof(proc_epics)/sizeof(struct proc_epics); - -/// Function to create /proc/{model}/epics/* files -/// -int -create_epics_proc_files() { - int i; - - for (i = 0; i < ner; i++) proc_epics_entry[i] = 0; - - for (i = 0; i < ner; i++) { - //printf("%s\n", proc_epics[i].name); - proc_epics_entry[i] = create_proc_entry(proc_epics[i].name, PROC_MODE, proc_epics_dir_entry); - if (proc_epics_entry[i] == NULL) { - remove_epics_proc_files(); - printk(KERN_ALERT "Error: Could not initialize /proc/%s/epics/%s\n", SYSTEM_NAME_STRING_LOWER, proc_epics[i].name); - return 0; - } - proc_epics_entry[i]->mode = S_IFREG | S_IRUGO; - switch (proc_epics[i].in) { - case 0: - proc_epics_entry[i]->write_proc = procfile_epics_write; - proc_epics_entry[i]->mode |= S_IWUGO; - // Fall through - case 1: - proc_epics_entry[i]->read_proc = procfile_epics_read; - break; - } - proc_epics_entry[i]->uid = PROC_UID; - proc_epics_entry[i]->gid = 0; - unsigned int ncel = proc_epics[i].nrow * proc_epics[i].ncol; // Enough space to deal with the matrix - proc_epics_entry[i]->size = ncel? 64 * ncel: 128; - proc_epics_entry[i]->data = proc_epics + i; - } - proc_futures_entry = create_proc_entry("futures", PROC_MODE, proc_epics_dir_entry); - if (proc_futures_entry == NULL) { - remove_epics_proc_files(); - printk(KERN_ALERT "Error: Could not initialize /proc/%s/epics/futures\n", SYSTEM_NAME_STRING_LOWER); - return 0; - } - proc_futures_entry->mode = S_IFREG | S_IRUGO; - proc_futures_entry->uid = PROC_UID; - proc_futures_entry->gid = 0; - proc_futures_entry->size = 10240; - proc_futures_entry->read_proc = procfile_futures_read; - return 1; -} - -/// Function to delete /proc/{model}/epics/* files -/// -void remove_epics_proc_files() { - int i; - for (i = 0; i < ner; i++) - if (proc_epics_entry[i] != NULL) { - remove_proc_entry(proc_epics[i].name, proc_epics_dir_entry); - proc_epics_entry[i] = 0; - } - remove_proc_entry("futures", proc_epics_dir_entry); -} - -// MAIN routine: Code starting point **************************************************************** -#ifdef ADC_MASTER -int need_to_load_IOP_first; -EXPORT_SYMBOL(need_to_load_IOP_first); -#endif -#ifdef ADC_SLAVE -extern int need_to_load_IOP_first; -#endif - -extern void set_fe_code_idle(void *(*ptr)(void *), unsigned int cpu); -extern void msleep(unsigned int); - -/// Startup function for initialization of kernel module. -int init_module (void) -{ - int status; - int ii,jj,kk; /// @param ii,jj,kk default loop counters - char fname[128]; /// @param fname[128] Name of shared mem area to allocate for DAQ data - int cards; /// @param cards Number of PCIe cards found on bus - int ret; /// @param ret Return value from various Malloc calls to allocate memory. - int cnt; - extern int cpu_down(unsigned int); /// @param cpu_down CPU shutdown call. - extern int is_cpu_taken_by_rcg_model(unsigned int cpu); /// @param is_cpu_taken_by_rcg_model Check to verify CPU availability for shutdown. - - kk = 0; -#ifdef SPECIFIC_CPU -#define CPUID SPECIFIC_CPU -#else -#define CPUID 1 -#endif - -#ifndef NO_CPU_SHUTDOWN - // See if our CPU core is free - if (is_cpu_taken_by_rcg_model(CPUID)) { - printk(KERN_ALERT "Error: CPU %d already taken\n", CPUID); - return -1; - } -#endif - -#ifdef ADC_SLAVE - need_to_load_IOP_first = 0; -#endif - - -#ifdef DOLPHIN_TEST - status = init_dolphin(2); - if (status != 0) { - return -1; - } -#endif - - // Create /proc filesystem tree - proc_dir_entry = proc_mkdir(SYSTEM_NAME_STRING_LOWER, NULL); - if (proc_dir_entry == NULL) { - printk(KERN_ALERT "Error: Could not initialize /proc/%s\n", SYSTEM_NAME_STRING_LOWER); - return -ENOMEM; - } - - proc_entry = create_proc_entry("status", PROC_MODE, proc_dir_entry); - if (proc_entry == NULL) { - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); - printk(KERN_ALERT "Error: Could not initialize /proc/%s/status\n", SYSTEM_NAME_STRING_LOWER); - return -ENOMEM; - } - - proc_gps_entry = create_proc_entry("gps", PROC_MODE, proc_dir_entry); - if (proc_gps_entry == NULL) { - remove_proc_entry("status", proc_dir_entry); - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); - printk(KERN_ALERT "Error: Could not initialize /proc/%s/gps\n", SYSTEM_NAME_STRING_LOWER); - return -ENOMEM; - } - - proc_epics_dir_entry = proc_mkdir("epics", proc_dir_entry); - if (proc_epics_dir_entry == NULL) { - remove_proc_entry("gps", proc_dir_entry); - remove_proc_entry("status", proc_dir_entry); - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); - printk(KERN_ALERT "Error: Could not initialize /proc/%s/epics\n", SYSTEM_NAME_STRING_LOWER); - return -ENOMEM; - } - - proc_entry->read_proc = procfile_status_read; - proc_entry->mode = S_IFREG | S_IRUGO; - proc_entry->uid = PROC_UID; - proc_entry->gid = 0; - proc_entry->size = 10240; - - proc_gps_entry->read_proc = procfile_gps_read; - proc_gps_entry->mode = S_IFREG | S_IRUGO; - proc_gps_entry->uid = PROC_UID; - proc_gps_entry->gid = 0; - proc_gps_entry->size = 128; - proc_gps_entry->data = &cycle_gps_time; - - // Create all /proc/{system}/epics/* files, one file per existing Epics channel - if (create_epics_proc_files() == 0) { - remove_proc_entry("epics", proc_dir_entry); - remove_proc_entry("gps", proc_dir_entry); - remove_proc_entry("status", proc_dir_entry); - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); - return -ENOMEM; - } - - printf("startup time is %ld\n", current_time()); - jj = 0; - printf("cpu clock %u\n",cpu_khz); - - - ret = mbuf_allocate_area(SYSTEM_NAME_STRING_LOWER, 64*1024*1024, 0); - if (ret < 0) { - printf("mbuf_allocate_area() failed; ret = %d\n", ret); - return -1; - } - _epics_shm = (unsigned char *)(kmalloc_area[ret]); - printf("EPICSM at 0x%x\n", _epics_shm); - ret = mbuf_allocate_area("ipc", 4*1024*1024, 0); - if (ret < 0) { - printf("mbuf_allocate_area(ipc) failed; ret = %d\n", ret); - return -1; - } - _ipc_shm = (unsigned char *)(kmalloc_area[ret]); - - printf("IPC at 0x%x\n",_ipc_shm); - ioMemData = (IO_MEM_DATA *)(_ipc_shm+ 0x4000); - printf("IOMEM at 0x%x size 0x%x\n",(_ipc_shm + 0x4000),sizeof(IO_MEM_DATA)); - - - // Find and initialize all PCI I/O modules ******************************************************* - // Following I/O card info is from feCode - cards = sizeof(cards_used)/sizeof(cards_used[0]); - printf("configured to use %d cards\n", cards); - cdsPciModules.cards = cards; - cdsPciModules.cards_used = cards_used; - //return -1; - printf("Initializing PCI Modules\n"); - cdsPciModules.adcCount = 1; - for(ii=0;ii<cdsPciModules.adcCount;ii++) - cdsPciModules.adcType[ii] = GSC_16AI64SSA; - cdsPciModules.dacCount = 0; - cdsPciModules.dioCount = 0; - cdsPciModules.doCount = 0; -#ifdef DOLPHIN_TEST - ioMemData->dolphinCount = 0; - ioMemData->dolphinRead[0] = 0; - ioMemData->dolphinWrite[0] = 0; - ioMemData->dolphinRead[1] = 0; - ioMemData->dolphinWrite[1] = 0; - ioMemData->dolphinCount = cdsPciModules.dolphinCount; - ioMemData->dolphinRead[0] = cdsPciModules.dolphinRead[0]; - ioMemData->dolphinWrite[0] = cdsPciModules.dolphinWrite[0]; - ioMemData->dolphinRead[1] = cdsPciModules.dolphinRead[1]; - ioMemData->dolphinWrite[1] = cdsPciModules.dolphinWrite[1]; -#else - cdsPciModules.dolphinCount = ioMemData->dolphinCount; - cdsPciModules.dolphinRead[0] = ioMemData->dolphinRead[0]; - cdsPciModules.dolphinWrite[0] = ioMemData->dolphinWrite[0]; - cdsPciModules.dolphinRead[1] = ioMemData->dolphinRead[1]; - cdsPciModules.dolphinWrite[1] = ioMemData->dolphinWrite[1]; - printf("dr0 = 0x%lx \n",(unsigned long) cdsPciModules.dolphinRead[0]); - printf("dw0 = 0x%lx \n",(unsigned long) cdsPciModules.dolphinWrite[0]); - printf("dr1 = 0x%lx \n",(unsigned long) cdsPciModules.dolphinRead[1]); - printf("dw1 = 0x%lx \n",(unsigned long) cdsPciModules.dolphinWrite[1]); - if (cdsPciModules.dolphinCount != 2) { - return -1; - } -#endif - - - // Code will run on internal timer if no ADC modules are found - printf("Virtual IOP ******* running on timer\n"); - run_on_timer = 1; - - // Initialize buffer for daqLib.c code - printf("Initializing space for daqLib buffers\n"); - daqBuffer = (long)&daqArea[0]; - - - pLocalEpics = (CDS_EPICS *)&((RFM_FE_COMMS *)_epics_shm)->epicsSpace; - for (cnt = 0; cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++) { - printf("Epics burt restore is %d\n", pLocalEpics->epicsInput.burtRestore); - msleep(1000); - } - if (cnt == 10) { - // Cleanup - remove_epics_proc_files(); - remove_proc_entry("epics", proc_dir_entry); - remove_proc_entry("gps", proc_dir_entry); - remove_proc_entry("status", proc_dir_entry); - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); -#ifdef DOLPHIN_TEST - finish_dolphin(); -#endif - return -1; - } - - pLocalEpics->epicsInput.vmeReset = 0; - -#ifdef NO_CPU_SHUTDOWN - struct task_struct *p; - p = kthread_create(fe_start, 0, "fe_start/%d", CPUID); - if (IS_ERR(p)){ - printf("Failed to kthread_create()\n"); - return -1; - } - kthread_bind(p, CPUID); - wake_up_process(p); -#endif - - -#ifndef NO_CPU_SHUTDOWN - set_fe_code_idle(fe_start, CPUID); - msleep(100); - - cpu_down(CPUID); - - // The code runs on the disabled CPU -#endif - return 0; -} - -void cleanup_module (void) { - int i; - extern int __cpuinit cpu_up(unsigned int cpu); - - remove_epics_proc_files(); - remove_proc_entry("epics", proc_dir_entry); - remove_proc_entry("gps", proc_dir_entry); - remove_proc_entry("status", proc_dir_entry); - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); - -#ifndef NO_CPU_SHUTDOWN - // Unset the code callback - set_fe_code_idle(0, CPUID); -#endif - - printk("Setting stop_working_threads to 1\n"); - // Stop the code and wait - stop_working_threads = 1; - msleep(1000); - -#ifdef DOLPHIN_TEST - finish_dolphin(); -#endif - -#ifndef NO_CPU_SHUTDOWN - - // Unset the code callback - set_fe_code_idle(0, CPUID); - printkl("Will bring back CPU %d\n", CPUID); - msleep(1000); - // Unmask all masked epics channels - for (i = 0; i < ner; i++) { - *((char *)(((void *)pLocalEpics) + proc_epics[i].mask_idx)) = 0; - } - // Bring the CPU back up - cpu_up(CPUID); - //msleep(1000); - printkl("Brought the CPU back up\n"); -#endif - printk("Just before returning from cleanup_module for " SYSTEM_NAME_STRING_LOWER "\n"); - -} - -MODULE_DESCRIPTION("Control system"); -MODULE_AUTHOR("LIGO"); -MODULE_LICENSE("Dual BSD/GPL"); -- GitLab