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
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., 675 Mass Ave, Cambridge, MA 02139, 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 } sigs[] = {
110   {0x14, 0xd0000},
111   {0x15, 0xd4000},
112   {0x16, 0xd8000},
113   {0x17, 0xdc000},
114   0};
115
116 #ifdef _MSC_VER
117 /* Get the base of the data segment.  This is needed to calculate the offset
118    between data segment addresses and the base of linear memory, which is where
119    device registers reside.  Note that this is really only necessary for
120    Win32s, since Win95 and NT keep the data segment at linear 0.  */
121
122 static unsigned long
123 get_ds_base (void)
124 {
125   unsigned short dsval;
126   LDT_ENTRY ldt;
127   unsigned long dsbase;
128
129   __asm
130     {
131       mov dsval,ds
132     }
133
134   dsbase = 0;
135
136   GetThreadSelectorEntry (GetCurrentThread(), dsval, &ldt);
137
138   dsbase = ldt.HighWord.Bits.BaseHi << 24 | ldt.HighWord.Bits.BaseMid << 16
139              | ldt.BaseLow;
140
141   return dsbase;
142 }
143 #else /* !_MSC_VER */
144 #define get_ds_base() 0
145 #endif /* _MSC_VER */ 
146
147 static int
148 e7000pc_init ()
149 {
150   int try;
151   unsigned long dsbase;
152   
153   dsbase = get_ds_base ();
154
155   /* Look around in memory for the board's signature */
156
157   for (try = 0; sigs[try].sw; try++)
158     {
159       int val;
160       board_at = sigs[try].addr - dsbase;
161       fa = board_at + OFF_FA;
162       fb = board_at + OFF_FB;
163       cpd = board_at + OFF_CPD;
164       cdp = board_at + OFF_CDP;
165       ready =board_at + OFF_READY;
166       pon = board_at + OFF_PON;       
167       irqtop = board_at + OFF_IRQTOP;
168       irqtod = board_at + OFF_IRQTOD;
169       
170       val = GET_WORD (ready);
171
172       if (val == (0xaaa0  | sigs[try].sw))
173         {
174           if (GET_WORD (pon) & 0xf)
175             {
176               SET_WORD (fa, 0);
177               SET_WORD (fb, 0);
178
179               SET_WORD (irqtop, 1); /* Disable interrupts from e7000 */
180               SET_WORD (ready, 1);
181               printf_filtered ("\nConnected to the E7000PC at address 0x%x\n", 
182                                sigs[try].addr);
183               return 1;       
184             }
185           error ("The E7000 PC board is working, but the E7000 is turned off.\n");
186           return 0;
187         }
188     }
189
190   error ("GDB cannot connect to the E7000 PC board, check that it is installed\n\
191 and that the switch settings are correct.  Some other DOS programs can \n\
192 stop the board from working.  Try starting from a very minimal boot, \n\
193 perhaps you need to disable EMM386 over the region where the board has\n\
194 its I/O space, remove other unneeded cards, etc etc\n");
195   return 0;
196
197 }
198
199 static int pbuf_size;
200 static int pbuf_index;
201
202 /* Return next byte from cdp.  If no more, then return -1.  */
203
204 static int 
205 e7000_get (void)
206 {
207   static char pbuf[1000];
208   char tmp[1000];
209   int x;
210
211   if (pbuf_index < pbuf_size) 
212     {
213       x = pbuf[pbuf_index++];
214     }
215   else if ((GET_WORD (fb) & 1))
216     {
217       int i;
218       pbuf_size = GET_WORD (cdp + 2);
219
220       dosmemget (cdp + 8, pbuf_size + 1, tmp);
221
222       /* Tell the E7000 we've eaten */
223       SET_WORD (fb, 0); 
224       /* Swap it around */
225       for (i = 0; i < pbuf_size; i++) 
226         {
227           pbuf[i] = tmp[i^1];
228         }
229       pbuf_index = 0;
230       x =  pbuf[pbuf_index++];
231     }
232   else 
233     { 
234       x = -1;
235     }
236   return x;
237 }
238
239 /* Works just like read(), except that it takes a TIMEOUT in seconds.  Note
240    that TIMEOUT == 0 is a poll, and TIMEOUT == -1 means wait forever. */
241
242 static int
243 dosasync_read (fd, buf, len, timeout)
244      int fd;
245      char *buf;
246      int len;
247      int timeout;
248
249 {
250   long now;
251   long then;
252   int i = 0;
253
254   /* Then look for some more if we're still hungry */
255   time (&now);
256   then = now + timeout;
257   while (i < len)
258     {
259       int ch = e7000_get();
260       
261       /* While there's room in the buffer, and we've already
262          read the stuff in, suck it over */
263       if (ch != -1) 
264         {
265           buf[i++] = ch;
266           while (i < len && pbuf_index < pbuf_size )
267             {
268               ch = e7000_get();
269               if (ch == -1)
270                 break;
271               buf[i++] = ch;
272             }
273         }
274
275       time (&now);
276
277       if (timeout == 0)
278         return i;
279       if (now >= then && timeout > 0)
280         {
281           return i;
282         }
283     }
284   return len;
285 }
286
287
288 static int
289 dosasync_write (fd, buf, len)
290      int fd;
291      const char *buf;
292      int len;
293 {
294   int i;
295   char dummy[1000];  
296   
297   /* Construct copy locally */
298   ((short *)dummy)[0] = CMD_CI;
299   ((short *)dummy)[1] = len;
300   ((short *)dummy)[2] = 0;
301   ((short *)dummy)[3] = 0;
302   for (i = 0; i < len ; i++) 
303     {
304       dummy[8 + i ^ 1] = buf[i];
305     }
306
307   /* Wait for the card to get ready */
308   while (GET_WORD (fa) & 1) ;
309
310   /* Blast onto the ISA card */
311   dosmemput (dummy, 8 + len + 1,  cpd);
312
313   SET_WORD (fa, 1);
314   SET_WORD (irqtod, 1); /* Interrupt the E7000 */
315
316   return len;
317 }
318
319 static int
320 e7000pc_open (scb, name)
321      serial_t scb;
322      const char *name;
323 {
324   if (strncasecmp (name, "pc", 2) != 0)
325     {
326       errno = ENOENT;
327       return -1;
328     }
329
330   scb->fd = e7000pc_init ();
331
332   if (!scb->fd)
333     return -1;
334
335   return 0;
336 }
337
338 static int
339 e7000pc_noop (scb)
340      serial_t scb;
341 {
342   return 0;
343 }
344
345 static void
346 e7000pc_raw (scb)
347      serial_t scb;
348 {
349   /* Always in raw mode */
350 }
351
352 static int
353 e7000pc_readchar (scb, timeout)
354      serial_t scb;
355      int timeout;
356 {
357   char buf;
358
359  top:
360
361   if (dosasync_read (scb->fd, &buf, 1, timeout))
362     {
363       if (buf == 0) goto top;
364       return buf;
365     }
366   else
367     return SERIAL_TIMEOUT;
368 }
369
370 struct e7000pc_ttystate {
371   int dummy;
372 };
373
374 /* e7000pc_{get set}_tty_state() are both dummys to fill out the function
375    vector.  Someday, they may do something real... */
376
377 static serial_ttystate
378 e7000pc_get_tty_state (scb)
379      serial_t scb;
380 {
381   struct e7000pc_ttystate *state;
382
383   state = (struct e7000pc_ttystate *) xmalloc (sizeof *state);
384
385   return (serial_ttystate) state;
386 }
387
388 static int
389 e7000pc_set_tty_state (scb, ttystate)
390      serial_t scb;
391      serial_ttystate ttystate;
392 {
393   return 0;
394 }
395
396 static int
397 e7000pc_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
398      serial_t scb;
399      serial_ttystate new_ttystate;
400      serial_ttystate old_ttystate;
401 {
402   return 0;
403 }
404
405 static void
406 e7000pc_print_tty_state (scb, ttystate)
407      serial_t scb;
408      serial_ttystate ttystate;
409 {
410   /* Nothing to print.  */
411   return;
412 }
413
414 static int
415 e7000pc_setbaudrate (scb, rate)
416      serial_t scb;
417      int rate;
418 {
419   return 0;
420 }
421
422 static int
423 e7000pc_write (scb, str, len)
424      serial_t scb;
425      const char *str;
426      int len;
427 {
428   dosasync_write (scb->fd, str, len);
429
430   return 0;
431 }
432
433 static void
434 e7000pc_close (scb)
435      serial_t scb;
436 {
437 }
438
439 static struct serial_ops e7000pc_ops =
440 {
441   "pc",
442   0,
443   e7000pc_open,
444   e7000pc_close,
445   e7000pc_readchar,
446   e7000pc_write,
447   e7000pc_noop,                 /* flush output */
448   e7000pc_noop,                 /* flush input */
449   e7000pc_noop,                 /* send break -- currently used only for nindy */
450   e7000pc_raw,
451   e7000pc_get_tty_state,
452   e7000pc_set_tty_state,
453   e7000pc_print_tty_state,
454   e7000pc_noflush_set_tty_state,
455   e7000pc_setbaudrate,
456   e7000pc_noop,                 /* wait for output to drain */
457 };
458
459 void
460 _initialize_ser_e7000pc ()
461 {
462   serial_add_interface (&e7000pc_ops);
463 }
464 #else
465
466 void
467 _initialize_ser_e7000pc ()
468 {
469
470 }
471 #endif