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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_45/] [or1ksim/] [vapi/] [vapi.c] - Blame information for rev 293

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

Line No. Rev Author Line
1 293 markom
/* vapi.c -- Verification API Interface
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 "config.h"
21
 
22
#include <stdio.h>
23
#include <ctype.h>
24
#include <string.h>
25
#include <stdlib.h>
26
#include <unistd.h>
27
#include <stdarg.h>
28
#include <signal.h>
29
#include <errno.h>
30
 
31
/* Added by CZ 24/05/01 */
32
#include <sys/stat.h>
33
#include <sys/types.h>
34
#include <sys/socket.h>
35
#include <netinet/in.h>
36
#include <sys/select.h>
37
#include <sys/poll.h>
38
#include <fcntl.h>
39
#include <netdb.h>
40
#include <netinet/tcp.h>
41
#include <inttypes.h>
42
 
43
//#include "sim-config.h"
44
 
45
unsigned int serverIP = 0;
46
 
47
struct {
48
  struct {
49
    unsigned int server_port;
50
  } vapi;
51
} config;
52
 
53
unsigned int server_fd = 0;
54
unsigned int vapi_fd = 0;
55
void server_request(void);
56
 
57
static int tcp_level = 0;
58
 
59
struct vapi_handler {
60
  unsigned long id;
61
  void (*read_func)(int);
62
  struct vapi_handler *next;
63
} *vapi_handler;
64
 
65
/* Added by CZ 24/05/01 */
66
int get_server_socket(const char* name,const char* proto,int port)
67
{
68
  struct servent *service;
69
  struct protoent *protocol;
70
  struct sockaddr_in sa;
71
  struct hostent *hp;
72
  int sockfd;
73
  char myname[256];
74
  int flags;
75
  char sTemp[256];
76
 
77
  /* First, get the protocol number of TCP */
78
  if(!(protocol = getprotobyname(proto))) {
79
    sprintf(sTemp,"Unable to load protocol \"%s\"",proto);
80
    perror(sTemp);
81
    return 0;
82
  }
83
  tcp_level = protocol->p_proto; /* Save for later */
84
 
85
  /* If we weren't passed a non standard port, get the port
86
     from the services directory. */
87
  if(!port) {
88
    if(service = getservbyname(name,protocol->p_name))
89
      port = ntohs(service->s_port);
90
  }
91
 
92
  /* Create the socket using the TCP protocol */
93
  if((sockfd = socket(PF_INET,SOCK_STREAM,protocol->p_proto)) < 0) {
94
    perror("Unable to create socket");
95
    return 0;
96
  }
97
 
98
  flags = 1;
99
  if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&flags,sizeof(int)) < 0) {
100
    sprintf(sTemp,"Can not set SO_REUSEADDR option on socket %d",sockfd);
101
    perror(sTemp);
102
    close(sockfd);
103
    return 0;
104
  }
105
 
106
  /* The server should also be non blocking. Get the current flags. */
107
  if(fcntl(sockfd,F_GETFL,&flags) < 0) {
108
    sprintf(sTemp,"Unable to get flags for socket %d",sockfd);
109
    perror(sTemp);
110
    close(sockfd);
111
    return 0;
112
  }
113
 
114
  /* Set the nonblocking flag */
115
  if(fcntl(sockfd,F_SETFL, flags | O_NONBLOCK) < 0) {
116
    sprintf(sTemp,"Unable to set flags for socket %d to value 0x%08x",
117
            sockfd,flags | O_NONBLOCK);
118
    perror(sTemp);
119
    close(sockfd);
120
    return 0;
121
  }
122
 
123
  /* Find out what our address is */
124
  memset(&sa,0,sizeof(struct sockaddr_in));
125
  gethostname(myname,sizeof(myname));
126
  if(!(hp = gethostbyname(myname))) {
127
    perror("Unable to read hostname");
128
    close(sockfd);
129
    return 0;
130
  }
131
 
132
  /* Bind our socket to the appropriate address */
133
  sa.sin_family = hp->h_addrtype;
134
  sa.sin_port = htons(port);
135
  if(bind(sockfd,(struct sockaddr*)&sa,sizeof(struct sockaddr_in)) < 0) {
136
    sprintf(sTemp,"Unable to bind socket %d to port %d",sockfd,port);
137
    perror(sTemp);
138
    close(sockfd);
139
    return 0;
140
  }
141
  serverIP = sa.sin_addr.s_addr;
142
  flags = sizeof(struct sockaddr_in);
143
  if(getsockname(sockfd,(struct sockaddr*)&sa,&flags) < 0) {
144
    sprintf(sTemp,"Unable to get socket information for socket %d",sockfd);
145
    perror(sTemp);
146
    close(sockfd);
147
    return 0;
148
  }
