nidas  v1.2-1520
Classes | Macros | Enumerations | Functions | Variables
pc104sg.c File Reference
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/poll.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/syscalls.h>
#include <linux/time.h>
#include <linux/unistd.h>
#include <linux/wait.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <asm/atomic.h>
#include <asm/io.h>
#include <linux/uaccess.h>
#include <nidas/linux/ver_macros.h>
#include <nidas/linux/irigclock.h>
#include <nidas/linux/isa_bus.h>
#include <nidas/linux/Revision.h>
#include <nidas/linux/klog.h>
#include "pc104sg.h"

Classes

struct  clockSnapShot
 One a second, or when clockAction == RESET_COUNTERS, the interrupt service routine grabs a snapshot of the following values. More...
 
struct  irig_device
 Device structure used in the file operations of the character device which provides IRIG samples. More...
 
struct  pc104sg_board
 Everything needed to access the board. More...
 

Macros

#define REPO_REVISION   "unknown"
 
#define IRQF_SHARED   SA_SHIRQ
 
#define INTERRUPT_RATE   100
 
#define MSEC_PER_INTERRUPT   (MSECS_PER_SEC / INTERRUPT_RATE)
 number of milliseconds per interrupt More...
 
#define TMSEC_PER_INTERRUPT   (TMSECS_PER_SEC / INTERRUPT_RATE)
 number of 1/10ths of milliseconds per interrupt More...
 
#define INTERRUPTS_PER_TASKLET   1
 We schedule the bottom-half tasklet after every INTERRUPTS_PER_TASKLET interrupts. More...
 
#define TMSEC_PER_SOFT_TIC
 Increment of the software clock on each schedule of the tasklet. More...
 
#define MAX_TASKLET_COUNTER   (10 * INTERRUPT_RATE * INTERRUPTS_PER_TASKLET)
 Allow for counting up to 10 seconds, so that we can do 0.1hz callbacks. More...
 
#define CALLBACK_POOL_SIZE   64 /* number of callbacks we can support */
 
#define PC104SG_SAMPLE_QUEUE_SIZE   16
 Length of the circular buffer of output samples. More...
 
#define MAX_TMSEC_SINCE_LAST_SYNC   (5 * TMSECS_PER_SEC)
 Values that are used to detect whether the bottom half tasklet has gotten out of sync with real-time. More...
 
#define SECS_PER_HOUR   (60 * 60)
 macros borrowed from glibc/time functions More...
 
#define SECS_PER_DAY   (SECS_PER_HOUR * 24)
 
#define my_isleap(year)   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
 
#define DIV(a, b)   ((a) / (b) - ((a) % (b) < 0))
 
#define LEAPS_THRU_END_OF(y)   (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
 

Enumerations

enum  clockAction { RESET_COUNTERS, NO_ACTION }
 What to do with the with the software clock and loop counter in the bottom-half tasklet. More...
 
enum  clockState { SYNCD_SET, UNSYNCD_SET }
 Enumeration of the state of the software clock. More...
 
enum  notifyClients { NO_NOTIFY, NOTIFY_CLIENTS }
 Whether to notify callback clients if clockAction is RESET_COUNTERS. More...
 

Functions

 MODULE_AUTHOR ("Gordon Maclean <maclean@ucar.edu>")
 
 MODULE_DESCRIPTION ("PC104-SG IRIG Card Driver")
 
 MODULE_LICENSE ("GPL")
 
 MODULE_VERSION (REPO_REVISION)
 
 module_param (Irq, int, 0)
 
 module_param (IoPort, int, 0)
 
 module_param (A2DClockFreq, int, 0)
 
 EXPORT_SYMBOL (TMsecClock)
 
 EXPORT_SYMBOL (ReadClock)
 
static const char * clockStateString (void)
 
struct irig_callback * register_irig_callback (irig_callback_func *callback, irig_callback_func *resync, enum irigClockRates rate, void *privateData, int *errp)
 Module function that allows other modules to register their callback function to be called at the given rate. More...
 
 EXPORT_SYMBOL (register_irig_callback)
 
int unregister_irig_callback (struct irig_callback *cb)
 Modules call this function to dequeue their callbacks. More...
 
 EXPORT_SYMBOL (unregister_irig_callback)
 
