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