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

Subversion Repositories vapi

[/] [vapi/] [trunk/] [vapi.c] - Blame information for rev 14

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 markom
/* vapi.c -- Verification API Interface test side
2
   Copyright (C) 2001, Marko Mlinar, markom@opencores.org
3
 
4
This file is part of OpenRISC 1000 Architectural Simulator.
5
 
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
 
20
#include <stdio.h>
21
#include <stdlib.h>
22
#include <string.h>
23
#include <sys/poll.h>
24
#include <sys/socket.h>
25
#include <netdb.h>
26
#include <netinet/in.h>
27
#include <netinet/tcp.h>
28
#include <sys/select.h>
29
#include <sys/time.h>
30
#include <unistd.h>
31
 
32
#include <signal.h>
33
#include <sys/types.h>
34
#include <sys/stat.h>
35
#include <sys/ioctl.h>
36
#include <fcntl.h>
37
#include <errno.h>
38
 
39 6 erez
#include "vapi.h"
40
 
41 2 markom
int vapi_fd;
42 6 erez
unsigned long first_id, last_id;
43 2 markom
 
44
static int vapi_write_stream(int fd, void* buf, int len)
45
{
46
  int n;
47
  char* w_buf = (char*)buf;
48
  struct pollfd block;
49
 
50
  while(len) {
51
    if((n = write(fd,w_buf,len)) < 0) {
52
      switch(errno) {
53
      case EWOULDBLOCK: /* or EAGAIN */
54
        /* We've been called on a descriptor marked
55
           for nonblocking I/O. We better simulate
56
           blocking behavior. */
57
        block.fd = fd;
58
        block.events = POLLOUT;
59
        block.revents = 0;
60
        poll(&block,1,-1);
61
        continue;
62
      case EINTR:
63
        continue;
64
      case EPIPE:
65
        close(fd);
66
        vapi_fd = 0;
67
        return -1;
68
      default:
69
        return -1;
70
      }
71
    } else {
72
      len -= n;
73
      w_buf += n;
74
    }
75
  }
76
  return 0;
77
}
78
 
79
static int vapi_read_stream(int fd, void* buf, int len)
80
{
81
  int n;
82
  char* r_buf = (char*)buf;
83
  struct pollfd block;
84
 
85
  while(len) {
86
    if((n = read(fd,r_buf,len)) < 0) {
87
      switch(errno) {
88
      case EWOULDBLOCK: /* or EAGAIN */
89
        /* We've been called on a descriptor marked
90
           for nonblocking I/O. We better simulate
91
           blocking behavior. */
92
        block.fd = fd;
93
        block.events = POLLIN;
94
        block.revents = 0;
95
        poll(&block,1,-1);
96
        continue;
97
      case EINTR:
98
        continue;
99
      default:
100
        return -1;
101
      }
102
    } else if(n == 0) {
103
      close(fd);
104
      fd = 0;
105
      return -1;
106
    } else {
107
      len -= n;
108
      r_buf += n;
109
    }
110
  }
111
  return 0;
112
}
113
 
114
static int write_packet (unsigned long id, unsigned long data) {
115
  id = htonl (id);
116
  if (vapi_write_stream(vapi_fd, &id, sizeof (id)) < 0)
117
    return 1;
118
  data = htonl (data);
119
  if (vapi_write_stream(vapi_fd, &data, sizeof (data)) < 0)
120
    return 1;
121
  return 0;
122
}
123
 
124
static int read_packet (unsigned long *id, unsigned long *data) {
125
  if (vapi_read_stream(vapi_fd, id, sizeof (unsigned long)) < 0)
126
    return 1;
127
  *id = htonl (*id);
128
  if (vapi_read_stream(vapi_fd, data, sizeof (unsigned long)) < 0)
129
    return 1;
130
  *data = htonl (*data);
131
  return 0;
132
}
133
 
