Commit | Line | Data |
---|---|---|
2494eaf6 SC |
1 | /* communicate.c -- ARMulator RDP comms code: ARM6 Instruction Emulator. |
2 | Copyright (C) 1994 Advanced RISC Machines Ltd. | |
3 | ||
4 | This program is free software; you can redistribute it and/or modify | |
5 | it under the terms of the GNU General Public License as published by | |
6 | the Free Software Foundation; either version 2 of the License, or | |
7 | (at your option) any later version. | |
8 | ||
9 | This program is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | GNU General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU General Public License | |
15 | along with this program; if not, write to the Free Software | |
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
17 | ||
18 | /**************************************************************************/ | |
19 | /* Functions to read and write characters or groups of characters */ | |
20 | /* down sockets or pipes. Those that return a value return -1 on failure */ | |
21 | /* and 0 on success. */ | |
22 | /**************************************************************************/ | |
23 | ||
24 | #include <sys/time.h> | |
25 | #include <sys/types.h> | |
26 | #include <sys/socket.h> | |
27 | #include <netinet/in.h> | |
28 | ||
29 | #include "armdefs.h" | |
30 | ||
31 | /* The socket to the debugger */ | |
32 | int debugsock; | |
33 | ||
34 | /* The maximum number of file descriptors */ | |
35 | extern int nfds; | |
36 | ||
37 | /* The socket handle */ | |
38 | extern int sockethandle; | |
39 | ||
40 | /* Read and Write routines down a pipe or socket */ | |
41 | ||
42 | /****************************************************************/ | |
43 | /* Read an individual character. */ | |
44 | /* All other read functions rely on this one. */ | |
45 | /* It waits 15 seconds until there is a character available: if */ | |
46 | /* no character is available, then it timeouts and returns -1. */ | |
47 | /****************************************************************/ | |
48 | int MYread_char(int sock, unsigned char *c) { | |
49 | int i; | |
50 | fd_set readfds; | |
51 | struct timeval timeout= {15, 0}; | |
52 | struct sockaddr_in isa; | |
53 | ||
54 | retry: | |
55 | ||
56 | FD_ZERO(&readfds); | |
57 | FD_SET(sock, &readfds); | |
58 | ||
59 | i = select(nfds, &readfds, | |
60 | (fd_set *) 0, | |
61 | (fd_set *) 0, | |
62 | &timeout); | |
63 | ||
64 | if (i < 0) { | |
65 | perror("select"); | |
66 | exit(1); | |
67 | } | |
68 | ||
69 | if (!i) { | |
70 | fprintf(stderr, "read: Timeout\n"); | |
71 | return -1; | |
72 | } | |
73 | ||
74 | if ((i = read(sock, c, 1)) < 1) { | |
75 | if (!i && sock == debugsock) { | |
76 | fprintf(stderr, "Connection with debugger severed.\n"); | |
77 | /* This shouldn't be necessary for a detached armulator, but | |
78 | the armulator cannot be cold started a second time, so | |
79 | this is probably preferable to locking up. */ | |
80 | return -1; | |
81 | fprintf(stderr, "Waiting for connection from debugger..."); | |
82 | debugsock = accept(sockethandle, &isa, &i); | |
83 | if (debugsock < 0) { /* Now we are in serious trouble... */ | |
84 | perror("accept"); | |
85 | return -1; | |
86 | } | |
87 | fprintf(stderr, " done.\nConnection Established.\n"); | |
88 | sock = debugsock; | |
89 | goto retry; | |
90 | } | |
91 | perror("read"); | |
92 | return -1; | |
93 | } | |
94 | ||
95 | #ifdef DEBUG | |
96 | if (sock == debugsock) fprintf(stderr, "<%02x ", *c); | |
97 | #endif | |
98 | ||
99 | return 0; | |
100 | } | |
101 | ||
102 | /****************************************************************/ | |
103 | /* Read an individual character. */ | |
104 | /* It waits until there is a character available. Returns -1 if */ | |
105 | /* an error occurs. */ | |
106 | /****************************************************************/ | |
107 | int MYread_charwait(int sock, unsigned char *c) { | |
108 | int i; | |
109 | fd_set readfds; | |
110 | struct sockaddr_in isa; | |
111 | ||
112 | retry: | |
113 | ||
114 | FD_ZERO(&readfds); | |
115 | FD_SET(sock, &readfds); | |
116 | ||
117 | i = select(nfds, &readfds, | |
118 | (fd_set *) 0, | |
119 | (fd_set *) 0, | |
120 | (struct timeval *) 0); | |
121 | ||
122 | if (i < 0) { | |
123 | perror("select"); | |
124 | exit(-1); | |
125 | } | |
126 | ||
127 | if ((i = read(sock, c, 1)) < 1) { | |
128 | if (!i && sock == debugsock) { | |
129 | fprintf(stderr, "Connection with debugger severed.\n"); | |
130 | return -1; | |
131 | fprintf(stderr, "Waiting for connection from debugger..."); | |
132 | debugsock = accept(sockethandle, &isa, &i); | |
133 | if (debugsock < 0) { /* Now we are in serious trouble... */ | |
134 | perror("accept"); | |
135 | return -1; | |
136 | } | |
137 | fprintf(stderr, " done.\nConnection Established.\n"); | |
138 | sock = debugsock; | |
139 | goto retry; | |
140 | } | |
141 | perror("read"); | |
142 | return -1; | |
143 | } | |
144 | ||
145 | #ifdef DEBUG | |
146 | if (sock == debugsock) fprintf(stderr, "<%02x ", *c); | |
147 | #endif | |
148 | ||
149 | return 0; | |
150 | } | |
151 | ||
152 | void MYwrite_char(int sock, unsigned char c) { | |
153 | ||
154 | if (write(sock, &c, 1) < 1) | |
155 | perror("write"); | |
156 | #ifdef DEBUG | |
157 | if (sock == debugsock) fprintf(stderr, ">%02x ", c); | |
158 | #endif | |
159 | } | |
160 | ||
161 | int MYread_word(int sock, ARMword *here) { | |
162 | unsigned char a, b, c, d; | |
163 | ||
164 | if (MYread_char(sock, &a) < 0) return -1; | |
165 | if (MYread_char(sock, &b) < 0) return -1; | |
166 | if (MYread_char(sock, &c) < 0) return -1; | |
167 | if (MYread_char(sock, &d) < 0) return -1; | |
168 | *here = a | b << 8 | c << 16 | d << 24; | |
169 | return 0; | |
170 | } | |
171 | ||
172 | void MYwrite_word(int sock, ARMword i) { | |
173 | MYwrite_char(sock, i & 0xff); | |
174 | MYwrite_char(sock, (i & 0xff00) >> 8); | |
175 | MYwrite_char(sock, (i & 0xff0000) >> 16); | |
176 | MYwrite_char(sock, (i & 0xff000000) >> 24); | |
177 | } | |
178 | ||
179 | void MYwrite_string(int sock, char *s) { | |
180 | int i; | |
181 | for (i = 0; MYwrite_char(sock, s[i]), s[i]; i++); | |
182 | } | |
183 | ||
184 | int MYread_FPword(int sock, char *putinhere) { | |
185 | int i; | |
186 | for (i = 0; i < 16; i++) | |
187 | if (MYread_char(sock, &putinhere[i]) < 0) return -1; | |
188 | return 0; | |
189 | } | |
190 | ||
191 | void MYwrite_FPword(int sock, char *fromhere) { | |
192 | int i; | |
193 | for (i = 0; i < 16; i++) | |
194 | MYwrite_char(sock, fromhere[i]); | |
195 | } | |
196 | ||
197 | /* Takes n bytes from source and those n bytes */ | |
198 | /* down to dest */ | |
199 | int passon(int source, int dest, int n) { | |
200 | char *p; | |
201 | int i; | |
202 | ||
203 | p = (char *) malloc(n); | |
204 | if (!p) { | |
205 | perror("Out of memory\n"); | |
206 | exit(1); | |
207 | } | |
208 | if (n) { | |
209 | for (i = 0; i < n; i++) | |
210 | if (MYread_char(source, &p[i]) < 0) return -1; | |
211 | ||
212 | #ifdef DEBUG | |
213 | if (dest == debugsock) | |
214 | for (i = 0; i < n; i++) fprintf(stderr, ")%02x ", (unsigned char) p[i]); | |
215 | #endif | |
216 | ||
217 | write(dest, p, n); | |
218 | } | |
219 | free(p); | |
220 | return 0; | |
221 | } |