From 60b23ffe0ebe90edf205250f5245b84630b176cb Mon Sep 17 00:00:00 2001 From: cvs Date: Mon, 6 Nov 2000 13:05:25 +0000 Subject: [PATCH] Main server program for sinqhm_srv --- sinqhm/sinqhm_srv_main.c | 361 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 361 insertions(+) create mode 100755 sinqhm/sinqhm_srv_main.c diff --git a/sinqhm/sinqhm_srv_main.c b/sinqhm/sinqhm_srv_main.c new file mode 100755 index 00000000..d62e611a --- /dev/null +++ b/sinqhm/sinqhm_srv_main.c @@ -0,0 +1,361 @@ +#define IDENT "1D02" +/* +** +--------------------------------------------------------------+ +** | Paul Scherrer Institute | +** | SINQ Division | +** | | +** | This software may be used freely by non-profit organizations.| +** | It may be copied provided that the name of P.S.I. and of the | +** | author is included. Neither P.S.I. nor the author assume any | +** | responsibility for the use of this software outside of P.S.I.| +** +--------------------------------------------------------------+ +** +** Module Name . . . . . . . . : [...SinqHM]SinqHM_srv_main.c +** +** Author . . . . . . . . . . : D. Maden +** Date of creation . . . . . . : Oct 1996 +** +** Updates: +** 1A01 1-Oct-1996 DM Initial version. +** 1B01 16-Jul-1997 DM Flush fibre-optic FIFO on SQHM_ZERO and SQHM_WRITE. +** 1C01 24-Jun-1998 DM Add TOF support. +** 1C06 10-Aug-1999 DM Add instrument dependent conditional code. +**--------------------------------------------------------------------------- +** SinqHM_srv_main.c is the main program of a SINQ Histogram Memory process +** which will run in a front-end processor and perform the necessary +** operations for a SINQ multi-detector. +** +** Communication between SinqHM_srv and the client is via TCP/IP protocol. +** +** To compile and link this program for VxWorks on PSS123, use: +** + ccvx '-DINST=""' SinqHM_srv_main.c + ccvx '-DINST=""' SinqHM_srv_routines.c + ccvx '-DINST=""' SinqHM_srv_filler.c + ccvx '-DINST=""' SinqHM_srv_server.c +** where + ccvx = ccppc -O0 \ + -mcpu=603 \ + -I${WIND_BASE}/target/h \ + -fno-builtin \ + -fno-for-scope \ + -nostdinc \ + -DCPU=PPC603 \ + -D_GNU_TOOL \ + -gdwarf -c -Wimplicit +** and +** = DMC, SANS, FOCUS, HRPT, TRICS or POLDI + + ldppc -o SinqHM_srv.o -r SinqHM_srv_main.o \ + SinqHM_srv_routines.o \ + SinqHM_srv_filler.o \ + SinqHM_srv_server.o + +** and, on the target, +** +** -> ld < /home/pss123/aco/maden/wind/SinqHM/SinqHM_srv.o +** -> taskSpawn "SinqHM_srv", 100, 8, 20000, SinqHM_srv, +** ^ +** | +** default = 2400 ------+ +** +**==================================================================== +*/ +#include "vxWorks.h" +#include "taskLib.h" +#include "msgQLib.h" +#include "sockLib.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* Get POSIX signal definitions. */ +#include +#include /* Get POSIX mem mgmnt definitions. */ +#include /* Get POSIX wait definitions. */ +/* +**==================== Global Definitions ===================================== +*/ +#include "SinqHM_def.h" +#include "SinqHM_gbl.h" +/* + +**============================================================================= +** Local routines. +** +** None +*/ +/*============================================================================== + +** Main line program +** ------------------ +**============================================================================*/ + int SinqHM_srv (int port, int use_level_gen, char *base_addr, + int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, + int suspend) { +/*============================================================================*/ + struct req_buff_struct req_buff; + struct rply_buff_struct rply_buff; + + int i, j, is, status, cntr; + int keep_going = OK; + int bytes_to_come, n_bytes_got; + char *p_addr; + int cl_port; + int do_send; + int cnct_skt; /* Connection socket */ + int rw_skt; /* Read/write socket */ + struct sockaddr_in lcl_sockname; + struct sockaddr_in rmt_sockname; + int rmt_sockname_len; + int pkt_size; + time_t timer; + + sigset_t proc_sigmask; + struct sigaction sig_action; + +/*============================================================================ +*/ + if (suspend != 0) { + printf ("\nSinqHM_srv: Suspending ...\n"); + taskSuspend (0); /* We've been told to suspend ourself, .. + ** .. presumably for debug reasons. + */ + printf ("\nSinqHM_srv: Suspension ended!\n"); + } +/*============================================================================ +** Perform the initialisation of global variables ... +*/ + StrJoin (Instr_name, sizeof (Instr_name), INST, ""); /* Save the instr. + ** name in a global + */ + StrJoin (Def_ident, sizeof (Def_ident), SINQHM_DEF_ID, ""); + StrJoin (Sqhm_main_ident, sizeof (Sqhm_main_ident), IDENT, ""); + StrJoin (Sqhm_main_date, sizeof (Sqhm_main_date), __DATE__, ", "); + StrJoin (Sqhm_main_date, sizeof (Sqhm_main_date), Sqhm_main_date, __TIME__); + SinqHM_server_setup_id (); + SinqHM_filler_setup_id (); + SinqHM_routines_setup_id (); + time (&Sqhm_start_time); /* Initialise the start time */ + + StrJoin (Tsk_name[0], sizeof (Tsk_name[0]), taskName (get_pid ()), ""); + + Dbg_mask = 0; + Dbg_lev0 = 0; + Dbg_lev1 = 0; + Dbg_lev2 = 0; + Dbg_lev3 = 0; + Cfgn_done = 0; /* Force a configuration before we can do anything. */ + + free_HM_memory (NULL); /* Release memory (possibly) in case .. + ** .. of a restart of the program */ + Parent_pid = get_pid (); + Filler_pid = 0; + for (i = 0; i <= MAX_CLIENTS; i++) { + Child_pid[i] = 0; + Child_exit_status[i] = 0; + } + + if (Sem_Filler == NULL) { + Sem_Filler = semBCreate (SEM_Q_FIFO, SEM_FULL); + } + + if (Sem_Server == NULL) { + Sem_Server = semBCreate (SEM_Q_FIFO, SEM_FULL); + } +/* +** Debug hint - set Use_sem_tmo to zero to disable semaphore time-outs +** during debug sessions. This will stop FILLER falling off. +*/ + Sem_tmo = 10; /* 10 second time-out by default */ + Use_sem_tmo = 0; + + setupLevelGenerator (use_level_gen, base_addr); +/*============================================================================ +** Clear the process signal mask to let in all signals (actually, on +** PPC VxWorks this seems to cause all signals to get ignored!) and then +** declare action routine for SIGUSR1. Our children signal with SIGUSR1 +** just before they exit in a more or less controlled manner. If the +** child gets deleted from the shell, it will not signal. +*/ + Cnt_SIGUSR1 = 0; + + status = sigemptyset (&proc_sigmask); + status = sigprocmask (SIG_SETMASK, &proc_sigmask, NULL); + status = sigemptyset (&sig_action.sa_mask); + sig_action.sa_handler = catch_signal; + sig_action.sa_flags = 0; + + if (sigaction (SIGUSR1, &sig_action, NULL) == -1) { + getErrno (&My_errno); + perror ("sigaction error:"); + exit (0); + } +/*============================================================================ +** Get a port number to use. If the argument "port" is not +** a valid port number (not in range 128 to 32767), use PORT_BASE. +*/ + Port_base = PORT_BASE; + if ((port >= 128) && (port < 32768)) Port_base = port; +/*============================================================================ +** Create a TCP/IP socket for receiving connection requests, bind it and +** set it to listen. +*/ + cnct_skt = socket (AF_INET, SOCK_STREAM, 0); + if (cnct_skt == -1) + failInet_port ("\nhmRoot%d -- Cnct-Socket socket error", Port_base); + lcl_sockname.sin_family = AF_INET; + lcl_sockname.sin_port = htons (Port_base); + lcl_sockname.sin_addr.s_addr = 0; + status = bind (cnct_skt, (struct sockaddr *) &lcl_sockname, + sizeof (lcl_sockname)); + if (status != 0) failInet_port ("\nhmRoot%d -- Cnct-Socket bind error", + Port_base); + status = listen (cnct_skt, 5); + if (status != 0) failInet_port ("\nhmRoot%d -- Cnct-Socket listen error", + Port_base); +/* +** Clients must now connect to the Connect-port and send either a +** connect, configure, deconfigure, status or exit request. A +** successful configure request must precede any connection request. +** +** When a configure request arrives, the histogram data structures are +** initialised, the histogram filler process (FILLER) is spawned and +** connection requests are enabled. A status reply is sent to the +** client and the connection closed. +** +** When a connection request arrives, a child will be spawned to +** handle the connection. The child will be told which port to use +** and he will release a semaphore when the port is ready. The parent +** then sends the client a reply to tell him which port to use. The +** connection is then closed to await further connections. +*/ + setup_inet_info (Inet_host, sizeof (Inet_host), /* Find out who we are */ + Inet_addr, sizeof (Inet_addr)); + printf ("\n%s: Program Ident = \"%s\". Started on %s (%s).\n", + Tsk_name[0], IDENT, Inet_host, Inet_addr); + printf ("%s: Protocol Ident = \"%s\"\n", Tsk_name[0], SINQHM_DEF_ID); + +#ifndef INST + #error Define the target instrument via the symbol "INST"! +#endif + + if (strcmp (INST, "DMC") == 0) { + printf ("%s: Instrument = \"%s\"\n", Tsk_name[0], "DMC"); + Lwl_hdr_daq_mask = LWL_HDR_NRL_MASK; + Lwl_hdr_daq_soll = 0; + }else if (strcmp (INST, "SANS") == 0) { + printf ("%s: Instrument = \"%s\"\n", Tsk_name[0], "SANS"); + Lwl_hdr_daq_mask = LWL_HDR_NRL_MASK; + Lwl_hdr_daq_soll = 0; + }else if (strcmp (INST, "FOCUS") == 0) { + Lwl_hdr_daq_mask = LWL_HDR_NRL_MASK | LWL_HDR_SYNC2_MASK; + Lwl_hdr_daq_soll = 0; + printf ("%s: Instrument = \"%s\"\n", Tsk_name[0], "FOCUS"); + }else if (strcmp (INST, "HRPT") == 0) { + printf ("%s: Instrument = \"%s\"\n", Tsk_name[0], "HRPT"); + Lwl_hdr_daq_mask = LWL_HDR_SYNC0_MASK | LWL_HDR_SYNC2_MASK; + Lwl_hdr_daq_soll = LWL_HDR_SYNC2_MASK; + }else if (strcmp (INST, "TRICS") == 0) { + printf ("%s: Instrument = \"%s\"\n", Tsk_name[0], "TriCS"); + Lwl_hdr_daq_mask = LWL_HDR_NRL_MASK; + Lwl_hdr_daq_soll = 0; + printf ("%s: Warning -- Lwl_hdr_daq_mask and Lwl_hdr_daq_soll are " + "provisional!\n", Tsk_name[0]); + }else if (strcmp (INST, "POLDI") == 0) { + printf ("%s: Instrument = \"%s\"\n", Tsk_name[0], "POLDI"); + Lwl_hdr_daq_mask = LWL_HDR_NRL_MASK; + Lwl_hdr_daq_soll = 0; + printf ("%s: Warning -- Lwl_hdr_daq_mask and Lwl_hdr_daq_soll are " + "provisional!\n", Tsk_name[0]); + }else { + printf ("%s: Instrument is not defined\n", Tsk_name[0]); + Lwl_hdr_daq_mask = LWL_HDR_NRL_MASK; + Lwl_hdr_daq_soll = 0; + } + printf ("%s: Lwl_hdr_daq_mask = 0x%08x", Tsk_name[0], Lwl_hdr_daq_mask); + if ((Lwl_hdr_daq_mask & LWL_HDR_NRL_MASK) != 0) printf (" NRL"); + if ((Lwl_hdr_daq_mask & LWL_HDR_SYNC3_MASK) != 0) printf (" SYNC3"); + if ((Lwl_hdr_daq_mask & LWL_HDR_SYNC2_MASK) != 0) printf (" SYNC2"); + if ((Lwl_hdr_daq_mask & LWL_HDR_SYNC1_MASK) != 0) printf (" SYNC1"); + if ((Lwl_hdr_daq_mask & LWL_HDR_SYNC0_MASK) != 0) printf (" SYNC0"); + printf ("\n%s: Lwl_hdr_daq_soll = 0x%08x", Tsk_name[0], Lwl_hdr_daq_soll); + if ((Lwl_hdr_daq_soll & LWL_HDR_NRL_MASK) != 0) printf (" NRL"); + if ((Lwl_hdr_daq_soll & LWL_HDR_SYNC3_MASK) != 0) printf (" SYNC3"); + if ((Lwl_hdr_daq_soll & LWL_HDR_SYNC2_MASK) != 0) printf (" SYNC2"); + if ((Lwl_hdr_daq_soll & LWL_HDR_SYNC1_MASK) != 0) printf (" SYNC1"); + if ((Lwl_hdr_daq_soll & LWL_HDR_SYNC0_MASK) != 0) printf (" SYNC0"); + printf ("\n"); + + while (keep_going == OK) { + rmt_sockname_len = sizeof (rmt_sockname); + rw_skt = accept (cnct_skt, (struct sockaddr *) &rmt_sockname, + &rmt_sockname_len); + if (rw_skt == -1) { + getErrno (&My_errno); + failInet_port ("\nhmRoot%d -- Cnct-Socket accept error", Port_base); + /* No return */ + } + Rw_bytes_got = 0; Rw_bytes_put = 0; + + p_addr = inet_ntoa (rmt_sockname.sin_addr); + cl_port = ntohs (rmt_sockname.sin_port); + printf ("\n%s: Connected to Host %s, Port %d.\n", + Tsk_name[0], p_addr, cl_port); + + bytes_to_come = sizeof (req_buff); /* Read a command */ + p_addr = (char *) &req_buff; + while (bytes_to_come > 0) { + n_bytes_got = recv (rw_skt, p_addr, bytes_to_come, 0); + if (n_bytes_got <= 0) break; + Rw_bytes_got += n_bytes_got; + bytes_to_come -= n_bytes_got; + p_addr += n_bytes_got; + } + + if (Cnt_SIGUSR1 > 0) { /* Have any children exited? */ + if (Dbg_lev0) printf ("hmRoot%d: Cleaning up children ...", Port_base); + cleanup_children (); /* Yes, update our database. */ + if (Dbg_lev0) printf ("\n ... cleanup of children done.\n"); + } + + if (n_bytes_got < 0) { + printf ("\007" + "%s -- R/W-Socket recv error\n", Tsk_name[0]); + printf ("%s -- Connection to %s will be closed.\n", Tsk_name[0], + inet_ntoa (rmt_sockname.sin_addr)); + }else if (n_bytes_got == 0) { + printf ("\007" + "%s -- no command received!\n", Tsk_name[0]); + printf ("%s -- Connection to %s will be closed.\n", Tsk_name[0], + inet_ntoa (rmt_sockname.sin_addr)); + }else if (n_bytes_got != sizeof (req_buff)) { + printf ("\007" + "%s -- command packet has wrong number of bytes:" + " %d instead of %d\n", Tsk_name[0], + n_bytes_got, sizeof (req_buff)); + printf ("%s -- Connection to %s will be closed.\n", Tsk_name[0], + inet_ntoa (rmt_sockname.sin_addr)); + }else if (ntohl (req_buff.bigend) != 0x12345678) { + printf ("\007" + "%s -- big-endian/little-endian problem!\n" + " Buffer received in non-network byte order!\n", Tsk_name[0]); + }else { + do_command (0, rw_skt, 4096, &req_buff, &rply_buff); + } + close (rw_skt); + if (ntohl (req_buff.cmnd) == SQHM_EXIT) keep_going = !OK; + } + close (cnct_skt); + exit (KER__SUCCESS); + } +/*========================================= End of SinqHM_srv_main.c ========*/