xref: /openbsd/gnu/usr.bin/binutils/gdb/ser-e7kpc.c (revision e93f7393)
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 #if defined(__GO32__) || defined(__WIN32__)
22 #if defined(__WIN32__)
23 //#define KERNEL
24 //#define STRICT
25 //#include <windows.h>
26 /* we define the 32-bit calls which thunk to 16-bit dll calls
27  */
28 #include "win-e7kpc.h"
29 /* msvc uses strnicmp instead */
30 #define strncasecmp strnicmp
31 #else
32 #include <sys/dos.h>
33 #include "defs.h"
34 #endif
35 #include "serial.h"
36 
37 
38 static int e7000pc_open PARAMS ((serial_t scb, const char *name));
39 static void e7000pc_raw PARAMS ((serial_t scb));
40 static int e7000pc_readchar PARAMS ((serial_t scb, int timeout));
41 static int e7000pc_setbaudrate PARAMS ((serial_t scb, int rate));
42 static int e7000pc_write PARAMS ((serial_t scb, const char *str, int len));
43 static void e7000pc_close PARAMS ((serial_t scb));
44 static serial_ttystate e7000pc_get_tty_state PARAMS ((serial_t scb));
45 static int e7000pc_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
46 static char *aptr PARAMS ((short p));
47 
48 static int dos_async_init PARAMS ((int port));
49 static void dos_async_tx PARAMS ((const char c));
50 static int dos_async_rx PARAMS (());
51 
52 
53 
54 #define OFF_DPD 	0x0000
55 #define OFF_DDP 	0x1000
56 #define OFF_CPD 	0x2000
57 #define OFF_CDP 	0x2400
58 #define OFF_FA  	0x3000
59 #define OFF_FB  	0x3002
60 #define OFF_FC  	0x3004
61 #define OFF_IRQTOD	0x3008
62 #define OFF_IRQTOP 	0x300a
63 #define OFF_READY  	0x300c
64 #define OFF_PON    	0x300e
65 
66 #define IDLE       0x0000
67 #define CMD_CI     0x4349
68 #define CMD_CO     0x434f
69 #define CMD_LO     0x4c4f
70 #define CMD_LS     0x4c53
71 #define CMD_SV     0x5356
72 #define CMD_SS     0x5353
73 #define CMD_OK     0x4f4b
74 #define CMD_ER     0x4552
75 #define CMD_NF     0x4e46
76 #define CMD_AB     0x4142
77 #define CMD_ED     0x4544
78 #define CMD_CE     0x4345
79 
80 static unsigned long fa;
81 static unsigned long irqtod;
82 static unsigned long ready;
83 static unsigned long fb;
84 static unsigned long cpd ;
85 static unsigned long cdp ;
86 static unsigned long ready;
87 static unsigned long pon;
88 static unsigned long irqtop;
89 static unsigned long board_at;
90 
91 #ifdef __WIN32__
92 // These routines are normally part of the go32 dos extender.
93 // We redefine them here to be calls into their Windoze equivs.
94 static void dosmemget(int offset, int length, void *buffer);
95 static void dosmemput(const void *buffer, int length, int offset);
96 
97 void dosmemget(int offset, int length, void *buffer)
98 {
99     win_mem_get(buffer, length, offset);
100 }
101 void dosmemput(const void *buffer, int length, int offset)
102 {
103     win_mem_put (buffer, length, offset);
104 }
105 
106 #endif
107 
108 #define SET_BYTE(x,y)   { char _buf = y;dosmemput(&_buf,1, x);}
109 #define SET_WORD(x,y)   { short _buf = y;dosmemput(&_buf,2, x);}
110 #define GET_BYTE(x)     ( dosmemget(x,1,&bb), bb)
111 #define GET_WORD(x)     ( dosmemget(x,2,&sb), sb)
112 
113 static unsigned char bb;
114 static unsigned short sb;
115 
116 
117 static struct sw
118 {
119   int sw;
120   int addr;
121 } sigs[] = {
122   {0x14, 0xd0000},
123   {0x15, 0xd4000},
124   {0x16, 0xd8000},
125   {0x17, 0xdc000},
126   0};
127 
128 static int
129 e7000pc_init ()
130 {
131   /* Look around in memory for the board's signature */
132 
133   int try;
134 
135   for (try = 0; sigs[try].sw; try++)
136 
137     {
138       int val;
139       board_at = sigs[try].addr;
140       fa = board_at + OFF_FA;
141       fb = board_at + OFF_FB;
142       cpd = board_at + OFF_CPD;
143       cdp = board_at + OFF_CDP;
144       ready =board_at + OFF_READY;
145       pon = board_at + OFF_PON;
146       irqtop = board_at + OFF_IRQTOP;
147       irqtod = board_at + OFF_IRQTOD;
148 
149       val = GET_WORD (ready);
150 
151       if (val == (0xaaa0  | sigs[try].sw))
152 	{
153 	  if (GET_BYTE (pon) & 0xf)
154 	    {
155 	      SET_BYTE(fa, 0);
156 	      SET_BYTE (fb, 0);
157 
158 	      SET_BYTE (irqtop, 1); /* Disable interrupts from e7000 */
159 	      SET_WORD (ready, 1);
160 	      printf_filtered ("\nConnected to the E7000PC at address 0x%x\n",
161 			       sigs[try].addr);
162 	      return 1;
163 	    }
164 	  error ("The E7000 PC board is working, but the E7000 is turned off.\n");
165 	  return 0;
166 	}
167     }
168 
169   error ("GDB cannot connect to the E7000 PC board, check that it is installed\n\
170 and that the switch settings are correct.  Some other DOS programs can \n\
171 stop the board from working.  Try starting from a very minimal boot, \n\
172 perhaps you need to disable EMM386 over the region where the board has\n\
173 its I/O space, remove other unneeded cards, etc etc\n");
174   return 0;
175 
176 }
177 
178 static int pbuf_size;
179 static int pbuf_index;
180 
181 static
182 int
183 e7000_get ()
184 {
185   static char pbuf[1000];
186   char tmp[1000];
187   int x;
188   if (pbuf_index < pbuf_size)
189     {
190       x = pbuf[pbuf_index++];
191     }
192   else if ((GET_BYTE (fb)  & 1))
193     {
194       int i;
195       pbuf_size = GET_WORD(cdp + 2);
196 
197       dosmemget (cdp + 8, pbuf_size + 1, tmp);
198 
199       /* Tell the E7000 we've eaten */
200       SET_BYTE(fb,0);
201       /* Swap it around */
202       for (i = 0; i < pbuf_size; i++)
203 	{
204 	  pbuf[i] = tmp[i^1];
205 	}
206       pbuf_index = 0;
207       x =  pbuf[pbuf_index++];
208     }
209   else
210     {
211       x = -1;
212     }
213   return x;
214 }
215 
216 static int
217 dosasync_read (fd, buf, len, timeout)
218      int fd;
219      char *buf;
220      int len;
221      int timeout;
222 
223 {
224   long now;
225   long then;
226   int i = 0;
227   int p;
228 
229   /* Then look for some more if we're still hungry */
230   time (&now);
231   then = now + timeout;
232   while (i < len)
233     {
234       int ch = e7000_get();
235 
236       /* While there's room in the buffer, and we've already
237 	 read the stuff in, suck it over */
238       if (ch != -1)
239 	{
240 	  buf[i++] = ch;
241 	  while (i < len && pbuf_index < pbuf_size )
242 	    {
243 	      ch = e7000_get();
244 	      if (ch == -1)
245 		break;
246 	      buf[i++] = ch;
247 	    }
248 	}
249 
250       time (&now);
251 
252       if (timeout == 0)
253 	return i;
254       if (now >= then && timeout > 0)
255 	{
256 	  return i;
257 	}
258     }
259   return len;
260 }
261 
262 
263 static int
264 dosasync_write (fd, buf, len)
265      int fd;
266      const char *buf;
267      int len;
268 {
269   int i;
270   char dummy[1000];
271 
272 
273   /* Construct copy locally */
274   ((short *)dummy)[0] = CMD_CI;
275   ((short *)dummy)[1] = len;
276   ((short *)dummy)[2] = 0;
277   ((short *)dummy)[3] = 0;
278   for (i = 0; i < len ; i++)
279     {
280       dummy[8 + i ^ 1] = buf[i];
281     }
282 
283   /* Wait for the card to get ready */
284   while ((GET_BYTE(fa) & 1) != 0)
285     ;
286 
287   /* Blast onto the ISA card */
288   dosmemput (dummy, 8 + len + 1,  cpd);
289 
290   SET_BYTE(fa, 1);
291   SET_BYTE(irqtod, 1); /* Interrupt the E7000 */
292 
293   return len;
294 }
295 
296 static int
297 e7000pc_open (scb, name)
298      serial_t scb;
299      const char *name;
300 {
301   if (strncasecmp (name, "pc", 2) != 0)
302     {
303       errno = ENOENT;
304       return -1;
305     }
306 #ifdef __WIN32__
307   if (win_load_e7kpc () != 0)
308     {
309       errno = ENOENT;
310       return -1;
311     }
312 #endif
313   scb->fd = e7000pc_init ();
314 
315   if (!scb->fd)
316     return -1;
317 
318   return 0;
319 }
320 
321 static int
322 e7000pc_noop (scb)
323      serial_t scb;
324 {
325   return 0;
326 }
327 
328 static void
329 e7000pc_raw (scb)
330      serial_t scb;
331 {
332   /* Always in raw mode */
333 }
334 
335 static int
336 e7000pc_readchar (scb, timeout)
337      serial_t scb;
338      int timeout;
339 {
340   char buf;
341 
342  top:
343 
344   if (dosasync_read (scb->fd, &buf, 1, timeout))
345     {
346       if (buf == 0) goto top;
347       return buf;
348     }
349   else
350     return SERIAL_TIMEOUT;
351 }
352 
353 struct e7000pc_ttystate {
354   int dummy;
355 };
356 
357 /* e7000pc_{get set}_tty_state() are both dummys to fill out the function
358    vector.  Someday, they may do something real... */
359 
360 static serial_ttystate
361 e7000pc_get_tty_state (scb)
362      serial_t scb;
363 {
364   struct e7000pc_ttystate *state;
365 
366   state = (struct e7000pc_ttystate *) xmalloc (sizeof *state);
367 
368   return (serial_ttystate) state;
369 }
370 
371 static int
372 e7000pc_set_tty_state (scb, ttystate)
373      serial_t scb;
374      serial_ttystate ttystate;
375 {
376   return 0;
377 }
378 
379 static int
380 e7000pc_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
381      serial_t scb;
382      serial_ttystate new_ttystate;
383      serial_ttystate old_ttystate;
384 {
385   return 0;
386 }
387 
388 static void
389 e7000pc_print_tty_state (scb, ttystate)
390      serial_t scb;
391      serial_ttystate ttystate;
392 {
393   /* Nothing to print.  */
394   return;
395 }
396 
397 static int
398 e7000pc_setbaudrate (scb, rate)
399      serial_t scb;
400      int rate;
401 {
402   return 0;
403 }
404 
405 static int
406 e7000pc_write (scb, str, len)
407      serial_t scb;
408      const char *str;
409      int len;
410 {
411   dosasync_write (scb->fd, str, len);
412 
413   return 0;
414 }
415 
416 static void
417 e7000pc_close (scb)
418      serial_t scb;
419 {
420 #ifdef __WIN32__
421   win_unload_e7kpc ();
422 #endif
423 }
424 
425 static struct serial_ops e7000pc_ops =
426 {
427   "pc",
428   0,
429   e7000pc_open,
430   e7000pc_close,
431   e7000pc_readchar,
432   e7000pc_write,
433   e7000pc_noop,			/* flush output */
434   e7000pc_noop,			/* flush input */
435   e7000pc_noop,			/* send break -- currently used only for nindy */
436   e7000pc_raw,
437   e7000pc_get_tty_state,
438   e7000pc_set_tty_state,
439   e7000pc_print_tty_state,
440   e7000pc_noflush_set_tty_state,
441   e7000pc_setbaudrate,
442 };
443 
444 void
445 _initialize_ser_e7000pc ()
446 {
447   serial_add_interface (&e7000pc_ops);
448 }
449 #else
450 
451 void
452 _initialize_ser_e7000pc ()
453 {
454 
455 }
456 #endif
457