int flush_irig_callbacks (void)
 
 EXPORT_SYMBOL (flush_irig_callbacks)
 
static void handlePendingCallbacks (void)
 Handle pending adds and removes of callbacks from the active list for the appropriate rate. More...
 
static void free_callbacks (void)
 Cleanup function that un-registers all callbacks. More...
 
static void resetHeartBeatLatch (void)
 After receiving a heartbeat interrupt, one must reset the heartbeat latch in the handler. More...
 
static void enableHeartBeatInt (void)
 Enable heart beat interrupts. More...
 
static void resetMatchLatch (void)
 Disable heart beat interrupts. More...
 
static void disableAllInts (void)
 Enable external time tag interrupt. More...
 
static int readDPRAM (unsigned char addr, unsigned char *val)
 Read dual port RAM. More...
 
static void requestDPRAM (unsigned char addr)
 The requestDPRAM()/getRequestedDPRAM() pair allow us to break a dual-port read into two parts. More...
 
static void getRequestedDPRAM (unsigned char *val)
 
static int writeDPRAM (unsigned char addr, unsigned char value)
 Set a value in dual port RAM. More...
 
static int setHeartBeatOutput (int rate)
 
static int setPrimarySyncReference (unsigned char val)
 Set the primary time reference. More...
 
static int setTimeCodeInputSelect (unsigned char val)
 
int setRate2Output (int rate)
 
static int counterRejam (void)
 
static void getTimeRegisters (struct irigTime *ti, int offset)
 Read time from the registers. More...
 
int getTimeUsec ()
 Read sub-second time fields from the card, return microseconds. More...
 
static void timespecToirig (const thiskernel_timespec_t *ts, struct irigTime *ti)
 Break a timespec into the fields of a struct irigTime. More...
 
static void irigTotimespec (const struct irigTime *ti, thiskernel_timespec_t *ts)
 Convert a struct irigTime into a thiskernel_timespec_t. More...
 
static int64_t irigTousec (const struct irigTime *ti)
 Convert a struct irigTime to a int64_t time in microseconds. More...
 
static void irigTotimeval32 (const struct irigTime *ti, struct timeval32 *tv)
 Convert a struct irigTime into a struct timeval32. More...
 
static void get_irig_time_nolock (struct irigTime *ti)
 Get value of on-board clock. More...
 
static void get_irig_timespec_nolock (thiskernel_timespec_t *ts)
 
void irig_clock_gettime (thiskernel_timespec_t *tp)
 This function is available for use by external modules. More...
 
 EXPORT_SYMBOL (irig_clock_gettime)
 
int get_msec_clock_resolution ()
 
static int setYear (int val)
 set the year fields in Dual Port RAM. More...
 
static int setMajorTime (struct irigTime *ti)
 The major time consists of the day-of-year, hour, minute and second fields. More...
 
static int setSoftTickers (const thiskernel_timespec_t *ts, int round)
 Set the software clock and the tasklet loop counter based on a clock value in a timespec struct. More...
 
static void checkSoftTicker (int newClock, int currClock, int scale, int notify)
 Try to determine if our software clock and client callbacks are keeping up with real-time. More...
 
static void doCallbacklist (int rate)
 Invoke the callback functions for a given rate. More...
 
static void doResyncCallbacks (void)
 Invoke all resync callback functions. More...
 
static void pc104sg_bh_100Hz (unsigned long dev)
 Tasklet called 100 times/second in softare interrupt context. More...
 
static void oneHzFunction (void *ptr)
 
static void requestExtendedStatus (void)
 
static irqreturn_t pc104sg_isr (int irq, void *callbackPtr)
 
static int pc104sg_open (struct inode *inode, struct file *filp)
 
static int pc104sg_release (struct inode *inode, struct file *filp)
 
static unsigned int pc104sg_poll (struct file *filp, poll_table *wait)
 
