]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/ser-e7kpc.c
* defs.h: Fix cntl-C to read from the Windows message queue.
[thirdparty/binutils-gdb.git] / gdb / ser-e7kpc.c
1 /* Remote serial interface using Hitachi E7000 PC ISA card in a PC
2
3 Copyright 1994 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
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.
11
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.
16
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
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21 //#define DEBUGIFY
22 #include "debugify.h"
23
24 #define RMT_DBG(x) if (remote_debug) printf_unfiltered x
25
26
27 #if defined(__GO32__) || defined(_WIN32)
28 #if defined(_WIN32)
29 /* we define the 32-bit calls which thunk to 16-bit dll calls
30 */
31 #include "win-e7kpc.h"
32 #include "target.h"
33 #ifdef _MSC_VER
34 /* msvc uses strnicmp instead of strncasecmp */
35 #define strncasecmp strnicmp
36 #define W32SUT_32
37 #include "windefs.h"
38 #include "w32sut.h"
39 #endif
40 #include "gdbwin.h"
41
42 #else
43 #include <sys/dos.h>
44 #include "defs.h"
45 #endif /* _WIN32 */
46 #include "serial.h"
47
48
49 static int e7000pc_open PARAMS ((serial_t scb, const char *name));
50 static void e7000pc_raw PARAMS ((serial_t scb));
51 static int e7000pc_readchar PARAMS ((serial_t scb, int timeout));
52 static int e7000pc_setbaudrate PARAMS ((serial_t scb, int rate));
53 static int e7000pc_write PARAMS ((serial_t scb, const char *str, int len));
54 static void e7000pc_close PARAMS ((serial_t scb));
55 static serial_ttystate e7000pc_get_tty_state PARAMS ((serial_t scb));
56 static int e7000pc_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
57 static char *aptr PARAMS ((short p));
58
59 static int dos_async_init PARAMS ((int port));
60 static void dos_async_tx PARAMS ((const char c));
61 static int dos_async_rx PARAMS (());
62
63
64
65 #define OFF_DPD 0x0000
66 #define OFF_DDP 0x1000
67 #define OFF_CPD 0x2000
68 #define OFF_CDP 0x2400
69 #define OFF_FA 0x3000
70 #define OFF_FB 0x3002
71 #define OFF_FC 0x3004
72 #define OFF_IRQTOD 0x3008
73 #define OFF_IRQTOP 0x300a
74 #define OFF_READY 0x300c
75 #define OFF_PON 0x300e
76
77 #define IDLE 0x0000
78 #define CMD_CI 0x4349
79 #define CMD_CO 0x434f
80 #define CMD_LO 0x4c4f
81 #define CMD_LS 0x4c53
82 #define CMD_SV 0x5356
83 #define CMD_SS 0x5353
84 #define CMD_OK 0x4f4b
85 #define CMD_ER 0x4552
86 #define CMD_NF 0x4e46
87 #define CMD_AB 0x4142
88 #define CMD_ED 0x4544
89 #define CMD_CE 0x4345
90
91 static unsigned long fa;
92 static unsigned long irqtod;
93 static unsigned long ready;
94 static unsigned long fb;
95 static unsigned long cpd ;
96 static unsigned long cdp ;
97 static unsigned long ready;
98 static unsigned long pon;
99 static unsigned long irqtop;
100 static unsigned long board_at;
101
102 #ifdef _WIN32
103 /* These routines are normally part of the go32 dos extender.
104 * We redefine them here to be calls into their Windoze equivs. */
105 static void dosmemget(int offset, int length, void *buffer);
106 static void dosmemput(const void *buffer, int length, int offset);
107
108 /* dll entry points for w32se7kpc.dll; call kernel32 to thunk for us */
109 typedef BOOL (APIENTRY * PUTREGISTER) (
110 HANDLE hModule,
111 LPCSTR lpsz16BitDLL,
112 LPCSTR lpszInitName,
113 LPCSTR lpszProcName,
114 UT32PROC * ppfn32Thunk,
115 FARPROC pfnUT32Callback,
116 LPVOID lpBuff
117 );
118
119 /* dll entry points for w95e7kpc.dll and w31e7kpc.dll */
120 HANDLE hWine7kpc = 0;
121
122 typedef int (APIENTRY * PWIN_LOAD_E7KPC) (void);
123 typedef void (APIENTRY * PWIN_UNLOAD_E7KPC) (void);
124 typedef void (APIENTRY * PWIN_MEM_GET) (unsigned char *buf, int len, int offset);
125 typedef void (APIENTRY * PWIN_MEM_PUT) (unsigned char *buf, int len, int offset);
126 typedef void (APIENTRY * PWIN_REMOTE_DEBUG) (int val);
127
128 PWIN_LOAD_E7KPC pwin_load_e7kpc=NULL;
129 PWIN_UNLOAD_E7KPC pwin_unload_e7kpc=NULL;
130 PWIN_MEM_GET pwin_mem_get=NULL;
131 PWIN_MEM_PUT pwin_mem_put=NULL;
132 PWIN_REMOTE_DEBUG pwin_remote_debug=NULL;
133
134 static int last_remote_debug = 0;
135 static int wine7kpc_loaded = 0;
136 static void win_unload_e7kpc (void);
137
138 static int win_load_e7kpc (void)
139 {
140 if (pwin_load_e7kpc && !wine7kpc_loaded)
141 {
142 wine7kpc_loaded = pwin_load_e7kpc();
143 if (wine7kpc_loaded)
144 make_final_cleanup(win_unload_e7kpc, 0);
145 }
146 return wine7kpc_loaded;
147 }
148
149 static void win_unload_e7kpc (void)
150 {
151 DBG(("win_unload_e7kpc\n"));
152 if (pwin_unload_e7kpc && wine7kpc_loaded)
153 pwin_unload_e7kpc();
154 wine7kpc_loaded = 0;
155 }
156
157 static void win_mem_get (unsigned char *buf, int offset, int len)
158 {
159 DBG(("win_mem_get(&buf=<x%x> offset=<x%x> len=<%d>)\n", buf, offset, len));
160 if (remote_debug!=last_remote_debug && pwin_remote_debug)
161 {
162 //DBG(("calling pwin_remote_debug\n"));
163 pwin_remote_debug(remote_debug);
164 last_remote_debug=remote_debug;
165 }
166 if (pwin_mem_get)
167 {
168 //DBG(("calling pwin_mem_get\n"));
169 pwin_mem_get (buf, offset, len);
170 }
171 //DBG(("leaving win_mem_get; buf=<%s>\n", buf));
172 }
173
174 static void win_mem_put (unsigned char *buf, int offset, int len)
175 {
176 DBG(("win_mem_put(buf=<%s> offset=<x%x> len=<%d>)\n", buf, offset, len));
177 if (remote_debug!=last_remote_debug && pwin_remote_debug)
178 {
179 pwin_remote_debug(remote_debug);
180 last_remote_debug=remote_debug;
181 }
182 if (pwin_mem_put)
183 pwin_mem_put (buf, offset, len);
184 }
185
186 static void dosmemget(int offset, int length, void *buffer)
187 {
188 win_mem_get(buffer, offset, length);
189 }
190
191 static void dosmemput(const void *buffer, int length, int offset)
192 {
193 win_mem_put((unsigned char*)buffer, offset, length);
194 }
195
196 #endif /* _WIN32 */
197
198 #define SET_BYTE(x,y) { char _buf = y;dosmemput(&_buf,1, x);}
199 #define SET_WORD(x,y) { short _buf = y;dosmemput(&_buf,2, x);}
200 #define GET_BYTE(x) ( dosmemget(x,1,&bb), bb)
201 #define GET_WORD(x) ( dosmemget(x,2,&sb), sb)
202
203 static unsigned char bb;
204 static unsigned short sb;
205
206
207 static struct sw
208 {
209 int sw;
210 int addr;
211 } sigs[] = {
212 {0x14, 0xd0000},
213 {0x15, 0xd4000},
214 {0x16, 0xd8000},
215 {0x17, 0xdc000},
216 0};
217
218 static int
219 e7000pc_init ()
220 {
221 /* Look around in memory for the board's signature */
222
223 int try;
224
225 DBG(("e7000pc_init()\n"));
226 for (try = 0; sigs[try].sw; try++)
227
228 {
229 int val;
230 board_at = sigs[try].addr;
231 fa = board_at + OFF_FA;
232 fb = board_at + OFF_FB;
233 cpd = board_at + OFF_CPD;
234 cdp = board_at + OFF_CDP;
235 ready =board_at + OFF_READY;
236 pon = board_at + OFF_PON;
237 irqtop = board_at + OFF_IRQTOP;
238 irqtod = board_at + OFF_IRQTOD;
239
240 RMT_DBG(("e7000pc_init: looking for board's signature, try=%d\n", try));
241
242 val = GET_WORD (ready);
243
244 //DBG(("e7000pc_init: GET_WORD returns x%x\n", val));
245
246 if (val == (0xaaa0 | sigs[try].sw))
247 {
248 if (GET_BYTE (pon) & 0xf)
249 {
250 SET_BYTE(fa, 0);
251 SET_BYTE (fb, 0);
252
253 SET_BYTE (irqtop, 1); /* Disable interrupts from e7000 */
254 SET_WORD (ready, 1);
255 DBG(("Yippie! Connected :-)\n"));
256 printf_filtered ("\nConnected to the E7000PC at address 0x%x\n",
257 sigs[try].addr);
258 return 1;
259 }
260 DBG(("Bummer! e7000pc not on :-(\n"));
261 error ("The E7000 PC board is working, but the E7000 is turned off.\n");
262 return 0;
263 }
264 }
265
266 DBG(("Bummer! Can't connect :-(\n"));
267 error ("GDB cannot connect to the E7000 PC board, check that it is installed\n\
268 and that the switch settings are correct. Some other DOS programs can \n\
269 stop the board from working. Try starting from a very minimal boot, \n\
270 perhaps you need to disable EMM386 over the region where the board has\n\
271 its I/O space, remove other unneeded cards, etc etc\n");
272 return 0;
273
274 }
275
276 static int pbuf_size;
277 static int pbuf_index;
278
279 static
280 int
281 e7000_get ()
282 {
283 static char pbuf[1000];
284 char tmp[1000];
285 int x;
286 DBG(("e7000_get()\n"));
287 if (pbuf_index < pbuf_size)
288 {
289 x = pbuf[pbuf_index++];
290 }
291 else if ((GET_BYTE (fb) & 1))
292 {
293 int i;
294 pbuf_size = GET_WORD(cdp + 2);
295
296 dosmemget (cdp + 8, pbuf_size + 1, tmp);
297
298 /* Tell the E7000 we've eaten */
299 SET_BYTE(fb,0);
300 /* Swap it around */
301 /* FIXME! We get in an infinite loop inside e7000_open...
302 * This is called from dosasync_readchar
303 * called from remote-e7000.c trying to sync up.
304 */
305 for (i = 0; i < pbuf_size; i++)
306 {
307 pbuf[i] = tmp[i^1];
308 }
309 pbuf_index = 0;
310 x = pbuf[pbuf_index++];
311 }
312 else
313 {
314 x = -1;
315 }
316 return x;
317 }
318
319 static int
320 dosasync_read (fd, buf, len, timeout)
321 int fd;
322 char *buf;
323 int len;
324 int timeout;
325
326 {
327 long now;
328 long then;
329 int i = 0;
330
331 DBG(("dosasync_read(fd=x%x,buf,len=x%x,timeout=x%x)\n",fd,len,timeout));
332 /* Then look for some more if we're still hungry */
333 time (&now);
334 then = now + timeout;
335 while (i < len)
336 {
337 int ch = e7000_get();
338 //DBG(("%d: e7000_get gotta x%x\n", i, ch\n"));
339
340 /* While there's room in the buffer, and we've already
341 * read the stuff in, suck it over */
342 if (ch != -1)
343 {
344 buf[i++] = ch;
345 //DBG(("e7000_get got x%x; before loop2: len=x%x, pbuf_index=x%x, pbuf_size=x%x\n", ch, len, pbuf_index, pbuf_size));
346 while (i < len && pbuf_index < pbuf_size )
347 {
348 ch = e7000_get();
349 if (ch == -1)
350 break;
351 buf[i++] = ch;
352 }
353 }
354
355 time (&now);
356
357 if (timeout == 0 || (now >= then && timeout > 0))
358 {
359 /* We timeout here but return i anyway...
360 * were we supposed to send a TIMEOUT ?
361 * While syncing, len = 1 and timeout=1..
362 * so always take this path and return 1 char.
363 */
364 DBG(("timeout; read x%x chars\n", i));
365 return i;
366 }
367 }
368 //DBG(("Yay! read x%x chars\n", len));
369 return len;
370 }
371
372
373 static int
374 dosasync_write (fd, buf, len)
375 int fd;
376 const char *buf;
377 int len;
378 {
379 int i;
380 char dummy[1000];
381
382 DBG(("dosasync_write(fd=x%x,buf=x%x,len=x%x)\n",fd,buf,len));
383
384 /* Construct copy locally */
385 ((short *)dummy)[0] = CMD_CI;
386 ((short *)dummy)[1] = len;
387 ((short *)dummy)[2] = 0;
388 ((short *)dummy)[3] = 0;
389 for (i = 0; i < len ; i++)
390 {
391 dummy[8 + i ^ 1] = buf[i];
392 }
393
394 /* Wait for the card to get ready */
395 while ((GET_BYTE(fa) & 1) != 0)
396 ;
397
398 /* Blast onto the ISA card */
399 dosmemput (dummy, 8 + len + 1, cpd);
400
401 SET_BYTE(fa, 1);
402 SET_BYTE(irqtod, 1); /* Interrupt the E7000 */
403
404 return len;
405 }
406
407
408 #ifdef _WIN32
409 static int
410 load_wine7kpc(void)
411 {
412 char dll[64];
413
414 DBG(("load_wine7kpc()\n"));
415 if (win_host()==winnt)
416 {
417 printf_filtered( "e7000pc not supported on this host.\n" );
418 return 0;
419 }
420 if (win_host()==win32s)
421 strcpy(dll, "w31e7kpc.Dll");
422 else if (win_host()==win95)
423 strcpy(dll, "w95e7kpc.Dll");
424 else return 0;
425
426 /* load dll for windows support of e7000pc */
427 DBG(("LoadLibrary(%s)\n",dll));
428 hWine7kpc = LoadLibrary (dll);
429 if (!hWine7kpc)
430 {
431 DBG(("LoadLibrary(%s) failed\n",dll));
432 printf_filtered( "Error: unable to load %s.\n",dll);
433 return 0;
434 }
435 pwin_load_e7kpc = (PWIN_LOAD_E7KPC) GetProcAddress (hWine7kpc, "win_load_e7kpc");
436 if (!pwin_load_e7kpc)
437 {
438 DBG(("!pwin_load_e7kpc\n"));
439 printf_filtered( "Error: unable to resolve win_load_e7kpc.\n" );
440 return 0;
441 }
442 pwin_unload_e7kpc = (PWIN_UNLOAD_E7KPC) GetProcAddress (hWine7kpc, "win_unload_e7kpc");
443 if (!pwin_unload_e7kpc)
444 {
445 DBG(("!pwin_unload_e7kpc\n"));
446 printf_filtered( "Error: unable to resolve win_unload_e7kpc.\n" );
447 return 0;
448 }
449 pwin_mem_get = (PWIN_MEM_GET) GetProcAddress (hWine7kpc, "win_mem_get");
450 if (!pwin_mem_get)
451 {
452 DBG(("!pwin_mem_get\n"));
453 printf_filtered( "Error: unable to resolve win_mem_get.\n" );
454 return 0;
455 }
456 pwin_mem_put= (PWIN_MEM_PUT) GetProcAddress (hWine7kpc, "win_mem_put");
457 if (!pwin_mem_put)
458 {
459 DBG(("!pwin_mem_put\n"));
460 printf_filtered( "Error: unable to resolve win_mem_put.\n" );
461 return 0;
462 }
463 pwin_remote_debug= (PWIN_REMOTE_DEBUG) GetProcAddress (hWine7kpc, "win_remote_debug");
464 if (!pwin_remote_debug)
465 {
466 DBG(("!pwin_remote_debug\n"));
467 printf_filtered( "Error: unable to resolve win_remote_debug.\n" );
468 return 0;
469 }
470 DBG(("load_wine7kpc Done! :-)\n"));
471 return 1;
472 }
473 #endif /* _WIN32 */
474
475 static int
476 e7000pc_open (scb, name)
477 serial_t scb;
478 const char *name;
479 {
480 DBG(("e7000pc_open\n"));
481 if (strncasecmp (name, "pc", 2) != 0)
482 {
483 errno = ENOENT;
484 return -1;
485 }
486 #ifdef _WIN32
487 if (!load_wine7kpc()) /* load windows dll for e7kpc support */
488 {
489 DBG(("Error! load_wine7kpc failed\n"));
490 printf_filtered("Failed to initialize dll for e7000pc support.\n" );
491 return -1;
492 }
493 //DBG(("calling win_load_e7kpc\n"));
494 if (win_load_e7kpc () != 0)
495 {
496 errno = ENOENT;
497 return -1;
498 }
499 #endif /* _WIN32 */
500 //DBG(("calling e7000pc_init\n"));
501 scb->fd = e7000pc_init ();
502
503 if (!scb->fd)
504 {
505 DBG(("Error! !scb->fd\n"));
506 return -1;
507 }
508
509 DBG(("e7000pc_open done! :-)\n"));
510 return 0;
511 }
512
513 static int
514 e7000pc_noop (scb)
515 serial_t scb;
516 {
517 return 0;
518 }
519
520 static void
521 e7000pc_raw (scb)
522 serial_t scb;
523 {
524 /* Always in raw mode */
525 }
526
527 static int
528 e7000pc_readchar (scb, timeout)
529 serial_t scb;
530 int timeout;
531 {
532 char buf;
533
534 DBG(("e7000pc_readchar\n"));
535 top:
536
537 /* FIXME! How does dosasync_read ever return 0?
538 * it always goes thru the loop once, so i>0
539 */
540 if (dosasync_read (scb->fd, &buf, 1, timeout))
541 {
542 if (buf == 0) goto top;
543 return buf;
544 }
545 else
546 return SERIAL_TIMEOUT;
547 }
548
549 struct e7000pc_ttystate {
550 int dummy;
551 };
552
553 /* e7000pc_{get set}_tty_state() are both dummys to fill out the function
554 vector. Someday, they may do something real... */
555
556 static serial_ttystate
557 e7000pc_get_tty_state (scb)
558 serial_t scb;
559 {
560 struct e7000pc_ttystate *state;
561 DBG(("e7000pc_get_tty_state\n"));
562
563 state = (struct e7000pc_ttystate *) xmalloc (sizeof *state);
564
565 return (serial_ttystate) state;
566 }
567
568 static int
569 e7000pc_set_tty_state (scb, ttystate)
570 serial_t scb;
571 serial_ttystate ttystate;
572 {
573 return 0;
574 }
575
576 static int
577 e7000pc_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
578 serial_t scb;
579 serial_ttystate new_ttystate;
580 serial_ttystate old_ttystate;
581 {
582 return 0;
583 }
584
585 static void
586 e7000pc_print_tty_state (scb, ttystate)
587 serial_t scb;
588 serial_ttystate ttystate;
589 {
590 /* Nothing to print. */
591 return;
592 }
593
594 static int
595 e7000pc_setbaudrate (scb, rate)
596 serial_t scb;
597 int rate;
598 {
599 return 0;
600 }
601
602 static int
603 e7000pc_write (scb, str, len)
604 serial_t scb;
605 const char *str;
606 int len;
607 {
608 DBG(("e7000pc_write(scb,str=%s,len=x%x)\n",str,len));
609 dosasync_write (scb->fd, str, len);
610
611 return 0;
612 }
613
614 static void
615 e7000pc_close (scb)
616 serial_t scb;
617 {
618 DBG(("e7000pc_close\n"));
619 #ifdef _WIN32
620 win_unload_e7kpc ();
621 #endif
622 }
623
624 static struct serial_ops e7000pc_ops =
625 {
626 "pc",
627 0,
628 e7000pc_open,
629 e7000pc_close,
630 e7000pc_readchar,
631 e7000pc_write,
632 e7000pc_noop, /* flush output */
633 e7000pc_noop, /* flush input */
634 e7000pc_noop, /* send break -- currently used only for nindy */
635 e7000pc_raw,
636 e7000pc_get_tty_state,
637 e7000pc_set_tty_state,
638 e7000pc_print_tty_state,
639 e7000pc_noflush_set_tty_state,
640 e7000pc_setbaudrate,
641 };
642
643 void
644 _initialize_ser_e7000pc ()
645 {
646 serial_add_interface (&e7000pc_ops);
647 }
648 #else
649
650 void
651 _initialize_ser_e7000pc ()
652 {
653
654 }
655 #endif /* defined(__GO32__) || defined(_WIN32) */