diff options
Diffstat (limited to 'mbglib/common/pcpsdrvr.c')
-rwxr-xr-x | mbglib/common/pcpsdrvr.c | 345 |
1 files changed, 203 insertions, 142 deletions
diff --git a/mbglib/common/pcpsdrvr.c b/mbglib/common/pcpsdrvr.c index 661f483..4ec7909 100755 --- a/mbglib/common/pcpsdrvr.c +++ b/mbglib/common/pcpsdrvr.c @@ -1,7 +1,7 @@ /************************************************************************** * - * $Id: pcpsdrvr.c 1.46.2.25 2011/02/07 15:47:28 martin TEST $ + * $Id: pcpsdrvr.c 1.46.2.35 2011/03/25 11:10:34 martin TRASH $ * * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany * @@ -61,6 +61,23 @@ * * ----------------------------------------------------------------------- * $Log: pcpsdrvr.c $ + * Revision 1.46.2.35 2011/03/25 11:10:34 martin + * Optionally support timespec for sys time (USE_TIMESPEC). + * Revision 1.46.2.34 2011/03/22 10:25:57 martin + * Modifications to support NetBSD. + * Revision 1.46.2.33 2011/03/21 16:26:03 martin + * Account for modified _pcps_kfree(). + * Revision 1.46.2.32 2011/02/16 10:14:37 martin + * Set up basic default receiver info for devices which don't + * support this structure. + * Revision 1.46.2.31 2011/02/15 14:24:57Z martin + * Revision 1.46.2.30 2011/02/10 09:18:07 martin + * Revision 1.46.2.29 2011/02/09 17:08:30Z martin + * Specify I/O range number when calling port I/O macros + * so they can be used for different ranges under BSD. + * Revision 1.46.2.28 2011/02/09 16:42:12 martin + * Revision 1.46.2.27 2011/02/09 15:27:49 martin + * Revision 1.46.2.26 2011/02/09 14:43:19Z martin * Revision 1.46.2.25 2011/02/07 15:47:28 martin * Fixed a potential trap in kernel messages. * Revision 1.46.2.24 2011/02/04 14:44:45 martin @@ -299,6 +316,8 @@ #include <pcpsdrvr.h> #undef _PCPSDRVR +#include <parmpcps.h> +#include <parmgps.h> #include <identdec.h> #include <mbgddmsg.h> #include <plxdefs.h> @@ -319,7 +338,7 @@ #include <assert.h> #endif -#if defined( MBG_TGT_BSD ) +#if defined( MBG_TGT_FREEBSD ) #include <sys/rman.h> #include <sys/libkern.h> #endif @@ -439,12 +458,16 @@ long mbg_delta_sys_time_ms( const MBG_SYS_TIME *t2, const MBG_SYS_TIME *t1 ) { #if defined( MBG_TGT_LINUX ) || defined( MBG_TGT_BSD ) long dt = ( t2->tv_sec - t1->tv_sec ) * 1000; - dt += ( t2->tv_usec - t1->tv_usec ) / 1000; + #if USE_TIMESPEC + dt += ( t2->tv_nsec - t1->tv_nsec ) / 1000000; + #else + dt += ( t2->tv_usec - t1->tv_usec ) / 1000; + #endif return dt; #elif defined( MBG_TGT_WIN32 ) return (long) ( ( t2->QuadPart - t1->QuadPart ) / HNS_PER_MS ); #else - #error mbg_delta_sys_time_ms not implemented for this target + return 0; #endif } // mbg_delta_sys_time_ms @@ -455,17 +478,17 @@ static /*HDR*/ void report_uptime( const MBG_SYS_UPTIME *p_uptime ) { #if defined( MBG_TGT_LINUX ) - printk( KERN_INFO "%s: system uptime %Lu jiffies -> %Lu s, required %u s\n", - pcps_driver_name, (uint64_t) get_jiffies_64() - INITIAL_JIFFIES, - (uint64_t) *p_uptime, MAX_BOOT_TIME_PTP270PEX ); + printk( KERN_INFO "%s: system uptime %llu jiffies -> %llu s, required %u s\n", + pcps_driver_name, (unsigned long long) ( get_jiffies_64() - INITIAL_JIFFIES ), + (unsigned long long) *p_uptime, MAX_BOOT_TIME_PTP270PEX ); #elif defined( MBG_TGT_BSD ) - printf( "%s: system uptime %lli s, required %u s\n", - pcps_driver_name, *p_uptime, MAX_BOOT_TIME_PTP270PEX ); + printf( "%s: system uptime %llu s, required %u s\n", + pcps_driver_name, (unsigned long long) *p_uptime, MAX_BOOT_TIME_PTP270PEX ); #elif defined( MBG_TGT_WIN32 ) WCHAR wcs_msg[120]; swprintf( wcs_msg, L"system uptime: %I64u s, required %u s", - (uint64_t) *p_uptime, MAX_BOOT_TIME_PTP270PEX ); + (int64_t) *p_uptime, MAX_BOOT_TIME_PTP270PEX ); _evt_msg( GlbDriverObject, wcs_msg ); #endif @@ -474,6 +497,65 @@ void report_uptime( const MBG_SYS_UPTIME *p_uptime ) static /*HDR*/ +void check_uptime( void ) +{ + #if !defined( MBG_TGT_DOS ) + MBG_SYS_TIME t1; + MBG_SYS_TIME t2; + MBG_SYS_UPTIME uptime; + int delayed = 0; + + mbg_get_sys_time( &t1 ); + + for (;;) + { + mbg_get_sys_uptime( &uptime ); + + #if !defined( DEBUG ) + if ( !delayed ) + #endif + report_uptime( &uptime ); + + if ( uptime == 0 ) + break; // assume uptime not supported + + if ( uptime >= MAX_BOOT_TIME_PTP270PEX ) + break; + + mbg_sleep_sec( 1 ); + delayed = 1; + } + + if ( delayed ) + { + long dt; + + mbg_get_sys_time( &t2 ); + + dt = mbg_delta_sys_time_ms( &t2, &t1 ); + + #if defined( MBG_TGT_LINUX ) + printk( KERN_INFO "PTP270PEX startup delay: %li.%03li s\n", + dt / 1000, ( ( dt < 0 ) ? -dt : dt ) % 1000 ); + #elif defined( MBG_TGT_BSD ) + printf( "PTP270PEX startup delay: %li.%03li s\n", + dt / 1000, ( ( dt < 0 ) ? -dt : dt ) % 1000 ); + #elif defined( MBG_TGT_WIN32 ) + { + WCHAR wcs_msg[128]; + swprintf( wcs_msg, L"PTP270PEX startup delay: %li.%03li s", + dt / 1000, ( ( dt < 0 ) ? -dt : dt ) % 1000 ); + _evt_msg( GlbDriverObject, wcs_msg ); + } + #endif + } + #endif + +} // check_uptime + + + +static /*HDR*/ int pcps_check_pex_irq_unsafe( PCPS_DDEV *pddev, uint16_t req_fw_ver, uint8_t req_asic_ver_major, uint8_t req_asic_ver_minor ) { @@ -515,10 +597,14 @@ int map_sys_virtual_address( PCPS_DDEV *pddev ) pddev->mm_addr = ioremap( ( (ulong) pddev->rsrc_info.mem[0].start ), sizeof( *pddev->mm_addr ) ); - #elif defined ( MBG_TGT_BSD ) + #elif defined ( MBG_TGT_FREEBSD ) pddev->mm_addr = rman_get_virtual( pddev->rsrc_info.mem[0].bsd.res ); + #elif defined ( MBG_TGT_NETBSD ) + + pddev->mm_addr = bus_space_vaddr( pddev->rsrc_info.mem[0].bsd.bst, pddev->rsrc_info.mem[0].bsd.bsh ); + #else // DOS, ... pddev->mm_addr = (PCPS_MM_LAYOUT FAR *) pddev->rsrc_info.mem[0].start; @@ -671,7 +757,7 @@ short pcps_read_std( PCPS_DDEV *pddev, uint8_t cmd, _pcps_disb_local_irq_save(); mbg_get_pc_cycles( &pddev->acc_cycles ); // write the command byte - _mbg_outp8( pddev, port, cmd ); + _mbg_outp8( pddev, 0, port, cmd ); _pcps_local_irq_restore(); // wait until BUSY flag goes low or timeout @@ -682,7 +768,7 @@ short pcps_read_std( PCPS_DDEV *pddev, uint8_t cmd, // no timeout: read bytes from the board's FIFO for ( i = 0; i < count; i++ ) { - *buffer++ = _mbg_inp8( pddev, port ); + *buffer++ = _mbg_inp8( pddev, 0, port ); #if DEBUG_IO _mbgddmsg_1( MBG_DBG_DETAIL, "pcps_read_std: %02X", buffer[i] ); @@ -714,15 +800,15 @@ short pcps_read_amcc_s5933( PCPS_DDEV *pddev, uint8_t cmd, #endif // reset inbound mailbox and FIFO status - _mbg_outp8( pddev, port + AMCC_OP_REG_MCSR + 3, 0x0C ); + _mbg_outp8( pddev, 0, port + AMCC_OP_REG_MCSR + 3, 0x0C ); // set FIFO - _mbg_outp8( pddev, port + AMCC_OP_REG_INTCSR + 3, 0x3C ); + _mbg_outp8( pddev, 0, port + AMCC_OP_REG_INTCSR + 3, 0x3C ); _pcps_disb_local_irq_save(); mbg_get_pc_cycles( &pddev->acc_cycles ); // write the command byte - _mbg_outp8( pddev, port + AMCC_OP_REG_OMB1, cmd ); + _mbg_outp8( pddev, 0, port + AMCC_OP_REG_OMB1, cmd ); _pcps_local_irq_restore(); // wait until BUSY flag goes low or timeout @@ -733,10 +819,10 @@ short pcps_read_amcc_s5933( PCPS_DDEV *pddev, uint8_t cmd, // no timeout: read bytes from the board's FIFO for ( i = 0; i < count; i++ ) { - if ( _mbg_inp16_to_cpu( pddev, port + AMCC_OP_REG_MCSR ) & 0x20 ) + if ( _mbg_inp16_to_cpu( pddev, 0, port + AMCC_OP_REG_MCSR ) & 0x20 ) return MBG_ERR_FIFO; - buffer[i] = _mbg_inp8( pddev, port + AMCC_OP_REG_FIFO + ( i % sizeof( uint32_t) ) ); + buffer[i] = _mbg_inp8( pddev, 0, port + AMCC_OP_REG_FIFO + ( i % sizeof( uint32_t) ) ); #if DEBUG_IO _mbgddmsg_1( MBG_DBG_DETAIL, "pcps_read_amcc_s5933: %02X", buffer[i] ); @@ -769,13 +855,15 @@ short pcps_read_amcc_s5920( PCPS_DDEV *pddev, uint8_t cmd, #if DEBUG_IO - _mbgddmsg_1( MBG_DBG_INIT_DEV, "pcps_read_amcc_s5920: cmd %02X", cmd ); + _mbgddmsg_3( MBG_DBG_INIT_DEV, "pcps_read_amcc_s5920: cmd %02X, port: %04lX, data_port: %04lX", + cmd, (ulong) _pcps_ddev_io_base_mapped( pddev, 0 ) + AMCC_OP_REG_OMB, + (ulong) data_port ); #endif _pcps_disb_local_irq_save(); mbg_get_pc_cycles( &pddev->acc_cycles ); // write the command byte - _mbg_outp8( pddev, _pcps_ddev_io_base_mapped( pddev, 0 ) + AMCC_OP_REG_OMB, cmd ); + _mbg_outp8( pddev, 0, _pcps_ddev_io_base_mapped( pddev, 0 ) + AMCC_OP_REG_OMB, cmd ); _pcps_local_irq_restore(); dt_quot = count / 4; @@ -795,7 +883,7 @@ short pcps_read_amcc_s5920( PCPS_DDEV *pddev, uint8_t cmd, // first read full 32 bit words for ( i = 0; i < dt_quot; i++ ) { - ul = _mbg_inp32_to_cpu( pddev, data_port ); + ul = _mbg_inp32_to_cpu( pddev, 1, data_port ); #if DEBUG_IO _mbgddmsg_1( MBG_DBG_INIT_DEV, "pcps_read_amcc_s5920: %08X", ul ); #endif @@ -806,7 +894,7 @@ short pcps_read_amcc_s5920( PCPS_DDEV *pddev, uint8_t cmd, // then read the remaining bytes, if required if ( dt_rem ) { - ul = _mbg_inp32_to_cpu( pddev, data_port ); + ul = _mbg_inp32_to_cpu( pddev, 1, data_port ); for ( i = 0; i < dt_rem; i++ ) { @@ -819,7 +907,7 @@ short pcps_read_amcc_s5920( PCPS_DDEV *pddev, uint8_t cmd, } } else - _mbg_inp32( pddev, data_port ); // do a dummy read + _mbg_inp32( pddev, 1, data_port ); // do a dummy read return MBG_SUCCESS; @@ -855,7 +943,7 @@ short pcps_read_asic( PCPS_DDEV *pddev, uint8_t cmd, _pcps_disb_local_irq_save(); mbg_get_pc_cycles( &pddev->acc_cycles ); // write the command byte - _mbg_outp32( pddev, _pcps_ddev_io_base_mapped( pddev, 0 ) + _mbg_outp32( pddev, 0, _pcps_ddev_io_base_mapped( pddev, 0 ) + offsetof( PCI_ASIC, pci_data ), cmd ); _pcps_local_irq_restore(); @@ -874,7 +962,7 @@ short pcps_read_asic( PCPS_DDEV *pddev, uint8_t cmd, // first read full 32 bit words for ( i = 0; i < dt_quot; i++ ) { - ar.ul = _mbg_inp32_to_cpu( pddev, data_port ); + ar.ul = _mbg_inp32_to_cpu( pddev, 0, data_port ); #if DEBUG_IO _mbgddmsg_1( MBG_DBG_INIT_DEV, "pcps_read_asic: %08X", ar.ul ); #endif @@ -886,7 +974,7 @@ short pcps_read_asic( PCPS_DDEV *pddev, uint8_t cmd, // then read the remaining bytes, if required if ( dt_rem ) { - ar.ul = _mbg_inp32_to_cpu( pddev, data_port ); + ar.ul = _mbg_inp32_to_cpu( pddev, 0, data_port ); for ( i = 0; i < dt_rem; i++ ) { @@ -1041,7 +1129,7 @@ short pcps_write( PCPS_DDEV *pddev, uint8_t cmd, rc = (int8_t) p[0]; // return the rc from the board } - _pcps_kfree( p ); + _pcps_kfree( p, n ); } else #endif // _PCPS_USE_USB @@ -1678,56 +1766,38 @@ int pcps_read_sernum( PCPS_DDEV *pddev ) // Check which way is supported by the clock, and // read the S/N, - // Read directly. This is supported by newer DCF77 clocks. - if ( _pcps_ddev_has_sernum( pddev ) ) + + // The S/N is part of the RECEIVER_INFO structure. If this + // structure is supported by the device then it should have + // already been set up, so we can simply copy the serial number. + if ( _pcps_ddev_has_receiver_info( pddev ) ) { #if DEBUG_SERNUM - _mbgddmsg_0( MBG_DBG_DETAIL, "getting S/N via PCPS_GIVE_SERNUM cmd" ); + _mbgddmsg_0( MBG_DBG_DETAIL, "copying S/N from receiver info" ); #endif - rc = _pcps_read( pddev, PCPS_GIVE_SERNUM, pddev->dev.cfg.sernum, PCPS_FIFO_SIZE ); - - if ( rc != MBG_SUCCESS ) - { - _mbgddmsg_2( MBG_DBG_INIT_DEV, "PCPS read SERNUM %X: rc = %i", - _pcps_ddev_dev_id( pddev ), rc ); - goto fail; - } - + strncpy( pddev->dev.cfg.sernum, pddev->ri.sernum, + sizeof( pddev->dev.cfg.sernum ) ); goto check; } - // The S/N is part of the RECEIVER_INFO structure, - // so use that one, if supported. - if ( _pcps_ddev_has_receiver_info( pddev ) ) + // Read directly. This is supported by newer DCF77 clocks. + if ( _pcps_ddev_has_sernum( pddev ) ) { - static_wc RECEIVER_INFO ri; - #if DEBUG_SERNUM - _mbgddmsg_0( MBG_DBG_DETAIL, "getting S/N from receiver info" ); + _mbgddmsg_0( MBG_DBG_DETAIL, "getting S/N via PCPS_GIVE_SERNUM cmd" ); #endif - rc = _pcps_read_gps_var( pddev, PC_GPS_RECEIVER_INFO, ri ); + rc = _pcps_read( pddev, PCPS_GIVE_SERNUM, pddev->dev.cfg.sernum, PCPS_FIFO_SIZE ); if ( rc != MBG_SUCCESS ) { - _mbgddmsg_2( MBG_DBG_INIT_DEV, "PCPS read GPS receiver info %X: rc = %i", + _mbgddmsg_2( MBG_DBG_INIT_DEV, "PCPS read SERNUM %X: rc = %i", _pcps_ddev_dev_id( pddev ), rc ); goto fail; } - _mbg_swab_receiver_info( &ri ); - - #if DEBUG_IO - _mbgddmsg_1( MBG_DBG_DETAIL, "ri.sw_rev.code: %04X", ri.sw_rev.code ); - _mbgddmsg_1( MBG_DBG_DETAIL, "ri.model_code: %04X", ri.model_code ); - _mbgddmsg_3( MBG_DBG_DETAIL, "ri.model_name: %-*.*s", (int) sizeof( ri.model_name ), (int) sizeof( ri.model_name ), ri.model_name ); - _mbgddmsg_1( MBG_DBG_DETAIL, "ri.features: %08X", ri.features ); - #endif - - strncpy( pddev->dev.cfg.sernum, ri.sernum, - sizeof( pddev->dev.cfg.sernum ) ); goto check; } @@ -2113,7 +2183,7 @@ void pcps_free_ddev( PCPS_DDEV *pddev ) { #if !_PCPS_STATIC_DEV_LIST if ( pddev ) - _pcps_kfree( pddev ); + _pcps_kfree( pddev, sizeof( *pddev ) ); #else memset( pddev, 0, sizeof( *pddev ) ); @@ -2616,57 +2686,9 @@ chip_setup_done: } #endif - // Make sure a PTP270PEX card has finished booting. + // Make sure a PTP270PEX card has finished booting. if ( _pcps_ddev_dev_id( pddev ) == PCI_DEV_PTP270PEX ) - { - MBG_SYS_TIME t1; - MBG_SYS_TIME t2; - MBG_SYS_UPTIME uptime; - int delayed = 0; - - mbg_get_sys_time( &t1 ); - - for (;;) - { - mbg_get_sys_uptime( &uptime ); - - #if !defined( DEBUG ) - if ( !delayed ) - #endif - report_uptime( &uptime ); - - if ( uptime == 0 ) - break; // assume uptime not supported - - if ( uptime >= MAX_BOOT_TIME_PTP270PEX ) - break; - - mbg_sleep_sec( 1 ); - delayed = 1; - } - - if ( delayed ) - { - long dt; - - mbg_get_sys_time( &t2 ); - - dt = mbg_delta_sys_time_ms( &t2, &t1 ); - - #if defined( MBG_TGT_LINUX ) - printk( KERN_INFO "PTP270PEX startup delay: %li.%03li s\n", - dt / 1000, ( ( dt < 0 ) ? -dt : dt ) % 1000 ); - #elif defined( MBG_TGT_BSD ) - printf( "PTP270PEX startup delay: %li.%03li s\n", - dt / 1000, ( ( dt < 0 ) ? -dt : dt ) % 1000 ); - #elif defined( MBG_TGT_WIN32 ) - swprintf( pddev->wcs_msg, L"PTP270PEX startup delay: %li.%03li s", - dt / 1000, ( ( dt < 0 ) ? -dt : dt ) % 1000 ); - _evt_msg( GlbDriverObject, pddev->wcs_msg ); - #endif - } - } - + check_uptime(); // try to read EPROM ID rc = pcps_get_fw_id( pddev, pddev->dev.cfg.fw_id ); @@ -2719,7 +2741,7 @@ chip_setup_done: // If no support for MCA has been compiled in, it may even // be a PS31 which is software compatible with a PC31. dev_type = - ( _mbg_inp16_to_cpu( pddev, _pcps_ddev_io_base_mapped( pddev, 0 ) + 2 ) + ( _mbg_inp16_to_cpu( pddev, 0, _pcps_ddev_io_base_mapped( pddev, 0 ) + 2 ) == pcps_dev_type[PCPS_TYPE_PC32].dev_id ) ? PCPS_TYPE_PC32 : PCPS_TYPE_PC31; } @@ -2743,7 +2765,7 @@ chip_setup_done: // If the device has an ASIC or EPLD read the ASIC version number if ( _pcps_ddev_has_asic_version( pddev ) ) { - pddev->raw_asic_version = _mbg_inp32_to_cpu( pddev, _pcps_ddev_io_base_mapped( pddev, 0 ) + pddev->raw_asic_version = _mbg_inp32_to_cpu( pddev, 0, _pcps_ddev_io_base_mapped( pddev, 0 ) + offsetof( PCI_ASIC, raw_version ) ); _mbg_swab_asic_version( &pddev->raw_asic_version ); @@ -2905,45 +2927,84 @@ chip_setup_done: if ( _pcps_ddev_has_receiver_info( pddev ) ) { - // detect the presence of some optional features at run time - RECEIVER_INFO rcvr_info; int rc; - rc = _pcps_read_gps_var( pddev, PC_GPS_RECEIVER_INFO, rcvr_info ); + rc = _pcps_read_gps_var( pddev, PC_GPS_RECEIVER_INFO, pddev->ri ); if ( rc == MBG_SUCCESS ) { _mbg_swab_receiver_info( &rcvr_info ); - - _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s v%03X RECEIVER_INFO features: 0x%08lX", - _pcps_ddev_type_name( pddev ), _pcps_ddev_fw_rev_num( pddev ), - (ulong) rcvr_info.features ); - - check_ri_feature( pddev, &rcvr_info, GPS_HAS_IRIG_TX, PCPS_HAS_IRIG_TX ); - check_ri_feature( pddev, &rcvr_info, GPS_HAS_IRIG_CTRL_BITS, PCPS_HAS_IRIG_CTRL_BITS ); - check_ri_feature( pddev, &rcvr_info, GPS_HAS_SYNTH, PCPS_HAS_SYNTH ); - check_ri_feature( pddev, &rcvr_info, GPS_HAS_TIME_SCALE, PCPS_HAS_TIME_SCALE ); - - // Devices which support a configurable time scale do also - // support reading/writing the GPS UTC parameters via the PC bus. - // This is not explicitely coded in the rcvr_info structure - // since the the rcvr_info structure can also be read via - // the serial port, and reading/writing the GPS UTC parameters - // via the serial port is supported by all GPS devices anyway. - check_ri_feature( pddev, &rcvr_info, GPS_HAS_TIME_SCALE, PCPS_HAS_UTC_PARM ); - - // Devices which support reading raw IRIG data via the PC interface also support - // reading the raw IRIG time. However, there is no receiver info feature flag - // since this call is not supported via the serial interface, so we use the - // GPS_HAS_RAW_IRIG_DATA flag to check both features. - check_ri_feature( pddev, &rcvr_info, GPS_HAS_RAW_IRIG_DATA, PCPS_HAS_IRIG_TIME ); - check_ri_feature( pddev, &rcvr_info, GPS_HAS_RAW_IRIG_DATA, PCPS_HAS_RAW_IRIG_DATA ); - - check_ri_feature( pddev, &rcvr_info, GPS_HAS_LAN_IP4, PCPS_HAS_LAN_INTF ); - check_ri_feature( pddev, &rcvr_info, GPS_HAS_PTP, PCPS_HAS_PTP ); + goto check; } } + _mbgddmsg_1( MBG_DBG_INIT_DEV, "Setting up default receiver info for dev %X", + _pcps_ddev_dev_id( pddev ) ); + + if ( _pcps_ddev_is_gps( pddev ) ) + _setup_default_receiver_info_gps( &pddev->ri ); + else + _setup_default_receiver_info_dcf( &pddev->ri, &pddev->dev ); + +check: + #if DEBUG_IO + _mbgddmsg_1( MBG_DBG_DETAIL, "ri.sw_rev.code: %04X", pddev->ri.sw_rev.code ); + _mbgddmsg_1( MBG_DBG_DETAIL, "ri.model_code: %04X", pddev->ri.model_code ); + _mbgddmsg_3( MBG_DBG_DETAIL, "ri.model_name: %-*.*s", (int) sizeof( pddev->ri.model_name ), + (int) sizeof( pddev->ri.model_name ), pddev->ri.model_name ); + #endif + + +#if 0 //##+++++++++ check if this is reasonnable + + // Make sure this program supports at least as many ports as + // the current clock device. + if ( pddev->ri.n_com_ports > MAX_PARM_PORT ) + { + _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s provides %i COM ports, but this driver only supports %i", + _pcps_ddev_type_name( pddev ), pddev->ri.n_com_ports, MAX_PARM_PORT ); + pddev->ri.n_com_ports = MAX_PARM_PORT; + } + + // Make sure this program supports at least as many string types + // as the current clock device. + if ( pddev->ri.n_str_type > MAX_PARM_STR_TYPE ) + { + _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s supports %i serial string formats, but this driver only supports %i", + _pcps_ddev_type_name( pddev ), pddev->ri.n_str_type, MAX_PARM_STR_TYPE ); + pddev->ri.n_str_type = MAX_PARM_STR_TYPE; + } +#endif + + + // detect the presence of some optional features at run time + _mbgddmsg_3( MBG_DBG_INIT_DEV, "%s v%03X RECEIVER_INFO features: 0x%08lX", + _pcps_ddev_type_name( pddev ), _pcps_ddev_fw_rev_num( pddev ), + (ulong) pddev->ri.features ); + + check_ri_feature( pddev, &pddev->ri, GPS_HAS_IRIG_TX, PCPS_HAS_IRIG_TX ); + check_ri_feature( pddev, &pddev->ri, GPS_HAS_IRIG_CTRL_BITS, PCPS_HAS_IRIG_CTRL_BITS ); + check_ri_feature( pddev, &pddev->ri, GPS_HAS_SYNTH, PCPS_HAS_SYNTH ); + check_ri_feature( pddev, &pddev->ri, GPS_HAS_TIME_SCALE, PCPS_HAS_TIME_SCALE ); + + // Devices which support a configurable time scale do also + // support reading/writing the GPS UTC parameters via the PC bus. + // This is not explicitely coded in the rcvr_info structure + // since the the rcvr_info structure can also be read via + // the serial port, and reading/writing the GPS UTC parameters + // via the serial port is supported by all GPS devices anyway. + check_ri_feature( pddev, &pddev->ri, GPS_HAS_TIME_SCALE, PCPS_HAS_UTC_PARM ); + + // Devices which support reading raw IRIG data via the PC interface also support + // reading the raw IRIG time. However, there is no receiver info feature flag + // since this call is not supported via the serial interface, so we use the + // GPS_HAS_RAW_IRIG_DATA flag to check both features. + check_ri_feature( pddev, &pddev->ri, GPS_HAS_RAW_IRIG_DATA, PCPS_HAS_IRIG_TIME ); + check_ri_feature( pddev, &pddev->ri, GPS_HAS_RAW_IRIG_DATA, PCPS_HAS_RAW_IRIG_DATA ); + + check_ri_feature( pddev, &pddev->ri, GPS_HAS_LAN_IP4, PCPS_HAS_LAN_INTF ); + check_ri_feature( pddev, &pddev->ri, GPS_HAS_PTP, PCPS_HAS_PTP ); + check_ri_feature( pddev, &pddev->ri, GPS_HAS_PTP_UNICAST, 0 ); // no equivalent in PCPS_DDEV features #if !defined( MBG_TGT_OS2 ) && !defined( MBG_TGT_BSD ) // Function strstr may not be supported at kernel level, @@ -2968,7 +3029,7 @@ chip_setup_done: if ( _pcps_ddev_has_asic_features( pddev ) ) { - pddev->asic_features = _mbg_inp32_to_cpu( pddev, _pcps_ddev_io_base_mapped( pddev, 0 ) + pddev->asic_features = _mbg_inp32_to_cpu( pddev, 0, _pcps_ddev_io_base_mapped( pddev, 0 ) + offsetof( PCI_ASIC, features ) ); _mbg_swab_asic_features( &pddev->asic_features ); |