static ssize_t pc104sg_read (struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
 
static long setIRIGclock (int64_t usec)
 Set the IRIG hardware clock fields in DPRAM. More...
 
static long pc104sg_ioctl (struct file *filp, unsigned int cmd, unsigned long arg)
 
static void pc104sg_cleanup (void)
 
static int __init pc104sg_init (void)
 
 module_init (pc104sg_init)
 
 module_exit (pc104sg_cleanup)
 

Variables

static char * driver_name = "pc104sg"
 
static unsigned int A2DClockFreq = 10000
 
static unsigned int Irq = 10
 
static unsigned int IoPort = 0x2a0
 
int TMsecClock [2] = { 0, 0 }
 A toggle buffer containing the current clock value in tenths of milliseconds since UTC midnight. More...
 
int ReadClock = 0
 Index into TMsecClock of the value to be read. More...
 
static struct pc104sg_board board
 
static int StaticYear
 The year field in the pc104sg time registers ranges from 0-99, so we keep track of the century. More...
 
static struct file_operations pc104sg_fops
 

Macro Definition Documentation

#define CALLBACK_POOL_SIZE   64 /* number of callbacks we can support */

Referenced by init_gpio_timer(), and pc104sg_init().

#define DIV (   a,
 
)    ((a) / (b) - ((a) % (b) < 0))
#define INTERRUPT_RATE   100

Referenced by pc104sg_init().

#define INTERRUPTS_PER_TASKLET   1

We schedule the bottom-half tasklet after every INTERRUPTS_PER_TASKLET interrupts.

#define IRQF_SHARED   SA_SHIRQ
#define LEAPS_THRU_END_OF (   y)    (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
#define MAX_TASKLET_COUNTER   (10 * INTERRUPT_RATE * INTERRUPTS_PER_TASKLET)

Allow for counting up to 10 seconds, so that we can do 0.1hz callbacks.

Referenced by pc104sg_bh_100Hz(), and setSoftTickers().

#define MAX_TMSEC_SINCE_LAST_SYNC   (5 * TMSECS_PER_SEC)

Values that are used to detect whether the bottom half tasklet has gotten out of sync with real-time.

Referenced by oneHzFunction().

#define MSEC_PER_INTERRUPT   (MSECS_PER_SEC / INTERRUPT_RATE)

number of milliseconds per interrupt

Referenced by get_msec_clock_resolution().

#define my_isleap (   year)    ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))

Referenced by timespecToirig().

#define PC104SG_SAMPLE_QUEUE_SIZE   16

Length of the circular buffer of output samples.

Referenced by oneHzFunction(), and pc104sg_open().

#define REPO_REVISION   "unknown"

Referenced by pc104sg_init().

#define SECS_PER_DAY   (SECS_PER_HOUR * 24)
#define SECS_PER_HOUR   (60 * 60)

macros borrowed from glibc/time functions

Referenced by timespecToirig().

#define TMSEC_PER_INTERRUPT   (TMSECS_PER_SEC / INTERRUPT_RATE)

number of 1/10ths of milliseconds per interrupt

#define TMSEC_PER_SOFT_TIC
Value:
#define INTERRUPTS_PER_TASKLET
We schedule the bottom-half tasklet after every INTERRUPTS_PER_TASKLET interrupts.
Definition: pc104sg.c:178
#define TMSEC_PER_INTERRUPT
number of 1/10ths of milliseconds per interrupt
Definition: pc104sg.c:172

Increment of the software clock on each schedule of the tasklet.

Referenced by checkSoftTicker(), pc104sg_bh_100Hz(), and setSoftTickers().

Enumeration Type Documentation

What to do with the with the software clock and loop counter in the bottom-half tasklet.

Enumerator
RESET_COUNTERS 
NO_ACTION 
enum clockState

Enumeration of the state of the software clock.

Enumerator
SYNCD_SET 
UNSYNCD_SET 

Whether to notify callback clients if clockAction is RESET_COUNTERS.

Enumerator
NO_NOTIFY 
NOTIFY_CLIENTS 

Function Documentation

static void checkSoftTicker ( int  newClock,
int  currClock,
int  scale,
int  notify 
)
static

Try to determine if our software clock and client callbacks are keeping up with real-time.

Other pc104 cards are receiving clock signals from this pc104sg card. If they want to do polling, or other periodic things, they register with this module for their callbacks to be called at a given rate by the 100Hz tasklet. We want to avoid missing a callback if at all possible.

