1130812Smarcel/* Remote serial interface using Renesas E7000 PC ISA card in a PC
2130812Smarcel   Copyright 1994, 1996, 1997, 1998, 1999, 2000
3130812Smarcel   Free Software Foundation, Inc.
4130812Smarcel
5130812Smarcel   This file is part of GDB.
6130812Smarcel
7130812Smarcel   This program is free software; you can redistribute it and/or modify
8130812Smarcel   it under the terms of the GNU General Public License as published by
9130812Smarcel   the Free Software Foundation; either version 2 of the License, or
10130812Smarcel   (at your option) any later version.
11130812Smarcel
12130812Smarcel   This program is distributed in the hope that it will be useful,
13130812Smarcel   but WITHOUT ANY WARRANTY; without even the implied warranty of
14130812Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15130812Smarcel   GNU General Public License for more details.
16130812Smarcel
17130812Smarcel   You should have received a copy of the GNU General Public License
18130812Smarcel   along with this program; if not, write to the Free Software
19130812Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
20130812Smarcel   Boston, MA 02111-1307, USA.  */
21130812Smarcel
22130812Smarcel#include "defs.h"
23130812Smarcel#if defined __GO32__ || defined _WIN32
24130812Smarcel#include "serial.h"
25130812Smarcel#include "gdb_string.h"
26130812Smarcel
27130812Smarcel#ifdef _WIN32
28130812Smarcel#define WIN32_LEAN_AND_MEAN
29130812Smarcel#include <windows.h>
30130812Smarcel#endif
31130812Smarcel
32130812Smarcel#ifdef __GO32__
33130812Smarcel#include <sys/dos.h>
34130812Smarcel#endif
35130812Smarcel
36130812Smarcelstatic int e7000pc_open (struct serial *scb, const char *name);
37130812Smarcelstatic void e7000pc_raw (struct serial *scb);
38130812Smarcelstatic int e7000pc_readchar (struct serial *scb, int timeout);
39130812Smarcelstatic int e7000pc_setbaudrate (struct serial *scb, int rate);
40130812Smarcelstatic int e7000pc_write (struct serial *scb, const char *str, int len);
41130812Smarcelstatic void e7000pc_close (struct serial *scb);
42130812Smarcelstatic serial_ttystate e7000pc_get_tty_state (struct serial *scb);
43130812Smarcelstatic int e7000pc_set_tty_state (struct serial *scb, serial_ttystate state);
44130812Smarcel
45130812Smarcel#define OFF_DPD 	0x0000
46130812Smarcel#define OFF_DDP 	0x1000
47130812Smarcel#define OFF_CPD 	0x2000
48130812Smarcel#define OFF_CDP 	0x2400
49130812Smarcel#define OFF_FA  	0x3000
50130812Smarcel#define OFF_FB  	0x3002
51130812Smarcel#define OFF_FC  	0x3004
52130812Smarcel#define OFF_IRQTOD	0x3008
53130812Smarcel#define OFF_IRQTOP 	0x300a
54130812Smarcel#define OFF_READY  	0x300c
55130812Smarcel#define OFF_PON    	0x300e
56130812Smarcel
57130812Smarcel#define IDLE       0x0000
58130812Smarcel#define CMD_CI     0x4349
59130812Smarcel#define CMD_CO     0x434f
60130812Smarcel#define CMD_LO     0x4c4f
61130812Smarcel#define CMD_LS     0x4c53
62130812Smarcel#define CMD_SV     0x5356
63130812Smarcel#define CMD_SS     0x5353
64130812Smarcel#define CMD_OK     0x4f4b
65130812Smarcel#define CMD_ER     0x4552
66130812Smarcel#define CMD_NF     0x4e46
67130812Smarcel#define CMD_AB     0x4142
68130812Smarcel#define CMD_ED     0x4544
69130812Smarcel#define CMD_CE     0x4345
70130812Smarcel
71130812Smarcelstatic unsigned long fa;
72130812Smarcelstatic unsigned long irqtod;
73130812Smarcelstatic unsigned long ready;
74130812Smarcelstatic unsigned long fb;
75130812Smarcelstatic unsigned long cpd;
76130812Smarcelstatic unsigned long cdp;
77130812Smarcelstatic unsigned long ready;
78130812Smarcelstatic unsigned long pon;
79130812Smarcelstatic unsigned long irqtop;
80130812Smarcelstatic unsigned long board_at;
81130812Smarcel
82130812Smarcel#ifdef __GO32__
83130812Smarcel
84130812Smarcel#define SET_BYTE(x,y)   { char _buf = y;dosmemput(&_buf,1, x);}
85130812Smarcel#define SET_WORD(x,y)   { short _buf = y;dosmemput(&_buf,2, x);}
86130812Smarcel#define GET_BYTE(x)     ( dosmemget(x,1,&bb), bb)
87130812Smarcel#define GET_WORD(x)     ( dosmemget(x,2,&sb), sb)
88130812Smarcelstatic unsigned char bb;
89130812Smarcelstatic unsigned short sb;
90130812Smarcel
91130812Smarcel#else /* win32 */
92130812Smarcel
93130812Smarcel#define SET_BYTE(x,y)   *(volatile unsigned char *)(x) = (y)
94130812Smarcel#define SET_WORD(x,y)   *(volatile unsigned short *)(x) = (y)
95130812Smarcel#define GET_BYTE(x)     (*(volatile unsigned char *)(x))
96130812Smarcel#define GET_WORD(x)     (*(volatile unsigned short *)(x))
97130812Smarcel#define dosmemget(FROM, LEN, TO) memcpy ((void *)(TO), (void *)(FROM), (LEN))
98130812Smarcel#define dosmemput(FROM, LEN, TO) memcpy ((void *)(TO), (void *)(FROM), (LEN))
99130812Smarcel#endif
100130812Smarcel
101130812Smarcelstatic struct sw
102130812Smarcel  {
103130812Smarcel    int sw;
104130812Smarcel    int addr;
105130812Smarcel  }
106130812Smarcelsigs[] =
107130812Smarcel{
108130812Smarcel  {
109130812Smarcel    0x14, 0xd0000
110130812Smarcel  }
111130812Smarcel  ,
112130812Smarcel  {
113130812Smarcel    0x15, 0xd4000
114130812Smarcel  }
115130812Smarcel  ,
116130812Smarcel  {
117130812Smarcel    0x16, 0xd8000
118130812Smarcel  }
119130812Smarcel  ,
120130812Smarcel  {
121130812Smarcel    0x17, 0xdc000
122130812Smarcel  }
123130812Smarcel  ,
124130812Smarcel    0
125130812Smarcel};
126130812Smarcel
127130812Smarcel#define get_ds_base() 0
128130812Smarcel
129130812Smarcelstatic int
130130812Smarcele7000pc_init (void)
131130812Smarcel{
132130812Smarcel  int try;
133130812Smarcel  unsigned long dsbase;
134130812Smarcel
135130812Smarcel  dsbase = get_ds_base ();
136130812Smarcel
137130812Smarcel  /* Look around in memory for the board's signature */
138130812Smarcel
139130812Smarcel  for (try = 0; sigs[try].sw; try++)
140130812Smarcel    {
141130812Smarcel      int val;
142130812Smarcel      board_at = sigs[try].addr - dsbase;
143130812Smarcel      fa = board_at + OFF_FA;
144130812Smarcel      fb = board_at + OFF_FB;
145130812Smarcel      cpd = board_at + OFF_CPD;
146130812Smarcel      cdp = board_at + OFF_CDP;
147130812Smarcel      ready = board_at + OFF_READY;
148130812Smarcel      pon = board_at + OFF_PON;
149130812Smarcel      irqtop = board_at + OFF_IRQTOP;
150130812Smarcel      irqtod = board_at + OFF_IRQTOD;
151130812Smarcel
152130812Smarcel      val = GET_WORD (ready);
153130812Smarcel
154130812Smarcel      if (val == (0xaaa0 | sigs[try].sw))
155130812Smarcel	{
156130812Smarcel	  if (GET_WORD (pon) & 0xf)
157130812Smarcel	    {
158130812Smarcel	      SET_WORD (fa, 0);
159130812Smarcel	      SET_WORD (fb, 0);
160130812Smarcel
161130812Smarcel	      SET_WORD (irqtop, 1);	/* Disable interrupts from e7000 */
162130812Smarcel	      SET_WORD (ready, 1);
163130812Smarcel	      printf_filtered ("\nConnected to the E7000PC at address 0x%x\n",
164130812Smarcel			       sigs[try].addr);
165130812Smarcel	      return 1;
166130812Smarcel	    }
167130812Smarcel	  error ("The E7000 PC board is working, but the E7000 is turned off.\n");
168130812Smarcel	  return 0;
169130812Smarcel	}
170130812Smarcel    }
171130812Smarcel
172130812Smarcel  error ("GDB cannot connect to the E7000 PC board, check that it is installed\n\
173130812Smarceland that the switch settings are correct.  Some other DOS programs can \n\
174130812Smarcelstop the board from working.  Try starting from a very minimal boot, \n\
175130812Smarcelperhaps you need to disable EMM386 over the region where the board has\n\
176130812Smarcelits I/O space, remove other unneeded cards, etc etc\n");
177130812Smarcel  return 0;
178130812Smarcel
179130812Smarcel}
180130812Smarcel
181130812Smarcelstatic int pbuf_size;
182130812Smarcelstatic int pbuf_index;
183130812Smarcel
184130812Smarcel/* Return next byte from cdp.  If no more, then return -1.  */
185130812Smarcel
186130812Smarcelstatic int
187130812Smarcele7000_get (void)
188130812Smarcel{
189130812Smarcel  static char pbuf[1000];
190130812Smarcel  char tmp[1000];
191130812Smarcel  int x;
192130812Smarcel
193130812Smarcel  if (pbuf_index < pbuf_size)
194130812Smarcel    {
195130812Smarcel      x = pbuf[pbuf_index++];
196130812Smarcel    }
197130812Smarcel  else if ((GET_WORD (fb) & 1))
198130812Smarcel    {
199130812Smarcel      int i;
200130812Smarcel      pbuf_size = GET_WORD (cdp + 2);
201130812Smarcel
202130812Smarcel      dosmemget (cdp + 8, pbuf_size + 1, tmp);
203130812Smarcel
204130812Smarcel      /* Tell the E7000 we've eaten */
205130812Smarcel      SET_WORD (fb, 0);
206130812Smarcel      /* Swap it around */
207130812Smarcel      for (i = 0; i < pbuf_size; i++)
208130812Smarcel	{
209130812Smarcel	  pbuf[i] = tmp[i ^ 1];
210130812Smarcel	}
211130812Smarcel      pbuf_index = 0;
212130812Smarcel      x = pbuf[pbuf_index++];
213130812Smarcel    }
214130812Smarcel  else
215130812Smarcel    {
216130812Smarcel      x = -1;
217130812Smarcel    }
218130812Smarcel  return x;
219130812Smarcel}
220130812Smarcel
221130812Smarcel/* Works just like read(), except that it takes a TIMEOUT in seconds.  Note
222130812Smarcel   that TIMEOUT == 0 is a poll, and TIMEOUT == -1 means wait forever. */
223130812Smarcel
224130812Smarcelstatic int
225130812Smarceldosasync_read (int fd, char *buf, int len, int timeout)
226130812Smarcel{
227130812Smarcel  long now;
228130812Smarcel  long then;
229130812Smarcel  int i = 0;
230130812Smarcel
231130812Smarcel  /* Then look for some more if we're still hungry */
232130812Smarcel  time (&now);
233130812Smarcel  then = now + timeout;
234130812Smarcel  while (i < len)
235130812Smarcel    {
236130812Smarcel      int ch = e7000_get ();
237130812Smarcel
238130812Smarcel      /* While there's room in the buffer, and we've already
239130812Smarcel         read the stuff in, suck it over */
240130812Smarcel      if (ch != -1)
241130812Smarcel	{
242130812Smarcel	  buf[i++] = ch;
243130812Smarcel	  while (i < len && pbuf_index < pbuf_size)
244130812Smarcel	    {
245130812Smarcel	      ch = e7000_get ();
246130812Smarcel	      if (ch == -1)
247130812Smarcel		break;
248130812Smarcel	      buf[i++] = ch;
249130812Smarcel	    }
250130812Smarcel	}
251130812Smarcel
252130812Smarcel      time (&now);
253130812Smarcel
254130812Smarcel      if (timeout == 0)
255130812Smarcel	return i;
256130812Smarcel      if (now >= then && timeout > 0)
257130812Smarcel	{
258130812Smarcel	  return i;
259130812Smarcel	}
260130812Smarcel    }
261130812Smarcel  return len;
262130812Smarcel}
263130812Smarcel
264130812Smarcel
265130812Smarcelstatic int
266130812Smarceldosasync_write (int fd, const char *buf, int len)
267130812Smarcel{
268130812Smarcel  int i;
269130812Smarcel  char dummy[1000];
270130812Smarcel
271130812Smarcel  /* Construct copy locally */
272130812Smarcel  ((short *) dummy)[0] = CMD_CI;
273130812Smarcel  ((short *) dummy)[1] = len;
274130812Smarcel  ((short *) dummy)[2] = 0;
275130812Smarcel  ((short *) dummy)[3] = 0;
276130812Smarcel  for (i = 0; i < len; i++)
277130812Smarcel    {
278130812Smarcel      dummy[(8 + i) ^ 1] = buf[i];
279130812Smarcel    }
280130812Smarcel
281130812Smarcel  /* Wait for the card to get ready */
282130812Smarcel  while (GET_WORD (fa) & 1);
283130812Smarcel
284130812Smarcel  /* Blast onto the ISA card */
285130812Smarcel  dosmemput (dummy, 8 + len + 1, cpd);
286130812Smarcel
287130812Smarcel  SET_WORD (fa, 1);
288130812Smarcel  SET_WORD (irqtod, 1);		/* Interrupt the E7000 */
289130812Smarcel
290130812Smarcel  return len;
291130812Smarcel}
292130812Smarcel
293130812Smarcelstatic int
294130812Smarcele7000pc_open (struct serial *scb, const char *name)
295130812Smarcel{
296130812Smarcel  if (strncasecmp (name, "pc", 2) != 0)
297130812Smarcel    {
298130812Smarcel      errno = ENOENT;
299130812Smarcel      return -1;
300130812Smarcel    }
301130812Smarcel
302130812Smarcel  scb->fd = e7000pc_init ();
303130812Smarcel
304130812Smarcel  if (!scb->fd)
305130812Smarcel    return -1;
306130812Smarcel
307130812Smarcel  return 0;
308130812Smarcel}
309130812Smarcel
310130812Smarcelstatic int
311130812Smarcele7000pc_noop (struct serial *scb)
312130812Smarcel{
313130812Smarcel  return 0;
314130812Smarcel}
315130812Smarcel
316130812Smarcelstatic void
317130812Smarcele7000pc_raw (struct serial *scb)
318130812Smarcel{
319130812Smarcel  /* Always in raw mode */
320130812Smarcel}
321130812Smarcel
322130812Smarcelstatic int
323130812Smarcele7000pc_readchar (struct serial *scb, int timeout)
324130812Smarcel{
325130812Smarcel  char buf;
326130812Smarcel
327130812Smarceltop:
328130812Smarcel
329130812Smarcel  if (dosasync_read (scb->fd, &buf, 1, timeout))
330130812Smarcel    {
331130812Smarcel      if (buf == 0)
332130812Smarcel	goto top;
333130812Smarcel      return buf;
334130812Smarcel    }
335130812Smarcel  else
336130812Smarcel    return SERIAL_TIMEOUT;
337130812Smarcel}
338130812Smarcel
339130812Smarcelstruct e7000pc_ttystate
340130812Smarcel{
341130812Smarcel  int dummy;
342130812Smarcel};
343130812Smarcel
344130812Smarcel/* e7000pc_{get set}_tty_state() are both dummys to fill out the function
345130812Smarcel   vector.  Someday, they may do something real... */
346130812Smarcel
347130812Smarcelstatic serial_ttystate
348130812Smarcele7000pc_get_tty_state (struct serial *scb)
349130812Smarcel{
350130812Smarcel  struct e7000pc_ttystate *state;
351130812Smarcel
352130812Smarcel  state = (struct e7000pc_ttystate *) xmalloc (sizeof *state);
353130812Smarcel
354130812Smarcel  return (serial_ttystate) state;
355130812Smarcel}
356130812Smarcel
357130812Smarcelstatic int
358130812Smarcele7000pc_set_tty_state (struct serial *scb, serial_ttystate ttystate)
359130812Smarcel{
360130812Smarcel  return 0;
361130812Smarcel}
362130812Smarcel
363130812Smarcelstatic int
364130812Smarcele7000pc_noflush_set_tty_state (struct serial *scb,
365130812Smarcel			       serial_ttystate new_ttystate,
366130812Smarcel			       serial_ttystate old_ttystate)
367130812Smarcel{
368130812Smarcel  return 0;
369130812Smarcel}
370130812Smarcel
371130812Smarcelstatic void
372130812Smarcele7000pc_print_tty_state (struct serial *scb,
373130812Smarcel			 serial_ttystate ttystate,
374130812Smarcel			 struct ui_file *stream)
375130812Smarcel{
376130812Smarcel  /* Nothing to print.  */
377130812Smarcel  return;
378130812Smarcel}
379130812Smarcel
380130812Smarcelstatic int
381130812Smarcele7000pc_setbaudrate (struct serial *scb, int rate)
382130812Smarcel{
383130812Smarcel  return 0;
384130812Smarcel}
385130812Smarcel
386130812Smarcelstatic int
387130812Smarcele7000pc_setstopbits (struct serial *scb, int rate)
388130812Smarcel{
389130812Smarcel  return 0;
390130812Smarcel}
391130812Smarcel
392130812Smarcelstatic int
393130812Smarcele7000pc_write (struct serial *scb, const char *str, int len)
394130812Smarcel{
395130812Smarcel  dosasync_write (scb->fd, str, len);
396130812Smarcel
397130812Smarcel  return 0;
398130812Smarcel}
399130812Smarcel
400130812Smarcelstatic void
401130812Smarcele7000pc_close (struct serial *scb)
402130812Smarcel{
403130812Smarcel}
404130812Smarcel
405130812Smarcelstatic struct serial_ops e7000pc_ops =
406130812Smarcel{
407130812Smarcel  "pc",
408130812Smarcel  0,
409130812Smarcel  e7000pc_open,
410130812Smarcel  e7000pc_close,
411130812Smarcel  e7000pc_readchar,
412130812Smarcel  e7000pc_write,
413130812Smarcel  e7000pc_noop,			/* flush output */
414130812Smarcel  e7000pc_noop,			/* flush input */
415130812Smarcel  e7000pc_noop,			/* send break -- currently used only for nindy */
416130812Smarcel  e7000pc_raw,
417130812Smarcel  e7000pc_get_tty_state,
418130812Smarcel  e7000pc_set_tty_state,
419130812Smarcel  e7000pc_print_tty_state,
420130812Smarcel  e7000pc_noflush_set_tty_state,
421130812Smarcel  e7000pc_setbaudrate,
422130812Smarcel  e7000pc_setstopbits,
423130812Smarcel  e7000pc_noop,			/* wait for output to drain */
424130812Smarcel};
425130812Smarcel
426130812Smarcel#endif /*_WIN32 or __GO32__*/
427130812Smarcel
428130812Smarcelextern initialize_file_ftype _initialize_ser_e7000pc; /* -Wmissing-prototypes */
429130812Smarcel
430130812Smarcelvoid
431130812Smarcel_initialize_ser_e7000pc (void)
432130812Smarcel{
433130812Smarcel#if defined __GO32__ || defined _WIN32
434130812Smarcel  serial_add_interface (&e7000pc_ops);
435130812Smarcel#endif
436130812Smarcel}
437