OpenCores
URL https://opencores.org/ocsvn/vapi/vapi/trunk

Subversion Repositories vapi

[/] [vapi/] [trunk/] [vapi.c] - Rev 13

Compare with Previous | Blame | View Log

/* vapi.c -- Verification API Interface test side
   Copyright (C) 2001, Marko Mlinar, markom@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>
 
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
 
#include "vapi.h"
 
int vapi_fd;
unsigned long first_id, last_id;
 
static int vapi_write_stream(int fd, void* buf, int len)
{
  int n;
  char* w_buf = (char*)buf;
  struct pollfd block;
 
  while(len) {
    if((n = write(fd,w_buf,len)) < 0) {
      switch(errno) {
      case EWOULDBLOCK: /* or EAGAIN */
        /* We've been called on a descriptor marked
           for nonblocking I/O. We better simulate
           blocking behavior. */
        block.fd = fd;
        block.events = POLLOUT;
        block.revents = 0;
        poll(&block,1,-1);
        continue;
      case EINTR:
        continue;
      case EPIPE:
        close(fd);
        vapi_fd = 0;
        return -1;
      default:
        return -1;
      }
    } else {
      len -= n;
      w_buf += n;
    }
  }
  return 0;
}
 
static int vapi_read_stream(int fd, void* buf, int len)
{
  int n;
  char* r_buf = (char*)buf;
  struct pollfd block;
 
  while(len) {
    if((n = read(fd,r_buf,len)) < 0) {
      switch(errno) {
      case EWOULDBLOCK: /* or EAGAIN */
        /* We've been called on a descriptor marked
           for nonblocking I/O. We better simulate
           blocking behavior. */
        block.fd = fd;
        block.events = POLLIN;
        block.revents = 0;
        poll(&block,1,-1);
        continue;
      case EINTR:
        continue;
      default:
        return -1;
      }
    } else if(n == 0) {
      close(fd);
      fd = 0;
      return -1;
    } else {
      len -= n;
      r_buf += n;
    }
  }
  return 0;
}
 
static int write_packet (unsigned long id, unsigned long data) {
  id = htonl (id);
  if (vapi_write_stream(vapi_fd, &id, sizeof (id)) < 0)
    return 1;
  data = htonl (data);
  if (vapi_write_stream(vapi_fd, &data, sizeof (data)) < 0)
    return 1;
  return 0;
}
 
static int read_packet (unsigned long *id, unsigned long *data) {
  if (vapi_read_stream(vapi_fd, id, sizeof (unsigned long)) < 0)
    return 1;
  *id = htonl (*id);
  if (vapi_read_stream(vapi_fd, data, sizeof (unsigned long)) < 0)
    return 1;
  *data = htonl (*data);
  return 0;
}
 
/* Added by CZ 24/05/01 */
static int connect_to_server(char* hostname,char* name)
{
  struct hostent *host;
  struct sockaddr_in sin;
  struct servent *service;
  struct protoent *protocol;
  int sock,flags;
  char sTemp[256],sTemp2[256];
  char* proto_name = "tcp";
  int port = 0;
  int on_off = 0; /* Turn off Nagel's algorithm on the socket */
  char *s;
 
  if(!(protocol = getprotobyname(proto_name))) {
    sprintf(sTemp,"Protocol \"%s\" not available.\n",
      proto_name);
    error(sTemp);
    return 0;
  }
 
  /* Convert name to an integer only if it is well formatted.
     Otherwise, assume that it is a service name. */
 
  port = strtol(name, &s, 10);
  if(*s)
    port = 0;
 
  if(!port) {
    if(!(service = getservbyname(name, protocol->p_name))) {
  	  sprintf(sTemp,"Unknown service \"%s\".\n",name);
  	  error(sTemp);
  	  return 0;
  	}
    port = ntohs(service->s_port);
  }
 
  if(!(host = gethostbyname(hostname))) {
    sprintf(sTemp,"Unknown host \"%s\"\n",hostname);
    error(sTemp);
    return 0;
  }
 
  if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
    sprintf(sTemp, "can't create socket errno = %d\n", errno);
    sprintf(sTemp2, "%s\n",strerror(errno));
    strcat(sTemp, sTemp2);
    error(sTemp);
    return 0;
  }
 
  if(fcntl(sock, F_GETFL, &flags) < 0) {
    sprintf(sTemp, "Unable to get flags for VAPI proxy socket %d", sock);
    error(sTemp);
    close(sock);
    return 0;
  }
 
  if(fcntl(sock,F_SETFL, flags & ~O_NONBLOCK) < 0) {
    sprintf(sTemp, "Unable to set flags for VAPI proxy socket %d to value 0x%08x", sock,flags | O_NONBLOCK);
    error(sTemp);
    close(sock);
    return 0;
  }
 
  memset(&sin,0,sizeof(sin));
  sin.sin_family = host->h_addrtype;
  memcpy(&sin.sin_addr, host->h_addr_list[0], host->h_length);
  sin.sin_port = htons(port);
 
  if((connect(sock, (struct sockaddr*)&sin, sizeof(sin)) < 0) 
     && errno != EINPROGRESS) {
 
    sprintf(sTemp, "connect failed  errno = %d\n", errno);
    sprintf(sTemp2, "%s\n", strerror(errno));
    close(sock);
    strcat(sTemp, sTemp2);
    error(sTemp); 
    return 0;
  }
 
  if(fcntl(sock,F_SETFL, flags | O_NONBLOCK) < 0) {
    sprintf(sTemp, "Unable to set flags for VAPI proxy socket %d to value 0x%08x", sock, flags | O_NONBLOCK);
    error(sTemp);
    close(sock);
    return 0;
  }
 
  if(setsockopt(sock,protocol->p_proto,TCP_NODELAY,&on_off,sizeof(int)) < 0) {
    sprintf(sTemp,"Unable to disable Nagel's algorithm for socket %d.\nsetsockopt", sock);
    error(sTemp);
    close(sock);
    return 0;
  }
 
  return sock;
}
 