It seems to happen, especially on vulcans, that a CPU card can miss one or more IRIG interrupts. When that happens, then one or more schedules of the bottom half tasklet are missed, which means that the software clock and the callbacks get behind.

This function compares the difference between the newClock value which was calculated from either the irig or unix clock, and currClock, which is the current software clock we provide to other modules. The difference is calculated as a number of 0.01 second delta-Ts.

This dT check is performed once a second.

If the clock difference is within limits of (IRIG_MAX_DT_DIFF / scale : IRIG_MIN_DT_DIFF / scale) then the pendingH100Hz counter is adjusted by the difference, so that the tasklet will be either scheduled more or less rapidly than 100 Hz for a period.

If the difference is negative, it is likely that a previous positive result was in error, or that spurious interrupts occurred. The latter doesn't seem to happen.

The hope is that in either case the software clock and callback loop counter get back in sync with the clock signals that were sent from the IRIG card to the other cards.

If the difference is outside those limits, then set clockAction is set to RESET_COUNTERS, so that the tasklet will reset the loop counter and the software clock the next time it is scheduled, and also call the resync callbacks of the clients, so that they could possibly resync their processing.

If the out-of-sync condition is caused by missed interrupts, or a temporary glitch in the irig clock, where it later recovers to be in sync with the output signals, this method should fix the problem.

Since we don't have any other details about the clock signals that were sent to other cards, we only have the value of the irig clock and unix clock to try to re-synchronize.

Another side issue arises when we are running without an IRIG source. This should only happen when bench testing. The pc104sg card still generates signals and interrupts, but they are based on an internal oscillator, which slowly drifts relative to the unix clock. In that case is is harder to determine what to do if a disagreement dTs is seen.

References board, pc104sg_board::clockAction, clockStateString(), pc104sg_board::deviceName, IRIG_MAX_DT_DIFF, IRIG_MIN_DT_DIFF, pc104sg_board::lock, pc104sg_board::ndtLast, pc104sg_board::ndtNSecs, pc104sg_board::pending100Hz, RESET_COUNTERS, pc104sg_status::slews, pc104sg_status::softwareClockResets, pc104sg_board::status, TMSEC_PER_SOFT_TIC, and TMSECS_PER_DAY.

Referenced by oneHzFunction().

static const char* clockStateString ( void  )
static
static int counterRejam ( void  )
static

References writeDPRAM().

Referenced by pc104sg_init().

static void disableAllInts ( void  )
static

Enable external time tag interrupt.

These are caused by a TTL input on a pin, and allows one to tag external events. This may be useful for synchronization tests of DSMs. Disable external time tag interrupt.

References pc104sg_board::addr, board, and pc104sg_board::IntMask.

Referenced by pc104sg_cleanup(), and pc104sg_init().

static void doCallbacklist ( int  rate)
inlinestatic

Invoke the callback functions for a given rate.

References board, pc104sg_board::CallbackLists, and rate.

Referenced by pc104sg_bh_100Hz().

static void doResyncCallbacks ( void  )
static

Invoke all resync callback functions.

References board, pc104sg_board::CallbackLists, IRIG_NUM_RATES, and rate.

Referenced by pc104sg_bh_100Hz().

static void enableHeartBeatInt ( void  )
static

Enable heart beat interrupts.

References board, pc104sg_board::IntMask, and resetHeartBeatLatch().

Referenced by pc104sg_init().

EXPORT_SYMBOL ( TMsecClock  )
EXPORT_SYMBOL ( ReadClock  )
EXPORT_SYMBOL ( register_irig_callback  )
EXPORT_SYMBOL ( unregister_irig_callback  )
EXPORT_SYMBOL ( flush_irig_callbacks  )
EXPORT_SYMBOL ( irig_clock_gettime  )
int flush_irig_callbacks ( void  )
static void free_callbacks ( void  )
static

Cleanup function that un-registers all callbacks.

References board, pc104sg_board::CallbackLists, pc104sg_board::CallbackPool, pc104sg_board::cblist_lock, handlePendingCallbacks(), and IRIG_NUM_RATES.

Referenced by pc104sg_cleanup().

