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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [rdi-share/] [etherdrv.c] - Blame information for rev 578

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

Line No. Rev Author Line
1 578 markom
/*
2
 * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
3
 *
4
 * This software may be freely used, copied, modified, and distributed
5
 * provided that the above copyright notice is preserved in all copies of the
6
 * software.
7
 */
8
 
9
/* -*-C-*-
10
 *
11
 * $Revision: 1.1.1.1 $
12
 *     $Date: 2002-01-16 10:24:33 $
13
 *
14
 *
15
 * etherdrv.c - Ethernet Driver for Angel.
16
 */
17
 
18
#ifdef __hpux
19
# define _POSIX_SOURCE 1
20
# define _HPUX_SOURCE 1
21
# define _XOPEN_SOURCE 1
22
#endif
23
 
24
#include <stdio.h>
25
#ifdef __hpux
26
# define uint hide_HPs_uint
27
#endif
28
#ifdef STDC_HEADERS
29
# include <unistd.h>
30
# ifdef __hpux
31
#   undef uint
32
# endif
33
#endif
34
#include <stdlib.h>
35
#include <string.h>
36
#ifdef __hpux
37
# define uint hide_HPs_uint
38
#endif
39
#include <fcntl.h>
40
#ifdef __hpux
41
# undef uint
42
#endif
43
#include <errno.h>
44
#include <stdarg.h>
45
#include <ctype.h>
46
#include "host.h"
47
 
48
#ifdef COMPILING_ON_WINDOWS
49
  typedef char * caddr_t;
50
# undef IGNORE
51
# include <winsock.h>
52
# include "angeldll.h"
53
#else
54
# ifdef __hpux
55
#   define uint hide_HPs_uint
56
# endif
57
# include <sys/types.h>
58
# include <sys/socket.h>
59
# ifdef __hpux
60
#   undef uint
61
# endif
62
# include <netdb.h>
63
# include <sys/time.h>
64
# include <sys/ioctl.h>
65
# ifdef HAVE_SYS_FILIO_H
66
#   include <sys/filio.h>
67
# endif
68
# include <netinet/in.h>
69
# include <arpa/inet.h>
70
#endif
71
 
72
#include "hsys.h"
73
#include "devices.h"
74
#include "angel_endian.h"
75
#include "buffers.h"
76
#include "hostchan.h"
77
#include "params.h"
78
#include "logging.h"
79
#include "ethernet.h"
80
 
81
 
82
#if !defined(COMPILING_ON_WINDOWS) && !defined(STDC_HEADERS)
83
/* These two might not work for windows.  */
84
extern int sys_nerr;
85
extern char * sys_errlist[];
86
#endif
87
 
88
#ifndef UNUSED
89
# define UNUSED(x) (x = x)      /* Silence compiler warnings */
90
#endif
91
 
92
/*
93
 * forward declarations of static functions
94
 */
95
static int EthernetOpen(const char *name, const char *arg);
96
static int EthernetMatch(const char *name, const char *arg);
97
static void EthernetClose(void);
98
static int EthernetRead(DriverCall *dc, bool block);
99
static int EthernetWrite(DriverCall *dc);
100
static int EthernetIoctl(const int opcode, void *args);
101
 
102
/*
103
 * the device descriptor for Ethernet
104
 */
105
DeviceDescr angel_EthernetDevice =
106
{
107
    "Ethernet",
108
    EthernetOpen,
109
    EthernetMatch,
110
    EthernetClose,
111
    EthernetRead,
112
    EthernetWrite,
113
    EthernetIoctl
114
};
115
 
116
/*
117
 * descriptor for the socket that we talk down
118
 */
119
static int sock = -1;
120
 
121
/*
122
 * address of the remote target
123
 */
124
static struct sockaddr_in remote, *ia = &remote;
125
 
126
/*
127
 * array of dynamic port numbers on target
128
 */
129
static unsigned short int ports[2];
130
 
131
/*
132
 *  Function: set_address
133
 *   Purpose: Try to get an address into an understandable form
134
 *
135
 *    Params:
136
 *       Input: addr    The address to parse
137
 *
138
 *      Output: ia      Structure to hold the parsed address
139
 *
140
 *   Returns:
141
 *          OK:  0
142
 *       Error: -1
143
 */
