eced332d2faa2f76c3d97223979ec82c697374d6
[external/binutils.git] / gdb / ser-go32.c
1 /* Remote serial interface for local (hardwired) serial ports for GO32.
2    Copyright 1992, 1993 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include "defs.h"
21 #include "serial.h"
22 #include <sys/dos.h>
23
24 #define disable() asm("cli")
25 #define enable() asm("sti")
26
27 struct go32_ttystate
28   {
29     int bogus;
30   };
31 typedef struct
32   {
33     short jmp_op;
34     short signature;
35     short version;
36     short buffer_start;
37     short buffer_end;
38     short getp;
39     short putp;
40     short iov;
41     short count;
42     short overflow;
43     short buffer_size;
44     short ovflushes;
45   }
46 ASYNC_STRUCT;
47
48 #define AOFF_JMP_OP             0
49 #define AOFF_SIGNATURE          2
50 #define AOFF_VERSION            4
51 #define AOFF_BUFFER_START       6
52 #define AOFF_BUFFER_END         8
53 #define AOFF_GETP               10
54 #define AOFF_PUTP               12
55 #define AOFF_IOV                14
56 #define AOFF_COUNT              16
57 #define AOFF_OVERFLOW           18
58 #define AOFF_BUFFER_SIZE        20
59 #define AOFF_OVFLUSHES          22
60
61
62 static ASYNC_STRUCT a;          /* Copy in our mem of the struct */
63 static long aindex;             /* index into dos space of struct */
64
65 static int go32_open PARAMS ((serial_t scb, const char *name));
66 static void go32_raw PARAMS ((serial_t scb));
67 static int go32_readchar PARAMS ((serial_t scb, int timeout));
68 static int go32_setbaudrate PARAMS ((serial_t scb, int rate));
69 static int go32_write PARAMS ((serial_t scb, const char *str, int len));
70 static void go32_close PARAMS ((serial_t scb));
71 static serial_ttystate go32_get_tty_state PARAMS ((serial_t scb));
72 static int go32_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
73 static unsigned char aptr PARAMS ((short p));
74 static unsigned long getivec PARAMS ((int which));
75 static int dos_async_init PARAMS ((int port));
76 static void dos_async_tx PARAMS ((const char c));
77 static int dos_async_rx PARAMS (());
78 static int dosasync_read PARAMS ((int fd, char *buf, int len, int timeout));
79 static int dosasync_write PARAMS ((int fd, const char *buf, int len));
80
81 #define SIGNATURE 0x4154
82 #define VERSION 1
83 #define OFFSET 0x104
84
85 unsigned char bb;
86 unsigned short sb;
87 unsigned long sl;
88
89 #define SET_BYTE(x,y)   { char _buf = y;dosmemput(&_buf,1, x);}
90 #define SET_WORD(x,y)   { short _buf = y;dosmemput(&_buf,2, x);}
91 #define GET_BYTE(x)     ( dosmemget((x),1,&bb), bb)
92
93
94 #define GET_LONG(x)     ( dosmemget((x),4,&sl), sl)
95
96 static
97 unsigned short 
98 GET_WORD (x)
99 {
100   unsigned short sb;
101   dosmemget ((x), 2, &sb);
102   return sb;
103 }
104
105 static int iov[2];
106
107 #define com_rb(n)       iov[n]
108 #define com_tb(n)       iov[n]
109 #define com_ier(n)      iov[n]+1
110 #define com_ifr(n)      iov[n]+2
111 #define com_bfr(n)      iov[n]+3
112 #define com_mcr(n)      iov[n]+4
113 #define com_lsr(n)      iov[n]+5
114 #define com_msr(n)      iov[n]+6
115
116 static unsigned char
117 aptr (p)
118      short p;
119 {
120   return GET_BYTE (aindex - OFFSET + p);
121 }
122
123 static unsigned long
124 getivec (int which)
125 {
126   long tryaindex;
127
128   if (GET_WORD (which * 4) != OFFSET)
129     return 0;
130
131   /* Find out where in memory this lives */
132   tryaindex = GET_WORD (which * 4 + 2) * 16 + GET_WORD (which * 4);
133
134   if (GET_WORD (tryaindex + 2) != SIGNATURE)
135     return 0;
136   if (GET_WORD (tryaindex + 4) != VERSION)
137     return 0;
138   return tryaindex;
139 }
140
141 static int
142 dos_async_init (port)
143      int port;
144 {
145   switch (port)
146     {
147     case 1:
148       aindex = getivec (12);
149       break;
150     case 2:
151       aindex = getivec (11);
152       break;
153     default:
154       return 0;
155     }
156
157   if (!aindex)
158     {
159       error ("GDB cannot connect to asynctsr program, check that it is installed\n\
160 and that serial I/O is not being redirected (perhaps by NFS)\n\n\
161 example configuration:\n\
162 C> mode com%d:9600,n,8,1,p\n\
163 C> asynctsr %d\n\
164 C> gdb \n", port, port);
165     }
166
167   iov[0] = GET_WORD (aindex + AOFF_IOV);
168   outportb (com_ier (0), 0x0f);
169   outportb (com_bfr (0), 0x03);
170   outportb (com_mcr (0), 0x0b);
171   return 1;
172 }
173
174 static void
175 dos_async_tx (c)
176      const char c;
177 {
178   while (~inportb (com_lsr (0)) & 0x20)
179     ;
180   outportb (com_tb (0), c);
181 }
182
183 static int
184 dos_async_ready ()
185 {
186   int ret;
187
188   disable ();
189 #if RDY_CNT
190   ret = GET_WORD (aindex + AOFF_COUNT);
191 #else
192   ret = GET_WORD (aindex + AOFF_GETP) != GET_WORD (aindex + AOFF_PUTP);
193 #endif
194   enable ();
195   return ret;
196
197
198 }
199
200 static int
201 dos_async_rx ()
202 {
203   char rv;
204   short idx;
205
206   while (!dos_async_ready ())
207     {
208       if (kbhit ())
209         {
210           printf_unfiltered ("abort!\n");
211           return 0;
212         }
213     }
214   disable ();
215   idx = GET_WORD (aindex + AOFF_GETP);
216   idx++;
217   SET_WORD (aindex + AOFF_GETP, idx);
218   rv = aptr (idx - 1);
219   SET_WORD (aindex + AOFF_COUNT, GET_WORD (aindex + AOFF_COUNT) - 1);
220   if (GET_WORD (aindex + AOFF_GETP) > GET_WORD (aindex + AOFF_BUFFER_END))
221     SET_WORD (aindex + AOFF_GETP, GET_WORD (aindex + AOFF_BUFFER_START));
222   enable ();
223   return rv;
224 }
225
226
227 static int
228 dosasync_read (fd, buf, len, timeout)
229      int fd;
230      char *buf;
231      int len;
232      int timeout;
233 {
234   long now, then;
235   int i;
236
237   time (&now);
238   then = now + timeout;
239
240   for (i = 0; i < len; i++)
241     {
242       if (timeout)
243         {
244           while (!dos_async_ready ())
245             {
246               time (&now);
247               if (now >= then && timeout > 0)
248                 return i;
249             }
250         }
251       *buf++ = dos_async_rx ();
252     }
253   return len;
254 }
255
256 static int
257 dosasync_write (fd, buf, len)
258      int fd;
259      const char *buf;
260      int len;
261 {
262   int l;
263
264   for (l = 0; l < len; l++)
265     dos_async_tx (*buf++);
266
267   return len;
268 }
269
270 static int
271 go32_open (scb, name)
272      serial_t scb;
273      const char *name;
274 {
275   int port;
276
277   if (strncasecmp (name, "com", 3) != 0)
278     {
279       errno = ENOENT;
280       return -1;
281     }
282
283   port = name[3] - '0';
284
285   if ((port != 1) && (port != 2))
286     {
287       errno = ENOENT;
288       return -11;
289     }
290
291   scb->fd = dos_async_init (port);
292   if (!scb->fd)
293     return -1;
294
295   return 0;
296 }
297
298 static int
299 go32_noop (scb)
300      serial_t scb;
301 {
302   return 0;
303 }
304
305 static void
306 go32_raw (scb)
307      serial_t scb;
308 {
309   /* Always in raw mode */
310 }
311
312 static int
313 go32_readchar (scb, timeout)
314      serial_t scb;
315      int timeout;
316 {
317   char buf;
318
319   /* Shortcut for polling */
320   if (timeout == 0)
321     {
322       if (dos_async_ready ())
323         {
324           return dos_async_rx ();
325         }
326       return SERIAL_TIMEOUT;
327     }
328
329   if (dosasync_read (scb->fd, &buf, 1, timeout))
330     return buf;
331   else
332     return SERIAL_TIMEOUT;
333 }
334
335 /* go32_{get set}_tty_state() are both dummys to fill out the function
336    vector.  Someday, they may do something real... */
337
338 static serial_ttystate
339 go32_get_tty_state (scb)
340      serial_t scb;
341 {
342   struct go32_ttystate *state;
343
344   state = (struct go32_ttystate *) xmalloc (sizeof *state);
345
346   return (serial_ttystate) state;
347 }
348
349 static int
350 go32_set_tty_state (scb, ttystate)
351      serial_t scb;
352      serial_ttystate ttystate;
353 {
354   return 0;
355 }
356
357 static int
358 go32_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
359      serial_t scb;
360      serial_ttystate new_ttystate;
361      serial_ttystate old_ttystate;
362 {
363   return 0;
364 }
365
366 static void
367 go32_print_tty_state (scb, ttystate)
368      serial_t scb;
369      serial_ttystate ttystate;
370 {
371   /* Nothing to print.  */
372   return;
373 }
374
375 static int
376 go32_setbaudrate (scb, rate)
377      serial_t scb;
378      int rate;
379 {
380   return 0;
381 }
382
383 static int
384 go32_write (scb, str, len)
385      serial_t scb;
386      const char *str;
387      int len;
388 {
389   dosasync_write (scb->fd, str, len);
390
391   return 0;
392 }
393
394 static void
395 go32_close (scb)
396      serial_t scb;
397 {
398 }
399
400 static struct serial_ops go32_ops =
401 {
402   "hardwire",
403   0,
404   go32_open,
405   go32_close,
406   go32_readchar,
407   go32_write,
408   go32_noop,                    /* flush output */
409   go32_noop,                    /* flush input */
410   go32_noop,                    /* send break -- currently used only for nindy */
411   go32_raw,
412   go32_get_tty_state,
413   go32_set_tty_state,
414   go32_print_tty_state,
415   go32_noflush_set_tty_state,
416   go32_setbaudrate,
417 };
418
419 void
420 _initialize_ser_go32 ()
421 {
422   serial_add_interface (&go32_ops);
423 }