Change type of sys_errlist[] to match definition in /usr/include/errno.h
[external/binutils.git] / gdb / rdi-share / etherdrv.c
1 /* 
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$
12  *     $Date$
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 __unix
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 # if !defined(__hpux) && !defined(__linux__) && !defined(_WIN32)
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 "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 #ifndef COMPILING_ON_WINDOWS
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     const char ctrlpacket[] = CTRL_MAGIC;
270         CtrlResponse response;
271
272     /*
273      * we will try 3 times to elicit a response from the target
274      */
275     for (i = 0; i < 3; ++i)
276     {
277         struct timeval tv;
278         fd_set fdset;
279
280         /*
281          * send the magic string to the control
282          * port on the remote target
283          */
284         ia->sin_port = htons(CTRL_PORT);
285         if (sendto(sock, ctrlpacket, sizeof(ctrlpacket), 0,
286                        (struct sockaddr *)ia, sizeof(*ia)) < 0)
287         {
288 #ifdef DEBUG
289             perror("fetch_ports: sendto");
290 #endif
291             return;
292         }
293
294         FD_ZERO(&fdset);
295         FD_SET(sock, &fdset);
296         tv.tv_sec = 0;
297         tv.tv_usec = 250000;
298
299         if (select(sock + 1, &fdset, NULL, NULL, &tv) < 0)
300         {
301 #ifdef DEBUG
302             perror("fetch_ports: select");
303 #endif
304             return;
305         }
306
307         if (FD_ISSET(sock, &fdset))
308         {
309             /*
310              * there is something there - read it
311              */
312             if (recv(sock, (char *)&response, sizeof(response), 0) < 0)
313             {
314 #ifdef COMPILING_ON_WINDOWS
315                 unsigned int werrno = WSAGetLastError();
316
317                 if (werrno == WSAEWOULDBLOCK || werrno == 0)
318 #else
319                 if (errno == EWOULDBLOCK)
320 #endif
321                 {
322                     --i;
323                     continue;
324                 }
325                 else
326                 {
327 #ifdef DEBUG
328                     perror("fetch_ports: recv");
329 #endif
330                     return;
331                 }
332             }
333             {
334                 /*
335                  * XXX
336                  *
337                  * this is *very* unpleasant - try to match the structure
338                  * layout
339                  */
340                 unsigned short *sptr = (unsigned short *)(response + RESP_DBUG);
341
342                 if (strcmp(response, ctrlpacket) == 0)
343                 {
344                     ports[DBUG_INDEX] = htons(*sptr);
345                     sptr++;
346                     ports[APPL_INDEX] = htons(*sptr);
347                 }
348
349 #ifdef DEBUG
350                 printf("fetch_ports: got response, DBUG=%d, APPL=%d\n",
351                        ports[DBUG_INDEX], ports[APPL_INDEX]);
352 #endif
353                 return;
354             }
355         }
356     }
357
358     /*
359      * we failed to get a response
360      */
361 #ifdef DEBUG
362     printf("fetch_ports: failed to get a real answer\n");
363 #endif
364 }
365
366 /*
367  *  Function: read_packet
368  *   Purpose: read a packet, and pass it back to higher levels
369  *
370  *    Params:
371  *      In/Out: packet  Holder for the read packet
372  *
373  *   Returns:  1 - Packet is complete
374  *             0 - No complete packet read
375  *
376  * Post-conditions: Will call panic() if something goes wrong with the OS
377  */
378 static int read_packet(struct data_packet *const packet)
379 {
380     struct sockaddr_in from;
381     int nbytes, fromlen = sizeof(from);
382     DevChanID devchan;
383
384     /*
385      * try to get the packet
386      */
387     if ((nbytes = recvfrom(sock, (char *)(packet->data), packet->buf_len, 0,
388                            (struct sockaddr *)&from, &fromlen)) < 0)
389     {
390 #ifdef COMPILING_ON_WINDOWS
391         if (nbytes == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
392             MessageBox(GetFocus(), "Error receiving packet\n", "Angel", MB_OK | MB_ICONSTOP);
393 #else
394         if (errno != EWOULDBLOCK)
395         {
396 # ifdef DEBUG
397             perror("recv");
398 # endif
399             panic("ethernet recv failure");
400         }
401 #endif
402         return 0;
403     }
404
405 #ifdef COMPILING_ON_WINDOWS
406     if (pfnProgressCallback != NULL && nbytes != SOCKET_ERROR)
407     {
408         progressInfo.nRead += nbytes;
409         (*pfnProgressCallback)(&progressInfo);
410     }
411 #endif
412
413     /*
414      * work out where the packet was from
415      */
416     if (from.sin_addr.s_addr != remote.sin_addr.s_addr)
417     {
418         /*
419          * not from our target - ignore it
420          */
421 #ifdef DEBUG
422         printf("read_packet: ignoring packet from %s\n",
423                inet_ntoa(from.sin_addr));
424 #endif
425
426         return 0;
427     }
428     else if (ntohs(from.sin_port) == ports[DBUG_INDEX])
429         devchan = DC_DBUG;
430     else if (ntohs(from.sin_port) == ports[APPL_INDEX])
431         devchan = DC_APPL;
432     else
433     {
434         /*
435          * unknown port number - ignore it
436          */
437 #ifdef DEBUG
438         printf("read_packet: ignore packet from port %hd\n",
439                htons(from.sin_port));
440 #endif
441
442         return 0;
443     }
444
445 #if defined(DEBUG) && !defined(DO_TRACE)
446     printf("EthernetRead: %d bytes from %s channel\n",
447            nbytes, (devchan == DC_DBUG) ? "DBUG" : "APPL");
448 #endif
449
450 #ifdef DO_TRACE
451     printf("[%d on %d]\n", nbytes, devchan);
452     {
453         int i = 0;
454         unsigned char *cptr = packet->data;
455
456         while (i < nbytes)
457         {
458             printf("<%02X ", *(cptr++));
459
460             if (!(++i % 16))
461                 printf("\n");
462         }
463
464         if (i % 16)
465             printf("\n");
466     }
467 #endif
468
469     /*
470      * OK - fill in the details
471      */
472     packet->type = devchan;
473     packet->len = nbytes;
474     return 1;
475 }
476
477 /**********************************************************************/
478
479 /*
480  *  Function: Ethernet_Open
481  *   Purpose: Open the Ethernet device.  See the documentation for
482  *              DeviceOpen in drivers.h
483  *
484  * Post-conditions: Will have updated struct sockaddr_in remote (*ia)
485  *                      with the address of the remote target.
486  */
487 static int EthernetOpen(const char *name, const char *arg)
488 {
489 #ifdef COMPILING_ON_WINDOWS
490     WORD wVersionRequested;
491     WSADATA wsaData;
492 #endif
493     /*
494      * name is passed as e=<blah>, so skip 1st two characters
495      */
496     const char *etheraddr = name + 2;
497
498 #ifdef DEBUG
499     printf("EthernetOpen: name `%s'\n", name);
500 #endif
501
502     /* Check that the name is a valid one */
503     if (EthernetMatch(name, arg) != 0)
504         return -1;
505
506 #ifdef COMPILING_ON_WINDOWS
507     wVersionRequested = MAKEWORD(1, 1);
508     if (WSAStartup(wVersionRequested, &wsaData) != 0)
509         /*
510          * Couldn't find a useable winsock.dll.
511          */
512         return -1;
513
514     if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
515     {
516         WSACleanup();
517
518         /*
519          * Couldn't find a winsock.dll with supported version.
520          */
521         return -1;
522     }
523 #endif
524
525     memset((char *)ia, 0, sizeof(*ia));
526     if (set_address(etheraddr, ia) < 0)
527     {
528 #ifdef COMPILING_ON_WINDOWS
529         /*
530          * SJ - I'm not sure that this is the correct way to handle this
531          * as Fail calls remote_disable and exits, while panic just exits.
532          * However at the time of writing remote_disable does nothing!
533          */
534  /*     Panic("EthernetOpen: bad name `%s'\n", etheraddr); */
535 #else
536         Fail("EthernetOpen: bad name `%s'\n", etheraddr);
537 #endif
538         return -1;
539     }
540
541     if ((sock = open_socket()) < 0)
542         return -1;
543
544     /*
545      * fetch the port numbers assigned by the remote target
546      * to its Debug and Application sockets
547      */
548     fetch_ports();
549
550     return 0;
551 }
552
553 static int EthernetMatch(const char *name, const char *arg)
554 {
555     /* IGNORE arg */
556     if (0)
557         arg = arg;
558
559     if (name == NULL)
560         return -1;
561
562     if (tolower(name[0]) != 'e' || name[1] != '=')
563         return -1;
564
565     return 0;
566 }
567
568 static void EthernetClose(void)
569 {
570     if (sock >= 0)
571     {
572         closesocket(sock);
573         sock = -1;
574     }
575
576 #ifdef COMPILING_ON_WINDOWS
577     WSACleanup();
578 #endif
579 }
580
581 static int EthernetRead(DriverCall *dc, bool block)
582 {
583     fd_set fdset;
584     struct timeval tv;
585     int err;
586
587     FD_ZERO(&fdset);
588     FD_SET(sock, &fdset);
589
590 #ifdef COMPILING_ON_WINDOWS
591     UNUSED(block);
592     tv.tv_sec = tv.tv_usec = 0;
593 #else
594     tv.tv_sec = 0;
595     tv.tv_usec = (block ? 10000 : 0);
596 #endif
597
598     err = select(sock + 1, &fdset, NULL, NULL, &tv);
599
600     if (err < 0) {
601       if (errno == EINTR) {
602         return 0;
603       }
604       panic("ethernet select failure (errno=%i)",errno);
605       return 0;
606     }
607
608     if (FD_ISSET(sock, &fdset))
609       return read_packet(&dc->dc_packet);
610     else
611       return 0;
612 }
613
614 static int EthernetWrite(DriverCall *dc)
615 {
616     int nbytes;
617     struct data_packet *packet = &dc->dc_packet;
618
619     if (packet->type == DC_DBUG)
620         ia->sin_port = htons(ports[DBUG_INDEX]);
621     else if (packet->type == DC_APPL)
622         ia->sin_port = htons(ports[APPL_INDEX]);
623     else
624     {
625         panic("EthernetWrite: unknown devchan");
626         return 0;
627     }
628
629 #if defined(DEBUG) && !defined(DO_TRACE)
630     printf("EthernetWrite: %d bytes to %s channel\n",
631            packet->len, (packet->type == DC_DBUG) ? "DBUG" : "APPL");
632 #endif
633
634 #ifdef DO_TRACE
635     printf("[%d on %d]\n", packet->len, packet->type);
636     {
637         int i = 0;
638         unsigned char *cptr = packet->data;
639
640         while (i < packet->len)
641         {
642             printf(">%02X ", *(cptr++));
643
644             if (!(++i % 16))
645                 printf("\n");
646         }
647
648         if (i % 16)
649             printf("\n");
650     }
651 #endif
652
653     if ((nbytes = sendto(sock, (char *)(packet->data), packet->len, 0,
654                          (struct sockaddr *)ia, sizeof(*ia))) != packet->len)
655     {
656 #ifdef COMPILING_ON_WINDOWS
657         if (nbytes == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
658 #else
659         if (nbytes < 0 && errno != EWOULDBLOCK)
660 #endif
661         {
662 #ifdef DEBUG
663             perror("sendto");
664 #endif
665 #ifdef COMPILING_ON_WINDOWS
666             panic("ethernet send failure\n");
667 #else
668             /* might not work for Windows */
669             panic("ethernet send failure [%s]\n",
670                   errno < sys_nerr ? sys_errlist[errno] : "unknown errno");
671 #endif
672         }
673 #ifdef DEBUG
674         else if (nbytes >= 0)
675             fprintf(stderr, "ethernet send: asked for %d, sent %d\n", packet->len, nbytes);
676 #endif
677         return 0;
678     }
679
680 #ifdef COMPILING_ON_WINDOWS
681     if (pfnProgressCallback != NULL && nbytes != SOCKET_ERROR)
682     {
683         progressInfo.nWritten += nbytes;
684         (*pfnProgressCallback)(&progressInfo);
685     }
686 #endif
687
688     return 1;
689 }
690
691 static int EthernetIoctl(const int opcode, void *args)
692 {
693 #ifdef DEBUG
694     printf( "EthernetIoctl: op %d arg %x\n", opcode, args );
695 #endif
696
697     /*
698      * IGNORE(opcode)
699      */
700     if (0)
701     {
702         int dummy = opcode;
703         UNUSED(dummy);
704     }
705     UNUSED(args);
706
707     switch ( opcode )
708     {
709         case DC_RESYNC:
710         {
711 #ifdef DEBUG
712             printf( "EthernetIoctl: resync\n" );
713 #endif
714             fetch_ports();
715             return 0;
716         }
717
718         default:
719         {
720             return -1;
721         }
722     }
723 }
724
725 /* EOF etherdrv.c */