LWL Test Generator server
This commit is contained in:
481
sinqhm/lwl_server.c
Executable file
481
sinqhm/lwl_server.c
Executable file
@ -0,0 +1,481 @@
|
||||
#define ident "1B03"
|
||||
/*
|
||||
** +--------------------------------------------------------------+
|
||||
** | Paul Scherrer Institute |
|
||||
** | Computing Section |
|
||||
** | |
|
||||
** | 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]LWL_SERVER.C
|
||||
**
|
||||
** Author . . . . . . . . . . : D. Maden
|
||||
** Date of creation . . . . . . : Oct 1996
|
||||
**
|
||||
** Updates:
|
||||
** 1A01 1-Oct-1996 DM Initial version.
|
||||
**---------------------------------------------------------------------------
|
||||
** LWL_SERVER.C is the main program of a SINQ Histogram Memory process
|
||||
** which will run in a front-end processor, accept a TCP/IP connection
|
||||
** and transfer received data into the LWL (Licht-Wellen-Leiter) Test
|
||||
** generator.
|
||||
**
|
||||
** To compile this program for VxWorks on PSS123, use:
|
||||
**
|
||||
ccvx lwl_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, on the target,
|
||||
**
|
||||
** -> ld < lwl_server.o
|
||||
** -> taskSpawn "lwl_server", 100, 8, 20000, lwl_server, \
|
||||
** <port>, <base-addr>, <verbose>
|
||||
** ^ ^ ^
|
||||
** | | |
|
||||
** default = 3501 ------+ | |
|
||||
** default = 0x1800 --------------+ |
|
||||
** verbose mode if non-zero ------------------+
|
||||
**
|
||||
** To suppress VME access, e.g. for test purposes, compile with the
|
||||
** option
|
||||
** -D_NO_VME
|
||||
**====================================================================
|
||||
*/
|
||||
#include <vxWorks.h>
|
||||
#include <taskLib.h>
|
||||
#include <msgQLib.h>
|
||||
#include <sockLib.h>
|
||||
#include <hostLib.h>
|
||||
#include <inetLib.h>
|
||||
#include <sysLib.h>
|
||||
#include <vme.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
/*** #include <sys/file.h> ***/ /* Get POSIX file definitions. */
|
||||
|
||||
#include <signal.h> /* Get POSIX signal definitions. */
|
||||
#include <sys/mman.h> /* Get POSIX mem mgmnt definitions. */
|
||||
#include <sys/wait.h> /* Get POSIX wait definitions. */
|
||||
|
||||
#include "vmio10_def.h"
|
||||
/*
|
||||
**==================== Global Definitions =====================================
|
||||
*/
|
||||
#define DFLT_PORT 3501
|
||||
#define DFLT_BASE_ADDR 0x1800
|
||||
/*
|
||||
**==================== Global Variables =====================================
|
||||
*/
|
||||
char *LwlBase;
|
||||
char Lwl_dummy[64]; /* Dummy array - used only when VME access ..
|
||||
** .. is disabled. */
|
||||
|
||||
int Lwl_cnct_skt = 0; /* Connection socket */
|
||||
int Lwl_rw_skt = 0; /* Read/write socket */
|
||||
|
||||
char Lwl_inet_node[20];
|
||||
char Lwl_inet_addr[20];
|
||||
int Lwl_my_errno;
|
||||
/*
|
||||
|
||||
**=============================================================================
|
||||
** Local routines.
|
||||
** Forward references ...
|
||||
*/
|
||||
void lwl_enable ();
|
||||
void lwl_failInet (char *text);
|
||||
void lwl_getErrno (int *his_errno);
|
||||
void lwl_resetcio ();
|
||||
void lwl_setup_inet_info ();
|
||||
void lwl_vmio_byte_send (char bit8, char lobits);
|
||||
void lwl_vmio_init ();
|
||||
void lwl_vmio_send (char nbytes, char *buff);
|
||||
void lwl_vmio_tg_reset ();
|
||||
void lwl_vmio_transp_init ();
|
||||
/*
|
||||
**-----------------------------------------------------------------*/
|
||||
void lwl_enable () {
|
||||
/* ==========
|
||||
** output/input enable for IC6 ,IC7
|
||||
*/
|
||||
LwlBase[VMIO_AB_CNTL] = 0x01;
|
||||
LwlBase[VMIO_AB_CNTL] = 0x94;
|
||||
LwlBase[VMIO_CD_CNTL] = 0x01;
|
||||
LwlBase[VMIO_CD_CNTL] = 0x94;
|
||||
}
|
||||
/*
|
||||
**-----------------------------------------------------------------*/
|
||||
void lwl_failInet (char *text) {
|
||||
/* ============
|
||||
** Output the given text and exit the process.
|
||||
*/
|
||||
int my_errno;
|
||||
|
||||
lwl_getErrno (&my_errno);
|
||||
printf ("\n### Internet Error ###\n");
|
||||
printf (" ### errno = %d.\n", my_errno);
|
||||
perror (text);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
/*
|
||||
**-----------------------------------------------------------------*/
|
||||
void lwl_getErrno (int *his_errno) {
|
||||
/* ============
|
||||
*/
|
||||
*his_errno = errno; /* Make copy of errno */
|
||||
return;
|
||||
}
|
||||
/*
|
||||
**-----------------------------------------------------------------*/
|
||||
void lwl_resetcio () {
|
||||
/* ============
|
||||
** Software reset for cio
|
||||
*/
|
||||
char aux;
|
||||
|
||||
aux = LwlBase[VMIO_AB_CNTL];
|
||||
LwlBase[VMIO_AB_CNTL] = 0x00;
|
||||
|
||||
aux = LwlBase[VMIO_AB_CNTL];
|
||||
LwlBase[VMIO_AB_CNTL] = 0x00;
|
||||
LwlBase[VMIO_AB_CNTL] = 0x01;
|
||||
LwlBase[VMIO_AB_CNTL] = 0x00;
|
||||
|
||||
aux = LwlBase[VMIO_CD_CNTL];
|
||||
LwlBase[VMIO_CD_CNTL] = 0x00;
|
||||
aux = LwlBase[VMIO_CD_CNTL];
|
||||
LwlBase[VMIO_CD_CNTL] = 0x00;
|
||||
LwlBase[VMIO_CD_CNTL] = 0x01;
|
||||
LwlBase[VMIO_CD_CNTL] = 0x00;
|
||||
}
|
||||
/*
|
||||
**-----------------------------------------------------------------*/
|
||||
void lwl_setup_inet_info () {
|
||||
/* ===================
|
||||
** Get Internet Nodename and Address from System.
|
||||
*/
|
||||
int status;
|
||||
struct in_addr my_addr;
|
||||
|
||||
status = gethostname (Lwl_inet_node, sizeof (Lwl_inet_node));
|
||||
if (status != 0) sprintf (Lwl_inet_node, "Undefined");
|
||||
|
||||
my_addr.s_addr = hostGetByName (Lwl_inet_node);
|
||||
inet_ntoa_b (my_addr, Lwl_inet_addr);
|
||||
}
|
||||
/*
|
||||
**-----------------------------------------------------------------*/
|
||||
void lwl_vmio_byte_send (char bit8, char lobits) {
|
||||
/* ==================
|
||||
** Send a byte (well, 9 bits really) via the VMIO10.
|
||||
*/
|
||||
char aux;
|
||||
|
||||
do { /* Wait for Output Reg. empty */
|
||||
LwlBase[VMIO_AB_CNTL] = 0X09; /* Select Port B status reg .. */
|
||||
aux = LwlBase[VMIO_AB_CNTL]; /* .. and read it. */
|
||||
} while ((aux & 0x08) == 0); /* Test its "empty" bit */
|
||||
|
||||
LwlBase[VMIO_PORT_C] = bit8; /* Send Bit-8 */
|
||||
LwlBase[VMIO_PORT_B] = lobits; /* Output the other bits */
|
||||
}
|
||||
/*
|
||||
**-----------------------------------------------------------------*/
|
||||
void lwl_vmio_init () {
|
||||
/* =============
|
||||
** initialise VMIO10 Module
|
||||
*/
|
||||
LwlBase[VMIO_CD_CNTL] = 0x2A; /* Port D %00101010 */
|
||||
LwlBase[VMIO_CD_CNTL] = 0x00; /* %00000000, non inverting */
|
||||
LwlBase[VMIO_CD_CNTL] = 0x2B; /* %00101011 */
|
||||
LwlBase[VMIO_CD_CNTL] = 0x0F; /* %00001111, Run, EF0_S, Q2, Q1, Q0 */
|
||||
|
||||
LwlBase[VMIO_AB_CNTL] = 0x2A; /* Port B */
|
||||
LwlBase[VMIO_AB_CNTL] = 0x00;
|
||||
LwlBase[VMIO_AB_CNTL] = 0x2B;
|
||||
LwlBase[VMIO_AB_CNTL] = 0x00;
|
||||
|
||||
LwlBase[VMIO_AB_CNTL] = 0x22; /* Port A %00100010 */
|
||||
LwlBase[VMIO_AB_CNTL] = 0x00; /* %00000000, non inverting */
|
||||
LwlBase[VMIO_AB_CNTL] = 0x23; /* %00100011 */
|
||||
LwlBase[VMIO_AB_CNTL] = 0x00; /* %00000000, all output */
|
||||
|
||||
LwlBase[VMIO_CD_CNTL] = 0x22; /* Port C */
|
||||
LwlBase[VMIO_CD_CNTL] = 0x00;
|
||||
LwlBase[VMIO_CD_CNTL] = 0x23;
|
||||
LwlBase[VMIO_CD_CNTL] = 0x00;
|
||||
}
|
||||
/*
|
||||
**-----------------------------------------------------------------*/
|
||||
void lwl_vmio_send (
|
||||
/* ============= Send bytes to the LWL.
|
||||
*/ char nbytes,
|
||||
char *buff) {
|
||||
/*
|
||||
** The bytes are buff[0] to buff[nbytes-1]. buff[0] gives the
|
||||
** headerbit for buff[1]. The remainder are sent with the 9th
|
||||
** bit clear.
|
||||
*/
|
||||
int i;
|
||||
char aux;
|
||||
/*
|
||||
** ---------- loop sending the bytes ---------------
|
||||
*/
|
||||
LwlBase[VMIO_PORT_C] = 0; /* Mode = 0 */
|
||||
|
||||
if (nbytes < 2) return;
|
||||
lwl_vmio_byte_send (buff[0], buff[1]); /* 2 bytes define the first "LWL-byte" */
|
||||
|
||||
if (nbytes < 3) return;
|
||||
|
||||
for (i = 2; i < nbytes; i++) { /* The remaining bytes have Bit-8 = 0 */
|
||||
lwl_vmio_byte_send (0x00, buff[i]);
|
||||
}
|
||||
}
|
||||
/*
|
||||
**-----------------------------------------------------------------*/
|
||||
void lwl_vmio_tg_reset () {
|
||||
/* =================
|
||||
** Initialise VMIO10 Test Generator Piggyback
|
||||
*/
|
||||
LwlBase[VMIO_PORT_AB] = 0x02; /* Clear Write, Strobe */
|
||||
LwlBase[VMIO_PORT_C] = 0x00; /* Mode = 0 -> R,W = High */
|
||||
LwlBase[VMIO_PORT_C] = 0x07; /* Mode = reset */
|
||||
LwlBase[VMIO_PORT_C] = 0x00; /* Mode = 0 */
|
||||
}
|
||||
/*
|
||||
**-----------------------------------------------------------------*/
|
||||
void lwl_vmio_transp_init () {
|
||||
/* ====================
|
||||
** Initialise VMIO10 ready for transparent
|
||||
** transmission of data.
|
||||
*/
|
||||
/*
|
||||
** ---------- initialize i/o ---------------
|
||||
*/
|
||||
LwlBase[VMIO_AB_CNTL] = 0x28; /* Port B output port-Mode Spec. Reg */
|
||||
LwlBase[VMIO_AB_CNTL] = 0x80;
|
||||
|
||||
LwlBase[VMIO_AB_CNTL] = 0x29; /* Port B handshake interlock */
|
||||
LwlBase[VMIO_AB_CNTL] = 0x00;
|
||||
}
|
||||
/*==============================================================================
|
||||
|
||||
** Main line program
|
||||
** ------------------
|
||||
**============================================================================*/
|
||||
int lwl_server (int port, int base_addr, int verbose,
|
||||
int arg4, int arg5, int arg6, int arg7, int arg8, int arg9,
|
||||
int suspend) {
|
||||
/*============================================================================*/
|
||||
STATUS status;
|
||||
char *my_task_name;
|
||||
int i, j, n_bytes_got, bytes_to_get;
|
||||
int msg_cnt = 0;
|
||||
char *p_addr;
|
||||
int cl_port;
|
||||
struct sockaddr_in lcl_sockname;
|
||||
struct sockaddr_in rmt_sockname;
|
||||
int rmt_sockname_len;
|
||||
|
||||
char nbytes, buff[256], *p_buff;
|
||||
/*============================================================================
|
||||
*/
|
||||
my_task_name = taskName (taskIdSelf());
|
||||
if (suspend != 0) {
|
||||
printf ("\n%s: Suspending ...\n", my_task_name);
|
||||
taskSuspend (0); /* We've been told to suspend ourself, ..
|
||||
** .. presumably for debug reasons.
|
||||
*/
|
||||
printf ("\n%s: ... suspension ended!\n", my_task_name);
|
||||
}
|
||||
/*============================================================================
|
||||
** Perform the initialisation of global variables ...
|
||||
*/
|
||||
if (Lwl_cnct_skt != 0) {
|
||||
printf ("\007Lwl_cnct_skt = %d -- still open? ... ", Lwl_cnct_skt);
|
||||
status = close (Lwl_cnct_skt);
|
||||
if (status != ERROR) taskDelay (30); /* Pause, maybe, to let system ..
|
||||
** .. tidy up. */
|
||||
printf ("it has been closed!\n");
|
||||
Lwl_cnct_skt = 0;
|
||||
}
|
||||
if (Lwl_rw_skt != 0) {
|
||||
printf ("\007Lwl_rw_skt = %d -- still open? ...", Lwl_rw_skt);
|
||||
status = close (Lwl_rw_skt);
|
||||
if (status != ERROR) taskDelay (30); /* Pause, maybe, to let system ..
|
||||
** .. tidy up. */
|
||||
printf ("it has been closed!\n");
|
||||
Lwl_rw_skt = 0;
|
||||
}
|
||||
/*============================================================================
|
||||
** Get a port number to use. If the argument "port" is not
|
||||
** a valid port number (not in range 128 to 32767), use DFLT_PORT.
|
||||
*/
|
||||
if ((port < 128) || (port > 32767)) port = DFLT_PORT;
|
||||
/*============================================================================
|
||||
** Get the VME base address of the Test Generator Module.
|
||||
** If the argument "base_addr" is zero, use DFLT_BASE_ADDR.
|
||||
*/
|
||||
if (base_addr == 0) base_addr = DFLT_BASE_ADDR;
|
||||
#ifdef _NO_VME
|
||||
printf ("LWL_SERVER: Warning, VME access disabled.\n");
|
||||
LwlBase = Lwl_dummy;
|
||||
#else
|
||||
status = sysBusToLocalAdrs (VME_AM_USR_SHORT_IO,
|
||||
(char *) base_addr, &LwlBase);
|
||||
if (status != OK) {
|
||||
printf ("Error status from sysBusToLocalAdrs\n");
|
||||
return ERROR;
|
||||
}
|
||||
#endif /* _NO_VME */
|
||||
/*
|
||||
** Initialise the Test Generator Module.
|
||||
*/
|
||||
lwl_resetcio ();
|
||||
lwl_vmio_init ();
|
||||
lwl_enable ();
|
||||
lwl_vmio_tg_reset ();
|
||||
/*============================================================================
|
||||
** Create a TCP/IP socket for receiving connection requests, bind it and
|
||||
** set it to listen.
|
||||
*/
|
||||
Lwl_cnct_skt = socket (AF_INET, SOCK_STREAM, 0);
|
||||
if (Lwl_cnct_skt == -1) lwl_failInet ("\nLWL_SERVER -- Cnct-Socket socket error");
|
||||
|
||||
lcl_sockname.sin_family = AF_INET;
|
||||
lcl_sockname.sin_port = htons (port);
|
||||
lcl_sockname.sin_addr.s_addr = 0;
|
||||
status = bind (Lwl_cnct_skt, (struct sockaddr *) &lcl_sockname,
|
||||
sizeof (lcl_sockname));
|
||||
if (status != 0) lwl_failInet ("\nLWL_SERVER -- Cnct-Socket bind error");
|
||||
|
||||
status = listen (Lwl_cnct_skt, 5);
|
||||
if (status != 0) lwl_failInet ("\nLWL_SERVER -- Cnct-Socket listen error");
|
||||
|
||||
lwl_setup_inet_info (); /* Find out who we are */
|
||||
printf ("\nLWL_SERVER Ident \"%s\" started on %s (%s). Port %d.\n",
|
||||
ident, Lwl_inet_node, Lwl_inet_addr, port);
|
||||
if (verbose != 0) printf ("Verbose mode\n");
|
||||
/*
|
||||
**===============================================
|
||||
** Loop accepting connections from clients.
|
||||
*/
|
||||
while (TRUE) {
|
||||
rmt_sockname_len = sizeof (rmt_sockname);
|
||||
Lwl_rw_skt = accept (Lwl_cnct_skt, (struct sockaddr *) &rmt_sockname,
|
||||
&rmt_sockname_len);
|
||||
if (Lwl_rw_skt <= 0) {
|
||||
lwl_getErrno (&Lwl_my_errno);
|
||||
close (Lwl_cnct_skt);
|
||||
Lwl_cnct_skt = 0;
|
||||
lwl_failInet ("\nLWL_SERVER -- Cnct-Socket accept error"); /* No return */
|
||||
}
|
||||
|
||||
p_addr = inet_ntoa (rmt_sockname.sin_addr);
|
||||
cl_port = ntohs (rmt_sockname.sin_port);
|
||||
printf ("\nLWL_SERVER_%d: Connected to Node %s, Port %d.\n",
|
||||
port, p_addr, cl_port);
|
||||
|
||||
lwl_vmio_transp_init (); /* Ensure the VMIO10 module is in correct mode. */
|
||||
/*
|
||||
**=======================================================
|
||||
** Loop reading messages from client.
|
||||
*/
|
||||
n_bytes_got = recv (Lwl_rw_skt, &nbytes, 1, NULL);
|
||||
while ((n_bytes_got == 1) && (nbytes != 0)) {
|
||||
if (verbose != 0) printf ("\nLWL:%3d", nbytes);
|
||||
/*
|
||||
** See if it's a "special" request (0x80 to 0xff).
|
||||
*/
|
||||
if ((nbytes & 0x80) == 0) {
|
||||
msg_cnt++;
|
||||
bytes_to_get = nbytes;
|
||||
p_buff = buff;
|
||||
while (bytes_to_get > 0) {
|
||||
n_bytes_got = recv (Lwl_rw_skt, p_buff, bytes_to_get, NULL);
|
||||
if (n_bytes_got != bytes_to_get) {
|
||||
if (n_bytes_got <= 0) {
|
||||
printf ("\nLWL_SERVER: recv error on message %d; "
|
||||
" recv status = %d\n", n_bytes_got);
|
||||
printf (" This is fatal - closing connection to %s.\n",
|
||||
inet_ntoa (rmt_sockname.sin_addr));
|
||||
close (Lwl_rw_skt);
|
||||
Lwl_rw_skt = 0;
|
||||
close (Lwl_cnct_skt);
|
||||
Lwl_cnct_skt = 0;
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
bytes_to_get -= n_bytes_got;
|
||||
p_buff += n_bytes_got;
|
||||
}
|
||||
if (verbose != 0) {
|
||||
for (i = 0; i < nbytes; i++) {
|
||||
if ((i % 16 == 0) && (i != 0)) {
|
||||
printf ("\n %02x", buff[i]);
|
||||
}else {
|
||||
printf (" %02x", buff[i]);
|
||||
}
|
||||
}
|
||||
printf ("\n");
|
||||
}
|
||||
lwl_vmio_send (nbytes, buff); /* Send the bytes to the LWL. */
|
||||
}else if (nbytes == 0x81) {
|
||||
printf ("\nLWL_SERVER: message count set to zero\n");
|
||||
msg_cnt = 0;
|
||||
}else if (nbytes == 0x82) {
|
||||
printf ("\nLWL_SERVER: message count = %d\n", msg_cnt);
|
||||
}else {
|
||||
printf ("\nLWL_SERVER: unrecognised request received -- exiting!\n");
|
||||
printf (" Request byte = 0x%x\n", nbytes);
|
||||
close (Lwl_rw_skt);
|
||||
Lwl_rw_skt = 0;
|
||||
close (Lwl_cnct_skt);
|
||||
Lwl_cnct_skt = 0;
|
||||
return ERROR;
|
||||
}
|
||||
n_bytes_got = recv (Lwl_rw_skt, &nbytes, 1, NULL);
|
||||
}
|
||||
/*
|
||||
** End of loop reading messages from client.
|
||||
**===============================================
|
||||
*/
|
||||
if (n_bytes_got <= 0) {
|
||||
printf ("\nLWL_SERVER -- R/W-Socket recv error.\n");
|
||||
printf (" Closing connection to %s.\n",
|
||||
inet_ntoa (rmt_sockname.sin_addr));
|
||||
}else {
|
||||
printf ("\nLWL_SERVER -- client %s has terminated his connection.\n",
|
||||
inet_ntoa (rmt_sockname.sin_addr));
|
||||
}
|
||||
close (Lwl_rw_skt);
|
||||
Lwl_rw_skt = 0;
|
||||
}
|
||||
/*
|
||||
** End of loop accepting connections from clients.
|
||||
**======================================================
|
||||
*/
|
||||
return OK;
|
||||
}
|
||||
/*========================================= End of LWL_SERVER.C ========*/
|
Reference in New Issue
Block a user