Files
pcas/src/RTEMS/base/rtems_init.c
T

313 lines
7.8 KiB
C

/*************************************************************************\
* Copyright (c) 2002 The University of Saskatchewan
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* RTEMS startup task for EPICS
* $Id$
* Author: W. Eric Norum
* eric.norum@usask.ca
* (306) 966-5394
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <errno.h>
#include <syslog.h>
#include <sys/termios.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <syslog.h>
#include <rtems.h>
#include <rtems/error.h>
#include <rtems/stackchk.h>
#include <rtems/rtems_bsdnet.h>
#include <rtems/tftp.h>
#include <epicsThread.h>
#include <logClient.h>
#include <iocsh.h>
static void logReset (void);
/*
***********************************************************************
* FATAL ERROR REPORTING *
***********************************************************************
*/
/*
* Delay for a while, then terminate
*/
static void
delayedPanic (const char *msg)
{
rtems_interval ticksPerSecond;
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
rtems_task_wake_after (ticksPerSecond);
rtems_panic (msg);
}
/*
* Log error and terminate
*/
void
LogFatal (const char *msg, ...)
{
va_list ap;
va_start (ap, msg);
vsyslog (LOG_ALERT, msg, ap);
va_end (ap);
delayedPanic (msg);
}
/*
* Log RTEMS error and terminate
*/
void
LogRtemsFatal (const char *msg, rtems_status_code sc)
{
syslog (LOG_ALERT, "%s: %s", msg, rtems_status_text (sc));
delayedPanic (msg);
}
/*
* Log network error and terminate
*/
void
LogNetFatal (const char *msg, int err)
{
syslog (LOG_ALERT, "%s: %d", msg, err);
delayedPanic (msg);
}
/*
***********************************************************************
* REMOTE FILE ACCESS *
***********************************************************************
*/
/*
* Add TFTP server and target prefix to pathnames
*/
static void
rtems_set_directory (void)
{
char *path;
int pathsize = 200;
int l;
if ((path = malloc (pathsize)) == NULL)
LogFatal ("Can't create TFTP path name -- no memory.\n");
strcpy (path, "/TFTP/BOOTP_HOST/epics/");
l = strlen (path);
if (gethostname (&path[l], pathsize - l - 2) || (path[l] == '\0'))
LogFatal ("Can't get host name");
strcat (path, "/");
if (chdir (path) < 0)
LogFatal ("Can't set initial TFTP directory");
}
/*
***********************************************************************
* RTEMS/EPICS COMMANDS *
***********************************************************************
*/
/*
* RTEMS status
*/
static void
rtems_netstat (unsigned int level)
{
rtems_bsdnet_show_if_stats ();
rtems_bsdnet_show_mbuf_stats ();
if (level >= 1) {
rtems_bsdnet_show_inet_routes ();
}
if (level >= 2) {
rtems_bsdnet_show_ip_stats ();
rtems_bsdnet_show_icmp_stats ();
rtems_bsdnet_show_udp_stats ();
rtems_bsdnet_show_tcp_stats ();
}
}
static const iocshArg netStatArg0 = { "level",iocshArgInt};
static const iocshArg * const netStatArgs[1] = {&netStatArg0};
static const iocshFuncDef netStatFuncDef = {"netstat",1,netStatArgs};
static void netStatCallFunc(const iocshArgBuf *args)
{
rtems_netstat(args[0].ival);
}
static const iocshFuncDef stackCheckFuncDef = {"stackCheck",0,NULL};
static void stackCheckCallFunc(const iocshArgBuf *args)
{
Stack_check_Dump_usage ();
}
/*
* Register RTEMS-specific commands
*/
static void iocshRegisterRTEMS (void)
{
iocshRegister(&netStatFuncDef, netStatCallFunc);
iocshRegister(&stackCheckFuncDef, stackCheckCallFunc);
}
/*
* Set up the console serial line (no handshaking)
*/
static void
initConsole (void)
{
struct termios t;
if (tcgetattr (fileno (stdin), &t) < 0) {
printf ("tcgetattr failed: %s\n", strerror (errno));
return;
}
t.c_iflag &= ~(IXOFF | IXON | IXANY);
if (tcsetattr (fileno (stdin), TCSANOW, &t) < 0) {
printf ("tcsetattr failed: %s\n", strerror (errno));
return;
}
}
/*
* Ensure that the configuration object files
* get pulled in from the library
*/
extern rtems_configuration_table Configuration;
extern struct rtems_bsdnet_config rtems_bsdnet_config;
const void *rtemsConfigArray[] = {
&Configuration,
&rtems_bsdnet_config
};
/*
* RTEMS Startup task
*/
rtems_task
Init (rtems_task_argument ignored)
{
int i;
char arg0[] = "RTEMS_IOC";
char arg1[] = "st.cmd";
char *argv[3] = { arg0, arg1, NULL };
rtems_interval ticksPerSecond;
/*
* Get configuration
*/
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
/*
* Create a reasonable environment
*/
initConsole ();
putenv ("TERM=xterm");
putenv ("IOCSH_PS1=epics> ");
putenv ("IOCSH_HISTSIZE=20");
/*
* Start network
*/
printf ("***** Initializing network *****\n");
rtems_bsdnet_initialize_network ();
printf ("***** Initializing TFTP *****\n");
rtems_bsdnet_initialize_tftp_filesystem ();
for (i = 0 ; ; i++) {
printf ("***** Initializing NTP *****\n");
if (rtems_bsdnet_synchronize_ntp (0, 0) >= 0)
break;
rtems_task_wake_after (5*ticksPerSecond);
if (i >= 12) {
rtems_status_code sc;
rtems_time_of_day now;
printf (" *************** WARNING ***************\n");
printf (" ***** NO RESPONSE FROM NTP SERVER *****\n");
printf (" ***** TIME SET TO DEFAULT VALUE *****\n");
printf (" ***************************************\n");
now.year = 2001;
now.month = 1;
now.day = 1;
now.hour = 0;
now.minute = 0;
now.second = 0;
now.ticks = 0;
if ((sc = rtems_clock_set (&now)) != RTEMS_SUCCESSFUL)
printf ("***** Can't set time: %s\n", rtems_status_text (sc));
break;
}
}
printf ("***** Initializing syslog *****\n");
openlog ("IOC", LOG_CONS, LOG_DAEMON);
logReset ();
/*
* Run the EPICS startup script
*/
printf ("***** Starting EPICS application *****\n");
iocshRegisterRTEMS ();
rtems_set_directory ();
i = main ((sizeof argv / sizeof argv[0]) - 1, argv);
printf ("***** IOC application terminating *****\n");
exit (i);
}
/*
* Architecture-dependent routines
*/
#ifdef __mcpu32__
#include <m68360.h>
static void
logReset (void)
{
int bit, rsr;
int i;
const char *cp;
char cbuf[80];
rsr = m360.rsr;
for (i = 0, bit = 0x80 ; bit != 0 ; bit >>= 1) {
if (rsr & bit) {
switch (bit) {
case 0x80: cp = "RESETH*"; break;
case 0x40: cp = "POWER-UP"; break;
case 0x20: cp = "WATCHDOG"; break;
case 0x10: cp = "DOUBLE FAULT"; break;
case 0x04: cp = "LOST CLOCK"; break;
case 0x02: cp = "RESET"; break;
case 0x01: cp = "RESETS*"; break;
default: cp = "??"; break;
}
i += sprintf (cbuf+i, cp);
rsr &= ~bit;
if (rsr)
i += sprintf (cbuf+i, ", ");
else
break;
}
}
syslog (LOG_NOTICE, "Startup after %s.", cbuf);
printf ("Startup after %s.\n", cbuf);
m360.rsr = ~0;
}
#else
static void
logReset (void)
{
syslog (LOG_NOTICE, "Started.");
}
#endif