static void get_irig_time_nolock ( struct irigTime *  ti)
static
static void get_irig_timespec_nolock ( thiskernel_timespec_t *  ts)
static
int get_msec_clock_resolution ( )

References MSEC_PER_INTERRUPT.

static void getRequestedDPRAM ( unsigned char *  val)
inlinestatic

References pc104sg_board::addr, and board.

Referenced by requestExtendedStatus().

static void getTimeRegisters ( struct irigTime *  ti,
int  offset 
)
static

Read time from the registers.

Set offset to 0 to read main clock. Set offset to 0x10 to read time of external pulse.

Data are stored in BCD form as 4 byte niblets, containing ones, tens or hundreds value for the respective time fields.

Called by: get_irig_time_nolock(&ti) from the ISR ioctls, from user space irig_clock_gettime(struct timespec* tp) other modules

Since reading the Usec1_Nsec100 value latches the other digits, all these calls hold a spin_lock before calling getTimeRegisters().

References pc104sg_board::addr, board, pc104sg_board::lastStatus, and StaticYear.

Referenced by get_irig_time_nolock().

int getTimeUsec ( )

Read sub-second time fields from the card, return microseconds.

May be useful for watching-the-clock when debugging.

References pc104sg_board::addr, board, and USECS_PER_MSEC.

static void handlePendingCallbacks ( void  )
static
void irig_clock_gettime ( thiskernel_timespec_t *  tp)

This function is available for use by external modules.

Note that it disables interrupts.

References board, get_irig_time_nolock(), irigTotimespec(), and pc104sg_board::lock.

static void irigTotimespec ( const struct irigTime *  ti,
thiskernel_timespec_t *  ts 
)
static

Convert a struct irigTime into a thiskernel_timespec_t.

References LEAPS_THRU_END_OF, NSECS_PER_MSEC, NSECS_PER_USEC, and SECS_PER_DAY.

Referenced by get_irig_time_nolock(), get_irig_timespec_nolock(), irig_clock_gettime(), and irigTotimeval32().

static void irigTotimeval32 ( const struct irigTime *  ti,
struct timeval32 tv 
)
static

Convert a struct irigTime into a struct timeval32.

Not 2038 compatible.

References irigTotimespec(), NSECS_PER_USEC, timeval32::tv_sec, and timeval32::tv_usec.

Referenced by pc104sg_ioctl().

static int64_t irigTousec ( const struct irigTime *  ti)
static

Convert a struct irigTime to a int64_t time in microseconds.

References LEAPS_THRU_END_OF, SECS_PER_DAY, USECS_PER_MSEC, and USECS_PER_SEC.

Referenced by pc104sg_ioctl().

MODULE_AUTHOR ( "Gordon Maclean <maclean@ucar.edu>"  )
MODULE_DESCRIPTION ( "PC104-SG IRIG Card Driver"  )
module_exit ( pc104sg_cleanup  )
module_init ( pc104sg_init  )
MODULE_LICENSE ( "GPL"  )
module_param ( Irq  ,
int  ,
 
)
module_param ( IoPort  ,
int  ,
 
)
module_param ( A2DClockFreq  ,
int  ,
 
)
MODULE_VERSION ( REPO_REVISION  )
static void oneHzFunction ( void *  ptr)
static
static void pc104sg_bh_100Hz ( unsigned long  dev)
static
static void pc104sg_cleanup ( void  )
static
static int __init pc104sg_init ( void  )
static
static long pc104sg_ioctl ( struct file *  filp,
unsigned int  cmd,
unsigned long  arg 
)
static
static irqreturn_t pc104sg_isr ( int  irq,
void *  callbackPtr 
)
static
static int pc104sg_open ( struct inode *  inode,
struct file *  filp 
)
static
static unsigned int pc104sg_poll ( struct file *  filp,
poll_table *  wait 
)
static
static ssize_t pc104sg_read ( struct file *  filp,
char __user *  buf,
size_t  count,
loff_t *  f_pos 
)
static
static int pc104sg_release ( struct inode *  inode,
struct file *  filp 
)
static
static int readDPRAM ( unsigned char  addr,
unsigned char *  val 
)
static

Read dual port RAM.

