This commit was generated by cvs2svn to track changes on a CVS vendor
[platform/upstream/binutils.git] / gdb / ser-e7kpc.c
1 /* Remote serial interface using Hitachi E7000 PC ISA card in a PC
2    Copyright 1994, 1999 Free Software Foundation, Inc.
3
4    This file is part of GDB.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 #if defined __GO32__ || defined _WIN32
22 #include "defs.h"
23 #include "serial.h"
24 #include "gdb_string.h"
25
26 /* MSVC uses strnicmp instead of strncasecmp */
27 #ifdef _MSC_VER
28 #define strncasecmp strnicmp
29 #define WIN32_LEAN_AND_MEAN
30 #endif
31
32 #ifdef _WIN32
33 #include <windows.h>
34 #endif
35
36 #ifdef __GO32__
37 #include <sys/dos.h>
38 #endif
39
40 static int e7000pc_open PARAMS ((serial_t scb, const char *name));
41 static void e7000pc_raw PARAMS ((serial_t scb));
42 static int e7000pc_readchar PARAMS ((serial_t scb, int timeout));
43 static int e7000pc_setbaudrate PARAMS ((serial_t scb, int rate));
44 static int e7000pc_write PARAMS ((serial_t scb, const char *str, int len));
45 static void e7000pc_close PARAMS ((serial_t scb));
46 static serial_ttystate e7000pc_get_tty_state PARAMS ((serial_t scb));
47 static int e7000pc_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
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
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
74
75 static unsigned long fa;
76 static unsigned long irqtod;
77 static unsigned long ready;
78 static unsigned long fb;
79 static unsigned long cpd;
80 static unsigned long cdp;
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
105 static struct sw
106   {
107     int sw;
108     int addr;
109   }
110 sigs[] =
111 {
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 };
130
131 #ifdef _MSC_VER
132 /* Get the base of the data segment.  This is needed to calculate the offset
133    between data segment addresses and the base of linear memory, which is where
134    device registers reside.  Note that this is really only necessary for
135    Win32s, since Win95 and NT keep the data segment at linear 0.  */
136
137 static unsigned long
138 get_ds_base (void)
139 {
140   unsigned short dsval;
141   LDT_ENTRY ldt;
142   unsigned long dsbase;
143
144   __asm
145   {
146     mov dsval, ds
147   }
148
149   dsbase = 0;
150
151   GetThreadSelectorEntry (GetCurrentThread (), dsval, &ldt);
152
153   dsbase = ldt.HighWord.Bits.BaseHi << 24 | ldt.HighWord.Bits.BaseMid << 16
154     | ldt.BaseLow;
155
156   return dsbase;
157 }
158 #else /* !_MSC_VER */
159 #define get_ds_base() 0
160 #endif /* _MSC_VER */
161
162 static int
163 e7000pc_init ()
164 {
165   int try;
166   unsigned long dsbase;
167
168   dsbase = get_ds_base ();
169
170   /* Look around in memory for the board's signature */
171
172   for (try = 0; sigs[try].sw; try++)
173     {
174       int val;
175       board_at = sigs[try].addr - dsbase;
176       fa = board_at + OFF_FA;
177       fb = board_at + OFF_FB;
178       cpd = board_at + OFF_CPD;
179       cdp = board_at + OFF_CDP;
180       ready = board_at + OFF_READY;
181       pon = board_at + OFF_PON;
182       irqtop = board_at + OFF_IRQTOP;
183       irqtod = board_at + OFF_IRQTOD;
184
185       val = GET_WORD (ready);
186
187       if (val == (0xaaa0 | sigs[try].sw))
188         {
189           if (GET_WORD (pon) & 0xf)
190             {
191               SET_WORD (fa, 0);
192               SET_WORD (fb, 0);
193
194               SET_WORD (irqtop, 1);     /* Disable interrupts from e7000 */
195               SET_WORD (ready, 1);
196               printf_filtered ("\nConnected to the E7000PC at address 0x%x\n",
197                                sigs[try].addr);
198               return 1;
199             }
200           error ("The E7000 PC board is working, but the E7000 is turned off.\n");
201           return 0;
202         }
203     }
204
205   error ("GDB cannot connect to the E7000 PC board, check that it is installed\n\
206 and that the switch settings are correct.  Some other DOS programs can \n\
207 stop the board from working.  Try starting from a very minimal boot, \n\
208 perhaps you need to disable EMM386 over the region where the board has\n\
209 its I/O space, remove other unneeded cards, etc etc\n");
210   return 0;
211
212 }
213
214 static int pbuf_size;
215 static int pbuf_index;
216
217 /* Return next byte from cdp.  If no more, then return -1.  */
218
219 static int
220 e7000_get (void)
221 {
222   static char pbuf[1000];
223   char tmp[1000];
224   int x;
225
226   if (pbuf_index < pbuf_size)
227     {
228       x = pbuf[pbuf_index++];
229     }
230   else if ((GET_WORD (fb) & 1))
231     {
232       int i;
233       pbuf_size = GET_WORD (cdp + 2);
234
235       dosmemget (cdp + 8, pbuf_size + 1, tmp);
236
237       /* Tell the E7000 we've eaten */
238       SET_WORD (fb, 0);
239       /* Swap it around */
240       for (i = 0; i < pbuf_size; i++)
241         {
242           pbuf[i] = tmp[i ^ 1];
243         }
244       pbuf_index = 0;
245       x = pbuf[pbuf_index++];
246     }
247   else
248     {
249       x = -1;
250     }
251   return x;
252 }
253
254 /* Works just like read(), except that it takes a TIMEOUT in seconds.  Note
255    that TIMEOUT == 0 is a poll, and TIMEOUT == -1 means wait forever. */
256
257 static int
258 dosasync_read (fd, buf, len, timeout)
259      int fd;
260      char *buf;
261      int len;
262      int timeout;
263
264 {
265   long now;
266   long then;
267   int i = 0;
268
269   /* Then look for some more if we're still hungry */
270   time (&now);
271   then = now + timeout;
272   while (i < len)
273     {
274       int ch = e7000_get ();
275
276       /* While there's room in the buffer, and we've already
277          read the stuff in, suck it over */
278       if (ch != -1)
279         {
280           buf[i++] = ch;
281           while (i < len && pbuf_index < pbuf_size)
282             {
283               ch = e7000_get ();
284               if (ch == -1)
285                 break;
286               buf[i++] = ch;
287             }
288         }
289
290       time (&now);
291
292       if (timeout == 0)
293         return i;
294       if (now >= then && timeout > 0)
295         {
296           return i;
297         }
298     }
299   return len;
300 }
301
302
303 static int
304 dosasync_write (fd, buf, len)
305      int fd;
306      const char *buf;
307      int len;
308 {
309   int i;
310   char dummy[1000];
311
312   /* Construct copy locally */
313   ((short *) dummy)[0] = CMD_CI;
314   ((short *) dummy)[1] = len;
315   ((short *) dummy)[2] = 0;
316   ((short *) dummy)[3] = 0;
317   for (i = 0; i < len; i++)
318     {
319       dummy[(8 + i) ^ 1] = buf[i];
320     }
321
322   /* Wait for the card to get ready */
323   while (GET_WORD (fa) & 1);
324
325   /* Blast onto the ISA card */
326   dosmemput (dummy, 8 + len + 1, cpd);
327
328   SET_WORD (fa, 1);
329   SET_WORD (irqtod, 1);         /* Interrupt the E7000 */
330
331   return len;
332 }
333
334 static int
335 e7000pc_open (scb, name)
336      serial_t scb;
337      const char *name;
338 {
339   if (strncasecmp (name, "pc", 2) != 0)
340     {
341       errno = ENOENT;
342       return -1;
343     }
344
345   scb->fd = e7000pc_init ();
346
347   if (!scb->fd)
348     return -1;
349
350   return 0;
351 }
352
353 static int
354 e7000pc_noop (scb)
355      serial_t scb;
356 {
357   return 0;
358 }
359
360 static void
361 e7000pc_raw (scb)
362      serial_t scb;
363 {
364   /* Always in raw mode */
365 }
366
367 static int
368 e7000pc_readchar (scb, timeout)
369      serial_t scb;
370      int timeout;
371 {
372   char buf;
373
374 top:
375
376   if (dosasync_read (scb->fd, &buf, 1, timeout))
377     {
378       if (buf == 0)
379         goto top;
380       return buf;
381     }
382   else
383     return SERIAL_TIMEOUT;
384 }
385
386 struct e7000pc_ttystate
387 {
388   int dummy;
389 };
390
391 /* e7000pc_{get set}_tty_state() are both dummys to fill out the function
392    vector.  Someday, they may do something real... */
393
394 static serial_ttystate
395 e7000pc_get_tty_state (scb)
396      serial_t scb;
397 {
398   struct e7000pc_ttystate *state;
399
400   state = (struct e7000pc_ttystate *) xmalloc (sizeof *state);
401
402   return (serial_ttystate) state;
403 }
404
405 static int
406 e7000pc_set_tty_state (scb, ttystate)
407      serial_t scb;
408      serial_ttystate ttystate;
409 {
410   return 0;
411 }
412
413 static int
414 e7000pc_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
415      serial_t scb;
416      serial_ttystate new_ttystate;
417      serial_ttystate old_ttystate;
418 {
419   return 0;
420 }
421
422 static void
423 e7000pc_print_tty_state (scb, ttystate)
424      serial_t scb;
425      serial_ttystate ttystate;
426 {
427   /* Nothing to print.  */
428   return;
429 }
430
431 static int
432 e7000pc_setbaudrate (scb, rate)
433      serial_t scb;
434      int rate;
435 {
436   return 0;
437 }
438
439 static int
440 e7000pc_write (scb, str, len)
441      serial_t scb;
442      const char *str;
443      int len;
444 {
445   dosasync_write (scb->fd, str, len);
446
447   return 0;
448 }
449
450 static void
451 e7000pc_close (scb)
452      serial_t scb;
453 {
454 }
455
456 static struct serial_ops e7000pc_ops =
457 {
458   "pc",
459   0,
460   e7000pc_open,
461   e7000pc_close,
462   e7000pc_readchar,
463   e7000pc_write,
464   e7000pc_noop,                 /* flush output */
465   e7000pc_noop,                 /* flush input */
466   e7000pc_noop,                 /* send break -- currently used only for nindy */
467   e7000pc_raw,
468   e7000pc_get_tty_state,
469   e7000pc_set_tty_state,
470   e7000pc_print_tty_state,
471   e7000pc_noflush_set_tty_state,
472   e7000pc_setbaudrate,
473   e7000pc_noop,                 /* wait for output to drain */
474 };
475
476 void
477 _initialize_ser_e7000pc ()
478 {
479   serial_add_interface (&e7000pc_ops);
480 }
481 #else
482
483 void
484 _initialize_ser_e7000pc ()
485 {
486
487 }
488 #endif