* defs.h: Fix cntl-C to read from the Windows message queue.
[platform/upstream/binutils.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) */