* Contribute CGEN simulator build support code.
[binutils-gdb.git] / gdb / rdi-share / etherdrv.c
blobb3156b226cd8b44829c130a91a19a234a0f40bbd
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 */
9 /* -*-C-*-
11 * $Revision$
12 * $Date$
15 * etherdrv.c - Ethernet Driver for Angel.
18 #ifdef __hpux
19 # define _POSIX_SOURCE 1
20 # define _HPUX_SOURCE 1
21 # define _XOPEN_SOURCE 1
22 #endif
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"
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
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"
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
88 #ifndef UNUSED
89 # define UNUSED(x) (x = x) /* Silence compiler warnings */
90 #endif
93 * forward declarations of static functions
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);
103 * the device descriptor for Ethernet
105 DeviceDescr angel_EthernetDevice =
107 "Ethernet",
108 EthernetOpen,
109 EthernetMatch,
110 EthernetClose,
111 EthernetRead,
112 EthernetWrite,
113 EthernetIoctl
117 * descriptor for the socket that we talk down
119 static int sock = -1;
122 * address of the remote target
124 static struct sockaddr_in remote, *ia = &remote;
127 * array of dynamic port numbers on target
129 static unsigned short int ports[2];
132 * Function: set_address
133 * Purpose: Try to get an address into an understandable form
135 * Params:
136 * Input: addr The address to parse
138 * Output: ia Structure to hold the parsed address
140 * Returns:
141 * OK: 0
142 * Error: -1
144 static int set_address(const char *const addr, struct sockaddr_in *const ia)
146 ia->sin_family = AF_INET;
149 * Try address as a dotted decimal
151 ia->sin_addr.s_addr = inet_addr(addr);
154 * If that failed, try it as a hostname
156 if (ia->sin_addr.s_addr == (u_int)-1)
158 struct hostent *hp = gethostbyname(addr);
160 if (hp == NULL)
161 return -1;
163 (void)memcpy((caddr_t)&ia->sin_addr, hp->h_addr, hp->h_length);
166 return 0;
170 * Function: open_socket
171 * Purpose: Open a non-blocking UDP socket, and bind it to a port
172 * assigned by the system.
174 * Params: None
176 * Returns:
177 * OK: socket descriptor
178 * Error: -1
180 static int open_socket(void)
182 int sfd;
183 #if 0 /* see #if 0 just below -VVV- */
184 int yesplease = 1;
185 #endif
186 struct sockaddr_in local;
189 * open the socket
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)
197 # ifdef DEBUG
198 perror("socket");
199 # endif
200 return -1;
202 #endif
205 * 960731 KWelton
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
213 #if 0
215 * enable non-blocking I/O
217 if (ioctlsocket(sfd, FIONBIO, &yesplease) < 0)
219 # ifdef DEBUG
220 perror("ioctl(FIONBIO)");
221 # endif
222 closesocket(sfd);
224 return -1;
226 #endif /* 0/1 */
229 * bind local address to a system-assigned port
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)
237 #ifdef DEBUG
238 perror("bind");
239 #endif
240 closesocket(sfd);
242 return -1;
246 * all done
248 return sfd;
252 * Function: fetch_ports
253 * Purpose: Request assigned port numbers from remote target
255 * Params: None
257 * Returns: Nothing
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.
266 static void fetch_ports(void)
268 int i;
269 char ctrlpacket[10];
270 CtrlResponse response;
272 memset (ctrlpacket, 0, 10);
273 strcpy (ctrlpacket, CTRL_MAGIC);
274 memset (response, 0, sizeof(CtrlResponse));
276 * we will try 3 times to elicit a response from the target
278 for (i = 0; i < 3; ++i)
280 struct timeval tv;
281 fd_set fdset;
284 * send the magic string to the control
285 * port on the remote target
287 ia->sin_port = htons(CTRL_PORT);
288 #ifdef DEBUG
289 printf("CTLR_PORT=0x%04x sin_port=0x%04x\n");
290 #endif
292 if (sendto(sock, ctrlpacket, sizeof(ctrlpacket), 0,
293 (struct sockaddr *)ia, sizeof(*ia)) < 0)
295 #ifdef DEBUG
296 perror("fetch_ports: sendto");
297 #endif
298 return;
301 FD_ZERO(&fdset);
302 FD_SET(sock, &fdset);
303 tv.tv_sec = 0;
304 tv.tv_usec = 250000;
306 if (select(sock + 1, &fdset, NULL, NULL, &tv) < 0)
308 #ifdef DEBUG
309 perror("fetch_ports: select");
310 #endif
311 return;
314 if (FD_ISSET(sock, &fdset))
317 * there is something there - read it
319 if (recv(sock, (char *)&response, sizeof(response), 0) < 0)
321 #ifdef COMPILING_ON_WINDOWS
322 unsigned int werrno = WSAGetLastError();
324 if (werrno == WSAEWOULDBLOCK || werrno == 0)
325 #else
326 if (errno == EWOULDBLOCK)
327 #endif
329 --i;
330 continue;
332 else
334 #ifdef DEBUG
335 perror("fetch_ports: recv");
336 #endif
337 return;
342 * XXX
344 * this is *very* unpleasant - try to match the structure
345 * layout
347 unsigned short *sptr = (unsigned short *)(response + RESP_DBUG);
349 if (strcmp(response, ctrlpacket) == 0)
351 ports[DBUG_INDEX] = htons(*sptr);
352 sptr++;
353 ports[APPL_INDEX] = htons(*sptr);
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;
366 * we failed to get a response
368 #ifdef DEBUG
369 printf("fetch_ports: failed to get a real answer\n");
370 #endif
374 * Function: read_packet
375 * Purpose: read a packet, and pass it back to higher levels
377 * Params:
378 * In/Out: packet Holder for the read packet
380 * Returns: 1 - Packet is complete
381 * 0 - No complete packet read
383 * Post-conditions: Will call panic() if something goes wrong with the OS
385 static int read_packet(struct data_packet *const packet)
387 struct sockaddr_in from;
388 int nbytes, fromlen = sizeof(from);
389 DevChanID devchan;
392 * try to get the packet
394 if ((nbytes = recvfrom(sock, (char *)(packet->data), packet->buf_len, 0,
395 (struct sockaddr *)&from, &fromlen)) < 0)
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)
403 # ifdef DEBUG
404 perror("recv");
405 # endif
406 panic("ethernet recv failure");
408 #endif
409 return 0;
412 #ifdef COMPILING_ON_WINDOWS
413 if (pfnProgressCallback != NULL && nbytes != SOCKET_ERROR)
415 progressInfo.nRead += nbytes;
416 (*pfnProgressCallback)(&progressInfo);
418 #endif
421 * work out where the packet was from
423 if (from.sin_addr.s_addr != remote.sin_addr.s_addr)
426 * not from our target - ignore it
428 #ifdef DEBUG
429 printf("read_packet: ignoring packet from %s\n",
430 inet_ntoa(from.sin_addr));
431 #endif
433 return 0;
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
442 * unknown port number - ignore it
444 #ifdef DEBUG
445 printf("read_packet: ignore packet from port %hd\n",
446 htons(from.sin_port));
447 #endif
449 return 0;
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
457 #ifdef DO_TRACE
458 printf("[%d on %d]\n", nbytes, devchan);
460 int i = 0;
461 unsigned char *cptr = packet->data;
463 while (i < nbytes)
465 printf("<%02X ", *(cptr++));
467 if (!(++i % 16))
468 printf("\n");
471 if (i % 16)
472 printf("\n");
474 #endif
477 * OK - fill in the details
479 packet->type = devchan;
480 packet->len = nbytes;
481 return 1;
484 /**********************************************************************/
487 * Function: Ethernet_Open
488 * Purpose: Open the Ethernet device. See the documentation for
489 * DeviceOpen in drivers.h
491 * Post-conditions: Will have updated struct sockaddr_in remote (*ia)
492 * with the address of the remote target.
494 static int EthernetOpen(const char *name, const char *arg)
496 #ifdef COMPILING_ON_WINDOWS
497 WORD wVersionRequested;
498 WSADATA wsaData;
499 #endif
501 * name is passed as e=<blah>, so skip 1st two characters
503 const char *etheraddr = name + 2;
505 #ifdef DEBUG
506 printf("EthernetOpen: name `%s'\n", name);
507 #endif
509 /* Check that the name is a valid one */
510 if (EthernetMatch(name, arg) != 0)
511 return -1;
513 #ifdef COMPILING_ON_WINDOWS
514 wVersionRequested = MAKEWORD(1, 1);
515 if (WSAStartup(wVersionRequested, &wsaData) != 0)
517 * Couldn't find a useable winsock.dll.
519 return -1;
521 if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
523 WSACleanup();
526 * Couldn't find a winsock.dll with supported version.
528 return -1;
530 #endif
532 memset((char *)ia, 0, sizeof(*ia));
533 if (set_address(etheraddr, ia) < 0)
535 #ifdef COMPILING_ON_WINDOWS
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!
541 /* Panic("EthernetOpen: bad name `%s'\n", etheraddr); */
542 #else
543 Fail("EthernetOpen: bad name `%s'\n", etheraddr);
544 #endif
545 return -1;
548 if ((sock = open_socket()) < 0)
549 return -1;
552 * fetch the port numbers assigned by the remote target
553 * to its Debug and Application sockets
555 fetch_ports();
557 return 0;
560 static int EthernetMatch(const char *name, const char *arg)
562 /* IGNORE arg */
563 if (0)
564 arg = arg;
566 if (name == NULL)
567 return -1;
569 if (tolower(name[0]) != 'e' || name[1] != '=')
570 return -1;
572 return 0;
575 static void EthernetClose(void)
577 if (sock >= 0)
579 closesocket(sock);
580 sock = -1;
583 #ifdef COMPILING_ON_WINDOWS
584 WSACleanup();
585 #endif
588 static int EthernetRead(DriverCall *dc, bool block)
590 fd_set fdset;
591 struct timeval tv;
592 int err;
594 FD_ZERO(&fdset);
595 FD_SET(sock, &fdset);
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
605 err = select(sock + 1, &fdset, NULL, NULL, &tv);
607 if (err < 0) {
608 if (errno == EINTR) {
609 return 0;
611 panic("ethernet select failure (errno=%i)",errno);
612 return 0;
615 if (FD_ISSET(sock, &fdset))
616 return read_packet(&dc->dc_packet);
617 else
618 return 0;
621 static int EthernetWrite(DriverCall *dc)
623 int nbytes;
624 struct data_packet *packet = &dc->dc_packet;
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
632 panic("EthernetWrite: unknown devchan");
633 return 0;
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
641 #ifdef DO_TRACE
642 printf("[%d on %d]\n", packet->len, packet->type);
644 int i = 0;
645 unsigned char *cptr = packet->data;
647 while (i < packet->len)
649 printf(">%02X ", *(cptr++));
651 if (!(++i % 16))
652 printf("\n");
655 if (i % 16)
656 printf("\n");
658 #endif
660 if ((nbytes = sendto(sock, (char *)(packet->data), packet->len, 0,
661 (struct sockaddr *)ia, sizeof(*ia))) != packet->len)
663 #ifdef COMPILING_ON_WINDOWS
664 if (nbytes == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
665 #else
666 if (nbytes < 0 && errno != EWOULDBLOCK)
667 #endif
669 #ifdef DEBUG
670 perror("sendto");
671 #endif
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
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;
692 #ifdef COMPILING_ON_WINDOWS
693 if (pfnProgressCallback != NULL && nbytes != SOCKET_ERROR)
695 progressInfo.nWritten += nbytes;
696 (*pfnProgressCallback)(&progressInfo);
698 #endif
700 return 1;
703 static int EthernetIoctl(const int opcode, void *args)
705 #ifdef DEBUG
706 printf( "EthernetIoctl: op %d arg %x\n", opcode, args );
707 #endif
710 * IGNORE(opcode)
712 if (0)
714 int dummy = opcode;
715 UNUSED(dummy);
717 UNUSED(args);
719 switch ( opcode )
721 case DC_RESYNC:
723 #ifdef DEBUG
724 printf( "EthernetIoctl: resync\n" );
725 #endif
726 fetch_ports();
727 return 0;
730 default:
732 return -1;
737 /* EOF etherdrv.c */