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