/* Check if a vapi id is "good" */
static inline int good_id (unsigned long id)
{
  return ((id >= first_id) && (id <= last_id));
}
 
 
/* Initialize a new connection to the or1k board, and make sure we are
   really connected.  */
 
int
vapi_init (char *port_name, unsigned long id)
{
  first_id = id;
  last_id = id + num_vapi_ids - 1;
  /* CZ 24/05/01 - Check to see if we have specified a remote
     VAPI interface or a local one. It is remote if it follows
     the URL naming convention vapi://<hostname>:<port> */
  if(!strncmp(port_name,"vapi://",7)) {
    char *port;
    char hostname[256];
 
    port = strchr(&port_name[7], ':');
    if(port) {
  	  int len = port - port_name - 7;
  	  strncpy(hostname,&port_name[7],len);
  	  hostname[len] = '\0';
  	  port++;
  	} else
      strcpy(hostname,&port_name[7]);
 
    /* Interface is remote */
    if(!(vapi_fd = connect_to_server(hostname,port))) {
  	  char sTemp[256];
  	  sprintf(sTemp,"Can not access VAPI Proxy Server at \"%s\"",
  		  &port_name[5]);
  	  error(sTemp);
  	}
    printf("Remote or1k testing using %s, id 0x%x\n", port_name, id);
    if (vapi_write_stream (vapi_fd, &id, sizeof (id)))
      return 1;
  } else
    return 1;
  return 0;
}
 
void
vapi_done ()  /* CZ */
{
  int flags = 0;
  struct linger linger;
  char sTemp[256];
 
  linger.l_onoff = 0;
  linger.l_linger = 0;
 
  /* First, make sure we're non blocking */
  if(fcntl(vapi_fd, F_GETFL,&flags) < 0) {
    sprintf(sTemp,"Unable to get flags for VAPI proxy socket %d", vapi_fd);
    error(sTemp);
  }
  if(fcntl(vapi_fd, F_SETFL, flags & ~O_NONBLOCK) < 0) {
    sprintf(sTemp,"Unable to set flags for VAPI proxy socket %d to value 0x%08x", vapi_fd, flags | O_NONBLOCK);
    error(sTemp);
  }
 
  /* Now, make sure we don't linger around */
  if(setsockopt(vapi_fd,SOL_SOCKET,SO_LINGER,&linger,sizeof(linger)) < 0) {
    sprintf(sTemp,"Unable to disable SO_LINGER for VAPI proxy socket %d.", vapi_fd);
    error(sTemp);
  }
 
  close(vapi_fd);
}
 
/* Writes an unsigned long to server */
void vapi_write(unsigned long data)
{
  vapi_write_with_id (0, data);
}
 
/* Writes an unsigned long to server with relative ID */
void vapi_write_with_id(unsigned long relative_id, unsigned long data)
{
  printf ("WRITE [%08x, %08x]\n", first_id + relative_id, data);
  if (write_packet (first_id + relative_id, data))
    perror ("write packet");
}
 
/* Reads an unsigned long from server */
unsigned long vapi_read()
{
  unsigned long relative_id, data;
  vapi_read_with_id (&relative_id, &data);
  return data;
}
 
/* Reads an unsigned long and vapi id from server */
void vapi_read_with_id(unsigned long *relative_id, unsigned long *data) 
{
  unsigned long id;
  if(read_packet (&id, data)) {
    if(vapi_fd) {
      perror("vapi read");
      close(vapi_fd);
      vapi_fd = 0;
    }
    exit (2);
  }
  if (!good_id (id)) {
    if (last_id > first_id)
      fprintf (stderr, "ERROR: Invalid id %x, expected %x..%x", id, first_id, last_id);
    else
      fprintf (stderr, "ERROR: Invalid id %x, expected %x.", id, first_id);
    exit (1);
  }
  printf ("READ [%08x, %08x]\n", id, *data);
  *relative_id = id - first_id;
}
 
/* Polls the port if anything is available and if do_read is set something is read from port. */
int vapi_waiting ()
{
  struct pollfd fds[1];
 
  if(vapi_fd) {
    fds[0].fd = vapi_fd;
    fds[0].events = POLLIN;
    fds[0].revents = 0;
  } else
    return;
 
  while(1) {
    switch(poll(fds, 1, 0)) {
    case -1:
      if(errno == EINTR)
        continue;
      perror("poll");
      break;
    case 0: /* Nothing interesting going on */
      return 0;
    default:
      return 1;
    } /* End of switch statement */
  } /* End of while statement */
}
 
int main (int argc, char *argv[]) {
  unsigned long id, data;
  if (argc != 3) {
    printf ("Usage: %s URL ID\n", argv[0]);
    printf ("%s vapi://localhost:9998 0x12345678\n", argv[0]);
    return 2;
  }
  id = atol (argv[2]);
  if (sscanf (argv[2], "0x%x", &id)) {
    if (vapi_init(argv[1], id))
      return 1;
  } else {
    fprintf (stderr, "Invalid vapi_id\n", argv[2]);
    return 2;
  }
 
  if (vapi_main ()) {
    fprintf (stderr, "TEST FAILED.\n");
    return 1;
  }
  printf ("Test passed.\n");
 
  vapi_done();
  return 0;
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.