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