144
static int set_address(const char *const addr, struct sockaddr_in *const ia)
145
{
146
    ia->sin_family = AF_INET;
147
 
148
    /*
149
     * Try address as a dotted decimal
150
     */
151
    ia->sin_addr.s_addr = inet_addr(addr);
152
 
153
    /*
154
     * If that failed, try it as a hostname
155
     */
156
    if (ia->sin_addr.s_addr == (u_int)-1)
157
    {
158
        struct hostent *hp = gethostbyname(addr);
159
 
160
        if (hp == NULL)
161
            return -1;
162
 
163
        (void)memcpy((caddr_t)&ia->sin_addr, hp->h_addr, hp->h_length);
164
    }
165
 
166
    return 0;
167
}
168
 
169
/*
170
 *  Function: open_socket
171
 *   Purpose: Open a non-blocking UDP socket, and bind it to a port
172
 *              assigned by the system.
173
 *
174
 *    Params: None
175
 *
176
 *   Returns:
177
 *          OK: socket descriptor
178
 *       Error: -1
179
 */
180
static int open_socket(void)
181
{
182
    int sfd;
183
#if 0                           /* see #if 0 just below -VVV- */
184
    int yesplease = 1;
185
#endif
186
    struct sockaddr_in local;
187
 
188
    /*
189
     * open the socket
190
     */
191
#ifdef COMPILING_ON_WINDOWS
192
    if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
193
        return -1;
194
#else
195
    if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
196
    {
197
# ifdef DEBUG
198
        perror("socket");
199
# endif
200
        return -1;
201
    }
202
#endif
203
 
204
    /*
205
     * 960731 KWelton
206
     *
207
     * I don't believe that this should be necessary - if we
208
     * use select(), then non-blocking I/O is redundant.
209
     * Unfortunately, select() appears to be broken (under
210
     * Solaris, with a limited amount of time available for
211
     * debug), so this code stays in for the time being
212
     */
213
#if 0
214
    /*
215
     * enable non-blocking I/O
216
     */
217
    if (ioctlsocket(sfd, FIONBIO, &yesplease) < 0)
218
    {
219
# ifdef DEBUG
220
        perror("ioctl(FIONBIO)");
221
# endif
222
        closesocket(sfd);
223
 
224
        return -1;
225
    }
226
#endif /* 0/1 */
227
 
228
    /*
229
     * bind local address to a system-assigned port
230
     */
231
    memset((char *)&local, 0, sizeof(local));
232
    local.sin_family = AF_INET;
233
    local.sin_port = htons(0);
234
    local.sin_addr.s_addr = INADDR_ANY;
235
    if (bind(sfd, (struct sockaddr *)&local, sizeof(local)) < 0)
236
    {
237
#ifdef DEBUG
238
        perror("bind");
239
#endif
240
        closesocket(sfd);
241
 
242
        return -1;
243
    }
244
 
245
    /*
246
     * all done
247
     */
248
    return sfd;
249
}
250
 
251
/*
252
 *  Function: fetch_ports
253
 *   Purpose: Request assigned port numbers from remote target
254
 *
255
 *    Params: None
256
 *
257
 *   Returns: Nothing
258
 *
259
 * Post-conditions: This routine will *always* return something for the
260
 *                      port numbers.  If the remote target does not
261
 *                      respond, then it makes something up - this allows
262
 *                      the standard error message (from ardi.c) to be
263
 *                      generated when the target is dead for whatever
264
 *                      reason.
265
 */
