mbgtools-lx  4.2.8
mbgclock_main.c
Go to the documentation of this file.
1 
2 /**************************************************************************
3  *
4  * $Id: mbgclock_main.c 1.30 2018/11/22 13:45:24 martin REL_M $
5  *
6  * Description:
7  * Main file for the mbgclock driver for Linux which allows access to
8  * Meinberg radio clock devices from user space.
9  *
10  * The binary is a loadable module called mbgclock which implements
11  * /dev/mbgclock* devices.
12  *
13  * -----------------------------------------------------------------------
14  * $Log: mbgclock_main.c $
15  * Revision 1.30 2018/11/22 13:45:24 martin
16  * Refactored debug logging stuff.
17  * Moved default DEBUG_* definitions elsewhere.
18  * 'PnP' is common, so don't explicitly mention it in startup msg.
19  * Revision 1.29 2018/09/21 14:56:50 martin
20  * Account for changed library symbols.
21  * Updated some debug stuff.
22  * Revision 1.28 2018/08/07 13:15:55 martin
23  * Cleaned up version information handling.
24  * Revision 1.27 2018/07/04 13:21:38 martin
25  * Removed some obsolete conditional code which
26  * caused duplicate names with kernel 4.17.
27  * Support TCR180USB.
28  * Support new parameter 'force_mm16_access'.
29  * Conditionally support DEBUG_MSG_SLEEP.
30  * Moved some debug message macros to mbgddmsg.h.
31  * Moved get_ioctl_name() as mbgioctl_get_name() to mbgioctl.c.
32  * Unified kernel driver messages.
33  * Use macros to check function return codes.
34  * Cleanup and improvements for cyclic USB.
35  * Use sys_rc as name for variables that hold system return codes.
36  * Use predefined string formats in log message.
37  * Account for some renamed symbols.
38  * Moved a success message to the library's probe routine.
39  * Revision 1.26 2017/07/05 19:18:04 martin
40  * Renamed this file from mbgdrvr.c to mbgclock_main.c.
41  * Account for renamed inline functions.
42  * Added definitions to support DCF600USB.
43  * Fixes to handle locked/unlocked ioctl calls depending on kernel settings.
44  * Account for modified _pcps_kfree() macro.
45  * Support privilege levels for IOCTL calls.
46  * Added device IDs for TCR600USB, MSF600USB, and WVB600USB.
47  * Enhanced IRQ timing debug code.
48  * Read jiffies at IRQ protected by a lock.
49  * Check all PCI base address registers and don't stop if one register is 0.
50  * Print IOCTL code names in debug messages.
51  * Print return code if request_irq() fails.
52  * Moved kernel version compatibility checks to mbg_lx.h.
53  * Use common code from lx-shared.h.
54  * Support new module parameter force_io_access.
55  * Obsoleted IRQF_DISABLED and SA_INTERRUPT which
56  * have been removed from kernel source 4.1.x.
57  * Let the IOCTL handler return MBG_ERROR_CODES.
58  * Use safer function scnprintf() to generate time string.
59  * New way to maintain version information.
60  * Removed obsolete definition of K26, and cleaned up.
61  * Revision 1.25 2010/05/03 15:00:42 martin
62  * Fixed exported functions mbgclock_default_get_ucap_entries()
63  * and mbgclock_default_get_ucap_event().
64  * Added some conditional debug code for exported kernel functions.
65  * Revision 1.24 2010/04/26 14:44:04 martin
66  * Generate a compiler warning if no cycles support to compute latencies.
67  * Revision 1.23 2010/03/05 14:41:31 martin
68  * If IRQ needs to be re-enabled the disable/unregister it first in order not to mess up
69  * the kernel. Moved mbgdrvr_disable_cyclic() up, in front of mbgdrvr_enable_cyclic().
70  * Revision 1.22 2010/02/23 16:02:25 martin
71  * Changed the name of some exported functions from mbgclock_get_default_...()
72  * to mbgclock_default_get_...() for a consistent nameing convention.
73  * Added and exported some new functions which provide access to the ucap FIFO.
74  * Revision 1.21 2009/12/21 15:52:46 martin
75  * Added functions which can be called from other kernel modules
76  * to read memory mapped timestamps.
77  * Moved some driver-internal definitions from the .h file here.
78  * Changed version code to 3.4.1.
79  * Revision 1.20 2009/09/29 14:55:46 martin
80  * Use the ioctl_switch() inline code instead of the macro.
81  * Revision 1.19 2009/09/21 13:53:20 martin
82  * Fixed CONFIG_COMPAT stuff for kernels 2.6.9.
83  * Revision 1.18 2009/08/12 15:25:29 martin
84  * Fixed a bug due to the device_create() parameter count in kernel 2.6.26.
85  * Revision 1.17 2009/07/22 12:36:30 martin
86  * Check rc of down_interruptible() with sem_usb_cyclic in mbgclock_read().
87  * Revision 1.16 2009/06/30 13:28:49 martin
88  * Set the UTC indicator in the time string passed to ntpd based on the
89  * UTC offset hours being 0, not based on the UTC status flag.
90  * Fixed printing of version number in kernel messages.
91  * Revision 1.15 2009/03/20 11:58:13 martin
92  * Enhanced error handling of USB devices.
93  * Revision 1.14 2008/12/22 13:26:50 martin
94  * Migrated former file mbginit.c to mbgdrvr.c and merged code
95  * from mbgclk.c and mbgntp.c which are now obsolete.
96  * Use only one common device node per HW device.
97  * Support USB devices and gracefully handle disconnect/reconnect
98  * while the device is opened.
99  * Return -EBUSY if ioctl() is called and unsafe PEX IRQ is enabled.
100  * Restrict usage to 2.6.x kernels for now.
101  * Create own device class with dynamical unique major number
102  * under kernel 2.6 instead of misc devices.
103  * Use 2.6 kernel API calls which trigger udev support.
104  * Enable device IRQ only when poll() or read() is called the first time.
105  * IRQs are disabled when open count decreases to 0 in release().
106  * A cyclic USB read thread emulates IRQs for USB devices.
107  * Init mutexes/spinlocks in pcps_start_device().
108  * Consistenly use pcps_drvr_name instead of mbgclock_name for messages.
109  * mbgclock_name should be used for device nodes/names etc.
110  * Conditionally use kthread API for USB cyclic polling threads.
111  * Protection against unsafe access is now handled in _ioctl_switch(),
112  * depending on whether HW access is required, or not.
113  * Initial debug level set from DEBUG symbol value.
114  * Account for signed irq_num.
115  * Changed debug messages to common fmt printing file pointers first.
116  * Check IRQ timeout also at blocking reads rather than only while polling.
117  * Use MBG_MEM_ADDR type for memory rather than split high/low types.
118  * Added conditional code for hardware timing debugging via LPT port.
119  * Use malloc'ed kernel memory for private PNP device data.
120  * Revision 1.13 2007/07/24 09:40:58 martin
121  * Added support for PEX511, TCR511PEX, and GPS170PEX.
122  * Account for new unified resource handling.
123  * Revision 1.12 2007/03/02 10:39:01 martin
124  * There are kernel sources around v2.6.9 which provide different
125  * versions of the "module_param_array" macro which is specified
126  * in the kernel header moduleparams.h.
127  * Newer versions of that file also define a macro "__MODULE_PARM_TYPE",
128  * so guess which version of "module_param_array" is to be used based
129  * on the presence of the "__MODULE_PARAM_TYPE" macro.
130  * Added type casts to avoid compiler warnings.
131  * Revision 1.11 2006/08/28 11:15:22 martin
132  * Added an optional module parameter pretend_sync which makes the driver
133  * pretend to NTP the device is always synchronized.
134  * Revision 1.10 2006/07/03 13:17:16 martin
135  * Added support for GPS170PCI, PCI511, and TCR511PCI.
136  * Updated copyright string and turned it into a macro.
137  * Export symbols which may be required for inter-module calls.
138  * Use module_param from 2.6.x kernels, if applicable.
139  * Revision 1.9 2005/06/02 15:48:34 martin
140  * Call pci_enable_device() which also accounts for IRQ routing in
141  * recent 2.6 kernels.
142  * Don't report the the return value of pci_register_driver() as number
143  * of devices found since this has been changed in the kernel code.
144  * Revision 1.8 2004/11/09 09:32:03 martin
145  * Modifications to support kernel 2.6.
146  * Use static table of supported devices to support "modinfo".
147  * Added support for TCR167PCI.
148  * New module parameter dev allows to select device.
149  * Modified load messages.
150  * Revision 1.7 2003/07/30 07:32:41 martin
151  * Print debug level before radio clock listing.
152  * Revision 1.6 2003/07/08 15:24:58 martin
153  * Use plug'n'play manager functions for PCI cards under
154  * kernel 2.4.0 or newer.
155  * Removed obsolete __initfunc() stuff.
156  * Revision 1.5 2003/04/25 10:22:10 martin
157  * Updated copyright string.
158  * Revision 1.4 2002/11/21 10:18:02 martin
159  * Modified startup syslog messages.
160  * Revision 1.3 2002/05/07 07:56:14 martin
161  * Added module license to prevent newer kernels from
162  * printing "module will taint the kernel" warning.
163  * Revision 1.2 2001/07/27 13:25:12 MARTIN
164  * Control usage of __initfunc().
165  * Revision 1.1 2001/03/05 17:19:28 MARTIN
166  * Initial revision
167  *
168  **************************************************************************/
169 
170 #define EXPORT_SYMTAB
171 
172 #define _MBGCLOCK
173  #include <mbgclock.h>
174 #undef _MBGCLOCK
175 
176 #include <mbgversion.h>
177 #include <mbgioctl.h>
178 #include <pcpsirq.h>
179 #include <mbgddmsg.h>
180 
181 #include <stddef.h>
182 
183 #include <linux/termios.h>
184 #include <linux/pci.h>
185 
186 #if _USE_LINUX_DEVFS
187  #include <linux/devfs_fs_kernel.h>
188 #endif
189 
190 #define MBG_COPYRIGHT "(c) Meinberg 2001-" MBG_CURRENT_COPYRIGHT_YEAR_STR
191 
192 #define MBG_DRVR_NAME "mbgclock"
193 
194 #if !defined( MBGCLOCK_MAX_DEVS )
195  #define MBGCLOCK_MAX_DEVS 20
196 #endif
197 
198 
199 #if !defined( DEBUG_IRQ_LATENCY )
200  #if ( defined( DEBUG ) )
201  #define DEBUG_IRQ_LATENCY 0
202  #else
203  #define DEBUG_IRQ_LATENCY 0
204  #endif
205 #endif
206 
207 #if !defined( DEBUG_IRQ_TIMING )
208  #if ( defined( DEBUG ) )
209  #define DEBUG_IRQ_TIMING 0
210  #else
211  #define DEBUG_IRQ_TIMING 0
212  #endif
213 #endif
214 
215 #if !defined( DEBUG_SYS_IRQS )
216  #if ( defined( DEBUG ) )
217  #define DEBUG_SYS_IRQS 0
218  #else
219  #define DEBUG_SYS_IRQS 0
220  #endif
221 #endif
222 
223 
224 #if !defined( OMIT_PRIV_CHECKING )
225  #define OMIT_PRIV_CHECKING 0
226 #endif
227 
228 
229 
232 
234 // NOTE: int debug is defined in a library module
235 
236 // The variable below is set to point to the first device supporting
237 // fast HR timestamps (via memotry mapped access).
240 
241 #if USE_DEBUG_PORT
242  static MBG_DBG_DATA mbg_dbg_data;
243  static MBG_DBG_PORT mbg_dbg_port = 0x378 + 0; //##++
244  static MBG_IOPORT_ADDR_MAPPED mbg_dbg_port_mapped; //##++
245 #endif // USE_DEBUG_PORT
246 
247 #include <macioctl.h>
248 
249 
250 // the following variables may be overwritten at load time
251 static int io[PCPS_MAX_ISA_CARDS];
253 
254 
255 static int major = 0;
256 static int minor = 0;
259 
260 
261 #ifdef MODULE
262 
263 MODULE_AUTHOR( "Martin Burnicki <martin.burnicki@meinberg.de>" );
264 MODULE_DESCRIPTION( "Driver for Meinberg plug-in and USB radio clocks." );
265 #ifdef MODULE_VERSION
266  MODULE_VERSION( MBG_FULL_VERSION_STR );
267 #endif
268 #ifdef MODULE_LICENSE
269  MODULE_LICENSE( "GPL" );
270 #endif
271 MODULE_SUPPORTED_DEVICE( "mbgclock" );
272 
273 #if defined( module_param_array )
274  static int n_io;
275  #if defined( __MODULE_PARM_TYPE )
276  module_param_array( io, int, &n_io, 0444 );
277  #else
278  module_param_array( io, int, n_io, 0444 );
279  #endif
280 #elif defined( MODULE_PARM )
281  MODULE_PARM( io, "1-" __MODULE_STRING( PCPS_MAX_ISA_CARDS ) "i" );
282 #endif
283 MODULE_PARM_DESC( io, "port address(es) of ISA card(s)" );
284 
285 #if defined( module_param_array )
286  static int n_irq;
287  #if defined( __MODULE_PARM_TYPE )
288  module_param_array( irq, int, &n_irq, 0444 );
289  #else
290  module_param_array( irq, int, n_irq, 0444 );
291  #endif
292 #elif defined( MODULE_PARM )
293  MODULE_PARM( irq, "1-" __MODULE_STRING( PCPS_MAX_ISA_CARDS ) "i" );
294 #endif
295 MODULE_PARM_DESC( irq, "IRQ line(s) used by ISA card(s)" );
296 
297 #if defined( module_param )
298  module_param( major, int, S_IRUGO );
299  module_param( minor, int, S_IRUGO );
300  module_param( max_devs, int, S_IRUGO );
301 #elif defined( MODULE_PARM )
302  MODULE_PARM( major, "i" );
303  MODULE_PARM( minor, "i" );
304  MODULE_PARM( max_devs, "i" );
305 #endif
306 MODULE_PARM_DESC( major, "major device number, dynamic by default" );
307 MODULE_PARM_DESC( minor, "first minor device number, dynamic by default" );
308 MODULE_PARM_DESC( max_devs, "max number of supported devices" );
309 
310 
311 #if defined( module_param )
312  module_param( pretend_sync, int, 0444 );
313 #elif defined( MODULE_PARM )
314  MODULE_PARM( pretend_sync, "i" );
315 #endif
316 MODULE_PARM_DESC( pretend_sync, "pretend to NTP to be always sync'ed" );
317 
318 #if _PCPS_USE_MM_IO
319  #if defined( module_param )
320  module_param( force_io_access, int, 0444 );
321  module_param( force_mm16_access, int, 0444 );
322  #elif defined( MODULE_PARM )
323  MODULE_PARM( force_io_access, "i" );
324  MODULE_PARM( force_mm16_access, "i" );
325  #endif
326  MODULE_PARM_DESC( force_io_access, "force I/O port access even if a device supports memory mapped access." );
327  MODULE_PARM_DESC( force_mm16_access, "force 16 bit memory mapped access for devices which support this." );
328 #endif
329 
330 #if DEBUG_MSG_SLEEP
331  #if defined( module_param )
332  module_param( debug_msg_sleep, int, 0444 );
333  #elif defined( MODULE_PARM )
334  MODULE_PARM( debug_msg_sleep, "i" );
335  #endif
336  MODULE_PARM_DESC( debug_msg_sleep, "debug only, msleep by this amount of ms after each message." );
337 #endif
338 
339 #ifdef DEBUG
340  #if defined( module_param )
341  module_param( debug, int, 0444 );
342  #elif defined( MODULE_PARM )
343  MODULE_PARM( debug, "i" );
344  #endif
345  MODULE_PARM_DESC( debug, "debug level, only if compiled with DEBUG" );
346 #endif
347 
348 #ifdef EXPORT_SYMBOL
349 #if 0 //##++
352 EXPORT_SYMBOL( access_in_progress );
353 #endif
354 #endif
355 
356 #ifndef module_init
357  #define mbgclock_init_module init_module
358  #define mbgclock_cleanup_module cleanup_module
359 #endif
360 
361 #endif
362 
363 #define DRV_NAME MBG_DRVR_NAME
364 
365 #define MBG_SIZE_TLG 33
366 
367 #define _min( _a, _b ) ( ( (_b) < (_a) ) ? (_b) : (_a) )
368 
369 #define CYCLIC_TIMEOUT ( (ulong) 2 * HZ ) // 2 seconds
370 
371 #if NEW_FASYNC2
372  #define _kill_fasync( _fa, _sig, _band ) \
373  kill_fasync( _fa, _sig, _band )
374 #elif NEW_FASYNC
375  #define _kill_fasync( _fa, _sig, _band ) \
376  kill_fasync( *(_fa), _sig, _band )
377 #else
378  #define _kill_fasync( _fa, _sig, _band ) \
379  kill_fasync( *(_fa), _sig )
380 #endif
381 
382 
383 #ifndef __exit
384  #define __exit
385 #endif
386 
388 static struct semaphore sem_fops; // still needs to be initialized !!
389 
390 // The definitions in this file are shared with other Linux drivers:
391 #include <lx-shared.h>
392 
393 
394 #if !defined( DEBUG_HW_LPT )
395  #define DEBUG_HW_LPT 0
396 #endif
397 
398 #if DEBUG_HW_LPT
399  static spinlock_t hwdbg_lock = SPIN_LOCK_UNLOCKED;
400 
401  #define MBG_BIT_OPEN 0x03
402  #define MBG_BIT_RELEASE 0x01
403  #define MBG_BIT_IRQ 0x04
404  #define MBG_BIT_TEST 0x08
405 
406 
407  #define _mbg_dbg_hw_lpt_vars \
408  unsigned long hwdbg_flags;
409 
410  #define _mbg_dbg_hw_lpt_set_bit( _b ) \
411  { \
412  spin_lock_irqsave( &hwdbg_lock, hwdbg_flags ); \
413  _mbg_dbg_set_bit( pddev, _b ); \
414  spin_unlock_irqrestore( &hwdbg_lock, hwdbg_flags ); \
415  }
416 
417  #define _mbg_dbg_hw_lpt_clr_bit( _b ) \
418  { \
419  spin_lock_irqsave( &hwdbg_lock, hwdbg_flags ); \
420  _mbg_dbg_clr_bit( pddev, _b ); \
421  spin_unlock_irqrestore( &hwdbg_lock, hwdbg_flags ); \
422  }
423 
424 #else
425 
426  #define _mbg_dbg_hw_lpt_vars
427  #define _mbg_dbg_hw_lpt_set_bit( _b );
428  #define _mbg_dbg_hw_lpt_clr_bit( _b );
429 
430 #endif
431 
432 
433 
434 #if _PCPS_HAVE_LINUX_CLASS
435  static char mbgclock_class_name[] = "mbgclock";
436  static char mbg_clk_dev_node_fmt[] = "mbgclock%d";
437 
438  #if _PCPS_HAVE_LINUX_CLASS_CREATE
439  static struct class *mbgclock_class;
440  #elif _PCPS_HAVE_LINUX_CLASS_SIMPLE
441  static struct class_simple *mbgclock_class;
442  #endif
443 #endif
444 
445 
446 #if DEBUG_IRQ_LATENCY
447  static unsigned long long tsc_irq_1;
448  static unsigned long long tsc_irq_2;
449  static unsigned long long tsc_usb_1;
450  static unsigned long long tsc_usb_2;
451 #endif
452 
453 
454 
455 #if DEBUG_SYS_IRQS
456 
457 static /*HDR*/
458 void list_system_irqs( void )
459 {
460  int i;
461  struct irq_desc *desc;
462 
463  // This is some sample code from a forum which should
464  // list some information on all IRQs supported by the kernel.
465  // However, the members of struct irq_desc may vary with
466  // the kernel version, so this code may need to be adapted
467  // depending on the kernel version.
468  for_each_irq_desc( i, desc )
469  {
470  if ( !desc )
471  continue;
472 
473  mbg_kdd_msg( MBG_LOG_INFO, "%d: status=%08x, chip=%08x, handle_irq=%08x",
474  i, (u32) desc->status, (u32) desc->chip, (u32) desc->handle_irq );
475  }
476 
477 } // list_system_irqs
478 
479 #endif
480 
481 
482 #if _PCPS_USE_LINUX_KTHREAD
483 
484  #define _usb_read_thread_should_stop() \
485  kthread_should_stop()
486 
487  #define _usb_read_thread_exit( _pddev, _v ) \
488  return (_v);
489 
490  #define _usb_read_thread_started( _pddev ) \
491  ( (_pddev)->usb_read_thread != NULL )
492 
493  #define _usb_read_thread_start( _fnc, _pddev ) \
494  (_pddev)->usb_read_thread = kthread_run( (_fnc), (_pddev), \
495  "%s%d", driver_name, MINOR( (_pddev)->lx_dev ) )
496 
497  #define _usb_read_thread_failed_to_start( _pddev ) \
498  ( IS_ERR( (_pddev)->usb_read_thread ) )
499 
500  #define _usb_read_thread_set_unused( _pddev ) \
501  (_pddev)->usb_read_thread = NULL;
502 
503  #define _usb_read_thread_stop( _pddev ) \
504  kthread_stop( (_pddev)->usb_read_thread )
505 
506  // This is not required if the kthread API is being used.
507  #define _usb_read_thread_daemonize( _pddev ) \
508  _nop_macro_fnc()
509 
510 #else
511 
512  #define _usb_read_thread_should_stop() \
513  signal_pending( current )
514 
515  #define _usb_read_thread_exit( _pddev, _v ) \
516  complete_and_exit( &pddev->usb_read_thread.exit, (_v) )
517 
518  #define _usb_read_thread_started( _pddev ) \
519  ( (_pddev)->usb_read_thread.pid != 0 )
520 
521  #define _usb_read_thread_start( _fnc, _pddev ) \
522  init_completion( &(_pddev)->usb_read_thread.exit ); \
523  (_pddev)->usb_read_thread.pid = kernel_thread( (_fnc), (_pddev), CLONE_KERNEL );
524 
525  #define _usb_read_thread_failed_to_start( _pddev ) \
526  ( (_pddev)->usb_read_thread.pid == 0 )
527 
528  #define _usb_read_thread_set_unused( _pddev ) \
529  (_pddev)->usb_read_thread.pid = 0;
530 
531  #define _usb_read_thread_stop( _pddev ) \
532  kill_proc( (_pddev)->usb_read_thread.pid, SIGKILL, 1 ); \
533  wait_for_completion( &(_pddev)->usb_read_thread.exit )
534 
535  #define _usb_read_thread_daemonize( _pddev ) \
536  snprintf( (_pddev)->usb_read_thread.name, sizeof( (_pddev)->usb_read_thread.name ), \
537  "%s%d", driver_name, MINOR( (_pddev)->lx_dev ) ); \
538  daemonize( (_pddev)->usb_read_thread.name ); \
539  allow_signal( SIGKILL )
540 
541 #endif
542 
543 
544 static void mbgdrvr_delete_device( PCPS_DDEV *pddev );
545 
546 
547 static /*HDR*/
548 void ddev_list_free( void )
549 {
550  if ( ddev_list )
551  {
552  _pcps_kfree( ddev_list, ddev_list_alloc_size );
553  ddev_list = NULL;
554 
555  _mbgddmsg_0( DEBUG_DRVR, MBG_LOG_INFO, "Freed device list" );
556  }
557 
558 } // ddev_list_free
559 
560 
561 
562 static /*HDR*/
563 int ddev_list_alloc( void )
564 {
565  ddev_list_alloc_size = max_devs * sizeof( *ddev_list );
566 
567  ddev_list = _pcps_kmalloc( ddev_list_alloc_size );
568 
569  if ( ddev_list == NULL )
570  {
571  mbg_kdd_msg( MBG_LOG_ERR, "Failed to allocate memory for device list" );
572  return -ENOMEM;
573  }
574 
575  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Allocated device list, %u bytes for up to %u entries",
577 
578  memset( ddev_list, 0, ddev_list_alloc_size );
579 
580  return 0;
581 
582 } // ddev_list_alloc
583 
584 
585 
586 static /*HDR*/
588 {
589  int i;
590 
591  for ( i = 0; i < max_devs; i++ )
592  {
593  PCPS_DDEV **ppddev = &ddev_list[i];
594 
595  if ( *ppddev )
596  if ( minor == MINOR( (*ppddev)->lx_dev ) )
597  return ppddev;
598  }
599 
600  mbg_kdd_msg( MBG_LOG_WARN, "Unable to locate minor %i in device list",
601  minor );
602 
603  return NULL;
604 
605 } // ddev_list_locate_minor
606 
607 
608 
609 static /*HDR*/
611 {
612  int i;
613 
614  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Searching device list for ID %04X, S/N %s",
615  dev_id, sernum );
616 
617  for ( i = 0; i < max_devs; i++ )
618  {
619  PCPS_DDEV **ppddev = &ddev_list[i];
620 
621  if ( *ppddev )
622  {
623  _mbgddmsg_3( DEBUG_DRVR, MBG_LOG_INFO, " Entry %i: ID %04X, S/N %s", i,
624  _pcps_ddev_dev_id( *ppddev ), _pcps_ddev_sernum( *ppddev ) );
625 
626  if ( ( dev_id == _pcps_ddev_dev_id( *ppddev ) )
627  && ( strcmp( sernum, _pcps_ddev_sernum( *ppddev ) ) == 0 ) )
628  {
629  // device found
630  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "New device %04X S/N %s already in device list",
631  dev_id, sernum );
632 
633  return ppddev;
634  }
635  }
636  }
637 
638  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Device ID %04X, S/N %s not found in device list",
639  dev_id, sernum );
640 
641  return NULL;
642 
643 } // ddev_list_locate_device
644 
645 
646 
647 static /*HDR*/
649 {
650  int i;
651 
652  for ( i = 0; i < max_devs; i++ )
653  {
654  PCPS_DDEV **ppddev = &ddev_list[i];
655 
656  if ( *ppddev == pddev )
657  {
658  *ppddev = NULL;
659  return 0;
660  }
661  }
662 
663  mbg_kdd_msg( MBG_LOG_WARN, "Failed to remove device minor %i from device list",
664  MINOR( pddev->lx_dev ) );
665 
666  return -1; //TODO
667 
668 } // ddev_list_remove_entry
669 
670 
671 
672 static /*HDR*/
674 {
675  int i;
676 
677  for ( i = 0; i < max_devs; i++ )
678  {
679  PCPS_DDEV **ppddev = &ddev_list[i];
680 
681  if ( *ppddev == NULL )
682  {
683  *ppddev = pddev;
684  return i;
685  }
686  }
687 
688  mbg_kdd_msg( MBG_LOG_WARN, "Failed to add device to device list: list full" );
689 
690  return -1; //TODO
691 
692 } // ddev_list_add_entry
693 
694 
695 
696 static /*HDR*/
697 void pcps_time_to_time_str( const PCPS_TIME *t, char *s, size_t max_len )
698 {
699  PCPS_TIME_STATUS status = t->status;
700 
701  if ( status & PCPS_INVT ) // invalid time
702  {
703  status |= PCPS_FREER;
704  status &= ~PCPS_SYNCD;
705  }
706 
707  scnprintf( s, max_len, "%cD:%02i.%02i.%02i;T:%i;U:%02i.%02i.%02i;%c%c%c%c%c",
708  '\02', // STX
709  t->mday, t->month, t->year, t->wday, // date and day-of-week
710  t->hour, t->min, t->sec, // time
711  ( pretend_sync || ( status & PCPS_SYNCD ) ) ? ' ' : '#', // sync'd after reset
712  ( !pretend_sync && ( status & PCPS_FREER ) ) ? '*' : ' ', // free running
713  ( t->offs_utc == 0 ) ? 'U' : // UTC
714  ( ( status & PCPS_DL_ENB ) ? 'S' : ' ' ), // DST enabled
715  ( status & PCPS_DL_ANN ) ? '!' : // DST change announced
716  ( ( status & PCPS_LS_ANN ) ? 'A' : ' ' ), // leap second announced
717  '\03' ); // ETX
718 
719 } // pcps_time_to_time_str
720 
721 
722 
723 // The interrupt handler for plug-in cards. USB devices
724 // don't generate periodic interrupts. Instead, they can
725 // send a periodic message once per second.
726 
727 static /*HDR*/
728 #if REQUEST_IRQ_WO_REGS
729  irqreturn_t mbgclock_irq_handler( int hw_irq, void *arg )
730 #else
731  irqreturn_t mbgclock_irq_handler( int hw_irq, void *arg, struct pt_regs *regs )
732 #endif
733 {
734  PCPS_DDEV *pddev;
735  unsigned long flags;
736  int curr_access_in_progress;
737  #if defined( IRQ_RETVAL )
738  int retval = IRQ_NONE;
739  #endif
740  #if DEBUG_IRQ_TIMING
741  unsigned long prv_jiffies_at_irq;
742  #endif
743  int rc;
745 
746 
747  pddev = (PCPS_DDEV *) arg;
748 
749  if ( pddev == NULL )
750  {
751  mbg_kdd_msg( MBG_LOG_WARN, "IRQ handler called with NULL device" );
752  goto out;
753  }
754 
755  if ( !_pcps_ddev_has_gen_irq( pddev ) )
756  goto out;
757 
758 
759  _mbg_dbg_hw_lpt_set_bit( MBG_BIT_IRQ );
760 
761  rc = -1;
762  spin_lock_irqsave( &pddev->irq_lock, flags );
763 
764  curr_access_in_progress = atomic_read( &pddev->access_in_progress );
765 
766  #if DEBUG_IRQ_TIMING
767  prv_jiffies_at_irq = pddev->jiffies_at_irq;
768  #endif
769  pddev->jiffies_at_irq = jiffies;
770 
771  #if DEBUG_IRQ_LATENCY
772  rdtscll( tsc_irq_1 );
773  #endif
774 
775  if ( !curr_access_in_progress )
776  rc = _pcps_read_var( pddev, PCPS_GIVE_TIME, pddev->t );
777 
778  #if DEBUG_IRQ_LATENCY
779  rdtscll( tsc_irq_2 );
780  #endif
781 
782  _pcps_ddev_ack_irq( pddev );
783 
784 
785  if ( !curr_access_in_progress )
786  {
787  if ( mbg_rc_is_success( rc ) )
788  {
789  atomic_set( &pddev->data_avail, 1 );
790 
791  wake_up_interruptible( &pddev->wait_queue );
792 
793  if ( pddev->fasyncptr )
794  _kill_fasync( &pddev->fasyncptr, SIGIO, POLL_IN );
795  }
796  }
797 
798  spin_unlock_irqrestore( &pddev->irq_lock, flags );
799 
800 
801  #if DEBUG_IRQ_TIMING
802  {
803  const char *info;
804 
805  if ( !curr_access_in_progress )
806  {
807  if ( mbg_rc_is_success( rc ) )
808  info = "data read";
809  else
810  info = "read error";
811  }
812  else
813  {
814  info = "** access in progress";
815  rc = curr_access_in_progress;
816  }
817 
818  mbg_kdd_msg( MBG_LOG_INFO, "IRQ handler %i at 0x%lX - 0x%lX -> %li, " MBG_DEV_NAME_FMT ": %s: %i",
819  _pcps_ddev_irq_num( pddev), pddev->jiffies_at_irq, prv_jiffies_at_irq,
820  (long) pddev->jiffies_at_irq - (long) prv_jiffies_at_irq,
821  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ),
822  info, rc );
823  }
824  #endif
825 
826  #if defined( IRQ_RETVAL )
827  retval = IRQ_HANDLED;
828  #endif
829 
830 out:
831  _mbg_dbg_hw_lpt_clr_bit( MBG_BIT_IRQ );
832 
833  #if defined( IRQ_RETVAL )
834  return retval;
835  #endif
836 
837 } // mbgclock_irq_handler
838 
839 
840 
841 __mbg_inline
842 int get_cyclic_lock( PCPS_DDEV *pddev, unsigned long *p_flags, const char *fnc_name )
843 {
844  #if _PCPS_USE_USB
845  if ( _pcps_ddev_is_usb( pddev ) )
846  {
847  if ( _down_interruptible_pddev( &pddev->sem_usb_cyclic, "sem_usb_cyclic", fnc_name, pddev ) < 0 )
848  return -ERESTARTSYS;
849  }
850  else
851  #endif
852  spin_lock_irqsave( &pddev->irq_lock, *p_flags );
853 
854  return 0;
855 
856 } // get_cyclic_lock
857 
858 
859 
860 __mbg_inline
861 void release_cyclic_lock( PCPS_DDEV *pddev, unsigned long *p_flags, const char *fnc_name )
862 {
863  #if _PCPS_USE_USB
864  if ( _pcps_ddev_is_usb( pddev ) )
865  _up_pddev( &pddev->sem_usb_cyclic, "sem_usb_cyclic", fnc_name, pddev );
866  else
867  #endif
868  spin_unlock_irqrestore( &pddev->irq_lock, *p_flags );
869 
870 } // release_cyclic_lock
871 
872 
873 
874 #if _PCPS_USE_USB
875 
876 // The function below is started as a new kernel thread in order to
877 // receive periodic messages from an USB device.
878 // This is used to emulate the hardware IRQ generated by
879 // plug-in cards.
880 
881 static /*HDR*/
882 int mbgdrvr_read_usb_cyclic( void *p )
883 {
884  PCPS_DDEV *pddev = p;
885 
886  _mbgddmsg_4( DEBUG_DRVR, MBG_LOG_INFO, "USB xmt tmo: %u, rcv tmo: %u, cycl tmo: %u, HZ: %u",
887  MBGUSB_TIMEOUT_SEND, MBGUSB_TIMEOUT_RECEIVE,
888  MBGUSB_TIMEOUT_RECEIVE_CYCLIC, HZ );
889 
891 
892  // The device sends a cyclic message in intervals of 1 s,
893  // so we have to wait more than 1 s totally to detect a
894  // timeout.
895  // Unfortunatly the USB read function does not return if
896  // we receive a signal (e.g. to terminate), so in order
897  // to be able to react on a signal in a timely manner
898  // we call the read function with a fraction of the total
899  // timeout and simply retry unless we have received a signal,
900  // or the total timeout interval has expired.
901  for (;;)
902  {
903  int rc;
904 
905  if ( _usb_read_thread_should_stop() ) // we have been signalled to abort
906  {
907  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Cyclic USB read " MBG_DEV_NAME_FMT " received signal to stop",
908  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
909  break;
910  }
911 
912  // read with fractional timeout interval
913  rc = _pcps_direct_usb_read_var_cyclic( pddev, &pddev->t_cyc );
914 
915  if ( mbg_rc_is_error( rc ) )
916  {
917  if ( rc == MBG_ERR_TIMEOUT )
918  {
919  #if ( 1 && defined( DEBUG ) ) // TODO DEBUG_CYCLIC
920  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_WARN, "Cyclic USB read " MBG_DEV_NAME_FMT " timed out",
921  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
922  #endif
923  continue; // this may be a normal case
924  }
925 
926  // Read has been terminated due to some other error.
927  // Eventually the device has been disconnected, in which case
928  // the USB stack may return -ETIME (-62), which is converted
929  // to MBG_ERR_TIMER.
930  _mbgddmsg_4( DEBUG_DRVR, MBG_LOG_WARN, "Cyclic USB read " MBG_DEV_NAME_FMT " returned %i: %s",
931  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ), rc, mbg_strerror( rc ) );
932  break;
933  }
934 
935  // success, so rc holds the number of bytes read
936  if ( rc != sizeof( pddev->t_cyc ) )
937  {
938  _mbgddmsg_4( DEBUG_DRVR, MBG_LOG_WARN, "Cyclic USB read " MBG_DEV_NAME_FMT " returned %i of %i bytes",
939  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ), rc, (int) sizeof( pddev->t_cyc ) );
940  continue;
941  }
942 
943  // received a message from the device
944  #if DEBUG_IRQ_LATENCY
945  rdtscll( tsc_usb_1 );
946  #endif
947 
948  if ( _down_interruptible_pddev( &pddev->sem_usb_cyclic, "sem_usb_cyclic", __func__, pddev ) < 0 )
949  break;
950 
951  #if DEBUG_IRQ_LATENCY
952  rdtscll( tsc_usb_2 );
953  #endif
954 
955  pddev->jiffies_at_irq = jiffies;
956  pddev->t = pddev->t_cyc;
957  atomic_set( &pddev->data_avail, 1 );
958 
959  _up_pddev( &pddev->sem_usb_cyclic, "sem_usb_cyclic", __func__, pddev );
960 
961  _mbgddmsg_6( DEBUG_DRVR, MBG_LOG_INFO, "Cyclic USB read " MBG_DEV_NAME_FMT " success: %02d:%02d:%02d.%02d",
962  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ),
963  pddev->t.hour, pddev->t.min, pddev->t.sec, pddev->t.sec100 );
964 
965  wake_up_interruptible( &pddev->wait_queue );
966 
967  if ( pddev->fasyncptr )
968  _kill_fasync( &pddev->fasyncptr, SIGIO, POLL_IN );
969  }
970 
971  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Cyclic USB read thread for " MBG_DEV_NAME_FMT " exits",
972  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
973 
975  _usb_read_thread_exit( pddev, 0 );
976 
977 } // mbgdrvr_read_usb_cyclic
978 
979 
980 
981 static /*HDR*/
982 int mbgdrvr_ctrl_usb_cyclic( PCPS_DDEV *pddev, uint8_t cmd )
983 {
984  int rc;
985 
986  if ( _down_interruptible( &pddev->dev_mutex, "dev_mutex", __func__, pddev ) < 0 )
987  return -ERESTARTSYS;
988 
989  pddev->cmd_info.cmd = cmd;
990  rc = _pcps_direct_usb_write_var( pddev, &pddev->cmd_info.cmd );
991 
992  _up( &pddev->dev_mutex, "dev_mutex", "ctrl_usb_cyclic", pddev );
993 
994  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Control USB cyclic cmd 0x%02X, rc: %d",
995  cmd, rc );
996 
997  return rc;
998 
999 } // mbgdrvr_ctrl_usb_cyclic
1000 
1001 #endif // _PCPS_USE_USB
1002 
1003 
1004 
1005 static /*HDR*/
1007 {
1009 
1010  if ( !( pddev->irq_stat_info & PCPS_IRQ_STAT_ENABLED ) )
1011  goto done;
1012 
1013  #if _PCPS_USE_USB
1014  if ( _pcps_ddev_is_usb( pddev ) )
1015  {
1016  _mbg_dbg_hw_lpt_set_bit( MBG_BIT_TEST );
1017  mbgdrvr_ctrl_usb_cyclic( pddev, PCPS_IRQ_NONE );
1018  _mbg_dbg_hw_lpt_clr_bit( MBG_BIT_TEST );
1019 
1020  _mbgddmsg_0( DEBUG_DRVR, MBG_LOG_INFO, "Disabled cyclic USB msgs" );
1021 
1022  if ( _usb_read_thread_started( pddev ) )
1023  {
1024  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Cyclic USB read thread for " MBG_DEV_NAME_FMT " going to be stopped",
1025  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1026 
1027  _usb_read_thread_stop( pddev );
1028 
1029  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Cyclic USB read thread for " MBG_DEV_NAME_FMT " has been stopped",
1030  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1031  }
1032  }
1033  else
1034  #endif
1035  {
1036  int irq_num = _pcps_ddev_irq_num( pddev );
1037 
1038  _mbg_dbg_hw_lpt_set_bit( MBG_BIT_TEST );
1039  _pcps_ddev_disb_irq( pddev );
1040  _mbg_dbg_hw_lpt_clr_bit( MBG_BIT_TEST );
1041 
1042  free_irq( irq_num, pddev );
1043 
1044  _mbgddmsg_1( DEBUG_DRVR, MBG_LOG_INFO, "Disabled IRQ %i", irq_num );
1045  }
1046 
1047 done:
1049  return 0;
1050 
1051 } // mbgdrvr_disable_cyclic
1052 
1053 
1054 
1055 static /*HDR*/
1056 int mbgdrvr_enable_cyclic( PCPS_DDEV *pddev, unsigned int force )
1057 {
1058  if ( ( force == 0 ) && ( pddev->irq_stat_info & PCPS_IRQ_STAT_ENABLE_CALLED ) )
1059  return 0; // has already been called
1060 
1061  if ( force > 1 )
1062  mbg_kdd_msg( MBG_LOG_WARN, "Trying to re-initialize cyclic msgs for " MBG_DEV_NAME_FMT,
1063  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1064 
1066 
1067  if ( pddev->irq_stat_info & PCPS_IRQ_STAT_UNSAFE )
1068  mbg_kdd_msg( MBG_LOG_WARN, "Enabling IRQs for dev " MBG_DEV_NAME_FMT " though unsafe",
1069  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1070 
1071  pddev->jiffies_at_irq = jiffies;
1072 
1073  #if _PCPS_USE_USB
1074  if ( _pcps_ddev_is_usb( pddev ) )
1075  {
1076  if ( force > 1 )
1077  usb_reset_device( pddev->udev );
1078 
1079  if ( !_usb_read_thread_started( pddev ) )
1080  {
1081  _usb_read_thread_start( mbgdrvr_read_usb_cyclic, pddev );
1082 
1083  if ( _usb_read_thread_failed_to_start( pddev ) )
1084  {
1085  mbg_kdd_msg( MBG_LOG_WARN, "Failed to start cyclic USB read thread for " MBG_DEV_NAME_FMT,
1086  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1087  _usb_read_thread_set_unused( pddev );
1088  }
1089  else
1090  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Cyclic USB read thread for " MBG_DEV_NAME_FMT " started successfully",
1091  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1092  }
1093  else
1094  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Cyclic USB read thread for " MBG_DEV_NAME_FMT " already started",
1095  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1096 
1097  if ( _usb_read_thread_started( pddev ) )
1098  {
1100  mbgdrvr_ctrl_usb_cyclic( pddev, PCPS_IRQ_1_SEC );
1101  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Initialized cyclic USB msgs for " MBG_DEV_NAME_FMT,
1102  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1103  }
1104  }
1105  else
1106  #endif
1107  {
1108  int irq_num = _pcps_ddev_irq_num( pddev );
1109  int rc;
1110  unsigned long flags = 0;
1111 
1112  // If the IRQ has already been enabled and registered with the kernel before
1113  // then we must disable and unregister it before we re-enable it and register
1114  // it once more. Otherwise the kernel's list of registered IRQ handlers as
1115  // reported by 'cat /proc/interrupts' will be messed up.
1116  if ( pddev->irq_stat_info & PCPS_IRQ_STAT_ENABLED )
1117  mbgdrvr_disable_cyclic( pddev );
1118 
1119  // The IRQF_DISABLED flag has been obsoleted in 2.6.35, and has completely
1120  // been removed in 4.1. Also the SA_INTERRUPT flag, which was used before
1121  // IRQF_DISABLED was introduced in 2.6.24 to distinguish between "fast"
1122  // and "slow" ISRs is now obsolete.
1123  // Usage of either of these flags is questionable anyway, see:
1124  // https://lwn.net/Articles/380931/
1125  // We leave an outcommented code fragment here, so it can easily be
1126  // activated if it should unexpectedly be required.
1127  #if 0
1128  #if defined( IRQF_DISABLED )
1129  flags |= IRQF_DISABLED;
1130  #elif defined( SA_INTERRUPT )
1131  flags |= SA_INTERRUPT;
1132  #endif
1133  #endif
1134 
1135  // Shared IRQs are not supported by old ISA cards, so we flag
1136  // the IRQ as "shared" only in case of non-ISA, namely PCI.
1137  // The symbol name of the "shared IRQ" flag varies with the
1138  // kernel version, though.
1139  if ( !_pcps_ddev_is_isa( pddev ) )
1140  {
1141  #if defined( IRQF_SHARED )
1142  flags |= IRQF_SHARED;
1143  #elif defined( SA_SHIRQ )
1144  flags |= SA_SHIRQ;
1145  #endif
1146  }
1147 
1148  rc = request_irq( irq_num, mbgclock_irq_handler, flags,
1149  driver_name, pddev );
1150 
1151  if ( rc < 0 )
1152  {
1153  mbg_kdd_msg( MBG_LOG_ERR, "Failed to request IRQ %i for " MBG_DEV_NAME_FMT ", rc: %i",
1154  irq_num, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ), rc );
1155  return -EBUSY;
1156  }
1157 
1159 
1161  _mbgddmsg_4( DEBUG_DRVR, MBG_LOG_INFO, "Initialized IRQ %i for " MBG_DEV_NAME_FMT " (open_count: %i)",
1162  irq_num, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ),
1163  atomic_read( &pddev->open_count ) );
1164  }
1165 
1166  return 0;
1167 
1168 } // mbgdrvr_enable_cyclic
1169 
1170 
1171 
1172 #if DEBUG_IRQ_TIMING
1173 
1174 static /*HDR*/
1175 void report_irq_timing( int lvl, const PCPS_DDEV *pddev,
1176  unsigned long jiffies_now,
1177  unsigned long jiffies_at_irq,
1178  long delta_jiffies )
1179 {
1180 
1181 } // report_irq_timing
1182 
1183 #endif // DEBUG_IRQ_TIMING
1184 
1185 
1186 
1187 static /*HDR*/
1188 unsigned int mbgclock_poll( struct file *filp, poll_table *pt )
1189 {
1190  unsigned int poll_retval = 0;
1191  PCPS_DDEV *pddev = NULL;
1192  int sys_rc = mbgdrvr_get_pddev( &pddev, filp, "poll" );
1193 
1194  if ( sys_rc < 0 )
1195  {
1196  poll_retval = POLLERR | POLLHUP;
1197  goto out;
1198  }
1199 
1200  mbgdrvr_enable_cyclic( pddev, 0 );
1201 
1202  poll_wait( filp, &pddev->wait_queue, pt );
1203 
1204  if ( atomic_read( &pddev->data_avail ) )
1205  poll_retval = POLLIN | POLLRDNORM;
1206  else
1207  {
1208  unsigned long flags = 0;
1209  unsigned long jiffies_now = jiffies;
1210  unsigned long jiffies_at_irq;
1211  long delta_jiffies;
1212 
1213  if ( get_cyclic_lock( pddev, &flags, __func__ ) < 0 )
1214  return -ERESTARTSYS;
1215 
1216  jiffies_at_irq = pddev->jiffies_at_irq;
1217 
1218  release_cyclic_lock( pddev, &flags, __func__ );
1219 
1220  delta_jiffies = (long) jiffies_now - (long) jiffies_at_irq;
1221 
1222 
1223  if ( delta_jiffies > CYCLIC_TIMEOUT )
1224  {
1225  mbg_kdd_msg( MBG_LOG_WARN, "** Cyclic timeout polling " MBG_DEV_NAME_FMT ": 0x%08lX - 0x%08lX = %li, exceeds %li",
1226  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ),
1227  jiffies_now, jiffies_at_irq,
1228  delta_jiffies, CYCLIC_TIMEOUT );
1229 
1230  #if DEBUG_IRQ_TIMING
1231  report_irq_timing( MBG_LOG_DEBUG, pddev, jiffies_now, jiffies_at_irq, delta_jiffies );
1232  #endif
1233 
1234  mbgdrvr_enable_cyclic( pddev, 2 );
1235  }
1236  else
1237  {
1238  #if DEBUG_IRQ_TIMING
1239  mbg_kdd_msg( MBG_LOG_DEBUG, "Poll chk cyclic timeout " MBG_DEV_NAME_FMT ": 0x%08lX - 0x%08lX = %li, timeout: %li",
1240  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ),
1241  jiffies_now, jiffies_at_irq,
1242  delta_jiffies, CYCLIC_TIMEOUT );
1243  #endif
1244  }
1245  }
1246 
1247 out:
1248  return poll_retval;
1249 
1250 } // mbgclock_poll
1251 
1252 
1253 
1254 /*
1255  * The function below is called whenever fcntl( .., F_SETFL, ..) is called
1256  * to change the device's FASYNC flag.
1257  *
1258  */
1259 static /*HDR*/
1260 int mbgclock_fasync( int fd, struct file *filp, int on )
1261 {
1262  PCPS_DDEV *pddev = NULL;
1263  int sys_rc = mbgdrvr_get_pddev( &pddev, filp, "fasync" );
1264 
1265  if ( sys_rc < 0 )
1266  goto out;
1267 
1268  // mbgdrvr_enable_cyclic( pddev, 0 ); //##++ conditionally / always enable IRQ here?
1269 
1270  sys_rc = fasync_helper( fd, filp, on, &pddev->fasyncptr );
1271 
1272 out:
1273  return sys_rc;
1274 
1275 } // mbgclock_fasync
1276 
1277 
1278 
1279 static /*HDR*/
1280 #if FLUSH_WITH_LOCK_OWNER_ID
1281 int mbgclock_flush( struct file *filp, fl_owner_t id )
1282 #else
1283 int mbgclock_flush( struct file *filp )
1284 #endif
1285 {
1286  PCPS_DDEV *pddev = NULL;
1287  int sys_rc = mbgdrvr_get_pddev( &pddev, filp, "flush" );
1288 
1289  if ( sys_rc < 0 )
1290  goto out;
1291 
1292  atomic_set( &pddev->data_avail, 0 );
1293 
1294 out:
1295  return sys_rc;
1296 
1297 } // mbgclock_flush
1298 
1299 
1300 
1301 static /*HDR*/
1302 int mbgclock_open( struct inode *inode, struct file *filp )
1303 {
1304  PCPS_DDEV **ppddev;
1305  PCPS_DDEV *pddev;
1306  int minor = iminor( inode );
1307  int retval = 0;
1309 
1310  _mbg_dbg_hw_lpt_set_bit( MBG_BIT_OPEN );
1311 
1312  if ( filp == NULL )
1313  {
1314  mbg_kdd_msg( MBG_LOG_WARN, "Open minor %i called with file pointer NULL", minor );
1315  retval = -EBADF;
1316  goto out;
1317  }
1318 
1319  if ( _down_interruptible( &sem_fops, "sem_fops", __func__, filp ) < 0 )
1320  {
1321  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "%p open minor %i: interrupted wait for sem_fops",
1322  filp, minor );
1323  retval = -ERESTARTSYS;
1324  goto out;
1325  }
1326 
1327  ppddev = ddev_list_locate_minor( minor );
1328 
1329  if ( ppddev == NULL )
1330  goto out_enodev;
1331 
1332  pddev = *ppddev;
1333 
1334  if ( pddev == NULL )
1335  goto out_enodev;
1336 
1337 
1338  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "%p open minor %i",
1339  filp, minor );
1340 
1341  filp->private_data = ppddev;
1342 
1343  atomic_inc( &pddev->open_count );
1344 
1345  _mbgddmsg_3( DEBUG_DRVR, MBG_LOG_INFO, "%p open: new open count: %i, dev: %p",
1346  filp, atomic_read( &pddev->open_count ), pddev );
1347 
1348  #if _PCPS_MUST_UPDATE_USE_COUNT
1349  MOD_INC_USE_COUNT;
1350  #endif
1351 
1352  goto out_up_sem_fops;
1353 
1354 
1355 out_enodev:
1356  retval = -ENODEV;
1357  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_WARN, "%p open failed for minor %i: ENODEV",
1358  filp, minor );
1359 
1360 out_up_sem_fops:
1361  _up( &sem_fops, "sem_fops", "open", filp );
1362 
1363 out:
1364  _mbg_dbg_hw_lpt_clr_bit( MBG_BIT_OPEN );
1365 
1366  return retval;
1367 
1368 } // mbgclock_open
1369 
1370 
1371 
1372 static /*HDR*/
1373 int mbgclock_release( struct inode *inode, struct file *filp )
1374 {
1375  PCPS_DDEV *pddev;
1376  int retval = 0;
1378 
1379 
1380  _mbg_dbg_hw_lpt_set_bit( MBG_BIT_RELEASE );
1381 
1382  if ( _down_interruptible( &sem_fops, "sem_fops", __func__, filp ) < 0 )
1383  {
1384  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "%p release %i: interrupted wait for sem_fops",
1385  filp, minor );
1386  retval = -ERESTARTSYS;
1387  goto out; // don't return directly
1388  }
1389 
1390  // sem_fops must not be released before we're through with pddev !
1391 
1392  pddev = *( (PCPS_DDEV **) filp->private_data );
1393 
1394  if ( pddev == NULL )
1395  {
1396  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_WARN, "%p release %i: closing with dev NULL",
1397  filp, iminor( inode ) );
1398  retval = -ENODEV;
1399  goto out_up_sem_fops;
1400  }
1401 
1402  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "%p release %i: closing",
1403  filp, iminor( inode ) );
1404 
1405  if ( atomic_dec_and_test( &pddev->open_count ) )
1406  {
1407  if ( get_dev_connected( pddev ) )
1408  {
1409  _mbgddmsg_4( DEBUG_DRVR, MBG_LOG_INFO, "%p release %i: closing with connected dev " MBG_DEV_NAME_FMT,
1410  filp, iminor( inode ),
1411  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1412  mbgdrvr_disable_cyclic( pddev );
1413  }
1414  else
1415  {
1416  _mbgddmsg_4( DEBUG_DRVR, MBG_LOG_INFO, "%p release %i: closing with disconnected dev " MBG_DEV_NAME_FMT,
1417  filp, iminor( inode ),
1418  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1419  mbgdrvr_delete_device( pddev );
1420  pddev = NULL;
1421  retval = -ENODEV;
1422  }
1423  }
1424  else
1425  _mbgddmsg_5( DEBUG_DRVR, MBG_LOG_INFO, "%p release %i: new open count: %i, dev " MBG_DEV_NAME_FMT,
1426  filp, iminor( inode ), atomic_read( &pddev->open_count ),
1427  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1428 
1429  #if _PCPS_MUST_UPDATE_USE_COUNT
1430  MOD_DEC_USE_COUNT;
1431  #endif
1432 
1433  if ( pddev ) // has not been deleted above
1434  {
1435  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "%p release %i calling fasync_helper",
1436  filp, iminor( inode ));
1437  fasync_helper( -1, filp, 0, &pddev->fasyncptr );
1438  }
1439 
1440 
1441 out_up_sem_fops:
1442  _up( &sem_fops, "sem_fops", "release", filp );
1443 
1444 out:
1445  _mbg_dbg_hw_lpt_clr_bit( MBG_BIT_RELEASE );
1446 
1447  return retval;
1448 
1449 } // mbgclock_release
1450 
1451 
1452 
1453 #if DEBUG_IRQ_LATENCY
1454 
1455 static /*HDR*/
1456 long dt( int64_t delta_cyc )
1457 {
1458  return (long) ( delta_cyc / cpu_khz / 1000 );
1459 
1460 } // dt
1461 
1462 #endif
1463 
1464 
1465 
1466 static /*HDR*/
1467 ssize_t mbgclock_read( struct file *filp, char *buffer,
1468  size_t count, loff_t *ppos )
1469 {
1470  PCPS_DDEV *pddev;
1471  unsigned long flags = 0;
1472  PCPS_TIME t;
1473  char timestr[MBG_SIZE_TLG];
1474  int bytes_to_copy;
1475  ssize_t sys_rc = mbgdrvr_get_pddev( &pddev, filp, ( filp->f_flags & O_NONBLOCK ) ?
1476  "read (non-blocking)" : "read (blocking)" );
1477 
1478  if ( sys_rc < 0 )
1479  goto out;
1480 
1481  _mbgddmsg_1( DEBUG_DRVR, MBG_LOG_INFO, "%p read starts", filp );
1482 
1483  if ( atomic_read( &pddev->open_count ) == 0 ) //##++
1484  {
1485  _mbgddmsg_3( DEBUG, MBG_LOG_ERR, "%p read: dev " MBG_DEV_NAME_FMT " not opened",
1486  filp, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1487  sys_rc = -EIO;
1488  goto out;
1489  }
1490 
1491  #if !ESPIPE_BY_VFS
1492  if ( ppos != &filp->f_pos )
1493  {
1494  _mbgddmsg_3( DEBUG_DRVR, MBG_LOG_WARN, "%p read: dev " MBG_DEV_NAME_FMT " past end",
1495  filp, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1496  sys_rc = -ESPIPE;
1497  goto out;
1498  }
1499  #endif
1500 
1501  if ( buffer == NULL )
1502  {
1503  _mbgddmsg_1( DEBUG, MBG_LOG_ERR, "%p read: no buffer specified", filp );
1504  sys_rc = -EINVAL;
1505  goto out;
1506  }
1507 
1508  mbgdrvr_enable_cyclic( pddev, 0 );
1509 
1510  if ( count < sizeof( timestr ) )
1511  _mbgddmsg_3( DEBUG, MBG_LOG_WARN, "%p read: buffer size (%i) less than required (%i)",
1512  filp, (int) count, (int) sizeof( timestr ) );
1513 
1514  _mbgddmsg_1( DEBUG_DRVR, MBG_LOG_INFO, "%p read: wait for data_avail", filp );
1515 
1516  while ( !atomic_read( &pddev->data_avail ) )
1517  {
1518  if ( filp->f_flags & O_NONBLOCK )
1519  {
1520  _mbgddmsg_3( DEBUG_DRVR, MBG_LOG_WARN, "%p read non-blocking returns with no data available, dev: " MBG_DEV_NAME_FMT,
1521  filp, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1522  sys_rc = -EAGAIN;
1523  goto out;
1524  }
1525 
1526  #if USE_WAIT_EVENT
1527  for (;;)
1528  {
1529  int dev_connected = 0;
1530  int this_rc = wait_event_interruptible_timeout( pddev->wait_queue,
1531  atomic_read( &pddev->data_avail ) || !(dev_connected = get_dev_connected( pddev ) ), CYCLIC_TIMEOUT );
1532 
1533  if ( this_rc < 0 ) // interrupted
1534  goto out_interrupted_wait;
1535 
1536  if ( !dev_connected ) // device has been removed
1537  {
1538  _mbgddmsg_3( DEBUG_DRVR, MBG_LOG_WARN, "%p read dev " MBG_DEV_NAME_FMT ": device removed while waiting",
1539  filp, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1540  sys_rc = -ERESTARTSYS;
1541  goto out;
1542  }
1543 
1544  if ( this_rc ) // data available, the normal case
1545  break;
1546 
1547  // timeout, cyclic reads may have been disabled, try to re-enable
1548  _mbgddmsg_3( DEBUG, MBG_LOG_WARN, "%p read: IRQ timeout, dev " MBG_DEV_NAME_FMT,
1549  filp, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1550 
1551  mbgdrvr_enable_cyclic( pddev, 2 );
1552  }
1553  #else
1554  // There may be a race condition if data has become available
1555  // after the while() check but before we go to sleep below.
1556  // However, this doesn't really matter for our application.
1557  interruptible_sleep_on_timeout( &pddev->wait_queue ); // used with 2.4.x and needs to be fixed
1558 
1559  if ( signal_pending( current ) )
1560  goto out_interrupted_wait;
1561  #endif
1562  }
1563 
1564 
1565  if ( get_cyclic_lock( pddev, &flags, __func__ ) < 0 )
1566  return -ERESTARTSYS;
1567 
1568  t = pddev->t;
1569  atomic_set( &pddev->data_avail, 0 );
1570 
1571  release_cyclic_lock( pddev, &flags, __func__ );
1572 
1573 
1574  pcps_time_to_time_str( &t, timestr, sizeof( timestr ) );
1575 
1576  #if DEBUG_IRQ_LATENCY
1577  if ( debug > 1 )
1578  {
1579  unsigned long long tsc;
1580 
1581  rdtscll( tsc );
1582 
1583  if ( _pcps_ddev_is_usb( pddev ) )
1584  mbg_kdd_msg( MBG_LOG_INFO, "%s %Lu %lu %lu, %lu", _pcps_ddev_type_name( pddev ),
1585  tsc, dt( tsc - tsc_usb_2 ), dt( tsc_usb_2 - tsc_usb_1 ),
1586  dt( tsc_usb_1 - tsc_irq_1 ) );
1587  else
1588  mbg_kdd_msg( MBG_LOG_INFO, "%s %Lu %lu %lu", _pcps_ddev_type_name( pddev ),
1589  tsc, dt( tsc - tsc_irq_2 ), dt( tsc_irq_2 - tsc_irq_1 ) );
1590  }
1591  #endif
1592 
1593  bytes_to_copy = _min( count, sizeof( timestr ) - 1 );
1594 
1595  if ( copy_to_user( buffer, timestr, bytes_to_copy ) )
1596  {
1597  _mbgddmsg_3( DEBUG_DRVR, MBG_LOG_ERR, "%p read: unable to copy to user space, dev " MBG_DEV_NAME_FMT,
1598  filp, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1599  sys_rc = -EFAULT;
1600  goto out;
1601  }
1602 
1603  sys_rc = bytes_to_copy;
1604  _mbgddmsg_4( DEBUG_DRVR, MBG_LOG_INFO, "%p read dev " MBG_DEV_NAME_FMT ": \"%s\"",
1605  filp, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ), timestr );
1606  goto out;
1607 
1608 
1609 out_interrupted_wait:
1610  _mbgddmsg_3( DEBUG_DRVR, MBG_LOG_INFO, "%p read dev " MBG_DEV_NAME_FMT ": blocking interrupted",
1611  filp, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1612  sys_rc = -ERESTARTSYS;
1613 
1614 out:
1615  return sys_rc;
1616 
1617 } // mbgclock_read
1618 
1619 
1620 
1621 static /*HDR*/
1622 ssize_t mbgclock_write( struct file *filp, const char *buffer,
1623  size_t count, loff_t *ppos )
1624 {
1625  _mbgddmsg_1( DEBUG, MBG_LOG_WARN, "%p write: not supported", filp );
1626 
1627  #if !ESPIPE_BY_VFS
1628  if ( ppos != &filp->f_pos )
1629  return -ESPIPE;
1630  #endif
1631 
1632  return -EIO;
1633 
1634 } // mbgclock_write
1635 
1636 
1637 
1638 static /*HDR*/
1639 int mbgdrvr_ioctl_emu_serial( struct file *filp, unsigned int cmd, unsigned long arg )
1640 {
1641  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "%p ioctl: emu serial cmd 0x%X", filp, cmd );
1642 
1643  switch ( cmd )
1644  {
1645  case TCGETS:
1646  {
1647  struct termios termios = { 0 };
1648 
1649  /*** Setzen der termios-Werte fuer die Meinberg Funkuhr
1650  ueber serielle Leitung zur Abfrage. ***/
1651  termios.c_iflag = IGNBRK|IGNPAR|ISTRIP; /* input mode flags */
1652  termios.c_oflag = 0; /* output mode flags */
1653  termios.c_cflag = B9600|CS7|PARENB|CREAD|HUPCL|CLOCAL; /* control mode flags */
1654  termios.c_lflag = 0; /* local mode flags */
1655  termios.c_line = 0; /* line discipline */
1656 
1657  if ( copy_to_user( (struct termios *) arg, &termios, sizeof( termios ) ) )
1658  {
1659  _mbgddmsg_1( DEBUG, MBG_LOG_WARN, "%p ioctl: cmd TCGETS copy_to_user failed", filp );
1660  return -EFAULT;
1661  }
1662 
1663  break;
1664  }
1665 
1666 
1667  case TIOCGWINSZ:
1668  {
1669  struct winsize winsize = { 0, 0, 0, 0 };
1670 
1671  if ( copy_to_user( (struct winsize *) arg, &winsize, sizeof( winsize ) ) )
1672  {
1673  _mbgddmsg_1( DEBUG, MBG_LOG_WARN, "%p ioctl: cmd TIOCGWINSZ copy_to_user failed", filp );
1674  return -EFAULT;
1675  }
1676 
1677  break;
1678  }
1679 
1680 
1681  case TCSETS:
1682  case TCFLSH:
1683  break;
1684 
1685  default:
1686  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_WARN, "%p ioctl: serial IOCTL cmd 0x%X not supported",
1687  filp, cmd );
1688  return -EINVAL;
1689 
1690  } // switch
1691 
1692  return 0;
1693 
1694 } // mbgdrvr_ioctl_emu_serial
1695 
1696 
1697 
1698 #if DEBUG_IOCTL
1699 
1700 static /*HDR*/
1701 void decode_ioctl( const char *s, ulong cmd )
1702 {
1703  _mbgddmsg_5( DEBUG_IOCTL, MBG_LOG_INFO, " %s 0x%08lX: type: 0x%02lX, nr: 0x%02lX, size: %lu",
1704  s, cmd, (ulong) _IOC_TYPE( cmd ), (ulong) _IOC_NR( cmd ), (ulong) _IOC_SIZE( cmd ) );
1705 
1706 } // decode_ioctl
1707 
1708 #endif
1709 
1710 
1711 
1712 static /*HDR*/
1713 // Unlike the other kernel functions which return POSIX errnos in case of
1714 // an error, this fuction returns one of the MBG_ERROR_CODES, except
1715 // for some IOCTLs for serial port emulation which are only received
1716 // if ntpd accesses this device via the parse driver.
1717 long mbgclock_unlocked_ioctl( struct file *filp, unsigned int cmd, unsigned long arg )
1718 {
1719  PCPS_DDEV *pddev = NULL;
1720  long sys_rc = mbgdrvr_get_pddev( &pddev, filp, "ioctl" );
1721  int priv_lvl;
1722  #if defined( DEBUG )
1723  const char *ioctl_name = mbgioctl_get_name( cmd );
1724  #endif
1725 
1726  if ( sys_rc < 0 ) // usually -ENODEV, or -ERESTARTSYS
1727  goto out;
1728 
1729  // Find out which privilege level is required
1730  // to execute this IOCTL command.
1731  priv_lvl = ioctl_get_required_privilege( cmd );
1732 
1733  // Check if the calling process has the required privilege.
1734  switch ( priv_lvl )
1735  {
1736  case MBG_REQ_PRIVL_NONE:
1737  _mbgddmsg_5( DEBUG, MBG_LOG_INFO, "%p %s (0x%02X): no priv lvl required, dev " MBG_DEV_NAME_FMT,
1738  filp, ioctl_name, cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1739  // Always allow.
1740  break;
1741 
1744  _mbgddmsg_5( DEBUG, MBG_LOG_INFO, "%p %s (0x%02X): no priv lvl required to read cfg, dev " MBG_DEV_NAME_FMT,
1745  filp, ioctl_name, cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1746  // This may require some privilege for the calling process.
1747  // Anyway, always allow for now.
1748  break;
1749 
1751  case MBG_REQ_PRIVL_SYSTEM:
1752  #if !OMIT_PRIV_CHECKING // this is the default case
1753  _mbgddmsg_5( DEBUG, MBG_LOG_INFO, "%p %s (0x%02X): admin rights required, dev " MBG_DEV_NAME_FMT,
1754  filp, ioctl_name, cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1755 
1756  if ( !capable( CAP_SYS_ADMIN ) ) // allow only if root privileges available.
1757  {
1758  _mbgddmsg_5( DEBUG, MBG_LOG_WARN, "%p %s (0x%02X): permission denied, dev " MBG_DEV_NAME_FMT,
1759  filp, ioctl_name, cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1760  return IOCTL_RC_ERR_PERM;
1761  }
1762  #else
1763  _mbgddmsg_5( DEBUG, MBG_LOG_WARN, "%p %s (0x%02X): admin rights would be required (checking omitted), dev " MBG_DEV_NAME_FMT,
1764  filp, ioctl_name, cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1765  #endif
1766  break;
1767 
1768  default:
1769  // maybe an unknown IOCTL code ...
1770  // This is OK if it is one of those codes required
1771  switch ( cmd )
1772  {
1773  case TCGETS:
1774  case TIOCGWINSZ:
1775  case TCSETS:
1776  case TCFLSH:
1777  sys_rc = mbgdrvr_ioctl_emu_serial( filp, cmd, arg );
1778 
1779  if ( sys_rc == 0 )
1780  goto out; // has been handled normally
1781 
1782  _mbgddmsg_5( DEBUG, MBG_LOG_WARN, "%p %s (0x%02X): invalid cmd, dev " MBG_DEV_NAME_FMT,
1783  filp, ioctl_name, cmd,
1784  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1785  #if DEBUG_IOCTL
1786  decode_ioctl( "ioctl", cmd );
1787  #endif
1788  break;
1789 
1790  default:
1791  _mbgddmsg_5( DEBUG, MBG_LOG_WARN, "%p %s (0x%02X): unknown command code, dev " MBG_DEV_NAME_FMT,
1792  filp, ioctl_name, cmd, _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
1793  #if DEBUG_IOCTL
1794  decode_ioctl( "ioctl", cmd );
1795  #endif
1796  return IOCTL_RC_ERR_UNSUPP_IOCTL; // TODO Is this ret val appropriate?
1797 
1798  } // switch
1799  }
1800 
1801  sys_rc = ioctl_switch( pddev, cmd, (void *) arg, (void *) arg );
1802 
1803 out:
1804  // If the return value is negative then this is considered as an error code.
1805  // The kernel converts this to a positive value which is stored in errno, and
1806  // lets the ioctl call return -1, so the calling user space code has to read
1807  // errno if -1 is returned.
1808 
1809  return sys_rc;
1810 
1811 } // mbgclock_unlocked_ioctl
1812 
1813 
1814 
1815 #if defined( HAVE_COMPAT_IOCTL ) && defined( CONFIG_COMPAT )
1816 
1817 static /*HDR*/
1818 long mbgclock_compat_ioctl( struct file *filp, unsigned int cmd, unsigned long arg )
1819 {
1820  long rc;
1821 
1822  #if DEBUG_IOCTL
1823  _mbg_kdd_msg_4( MBG_LOG_INFO, "%p compat_ioctl %s (0x%08X) calling ioctl (0x%08lX)",
1824  filp, mbgioctl_get_name( cmd ), cmd, (ulong) IOCTL_PCPS_GENERIC_READ_GPS );
1825 
1826  #endif
1827 
1828  rc = mbgclock_unlocked_ioctl( filp, cmd, arg );
1829 
1830  return rc;
1831 
1832 } // mbgclock_compat_ioctl
1833 
1834 #endif
1835 
1836 
1837 
1838 #if !defined( HAVE_UNLOCKED_IOCTL )
1839 
1840 static /*HDR*/
1841 int mbgclock_ioctl( struct inode *not_used, struct file *filp, unsigned int cmd, unsigned long arg )
1842 {
1843  long rc;
1844 
1845  _mbgddmsg_1( DEBUG_DRVR, MBG_LOG_INFO, "%p unlocked_ioctl calling ioctl()", filp );
1846 
1847  rc = mbgclock_unlocked_ioctl( filp, cmd, arg );
1848 
1849  return (int) rc;
1850 
1851 } // mbgclock_ioctl
1852 
1853 #endif
1854 
1855 
1856 
1857 static /*HDR*/
1858 int mbgclock_mmap( struct file * filp, struct vm_area_struct *vma )
1859 {
1860  MBG_IOMEM_ADDR_RAW addr;
1861  PCPS_DDEV *pddev = NULL;
1862  int rc = mbgdrvr_get_pddev( &pddev, filp, "mmap" );
1863 
1864  if ( rc < 0 )
1865  goto out;
1866 
1867  addr = pddev->rsrc_info.mem[0].start_raw;
1868 
1869 #if VMA_HAS_VM_PGOFF
1870  if ( ( ( vma->vm_end - vma->vm_start ) != PAGE_SIZE ) || vma->vm_pgoff )
1871 #else
1872  if ( ( ( vma->vm_end - vma->vm_start ) != PAGE_SIZE ) )
1873 #endif
1874  {
1875  mbg_kdd_msg( MBG_LOG_ERR, "vm_end (0x%08lX) - vm_start (0x%08lX) doesn't match PAGE_SIZE (0x%08lX)",
1876  vma->vm_end, vma->vm_start, (unsigned long) PAGE_SIZE );
1877  rc = -EINVAL;
1878  goto out;
1879  }
1880 
1881  #if VMA_HAS_VM_PGOFF
1883  "vm_end (0x%08lX) - vm_start (0x%08lX) == PAGE_SIZE (0x%08lX), pg_off: 0x%08lX",
1884  vma->vm_end, vma->vm_start, (unsigned long) PAGE_SIZE, vma->vm_pgoff );
1885  #else
1886  _mbgddmsg_3( DEBUG_DRVR, MBG_LOG_INFO, "vm_end (0x%08lX) - vm_start (0x%08lX) == PAGE_SIZE (0x%08lX)",
1887  vma->vm_end, vma->vm_start, (unsigned long) PAGE_SIZE );
1888  #endif
1889 
1890  vma->vm_flags |= VM_IO;
1891 
1892  #if defined( pgprot_noncached )
1893  vma->vm_page_prot = pgprot_noncached( vma->vm_page_prot );
1894  #endif
1895 
1896  #if _PCPS_HAS_REMAP_PFN
1897  rc = io_remap_pfn_range( vma, vma->vm_start, addr >> PAGE_SHIFT, PAGE_SIZE, vma->vm_page_prot );
1898  #else
1899  rc = io_remap_page_range( vma, vma->vm_start, addr, PAGE_SIZE, vma->vm_page_prot );
1900  #endif
1901 
1902  if ( rc )
1903  {
1904  rc = -EAGAIN;
1905  goto out;
1906  }
1907 
1908  rc = 0;
1909 
1910 out:
1911  return rc;
1912 
1913 } // mbgclock_mmap
1914 
1915 
1916 
1917 struct file_operations mbgclock_fops =
1918 {
1919  #if NEW_FILE_OPS
1920  owner: THIS_MODULE,
1921  #endif
1922 
1923  read: mbgclock_read,
1924  write: mbgclock_write,
1925  poll: mbgclock_poll,
1926  #if defined( HAVE_UNLOCKED_IOCTL )
1927  unlocked_ioctl: mbgclock_unlocked_ioctl,
1928  #else
1929  ioctl: mbgclock_ioctl,
1930  #endif
1931  #if defined( HAVE_COMPAT_IOCTL ) && defined( CONFIG_COMPAT )
1932  compat_ioctl: mbgclock_compat_ioctl, // called if a 32 bit app ioctls a 64 bit driver
1933  #endif
1934  open: mbgclock_open,
1935  flush: mbgclock_flush,
1936  release: mbgclock_release,
1937  fasync: mbgclock_fasync,
1938  mmap: mbgclock_mmap,
1939  llseek: NULL
1940 };
1941 
1942 
1943 
1944 #if _PCPS_USE_PCI_PNP
1945 
1946 static /*HDR*/
1947 int __devinit mbgdrvr_create_device( PCPS_DDEV *pddev )
1948 {
1949  int rc;
1950  int dev_idx;
1951  dev_t dev;
1952 
1954 
1955  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Going to create Linux device for " MBG_DEV_NAME_FMT,
1956  _pcps_ddev_type_name( pddev ),
1957  _pcps_ddev_sernum( pddev ) );
1958 
1959  dev_idx = ddev_list_add_entry( pddev );
1960 
1961  if ( dev_idx < 0 )
1962  {
1963  mbg_kdd_msg( MBG_LOG_WARN, "Didn't find free device list entry" );
1964  goto fail;
1965  }
1966 
1967  dev = MKDEV( major, minor + dev_idx );
1968  pddev->lx_dev = dev;
1969 
1970  cdev_init( &pddev->cdev, &mbgclock_fops );
1971  pddev->cdev.owner = THIS_MODULE;
1972 
1973  rc = cdev_add( &pddev->cdev, dev, 1 );
1974 
1975  if ( rc )
1976  {
1977  _mbgddmsg_1( DEBUG_DRVR, MBG_LOG_ERR, "Failed to add chrdev, index %d", dev_idx );
1978  goto fail;
1979  }
1980 
1981  _mbgddmsg_3( DEBUG_DRVR, MBG_LOG_INFO, "Successfully registered chrdev %d:%d, index %d",
1982  MAJOR( pddev->cdev.dev ), MINOR( pddev->cdev.dev ), dev_idx );
1983 
1984  #if _PCPS_HAVE_LINUX_CLASS
1985  if ( !IS_ERR( mbgclock_class ) )
1986  {
1987  #if _PCPS_CLASS_DEV_OBSOLETED
1988  struct device *device;
1989  device = device_create( mbgclock_class, NULL, dev,
1991  pddev,
1992  #endif
1993  mbg_clk_dev_node_fmt, minor + dev_idx );
1994  #elif _PCPS_HAVE_LINUX_CLASS_CREATE
1995  struct class_device *device;
1996  device = class_device_create( mbgclock_class,
1998  NULL,
1999  #endif
2000  dev, NULL, mbg_clk_dev_node_fmt, minor + dev_idx );
2001  #elif _PCPS_HAVE_LINUX_CLASS_SIMPLE
2002  struct class_device *device;
2003  device = class_simple_device_add( mbgclock_class, dev, NULL, mbg_clk_dev_node_fmt, minor + dev_idx );
2004  #endif
2005 
2006  if ( IS_ERR( device ) )
2007  {
2008  mbg_kdd_msg( MBG_LOG_WARN, "Failed to create device for " MBG_DEV_NAME_FMT ", errno: %li",
2009  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ), PTR_ERR( device ) );
2010  goto fail;
2011  }
2012  }
2013  #endif
2014 
2015 
2016  #if _USE_LINUX_DEVFS
2017  devfs_mk_cdev( MKDEV( pddev->major, 0 ),
2018  S_IFCHR | S_IRUSR | S_IWUSR, driver_name );
2019  #endif
2020 
2021  drvr_info.n_devs++;
2022 
2023  if ( pddev->irq_stat_info & PCPS_IRQ_STAT_UNSAFE )
2024  mbg_kdd_msg( MBG_LOG_WARN, "*** Warning: %s IRQ support unsafe with FW v" PCPS_FW_STR_FMT " and ASIC v" PCPS_ASIC_STR_FMT,
2025  _pcps_ddev_type_name( pddev ),
2030 
2031  #if NEW_WAIT_QUEUE
2032  init_waitqueue_head( &pddev->wait_queue );
2033  #else
2034  pddev->wait_queue = NULL;
2035  #endif
2036 
2037 #if 0 //##++++++++++
2038  pddev->remove_lock = ATOMIC_INIT( 0 );
2039  pddev->access_in_progress = ATOMIC_INIT( 0 );
2040  pddev->data_avail = ATOMIC_INIT( 0 );
2041 #endif
2042 
2043  #if _PCPS_USE_USB
2044  _sema_init_pddev( &pddev->sem_usb_cyclic, 1, "sem_usb_cyclic", __func__, pddev );
2045  #endif
2046 
2047  if ( default_fast_hr_time_pddev == NULL )
2048  if ( _pcps_ddev_has_fast_hr_timestamp( pddev ) )
2049  {
2050  default_fast_hr_time_pddev = pddev;
2051  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Made " MBG_DEV_NAME_FMT " the default device for MM access",
2052  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
2053  }
2054 
2055  if ( default_ucap_pddev == NULL )
2056  if ( _pcps_ddev_has_ucap( pddev ) )
2057  {
2058  default_ucap_pddev = pddev;
2059  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Made " MBG_DEV_NAME_FMT " the default device for user capture support",
2060  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
2061  }
2062 
2064  return 0;
2065 
2066 fail:
2068  return -1; // TODO
2069 
2070 } // mbgdrvr_create_device
2071 
2072 
2073 
2074 // Applying the _devexit attribute to the function below causes a linker warning
2075 // since the function could also be called from outside the exit section.
2076 
2077 static /*HDR*/
2078 void mbgdrvr_delete_device( PCPS_DDEV *pddev )
2079 {
2081 
2082  if ( pddev )
2083  {
2084  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Going to delete device " MBG_DEV_NAME_FMT,
2085  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
2086 
2087  if ( pddev == default_fast_hr_time_pddev )
2088  {
2089  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Removing " MBG_DEV_NAME_FMT " as default device for MM access",
2090  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
2091  default_fast_hr_time_pddev = NULL;
2092  }
2093 
2094  if ( pddev == default_ucap_pddev )
2095  {
2096  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Removing " MBG_DEV_NAME_FMT " as default device for ucap events",
2097  _pcps_ddev_type_name( pddev ), _pcps_ddev_sernum( pddev ) );
2098  default_ucap_pddev = NULL;
2099  }
2100 
2101  #if _USE_LINUX_DEVFS
2102  //##++ devfs_mk_cdev( MKDEV( pddev->major, 0 ),
2103  // S_IFCHR | S_IRUSR | S_IWUSR, driver_name );
2104  #endif
2105 
2106  cdev_del( &pddev->cdev );
2107 
2108  #if _PCPS_HAVE_LINUX_CLASS
2109  if ( !IS_ERR( mbgclock_class ) )
2110  {
2111  #if _PCPS_CLASS_DEV_OBSOLETED
2112  device_destroy( mbgclock_class, pddev->lx_dev );
2113  #elif _PCPS_HAVE_LINUX_CLASS_CREATE
2114  class_device_destroy( mbgclock_class, pddev->lx_dev );
2115  #elif _PCPS_HAVE_LINUX_CLASS_SIMPLE
2116  class_simple_device_remove( pddev->lx_dev );
2117  #endif
2118 
2119  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Destroyed class device %d:%d",
2120  MAJOR( pddev->lx_dev ), MINOR( pddev->lx_dev ) );
2121  }
2122  #endif
2123 
2124  pcps_cleanup_device( pddev );
2125  pcps_cleanup_ddev( pddev );
2126 
2127  ddev_list_remove_entry( pddev );
2128 
2129  if ( drvr_info.n_devs )
2130  drvr_info.n_devs--;
2131  }
2132  else
2133  _mbgddmsg_0( DEBUG_DRVR, MBG_LOG_INFO, "Unable to delete device: device pointer is NULL" );
2134 
2136 
2137 } // mbgdrvr_delete_device
2138 
2139 
2140 
2141 #if _PCPS_USE_ISA && !_PCPS_USE_ISA_PNP //##++ this needs cleanup
2142 
2143 static /*HDR*/
2144 int __devinit mbgdrvr_add_isa_device( PCPS_DDEV *pddev )
2145 {
2146  int rc = mbgdrvr_create_device( pddev );
2147 
2148  if ( rc >= 0 )
2149  set_dev_connected( pddev, 1 );
2150 
2151  return rc;
2152 
2153 } // mbgdrvr_add_isa_device
2154 
2155 #endif
2156 
2157 
2158 
2159 static /*HDR*/
2160 int __devinit mbgclock_probe_pci_device( struct pci_dev *pci_dev,
2161  const struct pci_device_id *ent )
2162 {
2163  PCPS_DDEV *pddev = NULL;
2164  int rc;
2165  int i;
2166 
2168 
2169  rc = pci_enable_device( pci_dev );
2170 
2171  if ( rc )
2172  {
2173  mbg_kdd_msg( MBG_LOG_ERR, "Failed to enable PCI device %04X, I/O %04lX: rc = %i",
2174  pci_dev->device, (ulong) pci_resource_start( pci_dev, 0 ), rc );
2175  goto fail;
2176  }
2177 
2178  // Get address of unused driver device structure.
2179  rc = pcps_init_ddev( &pddev );
2180 
2181  if ( mbg_rc_is_error( rc ) )
2182  {
2183  rc = -ENOMEM;
2184  goto fail;
2185  }
2186 
2187  rc = pcps_setup_ddev( pddev, PCPS_BUS_PCI, pci_dev->device );
2188 
2189  if ( mbg_rc_is_error( rc ) )
2190  {
2191  rc = -ENODEV;
2192  goto fail;
2193  }
2194 
2195  for ( i = 0; i < 5; i++ )
2196  {
2197  ulong flags = pci_resource_flags( pci_dev, i );
2198 
2199  if ( flags & IORESOURCE_IO )
2200  pcps_add_rsrc_io( pddev, pci_resource_start( pci_dev, i ), pci_resource_len( pci_dev, i ) );
2201  else
2202  if ( flags & IORESOURCE_MEM )
2203  pcps_add_rsrc_mem( pddev, pci_resource_start( pci_dev, i ), pci_resource_len( pci_dev, i ) );
2204  }
2205 
2206  pcps_add_rsrc_irq( pddev, pci_dev->irq );
2207 
2208  rc = pcps_probe_device( pddev, pci_dev->bus->number, pci_dev->devfn );
2209 
2210  if ( mbg_rc_is_error( rc ) )
2211  {
2212  rc = -EIO;
2213  goto fail;
2214  }
2215 
2216  pci_set_drvdata( pci_dev, pddev );
2217 
2218  rc = mbgdrvr_create_device( pddev );
2219 
2220  if ( rc < 0 )
2221  goto fail;
2222 
2223 
2224  set_dev_connected( pddev, 1 );
2225 
2227 
2228  return 0;
2229 
2230 fail:
2231  if ( pddev )
2232  pcps_cleanup_ddev( pddev );
2233 
2235  return rc;
2236 
2237 } // mbgclock_probe_pci_device
2238 
2239 
2240 
2241 static /*HDR*/
2242 void __devexit mbgclock_remove_pci_device( struct pci_dev *pci_dev )
2243 {
2244  PCPS_DDEV *pddev = (PCPS_DDEV *) pci_get_drvdata( pci_dev );
2245 
2246  _mbgddmsg_1( DEBUG_DRVR, MBG_LOG_INFO, "Removing PCI device %04X",
2247  pci_dev->device );
2248 
2249  set_dev_connected( pddev, 0 );
2250 
2251  mbgdrvr_delete_device( pddev );
2252 
2253  pci_set_drvdata( pci_dev, NULL );
2254 
2255 } // mbgclock_remove_pci_device
2256 
2257 
2258 
2259 static struct pci_device_id mbgclock_pci_tbl[] __devinitdata =
2260 {
2261  { PCI_VENDOR_MEINBERG, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID },
2262  { 0 }
2263 };
2264 
2265 MODULE_DEVICE_TABLE( pci, mbgclock_pci_tbl );
2266 
2267 static struct pci_driver mbgclock_pci_driver =
2268 {
2269  name: MBG_DRVR_NAME,
2270  id_table: mbgclock_pci_tbl,
2271  probe: mbgclock_probe_pci_device,
2272  remove: __devexit_p( mbgclock_remove_pci_device )
2273 };
2274 
2275 #endif // _PCPS_USE_PCI_PNP
2276 
2277 
2278 
2279 #if _PCPS_USE_USB
2280 
2281 static /*HDR*/
2282 int __devinit mbgclock_probe_usb_device( struct usb_interface *pintf,
2283  const struct usb_device_id *ent )
2284 {
2285  PCPS_DDEV **ppddev = NULL;
2286  PCPS_DDEV *pddev = NULL;
2287  PCPS_DEV_ID dev_id;
2288  int rc;
2289  struct usb_device *usb_device;
2290 
2292 
2293  if ( _down_interruptible( &sem_fops, "sem_fops", __func__, pintf ) < 0 )
2294  {
2295  rc = -ERESTARTSYS;
2296  goto fail;
2297  }
2298 
2299  usb_device = interface_to_usbdev( pintf );
2300  dev_id = le16_to_cpu( usb_device->descriptor.idProduct );
2301 
2302  // search list if device already exists!
2303 
2304  #if STRUCT_USB_DEVICE_HAS_SERIAL
2305  ppddev = ddev_list_locate_device( PCPS_BUS_USB, dev_id, usb_device->serial );
2306  #elif STRUCT_USB_DEVICE_HAS_STATIC_SERIAL
2307  ppddev = ddev_list_locate_device( PCPS_BUS_USB, dev_id, usb_device->static_serial );
2308  #else
2309  if ( usb_device->descriptor.iSerialNumber )
2310  {
2311  char buf[128];
2312 
2313  if ( usb_string( usb_device, usb_device->descriptor.iSerialNumber, buf, sizeof( buf ) ) > 0 )
2314  ppddev = ddev_list_locate_device( PCPS_BUS_USB, dev_id, buf );
2315  }
2316  #endif
2317 
2318  if ( ppddev )
2319  pddev = *ppddev;
2320  else
2321  {
2322  rc = pcps_init_ddev( &pddev );
2323 
2324  if ( mbg_rc_is_error( rc ) )
2325  {
2326  rc = -ENOMEM;
2327  goto fail_free_up_sem_fops;
2328  }
2329  }
2330 
2331  pddev->udev = usb_device;
2332 
2333  rc = pcps_setup_ddev( pddev, PCPS_BUS_USB, dev_id );
2334 
2335  if ( mbg_rc_is_error( rc ) )
2336  {
2337  rc = -ENODEV;
2338  goto fail_free_up_sem_fops;
2339  }
2340 
2341  pddev->intf = pintf;
2342 
2343  usb_set_intfdata( pintf, pddev );
2344  _mbgddmsg_0( DEBUG_DRVR, MBG_LOG_INFO, "Called usb_set_intfdata()" );
2345 
2346  // no resources to add
2347 
2348  rc = pcps_probe_device( pddev, 0, 0 );
2349 
2350  if ( mbg_rc_is_error( rc ) )
2351  {
2352  rc = -EIO;
2353  goto fail_free_up_sem_fops;
2354  }
2355 
2356  set_dev_connected( pddev, 1 );
2357 
2358  if ( ppddev == NULL ) // device did not exist before
2359  {
2360  rc = mbgdrvr_create_device( pddev );
2361 
2362  if ( rc < 0 )
2363  goto fail_free_up_sem_fops;
2364  }
2365 
2366  // If the device has been "recycled" and is still opened
2367  // by an application then we re-enable cyclic interrupts
2368  if ( atomic_read( &pddev->open_count ) )
2369  mbgdrvr_enable_cyclic( pddev, 1 );
2370 
2371  _up_pddev( &sem_fops, "sem_fops", __func__, pddev );
2372 
2374 
2375  return 0;
2376 
2377 fail_free_up_sem_fops:
2378  if ( pddev )
2379  pcps_cleanup_ddev( pddev );
2380 
2381  _mbgddmsg_fnc_exit_str( "via fail_free_up_sem_fops" );
2382  _up_pddev( &sem_fops, "sem_fops", __func__, NULL );
2383 
2384 fail:
2386  return rc;
2387 
2388 } // mbgclock_probe_usb_device
2389 
2390 
2391 
2392 static /*HDR*/
2393 void __devexit mbgclock_remove_usb_device( struct usb_interface *intf )
2394 {
2395  PCPS_DDEV *pddev = (PCPS_DDEV *) usb_get_intfdata( intf );
2396 
2398 
2399  set_dev_connected( pddev, 0 );
2400 
2401  _down( &sem_fops, "sem_fops", __func__, NULL );
2402 
2403  if ( atomic_read( &pddev->open_count ) )
2404  {
2405  _mbgddmsg_0( DEBUG_DRVR, MBG_LOG_INFO, "USB remove: calling wake_up_interruptible" );
2406  wake_up_interruptible( &pddev->wait_queue );
2407  }
2408 
2409  if ( atomic_read( &pddev->open_count) == 0 )
2410  {
2411  _mbgddmsg_0( DEBUG_DRVR, MBG_LOG_INFO, "USB remove: wait for outstanding requests" );
2412  _down( &pddev->dev_mutex, "dev_mutex", __func__, NULL );
2413 
2414  _mbgddmsg_0( DEBUG_DRVR, MBG_LOG_INFO, "USB remove: delete USB device" );
2415  mbgdrvr_delete_device( pddev );
2416  usb_set_intfdata( intf, NULL );
2417  }
2418 
2420 
2421  _up( &sem_fops, "sem_fops", "remove_usb_device", NULL );
2422 
2423 } // mbgclock_remove_usb_device
2424 
2425 
2426 
2427 static struct usb_device_id mbgclock_usb_tbl[] __devinitdata =
2428 {
2429  // A wildcard product ID for USB devices does not seem to be supported
2430  // by the kernel, so we have to specify each supported device explicitly:
2431  { USB_DEVICE( USB_VENDOR_MEINBERG, USB_DEV_USB5131 ) },
2432  { USB_DEVICE( USB_VENDOR_MEINBERG, USB_DEV_TCR51USB ) },
2433  { USB_DEVICE( USB_VENDOR_MEINBERG, USB_DEV_MSF51USB ) },
2434  { USB_DEVICE( USB_VENDOR_MEINBERG, USB_DEV_WWVB51USB ) },
2435  { USB_DEVICE( USB_VENDOR_MEINBERG, USB_DEV_DCF600USB ) },
2436  { USB_DEVICE( USB_VENDOR_MEINBERG, USB_DEV_TCR600USB ) },
2437  { USB_DEVICE( USB_VENDOR_MEINBERG, USB_DEV_MSF600USB ) },
2438  { USB_DEVICE( USB_VENDOR_MEINBERG, USB_DEV_WVB600USB ) },
2439  { USB_DEVICE( USB_VENDOR_MEINBERG, USB_DEV_TCR180USB ) },
2440  { 0 }
2441 };
2442 
2443 MODULE_DEVICE_TABLE( usb, mbgclock_usb_tbl );
2444 
2445 static struct usb_driver mbgclock_usb_driver =
2446 {
2447  name: MBG_DRVR_NAME,
2448  id_table: mbgclock_usb_tbl,
2449  probe: mbgclock_probe_usb_device,
2450  disconnect: mbgclock_remove_usb_device
2451 };
2452 
2453 #endif // _PCPS_USE_USB
2454 
2455 
2456 
2457 #ifdef MODULE
2458 
2459 // Applying the _exit attribute to the function below causes a linker warning
2460 // since the function could also be called from the module init function.
2461 
2462  /*HDR*/
2463 void mbgclock_cleanup_module( void )
2464 {
2465  int i;
2466 
2468 
2469  #if _PCPS_USE_PNP
2470  #if _PCPS_USE_PCI_PNP
2471  pci_unregister_driver( &mbgclock_pci_driver );
2472  _mbgddmsg_0( DEBUG_DRVR, MBG_LOG_INFO, "PCI driver has been unregistered" );
2473  #endif
2474 
2475  #if _PCPS_USE_USB
2476  usb_deregister( &mbgclock_usb_driver );
2477  _mbgddmsg_0( DEBUG_DRVR, MBG_LOG_INFO, "USB driver has been unregistered" );
2478  #endif
2479  #endif
2480 
2481  // Stop and remove all devices which are still active (maybe ISA cards)
2482  for ( i = 0; i < max_devs; i++ )
2483  {
2484  PCPS_DDEV **ppddev = &ddev_list[i];
2485 
2486  if ( *ppddev )
2487  {
2488  _mbgddmsg_2( DEBUG_DRVR, MBG_LOG_INFO, "Removing device %s, S/N %s",
2489  _pcps_ddev_type_name( *ppddev ), _pcps_ddev_sernum( *ppddev ) );
2490  mbgdrvr_delete_device( *ppddev );
2491  }
2492  }
2493 
2494  unregister_chrdev_region( MKDEV( major, minor ), max_devs );
2495  _mbgddmsg_0( DEBUG_DRVR, MBG_LOG_INFO, "chrdev device numbers have been unregistered" );
2496  ddev_list_free();
2497 
2498  #if _PCPS_HAVE_LINUX_CLASS
2499  if ( !IS_ERR( mbgclock_class ) )
2500  {
2501  #if _PCPS_HAVE_LINUX_CLASS_CREATE
2502  class_destroy( mbgclock_class );
2503  #elif _PCPS_HAVE_LINUX_CLASS_SIMPLE
2504  class_simple_destroy( mbgclock_class );
2505  #endif
2506 
2507  _mbgddmsg_1( DEBUG_DRVR, MBG_LOG_INFO, "Class %s destroyed", mbgclock_class_name );
2508  }
2509  #endif
2510 
2511  mbg_kdd_msg( MBG_LOG_INFO, "Meinberg radio clock driver unloading." );
2512 
2514 
2515 } // mbgclock_cleanup_module
2516 
2517 #endif
2518 
2519 
2520 
2521  /*HDR*/
2522 int __init mbgclock_init_module( void )
2523 {
2524  dev_t dev;
2525  int rc = 0;
2526 
2527  #if _PCPS_USE_PCI_PNP
2528  static const char info[] = ""; // PnP is common, so don't explicitly mention it.
2529  #else
2530  static const char info[] = " (non-PNP)";
2531  #endif
2532 
2533  #ifdef EXPORT_NO_SYMBOLS
2534  EXPORT_NO_SYMBOLS;
2535  #endif
2536 
2537  #ifdef DEBUG
2538  debug = DEBUG;
2539  #endif
2540 
2542 
2543  mbg_kdd_msg( MBG_LOG_INFO, "Meinberg radio clock driver v%u.%u.%u%s loading.",
2545  MBG_MICRO_VERSION_CODE, info );
2546 
2548 
2549  #if _DEFAULT_PCPS_USE_MM_IO
2550  #if _PCPS_USE_MM_IO
2551  if ( force_io_access )
2552  mbg_kdd_msg( MBG_LOG_WARN, "Forcing I/O access by command line parameter" );
2553 
2554  if ( force_mm16_access )
2555  mbg_kdd_msg( MBG_LOG_WARN, "Forcing 16 bit memory mapped access by command line parameter" );
2556  #else
2557  mbg_kdd_msg( MBG_LOG_WARN, "Memory mapped access disabled by build option" );
2558  #endif
2559  #endif
2560 
2561  #ifdef DEBUG
2562  mbg_kdd_msg( MBG_LOG_INFO, "Debug level = %i", debug );
2563  #endif
2564 
2565  #if DEBUG_MSG_SLEEP
2566  mbg_kdd_msg( MBG_LOG_WARN, "Sleeping for %i ms after each debug message",
2567  debug_msg_sleep );
2568  #endif
2569 
2570  #if DEBUG_SYS_IRQS
2571  list_system_irqs();
2572  #endif
2573 
2574  _sema_init_pddev( &sem_fops, 1, "sem_fops", __func__, NULL );
2575 
2576  // Note: In early 2.6.x kernels the functions alloc_chrdev_region()
2577  // and register_chrdev_region() expected (char *) rather than
2578  // (const char *) for the device name. Thus we cast driver_name
2579  // to (char *) below in order to avoid compiler warnings.
2580 
2581  if ( major ) //##++ != DYNAMIC_MAJOR ?
2582  {
2583  dev = MKDEV( major, minor );
2584  rc = register_chrdev_region( dev, max_devs, (char *) driver_name ); // see note above
2585 
2586  if ( rc < 0 )
2587  {
2588  mbg_kdd_msg( MBG_LOG_WARN, "Failed to register major %d", major );
2589  goto fail;
2590  }
2591  }
2592  else
2593  {
2594  rc = alloc_chrdev_region( &dev, minor, max_devs, (char *) driver_name ); // see note above
2595 
2596  if ( rc < 0 )
2597  {
2598  mbg_kdd_msg( MBG_LOG_WARN, "Failed to allocate dynamic major %d", major );
2599  goto fail;
2600  }
2601 
2602  major = MAJOR( dev );
2603  }
2604 
2605  _mbgddmsg_1( DEBUG_DRVR, MBG_LOG_INFO, "Successfully registered chrdev, major %d", major );
2606 
2607  #if _PCPS_HAVE_LINUX_CLASS
2608  #if _PCPS_HAVE_LINUX_CLASS_CREATE
2609  mbgclock_class = class_create( THIS_MODULE, mbgclock_class_name );
2610  #elif _PCPS_HAVE_LINUX_CLASS_SIMPLE
2611  mbgclock_class = class_simple_create( THIS_MODULE, mbgclock_class_name );
2612  #endif
2613 
2614  if ( !IS_ERR( mbgclock_class ) )
2615  {
2616  _mbgddmsg_1( DEBUG_DRVR, MBG_LOG_INFO, "Class %s created successfully",
2617  mbgclock_class_name );
2618  }
2619  else
2620  mbg_kdd_msg( MBG_LOG_WARN, "Failed to create class %s, no UDEV support",
2621  mbgclock_class_name );
2622  #endif
2623 
2624  rc = ddev_list_alloc();
2625 
2626  if ( rc < 0 )
2627  {
2628  mbg_kdd_msg( MBG_LOG_WARN, "failed to allocate device list" );
2629 
2630  goto fail_with_cleanup;
2631  }
2632 
2633  #if _USE_LINUX_DEVFS
2634  #error devfs support needs cleanup!!
2635  devfs_mk_cdev( MKDEV( pddev->major, 0 ),
2636  S_IFCHR | S_IRUSR | S_IWUSR, driver_name );
2637  #endif
2638 
2639  #if _PCPS_USE_PNP
2640  #if _PCPS_USE_ISA && !_PCPS_USE_ISA_PNP //##++ this needs cleanup
2641  pcps_detect_isa_devices( pcps_init_ddev, pcps_cleanup_ddev, mbgdrvr_add_isa_device, io, irq );
2642  #endif
2643 
2644  #if _PCPS_USE_PCI_PNP
2645  rc = pci_register_driver( &mbgclock_pci_driver );
2646 
2647  _mbgddmsg_1( DEBUG_DRVR, MBG_LOG_INFO, "Done registering PCI devices, rc: %d", rc );
2648  #endif // _PCPS_USE_PCI_PNP
2649 
2650  #if _PCPS_USE_USB //##++
2651  rc = usb_register( &mbgclock_usb_driver );
2652 
2653  _mbgddmsg_1( DEBUG_DRVR, MBG_LOG_INFO, "Done registering USB devices, rc: %d", rc );
2654  #endif // _PCPS_USE_USB
2655 
2656  #else
2658  #endif
2659 
2660 
2661  if ( drvr_info.n_devs == 0 )
2662  {
2663  mbg_kdd_msg( MBG_LOG_INFO, "No supported device found." );
2664  rc = -ENODEV;
2665  goto fail_with_cleanup;
2666  }
2667 
2668  if ( pretend_sync )
2669  mbg_kdd_msg( MBG_LOG_INFO, "Pretending to NTP to be always sync'ed" );
2670 
2672  return 0;
2673 
2674 
2675 fail_with_cleanup:
2676  mbgclock_cleanup_module();
2677 
2678 fail:
2680  return rc;
2681 
2682 } // mbgclock_init_module
2683 
2684 
2685 
2686 #ifdef module_init
2687  module_init( mbgclock_init_module );
2688  module_exit( mbgclock_cleanup_module );
2689 #endif
2690 
2691 
2692 
2693 /*HDR*/
2709 {
2710  if ( default_fast_hr_time_pddev == NULL )
2711  return MBG_ERR_NOT_SUPP_BY_DEV;
2712 
2714 
2715  do_get_fast_hr_timestamp_safe( default_fast_hr_time_pddev, p_ts );
2716 
2717  _mbg_swab_pcps_time_stamp( p_ts );
2718 
2720 
2721  return MBG_SUCCESS;
2722 
2723 } // mbgclock_default_get_fast_hr_timestamp
2724 
2726 
2727 
2728 
2729 /*HDR*/
2746 {
2747  if ( default_fast_hr_time_pddev == NULL )
2748  return MBG_ERR_NOT_SUPP_BY_DEV;
2749 
2751 
2752  do_get_fast_hr_timestamp_cycles_safe( default_fast_hr_time_pddev, p_ts_cyc );
2753 
2755 
2757 
2758  return MBG_SUCCESS;
2759 
2760 } // mbgclock_default_get_fast_hr_timestamp_cycles
2761 
2763 
2764 
2765 
2766 /*HDR*/
2782 {
2783  int rc;
2784 
2785  if ( default_ucap_pddev == NULL )
2786  return MBG_ERR_NOT_SUPP_BY_DEV;
2787 
2789 
2790  _pcps_sem_inc_safe( default_ucap_pddev );
2791  rc = _pcps_write_byte( default_ucap_pddev, PCPS_CLR_UCAP_BUFF );
2792  _pcps_sem_dec( default_ucap_pddev );
2793 
2795  return rc;
2796 
2797 err_busy_irq_unsafe:
2799  return MBG_ERR_IRQ_UNSAFE;
2800 
2801 } // mbgclock_default_clr_ucap_buff
2802 
2804 
2805 
2806 
2807 /*HDR*/
2824 {
2825  int rc;
2826 
2827  if ( default_ucap_pddev == NULL )
2828  return MBG_ERR_NOT_SUPP_BY_DEV;
2829 
2831 
2832  _pcps_sem_inc_safe( default_ucap_pddev );
2833  rc = _pcps_read_var( default_ucap_pddev, PCPS_GIVE_UCAP_ENTRIES, *p );
2834  _pcps_sem_dec( default_ucap_pddev );
2835 
2837 
2838  _mbgddmsg_4( DEBUG, MBG_LOG_INFO, MBG_LOG_FMT_LEAVING ": %u/%u, rc: %i",
2839  __func__, p->used, p->max, rc );
2840  return rc;
2841 
2842 err_busy_irq_unsafe:
2844  return MBG_ERR_IRQ_UNSAFE;
2845 
2846 } // mbgclock_default_get_ucap_entries
2847 
2849 
2850 
2851 
2852 /*HDR*/
2872 {
2873  int rc;
2874 
2875  if ( default_ucap_pddev == NULL )
2876  return MBG_ERR_NOT_SUPP_BY_DEV;
2877 
2879 
2880  _pcps_sem_inc_safe( default_ucap_pddev );
2881  rc = _pcps_read_var( default_ucap_pddev, PCPS_GIVE_UCAP_EVENT, *p );
2882  _pcps_sem_dec( default_ucap_pddev );
2883 
2885 
2886  _mbgddmsg_4( DEBUG, MBG_LOG_INFO, MBG_LOG_FMT_LEAVING ": %08lX.%08lX, rc: %i",
2887  __func__, (ulong) p->tstamp.sec, (ulong) p->tstamp.frac, rc );
2888  return rc;
2889 
2890 err_busy_irq_unsafe:
2892  return MBG_ERR_IRQ_UNSAFE;
2893 
2894 } // mbgclock_default_get_ucap_event
2895 
2897 
2898 
2899 
2900 #if defined( DEBUG )
2901 
2902 // In a debug build we define a few function pointer variables
2903 // just to verify the declaration of the function pointer types
2904 // match the associated function prototypes.
2905 
2908 
2912 
2913 #endif
2914 
2915 
2916 #if !MBG_PC_CYCLES_SUPPORTED
2917  #warning No cycles support to compute latencies on this platform.
2918 #endif
2919 
2920 #if OMIT_PRIV_CHECKING
2921  #warning IOCTL privilege checking is omitted on your own risk!
2922 #endif
#define USB_DEV_WWVB51USB
Definition: usbdefs.h:228
#define _usb_read_thread_started(_pddev)
#define _pcps_ddev_sernum(_p)
Definition: pcpsdrvr.h:1186
invalid time because battery had been disconnected, or absolute time can&#39;t be decoded safely ...
Definition: pcpsdefs.h:1261
#define PCPS_IRQ_STAT_ENABLE_CALLED
Definition: pcpsdev.h:1471
static irqreturn_t mbgclock_irq_handler(int hw_irq, void *arg, struct pt_regs *regs)
static void mbgdrvr_delete_device(PCPS_DDEV *pddev)
PCPS_RSRC_INFO rsrc_info
Summary of resources used by the device.
Definition: pcpsdrvr.h:797
uint8_t year
year of the century, 0..99
Definition: pcpsdefs.h:1138
#define _up(_s, _sn, _fn, _fp)
Definition: lx-shared.h:202
uint16_t MBG_DBG_PORT
Definition: pcpsdev.h:370
#define _pcps_sem_dec(_pddev)
Definition: pcpsdrvr.h:575
#define _pcps_fw_rev_num_minor(_v)
Definition: pcpsdev.h:1486
int force_mm16_access
MBGCLOCK_DEFAULT_GET_FAST_HR_TIMESTAMP_FNC get_fast_hr_timestamp_fnc
const char * mbgioctl_get_name(long code)
#define _pcps_ddev_disb_irq(_d)
Definition: pcpsirq.h:242
#define __devinit
Definition: mbg_lx.h:98
#define _pcps_fw_rev_num_major(_v)
Definition: pcpsdev.h:1483
uint32_t used
the number of saved capture events
Definition: pcpsdefs.h:1531
#define _mbgddmsg_fnc_entry()
Definition: mbgddmsg.h:399
#define _mbg_kdd_msg_4(_lvl, _fmt, _p1, _p2, _p3, _p4)
Definition: mbgddmsg.h:245
struct fasync_struct * fasyncptr
Used for asynchronous signalling when data is available.
Definition: pcpsdrvr.h:867
#define _pcps_ddev_is_usb(_p)
Definition: pcpsdrvr.h:1154
#define MBG_MICRO_VERSION_CODE
Definition: mbgversion.h:58
static int minor
uint8_t cmd
In case of small data we just need one of the PCPS_CMD_CODES.
Definition: pcpsdrvr.h:838
uint8_t mday
day of month, 0..31
Definition: pcpsdefs.h:1135
#define PCPS_IRQ_STAT_UNSAFE
Definition: pcpsdev.h:1473
uint8_t sec100
hundredths of seconds, 0..99, 10 ms resolution
Definition: pcpsdefs.h:1130
#define _pcps_asic_version_major(_v)
Extract the major part of an ASIC version number.
Definition: pci_asic.h:339
int mbgclock_default_get_ucap_entries(PCPS_UCAP_ENTRIES *p)
Read user capture FIFO information.
#define _mbgddmsg_3(_f, _lvl, _fmt, _p1, _p2, _p3)
Definition: mbgddmsg.h:330
PCPS_TIME t
Date and time read by IRQ handler.
Definition: pcpsdrvr.h:868
int mbgclock_default_get_fast_hr_timestamp(PCPS_TIME_STAMP *p_ts)
Read a high resolution PCPS_TIME_STAMP structure via memory mapped access.
#define USB_DEV_TCR600USB
Definition: usbdefs.h:221
static int mbgclock_flush(struct file *filp)
PCPS_IRQ_STAT_INFO irq_stat_info
Definition: pcpsdrvr.h:820
#define PCPS_CLR_UCAP_BUFF
(-w) No param., clear on-board capture FIFO, only if _pcps_has_ucap
Definition: pcpsdefs.h:768
MBGCLOCK_DEFAULT_GET_UCAP_EVENT_FNC get_ucap_event_fnc
unsigned long jiffies_at_irq
Set by IRQ handler, used to check if cyclic IRQs still occur.
Definition: pcpsdrvr.h:866
static PCPS_DDEV ** ddev_list_locate_minor(unsigned int minor)
static int mbgdrvr_enable_cyclic(PCPS_DDEV *pddev, unsigned int force)
static int ddev_list_alloc(void)
#define _down_interruptible_pddev(_s, _sn, _fn, _fp)
Definition: lx-shared.h:197
ulong MBG_IOPORT_ADDR_MAPPED
Definition: mbggenio.h:187
static int mbgclock_ioctl(struct inode *not_used, struct file *filp, unsigned int cmd, unsigned long arg)
#define PCI_VENDOR_MEINBERG
Definition: pcidefs.h:240
#define PCPS_IRQ_1_SEC
(-w) Enable IRQ per 1 second
Definition: pcpsdefs.h:723
static PCPS_DDEV * default_fast_hr_time_pddev
#define _sema_init_pddev(_s, _n, _sn, _fn, _fp)
Definition: lx-shared.h:196
PCPS_SECONDS sec
seconds since 1970, usually UTC scale
Definition: pcpsdefs.h:974
#define _mbgddmsg_fnc_exit_str(_s)
Definition: mbgddmsg.h:411
#define _mbg_swab_pcps_time_stamp_cycles(_p)
Definition: pcpsdev.h:1376
#define _usb_read_thread_failed_to_start(_pddev)
#define MBG_DEV_NAME_FMT
A string format specifier for MBG_DEV_NAME.
Definition: pcpsdev.h:1534
#define MBG_MAIN_VERSION_CODE
Definition: mbgversion.h:80
#define _mbgddmsg_6(_f, _lvl, _fmt, _p1, _p2, _p3, _p4, _p5, _p6)
Definition: mbgddmsg.h:348
#define DEBUG_DRVR
Definition: pcpsdrvr.h:414
#define _mbgddmsg_fnc_exit_success()
Definition: mbgddmsg.h:415
static PCPS_DDEV * default_ucap_pddev
#define _kill_fasync(_fa, _sig, _band)
#define _usb_read_thread_should_stop()
#define DEBUG_IOCTL
Definition: pcpsdrvr.h:426
void pcps_cleanup_ddev(PCPS_DDEV *pddev)
Clean up and free a previously initialized device info structure.
Definition: pcpsdrvr.c:4845
#define _mbgddmsg_0(_f, _lvl, _fmt)
Definition: mbgddmsg.h:312
int pcps_init_ddev(PCPS_DDEV **ppddev)
Allocate and initialize a device info structure.
Definition: pcpsdrvr.c:4799
#define mbg_rc_is_success(_rc)
Definition: mbgerror.h:618
#define IRQ_NONE
Definition: mbg_lx.h:261
#define _mbg_dbg_hw_lpt_clr_bit(_b)
static int ddev_list_alloc_size
#define _pcps_ddev_fw_rev_num(_p)
Definition: pcpsdrvr.h:1183
void mbg_kdd_msg(int lvl, const char *fmt,...)
#define _mbg_dbg_hw_lpt_vars
MBGCLOCK_DEFAULT_GET_UCAP_ENTRIES_FNC get_ucap_entries_fnc
#define PCPS_ASIC_STR_FMT
Definition: pci_asic.h:334
#define PCPS_IRQ_NONE
(-w) Disable IRQs
Definition: pcpsdefs.h:722
#define _mbgddmsg_5(_f, _lvl, _fmt, _p1, _p2, _p3, _p4, _p5)
Definition: mbgddmsg.h:342
#define _pcps_ddev_enb_irq(_d, _cmd)
Definition: pcpsirq.h:227
__mbg_inline int get_cyclic_lock(PCPS_DDEV *pddev, unsigned long *p_flags, const char *fnc_name)
static int mbgclock_open(struct inode *inode, struct file *filp)
High resolution time stamp plus associated system cycles count.
Definition: pcpsdev.h:1369
Status of the time capture FIFO buffer.
Definition: pcpsdefs.h:1529
int pcps_add_rsrc_mem(PCPS_DDEV *pddev, MBG_IOMEM_ADDR_RAW start, ulong len)
Add a memory address range resource to the device structure.
Definition: pcpsdrvr.c:4959
static __mbg_inline void do_get_fast_hr_timestamp_safe(PCPS_DDEV *pddev, PCPS_TIME_STAMP *p_ts)
Definition: macioctl.h:816
static __mbg_inline void do_get_fast_hr_timestamp_cycles_safe(PCPS_DDEV *pddev, PCPS_TIME_STAMP_CYCLES *p_ts_cyc)
Definition: macioctl.h:844
atomic_t open_count
Number of processes that have opened this device.
Definition: pcpsdrvr.h:876
#define MBG_MINOR_VERSION_CODE
Definition: mbgversion.h:57
#define _mbgddmsg_fnc_exit_err_dec(_errnum)
Definition: mbgddmsg.h:428
int pretend_sync
#define __devexit_p(_x)
Definition: mbg_lx.h:114
static PCPS_DDEV ** ddev_list_locate_device(PCPS_BUS_FLAGS bus_flags, PCPS_DEV_ID dev_id, PCPS_SN_STR sernum)
#define _PCPS_DEVICE_CREATE_WITH_DEV_DATA
Definition: mbg_lx.h:295
static __mbg_inline int ioctl_switch(PCPS_DDEV *pddev, unsigned int ioctl_code, void *pin, void *pout)
Decode and handle IOCTL commands.
Definition: macioctl.h:904
#define PCPS_GIVE_UCAP_ENTRIES
(r-) Read PCPS_UCAP_ENTRIES, only if _pcps_has_ucap
Definition: pcpsdefs.h:769
#define _mbgddmsg_1(_f, _lvl, _fmt, _p1)
Definition: mbgddmsg.h:318
uint16_t n_devs
the number of devices handled by the driver
Definition: pcpsdev.h:1333
MBGCLOCK_DEFAULT_GET_FAST_HR_TIMESTAMP_CYCLES_FNC get_fast_hr_timestamp_cycles_fnc
#define _pcps_sem_inc_safe(_pddev)
Definition: macioctl.h:409
#define MBG_ERR_IRQ_UNSAFE
Enabled IRQ of bus-level device is unsafe with this firmware/ASIC version.
Definition: mbgerror.h:293
#define _mbg_swab_pcps_hr_time(_p)
Definition: pcpsdefs.h:1094
int(* MBGCLOCK_DEFAULT_GET_FAST_HR_TIMESTAMP_FNC)(PCPS_TIME_STAMP *p_ts)
Definition: mbgclock.h:128
#define MBG_ERR_TIMEOUT
Timeout accessing the device.
Definition: mbgerror.h:270
#define USB_DEV_USB5131
Definition: usbdefs.h:214
MBG_IOMEM_RSRC mem[2]
Info on actually assigned memory ranges.
Definition: pcpsdrvr.h:684
int n_ddevs
#define MBG_COPYRIGHT
uint32_t max
capture buffer size
Definition: pcpsdefs.h:1532
uint64_t MBG_IOMEM_ADDR_RAW
Definition: mbggenio.h:175
struct file_operations mbgclock_fops
#define _pcps_read_var(_pddev, _cmd, _s)
Definition: pcpsdrvr.h:1391
#define _pcps_ddev_ack_irq(_d)
Definition: pcpsirq.h:212
#define _mbgddmsg_fnc_exit()
Definition: mbgddmsg.h:407
#define _pcps_ddev_has_gen_irq(_d)
Definition: pcpsirq.h:198
#define _mbg_dbg_hw_lpt_set_bit(_b)
static int irq[PCPS_MAX_ISA_CARDS]
uint16_t PCPS_DEV_ID
Definition: pcpsdev.h:500
#define PCPS_GIVE_UCAP_EVENT
(r-) Return oldest event as PCPS_HR_TIME, only if _pcps_has_ucap
Definition: pcpsdefs.h:770
#define PCPS_GIVE_TIME
Command codes used to communicate with bus level devices.
Definition: pcpsdefs.h:712
static __mbg_inline int ioctl_get_required_privilege(ulong ioctl_code)
Determine the privilege level required to execute a specific IOCTL command.
Definition: mbgioctl.h:973
#define _pcps_ddev_is_isa(_p)
Definition: pcpsdrvr.h:1151
PCPS_FRAC_32 frac
binary fractions of second, see PCPS_FRAC_32
Definition: pcpsdefs.h:975
daylight saving currently enabled
Definition: pcpsdefs.h:1255
void pcps_cleanup_device(PCPS_DDEV *pddev)
Clean up function called by pcps_probe_device on error.
Definition: pcpsdrvr.c:6247
static __mbg_inline int mbgdrvr_get_pddev(PCPS_DDEV **ppddev, struct file *filp, const char *info)
Definition: lx-shared.h:229
static PCPS_DDEV ** ddev_list
uint8_t MBG_DBG_DATA
Definition: pcpsdev.h:369
char PCPS_SN_STR[(16+1)]
A buffer for a serial number string, including terminating 0.
Definition: pcpsdefs.h:925
dev_t lx_dev
Linux device associated with this device.
Definition: pcpsdrvr.h:879
PCPS_TIME_STAMP tstamp
High resolution time stamp (UTC)
Definition: pcpsdefs.h:1087
int(* MBGCLOCK_DEFAULT_GET_UCAP_ENTRIES_FNC)(PCPS_UCAP_ENTRIES *p)
Definition: mbgclock.h:132
int debug
long wave or time code receiver has sync&#39;ed at least once after pwr up, sat receiver is synchronized ...
Definition: pcpsdefs.h:1256
#define _usb_read_thread_start(_fnc, _pddev)
#define _usb_read_thread_exit(_pddev, _v)
#define _up_pddev(_s, _sn, _fn, _fp)
Definition: lx-shared.h:198
static __mbg_inline void set_dev_connected(PCPS_DDEV *pddev, int state)
Definition: lx-shared.h:209
int mbgclock_default_clr_ucap_buff(void)
Clear the on-board user capture FIFO buffer.
#define PCPS_IRQ_STAT_ENABLED
Definition: pcpsdev.h:1472
unsigned char uint8_t
Definition: words.h:210
__int64 int64_t
Definition: words.h:249
static int mbgdrvr_disable_cyclic(PCPS_DDEV *pddev)
PCPS_DRVR_INFO drvr_info
int(* MBGCLOCK_DEFAULT_GET_FAST_HR_TIMESTAMP_CYCLES_FNC)(PCPS_TIME_STAMP_CYCLES *p_ts_cyc)
Definition: mbgclock.h:129
#define USB_DEV_DCF600USB
Definition: usbdefs.h:215
#define _pcps_ddev_irq_num(_p)
Definition: pcpsdrvr.h:1178
#define _usb_read_thread_stop(_pddev)
#define MBG_LOG_FMT_LEAVING
Definition: mbgddmsg.h:387
#define _usb_read_thread_daemonize(_pddev)
#define _pcps_ddev_has_ucap(_p)
Definition: pcpsdrvr.h:1236
static __mbg_inline int get_dev_connected(PCPS_DDEV *pddev)
Definition: lx-shared.h:220
int8_t offs_utc
[hours], 0 if not _pcps_has_utc_offs
Definition: pcpsdefs.h:1142
#define _mbg_swab_pcps_time_stamp(_p)
Definition: pcpsdefs.h:979
int(* MBGCLOCK_DEFAULT_CLR_UCAP_BUFF_FNC)(void)
Definition: mbgclock.h:131
#define IOCTL_PCPS_GENERIC_READ_GPS
Definition: mbgioctl.h:518
PCPS_DDEV pcps_ddev[16]
#define MBG_DRVR_NAME
#define _pcps_kmalloc(_sz)
Definition: pcpsdrvr.h:555
static ssize_t mbgclock_write(struct file *filp, const char *buffer, size_t count, loff_t *ppos)
#define _pcps_ddev_asic_version(_p)
Definition: pcpsdrvr.h:1190
#define MBG_SUCCESS
Error codes used with Meinberg devices and drivers.
Definition: mbgerror.h:259
int force_io_access
#define _mbgddmsg_4(_f, _lvl, _fmt, _p1, _p2, _p3, _p4)
Definition: mbgddmsg.h:336
#define _min(_a, _b)
#define _PCPS_CLASS_DEVICE_CREATE_WITH_PARENT
Definition: mbg_lx.h:289
static int max_devs
#define _pcps_ddev_has_fast_hr_timestamp(_p)
Definition: pcpsdrvr.h:1293
#define _mbgddmsg_2(_f, _lvl, _fmt, _p1, _p2)
Definition: mbgddmsg.h:324
static unsigned int mbgclock_poll(struct file *filp, poll_table *pt)
#define MBGCLOCK_MAX_DEVS
uint8_t hour
hours, 0..23
Definition: pcpsdefs.h:1133
#define PCPS_BUS_USB
USB.
Definition: pcpsdev.h:416
MBGCLOCK_DEFAULT_CLR_UCAP_BUFF_FNC clr_ucap_buff_fnc
static int io[PCPS_MAX_ISA_CARDS]
a change in daylight saving status is announced
Definition: pcpsdefs.h:1257
#define USB_DEV_WVB600USB
Definition: usbdefs.h:229
#define _pcps_kfree(_p, _sz)
Definition: pcpsdrvr.h:556
static ssize_t mbgclock_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
#define IRQ_HANDLED
Definition: mbg_lx.h:262
#define USB_DEV_MSF600USB
Definition: usbdefs.h:226
__mbg_inline void release_cyclic_lock(PCPS_DDEV *pddev, unsigned long *p_flags, const char *fnc_name)
static int ddev_list_remove_entry(PCPS_DDEV *pddev)
int(* MBGCLOCK_DEFAULT_GET_UCAP_EVENT_FNC)(PCPS_HR_TIME *p)
Definition: mbgclock.h:133
#define _pcps_ddev_type_name(_p)
Definition: pcpsdrvr.h:1131
atomic_t access_in_progress
Flag indicating if device access is currently in progress.
Definition: pcpsdrvr.h:864
static void ddev_list_free(void)
#define PCPS_BUS_PCI
PCI.
Definition: pcpsdev.h:415
EXPORT_SYMBOL(mbgclock_default_get_fast_hr_timestamp)
High resolution time including status and local time offset.
Definition: pcpsdefs.h:1085
int pcps_probe_device(PCPS_DDEV *pddev, PCPS_BUS_NUM bus_num, PCPS_SLOT_NUM dev_fnc_num)
Probe if a device is supported, and allocate and setup the device structure.
Definition: pcpsdrvr.c:5409
#define USB_DEV_MSF51USB
Definition: usbdefs.h:225
static int mbgclock_release(struct inode *inode, struct file *filp)
#define _down_interruptible(_s, _sn, _fn, _fp)
Definition: lx-shared.h:200
#define _pcps_write_byte(_pddev, _b)
Definition: pcpsdrvr.h:1358
const char driver_name[]
union PCPS_DDEV_s::@9 cmd_info
static int mbgclock_mmap(struct file *filp, struct vm_area_struct *vma)
#define MBG_SIZE_TLG
int pcps_setup_ddev(PCPS_DDEV *pddev, PCPS_BUS_FLAGS bus_mask, PCPS_DEV_ID dev_id)
Initialize an allocated device structure for a specific device.
static long mbgclock_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
Local calendar date and time, plus sync status.
Definition: pcpsdefs.h:1128
int pcps_add_rsrc_io(PCPS_DDEV *pddev, MBG_IOPORT_ADDR_RAW base, ulong num)
Add an I/O address range resource to the device structure.
Definition: pcpsdrvr.c:4897
#define _pcps_ddev_dev_id(_p)
Definition: pcpsdrvr.h:1132
static void pcps_time_to_time_str(const PCPS_TIME *t, char *s, size_t max_len)
atomic_t data_avail
Flag indicating if data has been made available by IRQ handler.
Definition: pcpsdrvr.h:865
void _MBG_INIT_CODE_ATTR pcps_detect_devices(int isa_ports[PCPS_MAX_ISA_CARDS], int isa_irqs[PCPS_MAX_ISA_CARDS])
Detect all bus-level devices in a non-PnP system.
Definition: pcpsdrvr.c:6683
unsigned long volatile jiffies
A high resolution time stamp.
Definition: pcpsdefs.h:972
#define _pcps_asic_version_minor(_v)
Extract the minor part of an ASIC version number.
Definition: pci_asic.h:346
uint16_t PCPS_BUS_FLAGS
Definition: pcpsdev.h:502
#define _down(_s, _sn, _fn, _fp)
Definition: lx-shared.h:199
#define CYCLIC_TIMEOUT
#define MBG_ERR_NOT_SUPP_BY_DEV
Command or feature not supported by device.
Definition: mbgerror.h:286
void irqreturn_t
Definition: mbg_lx.h:260
#define PCPS_MAX_ISA_CARDS
Definition: pcpsdrvr.h:1071
#define __devexit
Definition: mbg_lx.h:106
static int major
MBG_IOMEM_ADDR_RAW start_raw
A raw I/O memory start address.
Definition: mbggenio.h:278
#define mbg_rc_is_error(_rc)
Definition: mbgerror.h:617
uint8_t min
minutes, 0..59
Definition: pcpsdefs.h:1132
int __init mbgclock_init_module(void)
void pcps_detect_isa_devices(PCPS_DDEV_INIT_FNC *ddev_init_fnc, PCPS_DDEV_CLEANUP_FNC *ddev_cleanup_fnc, PCPS_DDEV_REGISTER_FNC *ddev_register_fnc, int isa_ports[PCPS_MAX_ISA_CARDS], int isa_irqs[PCPS_MAX_ISA_CARDS])
Detect and initialize ISA devices in a non-PnP system.
Definition: pcpsdrvr.c:6559
const char * mbg_strerror(int mbg_errno)
Return an error string associated with the MBG_ERROR_CODES.
Definition: mbgerror.c:685
#define _mbg_swab_pcps_ucap_entries(_p)
Definition: pcpsdefs.h:1536
MBG_MUTEX dev_mutex
Mutex used for device access serialization.
Definition: pcpsdrvr.h:802
Device driver information.
Definition: pcpsdev.h:1330
#define USB_DEV_TCR180USB
Definition: usbdefs.h:223
uint8_t PCPS_TIME_STATUS
Time synchronization status.
Definition: pcpsdefs.h:1112
static struct semaphore sem_fops
struct cdev cdev
Linux device class.
Definition: pcpsdrvr.h:878
#define USB_VENDOR_MEINBERG
Definition: usbdefs.h:131
int pcps_add_rsrc_irq(PCPS_DDEV *pddev, int16_t irq_num)
Add an IRQ number resource to the device structure.
Definition: pcpsdrvr.c:5021
static int mbgclock_fasync(int fd, struct file *filp, int on)
long wave or time code receiver running on xtal, satellite receiver has not verified its position ...
Definition: pcpsdefs.h:1254
unsigned long ulong
Definition: words.h:292
#define USB_DEV_TCR51USB
Definition: usbdefs.h:220
#define MBG_MAJOR_VERSION_CODE
Definition: mbgversion.h:56
int mbgclock_default_get_ucap_event(PCPS_HR_TIME *p)
Retrieve single time capture event.
#define _usb_read_thread_set_unused(_pddev)
#define PCPS_FW_STR_FMT
Definition: pcpsdev.h:1481
struct wait_queue * wait_queue
Used for asynchronous I/O (older kernel API)
Definition: pcpsdrvr.h:873
static int mbgdrvr_ioctl_emu_serial(struct file *filp, unsigned int cmd, unsigned long arg)
uint8_t month
month, 1..12
Definition: pcpsdefs.h:1137
PCPS_TIME_STATUS status
status bits, see PCPS_TIME_STATUS_FLAGS_COMMON
Definition: pcpsdefs.h:1140
int mbgclock_default_get_fast_hr_timestamp_cycles(PCPS_TIME_STAMP_CYCLES *p_ts_cyc)
Read a high resolution PCPS_TIME_STAMP_CYCLES structure via memory mapped access. ...
uint8_t sec
seconds, 0..59, or 60 if leap second
Definition: pcpsdefs.h:1131
leap second announced, for very old clocks see REV_PCPS_LS_ANN_PC31PS31
Definition: pcpsdefs.h:1259
uint8_t wday
day of week, 1..7, 1 = Monday
Definition: pcpsdefs.h:1136
static int ddev_list_add_entry(PCPS_DDEV *pddev)
#define MBG_FULL_VERSION_STR
Definition: mbgversion.h:86
uint32_t u32
Definition: lan_util.c:100