head 4.4; access ; symbols ; locks oasisa:4.4; strict; comment @ * @; 4.4 date 2001.06.19.12.13.26; author oasisa; state Exp; branches ; next ; desc @New Repository; 6/19/2001 (klh) @ 4.4 log @New Repository; 6/19/2001 (klh) @ text @/****************************************************************************/ /* Copyright 1991 MBARI */ /****************************************************************************/ /* $Header: drvr.c,v 1.1 2001/06/19 11:43:21 oasisa Exp $ */ /* Summary : Driver Management Routines for OASIS Mooring Controller */ /* Filename : drvr.c */ /* Author : Robert Herlien (rah) */ /* Project : OASIS Mooring */ /* $Revision: 1.1 $ */ /* Created : 02/14/91 */ /* */ /* MBARI provides this documentation and code "as is", with no warranty, */ /* express or implied, of its quality or consistency. It is provided without*/ /* support and without obligation on the part of the Monterey Bay Aquarium */ /* Research Institute to assist in its use, correction, modification, or */ /* enhancement. This information should not be published or distributed to */ /* third parties without specific written permission from MBARI. */ /* */ /****************************************************************************/ /* Modification History: */ /* 14feb91 rah - created */ /* $Log: drvr.c,v $ * Revision 1.1 2001/06/19 11:43:21 11:43:21 oasisa (Oasis users) * Initial revision * * Revision 4.3 99/06/16 10:21:33 10:21:33 bobh (Bob Herlien) * Mar/May '99 Deployments of M3/M2 * * Revision 4.2 98/09/09 10:48:01 10:48:01 bobh (Bob Herlien) * Sept/Oct '98 deployments of M1, Eqpac 1 & 2 * * Revision 3.8 97/09/12 10:50:50 10:50:50 bobh (Bob Herlien) * Redeploy M1 * * Revision 3.7 97/07/23 11:18:06 11:18:06 bobh (Bob Herlien) * July '97 M1 deployment, new shutter code * * Revision 3.6 96/10/30 14:00:12 14:00:12 bobh (Bob Herlien) * Release for EqPac, M2 Test Replacement * * Revision 3.5 96/07/17 14:38:43 14:38:43 bobh (Bob Herlien) * July '96 deployment of M2 with ARGOS code * * Revision 3.4 96/06/18 15:24:19 15:24:19 bobh (Bob Herlien) * June '96 deployment of M1 * * Revision 3.3 95/04/13 13:46:53 13:46:53 hebo (Bob Herlien) * Drifter Deployment for Coop (flip) cruise * * Revision 3.1 95/03/09 19:30:55 19:30:55 hebo (Bob Herlien) * March '95 Deployment of M1A * * Revision 3.0 95/02/21 18:42:41 18:42:41 hebo (Bob Herlien) * February '95 Deployment * * Revision 2.4 93/10/29 11:12:44 11:12:44 hebo (Bob Herlien) * November 1993 Deployment * * Revision 2.0 92/08/21 14:45:03 14:45:03 hebo (Bob Herlien) * August 1992 deployment * * Revision 1.3 92/03/05 14:22:29 14:22:29 hebo (Bob Herlien 408-647-3748) * New defaults, restart check, perm power stuff, analog command, gps changes * */ /****************************************************************************/ #include /* MBARI type definitions */ #include /* MBARI constants */ #include /* OASIS controller definitions*/ #include /* LOGGER definition */ #include /* OASIS I/O definitions */ #include /* Log record definitions */ #include /* OASIS Multitasking definitions */ #include <80C196.h> /* 80196 Register mapping */ #include /* Defines UINT_MAX */ #include /* Default driver headers */ #include /* String library functions */ /********************************/ /* External Functions */ /********************************/ Extern Void ser_init(Nat16 port, Nat16 baud); /* Serial port init */ Extern Void io_relay(Word select0, Word select1); /* Set ser relay mux */ Extern Void io_pwron( Word pwrbits ); /* Turn power on */ Extern Void io_pwroff( Word pwrbits ); /* Turn power off */ Extern Void xdrain_ser( Nat16 tmout ); /* Drain serial output */ Extern char *tmpMalloc( Nat16 size ); /* Alloc temp memory */ Extern Void tmpFree( char *ptr ); Extern char *permMalloc( Nat16 size ); /* Alloc permanent memory */ Extern TaskDesc *task_create( Reg Driver *dp ); /* Create driver task */ Extern Void logPutRec( LogRecHdr *hdr, Byte *data ); /* Log into logging memory */ Extern Void logError( Reg Word vect ); /* Log an error */ Extern char *cmp_ulc( char *s, char *cs ); /* Case insensitive strcmp */ Extern Void sensor_init( Void ); /* Normal init of sensor.c */ Extern Void bcopy( const Byte *src, Byte *dst, Nat16 len ); Extern Void bzero( void *s, int n ); /* Zero memory */ /********************************/ /* External Data */ /********************************/ Extern Reg TimeOfDay tod; /* Current time in TimeOfDay format */ Extern Reg Byte localHour; /* Hour of day (0 - 23) in local time*/ Extern Reg Nat16 port; /* Default serial port */ Extern Nat16 pwr_perm; /* Devices to leave powered on */ Extern TimeOfDay radio_time; /* Last time user connected on radio*/ /* (set in userif.c, used here) */ Extern Nat16 sync_tmout; /* Timeout for drvSync */ /********************************/ /* Global Data */ /********************************/ Global LstHead drv_list; /* Driver list header */ Global Semaphore ser_sem[NSER_PORTS]; /* Mutex sems for ser ports */ Global Semaphore no3_sem; /* Mutex sem for no3 driver */ Global Nat16 deploymentMode; /* In deployment mode mode */ /************************************************************************/ /* Function : null_func */ /* Purpose : Null function */ /* Inputs : None */ /* Outputs : TRUE */ /************************************************************************/ MBool null_func( Void ) { return( TRUE ); } /* null_func() */ /************************************************************************/ /* Function : drv_pwron */ /* Purpose : Turn on power for given driver */ /* Inputs : Driver Pointer */ /* Outputs : None */ /************************************************************************/ Void drv_pwron( Driver *dp ) { io_pwron( dp->drv_parms[PWR_CTRL] ); } /* drv_pwron() */ /************************************************************************/ /* Function : drv_pwroff */ /* Purpose : Turn off power for given driver */ /* Inputs : Driver Pointer */ /* Outputs : None */ /************************************************************************/ Void drv_pwroff( Driver *dp ) { Reg Word pwrbits; pwrbits = dp->drv_parms[PWR_CTRL]; if ( (pwrbits & pwr_perm) == 0 ) io_pwroff( pwrbits ); } /* drv_pwroff() */ /************************************************************************/ /* Function : drv_ser_port */ /* Purpose : Get access to serial port, init port */ /* Inputs : Driver Pointer */ /* Outputs : None */ /************************************************************************/ Void drv_ser_port( Driver *dp ) { if ( (port = dp->drv_parms[SER_PORT]) != NO_SERIAL ) { sem_take( &ser_sem[port] ); /* Get access to ser port */ drv_pwron( dp ); /* Turn on device */ io_relay( dp->drv_parms[SER_RELAY0], dp->drv_parms[SER_RELAY1] ); ser_init( port, dp->drv_parms[SER_SETUP] ); } /* Init serial port */ } /* drv_ser_port() */ /************************************************************************/ /* Function : drv_ser_release */ /* Purpose : Release access to serial port */ /* Inputs : Driver Pointer */ /* Outputs : None */ /************************************************************************/ Void drv_ser_release( Driver *dp ) { if ( (port = dp->drv_parms[SER_PORT]) != NO_SERIAL ) { xdrain_ser( 400 ); /* Wait for output to drain*/ sem_give( &ser_sem[port] ); /* Give up semaphore */ } } /* drv_ser_release() */ /************************************************************************/ /* Function : drvr_find */ /* Purpose : Find a driver by name */ /* Inputs : Pointer to name string */ /* Outputs : Corresponding driver, or DRV_NULL if none */ /************************************************************************/ Driver * drvr_find( char *name ) { Reg Driver *dp; for ( dp = (Driver *)(drv_list.lst_head); dp != DRV_NULL; dp = dp->drv_next ) if ( cmp_ulc(name, dp->drv_name) != NULL ) return( dp ); return( DRV_NULL ); } /* drvr_find() */ /************************************************************************/ /* Function : drvr_create */ /* Purpose : Create a driver header */ /* Inputs : Ptr to driver descriptor */ /* Outputs : Driver pointer */ /************************************************************************/ Driver * drvr_create( const DrvDesc *ddp ) { Reg Driver *dp; Reg Nat16 namelen; namelen = strlen( ddp->dd_name ) + 1; if ( (dp = (Driver *)permMalloc(sizeof(Driver) + namelen)) != DRV_NULL ) { bzero( (Byte *)dp, sizeof(Driver) ); bcopy( (Byte *)ddp, (Byte *)&(dp->drv_name), sizeof(DrvDesc) ); dp->drv_name = (char *)(dp + 1); bcopy( (Byte *)ddp->dd_name, (Byte *)dp->drv_name, namelen ); dp->drv_flags = DO_INIT; } return( dp ); } /* drvr_create() */ /************************************************************************/ /* Function : drvr_init */ /* Purpose : Initialize driver module */ /* Inputs : None */ /* Outputs : None */ /************************************************************************/ Void drvr_init( Void ) { Reg Driver *dp; /* Driver pointer */ Reg Int16 i; /* Scratch */ LogRecHdr rechdr; /* Logging record header */ for ( i = 0; i < NSER_PORTS; i++ ) sem_init( &ser_sem[i], 1 ); /* Init the serial semaphores */ for (dp = (Driver *)drv_list.lst_head; dp != DRV_NULL; dp = dp->drv_next) dp->drv_td = NULLTID; /* Init no driver tasks */ sensor_init(); /* Init sensor module */ sem_init( &no3_sem, 1 ); /* Init the no3 semaphore */ } /* drvr_init() */ /************************************************************************/ /* Function : drvrColdInit */ /* Purpose : Cold Initialize the driver module */ /* Inputs : None */ /* Outputs : None */ /* Comments : Called when system totally reset after power outage */ /************************************************************************/ Void drvrColdInit( Void ) { Reg Int16 i; Driver *dp; list_init( &drv_list ); /* Init driver list */ for ( i = 0; i < NUM_DRVRS; i++ ) /* Add default drivers */ if ( (dp = drvr_create(&drv_default[i])) != DRV_NULL ) { list_add( &drv_list, (Node *)dp ); /* Add to driver list */ dp->drv_wakeup = tod; /* Set to sample now */ } } /* drvrColdInit() */ /************************************************************************/ /* Function : drvWakeupTime */ /* Purpose : Determine time until driver needs to wake up */ /* Inputs : Driver pointer */ /* Outputs : Seconds until driver wakeup, or 0 if wakeup now */ /************************************************************************/ Nat16 drvWakeupTime( Reg Driver *dp ) { Reg Nat16 nexthr; if ( tod < dp->drv_wakeup ) /* If not time to run, */ return( (Nat16)(dp->drv_wakeup - tod) ); /* return time to wakeup*/ /* Time to wakeup now. Check flags*/ if ( dp->drv_flags & DO_SYNC ) /* If SYNC flag on, run */ return( 0 ); /* it now */ if ( dp->drv_parms[INTERVAL] == 0 ) /* If driver turned off */ return( NAT16_MAX ); /* return Max Nat16 */ if ( (deploymentMode == 0) && /* Check TOD mask */ (dp->drv_parms[TOD_MASK] & (1 << (localHour >> 1))) ) { /* If TOD mask on for this 2 hr period, */ /* go to next hour */ nexthr = 3600 - (tod % 3600); dp->drv_wakeup = tod + nexthr; return( nexthr ); } return( 0 ); /* If none above, run now*/ } /* drvWakeupTime() */ /************************************************************************/ /* Function : drvr_sample */ /* Purpose : (Re)start any driver not already running that should be*/ /* Inputs : None */ /* Outputs : Seconds until next driver wakeup */ /* Comments : Will restart any driver not already running that has */ /* exipired its wakeup time. */ /* Returns 0 if any tasks still running, to keep main alive*/ /************************************************************************/ Nat16 drvr_sample( Void ) { Reg Driver *dp; /* Cur drvr ptr */ Reg Nat16 wtime, t; /* Earliest wake time */ #ifdef SYNC_AT_MIDNIGHT wtime = 43200 - (tod % 43200); #else wtime = NAT16_MAX; #endif for ( dp = (Driver *)drv_list.lst_head; dp != DRV_NULL; dp = dp->drv_next ) { if ( dp->drv_td != NULLTID ) /* If anybody running, */ wtime = 0; /* next wake is now */ else { if ( (t = drvWakeupTime(dp)) == 0 ) /* If time to wake up */ { /* start the driver */ dp->drv_td = (Tid)task_create(dp); dp->drv_wakeup = tod + dp->drv_parms[INTERVAL]; } if ( t < wtime ) /* Save min wake time */ wtime = t; } } return( wtime ); } /* drvr_sample() */ /************************************************************************/ /* Function : drvLogError */ /* Purpose : Log an error for a driver */ /* Inputs : Driver ptr */ /* Outputs : None */ /************************************************************************/ Void drvLogError( Driver *dp, Errno err ) { LogRecHdr rechdr; /* Logging record header */ Nat16 recbuff[2]; rechdr.log_type = (Byte)LOG_ERROR; rechdr.log_len = sizeof( recbuff ); recbuff[0] = dp->drv_parms[SAMPLE_TYPE]; recbuff[1] = err; logPutRec( &rechdr, (Byte *)recbuff ); } /* drvLogError() */ /************************************************************************/ /* Function : drvLog */ /* Purpose : Default sample logging routine */ /* Inputs : Driver ptr, sample ptr, number bytes */ /* Outputs : None */ /************************************************************************/ Void drvLog( Driver *dp, Byte *samplep, Int16 len ) { LogRecHdr rh; rh.log_type = dp->drv_parms[SAMPLE_TYPE]; if ( (rh.log_len = len) > 0 ) logPutRec( &rh, (Byte *)samplep ); else drvLogError( dp, NO_DATA ); } /* drvLog() */ /************************************************************************/ /* Function : drvLogWords */ /* Purpose : Default sample logging routine */ /* Inputs : Driver ptr, sample ptr, number words */ /* Outputs : None */ /************************************************************************/ Void drvLogWords( Driver *dp, Nat16 *samplep, Int16 wrds ) { drvLog( dp, (Byte *)samplep, wrds * sizeof(Nat16) ); } /* drvLogWords() */ /************************************************************************/ /* Function : drvSerPortAndMalloc */ /* Purpose : Get serial port and malloc buffer */ /* Inputs : Driver Pointer, buffer size */ /* Outputs : Buffer ptr, or NULL if malloc fails */ /************************************************************************/ char * drvSerPortAndMalloc( Driver *dp, Nat16 size ) { char *mallocPtr; drv_ser_port( dp ); if ( (mallocPtr = tmpMalloc(size)) == NULL ) { drv_ser_release( dp ); drvLogError( dp, MALLOC_ERR ); } return( mallocPtr ); } /* drvSerPortAndMalloc() */ /************************************************************************/ /* Function : drvSerReleaseAndFree */ /* Purpose : Release serial port and malloc buffer */ /* Inputs : Driver Pointer, buffer ptr */ /* Outputs : None */ /************************************************************************/ Void drvSerReleaseAndFree( Driver *dp, char *buffer ) { drv_ser_release( dp ); tmpFree( buffer ); } /* drvSerReleaseAndFree() */ /************************************************************************/ /* Function : drvSync */ /* Purpose : Sync to an External driver */ /* Inputs : Driver name */ /* Outputs : None */ /************************************************************************/ Void drvSync( char *name ) { Driver *dp; Nat16 cnt; if ( (dp = drvr_find(name)) == DRV_NULL ) return; dp->drv_wakeup = tod; dp->drv_flags |= DO_SYNC; for ( cnt = sync_tmout; (cnt > 0) && (dp->drv_flags & DO_SYNC); cnt-- ) task_delay( TICKS_PER_SECOND ); } /* drvSync() */ /************************************************************************/ /* Function : drvr_timechange */ /* Purpose : Notify driver module that new time has been set */ /* Inputs : Amount that time changed */ /* Outputs : None */ /************************************************************************/ Void drvr_timechange( Int32 diff ) { Reg Driver *dp; /* Driver pointer */ for (dp = (Driver *)drv_list.lst_head; dp != DRV_NULL; dp = dp->drv_next) dp->drv_wakeup += diff; radio_time += diff; } /* drvr_timechange() */ @