266
static void fetch_ports(void)
267
{
268
    int i;
269
    char ctrlpacket[10];
270
    CtrlResponse response;
271
 
272
    memset (ctrlpacket, 0, 10);
273
    strcpy (ctrlpacket, CTRL_MAGIC);
274
    memset (response, 0, sizeof(CtrlResponse));
275
    /*
276
     * we will try 3 times to elicit a response from the target
277
     */
278
    for (i = 0; i < 3; ++i)
279
    {
280
        struct timeval tv;
281
        fd_set fdset;
282
 
283
        /*
284
         * send the magic string to the control
285
         * port on the remote target
286
         */
287
        ia->sin_port = htons(CTRL_PORT);
288
#ifdef DEBUG
289
        printf("CTLR_PORT=0x%04x  sin_port=0x%04x\n");
290
#endif
291
 
292
        if (sendto(sock, ctrlpacket, sizeof(ctrlpacket), 0,
293
                       (struct sockaddr *)ia, sizeof(*ia)) < 0)
294
        {
295
#ifdef DEBUG
296
            perror("fetch_ports: sendto");
297
#endif
298
            return;
299
        }
300
 
301
        FD_ZERO(&fdset);
302
        FD_SET(sock, &fdset);
303
        tv.tv_sec = 0;
304
        tv.tv_usec = 250000;
305
 
306
        if (select(sock + 1, &fdset, NULL, NULL, &tv) < 0)
307
        {
308
#ifdef DEBUG
309
            perror("fetch_ports: select");
310
#endif
311
            return;
312
        }
313
 
314
        if (FD_ISSET(sock, &fdset))
315
        {
316
            /*
317
             * there is something there - read it
318
             */
319
            if (recv(sock, (char *)&response, sizeof(response), 0) < 0)
320
            {
321
#ifdef COMPILING_ON_WINDOWS
322
                unsigned int werrno = WSAGetLastError();
323
 
324
                if (werrno == WSAEWOULDBLOCK || werrno == 0)
325
#else
326
                if (errno == EWOULDBLOCK)
327
#endif
328
                {
329
                    --i;
330
                    continue;
331
                }
332
                else
333
                {
334
#ifdef DEBUG
335
                    perror("fetch_ports: recv");
336
#endif
337
                    return;
338
                }
339
            }
340
            {
341
                /*
342
                 * XXX
343
                 *
344
                 * this is *very* unpleasant - try to match the structure
345
                 * layout
346
                 */
347
                unsigned short *sptr = (unsigned short *)(response + RESP_DBUG);
348
 
349
                if (strcmp(response, ctrlpacket) == 0)
350
                {
351
                    ports[DBUG_INDEX] = htons(*sptr);
352
                    sptr++;
353
                    ports[APPL_INDEX] = htons(*sptr);
354
                }
355
 
356
#ifdef DEBUG
357
                printf("fetch_ports: got response, DBUG=%d, APPL=%d\n",
358
                       ports[DBUG_INDEX], ports[APPL_INDEX]);
359
#endif
360
                return;
361
            }
362
        }
363
    }
364
 
365
    /*
366
     * we failed to get a response
367
     */
368
#ifdef DEBUG
369
    printf("fetch_ports: failed to get a real answer\n");
370
#endif
371
}
372
 
373
/*
374
 *  Function: read_packet
375
 *   Purpose: read a packet, and pass it back to higher levels
376
 *
377
 *    Params:
378
 *      In/Out: packet  Holder for the read packet
379
 *
380
 *   Returns:  1 - Packet is complete
381
 *             0 - No complete packet read
382
 *
383
 * Post-conditions: Will call panic() if something goes wrong with the OS
384
 */
