head 4.4; access ; symbols ; locks oasisa:4.4; strict; comment @ * @; 4.4 date 2001.06.19.12.16.13; 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: usrcmd1.c,v 1.1 2001/06/19 11:45:11 oasisa Exp $ */ /* Summary : More User Interface Commands for OASIS Mooring Controller */ /* Filename : usrcmd1.c */ /* Author : Robert Herlien (rah) */ /* Project : OASIS Mooring */ /* $Revision: 1.1 $ */ /* Created : 11/15/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: */ /* 15nov91 rah - created */ /* $Log: usrcmd1.c,v $ * Revision 1.1 2001/06/19 11:45:11 11:45:11 oasisa (Oasis users) * Initial revision * * Revision 4.2 98/09/09 10:48:09 10:48:09 bobh (Bob Herlien) * Sept/Oct '98 deployments of M1, Eqpac 1 & 2 * * Revision 4.0 98/03/09 11:44:47 11:44:47 bobh (Bob Herlien) * M3 Deployment of March '98, new Sat-Pac driver * * Revision 3.9 97/10/28 13:59:58 13:59:58 bobh (Bob Herlien) * EqPac Deployment of Nov 1997 * * Revision 3.8 97/09/12 10:51:04 10:51:04 bobh (Bob Herlien) * Redeploy M1 * * Revision 3.7 97/07/23 11:18:23 11:18:23 bobh (Bob Herlien) * July '97 M1 deployment, new shutter code * * Revision 3.6 96/10/30 14:00:27 14:00:27 bobh (Bob Herlien) * Release for EqPac, M2 Test Replacement * * Revision 3.5 96/07/17 13:01:42 13:01:42 bobh (Bob Herlien) * July '96 deployment of M2 with ARGOS code * * Revision 3.4 96/06/18 15:24:38 15:24:38 bobh (Bob Herlien) * June '96 deployment of M1 * * Revision 3.3 95/04/13 13:47:06 13:47:06 hebo (Bob Herlien) * Drifter Deployment for Coop (flip) cruise * * Revision 3.1 95/03/09 19:31:06 19:31:06 hebo (Bob Herlien) * March '95 Deployment of M1A * * Revision 3.0 95/02/21 18:42:52 18:42:52 hebo (Bob Herlien) * February '95 Deployment * * Revision 2.4 93/10/29 11:12:51 11:12:51 hebo (Bob Herlien) * November 1993 Deployment * * Revision 2.3 93/10/12 08:29:47 08:29:47 hebo (Bob Herlien) * Oct '93 Deployment of M2 * * Revision 2.0 92/08/26 10:32:26 10:32:26 hebo (Bob Herlien 408-647-3748) * August 1992 Deployment * * Revision 1.3 92/03/05 17:00:21 17:00:21 hebo (Bob Herlien 408-647-3748) * New defaults, restart check, perm power stuff, analog command * */ /****************************************************************************/ #include /* MBARI type definitions */ #include /* MBARI constants */ #include /* OASIS controller definitions */ #include /* OASIS I/O definitions */ #include /* OASIS task dispatcher */ #include /* DISK definition */ #include /* Log record definitions */ #include /* Standard I/O */ /********************************/ /* External Functions */ /********************************/ Extern char *permMalloc( Nat16 size ); Extern Void permFree( char *ptr ); Extern Nat16 chkProgRam( Void ); Extern Void xputc( Int16 byte ); Extern Void xputs( const char *s ); Extern Void xprintf( const char *format, ... ); Extern Void newline(Void); Extern Int16 xgetc_tmout( Nat16 tmout ); Extern Int16 xgets_tmout( char *s, Int16 len, Nat16 tmout ); Extern Int16 getByte( char *p, Nat16 radix ); Extern MBool getnum( char **s, Int16 *result, Nat16 radix ); Extern Driver *drvr_find( char *name ); Extern Driver *drvr_create( const DrvDesc *ddp ); Extern Void bankCopy( Nat16 bank, const Byte *src, Byte *dst, Nat16 len ); Extern LogRtn isLogged( LogPtr *lp ); Extern MBool logGetRec( LogPtr *lp, LogRec *logp ); Extern Void logNextBlk( LogPtr *lp ); Extern Void bzero( void *s, int n ); Extern Void bcopy( const Byte *src, Byte *dst, Nat16 len ); Extern Int16 ser_sndsts( Nat16 port ); /* # chars left to send */ Extern char *tmpMalloc( Nat16 size ); Extern Void tmpFree( char *ptr ); Extern MBool null_func(Void); /* Null function, rtns TRUE */ Extern MBool logSearch( LogPtr *lp ); /********************************/ /* External Data */ /********************************/ Extern Reg TimeOfDay tod; /* Current time in TimeOfDay format */ Extern Reg Nat16 port; /* Dflt ser port, saved by dispatch */ Extern LogPtr nextFreeLog; /* Next record to log */ Extern LogPtr nextUsrLog; /* Next log record to send to user */ Extern LstHead drv_list; /* Driver list header */ Extern Reg FuncPtr *SP; /* Stack Pointer */ #ifdef DISK Extern LogBlk dskBlksWritten; /* Nmbr blocks written to disk */ Extern Nat16 dskBlkErrors; /* Nmbr of above blks with errors */ #endif /********************************/ /* Global Data */ /********************************/ Global Nat16 progRamChksum; /* Checksum on program RAM */ Global MBool send_ascii; /* TRUE to send samples in ASCII */ /********************************/ /* Module Local Data */ /********************************/ typedef struct { const char *prompt; Nat16 offset; Nat16 radix; } ParmDesc; const ParmDesc drvprompts[] = { {"Interval (secs)", OffsetOf(Driver, drv_parms[INTERVAL]), 10}, {"Serial Port", OffsetOf(Driver, drv_parms[SER_PORT]), 10}, {"Serial Setup", OffsetOf(Driver, drv_parms[SER_SETUP]), 16}, {"Serial relay 0", OffsetOf(Driver, drv_parms[SER_RELAY0]), 16}, {"Serial relay 1", OffsetOf(Driver, drv_parms[SER_RELAY1]), 16}, {"Power ctrl", OffsetOf(Driver, drv_parms[PWR_CTRL]), 16}, {"Sample type", OffsetOf(Driver, drv_parms[SAMPLE_TYPE]), 10}, {"Hours off mask", OffsetOf(Driver, drv_parms[TOD_MASK]), 16}, {"Timeout (secs)", OffsetOf(Driver, drv_parms[TIMEOUT]), 10}, {"Extra parm 0", OffsetOf(Driver, drv_parms[PARM0]), 10}, {"Extra parm 1", OffsetOf(Driver, drv_parms[PARM1]), 10}, {"Extra parm 2", OffsetOf(Driver, drv_parms[PARM2]), 10}, {"Flags", OffsetOf(Driver, drv_flags), 16}, {"Counter", OffsetOf(Driver, drv_cnt), 10} }; #define NPARMS (sizeof(drvprompts)/sizeof(ParmDesc)) /************************************************************************/ /* Function : putascii */ /* Purpose : Send data to user in ASCII */ /* Inputs : Log Record ptr */ /* Outputs : None */ /************************************************************************/ Void putascii( LogRec *logp ) { Int16 len, curlen; Byte *p; union { TimeOfDay tm; Nat16 wrd[2]; } tm_union; len = logp->log_hdr.log_len; tm_union.tm = logp->log_hdr.log_time; xprintf( "%02x %04x %04x %04x%04x ", logp->log_hdr.log_type, logp->log_hdr.log_rcd, len, tm_union.wrd[1], tm_union.wrd[0] ); for ( p = logp->log_data; len > 0; ) { curlen = (len > 32) ? 32 : len; len -= curlen; while ( curlen-- ) xprintf("%02x", *p++ ); newline(); dispatch(); } } /* putascii() */ /************************************************************************/ /* Function : uuout */ /* Purpose : Encode one byte into uuencode format */ /* Inputs : Byte to encode */ /* Outputs : None */ /************************************************************************/ Void uuout( Int16 c ) { xputc( (c) ? (((c) & 0x3f) + ' ') : '`' ); }/* uuout() */ /************************************************************************/ /* Function : encode */ /* Purpose : Encode bytes into uuencode format */ /* Inputs : Ptr to data, length to encode */ /* Outputs : None */ /************************************************************************/ Void encode( Byte *dp, Int16 len ) { Byte *p; uuout( len ); for (p = dp; p < dp + len; p += 3) { uuout( *p >> 2 ); uuout( ((*p << 4) & 0x30) | ((p[1] >> 4) & 0x0f) ); uuout( ((p[1] << 2) & 0x3c) | ((p[2] >> 6) & 0x03) ); uuout( p[2] & 0x3f ); } xputc('\n'); dispatch(); } /* encode() */ /************************************************************************/ /* Function : putuu */ /* Purpose : Send data in uuencode fmt */ /* Inputs : Log Record ptr */ /* Outputs : None */ /************************************************************************/ Void putuu( LogRec *logp ) { Int16 len, curlen; Byte *p; len = logp->log_hdr.log_len + sizeof(LogRecHdr) - 1; for ( p = &(logp->log_hdr.log_type); len > 0; len -= curlen, p += curlen ) { curlen = (len > 45) ? 45 : len; encode( p, curlen ); } } /* putuu() */ /************************************************************************/ /* Function : putdata */ /* Purpose : Send data in log buffer to user */ /* Inputs : Log Record ptr */ /* Outputs : None */ /************************************************************************/ Void putdata( LogRec *logp ) { if (send_ascii) putascii( logp ); else putuu( logp ); } /* putdata() */ /************************************************************************/ /* Function : startdata */ /* Purpose : Send data header, get semaphore */ /* Inputs : Log Block number */ /* Outputs : None */ /************************************************************************/ Void startdata( LogBlk blk ) { xprintf( "begin 644 oasis.%u\n", blk ); } /* startdata() */ /************************************************************************/ /* Function : stopdata */ /* Purpose : Send data trailer, release semaphore */ /* Inputs : None */ /* Outputs : None */ /************************************************************************/ Void stopdata( Void ) { xputs( "`\nend\n" ); } /* stopdata() */ /************************************************************************/ /* Function : checkUsrInterrupt */ /* Purpose : Pause after sending log, and check for user interrupt */ /* Inputs : None */ /* Outputs : TRUE if user hit key to interupt, else FALSE */ /* Comment : This routine pauses after sending a log record to allow*/ /* the TNC to catch its breath. I suspect the TNC has its*/ /* XON/XOFF screwed up if it gets too busy */ /************************************************************************/ MBool checkUsrInterrupt( Void ) { #ifdef RADIO do { /* Let the output buffer drain */ if ( xgetc_tmout(0) != ERROR ) /* If user hit key, return FALSE*/ return( TRUE ); task_delay(TICKS_PER_SECOND/20); /* Else, wait 50 ms to give TNC */ } while ( ser_sndsts(port) > 0 ); /* time to catch its breath */ return( FALSE ); #else return ( xgetc_tmout(0) != ERROR ); #endif } /* checkUsrInterrupt() */ /************************************************************************/ /* Function : getLogRecs */ /* Purpose : Get specified data log records */ /* Inputs : LogBlk number, Log record number, number recs */ /* Outputs : OK, ERROR, or USR_INTERRUPT */ /************************************************************************/ Int16 getLogRecs( Nat16 log, Nat16 start, Nat16 nmbr ) { LogPtr logptr; LogRec *logp; Int16 rtn; logptr.lp_blk = log; logptr.lp_addr = LOG_START_ADDR; logptr.lp_rcd = start; if ( isLogged(&logptr) != LOG_OK ) { xprintf("Can't find log block %u record %u\n", log, start); return( ERROR ); } if ( (logp = (LogRec *)tmpMalloc(sizeof(LogRec))) == NULL ) { xprintf("Out of memory\n"); return( ERROR ); /* Get log buffer, rtn if none */ } if ( !send_ascii ) /* Send uuencode hdr, if needed */ startdata(log); for( rtn = OK; nmbr-- && logGetRec(&logptr, logp); ) { if ( checkUsrInterrupt() ) { rtn = USR_INTERRUPT; break; } putdata( logp ); /* Send all requested records */ } tmpFree( (char *)logp ); /* Free the buffer */ if ( !send_ascii ) /* Send uuencode trailer */ stopdata(); return( rtn ); } /* getLogRecs() */ /************************************************************************/ /* Function : getlog */ /* Purpose : Get specified data log records */ /* Inputs : Parm Mask, LogBlk number, Log record number, number recs*/ /* Outputs : OK */ /************************************************************************/ Int16 getlog( Nat16 pmask, Nat16 log, Nat16 start, Nat16 nmbr ) { if ( (pmask & 3) != 3 ) return( ERROR ); if ( getLogRecs(log, start, ((pmask & 4) == 0) ? 1 : nmbr) == ERROR ) return( ERROR ); return( OK ); } /* getlog() */ #ifndef YMODEM /************************************************************************/ /* Function : dump */ /* Purpose : Dump entire log block(s) */ /* Inputs : Parm Mask, block number, number of blocks */ /* Outputs : OK */ /************************************************************************/ Int16 dump( Nat16 pmask, Nat16 blk, Nat16 nblks ) { Nat16 curblk; Reg Int16 rtn; if ( (pmask & 1) == 0 ) return( ERROR ); for ( curblk = blk; (curblk < (blk + ((pmask & 2) ? nblks : 1))); curblk++ ) if ( (rtn = getLogRecs(curblk, 0, NAT16_MAX)) != OK ) return( (rtn == ERROR) ? ERROR : OK ); return( OK ); } /* dump() */ #endif #ifndef GETDATA_NEWEST_FIRST /* Traditional way, oldest data first */ /************************************************************************/ /* Function : getdata */ /* Purpose : Get data since last data dump */ /* Inputs : None */ /* Outputs : OK */ /************************************************************************/ Int16 getdata( Void ) { LogRec *logp; MBool ok; if ( (logp = (LogRec *)tmpMalloc(sizeof(LogRec))) == NULL ) return( ERROR ); /* Get log buffer, rtn if none */ do { startdata(nextUsrLog.lp_blk); /* Send uuencode header */ while( (ok = !checkUsrInterrupt()) && logGetRec(&nextUsrLog, logp) ) putuu( logp ); stopdata(); /* Send uuencode trailer */ if ( ok && (nextUsrLog.lp_blk < nextFreeLog.lp_blk) ) logNextBlk( &nextUsrLog ); else ok = FALSE; } while( ok ); tmpFree( (char *)logp ); /* Free buffer */ return( OK ); } /* getdata() */ #else /* Newest data first, originally for M3 */ /************************************************************************/ /* Function : sendNextRec */ /* Purpose : Send one data record */ /* Inputs : LogPtr, LogRec buffer */ /* Outputs : TRUE to continue, FALSE to end */ /************************************************************************/ MBool sendNextRec( LogPtr *lp, LogRec *logp ) { if ( checkUsrInterrupt() ) return( FALSE ); if ( lp->lp_rcd <= 0 ) { if ( lp->lp_blk <= 0 ) return( FALSE ); lp->lp_blk--; lp->lp_memblk = MemBlk(lp->lp_blk); stopdata(); startdata(lp->lp_blk); bankCopy( Bank(lp->lp_memblk, 0), Addr(0), (Byte *)(&lp->lp_rcd), sizeof(LogRecNum) ); } lp->lp_rcd--; if ( lp->lp_blk < nextUsrLog.lp_blk ) return( FALSE ); if ( (lp->lp_blk == nextUsrLog.lp_blk) && (lp->lp_rcd < nextUsrLog.lp_rcd) ) return( FALSE ); if ( !logSearch(lp) || !logGetRec(lp, logp) ) return( FALSE ); putuu( logp ); lp->lp_rcd--; /* logGetRec incremented it */ return( TRUE ); } /* sendNextRec() */ /************************************************************************/ /* Function : getdata */ /* Purpose : Get data since last data dump */ /* Inputs : None */ /* Outputs : OK */ /************************************************************************/ Int16 getdata( Void ) { LogRec *logp; LogPtr logToSend, lastLog; if ( (logp = (LogRec *)tmpMalloc(sizeof(LogRec))) == NULL ) return( ERROR ); /* Get log buffer, rtn if none */ bcopy( (Byte *)&nextFreeLog, (Byte *)&logToSend, sizeof(LogPtr) ); bcopy( (Byte *)&nextFreeLog, (Byte *)&lastLog, sizeof(LogPtr) ); startdata(logToSend.lp_blk); /* Send uuencode header */ while( sendNextRec(&logToSend, logp) ) ; stopdata(); /* Send uuencode trailer */ bcopy( (Byte *)&lastLog, (Byte *)&nextUsrLog, sizeof(LogPtr) ); tmpFree( (char *)logp ); return( OK ); } /* getdata() */ #endif /* GETDATA_NEWEST_FIRST */ /************************************************************************/ /* Function : getlognmbrs */ /* Purpose : Get Log Record numbers */ /* Inputs : None */ /* Outputs : OK */ /************************************************************************/ Int16 getlognmbrs(Void) { Reg LogBlk curBlk, oldBlk; LogRecNum numRcds; curBlk = nextFreeLog.lp_blk; if ( curBlk >= MEMBLKS_USED ) oldBlk = curBlk - MEMBLKS_USED + 1; else oldBlk = 0; xprintf("Log blocks in memory: %u to %u\n", oldBlk, curBlk); bankCopy( Bank(nextFreeLog.lp_memblk, 0), Addr(0), (Byte *)(&numRcds), sizeof(LogRecNum) ); /* Get nmbr rcds in block */ xprintf("Log records in block %u: %u\n", curBlk, nextFreeLog.lp_rcd ); #ifdef DISK xprintf("Log blocks written to disk: %u with %u errors\n", dskBlksWritten, dskBlkErrors); #endif } /* getlognmbrs() */ /************************************************************************/ /* Function : showDrivers */ /* Purpose : Tell user what drivers are in the system */ /* Inputs : None */ /* Outputs : None */ /************************************************************************/ Void showDrivers( Void ) { Reg Driver *dp; for ( dp = (Driver *)(drv_list.lst_head); dp != DRV_NULL; dp = dp->drv_next ) { asm push dp; xprintf( "%20s ", dp->drv_name ); asm ld dp, [SP]; if ( dp->drv_td != NULLTID ) xputs("Sampling\n"); else if ( dp->drv_parms[INTERVAL] == 0 ) xputs("Off\n"); else xprintf( "%u secs\n", (Nat16)(dp->drv_wakeup - tod) ); asm pop dp; } } /* showDrivers() */ /************************************************************************/ /* Function : drvUsrFunc */ /* Purpose : Perform driver user function */ /* Inputs : Drvr name, Time til func, parameter, function flag */ /* Outputs : OK */ /************************************************************************/ Int16 drvUsrFunc( char *name, Nat16 functime, Nat16 usrparm, Nat16 funcflag ) { Reg Driver *dp; if ( (dp = drvr_find(name)) == DRV_NULL ) return( ERROR ); dp->drv_usrparm = usrparm; dp->drv_wakeup = tod + functime; dp->drv_flags |= funcflag; return( OK ); } /* drvUsrFunc() */ /************************************************************************/ /* Function : aux */ /* Purpose : Perform Sensor auxiliary function */ /* Inputs : Parm Mask, Driver name, Time til do function */ /* Outputs : OK */ /************************************************************************/ Int16 aux( Nat16 pmask, char *name, Nat16 auxtime, Nat16 parm ) { return( drvUsrFunc(name, auxtime, parm, DO_AUX) ); } /* aux() */ /************************************************************************/ /* Function : init */ /* Purpose : Initialize driver */ /* Inputs : Parm Mask, Driver name, Time til init, parameter */ /* Outputs : OK */ /************************************************************************/ Int16 init( Nat16 pmask, char *name, Nat16 inittime, Nat16 parm ) { return( drvUsrFunc(name, inittime, parm, DO_INIT) ); } /* init() */ /************************************************************************/ /* Function : sync */ /* Purpose : Sync sensor */ /* Inputs : Parm Mask, Driver to sync (dflt ADCP), Time til do sync*/ /* Outputs : OK */ /************************************************************************/ Int16 sync( Nat16 pmask, char *name, Nat16 synctime, Nat16 parm ) { return( drvUsrFunc(name, synctime, parm, DO_SYNC) ); } /* sync() */ /************************************************************************/ /* Function : promptparm */ /* Purpose : Display parameter */ /* Inputs : Driver ptr, Parameter number */ /* Outputs : None */ /************************************************************************/ MBool promptparm( Driver *dp, Nat16 parm ) { const ParmDesc *pp; pp = &drvprompts[parm]; xprintf( "%20s ", pp->prompt ); if ( pp->radix == 16 ) xprintf( "hex %x ", *(Nat16 *)((Byte *)dp + pp->offset) ); else xprintf( "dec %u ", *(Nat16 *)((Byte *)dp + pp->offset) ); } /* promptparm() */ /************************************************************************/ /* Function : getparm */ /* Purpose : Get parameter value from user */ /* Inputs : Ptr to place for answer, radix */ /* Outputs : TRUE if got valid number */ /* Comments : Uses user command buffer, size is USR_BUFSIZE (256) */ /************************************************************************/ MBool getparm( Nat16 *result, Nat16 radix, Byte *buffer ) { Byte *p; p = buffer; if ( xgets_tmout((char *)buffer, USR_BUFSIZE, 30) > 0 ) return( getnum((char **)&p, (Int16 *)result, radix) ); return( FALSE ); } /* getparm() */ /************************************************************************/ /* Function : drvgetparms */ /* Purpose : Utility routine for drvparms(), drvadd() */ /* Inputs : Driver pointer, user I/F buffer */ /* Outputs : None */ /************************************************************************/ Void drvgetparms( Driver *dp, Byte *buffer ) { Nat16 i, val; xprintf("Num Parameter Radix Value\n"); for ( i = 0; i < NPARMS; i++ ) { xprintf( " %2d ", i ); promptparm( dp, i ); xputc( '\n' ); } while( TRUE ) { xprintf("Select parm number (0 - %u) ", NPARMS - 1); if ( !getparm(&val, 10, buffer) || (val >= NPARMS) ) return; promptparm( dp, val ); getparm( (Nat16 *)((Byte *)dp + drvprompts[val].offset), drvprompts[val].radix, buffer ); } } /* drvgetparms() */ /************************************************************************/ /* Function : drvparms */ /* Purpose : Set Driver parameters */ /* Inputs : Parm mask, ptr to driver name */ /* Outputs : OK */ /************************************************************************/ Int16 drvparms(Nat16 pmask, char *name, Nat16 unused1, Nat16 unused2, Byte *buffer) { Reg Driver *dp; if ( (pmask & 1) && ((dp = drvr_find(name)) != DRV_NULL) ) drvgetparms( dp, buffer ); else showDrivers(); return( OK ); } /* drvparms() */ /************************************************************************/ /* Function : drvadd */ /* Purpose : Add a driver to driver list */ /* Inputs : Parm mask, driver name, sample and serial wakeup funcs */ /* Outputs : OK or ERROR */ /************************************************************************/ Int16 drvadd( Nat16 pmask, char *name, Void (*sample)(), MBool (*wake)(), Byte *buffer ) { Driver *dp; DrvDesc drvdsc; if ( ((pmask & 3) != 3) || (drvr_find(name) != DRV_NULL) ) return( ERROR ); bzero( (Byte *)&drvdsc, sizeof(DrvDesc) ); drvdsc.dd_name = name; drvdsc.dd_task = sample; drvdsc.dd_serwake = (pmask & 4) ? wake : null_func; if ( ((Nat16)sample < 0x2080) || ((Nat16)(drvdsc.dd_serwake) < 0x2080) ) { xputs("Bad function address\n"); return( ERROR ); } if ( (dp = drvr_create(&drvdsc)) != DRV_NULL ) { drvgetparms( dp, buffer ); list_add( &drv_list, (Node *)dp ); } return( OK ); } /* drvadd() */ /************************************************************************/ /* Function : drvdel */ /* Purpose : Delete a driver from driver list */ /* Inputs : Parm mask, ptr to driver name */ /* Outputs : OK */ /************************************************************************/ Int16 drvdel(Nat16 pmask, char *name) { Driver *dp; if ( ((pmask & 1) == 0) || ((dp = drvr_find(name)) == DRV_NULL) ) showDrivers(); else { list_get( &drv_list, (Node *)dp ); permFree( (char *)dp ); } return( OK ); } /* drvdel() */ #define LOAD_DONE 1 /************************************************************************/ /* Function : loadOneHexRec */ /* Purpose : Load one Intel Hex record */ /* Inputs : Pointer to record */ /* Outputs : OK, ERROR, or LOAD_DONE */ /************************************************************************/ Int16 loadOneHexRec( Byte *rcd ) { Reg Byte *p; Reg Byte chksum; Reg Int16 i, c, len; p = rcd; /* Point to start of record */ if ( *p++ != ':' ) /* Look for leading ':' */ return( ERROR ); len = getByte( (char *)p, 16 ); /* Get hex record length */ for ( i = chksum = 0; i < len + 5; i++, p+=2 ) { /* Convert ASCII to hex */ if ( (c = getByte((char *)p, 16)) == ERROR ) return( ERROR ); rcd[i] = c; /* Note - converts in place */ chksum += c; } if ( chksum != 0 ) /* Check checksum */ return( ERROR ); /* Return if bad */ if ( (c =rcd[3]) == 1 ) /* Check record type */ return( LOAD_DONE ); /* If end of file, return */ else if ( c == 3 ) /* If start address, ignore */ return( OK ); else if ( c != 0 ) /* If bad type, error */ return( ERROR ); /* If all OK, copy the data */ bcopy( rcd+4, (Byte *)(((Nat16)rcd[1] << 8) + rcd[2]), len ); return( OK ); } /* loadOneHexRec() */ /************************************************************************/ /* Function : load */ /* Purpose : Load Intel Hex file */ /* Inputs : Parm mask, Buffer pointer */ /* Outputs : OK or error */ /* Comment : Buffer is user buffer from userif, size is USR_BUFSIZE */ /************************************************************************/ Int16 load(Nat16 pmask, Nat16 unused1, Nat16 unused2, Nat16 unused3, Byte *buffer) { Reg Int16 rtn; while ( (rtn = xgets_tmout((char *)buffer, USR_BUFSIZE - 1, 30)) >= 0 ) if ( rtn > 0 ) if ( (rtn = loadOneHexRec(buffer)) != OK ) break; /* Get all hex records */ progRamChksum = chkProgRam(); /* When done, recompute */ /* program RAM chksum */ return( (rtn == ERROR) ? ERROR : OK ); /* Return OK or ERROR */ } /* load() */ @