]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/rdi-share/serdrv.c
Initial creation of sourceware repository
[thirdparty/binutils-gdb.git] / gdb / rdi-share / serdrv.c
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
63 static 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
71 static struct re_state rxstate;
72
73 typedef struct writestate {
74 unsigned int wbindex;
75 /* static te_status testatus;*/
76 unsigned char writebuf[MAXWRITESIZE];
77 struct te_state txstate;
78 } writestate;
79
80 static struct writestate wstate;
81
82 /*
83 * The set of parameter options supported by the device
84 */
85 static unsigned int baud_options[] = {
86 #ifdef __hpux
87 115200, 57600,
88 #endif
89 38400, 19200, 9600
90 };
91
92 static ParameterList param_list[] = {
93 { AP_BAUD_RATE,
94 sizeof(baud_options)/sizeof(unsigned int),
95 baud_options }
96 };
97
98 static const ParameterOptions serial_options = {
99 sizeof(param_list)/sizeof(ParameterList), param_list };
100
101 /*
102 * The default parameter config for the device
103 */
104 static Parameter param_default[] = {
105 { AP_BAUD_RATE, 9600 }
106 };
107
108 static ParameterConfig serial_defaults = {
109 sizeof(param_default)/sizeof(Parameter), param_default };
110
111 /*
112 * The user-modified options for the device
113 */
114 static unsigned int user_baud_options[sizeof(baud_options)/sizeof(unsigned)];
115
116 static ParameterList param_user_list[] = {
117 { AP_BAUD_RATE,
118 sizeof(user_baud_options)/sizeof(unsigned),
119 user_baud_options }
120 };
121
122 static ParameterOptions user_options = {
123 sizeof(param_user_list)/sizeof(ParameterList), param_user_list };
124
125 static bool user_options_set;
126
127 /* forward declarations */
128 static int serial_reset( void );
129 static int serial_set_params( const ParameterConfig *config );
130 static int SerialMatch(const char *name, const char *arg);
131
132 static 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
188 static 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
259 static 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
272 static 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
285 static 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
393 static 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
493 static 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
509 static 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
537 static 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
577 static 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
596 static 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
607 static 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
641 DeviceDescr angel_SerialDevice = {
642 "SERIAL",
643 SerialOpen,
644 SerialMatch,
645 SerialClose,
646 SerialRead,
647 SerialWrite,
648 SerialIoctl
649 };