385
static int read_packet(struct data_packet *const packet)
386
{
387
    struct sockaddr_in from;
388
    int nbytes, fromlen = sizeof(from);
389
    DevChanID devchan;
390
 
391
    /*
392
     * try to get the packet
393
     */
394
    if ((nbytes = recvfrom(sock, (char *)(packet->data), packet->buf_len, 0,
395
                           (struct sockaddr *)&from, &fromlen)) < 0)
396
    {
397
#ifdef COMPILING_ON_WINDOWS
398
        if (nbytes == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
399
            MessageBox(GetFocus(), "Error receiving packet\n", "Angel", MB_OK | MB_ICONSTOP);
400
#else
401
        if (errno != EWOULDBLOCK)
402
        {
403
# ifdef DEBUG
404
            perror("recv");
405
# endif
406
            panic("ethernet recv failure");
407
        }
408
#endif
409
        return 0;
410
    }
411
 
412
#ifdef COMPILING_ON_WINDOWS
413
    if (pfnProgressCallback != NULL && nbytes != SOCKET_ERROR)
414
    {
415
        progressInfo.nRead += nbytes;
416
        (*pfnProgressCallback)(&progressInfo);
417
    }
418
#endif
419
 
420
    /*
421
     * work out where the packet was from
422
     */
423
    if (from.sin_addr.s_addr != remote.sin_addr.s_addr)
424
    {
425
        /*
426
         * not from our target - ignore it
427
         */
428
#ifdef DEBUG
429
        printf("read_packet: ignoring packet from %s\n",
430
               inet_ntoa(from.sin_addr));
431
#endif
432
 
433
        return 0;
434
    }
435
    else if (ntohs(from.sin_port) == ports[DBUG_INDEX])
436
        devchan = DC_DBUG;
437
    else if (ntohs(from.sin_port) == ports[APPL_INDEX])
438
        devchan = DC_APPL;
439
    else
440
    {
441
        /*
442
         * unknown port number - ignore it
443
         */
444
#ifdef DEBUG
445
        printf("read_packet: ignore packet from port %hd\n",
446
               htons(from.sin_port));
447
#endif
448
 
449
        return 0;
450
    }
451
 
452
#if defined(DEBUG) && !defined(DO_TRACE)
453
    printf("EthernetRead: %d bytes from %s channel\n",
454
           nbytes, (devchan == DC_DBUG) ? "DBUG" : "APPL");
455
#endif
456
 
457
#ifdef DO_TRACE
458
    printf("[%d on %d]\n", nbytes, devchan);
459
    {
460
        int i = 0;
461
        unsigned char *cptr = packet->data;
462
 
463
        while (i < nbytes)
464
        {
465
            printf("<%02X ", *(cptr++));
466
 
467
            if (!(++i % 16))
468
                printf("\n");
469
        }
470
 
471
        if (i % 16)
472
            printf("\n");
473
    }
474
#endif
475
 
476
    /*
477
     * OK - fill in the details
478
     */
479
    packet->type = devchan;
480
    packet->len = nbytes;
481
    return 1;
482
}
483
 
484
/**********************************************************************/
485
 
486
/*
487
 *  Function: Ethernet_Open
488
 *   Purpose: Open the Ethernet device.  See the documentation for
489
 *              DeviceOpen in drivers.h
490
 *
491
 * Post-conditions: Will have updated struct sockaddr_in remote (*ia)
492
 *                      with the address of the remote target.
493
 */
494
static int EthernetOpen(const char *name, const char *arg)
495
{
496
#ifdef COMPILING_ON_WINDOWS
497
    WORD wVersionRequested;
498
    WSADATA wsaData;
499
#endif
500
    /*
501
     * name is passed as e=<blah>, so skip 1st two characters
502
     */
503
    const char *etheraddr = name + 2;
504
 
505
#ifdef DEBUG
506
    printf("EthernetOpen: name `%s'\n", name);
507
#endif
508
 
509
    /* Check that the name is a valid one */
510
    if (EthernetMatch(name, arg) != 0)
511
        return -1;
512
 
513
#ifdef COMPILING_ON_WINDOWS
514
    wVersionRequested = MAKEWORD(1, 1);
515
    if (WSAStartup(wVersionRequested, &wsaData) != 0)
516
        /*
517
         * Couldn't find a useable winsock.dll.
518
         */
519
        return -1;
520
 
521
    if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
522
    {
523
        WSACleanup();
524
 
525
        /*
526
         * Couldn't find a winsock.dll with supported version.
527
         */
528
        return -1;
529
    }
530
#endif
531
 
532
    memset((char *)ia, 0, sizeof(*ia));
533
    if (set_address(etheraddr, ia) < 0)
534
    {
535
#ifdef COMPILING_ON_WINDOWS
536
        /*
537
         * SJ - I'm not sure that this is the correct way to handle this
538
         * as Fail calls remote_disable and exits, while panic just exits.
539
         * However at the time of writing remote_disable does nothing!
540
         */
541
 /*     Panic("EthernetOpen: bad name `%s'\n", etheraddr); */
542
#else
543
        Fail("EthernetOpen: bad name `%s'\n", etheraddr);
544
#endif
545
        return -1;
546
    }
547
 
548
    if ((sock = open_socket()) < 0)
549
        return -1;
550
 
551
    /*
552
     * fetch the port numbers assigned by the remote target
553
     * to its Debug and Application sockets
554
     */
555
    fetch_ports();
556
 
557
    return 0;
558
}
559
 
560
static int EthernetMatch(const char *name, const char *arg)
561
{
562
    /* IGNORE arg */
563
    if (0)
564
        arg = arg;
565
 
566
    if (name == NULL)
567
        return -1;
568
 
569
    if (tolower(name[0]) != 'e' || name[1] != '=')
570
        return -1;
571
 
572
    return 0;
573
}
574
 
575
static void EthernetClose(void)
576
{
577
    if (sock >= 0)
578
    {
579
        closesocket(sock);
580
        sock = -1;
581
    }
582
 
583
#ifdef COMPILING_ON_WINDOWS
584
    WSACleanup();
585
#endif
586
}
587
 
588
static int EthernetRead(DriverCall *dc, bool block)
589
{
590
    fd_set fdset;
591
    struct timeval tv;
592
    int err;
593
 
594
    FD_ZERO(&fdset);
595
    FD_SET(sock, &fdset);
596
 
597
#ifdef COMPILING_ON_WINDOWS
598
    UNUSED(block);
599
    tv.tv_sec = tv.tv_usec = 0;
600
#else
601
    tv.tv_sec = 0;
602
    tv.tv_usec = (block ? 10000 : 0);
603
#endif
604
 
605
    err = select(sock + 1, &fdset, NULL, NULL, &tv);
606
 
607
    if (err < 0) {
608
      if (errno == EINTR) {
609
        return 0;
610
      }
611
      panic("ethernet select failure (errno=%i)",errno);
612
      return 0;
613
    }
614
 
615
    if (FD_ISSET(sock, &fdset))
616
      return read_packet(&dc->dc_packet);
617
    else
618
      return 0;
619
}
620
 
621
static int EthernetWrite(DriverCall *dc)
622
{
623
    int nbytes;
624
    struct data_packet *packet = &dc->dc_packet;
625
 
626
    if (packet->type == DC_DBUG)
627
        ia->sin_port = htons(ports[DBUG_INDEX]);
628
    else if (packet->type == DC_APPL)
629
        ia->sin_port = htons(ports[APPL_INDEX]);
630
    else
631
    {
632
        panic("EthernetWrite: unknown devchan");
633
        return 0;
634
    }
635
 
636
#if defined(DEBUG) && !defined(DO_TRACE)
637
    printf("EthernetWrite: %d bytes to %s channel\n",
638
           packet->len, (packet->type == DC_DBUG) ? "DBUG" : "APPL");
639
#endif
640
 
641
#ifdef DO_TRACE
642
    printf("[%d on %d]\n", packet->len, packet->type);
643
    {
644
        int i = 0;
645
        unsigned char *cptr = packet->data;
646
 
647
        while (i < packet->len)
648
        {
649
            printf(">%02X ", *(cptr++));
650
 
651
            if (!(++i % 16))
652
                printf("\n");
653
        }
654
 
655
        if (i % 16)
656
            printf("\n");
657
    }
658
#endif
659
 
660
    if ((nbytes = sendto(sock, (char *)(packet->data), packet->len, 0,
661
                         (struct sockaddr *)ia, sizeof(*ia))) != packet->len)
662
    {
663
#ifdef COMPILING_ON_WINDOWS
664
        if (nbytes == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
665
#else
666
        if (nbytes < 0 && errno != EWOULDBLOCK)
667
#endif
668
        {
669
#ifdef DEBUG
670
            perror("sendto");
671
#endif
672
 
673
#ifdef COMPILING_ON_WINDOWS
674
            panic("ethernet send failure\n");
675
#else
676
            /* might not work for Windows */
677
            panic("ethernet send failure [%s]\n",
678
#ifdef STDC_HEADERS
679
                  strerror(errno));
680
#else
681
                  errno < sys_nerr ? sys_errlist[errno] : "unknown errno");
682
#endif /* STDC_HEADERS */
683
#endif
684
        }
685
#ifdef DEBUG
686
        else if (nbytes >= 0)
687
            fprintf(stderr, "ethernet send: asked for %d, sent %d\n", packet->len, nbytes);
688
#endif
689
        return 0;
690
    }
691
 
692
#ifdef COMPILING_ON_WINDOWS
693
    if (pfnProgressCallback != NULL && nbytes != SOCKET_ERROR)
694
    {
695
        progressInfo.nWritten += nbytes;
696
        (*pfnProgressCallback)(&progressInfo);
697
    }
698
#endif
699
 
700
    return 1;
701
}
702
 
703
static int EthernetIoctl(const int opcode, void *args)
704
{
705
#ifdef DEBUG
706
    printf( "EthernetIoctl: op %d arg %x\n", opcode, args );
707
#endif
708
 
709
    /*
710
     * IGNORE(opcode)
711
     */
712
    if (0)
713
    {
714
        int dummy = opcode;
715
        UNUSED(dummy);
716
    }
717
    UNUSED(args);
718
 
719
    switch ( opcode )
720
    {
721
        case DC_RESYNC:
722
        {
723
#ifdef DEBUG
724
            printf( "EthernetIoctl: resync\n" );
725
#endif
726
            fetch_ports();
727
            return 0;
728
        }
729
 
730
        default:
731
        {
732
            return -1;
733
        }
734
    }
735
}
736
 
737
/* EOF etherdrv.c */

powered by: WebSVN 2.1.0

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