149
  config.vapi.server_port = ntohs(sa.sin_port);
150
 
151
  /* Set the backlog to 1 connections */
152
  if(listen(sockfd,1) < 0) {
153
    sprintf(sTemp,"Unable to set backlog on socket %d to %d",sockfd,1);
154
    perror(sTemp);
155
    close(sockfd);
156
    return 0;
157
  }
158
 
159
  return sockfd;
160
}
161
 
162
void server_request()
163
{
164
  struct sockaddr_in sa;
165
  struct sockaddr* addr = (struct sockaddr*)&sa;
166
  int n = sizeof(struct sockaddr_in);
167
  int fd = accept(server_fd,addr,&n);
168
  int on_off = 0; /* Turn off Nagel's algorithm on the socket */
169
  int flags;
170
  char sTemp[256];
171
 
172
  if(fd < 0) {
173
    /* This is valid, because a connection could have started,
174
       and then terminated due to a protocol error or user
175
       initiation before the accept could take place. */
176
    if(errno != EWOULDBLOCK && errno != EAGAIN) {
177
      perror("accept");
178
      close(server_fd);
179
      server_fd = 0;
180
      config.vapi.server_port = 0;
181
      serverIP = 0;
182
      }
183
    return;
184
  }
185
 
186
  if(vapi_fd) {
187
    close(fd);
188
    return;
189
  }
190
 
191
  if(fcntl(fd,F_GETFL,&flags) < 0) {
192
    sprintf(sTemp,"Unable to get flags for vapi socket %d",fd);
193
    perror(sTemp);
194
    close(fd);
195
    return;
196
  }
197
 
198
  if(fcntl(fd,F_SETFL, flags | O_NONBLOCK) < 0) {
199
    sprintf(sTemp,"Unable to set flags for vapi socket %d to value 0x%08x",
200
            fd,flags | O_NONBLOCK);
201
    perror(sTemp);
202
    close(fd);
203
    return;
204
  }
205
 
206
  if(setsockopt(fd,tcp_level,TCP_NODELAY,&on_off,sizeof(int)) < 0) {
207
    sprintf(sTemp,"Unable to disable Nagel's algorithm for socket %d.\nsetsockopt",fd);
208
    perror(sTemp);
209
    close(fd);
210
    return;
211
  }
212
 
213
  vapi_fd = fd;
214
}
215
 
216
static int vapi_write_stream(void* buf, int len)
217
{
218
  int n;
219
  char* w_buf = (char*)buf;
220
  struct pollfd block;
221
 
222
  while(len) {
223
    if((n = write(vapi_fd,w_buf,len)) < 0) {
224
      switch(errno) {
225
      case EWOULDBLOCK: /* or EAGAIN */
226
        /* We've been called on a descriptor marked
227
           for nonblocking I/O. We better simulate
228
           blocking behavior. */
229
        block.fd = vapi_fd;
230
        block.events = POLLOUT;
231
        block.revents = 0;
232
        poll(&block,1,-1);
233
        continue;
234
      case EINTR:
235
        continue;
236
      case EPIPE:
237
        close(vapi_fd);
238
        vapi_fd = 0;
239
        return -1;
240
      default:
241
        return -1;
242
      }
243
    } else {
244
      len -= n;
245
      w_buf += n;
246
    }
247
  }
248
  return 0;
249
}
250
 
251
static int vapi_read_stream(void* buf, int len)
252
{
253
  int n;
254
  char* r_buf = (char*)buf;
255
  struct pollfd block;
256
 
257
  while(len) {
258
    if((n = read(vapi_fd,r_buf,len)) < 0) {
259
      switch(errno) {
260
      case EWOULDBLOCK: /* or EAGAIN */
261
        /* We've been called on a descriptor marked
262
           for nonblocking I/O. We better simulate
263
           blocking behavior. */
264
        block.fd = vapi_fd;
265
        block.events = POLLIN;
266
        block.revents = 0;
267
        poll(&block,1,-1);
268
        continue;
269
      case EINTR:
270
        continue;
271
      default:
272
        return -1;
273
      }
274
    } else if(n == 0) {
275
      close(vapi_fd);
276
      vapi_fd = 0;
277
      return -1;
278
    } else {
279
      len -= n;
280
      r_buf += n;
281
    }
282
  }
283
  return 0;
284
}
285
 
286
static int write_packet (unsigned long id, unsigned long data) {
287
  id = htonl (id);
288
  if (vapi_write_stream(&id, sizeof (id)) < 0)
289
    return 1;
290
  data = htonl (data);
291
  if (vapi_write_stream(&data, sizeof (data)) < 0)
292
    return 1;
293
  return 0;
294
}
295
 