Parameters
addrdual-port RAM address to read

Called by (all by module init) setHeartBeatOutput(int rate) setPrimarySyncReference(unsigned char val) setRate2Output(int rate) init

References pc104sg_board::addr, board, and pc104sg_board::lock.

Referenced by setHeartBeatOutput(), setPrimarySyncReference(), and setRate2Output().

struct irig_callback* register_irig_callback ( irig_callback_func *  callback,
irig_callback_func *  resync,
enum irigClockRates  rate,
void *  privateData,
int *  errp 
)

Module function that allows other modules to register their callback function to be called at the given rate.

register_irig_callback can be called at anytime. Note that register_irig_callback and unregister_irig_callback do not alter the active callback lists but instead add requests to a group of pending requests. The loop function, pc104sg_bh_100Hz, does not do any locking on the active list. Once on each pass through the loop it acts on the pending requests.

References board, pc104sg_board::CallbackPool, pc104sg_board::cblist_lock, IRIG_NUM_RATES, pc104sg_board::nPendingCallbackChanges, pc104sg_board::pendingAdds, and rate.

Referenced by arinc_init(), arinc_ioctl(), mesa_ioctl(), pc104sg_init(), resetBoard(), and waitFor1PPS().

static void requestDPRAM ( unsigned char  addr)
inlinestatic

The requestDPRAM()/getRequestedDPRAM() pair allow us to break a dual-port read into two parts.

This is used by the interrupt service routine. Each entry into the ISR reads the value ready from the previous request, then issues another request. In this way, the necessary delay between requesting dual-port RAM and actually getting the value happens between interrupts, rather than by a busy wait.

If non ISR code wants to access dual ported RAM, it should do the following, which prevents the ISR from accessing it, without disabling interrupts while accessing the DP ram: spin_lock_irqsave(&board.lock, flags); board.DP_RamExtStatusEnabled = 0; board.DP_RamExtStatusRequested = 0; spin_unlock_irqrestore(&board.lock, flags); Then access the RAM, for example: setYear(n); ... Then re-enable access by the ISR spin_lock_irqsave(&board.lock, flags); board.DP_RamExtStatusEnabled = 1; spin_unlock_irqrestore(&board.lock, flags);

References pc104sg_board::addr, and board.

Referenced by pc104sg_init(), and requestExtendedStatus().

static void requestExtendedStatus ( void  )
inlinestatic
static void resetHeartBeatLatch ( void  )
inlinestatic

After receiving a heartbeat interrupt, one must reset the heartbeat latch in the handler.

Otherwise either of two bad things will happen, depending on how the system is configured to handle interrupt levels:

  1. the interrupt handler will be called again immediately after it returns, resulting in a system lockup.
  2. you won't get any further interrupts.

References pc104sg_board::addr, board, and pc104sg_board::IntMask.

Referenced by enableHeartBeatInt(), and pc104sg_isr().

static void resetMatchLatch ( void  )
inlinestatic

Disable heart beat interrupts.

After receiving a match interrupt, one must reset the match flag in order to receive further interrupts.

References pc104sg_board::addr, board, and pc104sg_board::IntMask.

static int setHeartBeatOutput ( int  rate)
static

References rate, readDPRAM(), and writeDPRAM().

Referenced by pc104sg_init().

static long setIRIGclock ( int64_t  usec)
static
static int setMajorTime ( struct irigTime *  ti)
static

The major time consists of the day-of-year, hour, minute and second fields.

Ideally they are set via the time-code input, but this function can be used if there is no time-code.

The sub-second values are determined from the PPS input, and I see no way to change them if there is no PPS or time-code.

References board, pc104sg_board::clockState, pc104sg_board::lastStatus, setYear(), and writeDPRAM().

Referenced by pc104sg_init(), and setIRIGclock().

static int setPrimarySyncReference ( unsigned char  val)
static

Set the primary time reference.

Parameters
val0=PPS is primary time reference, 1=time code is primary

References readDPRAM(), and writeDPRAM().

Referenced by pc104sg_init().

int setRate2Output ( int  rate)

References rate, readDPRAM(), and writeDPRAM().

Referenced by pc104sg_init().

