]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/rdi-share/etherdrv.c
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.git] / gdb / rdi-share / etherdrv.c
CommitLineData
3a9c3d12
NC
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
f45d8080 28#ifdef STDC_HEADERS
3a9c3d12
NC
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>
f45d8080 65# ifdef HAVE_SYS_FILIO_H
3a9c3d12
NC
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
f45d8080 82#if !defined(COMPILING_ON_WINDOWS) && !defined(STDC_HEADERS)
3f7e239d
NC
83/* These two might not work for windows. */
84extern int sys_nerr;
85extern char * sys_errlist[];
290d79e0 86#endif
3a9c3d12
NC
87
88#ifndef UNUSED
89# define UNUSED(x) (x = x) /* Silence compiler warnings */
90#endif
91
92/*
93 * forward declarations of static functions
94 */
95static int EthernetOpen(const char *name, const char *arg);
96static int EthernetMatch(const char *name, const char *arg);
97static void EthernetClose(void);
98static int EthernetRead(DriverCall *dc, bool block);
99static int EthernetWrite(DriverCall *dc);
100static int EthernetIoctl(const int opcode, void *args);
101
102/*
103 * the device descriptor for Ethernet
104 */
105DeviceDescr 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 */
119static int sock = -1;
120
121/*
122 * address of the remote target
123 */
124static struct sockaddr_in remote, *ia = &remote;
125
126/*
127 * array of dynamic port numbers on target
128 */
129static 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 */
144static 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 */
180static 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 */
266static 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 */
378static 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 */
487static 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
553static 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
568static 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
581static 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
614static 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
a17aca47 665
3a9c3d12
NC
666#ifdef COMPILING_ON_WINDOWS
667 panic("ethernet send failure\n");
668#else
669 /* might not work for Windows */
670 panic("ethernet send failure [%s]\n",
a17aca47
JM
671#ifdef STDC_HEADERS
672 strerror(errno));
673#else
3a9c3d12 674 errno < sys_nerr ? sys_errlist[errno] : "unknown errno");
a17aca47 675#endif /* STDC_HEADERS */
3a9c3d12
NC
676#endif
677 }
678#ifdef DEBUG
679 else if (nbytes >= 0)
680 fprintf(stderr, "ethernet send: asked for %d, sent %d\n", packet->len, nbytes);
681#endif
682 return 0;
683 }
684
685#ifdef COMPILING_ON_WINDOWS
686 if (pfnProgressCallback != NULL && nbytes != SOCKET_ERROR)
687 {
688 progressInfo.nWritten += nbytes;
689 (*pfnProgressCallback)(&progressInfo);
690 }
691#endif
692
693 return 1;
694}
695
696static int EthernetIoctl(const int opcode, void *args)
697{
698#ifdef DEBUG
699 printf( "EthernetIoctl: op %d arg %x\n", opcode, args );
700#endif
701
702 /*
703 * IGNORE(opcode)
704 */
705 if (0)
706 {
707 int dummy = opcode;
708 UNUSED(dummy);
709 }
710 UNUSED(args);
711
712 switch ( opcode )
713 {
714 case DC_RESYNC:
715 {
716#ifdef DEBUG
717 printf( "EthernetIoctl: resync\n" );
718#endif
719 fetch_ports();
720 return 0;
721 }
722
723 default:
724 {
725 return -1;
726 }
727 }
728}
729
730/* EOF etherdrv.c */