134
/* Added by CZ 24/05/01 */
135
static int connect_to_server(char* hostname,char* name)
136
{
137
  struct hostent *host;
138
  struct sockaddr_in sin;
139
  struct servent *service;
140
  struct protoent *protocol;
141
  int sock,flags;
142
  char sTemp[256],sTemp2[256];
143
  char* proto_name = "tcp";
144
  int port = 0;
145
  int on_off = 0; /* Turn off Nagel's algorithm on the socket */
146
  char *s;
147
 
148
  if(!(protocol = getprotobyname(proto_name))) {
149
    sprintf(sTemp,"Protocol \"%s\" not available.\n",
150
      proto_name);
151
    error(sTemp);
152
    return 0;
153
  }
154
 
155
  /* Convert name to an integer only if it is well formatted.
156
     Otherwise, assume that it is a service name. */
157
 
158
  port = strtol(name, &s, 10);
159
  if(*s)
160
    port = 0;
161
 
162
  if(!port) {
163
    if(!(service = getservbyname(name, protocol->p_name))) {
164
          sprintf(sTemp,"Unknown service \"%s\".\n",name);
165
          error(sTemp);
166
          return 0;
167
        }
168
    port = ntohs(service->s_port);
169
  }
170
 
171
  if(!(host = gethostbyname(hostname))) {
172
    sprintf(sTemp,"Unknown host \"%s\"\n",hostname);
173
    error(sTemp);
174
    return 0;
175
  }
176
 
177
  if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
178
    sprintf(sTemp, "can't create socket errno = %d\n", errno);
179
    sprintf(sTemp2, "%s\n",strerror(errno));
180
    strcat(sTemp, sTemp2);
181
    error(sTemp);
182
    return 0;
183
  }
184
 
185
  if(fcntl(sock, F_GETFL, &flags) < 0) {
186
    sprintf(sTemp, "Unable to get flags for VAPI proxy socket %d", sock);
187
    error(sTemp);
188
    close(sock);
189
    return 0;
190
  }
191
 
192
  if(fcntl(sock,F_SETFL, flags & ~O_NONBLOCK) < 0) {
193
    sprintf(sTemp, "Unable to set flags for VAPI proxy socket %d to value 0x%08x", sock,flags | O_NONBLOCK);
194
    error(sTemp);
195
    close(sock);
196
    return 0;
197
  }
198
 
199
  memset(&sin,0,sizeof(sin));
200
  sin.sin_family = host->h_addrtype;
201
  memcpy(&sin.sin_addr, host->h_addr_list[0], host->h_length);
202
  sin.sin_port = htons(port);
203
 
204
  if((connect(sock, (struct sockaddr*)&sin, sizeof(sin)) < 0)
205
     && errno != EINPROGRESS) {
206
 
207
    sprintf(sTemp, "connect failed  errno = %d\n", errno);
208
    sprintf(sTemp2, "%s\n", strerror(errno));
209
    close(sock);
210
    strcat(sTemp, sTemp2);
211
    error(sTemp);
212
    return 0;
213
  }
214
 
215
  if(fcntl(sock,F_SETFL, flags | O_NONBLOCK) < 0) {
216
    sprintf(sTemp, "Unable to set flags for VAPI proxy socket %d to value 0x%08x", sock, flags | O_NONBLOCK);
217
    error(sTemp);
218
    close(sock);
219
    return 0;
220
  }
221
 
222
  if(setsockopt(sock,protocol->p_proto,TCP_NODELAY,&on_off,sizeof(int)) < 0) {
223
    sprintf(sTemp,"Unable to disable Nagel's algorithm for socket %d.\nsetsockopt", sock);
224
    error(sTemp);
225
    close(sock);
226
    return 0;
227
  }
228
 
229
  return sock;
230
}
231
 
232 6 erez
/* Check if a vapi id is "good" */
233
static inline int good_id (unsigned long id)
234
{
235
  return ((id >= first_id) && (id <= last_id));
236
}
237
 
238
 
239 2 markom
/* Initialize a new connection to the or1k board, and make sure we are
240
   really connected.  */
241
 
242
int
243
vapi_init (char *port_name, unsigned long id)
244
{
245 6 erez
  first_id = id;
246
  last_id = id + num_vapi_ids - 1;
247 2 markom
  /* CZ 24/05/01 - Check to see if we have specified a remote
248
     VAPI interface or a local one. It is remote if it follows
249
     the URL naming convention vapi://<hostname>:<port> */
250
  if(!strncmp(port_name,"vapi://",7)) {
251
    char *port;
252
    char hostname[256];
253
 
254
    port = strchr(&port_name[7], ':');
255
    if(port) {
256
          int len = port - port_name - 7;
257
          strncpy(hostname,&port_name[7],len);
258
          hostname[len] = '\0';
259
          port++;
260
        } else
261
      strcpy(hostname,&port_name[7]);
262
 
263
    /* Interface is remote */
264
    if(!(vapi_fd = connect_to_server(hostname,port))) {
265
          char sTemp[256];
266
          sprintf(sTemp,"Can not access VAPI Proxy Server at \"%s\"",
267
                  &port_name[5]);
268
          error(sTemp);
269
        }
270
    printf("Remote or1k testing using %s, id 0x%x\n", port_name, id);
271
    if (vapi_write_stream (vapi_fd, &id, sizeof (id)))
272
      return 1;
273
  } else
274
    return 1;
275
  return 0;
276
}
277
 
