2004-02-12 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / rdi-share / serdrv.c
CommitLineData
c906108c
SS
1/*
2 * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
3 *
4 * This software may be freely used, copied, modified, and distributed
5 * provided that the above copyright notice is preserved in all copies of the
6 * software.
7 */
8
9/* -*-C-*-
10 *
11 * $Revision$
12 * $Date$
13 *
14 *
15 * serdrv.c - Synchronous Serial Driver for Angel.
16 * This is nice and simple just to get something going.
17 */
18
19#ifdef __hpux
20# define _POSIX_SOURCE 1
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27#include "crc.h"
28#include "devices.h"
29#include "buffers.h"
30#include "rxtx.h"
31#include "hostchan.h"
32#include "params.h"
33#include "logging.h"
34
0d06e24b
JM
35extern int baud_rate; /* From gdb/top.c */
36
c906108c
SS
37#ifdef COMPILING_ON_WINDOWS
38# undef ERROR
39# undef IGNORE
40# include <windows.h>
41# include "angeldll.h"
42# include "comb_api.h"
43#else
44# ifdef __hpux
45# define _TERMIOS_INCLUDED
46# include <sys/termio.h>
47# undef _TERMIOS_INCLUDED
48# else
49# include <termios.h>
50# endif
51# include "unixcomm.h"
52#endif
53
54#ifndef UNUSED
55# define UNUSED(x) (x = x) /* Silence compiler warnings */
56#endif
57
58#define MAXREADSIZE 512
59#define MAXWRITESIZE 512
60
61#define SERIAL_FC_SET ((1<<serial_XON)|(1<<serial_XOFF))
62#define SERIAL_CTL_SET ((1<<serial_STX)|(1<<serial_ETX)|(1<<serial_ESC))
63#define SERIAL_ESC_SET (SERIAL_FC_SET|SERIAL_CTL_SET)
64
65static const struct re_config config = {
66 serial_STX, serial_ETX, serial_ESC, /* self-explanatory? */
67 SERIAL_FC_SET, /* set of flow-control characters */
68 SERIAL_ESC_SET, /* set of characters to be escaped */
69 NULL /* serial_flow_control */, NULL , /* what to do with FC chars */
70 angel_DD_RxEng_BufferAlloc, NULL /* how to get a buffer */
71};
72
73static struct re_state rxstate;
74
75typedef struct writestate {
76 unsigned int wbindex;
77 /* static te_status testatus;*/
78 unsigned char writebuf[MAXWRITESIZE];
79 struct te_state txstate;
80} writestate;
81
82static struct writestate wstate;
83
84/*
85 * The set of parameter options supported by the device
86 */
87static unsigned int baud_options[] = {
c5394b80 88#if defined(B115200) || defined(__hpux)
0d06e24b
JM
89 115200,
90#endif
c5394b80 91#if defined(B57600) || defined(__hpux)
0d06e24b 92 57600,
c906108c
SS
93#endif
94 38400, 19200, 9600
95};
96
97static ParameterList param_list[] = {
98 { AP_BAUD_RATE,
99 sizeof(baud_options)/sizeof(unsigned int),
100 baud_options }
101};
102
103static const ParameterOptions serial_options = {
104 sizeof(param_list)/sizeof(ParameterList), param_list };
105
106/*
107 * The default parameter config for the device
108 */
109static Parameter param_default[] = {
110 { AP_BAUD_RATE, 9600 }
111};
112
113static ParameterConfig serial_defaults = {
114 sizeof(param_default)/sizeof(Parameter), param_default };
115
116/*
117 * The user-modified options for the device
118 */
119static unsigned int user_baud_options[sizeof(baud_options)/sizeof(unsigned)];
120
121static ParameterList param_user_list[] = {
122 { AP_BAUD_RATE,
123 sizeof(user_baud_options)/sizeof(unsigned),
124 user_baud_options }
125};
126
127static ParameterOptions user_options = {
128 sizeof(param_user_list)/sizeof(ParameterList), param_user_list };
129
130static bool user_options_set;
131
132/* forward declarations */
133static int serial_reset( void );
134static int serial_set_params( const ParameterConfig *config );
135static int SerialMatch(const char *name, const char *arg);
136
137static void process_baud_rate( unsigned int target_baud_rate )
138{
139 const ParameterList *full_list;
140 ParameterList *user_list;
141
142 /* create subset of full options */
143 full_list = Angel_FindParamList( &serial_options, AP_BAUD_RATE );
144 user_list = Angel_FindParamList( &user_options, AP_BAUD_RATE );
145
146 if ( full_list != NULL && user_list != NULL )
147 {
148 unsigned int i, j;
149 unsigned int def_baud = 0;
150
151 /* find lower or equal to */
152 for ( i = 0; i < full_list->num_options; ++i )
153 if ( target_baud_rate >= full_list->option[i] )
154 {
155 /* copy remaining */
156 for ( j = 0; j < (full_list->num_options - i); ++j )
157 user_list->option[j] = full_list->option[i+j];
158 user_list->num_options = j;
159
160 /* check this is not the default */
161 Angel_FindParam( AP_BAUD_RATE, &serial_defaults, &def_baud );
162 if ( (j == 1) && (user_list->option[0] == def_baud) )
163 {
164#ifdef DEBUG
165 printf( "user selected default\n" );
166#endif
167 }
168 else
169 {
170 user_options_set = TRUE;
171#ifdef DEBUG
172 printf( "user options are: " );
173 for ( j = 0; j < user_list->num_options; ++j )
174 printf( "%u ", user_list->option[j] );
175 printf( "\n" );
176#endif
177 }
178
179 break; /* out of i loop */
180 }
181
182#ifdef DEBUG
183 if ( i >= full_list->num_options )
184 printf( "couldn't match baud rate %u\n", target_baud_rate );
185#endif
186 }
187#ifdef DEBUG
188 else
189 printf( "failed to find lists\n" );
190#endif
191}
192
193static int SerialOpen(const char *name, const char *arg)
194{
195 const char *port_name = name;
196
197#ifdef DEBUG
198 printf("SerialOpen: name %s arg %s\n", name, arg ? arg : "<NULL>");
199#endif
200
201#ifdef COMPILING_ON_WINDOWS
202 if (IsOpenSerial()) return -1;
203#else
204 if (Unix_IsSerialInUse()) return -1;
205#endif
206
207#ifdef COMPILING_ON_WINDOWS
208 if (SerialMatch(name, arg) != adp_ok)
209 return adp_failed;
210#else
211 port_name = Unix_MatchValidSerialDevice(port_name);
212# ifdef DEBUG
213 printf("translated port to %s\n", port_name == 0 ? "NULL" : port_name);
214# endif
215 if (port_name == 0) return adp_failed;
216#endif
217
218 user_options_set = FALSE;
219
220 /* interpret and store the arguments */
221 if ( arg != NULL )
222 {
223 unsigned int target_baud_rate;
224 target_baud_rate = (unsigned int)strtoul(arg, NULL, 10);
225 if (target_baud_rate > 0)
226 {
227#ifdef DEBUG
228 printf( "user selected baud rate %u\n", target_baud_rate );
229#endif
230 process_baud_rate( target_baud_rate );
231 }
232#ifdef DEBUG
233 else
234 printf( "could not understand baud rate %s\n", arg );
235#endif
236 }
0d06e24b
JM
237 else if (baud_rate > 0)
238 {
239 /* If the user specified a baud rate on the command line "-b" or via
240 the "set remotebaud" command then try to use that one */
241 process_baud_rate( baud_rate );
242 }
c906108c
SS
243
244#ifdef COMPILING_ON_WINDOWS
245 {
246 int port = IsValidDevice(name);
247 if (OpenSerial(port, FALSE) != COM_OK)
248 return -1;
249 }
250#else
251 if (Unix_OpenSerial(port_name) < 0)
252 return -1;
253#endif
254
255 serial_reset();
256
a3efda28 257#if defined(__unix) || defined(__CYGWIN__)
c906108c
SS
258 Unix_ioctlNonBlocking();
259#endif
260
261 Angel_RxEngineInit(&config, &rxstate);
262 /*
263 * DANGER!: passing in NULL as the packet is ok for now as it is just
264 * IGNOREd but this may well change
265 */
266 Angel_TxEngineInit(&config, NULL, &wstate.txstate);
267 return 0;
268}
269
270static int SerialMatch(const char *name, const char *arg)
271{
272 UNUSED(arg);
273#ifdef COMPILING_ON_WINDOWS
274 if (IsValidDevice(name) == COM_DEVICENOTVALID)
275 return -1;
276 else
277 return 0;
278#else
279 return Unix_MatchValidSerialDevice(name) == 0 ? -1 : 0;
280#endif
281}
282
283static void SerialClose(void)
284{
285#ifdef DO_TRACE
286 printf("SerialClose()\n");
287#endif
288
289#ifdef COMPILING_ON_WINDOWS
290 CloseSerial();
291#else
292 Unix_CloseSerial();
293#endif
294}
295
296static int SerialRead(DriverCall *dc, bool block) {
297 static unsigned char readbuf[MAXREADSIZE];
298 static int rbindex=0;
299
300 int nread;
301 int read_errno;
302 int c=0;
303 re_status restatus;
304 int ret_code = -1; /* assume bad packet or error */
305
306 /* must not overflow buffer and must start after the existing data */
307#ifdef COMPILING_ON_WINDOWS
308 {
309 BOOL dummy = FALSE;
310 nread = BytesInRXBufferSerial();
311
312 if (nread > MAXREADSIZE - rbindex)
313 nread = MAXREADSIZE - rbindex;
314
315 if ((read_errno = ReadSerial(readbuf+rbindex, nread, &dummy)) == COM_READFAIL)
316 {
317 MessageBox(GetFocus(), "Read error\n", "Angel", MB_OK | MB_ICONSTOP);
318 return -1; /* SJ - This really needs to return a value, which is picked up in */
319 /* DevSW_Read as meaning stop debugger but don't kill. */
320 }
321 else if (pfnProgressCallback != NULL && read_errno == COM_OK)
322 {
323 progressInfo.nRead += nread;
324 (*pfnProgressCallback)(&progressInfo);
325 }
326 }
327#else
328 nread = Unix_ReadSerial(readbuf+rbindex, MAXREADSIZE-rbindex, block);
329 read_errno = errno;
330#endif
331
332 if ((nread > 0) || (rbindex > 0)) {
333
334#ifdef DO_TRACE
335 printf("[%d@%d] ", nread, rbindex);
336#endif
337
338 if (nread>0)
339 rbindex = rbindex+nread;
340
341 do {
342 restatus = Angel_RxEngine(readbuf[c], &(dc->dc_packet), &rxstate);
343#ifdef DO_TRACE
344 printf("<%02X ",readbuf[c]);
345 if (!(++c % 16))
346 printf("\n");
347#else
348 c++;
349#endif
350 } while (c<rbindex &&
351 ((restatus == RS_IN_PKT) || (restatus == RS_WAIT_PKT)));
352
353#ifdef DO_TRACE
354 if (c % 16)
355 printf("\n");
356#endif
357
358 switch(restatus) {
359
360 case RS_GOOD_PKT:
361 ret_code = 1;
362 /* fall through to: */
363
364 case RS_BAD_PKT:
365 /*
366 * We now need to shuffle any left over data down to the
367 * beginning of our private buffer ready to be used
368 *for the next packet
369 */
370#ifdef DO_TRACE
371 printf("SerialRead() processed %d, moving down %d\n", c, rbindex-c);
372#endif
373 if (c != rbindex) memmove((char *) readbuf, (char *) (readbuf+c),
374 rbindex-c);
375 rbindex -= c;
376 break;
377
378 case RS_IN_PKT:
379 case RS_WAIT_PKT:
380 rbindex = 0; /* will have processed all we had */
381 ret_code = 0;
382 break;
383
384 default:
385#ifdef DEBUG
386 printf("Bad re_status in serialRead()\n");
387#endif
388 break;
389 }
390 } else if (nread == 0)
391 ret_code = 0; /* nothing to read */
392 else if (read_errno == ERRNO_FOR_BLOCKED_IO) /* nread < 0 */
393 ret_code = 0;
394
395#ifdef DEBUG
396 if ((nread<0) && (read_errno!=ERRNO_FOR_BLOCKED_IO))
397 perror("read() error in serialRead()");
398#endif
399
400 return ret_code;
401}
402
403
404static int SerialWrite(DriverCall *dc) {
405 int nwritten = 0;
406 te_status testatus = TS_IN_PKT;
407
408 if (dc->dc_context == NULL) {
409 Angel_TxEngineInit(&config, &(dc->dc_packet), &(wstate.txstate));
410 wstate.wbindex = 0;
411 dc->dc_context = &wstate;
412 }
413
414 while ((testatus == TS_IN_PKT) && (wstate.wbindex < MAXWRITESIZE))
415 {
416 /* send the raw data through the tx engine to escape and encapsulate */
417 testatus = Angel_TxEngine(&(dc->dc_packet), &(wstate.txstate),
418 &(wstate.writebuf)[wstate.wbindex]);
419 if (testatus != TS_IDLE) wstate.wbindex++;
420 }
421
422 if (testatus == TS_IDLE) {
423#ifdef DEBUG
424 printf("SerialWrite: testatus is TS_IDLE during preprocessing\n");
425#endif
426 }
427
428#ifdef DO_TRACE
429 {
430 int i = 0;
431
432 while (i<wstate.wbindex)
433 {
434 printf(">%02X ",wstate.writebuf[i]);
435
436 if (!(++i % 16))
437 printf("\n");
438 }
439 if (i % 16)
440 printf("\n");
441 }
442#endif
443
444#ifdef COMPILING_ON_WINDOWS
445 if (WriteSerial(wstate.writebuf, wstate.wbindex) == COM_OK)
446 {
447 nwritten = wstate.wbindex;
448 if (pfnProgressCallback != NULL)
449 {
450 progressInfo.nWritten += nwritten;
451 (*pfnProgressCallback)(&progressInfo);
452 }
453 }
454 else
455 {
456 MessageBox(GetFocus(), "Write error\n", "Angel", MB_OK | MB_ICONSTOP);
457 return -1; /* SJ - This really needs to return a value, which is picked up in */
458 /* DevSW_Read as meaning stop debugger but don't kill. */
459 }
460#else
461 nwritten = Unix_WriteSerial(wstate.writebuf, wstate.wbindex);
462
463 if (nwritten < 0) {
464 nwritten=0;
465 }
466#endif
467
468#ifdef DEBUG
469 if (nwritten > 0)
470 printf("Wrote %#04x bytes\n", nwritten);
471#endif
472
473 if ((unsigned) nwritten == wstate.wbindex &&
474 (testatus == TS_DONE_PKT || testatus == TS_IDLE)) {
475
476 /* finished sending the packet */
477
478#ifdef DEBUG
479 printf("SerialWrite: calling Angel_TxEngineInit after sending packet (len=%i)\n",wstate.wbindex);
480#endif
481 testatus = TS_IN_PKT;
482 wstate.wbindex = 0;
483 return 1;
484 }
485 else {
486#ifdef DEBUG
487 printf("SerialWrite: Wrote part of packet wbindex=%i, nwritten=%i\n",
488 wstate.wbindex, nwritten);
489#endif
490
491 /*
492 * still some data left to send shuffle whats left down and reset
493 * the ptr
494 */
495 memmove((char *) wstate.writebuf, (char *) (wstate.writebuf+nwritten),
496 wstate.wbindex-nwritten);
497 wstate.wbindex -= nwritten;
498 return 0;
499 }
500 return -1;
501}
502
503
504static int serial_reset( void )
505{
506#ifdef DEBUG
507 printf( "serial_reset\n" );
508#endif
509
510#ifdef COMPILING_ON_WINDOWS
511 FlushSerial();
512#else
513 Unix_ResetSerial();
514#endif
515
516 return serial_set_params( &serial_defaults );
517}
518
519
520static int find_baud_rate( unsigned int *speed )
521{
522 static struct {
523 unsigned int baud;
524 int termiosValue;
525 } possibleBaudRates[] = {
526#if defined(__hpux)
527 {115200,_B115200}, {57600,_B57600},
0d06e24b
JM
528#else
529#ifdef B115200
530 {115200,B115200},
531#endif
532#ifdef B57600
533 {57600,B57600},
534#endif
c906108c
SS
535#endif
536#ifdef COMPILING_ON_WINDOWS
537 {38400,CBR_38400}, {19200,CBR_19200}, {9600, CBR_9600}, {0,0}
538#else
539 {38400,B38400}, {19200,B19200}, {9600, B9600}, {0,0}
540#endif
541 };
542 unsigned int i;
543
544 /* look for lower or matching -- will always terminate at 0 end marker */
545 for ( i = 0; possibleBaudRates[i].baud > *speed; ++i )
546 /* do nothing */ ;
547
548 if ( possibleBaudRates[i].baud > 0 )
549 *speed = possibleBaudRates[i].baud;
550
551 return possibleBaudRates[i].termiosValue;
552}
553
554
555static int serial_set_params( const ParameterConfig *config )
556{
557 unsigned int speed;
558 int termios_value;
559
560#ifdef DEBUG
561 printf( "serial_set_params\n" );
562#endif
563
564 if ( ! Angel_FindParam( AP_BAUD_RATE, config, &speed ) )
565 {
566#ifdef DEBUG
567 printf( "speed not found in config\n" );
568#endif
569 return DE_OKAY;
570 }
571
572 termios_value = find_baud_rate( &speed );
573 if ( termios_value == 0 )
574 {
575#ifdef DEBUG
576 printf( "speed not valid: %u\n", speed );
577#endif
578 return DE_OKAY;
579 }
580
581#ifdef DEBUG
582 printf( "setting speed to %u\n", speed );
583#endif
584
585#ifdef COMPILING_ON_WINDOWS
586 SetBaudRate((WORD)termios_value);
587#else
588 Unix_SetSerialBaudRate(termios_value);
589#endif
590
591 return DE_OKAY;
592}
593
594
595static int serial_get_user_params( ParameterOptions **p_options )
596{
597#ifdef DEBUG
598 printf( "serial_get_user_params\n" );
599#endif
600
601 if ( user_options_set )
602 {
603 *p_options = &user_options;
604 }
605 else
606 {
607 *p_options = NULL;
608 }
609
610 return DE_OKAY;
611}
612
613
614static int serial_get_default_params( ParameterConfig **p_config )
615{
616#ifdef DEBUG
617 printf( "serial_get_default_params\n" );
618#endif
619
620 *p_config = (ParameterConfig *) &serial_defaults;
621 return DE_OKAY;
622}
623
624
625static int SerialIoctl(const int opcode, void *args) {
626
627 int ret_code;
628
629#ifdef DEBUG
630 printf( "SerialIoctl: op %d arg %p\n", opcode, args ? args : "<NULL>");
631#endif
632
633 switch (opcode)
634 {
635 case DC_RESET:
636 ret_code = serial_reset();
637 break;
638
639 case DC_SET_PARAMS:
640 ret_code = serial_set_params((const ParameterConfig *)args);
641 break;
642
643 case DC_GET_USER_PARAMS:
644 ret_code = serial_get_user_params((ParameterOptions **)args);
645 break;
646
647 case DC_GET_DEFAULT_PARAMS:
648 ret_code = serial_get_default_params((ParameterConfig **)args);
649 break;
650
651 default:
652 ret_code = DE_BAD_OP;
653 break;
654 }
655
656 return ret_code;
657}
658
659DeviceDescr angel_SerialDevice = {
660 "SERIAL",
661 SerialOpen,
662 SerialMatch,
663 SerialClose,
664 SerialRead,
665 SerialWrite,
666 SerialIoctl
667};
This page took 0.383322 seconds and 4 git commands to generate.