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