]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/rdi-share/etherdrv.c
d9c5c0fa2cd5faf8ae8c1e470e73376292dfb170
[thirdparty/binutils-gdb.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 */