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