static int setSoftTickers ( const thiskernel_timespec_t *  ts,
int  round 
)
static

Set the software clock and the tasklet loop counter based on a clock value in a timespec struct.

This function is called by the bottom half tasklet if clockAction==RESET_COUNTERS.

Note: we are seeing sub-millisecond agreement between the IRIG register clocks and the system clock (conditioned by NTP), with a GPS-conditioned timeserver providing the IRIG and NTP references.

This function sets TMsecClockTicker from the timespec.

References board, if(), MAX_TASKLET_COUNTER, pc104sg_board::ndtLast, pc104sg_board::ndtNSecs, NSECS_PER_TMSEC, pc104sg_board::pending100Hz, SECS_PER_DAY, pc104sg_status::softwareClockResets, pc104sg_board::status, TMSEC_PER_SOFT_TIC, pc104sg_board::TMsecClockTicker, TMSECS_PER_DAY, and TMSECS_PER_SEC.

Referenced by pc104sg_bh_100Hz().

static int setTimeCodeInputSelect ( unsigned char  val)
static

References writeDPRAM().

Referenced by pc104sg_init().

static int setYear ( int  val)
static

set the year fields in Dual Port RAM.

References StaticYear, and writeDPRAM().

Referenced by setIRIGclock(), and setMajorTime().

static void timespecToirig ( const thiskernel_timespec_t *  ts,
struct irigTime *  ti 
)
static

Break a timespec into the fields of a struct irigTime.

This uses some code from glibc/time routines.

References LEAPS_THRU_END_OF, my_isleap, NSECS_PER_MSEC, NSECS_PER_USEC, SECS_PER_DAY, and SECS_PER_HOUR.

Referenced by pc104sg_init(), and setIRIGclock().

int unregister_irig_callback ( struct irig_callback *  cb)

Modules call this function to dequeue their callbacks.

A callback function can cancel itself, or any other callback function.

Returns
0: OK, but callback might be called once more. Do flush_irig_callback to wait until it is definitely finished. <0: errno

References board, pc104sg_board::cblist_lock, IRIG_NUM_RATES, pc104sg_board::nPendingCallbackChanges, pc104sg_board::nPendingRemoves, and pc104sg_board::pendingRemoves.

Referenced by arinc_cleanup(), arinc_release(), close_ports(), mesa_ioctl(), ncar_a2d_cleanup(), pc104sg_cleanup(), resetBoard(), stopBoard(), and waitFor1PPS().

static int writeDPRAM ( unsigned char  addr,
unsigned char  value 
)
static

Variable Documentation

unsigned int A2DClockFreq = 10000
static

Referenced by pc104sg_init().

struct pc104sg_board board
static
char* driver_name = "pc104sg"
static

Referenced by pc104sg_init().

unsigned int IoPort = 0x2a0
static

Referenced by pc104sg_init().

unsigned int Irq = 10
static

Referenced by pc104sg_init().

struct file_operations pc104sg_fops
static
Initial value:
= {
.owner = THIS_MODULE,
.read = pc104sg_read,
.poll = pc104sg_poll,
.open = pc104sg_open,
.unlocked_ioctl = pc104sg_ioctl,
.release = pc104sg_release,
.llseek = no_llseek,
}
static int pc104sg_release(struct inode *inode, struct file *filp)
Definition: pc104sg.c:2329
static long pc104sg_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
Definition: pc104sg.c:2415
static int pc104sg_open(struct inode *inode, struct file *filp)
Definition: pc104sg.c:2280
static ssize_t pc104sg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
Definition: pc104sg.c:2365
static unsigned int pc104sg_poll(struct file *filp, poll_table *wait)
Definition: pc104sg.c:2348
int ReadClock = 0

Index into TMsecClock of the value to be read.

Referenced by pc104sg_bh_100Hz(), and pc104sg_init().

int StaticYear
static

The year field in the pc104sg time registers ranges from 0-99, so we keep track of the century.

Referenced by getTimeRegisters(), and setYear().

int TMsecClock[2] = { 0, 0 }

A toggle buffer containing the current clock value in tenths of milliseconds since UTC midnight.

Referenced by pc104sg_bh_100Hz(), and pc104sg_init().