]>
Commit | Line | Data |
---|---|---|
85a453d5 | 1 | /* Remote serial interface using Renesas E7000 PC ISA card in a PC |
197e01b6 | 2 | Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000 |
b6ba6518 | 3 | Free Software Foundation, Inc. |
c906108c | 4 | |
c5aa993b | 5 | This file is part of GDB. |
c906108c | 6 | |
c5aa993b JM |
7 | This program is free software; you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2 of the License, or | |
10 | (at your option) any later version. | |
c906108c | 11 | |
c5aa993b JM |
12 | This program is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
c906108c | 16 | |
c5aa993b JM |
17 | You should have received a copy of the GNU General Public License |
18 | along with this program; if not, write to the Free Software | |
197e01b6 EZ |
19 | Foundation, Inc., 51 Franklin Street, Fifth Floor, |
20 | Boston, MA 02110-1301, USA. */ | |
c906108c | 21 | |
c906108c | 22 | #include "defs.h" |
a78f21af | 23 | #if defined __GO32__ || defined _WIN32 |
c906108c SS |
24 | #include "serial.h" |
25 | #include "gdb_string.h" | |
26 | ||
c906108c | 27 | #ifdef _WIN32 |
0b6a968e | 28 | #define WIN32_LEAN_AND_MEAN |
c906108c SS |
29 | #include <windows.h> |
30 | #endif | |
31 | ||
32 | #ifdef __GO32__ | |
33 | #include <sys/dos.h> | |
34 | #endif | |
35 | ||
cd96dfc9 DJ |
36 | #ifdef HAVE_TIME_H |
37 | #include <time.h> | |
38 | #endif | |
39 | ||
819cc324 AC |
40 | static int e7000pc_open (struct serial *scb, const char *name); |
41 | static void e7000pc_raw (struct serial *scb); | |
42 | static int e7000pc_readchar (struct serial *scb, int timeout); | |
43 | static int e7000pc_setbaudrate (struct serial *scb, int rate); | |
44 | static int e7000pc_write (struct serial *scb, const char *str, int len); | |
45 | static void e7000pc_close (struct serial *scb); | |
46 | static serial_ttystate e7000pc_get_tty_state (struct serial *scb); | |
47 | static int e7000pc_set_tty_state (struct serial *scb, serial_ttystate state); | |
c906108c SS |
48 | |
49 | #define OFF_DPD 0x0000 | |
50 | #define OFF_DDP 0x1000 | |
51 | #define OFF_CPD 0x2000 | |
52 | #define OFF_CDP 0x2400 | |
53 | #define OFF_FA 0x3000 | |
54 | #define OFF_FB 0x3002 | |
55 | #define OFF_FC 0x3004 | |
56 | #define OFF_IRQTOD 0x3008 | |
57 | #define OFF_IRQTOP 0x300a | |
58 | #define OFF_READY 0x300c | |
59 | #define OFF_PON 0x300e | |
60 | ||
c5aa993b JM |
61 | #define IDLE 0x0000 |
62 | #define CMD_CI 0x4349 | |
63 | #define CMD_CO 0x434f | |
64 | #define CMD_LO 0x4c4f | |
65 | #define CMD_LS 0x4c53 | |
66 | #define CMD_SV 0x5356 | |
67 | #define CMD_SS 0x5353 | |
68 | #define CMD_OK 0x4f4b | |
69 | #define CMD_ER 0x4552 | |
70 | #define CMD_NF 0x4e46 | |
71 | #define CMD_AB 0x4142 | |
72 | #define CMD_ED 0x4544 | |
73 | #define CMD_CE 0x4345 | |
c906108c SS |
74 | |
75 | static unsigned long fa; | |
76 | static unsigned long irqtod; | |
77 | static unsigned long ready; | |
78 | static unsigned long fb; | |
c5aa993b JM |
79 | static unsigned long cpd; |
80 | static unsigned long cdp; | |
c906108c SS |
81 | static unsigned long ready; |
82 | static unsigned long pon; | |
83 | static unsigned long irqtop; | |
84 | static unsigned long board_at; | |
85 | ||
86 | #ifdef __GO32__ | |
87 | ||
88 | #define SET_BYTE(x,y) { char _buf = y;dosmemput(&_buf,1, x);} | |
89 | #define SET_WORD(x,y) { short _buf = y;dosmemput(&_buf,2, x);} | |
90 | #define GET_BYTE(x) ( dosmemget(x,1,&bb), bb) | |
91 | #define GET_WORD(x) ( dosmemget(x,2,&sb), sb) | |
92 | static unsigned char bb; | |
93 | static unsigned short sb; | |
94 | ||
95 | #else /* win32 */ | |
96 | ||
97 | #define SET_BYTE(x,y) *(volatile unsigned char *)(x) = (y) | |
98 | #define SET_WORD(x,y) *(volatile unsigned short *)(x) = (y) | |
99 | #define GET_BYTE(x) (*(volatile unsigned char *)(x)) | |
100 | #define GET_WORD(x) (*(volatile unsigned short *)(x)) | |
101 | #define dosmemget(FROM, LEN, TO) memcpy ((void *)(TO), (void *)(FROM), (LEN)) | |
102 | #define dosmemput(FROM, LEN, TO) memcpy ((void *)(TO), (void *)(FROM), (LEN)) | |
103 | #endif | |
104 | ||
c5aa993b JM |
105 | static struct sw |
106 | { | |
107 | int sw; | |
108 | int addr; | |
109 | } | |
110 | sigs[] = | |
c906108c | 111 | { |
c5aa993b JM |
112 | { |
113 | 0x14, 0xd0000 | |
114 | } | |
115 | , | |
116 | { | |
117 | 0x15, 0xd4000 | |
118 | } | |
119 | , | |
120 | { | |
121 | 0x16, 0xd8000 | |
122 | } | |
123 | , | |
124 | { | |
125 | 0x17, 0xdc000 | |
126 | } | |
127 | , | |
128 | 0 | |
129 | }; | |
c906108c | 130 | |
c906108c | 131 | #define get_ds_base() 0 |
c906108c SS |
132 | |
133 | static int | |
fba45db2 | 134 | e7000pc_init (void) |
c906108c SS |
135 | { |
136 | int try; | |
137 | unsigned long dsbase; | |
c5aa993b | 138 | |
c906108c SS |
139 | dsbase = get_ds_base (); |
140 | ||
141 | /* Look around in memory for the board's signature */ | |
142 | ||
143 | for (try = 0; sigs[try].sw; try++) | |
144 | { | |
145 | int val; | |
146 | board_at = sigs[try].addr - dsbase; | |
147 | fa = board_at + OFF_FA; | |
148 | fb = board_at + OFF_FB; | |
149 | cpd = board_at + OFF_CPD; | |
150 | cdp = board_at + OFF_CDP; | |
c5aa993b JM |
151 | ready = board_at + OFF_READY; |
152 | pon = board_at + OFF_PON; | |
c906108c SS |
153 | irqtop = board_at + OFF_IRQTOP; |
154 | irqtod = board_at + OFF_IRQTOD; | |
c5aa993b | 155 | |
c906108c SS |
156 | val = GET_WORD (ready); |
157 | ||
c5aa993b | 158 | if (val == (0xaaa0 | sigs[try].sw)) |
c906108c SS |
159 | { |
160 | if (GET_WORD (pon) & 0xf) | |
161 | { | |
162 | SET_WORD (fa, 0); | |
163 | SET_WORD (fb, 0); | |
164 | ||
c5aa993b | 165 | SET_WORD (irqtop, 1); /* Disable interrupts from e7000 */ |
c906108c | 166 | SET_WORD (ready, 1); |
c5aa993b | 167 | printf_filtered ("\nConnected to the E7000PC at address 0x%x\n", |
c906108c | 168 | sigs[try].addr); |
c5aa993b | 169 | return 1; |
c906108c | 170 | } |
8a3fe4f8 | 171 | error (_("The E7000 PC board is working, but the E7000 is turned off.")); |
c906108c SS |
172 | return 0; |
173 | } | |
174 | } | |
175 | ||
8a3fe4f8 | 176 | error (_("GDB cannot connect to the E7000 PC board, check that it is installed\n\ |
c906108c SS |
177 | and that the switch settings are correct. Some other DOS programs can \n\ |
178 | stop the board from working. Try starting from a very minimal boot, \n\ | |
179 | perhaps you need to disable EMM386 over the region where the board has\n\ | |
8a3fe4f8 | 180 | its I/O space, remove other unneeded cards, etc etc\n")); |
c906108c SS |
181 | return 0; |
182 | ||
183 | } | |
184 | ||
185 | static int pbuf_size; | |
186 | static int pbuf_index; | |
187 | ||
188 | /* Return next byte from cdp. If no more, then return -1. */ | |
189 | ||
c5aa993b | 190 | static int |
c906108c SS |
191 | e7000_get (void) |
192 | { | |
193 | static char pbuf[1000]; | |
194 | char tmp[1000]; | |
195 | int x; | |
196 | ||
c5aa993b | 197 | if (pbuf_index < pbuf_size) |
c906108c SS |
198 | { |
199 | x = pbuf[pbuf_index++]; | |
200 | } | |
201 | else if ((GET_WORD (fb) & 1)) | |
202 | { | |
203 | int i; | |
204 | pbuf_size = GET_WORD (cdp + 2); | |
205 | ||
206 | dosmemget (cdp + 8, pbuf_size + 1, tmp); | |
207 | ||
208 | /* Tell the E7000 we've eaten */ | |
c5aa993b | 209 | SET_WORD (fb, 0); |
c906108c | 210 | /* Swap it around */ |
c5aa993b | 211 | for (i = 0; i < pbuf_size; i++) |
c906108c | 212 | { |
c5aa993b | 213 | pbuf[i] = tmp[i ^ 1]; |
c906108c SS |
214 | } |
215 | pbuf_index = 0; | |
c5aa993b | 216 | x = pbuf[pbuf_index++]; |
c906108c | 217 | } |
c5aa993b JM |
218 | else |
219 | { | |
c906108c SS |
220 | x = -1; |
221 | } | |
222 | return x; | |
223 | } | |
224 | ||
225 | /* Works just like read(), except that it takes a TIMEOUT in seconds. Note | |
226 | that TIMEOUT == 0 is a poll, and TIMEOUT == -1 means wait forever. */ | |
227 | ||
228 | static int | |
fba45db2 | 229 | dosasync_read (int fd, char *buf, int len, int timeout) |
c906108c SS |
230 | { |
231 | long now; | |
232 | long then; | |
233 | int i = 0; | |
234 | ||
235 | /* Then look for some more if we're still hungry */ | |
236 | time (&now); | |
237 | then = now + timeout; | |
238 | while (i < len) | |
239 | { | |
c5aa993b JM |
240 | int ch = e7000_get (); |
241 | ||
c906108c | 242 | /* While there's room in the buffer, and we've already |
c5aa993b JM |
243 | read the stuff in, suck it over */ |
244 | if (ch != -1) | |
c906108c SS |
245 | { |
246 | buf[i++] = ch; | |
c5aa993b | 247 | while (i < len && pbuf_index < pbuf_size) |
c906108c | 248 | { |
c5aa993b | 249 | ch = e7000_get (); |
c906108c SS |
250 | if (ch == -1) |
251 | break; | |
252 | buf[i++] = ch; | |
253 | } | |
254 | } | |
255 | ||
256 | time (&now); | |
257 | ||
258 | if (timeout == 0) | |
259 | return i; | |
260 | if (now >= then && timeout > 0) | |
261 | { | |
262 | return i; | |
263 | } | |
264 | } | |
265 | return len; | |
266 | } | |
267 | ||
268 | ||
269 | static int | |
fba45db2 | 270 | dosasync_write (int fd, const char *buf, int len) |
c906108c SS |
271 | { |
272 | int i; | |
c5aa993b JM |
273 | char dummy[1000]; |
274 | ||
c906108c | 275 | /* Construct copy locally */ |
c5aa993b JM |
276 | ((short *) dummy)[0] = CMD_CI; |
277 | ((short *) dummy)[1] = len; | |
278 | ((short *) dummy)[2] = 0; | |
279 | ((short *) dummy)[3] = 0; | |
280 | for (i = 0; i < len; i++) | |
c906108c | 281 | { |
7a292a7a | 282 | dummy[(8 + i) ^ 1] = buf[i]; |
c906108c SS |
283 | } |
284 | ||
285 | /* Wait for the card to get ready */ | |
c5aa993b | 286 | while (GET_WORD (fa) & 1); |
c906108c SS |
287 | |
288 | /* Blast onto the ISA card */ | |
c5aa993b | 289 | dosmemput (dummy, 8 + len + 1, cpd); |
c906108c SS |
290 | |
291 | SET_WORD (fa, 1); | |
c5aa993b | 292 | SET_WORD (irqtod, 1); /* Interrupt the E7000 */ |
c906108c SS |
293 | |
294 | return len; | |
295 | } | |
296 | ||
297 | static int | |
819cc324 | 298 | e7000pc_open (struct serial *scb, const char *name) |
c906108c SS |
299 | { |
300 | if (strncasecmp (name, "pc", 2) != 0) | |
301 | { | |
302 | errno = ENOENT; | |
303 | return -1; | |
304 | } | |
305 | ||
306 | scb->fd = e7000pc_init (); | |
307 | ||
308 | if (!scb->fd) | |
309 | return -1; | |
310 | ||
311 | return 0; | |
312 | } | |
313 | ||
314 | static int | |
819cc324 | 315 | e7000pc_noop (struct serial *scb) |
c906108c SS |
316 | { |
317 | return 0; | |
318 | } | |
319 | ||
320 | static void | |
819cc324 | 321 | e7000pc_raw (struct serial *scb) |
c906108c SS |
322 | { |
323 | /* Always in raw mode */ | |
324 | } | |
325 | ||
326 | static int | |
819cc324 | 327 | e7000pc_readchar (struct serial *scb, int timeout) |
c906108c SS |
328 | { |
329 | char buf; | |
330 | ||
c5aa993b | 331 | top: |
c906108c SS |
332 | |
333 | if (dosasync_read (scb->fd, &buf, 1, timeout)) | |
334 | { | |
c5aa993b JM |
335 | if (buf == 0) |
336 | goto top; | |
c906108c SS |
337 | return buf; |
338 | } | |
339 | else | |
340 | return SERIAL_TIMEOUT; | |
341 | } | |
342 | ||
c5aa993b JM |
343 | struct e7000pc_ttystate |
344 | { | |
c906108c SS |
345 | int dummy; |
346 | }; | |
347 | ||
348 | /* e7000pc_{get set}_tty_state() are both dummys to fill out the function | |
349 | vector. Someday, they may do something real... */ | |
350 | ||
351 | static serial_ttystate | |
819cc324 | 352 | e7000pc_get_tty_state (struct serial *scb) |
c906108c SS |
353 | { |
354 | struct e7000pc_ttystate *state; | |
355 | ||
356 | state = (struct e7000pc_ttystate *) xmalloc (sizeof *state); | |
357 | ||
358 | return (serial_ttystate) state; | |
359 | } | |
360 | ||
361 | static int | |
819cc324 | 362 | e7000pc_set_tty_state (struct serial *scb, serial_ttystate ttystate) |
c906108c SS |
363 | { |
364 | return 0; | |
365 | } | |
366 | ||
367 | static int | |
819cc324 AC |
368 | e7000pc_noflush_set_tty_state (struct serial *scb, |
369 | serial_ttystate new_ttystate, | |
fba45db2 | 370 | serial_ttystate old_ttystate) |
c906108c SS |
371 | { |
372 | return 0; | |
373 | } | |
374 | ||
375 | static void | |
819cc324 | 376 | e7000pc_print_tty_state (struct serial *scb, |
c2c6d25f | 377 | serial_ttystate ttystate, |
d9fcf2fb | 378 | struct ui_file *stream) |
c906108c SS |
379 | { |
380 | /* Nothing to print. */ | |
381 | return; | |
382 | } | |
383 | ||
384 | static int | |
819cc324 | 385 | e7000pc_setbaudrate (struct serial *scb, int rate) |
c906108c SS |
386 | { |
387 | return 0; | |
388 | } | |
389 | ||
55d80160 | 390 | static int |
819cc324 | 391 | e7000pc_setstopbits (struct serial *scb, int rate) |
55d80160 AC |
392 | { |
393 | return 0; | |
394 | } | |
395 | ||
c906108c | 396 | static int |
819cc324 | 397 | e7000pc_write (struct serial *scb, const char *str, int len) |
c906108c SS |
398 | { |
399 | dosasync_write (scb->fd, str, len); | |
400 | ||
401 | return 0; | |
402 | } | |
403 | ||
404 | static void | |
819cc324 | 405 | e7000pc_close (struct serial *scb) |
c906108c SS |
406 | { |
407 | } | |
408 | ||
409 | static struct serial_ops e7000pc_ops = | |
410 | { | |
411 | "pc", | |
412 | 0, | |
413 | e7000pc_open, | |
414 | e7000pc_close, | |
415 | e7000pc_readchar, | |
416 | e7000pc_write, | |
417 | e7000pc_noop, /* flush output */ | |
418 | e7000pc_noop, /* flush input */ | |
419 | e7000pc_noop, /* send break -- currently used only for nindy */ | |
420 | e7000pc_raw, | |
421 | e7000pc_get_tty_state, | |
422 | e7000pc_set_tty_state, | |
423 | e7000pc_print_tty_state, | |
424 | e7000pc_noflush_set_tty_state, | |
425 | e7000pc_setbaudrate, | |
55d80160 | 426 | e7000pc_setstopbits, |
c906108c SS |
427 | e7000pc_noop, /* wait for output to drain */ |
428 | }; | |
429 | ||
304270b6 | 430 | #endif /*_WIN32 or __GO32__*/ |
c906108c | 431 | |
a78f21af AC |
432 | extern initialize_file_ftype _initialize_ser_e7000pc; /* -Wmissing-prototypes */ |
433 | ||
c906108c | 434 | void |
fba45db2 | 435 | _initialize_ser_e7000pc (void) |
c906108c | 436 | { |
304270b6 AV |
437 | #if defined __GO32__ || defined _WIN32 |
438 | serial_add_interface (&e7000pc_ops); | |
439 | #endif | |
c906108c | 440 | } |