2 * Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved.
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
15 * serdrv.c - Synchronous Serial Driver for Angel.
16 * This is nice and simple just to get something going.
20 # define _POSIX_SOURCE 1
35 extern int baud_rate
; /* From gdb/top.c */
37 #ifdef COMPILING_ON_WINDOWS
41 # include "angeldll.h"
42 # include "comb_api.h"
45 # define _TERMIOS_INCLUDED
46 # include <sys/termio.h>
47 # undef _TERMIOS_INCLUDED
51 # include "unixcomm.h"
55 # define UNUSED(x) (x = x) /* Silence compiler warnings */
58 #define MAXREADSIZE 512
59 #define MAXWRITESIZE 512
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)
65 static 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 */
73 static struct re_state rxstate
;
75 typedef struct writestate
{
77 /* static te_status testatus;*/
78 unsigned char writebuf
[MAXWRITESIZE
];
79 struct te_state txstate
;
82 static struct writestate wstate
;
85 * The set of parameter options supported by the device
87 static unsigned int baud_options
[] = {
88 #if defined(B115200) || defined(__hpux)
91 #if defined(B57600) || defined(__hpux)
97 static ParameterList param_list
[] = {
99 sizeof(baud_options
)/sizeof(unsigned int),
103 static const ParameterOptions serial_options
= {
104 sizeof(param_list
)/sizeof(ParameterList
), param_list
};
107 * The default parameter config for the device
109 static Parameter param_default
[] = {
110 { AP_BAUD_RATE
, 9600 }
113 static ParameterConfig serial_defaults
= {
114 sizeof(param_default
)/sizeof(Parameter
), param_default
};
117 * The user-modified options for the device
119 static unsigned int user_baud_options
[sizeof(baud_options
)/sizeof(unsigned)];
121 static ParameterList param_user_list
[] = {
123 sizeof(user_baud_options
)/sizeof(unsigned),
127 static ParameterOptions user_options
= {
128 sizeof(param_user_list
)/sizeof(ParameterList
), param_user_list
};
130 static bool user_options_set
;
132 /* forward declarations */
133 static int serial_reset( void );
134 static int serial_set_params( const ParameterConfig
*config
);
135 static int SerialMatch(const char *name
, const char *arg
);
137 static void process_baud_rate( unsigned int target_baud_rate
)
139 const ParameterList
*full_list
;
140 ParameterList
*user_list
;
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
);
146 if ( full_list
!= NULL
&& user_list
!= NULL
)
149 unsigned int def_baud
= 0;
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
] )
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
;
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
) )
165 printf( "user selected default\n" );
170 user_options_set
= TRUE
;
172 printf( "user options are: " );
173 for ( j
= 0; j
< user_list
->num_options
; ++j
)
174 printf( "%u ", user_list
->option
[j
] );
179 break; /* out of i loop */
183 if ( i
>= full_list
->num_options
)
184 printf( "couldn't match baud rate %u\n", target_baud_rate
);
189 printf( "failed to find lists\n" );
193 static int SerialOpen(const char *name
, const char *arg
)
195 const char *port_name
= name
;
198 printf("SerialOpen: name %s arg %s\n", name
, arg
? arg
: "<NULL>");
201 #ifdef COMPILING_ON_WINDOWS
202 if (IsOpenSerial()) return -1;
204 if (Unix_IsSerialInUse()) return -1;
207 #ifdef COMPILING_ON_WINDOWS
208 if (SerialMatch(name
, arg
) != adp_ok
)
211 port_name
= Unix_MatchValidSerialDevice(port_name
);
213 printf("translated port to %s\n", port_name
== 0 ? "NULL" : port_name
);
215 if (port_name
== 0) return adp_failed
;
218 user_options_set
= FALSE
;
220 /* interpret and store the arguments */
223 unsigned int target_baud_rate
;
224 target_baud_rate
= (unsigned int)strtoul(arg
, NULL
, 10);
225 if (target_baud_rate
> 0)
228 printf( "user selected baud rate %u\n", target_baud_rate
);
230 process_baud_rate( target_baud_rate
);
234 printf( "could not understand baud rate %s\n", arg
);
237 else if (baud_rate
> 0)
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
);
244 #ifdef COMPILING_ON_WINDOWS
246 int port
= IsValidDevice(name
);
247 if (OpenSerial(port
, FALSE
) != COM_OK
)
251 if (Unix_OpenSerial(port_name
) < 0)
257 #if defined(__unix) || defined(__CYGWIN32__)
258 Unix_ioctlNonBlocking();
261 Angel_RxEngineInit(&config
, &rxstate
);
263 * DANGER!: passing in NULL as the packet is ok for now as it is just
264 * IGNOREd but this may well change
266 Angel_TxEngineInit(&config
, NULL
, &wstate
.txstate
);
270 static int SerialMatch(const char *name
, const char *arg
)
273 #ifdef COMPILING_ON_WINDOWS
274 if (IsValidDevice(name
) == COM_DEVICENOTVALID
)
279 return Unix_MatchValidSerialDevice(name
) == 0 ? -1 : 0;
283 static void SerialClose(void)
286 printf("SerialClose()\n");
289 #ifdef COMPILING_ON_WINDOWS
296 static int SerialRead(DriverCall
*dc
, bool block
) {
297 static unsigned char readbuf
[MAXREADSIZE
];
298 static int rbindex
=0;
304 int ret_code
= -1; /* assume bad packet or error */
306 /* must not overflow buffer and must start after the existing data */
307 #ifdef COMPILING_ON_WINDOWS
310 nread
= BytesInRXBufferSerial();
312 if (nread
> MAXREADSIZE
- rbindex
)
313 nread
= MAXREADSIZE
- rbindex
;
315 if ((read_errno
= ReadSerial(readbuf
+rbindex
, nread
, &dummy
)) == COM_READFAIL
)
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. */
321 else if (pfnProgressCallback
!= NULL
&& read_errno
== COM_OK
)
323 progressInfo
.nRead
+= nread
;
324 (*pfnProgressCallback
)(&progressInfo
);
328 nread
= Unix_ReadSerial(readbuf
+rbindex
, MAXREADSIZE
-rbindex
, block
);
332 if ((nread
> 0) || (rbindex
> 0)) {
335 printf("[%d@%d] ", nread
, rbindex
);
339 rbindex
= rbindex
+nread
;
342 restatus
= Angel_RxEngine(readbuf
[c
], &(dc
->dc_packet
), &rxstate
);
344 printf("<%02X ",readbuf
[c
]);
350 } while (c
<rbindex
&&
351 ((restatus
== RS_IN_PKT
) || (restatus
== RS_WAIT_PKT
)));
362 /* fall through to: */
366 * We now need to shuffle any left over data down to the
367 * beginning of our private buffer ready to be used
371 printf("SerialRead() processed %d, moving down %d\n", c
, rbindex
-c
);
373 if (c
!= rbindex
) memmove((char *) readbuf
, (char *) (readbuf
+c
),
380 rbindex
= 0; /* will have processed all we had */
386 printf("Bad re_status in serialRead()\n");
390 } else if (nread
== 0)
391 ret_code
= 0; /* nothing to read */
392 else if (read_errno
== ERRNO_FOR_BLOCKED_IO
) /* nread < 0 */
396 if ((nread
<0) && (read_errno
!=ERRNO_FOR_BLOCKED_IO
))
397 perror("read() error in serialRead()");
404 static int SerialWrite(DriverCall
*dc
) {
406 te_status testatus
= TS_IN_PKT
;
408 if (dc
->dc_context
== NULL
) {
409 Angel_TxEngineInit(&config
, &(dc
->dc_packet
), &(wstate
.txstate
));
411 dc
->dc_context
= &wstate
;
414 while ((testatus
== TS_IN_PKT
) && (wstate
.wbindex
< MAXWRITESIZE
))
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
++;
422 if (testatus
== TS_IDLE
) {
424 printf("SerialWrite: testatus is TS_IDLE during preprocessing\n");
432 while (i
<wstate
.wbindex
)
434 printf(">%02X ",wstate
.writebuf
[i
]);
444 #ifdef COMPILING_ON_WINDOWS
445 if (WriteSerial(wstate
.writebuf
, wstate
.wbindex
) == COM_OK
)
447 nwritten
= wstate
.wbindex
;
448 if (pfnProgressCallback
!= NULL
)
450 progressInfo
.nWritten
+= nwritten
;
451 (*pfnProgressCallback
)(&progressInfo
);
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. */
461 nwritten
= Unix_WriteSerial(wstate
.writebuf
, wstate
.wbindex
);
470 printf("Wrote %#04x bytes\n", nwritten
);
473 if ((unsigned) nwritten
== wstate
.wbindex
&&
474 (testatus
== TS_DONE_PKT
|| testatus
== TS_IDLE
)) {
476 /* finished sending the packet */
479 printf("SerialWrite: calling Angel_TxEngineInit after sending packet (len=%i)\n",wstate
.wbindex
);
481 testatus
= TS_IN_PKT
;
487 printf("SerialWrite: Wrote part of packet wbindex=%i, nwritten=%i\n",
488 wstate
.wbindex
, nwritten
);
492 * still some data left to send shuffle whats left down and reset
495 memmove((char *) wstate
.writebuf
, (char *) (wstate
.writebuf
+nwritten
),
496 wstate
.wbindex
-nwritten
);
497 wstate
.wbindex
-= nwritten
;
504 static int serial_reset( void )
507 printf( "serial_reset\n" );
510 #ifdef COMPILING_ON_WINDOWS
516 return serial_set_params( &serial_defaults
);
520 static int find_baud_rate( unsigned int *speed
)
525 } possibleBaudRates
[] = {
527 {115200,_B115200
}, {57600,_B57600
},
536 #ifdef COMPILING_ON_WINDOWS
537 {38400,CBR_38400
}, {19200,CBR_19200
}, {9600, CBR_9600
}, {0,0}
539 {38400,B38400
}, {19200,B19200
}, {9600, B9600
}, {0,0}
544 /* look for lower or matching -- will always terminate at 0 end marker */
545 for ( i
= 0; possibleBaudRates
[i
].baud
> *speed
; ++i
)
548 if ( possibleBaudRates
[i
].baud
> 0 )
549 *speed
= possibleBaudRates
[i
].baud
;
551 return possibleBaudRates
[i
].termiosValue
;
555 static int serial_set_params( const ParameterConfig
*config
)
561 printf( "serial_set_params\n" );
564 if ( ! Angel_FindParam( AP_BAUD_RATE
, config
, &speed
) )
567 printf( "speed not found in config\n" );
572 termios_value
= find_baud_rate( &speed
);
573 if ( termios_value
== 0 )
576 printf( "speed not valid: %u\n", speed
);
582 printf( "setting speed to %u\n", speed
);
585 #ifdef COMPILING_ON_WINDOWS
586 SetBaudRate((WORD
)termios_value
);
588 Unix_SetSerialBaudRate(termios_value
);
595 static int serial_get_user_params( ParameterOptions
**p_options
)
598 printf( "serial_get_user_params\n" );
601 if ( user_options_set
)
603 *p_options
= &user_options
;
614 static int serial_get_default_params( ParameterConfig
**p_config
)
617 printf( "serial_get_default_params\n" );
620 *p_config
= (ParameterConfig
*) &serial_defaults
;
625 static int SerialIoctl(const int opcode
, void *args
) {
630 printf( "SerialIoctl: op %d arg %p\n", opcode
, args
? args
: "<NULL>");
636 ret_code
= serial_reset();
640 ret_code
= serial_set_params((const ParameterConfig
*)args
);
643 case DC_GET_USER_PARAMS
:
644 ret_code
= serial_get_user_params((ParameterOptions
**)args
);
647 case DC_GET_DEFAULT_PARAMS
:
648 ret_code
= serial_get_default_params((ParameterConfig
**)args
);
652 ret_code
= DE_BAD_OP
;
659 DeviceDescr angel_SerialDevice
= {