#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 ========*/