296
static int read_packet (unsigned long *id, unsigned long *data) {
297
  if (vapi_read_stream(id, sizeof (unsigned long)) < 0)
298
    return 1;
299
  *id = htonl (*id);
300
  if (vapi_read_stream(data, sizeof (unsigned long)) < 0)
301
    return 1;
302
  *data = htonl (*data);
303
  return 0;
304
}
305
 
306
static void vapi_request()
307
{
308
  unsigned long id, data;
309
  struct vapi_handler *t;
310
  if(read_packet (&id, &data)) {
311
    if(vapi_fd) {
312
      perror("vapi read");
313
      close(vapi_fd);
314
      vapi_fd = 0;
315
    }
316
    return;
317
  }
318
 
319
  printf ("[%08x, %08x]\n", id, data);
320
  t = vapi_handler;
321
  while (t && t->id != id)
322
    t = t->next;
323
  if (!t && t->read_func)
324
    fprintf (stderr, "WARNING: packet sent to undefined id %x, %x\n", id, data);
325
  else
326
    t->read_func(data);
327
  write_packet (id, data + 1);
328
}
329
 
330
void vapi_check ()
331
{
332
  struct pollfd fds[2];
333
  int nfds = 0;
334
  int o_serv_fd = server_fd;
335
 
336
  if(!o_serv_fd && !vapi_fd)
337
    return;
338
 
339
  if(o_serv_fd) {
340
    fds[nfds].fd = o_serv_fd;
341
    fds[nfds].events = POLLIN;
342
    fds[nfds++].revents = 0;
343
  }
344
  if(vapi_fd) {
345
    fds[nfds].fd = vapi_fd;
346
    fds[nfds].events = POLLIN;
347
    fds[nfds++].revents = 0;
348
  }
349
 
350
  while(1) {
351
    switch(poll(fds,nfds,0)) {
352
    case -1:
353
      if(errno == EINTR)
354
        continue;
355
      perror("poll");
356
      server_fd = 0;
357
      break;
358
    case 0: /* Nothing interesting going on */
359
      return;
360
    default:
361
      /* Make sure to handle the vapi port first! */
362
      if((fds[0].revents && (vapi_fd && !o_serv_fd) ||
363
          fds[1].revents && (server_fd && vapi_fd))) {
364
        int revents = o_serv_fd ? fds[1].revents : fds[0].revents;
365
 
366
        if(revents & POLLIN)
367
          vapi_request();
368
        else { /* Error Occurred */
369
          fprintf(stderr,"Received flags 0x%08x on vapi socket. Shutting down.\n",revents);
370
          close(vapi_fd);
371
          vapi_fd = 0;
372
        }
373
      }
374
      if(fds[0].revents && o_serv_fd) {
375
        if(fds[0].revents & POLLIN)
376
          server_request();
377
        else { /* Error Occurred */
378
          fprintf(stderr,"Received flags 0x%08x on server. Shutting down.\n",fds[0].revents);
379
          close(o_serv_fd);
380
          server_fd = 0;
381
          config.vapi.server_port = 0;
382
          serverIP = 0;
383
        }
384
      }
385
      break;
386
    } /* End of switch statement */
387
  } /* End of while statement */
388
}
389
 
390
int vapi_init () {
391
{
392
  if(server_fd = get_server_socket("or1ksim","tcp",config.vapi.server_port))
393
    printf("VAPI Server started on port %d\n",config.vapi.server_port);
394
  else
395
    perror ("Connection");
396
 
397
  freopen("/dev/fd/0", "w+", stdout);
398
}
399
 
400
void vapi_done () {}
401
 
402
/* Installs a vapi handler to VAPI id */
403
void vapi_install_handler (unsigned long id, void (*read_func) (unsigned long)) {
404
  struct vapi_handler **t = &vapi_handler;
405
  struct vapi_handler *tt;
406
  if (readfunc == NULL) {
407
    while ((*t) && (*t)->id != id)
408
      t = &(*t)->next;
409
    if (!t) {
410
      fprintf (stderr, "Cannot uninstall VAPI read handler from id %x\n", id);
411
      exit (1);
412
    }
413
    tt = *t;
414
    (*t) = (*t)->next;
415
    free (tt);
416
  } else {
417
    while ((*t))
418
      t = &(*t)->next;
419
    tt = (struct vapi_handler *)malloc (sizeof (struct vapi_handler));
420
    tt->next = NULL;
421
    tt->id = id;
422
    tt->read_func = read_func;
423
    (*t) = tt;
424
  }
425
}
426
 
427
int main () {
428
  vapi_init ();
429
  while (1) {
430
    vapi_check();
431
  }
432
  vapi_done ();
433
}

powered by: WebSVN 2.1.0

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