diff --git a/sinqhm/lwl_server.c b/sinqhm/lwl_server.c new file mode 100755 index 00000000..59b88244 --- /dev/null +++ b/sinqhm/lwl_server.c @@ -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, \ +** , , +** ^ ^ ^ +** | | | +** 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/*** #include ***/ /* Get POSIX file definitions. */ + +#include /* Get POSIX signal definitions. */ +#include /* Get POSIX mem mgmnt definitions. */ +#include /* 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 ========*/