278
void
279
vapi_done ()  /* CZ */
280
{
281
  int flags = 0;
282
  struct linger linger;
283
  char sTemp[256];
284
 
285
  linger.l_onoff = 0;
286
  linger.l_linger = 0;
287
 
288
  /* First, make sure we're non blocking */
289
  if(fcntl(vapi_fd, F_GETFL,&flags) < 0) {
290
    sprintf(sTemp,"Unable to get flags for VAPI proxy socket %d", vapi_fd);
291
    error(sTemp);
292
  }
293
  if(fcntl(vapi_fd, F_SETFL, flags & ~O_NONBLOCK) < 0) {
294
    sprintf(sTemp,"Unable to set flags for VAPI proxy socket %d to value 0x%08x", vapi_fd, flags | O_NONBLOCK);
295
    error(sTemp);
296
  }
297
 
298
  /* Now, make sure we don't linger around */
299
  if(setsockopt(vapi_fd,SOL_SOCKET,SO_LINGER,&linger,sizeof(linger)) < 0) {
300
    sprintf(sTemp,"Unable to disable SO_LINGER for VAPI proxy socket %d.", vapi_fd);
301
    error(sTemp);
302
  }
303
 
304
  close(vapi_fd);
305
}
306
 
307
/* Writes an unsigned long to server */
308 6 erez
void vapi_write(unsigned long data)
309
{
310
  vapi_write_with_id (0, data);
311
}
312
 
313
/* Writes an unsigned long to server with relative ID */
314
void vapi_write_with_id(unsigned long relative_id, unsigned long data)
315
{
316
  printf ("WRITE [%08x, %08x]\n", first_id + relative_id, data);
317
  if (write_packet (first_id + relative_id, data))
318 2 markom
    perror ("write packet");
319
}
320
 
321
/* Reads an unsigned long from server */
322 6 erez
unsigned long vapi_read()
323
{
324
  unsigned long relative_id, data;
325
  vapi_read_with_id (&relative_id, &data);
326
  return data;
327
}
328
 
329
/* Reads an unsigned long and vapi id from server */
330
void vapi_read_with_id(unsigned long *relative_id, unsigned long *data)
331
{
332
  unsigned long id;
333
  if(read_packet (&id, data)) {
334 2 markom
    if(vapi_fd) {
335
      perror("vapi read");
336
      close(vapi_fd);
337
      vapi_fd = 0;
338
    }
339
    exit (2);
340
  }
341 6 erez
  if (!good_id (id)) {
342
    if (last_id > first_id)
343
      fprintf (stderr, "ERROR: Invalid id %x, expected %x..%x", id, first_id, last_id);
344
    else
345
      fprintf (stderr, "ERROR: Invalid id %x, expected %x.", id, first_id);
346 2 markom
    exit (1);
347
  }
348 6 erez
  printf ("READ [%08x, %08x]\n", id, *data);
349
  *relative_id = id - first_id;
350 2 markom
}
351
 
352
/* Polls the port if anything is available and if do_read is set something is read from port. */
353
int vapi_waiting ()
354
{
355
  struct pollfd fds[1];
356
 
357
  if(vapi_fd) {
358
    fds[0].fd = vapi_fd;
359
    fds[0].events = POLLIN;
360
    fds[0].revents = 0;
361
  } else
362
    return;
363
 
364
  while(1) {
365
    switch(poll(fds, 1, 0)) {
366
    case -1:
367
      if(errno == EINTR)
368
        continue;
369
      perror("poll");
370
      break;
371
    case 0: /* Nothing interesting going on */
372
      return 0;
373
    default:
374
      return 1;
375
    } /* End of switch statement */
376
  } /* End of while statement */
377
}
378
 
379
int main (int argc, char *argv[]) {
380
  unsigned long id, data;
381
  if (argc != 3) {
382 6 erez
    printf ("Usage: %s URL ID\n", argv[0]);
383
    printf ("%s vapi://localhost:9998 0x12345678\n", argv[0]);
384 2 markom
    return 2;
385
  }
386
  id = atol (argv[2]);
387
  if (sscanf (argv[2], "0x%x", &id)) {
388
    if (vapi_init(argv[1], id))
389
      return 1;
390
  } else {
391
    fprintf (stderr, "Invalid vapi_id\n", argv[2]);
392
    return 2;
393
  }
394
 
395
  if (vapi_main ()) {
396
    fprintf (stderr, "TEST FAILED.\n");
397
    return 1;
398
  }
399
  printf ("Test passed.\n");
400
 
401
  vapi_done();
402
  return 0;
403
}

powered by: WebSVN 2.1.0

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